319 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| 	The logging machine
 | |
| */
 | |
| 
 | |
| /* $Header$ */
 | |
| 
 | |
| #include	<stdio.h>
 | |
| #include	<varargs.h>
 | |
| 
 | |
| #include	"logging.h"
 | |
| #include	"global.h"
 | |
| #include	"linfil.h"
 | |
| 
 | |
| #ifdef	LOGGING
 | |
| 
 | |
| extern char *sprintf();
 | |
| extern int strlen();
 | |
| extern char *strcpy();
 | |
| 
 | |
| extern long mess_id;			/* from io.c */
 | |
| extern FILE *fcreat_high();		/* from io.c */
 | |
| 
 | |
| /******** The Logging Machine Variables ********/
 | |
| 
 | |
| extern long atol();
 | |
| 
 | |
| long inr;				/* current instruction number */
 | |
| 
 | |
| int must_log;				/* set if logging may be required */
 | |
| long log_start;				/* first instruction to be logged */
 | |
| int logging;				/* set as soon as logging starts */
 | |
| 
 | |
| PRIVATE long stop;			/* inr after which to stop */
 | |
| PRIVATE long gdump;			/* inr at which to dump GDA */
 | |
| PRIVATE ptr gmin, gmax;			/* GDA dump limits */
 | |
| PRIVATE long hdump;			/* inr at which to dump the heap */
 | |
| PRIVATE long stdsize;			/* optional size of stack dump */
 | |
| PRIVATE int stdrawflag;			/* set if unformatted stack dump */
 | |
| 
 | |
| PRIVATE char log_file[64] = "int.log";	/* Name of log file */
 | |
| PRIVATE long at;			/* patch to set log_start */
 | |
| PRIVATE char *lmask;			/* patch to set logmask */
 | |
| PRIVATE char *logvar;			/* Name of LOG variable */
 | |
| PRIVATE int log_level[128];		/* Holds the log levels */
 | |
| PRIVATE FILE *log_fp;			/* Filepointer of log file */
 | |
| 
 | |
| /* arguments for the logging machine */
 | |
| PRIVATE int argcount;
 | |
| PRIVATE char *arglist[20];		/* arbitrary size */
 | |
| 
 | |
| PRIVATE char *getpar();
 | |
| PRIVATE long longpar();
 | |
| PRIVATE set_lmask();
 | |
| 
 | |
| int logarg(str)
 | |
| 	char *str;
 | |
| {
 | |
| 	/*	If the string might be an interesting argument for the
 | |
| 		logging machine, it is stored in the arglist, and logarg
 | |
| 		succeeds.  Otherwise it fails.
 | |
| 
 | |
| 		The string is interesting if it contains a '='.
 | |
| 	*/
 | |
| 	register char *arg = str;
 | |
| 	register char ch;
 | |
| 	
 | |
| 	while ((ch = *arg) && (ch != '=')) {
 | |
| 		arg++;
 | |
| 	}
 | |
| 	if (ch == '=') {
 | |
| 		if (argcount == (sizeof arglist /sizeof arglist[0]))
 | |
| 			fatal("too many logging arguments on command line");
 | |
| 		arglist[argcount++] = str;
 | |
| 		return 1;
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| init_log()
 | |
| {
 | |
| 	/* setting the logging machine */
 | |
| 
 | |
| 	stop = longpar("STOP", 0L);
 | |
| 	gdump = longpar("GDA", 0L);
 | |
| 	if (gdump) {
 | |
| 		gmin = i2p(longpar("GMIN", 0L));
 | |
| 		gmax = i2p(longpar("GMAX", 0L));
 | |
| 		set_lmask("+1");
 | |
| 	}
 | |
| 	hdump = longpar("HEAP", 0L);
 | |
| 	if (hdump) {
 | |
| 		set_lmask("*1");
 | |
| 	}
 | |
| 	stdsize = longpar("STDSIZE", 0L);
 | |
| 	stdrawflag = longpar("RAWSTACK", 0L);
 | |
| 
 | |
| 	if (getpar("LOGFILE")) {
 | |
| 		strcpy(log_file, getpar("LOGFILE"));
 | |
| 	}
 | |
| 
 | |
| 	if ((at = longpar("AT", 0L))) {
 | |
| 		/* abbreviation for: */
 | |
| 		stop = at + 1;		/* stop AFTER at + 1 */
 | |
| 		/*	Note: the setting of log_start is deferred to
 | |
| 			init_ofiles(1), for implementation reasons. The
 | |
| 			AT-variable presently only works for the top
 | |
| 			level.
 | |
| 		*/
 | |
| 	}
 | |
| 
 | |
| 	if ((lmask = getpar("L"))) {
 | |
| 		/* abbreviation for: */
 | |
| 		log_start = 0;
 | |
| 		must_log = 1;
 | |
| 	}
 | |
| 
 | |
| 	inr = 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /********  The log file  ********/
 | |
| 
 | |
| open_log(firsttime)
 | |
| 	int firsttime;
 | |
| {
 | |
| 	if (!firsttime) {
 | |
| 		sprintf(logvar, "%s%ld", logvar, mess_id);
 | |
| 		if (log_fp) {
 | |
| 			fclose(log_fp);
 | |
| 			log_fp = 0;
 | |
| 		}
 | |
| 		logging = 0;
 | |
| 		if ((must_log = getpar(logvar) != 0)) {
 | |
| 			sprintf(log_file, "%s%ld", log_file, mess_id);
 | |
| 			log_start = atol(getpar(logvar));
 | |
| 		}
 | |
| 	}
 | |
| 	else {
 | |
| 		/* first time, top level */
 | |
| 		logvar = "LOG\0            ";
 | |
| 
 | |
| 		if (at) {		/* patch */
 | |
| 			must_log = 1;
 | |
| 			log_start = at - 1;
 | |
| 		}
 | |
| 		else
 | |
| 		if (!must_log && (must_log = getpar(logvar) != 0)) {
 | |
| 			log_start = atoi(getpar(logvar));
 | |
| 		}
 | |
| 
 | |
| 		set_lmask(lmask ? lmask :
 | |
| 			getpar("LOGMASK") ? getpar("LOGMASK") :
 | |
| 			"A-Z9d2twx9");
 | |
| 	}
 | |
| 	
 | |
| 	/* Create logfile if needed */
 | |
| 	if (must_log) {
 | |
| 		if ((log_fp = fcreat_high(log_file)) == NULL)
 | |
| 			fatal("Cannot create logfile '%s'", log_file);
 | |
| 	}
 | |
| 
 | |
| 	if (must_log && inr >= log_start) {
 | |
| 		logging = 1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| close_log() {
 | |
| 	if (log_fp) {
 | |
| 		fclose(log_fp);
 | |
| 		log_fp = 0;
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /******** The logmask ********/
 | |
| 
 | |
| #define	inrange(c,l,h)		(l <= c && c <= h)
 | |
| #define	layout(c)		(c == ' ' || c == '\t' || c == ',')
 | |
| 
 | |
| PRIVATE set_lmask(mask)
 | |
| 	char *mask;
 | |
| {
 | |
| 	register char *mp = mask;
 | |
| 
 | |
| 	while (*mp != 0) {
 | |
| 		register char *lvp;
 | |
| 		register int lev;
 | |
| 
 | |
| 		while (layout(*mp)) {
 | |
| 			mp++;
 | |
| 		}
 | |
| 		/* find level */
 | |
| 		lvp = mp;
 | |
| 		while (*lvp != 0 && !inrange(*lvp, '0', '9')) {
 | |
| 			lvp++;
 | |
| 		}
 | |
| 		lev = *lvp - '0';
 | |
| 		/* find classes */
 | |
| 		while (mp != lvp) {
 | |
| 			register mc = *mp;
 | |
| 
 | |
| 			if (	inrange(mc, 'a', 'z')
 | |
| 			||	inrange(mc, 'A', 'Z')
 | |
| 			||	mc == '+'
 | |
| 			||	mc == '*'
 | |
| 			) {
 | |
| 				log_level[mc] = lev;
 | |
| 				mp++;
 | |
| 			}
 | |
| 			else if (mc == '-') {
 | |
| 				register char c;
 | |
| 
 | |
| 				for (c = *(mp-1) + 1; c <= *(mp + 1); c++) {
 | |
| 					log_level[c] = lev;
 | |
| 				}
 | |
| 				mp += 2;
 | |
| 			}
 | |
| 			else if (layout(mc)) {
 | |
| 				mp++;
 | |
| 			}
 | |
| 			else fatal("Bad logmask initialization string");
 | |
| 		}
 | |
| 		mp = lvp + 1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| /******** The logging ********/
 | |
| 
 | |
| int check_log(mark)
 | |
| 	char mark[];
 | |
| {
 | |
| 	/*	mark must be of the form ".CL...", C is class letter,
 | |
| 		L is level digit.
 | |
| 	*/
 | |
| 	if (!logging)
 | |
| 		return 0;
 | |
| 
 | |
| 	return ((mark[2] - '0') <= log_level[mark[1]]);
 | |
| }
 | |
| 
 | |
| /*VARARGS*/
 | |
| do_log(va_alist)
 | |
| 	va_dcl
 | |
| {
 | |
| 	va_list ap;
 | |
| 
 | |
| 	va_start(ap);
 | |
| 	{
 | |
| 		char *fmt = va_arg(ap, char *);
 | |
| 
 | |
| 		if (!check_log(fmt))
 | |
| 			return;
 | |
| 
 | |
| 		if (fmt[0] == '@') {
 | |
| 			/* include position */
 | |
| 			fprintf(log_fp, "%.4s%s, ", fmt, position());
 | |
| 			_doprnt(&fmt[4], ap, log_fp);
 | |
| 		}
 | |
| 		else {
 | |
| 			_doprnt(&fmt[0], ap, log_fp);
 | |
| 		}
 | |
| 	}
 | |
| 	va_end(ap);
 | |
| 
 | |
| 	putc('\n', log_fp);
 | |
| }
 | |
| 
 | |
| log_eoi()
 | |
| {
 | |
| 	/* Logging to be done at end of instruction */
 | |
| 	if (logging) {
 | |
| 		if (inr == gdump)
 | |
| 			gdad_all(gmin, gmax);
 | |
| 		if (inr == hdump)
 | |
| 			hpd_all();
 | |
| 		std_all(stdsize, stdrawflag);
 | |
| 	}
 | |
| 
 | |
| 	if (inr == stop) {
 | |
| 		message("program stopped on request");
 | |
| 		close_down(0);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| /******** Service routines ********/
 | |
| 
 | |
| PRIVATE char *getpar(var)
 | |
| 	char *var;
 | |
| {
 | |
| 	/*	Looks up the name in the argument list.
 | |
| 	*/
 | |
| 	register int count;
 | |
| 	register int ln = strlen(var);
 | |
| 
 | |
| 	for (count = 0; count < argcount; count++) {
 | |
| 		register char *arg = arglist[count];
 | |
| 
 | |
| 		if (strncmp(var, arg, ln) == 0 && arg[ln] == '=') {
 | |
| 			return &arg[ln+1];
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| PRIVATE long longpar(var, def)
 | |
| 	char *var;			/* name of the variable */
 | |
| 	long def;			/* default value */
 | |
| {
 | |
| 	register char *res = getpar(var);
 | |
| 	
 | |
| 	return (res ? atol(res) : def);
 | |
| }
 | |
| 
 | |
| #endif	LOGGING
 | |
| 
 |