|
|
1.1 root 1: /*
2: * coh/cc.c
3: * CC command.
4: * Compile, assemble and link edit C programs.
5: * A lot of grunge.
6: * Revised by rec may1987 to incorporate all
7: * coherent and gemdos revisions to date.
8: * Revised by steve 3/92 to produce monolithic COHERENT compiler.
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: * Still up for grabs:
21: * [ C FGH J R W Y ]
22: * [ b gh j m v yz]
23: *
24: * A run in auto edit mode
25: *7c Bstring use string to find compiler passes
26: *7 Dname[=value] preprocessor: #define
27: *7 E run preprocessor to stdout
28: *7 Ipathname preprocessor: #include search directory
29: * K keep intermediate files in name.[P012so]
30: * Lpathname loader: library directory specification
31: * Mstring use string as cross-compiler prefix
32: * N[01ab2sdlrt]string rename pass with string
33: *7 O run object code optimiser
34: *7d P put preprocessor output into name.i; use -Kqp
35: * Q be quiet, make no messages
36: *7 S make assembly language output in name.s
37: * T[value] use in-memory tempfiles of size value (default: 64K)
38: *7 Uname preprocessor: #undef
39: * V be verbose, report everything
40: * Vvariant enable variant
41: * X loader: remove c generated local symbols
42: * Z (GEMDOS) floppy change prompts for phases
43: * a do not implicit output file name to loader
44: *7 c compile but do not load
45: * d loader: define common space
46: *7 e name loader: entry point specification
47: *7c f fake floating point operations
48: *7u i loader: separate i and d spaces
49: * k[system] loader: bind as kernel process
50: *7c lname loader: library specification
51: *7u n loader: shared instruction space
52: *7 o name loader: output file name
53: *7 p generate code to profile function calls
54: * q[p012s] quit after specified pass
55: * r loader: retain relocation in output
56: * s loader: strip symbol table
57: *7c t[p012adlrt] take specified passes from -Bdirectory
58: *7 u name loader: enter name into symbol table
59: * w loader: watch
60: * x loader: remove local symbols from symbol table
61: */
62:
63: #if GEMDOS
64: #ifndef VERS
65: #define VERS "2.1"
66: #endif
67: #endif
68:
69: #include <stdio.h>
70: #include <setjmp.h>
71: #include <string.h>
72: #include <ctype.h>
73: #include <signal.h>
74: #include <path.h>
75: #include <errno.h>
76: #include "mch.h"
77: #include "host.h"
78: #include "ops.h"
79: #include "stream.h"
80: #undef NONE
81: #include "var.h"
82: #include "varmch.h"
83:
84: #ifndef VeryVflag
85: #define VeryVflag 0
86: #endif
87:
88: #ifndef PREFIX
89: #define PREFIX ""
90: #endif
91:
92: #if _I386
93: #define DTEFG "_dtefg"
94: #else
95: #define DTEFG "_dtefg_"
96: #endif
97:
98: /*
99: ** Pass information.
100: */
101: #define NONE -1
102: #define CPP 0 /* Pass index numbers */
103: #define CC0 1
104: #define CC1 2
105: #define CC2 3
106: #define CC3 4
107: #define CC4 5 /* Output writer postprocessor */
108: #define AS 6
109: #define LD 7
110: #define LD2 8 /* Loader postprocessor */
111: #define ED 9
112: #define LIB 10
113: #define CRT 11
114: #define TMP 12
115: #define ALL 13
116: #define CC2B 14 /* for monolithic compiler */
117:
118: #define P_TAKE 1 /* Take pass from backup directory */
119: #define P_BACK 2 /* Backup directory specified */
120: #define P_LIB 4 /* Take pass from LIBPATH */
121: #define P_BIN 8 /* Take pass from BIN */
122:
123: #define PTMP 16 /* Pass name buffer size */
124:
125: char dnul[] = ""; /* Global null string */
126: char dmch[PTMP] = PREFIX; /* Cross compiler prefix */
127:
128: struct pass {
129: char p_flag; /* Flags */
130: char p_psn; /* Pass short name */
131: char p_pln[PTMP]; /* Pass long name */
132: char p_pfs[4]; /* Pass output file suffix */
133: char *p_ifn; /* Input file name */
134: char *p_ofn; /* Output file name */
135: char *p_sfn; /* Scratch file name */
136: char *p_dir; /* Path lookup or backup string */
137: char *p_mch; /* Machine prefix name */
138: } pass[] = {
139: { P_LIB, 'p', "cpp", "i", NULL, NULL, NULL, NULL, dmch },
140: { P_LIB, '0', "cc0", "0", NULL, NULL, NULL, NULL, dmch },
141: { P_LIB, '1', "cc1", "1", NULL, NULL, NULL, NULL, dmch },
142: { P_LIB, '2', "cc2", "o", NULL, NULL, NULL, NULL, dmch },
143: { P_LIB, '3', "cc3", "s", NULL, NULL, NULL, NULL, dmch },
144: { P_LIB, '4', "cc4", "o", NULL, NULL, NULL, NULL, dmch },
145: { P_BIN, 's', "as", "o", NULL, NULL, NULL, NULL, dmch },
146: { P_BIN, 'd', "ld", "", NULL, NULL, NULL, NULL, dnul },
147: { P_BIN, 'x', "ld2", "", NULL, NULL, NULL, NULL, dnul },
148: { P_BIN, 'e', "me", "", NULL, NULL, NULL, NULL, dnul },
149: { P_LIB, 'l', "lib", "a", NULL, NULL, NULL, NULL, dmch },
150: { P_LIB, 'r', "crts0.o", "", NULL, NULL, NULL, NULL, dmch },
151: { 0, 't', "cc", "", NULL, NULL, NULL, NULL, dnul }
152: };
153:
154: /*
155: ** Option and argument information.
156: */
157: #define CCOPT 0x001 /* Argument flags in argf[] */
158: #define PPOPT 0x002 /* Also in option table, at least */
159: #define LDOPT 0x004 /* those that fit in a byte */
160: #define LD2OPT 0x008
161: #define CCLIB 0x010
162: #define LDLIB 0x020
163: #define CCARG 0x040
164: #define ASARG 0x080
165: #define MARG 0x100
166: #define LDARG 0x200
167:
168: /* Flag bits for ccvariant. */
169: #define FLAG_c 0x001 /* -c flag */
170: #define FLAG_O 0x002 /* -O flag */
171: #define FLAG_f 0x004 /* -f flag */
172: #define FLAG_K 0x008 /* -K or -VKEEP flag */
173: #define VS 0x010 /* Turn on strict messages */
174: #define VDB 0x020 /* Turn on debugging */
175: #define FLAG_A 0x040 /* Auto edit mode */
176: #define FLAG_Z 0x080 /* Floppy change prompts */
177: #define FLAG_V 0x100 /* Verbose flag */
178: #define FLAG_GEMAPP 0x200 /* Gem application compile */
179: #define FLAG_GEMACC 0x400 /* Gem accessory compile */
180: #define FLAG_a 0x800 /* Suppress output file name to ld */
181:
182: struct option { /* option table */
183: char o_kind;
184: char o_flag;
185: char *o_name;
186: int o_bits;
187: } option[] = {
188: /* Strict */
189: { 0, CCOPT, "VSUREG", VSUREG },
190: { 0, CCOPT, "VSUVAR", VSUVAR },
191: { 0, CCOPT, "VSNREG", VSNREG },
192: { 0, CCOPT, "VSRTVC", VSRTVC },
193: { 0, CCOPT, "VSMEMB", VSMEMB },
194: { 0, CCOPT, "VSBOOK", VSBOOK },
195: { 0, CCOPT, "VSLCON", VSLCON },
196: { 0, CCOPT, "VSPVAL", VSPVAL },
197: { 0, CCOPT, "VSCCON", VSCCON },
198: /* Debug */
199: { 0, CCOPT, "VDEBUG", VDEBUG },
200: { 0, CCOPT, "VDLINE", VLINES },
201: { 0, CCOPT, "VDTYPE", VTYPES },
202: { 0, CCOPT, "VDSYMB", VDSYMB },
203: { 0, CCOPT, "VDCALL", VCALLS },
204: /* Miscellaneous */
205: { 0, CCOPT, "VSTAT", VSTAT },
206: { 0, CCOPT, "VSINU", VSINU },
207: { 0, CCOPT, "VPEEP", VPEEP },
208: { 0, CCOPT, "VCOMM", VCOMM },
209: { 0, CCOPT, "VQUIET", VQUIET },
210: { 0, CCOPT, "VPSTR", VPSTR },
211: { 0, CCOPT, "VROM", VROM },
212: { 0, CCOPT, "VASM", VASM },
213: { 0, CCOPT, "VPROF", VPROF },
214: { 0, CCOPT, "VALIEN", VALIEN },
215: { 0, CCOPT, "VNOOPT", VNOOPT },
216: { 0, CCOPT, "VCHASM", VCHASM },
217: { 0, CCOPT, "VCPPC", VCPPC },
218: { 0, CCOPT, "VCPPE", VCPPE },
219: { 0, CCOPT, "VCPP", VCPP },
220: { 0, CCOPT, "VTPROF", VTPROF },
221: { 0, CCOPT, "V3GRAPH", V3GRAPH },
222: #if 1
223: /* Intel flags */
224: { 0, CCOPT, "VSMALL", VSMALL },
225: { 0, CCOPT, "VLARGE", VLARGE },
226: { 0, CCOPT, "V8087", V8087 },
227: { 0, CCOPT, "VRAM", VRAM },
228: { 0, CCOPT, "VOMF", VOMF },
229: { 0, CCOPT, "V80186", V80186 },
230: { 0, CCOPT, "V80287", V80287 },
231: { 0, CCOPT, "VALIGN", VALIGN },
232: { 0, CCOPT, "VEMU87", VEMU87 },
233: #endif
234: /* Motorola and Gemdos flags */
235: { 12, CCOPT, "VGEMACC", FLAG_GEMACC },
236: { 12, CCOPT, "VGEMAPP", FLAG_GEMAPP },
237: { 12, CCOPT, "VGEM", FLAG_GEMAPP },
238: { 10, CCOPT, "VSPLIM", VSPLIM },
239: { 10, CCOPT, "VNOTRAPS", VNOTRAPS },
240: /* More miscellaneous flags */
241: { 2, CCOPT, "VDB", VDB },
242: { 2, CCOPT, "VS", VS },
243: { 12, CCOPT, "A", FLAG_A },
244: { 12, CCOPT, "a", FLAG_a },
245: { 12, CCOPT, "Z", FLAG_Z },
246: { 12, CCOPT, "c", FLAG_c },
247: { 10, CCOPT, "S", VASM },
248: { 2, CCOPT, "O", FLAG_O },
249: { 0, CCOPT, "E", VCPPE },
250: { 12, CCOPT, "f", FLAG_f },
251: { 12, CCOPT, "VFLOAT", FLAG_f },
252: { 0, CCOPT, "p", VPROF },
253: { 12, CCOPT, "VKEEP", FLAG_K },
254: { 12, CCOPT, "K", FLAG_K },
255: { 0, CCOPT, "Q", VQUIET },
256: { 12, CCOPT, "V", FLAG_V },
257: { 12, CCOPT, "v", FLAG_V },
258: /* Preprocessor options */
259: { 3, PPOPT, "D" },
260: { 3, PPOPT, "I" },
261: { 3, PPOPT, "U" },
262: /* Loader options */
263: { 4, LDOPT, "d" },
264: { 4, LDOPT, "i" },
265: { 4, LDOPT, "n" },
266: { 5, LDOPT, "o" },
267: { 4, LDOPT, "r" },
268: { 4, LDOPT, "s" },
269: { 4, LDOPT, "w" },
270: { 4, LDOPT, "x" },
271: { 4, LDOPT, "X" },
272: #if 1
273: { 8, LDOPT, "L" },
274: #endif
275: { 5, LDOPT, "e" },
276: { 5, LDOPT, "k" },
277: { 5, LDOPT, "u" },
278: /* C dispatcher options */
279: { 6, CCOPT, "q" },
280: { 7, CCOPT, "t" },
281: { 7, CCOPT, "B" },
282: { 7, CCOPT, "M" },
283: { 7, CCOPT, "N" },
284: #if TEMPBUF
285: { 9, CCOPT, "T" },
286: #endif
287: { 8, CCLIB, "l" },
288:
289: { -1, -1, "" }
290: };
291:
292: int ccvariant = 0; /* Variant template */
293: VARIANT variant; /* Binary variant template */
294: char vstr[2*VMAXIM/VGRANU + 1]; /* Ascii variant string */
295: char vstr2[2*VMAXIM/VGRANU + 1]; /* Ascii variant string for .m */
296:
297: /*
298: ** Compiler parameters and flags
299: */
300: #define NCMDA 128 /* Size of argument pointer buffer */
301: #define NCMDB 1024 /* Size of argument buffer */
302: #define NTMP L_tmpnam /* Temp file buffer size, from stdio.h */
303: #define MAGIC 127 /* Exit status mask */
304: #define NSLEEP 10 /* # of sleeps */
305: #define DELAY 5 /* Sleep delay, seconds */
306:
307: int nldob; /* Number of objects created */
308: int nfile; /* Number of files to compile or assemble */
309: int nname; /* Number of file name arguments */
310: int ndota;
311: int ndotc;
312: int ndotm;
313: int ndoto;
314: int ndots;
315: int partial; /* Partial link specified */
316:
317: #define aflag ((ccvariant&FLAG_a)!=0)
318: #define cflag ((ccvariant&FLAG_c)!=0)
319: #define pflag isvariant(VPROF)
320: #define fflag ((ccvariant&FLAG_f)!=0)
321: #define Kflag ((ccvariant&FLAG_K)!=0)
322: #define Oflag ((ccvariant&FLAG_O)!=0)
323: #define Sflag isvariant(VASM)
324: #define Eflag isvariant(VCPPE)
325: #define Vflag ((ccvariant&FLAG_V)!=0)
326: #define Qflag isvariant(VQUIET)
327: #define Aflag ((ccvariant&FLAG_A)!=0)
328: #define Zflag ((ccvariant&FLAG_Z)!=0)
329: #define GEMAPPflag ((ccvariant&FLAG_GEMAPP)!=0)
330: #define GEMACCflag ((ccvariant&FLAG_GEMACC)!=0)
331:
332: int qpass = NONE; /* Quit after this pass */
333: int nload; /* No load phase */
334: char *outf; /* Output file */
335: char *doutf; /* Default output file stem */
336: char *dpath = DEFPATH;
337: char *dlibpath = DEFLIBPATH;
338: int xstat; /* Exit status */
339:
340: char *cmda[NCMDA]; /* Argument pointer buffer */
341: char cmdb[NCMDB]; /* Argument buffer */
342: char newo[NTMP]; /* New object to be removed */
343: char tmp[7][NTMP]; /* Intermediate filenames */
344: char istmp[7]; /* Truth about their temporariness */
345: int argf[NCMDA]; /* Argument flags */
346: char optb[NCMDB]; /* Option rewrite buffer */
347: char *optp = &optb[0]; /* Option rewrite position */
348:
349: #if TEMPBUF
350: unsigned char *inbuf; /* memory input buffer */
351: unsigned char *inbufp; /* input buffer pointer */
352: unsigned char *inbufmax; /* input buffer end */
353: unsigned char *outbuf; /* memory output buffer */
354: unsigned char *outbufp; /* output buffer pointer */
355: unsigned char *outbufmax; /* output buffer end */
356: unsigned int tempsize = 65536; /* memory buffer size */
357: #endif
358:
359: #if MONOLITHIC
360: /* Information passed to phases through globals in monolithic compiler */
361: jmp_buf death; /* for fatal error handling */
362: int dotseg; /* current segment */
363: char file[NFNAME]; /* input file name buffer */
364: char id[NCSYMB]; /* global identifier buffer */
365: FILE *ifp; /* input FILE */
366: int line; /* line number */
367: int mflag; /* debug flag */
368: char module[NMNAME]; /* module name buffer */
369: int oflag; /* debug flag */
370: FILE *ofp; /* output FILE */
371: int sflag; /* debug flag */
372: #endif
373:
374: /* Forward. */
375: FILE *ccopen();
376: char *makepass();
377: char *makelib();
378: int cleanup();
379:
380: /* External. */
381: char *getenv();
382: char *malloc();
383: char *tempnam();
384: char *path();
385:
386: main(argc, argv) int argc; char *argv[];
387: {
388: register char *p;
389: register struct option *op;
390: int i, narg, c;
391:
392: #if COHERENT
393: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
394: signal(SIGINT, cleanup);
395: #endif
396: #if _I386
397: /* Conditionalized only because _addargs() not in COH286 libc.a yet. */
398: _addargs("CC", &argc, &argv);
399: #endif
400: setbuf(stdout, NULL);
401: setbuf(stderr, NULL);
402: setvariant(VSUVAR);
403: setvariant(VSMEMB);
404: setvariant(VSLCON);
405: setvariant(VSPVAL);
406: setvariant(VPEEP);
407: setvariant(VCOMM);
408: setvariant(VPSTR);
409: setvariant(V80186);
410:
411: #if 0
412: printmem("initially");
413: #endif
414: if (p = getenv("PATH")) dpath = p;
415: if (p = getenv("LIBPATH")) dlibpath = p;
416: if (p = getenv("EDITOR")) strcpy(pass[ED].p_pln, p);
417:
418: for (i=1; i<argc; i+=narg) {
419: narg = 1;
420: p = argv[i];
421: if (*p++ == '-') {
422: static char tppopt[64] = "-";
423: static char tldopt[64] = "-";
424: char *tpp = &tppopt[1];
425: char *tlp = &tldopt[1];
426:
427: if (*p == '\0') {
428: badopt:
429: whatopt(argv[i]);
430: continue;
431: }
432: while (*p != '\0') {
433: for (op = &option[0]; ; op += 1)
434: if (op->o_name[0] == '\0')
435: goto badopt;
436: else if (opeq(op->o_name, p))
437: break;
438: if (VeryVflag && Vflag)
439: printf("Option: -%s\n", op->o_name);
440: argf[i] |= op->o_flag;
441: switch (op->o_kind) {
442: case 0:
443: chgvariant(op->o_bits);
444: p += strlen(op->o_name);
445: continue;
446: case 10:
447: setvariant(op->o_bits);
448: p += strlen(op->o_name);
449: continue;
450: case 2:
451: ccvariant ^= op->o_bits;
452: p += strlen(op->o_name);
453: /* Set strict */
454: if ((ccvariant&VS) != 0) {
455: for (op = &option[0];; op += 1)
456: if (op->o_name[1]=='S')
457: break;
458: while (op->o_name[1]=='S') {
459: setvariant(op->o_bits);
460: op += 1;
461: }
462: }
463: /* Set debug */
464: if ((ccvariant&VDB) != 0) {
465: for (op = &option[0];; op += 1)
466: if (op->o_name[1]=='D')
467: break;
468: while (op->o_name[1]=='D') {
469: setvariant(op->o_bits);
470: op += 1;
471: }
472: }
473: continue;
474: case 12:
475: ccvariant |= op->o_bits;
476: p += strlen(op->o_name);
477: continue;
478: case 3:
479: while (*tpp++ = *p)
480: p++;
481: continue;
482: case 5:
483: if (*p == 'o') {
484: outf = argv[i+narg];
485: }
486: if (*p == 'u')
487: ndoto += 1;
488: if (i+narg >= argc)
489: missingname();
490: argf[i+narg++] = LDOPT;
491: /* Fall through */
492: case 4:
493: if (*p == 'r')
494: ++partial;
495: strcpy(tlp, op->o_name);
496: tlp += strlen(op->o_name);
497: p += strlen(op->o_name);
498: continue;
499: case 6:
500: if ((c = p[1]) == '\0'
501: || (c = getpsn(c)) < CPP)
502: goto badopt;
503: qpass = c;
504: p += 2;
505: continue;
506: case 7:
507: c = p[0];
508: getpass(c, p+1);
509: p = dnul;
510: continue;
511: case 8:
512: p = dnul;
513: continue;
514: #if TEMPBUF
515: case 9:
516: tempsize = atoi(++p);
517: tempsize = (tempsize + 3) & ~3;
518: p = dnul;
519: continue;
520: #endif
521: default:
522: cquit("options");
523: }
524: }
525: if (((unsigned)argf[i]-1)&((unsigned)argf[i])) {
526: strcpy(optp, argv[i]);
527: argv[i] = optp;
528: optp += strlen(optp)+1;
529: strcpy(optp, tppopt);
530: optp += strlen(optp)+1;
531: strcpy(optp, tldopt);
532: optp += strlen(optp)+1;
533: }
534: } else {
535: while (*p) p+=1;
536: c = *--p;
537: if (*--p != '.') c = 0;
538: if (c >= 'A' && c <= 'Z')
539: c |= 'a'-'A';
540: switch (c) {
541: case 'h':
542: case 'c':
543: if (doutf == NULL) doutf = argv[i];
544: ndotc += 1;
545: argf[i] = CCARG;
546: if (VeryVflag && Vflag)
547: printf("cc file: %s\n", argv[i]);
548: break;
549: case 's':
550: if (doutf == NULL) doutf = argv[i];
551: ndots += 1;
552: argf[i] = ASARG;
553: if (VeryVflag && Vflag)
554: printf("as file: %s\n", argv[i]);
555: break;
556: case 'm':
557: if (doutf == NULL) doutf = argv[i];
558: ndotm += 1;
559: argf[i] = MARG;
560: if (VeryVflag && Vflag)
561: printf("m file: %s\n", argv[i]);
562: break;
563: case 'o':
564: if (doutf == NULL) doutf = argv[i];
565: ndoto += 1;
566: argf[i] = LDARG;
567: if (VeryVflag && Vflag)
568: printf("ld file: %s\n", argv[i]);
569: break;
570: case 'a':
571: default:
572: ndota += 1;
573: argf[i] = LDLIB;
574: if (VeryVflag && Vflag)
575: printf("library: %s\n", argv[i]);
576: break;
577: }
578: }
579: }
580: #if GEMDOS
581: if (Vflag) {
582: fprintf(stderr, "Mark Williams C for the Atari ST, %s\n", VERS);
583: fprintf(stderr, "Copyright 1984-1987, Mark Williams Co., Chicago\n");
584: }
585: #endif
586: resolve();
587: compile(argc, argv);
588: if (nload==0 && runld(argc, argv)==0) {
589: if (Kflag==0 && nldob==1 && newo[0]!=0)
590: rm(newo);
591: }
592: #if TEMPBUF
593: if (inbuf != NULL)
594: free(inbuf);
595: if (outbuf != NULL)
596: free(outbuf);
597: #if 0
598: printmem("before exit");
599: #endif
600: #endif
601: exit(xstat);
602: }
603:
604: /*
605: * Resolve remaining ambiguities.
606: * Initialize variant arguments and files.
607: */
608: resolve()
609: {
610: register int i;
611:
612: #if TEMPBUF
613: register char *p;
614:
615: /*
616: * The following malloc is a temporary hack for COH386 efficiency.
617: * The rationale is:
618: * (1) reduce the number of required sbrk() calls, and
619: * (2) reduce the risk of running out of memory,
620: * because COH386 without paging requires old+new bytes free
621: * to grow from old to new.
622: * This will doubtless be changed in the future.
623: */
624: #define NARENA 131072
625: if ((p = malloc(tempsize + tempsize + NARENA)) != NULL)
626: free(p);
627: if (tempsize != 0 && Eflag == 0 && Kflag == 0) {
628: inbuf = malloc(tempsize);
629: outbuf = malloc(tempsize);
630: outbufp = outbuf;
631: outbufmax = outbuf + tempsize;
632: if (inbuf == NULL || outbuf == NULL) {
633: fprintf(stderr, "cc: in-memory tempfile buffer allocation failed\n");
634: if (inbuf != NULL)
635: free(inbuf);
636: inbuf = outbuf = NULL;
637: }
638: }
639: #if 0
640: printmem("after buffer allocation");
641: #endif
642: #endif
643: for (i = CPP; i < ALL; i += 1) {
644: if (pass[i].p_flag & P_BACK)
645: ;
646: else if (pass[i].p_flag & P_LIB)
647: pass[i].p_dir = dlibpath;
648: else if (pass[i].p_flag & P_BIN)
649: pass[i].p_dir = dpath;
650: strcpy(cmdb, pass[i].p_mch);
651: strcat(cmdb, pass[i].p_pln);
652: #if GEMDOS
653: if (i <= ED && strchr(pass[i].p_pln, '.') == NULL)
654: strcat(cmdb, i==ED ? ".tos" : ".prg");
655: #endif
656: if (strlen(cmdb) > PTMP-1)
657: cquit("pass name \"%s\" is too long", cmdb);
658: strcpy(pass[i].p_pln, cmdb);
659: }
660: #if 1
661: if (isvariant(VOMF)) {
662: clrvariant(VCOMM);
663: if (isvariant(VLARGE) && isvariant(VSMALL))
664: cquit("invalid model specification");
665: if (notvariant(VLARGE) && notvariant(VSMALL))
666: setvariant(VSMALL);
667: } else {
668: clrvariant(VLARGE);
669: setvariant(VSMALL);
670: }
671: #endif
672: if (GEMAPPflag && GEMACCflag)
673: cquit("specify VGEMAPP or VGEMACC, not both");
674: if (GEMAPPflag) getpass('N', "rcrtsg.o");
675: if (GEMACCflag) getpass('N', "rcrtsd.o");
676: if (pflag) getpass('N', "rmcrts0.o");
677: if (Eflag) setvariant(VCPP);
678: if (qpass == NONE) {
679: if (isvariant(VCPP))
680: qpass = CPP;
681: else if (Sflag)
682: qpass = CC3;
683: else if (cflag)
684: qpass = AS;
685: else
686: qpass = LD;
687: } else if (qpass == CPP)
688: setvariant(VCPP);
689: if (VeryVflag && Vflag)
690: printf("quit pass is %s\n", pass[qpass].p_pln);
691: makvariant(vstr);
692: if (ndotm != 0 && notvariant(VCPP) && notvariant(VCPPE)) {
693: setvariant(VCPP);
694: setvariant(VCPPE);
695: makvariant(vstr2);
696: clrvariant(VCPP);
697: clrvariant(VCPPE);
698: }
699: nfile = ndotc + ndots + ndotm;
700: nname = nfile + ndoto + ndota;
701: if (nname == 0) {
702: fprintf(stderr,
703: "Usage: cc [ -o output ] [ options ] file [ ... ]\n");
704: exit(1);
705: }
706: if (qpass < LD)
707: ++nload;
708: if (Aflag)
709: maketempfile(6);
710: if ( ! Eflag) {
711: chkofile();
712: if (Kflag) {
713: pass[CPP].p_ofn = pass[CC0].p_ifn = tmp[0];
714: pass[CC0].p_ofn = pass[CC1].p_ifn = tmp[1];
715: pass[CC1].p_ofn = pass[CC2].p_ifn = tmp[2];
716: if ( ! Sflag) {
717: pass[CC2].p_sfn = tmp[3];
718: pass[CC2].p_ofn = tmp[5];
719: } else {
720: pass[CC3].p_ifn = pass[CC2].p_ofn = tmp[3];
721: pass[CC3].p_ofn = tmp[5];
722: }
723: } else {
724: pass[CPP].p_ofn = pass[CC0].p_ifn = tmp[0];
725: pass[CC0].p_ofn = pass[CC1].p_ifn = tmp[1];
726: pass[CC1].p_ofn = pass[CC2].p_ifn = tmp[0];
727: if ( ! Sflag) {
728: pass[CC2].p_sfn = tmp[1];
729: pass[CC2].p_ofn = tmp[5];
730: } else {
731: pass[CC3].p_ifn = pass[CC2].p_ofn = tmp[1];
732: pass[CC3].p_ofn = tmp[5];
733: }
734: #if TEMPBUF
735: if (inbuf != NULL && outbuf != NULL)
736: tmp[0][0] = tmp[1][0] = '\0';
737: else
738: #endif
739: {
740: maketempfile(0);
741: maketempfile(1);
742: }
743: }
744: pass[AS].p_ofn = tmp[5];
745: }
746: }
747:
748: maketempfile(i) register int i;
749: {
750: register char *p;
751:
752: strcpy(tmp[i], p = tempnam(pass[TMP].p_dir, pass[TMP].p_pln));
753: free(p);
754: ++istmp[i];
755: }
756:
757: /*
758: ** Compilation.
759: */
760: compile(argc, argv) int argc; char *argv[];
761: {
762: register char *p1;
763: register c, i, err;
764:
765: err = 0;
766: for (i=1; i<argc; ++i) {
767: if ((c = (argf[i] & (CCARG | ASARG | MARG))) == 0)
768: continue;
769: p1 = argv[i];
770: if (err) {
771: err = 0;
772: if (runme(p1)) {
773: ++nload;
774: } else {
775: --i;
776: xstat = 0;
777: }
778: continue;
779: }
780: if (nfile > 1 && Qflag == 0)
781: printf("%s:\n", p1);
782: setfiles(c, p1);
783: if (c == CCARG) {
784: if (runpp(argc, argv, vstr)) {
785: if (Aflag) {
786: ++err; --i;
787: } else
788: ++nload;
789: continue;
790: }
791: if (qpass <= CC0)
792: continue;
793: if (runcc(CC1)) {
794: ++nload;
795: continue;
796: }
797: if (qpass <= CC1)
798: continue;
799: if (runcc(CC2)) {
800: ++nload;
801: continue;
802: }
803: if (qpass <= CC2)
804: continue;
805: if (Sflag) {
806: if (runcc(CC3)) {
807: ++nload;
808: continue;
809: }
810: if (qpass <= CC3)
811: continue;
812: }
813: } else if (c == ASARG && qpass>=AS) {
814: if (runas()) {
815: if (Aflag) {
816: ++err; --i;
817: } else
818: ++nload;
819: continue;
820: }
821: if (qpass <= AS)
822: continue;
823: } else if (c == MARG) {
824: if (runpp(argc, argv, vstr2)) {
825: if (Aflag) {
826: ++err; --i;
827: } else
828: ++nload;
829: continue;
830: }
831: if (qpass < AS)
832: continue;
833: if (runas()) {
834: if (Aflag) {
835: ++err; --i;
836: } else
837: ++nload;
838: continue;
839: }
840: if (qpass == AS)
841: continue;
842: }
843: makeft(p1, p1, "o");
844: }
845: cleanup(0);
846: }
847:
848: runpp(argc, argv, var) int argc; register char *argv[]; char var[];
849: {
850: register char **cp;
851: register int i;
852: char *p1;
853: #if MONOLITHIC
854: int status;
855: extern int nerr; /* in common/diag.c */
856: #endif
857:
858: cp = cmda;
859: #if MONOLITHIC
860: nerr = 0;
861: *cp++ = "cc0";
862: #else
863: p1 = cmdb;
864: p1 = makepass(CC0, *cp++ = p1, AEXEC);
865: #endif
866: *cp++ = var;
867: *cp++ = pass[CPP].p_ifn;
868: if (qpass < CC0)
869: p1 = *cp++ = Kflag ? pass[CPP].p_ofn : "-";
870: else
871: p1 = *cp++ = pass[CC0].p_ofn;
872: for (i=1; i<argc; ++i) {
873: if ((argf[i]&PPOPT) != 0) {
874: *cp++ = argv[i];
875: if ((argf[i]&~PPOPT) != 0)
876: cp[-1] += strlen(cp[-1])+1;
877: }
878: }
879: *cp = 0;
880: #if MONOLITHIC
881: if ((ifp = fopen(pass[CPP].p_ifn, "r")) == NULL) {
882: fprintf(stderr, "cc: cannot open %s\n", pass[CPP].p_ifn);
883: return 1;
884: }
885: if (Eflag)
886: ofp = (strcmp(p1, "-") == 0) ? stdout : ccopen(p1, "w");
887: else
888: ofp = (*p1 == '\0') ? NULL : ccopen(p1, SWMODE);
889: argc = cp - cmda;
890: if (Vflag) {
891: for (i = 0; i < argc; i++)
892: printf("%s ", cmda[i]);
893: if (ofp == NULL)
894: printf("0x%x", outbuf);
895: printf("\n");
896: }
897: if (Aflag)
898: err_open();
899: status = cc0(argc, cmda);
900: if (Aflag)
901: err_close(status);
902: closeinout();
903: #if 0
904: printmem("after cc0");
905: #endif
906: if (status)
907: xstat = 1;
908: return status;
909: #else
910: return run(Aflag, 0);
911: #endif
912: }
913:
914: #if MONOLITHIC
915:
916: #if 0
917: /* This is temporary stuff, here for malloc arena debugging. */
918: /* Knows format of malloc arena. */
919: #include <sys/malloc.h>
920: printmem(s) char *s;
921: {
922: register int i, j;
923: unsigned int u;
924: register MBLOCK *p;
925: register unsigned char *cp;
926: int nfree, nused, bfree, bused, freef;
927:
928: printf("%s:\n", s);
929: printf("__a_count=%d\n", __a_count);
930: printf("__a_scanp=%x\n", __a_scanp);
931: printf("__a_first=%x\n", __a_first);
932: nfree = nused = bfree = bused = 0;
933: for (p = __a_first, i = 0; i < __a_count; i++) {
934: u = p->blksize;
935: freef = isfree(u);
936: u = realsize(u);
937: printf("%x: size %d ", p, u-4);
938: if (freef) {
939: printf("free\n");
940: ++nfree;
941: bfree += u - sizeof(unsigned);
942: } else {
943: ++nused;
944: if (u != 0) {
945: printf("%x: size %d ", p, u-4);
946: printf("used\n");
947: bused += u - sizeof(unsigned);
948: }
949: if (u != tempsize + 4) {
950: for (j = 4, cp = (char *)p + 4; j < u; j++)
951: printf("%02x ", *cp++);
952: printf("\n");
953: }
954: }
955: p = bumpp(p, u);
956: }
957: printf("nfree=%d nused=%d\n", nfree, nused-1);
958: printf("bfree=%d bused=%d overhead=%d total=%d\n",
959: bfree, bused, 4*(nfree+nused+1), bfree+bused+4*(nfree+nused+1));
960: }
961: #endif
962:
963: /*
964: * Close input and output files as appropriate.
965: */
966: closeinout()
967: {
968: if (ifp != NULL) {
969: fclose(ifp);
970: ifp = NULL;
971: }
972: if (ofp != NULL) {
973: fclose(ofp);
974: ofp = NULL;
975: }
976: }
977:
978: /*
979: * Set input and output file pointers for monolithic compiler.
980: * Print verbose phase message if Vflag.
981: */
982: setinout(pn) register int pn;
983: {
984: register char *p, *in, *out, *ln;
985:
986: if (pn == CC2B) {
987: ln = "cc2b";
988: in = pass[CC2].p_sfn;
989: out = pass[CC2].p_ofn;
990: } else {
991: in = pass[pn].p_ifn;
992: if (pn == CC2) {
993: ln = "cc2a";
994: out = (Sflag) ? pass[pn].p_ofn : pass[pn].p_sfn;
995: } else {
996: ln = pass[pn].p_pln;
997: out = pass[pn].p_ofn;
998: }
999: }
1000: if (Vflag)
1001: printf("%s %s ", ln, vstr);
1002: if (*in == '\0') {
1003: ifp = NULL;
1004: p = inbuf;
1005: inbuf = inbufp = outbuf;
1006: inbufmax = outbufp;
1007: outbuf = outbufp = p;
1008: outbufmax = outbuf + tempsize;
1009: if (Vflag)
1010: printf("0x%x ", inbuf);
1011: } else {
1012: ifp = ccopen(in, SRMODE);
1013: if (Vflag)
1014: printf("%s ", in);
1015: }
1016: if (*out == '\0') {
1017: ofp = NULL;
1018: if (Vflag)
1019: printf("0x%x\n", outbuf);
1020: } else {
1021: ofp = ccopen(out, SWMODE);
1022: if (Vflag)
1023: printf("%s\n", out);
1024: }
1025: }
1026: #endif
1027:
1028: runcc(pn) register int pn;
1029: {
1030: #if MONOLITHIC
1031: register int status;
1032:
1033: setinout(pn);
1034: switch(pn) {
1035: case CC1:
1036: status = cc1();
1037: break;
1038: case CC2:
1039: if (status = cc2a())
1040: break;
1041: if (!Sflag) {
1042: closeinout();
1043: setinout(CC2B);
1044: status = cc2b();
1045: }
1046: break;
1047: case CC3:
1048: status = cc3();
1049: break;
1050: default:
1051: cquit("bad pass number %d", pn);
1052: break;
1053: }
1054: closeinout();
1055: #if 0
1056: printmem((pn == CC1) ? "after cc1": (pn == CC2) ? "after cc2" : "after cc3");
1057: #endif
1058: return status;
1059: #else
1060: register char **cp;
1061:
1062: cp = cmda;
1063: makepass(pn, *cp++ = cmdb, AEXEC);
1064: *cp++ = vstr;
1065: *cp++ = pass[pn].p_ifn;
1066: *cp++ = pass[pn].p_ofn;
1067: if (pn == CC2)
1068: *cp++ = pass[CC2].p_sfn;
1069: *cp = 0;
1070: return run(0, 0);
1071: #endif
1072: }
1073:
1074: runas()
1075: {
1076: register char **cp;
1077:
1078: cp = cmda;
1079: makepass(AS, *cp++ = cmdb, AEXEC);
1080: #if _I386
1081: *cp++ = "-fgx";
1082: if (Qflag)
1083: *cp++ = "-w";
1084: #else
1085: *cp++ = "-gx";
1086: #endif
1087: *cp++ = "-o";
1088: *cp++ = pass[AS].p_ofn;
1089: *cp++ = pass[AS].p_ifn;
1090: *cp = 0;
1091: return run(Aflag, 0);
1092: }
1093:
1094: runme(fn)
1095: char *fn;
1096: {
1097: register char **cp;
1098:
1099: cp = cmda;
1100: makepass(ED, *cp++ = cmdb, AEXEC);
1101: *cp++ = fn;
1102: *cp++ = "-e";
1103: *cp++ = tmp[6];
1104: *cp = 0;
1105: return run(0, 0);
1106: }
1107: runld(argc, argv)
1108: char *argv[];
1109: {
1110: char *p1;
1111: register char *p2;
1112: register char **cp;
1113: char **cp1;
1114: register char **cp2;
1115: int i;
1116: static char buff[32];
1117:
1118: cp = cmda;
1119: p1 = makepass(LD, *cp++ = cmdb, AEXEC);
1120: *cp++ = "-X";
1121: #if _I386
1122: if (Qflag)
1123: *cp++ = "-Q";
1124: #endif
1125: if (outf == NULL && !aflag) {
1126: *cp++ = "-o";
1127: if (partial || doutf == NULL) {
1128: #if COHERENT
1129: *cp++ = "l.out";
1130: #endif
1131: #if GEMDOS
1132: *cp++ = "l.prg";
1133: #endif
1134: } else {
1135: basename(doutf, buff);
1136: #if GEMDOS
1137: strcat(buff, ".prg");
1138: #endif
1139: *cp++ = buff;
1140: }
1141: }
1142: for (i=1; i<argc; ++i) {
1143: if ((argf[i]&LDOPT)!=0) {
1144: *cp++ = argv[i];
1145: if ((argf[i]&~LDOPT)!=0) {
1146: cp[-1] += strlen(cp[-1])+1;
1147: cp[-1] += strlen(cp[-1])+1;
1148: }
1149: }
1150: }
1151: cp1 = cp;
1152: p1 = makepass(CRT, *cp++ = p1, AREAD);
1153: if (fflag) {
1154: *cp++ = "-u";
1155: *cp++ = DTEFG;
1156: }
1157: for (i=1; i<argc; ++i) {
1158: p2 = argv[i];
1159: if ((argf[i]&CCLIB)!=0) {
1160: while (*p2++ != 'l');
1161: p1 = makelib(LIB, *cp++ = p1, p2);
1162: } else if ((argf[i]&(CCARG|ASARG|MARG|LDARG))!=0) {
1163: for (cp2=cp1; cp2<cp; ++cp2)
1164: if (strcmp(*cp2, p2) == 0)
1165: break;
1166: if (cp2 == cp) {
1167: *cp++ = p2;
1168: ++nldob;
1169: }
1170: } else if ((argf[i]&LDLIB)!=0) {
1171: *cp++ = p2;
1172: }
1173: }
1174: if ( ! partial && (GEMAPPflag || GEMACCflag)) {
1175: p1 = makelib(LIB, *cp++ = p1, "aes");
1176: p1 = makelib(LIB, *cp++ = p1, "vdi");
1177: }
1178: p1 = makelib(LIB, *cp++ = p1, "c");
1179: #if _I386
1180: if (Kflag == 0 && nldob == 1 && newo[0] != 0) {
1181: *cp++ = "-Z";
1182: *cp++ = newo;
1183: }
1184: #endif
1185: *cp = 0;
1186: return run(0, 1);
1187: }
1188:
1189: basename(in, out)
1190: char *in, *out;
1191: {
1192: register char *s;
1193: register int n;
1194:
1195: if ((s = strrchr(in, PATHSEP)) != NULL)
1196: in = ++s; /* skip past last PATHSEP */
1197: if ((s = strrchr(in, '.')) != NULL)
1198: n = s - in; /* copy to last '.' */
1199: else
1200: n = strlen(in); /* copy all */
1201: strncpy(out, in, n); /* copy as appropriate */
1202: out[n] = '\0'; /* and NUL-terminate */
1203: }
1204:
1205: run(catch_errors, nofork) int catch_errors; int nofork;
1206: {
1207: int s;
1208: extern char **environ;
1209:
1210: if (Vflag) {
1211: char *cp, **cpp;
1212: cpp = cmda;
1213: while ((cp = *cpp) != NULL) {
1214: if (cpp != cmda)
1215: putchar(' ');
1216: printf("%s", cp);
1217: ++cpp;
1218: }
1219: putchar('\n');
1220: fflush(stdout);
1221: }
1222: if (catch_errors)
1223: err_open();
1224: #if COHERENT
1225: #if _I386
1226: if (nofork) {
1227: execve(cmda[0], cmda, environ);
1228: cquit("cannot execute %s", cmda[0]);
1229: }
1230: #endif
1231: {
1232: int nsleep;
1233: int status;
1234: int pid;
1235: nsleep = NSLEEP;
1236: while ((pid=fork())<0 && nsleep--)
1237: sleep(DELAY);
1238: if (pid < 0)
1239: cquit("can't fork");
1240: if (pid == 0) {
1241: execve(cmda[0], cmda, environ);
1242: exit(MAGIC);
1243: }
1244: while (wait(&status) != pid)
1245: ;
1246: if ((s = status&0177)!=0 && s!=SIGINT) {
1247: extern char *signame[];
1248:
1249: fprintf(stderr, "cc: %s ", cmda[0]);
1250: if (s==SIGSYS && (status&0200)==0)
1251: fprintf(stderr, "exec failed");
1252: else
1253: fprintf(stderr, signame[s]);
1254: if ((status&0200) != 0)
1255: fprintf(stderr, " -- core dumped");
1256: fprintf(stderr, "\n");
1257: } else if ((s = (status>>8)&0377) == MAGIC)
1258: cquit("cannot execute %s", cmda[0]);
1259: }
1260: #else
1261: if (s = execve(cmda[0], cmda, environ))
1262: if (s < 0)
1263: perror(cmda[0]);
1264: #endif
1265: if (catch_errors)
1266: err_close(s);
1267: if (s != 0)
1268: xstat = 1;
1269: return s;
1270: }
1271:
1272: /*
1273: * Routines to catch and release stdout for -A.
1274: */
1275: int new_fd;
1276: int saved_fd;
1277:
1278: err_open()
1279: {
1280: fflush(stdout);
1281: saved_fd = dup(1);
1282: if ((new_fd = creat(tmp[6], 0644)) < 0)
1283: cquit("%s: %s", tmp[6], sys_errlist[errno]);
1284: if (dup2(new_fd, 1) < 0)
1285: cquit("dup2 failed");
1286: }
1287:
1288: err_close(status) int status;
1289: {
1290: register int c;
1291: register FILE *fp;
1292:
1293: fflush(stdout);
1294: if (dup2(saved_fd, 1) < 0)
1295: cquit("dup2 failed");
1296: if (close(new_fd) < 0)
1297: /* cquit("error on close") */ ;
1298: if (status == 0 && (fp = fopen(tmp[6], "r")) != NULL) {
1299: /* Copy warnings, otherwise they go down the rathole. */
1300: while ((c = getc(fp)) != EOF)
1301: putchar(c);
1302: fclose(fp);
1303: }
1304: }
1305:
1306: /*
1307: ** Option processing.
1308: */
1309:
1310: /*
1311: * Compare option name to argument.
1312: */
1313: opeq(op, ap)
1314: register char *op, *ap;
1315: {
1316: while (*op!=0)
1317: if (*op++ != *ap++)
1318: return 0;
1319: return 1;
1320: }
1321:
1322:
1323: /*
1324: * Get short pass name.
1325: * translate single character code into pass index number.
1326: */
1327: getpsn(c)
1328: register int c;
1329: {
1330: register int pn;
1331:
1332: for (pn = CPP; pn < ALL; pn += 1)
1333: if (pass[pn].p_psn == c)
1334: return pn;
1335: return NONE;
1336: }
1337:
1338: /*
1339: * Process -t*, -B*, -M* options.
1340: * -t* sets take flag for specified passes.
1341: * -B* copies prefix string for flagged passes
1342: * or for all machine dependent passes if none flagged.
1343: * -M* copies machine string for machine dependent passes.
1344: * -N* renames a pass, such as crts0.o.
1345: */
1346: getpass(c, cp)
1347: register int c;
1348: register char *cp;
1349: {
1350: if (c == 't') { /* Take passes from backup */
1351: if (*cp != 0)
1352: while ((c = *cp++) != 0)
1353: if ((c = getpsn(c)) >= CPP) {
1354: pass[c].p_flag |= P_TAKE;
1355: pass[c].p_dir = dnul;
1356: if (Vflag)
1357: passrpt(c);
1358: } else {
1359: badpsn(cp[-1]);
1360: }
1361: else
1362: getpass('t', "01234");
1363: } else if (c == 'B') { /* Get backup string */
1364: for (c = CPP; c < ALL; c += 1) {
1365: if ((pass[c].p_flag&P_TAKE) != 0) {
1366: pass[c].p_flag ^= P_TAKE;
1367: pass[c].p_flag |= P_BACK;
1368: pass[c].p_dir = cp;
1369: if (Vflag)
1370: passrpt(c);
1371: }
1372: }
1373: } else if (c == 'M') { /* Machine prefix string */
1374: if (strlen(cp) > PTMP-1)
1375: toolong(cp);
1376: strcpy(dmch, cp);
1377: if (Vflag)
1378: printf("Prefix: %s\n", dmch);
1379: } else if (c == 'N') { /* New pass name */
1380: if ((c = getpsn(*cp++)) >= CPP) {
1381: if (strlen(cp) > PTMP-1)
1382: toolong(cp);
1383: if (Vflag)
1384: printf("Rename: %s to %s\n", pass[c].p_pln, cp);
1385: strcpy(pass[c].p_pln, cp);
1386: } else
1387: badpsn(cp[-1]);
1388: }
1389: }
1390:
1391: passrpt(c)
1392: register int c;
1393: {
1394: printf("Use: {%s}%s%s\n", pass[c].p_dir, pass[c].p_mch, pass[c].p_pln);
1395: }
1396:
1397: missingname()
1398: {
1399: fprintf(stderr, "cc: missing name in -o, -e or -u\n");
1400: exit(1);
1401: }
1402:
1403: badoutput()
1404: {
1405: fprintf(stderr, "cc: improbable name in -o: %s\n", outf);
1406: exit(1);
1407: }
1408:
1409: toomany()
1410: {
1411: fprintf(stderr, "cc: too many files for -o option\n");
1412: exit(1);
1413: }
1414:
1415: badpsn(c)
1416: {
1417: fprintf(stderr, "cc: unknown short path name: %c\n", c);
1418: exit(1);
1419: }
1420:
1421: toolong(cp)
1422: char *cp;
1423: {
1424: fprintf(stderr, "cc: name, prefix, or directory too long: %s\n", cp);
1425: exit(1);
1426: }
1427:
1428: /*
1429: * Check specified output file name,
1430: * or construct name from first file
1431: * name seen.
1432: */
1433: chkofile()
1434: {
1435: register char *fn;
1436: register char c;
1437:
1438: if ((fn = outf) == NULL)
1439: return;
1440: if (fn[0] == '-')
1441: badoutput();
1442: if (nname > 1 && qpass < LD)
1443: toomany();
1444: while (*fn != 0)
1445: ++fn;
1446: while (*fn != '.' && fn > outf)
1447: --fn;
1448: if (*fn++ == '.' && (c = *fn++) && *fn == '\0') {
1449: if (c == 'c'
1450: || c == 'h'
1451: || c == 'm'
1452: || (c != 'o' && cflag)
1453: || (c == 'o' && !cflag)
1454: || (c != 's' && Sflag)
1455: || (c == 's' && !Sflag))
1456: badoutput();
1457: } else {
1458: if (Sflag || cflag)
1459: badoutput();
1460: }
1461: }
1462:
1463: whatopt(s)
1464: char *s;
1465: {
1466: fprintf(stderr, "cc: unrecognized option: %s\n", s);
1467: exit(1);
1468: }
1469:
1470: cquit(s)
1471: char *s;
1472: {
1473: fprintf(stderr, "cc: fatal error: %r\n", &s);
1474: cleanup(0);
1475: exit(1);
1476: }
1477:
1478: /*
1479: ** Intermediate file processing.
1480: */
1481: /*
1482: * Given cp -> `name.[chms]' rewrite ultimate destination and intermediates
1483: * if necessary.
1484: */
1485: setfiles(c, cp)
1486: int c;
1487: register char *cp;
1488: {
1489: register char *ip;
1490:
1491: ip = cp;
1492: if (qpass < LD && outf != NULL)
1493: cp = outf;
1494: if (c == CCARG) {
1495: pass[CPP].p_ifn = ip;
1496: if (Eflag)
1497: return;
1498: if (Kflag) {
1499: makeft(pass[CPP].p_ofn, cp, "i");
1500: makeft(pass[CC0].p_ofn, cp, "0");
1501: makeft(pass[CC1].p_ofn, cp, "1");
1502: if ( ! Sflag)
1503: makeft(pass[CC2].p_sfn, cp, "2");
1504: else
1505: makeft(pass[CC2].p_ofn, cp, "2");
1506: }
1507: } else if (c == MARG) {
1508: pass[CPP].p_ifn = ip;
1509: if (Kflag)
1510: makeft(pass[CC0].p_ofn, cp, "s");
1511: pass[AS].p_ifn = pass[CC0].p_ofn;
1512: } else if (c == ASARG)
1513: pass[AS].p_ifn = ip;
1514: makeft(tmp[5], cp, Sflag ? "s" : "o");
1515: if (!Sflag && newo[0] == 0 && access(tmp[5], 0) < 0)
1516: strcpy(newo, tmp[5]);
1517: }
1518:
1519: #if MONOLITHIC
1520: /*
1521: * Open a file, die on failure.
1522: */
1523: FILE *
1524: ccopen(name, mode) char *name; char *mode;
1525: {
1526: register FILE *fp;
1527:
1528: if ((fp = fopen(name, mode)) != NULL)
1529: return fp;
1530: cquit("cannot open file \"%s\"", name);
1531: }
1532: #endif
1533:
1534: /*
1535: * Unlink a file.
1536: * If `-V' echo the rm.
1537: */
1538: rm(s)
1539: register char *s;
1540: {
1541: if (Vflag)
1542: printf("rm %s\n", s);
1543: unlink(s);
1544: }
1545:
1546: /*
1547: * Cleanup after yourself if
1548: * the user hits interrupt during a compile (sig == SIGINT),
1549: * or when all compiles have completed (sig == 0).
1550: */
1551: cleanup(sig)
1552: {
1553: register int i;
1554:
1555: #if COHERENT
1556: if (sig == SIGINT)
1557: signal(SIGINT, SIG_IGN);
1558: #endif
1559: for (i = 0; i < 7; i += 1)
1560: if (istmp[i])
1561: rm(tmp[i]);
1562: #if COHERENT
1563: if (sig == SIGINT && nldob==1 && newo[0]!=0)
1564: rm(newo);
1565: if (sig == SIGINT)
1566: exit(1);
1567: #endif
1568: }
1569:
1570: /*
1571: ** Name construction.
1572: */
1573: char *
1574: ccpath(cp, p, n, mode) register char *cp; char *p, *n; int mode;
1575: {
1576: register char *pn;
1577: if (VeryVflag && Vflag)
1578: printf("search %s for %s\n", p, n);
1579: while ((pn = path(p, n, mode)) == NULL) {
1580: if (Zflag) { /* Disk swap dialog flag */
1581: fprintf(stderr, "Insert %s's disk in a free drive and press <Return>\n", n);
1582: gets(cp);
1583: continue;
1584: }
1585: pn = n;
1586: break;
1587: }
1588: while (*cp++ = *pn++) ;
1589: return cp;
1590: }
1591:
1592: char *
1593: makepass(pn, cp, mode)
1594: int pn;
1595: register char *cp;
1596: int mode;
1597: {
1598: return ccpath(cp, pass[pn].p_dir, pass[pn].p_pln, mode);
1599: }
1600:
1601: char *
1602: makelib(pn, cp, lp)
1603: int pn;
1604: char *cp;
1605: char *lp;
1606: {
1607: strcpy(cp, pass[pn].p_pln);
1608: strcat(cp, lp);
1609: strcat(cp, ".a");
1610: return ccpath(cp, pass[pn].p_dir, cp, AREAD);
1611: }
1612:
1613: makeft(op, ip, ft)
1614: char *op, *ip, *ft;
1615: {
1616: register char *ep, *tp;
1617: register c;
1618: char *dp;
1619:
1620: ep = ip;
1621: tp = op;
1622: dp = NULL;
1623: while ((c = *ep++) != '\0') {
1624: if (c == PATHSEP && ip != outf) {
1625: tp = op;
1626: dp = NULL;
1627: } else {
1628: if (c == '.')
1629: dp = tp;
1630: *tp++ = c;
1631: }
1632: }
1633: if (ip == outf)
1634: return;
1635: if (dp != NULL)
1636: tp = dp;
1637: *tp++ = '.';
1638: ep = ft;
1639: while (*tp++ = *ep++)
1640: ;
1641: }
1642:
1643: /* end of coh/cc.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.