1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Traceback implementation */
27 #include "allobjects.h"
29 #include "sysmodule.h"
31 #include "frameobject.h"
32 #include "traceback.h"
33 #include "structmember.h"
36 typedef struct _tracebackobject
{
38 struct _tracebackobject
*tb_next
;
39 frameobject
*tb_frame
;
44 #define OFF(x) offsetof(tracebackobject, x)
46 static struct memberlist tb_memberlist
[] = {
47 {"tb_next", T_OBJECT
, OFF(tb_next
)},
48 {"tb_frame", T_OBJECT
, OFF(tb_frame
)},
49 {"tb_lasti", T_INT
, OFF(tb_lasti
)},
50 {"tb_lineno", T_INT
, OFF(tb_lineno
)},
59 return getmember((char *)tb
, tb_memberlist
, name
);
67 XDECREF(tb
->tb_frame
);
71 static typeobject Tracebacktype
= {
72 OB_HEAD_INIT(&Typetype
)
75 sizeof(tracebackobject
),
77 (destructor
)tb_dealloc
, /*tp_dealloc*/
79 (getattrfunc
)tb_getattr
, /*tp_getattr*/
88 #define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
90 static tracebackobject
*
91 newtracebackobject(next
, frame
, lasti
, lineno
)
92 tracebackobject
*next
;
97 if ((next
!= NULL
&& !is_tracebackobject(next
)) ||
98 frame
== NULL
|| !is_frameobject(frame
)) {
102 tb
= NEWOBJ(tracebackobject
, &Tracebacktype
);
107 tb
->tb_frame
= frame
;
108 tb
->tb_lasti
= lasti
;
109 tb
->tb_lineno
= lineno
;
114 static tracebackobject
*tb_current
= NULL
;
121 tb
= newtracebackobject(tb_current
, frame
, frame
->f_lasti
, frame
->f_lineno
);
133 v
= (object
*)tb_current
;
142 if (v
!= NULL
&& !is_tracebackobject(v
)) {
148 tb_current
= (tracebackobject
*)v
;
153 tb_displayline(f
, filename
, lineno
, name
)
163 /* This is needed by MPW's File and Line commands */
164 #define FMT " File \"%.900s\"; line %d # in %s\n"
166 /* This is needed by Emacs' compile command */
167 #define FMT " File \"%.900s\", line %d, in %s\n"
169 xfp
= fopen(filename
, "r");
171 /* Search tail of filename in sys.path before giving up */
173 char *tail
= strrchr(filename
, SEP
);
178 path
= sysget("path");
179 if (path
!= NULL
&& is_listobject(path
)) {
180 int npath
= getlistsize(path
);
181 int taillen
= strlen(tail
);
182 char namebuf
[MAXPATHLEN
+1];
183 for (i
= 0; i
< npath
; i
++) {
184 object
*v
= getlistitem(path
, i
);
185 if (is_stringobject(v
)) {
187 len
= getstringsize(v
);
188 if (len
+ 1 + taillen
>= MAXPATHLEN
)
189 continue; /* Too long */
190 strcpy(namebuf
, getstringvalue(v
));
191 if (strlen(namebuf
) != len
)
192 continue; /* v contains '\0' */
193 if (len
> 0 && namebuf
[len
-1] != SEP
)
194 namebuf
[len
++] = SEP
;
195 strcpy(namebuf
+len
, tail
);
196 xfp
= fopen(namebuf
, "r");
205 sprintf(linebuf
, FMT
, filename
, lineno
, name
);
206 writestring(linebuf
, f
);
209 for (i
= 0; i
< lineno
; i
++) {
210 if (fgets(linebuf
, sizeof linebuf
, xfp
) == NULL
)
215 while (*p
== ' ' || *p
== '\t')
219 if (strchr(p
, '\n') == NULL
)
220 writestring("\n", f
);
226 tb_printinternal(tb
, f
, limit
)
232 tracebackobject
*tb1
= tb
;
233 while (tb1
!= NULL
) {
237 while (tb
!= NULL
&& !intrcheck()) {
240 getstringvalue(tb
->tb_frame
->f_code
->co_filename
),
242 getstringvalue(tb
->tb_frame
->f_code
->co_name
));
257 if (!is_tracebackobject(v
)) {
261 limitv
= sysget("tracebacklimit");
262 if (limitv
&& is_intobject(limitv
)) {
263 limit
= getintvalue(limitv
);
267 writestring("Traceback (innermost last):\n", f
);
268 tb_printinternal((tracebackobject
*)v
, f
, limit
);