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