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

1.1     ! root        1: /*
        !             2:  * lcc [ option ]... [ file | -llib ]...
        !             3:  * front end for the ANSI C compiler
        !             4:  */
        !             5: /* Fri Feb 5 07:56:38 EST 1993 */
        !             6: #define VERSION ((2<<8)|0)
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include <ctype.h>
        !            10: #include <signal.h>
        !            11: 
        !            12: #ifndef TEMPDIR
        !            13: #define TEMPDIR "/tmp"
        !            14: #endif
        !            15: 
        !            16: typedef struct list *List;
        !            17: struct list {          /* circular list nodes: */
        !            18:        char *str;              /* option or file name */
        !            19:        List link;              /* next list element */
        !            20: };
        !            21: 
        !            22: #if __LCC__ || __STDC__
        !            23: #include <stdlib.h>
        !            24: #include <string.h>
        !            25: #include <assert.h>
        !            26: #define dclproto(func,args) func args
        !            27: dclproto(static void interrupt,(int));
        !            28: #else
        !            29: #define assert(e) ((void)((e)||(fprintf(stderr, "assertion failed: file %s, line %d\n", \
        !            30:        __FILE__, __LINE__), abort(), 0)))
        !            31: #define dclproto(func,args) func()
        !            32: dclproto(static void interrupt,());
        !            33: #endif
        !            34: 
        !            35: dclproto(static char *alloc,(int));
        !            36: dclproto(static List append,(char *,List));
        !            37: dclproto(extern char *basename,(char *));
        !            38: dclproto(static int callsys,(char *[]));
        !            39: dclproto(extern char *concat,(char *, char *));
        !            40: dclproto(static int compile,(char *, char *));
        !            41: dclproto(static void compose,(char *[], List, List, List));
        !            42: dclproto(static void cprint,(char *[], char *));
        !            43: dclproto(static void error,(char *, char *));
        !            44: dclproto(static void execute,(char *[]));
        !            45: dclproto(static int exists,(char *));
        !            46: dclproto(static int filename,(char *, char *));
        !            47: dclproto(static List find,(char *, List));
        !            48: dclproto(static void opt,(char *));
        !            49: dclproto(static void rm,(List));
        !            50: dclproto(extern char *strsave,(char *));
        !            51: dclproto(extern int suffix,(char *));
        !            52: 
        !            53: dclproto(extern int execv,(char *, char *[]));
        !            54: dclproto(extern int fork,(void));
        !            55: dclproto(extern int close,(int));
        !            56: dclproto(extern int dup,(int));
        !            57: dclproto(extern int fork,(void));
        !            58: dclproto(extern int getpid,(void));
        !            59: dclproto(extern int open,(char *, int));
        !            60: dclproto(extern int pipe,(int[]));
        !            61: dclproto(extern int read,(int, char *, int));
        !            62: dclproto(extern int unlink,(char *));
        !            63: dclproto(extern int wait,(int*));
        !            64: 
        !            65: extern char *cpp[], *include[], *com[], *as[],*ld[];
        !            66: dclproto(extern int option,(char *));
        !            67: 
        !            68: static int errcnt;             /* number of errors */
        !            69: static int Eflag;              /* -E specified */
        !            70: static int Sflag;              /* -S specified */
        !            71: static int cflag;              /* -c specified */
        !            72: static int verbose;            /* incremented for each -v */
        !            73: static List llist[2];          /* loader files, flags */
        !            74: static List alist;             /* assembler flags */
        !            75: static List clist;             /* compiler flags */
        !            76: static List plist;             /* preprocessor flags */
        !            77: static List rmlist;            /* list of files to remove */
        !            78: static char *outfile;          /* ld output file or -[cS] object file */
        !            79: static int ac;                 /* argument count */
        !            80: static char **av;              /* argument vector */
        !            81: static char tempname[sizeof TEMPDIR + 15];     /* temporary .s file */
        !            82: static char *progname;
        !            83: 
        !            84: main(argc, argv) char *argv[]; {
        !            85:        int i, j, nf;
        !            86:        
        !            87:        progname = argv[0];
        !            88:        ac = argc + 50;
        !            89:        av = (char **)alloc(ac*sizeof(char *));
        !            90:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !            91:                signal(SIGINT, interrupt);
        !            92:        if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
        !            93:                signal(SIGTERM, interrupt);
        !            94: #ifdef SIGHUP
        !            95:        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
        !            96:                signal(SIGHUP, interrupt);
        !            97: #endif
        !            98:        sprintf(tempname, "%s/lcc%05d.s", TEMPDIR, getpid());
        !            99:        rmlist = append(tempname, rmlist);
        !           100:        plist = append("-D__LCC__", append("-Dunix", 0));
        !           101:        for (nf = 0, i = j = 1; i < argc; i++) {
        !           102:                if (strcmp(argv[i], "-o") == 0) {
        !           103:                        if (++i < argc) {
        !           104:                                if (strchr("ci", suffix(argv[i]))) {
        !           105:                                        error("-o would overwrite %s", argv[i]);
        !           106:                                        exit(8);
        !           107:                                }
        !           108:                                outfile = argv[i];
        !           109:                                continue;
        !           110:                        } else {
        !           111:                                error("unrecognized option `%s'", argv[i]);
        !           112:                                exit(8);
        !           113:                        }
        !           114: #ifdef sun
        !           115:                } else if (strcmp(argv[i], "-target") == 0) {
        !           116:                        if (argv[i+1] && *argv[i+1] != '-')
        !           117:                                i++;
        !           118:                        continue;
        !           119: #endif
        !           120:                } else if (*argv[i] == '-' && argv[i][1] != 'l') {
        !           121:                        opt(argv[i]);
        !           122:                        continue;
        !           123:                } else if (*argv[i] != '-' && strchr("csi", suffix(argv[i])))
        !           124:                        nf++;
        !           125:                argv[j++] = argv[i];
        !           126:        }
        !           127:        if ((cflag || Sflag) && outfile && nf != 1) {
        !           128:                fprintf(stderr, "%s: -o %s ignored\n", progname, outfile);
        !           129:                outfile = 0;
        !           130:        }
        !           131:        argv[j] = 0;
        !           132:        for (i = 0; include[i]; i++)
        !           133:                plist = append(include[i], plist);
        !           134:        for (i = 1; argv[i]; i++)
        !           135:                if (*argv[i] == '-')
        !           136:                        opt(argv[i]);
        !           137:                else {
        !           138:                        if (nf > 1 && strchr("csi", suffix(argv[i]))) {
        !           139:                                fprintf(stderr, "%s:\n", argv[i]);
        !           140:                                fflush(stdout);
        !           141:                        }
        !           142:                        filename(argv[i], 0);
        !           143:                }
        !           144:        if (errcnt == 0 && !Eflag && !Sflag && !cflag && llist[1]) {
        !           145:                if (i == 2 && strchr("csi", suffix(argv[1])))
        !           146:                        rmlist = append(concat(basename(argv[1]), ".o"), rmlist);
        !           147:                compose(ld, llist[0], llist[1], append(outfile ? outfile : "a.out", 0));
        !           148:                if (callsys(av))
        !           149:                        errcnt++;
        !           150:        }
        !           151:        rm(rmlist);     
        !           152:        exit(errcnt > 0);
        !           153: }
        !           154: 
        !           155: /* alloc - allocate n bytes or die */
        !           156: static char *alloc(n) {
        !           157:        static char *avail, *limit;
        !           158:        
        !           159:        n = (n + sizeof(char *) - 1)&~(sizeof(char *) - 1);
        !           160:        if (avail + n >= limit) {
        !           161:                avail = (char *)malloc(n + 4*1024);
        !           162:                assert(avail);
        !           163:                limit = avail + n + 4*1024;
        !           164:        }
        !           165:        avail += n;
        !           166:        return avail - n;
        !           167: }
        !           168: 
        !           169: /* append - append a node with string str onto list, return new list */        
        !           170: static List append(str, list) char *str; List list; {
        !           171:        List p = (List) alloc(sizeof *p);
        !           172: 
        !           173:        p->str = str;
        !           174:        if (list) {
        !           175:                p->link = list->link;
        !           176:                list->link = p;
        !           177:        } else
        !           178:                p->link = p;
        !           179:        return p;
        !           180: }
        !           181: 
        !           182: /* basename - return base name for name, e.g. /usr/drh/foo.c => foo */
        !           183: char *basename(name) char *name; {
        !           184:        char *s, *b, *t = 0;
        !           185: 
        !           186:        for (b = s = name; *s; s++)
        !           187:                if (*s == '/') {
        !           188:                        b = s + 1;
        !           189:                        t = 0;
        !           190:                } else if (*s == '.')
        !           191:                        t = s;
        !           192:        s = strsave(b);
        !           193:        if (t)
        !           194:                s[t-b] = 0;
        !           195:        return s;
        !           196: }
        !           197: 
        !           198: /* callsys - fork and execute the command described by argv[0...], return status */
        !           199: static int callsys(argv) char **argv; {
        !           200:        int n, m = 0, status = 0, pid;
        !           201: 
        !           202:        cprint(argv, 0);
        !           203:        if (verbose >= 2)
        !           204:                return 0;
        !           205:        switch (pid = fork()) {
        !           206:        case -1:
        !           207:                fprintf(stderr, "%s: no more processes\n", progname);
        !           208:                return 100;
        !           209:        case 0:
        !           210:                execute(argv);
        !           211:        }
        !           212:        while ((n = wait(&m)) != pid && n != -1)
        !           213:                status |= m;
        !           214:        status |= m;
        !           215:        if (status&0377) {
        !           216:                fprintf(stderr, "%s: fatal error in %s\n", progname, argv[0]);
        !           217:                status |= 0400;
        !           218:        }
        !           219:        return (status>>8)&0377;
        !           220: }
        !           221: 
        !           222: /* concat - return concatenation of strings s1 and s2 */
        !           223: char *concat(s1, s2) char *s1, *s2; {
        !           224:        int n = strlen(s1);
        !           225:        char *s = alloc(n + strlen(s2) + 1);
        !           226: 
        !           227:        strcpy(s, s1);
        !           228:        strcpy(s + n, s2);
        !           229:        return s;
        !           230: }
        !           231: 
        !           232: /* compile - compile src into dst, return status */
        !           233: static int compile(src, dst) char *src, *dst; {
        !           234:        int n, status;
        !           235: 
        !           236:        compose(com, clist, append(src, 0), append(dst, 0));
        !           237:        status = callsys(av);
        !           238:        if (status && *src == '-') {
        !           239:                char buf[1024];
        !           240:                while ((n = read(0, buf, sizeof buf)) > 0)
        !           241:                        ;
        !           242:        }
        !           243:        return status;
        !           244: }
        !           245: 
        !           246: /* compose - compose cmd into av substituting a, b, c for $1, $2, $3, resp. */
        !           247: static void compose(cmd, a, b, c) char *cmd[]; List a, b, c; {
        !           248:        int i, j;
        !           249:        List lists[3];
        !           250: 
        !           251:        lists[0] = a;
        !           252:        lists[1] = b;
        !           253:        lists[2] = c;
        !           254:        for (i = j = 0; cmd[i]; i++)
        !           255:                if (cmd[i][0] == '$' && isdigit(cmd[i][1])) {
        !           256:                        int k = cmd[i][1] - '0';
        !           257:                        assert(k >= 1 && k <= 3);
        !           258:                        if (b = lists[k-1])
        !           259:                                do {
        !           260:                                        b = b->link;
        !           261:                                        assert(j < ac);
        !           262:                                        av[j++] = b->str;
        !           263:                                } while (b != lists[k-1]);
        !           264:                } else if (*cmd[i]) {
        !           265:                        assert(j < ac);
        !           266:                        av[j++] = cmd[i];
        !           267:                }
        !           268:        av[j] = 0;
        !           269: }
        !           270: 
        !           271: /* cprint - print the command described by argv[0...] followed by str or \n */
        !           272: static void cprint(argv, str) char *argv[], *str; {
        !           273:        if (verbose) {
        !           274:                fprintf(stderr, "%s", *argv++);
        !           275:                while (*argv)
        !           276:                        fprintf(stderr, " %s", *argv++);
        !           277:                if (str == 0)
        !           278:                        str = "\n";
        !           279:                fprintf(stderr, str);
        !           280:        }
        !           281: }
        !           282: 
        !           283: /* error - issue error msg according to fmt, bump error count */
        !           284: static void error(fmt, msg) char *fmt, *msg; {
        !           285:        fprintf(stderr, "%s: ", progname);
        !           286:        fprintf(stderr, fmt, msg);
        !           287:        fprintf(stderr, "\n");
        !           288:        errcnt++;
        !           289: }
        !           290: 
        !           291: /* execute - replace this process by the command described by argv[0...] */
        !           292: static void execute(argv) char *argv[]; {
        !           293:        if (verbose >= 2)
        !           294:                return;
        !           295:        execv(argv[0], argv);
        !           296:        fprintf(stderr, "%s: can't execute `%s'\n", progname, argv[0]);
        !           297:        fflush(stdout);
        !           298:        exit(100);
        !           299: }
        !           300: 
        !           301: /* exists - is `name' readable? issue message if not */
        !           302: static int exists(name) char *name; {
        !           303:        if (verbose > 1 || access(name, 4) == 0)
        !           304:                return 1;
        !           305:        error("can't read `%s'", name);
        !           306:        return 0;
        !           307: }
        !           308: 
        !           309: /* filename - process file name argument `name', return status */
        !           310: static int filename(name, base) char *name, *base; {
        !           311:        int status = 0;
        !           312: 
        !           313:        if (base == 0)
        !           314:                base = basename(name);
        !           315:        switch (suffix(name)) {
        !           316:        case 'c':
        !           317:                if (!exists(name))
        !           318:                        break;
        !           319:                compose(cpp, plist, append(name, 0), 0);
        !           320:                if (Eflag) {
        !           321:                        status = callsys(av);
        !           322:                        break;
        !           323:                }
        !           324:                cprint(av, " | ");
        !           325:                if (verbose <= 1) {
        !           326:                        int fd[2], pid;
        !           327:                        if (pipe(fd) < 0) {
        !           328:                                error("can't create preprocessor-compiler pipe\n", 0);
        !           329:                                exit(1);
        !           330:                        }
        !           331:                        switch (pid = fork()) {
        !           332:                        case -1:
        !           333:                                fprintf(stderr, "%s: no more processes\n", progname);
        !           334:                                return 100;
        !           335:                        case 0:
        !           336:                                close(1);
        !           337:                                dup(fd[1]);
        !           338:                                close(fd[0]);
        !           339:                                close(fd[1]);
        !           340:                                execute(av);
        !           341:                                assert(0);      /* no return from execute */
        !           342:                        }
        !           343:                        close(0);
        !           344:                        dup(fd[0]);
        !           345:                        close(fd[0]);
        !           346:                        close(fd[1]);
        !           347:                }
        !           348:                if (Sflag)
        !           349:                        status = compile("-", outfile ? outfile : concat(base, ".s"));
        !           350:                else if ((status = compile("-", tempname)) == 0)
        !           351:                        return filename(tempname, base);
        !           352:                break;
        !           353:        case 'i':
        !           354:                if (!exists(name) || Eflag)
        !           355:                        break;
        !           356:                if (Sflag)
        !           357:                        status = compile(name, outfile ? outfile : concat(base, ".s"));
        !           358:                else if ((status = compile(name, tempname)) == 0)
        !           359:                        return filename(tempname, base);
        !           360:                break;
        !           361:        case 's':
        !           362:                if (Eflag)
        !           363:                        break;
        !           364:                if (!Sflag) {
        !           365:                        char *ofile = cflag && outfile ? outfile : concat(base, ".o");
        !           366:                        compose(as, alist, append(name, 0), append(ofile, 0));
        !           367:                        status = callsys(av);
        !           368:                        if (!find(ofile, llist[1]))
        !           369:                                llist[1] = append(ofile, llist[1]);
        !           370:                }
        !           371:                break;
        !           372:        case 'o':
        !           373:                if (!find(name, llist[1]))
        !           374:                        llist[1] = append(name, llist[1]);
        !           375:                break;
        !           376:        case -1:
        !           377:                if (Eflag) {
        !           378:                        compose(cpp, plist, append(name, 0), 0);
        !           379:                        status = callsys(av);
        !           380:                } /* else fall thru */
        !           381:        default:
        !           382:                llist[1] = append(name, llist[1]);
        !           383:                break;
        !           384:        }
        !           385:        if (status)
        !           386:                errcnt++;
        !           387:        return status;
        !           388: }
        !           389: 
        !           390: /* find - find 1st occurrence of str in list, return list node or 0 */
        !           391: static List find(str, list) char *str; List list; {
        !           392:        List b;
        !           393:        
        !           394:        if (b = list)
        !           395:                do {
        !           396:                        if (strcmp(str, b->str) == 0)
        !           397:                                return b;
        !           398:                } while ((b = b->link) != list);
        !           399:        return 0;
        !           400: }
        !           401: 
        !           402: static
        !           403: void
        !           404: interrupt(n) {
        !           405:        rm(rmlist);
        !           406:        exit(n = 100);
        !           407: }
        !           408: 
        !           409: /* opt - process option in arg */
        !           410: static void opt(arg) char *arg; {
        !           411:        switch (arg[1]) {       /* multi-character options */
        !           412:        case 'W':       /* -Wxarg */
        !           413:                if (arg[2] && arg[3])
        !           414:                        switch (arg[2]) {
        !           415:                        case 'o':
        !           416:                                if (option(&arg[3]))
        !           417:                                        return;
        !           418:                                break;
        !           419:                        case 'p':
        !           420:                                plist = append(&arg[3], plist);
        !           421:                                return;
        !           422:                        case 'f':
        !           423:                                if (strcmp(&arg[3], "-C") || option("-b")) {
        !           424:                                        clist = append(&arg[3], clist);
        !           425:                                        return;
        !           426:                                }
        !           427:                                break; /* and fall thru */
        !           428:                        case 'a':
        !           429:                                alist = append(&arg[3], alist);
        !           430:                                return;
        !           431:                        case 'l':
        !           432:                                llist[0] = append(&arg[3], llist[0]);
        !           433:                                return;
        !           434:                        }
        !           435:                fprintf(stderr, "%s: %s ignored\n", progname, arg);
        !           436:                return;
        !           437:        case 'd':       /* -dn */
        !           438:                arg[1] = 's';
        !           439:                /* fall thru */
        !           440:        case 't':       /* -t -tname */
        !           441:                clist = append(arg, clist);
        !           442:                return;
        !           443: #ifdef sun
        !           444:        case 'f':       /* -f68881 */
        !           445:                if (!option(arg))
        !           446:                        fprintf(stderr, "%s: %s ignored\n", progname, arg);
        !           447:                return;
        !           448: #endif
        !           449:        case 'p':       /* -p -pg */
        !           450:                if (option(arg))
        !           451:                        clist = append(arg, clist);
        !           452:                else
        !           453:                        fprintf(stderr, "%s: %s ignored\n", progname, arg);
        !           454:                return;
        !           455:        case 'D':       /* -Dname -Dname=def */
        !           456:        case 'U':       /* -Uname */
        !           457:        case 'I':       /* -Idir */
        !           458:                plist = append(arg, plist);
        !           459:                return;
        !           460:        case 'B':       /* -Bdir/ -Bstatic -Bdynamic */
        !           461: #ifdef sun
        !           462:                if (strcmp(arg, "-Bstatic") == 0 || strcmp(arg, "-Bdynamic") == 0)
        !           463:                        llist[1] = append(arg, llist[1]);
        !           464:                else
        !           465: #endif 
        !           466:                {
        !           467:                static char *path;
        !           468:                if (path)
        !           469:                        error("-B overwrites earlier option", 0);
        !           470:                path = arg + 2;
        !           471:                com[0] = concat(path, "rcc");
        !           472:                if (path[0] == 0)
        !           473:                        error("missing directory in -B option", 0);
        !           474:                }
        !           475:                return;
        !           476:        }
        !           477:        if (arg[2] == 0)
        !           478:                switch (arg[1]) {       /* single-character options */
        !           479:                case 'S':
        !           480:                        Sflag++;
        !           481:                        return;
        !           482:                case 'O':
        !           483:                        fprintf(stderr, "%s: %s ignored\n", progname, arg);
        !           484:                        return;
        !           485:                case 'A': case 'n': case 'w': case 'P':
        !           486:                        clist = append(arg, clist);
        !           487:                        return;
        !           488:                case 'g': case 'b':
        !           489:                        if (option(arg))
        !           490:                                clist = append(arg[1] == 'g' ? "-g2" : arg, clist);
        !           491:                        else
        !           492:                                fprintf(stderr, "%s: %s ignored\n", progname, arg);
        !           493:                        return;
        !           494:                case 'G':
        !           495:                        if (option(arg)) {
        !           496:                                clist = append("-g3", clist);
        !           497:                                llist[0] = append("-N", llist[0]);
        !           498:                        } else
        !           499:                                fprintf(stderr, "%s: %s ignored\n", progname, arg);
        !           500:                        return;
        !           501:                case 'E':
        !           502:                        Eflag++;
        !           503:                        return;
        !           504:                case 'c':
        !           505:                        cflag++;
        !           506:                        return;
        !           507:                case 'C':
        !           508:                        plist = append(arg, plist);
        !           509:                        return;
        !           510:                case 'N':
        !           511:                        if (strcmp(basename(cpp[0]), "gcc-cpp") == 0)
        !           512:                                plist = append("-nostdinc", plist);
        !           513:                        include[0] = 0;
        !           514:                        return;
        !           515:                case 'v':
        !           516:                        if (verbose++ == 0) {
        !           517:                                if (strcmp(basename(cpp[0]), "gcc-cpp") == 0)
        !           518:                                        plist = append(arg, plist);
        !           519:                                clist = append(arg, clist);
        !           520:                                fprintf(stderr, "%s version %d.%d\n", progname, VERSION>>8, VERSION&0xff);
        !           521:                        }
        !           522:                        return;
        !           523:                }
        !           524:        if (cflag || Sflag || Eflag)
        !           525:                fprintf(stderr, "%s: %s ignored\n", progname, arg);
        !           526:        else
        !           527:                llist[1] = append(arg, llist[1]);
        !           528: }
        !           529: 
        !           530: /* rm - remove files in list */
        !           531: static void rm(list) List list; {
        !           532:        if (list) {
        !           533:                List b = list;
        !           534:                if (verbose)
        !           535:                        fprintf(stderr, "rm");
        !           536:                do {
        !           537:                        if (verbose)
        !           538:                                fprintf(stderr, " %s", b->str);
        !           539:                        unlink(b->str);
        !           540:                } while ((b = b->link) != list);
        !           541:                if (verbose)
        !           542:                        fprintf(stderr, "\n");
        !           543:        }
        !           544: }
        !           545: 
        !           546: /* strsave - return a saved copy of string str */
        !           547: char *strsave(str) char *str; {
        !           548:        return (char *)strcpy(alloc(strlen(str)+1), str);
        !           549: }
        !           550: 
        !           551: /* suffix - return the 1-character suffix of name, e.g. /usr/drh/foo.c => 'c' */
        !           552: int suffix(name) char *name; {
        !           553:        char *t = 0, *s;
        !           554: 
        !           555:        for (s = name; *s; s++)
        !           556:                if (*s == '/')
        !           557:                        t = 0;
        !           558:                else if (*s == '.')
        !           559:                        t = s + 1;
        !           560:        if (t && t[1] == 0)
        !           561:                return t[0];
        !           562:        return -1;
        !           563: }

unix.superglobalmegacorp.com

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