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