|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.