144606Sbostic /*-
2*62106Sbostic * Copyright (c) 1990, 1993
3*62106Sbostic * The Regents of the University of California. All rights reserved.
444606Sbostic *
544606Sbostic * %sccs.include.redist.c%
622260Sdist */
722260Sdist
813724Ssam #ifndef lint
9*62106Sbostic static char copyright[] =
10*62106Sbostic "@(#) Copyright (c) 1990, 1993\n\
11*62106Sbostic The Regents of the University of California. All rights reserved.\n";
1244606Sbostic #endif /* not lint */
135054Smckusic
1422260Sdist #ifndef lint
15*62106Sbostic static char sccsid[] = "@(#)pc.c 8.1 (Berkeley) 06/06/93";
1644606Sbostic #endif /* not lint */
1722260Sdist
1831043Ssam #include <sys/param.h>
1944606Sbostic #include <sys/signal.h>
2013724Ssam #include <sys/wait.h>
2144606Sbostic #include <stdio.h>
2244606Sbostic #include "pathnames.h"
23621Sbill
24621Sbill /*
25654Sbill * Pc - front end for Pascal compiler.
26621Sbill */
2744606Sbostic char *pc0 = _PATH_PC0;
2844606Sbostic char *pc1 = _PATH_PC1;
2944606Sbostic char *pc2 = _PATH_PC2;
3044606Sbostic char *c2 = _PATH_C2;
3144606Sbostic char *pc3 = _PATH_PC3;
3244606Sbostic char *ld = _PATH_LD;
3344606Sbostic char *as = _PATH_AS;
34621Sbill char *lpc = "-lpc";
3544606Sbostic char *crt0 = _PATH_CRT0;
3644606Sbostic char *mcrt0 = _PATH_MCRT0;
3744606Sbostic char *gcrt0 = _PATH_GCRT0;
38621Sbill
39621Sbill char *mktemp();
4044606Sbostic char *tmpdir = _PATH_TMP;
4112870Speter char tmp0[MAXPATHLEN], tmp1[MAXPATHLEN];
42621Sbill char *tname[2];
43621Sbill char *tfile[2];
44621Sbill
45621Sbill char *setsuf(), *savestr();
46621Sbill
4712870Speter int Jflag, Sflag, Oflag, Tlflag, cflag, gflag, pflag, wflag, tflag;
48621Sbill int debug;
49621Sbill
50621Sbill #define NARGS 512
51621Sbill int ldargx = 3;
52621Sbill int pc0argx = 3;
53621Sbill char *pc0args[NARGS] = { "pc0", "-o", "XXX" };
54621Sbill char *pc1args[3] = { "pc1", 0, };
55621Sbill char *pc2args[2] = { "pc2", 0 };
56621Sbill char *c2args[4] = { "c2", 0, 0, 0 };
577596Smckusick int pc3argx = 1;
58621Sbill #define pc3args pc0args
59621Sbill #define ldargs pc0args
607596Smckusick /* char *pc3args[NARGS] = { "pc3", 0 }; */
6144606Sbostic /* char *ldargs[NARGS] = { "ld", "-X", _PATH_CRT0, 0, }; */
6212870Speter
6312870Speter /* as -J -t tmpdir -o objfile srcfile \0 */
64908Sbill int asargx;
6512870Speter char *asargs[8] = { "as", 0, };
66621Sbill
677766Smckusick char *mesg[] = {
687766Smckusick 0,
697766Smckusick "Hangup",
707766Smckusick "Interrupt",
717766Smckusick "Quit",
727766Smckusick "Illegal instruction",
737766Smckusick "Trace/BPT trap",
747766Smckusick "IOT trap",
757766Smckusick "EMT trap",
767766Smckusick "Floating exception",
777766Smckusick "Killed",
787766Smckusick "Bus error",
797766Smckusick "Segmentation fault",
807766Smckusick "Bad system call",
817766Smckusick "Broken pipe",
827766Smckusick "Alarm clock",
837766Smckusick "Terminated",
847766Smckusick "Signal 16",
857766Smckusick "Stopped (signal)",
867766Smckusick "Stopped",
877766Smckusick "Continued",
887766Smckusick "Child exited",
897766Smckusick "Stopped (tty input)",
907766Smckusick "Stopped (tty output)",
917766Smckusick "Tty input interrupt",
927766Smckusick "Cputime limit exceeded",
937766Smckusick "Filesize limit exceeded",
947766Smckusick "Signal 26",
957766Smckusick "Signal 27",
967766Smckusick "Signal 28",
977766Smckusick "Signal 29",
987766Smckusick "Signal 30",
997766Smckusick "Signal 31",
1007766Smckusick "Signal 32"
1017766Smckusick };
1027766Smckusick
103621Sbill /*
104621Sbill * If the number of .p arguments (np) is 1, and the number of .o arguments
105621Sbill * (nxo) is 0, and we successfully create an ``a.out'', then we remove
106621Sbill * the one .ps .o file (onepso).
107621Sbill */
108621Sbill int np, nxo;
109621Sbill char *onepso;
110621Sbill int errs;
111621Sbill
112621Sbill int onintr();
113621Sbill
main(argc,argv)114621Sbill main(argc, argv)
115621Sbill int argc;
116621Sbill char **argv;
117621Sbill {
118621Sbill register char *argp;
119621Sbill register int i;
120621Sbill int savargx;
121621Sbill char *t, c;
122621Sbill int j;
123621Sbill
124621Sbill argc--, argv++;
125621Sbill if (argc == 0) {
12644606Sbostic execl(_PATH_CAT, "cat", _PATH_HOWPC);
127621Sbill exit(1);
128621Sbill }
129621Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
130621Sbill signal(SIGINT, onintr);
131621Sbill signal(SIGTERM, onintr);
132621Sbill }
133621Sbill for (i = 0; i < argc; i++) {
134621Sbill argp = argv[i];
135621Sbill if (argp[0] != '-')
136621Sbill continue;
137621Sbill switch (argp[1]) {
138621Sbill
139621Sbill case 'd':
140621Sbill if (argp[2] == 0)
141621Sbill debug++;
142621Sbill continue;
143621Sbill case 'i':
144621Sbill pc0args[pc0argx++] = "-i";
145621Sbill while (i+1 < argc && argv[i+1][0] != '-' &&
146621Sbill getsuf(argv[i+1]) != 'p') {
147621Sbill pc0args[pc0argx++] = argv[i+1];
148621Sbill i++;
149621Sbill }
150621Sbill if (i+1 == argc) {
151621Sbill fprintf(stderr, "pc: bad -i construction\n");
152621Sbill exit(1);
153621Sbill }
154621Sbill continue;
155621Sbill case 'o':
156621Sbill i++;
157621Sbill if (i == argc) {
158621Sbill fprintf(stderr, "pc: -o must specify file\n");
159621Sbill exit(1);
160621Sbill }
161621Sbill c = getsuf(argv[i]);
162621Sbill if (c == 'o' || c == 'p' || c == 'c') {
163621Sbill fprintf(stderr, "pc: -o would overwrite %s\n",
164621Sbill argv[i]);
165621Sbill exit(1);
166621Sbill }
167621Sbill continue;
16812870Speter case 't':
16912870Speter i++;
17012870Speter if (i == argc) {
17112931Speter fprintf(stderr, "pc: -t but no directory\n");
17212870Speter exit(1);
17312870Speter }
17412931Speter if (argp[2] != '\0') {
17512931Speter fprintf(stderr, "pc: bad -t option\n");
17612931Speter exit(1);
17712931Speter }
17812870Speter tmpdir = argv[i];
17912931Speter if (tmpdir[0] == '-') {
18012931Speter fprintf(stderr, "pc: bad -t option\n");
18112931Speter exit(1);
18212931Speter }
18312870Speter tflag = 1;
18412870Speter continue;
185621Sbill case 'O':
186621Sbill Oflag = 1;
187621Sbill continue;
188621Sbill case 'S':
189621Sbill Sflag = 1;
190621Sbill continue;
191908Sbill case 'J':
192908Sbill Jflag = 1;
193908Sbill continue;
194621Sbill case 'T':
195621Sbill switch (argp[2]) {
196621Sbill
197621Sbill case '0':
19844606Sbostic pc0 = _PATH_DPC0;
1993862Smckusic if (argp[3] != '\0') {
2003862Smckusic pc0 = &argp[3];
2013862Smckusic }
202621Sbill continue;
203621Sbill case '1':
20444606Sbostic pc1 = _PATH_DPC1;
2053862Smckusic if (argp[3] != '\0') {
2063862Smckusic pc1 = &argp[3];
2073862Smckusic }
208621Sbill continue;
209621Sbill case '2':
21044606Sbostic pc2 = _PATH_DPC2;
2113862Smckusic if (argp[3] != '\0') {
2123862Smckusic pc2 = &argp[3];
2133862Smckusic }
214621Sbill continue;
215621Sbill case '3':
21644606Sbostic pc3 = _PATH_DPC3;
2173862Smckusic if (argp[3] != '\0') {
2183862Smckusic pc3 = &argp[3];
2193862Smckusic }
220621Sbill continue;
221621Sbill case 'l':
2225054Smckusic Tlflag = 1;
22344606Sbostic lpc = _PATH_DLPC;
2243862Smckusic if (argp[3] != '\0') {
2253862Smckusic lpc = &argp[3];
2263862Smckusic }
227621Sbill continue;
228621Sbill }
229621Sbill continue;
230621Sbill case 'c':
231621Sbill cflag = 1;
232621Sbill continue;
233621Sbill case 'l':
234621Sbill if (argp[2])
235621Sbill continue;
236621Sbill /* fall into ... */
237621Sbill case 'b':
238621Sbill case 's':
239621Sbill case 'z':
240621Sbill case 'C':
241621Sbill pc0args[pc0argx++] = argp;
242621Sbill continue;
2437596Smckusick case 'w':
2447596Smckusick wflag = 1;
2457596Smckusick pc0args[pc0argx++] = argp;
2467596Smckusick continue;
2477596Smckusick case 'g':
2487596Smckusick gflag = 1;
2497596Smckusick pc0args[pc0argx++] = argp;
2507596Smckusick continue;
251621Sbill case 'p':
2525054Smckusic if (argp[2] == 'g')
2535054Smckusic crt0 = gcrt0;
2545054Smckusic else
2555054Smckusic crt0 = mcrt0;
2565054Smckusic if (!Tlflag)
2575054Smckusic lpc = "-lpc_p";
2585054Smckusic pflag = 1;
259654Sbill continue;
260621Sbill }
261621Sbill }
262621Sbill if (gflag && Oflag) {
263621Sbill fprintf(stderr, "pc: warning: -g overrides -O\n");
264621Sbill Oflag = 0;
265621Sbill }
26612870Speter sprintf(tmp0, "%s/%s", tmpdir, "p0XXXXXX");
26712870Speter tname[0] = mktemp(tmp0);
26812870Speter sprintf(tmp1, "%s/%s", tmpdir, "p1XXXXXX");
26912870Speter tname[1] = mktemp(tmp1);
270621Sbill savargx = pc0argx;
271621Sbill for (i = 0; i < argc; i++) {
272621Sbill argp = argv[i];
273621Sbill if (argp[0] == '-')
274621Sbill continue;
2751211Speter if (suffix(argp) == 's') {
2761211Speter asargx = 1;
2771211Speter if (Jflag)
2781211Speter asargs[asargx++] = "-J";
27930092Smckusick # if defined(vax) || defined(tahoe)
28012870Speter if (tflag) {
28112870Speter asargs[asargx++] = "-t";
28212870Speter asargs[asargx++] = tmpdir;
28312870Speter }
28430092Smckusick # endif vax || tahoe
2851211Speter asargs[asargx++] = argp;
2861211Speter asargs[asargx++] = "-o";
2871211Speter tfile[1] = setsuf(argp, 'o');
2881211Speter asargs[asargx++] = tfile[1];
2891211Speter asargs[asargx] = 0;
2901211Speter if (dosys(as, asargs, 0, 0))
2911211Speter continue;
2921211Speter tfile[1] = 0;
2931211Speter continue;
2941211Speter }
295621Sbill if (suffix(argp) != 'p')
296621Sbill continue;
297621Sbill tfile[0] = tname[0];
298621Sbill pc0args[2] = tfile[0];
299621Sbill pc0argx = savargx;
300654Sbill if (pflag)
301654Sbill pc0args[pc0argx++] = "-p";
30212966Smckusick if (Jflag)
30312966Smckusick pc0args[pc0argx++] = "-J";
304621Sbill pc0args[pc0argx++] = argp;
305621Sbill pc0args[pc0argx] = 0;
306621Sbill if (dosys(pc0, pc0args, 0, 0))
307621Sbill continue;
308621Sbill pc1args[1] = tfile[0];
309654Sbill tfile[1] = tname[1];
310621Sbill if (dosys(pc1, pc1args, 0, tfile[1]))
311621Sbill continue;
312621Sbill unlink(tfile[0]);
3132340Smckusic tfile[0] = tname[0];
3142340Smckusic if (Oflag) {
3152340Smckusic if (dosys(c2, c2args, tfile[1], tfile[0]))
3162340Smckusic continue;
3172340Smckusic unlink(tfile[1]);
3182340Smckusic tfile[1] = tfile[0];
3192340Smckusic tfile[0] = tname[1];
3202340Smckusic }
3212340Smckusic if (Sflag)
322654Sbill tfile[0] = setsuf(argp, 's');
323621Sbill if (dosys(pc2, pc2args, tfile[1], tfile[0]))
324621Sbill continue;
325621Sbill unlink(tfile[1]);
326621Sbill tfile[1] = 0;
327654Sbill if (Sflag) {
328654Sbill tfile[0] = 0;
329621Sbill continue;
330654Sbill }
331908Sbill asargx = 1;
332908Sbill if (Jflag)
333908Sbill asargs[asargx++] = "-J";
33430092Smckusick # if defined(vax) || defined(tahoe)
33512870Speter if (tflag) {
33612870Speter asargs[asargx++] = "-t";
33712870Speter asargs[asargx++] = tmpdir;
33812870Speter }
33930092Smckusick # endif vax || tahoe
340908Sbill asargs[asargx++] = tfile[0];
341908Sbill asargs[asargx++] = "-o";
342621Sbill tfile[1] = setsuf(argp, 'o');
343908Sbill asargs[asargx++] = tfile[1];
344908Sbill asargs[asargx] = 0;
345621Sbill if (dosys(as, asargs, 0, 0))
346621Sbill continue;
347621Sbill tfile[1] = 0;
34846313Storek removetemps();
349621Sbill }
350621Sbill if (errs || cflag || Sflag)
351621Sbill done();
3527596Smckusick /* char *pc3args[NARGS] = { "pc3", 0 }; */
353621Sbill pc3args[0] = "pc3";
3547596Smckusick if (wflag)
3557596Smckusick pc3args[pc3argx++] = "-w";
35644606Sbostic pc3args[pc3argx++] = _PATH_PCEXTERN;
357621Sbill for (i = 0; i < argc; i++) {
358621Sbill argp = argv[i];
359621Sbill if (!strcmp(argp, "-o"))
360621Sbill i++;
361621Sbill if (argp[0] == '-')
362621Sbill continue;
363621Sbill switch (getsuf(argp)) {
364621Sbill
365621Sbill case 'o':
366621Sbill pc3args[pc3argx++] = argp;
367621Sbill nxo++;
368621Sbill continue;
3691211Speter case 's':
370621Sbill case 'p':
371621Sbill onepso = pc3args[pc3argx++] =
372621Sbill savestr(setsuf(argp, 'o'));
373621Sbill np++;
374621Sbill continue;
375621Sbill }
376621Sbill }
377621Sbill pc3args[pc3argx] = 0;
3787596Smckusick if (dosys(pc3, pc3args, 0, 0) > 1)
379621Sbill done();
38010672Speter errs = 0;
38144606Sbostic /* char *ldargs[NARGS] = { "ld", "-X", _PATH_CRT0, 0, }; */
382621Sbill ldargs[0] = "ld";
383621Sbill ldargs[1] = "-X";
384654Sbill ldargs[2] = crt0;
385621Sbill for (i = 0; i < argc; i++) {
386621Sbill argp = argv[i];
387621Sbill if (argp[0] != '-') {
388621Sbill switch (getsuf(argp)) {
389621Sbill
390621Sbill case 'p':
3911211Speter case 's':
392621Sbill ldargs[ldargx] = savestr(setsuf(argp, 'o'));
393621Sbill break;
394621Sbill default:
395621Sbill ldargs[ldargx] = argp;
396621Sbill break;
397621Sbill }
398621Sbill if (getsuf(ldargs[ldargx]) == 'o')
399621Sbill for (j = 0; j < ldargx; j++)
400621Sbill if (!strcmp(ldargs[j], ldargs[ldargx]))
401621Sbill goto duplicate;
402621Sbill ldargx++;
403621Sbill duplicate:
404621Sbill continue;
405621Sbill }
406621Sbill switch (argp[1]) {
407621Sbill
408621Sbill case 'i':
409621Sbill while (i+1 < argc && argv[i+1][0] != '-' &&
410621Sbill getsuf(argv[i+1]) != 'p')
411621Sbill i++;
412621Sbill continue;
413621Sbill case 'd':
414621Sbill if (argp[2] == 0)
415621Sbill continue;
416621Sbill ldargs[ldargx++] = argp;
417621Sbill continue;
418621Sbill case 'o':
419621Sbill ldargs[ldargx++] = argp;
420621Sbill i++;
421621Sbill ldargs[ldargx++] = argv[i];
422621Sbill continue;
423621Sbill case 'l':
424621Sbill if (argp[2])
425621Sbill ldargs[ldargx++] = argp;
426621Sbill continue;
42712870Speter case 't':
42812870Speter i++;
42912870Speter continue;
430621Sbill case 'c':
431621Sbill case 'g':
432621Sbill case 'w':
433621Sbill case 'p':
434621Sbill case 'S':
435908Sbill case 'J':
436621Sbill case 'T':
437621Sbill case 'O':
438621Sbill case 'C':
439621Sbill case 'b':
440621Sbill case 's':
441621Sbill case 'z':
442621Sbill continue;
443621Sbill default:
444621Sbill ldargs[ldargx++] = argp;
445621Sbill continue;
446621Sbill }
447621Sbill }
448621Sbill ldargs[ldargx++] = lpc;
449621Sbill if (gflag)
450621Sbill ldargs[ldargx++] = "-lg";
4515054Smckusic if (pflag) {
4525054Smckusic ldargs[ldargx++] = "-lm_p";
4535054Smckusic ldargs[ldargx++] = "-lc_p";
4545054Smckusic } else {
4555054Smckusic ldargs[ldargx++] = "-lm";
4565054Smckusic ldargs[ldargx++] = "-lc";
4575054Smckusic }
458621Sbill ldargs[ldargx] = 0;
459621Sbill if (dosys(ld, ldargs, 0, 0)==0 && np == 1 && nxo == 0)
460621Sbill unlink(onepso);
461621Sbill done();
462621Sbill }
463621Sbill
dosys(cmd,argv,in,out)464621Sbill dosys(cmd, argv, in, out)
465621Sbill char *cmd, **argv, *in, *out;
466621Sbill {
467621Sbill union wait status;
468621Sbill int pid;
469621Sbill
470621Sbill if (debug) {
471621Sbill int i;
472621Sbill printf("%s:", cmd);
473621Sbill for (i = 0; argv[i]; i++)
474621Sbill printf(" %s", argv[i]);
475621Sbill if (in)
476621Sbill printf(" <%s", in);
477621Sbill if (out)
478621Sbill printf(" >%s", out);
479621Sbill printf("\n");
480621Sbill }
48115776Saoki /*
48215776Saoki * warning: vfork doesn't work here, because the call to signal()
48315776Saoki * done by the child process destroys the parent's SIGINT handler.
48415776Saoki */
48515776Saoki pid = fork();
486621Sbill if (pid < 0) {
487621Sbill fprintf(stderr, "pc: No more processes\n");
488621Sbill done();
489621Sbill }
490621Sbill if (pid == 0) {
491621Sbill if (in) {
492621Sbill close(0);
493621Sbill if (open(in, 0) != 0) {
494621Sbill perror(in);
495621Sbill exit(1);
496621Sbill }
497621Sbill }
498621Sbill if (out) {
499621Sbill close(1);
500621Sbill unlink(out);
501621Sbill if (creat(out, 0666) != 1) {
502621Sbill perror(out);
503621Sbill exit(1);
504621Sbill }
505621Sbill }
506621Sbill signal(SIGINT, SIG_DFL);
507621Sbill execv(cmd, argv);
508621Sbill perror(cmd);
509621Sbill exit(1);
510621Sbill }
511621Sbill while (wait(&status) != pid)
512621Sbill ;
513621Sbill if (WIFSIGNALED(status)) {
5147766Smckusick if (status.w_termsig != SIGINT) {
5157766Smckusick fprintf(stderr, "%s: %s", cmd, mesg[status.w_termsig]);
5167766Smckusick if (status.w_coredump)
5177766Smckusick fprintf(stderr, " (core dumped)");
5187766Smckusick fprintf(stderr, "\n");
5197766Smckusick }
520621Sbill errs = 100;
521621Sbill done();
522621Sbill /*NOTREACHED*/
523621Sbill }
524621Sbill if (status.w_retcode) {
525621Sbill errs = 1;
52646313Storek removetemps();
527621Sbill }
528621Sbill return (status.w_retcode);
529621Sbill }
530621Sbill
done()531621Sbill done()
532621Sbill {
533621Sbill
53446313Storek removetemps();
535621Sbill exit(errs);
536621Sbill }
537621Sbill
removetemps()53846313Storek removetemps()
539621Sbill {
540621Sbill
541621Sbill if (tfile[0])
542621Sbill unlink(tfile[0]);
543621Sbill if (tfile[1])
544621Sbill unlink(tfile[1]);
545621Sbill }
546621Sbill
onintr()547621Sbill onintr()
548621Sbill {
549621Sbill
550621Sbill errs = 1;
551621Sbill done();
552621Sbill }
553621Sbill
getsuf(cp)554621Sbill getsuf(cp)
555621Sbill char *cp;
556621Sbill {
557621Sbill
558621Sbill if (*cp == 0)
559621Sbill return;
560621Sbill while (cp[1])
561621Sbill cp++;
562621Sbill if (cp[-1] != '.')
563621Sbill return (0);
564621Sbill return (*cp);
565621Sbill }
566621Sbill
567621Sbill char *
setsuf(as,ch)568654Sbill setsuf(as, ch)
569654Sbill char *as;
57046313Storek int ch;
571621Sbill {
572654Sbill register char *s, *s1;
573621Sbill
574654Sbill s = s1 = savestr(as);
575654Sbill while (*s)
576654Sbill if (*s++ == '/')
577654Sbill s1 = s;
578654Sbill s[-1] = ch;
579654Sbill return (s1);
580621Sbill }
581621Sbill
582621Sbill #define NSAVETAB 512
583621Sbill char *savetab;
584621Sbill int saveleft;
585621Sbill
586621Sbill char *
savestr(cp)587621Sbill savestr(cp)
588621Sbill register char *cp;
589621Sbill {
590621Sbill register int len;
591621Sbill
592621Sbill len = strlen(cp) + 1;
593621Sbill if (len > saveleft) {
594621Sbill saveleft = NSAVETAB;
595621Sbill if (len > saveleft)
596621Sbill saveleft = len;
597621Sbill savetab = (char *)malloc(saveleft);
598621Sbill if (savetab == 0) {
599621Sbill fprintf(stderr, "ran out of memory (savestr)\n");
600621Sbill exit(1);
601621Sbill }
602621Sbill }
603621Sbill strncpy(savetab, cp, len);
604621Sbill cp = savetab;
605621Sbill savetab += len;
606621Sbill return (cp);
607621Sbill }
608621Sbill
suffix(cp)609621Sbill suffix(cp)
610621Sbill char *cp;
611621Sbill {
612621Sbill
613621Sbill if (cp[0] == 0 || cp[1] == 0)
614621Sbill return (0);
615621Sbill while (cp[1])
616621Sbill cp++;
617621Sbill if (cp[-1] == '.')
618621Sbill return (*cp);
619621Sbill return (0);
620621Sbill }
621