xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 10561)
1 static	char sccsid[] = "@(#)pc.c 3.18 01/21/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/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/pc2";
173 				if (argp[3] != '\0') {
174 					pc2 = &argp[3];
175 				}
176 				continue;
177 			case '3':
178 				pc3 = "/usr/src/ucb/pascal/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 /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
330 	ldargs[0] = "ld";
331 	ldargs[1] = "-X";
332 	ldargs[2] = crt0;
333 	for (i = 0; i < argc; i++) {
334 		argp = argv[i];
335 		if (argp[0] != '-') {
336 			switch (getsuf(argp)) {
337 
338 			case 'p':
339 			case 's':
340 				ldargs[ldargx] = savestr(setsuf(argp, 'o'));
341 				break;
342 			default:
343 				ldargs[ldargx] = argp;
344 				break;
345 			}
346 			if (getsuf(ldargs[ldargx]) == 'o')
347 			for (j = 0; j < ldargx; j++)
348 				if (!strcmp(ldargs[j], ldargs[ldargx]))
349 					goto duplicate;
350 			ldargx++;
351 duplicate:
352 			continue;
353 		}
354 		switch (argp[1]) {
355 
356 		case 'i':
357 			while (i+1 < argc && argv[i+1][0] != '-' &&
358 			    getsuf(argv[i+1]) != 'p')
359 				i++;
360 			continue;
361 		case 'd':
362 			if (argp[2] == 0)
363 				continue;
364 			ldargs[ldargx++] = argp;
365 			continue;
366 		case 'o':
367 			ldargs[ldargx++] = argp;
368 			i++;
369 			ldargs[ldargx++] = argv[i];
370 			continue;
371 		case 'l':
372 			if (argp[2])
373 				ldargs[ldargx++] = argp;
374 			continue;
375 		case 'c':
376 		case 'g':
377 		case 'w':
378 		case 'p':
379 		case 'S':
380 		case 'J':
381 		case 'T':
382 		case 'O':
383 		case 'C':
384 		case 'b':
385 		case 's':
386 		case 'z':
387 			continue;
388 		default:
389 			ldargs[ldargx++] = argp;
390 			continue;
391 		}
392 	}
393 	ldargs[ldargx++] = lpc;
394 	if (gflag)
395 		ldargs[ldargx++] = "-lg";
396 	if (pflag) {
397 		ldargs[ldargx++] = "-lm_p";
398 		ldargs[ldargx++] = "-lc_p";
399 	} else {
400 #ifndef sun
401 		ldargs[ldargx++] = "-lm";
402 		ldargs[ldargx++] = "-lc";
403 #else
404 		ldargs[ldargx++] = "-lMm";
405 		ldargs[ldargx++] = "-lMc";
406 #endif
407 	}
408 	ldargs[ldargx] = 0;
409 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
410 		unlink(onepso);
411 	done();
412 }
413 
414 dosys(cmd, argv, in, out)
415 	char *cmd, **argv, *in, *out;
416 {
417 	union wait status;
418 	int pid;
419 
420 	if (debug) {
421 		int i;
422 		printf("%s:", cmd);
423 		for (i = 0; argv[i]; i++)
424 			printf(" %s", argv[i]);
425 		if (in)
426 			printf(" <%s", in);
427 		if (out)
428 			printf(" >%s", out);
429 		printf("\n");
430 	}
431 	pid = vfork();
432 	if (pid < 0) {
433 		fprintf(stderr, "pc: No more processes\n");
434 		done();
435 	}
436 	if (pid == 0) {
437 		if (in) {
438 			close(0);
439 			if (open(in, 0) != 0) {
440 				perror(in);
441 				exit(1);
442 			}
443 		}
444 		if (out) {
445 			close(1);
446 			unlink(out);
447 			if (creat(out, 0666) != 1) {
448 				perror(out);
449 				exit(1);
450 			}
451 		}
452 		signal(SIGINT, SIG_DFL);
453 		execv(cmd, argv);
454 		perror(cmd);
455 		exit(1);
456 	}
457 	while (wait(&status) != pid)
458 		;
459 	if (WIFSIGNALED(status)) {
460 		if (status.w_termsig != SIGINT) {
461 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
462 			if (status.w_coredump)
463 				fprintf(stderr, " (core dumped)");
464 			fprintf(stderr, "\n");
465 		}
466 		errs = 100;
467 		done();
468 		/*NOTREACHED*/
469 	}
470 	if (status.w_retcode) {
471 		errs = 1;
472 		remove();
473 	}
474 	return (status.w_retcode);
475 }
476 
477 done()
478 {
479 
480 	remove();
481 	exit(errs);
482 }
483 
484 remove()
485 {
486 
487 	if (tfile[0])
488 		unlink(tfile[0]);
489 	if (tfile[1])
490 		unlink(tfile[1]);
491 }
492 
493 onintr()
494 {
495 
496 	errs = 1;
497 	done();
498 }
499 
500 getsuf(cp)
501 	char *cp;
502 {
503 
504 	if (*cp == 0)
505 		return;
506 	while (cp[1])
507 		cp++;
508 	if (cp[-1] != '.')
509 		return (0);
510 	return (*cp);
511 }
512 
513 char *
514 setsuf(as, ch)
515 	char *as;
516 {
517 	register char *s, *s1;
518 
519 	s = s1 = savestr(as);
520 	while (*s)
521 		if (*s++ == '/')
522 			s1 = s;
523 	s[-1] = ch;
524 	return (s1);
525 }
526 
527 #define	NSAVETAB	512
528 char	*savetab;
529 int	saveleft;
530 
531 char *
532 savestr(cp)
533 	register char *cp;
534 {
535 	register int len;
536 
537 	len = strlen(cp) + 1;
538 	if (len > saveleft) {
539 		saveleft = NSAVETAB;
540 		if (len > saveleft)
541 			saveleft = len;
542 		savetab = (char *)malloc(saveleft);
543 		if (savetab == 0) {
544 			fprintf(stderr, "ran out of memory (savestr)\n");
545 			exit(1);
546 		}
547 	}
548 	strncpy(savetab, cp, len);
549 	cp = savetab;
550 	savetab += len;
551 	return (cp);
552 }
553 
554 suffix(cp)
555 	char *cp;
556 {
557 
558 	if (cp[0] == 0 || cp[1] == 0)
559 		return (0);
560 	while (cp[1])
561 		cp++;
562 	if (cp[-1] == '.')
563 		return (*cp);
564 	return (0);
565 }
566