Annotation of researchv10no/cmd/lcc/etc/lcc.c, revision 1.1.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.