blob: 9633db15d96f49d1c53bdb23db1209c3acc64546 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossumf70e43a1991-02-19 12:39:46 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossumf70e43a1991-02-19 12:39:46 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossumf70e43a1991-02-19 12:39:46 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossumf70e43a1991-02-19 12:39:46 +000029
30******************************************************************/
31
Guido van Rossum3f5da241990-12-20 15:06:42 +000032/* Traceback implementation */
33
Guido van Rossum65bf9f21997-04-29 18:33:38 +000034#include "Python.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000035
36#include "compile.h"
37#include "frameobject.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000038#include "structmember.h"
Guido van Rossum7169dbb1992-02-26 15:17:59 +000039#include "osdefs.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000040
41typedef struct _tracebackobject {
Guido van Rossum65bf9f21997-04-29 18:33:38 +000042 PyObject_HEAD
Guido van Rossum3f5da241990-12-20 15:06:42 +000043 struct _tracebackobject *tb_next;
Guido van Rossum65bf9f21997-04-29 18:33:38 +000044 PyFrameObject *tb_frame;
Guido van Rossum3f5da241990-12-20 15:06:42 +000045 int tb_lasti;
46 int tb_lineno;
47} tracebackobject;
48
49#define OFF(x) offsetof(tracebackobject, x)
50
51static struct memberlist tb_memberlist[] = {
52 {"tb_next", T_OBJECT, OFF(tb_next)},
53 {"tb_frame", T_OBJECT, OFF(tb_frame)},
54 {"tb_lasti", T_INT, OFF(tb_lasti)},
55 {"tb_lineno", T_INT, OFF(tb_lineno)},
56 {NULL} /* Sentinel */
57};
58
Guido van Rossum65bf9f21997-04-29 18:33:38 +000059static PyObject *
Guido van Rossum3f5da241990-12-20 15:06:42 +000060tb_getattr(tb, name)
61 tracebackobject *tb;
62 char *name;
63{
Guido van Rossum65bf9f21997-04-29 18:33:38 +000064 return PyMember_Get((char *)tb, tb_memberlist, name);
Guido van Rossum3f5da241990-12-20 15:06:42 +000065}
66
67static void
68tb_dealloc(tb)
69 tracebackobject *tb;
70{
Guido van Rossum65bf9f21997-04-29 18:33:38 +000071 Py_XDECREF(tb->tb_next);
72 Py_XDECREF(tb->tb_frame);
73 PyMem_DEL(tb);
Guido van Rossum3f5da241990-12-20 15:06:42 +000074}
75
Guido van Rossum9d78d8d1995-09-18 21:29:36 +000076#define Tracebacktype PyTraceBack_Type
77#define is_tracebackobject PyTraceBack_Check
Guido van Rossum681d79a1995-07-18 14:51:37 +000078
Guido van Rossum65bf9f21997-04-29 18:33:38 +000079PyTypeObject Tracebacktype = {
80 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum3f5da241990-12-20 15:06:42 +000081 0,
82 "traceback",
83 sizeof(tracebackobject),
84 0,
Guido van Rossum13836d91994-08-29 12:09:58 +000085 (destructor)tb_dealloc, /*tp_dealloc*/
Guido van Rossum3f5da241990-12-20 15:06:42 +000086 0, /*tp_print*/
Guido van Rossum13836d91994-08-29 12:09:58 +000087 (getattrfunc)tb_getattr, /*tp_getattr*/
Guido van Rossum3f5da241990-12-20 15:06:42 +000088 0, /*tp_setattr*/
89 0, /*tp_compare*/
90 0, /*tp_repr*/
91 0, /*tp_as_number*/
92 0, /*tp_as_sequence*/
93 0, /*tp_as_mapping*/
94};
95
Guido van Rossum3f5da241990-12-20 15:06:42 +000096static tracebackobject *
97newtracebackobject(next, frame, lasti, lineno)
98 tracebackobject *next;
Guido van Rossum65bf9f21997-04-29 18:33:38 +000099 PyFrameObject *frame;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000100 int lasti, lineno;
101{
102 tracebackobject *tb;
103 if ((next != NULL && !is_tracebackobject(next)) ||
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000104 frame == NULL || !PyFrame_Check(frame)) {
105 PyErr_BadInternalCall();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000106 return NULL;
107 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000108 tb = PyObject_NEW(tracebackobject, &Tracebacktype);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000109 if (tb != NULL) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000110 Py_XINCREF(next);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000111 tb->tb_next = next;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000112 Py_XINCREF(frame);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000113 tb->tb_frame = frame;
114 tb->tb_lasti = lasti;
115 tb->tb_lineno = lineno;
116 }
117 return tb;
118}
119
120static tracebackobject *tb_current = NULL;
121
122int
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000123PyTraceBack_Here(frame)
124 PyFrameObject *frame;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000125{
126 tracebackobject *tb;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000127 tb = newtracebackobject(tb_current, frame,
128 frame->f_lasti, frame->f_lineno);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000129 if (tb == NULL)
130 return -1;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000131 Py_XDECREF(tb_current);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000132 tb_current = tb;
133 return 0;
134}
135
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000136PyObject *
137PyTraceBack_Fetch()
Guido van Rossum3f5da241990-12-20 15:06:42 +0000138{
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000139 PyObject *v;
140 v = (PyObject *)tb_current;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000141 tb_current = NULL;
142 return v;
143}
144
145int
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000146PyTraceBack_Store(v)
147 PyObject *v;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000148{
149 if (v != NULL && !is_tracebackobject(v)) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000150 PyErr_BadInternalCall();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000151 return -1;
152 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000153 Py_XDECREF(tb_current);
154 Py_XINCREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000155 tb_current = (tracebackobject *)v;
156 return 0;
157}
158
159static void
Guido van Rossum13836d91994-08-29 12:09:58 +0000160tb_displayline(f, filename, lineno, name)
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000161 PyObject *f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000162 char *filename;
163 int lineno;
Guido van Rossum13836d91994-08-29 12:09:58 +0000164 char *name;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000165{
166 FILE *xfp;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000167 char linebuf[1000];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000168 int i;
Guido van Rossum13836d91994-08-29 12:09:58 +0000169#ifdef MPW
170 /* This is needed by MPW's File and Line commands */
171#define FMT " File \"%.900s\"; line %d # in %s\n"
172#else
173 /* This is needed by Emacs' compile command */
174#define FMT " File \"%.900s\", line %d, in %s\n"
175#endif
Guido van Rossum3f5da241990-12-20 15:06:42 +0000176 xfp = fopen(filename, "r");
177 if (xfp == NULL) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000178 /* Search tail of filename in sys.path before giving up */
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000179 PyObject *path;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000180 char *tail = strrchr(filename, SEP);
181 if (tail == NULL)
182 tail = filename;
183 else
184 tail++;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000185 path = PySys_GetObject("path");
186 if (path != NULL && PyList_Check(path)) {
187 int npath = PyList_Size(path);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000188 int taillen = strlen(tail);
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000189 char namebuf[MAXPATHLEN+1];
190 for (i = 0; i < npath; i++) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000191 PyObject *v = PyList_GetItem(path, i);
192 if (PyString_Check(v)) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000193 int len;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000194 len = PyString_Size(v);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000195 if (len + 1 + taillen >= MAXPATHLEN)
196 continue; /* Too long */
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000197 strcpy(namebuf, PyString_AsString(v));
Guido van Rossum6bf62da1997-04-11 20:37:35 +0000198 if ((int)strlen(namebuf) != len)
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000199 continue; /* v contains '\0' */
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000200 if (len > 0 && namebuf[len-1] != SEP)
201 namebuf[len++] = SEP;
202 strcpy(namebuf+len, tail);
203 xfp = fopen(namebuf, "r");
204 if (xfp != NULL) {
205 filename = namebuf;
206 break;
207 }
208 }
209 }
210 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000211 }
Guido van Rossum13836d91994-08-29 12:09:58 +0000212 sprintf(linebuf, FMT, filename, lineno, name);
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000213 PyFile_WriteString(linebuf, f);
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000214 if (xfp == NULL)
215 return;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000216 for (i = 0; i < lineno; i++) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000217 if (fgets(linebuf, sizeof linebuf, xfp) == NULL)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000218 break;
219 }
220 if (i == lineno) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000221 char *p = linebuf;
Guido van Rossume78c5d01995-07-07 22:45:41 +0000222 while (*p == ' ' || *p == '\t' || *p == '\014')
Guido van Rossum3f5da241990-12-20 15:06:42 +0000223 p++;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000224 PyFile_WriteString(" ", f);
225 PyFile_WriteString(p, f);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000226 if (strchr(p, '\n') == NULL)
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000227 PyFile_WriteString("\n", f);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000228 }
229 fclose(xfp);
230}
231
232static void
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000233tb_printinternal(tb, f, limit)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000234 tracebackobject *tb;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000235 PyObject *f;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000236 int limit;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000237{
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000238 int depth = 0;
239 tracebackobject *tb1 = tb;
240 while (tb1 != NULL) {
241 depth++;
242 tb1 = tb1->tb_next;
243 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000244 while (tb != NULL && !PyOS_InterruptOccurred()) {
Guido van Rossumb3f515a1997-01-24 04:02:55 +0000245 if (depth <= limit) {
246 tb->tb_lineno = PyCode_Addr2Line(tb->tb_frame->f_code,
247 tb->tb_lasti);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000248 tb_displayline(f,
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000249 PyString_AsString(
250 tb->tb_frame->f_code->co_filename),
Guido van Rossum13836d91994-08-29 12:09:58 +0000251 tb->tb_lineno,
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000252 PyString_AsString(tb->tb_frame->f_code->co_name));
Guido van Rossumb3f515a1997-01-24 04:02:55 +0000253 }
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000254 depth--;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000255 tb = tb->tb_next;
256 }
257}
258
259int
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000260PyTraceBack_Print(v, f)
261 PyObject *v;
262 PyObject *f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000263{
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000264 PyObject *limitv;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000265 int limit = 1000;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000266 if (v == NULL)
267 return 0;
268 if (!is_tracebackobject(v)) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000269 PyErr_BadInternalCall();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000270 return -1;
271 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000272 limitv = PySys_GetObject("tracebacklimit");
273 if (limitv && PyInt_Check(limitv)) {
274 limit = PyInt_AsLong(limitv);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000275 if (limit <= 0)
276 return 0;
277 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000278 PyFile_WriteString("Traceback (innermost last):\n", f);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000279 tb_printinternal((tracebackobject *)v, f, limit);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000280 return 0;
281}