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