blob: f32dcf66f36719349c98767e28f6d69ea6c3b352 [file] [log] [blame]
Guido van Rossum3f5da241990-12-20 15:06:42 +00001/* 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
10typedef 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
20static 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
28static object *
29tb_getattr(tb, name)
30 tracebackobject *tb;
31 char *name;
32{
33 return getmember((char *)tb, tb_memberlist, name);
34}
35
36static void
37tb_dealloc(tb)
38 tracebackobject *tb;
39{
40 XDECREF(tb->tb_next);
41 XDECREF(tb->tb_frame);
42 DEL(tb);
43}
44
45static 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
64static tracebackobject *
65newtracebackobject(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
88static tracebackobject *tb_current = NULL;
89
90int
91tb_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
105object *
106tb_fetch()
107{
108 object *v;
109 v = (object *)tb_current;
110 tb_current = NULL;
111 return v;
112}
113
114int
115tb_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
128static void
129tb_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
159static void
160tb_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
179int
180tb_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}