Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

trace.c (4602B)


      1 #include "c.h"
      2 
      3 
      4 static char *fmt, *fp, *fmtend;	/* format string, current & limit pointer */
      5 static Tree args;		/* printf arguments */
      6 static Symbol frameno;		/* local holding frame number */
      7 
      8 /* appendstr - append str to the evolving format string, expanding it if necessary */
      9 static void appendstr(char *str) {
     10 	do
     11 		if (fp == fmtend)
     12 			if (fp) {
     13 				char *s = allocate(2*(fmtend - fmt), FUNC);
     14 				strncpy(s, fmt, fmtend - fmt);
     15 				fp = s + (fmtend - fmt);
     16 				fmtend = s + 2*(fmtend - fmt);
     17 				fmt = s;
     18 			} else {
     19 				fp = fmt = allocate(80, FUNC);
     20 				fmtend = fmt + 80;
     21 			}
     22 	while ((*fp++ = *str++) != 0);
     23 	fp--;
     24 }
     25 
     26 /* tracevalue - append format and argument to print the value of e */
     27 static void tracevalue(Tree e, int lev) {
     28 	Type ty = unqual(e->type);
     29 
     30 	switch (ty->op) {
     31 	case INT:
     32 		if (ty == chartype || ty == signedchar)
     33 			appendstr("'\\x%02x'");
     34 		else if (ty == longtype)
     35 			appendstr("0x%ld");
     36 		else
     37 			appendstr("0x%d");
     38 		break;
     39 	case UNSIGNED:
     40 		if (ty == chartype || ty == unsignedchar)
     41 			appendstr("'\\x%02x'");
     42 		else if (ty == unsignedlong)
     43 			appendstr("0x%lx");
     44 		else
     45 			appendstr("0x%x");
     46 		break;
     47 	case FLOAT:
     48 		if (ty == longdouble)
     49 			appendstr("%Lg");
     50 		else
     51 			appendstr("%g");
     52 		break;
     53 	case POINTER:
     54 		if (unqual(ty->type) == chartype
     55 		||  unqual(ty->type) == signedchar
     56 		||  unqual(ty->type) == unsignedchar) {
     57 			static Symbol null;
     58 			if (null == NULL)
     59 				null = mkstr("(null)");
     60 			tracevalue(cast(e, unsignedtype), lev + 1);
     61 			appendstr(" \"%.30s\"");
     62 			e = condtree(e, e, pointer(idtree(null->u.c.loc)));
     63 		} else {
     64 			appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x");
     65 		}
     66 		break;
     67 	case STRUCT: {
     68 		Field q;
     69 		appendstr("("); appendstr(typestring(ty, "")); appendstr("){");
     70 		for (q = ty->u.sym->u.s.flist; q; q = q->link) {
     71 			appendstr(q->name); appendstr("=");
     72 			tracevalue(field(addrof(e), q->name), lev + 1);
     73 			if (q->link)
     74 				appendstr(",");
     75 		}
     76 		appendstr("}");
     77 		return;
     78 		}
     79 	case UNION:
     80 		appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}");
     81 		return;
     82 	case ARRAY:
     83 		if (lev && ty->type->size > 0) {
     84 			int i;
     85 			e = pointer(e);
     86 			appendstr("{");
     87 			for (i = 0; i < ty->size/ty->type->size; i++) {
     88 				Tree p = (*optree['+'])(ADD, e, consttree(i, inttype));
     89 				if (isptr(p->type) && isarray(p->type->type))
     90 					p = retype(p, p->type->type);
     91 				else
     92 					p = rvalue(p);
     93 				if (i)
     94 					appendstr(",");
     95 				tracevalue(p, lev + 1);
     96 			}
     97 			appendstr("}");
     98 		} else
     99 			appendstr(typestring(ty, ""));
    100 		return;
    101 	default:
    102 		assert(0);
    103 	}
    104 	e = cast(e, promote(ty));
    105 	args = tree(mkop(ARG,e->type), e->type, e, args);
    106 }
    107 
    108 /* tracefinis - complete & generate the trace call to print */
    109 static void tracefinis(Symbol printer) {
    110 	Tree *ap;
    111 	Symbol p;
    112 
    113 	*fp = 0;
    114 	p = mkstr(string(fmt));
    115 	for (ap = &args; *ap; ap = &(*ap)->kids[1])
    116 		;
    117 	*ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0);
    118 	walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0);
    119 	args = 0;
    120 	fp = fmtend = 0;
    121 }
    122 
    123 /* tracecall - generate code to trace entry to f */
    124 static void tracecall(Symbol printer, Symbol f) {
    125 	int i;
    126 	Symbol counter = genident(STATIC, inttype, GLOBAL);
    127 
    128 	defglobal(counter, BSS);
    129 	(*IR->space)(counter->type->size);
    130 	frameno = genident(AUTO, inttype, level);
    131 	addlocal(frameno);
    132 	appendstr(f->name); appendstr("#");
    133 	tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0);
    134 	appendstr("(");
    135 	for (i = 0; f->u.f.callee[i]; i++) {
    136 		if (i)
    137 			appendstr(",");
    138 		appendstr(f->u.f.callee[i]->name); appendstr("=");
    139 		tracevalue(idtree(f->u.f.callee[i]), 0);
    140 	}
    141 	if (variadic(f->type))
    142 		appendstr(",...");
    143 	appendstr(") called\n");
    144 	tracefinis(printer);
    145 }
    146 
    147 /* tracereturn - generate code to trace return e */
    148 static void tracereturn(Symbol printer, Symbol f, Tree e) {
    149 	appendstr(f->name); appendstr("#");
    150 	tracevalue(idtree(frameno), 0);
    151 	appendstr(" returned");
    152 	if (freturn(f->type) != voidtype && e) {
    153 		appendstr(" ");
    154 		tracevalue(e, 0);
    155 	}
    156 	appendstr("\n");
    157 	tracefinis(printer);
    158 }
    159 
    160 /* trace_init - initialize for tracing */
    161 void trace_init(int argc, char *argv[]) {
    162 	int i;
    163 	static int inited;
    164 
    165 	if (inited)
    166 		return;
    167 	inited = 1;
    168 	type_init(argc, argv);
    169 	if (IR)
    170 		for (i = 1; i < argc; i++)
    171 			if (strncmp(argv[i], "-t", 2) == 0 &&  strchr(argv[i], '=') == NULL) {
    172 				Symbol printer = mksymbol(EXTERN,
    173 					argv[i][2] ? &argv[i][2] : "printf",
    174 				ftype(inttype, ptr(qual(CONST, chartype))));
    175 				printer->defined = 0;
    176 				attach((Apply)tracecall,   printer, &events.entry);
    177 				attach((Apply)tracereturn, printer, &events.returns);
    178 				break;
    179 			}
    180 }