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