]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.10/Python/traceback.c
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Python / traceback.c
CommitLineData
c8042e10
DM
1\r
2/* Traceback implementation */\r
3\r
4#include "Python.h"\r
5\r
6#include "code.h"\r
7#include "frameobject.h"\r
8#include "structmember.h"\r
9#include "osdefs.h"\r
10#include "traceback.h"\r
11\r
12#define OFF(x) offsetof(PyTracebackObject, x)\r
13\r
14static PyMemberDef tb_memberlist[] = {\r
15 {"tb_next", T_OBJECT, OFF(tb_next), READONLY},\r
16 {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},\r
17 {"tb_lasti", T_INT, OFF(tb_lasti), READONLY},\r
18 {"tb_lineno", T_INT, OFF(tb_lineno), READONLY},\r
19 {NULL} /* Sentinel */\r
20};\r
21\r
22static void\r
23tb_dealloc(PyTracebackObject *tb)\r
24{\r
25 PyObject_GC_UnTrack(tb);\r
26 Py_TRASHCAN_SAFE_BEGIN(tb)\r
27 Py_XDECREF(tb->tb_next);\r
28 Py_XDECREF(tb->tb_frame);\r
29 PyObject_GC_Del(tb);\r
30 Py_TRASHCAN_SAFE_END(tb)\r
31}\r
32\r
33static int\r
34tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)\r
35{\r
36 Py_VISIT(tb->tb_next);\r
37 Py_VISIT(tb->tb_frame);\r
38 return 0;\r
39}\r
40\r
41static void\r
42tb_clear(PyTracebackObject *tb)\r
43{\r
44 Py_CLEAR(tb->tb_next);\r
45 Py_CLEAR(tb->tb_frame);\r
46}\r
47\r
48PyTypeObject PyTraceBack_Type = {\r
49 PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
50 "traceback",\r
51 sizeof(PyTracebackObject),\r
52 0,\r
53 (destructor)tb_dealloc, /*tp_dealloc*/\r
54 0, /*tp_print*/\r
55 0, /*tp_getattr*/\r
56 0, /*tp_setattr*/\r
57 0, /*tp_compare*/\r
58 0, /*tp_repr*/\r
59 0, /*tp_as_number*/\r
60 0, /*tp_as_sequence*/\r
61 0, /*tp_as_mapping*/\r
62 0, /* tp_hash */\r
63 0, /* tp_call */\r
64 0, /* tp_str */\r
65 0, /* tp_getattro */\r
66 0, /* tp_setattro */\r
67 0, /* tp_as_buffer */\r
68 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\r
69 0, /* tp_doc */\r
70 (traverseproc)tb_traverse, /* tp_traverse */\r
71 (inquiry)tb_clear, /* tp_clear */\r
72 0, /* tp_richcompare */\r
73 0, /* tp_weaklistoffset */\r
74 0, /* tp_iter */\r
75 0, /* tp_iternext */\r
76 0, /* tp_methods */\r
77 tb_memberlist, /* tp_members */\r
78 0, /* tp_getset */\r
79 0, /* tp_base */\r
80 0, /* tp_dict */\r
81};\r
82\r
83static PyTracebackObject *\r
84newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)\r
85{\r
86 PyTracebackObject *tb;\r
87 if ((next != NULL && !PyTraceBack_Check(next)) ||\r
88 frame == NULL || !PyFrame_Check(frame)) {\r
89 PyErr_BadInternalCall();\r
90 return NULL;\r
91 }\r
92 tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);\r
93 if (tb != NULL) {\r
94 Py_XINCREF(next);\r
95 tb->tb_next = next;\r
96 Py_XINCREF(frame);\r
97 tb->tb_frame = frame;\r
98 tb->tb_lasti = frame->f_lasti;\r
99 tb->tb_lineno = PyFrame_GetLineNumber(frame);\r
100 PyObject_GC_Track(tb);\r
101 }\r
102 return tb;\r
103}\r
104\r
105int\r
106PyTraceBack_Here(PyFrameObject *frame)\r
107{\r
108 PyThreadState *tstate = PyThreadState_GET();\r
109 PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;\r
110 PyTracebackObject *tb = newtracebackobject(oldtb, frame);\r
111 if (tb == NULL)\r
112 return -1;\r
113 tstate->curexc_traceback = (PyObject *)tb;\r
114 Py_XDECREF(oldtb);\r
115 return 0;\r
116}\r
117\r
118int\r
119_Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent)\r
120{\r
121 int err = 0;\r
122 FILE *xfp = NULL;\r
123 char linebuf[2000];\r
124 int i;\r
125 char namebuf[MAXPATHLEN+1];\r
126\r
127 if (filename == NULL)\r
128 return -1;\r
129 /* This is needed by Emacs' compile command */\r
130#define FMT " File \"%.500s\", line %d, in %.500s\n"\r
131 xfp = fopen(filename, "r" PY_STDIOTEXTMODE);\r
132 if (xfp == NULL) {\r
133 /* Search tail of filename in sys.path before giving up */\r
134 PyObject *path;\r
135 const char *tail = strrchr(filename, SEP);\r
136 if (tail == NULL)\r
137 tail = filename;\r
138 else\r
139 tail++;\r
140 path = PySys_GetObject("path");\r
141 if (path != NULL && PyList_Check(path)) {\r
142 Py_ssize_t _npath = PyList_Size(path);\r
143 int npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);\r
144 size_t taillen = strlen(tail);\r
145 for (i = 0; i < npath; i++) {\r
146 PyObject *v = PyList_GetItem(path, i);\r
147 if (v == NULL) {\r
148 PyErr_Clear();\r
149 break;\r
150 }\r
151 if (PyString_Check(v)) {\r
152 size_t len;\r
153 len = PyString_GET_SIZE(v);\r
154 if (len + 1 + taillen >= MAXPATHLEN)\r
155 continue; /* Too long */\r
156 strcpy(namebuf, PyString_AsString(v));\r
157 if (strlen(namebuf) != len)\r
158 continue; /* v contains '\0' */\r
159 if (len > 0 && namebuf[len-1] != SEP)\r
160 namebuf[len++] = SEP;\r
161 strcpy(namebuf+len, tail);\r
162 xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE);\r
163 if (xfp != NULL) {\r
164 break;\r
165 }\r
166 }\r
167 }\r
168 }\r
169 }\r
170\r
171 if (xfp == NULL)\r
172 return err;\r
173 if (err != 0) {\r
174 fclose(xfp);\r
175 return err;\r
176 }\r
177\r
178 for (i = 0; i < lineno; i++) {\r
179 char* pLastChar = &linebuf[sizeof(linebuf)-2];\r
180 do {\r
181 *pLastChar = '\0';\r
182 if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL)\r
183 break;\r
184 /* fgets read *something*; if it didn't get as\r
185 far as pLastChar, it must have found a newline\r
186 or hit the end of the file; if pLastChar is \n,\r
187 it obviously found a newline; else we haven't\r
188 yet seen a newline, so must continue */\r
189 } while (*pLastChar != '\0' && *pLastChar != '\n');\r
190 }\r
191 if (i == lineno) {\r
192 char buf[11];\r
193 char *p = linebuf;\r
194 while (*p == ' ' || *p == '\t' || *p == '\014')\r
195 p++;\r
196\r
197 /* Write some spaces before the line */\r
198 strcpy(buf, " ");\r
199 assert (strlen(buf) == 10);\r
200 while (indent > 0) {\r
201 if(indent < 10)\r
202 buf[indent] = '\0';\r
203 err = PyFile_WriteString(buf, f);\r
204 if (err != 0)\r
205 break;\r
206 indent -= 10;\r
207 }\r
208\r
209 if (err == 0)\r
210 err = PyFile_WriteString(p, f);\r
211 if (err == 0 && strchr(p, '\n') == NULL)\r
212 err = PyFile_WriteString("\n", f);\r
213 }\r
214 fclose(xfp);\r
215 return err;\r
216}\r
217\r
218static int\r
219tb_displayline(PyObject *f, const char *filename, int lineno, const char *name)\r
220{\r
221 int err = 0;\r
222 char linebuf[2000];\r
223\r
224 if (filename == NULL || name == NULL)\r
225 return -1;\r
226 /* This is needed by Emacs' compile command */\r
227#define FMT " File \"%.500s\", line %d, in %.500s\n"\r
228 PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);\r
229 err = PyFile_WriteString(linebuf, f);\r
230 if (err != 0)\r
231 return err;\r
232 return _Py_DisplaySourceLine(f, filename, lineno, 4);\r
233}\r
234\r
235static int\r
236tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)\r
237{\r
238 int err = 0;\r
239 long depth = 0;\r
240 PyTracebackObject *tb1 = tb;\r
241 while (tb1 != NULL) {\r
242 depth++;\r
243 tb1 = tb1->tb_next;\r
244 }\r
245 while (tb != NULL && err == 0) {\r
246 if (depth <= limit) {\r
247 err = tb_displayline(f,\r
248 PyString_AsString(\r
249 tb->tb_frame->f_code->co_filename),\r
250 tb->tb_lineno,\r
251 PyString_AsString(tb->tb_frame->f_code->co_name));\r
252 }\r
253 depth--;\r
254 tb = tb->tb_next;\r
255 if (err == 0)\r
256 err = PyErr_CheckSignals();\r
257 }\r
258 return err;\r
259}\r
260\r
261int\r
262PyTraceBack_Print(PyObject *v, PyObject *f)\r
263{\r
264 int err;\r
265 PyObject *limitv;\r
266 long limit = 1000;\r
267 if (v == NULL)\r
268 return 0;\r
269 if (!PyTraceBack_Check(v)) {\r
270 PyErr_BadInternalCall();\r
271 return -1;\r
272 }\r
273 limitv = PySys_GetObject("tracebacklimit");\r
274 if (limitv && PyInt_Check(limitv)) {\r
275 limit = PyInt_AsLong(limitv);\r
276 if (limit <= 0)\r
277 return 0;\r
278 }\r
279 err = PyFile_WriteString("Traceback (most recent call last):\n", f);\r
280 if (!err)\r
281 err = tb_printinternal((PyTracebackObject *)v, f, limit);\r
282 return err;\r
283}\r