blob: ea99152ddfb2b05dc0895f350ded3ad2627c01b9 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum3f5da241990-12-20 15:06:42 +000025/* Traceback implementation */
26
27#include "allobjects.h"
28
Guido van Rossum7169dbb1992-02-26 15:17:59 +000029#include "sysmodule.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000030#include "compile.h"
31#include "frameobject.h"
32#include "traceback.h"
33#include "structmember.h"
Guido van Rossum7169dbb1992-02-26 15:17:59 +000034#include "osdefs.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000035
36typedef struct _tracebackobject {
37 OB_HEAD
38 struct _tracebackobject *tb_next;
39 frameobject *tb_frame;
40 int tb_lasti;
41 int tb_lineno;
42} tracebackobject;
43
44#define OFF(x) offsetof(tracebackobject, x)
45
46static 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)},
51 {NULL} /* Sentinel */
52};
53
54static object *
55tb_getattr(tb, name)
56 tracebackobject *tb;
57 char *name;
58{
59 return getmember((char *)tb, tb_memberlist, name);
60}
61
62static void
63tb_dealloc(tb)
64 tracebackobject *tb;
65{
66 XDECREF(tb->tb_next);
67 XDECREF(tb->tb_frame);
68 DEL(tb);
69}
70
71static typeobject Tracebacktype = {
72 OB_HEAD_INIT(&Typetype)
73 0,
74 "traceback",
75 sizeof(tracebackobject),
76 0,
77 tb_dealloc, /*tp_dealloc*/
78 0, /*tp_print*/
79 tb_getattr, /*tp_getattr*/
80 0, /*tp_setattr*/
81 0, /*tp_compare*/
82 0, /*tp_repr*/
83 0, /*tp_as_number*/
84 0, /*tp_as_sequence*/
85 0, /*tp_as_mapping*/
86};
87
88#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
89
90static tracebackobject *
91newtracebackobject(next, frame, lasti, lineno)
92 tracebackobject *next;
93 frameobject *frame;
94 int lasti, lineno;
95{
96 tracebackobject *tb;
97 if ((next != NULL && !is_tracebackobject(next)) ||
98 frame == NULL || !is_frameobject(frame)) {
99 err_badcall();
100 return NULL;
101 }
102 tb = NEWOBJ(tracebackobject, &Tracebacktype);
103 if (tb != NULL) {
104 XINCREF(next);
105 tb->tb_next = next;
106 XINCREF(frame);
107 tb->tb_frame = frame;
108 tb->tb_lasti = lasti;
109 tb->tb_lineno = lineno;
110 }
111 return tb;
112}
113
114static tracebackobject *tb_current = NULL;
115
116int
Guido van Rossumc6515d11992-01-14 18:44:48 +0000117tb_here(frame)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000118 frameobject *frame;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000119{
120 tracebackobject *tb;
Guido van Rossumc6515d11992-01-14 18:44:48 +0000121 tb = newtracebackobject(tb_current, frame, frame->f_lasti, frame->f_lineno);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000122 if (tb == NULL)
123 return -1;
124 XDECREF(tb_current);
125 tb_current = tb;
126 return 0;
127}
128
129object *
130tb_fetch()
131{
132 object *v;
133 v = (object *)tb_current;
134 tb_current = NULL;
135 return v;
136}
137
138int
139tb_store(v)
140 object *v;
141{
142 if (v != NULL && !is_tracebackobject(v)) {
143 err_badcall();
144 return -1;
145 }
146 XDECREF(tb_current);
147 XINCREF(v);
148 tb_current = (tracebackobject *)v;
149 return 0;
150}
151
152static void
153tb_displayline(fp, filename, lineno)
154 FILE *fp;
155 char *filename;
156 int lineno;
157{
158 FILE *xfp;
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000159 char linebuf[1000];
Guido van Rossum3f5da241990-12-20 15:06:42 +0000160 int i;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000161 xfp = fopen(filename, "r");
162 if (xfp == NULL) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000163 /* Search tail of filename in sys.path before giving up */
164 object *path;
165 char *tail = strrchr(filename, SEP);
166 if (tail == NULL)
167 tail = filename;
168 else
169 tail++;
170 path = sysget("path");
171 if (path != NULL && is_listobject(path)) {
172 int npath = getlistsize(path);
173 char namebuf[MAXPATHLEN+1];
174 for (i = 0; i < npath; i++) {
175 object *v = getlistitem(path, i);
176 if (is_stringobject(v)) {
177 int len;
178 strcpy(namebuf, getstringvalue(v));
179 len = getstringsize(v);
180 if (len > 0 && namebuf[len-1] != SEP)
181 namebuf[len++] = SEP;
182 strcpy(namebuf+len, tail);
183 xfp = fopen(namebuf, "r");
184 if (xfp != NULL) {
185 filename = namebuf;
186 break;
187 }
188 }
189 }
190 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000191 }
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000192 fprintf(fp, " File \"%s\"", filename);
193#ifdef applec /* MPW */
194 /* This is needed by MPW's File and Line commands */
195 fprintf(fp, "; ");
196#else
197 /* This is needed by Emacs' compile command */
198 fprintf(fp, ", ");
199#endif
200 fprintf(fp, "line %d\n", lineno);
201 if (xfp == NULL)
202 return;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000203 for (i = 0; i < lineno; i++) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000204 if (fgets(linebuf, sizeof linebuf, xfp) == NULL)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000205 break;
206 }
207 if (i == lineno) {
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000208 char *p = linebuf;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000209 while (*p == ' ' || *p == '\t')
210 p++;
211 fprintf(fp, " %s", p);
212 if (strchr(p, '\n') == NULL)
213 fprintf(fp, "\n");
214 }
215 fclose(xfp);
216}
217
218static void
219tb_printinternal(tb, fp)
220 tracebackobject *tb;
221 FILE *fp;
222{
Guido van Rossum7169dbb1992-02-26 15:17:59 +0000223 while (tb != NULL && !intrcheck()) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000224 tb_displayline(fp,
225 getstringvalue(tb->tb_frame->f_code->co_filename),
226 tb->tb_lineno);
227 tb = tb->tb_next;
228 }
229}
230
231int
232tb_print(v, fp)
233 object *v;
234 FILE *fp;
235{
236 if (v == NULL)
237 return 0;
238 if (!is_tracebackobject(v)) {
239 err_badcall();
240 return -1;
241 }
242 sysset("last_traceback", v);
243 tb_printinternal((tracebackobject *)v, fp);
244 return 0;
245}