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