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