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