diff options
Diffstat (limited to 'Python/traceback.c')
-rw-r--r-- | Python/traceback.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/Python/traceback.c b/Python/traceback.c new file mode 100644 index 0000000..f32dcf6 --- /dev/null +++ b/Python/traceback.c @@ -0,0 +1,193 @@ +/* Traceback implementation */ + +#include "allobjects.h" + +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +#include "structmember.h" + +typedef struct _tracebackobject { + OB_HEAD + struct _tracebackobject *tb_next; + frameobject *tb_frame; + int tb_lasti; + int tb_lineno; +} tracebackobject; + +#define OFF(x) offsetof(tracebackobject, x) + +static struct memberlist tb_memberlist[] = { + {"tb_next", T_OBJECT, OFF(tb_next)}, + {"tb_frame", T_OBJECT, OFF(tb_frame)}, + {"tb_lasti", T_INT, OFF(tb_lasti)}, + {"tb_lineno", T_INT, OFF(tb_lineno)}, + {NULL} /* Sentinel */ +}; + +static object * +tb_getattr(tb, name) + tracebackobject *tb; + char *name; +{ + return getmember((char *)tb, tb_memberlist, name); +} + +static void +tb_dealloc(tb) + tracebackobject *tb; +{ + XDECREF(tb->tb_next); + XDECREF(tb->tb_frame); + DEL(tb); +} + +static typeobject Tracebacktype = { + OB_HEAD_INIT(&Typetype) + 0, + "traceback", + sizeof(tracebackobject), + 0, + tb_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + tb_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; + +#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype) + +static tracebackobject * +newtracebackobject(next, frame, lasti, lineno) + tracebackobject *next; + frameobject *frame; + int lasti, lineno; +{ + tracebackobject *tb; + if ((next != NULL && !is_tracebackobject(next)) || + frame == NULL || !is_frameobject(frame)) { + err_badcall(); + return NULL; + } + tb = NEWOBJ(tracebackobject, &Tracebacktype); + if (tb != NULL) { + XINCREF(next); + tb->tb_next = next; + XINCREF(frame); + tb->tb_frame = frame; + tb->tb_lasti = lasti; + tb->tb_lineno = lineno; + } + return tb; +} + +static tracebackobject *tb_current = NULL; + +int +tb_here(frame, lasti, lineno) + frameobject *frame; + int lasti; + int lineno; +{ + tracebackobject *tb; + tb = newtracebackobject(tb_current, frame, lasti, lineno); + if (tb == NULL) + return -1; + XDECREF(tb_current); + tb_current = tb; + return 0; +} + +object * +tb_fetch() +{ + object *v; + v = (object *)tb_current; + tb_current = NULL; + return v; +} + +int +tb_store(v) + object *v; +{ + if (v != NULL && !is_tracebackobject(v)) { + err_badcall(); + return -1; + } + XDECREF(tb_current); + XINCREF(v); + tb_current = (tracebackobject *)v; + return 0; +} + +static void +tb_displayline(fp, filename, lineno) + FILE *fp; + char *filename; + int lineno; +{ + FILE *xfp; + char buf[1000]; + int i; + if (filename[0] == '<' && filename[strlen(filename)-1] == '>') + return; + xfp = fopen(filename, "r"); + if (xfp == NULL) { + fprintf(fp, " (cannot open \"%s\")\n", filename); + return; + } + for (i = 0; i < lineno; i++) { + if (fgets(buf, sizeof buf, xfp) == NULL) + break; + } + if (i == lineno) { + char *p = buf; + while (*p == ' ' || *p == '\t') + p++; + fprintf(fp, " %s", p); + if (strchr(p, '\n') == NULL) + fprintf(fp, "\n"); + } + fclose(xfp); +} + +static void +tb_printinternal(tb, fp) + tracebackobject *tb; + FILE *fp; +{ + while (tb != NULL) { + if (intrcheck()) { + fprintf(fp, "[interrupted]\n"); + break; + } + fprintf(fp, " File \""); + printobject(tb->tb_frame->f_code->co_filename, fp, PRINT_RAW); + fprintf(fp, "\", line %d\n", tb->tb_lineno); + tb_displayline(fp, + getstringvalue(tb->tb_frame->f_code->co_filename), + tb->tb_lineno); + tb = tb->tb_next; + } +} + +int +tb_print(v, fp) + object *v; + FILE *fp; +{ + if (v == NULL) + return 0; + if (!is_tracebackobject(v)) { + err_badcall(); + return -1; + } + sysset("last_traceback", v); + tb_printinternal((tracebackobject *)v, fp); + return 0; +} |