xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 10721)
1 static	char sccsid[] = "@(#)pc.c 3.20 02/03/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 #ifndef sun
402 		ldargs[ldargx++] = "-lm";
403 		ldargs[ldargx++] = "-lc";
404 #else
405 		ldargs[ldargx++] = "-lMm";
406 		ldargs[ldargx++] = "-lMc";
407 #endif
408 	}
409 	ldargs[ldargx] = 0;
410 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
411 		unlink(onepso);
412 	done();
413 }
414 
415 dosys(cmd, argv, in, out)
416 	char *cmd, **argv, *in, *out;
417 {
418 	union wait status;
419 	int pid;
420 
421 	if (debug) {
422 		int i;
423 		printf("%s:", cmd);
424 		for (i = 0; argv[i]; i++)
425 			printf(" %s", argv[i]);
426 		if (in)
427 			printf(" <%s", in);
428 		if (out)
429 			printf(" >%s", out);
430 		printf("\n");
431 	}
432 	pid = vfork();
433 	if (pid < 0) {
434 		fprintf(stderr, "pc: No more processes\n");
435 		done();
436 	}
437 	if (pid == 0) {
438 		if (in) {
439 			close(0);
440 			if (open(in, 0) != 0) {
441 				perror(in);
442 				exit(1);
443 			}
444 		}
445 		if (out) {
446 			close(1);
447 			unlink(out);
448 			if (creat(out, 0666) != 1) {
449 				perror(out);
450 				exit(1);
451 			}
452 		}
453 		signal(SIGINT, SIG_DFL);
454 		execv(cmd, argv);
455 		perror(cmd);
456 		exit(1);
457 	}
458 	while (wait(&status) != pid)
459 		;
460 	if (WIFSIGNALED(status)) {
461 		if (status.w_termsig != SIGINT) {
462 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
463 			if (status.w_coredump)
464 				fprintf(stderr, " (core dumped)");
465 			fprintf(stderr, "\n");
466 		}
467 		errs = 100;
468 		done();
469 		/*NOTREACHED*/
470 	}
471 	if (status.w_retcode) {
472 		errs = 1;
473 		remove();
474 	}
475 	return (status.w_retcode);
476 }
477 
478 done()
479 {
480 
481 	remove();
482 	exit(errs);
483 }
484 
485 remove()
486 {
487 
488 	if (tfile[0])
489 		unlink(tfile[0]);
490 	if (tfile[1])
491 		unlink(tfile[1]);
492 }
493 
494 onintr()
495 {
496 
497 	errs = 1;
498 	done();
499 }
500 
501 getsuf(cp)
502 	char *cp;
503 {
504 
505 	if (*cp == 0)
506 		return;
507 	while (cp[1])
508 		cp++;
509 	if (cp[-1] != '.')
510 		return (0);
511 	return (*cp);
512 }
513 
514 char *
515 setsuf(as, ch)
516 	char *as;
517 {
518 	register char *s, *s1;
519 
520 	s = s1 = savestr(as);
521 	while (*s)
522 		if (*s++ == '/')
523 			s1 = s;
524 	s[-1] = ch;
525 	return (s1);
526 }
527 
528 #define	NSAVETAB	512
529 char	*savetab;
530 int	saveleft;
531 
532 char *
533 savestr(cp)
534 	register char *cp;
535 {
536 	register int len;
537 
538 	len = strlen(cp) + 1;
539 	if (len > saveleft) {
540 		saveleft = NSAVETAB;
541 		if (len > saveleft)
542 			saveleft = len;
543 		savetab = (char *)malloc(saveleft);
544 		if (savetab == 0) {
545 			fprintf(stderr, "ran out of memory (savestr)\n");
546 			exit(1);
547 		}
548 	}
549 	strncpy(savetab, cp, len);
550 	cp = savetab;
551 	savetab += len;
552 	return (cp);
553 }
554 
555 suffix(cp)
556 	char *cp;
557 {
558 
559 	if (cp[0] == 0 || cp[1] == 0)
560 		return (0);
561 	while (cp[1])
562 		cp++;
563 	if (cp[-1] == '.')
564 		return (*cp);
565 	return (0);
566 }
567