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