|
|
1.1 ! root 1: /* C compiler: main program */ ! 2: ! 3: #include "version.h" ! 4: #include "c.h" ! 5: ! 6: Interface *IR; ! 7: ! 8: int Aflag; /* >= 0 if -A specified */ ! 9: int Pflag; /* != 0 if -P specified */ ! 10: int glevel; /* == [0-9] if -g[0-9] specified */ ! 11: int xref; /* != 0 for cross-reference data */ ! 12: Symbol YYnull; /* symbol for _YYnull if -n specified */ ! 13: ! 14: static char *infile; /* input file */ ! 15: static char *outfile; /* output file */ ! 16: static char *progname; /* argv[0] */ ! 17: ! 18: List loci, tables; /* current (locus,table) lists */ ! 19: ! 20: dclproto(static void compile,(char *)); ! 21: dclproto(static int doargs,(int, char **)); ! 22: dclproto(static void emitYYnull,(void)); ! 23: dclproto(static Type ftype,(Type, Type)); ! 24: dclproto(static void typestab,(Symbol, Generic)); ! 25: ! 26: int main(argc, argv) char *argv[]; { ! 27: Symbol symroot = 0; /* root of the global symbols */ ! 28: static Events z; ! 29: int i, infd = 0, outfd = 1; ! 30: ! 31: assert(MAXKIDS >= 2); ! 32: assert(MAXSYMS >= 2); ! 33: progname = argv[0]; ! 34: level = GLOBAL; ! 35: IR = interfaces[0]; ! 36: for (i = 1; i < argc; i++) ! 37: if (strncmp(argv[i], "target=", 7) == 0) { ! 38: int k; ! 39: for (k = 0; interfaces[k]; k++) ! 40: if (strcmp(&argv[i][7], interfaces[k]->target) == 0) ! 41: break; ! 42: if (interfaces[k]) ! 43: IR = interfaces[k]; ! 44: else ! 45: fprint(2, "%s: unknown target `%s'\n", argv[0], &argv[i][7]); ! 46: } ! 47: assert(IR); ! 48: typeInit(); ! 49: assert(inttype->size >= voidptype->size); ! 50: argc = doargs(argc, argv); ! 51: if (infile && *infile != '-') { ! 52: close(infd); ! 53: if ((infd = open(infile, 0)) < 0) { ! 54: fprint(2, "%s: can't read %s\n", argv[0], infile); ! 55: exit(1); ! 56: } ! 57: } ! 58: if (outfile && *outfile != '-') { ! 59: close(outfd); ! 60: if ((outfd = creat(outfile, 0666)) < 0) { ! 61: fprint(2, "%s: can't write %s\n", argv[0], outfile); ! 62: exit(1); ! 63: } ! 64: } ! 65: inputInit(infd); ! 66: outputInit(outfd); ! 67: t = gettok(); ! 68: (*IR->progbeg)(argc, argv); ! 69: if (glevel && IR->stabinit) ! 70: (*IR->stabinit)(firstfile, argc, argv); ! 71: program(); ! 72: if (events.end) ! 73: apply(events.end, (Generic)0, (Generic)0); ! 74: events = z; ! 75: emitYYnull(); ! 76: finalize(); ! 77: if (glevel || xref) { ! 78: Coordinate src; ! 79: foreach(types, GLOBAL, typestab, (Generic)&symroot); ! 80: foreach(identifiers, GLOBAL, typestab, (Generic)&symroot); ! 81: src.file = firstfile; ! 82: src.x = 0; ! 83: src.y = lineno; ! 84: if ((glevel > 2 || xref) && IR->stabend) ! 85: (*IR->stabend)(&src, symroot, (Coordinate **)ltoa(append((Generic)0, loci), 0), ! 86: (Symbol *)ltoa(append((Generic)0, tables), 0), ! 87: symbols ? (Symbol *)ltoa(symbols, 0) : (Symbol *)0); ! 88: else if (IR->stabend) ! 89: (*IR->stabend)(&src, 0, 0, 0, 0); ! 90: } ! 91: (*IR->progend)(); ! 92: outflush(); ! 93: exit(errcnt > 0); ! 94: return 0; ! 95: } ! 96: ! 97: /* compile - compile str */ ! 98: static void compile(str) char *str; { ! 99: inputstring(str); ! 100: t = gettok(); ! 101: program(); ! 102: } ! 103: ! 104: /* doargs - process program arguments, removing top-half arguments from argv */ ! 105: static int doargs(argc, argv) char *argv[]; { ! 106: char *s; ! 107: int i, j, x; ! 108: Symbol p; ! 109: ! 110: for (i = j = 1; i < argc; i++) ! 111: if (strcmp(argv[i], "-g") == 0) ! 112: glevel = 2; ! 113: else if (strncmp(argv[i], "-g", 2) == 0 ! 114: && argv[i][2] && argv[i][2] >= '0' && argv[i][2] <= '9') ! 115: glevel = argv[i][2] - '0'; ! 116: else if (strcmp(argv[i], "-x") == 0) ! 117: xref++; ! 118: else if (strcmp(argv[i], "-A") == 0) ! 119: Aflag++; ! 120: else if (strcmp(argv[i], "-P") == 0) ! 121: Pflag++; ! 122: else if (strcmp(argv[i], "-w") == 0) ! 123: wflag++; ! 124: else if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-C") == 0 ! 125: || strncmp(argv[i], "-a", 2) == 0) ! 126: bbinit(argv[i]); ! 127: else if (strcmp(argv[i], "-n") == 0) { ! 128: if (!YYnull) { ! 129: YYnull = mksymbol(EXTERN, "_YYnull", ftype(voidtype, inttype)); ! 130: YYnull->sclass = STATIC; ! 131: } ! 132: } else if (strncmp(argv[i], "-t", 2) == 0) ! 133: traceinit(&argv[i][2]); ! 134: else if (strcmp(argv[i], "-v") == 0) ! 135: fprint(2, "%s target='%s' version %d.%d\n", progname, IR->target, ! 136: VERSION>>8, VERSION&0xff); ! 137: else if (strncmp(argv[i], "-s", 2) == 0) ! 138: density = strtod(&argv[i][2], (char **)0); ! 139: else if (strncmp(argv[i], "-e", 2) == 0) { ! 140: if ((x = strtol(&argv[i][2], (char **)0, 0)) > 0) ! 141: errlimit = x; ! 142: } else if (strncmp(argv[i], "target=", 7) == 0) ! 143: ; ! 144: else if (strcmp(argv[i], "-nodag") == 0) ! 145: IR->no_dag = !IR->no_dag; ! 146: else if (strcmp(argv[i], "-") == 0 || *argv[i] != '-') { ! 147: if (infile == 0) ! 148: infile = argv[i]; ! 149: else if (outfile == 0) ! 150: outfile = argv[i]; ! 151: else ! 152: argv[j++] = argv[i]; ! 153: } else { ! 154: if (strcmp(argv[i], "-XP") == 0) ! 155: argv[i] = "-p"; ! 156: else if (strncmp(argv[i], "-X", 2) == 0) ! 157: *++argv[i] = '-'; ! 158: argv[j++] = argv[i]; ! 159: } ! 160: argv[j] = 0; ! 161: return j; ! 162: } ! 163: ! 164: /* emitYYnull - compile definition for _YYnull, if referenced */ ! 165: static void emitYYnull() { ! 166: if (YYnull && YYnull->ref) { ! 167: Aflag = 0; ! 168: YYnull->defined = 0; ! 169: YYnull = 0; ! 170: compile(stringf("static char *_YYfile = \"%s\";\n", file)); ! 171: compile("static void _YYnull(int line,...) {\n\ ! 172: char buf[200];\n\ ! 173: sprintf(buf, \"null pointer dereferenced @%s:%d\\n\", _YYfile, line);\n\ ! 174: write(2, buf, strlen(buf));\n\ ! 175: abort();\n\ ! 176: }\n"); ! 177: } else if (YYnull) ! 178: YYnull->ref = 1; ! 179: } ! 180: ! 181: /* ftype - return a function type for `rty function (ty,...)' */ ! 182: static Type ftype(rty, ty) Type rty, ty; { ! 183: List list = append(ty, 0); ! 184: ! 185: list = append(voidtype, list); ! 186: return func(rty, (Type *)ltoa(list, (Generic *)alloc((length(list) + 1)*sizeof (Type))), 0); ! 187: } ! 188: ! 189: /* mkstr - make a string constant */ ! 190: Symbol mkstr(str) char *str; { ! 191: Value v; ! 192: Symbol p; ! 193: ! 194: v.p = str; ! 195: p = constant(array(chartype, strlen(v.p) + 1, 0), v); ! 196: if (p->u.c.loc == 0) ! 197: p->u.c.loc = genident(STATIC, p->type, GLOBAL); ! 198: return p; ! 199: } ! 200: ! 201: /* mksymbol - make a symbol for name, install in &globals if sclass==EXTERN */ ! 202: Symbol mksymbol(sclass, name, ty) char *name; Type ty; { ! 203: Symbol p; ! 204: ! 205: if (sclass == EXTERN) ! 206: p = install(string(name), &globals, 1); ! 207: else { ! 208: p = (Symbol)alloc(sizeof *p); ! 209: BZERO(p, struct symbol); ! 210: p->name = string(name); ! 211: p->scope = GLOBAL; ! 212: } ! 213: p->sclass = sclass; ! 214: p->type = ty; ! 215: (*IR->defsymbol)(p); ! 216: p->defined = 1; ! 217: return p; ! 218: } ! 219: ! 220: /* typestab - emit stab entries for p */ ! 221: static void typestab(p, cl) Symbol p; Generic cl; { ! 222: if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF) ! 223: *(Symbol *)cl = p; ! 224: if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype) ! 225: (*IR->stabtype)(p); ! 226: } ! 227: ! 228: struct callsite { ! 229: char *file, *name; ! 230: union coordinate { ! 231: unsigned int coord; ! 232: struct { unsigned int y:16,x:10,index:6; } le; ! 233: struct { unsigned int index:6,x:10,y:16; } be; ! 234: } u; ! 235: }; ! 236: struct func { ! 237: struct func *link; ! 238: struct caller *callers; ! 239: char *name; ! 240: union coordinate src; ! 241: }; ! 242: struct map { /* source code map; 200 coordinates/map */ ! 243: int size; ! 244: union coordinate u[200]; ! 245: }; ! 246: int npoints; /* # of execution points if -b specified */ ! 247: int ncalled = -1; /* #times prof.out says current function was called */ ! 248: static Symbol YYlink; /* symbol for file's struct _bbdata */ ! 249: static Symbol YYcounts; /* symbol for _YYcounts if -b specified */ ! 250: static List maplist; /* list of struct map *'s */ ! 251: static List filelist; /* list of file names */ ! 252: static Symbol funclist; /* list of struct func *'s */ ! 253: static Symbol afunc; /* current function's struct func */ ! 254: ! 255: dclproto(static void bbcall,(Symbol, Coordinate *, Tree *)); ! 256: dclproto(static void bbentry,(Symbol, Symbol)); ! 257: dclproto(static void bbexit,(Symbol, Symbol, Tree)); ! 258: dclproto(static int bbfile,(char *)); ! 259: dclproto(static void bbfunc,(Symbol, Symbol)); ! 260: dclproto(static void bbincr,(Symbol, Coordinate *, Tree *)); ! 261: dclproto(static void bbvars,(Symbol)); ! 262: ! 263: /* bbcall - build tree to set _callsite at call site *cp, emit call site data */ ! 264: static void bbcall(yycounts, cp, e) Symbol yycounts; Coordinate *cp; Tree *e; { ! 265: static Symbol caller; ! 266: Value v; ! 267: union coordinate u; ! 268: Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL); ! 269: ! 270: defglobal(p, LIT); ! 271: defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0); ! 272: defpointer(mkstr(cfunc->name)->u.c.loc); ! 273: if (IR->little_endian) { ! 274: u.le.x = cp->x; ! 275: u.le.y = cp->y; ! 276: } else { ! 277: u.be.x = cp->x; ! 278: u.be.y = cp->y; ! 279: } ! 280: (*IR->defconst)(U, (v.u = u.coord, v)); ! 281: if (caller == 0) ! 282: caller = mksymbol(EXTERN, "_caller", ptr(voidptype)); ! 283: *e = right(asgn(caller, idnode(p)), *e); ! 284: } ! 285: ! 286: /* bbentry - return tree for `_prologue(&afunc, &YYlink)' */ ! 287: static void bbentry(yylink, f) Symbol yylink, f; { ! 288: static Symbol p; ! 289: ! 290: afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL); ! 291: if (p == 0) ! 292: p = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype)); ! 293: walk(callnode(pointer(idnode(p)), freturn(p->type), ! 294: tree(ARG+P, ptr(unsignedtype), idnode(yylink), ! 295: tree(ARG+P, ptr(unsignedtype), idnode(afunc), 0))), 0, 0); ! 296: } ! 297: ! 298: /* bbexit - return tree for `_epilogue(&afunc)' */ ! 299: static void bbexit(yylink, f, e) Symbol yylink, f; Tree e; { ! 300: static Symbol p; ! 301: ! 302: if (p == 0) ! 303: p = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype)); ! 304: walk(callnode(pointer(idnode(p)), freturn(p->type), ! 305: tree(ARG+P, ptr(unsignedtype), idnode(afunc), 0)), 0, 0); ! 306: } ! 307: ! 308: /* bbfile - add file to list of file names, return its index */ ! 309: static int bbfile(file) char *file; { ! 310: if (file) { ! 311: List lp; ! 312: int i = 1; ! 313: if (lp = filelist) ! 314: do { ! 315: lp = lp->link; ! 316: if (((Symbol)lp->x)->u.c.v.p == file) ! 317: return i; ! 318: i++; ! 319: } while (lp != filelist); ! 320: filelist = append(mkstr(file), filelist); ! 321: return i; ! 322: } ! 323: return 0; ! 324: } ! 325: ! 326: /* bbfunc - emit function name and src coordinates */ ! 327: static void bbfunc(yylink, f) Symbol yylink, f; { ! 328: Value v; ! 329: union coordinate u; ! 330: ! 331: defglobal(afunc, DATA); ! 332: defpointer(funclist); ! 333: defpointer(0); ! 334: defpointer(mkstr(f->name)->u.c.loc); ! 335: if (IR->little_endian) { ! 336: u.le.x = f->u.f.pt[2].x; ! 337: u.le.y = f->u.f.pt[2].y; ! 338: u.le.index = bbfile(f->u.f.pt[2].file); ! 339: } else { ! 340: u.be.x = f->u.f.pt[2].x; ! 341: u.be.y = f->u.f.pt[2].y; ! 342: u.be.index = bbfile(f->u.f.pt[2].file); ! 343: } ! 344: (*IR->defconst)(U, (v.u = u.coord, v)); ! 345: funclist = afunc; ! 346: } ! 347: ! 348: /* bbincr - build tree to increment execution point at *cp */ ! 349: static void bbincr(yycounts, cp, e) Symbol yycounts; Coordinate *cp; Tree *e; { ! 350: struct map *mp = (struct map *)maplist->x; ! 351: ! 352: /* append *cp to source map */ ! 353: if (mp->size >= sizeof mp->u/sizeof mp->u[0]) { ! 354: mp = (struct map *)alloc(sizeof *mp); ! 355: mp->size = 0; ! 356: maplist = append((Generic *)mp, maplist); ! 357: } ! 358: if (IR->little_endian) { ! 359: mp->u[mp->size].le.x = cp->x; ! 360: mp->u[mp->size].le.y = cp->y; ! 361: mp->u[mp->size++].le.index = bbfile(cp->file); ! 362: } else { ! 363: mp->u[mp->size].be.x = cp->x; ! 364: mp->u[mp->size].be.y = cp->y; ! 365: mp->u[mp->size++].be.index = bbfile(cp->file); ! 366: } ! 367: *e = right(incr('+', rvalue((*opnode['+'])(ADD, pointer(idnode(yycounts)), ! 368: constnode(npoints++, inttype))), constnode(1, inttype)), *e); ! 369: } ! 370: ! 371: /* bbinit - initialize basic block counting options */ ! 372: void bbinit(opt) char *opt; { ! 373: if (strncmp(opt, "-a", 2) == 0) { ! 374: if (ncalled == -1 && process(opt[2] ? &opt[2] : "prof.out") > 0) ! 375: ncalled = 0; ! 376: } else if ((strcmp(opt, "-b") == 0 || strcmp(opt, "-C") == 0) && YYlink == 0) { ! 377: YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); ! 378: attach((Apply)bbentry, (Generic)YYlink, &events.entry); ! 379: attach((Apply)bbexit, (Generic)YYlink, &events.returns); ! 380: attach((Apply)bbfunc, (Generic)YYlink, &events.exit); ! 381: attach((Apply)bbvars, (Generic)YYlink, &events.end); ! 382: if (strcmp(opt, "-b") == 0) { ! 383: YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); ! 384: maplist = append((Generic)alloc(sizeof(struct map)), maplist); ! 385: ((struct map *)maplist->x)->size = 0; ! 386: attach((Apply)bbcall, (Generic)YYcounts, &events.calls); ! 387: attach((Apply)bbincr, (Generic)YYcounts, &events.points); ! 388: } ! 389: } ! 390: } ! 391: ! 392: /* bbvars - emit definition for basic block counting data */ ! 393: static void bbvars(yylink) Symbol yylink; { ! 394: int i, j, n = npoints; ! 395: Value v; ! 396: struct map **mp; ! 397: Symbol coords, files, *p; ! 398: ! 399: if (!YYcounts && !yylink) ! 400: return; ! 401: if (YYcounts) { ! 402: if (n <= 0) ! 403: n = 1; ! 404: defglobal(YYcounts, BSS); ! 405: (*IR->space)(n*YYcounts->type->type->size); ! 406: } ! 407: files = genident(STATIC, array(ptr(chartype), 1, 0), GLOBAL); ! 408: defglobal(files, LIT); ! 409: for (p = (Symbol *)ltoa(filelist, 0); *p; p++) ! 410: defpointer((*p)->u.c.loc); ! 411: defpointer(0); ! 412: coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL); ! 413: defglobal(coords, LIT); ! 414: for (i = n, mp = (struct map **)ltoa(maplist, 0); *mp; i -= (*mp)->size, mp++) ! 415: for (j = 0; j < (*mp)->size; j++) ! 416: (*IR->defconst)(U, (v.u = (*mp)->u[j].coord, v)); ! 417: if (i > 0) ! 418: (*IR->space)(i*coords->type->type->size); ! 419: defpointer(0); ! 420: defglobal(yylink, DATA); ! 421: defpointer(0); ! 422: (*IR->defconst)(U, (v.u = n, v)); ! 423: defpointer(YYcounts); ! 424: defpointer(coords); ! 425: defpointer(files); ! 426: defpointer(funclist); ! 427: } ! 428: ! 429: static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */ ! 430: static Tree args; /* printf arguments */ ! 431: static Symbol frameno; /* local holding frame number */ ! 432: ! 433: dclproto(static void appendstr,(char *)); ! 434: dclproto(static void tracecall,(Symbol, Symbol)); ! 435: dclproto(static void tracefinis,(Symbol)); ! 436: dclproto(static void tracereturn,(Symbol, Symbol, Tree)); ! 437: dclproto(static void tracevalue,(Tree, int)); ! 438: ! 439: /* appendstr - append str to the evolving format string, expanding it if necessary */ ! 440: static void appendstr(str) char *str; { ! 441: do ! 442: if (fp == fmtend) ! 443: if (fp) { ! 444: char *s = (char *)talloc(2*(fmtend - fmt)); ! 445: strncpy(s, fmt, fmtend - fmt); ! 446: fp = s + (fmtend - fmt); ! 447: fmtend = s + 2*(fmtend - fmt); ! 448: fmt = s; ! 449: } else { ! 450: fp = fmt = (char *)talloc(80); ! 451: fmtend = fmt + 80; ! 452: } ! 453: while (*fp++ = *str++); ! 454: fp--; ! 455: } ! 456: ! 457: /* tracecall - generate code to trace entry to f */ ! 458: static void tracecall(printer, f) Symbol printer, f; { ! 459: int i; ! 460: Symbol counter = genident(STATIC, inttype, GLOBAL); ! 461: ! 462: defglobal(counter, BSS); ! 463: (*IR->space)(counter->type->size); ! 464: frameno = genident(AUTO, inttype, level); ! 465: addlocal(frameno); ! 466: appendstr(f->name); appendstr("#"); ! 467: tracevalue(asgn(frameno, incr(INCR, idnode(counter), constnode(1, inttype))), 0); ! 468: appendstr("("); ! 469: for (i = 0; f->u.f.callee[i]; i++) { ! 470: if (i) ! 471: appendstr(","); ! 472: appendstr(f->u.f.callee[i]->name); appendstr("="); ! 473: tracevalue(idnode(f->u.f.callee[i]), 0); ! 474: } ! 475: if (variadic(f->type)) ! 476: appendstr(",..."); ! 477: appendstr(") called\n"); ! 478: tracefinis(printer); ! 479: } ! 480: ! 481: /* tracefinis - complete & generate the trace call to print */ ! 482: static void tracefinis(printer) Symbol printer; { ! 483: Tree *ap; ! 484: Symbol p; ! 485: ! 486: *fp = 0; ! 487: p = mkstr(string(fmt)); ! 488: for (ap = &args; *ap; ap = &(*ap)->kids[1]) ! 489: ; ! 490: *ap = tree(ARG+P, ptr(chartype), pointer(idnode(p->u.c.loc)), 0); ! 491: walk(callnode(pointer(idnode(printer)), freturn(printer->type), args), 0, 0); ! 492: args = 0; ! 493: fp = fmtend = 0; ! 494: } ! 495: ! 496: /* traceinit - initialize for tracing */ ! 497: void traceinit(print) char *print; { ! 498: static Symbol printer; ! 499: ! 500: if (!printer) { ! 501: printer = mksymbol(STATIC, print && *print ? print : "printf", ! 502: ftype(voidtype, ptr(chartype))); ! 503: printer->sclass = EXTERN; ! 504: attach((Apply)tracecall, (Generic)printer, &events.entry); ! 505: attach((Apply)tracereturn, (Generic)printer, &events.returns); ! 506: } ! 507: } ! 508: ! 509: /* tracereturn - generate code to trace return e */ ! 510: static void tracereturn(printer, f, e) Symbol printer, f; Tree e; { ! 511: appendstr(f->name); appendstr("#"); ! 512: tracevalue(idnode(frameno), 0); ! 513: appendstr(" returned"); ! 514: if (freturn(f->type) != voidtype && e) { ! 515: appendstr(" "); ! 516: tracevalue(e, 0); ! 517: } ! 518: appendstr("\n"); ! 519: tracefinis(printer); ! 520: } ! 521: ! 522: /* tracevalue - append format and argument to print the value of e */ ! 523: static void tracevalue(e, lev) Tree e; { ! 524: Type ty = unqual(e->type); ! 525: ! 526: switch (ty->op) { ! 527: case CHAR: ! 528: appendstr("'\\x%2x'"); ! 529: break; ! 530: case SHORT: ! 531: if (ty == unsignedshort) ! 532: appendstr("0x%x"); ! 533: else /* fall thru */ ! 534: case INT: ! 535: appendstr("%d"); ! 536: break; ! 537: case UNSIGNED: ! 538: appendstr("0x%x"); ! 539: break; ! 540: case FLOAT: case DOUBLE: ! 541: appendstr("%g"); ! 542: break; ! 543: case POINTER: ! 544: if (unqual(ty->type) == chartype) { ! 545: static Symbol null; ! 546: if (null == 0) ! 547: null = mkstr("(null)"); ! 548: tracevalue(constnode(0, unsignedtype), lev + 1); ! 549: appendstr(" \"%s\""); ! 550: e = condnode(e, e, pointer(idnode(null->u.c.loc))); ! 551: } else { ! 552: appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x"); ! 553: } ! 554: break; ! 555: case STRUCT: { ! 556: Field q; ! 557: appendstr("("); appendstr(typestring(ty, "")); appendstr("){"); ! 558: for (q = ty->u.sym->u.s.flist; q; q = q->link) { ! 559: appendstr(q->name); appendstr("="); ! 560: tracevalue(field(addrof(e), q->name), lev + 1); ! 561: if (q->link) ! 562: appendstr(","); ! 563: } ! 564: appendstr("}"); ! 565: return; ! 566: } ! 567: case UNION: ! 568: appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}"); ! 569: return; ! 570: case ARRAY: ! 571: if (lev && ty->type->size > 0) { ! 572: int i; ! 573: e = pointer(e); ! 574: appendstr("{"); ! 575: for (i = 0; i < ty->size/ty->type->size; i++) { ! 576: Tree p = (*opnode['+'])(ADD, e, constnode(i, inttype)); ! 577: if (isptr(p->type) && isarray(p->type->type)) ! 578: p = retype(p, p->type->type); ! 579: else ! 580: p = rvalue(p); ! 581: if (i) ! 582: appendstr(","); ! 583: tracevalue(p, lev + 1); ! 584: } ! 585: appendstr("}"); ! 586: } else ! 587: appendstr(typestring(ty, "")); ! 588: return; ! 589: default: ! 590: assert(0); ! 591: } ! 592: if (ty == floattype) ! 593: e = cast(e, doubletype); ! 594: else if ((isint(ty) || isenum(ty)) && ty->size != inttype->size) ! 595: e = cast(e, promote(ty)); ! 596: args = tree(ARG + widen(e->type), e->type, e, args); ! 597: } ! 598: Events events; ! 599: ! 600: struct entry { ! 601: Apply func; ! 602: Generic cl; ! 603: }; ! 604: ! 605: void attach(func, cl, list) Apply func; Generic cl; List *list; { ! 606: struct entry *p = (struct entry *)alloc(sizeof *p); ! 607: ! 608: p->func = func; ! 609: p->cl = cl; ! 610: *list = append((Generic)p, *list); ! 611: } ! 612: void apply(list, arg1, arg2) List list; Generic arg1, arg2; { ! 613: if (list) { ! 614: List lp = list; ! 615: do { ! 616: struct entry *p = (struct entry *)lp->x; ! 617: (*p->func)(p->cl, arg1, arg2); ! 618: lp = lp->link; ! 619: } while (lp != list); ! 620: } ! 621: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.