xref: /original-bsd/usr.bin/pascal/pc/pc.c (revision d25e1985)
1 static	char sccsid[] = "@(#)pc.c 3.6 09/24/80";
2 #include <stdio.h>
3 #include <signal.h>
4 #include <wait.h>
5 
6 /*
7  * Pc - front end for Pascal compiler.
8  */
9 char	*pc0 = "/usr/lib/pc0";
10 char	*pc1 = "/lib/f1";
11 char	*pc2 = "/usr/lib/pc2";
12 char	*c2 = "/lib/c2";
13 char	*pc3 = "/usr/lib/pc3";
14 char	*ld = "/bin/ld";
15 char	*as = "/bin/as";
16 char	*lpc = "-lpc";
17 char	*crt0 = "/lib/crt0.o";
18 char	*mcrt0 = "/lib/mcrt0.o";
19 
20 char	*mktemp();
21 char	*tname[2];
22 char	*tfile[2];
23 
24 char	*setsuf(), *savestr();
25 
26 int	Jflag, Sflag, Oflag, cflag, gflag, pflag;
27 int	debug;
28 
29 #define	NARGS	512
30 int	ldargx = 3;
31 int	pc0argx = 3;
32 char	*pc0args[NARGS] =	{ "pc0", "-o", "XXX" };
33 char	*pc1args[3] =		{ "pc1", 0, };
34 char	*pc2args[2] =		{ "pc2", 0 };
35 char	*c2args[4] =		{ "c2", 0, 0, 0 };
36 int	pc3argx = 1;
37 #define	pc3args	pc0args
38 #define	ldargs	pc0args
39 /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
40 /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
41 int	asargx;
42 char	*asargs[6] =		{ "as", 0, };
43 
44 /*
45  * If the number of .p arguments (np) is 1, and the number of .o arguments
46  * (nxo) is 0, and we successfully create an ``a.out'', then we remove
47  * the one .ps .o file (onepso).
48  */
49 int	np, nxo;
50 char	*onepso;
51 int	errs;
52 
53 int	onintr();
54 
55 main(argc, argv)
56 	int argc;
57 	char **argv;
58 {
59 	register char *argp;
60 	register int i;
61 	int savargx;
62 	char *t, c;
63 	int j;
64 
65 	argc--, argv++;
66 	if (argc == 0) {
67 		execl("/bin/cat", "cat", "/usr/lib/how_pc");
68 		exit(1);
69 	}
70 	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
71 		signal(SIGINT, onintr);
72 		signal(SIGTERM, onintr);
73 	}
74 	for (i = 0; i < argc; i++) {
75 		argp = argv[i];
76 		if (argp[0] != '-')
77 			continue;
78 		switch (argp[1]) {
79 
80 		case 'd':
81 			if (argp[2] == 0)
82 				debug++;
83 			continue;
84 		case 'i':
85 			pc0args[pc0argx++] = "-i";
86 			while (i+1 < argc && argv[i+1][0] != '-' &&
87 			    getsuf(argv[i+1]) != 'p') {
88 				pc0args[pc0argx++] = argv[i+1];
89 				i++;
90 			}
91 			if (i+1 == argc) {
92 				fprintf(stderr, "pc: bad -i construction\n");
93 				exit(1);
94 			}
95 			continue;
96 		case 'o':
97 			i++;
98 			if (i == argc) {
99 				fprintf(stderr, "pc: -o must specify file\n");
100 				exit(1);
101 			}
102 			c = getsuf(argv[i]);
103 			if (c == 'o' || c == 'p' || c == 'c') {
104 				fprintf(stderr, "pc: -o would overwrite %s\n",
105 				    argv[i]);
106 				exit(1);
107 			}
108 			continue;
109 		case 'O':
110 			Oflag = 1;
111 			continue;
112 		case 'S':
113 			Sflag = 1;
114 			continue;
115 		case 'J':
116 			Jflag = 1;
117 			continue;
118 		case 'T':
119 			switch (argp[2]) {
120 
121 			case '0':
122 				pc0 = "/usr/src/cmd/pc0/a.out";
123 				continue;
124 			case '1':
125 				pc1 = "/usr/src/cmd/pcc/pc1";
126 				continue;
127 			case '2':
128 				pc2 = "/usr/src/cmd/pc2/a.out";
129 				continue;
130 			case '3':
131 				pc3 = "/usr/src/cmd/pc3/a.out";
132 				continue;
133 			case 'l':
134 				lpc = "-lnpc";
135 				continue;
136 			}
137 			continue;
138 		case 'c':
139 			cflag = 1;
140 			continue;
141 		case 'l':
142 			if (argp[2])
143 				continue;
144 			/* fall into ... */
145 		case 'b':
146 		case 'g':
147 		case 's':
148 		case 'w':
149 		case 'z':
150 		case 'C':
151 			pc0args[pc0argx++] = argp;
152 			if (argp[1] == 'g')
153 				gflag = 1;
154 			continue;
155 		case 't':
156 			fprintf(stderr, "pc: -t is default; -C for checking\n");
157 			continue;
158 		case 'p':
159 			crt0 = mcrt0;
160 			pflag++;
161 			continue;
162 		}
163 	}
164 	if (gflag && Oflag) {
165 		fprintf(stderr, "pc: warning: -g overrides -O\n");
166 		Oflag = 0;
167 	}
168 	tname[0] = mktemp("/tmp/p0XXXXXX");
169 	tname[1] = mktemp("/tmp/p1XXXXXX");
170 	savargx = pc0argx;
171 	for (i = 0; i < argc; i++) {
172 		argp = argv[i];
173 		if (argp[0] == '-')
174 			continue;
175 		if (suffix(argp) != 'p')
176 			continue;
177 		tfile[0] = tname[0];
178 		pc0args[2] = tfile[0];
179 		pc0argx = savargx;
180 		if (pflag)
181 			pc0args[pc0argx++] = "-p";
182 		pc0args[pc0argx++] = argp;
183 		pc0args[pc0argx] = 0;
184 		if (dosys(pc0, pc0args, 0, 0))
185 			continue;
186 		pc1args[1] = tfile[0];
187 		tfile[1] = tname[1];
188 		if (dosys(pc1, pc1args, 0, tfile[1]))
189 			continue;
190 		unlink(tfile[0]);
191 		if (Sflag && !Oflag)
192 			tfile[0] = setsuf(argp, 's');
193 		else
194 			tfile[0] = tname[0];
195 		if (dosys(pc2, pc2args, tfile[1], tfile[0]))
196 			continue;
197 		unlink(tfile[1]);
198 		tfile[1] = 0;
199 		if (Oflag) {
200 			if (Sflag)
201 				tfile[1] = setsuf(argp, 's');
202 			else
203 				tfile[1] = tname[1];
204 			if (dosys(c2, c2args, tfile[0], tfile[1]))
205 				continue;
206 			unlink(tfile[0]);
207 			tfile[0] = tfile[1];
208 			tfile[1] = 0;
209 		}
210 		if (Sflag) {
211 			tfile[0] = 0;
212 			continue;
213 		}
214 		asargx = 1;
215 		if (Jflag)
216 			asargs[asargx++] = "-J";
217 		asargs[asargx++] = tfile[0];
218 		asargs[asargx++] = "-o";
219 		tfile[1] = setsuf(argp, 'o');
220 		asargs[asargx++] = tfile[1];
221 		asargs[asargx] = 0;
222 		if (dosys(as, asargs, 0, 0))
223 			continue;
224 		tfile[1] = 0;
225 		remove();
226 	}
227 	if (errs || cflag || Sflag)
228 		done();
229 /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
230 	pc3args[0] = "pc3";
231 	for (i = 0; i < argc; i++) {
232 		argp = argv[i];
233 		if (!strcmp(argp, "-o"))
234 			i++;
235 		if (argp[0] == '-')
236 			continue;
237 		switch (getsuf(argp)) {
238 
239 		case 'o':
240 			pc3args[pc3argx++] = argp;
241 			nxo++;
242 			continue;
243 		case 'p':
244 			onepso = pc3args[pc3argx++] =
245 			    savestr(setsuf(argp, 'o'));
246 			np++;
247 			continue;
248 		}
249 	}
250 	pc3args[pc3argx] = 0;
251 	if (dosys(pc3, pc3args, 0, 0))
252 		done();
253 /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
254 	ldargs[0] = "ld";
255 	ldargs[1] = "-X";
256 	ldargs[2] = crt0;
257 	for (i = 0; i < argc; i++) {
258 		argp = argv[i];
259 		if (argp[0] != '-') {
260 			switch (getsuf(argp)) {
261 
262 			case 'p':
263 				ldargs[ldargx] = savestr(setsuf(argp, 'o'));
264 				break;
265 			default:
266 				ldargs[ldargx] = argp;
267 				break;
268 			}
269 			if (getsuf(ldargs[ldargx]) == 'o')
270 			for (j = 0; j < ldargx; j++)
271 				if (!strcmp(ldargs[j], ldargs[ldargx]))
272 					goto duplicate;
273 			ldargx++;
274 duplicate:
275 			continue;
276 		}
277 		switch (argp[1]) {
278 
279 		case 'i':
280 			while (i+1 < argc && argv[i+1][0] != '-' &&
281 			    getsuf(argv[i+1]) != 'p')
282 				i++;
283 			continue;
284 		case 'd':
285 			if (argp[2] == 0)
286 				continue;
287 			ldargs[ldargx++] = argp;
288 			continue;
289 		case 'o':
290 			ldargs[ldargx++] = argp;
291 			i++;
292 			ldargs[ldargx++] = argv[i];
293 			continue;
294 		case 'l':
295 			if (argp[2])
296 				ldargs[ldargx++] = argp;
297 			continue;
298 		case 'c':
299 		case 'g':
300 		case 'w':
301 		case 'p':
302 		case 'S':
303 		case 'J':
304 		case 'T':
305 		case 'O':
306 		case 'C':
307 		case 'b':
308 		case 's':
309 		case 'z':
310 			continue;
311 		default:
312 			ldargs[ldargx++] = argp;
313 			continue;
314 		}
315 	}
316 	ldargs[ldargx++] = lpc;
317 	if (gflag)
318 		ldargs[ldargx++] = "-lg";
319 	ldargs[ldargx++] = "-lm";
320 	ldargs[ldargx++] = "-lc";
321 	ldargs[ldargx] = 0;
322 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
323 		unlink(onepso);
324 	done();
325 }
326 
327 dosys(cmd, argv, in, out)
328 	char *cmd, **argv, *in, *out;
329 {
330 	union wait status;
331 	int pid;
332 
333 	if (debug) {
334 		int i;
335 		printf("%s:", cmd);
336 		for (i = 0; argv[i]; i++)
337 			printf(" %s", argv[i]);
338 		if (in)
339 			printf(" <%s", in);
340 		if (out)
341 			printf(" >%s", out);
342 		printf("\n");
343 	}
344 	pid = vfork();
345 	if (pid < 0) {
346 		fprintf(stderr, "pc: No more processes\n");
347 		done();
348 	}
349 	if (pid == 0) {
350 		if (in) {
351 			close(0);
352 			if (open(in, 0) != 0) {
353 				perror(in);
354 				exit(1);
355 			}
356 		}
357 		if (out) {
358 			close(1);
359 			unlink(out);
360 			if (creat(out, 0666) != 1) {
361 				perror(out);
362 				exit(1);
363 			}
364 		}
365 		signal(SIGINT, SIG_DFL);
366 		execv(cmd, argv);
367 		perror(cmd);
368 		exit(1);
369 	}
370 	while (wait(&status) != pid)
371 		;
372 	if (WIFSIGNALED(status)) {
373 		if (status.w_termsig != SIGINT)
374 			fprintf(stderr, "Fatal error in %s\n", cmd);
375 		errs = 100;
376 		done();
377 		/*NOTREACHED*/
378 	}
379 	if (status.w_retcode) {
380 		errs = 1;
381 		remove();
382 	}
383 	return (status.w_retcode);
384 }
385 
386 done()
387 {
388 
389 	remove();
390 	exit(errs);
391 }
392 
393 remove()
394 {
395 
396 	if (tfile[0])
397 		unlink(tfile[0]);
398 	if (tfile[1])
399 		unlink(tfile[1]);
400 }
401 
402 onintr()
403 {
404 
405 	errs = 1;
406 	done();
407 }
408 
409 getsuf(cp)
410 	char *cp;
411 {
412 
413 	if (*cp == 0)
414 		return;
415 	while (cp[1])
416 		cp++;
417 	if (cp[-1] != '.')
418 		return (0);
419 	return (*cp);
420 }
421 
422 char *
423 setsuf(as, ch)
424 	char *as;
425 {
426 	register char *s, *s1;
427 
428 	s = s1 = savestr(as);
429 	while (*s)
430 		if (*s++ == '/')
431 			s1 = s;
432 	s[-1] = ch;
433 	return (s1);
434 }
435 
436 #define	NSAVETAB	512
437 char	*savetab;
438 int	saveleft;
439 
440 char *
441 savestr(cp)
442 	register char *cp;
443 {
444 	register int len;
445 
446 	len = strlen(cp) + 1;
447 	if (len > saveleft) {
448 		saveleft = NSAVETAB;
449 		if (len > saveleft)
450 			saveleft = len;
451 		savetab = (char *)malloc(saveleft);
452 		if (savetab == 0) {
453 			fprintf(stderr, "ran out of memory (savestr)\n");
454 			exit(1);
455 		}
456 	}
457 	strncpy(savetab, cp, len);
458 	cp = savetab;
459 	savetab += len;
460 	return (cp);
461 }
462 
463 suffix(cp)
464 	char *cp;
465 {
466 
467 	if (cp[0] == 0 || cp[1] == 0)
468 		return (0);
469 	while (cp[1])
470 		cp++;
471 	if (cp[-1] == '.')
472 		return (*cp);
473 	return (0);
474 }
475