blob: 3f80ef5e56c882f2d4d7c7500360fccc578a84b3 [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
34#include "allobjects.h"
35
Guido van Rossum7169dbb1992-02-26 15:17:59 +000036#include "sysmodule.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000037#include "compile.h"
38#include "frameobject.h"
39#include "traceback.h"
40#include "structmember.h"
Guido van Rossum7169dbb1992-02-26 15:17:59 +000041#include "osdefs.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000042
43typedef struct _tracebackobject {
44 OB_HEAD
45 struct _tracebackobject *tb_next;
46 frameobject *tb_frame;
47 int tb_lasti;
48 int tb_lineno;
49} tracebackobject;
50
51#define OFF(x) offsetof(tracebackobject, x)
52
53static struct memberlist tb_memberlist[] = {
54 {"tb_next", T_OBJECT, OFF(tb_next)},
55 {"tb_frame", T_OBJECT, OFF(tb_frame)},
56 {"tb_lasti", T_INT, OFF(tb_lasti)},
57 {"tb_lineno", T_INT, OFF(tb_lineno)},
58 {NULL} /* Sentinel */
59};
60
61static object *
62tb_getattr(tb, name)
63 tracebackobject *tb;
64 char *name;
65{
66 return getmember((char *)tb, tb_memberlist, name);
67}
68
69static void
70tb_dealloc(tb)
71 tracebackobject *tb;
72{
73 XDECREF(tb->tb_next);
74 XDECREF(tb->tb_frame);
75 DEL(tb);
76}
77
Guido van Rossum9d78d8d1995-09-18 21:29:36 +000078#define Tracebacktype PyTraceBack_Type
79#define is_tracebackobject PyTraceBack_Check
Guido van Rossum681d79a1995-07-18 14:51:37 +000080
81typeobject Tracebacktype = {
Guido van Rossum3f5da241990-12-20 15:06:42 +000082 OB_HEAD_INIT(&Typetype)
83 0,
84 "traceback",
85 sizeof(tracebackobject),
86 0,
Guido van Rossum13836d91994-08-29 12:09:58 +000087 (destructor)tb_dealloc, /*tp_dealloc*/
Guido van Rossum3f5da241990-12-20 15:06:42 +000088 0, /*tp_print*/
Guido van Rossum13836d91994-08-29 12:09:58 +000089 (getattrfunc)tb_getattr, /*tp_getattr*/
Guido van Rossum3f5da241990-12-20 15:06:42 +000090 0, /*tp_setattr*/
91 0, /*tp_compare*/
92 0, /*tp_repr*/
93 0, /*tp_as_number*/
94 0, /*tp_as_sequence*/
95 0, /*tp_as_mapping*/
96};
97
Guido van Rossum3f5da241990-12-20 15:06:42 +000098static tracebackobject *
99newtracebackobject(next, frame, lasti, lineno)
100 tracebackobject *next;
101 frameobject *frame;
102 int lasti, lineno;
103{
104 tracebackobject *tb;
105 if ((next != NULL && !is_tracebackobject(next)) ||
106 frame == NULL || !is_frameobject(frame)) {
107 err_badcall();
108 return NULL;
109 }
110 tb = NEWOBJ(tracebackobject, &Tracebacktype);
111 if (tb != NULL) {
112 XINCREF(next);
113 tb->tb_next = next;
114 XINCREF(frame);
115 tb->tb_frame = frame;
116 tb->tb_lasti = lasti;
117 tb->tb_lineno = lineno;
118 }
119 return tb;
120}
121
122static tracebackobject *tb_current = NULL;
123
124int
Guido van Rossumc6515d11992-01-14 18:44:48 +0000125tb_here(frame)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000126 frameobject *frame;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000127{
128 tracebackobject *tb;
Guido van Rossumc6515d11992-01-14 18:44:48 +0000129 tb = newtracebackobject(tb_current, frame, frame->f_lasti, frame->f_lineno);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000130 if (tb == NULL)
131 return -1;
132 XDECREF(tb_current);
133 tb_current = tb;
134 return 0;
135}
136
137object *
138tb_fetch()
139{
140 object *v;
141 v = (object *)tb_current;
142 tb_current = NULL;
143 return v;
144}
145
146int
147tb_store(v)
148 object *v;
149{
150 if (v != NULL && !is_tracebackobject(v)) {
151 err_badcall();
152 return -1;
153 }
154 XDECREF(tb_current);
155 XINCREF(v);
156 tb_current = (tracebackobject *)v;
157 return 0;
158}
159
160static void
Guido van Rossum13836d91994-08-29 12:09:58 +0000161tb_displayline(f, filename, lineno, name)
Guido van Rossum3165fe61992-09-25 21:59:05 +0000162 object *f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000163 char *filename;
164 int lineno;
Guido van Rossum13836d91994-08-29 12:09:58 +0000165 char *name;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000166{
167 FILE *xfp;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000168 char linebuf[1000];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000169 int i;
Guido van Rossum13836d91994-08-29 12:09:58 +0000170#ifdef MPW
171 /* This is needed by MPW's File and Line commands */
172#define FMT " File \"%.900s\"; line %d # in %s\n"
173#else
174 /* This is needed by Emacs' compile command */
175#define FMT " File \"%.900s\", line %d, in %s\n"
176#endif
Guido van Rossum3f5da241990-12-20 15:06:42 +0000177 xfp = fopen(filename, "r");
178 if (xfp == NULL) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000179 /* Search tail of filename in sys.path before giving up */
180 object *path;
181 char *tail = strrchr(filename, SEP);
182 if (tail == NULL)
183 tail = filename;
184 else
185 tail++;
186 path = sysget("path");
187 if (path != NULL && is_listobject(path)) {
188 int npath = getlistsize(path);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000189 int taillen = strlen(tail);
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000190 char namebuf[MAXPATHLEN+1];
191 for (i = 0; i < npath; i++) {
192 object *v = getlistitem(path, i);
193 if (is_stringobject(v)) {
194 int len;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000195 len = getstringsize(v);
Guido van Rossumbfd5d7551994-09-29 09:38:04 +0000196 if (len + 1 + taillen >= MAXPATHLEN)
197 continue; /* Too long */
198 strcpy(namebuf, getstringvalue(v));
199 if (strlen(namebuf) != len)
200 continue; /* v contains '\0' */
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000201 if (len > 0 && namebuf[len-1] != SEP)
202 namebuf[len++] = SEP;
203 strcpy(namebuf+len, tail);
204 xfp = fopen(namebuf, "r");
205 if (xfp != NULL) {
206 filename = namebuf;
207 break;
208 }
209 }
210 }
211 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000212 }
Guido van Rossum13836d91994-08-29 12:09:58 +0000213 sprintf(linebuf, FMT, filename, lineno, name);
Guido van Rossum3165fe61992-09-25 21:59:05 +0000214 writestring(linebuf, f);
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000215 if (xfp == NULL)
216 return;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000217 for (i = 0; i < lineno; i++) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000218 if (fgets(linebuf, sizeof linebuf, xfp) == NULL)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000219 break;
220 }
221 if (i == lineno) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000222 char *p = linebuf;
Guido van Rossume78c5d01995-07-07 22:45:41 +0000223 while (*p == ' ' || *p == '\t' || *p == '\014')
Guido van Rossum3f5da241990-12-20 15:06:42 +0000224 p++;
Guido van Rossum3165fe61992-09-25 21:59:05 +0000225 writestring(" ", f);
226 writestring(p, f);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000227 if (strchr(p, '\n') == NULL)
Guido van Rossum3165fe61992-09-25 21:59:05 +0000228 writestring("\n", f);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000229 }
230 fclose(xfp);
231}
232
233static void
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000234tb_printinternal(tb, f, limit)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000235 tracebackobject *tb;
Guido van Rossum3165fe61992-09-25 21:59:05 +0000236 object *f;
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000237 int limit;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000238{
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000239 int depth = 0;
240 tracebackobject *tb1 = tb;
241 while (tb1 != NULL) {
242 depth++;
243 tb1 = tb1->tb_next;
244 }
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000245 while (tb != NULL && !intrcheck()) {
Guido van Rossumb3f515a1997-01-24 04:02:55 +0000246 if (depth <= limit) {
247 tb->tb_lineno = PyCode_Addr2Line(tb->tb_frame->f_code,
248 tb->tb_lasti);
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000249 tb_displayline(f,
250 getstringvalue(tb->tb_frame->f_code->co_filename),
Guido van Rossum13836d91994-08-29 12:09:58 +0000251 tb->tb_lineno,
252 getstringvalue(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 Rossum3165fe61992-09-25 21:59:05 +0000260tb_print(v, f)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000261 object *v;
Guido van Rossum3165fe61992-09-25 21:59:05 +0000262 object *f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000263{
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000264 object *limitv;
265 int limit = 1000;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000266 if (v == NULL)
267 return 0;
268 if (!is_tracebackobject(v)) {
269 err_badcall();
270 return -1;
271 }
Guido van Rossum67a5fdb1993-12-17 12:09:14 +0000272 limitv = sysget("tracebacklimit");
273 if (limitv && is_intobject(limitv)) {
274 limit = getintvalue(limitv);
275 if (limit <= 0)
276 return 0;
277 }
278 writestring("Traceback (innermost last):\n", f);
279 tb_printinternal((tracebackobject *)v, f, limit);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000280 return 0;
281}