|
|
1.1 root 1: /*
2: * cc.c
3: * 11/3/90
4: * CC command.
5: * Compile, assemble and link edit C programs.
6: * A lot of grunge.
7: * Revised by rec may1987 to incorporate all
8: * coherent and gemdos revisions to date.
9: *
10: * Defining VeryVflag will produce very verbose output under -VSTAT
11: * option
12: *
13: * C compiler/loader switch map.
14: * *7 marks a version seven documented option.
15: * *7d marks a defunct version seven option.
16: * *7c marks a changed version seven option.
17: * *u marks an option unrecognized by cc, ie passed to linker
18: * with no interpretation or processing.
19: *
20: *7c Bstring use string to find compiler passes
21: * A run in auto edit mode
22: *7 Dname[=value] preprocessor: #define
23: *7 E run preprocessor to stdout
24: *7 Ipathname preprocessor: #include search directory
25: * K keep intermediate files in name.[P012so]
26: * L loader: directive for >64K file sizes
27: * Mstring use string as cross-compiler prefix
28: * N[01ab2sdlrt]string rename pass with string
29: *7 O run object code optimiser
30: *7d P put preprocessor output into name.i; use -Kqp
31: * Q be quiet, make no messages
32: *7 S make assembly language output in name.s
33: *7 Uname preprocessor: #undef
34: * V be verbose, report everything
35: * Vvariant enable variant
36: * X loader: remove c generated local symbols
37: * Z (GEMDOS) floppy change prompts for phases
38: *7 c compile but do not load
39: * d loader: define common space
40: *7 e name loader: entry point specification
41: *7c f fake floating point operations
42: *7u i loader: separate i and d spaces
43: * k[system] loader: bind as kernel process
44: *7c lname loader: library specification
45: *7u n loader: shared instruction space
46: *7 o name loader: output file name
47: *7 p generate code to profile function calls
48: * q[p012s] quit after specified pass
49: * r loader: retain relocation in output
50: * s loader: strip symbol table
51: *7c t[p012adlrt] take specified passes from -Bdirectory
52: *7 u name loader: enter name into symbol table
53: * w loader: watch
54: * x loader: remove local symbols from symbol table
55: */
56: #if GEMDOS
57: #ifndef VERS
58: #define VERS "2.1"
59: #endif
60: #endif
61:
62: #include <stdio.h>
63: #include <ctype.h>
64: #include <signal.h>
65: #include <path.h>
66: #include <errno.h>
67: #include "mch.h"
68: #undef NONE
69: #include "var.h"
70: #include "varmch.h"
71:
72: #ifndef VeryVflag
73: #define VeryVflag 0
74: #endif
75:
76: #ifndef PREFIX
77: #define PREFIX ""
78: #endif
79:
80: /*
81: ** Pass information.
82: */
83: #define NONE -1
84: #define CPP 0 /* Pass index numbers */
85: #define CC0 1
86: #define CC1 2
87: #define CC2 3
88: #define CC3 4
89: #define CC4 5 /* Output writer postprocessor */
90: #define AS 6
91: #define LD 7
92: #define LD2 8 /* Loader postprocessor */
93: #define ED 9
94: #define LIB 10
95: #define CRT 11
96: #define TMP 12
97: #define ALL 13
98:
99: #define P_TAKE 1 /* Take pass from backup directory */
100: #define P_BACK 2 /* Backup directory specified */
101: #define P_LIB 4 /* Take pass from LIBPATH */
102: #define P_BIN 8 /* Take pass from BIN */
103:
104: #define PTMP 16 /* Pass name buffer size */
105:
106: char dnul[] = ""; /* Global null string */
107: char dmch[PTMP] = PREFIX; /* Cross compiler prefix */
108:
109: struct pass {
110: char p_flag; /* Flags */
111: char p_psn; /* Pass short name */
112: char p_pln[PTMP]; /* Pass long name */
113: char p_pfs[4]; /* Pass output file suffix */
114: char *p_ifn; /* Input file name */
115: char *p_ofn; /* Output file name */
116: char *p_sfn; /* Scratch file name */
117: char *p_dir; /* Path lookup or backup string */
118: char *p_mch; /* Machine prefix name */
119: } pass[] = {
120: { P_LIB, 'p', "cpp", "i", NULL, NULL, NULL, NULL, dmch },
121: { P_LIB, '0', "cc0", "0", NULL, NULL, NULL, NULL, dmch },
122: { P_LIB, '1', "cc1", "1", NULL, NULL, NULL, NULL, dmch },
123: { P_LIB, '2', "cc2", "o", NULL, NULL, NULL, NULL, dmch },
124: { P_LIB, '3', "cc3", "s", NULL, NULL, NULL, NULL, dmch },
125: { P_LIB, '4', "cc4", "o", NULL, NULL, NULL, NULL, dmch },
126: { P_BIN, 's', "as", "o", NULL, NULL, NULL, NULL, dmch },
127: { P_BIN, 'd', "ld", "", NULL, NULL, NULL, NULL, dnul },
128: { P_BIN, 'x', "ld2", "", NULL, NULL, NULL, NULL, dnul },
129: { P_BIN, 'e', "me", "", NULL, NULL, NULL, NULL, dnul },
130: { P_LIB, 'l', "lib", "a", NULL, NULL, NULL, NULL, dmch },
131: { P_LIB, 'r', "crts0.o", "", NULL, NULL, NULL, NULL, dmch },
132: { 0, 't', "cc", "", NULL, NULL, NULL, NULL, dnul }
133: };
134:
135: /*
136: ** Option and argument information.
137: */
138: #define CCOPT 0x001 /* Argument flags in argf[] */
139: #define PPOPT 0x002 /* Also in option table, at least */
140: #define LDOPT 0x004 /* those that fit in a byte */
141: #define LD2OPT 0x008
142: #define CCLIB 0x010
143: #define LDLIB 0x020
144: #define CCARG 0x040
145: #define ASARG 0x080
146: #define MARG 0x100
147: #define LDARG 0x200
148:
149: #define FLAG_c 1 /* -c flag */
150: #define FLAG_O 2 /* -O flag */
151: #define FLAG_f 4 /* -f flag */
152: #define FLAG_K 010 /* -K or -VKEEP flag */
153: #define VS 020 /* Turn on strict messages */
154: #define VDB 040 /* Turn on debugging */
155: #define FLAG_A 0100 /* Auto edit mode */
156: #define FLAG_Z 0200 /* Floppy change prompts */
157: #define FLAG_V 0400 /* Verbose flag */
158:
159: #define FLAG_GEMAPP 01000 /* Gem application compile */
160: #define FLAG_GEMACC 02000 /* Gem accessory compile */
161:
162: struct option { /* option table */
163: char o_kind;
164: char o_flag;
165: char *o_name;
166: int o_bits;
167: } option[] = {
168: /* Strict */
169: { 0, CCOPT, "VSUREG", VSUREG },
170: { 0, CCOPT, "VSUVAR", VSUVAR },
171: { 0, CCOPT, "VSNREG", VSNREG },
172: { 0, CCOPT, "VSRTVC", VSRTVC },
173: { 0, CCOPT, "VSMEMB", VSMEMB },
174: { 0, CCOPT, "VSBOOK", VSBOOK },
175: { 0, CCOPT, "VSLCON", VSLCON },
176: { 0, CCOPT, "VSPVAL", VSPVAL },
177: { 0, CCOPT, "VSCCON", VSCCON },
178: /* Debug */
179: { 0, CCOPT, "VDEBUG", VDEBUG },
180: { 0, CCOPT, "VDLINE", VLINES },
181: { 0, CCOPT, "VDTYPE", VTYPES },
182: { 0, CCOPT, "VDSYMB", VDSYMB },
183: { 0, CCOPT, "VDCALL", VCALLS },
184: /* Miscellaneous */
185: { 0, CCOPT, "VSTAT", VSTAT },
186: { 0, CCOPT, "VSINU", VSINU },
187: { 0, CCOPT, "VPEEP", VPEEP },
188: { 0, CCOPT, "VCOMM", VCOMM },
189: { 0, CCOPT, "VQUIET", VQUIET },
190: { 0, CCOPT, "VPSTR", VPSTR },
191: { 0, CCOPT, "VROM", VROM },
192: { 0, CCOPT, "VASM", VASM },
193: { 0, CCOPT, "VPROF", VPROF },
194: { 0, CCOPT, "VALIEN", VALIEN },
195: { 0, CCOPT, "VNOOPT", VNOOPT },
196: { 0, CCOPT, "VCHASM", VCHASM },
197: { 0, CCOPT, "VCPP", VCPP },
198: { 0, CCOPT, "VCPPE", VCPPE },
199: { 0, CCOPT, "VTPROF", VTPROF },
200: { 0, CCOPT, "V3GRAPH", V3GRAPH },
201: #if 1
202: /* Intel flags */
203: { 0, CCOPT, "VSMALL", VSMALL },
204: { 0, CCOPT, "VLARGE", VLARGE },
205: { 0, CCOPT, "V8087", V8087 },
206: { 0, CCOPT, "VRAM", VRAM },
207: { 0, CCOPT, "VOMF", VOMF },
208: { 0, CCOPT, "V80186", V80186 },
209: { 0, CCOPT, "V80287", V80287 },
210: { 0, CCOPT, "VALIGN", VALIGN },
211: { 0, CCOPT, "VEMU87", VEMU87 },
212: #endif
213: /* Motorola and Gemdos flags */
214: { 12, CCOPT, "VGEMACC", FLAG_GEMACC },
215: { 12, CCOPT, "VGEMAPP", FLAG_GEMAPP },
216: { 12, CCOPT, "VGEM", FLAG_GEMAPP },
217: { 10, CCOPT, "VSPLIM", VSPLIM },
218: { 10, CCOPT, "VNOTRAPS", VNOTRAPS },
219: /* More miscellaneous flags */
220: { 2, CCOPT, "VDB", VDB },
221: { 2, CCOPT, "VS", VS },
222: { 12, CCOPT, "A", FLAG_A },
223: { 12, CCOPT, "Z", FLAG_Z },
224: { 12, CCOPT, "c", FLAG_c },
225: { 10, CCOPT, "S", VASM },
226: { 2, CCOPT, "O", FLAG_O },
227: { 0, CCOPT, "E", VCPPE },
228: { 12, CCOPT, "f", FLAG_f },
229: { 12, CCOPT, "VFLOAT", FLAG_f },
230: { 0, CCOPT, "p", VPROF },
231: { 12, CCOPT, "VKEEP", FLAG_K },
232: { 12, CCOPT, "K", FLAG_K },
233: { 0, CCOPT, "Q", VQUIET },
234: { 12, CCOPT, "V", FLAG_V },
235: { 12, CCOPT, "v", FLAG_V },
236: /* Preprocessor options */
237: { 3, PPOPT, "D" },
238: { 3, PPOPT, "I" },
239: { 3, PPOPT, "U" },
240: /* Loader options */
241: { 4, LDOPT, "d" },
242: { 4, LDOPT, "i" },
243: { 4, LDOPT, "n" },
244: { 5, LDOPT, "o" },
245: { 4, LDOPT, "r" },
246: { 4, LDOPT, "s" },
247: { 4, LDOPT, "w" },
248: { 4, LDOPT, "x" },
249: { 4, LDOPT, "X" },
250: #if 0
251: { 4, LDOPT, "L" },
252: #endif
253: { 5, LDOPT, "e" },
254: { 5, LDOPT, "k" },
255: { 5, LDOPT, "u" },
256: /* C dispatcher options */
257: { 6, CCOPT, "q" },
258: { 7, CCOPT, "t" },
259: { 7, CCOPT, "B" },
260: { 7, CCOPT, "M" },
261: { 7, CCOPT, "N" },
262: { 8, CCLIB, "l" },
263:
264: { -1, -1, "" }
265: };
266:
267: int ccvariant = 0; /* Variant template */
268: VARIANT variant; /* Binary variant template */
269: char vstr[2*VMAXIM/VGRANU + 1]; /* Ascii variant string */
270: char vstr2[2*VMAXIM/VGRANU + 1]; /* Ascii variant string for .m */
271:
272: /*
273: ** Compiler parameters and flags
274: */
275: #define NCMDA 128 /* Size of argument pointer buffer */
276: #define NCMDB 1024 /* Size of argument buffer */
277: #define NTMP L_tmpnam /* Temp file buffer size, from stdio.h */
278: #define MAGIC 127 /* Exit status mask */
279: #define NSLEEP 10 /* # of sleeps */
280: #define DELAY 5 /* Sleep delay, seconds */
281:
282: int nldob; /* Number of objects created */
283: int nfile; /* Number of files to compile or assemble */
284: int nname; /* Number of file name arguments */
285: int ndota;
286: int ndotc;
287: int ndotm;
288: int ndoto;
289: int ndots;
290: int partial; /* Partial link specified */
291:
292: #define cflag ((ccvariant&FLAG_c)!=0)
293: #define pflag isvariant(VPROF)
294: #define fflag ((ccvariant&FLAG_f)!=0)
295: #define Kflag ((ccvariant&FLAG_K)!=0)
296: #define Oflag ((ccvariant&FLAG_O)!=0)
297: #define Sflag isvariant(VASM)
298: #define Eflag isvariant(VCPPE)
299: #define Vflag ((ccvariant&FLAG_V)!=0)
300: #define Qflag isvariant(VQUIET)
301: #define Aflag ((ccvariant&FLAG_A)!=0)
302: #define Zflag ((ccvariant&FLAG_Z)!=0)
303: #define GEMAPPflag ((ccvariant&FLAG_GEMAPP)!=0)
304: #define GEMACCflag ((ccvariant&FLAG_GEMACC)!=0)
305:
306: int qpass = NONE; /* Quit after this pass */
307: int nload; /* No load phase */
308: char *outf; /* Output file */
309: char *doutf; /* Default output file stem */
310: char *dpath = DEFPATH;
311: char *dlibpath = DEFLIBPATH;
312: int xstat; /* Exit status */
313:
314: char *cmda[NCMDA]; /* Argument pointer buffer */
315: char cmdb[NCMDB]; /* Argument buffer */
316: char newo[NTMP]; /* New object to be removed */
317: char tmp[7][NTMP]; /* Intermediate filenames */
318: char istmp[7]; /* Truth about their temporariness */
319: int argf[NCMDA]; /* Argument flags */
320: char optb[NCMDB]; /* Option rewrite buffer */
321: char *optp = &optb[0]; /* Option rewrite position */
322:
323: char *makepass();
324: char *makelib();
325: int cleanup();
326: char *getenv();
327: char *tempnam();
328: char *path();
329:
330: main(argc, argv)
331: char *argv[];
332: {
333: register char *p;
334: register struct option *op;
335: int i, narg, c;
336:
337: #if COHERENT
338: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
339: signal(SIGINT, cleanup);
340: #endif
341: setbuf(stdout, NULL);
342: setbuf(stderr, NULL);
343: setvariant(VSUVAR);
344: setvariant(VSMEMB);
345: setvariant(VSLCON);
346: setvariant(VSPVAL);
347: setvariant(VPEEP);
348: setvariant(VCOMM);
349: setvariant(V80186);
350:
351: if (p = getenv("PATH")) dpath = p;
352: if (p = getenv("LIBPATH")) dlibpath = p;
353: if (p = getenv("EDITOR")) strcpy(pass[ED].p_pln, p);
354:
355: for (i=1; i<argc; i+=narg) {
356: narg = 1;
357: p = argv[i];
358: if (*p++ == '-') {
359: static char tppopt[64] = "-";
360: static char tldopt[64] = "-";
361: char *tpp = &tppopt[1];
362: char *tlp = &tldopt[1];
363:
364: if (*p == '\0') {
365: badopt:
366: whatopt(argv[i]);
367: continue;
368: }
369: while (*p != '\0') {
370: for (op = &option[0]; ; op += 1)
371: if (op->o_name[0] == '\0')
372: goto badopt;
373: else if (opeq(op->o_name, p))
374: break;
375: if (VeryVflag && Vflag)
376: printf("Option: -%s\n", op->o_name);
377: argf[i] |= op->o_flag;
378: switch (op->o_kind) {
379: case 0:
380: chgvariant(op->o_bits);
381: p += strlen(op->o_name);
382: continue;
383: case 10:
384: setvariant(op->o_bits);
385: p += strlen(op->o_name);
386: continue;
387: case 2:
388: ccvariant ^= op->o_bits;
389: p += strlen(op->o_name);
390: /* Set strict */
391: if ((ccvariant&VS) != 0) {
392: for (op = &option[0];; op += 1)
393: if (op->o_name[1]=='S')
394: break;
395: while (op->o_name[1]=='S') {
396: setvariant(op->o_bits);
397: op += 1;
398: }
399: }
400: /* Set debug */
401: if ((ccvariant&VDB) != 0) {
402: for (op = &option[0];; op += 1)
403: if (op->o_name[1]=='D')
404: break;
405: while (op->o_name[1]=='D') {
406: setvariant(op->o_bits);
407: op += 1;
408: }
409: }
410: continue;
411: case 12:
412: ccvariant |= op->o_bits;
413: p += strlen(op->o_name);
414: continue;
415: case 3:
416: while (*tpp++ = *p)
417: p++;
418: continue;
419: case 5:
420: if (*p == 'o') {
421: outf = argv[i+narg];
422: }
423: if (*p == 'u')
424: ndoto += 1;
425: if (i+narg >= argc)
426: missingname();
427: argf[i+narg++] = LDOPT;
428: /* Fall through */
429: case 4:
430: if (*p == 'r')
431: ++partial;
432: strcpy(tlp, op->o_name);
433: tlp += strlen(op->o_name);
434: p += strlen(op->o_name);
435: continue;
436: case 6:
437: if ((c = p[1]) == '\0'
438: || (c = getpsn(c)) < CPP)
439: goto badopt;
440: qpass = c;
441: p += 2;
442: continue;
443: case 7:
444: c = p[0];
445: getpass(c, p+1);
446: p = dnul;
447: continue;
448: case 8:
449: p = dnul;
450: continue;
451: default:
452: cfatal("options");
453: }
454: }
455: if (((unsigned)argf[i]-1)&((unsigned)argf[i])) {
456: strcpy(optp, argv[i]);
457: argv[i] = optp;
458: optp += strlen(optp)+1;
459: strcpy(optp, tppopt);
460: optp += strlen(optp)+1;
461: strcpy(optp, tldopt);
462: optp += strlen(optp)+1;
463: }
464: } else {
465: while (*p) p+=1;
466: c = *--p;
467: if (*--p != '.') c = 0;
468: if (c >= 'A' && c <= 'Z')
469: c |= 'a'-'A';
470: switch (c) {
471: case 'h':
472: case 'c':
473: if (doutf == NULL) doutf = argv[i];
474: ndotc += 1;
475: argf[i] = CCARG;
476: if (VeryVflag && Vflag)
477: printf("cc file: %s\n", argv[i]);
478: break;
479: case 's':
480: if (doutf == NULL) doutf = argv[i];
481: ndots += 1;
482: argf[i] = ASARG;
483: if (VeryVflag && Vflag)
484: printf("as file: %s\n", argv[i]);
485: break;
486: case 'm':
487: if (doutf == NULL) doutf = argv[i];
488: ndotm += 1;
489: argf[i] = MARG;
490: if (VeryVflag && Vflag)
491: printf("m file: %s\n", argv[i]);
492: break;
493: case 'o':
494: if (doutf == NULL) doutf = argv[i];
495: ndoto += 1;
496: argf[i] = LDARG;
497: if (VeryVflag && Vflag)
498: printf("ld file: %s\n", argv[i]);
499: break;
500: case 'a':
501: default:
502: ndota += 1;
503: argf[i] = LDLIB;
504: if (VeryVflag && Vflag)
505: printf("library: %s\n", argv[i]);
506: break;
507: }
508: }
509: }
510: #if GEMDOS
511: if (Vflag) {
512: fprintf(stderr, "Mark Williams C for the Atart ST, %s\n", VERS);
513: fprintf(stderr, "Copyright 1984-1987, Mark Williams Co., Chicago\n");
514: }
515: #endif
516: resolve();
517: compile(argc, argv);
518: if (nload==0 && runld(argc, argv)==0) {
519: if (Kflag==0 && nldob==1 && newo[0]!=0)
520: rm(newo);
521: }
522: exit(xstat);
523: }
524:
525: /*
526: * Resolve remaining ambiguities.
527: * Initialize variant arguments and files.
528: */
529: resolve()
530: {
531: register int i;
532: extern char *index();
533:
534: for (i = CPP; i < ALL; i += 1) {
535: if (pass[i].p_flag & P_BACK)
536: ;
537: else if (pass[i].p_flag & P_LIB)
538: pass[i].p_dir = dlibpath;
539: else if (pass[i].p_flag & P_BIN)
540: pass[i].p_dir = dpath;
541: strcpy(cmdb, pass[i].p_mch);
542: strcat(cmdb, pass[i].p_pln);
543: #if GEMDOS
544: if (i <= ED && index(pass[i].p_pln, '.') == NULL)
545: strcat(cmdb, i==ED ? ".tos" : ".prg");
546: #endif
547: if (strlen(cmdb) > PTMP-1)
548: cfatal("pass name \"%s\" is too long", cmdb);
549: strcpy(pass[i].p_pln, cmdb);
550: }
551: #if 1
552: if (isvariant(VOMF)) {
553: clrvariant(VCOMM);
554: if (isvariant(VLARGE) && isvariant(VSMALL))
555: cfatal("invalid model specification");
556: if (notvariant(VLARGE) && notvariant(VSMALL))
557: setvariant(VSMALL);
558: } else {
559: clrvariant(VLARGE);
560: setvariant(VSMALL);
561: }
562: #endif
563: if (GEMAPPflag && GEMACCflag)
564: cfatal("specify VGEMAPP or VGEMACC, not both");
565: if (GEMAPPflag) getpass('N', "rcrtsg.o");
566: if (GEMACCflag) getpass('N', "rcrtsd.o");
567: if (pflag) getpass('N', "rmcrts0.o");
568: if (Eflag) setvariant(VCPP);
569: if (qpass == NONE) {
570: if (isvariant(VCPP))
571: qpass = CPP;
572: else if (Sflag)
573: qpass = CC3;
574: else if (cflag)
575: qpass = AS;
576: else
577: qpass = LD;
578: } else if (qpass == CPP)
579: setvariant(VCPP);
580: if (VeryVflag && Vflag)
581: printf("quit pass is %s\n", pass[qpass].p_pln);
582: makvariant(vstr);
583: if (ndotm != 0 && notvariant(VCPP) && notvariant(VCPPE)) {
584: setvariant(VCPP);
585: setvariant(VCPPE);
586: makvariant(vstr2);
587: clrvariant(VCPP);
588: clrvariant(VCPPE);
589: }
590: nfile = ndotc + ndots + ndotm;
591: nname = nfile + ndoto + ndota;
592: if (nname == 0) {
593: fprintf(stderr,
594: "Usage: cc [ -o output ] [ options ] file [ ... ]\n");
595: exit(1);
596: }
597: if (qpass < LD)
598: ++nload;
599: if (Aflag)
600: maketempfile(6);
601: if ( ! Eflag) {
602: chkofile();
603: if (Kflag) {
604: pass[CPP].p_ofn = pass[CC0].p_ifn = tmp[0];
605: pass[CC0].p_ofn = pass[CC1].p_ifn = tmp[1];
606: pass[CC1].p_ofn = pass[CC2].p_ifn = tmp[2];
607: if ( ! Sflag) {
608: pass[CC2].p_sfn = tmp[3];
609: pass[CC2].p_ofn = tmp[5];
610: } else {
611: pass[CC3].p_ifn = pass[CC2].p_ofn = tmp[3];
612: pass[CC3].p_ofn = tmp[5];
613: }
614: } else {
615: pass[CPP].p_ofn = pass[CC0].p_ifn = tmp[0];
616: pass[CC0].p_ofn = pass[CC1].p_ifn = tmp[1];
617: pass[CC1].p_ofn = pass[CC2].p_ifn = tmp[0];
618: if ( ! Sflag) {
619: pass[CC2].p_sfn = tmp[1];
620: pass[CC2].p_ofn = tmp[5];
621: } else {
622: pass[CC3].p_ifn = pass[CC2].p_ofn = tmp[1];
623: pass[CC3].p_ofn = tmp[5];
624: }
625: maketempfile(0);
626: maketempfile(1);
627: }
628: pass[AS].p_ofn = tmp[5];
629: }
630: }
631:
632: maketempfile(i) int i;
633: {
634: char *p;
635: strcpy(tmp[i], p = tempnam(pass[TMP].p_dir, pass[TMP].p_pln));
636: free(p);
637: ++istmp[i];
638: }
639:
640: /*
641: ** Compilation.
642: */
643: compile(argc, argv)
644: char *argv[];
645: {
646: register char *p1;
647: register c, i, err;
648:
649: err = 0;
650: for (i=1; i<argc; ++i) {
651: if ((c = (argf[i] & (CCARG | ASARG | MARG))) == 0)
652: continue;
653: p1 = argv[i];
654: if (err) {
655: err = 0;
656: if (runme(p1)) {
657: ++nload;
658: } else {
659: --i;
660: xstat = 0;
661: }
662: continue;
663: }
664: if (nfile > 1 && Qflag == 0)
665: printf("%s:\n", p1);
666: setfiles(c, p1);
667: if (c == CCARG) {
668: if (runpp(argc, argv, vstr)) {
669: if (Aflag) {
670: ++err; --i;
671: } else
672: ++nload;
673: continue;
674: }
675: if (qpass <= CC0)
676: continue;
677: if (runcc(CC1)) {
678: ++nload;
679: continue;
680: }
681: if (qpass <= CC1)
682: continue;
683: if (runcc(CC2)) {
684: ++nload;
685: continue;
686: }
687: if (qpass <= CC2)
688: continue;
689: if (Sflag) {
690: if (runcc(CC3)) {
691: ++nload;
692: continue;
693: }
694: if (qpass <= CC3)
695: continue;
696: }
697: } else if (c == ASARG && qpass>=AS) {
698: if (runas()) {
699: if (Aflag) {
700: ++err; --i;
701: } else
702: ++nload;
703: continue;
704: }
705: if (qpass <= AS)
706: continue;
707: } else if (c == MARG) {
708: if (runpp(argc, argv, vstr2)) {
709: if (Aflag) {
710: ++err; --i;
711: } else
712: ++nload;
713: continue;
714: }
715: if (qpass < AS)
716: continue;
717: if (runas()) {
718: if (Aflag) {
719: ++err; --i;
720: } else
721: ++nload;
722: continue;
723: }
724: if (qpass == AS)
725: continue;
726: }
727: makeft(p1, p1, "o");
728: }
729: cleanup(0);
730: }
731:
732: runpp(argc, argv, var)
733: register char *argv[];
734: char var[];
735: {
736: register char **cp;
737: register int i;
738: char *p1;
739:
740: cp = cmda;
741: p1 = cmdb;
742: p1 = makepass(CC0, *cp++ = p1, AEXEC);
743: *cp++ = var;
744: *cp++ = pass[CPP].p_ifn;
745: if (qpass < CC0)
746: *cp++ = Kflag ? pass[CPP].p_ofn : "-";
747: else
748: *cp++ = pass[CC0].p_ofn;
749: for (i=1; i<argc; ++i) {
750: if ((argf[i]&PPOPT) != 0) {
751: *cp++ = argv[i];
752: if ((argf[i]&~PPOPT) != 0)
753: cp[-1] += strlen(cp[-1])+1;
754: }
755: }
756: *cp = 0;
757: return (run(Aflag));
758: }
759:
760: runcc(pn)
761: {
762: register char **cp;
763:
764: cp = cmda;
765: makepass(pn, *cp++ = cmdb, AEXEC);
766: *cp++ = vstr;
767: *cp++ = pass[pn].p_ifn;
768: *cp++ = pass[pn].p_ofn;
769: if (pn == CC2)
770: *cp++ = pass[CC2].p_sfn;
771: *cp = 0;
772: return (run(0));
773: }
774:
775: runas()
776: {
777: register char **cp;
778:
779: cp = cmda;
780: makepass(AS, *cp++ = cmdb, AEXEC);
781: *cp++ = "-gx";
782: *cp++ = "-o";
783: *cp++ = pass[AS].p_ofn;
784: *cp++ = pass[AS].p_ifn;
785: *cp = 0;
786: return (run(Aflag));
787: }
788:
789: runme(fn)
790: char *fn;
791: {
792: register char **cp;
793:
794: cp = cmda;
795: makepass(ED, *cp++ = cmdb, AEXEC);
796: *cp++ = fn;
797: *cp++ = "-e";
798: *cp++ = tmp[6];
799: *cp = 0;
800: return (run(0));
801: }
802: runld(argc, argv)
803: char *argv[];
804: {
805: char *p1;
806: register char *p2;
807: register char **cp;
808: char **cp1;
809: register char **cp2;
810: int i;
811: static char buff[32];
812:
813: cp = cmda;
814: p1 = makepass(LD, *cp++ = cmdb, AEXEC);
815: *cp++ = "-X";
816: if (outf == NULL) {
817: *cp++ = "-o";
818: if (partial || doutf == NULL) {
819: #if COHERENT
820: *cp++ = "l.out";
821: #endif
822: #if GEMDOS
823: *cp++ = "l.prg";
824: #endif
825: } else {
826: basename(doutf, buff);
827: #if GEMDOS
828: strcat(buff, ".prg");
829: #endif
830: *cp++ = buff;
831: }
832: }
833: for (i=1; i<argc; ++i) {
834: if ((argf[i]&LDOPT)!=0) {
835: *cp++ = argv[i];
836: if ((argf[i]&~LDOPT)!=0) {
837: cp[-1] += strlen(cp[-1])+1;
838: cp[-1] += strlen(cp[-1])+1;
839: }
840: }
841: }
842: cp1 = cp;
843: p1 = makepass(CRT, *cp++ = p1, AREAD);
844: if (fflag) {
845: *cp++ = "-u";
846: *cp++ = "_dtefg_";
847: }
848: for (i=1; i<argc; ++i) {
849: p2 = argv[i];
850: if ((argf[i]&CCLIB)!=0) {
851: while (*p2++ != 'l');
852: p1 = makelib(LIB, *cp++ = p1, p2);
853: } else if ((argf[i]&(CCARG|ASARG|MARG|LDARG))!=0) {
854: for (cp2=cp1; cp2<cp; ++cp2)
855: if (strcmp(*cp2, p2) == 0)
856: break;
857: if (cp2 == cp) {
858: *cp++ = p2;
859: ++nldob;
860: }
861: } else if ((argf[i]&LDLIB)!=0) {
862: *cp++ = p2;
863: }
864: }
865: if ( ! partial && (GEMAPPflag || GEMACCflag)) {
866: p1 = makelib(LIB, *cp++ = p1, "aes");
867: p1 = makelib(LIB, *cp++ = p1, "vdi");
868: }
869: p1 = makelib(LIB, *cp++ = p1, "c");
870: *cp = 0;
871: return (run(0));
872: }
873:
874: basename(in, out)
875: char *in, *out;
876: {
877: register char *ip = in, *op = out;
878: register int c;
879:
880: while (*ip++)
881: ;
882: ip -= 2;
883: while (ip >= in && *ip != PATHSEP)
884: --ip;
885: while ((c = *++ip) && c != '.')
886: *op++ = c;
887: *op = '\0';
888: }
889:
890: run(catch_errors) int catch_errors;
891: {
892: int new_fd;
893: int saved_fd;
894: int s;
895: extern char **environ;
896:
897: if (Vflag) {
898: char *cp, **cpp;
899: cpp = cmda;
900: while ((cp = *cpp) != NULL) {
901: if (cpp != cmda)
902: putchar(' ');
903: printf("%s", cp);
904: ++cpp;
905: }
906: putchar('\n');
907: fflush(stdout);
908: }
909: if (catch_errors) {
910: fflush(stdout);
911: saved_fd = dup(1);
912: if ((new_fd = creat(tmp[6], 0644)) < 0)
913: cfatal("%s: %s", tmp[6], sys_errlist[errno]);
914: if (dup2(new_fd, 1) < 0)
915: cfatal("dup2 failed");
916: }
917: #if COHERENT
918: {
919: int nsleep;
920: int status;
921: int pid;
922: nsleep = NSLEEP;
923: while ((pid=fork())<0 && nsleep--)
924: sleep(DELAY);
925: if (pid < 0)
926: cfatal("can't fork");
927: if (pid == 0) {
928: execve(cmda[0], cmda, environ);
929: exit(MAGIC);
930: }
931: while (wait(&status) != pid)
932: ;
933: if ((s = status&0177)!=0 && s!=SIGINT) {
934: extern char *signame[];
935:
936: fprintf(stderr, "cc: %s ", cmda[0]);
937: if (s==SIGSYS && (status&0200)==0)
938: fprintf(stderr, "exec failed");
939: else
940: fprintf(stderr, signame[s]);
941: if ((status&0200) != 0)
942: fprintf(stderr, " -- core dumped");
943: fprintf(stderr, "\n");
944: } else if ((s = (status>>8)&0377) == MAGIC)
945: cfatal("cannot execute %s", cmda[0]);
946: }
947: #else
948: if (s = execve(cmda[0], cmda, environ))
949: if (s < 0)
950: perror(cmda[0]);
951: #endif
952: if (catch_errors) {
953: fflush(stdout);
954: if (dup2(saved_fd, 1) < 0)
955: cfatal("dup2 failed");
956: if (close(new_fd) < 0)
957: /* cfatal("error on close") */ ;
958: }
959: if (s != 0)
960: xstat = 1;
961: return (s);
962: }
963:
964: /*
965: ** Option processing.
966: */
967:
968: /*
969: * Compare option name to argument.
970: */
971: opeq(op, ap)
972: register char *op, *ap;
973: {
974: while (*op!=0)
975: if (*op++ != *ap++)
976: return (0);
977: return (1);
978: }
979:
980:
981: /*
982: * Get short pass name.
983: * translate single character code into pass index number.
984: */
985: getpsn(c)
986: register int c;
987: {
988: register int pn;
989:
990: for (pn = CPP; pn < ALL; pn += 1)
991: if (pass[pn].p_psn == c)
992: return (pn);
993: return (NONE);
994: }
995:
996: /*
997: * Process -t*, -B*, -M* options.
998: * -t* sets take flag for specified passes.
999: * -B* copies prefix string for flagged passes
1000: * or for all machine dependent passes if none flagged.
1001: * -M* copies machine string for machine dependent passes.
1002: * -N* renames a pass, such as crts0.o.
1003: */
1004: getpass(c, cp)
1005: register int c;
1006: register char *cp;
1007: {
1008: if (c == 't') { /* Take passes from backup */
1009: if (*cp != 0)
1010: while ((c = *cp++) != 0)
1011: if ((c = getpsn(c)) >= CPP) {
1012: pass[c].p_flag |= P_TAKE;
1013: pass[c].p_dir = dnul;
1014: if (Vflag)
1015: passrpt(c);
1016: } else {
1017: badpsn(cp[-1]);
1018: }
1019: else
1020: getpass('t', "01234");
1021: } else if (c == 'B') { /* Get backup string */
1022: for (c = CPP; c < ALL; c += 1) {
1023: if ((pass[c].p_flag&P_TAKE) != 0) {
1024: pass[c].p_flag ^= P_TAKE;
1025: pass[c].p_flag |= P_BACK;
1026: pass[c].p_dir = cp;
1027: if (Vflag)
1028: passrpt(c);
1029: }
1030: }
1031: } else if (c == 'M') { /* Machine prefix string */
1032: if (strlen(cp) > PTMP-1)
1033: toolong(cp);
1034: strcpy(dmch, cp);
1035: if (Vflag)
1036: printf("Prefix: %s\n", dmch);
1037: } else if (c == 'N') { /* New pass name */
1038: if ((c = getpsn(*cp++)) >= CPP) {
1039: if (strlen(cp) > PTMP-1)
1040: toolong(cp);
1041: if (Vflag)
1042: printf("Rename: %s to %s\n", pass[c].p_pln, cp);
1043: strcpy(pass[c].p_pln, cp);
1044: } else
1045: badpsn(cp[-1]);
1046: }
1047: }
1048:
1049: passrpt(c)
1050: register int c;
1051: {
1052: printf("Use: {%s}%s%s\n", pass[c].p_dir, pass[c].p_mch, pass[c].p_pln);
1053: }
1054:
1055: missingname()
1056: {
1057: fprintf(stderr, "cc: missing name in -o, -e or -u\n");
1058: exit(1);
1059: }
1060:
1061: badoutput()
1062: {
1063: fprintf(stderr, "cc: improbable name in -o: %s\n", outf);
1064: exit(1);
1065: }
1066:
1067: toomany()
1068: {
1069: fprintf(stderr, "cc: too many files for -o option\n");
1070: exit(1);
1071: }
1072:
1073: badpsn(c)
1074: {
1075: fprintf(stderr, "cc: unknown short path name: %c\n", c);
1076: exit(1);
1077: }
1078:
1079: toolong(cp)
1080: char *cp;
1081: {
1082: fprintf(stderr, "cc: name, prefix, or directory too long: %s\n", cp);
1083: exit(1);
1084: }
1085:
1086: /*
1087: * Check specified output file name,
1088: * or construct name from first file
1089: * name seen.
1090: */
1091: chkofile()
1092: {
1093: register char *fn;
1094: register char c;
1095:
1096: if ((fn = outf) == NULL)
1097: return;
1098: if (fn[0] == '-')
1099: badoutput();
1100: if (nname > 1 && qpass < LD)
1101: toomany();
1102: while (*fn != 0)
1103: ++fn;
1104: while (*fn != '.' && fn > outf)
1105: --fn;
1106: if (*fn++ == '.' && (c = *fn++) && *fn == '\0') {
1107: if (c == 'c'
1108: || c == 'h'
1109: || c == 'm'
1110: || (c != 'o' && cflag)
1111: || (c == 'o' && !cflag)
1112: || (c != 's' && Sflag)
1113: || (c == 's' && !Sflag))
1114: badoutput();
1115: } else {
1116: if (Sflag || cflag)
1117: badoutput();
1118: }
1119: }
1120:
1121: whatopt(s)
1122: char *s;
1123: {
1124: fprintf(stderr, "cc: unrecognized option: %s\n", s);
1125: exit(1);
1126: }
1127:
1128: cfatal(s)
1129: char *s;
1130: {
1131: fprintf(stderr, "cc: fatal error: %r\n", &s);
1132: cleanup(0);
1133: exit(1);
1134: }
1135:
1136: /*
1137: ** Intermediate file processing.
1138: */
1139: /*
1140: * Given cp -> `name.[chms]' rewrite ultimate destination and intermediates
1141: * if necessary.
1142: */
1143: setfiles(c, cp)
1144: int c;
1145: register char *cp;
1146: {
1147: register char *ip;
1148:
1149: ip = cp;
1150: if (qpass < LD && outf != NULL)
1151: cp = outf;
1152: if (c == CCARG) {
1153: pass[CPP].p_ifn = ip;
1154: if (Eflag)
1155: return;
1156: if (Kflag) {
1157: makeft(pass[CPP].p_ofn, cp, "i");
1158: makeft(pass[CC0].p_ofn, cp, "0");
1159: makeft(pass[CC1].p_ofn, cp, "1");
1160: if ( ! Sflag)
1161: makeft(pass[CC2].p_sfn, cp, "2");
1162: else
1163: makeft(pass[CC2].p_ofn, cp, "2");
1164: }
1165: } else if (c == MARG) {
1166: pass[CPP].p_ifn = ip;
1167: if (Kflag)
1168: makeft(pass[CC0].p_ofn, cp, "s");
1169: pass[AS].p_ifn = pass[CC0].p_ofn;
1170: } else if (c == ASARG)
1171: pass[AS].p_ifn = ip;
1172: makeft(tmp[5], cp, Sflag ? "s" : "o");
1173: if (!Sflag && newo[0] == 0 && access(tmp[5], 0) < 0)
1174: strcpy(newo, tmp[5]);
1175: }
1176:
1177: /*
1178: * Unlink a file.
1179: * If `-V' echo the rm.
1180: */
1181: rm(s)
1182: register char *s;
1183: {
1184: if (Vflag)
1185: printf("rm %s\n", s);
1186: unlink(s);
1187: }
1188:
1189: /*
1190: * Cleanup after yourself if
1191: * the user hits interrupt during a compile (sig == SIGINT),
1192: * or when all compiles have completed (sig == 0).
1193: */
1194: cleanup(sig)
1195: {
1196: register int i;
1197:
1198: #if COHERENT
1199: if (sig == SIGINT)
1200: signal(SIGINT, SIG_IGN);
1201: #endif
1202: for (i = 0; i < 7; i += 1)
1203: if (istmp[i])
1204: rm(tmp[i]);
1205: #if COHERENT
1206: if (sig == SIGINT && nldob==1 && newo[0]!=0)
1207: rm(newo);
1208: if (sig == SIGINT)
1209: exit(1);
1210: #endif
1211: }
1212:
1213: /*
1214: ** Name construction.
1215: */
1216: char *
1217: ccpath(cp, p, n, mode) register char *cp; char *p, *n; int mode;
1218: {
1219: register char *pn;
1220: if (VeryVflag && Vflag)
1221: printf("search %s for %s\n", p, n);
1222: while ((pn = path(p, n, mode)) == NULL) {
1223: if (Zflag) { /* Disk swap dialog flag */
1224: fprintf(stderr, "Insert %s's disk in a free drive and press <Return>\n", n);
1225: gets(cp);
1226: continue;
1227: }
1228: pn = n;
1229: break;
1230: }
1231: while (*cp++ = *pn++) ;
1232: return cp;
1233: }
1234:
1235: char *
1236: makepass(pn, cp, mode)
1237: int pn;
1238: register char *cp;
1239: int mode;
1240: {
1241: return ccpath(cp, pass[pn].p_dir, pass[pn].p_pln, mode);
1242: }
1243:
1244: char *
1245: makelib(pn, cp, lp)
1246: int pn;
1247: char *cp;
1248: char *lp;
1249: {
1250: strcpy(cp, pass[pn].p_pln);
1251: strcat(cp, lp);
1252: strcat(cp, ".a");
1253: return ccpath(cp, pass[pn].p_dir, cp, AREAD);
1254: }
1255:
1256: makeft(op, ip, ft)
1257: char *op, *ip, *ft;
1258: {
1259: register char *ep, *tp;
1260: register c;
1261: char *dp;
1262:
1263: ep = ip;
1264: tp = op;
1265: dp = NULL;
1266: while ((c = *ep++) != '\0') {
1267: if (c == PATHSEP && ip != outf) {
1268: tp = op;
1269: dp = NULL;
1270: } else {
1271: if (c == '.')
1272: dp = tp;
1273: *tp++ = c;
1274: }
1275: }
1276: if (ip == outf)
1277: return;
1278: if (dp != NULL)
1279: tp = dp;
1280: *tp++ = '.';
1281: ep = ft;
1282: while (*tp++ = *ep++)
1283: ;
1284: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.