blob: 06fcc5382005afe60e3ba9942c2eb953901b4bcc [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
Guido van Rossum3f5da241990-12-20 15:06:42 +0000120int
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000121PyTraceBack_Here(frame)
122 PyFrameObject *frame;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000123{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000124 PyThreadState *tstate = frame->f_tstate;
125 tracebackobject *oldtb = (tracebackobject *) tstate->curexc_traceback;
126 tracebackobject *tb = newtracebackobject(oldtb,
127 frame, frame->f_lasti, frame->f_lineno);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000128 if (tb == NULL)
129 return -1;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000130 tstate->curexc_traceback = (PyObject *)tb;
131 Py_XDECREF(oldtb);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000132 return 0;
133}
134
135static void
Guido van Rossum13836d91994-08-29 12:09:58 +0000136tb_displayline(f, filename, lineno, name)
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000137 PyObject *f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000138 char *filename;
139 int lineno;
Guido van Rossum13836d91994-08-29 12:09:58 +0000140 char *name;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000141{
142 FILE *xfp;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000143 char linebuf[1000];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000144 int i;
Guido van Rossum13836d91994-08-29 12:09:58 +0000145#ifdef MPW
146 /* This is needed by MPW's File and Line commands */
147#define FMT " File \"%.900s\"; line %d # in %s\n"
148#else
149 /* This is needed by Emacs' compile command */
150#define FMT " File \"%.900s\", line %d, in %s\n"
151#endif
Guido van Rossum3f5da241990-12-20 15:06:42 +0000152 xfp = fopen(filename, "r");
153 if (xfp == NULL) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000154 /* Search tail of filename in sys.path before giving up */
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000155 PyObject *path;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000156 char *tail = strrchr(filename, SEP);
157 if (tail == NULL)
158 tail = filename;
159 else
160 tail++;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000161 path = PySys_GetObject("path");
162 if (path != NULL && PyList_Check(path)) {
163 int npath = PyList_Size(path);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000164 int taillen = strlen(tail);
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000165 char namebuf[MAXPATHLEN+1];
166 for (i = 0; i < npath; i++) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000167 PyObject *v = PyList_GetItem(path, i);
168 if (PyString_Check(v)) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000169 int len;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000170 len = PyString_Size(v);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000171 if (len + 1 + taillen >= MAXPATHLEN)
172 continue; /* Too long */
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000173 strcpy(namebuf, PyString_AsString(v));
Guido van Rossum6bf62da1997-04-11 20:37:35 +0000174 if ((int)strlen(namebuf) != len)
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000175 continue; /* v contains '\0' */
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000176 if (len > 0 && namebuf[len-1] != SEP)
177 namebuf[len++] = SEP;
178 strcpy(namebuf+len, tail);
179 xfp = fopen(namebuf, "r");
180 if (xfp != NULL) {
181 filename = namebuf;
182 break;
183 }
184 }
185 }
186 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000187 }
Guido van Rossum13836d91994-08-29 12:09:58 +0000188 sprintf(linebuf, FMT, filename, lineno, name);
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000189 PyFile_WriteString(linebuf, f);
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000190 if (xfp == NULL)
191 return;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000192 for (i = 0; i < lineno; i++) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000193 if (fgets(linebuf, sizeof linebuf, xfp) == NULL)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000194 break;
195 }
196 if (i == lineno) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000197 char *p = linebuf;
Guido van Rossume78c5d01995-07-07 22:45:41 +0000198 while (*p == ' ' || *p == '\t' || *p == '\014')
Guido van Rossum3f5da241990-12-20 15:06:42 +0000199 p++;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000200 PyFile_WriteString(" ", f);
201 PyFile_WriteString(p, f);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000202 if (strchr(p, '\n') == NULL)
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000203 PyFile_WriteString("\n", f);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000204 }
205 fclose(xfp);
206}
207
208static void
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000209tb_printinternal(tb, f, limit)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000210 tracebackobject *tb;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000211 PyObject *f;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000212 int limit;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000213{
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000214 int depth = 0;
215 tracebackobject *tb1 = tb;
216 while (tb1 != NULL) {
217 depth++;
218 tb1 = tb1->tb_next;
219 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000220 while (tb != NULL && !PyOS_InterruptOccurred()) {
Guido van Rossumb3f515a1997-01-24 04:02:55 +0000221 if (depth <= limit) {
Guido van Rossum73237c51997-05-05 20:53:25 +0000222 if (Py_OptimizeFlag)
223 tb->tb_lineno = PyCode_Addr2Line(
224 tb->tb_frame->f_code, tb->tb_lasti);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000225 tb_displayline(f,
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000226 PyString_AsString(
227 tb->tb_frame->f_code->co_filename),
Guido van Rossum13836d91994-08-29 12:09:58 +0000228 tb->tb_lineno,
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000229 PyString_AsString(tb->tb_frame->f_code->co_name));
Guido van Rossumb3f515a1997-01-24 04:02:55 +0000230 }
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000231 depth--;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000232 tb = tb->tb_next;
233 }
234}
235
236int
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000237PyTraceBack_Print(v, f)
238 PyObject *v;
239 PyObject *f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000240{
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000241 PyObject *limitv;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000242 int limit = 1000;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000243 if (v == NULL)
244 return 0;
245 if (!is_tracebackobject(v)) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000246 PyErr_BadInternalCall();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000247 return -1;
248 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000249 limitv = PySys_GetObject("tracebacklimit");
250 if (limitv && PyInt_Check(limitv)) {
251 limit = PyInt_AsLong(limitv);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000252 if (limit <= 0)
253 return 0;
254 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000255 PyFile_WriteString("Traceback (innermost last):\n", f);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000256 tb_printinternal((tracebackobject *)v, f, limit);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000257 return 0;
258}