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