xref: /original-bsd/usr.bin/pascal/pc/pc.c (revision f0fd5f8a)
1 static	char sccsid[] = "@(#)pc.c 3.17 11/12/82";
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 		ldargs[ldargx++] = "-lm";
401 		ldargs[ldargx++] = "-lc";
402 	}
403 	ldargs[ldargx] = 0;
404 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
405 		unlink(onepso);
406 	done();
407 }
408 
409 dosys(cmd, argv, in, out)
410 	char *cmd, **argv, *in, *out;
411 {
412 	union wait status;
413 	int pid;
414 
415 	if (debug) {
416 		int i;
417 		printf("%s:", cmd);
418 		for (i = 0; argv[i]; i++)
419 			printf(" %s", argv[i]);
420 		if (in)
421 			printf(" <%s", in);
422 		if (out)
423 			printf(" >%s", out);
424 		printf("\n");
425 	}
426 	pid = vfork();
427 	if (pid < 0) {
428 		fprintf(stderr, "pc: No more processes\n");
429 		done();
430 	}
431 	if (pid == 0) {
432 		if (in) {
433 			close(0);
434 			if (open(in, 0) != 0) {
435 				perror(in);
436 				exit(1);
437 			}
438 		}
439 		if (out) {
440 			close(1);
441 			unlink(out);
442 			if (creat(out, 0666) != 1) {
443 				perror(out);
444 				exit(1);
445 			}
446 		}
447 		signal(SIGINT, SIG_DFL);
448 		execv(cmd, argv);
449 		perror(cmd);
450 		exit(1);
451 	}
452 	while (wait(&status) != pid)
453 		;
454 	if (WIFSIGNALED(status)) {
455 		if (status.w_termsig != SIGINT) {
456 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
457 			if (status.w_coredump)
458 				fprintf(stderr, " (core dumped)");
459 			fprintf(stderr, "\n");
460 		}
461 		errs = 100;
462 		done();
463 		/*NOTREACHED*/
464 	}
465 	if (status.w_retcode) {
466 		errs = 1;
467 		remove();
468 	}
469 	return (status.w_retcode);
470 }
471 
472 done()
473 {
474 
475 	remove();
476 	exit(errs);
477 }
478 
479 remove()
480 {
481 
482 	if (tfile[0])
483 		unlink(tfile[0]);
484 	if (tfile[1])
485 		unlink(tfile[1]);
486 }
487 
488 onintr()
489 {
490 
491 	errs = 1;
492 	done();
493 }
494 
495 getsuf(cp)
496 	char *cp;
497 {
498 
499 	if (*cp == 0)
500 		return;
501 	while (cp[1])
502 		cp++;
503 	if (cp[-1] != '.')
504 		return (0);
505 	return (*cp);
506 }
507 
508 char *
509 setsuf(as, ch)
510 	char *as;
511 {
512 	register char *s, *s1;
513 
514 	s = s1 = savestr(as);
515 	while (*s)
516 		if (*s++ == '/')
517 			s1 = s;
518 	s[-1] = ch;
519 	return (s1);
520 }
521 
522 #define	NSAVETAB	512
523 char	*savetab;
524 int	saveleft;
525 
526 char *
527 savestr(cp)
528 	register char *cp;
529 {
530 	register int len;
531 
532 	len = strlen(cp) + 1;
533 	if (len > saveleft) {
534 		saveleft = NSAVETAB;
535 		if (len > saveleft)
536 			saveleft = len;
537 		savetab = (char *)malloc(saveleft);
538 		if (savetab == 0) {
539 			fprintf(stderr, "ran out of memory (savestr)\n");
540 			exit(1);
541 		}
542 	}
543 	strncpy(savetab, cp, len);
544 	cp = savetab;
545 	savetab += len;
546 	return (cp);
547 }
548 
549 suffix(cp)
550 	char *cp;
551 {
552 
553 	if (cp[0] == 0 || cp[1] == 0)
554 		return (0);
555 	while (cp[1])
556 		cp++;
557 	if (cp[-1] == '.')
558 		return (*cp);
559 	return (0);
560 }
561