source: trunk/minix/commands/i86/cc.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 22.3 KB
Line 
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: /cvsup/minix/src/commands/i86/cc.c,v 1.1.1.1 2005/04/21 14:54:55 beng Exp $ */
8
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>
17
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"
40
41
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.
45*/
46struct 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
58 */
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) */
70};
71
72#define MAXHEAD 10
73#define MAXTAIL 5
74#define MAXPASS 7
75
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.
87*/
88struct 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 */
98};
99
100struct 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}
113};
114
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"
118
119struct pass preprocessor = { "cpp",
120 { PREP_FLAGS }
121 , {0}
122 };
123
124struct pass prepnoln = { "cpp",
125 { PREP_FLAGS, "-P" }
126 , {0}
127 };
128
129struct pass irrel = { "irrel",
130 {0}
131 };
132
133/* The "*" in the arguments for the loader indicates the place where the
134 * fp-emulation library should come.
135 */
136struct 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} }
145 },
146 DEFLANG
147},
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} }
157 },
158 DEFLANG
159},
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} }
169 },
170 DEFLANG
171},
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} }
179 },
180 DEFLANG
181},
182{ "s", "as",
183 { { "as", {0}, {0}}
184 },
185 0
186},
187{ "CPP", "cpp",
188 { { "cpp", {PREP_FLAGS}, {0}}
189 },
190 DEFLANG
191},
192{ 0},
193};
194
195#define MAXARGC 150 /* maximum number of arguments allowed in a list */
196#define USTR_SIZE 64 /* maximum length of string variable */
197
198typedef char USTRING[USTR_SIZE];
199
200struct arglist {
201 int al_argc;
202 char *al_argv[MAXARGC];
203};
204
205struct arglist CALLVEC;
206
207int kids = -1;
208
209char *o_FILE = "a.out"; /* default name for executable file */
210
211#define init(a) ((a)->al_argc = 1)
212#define cleanup(str) (str && remove(str))
213
214char *ProgCall = 0;
215
216int RET_CODE = 0;
217
218char *stopsuffix;
219int v_flag = 0;
220int t_flag = 0;
221int noexec = 0;
222int fp_lib = 1;
223int E_flag = 0;
224int i_flag = 1;
225
226
227USTRING curfil;
228USTRING newfil;
229struct arglist SRCFILES;
230struct arglist LDIRS;
231struct arglist LDFILES;
232struct arglist GEN_LDFILES;
233struct arglist FLAGS;
234
235char *tmpdir = "/tmp";
236char tmpname[64];
237
238struct compile *compbase;
239struct pass *loader;
240struct passinfo *loaderinfo;
241char *source;
242int maxLlen;
243
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 ));
272
273
274
275char *
276library(nm)
277 char *nm;
278{
279 static char f[512];
280 int Lcount;
281
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;
288 }
289 return f;
290 }
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';
297 }
298 return f;
299}
300
301void trapcc(sig)
302 int sig;
303{
304 signal(sig, SIG_IGN);
305 if (kids != -1) kill(kids, sig);
306 cleanup(newfil);
307 cleanup(curfil);
308 exit(1);
309}
310
311main(argc, argv)
312 char *argv[];
313{
314 char *str;
315 char **argvec;
316 int count;
317 char *file;
318
319 maxLlen = strlen(LIBDIR);
320 ProgCall = *argv++;
321
322 mkbase();
323
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;
334 }
335
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]) {
343
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;
395 }
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);
405
406 }
407 }
408 }
409
410 if (i_flag) append(&FLAGS, "-i");
411
412 mktempname(tmpname);
413
414 count = SRCFILES.al_argc;
415 argvec = &(SRCFILES.al_argv[0]);
416
417 while (count-- > 0) {
418
419 file = *argvec++;
420 source = file;
421
422 file = process(file, 1);
423
424 if (file && ! stopsuffix) append(&LDFILES, file);
425 }
426
427 clean(&SRCFILES);
428
429 /* loader ... */
430 if (RET_CODE == 0 && LDFILES.al_argc > 0) {
431 register struct passinfo *pp = passinfo;
432
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;
438
439 while (i-- > 0) {
440 remove(GEN_LDFILES.al_argv[i]);
441 free(GEN_LDFILES.al_argv[i]);
442 }
443 if ((++pp)->p_name) {
444 process(newfil, 0);
445 }
446 }
447 }
448 exit(RET_CODE);
449}
450
451remove(str)
452 char *str;
453{
454 if (t_flag)
455 return;
456 if (v_flag) {
457 prs("rm ");
458 prs(str);
459 prs("\n");
460 }
461 if (noexec)
462 return;
463 unlink(str);
464}
465
466char *
467alloc(u)
468 unsigned u;
469{
470 register char *p = malloc(u);
471
472 if (p == 0) panic("no space\n");
473 return p;
474}
475
476append(al, arg)
477 struct arglist *al;
478 char *arg;
479{
480 char *a = alloc((unsigned) (strlen(arg) + 1));
481
482 strcpy(a, arg);
483 if (al->al_argc >= MAXARGC)
484 panic("argument list overflow\n");
485 al->al_argv[(al->al_argc)++] = a;
486}
487
488concat(al1, al2)
489 struct arglist *al1, *al2;
490{
491 register i = al2->al_argc;
492 register char **p = &(al1->al_argv[al1->al_argc]);
493 register char **q = &(al2->al_argv[0]);
494
495 if ((al1->al_argc += i) >= MAXARGC)
496 panic("argument list overflow\n");
497 while (i-- > 0)
498 *p++ = *q++;
499}
500
501char *
502mkstr(dst, arg1, arg2, arg3)
503 char *dst, *arg1, *arg2, *arg3;
504{
505 register char *p;
506 register char *q = dst;
507
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;
518}
519
520basename(str, dst)
521 char *str;
522 register char *dst;
523{
524 register char *p1 = str;
525 register char *p2 = p1;
526
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 = '.';
536 }
537 else
538 while (*dst++ = *p2++);
539}
540
541char *
542extension(fln)
543 char *fln;
544{
545 register char *fn = fln;
546
547 while (*fn) fn++;
548 while (fn > fln && *fn != '.') fn--;
549 if (fn != fln) return fn+1;
550 return (char *)0;
551}
552
553runvec(vec, pass, in, out)
554 struct arglist *vec;
555 struct passinfo *pass;
556 char *in, *out;
557{
558 int pid, status;
559 int shifted = 0;
560
561 if (
562 strncmp(vec->al_argv[1], "/usr/", 5) == 0
563 &&
564 access(vec->al_argv[1] + 4, 1) == 0
565 ) {
566 vec->al_argv[1] += 4;
567 shifted = 1;
568 }
569
570 if (v_flag) {
571 pr_vec(vec);
572 if (pass->p_flags & STDIN) {
573 prs(" <");
574 prs(in);
575 }
576 if (pass->p_flags & STDOUT && !E_flag) {
577 prs(" >");
578 prs(out);
579 }
580 prs("\n");
581 }
582 if (noexec) {
583 if (shifted) vec->al_argv[1] -= 4;
584 clean(vec);
585 return 1;
586 }
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");
593 }
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");
599 }
600 ex_vec(vec);
601 }
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");
619 }
620 if (shifted) vec->al_argv[1] -= 4;
621 clean(vec);
622 kids = -1;
623 return status ? ((RET_CODE = 1), 0) : 1;
624}
625
626prnum(x)
627 register unsigned x;
628{
629 static char numbuf[8]; /* though it prints at most 3 characters */
630 register char *cp = numbuf + sizeof(numbuf) - 1;
631
632 *cp = '\0';
633 while (x >= 10) {
634 *--cp = (x % 10) + '0';
635 x /= 10;
636 }
637 *--cp = x + '0';
638 prs(cp);
639
640}
641
642prs(str)
643 char *str;
644{
645 if (str && *str)
646 write(2, str, strlen(str));
647}
648
649panic(str)
650 char *str;
651{
652 prs(str);
653 trapcc(SIGINT);
654}
655
656pr_vec(vec)
657 register struct arglist *vec;
658{
659 register char **ap = &vec->al_argv[1];
660
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)");
669 }
670}
671
672ex_vec(vec)
673 register struct arglist *vec;
674{
675 extern int errno;
676
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]));
682 }
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");
692 }
693 exit(1);
694}
695
696mktempname(nm)
697 register char *nm;
698{
699 register int i;
700 register int pid = getpid();
701
702 mkstr(nm, tmpdir, "/", compbase->c_callname);
703 while (*nm) nm++;
704
705 for (i = 9; i > 3; i--) {
706 *nm++ = (pid % 10) + '0';
707 pid /= 10;
708 }
709 *nm++ = '.';
710 *nm++ = '\0'; /* null termination */
711}
712
713mkbase()
714{
715 register struct compile *p = passes;
716 USTRING callname;
717 register int len;
718
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;
726 }
727 p++;
728 }
729 /* we should not get here */
730 panic("internal error\n");
731}
732
733mkloader()
734{
735 register struct passinfo *p = passinfo;
736 register struct pass *pass;
737
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;
743}
744
745needsprep(name)
746 char *name;
747{
748 int file;
749 char fc;
750
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 == '#';
756}
757
758cfile(name)
759 char *name;
760{
761 while (*name != '\0' && *name != '.')
762 name++;
763
764 if (*name == '\0') return 0;
765 return (*++name == 'c' && *++name == '\0');
766}
767
768char *
769apply(pinf, cp, name, passindex, noremove, first, resultname)
770 register struct passinfo *pinf;
771 register struct compile *cp;
772 char *name, *resultname;
773{
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.
780 */
781
782 struct arglist *call = &CALLVEC;
783 struct pass *pass = &(cp->c_passes[passindex]);
784 char *outname;
785
786 if ( /* this pass is the first pass */
787 first
788 &&
789 ( /* preprocessor always needed */
790 (pinf->p_flags & PREPALWAYS)
791 ||/* or only when "needsprep" says so */
792 ( (pinf->p_flags & PREPCOND) && needsprep(name))
793 )
794 ) {
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;
802 }
803
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;
811 }
812 }
813 strcpy(curfil, newfil);
814 newfil[0] = '\0';
815 name = curfil;
816 noremove = 0;
817 }
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;
825 }
826 if (! noremove) cleanup(name);
827 strcpy(curfil, newfil);
828 newfil[0] = '\0';
829 return curfil;
830}
831
832int
833applicable(pinf, suffix)
834 struct passinfo *pinf;
835 char *suffix;
836{
837 /* Return one if the pass indicated by "pinfo" is applicable to
838 a file with suffix "suffix".
839 */
840 register char *sfx = pinf->p_from;
841 int l;
842
843 if (! suffix) return 0;
844 l = strlen(suffix);
845 while (*sfx) {
846 register char *p = sfx;
847
848 while (*p && *p != ',') p++;
849 if (l == p - sfx && strncmp(sfx, suffix, l) == 0) {
850 return 1;
851 }
852 if (*p == ',') sfx = p+1;
853 else sfx = p;
854 }
855 return 0;
856}
857
858char *
859process(name, noremove)
860 char *name;
861{
862 register struct compile *cp = passes;
863 char *suffix = extension(name);
864 USTRING base;
865 register struct pass *pass;
866 register struct passinfo *pinf;
867
868 if (E_flag) {
869 /* -E uses the cpp pass. */
870 suffix = "CPP";
871 }
872
873 if (! suffix) return name;
874
875 basename(name, base);
876
877 while (cp->c_suffix) {
878 if ((cp->c_flags & DEFLANG) &&
879 strcmp(cp->c_suffix, suffix) == 0)
880 break;
881 cp++;
882 }
883 if (! cp->c_suffix) cp = compbase;
884 pass = cp->c_passes;
885 while (pass->pp_name) {
886 int first = 1;
887
888 for (pinf=passinfo; strcmp(pass->pp_name,pinf->p_name);pinf++)
889 ;
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,
894 cp,
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;
906 }
907 pass++;
908 }
909 if (!noremove && name)
910 append(&GEN_LDFILES, name);
911 return name;
912}
913
914mkvec(call, in, out, pass, pinf)
915 struct arglist *call;
916 char *in, *out;
917 struct pass *pass;
918 register struct passinfo *pinf;
919{
920 register int i;
921
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);
936 }
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;
941}
942
943callld(in, out, pass, pinf)
944 struct arglist *in;
945 char *out;
946 struct pass *pass;
947 register struct passinfo *pinf;
948{
949 struct arglist *call = &CALLVEC;
950 register int i;
951
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])));
970 }
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;
976 }
977 if (! runvec(call, pinf, (char *) 0, out)) {
978 cleanup(out);
979 RET_CODE = 1;
980 }
981}
982
983clean(c)
984 register struct arglist *c;
985{
986 register int i;
987
988 for (i = 1; i < c->al_argc; i++) {
989 free(c->al_argv[i]);
990 c->al_argv[i] = 0;
991 }
992 c->al_argc = 0;
993}
994
995scanflags(call, pinf)
996 struct arglist *call;
997 struct passinfo *pinf;
998{
999 /* Find out which flags from FLAGS must be passed to pass "pinf",
1000 and how.
1001 Append them to "call"
1002 */
1003 register int i;
1004 USTRING flg;
1005
1006 for (i = 0; i < FLAGS.al_argc; i++) {
1007 register char *q = pinf->p_acceptflags;
1008
1009 while (*q) {
1010 register char *p = FLAGS.al_argv[i] + 1;
1011
1012 while (*q && *q == *p) {
1013 q++; p++;
1014 }
1015 if (*q == ',' || !*q) {
1016 if (! *p) {
1017 /* append literally */
1018 append(call, FLAGS.al_argv[i]);
1019 }
1020 break;
1021 }
1022 if (*q == '*') {
1023 register char *s = flg;
1024
1025 if (*++q != '=') {
1026 /* append literally */
1027 append(call, FLAGS.al_argv[i]);
1028 break;
1029 }
1030 *s++ = '-';
1031 if (*q) q++; /* skip ',' */
1032 while (*q && *q != ',' && *q != '*') {
1033 /* copy replacement flag */
1034 *s++ = *q++;
1035 }
1036 if (*q == '*') {
1037 /* copy rest */
1038 while (*p) *s++ = *p++;
1039 }
1040 *s = 0;
1041 append(call, flg);
1042 break;
1043 }
1044 if (*q == '=') {
1045 /* copy replacement */
1046 register char *s = flg;
1047
1048 *s++ = '-';
1049 q++;
1050 while (*q && *q != ',') *s++ = *q++;
1051 *s = 0;
1052 append(call, flg);
1053 break;
1054 }
1055 while (*q && *q++ != ',')
1056 ;
1057 }
1058 }
1059}
Note: See TracBrowser for help on using the repository browser.