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