| 
									
										
										
										
											1991-02-19 12:39:46 +00:00
										 |  |  | /***********************************************************
 | 
					
						
							| 
									
										
										
										
											1995-01-04 19:12:13 +00:00
										 |  |  | Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, | 
					
						
							|  |  |  | The Netherlands. | 
					
						
							| 
									
										
										
										
											1991-02-19 12:39:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                         All Rights Reserved | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Permission to use, copy, modify, and distribute this software and its  | 
					
						
							|  |  |  | documentation for any purpose and without fee is hereby granted,  | 
					
						
							|  |  |  | provided that the above copyright notice appear in all copies and that | 
					
						
							|  |  |  | both that copyright notice and this permission notice appear in  | 
					
						
							|  |  |  | supporting documentation, and that the names of Stichting Mathematisch | 
					
						
							|  |  |  | Centrum or CWI not be used in advertising or publicity pertaining to | 
					
						
							|  |  |  | distribution of the software without specific, written prior permission. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO | 
					
						
							|  |  |  | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | 
					
						
							|  |  |  | FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE | 
					
						
							|  |  |  | FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
					
						
							|  |  |  | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 
					
						
							|  |  |  | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | 
					
						
							|  |  |  | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ******************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | /* Traceback implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "allobjects.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | #include "sysmodule.h"
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | #include "compile.h"
 | 
					
						
							|  |  |  | #include "frameobject.h"
 | 
					
						
							|  |  |  | #include "traceback.h"
 | 
					
						
							|  |  |  | #include "structmember.h"
 | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | #include "osdefs.h"
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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, | 
					
						
							| 
									
										
										
										
											1994-08-29 12:09:58 +00:00
										 |  |  | 	(destructor)tb_dealloc, /*tp_dealloc*/ | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	0,		/*tp_print*/ | 
					
						
							| 
									
										
										
										
											1994-08-29 12:09:58 +00:00
										 |  |  | 	(getattrfunc)tb_getattr, /*tp_getattr*/ | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	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 | 
					
						
							| 
									
										
										
										
											1992-01-14 18:44:48 +00:00
										 |  |  | tb_here(frame) | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	frameobject *frame; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	tracebackobject *tb; | 
					
						
							| 
									
										
										
										
											1992-01-14 18:44:48 +00:00
										 |  |  | 	tb = newtracebackobject(tb_current, frame, frame->f_lasti, frame->f_lineno); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	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 | 
					
						
							| 
									
										
										
										
											1994-08-29 12:09:58 +00:00
										 |  |  | tb_displayline(f, filename, lineno, name) | 
					
						
							| 
									
										
										
										
											1992-09-25 21:59:05 +00:00
										 |  |  | 	object *f; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	char *filename; | 
					
						
							|  |  |  | 	int lineno; | 
					
						
							| 
									
										
										
										
											1994-08-29 12:09:58 +00:00
										 |  |  | 	char *name; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *xfp; | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 	char linebuf[1000]; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											1994-08-29 12:09:58 +00:00
										 |  |  | #ifdef MPW
 | 
					
						
							|  |  |  | 	/* This is needed by MPW's File and Line commands */ | 
					
						
							|  |  |  | #define FMT "  File \"%.900s\"; line %d # in %s\n"
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	/* This is needed by Emacs' compile command */ | 
					
						
							|  |  |  | #define FMT "  File \"%.900s\", line %d, in %s\n"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	xfp = fopen(filename, "r"); | 
					
						
							|  |  |  | 	if (xfp == NULL) { | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 		/* Search tail of filename in sys.path before giving up */ | 
					
						
							|  |  |  | 		object *path; | 
					
						
							|  |  |  | 		char *tail = strrchr(filename, SEP); | 
					
						
							|  |  |  | 		if (tail == NULL) | 
					
						
							|  |  |  | 			tail = filename; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			tail++; | 
					
						
							|  |  |  | 		path = sysget("path"); | 
					
						
							|  |  |  | 		if (path != NULL && is_listobject(path)) { | 
					
						
							|  |  |  | 			int npath = getlistsize(path); | 
					
						
							| 
									
										
										
										
											1994-09-29 09:38:04 +00:00
										 |  |  | 			int taillen = strlen(tail); | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 			char namebuf[MAXPATHLEN+1]; | 
					
						
							|  |  |  | 			for (i = 0; i < npath; i++) { | 
					
						
							|  |  |  | 				object *v = getlistitem(path, i); | 
					
						
							|  |  |  | 				if (is_stringobject(v)) { | 
					
						
							|  |  |  | 					int len; | 
					
						
							|  |  |  | 					len = getstringsize(v); | 
					
						
							| 
									
										
										
										
											1994-09-29 09:38:04 +00:00
										 |  |  | 					if (len + 1 + taillen >= MAXPATHLEN) | 
					
						
							|  |  |  | 						continue; /* Too long */ | 
					
						
							|  |  |  | 					strcpy(namebuf, getstringvalue(v)); | 
					
						
							|  |  |  | 					if (strlen(namebuf) != len) | 
					
						
							|  |  |  | 						continue; /* v contains '\0' */ | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 					if (len > 0 && namebuf[len-1] != SEP) | 
					
						
							|  |  |  | 						namebuf[len++] = SEP; | 
					
						
							|  |  |  | 					strcpy(namebuf+len, tail); | 
					
						
							|  |  |  | 					xfp = fopen(namebuf, "r"); | 
					
						
							|  |  |  | 					if (xfp != NULL) { | 
					
						
							|  |  |  | 						filename = namebuf; | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1994-08-29 12:09:58 +00:00
										 |  |  | 	sprintf(linebuf, FMT, filename, lineno, name); | 
					
						
							| 
									
										
										
										
											1992-09-25 21:59:05 +00:00
										 |  |  | 	writestring(linebuf, f); | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 	if (xfp == NULL) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	for (i = 0; i < lineno; i++) { | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 		if (fgets(linebuf, sizeof linebuf, xfp) == NULL) | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (i == lineno) { | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 		char *p = linebuf; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 		while (*p == ' ' || *p == '\t') | 
					
						
							|  |  |  | 			p++; | 
					
						
							| 
									
										
										
										
											1992-09-25 21:59:05 +00:00
										 |  |  | 		writestring("    ", f); | 
					
						
							|  |  |  | 		writestring(p, f); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 		if (strchr(p, '\n') == NULL) | 
					
						
							| 
									
										
										
										
											1992-09-25 21:59:05 +00:00
										 |  |  | 			writestring("\n", f); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	fclose(xfp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											1993-12-17 12:09:14 +00:00
										 |  |  | tb_printinternal(tb, f, limit) | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	tracebackobject *tb; | 
					
						
							| 
									
										
										
										
											1992-09-25 21:59:05 +00:00
										 |  |  | 	object *f; | 
					
						
							| 
									
										
										
										
											1993-12-17 12:09:14 +00:00
										 |  |  | 	int limit; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1993-12-17 12:09:14 +00:00
										 |  |  | 	int depth = 0; | 
					
						
							|  |  |  | 	tracebackobject *tb1 = tb; | 
					
						
							|  |  |  | 	while (tb1 != NULL) { | 
					
						
							|  |  |  | 		depth++; | 
					
						
							|  |  |  | 		tb1 = tb1->tb_next; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1992-02-26 15:17:59 +00:00
										 |  |  | 	while (tb != NULL && !intrcheck()) { | 
					
						
							| 
									
										
										
										
											1993-12-17 12:09:14 +00:00
										 |  |  | 		if (depth <= limit) | 
					
						
							|  |  |  | 			tb_displayline(f, | 
					
						
							|  |  |  | 			    getstringvalue(tb->tb_frame->f_code->co_filename), | 
					
						
							| 
									
										
										
										
											1994-08-29 12:09:58 +00:00
										 |  |  | 			    tb->tb_lineno, | 
					
						
							|  |  |  | 			    getstringvalue(tb->tb_frame->f_code->co_name)); | 
					
						
							| 
									
										
										
										
											1993-12-17 12:09:14 +00:00
										 |  |  | 		depth--; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 		tb = tb->tb_next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											1992-09-25 21:59:05 +00:00
										 |  |  | tb_print(v, f) | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	object *v; | 
					
						
							| 
									
										
										
										
											1992-09-25 21:59:05 +00:00
										 |  |  | 	object *f; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1993-12-17 12:09:14 +00:00
										 |  |  | 	object *limitv; | 
					
						
							|  |  |  | 	int limit = 1000; | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	if (v == NULL) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	if (!is_tracebackobject(v)) { | 
					
						
							|  |  |  | 		err_badcall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1993-12-17 12:09:14 +00:00
										 |  |  | 	limitv = sysget("tracebacklimit"); | 
					
						
							|  |  |  | 	if (limitv && is_intobject(limitv)) { | 
					
						
							|  |  |  | 		limit = getintvalue(limitv); | 
					
						
							|  |  |  | 		if (limit <= 0) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	writestring("Traceback (innermost last):\n", f); | 
					
						
							|  |  |  | 	tb_printinternal((tracebackobject *)v, f, limit); | 
					
						
							| 
									
										
										
										
											1990-12-20 15:06:42 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } |