xref: /csrg-svn/usr.bin/pascal/pc/pc.c (revision 12870)
1 static	char sccsid[] = "@(#)pc.c 3.22 06/01/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 			tmpdir = argv[i];
159 			tflag = 1;
160 			continue;
161 		case 'O':
162 			Oflag = 1;
163 			continue;
164 		case 'S':
165 			Sflag = 1;
166 			continue;
167 		case 'J':
168 			Jflag = 1;
169 			continue;
170 		case 'T':
171 			switch (argp[2]) {
172 
173 			case '0':
174 				pc0 = "/usr/src/ucb/pascal/pc0/a.out";
175 				if (argp[3] != '\0') {
176 					pc0 = &argp[3];
177 				}
178 				continue;
179 			case '1':
180 				pc1 = "/usr/src/lib/pcc/fort";
181 				if (argp[3] != '\0') {
182 					pc1 = &argp[3];
183 				}
184 				continue;
185 			case '2':
186 				pc2 = "/usr/src/ucb/pascal/utilities/pc2";
187 				if (argp[3] != '\0') {
188 					pc2 = &argp[3];
189 				}
190 				continue;
191 			case '3':
192 				pc3 = "/usr/src/ucb/pascal/utilities/pc3";
193 				if (argp[3] != '\0') {
194 					pc3 = &argp[3];
195 				}
196 				continue;
197 			case 'l':
198 				Tlflag = 1;
199 				lpc = "/usr/src/usr.lib/libpc/libpc";
200 				if (argp[3] != '\0') {
201 					lpc = &argp[3];
202 				}
203 				continue;
204 			}
205 			continue;
206 		case 'c':
207 			cflag = 1;
208 			continue;
209 		case 'l':
210 			if (argp[2])
211 				continue;
212 			/* fall into ... */
213 		case 'b':
214 		case 's':
215 		case 'z':
216 		case 'C':
217 			pc0args[pc0argx++] = argp;
218 			continue;
219 		case 'w':
220 			wflag = 1;
221 			pc0args[pc0argx++] = argp;
222 			continue;
223 		case 'g':
224 			gflag = 1;
225 			pc0args[pc0argx++] = argp;
226 			continue;
227 		case 'p':
228 			if (argp[2] == 'g')
229 				crt0 = gcrt0;
230 			else
231 				crt0 = mcrt0;
232 			if (!Tlflag)
233 				lpc = "-lpc_p";
234 			pflag = 1;
235 			continue;
236 		}
237 	}
238 	if (gflag && Oflag) {
239 		fprintf(stderr, "pc: warning: -g overrides -O\n");
240 		Oflag = 0;
241 	}
242 	sprintf(tmp0, "%s/%s", tmpdir, "p0XXXXXX");
243 	tname[0] = mktemp(tmp0);
244 	sprintf(tmp1, "%s/%s", tmpdir, "p1XXXXXX");
245 	tname[1] = mktemp(tmp1);
246 	savargx = pc0argx;
247 	for (i = 0; i < argc; i++) {
248 		argp = argv[i];
249 		if (argp[0] == '-')
250 			continue;
251 		if (suffix(argp) == 's') {
252 			asargx = 1;
253 			if (Jflag)
254 				asargs[asargx++] = "-J";
255 #			ifdef vax
256 				if (tflag) {
257 					asargs[asargx++] = "-t";
258 					asargs[asargx++] = tmpdir;
259 				}
260 #			endif vax
261 			asargs[asargx++] = argp;
262 			asargs[asargx++] = "-o";
263 			tfile[1] = setsuf(argp, 'o');
264 			asargs[asargx++] = tfile[1];
265 			asargs[asargx] = 0;
266 			if (dosys(as, asargs, 0, 0))
267 				continue;
268 			tfile[1] = 0;
269 			continue;
270 		}
271 		if (suffix(argp) != 'p')
272 			continue;
273 		tfile[0] = tname[0];
274 		pc0args[2] = tfile[0];
275 		pc0argx = savargx;
276 		if (pflag)
277 			pc0args[pc0argx++] = "-p";
278 		pc0args[pc0argx++] = argp;
279 		pc0args[pc0argx] = 0;
280 		if (dosys(pc0, pc0args, 0, 0))
281 			continue;
282 		pc1args[1] = tfile[0];
283 		tfile[1] = tname[1];
284 		if (dosys(pc1, pc1args, 0, tfile[1]))
285 			continue;
286 		unlink(tfile[0]);
287 		tfile[0] = tname[0];
288 		if (Oflag) {
289 			if (dosys(c2, c2args, tfile[1], tfile[0]))
290 				continue;
291 			unlink(tfile[1]);
292 			tfile[1] = tfile[0];
293 			tfile[0] = tname[1];
294 		}
295 		if (Sflag)
296 			tfile[0] = setsuf(argp, 's');
297 		if (dosys(pc2, pc2args, tfile[1], tfile[0]))
298 			continue;
299 		unlink(tfile[1]);
300 		tfile[1] = 0;
301 		if (Sflag) {
302 			tfile[0] = 0;
303 			continue;
304 		}
305 		asargx = 1;
306 		if (Jflag)
307 			asargs[asargx++] = "-J";
308 #		ifdef vax
309 			if (tflag) {
310 				asargs[asargx++] = "-t";
311 				asargs[asargx++] = tmpdir;
312 			}
313 #		endif vax
314 		asargs[asargx++] = tfile[0];
315 		asargs[asargx++] = "-o";
316 		tfile[1] = setsuf(argp, 'o');
317 		asargs[asargx++] = tfile[1];
318 		asargs[asargx] = 0;
319 		if (dosys(as, asargs, 0, 0))
320 			continue;
321 		tfile[1] = 0;
322 		remove();
323 	}
324 	if (errs || cflag || Sflag)
325 		done();
326 /* char	*pc3args[NARGS] =	{ "pc3", 0 }; */
327 	pc3args[0] = "pc3";
328 	if (wflag)
329 		pc3args[pc3argx++] = "-w";
330 	pc3args[pc3argx++] = "/usr/lib/pcexterns.o";
331 	for (i = 0; i < argc; i++) {
332 		argp = argv[i];
333 		if (!strcmp(argp, "-o"))
334 			i++;
335 		if (argp[0] == '-')
336 			continue;
337 		switch (getsuf(argp)) {
338 
339 		case 'o':
340 			pc3args[pc3argx++] = argp;
341 			nxo++;
342 			continue;
343 		case 's':
344 		case 'p':
345 			onepso = pc3args[pc3argx++] =
346 			    savestr(setsuf(argp, 'o'));
347 			np++;
348 			continue;
349 		}
350 	}
351 	pc3args[pc3argx] = 0;
352 	if (dosys(pc3, pc3args, 0, 0) > 1)
353 		done();
354 	errs = 0;
355 /* char	*ldargs[NARGS] =	{ "ld", "-X", "/lib/crt0.o", 0, }; */
356 	ldargs[0] = "ld";
357 	ldargs[1] = "-X";
358 	ldargs[2] = crt0;
359 	for (i = 0; i < argc; i++) {
360 		argp = argv[i];
361 		if (argp[0] != '-') {
362 			switch (getsuf(argp)) {
363 
364 			case 'p':
365 			case 's':
366 				ldargs[ldargx] = savestr(setsuf(argp, 'o'));
367 				break;
368 			default:
369 				ldargs[ldargx] = argp;
370 				break;
371 			}
372 			if (getsuf(ldargs[ldargx]) == 'o')
373 			for (j = 0; j < ldargx; j++)
374 				if (!strcmp(ldargs[j], ldargs[ldargx]))
375 					goto duplicate;
376 			ldargx++;
377 duplicate:
378 			continue;
379 		}
380 		switch (argp[1]) {
381 
382 		case 'i':
383 			while (i+1 < argc && argv[i+1][0] != '-' &&
384 			    getsuf(argv[i+1]) != 'p')
385 				i++;
386 			continue;
387 		case 'd':
388 			if (argp[2] == 0)
389 				continue;
390 			ldargs[ldargx++] = argp;
391 			continue;
392 		case 'o':
393 			ldargs[ldargx++] = argp;
394 			i++;
395 			ldargs[ldargx++] = argv[i];
396 			continue;
397 		case 'l':
398 			if (argp[2])
399 				ldargs[ldargx++] = argp;
400 			continue;
401 		case 't':
402 			i++;
403 			continue;
404 		case 'c':
405 		case 'g':
406 		case 'w':
407 		case 'p':
408 		case 'S':
409 		case 'J':
410 		case 'T':
411 		case 'O':
412 		case 'C':
413 		case 'b':
414 		case 's':
415 		case 'z':
416 			continue;
417 		default:
418 			ldargs[ldargx++] = argp;
419 			continue;
420 		}
421 	}
422 	ldargs[ldargx++] = lpc;
423 	if (gflag)
424 		ldargs[ldargx++] = "-lg";
425 	if (pflag) {
426 		ldargs[ldargx++] = "-lm_p";
427 		ldargs[ldargx++] = "-lc_p";
428 	} else {
429 		ldargs[ldargx++] = "-lm";
430 		ldargs[ldargx++] = "-lc";
431 	}
432 	ldargs[ldargx] = 0;
433 	if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
434 		unlink(onepso);
435 	done();
436 }
437 
438 dosys(cmd, argv, in, out)
439 	char *cmd, **argv, *in, *out;
440 {
441 	union wait status;
442 	int pid;
443 
444 	if (debug) {
445 		int i;
446 		printf("%s:", cmd);
447 		for (i = 0; argv[i]; i++)
448 			printf(" %s", argv[i]);
449 		if (in)
450 			printf(" <%s", in);
451 		if (out)
452 			printf(" >%s", out);
453 		printf("\n");
454 	}
455 	pid = vfork();
456 	if (pid < 0) {
457 		fprintf(stderr, "pc: No more processes\n");
458 		done();
459 	}
460 	if (pid == 0) {
461 		if (in) {
462 			close(0);
463 			if (open(in, 0) != 0) {
464 				perror(in);
465 				exit(1);
466 			}
467 		}
468 		if (out) {
469 			close(1);
470 			unlink(out);
471 			if (creat(out, 0666) != 1) {
472 				perror(out);
473 				exit(1);
474 			}
475 		}
476 		signal(SIGINT, SIG_DFL);
477 		execv(cmd, argv);
478 		perror(cmd);
479 		exit(1);
480 	}
481 	while (wait(&status) != pid)
482 		;
483 	if (WIFSIGNALED(status)) {
484 		if (status.w_termsig != SIGINT) {
485 			fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
486 			if (status.w_coredump)
487 				fprintf(stderr, " (core dumped)");
488 			fprintf(stderr, "\n");
489 		}
490 		errs = 100;
491 		done();
492 		/*NOTREACHED*/
493 	}
494 	if (status.w_retcode) {
495 		errs = 1;
496 		remove();
497 	}
498 	return (status.w_retcode);
499 }
500 
501 done()
502 {
503 
504 	remove();
505 	exit(errs);
506 }
507 
508 remove()
509 {
510 
511 	if (tfile[0])
512 		unlink(tfile[0]);
513 	if (tfile[1])
514 		unlink(tfile[1]);
515 }
516 
517 onintr()
518 {
519 
520 	errs = 1;
521 	done();
522 }
523 
524 getsuf(cp)
525 	char *cp;
526 {
527 
528 	if (*cp == 0)
529 		return;
530 	while (cp[1])
531 		cp++;
532 	if (cp[-1] != '.')
533 		return (0);
534 	return (*cp);
535 }
536 
537 char *
538 setsuf(as, ch)
539 	char *as;
540 {
541 	register char *s, *s1;
542 
543 	s = s1 = savestr(as);
544 	while (*s)
545 		if (*s++ == '/')
546 			s1 = s;
547 	s[-1] = ch;
548 	return (s1);
549 }
550 
551 #define	NSAVETAB	512
552 char	*savetab;
553 int	saveleft;
554 
555 char *
556 savestr(cp)
557 	register char *cp;
558 {
559 	register int len;
560 
561 	len = strlen(cp) + 1;
562 	if (len > saveleft) {
563 		saveleft = NSAVETAB;
564 		if (len > saveleft)
565 			saveleft = len;
566 		savetab = (char *)malloc(saveleft);
567 		if (savetab == 0) {
568 			fprintf(stderr, "ran out of memory (savestr)\n");
569 			exit(1);
570 		}
571 	}
572 	strncpy(savetab, cp, len);
573 	cp = savetab;
574 	savetab += len;
575 	return (cp);
576 }
577 
578 suffix(cp)
579 	char *cp;
580 {
581 
582 	if (cp[0] == 0 || cp[1] == 0)
583 		return (0);
584 	while (cp[1])
585 		cp++;
586 	if (cp[-1] == '.')
587 		return (*cp);
588 	return (0);
589 }
590