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