blob: 53b84f307ea3e45e9220f582a414d618cc96255a [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
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000135static int
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{
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000142 int err = 0;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143 FILE *xfp;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000144 char linebuf[1000];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000145 int i;
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000146 if (filename == NULL || name == NULL)
147 return -1;
Guido van Rossum13836d91994-08-29 12:09:58 +0000148#ifdef MPW
149 /* This is needed by MPW's File and Line commands */
150#define FMT " File \"%.900s\"; line %d # in %s\n"
151#else
152 /* This is needed by Emacs' compile command */
153#define FMT " File \"%.900s\", line %d, in %s\n"
154#endif
Guido van Rossum3f5da241990-12-20 15:06:42 +0000155 xfp = fopen(filename, "r");
156 if (xfp == NULL) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000157 /* Search tail of filename in sys.path before giving up */
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000158 PyObject *path;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000159 char *tail = strrchr(filename, SEP);
160 if (tail == NULL)
161 tail = filename;
162 else
163 tail++;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000164 path = PySys_GetObject("path");
165 if (path != NULL && PyList_Check(path)) {
166 int npath = PyList_Size(path);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000167 int taillen = strlen(tail);
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000168 char namebuf[MAXPATHLEN+1];
169 for (i = 0; i < npath; i++) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000170 PyObject *v = PyList_GetItem(path, i);
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000171 if (v == NULL) {
172 PyErr_Clear();
173 break;
174 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000175 if (PyString_Check(v)) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000176 int len;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000177 len = PyString_Size(v);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000178 if (len + 1 + taillen >= MAXPATHLEN)
179 continue; /* Too long */
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000180 strcpy(namebuf, PyString_AsString(v));
Guido van Rossum6bf62da1997-04-11 20:37:35 +0000181 if ((int)strlen(namebuf) != len)
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000182 continue; /* v contains '\0' */
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000183 if (len > 0 && namebuf[len-1] != SEP)
184 namebuf[len++] = SEP;
185 strcpy(namebuf+len, tail);
186 xfp = fopen(namebuf, "r");
187 if (xfp != NULL) {
188 filename = namebuf;
189 break;
190 }
191 }
192 }
193 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000194 }
Guido van Rossum13836d91994-08-29 12:09:58 +0000195 sprintf(linebuf, FMT, filename, lineno, name);
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000196 err = PyFile_WriteString(linebuf, f);
197 if (xfp == NULL || err != 0)
198 return err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000199 for (i = 0; i < lineno; i++) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000200 if (fgets(linebuf, sizeof linebuf, xfp) == NULL)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000201 break;
202 }
203 if (i == lineno) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000204 char *p = linebuf;
Guido van Rossume78c5d01995-07-07 22:45:41 +0000205 while (*p == ' ' || *p == '\t' || *p == '\014')
Guido van Rossum3f5da241990-12-20 15:06:42 +0000206 p++;
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000207 err = PyFile_WriteString(" ", f);
208 if (err == 0) {
209 err = PyFile_WriteString(p, f);
210 if (err == 0 && strchr(p, '\n') == NULL)
211 err = PyFile_WriteString("\n", f);
212 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000213 }
214 fclose(xfp);
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000215 return err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000216}
217
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000218static int
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000219tb_printinternal(tb, f, limit)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000220 tracebackobject *tb;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000221 PyObject *f;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000222 int limit;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000223{
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000224 int err = 0;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000225 int depth = 0;
226 tracebackobject *tb1 = tb;
227 while (tb1 != NULL) {
228 depth++;
229 tb1 = tb1->tb_next;
230 }
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000231 while (tb != NULL && err == 0) {
Guido van Rossumb3f515a1997-01-24 04:02:55 +0000232 if (depth <= limit) {
Guido van Rossum73237c51997-05-05 20:53:25 +0000233 if (Py_OptimizeFlag)
234 tb->tb_lineno = PyCode_Addr2Line(
235 tb->tb_frame->f_code, tb->tb_lasti);
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000236 err = tb_displayline(f,
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000237 PyString_AsString(
238 tb->tb_frame->f_code->co_filename),
Guido van Rossum13836d91994-08-29 12:09:58 +0000239 tb->tb_lineno,
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000240 PyString_AsString(tb->tb_frame->f_code->co_name));
Guido van Rossumb3f515a1997-01-24 04:02:55 +0000241 }
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000242 depth--;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000243 tb = tb->tb_next;
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000244 if (err == 0)
245 err = PyErr_CheckSignals();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000246 }
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000247 return err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000248}
249
250int
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000251PyTraceBack_Print(v, f)
252 PyObject *v;
253 PyObject *f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000254{
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000255 int err;
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000256 PyObject *limitv;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000257 int limit = 1000;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000258 if (v == NULL)
259 return 0;
260 if (!is_tracebackobject(v)) {
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000261 PyErr_BadInternalCall();
Guido van Rossum3f5da241990-12-20 15:06:42 +0000262 return -1;
263 }
Guido van Rossum65bf9f21997-04-29 18:33:38 +0000264 limitv = PySys_GetObject("tracebacklimit");
265 if (limitv && PyInt_Check(limitv)) {
266 limit = PyInt_AsLong(limitv);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000267 if (limit <= 0)
268 return 0;
269 }
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000270 err = PyFile_WriteString("Traceback (innermost last):\n", f);
271 if (!err)
272 err = tb_printinternal((tracebackobject *)v, f, limit);
273 return err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000274}