xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 12966)
1 static	char sccsid[] = "@(#)pc.c 3.24 06/10/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 		if (Jflag)
287 			pc0args[pc0argx++] = "-J";
288 		pc0args[pc0argx++] = argp;
289 		pc0args[pc0argx] = 0;
290 		if (dosys(pc0, pc0args, 0, 0))
291 			continue;
292 		pc1args[1] = tfile[0];
293 		tfile[1] = tname[1];
294 		if (dosys(pc1, pc1args, 0, tfile[1]))
295 			continue;
296 		unlink(tfile[0]);
297 		tfile[0] = tname[0];
298 		if (Oflag) {
299 			if (dosys(c2, c2args, tfile[1], tfile[0]))
300 				continue;
301 			unlink(tfile[1]);
302 			tfile[1] = tfile[0];
303 			tfile[0] = tname[1];
304 		}
305 		if (Sflag)
306 			tfile[0] = setsuf(argp, 's');
307 		if (dosys(pc2, pc2args, tfile[1], tfile[0]))
308 			continue;
309 		unlink(tfile[1]);
310 		tfile[1] = 0;
311 		if (Sflag) {
312 			tfile[0] = 0;
313 			continue;
314 		}
315 		asargx = 1;
316 		if (Jflag)
317 			asargs[asargx++] = "-J";
318 #		ifdef vax
319 			if (tflag) {
320 				asargs[asargx++] = "-t";
321 				asargs[asargx++] = tmpdir;
322 			}
323 #		endif vax
324 		asargs[asargx++] = tfile[0];
325 		asargs[asargx++] = "-o";
326 		tfile[1] = setsuf(argp, 'o');
327 		asargs[asargx++] = tfile[1];
328 		asargs[asargx] = 0;
329 		if (dosys(as, asargs, 0, 0))
330 			continue;
331 		tfile[1] = 0;
332 		remove();
333 	}
334 	if (errs || cflag || Sflag)
335 		done();
336 /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
337 	pc3args[0] = "pc3";
338 	if (wflag)
339 		pc3args[pc3argx++] = "-w";
340 	pc3args[pc3argx++] = "/usr/lib/pcexterns.o";
341 	for (i = 0; i < argc; i++) {
342 		argp = argv[i];
343 		if (!strcmp(argp, "-o"))
344 			i++;
345 		if (argp[0] == '-')
346 			continue;
347 		switch (getsuf(argp)) {
348 
349 		case 'o':
350 			pc3args[pc3argx++] = argp;
351 			nxo++;
352 			continue;
353 		case 's':
354 		case 'p':
355 			onepso = pc3args[pc3argx++] =
356 			    savestr(setsuf(argp, 'o'));
357 			np++;
358 			continue;
359 		}
360 	}
361 	pc3args[pc3argx] = 0;
362 	if (dosys(pc3, pc3args, 0, 0) > 1)
363 		done();
364 	errs = 0;
365 /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
366 	ldargs[0] = "ld";
367 	ldargs[1] = "-X";
368 	ldargs[2] = crt0;
369 	for (i = 0; i < argc; i++) {
370 		argp = argv[i];
371 		if (argp[0] != '-') {
372 			switch (getsuf(argp)) {
373 
374 			case 'p':
375 			case 's':
376 				ldargs[ldargx] = savestr(setsuf(argp, 'o'));
377 				break;
378 			default:
379 				ldargs[ldargx] = argp;
380 				break;
381 			}
382 			if (getsuf(ldargs[ldargx]) == 'o')
383 			for (j = 0; j < ldargx; j++)
384 				if (!strcmp(ldargs[j], ldargs[ldargx]))
385 					goto duplicate;
386 			ldargx++;
387 duplicate:
388 			continue;
389 		}
390 		switch (argp[1]) {
391 
392 		case 'i':
393 			while (i+1 < argc && argv[i+1][0] != '-' &&
394 			    getsuf(argv[i+1]) != 'p')
395 				i++;
396 			continue;
397 		case 'd':
398 			if (argp[2] == 0)
399 				continue;
400 			ldargs[ldargx++] = argp;
401 			continue;
402 		case 'o':
403 			ldargs[ldargx++] = argp;
404 			i++;
405 			ldargs[ldargx++] = argv[i];
406 			continue;
407 		case 'l':
408 			if (argp[2])
409 				ldargs[ldargx++] = argp;
410 			continue;
411 		case 't':
412 			i++;
413 			continue;
414 		case 'c':
415 		case 'g':
416 		case 'w':
417 		case 'p':
418 		case 'S':
419 		case 'J':
420 		case 'T':
421 		case 'O':
422 		case 'C':
423 		case 'b':
424 		case 's':
425 		case 'z':
426 			continue;
427 		default:
428 			ldargs[ldargx++] = argp;
429 			continue;
430 		}
431 	}
432 	ldargs[ldargx++] = lpc;
433 	if (gflag)
434 		ldargs[ldargx++] = "-lg";
435 	if (pflag) {
436 		ldargs[ldargx++] = "-lm_p";
437 		ldargs[ldargx++] = "-lc_p";
438 	} else {
439 		ldargs[ldargx++] = "-lm";
440 		ldargs[ldargx++] = "-lc";
441 	}
442 	ldargs[ldargx] = 0;
443 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
444 		unlink(onepso);
445 	done();
446 }
447 
448 dosys(cmd, argv, in, out)
449 	char *cmd, **argv, *in, *out;
450 {
451 	union wait status;
452 	int pid;
453 
454 	if (debug) {
455 		int i;
456 		printf("%s:", cmd);
457 		for (i = 0; argv[i]; i++)
458 			printf(" %s", argv[i]);
459 		if (in)
460 			printf(" <%s", in);
461 		if (out)
462 			printf(" >%s", out);
463 		printf("\n");
464 	}
465 	pid = vfork();
466 	if (pid < 0) {
467 		fprintf(stderr, "pc: No more processes\n");
468 		done();
469 	}
470 	if (pid == 0) {
471 		if (in) {
472 			close(0);
473 			if (open(in, 0) != 0) {
474 				perror(in);
475 				exit(1);
476 			}
477 		}
478 		if (out) {
479 			close(1);
480 			unlink(out);
481 			if (creat(out, 0666) != 1) {
482 				perror(out);
483 				exit(1);
484 			}
485 		}
486 		signal(SIGINT, SIG_DFL);
487 		execv(cmd, argv);
488 		perror(cmd);
489 		exit(1);
490 	}
491 	while (wait(&status) != pid)
492 		;
493 	if (WIFSIGNALED(status)) {
494 		if (status.w_termsig != SIGINT) {
495 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
496 			if (status.w_coredump)
497 				fprintf(stderr, " (core dumped)");
498 			fprintf(stderr, "\n");
499 		}
500 		errs = 100;
501 		done();
502 		/*NOTREACHED*/
503 	}
504 	if (status.w_retcode) {
505 		errs = 1;
506 		remove();
507 	}
508 	return (status.w_retcode);
509 }
510 
511 done()
512 {
513 
514 	remove();
515 	exit(errs);
516 }
517 
518 remove()
519 {
520 
521 	if (tfile[0])
522 		unlink(tfile[0]);
523 	if (tfile[1])
524 		unlink(tfile[1]);
525 }
526 
527 onintr()
528 {
529 
530 	errs = 1;
531 	done();
532 }
533 
534 getsuf(cp)
535 	char *cp;
536 {
537 
538 	if (*cp == 0)
539 		return;
540 	while (cp[1])
541 		cp++;
542 	if (cp[-1] != '.')
543 		return (0);
544 	return (*cp);
545 }
546 
547 char *
548 setsuf(as, ch)
549 	char *as;
550 {
551 	register char *s, *s1;
552 
553 	s = s1 = savestr(as);
554 	while (*s)
555 		if (*s++ == '/')
556 			s1 = s;
557 	s[-1] = ch;
558 	return (s1);
559 }
560 
561 #define	NSAVETAB	512
562 char	*savetab;
563 int	saveleft;
564 
565 char *
566 savestr(cp)
567 	register char *cp;
568 {
569 	register int len;
570 
571 	len = strlen(cp) + 1;
572 	if (len > saveleft) {
573 		saveleft = NSAVETAB;
574 		if (len > saveleft)
575 			saveleft = len;
576 		savetab = (char *)malloc(saveleft);
577 		if (savetab == 0) {
578 			fprintf(stderr, "ran out of memory (savestr)\n");
579 			exit(1);
580 		}
581 	}
582 	strncpy(savetab, cp, len);
583 	cp = savetab;
584 	savetab += len;
585 	return (cp);
586 }
587 
588 suffix(cp)
589 	char *cp;
590 {
591 
592 	if (cp[0] == 0 || cp[1] == 0)
593 		return (0);
594 	while (cp[1])
595 		cp++;
596 	if (cp[-1] == '.')
597 		return (*cp);
598 	return (0);
599 }
600