xref: /original-bsd/usr.bin/pascal/pc/pc.c (revision 4b2c5e10)
1 #ifndef lint
2 static	char sccsid[] = "@(#)pc.c	3.25 (Berkeley) 07/02/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 	pid = vfork();
468 	if (pid < 0) {
469 		fprintf(stderr, "pc: No more processes\n");
470 		done();
471 	}
472 	if (pid == 0) {
473 		if (in) {
474 			close(0);
475 			if (open(in, 0) != 0) {
476 				perror(in);
477 				exit(1);
478 			}
479 		}
480 		if (out) {
481 			close(1);
482 			unlink(out);
483 			if (creat(out, 0666) != 1) {
484 				perror(out);
485 				exit(1);
486 			}
487 		}
488 		signal(SIGINT, SIG_DFL);
489 		execv(cmd, argv);
490 		perror(cmd);
491 		exit(1);
492 	}
493 	while (wait(&status) != pid)
494 		;
495 	if (WIFSIGNALED(status)) {
496 		if (status.w_termsig != SIGINT) {
497 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
498 			if (status.w_coredump)
499 				fprintf(stderr, " (core dumped)");
500 			fprintf(stderr, "\n");
501 		}
502 		errs = 100;
503 		done();
504 		/*NOTREACHED*/
505 	}
506 	if (status.w_retcode) {
507 		errs = 1;
508 		remove();
509 	}
510 	return (status.w_retcode);
511 }
512 
513 done()
514 {
515 
516 	remove();
517 	exit(errs);
518 }
519 
520 remove()
521 {
522 
523 	if (tfile[0])
524 		unlink(tfile[0]);
525 	if (tfile[1])
526 		unlink(tfile[1]);
527 }
528 
529 onintr()
530 {
531 
532 	errs = 1;
533 	done();
534 }
535 
536 getsuf(cp)
537 	char *cp;
538 {
539 
540 	if (*cp == 0)
541 		return;
542 	while (cp[1])
543 		cp++;
544 	if (cp[-1] != '.')
545 		return (0);
546 	return (*cp);
547 }
548 
549 char *
550 setsuf(as, ch)
551 	char *as;
552 {
553 	register char *s, *s1;
554 
555 	s = s1 = savestr(as);
556 	while (*s)
557 		if (*s++ == '/')
558 			s1 = s;
559 	s[-1] = ch;
560 	return (s1);
561 }
562 
563 #define	NSAVETAB	512
564 char	*savetab;
565 int	saveleft;
566 
567 char *
568 savestr(cp)
569 	register char *cp;
570 {
571 	register int len;
572 
573 	len = strlen(cp) + 1;
574 	if (len > saveleft) {
575 		saveleft = NSAVETAB;
576 		if (len > saveleft)
577 			saveleft = len;
578 		savetab = (char *)malloc(saveleft);
579 		if (savetab == 0) {
580 			fprintf(stderr, "ran out of memory (savestr)\n");
581 			exit(1);
582 		}
583 	}
584 	strncpy(savetab, cp, len);
585 	cp = savetab;
586 	savetab += len;
587 	return (cp);
588 }
589 
590 suffix(cp)
591 	char *cp;
592 {
593 
594 	if (cp[0] == 0 || cp[1] == 0)
595 		return (0);
596 	while (cp[1])
597 		cp++;
598 	if (cp[-1] == '.')
599 		return (*cp);
600 	return (0);
601 }
602