Mercurial > cpython-lru_cache-weakref
comparison Python/traceback.c @ 61467:f197407bdba2 3.1
Recorded merge of revisions 81032 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
................
r81032 | antoine.pitrou | 2010-05-09 17:52:27 +0200 (dim., 09 mai 2010) | 9 lines
Recorded merge of revisions 81029 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines
Untabify C files. Will watch buildbots.
........
................
| author | Antoine Pitrou <solipsis@pitrou.net> |
|---|---|
| date | Sun, 09 May 2010 16:14:21 +0000 |
| parents | 87fbbf22adf3 |
| children | fa830371c724 |
comparison
equal
deleted
inserted
replaced
| 61459:f8c19c5f5dd2 | 61467:f197407bdba2 |
|---|---|
| 28 {"__dir__", (PyCFunction)tb_dir, METH_NOARGS}, | 28 {"__dir__", (PyCFunction)tb_dir, METH_NOARGS}, |
| 29 {NULL, NULL, 0, NULL}, | 29 {NULL, NULL, 0, NULL}, |
| 30 }; | 30 }; |
| 31 | 31 |
| 32 static PyMemberDef tb_memberlist[] = { | 32 static PyMemberDef tb_memberlist[] = { |
| 33 {"tb_next", T_OBJECT, OFF(tb_next), READONLY}, | 33 {"tb_next", T_OBJECT, OFF(tb_next), READONLY}, |
| 34 {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, | 34 {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, |
| 35 {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, | 35 {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, |
| 36 {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, | 36 {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, |
| 37 {NULL} /* Sentinel */ | 37 {NULL} /* Sentinel */ |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 static void | 40 static void |
| 41 tb_dealloc(PyTracebackObject *tb) | 41 tb_dealloc(PyTracebackObject *tb) |
| 42 { | 42 { |
| 43 PyObject_GC_UnTrack(tb); | 43 PyObject_GC_UnTrack(tb); |
| 44 Py_TRASHCAN_SAFE_BEGIN(tb) | 44 Py_TRASHCAN_SAFE_BEGIN(tb) |
| 45 Py_XDECREF(tb->tb_next); | 45 Py_XDECREF(tb->tb_next); |
| 46 Py_XDECREF(tb->tb_frame); | 46 Py_XDECREF(tb->tb_frame); |
| 47 PyObject_GC_Del(tb); | 47 PyObject_GC_Del(tb); |
| 48 Py_TRASHCAN_SAFE_END(tb) | 48 Py_TRASHCAN_SAFE_END(tb) |
| 49 } | 49 } |
| 50 | 50 |
| 51 static int | 51 static int |
| 52 tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg) | 52 tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg) |
| 53 { | 53 { |
| 54 Py_VISIT(tb->tb_next); | 54 Py_VISIT(tb->tb_next); |
| 55 Py_VISIT(tb->tb_frame); | 55 Py_VISIT(tb->tb_frame); |
| 56 return 0; | 56 return 0; |
| 57 } | 57 } |
| 58 | 58 |
| 59 static void | 59 static void |
| 60 tb_clear(PyTracebackObject *tb) | 60 tb_clear(PyTracebackObject *tb) |
| 61 { | 61 { |
| 62 Py_CLEAR(tb->tb_next); | 62 Py_CLEAR(tb->tb_next); |
| 63 Py_CLEAR(tb->tb_frame); | 63 Py_CLEAR(tb->tb_frame); |
| 64 } | 64 } |
| 65 | 65 |
| 66 PyTypeObject PyTraceBack_Type = { | 66 PyTypeObject PyTraceBack_Type = { |
| 67 PyVarObject_HEAD_INIT(&PyType_Type, 0) | 67 PyVarObject_HEAD_INIT(&PyType_Type, 0) |
| 68 "traceback", | 68 "traceback", |
| 69 sizeof(PyTracebackObject), | 69 sizeof(PyTracebackObject), |
| 70 0, | 70 0, |
| 71 (destructor)tb_dealloc, /*tp_dealloc*/ | 71 (destructor)tb_dealloc, /*tp_dealloc*/ |
| 72 0, /*tp_print*/ | 72 0, /*tp_print*/ |
| 73 0, /*tp_getattr*/ | 73 0, /*tp_getattr*/ |
| 74 0, /*tp_setattr*/ | 74 0, /*tp_setattr*/ |
| 75 0, /*tp_reserved*/ | 75 0, /*tp_reserved*/ |
| 76 0, /*tp_repr*/ | 76 0, /*tp_repr*/ |
| 77 0, /*tp_as_number*/ | 77 0, /*tp_as_number*/ |
| 78 0, /*tp_as_sequence*/ | 78 0, /*tp_as_sequence*/ |
| 79 0, /*tp_as_mapping*/ | 79 0, /*tp_as_mapping*/ |
| 80 0, /* tp_hash */ | 80 0, /* tp_hash */ |
| 81 0, /* tp_call */ | 81 0, /* tp_call */ |
| 82 0, /* tp_str */ | 82 0, /* tp_str */ |
| 83 PyObject_GenericGetAttr, /* tp_getattro */ | 83 PyObject_GenericGetAttr, /* tp_getattro */ |
| 84 0, /* tp_setattro */ | 84 0, /* tp_setattro */ |
| 85 0, /* tp_as_buffer */ | 85 0, /* tp_as_buffer */ |
| 86 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ | 86 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ |
| 87 0, /* tp_doc */ | 87 0, /* tp_doc */ |
| 88 (traverseproc)tb_traverse, /* tp_traverse */ | 88 (traverseproc)tb_traverse, /* tp_traverse */ |
| 89 (inquiry)tb_clear, /* tp_clear */ | 89 (inquiry)tb_clear, /* tp_clear */ |
| 90 0, /* tp_richcompare */ | 90 0, /* tp_richcompare */ |
| 91 0, /* tp_weaklistoffset */ | 91 0, /* tp_weaklistoffset */ |
| 92 0, /* tp_iter */ | 92 0, /* tp_iter */ |
| 93 0, /* tp_iternext */ | 93 0, /* tp_iternext */ |
| 94 tb_methods, /* tp_methods */ | 94 tb_methods, /* tp_methods */ |
| 95 tb_memberlist, /* tp_members */ | 95 tb_memberlist, /* tp_members */ |
| 96 0, /* tp_getset */ | 96 0, /* tp_getset */ |
| 97 0, /* tp_base */ | 97 0, /* tp_base */ |
| 98 0, /* tp_dict */ | 98 0, /* tp_dict */ |
| 99 }; | 99 }; |
| 100 | 100 |
| 101 static PyTracebackObject * | 101 static PyTracebackObject * |
| 102 newtracebackobject(PyTracebackObject *next, PyFrameObject *frame) | 102 newtracebackobject(PyTracebackObject *next, PyFrameObject *frame) |
| 103 { | 103 { |
| 104 PyTracebackObject *tb; | 104 PyTracebackObject *tb; |
| 105 if ((next != NULL && !PyTraceBack_Check(next)) || | 105 if ((next != NULL && !PyTraceBack_Check(next)) || |
| 106 frame == NULL || !PyFrame_Check(frame)) { | 106 frame == NULL || !PyFrame_Check(frame)) { |
| 107 PyErr_BadInternalCall(); | 107 PyErr_BadInternalCall(); |
| 108 return NULL; | 108 return NULL; |
| 109 } | 109 } |
| 110 tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type); | 110 tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type); |
| 111 if (tb != NULL) { | 111 if (tb != NULL) { |
| 112 Py_XINCREF(next); | 112 Py_XINCREF(next); |
| 113 tb->tb_next = next; | 113 tb->tb_next = next; |
| 114 Py_XINCREF(frame); | 114 Py_XINCREF(frame); |
| 115 tb->tb_frame = frame; | 115 tb->tb_frame = frame; |
| 116 tb->tb_lasti = frame->f_lasti; | 116 tb->tb_lasti = frame->f_lasti; |
| 117 tb->tb_lineno = PyCode_Addr2Line(frame->f_code, | 117 tb->tb_lineno = PyCode_Addr2Line(frame->f_code, |
| 118 frame->f_lasti); | 118 frame->f_lasti); |
| 119 PyObject_GC_Track(tb); | 119 PyObject_GC_Track(tb); |
| 120 } | 120 } |
| 121 return tb; | 121 return tb; |
| 122 } | 122 } |
| 123 | 123 |
| 124 int | 124 int |
| 125 PyTraceBack_Here(PyFrameObject *frame) | 125 PyTraceBack_Here(PyFrameObject *frame) |
| 126 { | 126 { |
| 127 PyThreadState *tstate = PyThreadState_GET(); | 127 PyThreadState *tstate = PyThreadState_GET(); |
| 128 PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback; | 128 PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback; |
| 129 PyTracebackObject *tb = newtracebackobject(oldtb, frame); | 129 PyTracebackObject *tb = newtracebackobject(oldtb, frame); |
| 130 if (tb == NULL) | 130 if (tb == NULL) |
| 131 return -1; | 131 return -1; |
| 132 tstate->curexc_traceback = (PyObject *)tb; | 132 tstate->curexc_traceback = (PyObject *)tb; |
| 133 Py_XDECREF(oldtb); | 133 Py_XDECREF(oldtb); |
| 134 return 0; | 134 return 0; |
| 135 } | 135 } |
| 136 | 136 |
| 137 static int | 137 static int |
| 138 _Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open_flags) | 138 _Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open_flags) |
| 139 { | 139 { |
| 140 int i; | 140 int i; |
| 141 int fd = -1; | 141 int fd = -1; |
| 142 PyObject *v; | 142 PyObject *v; |
| 143 Py_ssize_t _npath; | 143 Py_ssize_t _npath; |
| 144 int npath; | 144 int npath; |
| 145 size_t taillen; | 145 size_t taillen; |
| 146 PyObject *syspath; | 146 PyObject *syspath; |
| 147 const char* path; | 147 const char* path; |
| 148 const char* tail; | 148 const char* tail; |
| 149 Py_ssize_t len; | 149 Py_ssize_t len; |
| 150 | 150 |
| 151 /* Search tail of filename in sys.path before giving up */ | 151 /* Search tail of filename in sys.path before giving up */ |
| 152 tail = strrchr(filename, SEP); | 152 tail = strrchr(filename, SEP); |
| 153 if (tail == NULL) | 153 if (tail == NULL) |
| 154 tail = filename; | 154 tail = filename; |
| 155 else | 155 else |
| 156 tail++; | 156 tail++; |
| 157 taillen = strlen(tail); | 157 taillen = strlen(tail); |
| 158 | 158 |
| 159 syspath = PySys_GetObject("path"); | 159 syspath = PySys_GetObject("path"); |
| 160 if (syspath == NULL || !PyList_Check(syspath)) | 160 if (syspath == NULL || !PyList_Check(syspath)) |
| 161 return -1; | 161 return -1; |
| 162 _npath = PyList_Size(syspath); | 162 _npath = PyList_Size(syspath); |
| 163 npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int); | 163 npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int); |
| 164 | 164 |
| 165 for (i = 0; i < npath; i++) { | 165 for (i = 0; i < npath; i++) { |
| 166 v = PyList_GetItem(syspath, i); | 166 v = PyList_GetItem(syspath, i); |
| 167 if (v == NULL) { | 167 if (v == NULL) { |
| 168 PyErr_Clear(); | 168 PyErr_Clear(); |
| 169 break; | 169 break; |
| 170 } | 170 } |
| 171 if (!PyUnicode_Check(v)) | 171 if (!PyUnicode_Check(v)) |
| 172 continue; | 172 continue; |
| 173 path = _PyUnicode_AsStringAndSize(v, &len); | 173 path = _PyUnicode_AsStringAndSize(v, &len); |
| 174 if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) | 174 if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) |
| 175 continue; /* Too long */ | 175 continue; /* Too long */ |
| 176 strcpy(namebuf, path); | 176 strcpy(namebuf, path); |
| 177 if (strlen(namebuf) != len) | 177 if (strlen(namebuf) != len) |
| 178 continue; /* v contains '\0' */ | 178 continue; /* v contains '\0' */ |
| 179 if (len > 0 && namebuf[len-1] != SEP) | 179 if (len > 0 && namebuf[len-1] != SEP) |
| 180 namebuf[len++] = SEP; | 180 namebuf[len++] = SEP; |
| 181 strcpy(namebuf+len, tail); | 181 strcpy(namebuf+len, tail); |
| 182 Py_BEGIN_ALLOW_THREADS | 182 Py_BEGIN_ALLOW_THREADS |
| 183 fd = open(namebuf, open_flags); | 183 fd = open(namebuf, open_flags); |
| 184 Py_END_ALLOW_THREADS | 184 Py_END_ALLOW_THREADS |
| 185 if (0 <= fd) { | 185 if (0 <= fd) { |
| 186 return fd; | 186 return fd; |
| 187 } | 187 } |
| 188 } | 188 } |
| 189 return -1; | 189 return -1; |
| 190 } | 190 } |
| 191 | 191 |
| 192 int | 192 int |
| 193 _Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) | 193 _Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) |
| 194 { | 194 { |
| 195 int err = 0; | 195 int err = 0; |
| 196 int fd; | 196 int fd; |
| 197 int i; | 197 int i; |
| 198 char *found_encoding; | 198 char *found_encoding; |
| 199 char *encoding; | 199 char *encoding; |
| 200 PyObject *fob = NULL; | 200 PyObject *fob = NULL; |
| 201 PyObject *lineobj = NULL; | 201 PyObject *lineobj = NULL; |
| 202 #ifdef O_BINARY | 202 #ifdef O_BINARY |
| 203 const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */ | 203 const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */ |
| 204 #else | 204 #else |
| 205 const int open_flags = O_RDONLY; | 205 const int open_flags = O_RDONLY; |
| 206 #endif | 206 #endif |
| 207 char buf[MAXPATHLEN+1]; | 207 char buf[MAXPATHLEN+1]; |
| 208 Py_UNICODE *u, *p; | 208 Py_UNICODE *u, *p; |
| 209 Py_ssize_t len; | 209 Py_ssize_t len; |
| 210 | 210 |
| 211 /* open the file */ | 211 /* open the file */ |
| 212 if (filename == NULL) | 212 if (filename == NULL) |
| 213 return 0; | 213 return 0; |
| 214 Py_BEGIN_ALLOW_THREADS | 214 Py_BEGIN_ALLOW_THREADS |
| 215 fd = open(filename, open_flags); | 215 fd = open(filename, open_flags); |
| 216 Py_END_ALLOW_THREADS | 216 Py_END_ALLOW_THREADS |
| 217 if (fd < 0) { | 217 if (fd < 0) { |
| 218 fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags); | 218 fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags); |
| 219 if (fd < 0) | 219 if (fd < 0) |
| 220 return 0; | 220 return 0; |
| 221 filename = buf; | 221 filename = buf; |
| 222 } | 222 } |
| 223 | 223 |
| 224 /* use the right encoding to decode the file as unicode */ | 224 /* use the right encoding to decode the file as unicode */ |
| 225 found_encoding = PyTokenizer_FindEncoding(fd); | 225 found_encoding = PyTokenizer_FindEncoding(fd); |
| 226 encoding = (found_encoding != NULL) ? found_encoding : | 226 encoding = (found_encoding != NULL) ? found_encoding : |
| 227 (char*)PyUnicode_GetDefaultEncoding(); | 227 (char*)PyUnicode_GetDefaultEncoding(); |
| 228 lseek(fd, 0, 0); /* Reset position */ | 228 lseek(fd, 0, 0); /* Reset position */ |
| 229 fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding, | 229 fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding, |
| 230 NULL, NULL, 1); | 230 NULL, NULL, 1); |
| 231 PyMem_FREE(found_encoding); | 231 PyMem_FREE(found_encoding); |
| 232 if (fob == NULL) { | 232 if (fob == NULL) { |
| 233 PyErr_Clear(); | 233 PyErr_Clear(); |
| 234 close(fd); | 234 close(fd); |
| 235 return 0; | 235 return 0; |
| 236 } | 236 } |
| 237 | 237 |
| 238 /* get the line number lineno */ | 238 /* get the line number lineno */ |
| 239 for (i = 0; i < lineno; i++) { | 239 for (i = 0; i < lineno; i++) { |
| 240 Py_XDECREF(lineobj); | 240 Py_XDECREF(lineobj); |
| 241 lineobj = PyFile_GetLine(fob, -1); | 241 lineobj = PyFile_GetLine(fob, -1); |
| 242 if (!lineobj) { | 242 if (!lineobj) { |
| 243 err = -1; | 243 err = -1; |
| 244 break; | 244 break; |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 Py_DECREF(fob); | 247 Py_DECREF(fob); |
| 248 if (!lineobj || !PyUnicode_Check(lineobj)) { | 248 if (!lineobj || !PyUnicode_Check(lineobj)) { |
| 249 Py_XDECREF(lineobj); | 249 Py_XDECREF(lineobj); |
| 250 return err; | 250 return err; |
| 251 } | 251 } |
| 252 | 252 |
| 253 /* remove the indentation of the line */ | 253 /* remove the indentation of the line */ |
| 254 u = PyUnicode_AS_UNICODE(lineobj); | 254 u = PyUnicode_AS_UNICODE(lineobj); |
| 255 len = PyUnicode_GET_SIZE(lineobj); | 255 len = PyUnicode_GET_SIZE(lineobj); |
| 256 for (p=u; *p == ' ' || *p == '\t' || *p == '\014'; p++) | 256 for (p=u; *p == ' ' || *p == '\t' || *p == '\014'; p++) |
| 257 len--; | 257 len--; |
| 258 if (u != p) { | 258 if (u != p) { |
| 259 PyObject *truncated; | 259 PyObject *truncated; |
| 260 truncated = PyUnicode_FromUnicode(p, len); | 260 truncated = PyUnicode_FromUnicode(p, len); |
| 261 if (truncated) { | 261 if (truncated) { |
| 262 Py_DECREF(lineobj); | 262 Py_DECREF(lineobj); |
| 263 lineobj = truncated; | 263 lineobj = truncated; |
| 264 } else { | 264 } else { |
| 265 PyErr_Clear(); | 265 PyErr_Clear(); |
| 266 } | 266 } |
| 267 } | 267 } |
| 268 | 268 |
| 269 /* Write some spaces before the line */ | 269 /* Write some spaces before the line */ |
| 270 strcpy(buf, " "); | 270 strcpy(buf, " "); |
| 271 assert (strlen(buf) == 10); | 271 assert (strlen(buf) == 10); |
| 272 while (indent > 0) { | 272 while (indent > 0) { |
| 273 if(indent < 10) | 273 if(indent < 10) |
| 274 buf[indent] = '\0'; | 274 buf[indent] = '\0'; |
| 275 err = PyFile_WriteString(buf, f); | 275 err = PyFile_WriteString(buf, f); |
| 276 if (err != 0) | 276 if (err != 0) |
| 277 break; | 277 break; |
| 278 indent -= 10; | 278 indent -= 10; |
| 279 } | 279 } |
| 280 | 280 |
| 281 /* finally display the line */ | 281 /* finally display the line */ |
| 282 if (err == 0) | 282 if (err == 0) |
| 283 err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); | 283 err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); |
| 284 Py_DECREF(lineobj); | 284 Py_DECREF(lineobj); |
| 285 if (err == 0) | 285 if (err == 0) |
| 286 err = PyFile_WriteString("\n", f); | 286 err = PyFile_WriteString("\n", f); |
| 287 return err; | 287 return err; |
| 288 } | 288 } |
| 289 | 289 |
| 290 static int | 290 static int |
| 291 tb_displayline(PyObject *f, const char *filename, int lineno, const char *name) | 291 tb_displayline(PyObject *f, const char *filename, int lineno, const char *name) |
| 292 { | 292 { |
| 293 int err = 0; | 293 int err = 0; |
| 294 char linebuf[2000]; | 294 char linebuf[2000]; |
| 295 | 295 |
| 296 if (filename == NULL || name == NULL) | 296 if (filename == NULL || name == NULL) |
| 297 return -1; | 297 return -1; |
| 298 /* This is needed by Emacs' compile command */ | 298 /* This is needed by Emacs' compile command */ |
| 299 #define FMT " File \"%.500s\", line %d, in %.500s\n" | 299 #define FMT " File \"%.500s\", line %d, in %.500s\n" |
| 300 PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); | 300 PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); |
| 301 err = PyFile_WriteString(linebuf, f); | 301 err = PyFile_WriteString(linebuf, f); |
| 302 if (err != 0) | 302 if (err != 0) |
| 303 return err; | 303 return err; |
| 304 return _Py_DisplaySourceLine(f, filename, lineno, 4); | 304 return _Py_DisplaySourceLine(f, filename, lineno, 4); |
| 305 } | 305 } |
| 306 | 306 |
| 307 static int | 307 static int |
| 308 tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) | 308 tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) |
| 309 { | 309 { |
| 310 int err = 0; | 310 int err = 0; |
| 311 long depth = 0; | 311 long depth = 0; |
| 312 PyTracebackObject *tb1 = tb; | 312 PyTracebackObject *tb1 = tb; |
| 313 while (tb1 != NULL) { | 313 while (tb1 != NULL) { |
| 314 depth++; | 314 depth++; |
| 315 tb1 = tb1->tb_next; | 315 tb1 = tb1->tb_next; |
| 316 } | 316 } |
| 317 while (tb != NULL && err == 0) { | 317 while (tb != NULL && err == 0) { |
| 318 if (depth <= limit) { | 318 if (depth <= limit) { |
| 319 err = tb_displayline(f, | 319 err = tb_displayline(f, |
| 320 _PyUnicode_AsString( | 320 _PyUnicode_AsString( |
| 321 tb->tb_frame->f_code->co_filename), | 321 tb->tb_frame->f_code->co_filename), |
| 322 tb->tb_lineno, | 322 tb->tb_lineno, |
| 323 _PyUnicode_AsString(tb->tb_frame->f_code->co_name)); | 323 _PyUnicode_AsString(tb->tb_frame->f_code->co_name)); |
| 324 } | 324 } |
| 325 depth--; | 325 depth--; |
| 326 tb = tb->tb_next; | 326 tb = tb->tb_next; |
| 327 if (err == 0) | 327 if (err == 0) |
| 328 err = PyErr_CheckSignals(); | 328 err = PyErr_CheckSignals(); |
| 329 } | 329 } |
| 330 return err; | 330 return err; |
| 331 } | 331 } |
| 332 | 332 |
| 333 #define PyTraceBack_LIMIT 1000 | 333 #define PyTraceBack_LIMIT 1000 |
| 334 | 334 |
| 335 int | 335 int |
| 336 PyTraceBack_Print(PyObject *v, PyObject *f) | 336 PyTraceBack_Print(PyObject *v, PyObject *f) |
| 337 { | 337 { |
| 338 int err; | 338 int err; |
| 339 PyObject *limitv; | 339 PyObject *limitv; |
| 340 long limit = PyTraceBack_LIMIT; | 340 long limit = PyTraceBack_LIMIT; |
| 341 | 341 |
| 342 if (v == NULL) | 342 if (v == NULL) |
| 343 return 0; | 343 return 0; |
| 344 if (!PyTraceBack_Check(v)) { | 344 if (!PyTraceBack_Check(v)) { |
| 345 PyErr_BadInternalCall(); | 345 PyErr_BadInternalCall(); |
| 346 return -1; | 346 return -1; |
| 347 } | 347 } |
| 348 limitv = PySys_GetObject("tracebacklimit"); | 348 limitv = PySys_GetObject("tracebacklimit"); |
| 349 if (limitv) { | 349 if (limitv) { |
| 350 PyObject *exc_type, *exc_value, *exc_tb; | 350 PyObject *exc_type, *exc_value, *exc_tb; |
| 351 | 351 |
| 352 PyErr_Fetch(&exc_type, &exc_value, &exc_tb); | 352 PyErr_Fetch(&exc_type, &exc_value, &exc_tb); |
| 353 limit = PyLong_AsLong(limitv); | 353 limit = PyLong_AsLong(limitv); |
| 354 if (limit == -1 && PyErr_Occurred()) { | 354 if (limit == -1 && PyErr_Occurred()) { |
| 355 if (PyErr_ExceptionMatches(PyExc_OverflowError)) { | 355 if (PyErr_ExceptionMatches(PyExc_OverflowError)) { |
| 356 limit = PyTraceBack_LIMIT; | 356 limit = PyTraceBack_LIMIT; |
| 357 } | 357 } |
| 358 else { | 358 else { |
| 359 Py_XDECREF(exc_type); | 359 Py_XDECREF(exc_type); |
| 360 Py_XDECREF(exc_value); | 360 Py_XDECREF(exc_value); |
| 361 Py_XDECREF(exc_tb); | 361 Py_XDECREF(exc_tb); |
| 362 return 0; | 362 return 0; |
| 363 } | 363 } |
| 364 } | 364 } |
| 365 else if (limit <= 0) { | 365 else if (limit <= 0) { |
| 366 limit = PyTraceBack_LIMIT; | 366 limit = PyTraceBack_LIMIT; |
| 367 } | 367 } |
| 368 PyErr_Restore(exc_type, exc_value, exc_tb); | 368 PyErr_Restore(exc_type, exc_value, exc_tb); |
| 369 } | 369 } |
| 370 err = PyFile_WriteString("Traceback (most recent call last):\n", f); | 370 err = PyFile_WriteString("Traceback (most recent call last):\n", f); |
| 371 if (!err) | 371 if (!err) |
| 372 err = tb_printinternal((PyTracebackObject *)v, f, limit); | 372 err = tb_printinternal((PyTracebackObject *)v, f, limit); |
| 373 return err; | 373 return err; |
| 374 } | 374 } |
