xref: /csrg-svn/old/pcc/cc/cc.c (revision 896)
1*896Sbill static	char sccsid[] = "@(#)cc.c 3.5 09/20/80";
2611Sbill /*
3611Sbill  * cc - front end for C compiler
4611Sbill  */
5611Sbill #include <sys/types.h>
6611Sbill #include <stdio.h>
7611Sbill #include <ctype.h>
8611Sbill #include <signal.h>
9611Sbill #include <dir.h>
10611Sbill 
11*896Sbill char	*cpp = "/lib/cpp";
12*896Sbill char	*ccom = "/lib/ccom";
13*896Sbill char	*c2 = "/lib/c2";
14*896Sbill char	*as = "/bin/as";
15*896Sbill char	*ld = "/bin/ld";
16*896Sbill char	*crt0 = "/lib/crt0.o";
17611Sbill 
18611Sbill char	tmp0[30];		/* big enough for /tmp/ctm%05.5d */
19611Sbill char	*tmp1, *tmp2, *tmp3, *tmp4, *tmp5;
20611Sbill char	*outfile;
21611Sbill char	*savestr(), *strspl(), *setsuf();
22611Sbill int	idexit();
23611Sbill char	**av, **clist, **llist, **plist;
24652Sbill int	cflag, eflag, gflag, oflag, pflag, sflag, wflag, Rflag, exflag, proflag;
25611Sbill char	*dflag;
26611Sbill int	exfail;
27611Sbill char	*chpass;
28611Sbill char	*npassname;
29611Sbill 
30611Sbill int	nc, nl, np, nxo, na;
31611Sbill 
32611Sbill #define	cunlink(s)	if (s) unlink(s)
33611Sbill 
34611Sbill main(argc, argv)
35611Sbill 	char **argv;
36611Sbill {
37611Sbill 	char *t;
38611Sbill 	char *assource;
39611Sbill 	int i, j, c;
40611Sbill 
41611Sbill 	/* ld currently adds upto 5 args; 10 is room to spare */
42611Sbill 	av = (char **)calloc(argc+10, sizeof (char **));
43611Sbill 	clist = (char **)calloc(argc, sizeof (char **));
44611Sbill 	llist = (char **)calloc(argc, sizeof (char **));
45611Sbill 	plist = (char **)calloc(argc, sizeof (char **));
46611Sbill 	for (i = 1; i < argc; i++) {
47611Sbill 		if (*argv[i] == '-') switch (argv[i][1]) {
48611Sbill 
49611Sbill 		case 'S':
50611Sbill 			sflag++;
51611Sbill 			cflag++;
52611Sbill 			continue;
53611Sbill 		case 'o':
54611Sbill 			if (++i < argc) {
55611Sbill 				outfile = argv[i];
56611Sbill 				switch (getsuf(outfile)) {
57611Sbill 
58611Sbill 				case 'c':
59611Sbill 				case 'o':
60611Sbill 					error("-o would overwrite %s",
61611Sbill 					    outfile);
62611Sbill 					exit(8);
63611Sbill 				}
64611Sbill 			}
65611Sbill 			continue;
66652Sbill 		case 'R':
67652Sbill 			Rflag++;
68652Sbill 			continue;
69611Sbill 		case 'O':
70611Sbill 			oflag++;
71611Sbill 			continue;
72611Sbill 		case 'p':
73611Sbill 			proflag++;
74611Sbill 			continue;
75611Sbill 		case 'g':
76611Sbill 			gflag++;
77611Sbill 			continue;
78611Sbill 		case 'w':
79611Sbill 			wflag++;
80611Sbill 			continue;
81611Sbill 		case 'E':
82611Sbill 			exflag++;
83611Sbill 		case 'P':
84611Sbill 			pflag++;
85611Sbill 			if (argv[i][1]=='P')
86611Sbill 				fprintf(stderr,
87611Sbill 	"cc: warning: -P option obsolete; you should use -E instead\n");
88611Sbill 			plist[np++] = argv[i];
89611Sbill 		case 'c':
90611Sbill 			cflag++;
91611Sbill 			continue;
92611Sbill 		case 'D':
93611Sbill 		case 'I':
94611Sbill 		case 'U':
95611Sbill 		case 'C':
96611Sbill 			plist[np++] = argv[i];
97611Sbill 			continue;
98611Sbill 		case 't':
99611Sbill 			if (chpass)
100611Sbill 				error("-t overwrites earlier option", 0);
101611Sbill 			chpass = argv[i]+2;
102611Sbill 			if (chpass[0]==0)
103611Sbill 				chpass = "012p";
104611Sbill 			continue;
105611Sbill 		case 'B':
106611Sbill 			if (npassname)
107611Sbill 				error("-B overwrites earlier option", 0);
108611Sbill 			npassname = argv[i]+2;
109611Sbill 			if (npassname[0]==0)
110611Sbill 				npassname = "/usr/c/o";
111611Sbill 			continue;
112611Sbill 		case 'd':
113611Sbill 			dflag = argv[i];
114611Sbill 			continue;
115611Sbill 		}
116611Sbill 		t = argv[i];
117611Sbill 		c = getsuf(t);
118611Sbill 		if (c=='c' || c=='s' || exflag) {
119611Sbill 			clist[nc++] = t;
120611Sbill 			t = setsuf(t, 'o');
121611Sbill 		}
122611Sbill 		if (nodup(llist, t)) {
123611Sbill 			llist[nl++] = t;
124611Sbill 			if (getsuf(t)=='o')
125611Sbill 				nxo++;
126611Sbill 		}
127611Sbill 	}
128611Sbill 	if (gflag) {
129611Sbill 		if (oflag)
130611Sbill 			fprintf(stderr, "cc: warning: -g disables -O\n");
131611Sbill 		oflag = 0;
132611Sbill 	}
133611Sbill 	if (npassname && chpass ==0)
134611Sbill 		chpass = "012p";
135611Sbill 	if (chpass && npassname==0)
136*896Sbill 		npassname = "/usr/new";
137611Sbill 	if (chpass)
138611Sbill 	for (t=chpass; *t; t++) {
139611Sbill 		switch (*t) {
140611Sbill 
141611Sbill 		case '0':
142611Sbill 			ccom = strspl(npassname, "ccom");
143611Sbill 			continue;
144611Sbill 		case '2':
145611Sbill 			c2 = strspl(npassname, "c2");
146611Sbill 			continue;
147611Sbill 		case 'p':
148611Sbill 			cpp = strspl(npassname, "cpp");
149611Sbill 			continue;
150611Sbill 		}
151611Sbill 	}
152611Sbill 	if (proflag)
153*896Sbill 		crt0 = "/lib/mcrt0.o";
154611Sbill 	if (nc==0)
155611Sbill 		goto nocom;
156611Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
157611Sbill 		signal(SIGINT, idexit);
158611Sbill 	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
159611Sbill 		signal(SIGTERM, idexit);
160611Sbill 	if (pflag==0)
161611Sbill 		sprintf(tmp0, "/tmp/ctm%05.5d", getpid());
162611Sbill 	tmp1 = strspl(tmp0, "1");
163611Sbill 	tmp2 = strspl(tmp0, "2");
164611Sbill 	tmp3 = strspl(tmp0, "3");
165611Sbill 	if (pflag==0)
166611Sbill 		tmp4 = strspl(tmp0, "4");
167611Sbill 	if (oflag)
168611Sbill 		tmp5 = strspl(tmp0, "5");
169611Sbill 	for (i=0; i<nc; i++) {
170611Sbill 		if (nc > 1) {
171611Sbill 			printf("%s:\n", clist[i]);
172611Sbill 			fflush(stdout);
173611Sbill 		}
174611Sbill 		if (getsuf(clist[i]) == 's') {
175611Sbill 			assource = clist[i];
176611Sbill 			goto assemble;
177611Sbill 		} else
178611Sbill 			assource = tmp3;
179611Sbill 		if (pflag)
180611Sbill 			tmp4 = setsuf(clist[i], 'i');
181611Sbill 		av[0] = "cpp"; av[1] = clist[i]; av[2] = exflag ? "-" : tmp4;
182611Sbill 		na = 3;
183611Sbill 		for (j = 0; j < np; j++)
184611Sbill 			av[na++] = plist[j];
185611Sbill 		av[na++] = 0;
186611Sbill 		if (callsys(cpp, av)) {
187611Sbill 			exfail++;
188611Sbill 			eflag++;
189611Sbill 		}
190611Sbill 		if (pflag || exfail) {
191611Sbill 			cflag++;
192611Sbill 			continue;
193611Sbill 		}
194611Sbill 		if (sflag)
195611Sbill 			assource = tmp3 = setsuf(clist[i], 's');
196611Sbill 		av[0] = "ccom"; av[1] = tmp4; av[2] = oflag?tmp5:tmp3; na = 3;
197611Sbill 		if (proflag)
198611Sbill 			av[na++] = "-XP";
199611Sbill 		if (gflag)
200611Sbill 			av[na++] = "-Xg";
201611Sbill 		if (wflag)
202611Sbill 			av[na++] = "-w";
203611Sbill 		av[na] = 0;
204611Sbill 		if (callsys(ccom, av)) {
205611Sbill 			cflag++;
206611Sbill 			eflag++;
207611Sbill 			continue;
208611Sbill 		}
209611Sbill 		if (oflag) {
210611Sbill 			av[0] = "c2"; av[1] = tmp5; av[2] = tmp3; av[3] = 0;
211611Sbill 			if (callsys(c2, av)) {
212611Sbill 				unlink(tmp3);
213611Sbill 				tmp3 = assource = tmp5;
214611Sbill 			} else
215611Sbill 				unlink(tmp5);
216611Sbill 		}
217611Sbill 		if (sflag)
218611Sbill 			continue;
219611Sbill 	assemble:
220611Sbill 		cunlink(tmp1); cunlink(tmp2); cunlink(tmp4);
221611Sbill 		av[0] = "as"; av[1] = "-o"; av[2] = setsuf(clist[i], 'o');
222652Sbill 		na = 3;
223652Sbill 		if (Rflag)
224652Sbill 			av[na++] = "-R";
225611Sbill 		if (dflag)
226611Sbill 			av[na++] = dflag;
227652Sbill 		av[na++] = assource;
228611Sbill 		av[na] = 0;
229611Sbill 		if (callsys(as, av) > 1) {
230611Sbill 			cflag++;
231611Sbill 			eflag++;
232611Sbill 			continue;
233611Sbill 		}
234611Sbill 	}
235611Sbill nocom:
236611Sbill 	if (cflag==0 && nl!=0) {
237611Sbill 		i = 0;
238611Sbill 		av[0] = "ld"; av[1] = "-X"; av[2] = crt0; na = 3;
239611Sbill 		if (outfile) {
240611Sbill 			av[na++] = "-o";
241611Sbill 			av[na++] = outfile;
242611Sbill 		}
243611Sbill 		while (i < nl)
244611Sbill 			av[na++] = llist[i++];
245611Sbill 		if (gflag)
246611Sbill 			av[na++] = "-lg";
247611Sbill 		av[na++] = "-lc";
248611Sbill 		av[na++] = 0;
249611Sbill 		eflag |= callsys(ld, av);
250611Sbill 		if (nc==1 && nxo==1 && eflag==0)
251611Sbill 			unlink(setsuf(clist[0], 'o'));
252611Sbill 	}
253611Sbill 	dexit();
254611Sbill }
255611Sbill 
256611Sbill idexit()
257611Sbill {
258611Sbill 
259611Sbill 	eflag = 100;
260611Sbill 	dexit();
261611Sbill }
262611Sbill 
263611Sbill dexit()
264611Sbill {
265611Sbill 
266611Sbill 	if (!pflag) {
267611Sbill 		cunlink(tmp1);
268611Sbill 		cunlink(tmp2);
269611Sbill 		if (sflag==0)
270611Sbill 			cunlink(tmp3);
271611Sbill 		cunlink(tmp4);
272611Sbill 		cunlink(tmp5);
273611Sbill 	}
274611Sbill 	exit(eflag);
275611Sbill }
276611Sbill 
277611Sbill error(s, x)
278611Sbill 	char *s, *x;
279611Sbill {
280611Sbill 	FILE *diag = exflag ? stderr : stdout;
281611Sbill 
282611Sbill 	fprintf(diag, "cc: ");
283611Sbill 	fprintf(diag, s, x);
284611Sbill 	putc('\n', diag);
285611Sbill 	exfail++;
286611Sbill 	cflag++;
287611Sbill 	eflag++;
288611Sbill }
289611Sbill 
290611Sbill getsuf(as)
291611Sbill char as[];
292611Sbill {
293611Sbill 	register int c;
294611Sbill 	register char *s;
295611Sbill 	register int t;
296611Sbill 
297611Sbill 	s = as;
298611Sbill 	c = 0;
299611Sbill 	while (t = *s++)
300611Sbill 		if (t=='/')
301611Sbill 			c = 0;
302611Sbill 		else
303611Sbill 			c++;
304611Sbill 	s -= 3;
305611Sbill 	if (c <= DIRSIZ && c > 2 && *s++ == '.')
306611Sbill 		return (*s);
307611Sbill 	return (0);
308611Sbill }
309611Sbill 
310611Sbill char *
311611Sbill setsuf(as, ch)
312611Sbill 	char *as;
313611Sbill {
314611Sbill 	register char *s, *s1;
315611Sbill 
316611Sbill 	s = s1 = savestr(as);
317611Sbill 	while (*s)
318611Sbill 		if (*s++ == '/')
319611Sbill 			s1 = s;
320611Sbill 	s[-1] = ch;
321611Sbill 	return (s1);
322611Sbill }
323611Sbill 
324611Sbill callsys(f, v)
325611Sbill 	char *f, **v;
326611Sbill {
327611Sbill 	int t, status;
328611Sbill 
329611Sbill 	t = vfork();
330611Sbill 	if (t == -1) {
331611Sbill 		printf("No more processes\n");
332611Sbill 		return (100);
333611Sbill 	}
334611Sbill 	if (t == 0) {
335611Sbill 		execv(f, v);
336611Sbill 		printf("Can't find %s\n", f);
337611Sbill 		fflush(stdout);
338611Sbill 		_exit(100);
339611Sbill 	}
340611Sbill 	while (t != wait(&status))
341611Sbill 		;
342611Sbill 	if ((t=(status&0377)) != 0 && t!=14) {
343611Sbill 		if (t!=2) {
344611Sbill 			printf("Fatal error in %s\n", f);
345611Sbill 			eflag = 8;
346611Sbill 		}
347611Sbill 		dexit();
348611Sbill 	}
349611Sbill 	return ((status>>8) & 0377);
350611Sbill }
351611Sbill 
352611Sbill nodup(l, os)
353611Sbill 	char **l, *os;
354611Sbill {
355611Sbill 	register char *t, *s;
356611Sbill 	register int c;
357611Sbill 
358611Sbill 	s = os;
359611Sbill 	if (getsuf(s) != 'o')
360611Sbill 		return (1);
361611Sbill 	while (t = *l++) {
362611Sbill 		while (c = *s++)
363611Sbill 			if (c != *t++)
364611Sbill 				break;
365611Sbill 		if (*t==0 && c==0)
366611Sbill 			return (0);
367611Sbill 		s = os;
368611Sbill 	}
369611Sbill 	return (1);
370611Sbill }
371611Sbill 
372611Sbill #define	NSAVETAB	1024
373611Sbill char	*savetab;
374611Sbill int	saveleft;
375611Sbill 
376611Sbill char *
377611Sbill savestr(cp)
378611Sbill 	register char *cp;
379611Sbill {
380611Sbill 	register int len;
381611Sbill 
382611Sbill 	len = strlen(cp) + 1;
383611Sbill 	if (len > saveleft) {
384611Sbill 		saveleft = NSAVETAB;
385611Sbill 		if (len > saveleft)
386611Sbill 			saveleft = len;
387611Sbill 		savetab = (char *)malloc(saveleft);
388611Sbill 		if (savetab == 0) {
389611Sbill 			fprintf(stderr, "ran out of memory (savestr)\n");
390611Sbill 			exit(1);
391611Sbill 		}
392611Sbill 	}
393611Sbill 	strncpy(savetab, cp, len);
394611Sbill 	cp = savetab;
395611Sbill 	savetab += len;
396611Sbill 	saveleft -= len;
397611Sbill 	return (cp);
398611Sbill }
399611Sbill 
400611Sbill char *
401611Sbill strspl(left, right)
402611Sbill 	char *left, *right;
403611Sbill {
404611Sbill 	char buf[BUFSIZ];
405611Sbill 
406611Sbill 	strcpy(buf, left);
407611Sbill 	strcat(buf, right);
408611Sbill 	return (savestr(buf));
409611Sbill }
410