Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

trace.c

Go to the documentation of this file.
00001 #include "c.h"
00002 
00003 
00004 static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */
00005 static Tree args;       /* printf arguments */
00006 static Symbol frameno;      /* local holding frame number */
00007 
00008 /* appendstr - append str to the evolving format string, expanding it if necessary */
00009 static void appendstr(char *str) {
00010     do
00011         if (fp == fmtend)
00012             if (fp) {
00013                 char *s = allocate(2*(fmtend - fmt), FUNC);
00014                 strncpy(s, fmt, fmtend - fmt);
00015                 fp = s + (fmtend - fmt);
00016                 fmtend = s + 2*(fmtend - fmt);
00017                 fmt = s;
00018             } else {
00019                 fp = fmt = allocate(80, FUNC);
00020                 fmtend = fmt + 80;
00021             }
00022     while ((*fp++ = *str++) != 0);
00023     fp--;
00024 }
00025 
00026 /* tracevalue - append format and argument to print the value of e */
00027 static void tracevalue(Tree e, int lev) {
00028     Type ty = unqual(e->type);
00029 
00030     switch (ty->op) {
00031     case INT:
00032         if (ty == chartype || ty == signedchar)
00033             appendstr("'\\x%02x'");
00034         else if (ty == longtype)
00035             appendstr("0x%ld");
00036         else
00037             appendstr("0x%d");
00038         break;
00039     case UNSIGNED:
00040         if (ty == chartype || ty == unsignedchar)
00041             appendstr("'\\x%02x'");
00042         else if (ty == unsignedlong)
00043             appendstr("0x%lx");
00044         else
00045             appendstr("0x%x");
00046         break;
00047     case FLOAT:
00048         if (ty == longdouble)
00049             appendstr("%Lg");
00050         else
00051             appendstr("%g");
00052         break;
00053     case POINTER:
00054         if (unqual(ty->type) == chartype
00055         ||  unqual(ty->type) == signedchar
00056         ||  unqual(ty->type) == unsignedchar) {
00057             static Symbol null;
00058             if (null == NULL)
00059                 null = mkstr("(null)");
00060             tracevalue(cast(e, unsignedtype), lev + 1);
00061             appendstr(" \"%.30s\"");
00062             e = condtree(e, e, pointer(idtree(null->u.c.loc)));
00063         } else {
00064             appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x");
00065         }
00066         break;
00067     case STRUCT: {
00068         Field q;
00069         appendstr("("); appendstr(typestring(ty, "")); appendstr("){");
00070         for (q = ty->u.sym->u.s.flist; q; q = q->link) {
00071             appendstr(q->name); appendstr("=");
00072             tracevalue(field(addrof(e), q->name), lev + 1);
00073             if (q->link)
00074                 appendstr(",");
00075         }
00076         appendstr("}");
00077         return;
00078         }
00079     case UNION:
00080         appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}");
00081         return;
00082     case ARRAY:
00083         if (lev && ty->type->size > 0) {
00084             int i;
00085             e = pointer(e);
00086             appendstr("{");
00087             for (i = 0; i < ty->size/ty->type->size; i++) {
00088                 Tree p = (*optree['+'])(ADD, e, consttree(i, inttype));
00089                 if (isptr(p->type) && isarray(p->type->type))
00090                     p = retype(p, p->type->type);
00091                 else
00092                     p = rvalue(p);
00093                 if (i)
00094                     appendstr(",");
00095                 tracevalue(p, lev + 1);
00096             }
00097             appendstr("}");
00098         } else
00099             appendstr(typestring(ty, ""));
00100         return;
00101     default:
00102         assert(0);
00103     }
00104     e = cast(e, promote(ty));
00105     args = tree(mkop(ARG,e->type), e->type, e, args);
00106 }
00107 
00108 /* tracefinis - complete & generate the trace call to print */
00109 static void tracefinis(Symbol printer) {
00110     Tree *ap;
00111     Symbol p;
00112 
00113     *fp = 0;
00114     p = mkstr(string(fmt));
00115     for (ap = &args; *ap; ap = &(*ap)->kids[1])
00116         ;
00117     *ap = tree(ARG+P, charptype, pointer(idtree(p->u.c.loc)), 0);
00118     walk(calltree(pointer(idtree(printer)), freturn(printer->type), args, NULL), 0, 0);
00119     args = 0;
00120     fp = fmtend = 0;
00121 }
00122 
00123 /* tracecall - generate code to trace entry to f */
00124 static void tracecall(Symbol printer, Symbol f) {
00125     int i;
00126     Symbol counter = genident(STATIC, inttype, GLOBAL);
00127 
00128     defglobal(counter, BSS);
00129     (*IR->space)(counter->type->size);
00130     frameno = genident(AUTO, inttype, level);
00131     addlocal(frameno);
00132     appendstr(f->name); appendstr("#");
00133     tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0);
00134     appendstr("(");
00135     for (i = 0; f->u.f.callee[i]; i++) {
00136         if (i)
00137             appendstr(",");
00138         appendstr(f->u.f.callee[i]->name); appendstr("=");
00139         tracevalue(idtree(f->u.f.callee[i]), 0);
00140     }
00141     if (variadic(f->type))
00142         appendstr(",...");
00143     appendstr(") called\n");
00144     tracefinis(printer);
00145 }
00146 
00147 /* tracereturn - generate code to trace return e */
00148 static void tracereturn(Symbol printer, Symbol f, Tree e) {
00149     appendstr(f->name); appendstr("#");
00150     tracevalue(idtree(frameno), 0);
00151     appendstr(" returned");
00152     if (freturn(f->type) != voidtype && e) {
00153         appendstr(" ");
00154         tracevalue(e, 0);
00155     }
00156     appendstr("\n");
00157     tracefinis(printer);
00158 }
00159 
00160 /* trace_init - initialize for tracing */
00161 void trace_init(int argc, char *argv[]) {
00162     int i;
00163     static int inited;
00164 
00165     if (inited)
00166         return;
00167     inited = 1;
00168     type_init(argc, argv);
00169     if (IR)
00170         for (i = 1; i < argc; i++)
00171             if (strncmp(argv[i], "-t", 2) == 0 &&  strchr(argv[i], '=') == NULL) {
00172                 Symbol printer = mksymbol(EXTERN,
00173                     argv[i][2] ? &argv[i][2] : "printf",
00174                 ftype(inttype, ptr(qual(CONST, chartype))));
00175                 printer->defined = 0;
00176                 attach((Apply)tracecall,   printer, &events.entry);
00177                 attach((Apply)tracereturn, printer, &events.returns);
00178                 break;
00179             }
00180 }

Generated on Thu Aug 25 12:38:15 2005 for Quake III Arena by  doxygen 1.3.9.1