Don't reference removed files in Makefile
[python/dscho.git] / Python / traceback.c
blobbea0b19b57e7608d389474f8e1342603b3d30590
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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"
30 #include "compile.h"
31 #include "frameobject.h"
32 #include "traceback.h"
33 #include "structmember.h"
34 #include "osdefs.h"
36 typedef struct _tracebackobject {
37 OB_HEAD
38 struct _tracebackobject *tb_next;
39 frameobject *tb_frame;
40 int tb_lasti;
41 int tb_lineno;
42 } tracebackobject;
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)},
51 {NULL} /* Sentinel */
54 static object *
55 tb_getattr(tb, name)
56 tracebackobject *tb;
57 char *name;
59 return getmember((char *)tb, tb_memberlist, name);
62 static void
63 tb_dealloc(tb)
64 tracebackobject *tb;
66 XDECREF(tb->tb_next);
67 XDECREF(tb->tb_frame);
68 DEL(tb);
71 static typeobject Tracebacktype = {
72 OB_HEAD_INIT(&Typetype)
74 "traceback",
75 sizeof(tracebackobject),
77 (destructor)tb_dealloc, /*tp_dealloc*/
78 0, /*tp_print*/
79 (getattrfunc)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*/
88 #define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
90 static tracebackobject *
91 newtracebackobject(next, frame, lasti, lineno)
92 tracebackobject *next;
93 frameobject *frame;
94 int lasti, lineno;
96 tracebackobject *tb;
97 if ((next != NULL && !is_tracebackobject(next)) ||
98 frame == NULL || !is_frameobject(frame)) {
99 err_badcall();
100 return NULL;
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;
111 return tb;
114 static tracebackobject *tb_current = NULL;
117 tb_here(frame)
118 frameobject *frame;
120 tracebackobject *tb;
121 tb = newtracebackobject(tb_current, frame, frame->f_lasti, frame->f_lineno);
122 if (tb == NULL)
123 return -1;
124 XDECREF(tb_current);
125 tb_current = tb;
126 return 0;
129 object *
130 tb_fetch()
132 object *v;
133 v = (object *)tb_current;
134 tb_current = NULL;
135 return v;
139 tb_store(v)
140 object *v;
142 if (v != NULL && !is_tracebackobject(v)) {
143 err_badcall();
144 return -1;
146 XDECREF(tb_current);
147 XINCREF(v);
148 tb_current = (tracebackobject *)v;
149 return 0;
152 static void
153 tb_displayline(f, filename, lineno, name)
154 object *f;
155 char *filename;
156 int lineno;
157 char *name;
159 FILE *xfp;
160 char linebuf[1000];
161 int i;
162 #ifdef MPW
163 /* This is needed by MPW's File and Line commands */
164 #define FMT " File \"%.900s\"; line %d # in %s\n"
165 #else
166 /* This is needed by Emacs' compile command */
167 #define FMT " File \"%.900s\", line %d, in %s\n"
168 #endif
169 xfp = fopen(filename, "r");
170 if (xfp == NULL) {
171 /* Search tail of filename in sys.path before giving up */
172 object *path;
173 char *tail = strrchr(filename, SEP);
174 if (tail == NULL)
175 tail = filename;
176 else
177 tail++;
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)) {
186 int len;
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");
197 if (xfp != NULL) {
198 filename = namebuf;
199 break;
205 sprintf(linebuf, FMT, filename, lineno, name);
206 writestring(linebuf, f);
207 if (xfp == NULL)
208 return;
209 for (i = 0; i < lineno; i++) {
210 if (fgets(linebuf, sizeof linebuf, xfp) == NULL)
211 break;
213 if (i == lineno) {
214 char *p = linebuf;
215 while (*p == ' ' || *p == '\t')
216 p++;
217 writestring(" ", f);
218 writestring(p, f);
219 if (strchr(p, '\n') == NULL)
220 writestring("\n", f);
222 fclose(xfp);
225 static void
226 tb_printinternal(tb, f, limit)
227 tracebackobject *tb;
228 object *f;
229 int limit;
231 int depth = 0;
232 tracebackobject *tb1 = tb;
233 while (tb1 != NULL) {
234 depth++;
235 tb1 = tb1->tb_next;
237 while (tb != NULL && !intrcheck()) {
238 if (depth <= limit)
239 tb_displayline(f,
240 getstringvalue(tb->tb_frame->f_code->co_filename),
241 tb->tb_lineno,
242 getstringvalue(tb->tb_frame->f_code->co_name));
243 depth--;
244 tb = tb->tb_next;
249 tb_print(v, f)
250 object *v;
251 object *f;
253 object *limitv;
254 int limit = 1000;
255 if (v == NULL)
256 return 0;
257 if (!is_tracebackobject(v)) {
258 err_badcall();
259 return -1;
261 limitv = sysget("tracebacklimit");
262 if (limitv && is_intobject(limitv)) {
263 limit = getintvalue(limitv);
264 if (limit <= 0)
265 return 0;
267 writestring("Traceback (innermost last):\n", f);
268 tb_printinternal((tracebackobject *)v, f, limit);
269 return 0;