forget difference between big and small commands - obsolete with vm.
[minix.git] / commands / i86 / cc.c
blobf753232dbcbd2accd29640bdee5b9faf7fe400e1
1 /* Driver for Minix compilers.
2 Written june 1987 by Ceriel J.H. Jacobs, partly derived from old
3 cc-driver, written by Erik Baalbergen.
4 This driver is mostly table-driven, the table being in the form of
5 some global initialized structures.
6 */
7 /* $Header$ */
9 #include <sys/types.h>
10 #include <sys/wait.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <fcntl.h>
16 #include <unistd.h>
18 /* Paths. (Executables in /usr are first tried with /usr stripped off.) */
19 #define SHELL "/bin/sh"
20 #define PP "/usr/lib/ncpp"
21 #define IRREL "/usr/lib/irrel"
22 #define CEM "/usr/lib/ncem"
23 #define M2EM "/usr/lib/nm2em"
24 #define ENCODE "/usr/lib/em_encode"
25 #define OPT "/usr/lib/nopt"
26 #define CG "/usr/lib/ncg"
27 #define AS "/usr/lib/as"
28 #define LD "/usr/lib/ld"
29 #define CV "/usr/lib/cv"
30 #define LIBDIR "/usr/lib"
31 #define CRT "/usr/lib/ncrtso.o"
32 #define PEM "/usr/lib/npem"
33 #define PRT "/usr/lib/nprtso.o"
34 #define M2RT "/usr/lib/nm2rtso.o"
35 #define LIBC "/usr/lib/libd.a", "/usr/lib/libc.a"
36 #define LIBP "/usr/lib/libp.a", "/usr/lib/libc.a"
37 #define LIBM2 "/usr/lib/libm2.a", "/usr/lib/libc.a"
38 #define END "/usr/lib/libe.a", "/usr/lib/end.a"
39 #define M2DEF "-I/usr/lib/m2"
42 /* every pass that this program knows about has associated with it
43 a structure, containing such information as its name, where it
44 resides, the flags it accepts, and the like.
46 struct passinfo {
47 char *p_name; /* name of this pass */
48 char *p_path; /* where is it */
49 char *p_from; /* suffix of source (comma-separated list) */
50 char *p_to; /* suffix of destination */
51 char *p_acceptflags; /* comma separated list; format:
52 flag
53 flag*
54 flag=xxx
55 flag*=xxx[*]
56 where a star matches a, possibly empty,
57 string
59 int p_flags;
60 #define INPUT 01 /* needs input file as argument */
61 #define OUTPUT 02 /* needs output file as argument */
62 #define LOADER 04 /* this pass is the loader */
63 #define STDIN 010 /* reads from standard input */
64 #define STDOUT 020 /* writes on standard output */
65 #define NOCLEAN 040 /* do not remove target if this pass fails */
66 #define O_OUTPUT 0100 /* -o outputfile, hack for as */
67 #define PREPALWAYS 0200 /* always to be preprocessed */
68 #define PREPCOND 0400 /* preprocessed when starting with '#' */
69 #define PREPNOLN 01000 /* suppress line number info (cpp -P) */
72 #define MAXHEAD 10
73 #define MAXTAIL 5
74 #define MAXPASS 7
76 /* Every language handled by this program has a "compile" structure
77 associated with it, describing the start-suffix, how the driver for
78 this language is called, which passes must be called, which flags
79 and arguments must be passed to these passes, etc.
80 The language is determined by the suffix of the argument program.
81 However, if this suffix does not determine a language (DEFLANG),
82 the callname is used.
83 Notice that the 's' suffix does not determine a language, because
84 the input file could have been derived from f.i. a C-program.
85 So, if you use "cc x.s", the C-runtime system will be used, but if
86 you use "as x.s", it will not.
88 struct compile {
89 char *c_suffix; /* starting suffix of this list of passes */
90 char *c_callname; /* affects runtime system loaded with program */
91 struct pass {
92 char *pp_name; /* name of the pass */
93 char *pp_head[MAXHEAD]; /* args in front of filename */
94 char *pp_tail[MAXTAIL]; /* args after filename */
95 } c_passes[MAXPASS];
96 int c_flags;
97 #define DEFLANG 010 /* this suffix determines a language */
100 struct passinfo passinfo[] = {
101 { "cpp", PP, "CPP", "i", "wo=o,I*,D*,U*,P", INPUT|STDOUT },
102 { "irrel", IRREL, "i", "i", "m", INPUT},
103 { "cem", CEM, "i,c", "k", "m=o,p,wa=a,wo=o,ws=s,w,T*", INPUT|OUTPUT|PREPALWAYS },
104 { "pc", PEM, "i,p", "k", "n=L,w,a,A,R", INPUT|OUTPUT|PREPCOND },
105 { "m2", M2EM, "i,mod", "k", "n=L,w*,A,R,W*,3,I*", INPUT|OUTPUT|PREPCOND },
106 { "encode", ENCODE, "i,e", "k", "", INPUT|STDOUT|PREPCOND|PREPNOLN },
107 { "opt", OPT, "k", "m", "", STDIN|STDOUT },
108 { "cg", CG, "m", "s", "O=p4", INPUT|OUTPUT },
109 { "as", AS, "i,s", "o", "T*", INPUT|O_OUTPUT|PREPCOND },
110 { "ld", LD, "o", "out", "i,s", INPUT|LOADER }, /* changed */
111 { "cv", CV, "out", 0, "", INPUT|OUTPUT|NOCLEAN }, /* must come after loader */
112 { 0}
115 #define PREP_FLAGS "-D_EM_WSIZE=2", "-D_EM_PSIZE=2", "-D_EM_SSIZE=2", \
116 "-D_EM_LSIZE=4", "-D_EM_FSIZE=4", "-D_EM_DSIZE=8", \
117 "-D__ACK__", "-D__minix", "-D__i86"
119 struct pass preprocessor = { "cpp",
120 { PREP_FLAGS }
121 , {0}
124 struct pass prepnoln = { "cpp",
125 { PREP_FLAGS, "-P" }
126 , {0}
129 struct pass irrel = { "irrel",
133 /* The "*" in the arguments for the loader indicates the place where the
134 * fp-emulation library should come.
136 struct compile passes[] = {
137 { "c", "cc",
138 { { "cem", {"-L"}, {0} }, /* changed */
139 { "opt", {0}, {0} },
140 { "cg", {0}, {0} },
141 { "as", {"-"}, {0} },
142 { "ld", {CRT}, /* changed */
143 {LIBC, "*", END}},
144 { "cv", {0}, {0} }
146 DEFLANG
148 { "p", "pc",
149 { { "pc", {0}, {0} },
150 { "opt", {0}, {0} },
151 { "cg", {0}, {0} },
152 { "as", {"-"}, {0} },
153 { "ld", {PRT},
154 {LIBP,
155 "*", END}},
156 { "cv", {0}, {0} }
158 DEFLANG
160 { "mod", "m2",
161 { { "m2", {M2DEF}, {0} },
162 { "opt", {0}, {0} },
163 { "cg", {0}, {0} },
164 { "as", {"-"}, {0} },
165 { "ld", {M2RT},
166 {LIBM2,
167 "*", END}},
168 { "cv", {0}, {0} }
170 DEFLANG
172 { "e", "encode",
173 { { "encode", {0}, {0}},
174 { "opt", {0}, {0} },
175 { "cg", {0}, {0} },
176 { "as", {"-"}, {0} },
177 { "ld", {0}, {"*", END}},
178 { "cv", {0}, {0} }
180 DEFLANG
182 { "s", "as",
183 { { "as", {0}, {0}}
187 { "CPP", "cpp",
188 { { "cpp", {PREP_FLAGS}, {0}}
190 DEFLANG
192 { 0},
195 #define MAXARGC 150 /* maximum number of arguments allowed in a list */
196 #define USTR_SIZE 64 /* maximum length of string variable */
198 typedef char USTRING[USTR_SIZE];
200 struct arglist {
201 int al_argc;
202 char *al_argv[MAXARGC];
205 struct arglist CALLVEC;
207 int kids = -1;
209 char *o_FILE = "a.out"; /* default name for executable file */
211 #define init(a) ((a)->al_argc = 1)
212 #define cleanup(str) (str && remove(str))
214 char *ProgCall = 0;
216 int RET_CODE = 0;
218 char *stopsuffix;
219 int v_flag = 0;
220 int t_flag = 0;
221 int noexec = 0;
222 int fp_lib = 1;
223 int E_flag = 0;
224 int i_flag = 1;
227 USTRING curfil;
228 USTRING newfil;
229 struct arglist SRCFILES;
230 struct arglist LDIRS;
231 struct arglist LDFILES;
232 struct arglist GEN_LDFILES;
233 struct arglist FLAGS;
235 char *tmpdir = "/tmp";
236 char tmpname[64];
238 struct compile *compbase;
239 struct pass *loader;
240 struct passinfo *loaderinfo;
241 char *source;
242 int maxLlen;
244 _PROTOTYPE(char *library, (char *nm ));
245 _PROTOTYPE(void trapcc, (int sig ));
246 _PROTOTYPE(int main, (int argc, char *argv []));
247 _PROTOTYPE(int remove, (char *str ));
248 _PROTOTYPE(char *alloc, (unsigned u ));
249 _PROTOTYPE(int append, (struct arglist *al, char *arg ));
250 _PROTOTYPE(int concat, (struct arglist *al1, struct arglist *al2 ));
251 _PROTOTYPE(char *mkstr, (char *dst, char *arg1, char *arg2, char *arg3 ));
252 _PROTOTYPE(int basename, (char *str, char *dst ));
253 _PROTOTYPE(char *extension, (char *fln ));
254 _PROTOTYPE(int runvec, (struct arglist *vec, struct passinfo *pass, char *in, char *out ));
255 _PROTOTYPE(int prnum, (unsigned x ));
256 _PROTOTYPE(int prs, (char *str ));
257 _PROTOTYPE(int panic, (char *str ));
258 _PROTOTYPE(int pr_vec, (struct arglist *vec ));
259 _PROTOTYPE(int ex_vec, (struct arglist *vec ));
260 _PROTOTYPE(int mktempname, (char *nm ));
261 _PROTOTYPE(int mkbase, (void));
262 _PROTOTYPE(int mkloader, (void));
263 _PROTOTYPE(int needsprep, (char *name ));
264 _PROTOTYPE(int cfile, (char *name ));
265 _PROTOTYPE(char *apply, (struct passinfo *pinf, struct compile *cp, char *name, int passindex, int noremove, int first, char *resultname ));
266 _PROTOTYPE(int applicable, (struct passinfo *pinf, char *suffix ));
267 _PROTOTYPE(char *process, (char *name, int noremove ));
268 _PROTOTYPE(int mkvec, (struct arglist *call, char *in, char *out, struct pass *pass, struct passinfo *pinf ));
269 _PROTOTYPE(int callld, (struct arglist *in, char *out, struct pass *pass, struct passinfo *pinf ));
270 _PROTOTYPE(int clean, (struct arglist *c ));
271 _PROTOTYPE(int scanflags, (struct arglist *call, struct passinfo *pinf ));
275 char *
276 library(nm)
277 char *nm;
279 static char f[512];
280 int Lcount;
282 for (Lcount = 0; Lcount < LDIRS.al_argc; Lcount++) {
283 mkstr(f, LDIRS.al_argv[Lcount], "/lib", nm);
284 strcat(f, ".a");
285 if (access(f, 0) != 0) {
286 f[strlen(f)-1] = 'a';
287 if (access(f, 0) != 0) continue;
289 return f;
291 mkstr(f, LIBDIR, "/lib", nm);
292 strcat(f, ".a");
293 if (access(f, 0) != 0) {
294 int i = strlen(f) - 1;
295 f[i] = 'a';
296 if (access(f, 0) != 0) f[i] = 'A';
298 return f;
301 void trapcc(sig)
302 int sig;
304 signal(sig, SIG_IGN);
305 if (kids != -1) kill(kids, sig);
306 cleanup(newfil);
307 cleanup(curfil);
308 exit(1);
311 main(argc, argv)
312 char *argv[];
314 char *str;
315 char **argvec;
316 int count;
317 char *file;
319 maxLlen = strlen(LIBDIR);
320 ProgCall = *argv++;
322 mkbase();
324 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
325 signal(SIGHUP, trapcc);
326 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
327 signal(SIGINT, trapcc);
328 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
329 signal(SIGQUIT, trapcc);
330 while (--argc > 0) {
331 if (*(str = *argv++) != '-' || str[1] == 0) {
332 append(&SRCFILES, str);
333 continue;
336 if (strcmp(str, "-com") == 0) {
337 i_flag = 0;
338 } else
339 if (strcmp(str, "-sep") == 0) {
340 i_flag = 1;
341 } else {
342 switch (str[1]) {
344 case 'c':
345 stopsuffix = "o";
346 if (str[2] == '.') stopsuffix = str + 3;
347 break;
348 case 'f':
349 fp_lib = (strcmp(str+2, "hard") != 0);
350 break;
351 case 'F':
352 case 'W':
353 /* Ignore. */
354 break;
355 case 'L':
356 append(&LDIRS, &str[2]);
357 count = strlen(&str[2]);
358 if (count > maxLlen) maxLlen = count;
359 break;
360 case 'l':
361 append(&SRCFILES, library(&str[2]));
362 break;
363 case 'm':
364 /* Use -m, ignore -mxxx. */
365 if (str[2] == 0) append(&FLAGS, str);
366 break;
367 case 'o':
368 if (argc-- >= 0)
369 o_FILE = *argv++;
370 break;
371 case 'S':
372 stopsuffix = "s";
373 break;
374 case 'E':
375 E_flag = 1;
376 stopsuffix = "i";
377 break;
378 case 'P':
379 stopsuffix = "i";
380 append(&FLAGS, str);
381 break;
382 case 'v':
383 v_flag++;
384 if (str[2] == 'n')
385 noexec = 1;
386 break;
387 case 't':
388 /* save temporaries */
389 t_flag++;
390 break;
391 case '.':
392 if (str[2] == 'o') {
393 /* no runtime start-off */
394 loader->pp_head[0] = 0;
396 break;
397 case 'i':
398 i_flag++;
399 break;
400 case 'T':
401 tmpdir = &str[2];
402 /*FALLTHROUGH*/
403 default:
404 append(&FLAGS, str);
410 if (i_flag) append(&FLAGS, "-i");
412 mktempname(tmpname);
414 count = SRCFILES.al_argc;
415 argvec = &(SRCFILES.al_argv[0]);
417 while (count-- > 0) {
419 file = *argvec++;
420 source = file;
422 file = process(file, 1);
424 if (file && ! stopsuffix) append(&LDFILES, file);
427 clean(&SRCFILES);
429 /* loader ... */
430 if (RET_CODE == 0 && LDFILES.al_argc > 0) {
431 register struct passinfo *pp = passinfo;
433 while (!(pp->p_flags & LOADER)) pp++;
434 mkstr(newfil, tmpname, pp->p_to, "");
435 callld(&LDFILES, !((pp+1)->p_name) ? o_FILE : newfil, loader, pp);
436 if (RET_CODE == 0) {
437 register int i = GEN_LDFILES.al_argc;
439 while (i-- > 0) {
440 remove(GEN_LDFILES.al_argv[i]);
441 free(GEN_LDFILES.al_argv[i]);
443 if ((++pp)->p_name) {
444 process(newfil, 0);
448 exit(RET_CODE);
451 remove(str)
452 char *str;
454 if (t_flag)
455 return;
456 if (v_flag) {
457 prs("rm ");
458 prs(str);
459 prs("\n");
461 if (noexec)
462 return;
463 unlink(str);
466 char *
467 alloc(u)
468 unsigned u;
470 register char *p = malloc(u);
472 if (p == 0) panic("no space\n");
473 return p;
476 append(al, arg)
477 struct arglist *al;
478 char *arg;
480 char *a = alloc((unsigned) (strlen(arg) + 1));
482 strcpy(a, arg);
483 if (al->al_argc >= MAXARGC)
484 panic("argument list overflow\n");
485 al->al_argv[(al->al_argc)++] = a;
488 concat(al1, al2)
489 struct arglist *al1, *al2;
491 register i = al2->al_argc;
492 register char **p = &(al1->al_argv[al1->al_argc]);
493 register char **q = &(al2->al_argv[0]);
495 if ((al1->al_argc += i) >= MAXARGC)
496 panic("argument list overflow\n");
497 while (i-- > 0)
498 *p++ = *q++;
501 char *
502 mkstr(dst, arg1, arg2, arg3)
503 char *dst, *arg1, *arg2, *arg3;
505 register char *p;
506 register char *q = dst;
508 p = arg1;
509 while (*q++ = *p++);
510 q--;
511 p = arg2;
512 while (*q++ = *p++);
513 q--;
514 p = arg3;
515 while (*q++ = *p++);
516 q--;
517 return dst;
520 basename(str, dst)
521 char *str;
522 register char *dst;
524 register char *p1 = str;
525 register char *p2 = p1;
527 while (*p1)
528 if (*p1++ == '/')
529 p2 = p1;
530 p1--;
531 while (*p1 != '.' && p1 > p2) p1--;
532 if (*p1 == '.') {
533 *p1 = '\0';
534 while (*dst++ = *p2++);
535 *p1 = '.';
537 else
538 while (*dst++ = *p2++);
541 char *
542 extension(fln)
543 char *fln;
545 register char *fn = fln;
547 while (*fn) fn++;
548 while (fn > fln && *fn != '.') fn--;
549 if (fn != fln) return fn+1;
550 return (char *)0;
553 runvec(vec, pass, in, out)
554 struct arglist *vec;
555 struct passinfo *pass;
556 char *in, *out;
558 int pid, status;
559 int shifted = 0;
561 if (
562 strncmp(vec->al_argv[1], "/usr/", 5) == 0
564 access(vec->al_argv[1] + 4, 1) == 0
566 vec->al_argv[1] += 4;
567 shifted = 1;
570 if (v_flag) {
571 pr_vec(vec);
572 if (pass->p_flags & STDIN) {
573 prs(" <");
574 prs(in);
576 if (pass->p_flags & STDOUT && !E_flag) {
577 prs(" >");
578 prs(out);
580 prs("\n");
582 if (noexec) {
583 if (shifted) vec->al_argv[1] -= 4;
584 clean(vec);
585 return 1;
587 if ((pid = fork()) == 0) { /* start up the process */
588 if (pass->p_flags & STDIN && strcmp(in, "-") != 0) {
589 /* redirect standard input */
590 close(0);
591 if (open(in, 0) != 0)
592 panic("cannot open input file\n");
594 if (pass->p_flags & STDOUT && !E_flag) {
595 /* redirect standard output */
596 close(1);
597 if (creat(out, 0666) != 1)
598 panic("cannot create output file\n");
600 ex_vec(vec);
602 if (pid == -1)
603 panic("no more processes\n");
604 kids = pid;
605 wait(&status);
606 if (status) switch(status & 0177) {
607 case SIGHUP:
608 case SIGINT:
609 case SIGQUIT:
610 case SIGTERM:
611 case 0:
612 break;
613 default:
614 if (E_flag && (status & 0177) == SIGPIPE) break;
615 prs(vec->al_argv[1]);
616 prs(" died with signal ");
617 prnum(status & 0177);
618 prs("\n");
620 if (shifted) vec->al_argv[1] -= 4;
621 clean(vec);
622 kids = -1;
623 return status ? ((RET_CODE = 1), 0) : 1;
626 prnum(x)
627 register unsigned x;
629 static char numbuf[8]; /* though it prints at most 3 characters */
630 register char *cp = numbuf + sizeof(numbuf) - 1;
632 *cp = '\0';
633 while (x >= 10) {
634 *--cp = (x % 10) + '0';
635 x /= 10;
637 *--cp = x + '0';
638 prs(cp);
642 prs(str)
643 char *str;
645 if (str && *str)
646 write(2, str, strlen(str));
649 panic(str)
650 char *str;
652 prs(str);
653 trapcc(SIGINT);
656 pr_vec(vec)
657 register struct arglist *vec;
659 register char **ap = &vec->al_argv[1];
661 vec->al_argv[vec->al_argc] = 0;
662 prs(*ap);
663 while (*++ap) {
664 prs(" ");
665 if (strlen(*ap))
666 prs(*ap);
667 else
668 prs("(empty)");
672 ex_vec(vec)
673 register struct arglist *vec;
675 extern int errno;
677 vec->al_argv[vec->al_argc] = 0;
678 execv(vec->al_argv[1], &(vec->al_argv[1]));
679 if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
680 vec->al_argv[0] = SHELL;
681 execv(SHELL, &(vec->al_argv[0]));
683 if (access(vec->al_argv[1], 1) == 0) {
684 /* File is executable. */
685 prs("Cannot execute ");
686 prs(vec->al_argv[1]);
687 prs(". Not enough memory.\n");
688 prs("Reduce the memory use of your system and try again\n");
689 } else {
690 prs(vec->al_argv[1]);
691 prs(" is not executable\n");
693 exit(1);
696 mktempname(nm)
697 register char *nm;
699 register int i;
700 register int pid = getpid();
702 mkstr(nm, tmpdir, "/", compbase->c_callname);
703 while (*nm) nm++;
705 for (i = 9; i > 3; i--) {
706 *nm++ = (pid % 10) + '0';
707 pid /= 10;
709 *nm++ = '.';
710 *nm++ = '\0'; /* null termination */
713 mkbase()
715 register struct compile *p = passes;
716 USTRING callname;
717 register int len;
719 basename(ProgCall, callname);
720 len = strlen(callname);
721 while (p->c_suffix) {
722 if (strcmp(p->c_callname, callname+len-strlen(p->c_callname)) == 0) {
723 compbase = p;
724 mkloader();
725 return;
727 p++;
729 /* we should not get here */
730 panic("internal error\n");
733 mkloader()
735 register struct passinfo *p = passinfo;
736 register struct pass *pass;
738 while (!(p->p_flags & LOADER)) p++;
739 loaderinfo = p;
740 pass = &(compbase->c_passes[0]);
741 while (strcmp(pass->pp_name, p->p_name)) pass++;
742 loader = pass;
745 needsprep(name)
746 char *name;
748 int file;
749 char fc;
751 file = open(name,0);
752 if (file <0) return 0;
753 if (read(file, &fc, 1) != 1) fc = 0;
754 close(file);
755 return fc == '#';
758 cfile(name)
759 char *name;
761 while (*name != '\0' && *name != '.')
762 name++;
764 if (*name == '\0') return 0;
765 return (*++name == 'c' && *++name == '\0');
768 char *
769 apply(pinf, cp, name, passindex, noremove, first, resultname)
770 register struct passinfo *pinf;
771 register struct compile *cp;
772 char *name, *resultname;
774 /* Apply a pass, indicated by "pinf", with args in
775 cp->c_passes[passindex], to name "name", leaving the result
776 in a file with name "resultname", concatenated with result
777 suffix.
778 When neccessary, the preprocessor is run first.
779 If "noremove" is NOT set, the file "name" is removed.
782 struct arglist *call = &CALLVEC;
783 struct pass *pass = &(cp->c_passes[passindex]);
784 char *outname;
786 if ( /* this pass is the first pass */
787 first
789 ( /* preprocessor always needed */
790 (pinf->p_flags & PREPALWAYS)
791 ||/* or only when "needsprep" says so */
792 ( (pinf->p_flags & PREPCOND) && needsprep(name))
795 mkstr(newfil, tmpname, passinfo[0].p_to, "");
796 mkvec(call, name, newfil,
797 (pinf->p_flags & PREPNOLN) ? &prepnoln : &preprocessor,
798 &passinfo[0]);
799 if (! runvec(call, &passinfo[0], name, newfil)) {
800 cleanup(newfil);
801 return 0;
804 /* A .c file must always be mishandled by irrel. */
805 if (cfile(name)) {
806 /* newfil is OK */
807 mkvec(call, newfil, newfil, &irrel, &passinfo[1]);
808 if (! runvec(call, &passinfo[1], newfil, newfil)) {
809 cleanup(newfil);
810 return 0;
813 strcpy(curfil, newfil);
814 newfil[0] = '\0';
815 name = curfil;
816 noremove = 0;
818 if (pinf->p_to) outname = mkstr(newfil, resultname, pinf->p_to, "");
819 else outname = o_FILE;
820 mkvec(call, name, outname, pass, pinf);
821 if (! runvec(call, pinf, name, outname)) {
822 if (! (pinf->p_flags & NOCLEAN)) cleanup(outname);
823 if (! noremove) cleanup(name);
824 return 0;
826 if (! noremove) cleanup(name);
827 strcpy(curfil, newfil);
828 newfil[0] = '\0';
829 return curfil;
833 applicable(pinf, suffix)
834 struct passinfo *pinf;
835 char *suffix;
837 /* Return one if the pass indicated by "pinfo" is applicable to
838 a file with suffix "suffix".
840 register char *sfx = pinf->p_from;
841 int l;
843 if (! suffix) return 0;
844 l = strlen(suffix);
845 while (*sfx) {
846 register char *p = sfx;
848 while (*p && *p != ',') p++;
849 if (l == p - sfx && strncmp(sfx, suffix, l) == 0) {
850 return 1;
852 if (*p == ',') sfx = p+1;
853 else sfx = p;
855 return 0;
858 char *
859 process(name, noremove)
860 char *name;
862 register struct compile *cp = passes;
863 char *suffix = extension(name);
864 USTRING base;
865 register struct pass *pass;
866 register struct passinfo *pinf;
868 if (E_flag) {
869 /* -E uses the cpp pass. */
870 suffix = "CPP";
873 if (! suffix) return name;
875 basename(name, base);
877 while (cp->c_suffix) {
878 if ((cp->c_flags & DEFLANG) &&
879 strcmp(cp->c_suffix, suffix) == 0)
880 break;
881 cp++;
883 if (! cp->c_suffix) cp = compbase;
884 pass = cp->c_passes;
885 while (pass->pp_name) {
886 int first = 1;
888 for (pinf=passinfo; strcmp(pass->pp_name,pinf->p_name);pinf++)
890 if (! (pinf->p_flags & LOADER) && applicable(pinf, suffix)) {
891 int cont = ! stopsuffix || ! pinf->p_to ||
892 strcmp(stopsuffix, pinf->p_to) != 0;
893 name = apply(pinf,
895 name,
896 (int) (pass - cp->c_passes),
897 noremove,
898 first,
899 applicable(loaderinfo, pinf->p_to) ||
900 !cont ?
901 strcat(base, ".") :
902 tmpname);
903 first = noremove = 0;
904 suffix = pinf->p_to;
905 if (!cont || !name) break;
907 pass++;
909 if (!noremove && name)
910 append(&GEN_LDFILES, name);
911 return name;
914 mkvec(call, in, out, pass, pinf)
915 struct arglist *call;
916 char *in, *out;
917 struct pass *pass;
918 register struct passinfo *pinf;
920 register int i;
922 init(call);
923 append(call, pinf->p_path);
924 scanflags(call, pinf);
925 if (pass) for (i = 0; i < MAXHEAD; i++)
926 if (pass->pp_head[i])
927 append(call, pass->pp_head[i]);
928 else break;
929 if (pinf->p_flags & INPUT && strcmp(in, "-") != 0)
930 append(call, in);
931 if (pinf->p_flags & OUTPUT)
932 append(call, out);
933 if (pinf->p_flags & O_OUTPUT) {
934 append(call, "-o");
935 append(call, out);
937 if (pass) for (i = 0; i < MAXTAIL; i++)
938 if (pass->pp_tail[i])
939 append(call, pass->pp_tail[i]);
940 else break;
943 callld(in, out, pass, pinf)
944 struct arglist *in;
945 char *out;
946 struct pass *pass;
947 register struct passinfo *pinf;
949 struct arglist *call = &CALLVEC;
950 register int i;
952 init(call);
953 append(call, pinf->p_path);
954 scanflags(call, pinf);
955 append(call, "-o");
956 append(call, out);
957 for (i = 0; i < MAXHEAD; i++)
958 if (pass->pp_head[i])
959 append(call, pass->pp_head[i]);
960 else break;
961 if (pinf->p_flags & INPUT)
962 concat(call, in);
963 if (pinf->p_flags & OUTPUT)
964 append(call, out);
965 for (i = 0; i < MAXTAIL; i++) {
966 if (pass->pp_tail[i]) {
967 if (pass->pp_tail[i][0] == '-' &&
968 pass->pp_tail[i][1] == 'l') {
969 append(call, library(&(pass->pp_tail[i][2])));
971 else if (*(pass->pp_tail[i]) != '*')
972 append(call, pass->pp_tail[i]);
973 else if (fp_lib)
974 append(call, library("fp"));
975 } else break;
977 if (! runvec(call, pinf, (char *) 0, out)) {
978 cleanup(out);
979 RET_CODE = 1;
983 clean(c)
984 register struct arglist *c;
986 register int i;
988 for (i = 1; i < c->al_argc; i++) {
989 free(c->al_argv[i]);
990 c->al_argv[i] = 0;
992 c->al_argc = 0;
995 scanflags(call, pinf)
996 struct arglist *call;
997 struct passinfo *pinf;
999 /* Find out which flags from FLAGS must be passed to pass "pinf",
1000 and how.
1001 Append them to "call"
1003 register int i;
1004 USTRING flg;
1006 for (i = 0; i < FLAGS.al_argc; i++) {
1007 register char *q = pinf->p_acceptflags;
1009 while (*q) {
1010 register char *p = FLAGS.al_argv[i] + 1;
1012 while (*q && *q == *p) {
1013 q++; p++;
1015 if (*q == ',' || !*q) {
1016 if (! *p) {
1017 /* append literally */
1018 append(call, FLAGS.al_argv[i]);
1020 break;
1022 if (*q == '*') {
1023 register char *s = flg;
1025 if (*++q != '=') {
1026 /* append literally */
1027 append(call, FLAGS.al_argv[i]);
1028 break;
1030 *s++ = '-';
1031 if (*q) q++; /* skip ',' */
1032 while (*q && *q != ',' && *q != '*') {
1033 /* copy replacement flag */
1034 *s++ = *q++;
1036 if (*q == '*') {
1037 /* copy rest */
1038 while (*p) *s++ = *p++;
1040 *s = 0;
1041 append(call, flg);
1042 break;
1044 if (*q == '=') {
1045 /* copy replacement */
1046 register char *s = flg;
1048 *s++ = '-';
1049 q++;
1050 while (*q && *q != ',') *s++ = *q++;
1051 *s = 0;
1052 append(call, flg);
1053 break;
1055 while (*q && *q++ != ',')