|
|
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.