/* tracereturn - generate code to trace return e */ static void tracereturn(Symbol printer, Symbol f, Tree e) { appendstr(f->name); appendstr("#"); tracevalue(idtree(frameno), 0); appendstr(" returned"); if (freturn(f->type) != voidtype && e) { appendstr(" "); tracevalue(e, 0); } appendstr("\n"); tracefinis(printer); }
/* tracecall - generate code to trace entry to f */ static void tracecall(Symbol printer, Symbol f, void *ignore) { int i; Symbol counter = genident(STATIC, inttype, GLOBAL); defglobal(counter, BSS); (*IR->space)(counter->type->size); frameno = genident(AUTO, inttype, level); addlocal(frameno); appendstr(f->name); appendstr("#"); tracevalue(asgn(frameno, incr(INCR, idtree(counter), consttree(1, inttype))), 0); appendstr("("); for (i = 0; f->u.f.callee[i]; i++) { if (i) appendstr(","); appendstr(f->u.f.callee[i]->name); appendstr("="); tracevalue(idtree(f->u.f.callee[i]), 0); } if (variadic(f->type)) appendstr(",..."); appendstr(") called\n"); tracefinis(printer); }
/* * This parses a part of the source string, determined by (start) * and (len) into the variables of the (thisptr) tree. Only variables * are handled, not patterns. It will be called by doparse() to fit a * string into a set of variables and placeholder. * * Start points to the first character to be parsed, while len gives the * length of the string. len MUST be >= 0, which is currently detected by * doparse. * * There is no returnvalue from this function, it is only called to * achieve the special effects of setting variables and tracing * variables and placeholders. Actually, this routine used to be * tailrecursive, but I changed it into a goto. * * The variables and placeholders to parse ares stored in a chained * of pointers, chased through p[0]. 'start' is a ptr to the first * characters to be parsed by this function. 'len' gives the length * of the string to be parsed by this function. */ static void doparse3( tsd_t *TSD, cnodeptr thisptr, const char *start, int len ) { int wordlen ; streng *tptr ; int CutLast = 0; /* see below */ recurse: assert(len >= 0); /* * Since we are going to put the next word of the input string * into a variable, we must first find that value. The if tests * whether we are the last word before an 'anchor' to be parsed. * if so, use the rest of the string. If not, scan forwards to * identify a word. */ if (thisptr->p[0]) { /* * We shall only fetch out one word. First skip leading spaces, * then find the end of the next word. */ while (len && rx_isspace(*start)) { start++; len--; } wordlen = 0; while ((wordlen < len) && !rx_isspace(start[wordlen])) wordlen++; } else { /* * We are last word, use rest of string as value. * FGC: This is NOT true. Accoring to ANSI standard, we have to * cut the first char if it is a space AND it is not * the only pattern to match. */ if (CutLast && len && rx_isspace(*start)) { start++; len--; } wordlen = len; } CutLast = 1; /* * We have found the word to be parsed into something. Now we have * to decide what to parse it into. There are two possibilities. * It might be a variable, or just a placeholder (dot). The two are * handled in each part of the if-statement below. The setting of * 'tptr' could be lifted out of the if-statement to save space, * but at the cost of MUCH more CPU. * DON'T DO IT! */ if ( thisptr->type == X_TPL_SYMBOL ) { tptr = Str_ncreTSD( start, wordlen ); if ( TSD->traceparse ) tracevalue( TSD, tptr, '>' ); if ( thisptr->p[1]->type == X_HEAD_SYMBOL ) fix_compound( TSD, thisptr->p[1], tptr ); else setshortcut( TSD, thisptr->p[1], tptr ); } else { /* * It's a placeholder, actually, we skip this if we arn't * tracing. No harm is done if tracevalue() is called unnecessary, * but this way we save three function calls whenever we're not * doing TRACE INT. * * The three operations below do: 1) get the value to be traced, * 2) then output the trace information, 3) and then free the * temporary storage. */ if ( TSD->traceparse ) { tptr = Str_ncreTSD( start, wordlen ); tracevalue( TSD, tptr, '.' ); Free_stringTSD( tptr ); } } /* * Now, this should actually be a tail recursion, but since be don't * trust compilers, we are optimizeing it ourselves. */ if ((thisptr = thisptr->p[0]) != NULL) { start += wordlen ; len -= wordlen ; goto recurse ; } }
/* tracevalue - append format and argument to print the value of e */ static void tracevalue(Tree e, int lev) { Type ty = unqual(e->type); switch (ty->op) { case INT: if (ty == chartype || ty == signedchar) appendstr("'\\x%02x'"); else if (ty == longtype) appendstr("0x%ld"); else appendstr("0x%d"); break; case UNSIGNED: if (ty == chartype || ty == unsignedchar) appendstr("'\\x%02x'"); else if (ty == unsignedlong) appendstr("0x%lx"); else appendstr("0x%x"); break; case FLOAT: if (ty == longdouble) appendstr("%Lg"); else appendstr("%g"); break; case POINTER: if (unqual(ty->type) == chartype || unqual(ty->type) == signedchar || unqual(ty->type) == unsignedchar) { static Symbol null; if (null == NULL) null = mkstr("(null)"); tracevalue(cast(e, unsignedtype), lev + 1); appendstr(" \"%.30s\""); e = condtree(e, e, pointer(idtree(null->u.c.loc))); } else { appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x"); } break; case STRUCT: { Field q; appendstr("("); appendstr(typestring(ty, "")); appendstr("){"); for (q = ty->u.sym->u.s.flist; q; q = q->link) { appendstr(q->name); appendstr("="); tracevalue(field(addrof(e), q->name), lev + 1); if (q->link) appendstr(","); } appendstr("}"); return; } case UNION: appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}"); return; case ARRAY: if (lev && ty->type->size > 0) { int i; e = pointer(e); appendstr("{"); for (i = 0; i < ty->size/ty->type->size; i++) { Tree p = (*optree['+'])(ADD, e, consttree(i, inttype)); if (isptr(p->type) && isarray(p->type->type)) p = retype(p, p->type->type); else p = rvalue(p); if (i) appendstr(","); tracevalue(p, lev + 1); } appendstr("}"); } else appendstr(typestring(ty, "")); return; default: assert(0); } e = cast(e, promote(ty)); args = tree(mkop(ARG,e->type), e->type, e, args); }