Annotation of researchv10no/cmd/lcc/c/main.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.