|
145
|
1 /***********************************************************
|
|
|
2 Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
|
|
|
3 Netherlands.
|
|
|
4
|
|
|
5 All Rights Reserved
|
|
|
6
|
|
|
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.
|
|
|
14
|
|
|
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.
|
|
|
22
|
|
|
23 ******************************************************************/
|
|
|
24
|
|
86
|
25 /* Traceback implementation */
|
|
|
26
|
|
|
27 #include "allobjects.h"
|
|
|
28
|
|
|
29 #include "compile.h"
|
|
|
30 #include "frameobject.h"
|
|
|
31 #include "traceback.h"
|
|
|
32 #include "structmember.h"
|
|
|
33
|
|
|
34 typedef struct _tracebackobject {
|
|
|
35 OB_HEAD
|
|
|
36 struct _tracebackobject *tb_next;
|
|
|
37 frameobject *tb_frame;
|
|
|
38 int tb_lasti;
|
|
|
39 int tb_lineno;
|
|
|
40 } tracebackobject;
|
|
|
41
|
|
|
42 #define OFF(x) offsetof(tracebackobject, x)
|
|
|
43
|
|
|
44 static struct memberlist tb_memberlist[] = {
|
|
|
45 {"tb_next", T_OBJECT, OFF(tb_next)},
|
|
|
46 {"tb_frame", T_OBJECT, OFF(tb_frame)},
|
|
|
47 {"tb_lasti", T_INT, OFF(tb_lasti)},
|
|
|
48 {"tb_lineno", T_INT, OFF(tb_lineno)},
|
|
|
49 {NULL} /* Sentinel */
|
|
|
50 };
|
|
|
51
|
|
|
52 static object *
|
|
|
53 tb_getattr(tb, name)
|
|
|
54 tracebackobject *tb;
|
|
|
55 char *name;
|
|
|
56 {
|
|
|
57 return getmember((char *)tb, tb_memberlist, name);
|
|
|
58 }
|
|
|
59
|
|
|
60 static void
|
|
|
61 tb_dealloc(tb)
|
|
|
62 tracebackobject *tb;
|
|
|
63 {
|
|
|
64 XDECREF(tb->tb_next);
|
|
|
65 XDECREF(tb->tb_frame);
|
|
|
66 DEL(tb);
|
|
|
67 }
|
|
|
68
|
|
|
69 static typeobject Tracebacktype = {
|
|
|
70 OB_HEAD_INIT(&Typetype)
|
|
|
71 0,
|
|
|
72 "traceback",
|
|
|
73 sizeof(tracebackobject),
|
|
|
74 0,
|
|
|
75 tb_dealloc, /*tp_dealloc*/
|
|
|
76 0, /*tp_print*/
|
|
|
77 tb_getattr, /*tp_getattr*/
|
|
|
78 0, /*tp_setattr*/
|
|
|
79 0, /*tp_compare*/
|
|
|
80 0, /*tp_repr*/
|
|
|
81 0, /*tp_as_number*/
|
|
|
82 0, /*tp_as_sequence*/
|
|
|
83 0, /*tp_as_mapping*/
|
|
|
84 };
|
|
|
85
|
|
|
86 #define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
|
|
|
87
|
|
|
88 static tracebackobject *
|
|
|
89 newtracebackobject(next, frame, lasti, lineno)
|
|
|
90 tracebackobject *next;
|
|
|
91 frameobject *frame;
|
|
|
92 int lasti, lineno;
|
|
|
93 {
|
|
|
94 tracebackobject *tb;
|
|
|
95 if ((next != NULL && !is_tracebackobject(next)) ||
|
|
|
96 frame == NULL || !is_frameobject(frame)) {
|
|
|
97 err_badcall();
|
|
|
98 return NULL;
|
|
|
99 }
|
|
|
100 tb = NEWOBJ(tracebackobject, &Tracebacktype);
|
|
|
101 if (tb != NULL) {
|
|
|
102 XINCREF(next);
|
|
|
103 tb->tb_next = next;
|
|
|
104 XINCREF(frame);
|
|
|
105 tb->tb_frame = frame;
|
|
|
106 tb->tb_lasti = lasti;
|
|
|
107 tb->tb_lineno = lineno;
|
|
|
108 }
|
|
|
109 return tb;
|
|
|
110 }
|
|
|
111
|
|
|
112 static tracebackobject *tb_current = NULL;
|
|
|
113
|
|
|
114 int
|
|
|
115 tb_here(frame, lasti, lineno)
|
|
|
116 frameobject *frame;
|
|
|
117 int lasti;
|
|
|
118 int lineno;
|
|
|
119 {
|
|
|
120 tracebackobject *tb;
|
|
|
121 tb = newtracebackobject(tb_current, frame, lasti, lineno);
|
|
|
122 if (tb == NULL)
|
|
|
123 return -1;
|
|
|
124 XDECREF(tb_current);
|
|
|
125 tb_current = tb;
|
|
|
126 return 0;
|
|
|
127 }
|
|
|
128
|
|
|
129 object *
|
|
|
130 tb_fetch()
|
|
|
131 {
|
|
|
132 object *v;
|
|
|
133 v = (object *)tb_current;
|
|
|
134 tb_current = NULL;
|
|
|
135 return v;
|
|
|
136 }
|
|
|
137
|
|
|
138 int
|
|
|
139 tb_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
|
|
|
152 static void
|
|
|
153 tb_displayline(fp, filename, lineno)
|
|
|
154 FILE *fp;
|
|
|
155 char *filename;
|
|
|
156 int lineno;
|
|
|
157 {
|
|
|
158 FILE *xfp;
|
|
|
159 char buf[1000];
|
|
|
160 int i;
|
|
|
161 if (filename[0] == '<' && filename[strlen(filename)-1] == '>')
|
|
|
162 return;
|
|
|
163 xfp = fopen(filename, "r");
|
|
|
164 if (xfp == NULL) {
|
|
|
165 fprintf(fp, " (cannot open \"%s\")\n", filename);
|
|
|
166 return;
|
|
|
167 }
|
|
|
168 for (i = 0; i < lineno; i++) {
|
|
|
169 if (fgets(buf, sizeof buf, xfp) == NULL)
|
|
|
170 break;
|
|
|
171 }
|
|
|
172 if (i == lineno) {
|
|
|
173 char *p = buf;
|
|
|
174 while (*p == ' ' || *p == '\t')
|
|
|
175 p++;
|
|
|
176 fprintf(fp, " %s", p);
|
|
|
177 if (strchr(p, '\n') == NULL)
|
|
|
178 fprintf(fp, "\n");
|
|
|
179 }
|
|
|
180 fclose(xfp);
|
|
|
181 }
|
|
|
182
|
|
|
183 static void
|
|
|
184 tb_printinternal(tb, fp)
|
|
|
185 tracebackobject *tb;
|
|
|
186 FILE *fp;
|
|
|
187 {
|
|
|
188 while (tb != NULL) {
|
|
|
189 if (intrcheck()) {
|
|
|
190 fprintf(fp, "[interrupted]\n");
|
|
|
191 break;
|
|
|
192 }
|
|
|
193 fprintf(fp, " File \"");
|
|
|
194 printobject(tb->tb_frame->f_code->co_filename, fp, PRINT_RAW);
|
|
|
195 fprintf(fp, "\", line %d\n", tb->tb_lineno);
|
|
|
196 tb_displayline(fp,
|
|
|
197 getstringvalue(tb->tb_frame->f_code->co_filename),
|
|
|
198 tb->tb_lineno);
|
|
|
199 tb = tb->tb_next;
|
|
|
200 }
|
|
|
201 }
|
|
|
202
|
|
|
203 int
|
|
|
204 tb_print(v, fp)
|
|
|
205 object *v;
|
|
|
206 FILE *fp;
|
|
|
207 {
|
|
|
208 if (v == NULL)
|
|
|
209 return 0;
|
|
|
210 if (!is_tracebackobject(v)) {
|
|
|
211 err_badcall();
|
|
|
212 return -1;
|
|
|
213 }
|
|
|
214 sysset("last_traceback", v);
|
|
|
215 tb_printinternal((tracebackobject *)v, fp);
|
|
|
216 return 0;
|
|
|
217 }
|