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