cc.c

Go to the documentation of this file.
00001 /*      Driver for Minix compilers.
00002         Written june 1987 by Ceriel J.H. Jacobs, partly derived from old
00003         cc-driver, written by Erik Baalbergen.
00004         This driver is mostly table-driven, the table being in the form of
00005         some global initialized structures.
00006 */
00007 /* $Header: /opt/proj/minix/cvsroot/src/commands/i86/cc.c,v 1.1.1.1 2005/04/21 14:54:55 beng Exp $ */
00008 
00009 #include <sys/types.h>
00010 #include <sys/wait.h>
00011 #include <errno.h>
00012 #include <signal.h>
00013 #include <string.h>
00014 #include <stdlib.h>
00015 #include <fcntl.h>
00016 #include <unistd.h>
00017 
00018 /* Paths.  (Executables in /usr are first tried with /usr stripped off.) */
00019 #define SHELL           "/bin/sh"
00020 #define PP              "/usr/lib/ncpp"
00021 #define IRREL           "/usr/lib/irrel"
00022 #define CEM             "/usr/lib/ncem"
00023 #define M2EM            "/usr/lib/nm2em"
00024 #define ENCODE          "/usr/lib/em_encode"
00025 #define OPT             "/usr/lib/nopt"
00026 #define CG              "/usr/lib/ncg"
00027 #define AS              "/usr/lib/as"
00028 #define LD              "/usr/lib/ld"
00029 #define CV              "/usr/lib/cv"
00030 #define LIBDIR          "/usr/lib"
00031 #define CRT             "/usr/lib/ncrtso.o"
00032 #define PEM             "/usr/lib/npem"
00033 #define PRT             "/usr/lib/nprtso.o"
00034 #define M2RT            "/usr/lib/nm2rtso.o"
00035 #define LIBC            "/usr/lib/libd.a", "/usr/lib/libc.a"
00036 #define LIBP            "/usr/lib/libp.a", "/usr/lib/libc.a"
00037 #define LIBM2           "/usr/lib/libm2.a", "/usr/lib/libc.a"
00038 #define END             "/usr/lib/libe.a", "/usr/lib/end.a"
00039 #define M2DEF           "-I/usr/lib/m2"
00040 
00041 
00042 /*      every pass that this program knows about has associated with it
00043         a structure, containing such information as its name, where it
00044         resides, the flags it accepts, and the like.
00045 */
00046 struct passinfo {
00047         char *p_name;           /* name of this pass */
00048         char *p_path;           /* where is it */
00049         char *p_from;           /* suffix of source (comma-separated list) */
00050         char *p_to;             /* suffix of destination */
00051         char *p_acceptflags;    /* comma separated list; format:
00052                                         flag
00053                                         flag*
00054                                         flag=xxx
00055                                         flag*=xxx[*]
00056                                    where a star matches a, possibly empty, 
00057                                    string
00058                                 */
00059         int  p_flags;
00060 #define INPUT   01              /* needs input file as argument */
00061 #define OUTPUT  02              /* needs output file as argument */
00062 #define LOADER  04              /* this pass is the loader */
00063 #define STDIN   010             /* reads from standard input */
00064 #define STDOUT  020             /* writes on standard output */
00065 #define NOCLEAN 040             /* do not remove target if this pass fails */
00066 #define O_OUTPUT 0100           /* -o outputfile, hack for as */
00067 #define PREPALWAYS      0200    /* always to be preprocessed */
00068 #define PREPCOND        0400    /* preprocessed when starting with '#' */
00069 #define PREPNOLN        01000   /* suppress line number info (cpp -P) */
00070 };
00071 
00072 #define MAXHEAD 10
00073 #define MAXTAIL 5
00074 #define MAXPASS 7
00075 
00076 /*      Every language handled by this program has a "compile" structure
00077         associated with it, describing the start-suffix, how the driver for
00078         this language is called, which passes must be called, which flags
00079         and arguments must be passed to these passes, etc.
00080         The language is determined by the suffix of the argument program.
00081         However, if this suffix does not determine a language (DEFLANG),
00082         the callname is used.
00083         Notice that the 's' suffix does not determine a language, because
00084         the input file could have been derived from f.i. a C-program.
00085         So, if you use "cc x.s", the C-runtime system will be used, but if
00086         you use "as x.s", it will not.
00087 */
00088 struct compile {
00089         char *c_suffix;         /* starting suffix of this list of passes */
00090         char *c_callname;       /* affects runtime system loaded with program */
00091         struct pass {
00092                 char *pp_name;          /* name of the pass */
00093                 char *pp_head[MAXHEAD]; /* args in front of filename */
00094                 char *pp_tail[MAXTAIL]; /* args after filename */
00095         } c_passes[MAXPASS];
00096         int  c_flags;
00097 #define DEFLANG         010     /* this suffix determines a language */
00098 };
00099 
00100 struct passinfo passinfo[] = {
00101         { "cpp", PP, "CPP", "i", "wo=o,I*,D*,U*,P", INPUT|STDOUT },
00102         { "irrel", IRREL, "i", "i", "m", INPUT},
00103         { "cem", CEM, "i,c", "k", "m=o,p,wa=a,wo=o,ws=s,w,T*", INPUT|OUTPUT|PREPALWAYS },
00104         { "pc", PEM, "i,p", "k", "n=L,w,a,A,R", INPUT|OUTPUT|PREPCOND },
00105         { "m2", M2EM, "i,mod", "k", "n=L,w*,A,R,W*,3,I*", INPUT|OUTPUT|PREPCOND },
00106         { "encode", ENCODE, "i,e", "k", "", INPUT|STDOUT|PREPCOND|PREPNOLN },
00107         { "opt", OPT, "k", "m", "", STDIN|STDOUT },
00108         { "cg", CG, "m", "s", "O=p4", INPUT|OUTPUT },
00109         { "as", AS, "i,s", "o", "T*", INPUT|O_OUTPUT|PREPCOND },
00110         { "ld", LD, "o", "out", "i,s", INPUT|LOADER },  /* changed */
00111         { "cv", CV, "out", 0, "", INPUT|OUTPUT|NOCLEAN },       /* must come after loader */
00112         { 0}
00113 };
00114 
00115 #define PREP_FLAGS      "-D_EM_WSIZE=2", "-D_EM_PSIZE=2", "-D_EM_SSIZE=2", \
00116                         "-D_EM_LSIZE=4", "-D_EM_FSIZE=4", "-D_EM_DSIZE=8", \
00117                         "-D__ACK__", "-D__minix", "-D__i86"
00118 
00119 struct pass preprocessor = { "cpp",
00120                             { PREP_FLAGS }
00121                             , {0}
00122                             };
00123 
00124 struct pass prepnoln = { "cpp",
00125                             { PREP_FLAGS, "-P" }
00126                             , {0}
00127                             };
00128 
00129 struct pass irrel = { "irrel",
00130                             {0}
00131                         };
00132 
00133 /* The "*" in the arguments for the loader indicates the place where the
00134  * fp-emulation library should come.
00135  */
00136 struct compile passes[] = {
00137 {       "c", "cc", 
00138         {       { "cem", {"-L"}, {0} }, /* changed */
00139                 { "opt", {0}, {0} },
00140                 { "cg", {0}, {0} },
00141                 { "as", {"-"}, {0} },
00142                 { "ld", {CRT}, /* changed */
00143                           {LIBC, "*",  END}},
00144                 { "cv", {0}, {0} }
00145         },
00146         DEFLANG
00147 },
00148 {       "p", "pc",
00149         {       { "pc", {0}, {0} },
00150                 { "opt", {0}, {0} },
00151                 { "cg", {0}, {0} },
00152                 { "as", {"-"}, {0} },
00153                 { "ld", {PRT}, 
00154                           {LIBP,
00155                             "*", END}},
00156                 { "cv", {0}, {0} }
00157         },
00158         DEFLANG
00159 },
00160 {       "mod", "m2",
00161         {       { "m2", {M2DEF}, {0} },
00162                 { "opt", {0}, {0} },
00163                 { "cg", {0}, {0} },
00164                 { "as", {"-"}, {0} },
00165                 { "ld", {M2RT}, 
00166                           {LIBM2,
00167                             "*", END}},
00168                 { "cv", {0}, {0} }
00169         },
00170         DEFLANG
00171 },
00172 {       "e", "encode",
00173         {       { "encode", {0}, {0}},
00174                 { "opt", {0}, {0} },
00175                 { "cg", {0}, {0} },
00176                 { "as", {"-"}, {0} },
00177                 { "ld", {0}, {"*", END}},
00178                 { "cv", {0}, {0} }
00179         },
00180         DEFLANG
00181 },
00182 {       "s", "as",
00183         {       { "as", {0}, {0}}
00184         },
00185         0
00186 },
00187 {       "CPP", "cpp",
00188         {       { "cpp", {PREP_FLAGS}, {0}}
00189         },
00190         DEFLANG
00191 },
00192 {       0},
00193 };
00194 
00195 #define MAXARGC 150     /* maximum number of arguments allowed in a list */
00196 #define USTR_SIZE       64      /* maximum length of string variable */
00197 
00198 typedef char USTRING[USTR_SIZE];
00199 
00200 struct arglist {
00201         int al_argc;
00202         char *al_argv[MAXARGC];
00203 };
00204 
00205 struct arglist CALLVEC;
00206 
00207 int kids = -1;
00208 
00209 char *o_FILE = "a.out"; /* default name for executable file */
00210 
00211 #define init(a)         ((a)->al_argc = 1)
00212 #define cleanup(str)            (str && remove(str))
00213 
00214 char *ProgCall = 0;
00215 
00216 int RET_CODE = 0;
00217 
00218 char *stopsuffix;
00219 int v_flag = 0;
00220 int t_flag = 0;
00221 int noexec = 0;
00222 int fp_lib = 1;
00223 int E_flag = 0;
00224 int i_flag = 1;
00225 
00226 
00227 USTRING curfil;
00228 USTRING newfil;
00229 struct arglist SRCFILES;
00230 struct arglist LDIRS;
00231 struct arglist LDFILES;
00232 struct arglist GEN_LDFILES;
00233 struct arglist FLAGS;
00234 
00235 char *tmpdir = "/tmp";
00236 char tmpname[64];
00237 
00238 struct compile *compbase;
00239 struct pass *loader;
00240 struct passinfo *loaderinfo;
00241 char *source;
00242 int maxLlen;
00243 
00244 _PROTOTYPE(char *library, (char *nm ));
00245 _PROTOTYPE(void trapcc, (int sig ));
00246 _PROTOTYPE(int main, (int argc, char *argv []));
00247 _PROTOTYPE(int remove, (char *str ));
00248 _PROTOTYPE(char *alloc, (unsigned u ));
00249 _PROTOTYPE(int append, (struct arglist *al, char *arg ));
00250 _PROTOTYPE(int concat, (struct arglist *al1, struct arglist *al2 ));
00251 _PROTOTYPE(char *mkstr, (char *dst, char *arg1, char *arg2, char *arg3 ));
00252 _PROTOTYPE(int basename, (char *str, char *dst ));
00253 _PROTOTYPE(char *extension, (char *fln ));
00254 _PROTOTYPE(int runvec, (struct arglist *vec, struct passinfo *pass, char *in, char *out ));
00255 _PROTOTYPE(int prnum, (unsigned x ));
00256 _PROTOTYPE(int prs, (char *str ));
00257 _PROTOTYPE(int panic, (char *str ));
00258 _PROTOTYPE(int pr_vec, (struct arglist *vec ));
00259 _PROTOTYPE(int ex_vec, (struct arglist *vec ));
00260 _PROTOTYPE(int mktempname, (char *nm ));
00261 _PROTOTYPE(int mkbase, (void));
00262 _PROTOTYPE(int mkloader, (void));
00263 _PROTOTYPE(int needsprep, (char *name ));
00264 _PROTOTYPE(int cfile, (char *name ));
00265 _PROTOTYPE(char *apply, (struct passinfo *pinf, struct compile *cp, char *name, int passindex, int noremove, int first, char *resultname ));
00266 _PROTOTYPE(int applicable, (struct passinfo *pinf, char *suffix ));
00267 _PROTOTYPE(char *process, (char *name, int noremove ));
00268 _PROTOTYPE(int mkvec, (struct arglist *call, char *in, char *out, struct pass *pass, struct passinfo *pinf ));
00269 _PROTOTYPE(int callld, (struct arglist *in, char *out, struct pass *pass, struct passinfo *pinf ));
00270 _PROTOTYPE(int clean, (struct arglist *c ));
00271 _PROTOTYPE(int scanflags, (struct arglist *call, struct passinfo *pinf ));
00272 
00273 
00274 
00275 char *
00276 library(nm)
00277         char    *nm;
00278 {
00279         static char     f[512];
00280         int     Lcount;
00281 
00282         for (Lcount = 0; Lcount < LDIRS.al_argc; Lcount++) {
00283                 mkstr(f, LDIRS.al_argv[Lcount], "/lib", nm);
00284                 strcat(f, ".a");
00285                 if (access(f, 0) != 0) {
00286                         f[strlen(f)-1] = 'a';
00287                         if (access(f, 0) != 0) continue;
00288                 }
00289                 return f;
00290         }
00291         mkstr(f, LIBDIR, "/lib", nm);
00292         strcat(f, ".a");
00293         if (access(f, 0) != 0) {
00294                 int i = strlen(f) - 1;
00295                 f[i] = 'a';
00296                 if (access(f, 0) != 0) f[i] = 'A';
00297         }
00298         return f;
00299 }
00300 
00301 void trapcc(sig)
00302         int sig;
00303 {
00304         signal(sig, SIG_IGN);
00305         if (kids != -1) kill(kids, sig);
00306         cleanup(newfil);
00307         cleanup(curfil);
00308         exit(1);
00309 }
00310 
00311 main(argc, argv)
00312         char *argv[];
00313 {
00314         char *str;
00315         char **argvec;
00316         int count;
00317         char *file;
00318 
00319         maxLlen = strlen(LIBDIR);
00320         ProgCall = *argv++;
00321 
00322         mkbase();
00323 
00324         if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
00325                 signal(SIGHUP, trapcc);
00326         if (signal(SIGINT, SIG_IGN) != SIG_IGN)
00327                 signal(SIGINT, trapcc);
00328         if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
00329                 signal(SIGQUIT, trapcc);
00330         while (--argc > 0) {
00331                 if (*(str = *argv++) != '-' || str[1] == 0) {
00332                         append(&SRCFILES, str);
00333                         continue;
00334                 }
00335 
00336                 if (strcmp(str, "-com") == 0) {
00337                         i_flag = 0;
00338                 } else
00339                 if (strcmp(str, "-sep") == 0) {
00340                         i_flag = 1;
00341                 } else {
00342                         switch (str[1]) {
00343 
00344                         case 'c':
00345                                 stopsuffix = "o";
00346                                 if (str[2] == '.') stopsuffix = str + 3;
00347                                 break;
00348                         case 'f':
00349                                 fp_lib = (strcmp(str+2, "hard") != 0);
00350                                 break;
00351                         case 'F':
00352                         case 'W':
00353                                 /* Ignore. */
00354                                 break;
00355                         case 'L':
00356                                 append(&LDIRS, &str[2]);
00357                                 count = strlen(&str[2]);
00358                                 if (count > maxLlen) maxLlen = count;
00359                                 break;
00360                         case 'l':
00361                                 append(&SRCFILES, library(&str[2]));
00362                                 break;
00363                         case 'm':
00364                                 /* Use -m, ignore -mxxx. */
00365                                 if (str[2] == 0) append(&FLAGS, str);
00366                                 break;
00367                         case 'o':
00368                                 if (argc-- >= 0)
00369                                         o_FILE = *argv++;
00370                                 break;
00371                         case 'S':
00372                                 stopsuffix = "s";
00373                                 break;
00374                         case 'E':
00375                                 E_flag = 1;
00376                                 stopsuffix = "i";
00377                                 break;
00378                         case 'P':
00379                                 stopsuffix = "i";
00380                                 append(&FLAGS, str);
00381                                 break;
00382                         case 'v':
00383                                 v_flag++;
00384                                 if (str[2] == 'n')
00385                                         noexec = 1;
00386                                 break;
00387                         case 't':
00388                                 /* save temporaries */
00389                                 t_flag++;
00390                                 break;
00391                         case '.':
00392                                 if (str[2] == 'o') {
00393                                         /* no runtime start-off */
00394                                         loader->pp_head[0] = 0;
00395                                 }
00396                                 break;
00397                         case 'i':
00398                                 i_flag++;
00399                                 break;
00400                         case 'T':
00401                                 tmpdir = &str[2];
00402                                 /*FALLTHROUGH*/
00403                         default:
00404                                 append(&FLAGS, str);
00405 
00406                         }
00407                 }
00408         }
00409 
00410         if (i_flag) append(&FLAGS, "-i");
00411 
00412         mktempname(tmpname);
00413 
00414         count = SRCFILES.al_argc;
00415         argvec = &(SRCFILES.al_argv[0]);
00416 
00417         while (count-- > 0) {
00418 
00419                 file = *argvec++;
00420                 source = file;
00421 
00422                 file = process(file, 1);
00423         
00424                 if (file && ! stopsuffix) append(&LDFILES, file);
00425         }
00426 
00427         clean(&SRCFILES);
00428 
00429         /* loader ... */
00430         if (RET_CODE == 0 && LDFILES.al_argc > 0) {
00431                 register struct passinfo *pp = passinfo;
00432 
00433                 while (!(pp->p_flags & LOADER)) pp++;
00434                 mkstr(newfil, tmpname, pp->p_to, "");
00435                 callld(&LDFILES, !((pp+1)->p_name) ? o_FILE : newfil, loader, pp);
00436                 if (RET_CODE == 0) {
00437                         register int i = GEN_LDFILES.al_argc;
00438 
00439                         while (i-- > 0) {
00440                                 remove(GEN_LDFILES.al_argv[i]);
00441                                 free(GEN_LDFILES.al_argv[i]);
00442                         }
00443                         if ((++pp)->p_name) {
00444                                 process(newfil, 0);
00445                         }
00446                 }
00447         }
00448         exit(RET_CODE);
00449 }
00450 
00451 remove(str)
00452         char *str;
00453 {
00454         if (t_flag)
00455                 return;
00456         if (v_flag) {
00457                 prs("rm ");
00458                 prs(str);
00459                 prs("\n");
00460         }
00461         if (noexec)
00462                 return;
00463         unlink(str);
00464 }
00465 
00466 char *
00467 alloc(u)
00468         unsigned u;
00469 {
00470         register char *p = malloc(u);
00471 
00472         if (p == 0) panic("no space\n");
00473         return p;
00474 }
00475 
00476 append(al, arg)
00477         struct arglist *al;
00478         char *arg;
00479 {
00480         char *a = alloc((unsigned) (strlen(arg) + 1));
00481 
00482         strcpy(a, arg);
00483         if (al->al_argc >= MAXARGC)
00484                 panic("argument list overflow\n");
00485         al->al_argv[(al->al_argc)++] = a;
00486 }
00487 
00488 concat(al1, al2)
00489         struct arglist *al1, *al2;
00490 {
00491         register i = al2->al_argc;
00492         register char **p = &(al1->al_argv[al1->al_argc]);
00493         register char **q = &(al2->al_argv[0]);
00494 
00495         if ((al1->al_argc += i) >= MAXARGC)
00496                 panic("argument list overflow\n");
00497         while (i-- > 0)
00498                 *p++ = *q++;
00499 }
00500 
00501 char *
00502 mkstr(dst, arg1, arg2, arg3)
00503         char *dst, *arg1, *arg2, *arg3;
00504 {
00505         register char *p;
00506         register char *q = dst;
00507 
00508         p = arg1;
00509         while (*q++ = *p++);
00510         q--;
00511         p = arg2;
00512         while (*q++ = *p++);
00513         q--;
00514         p = arg3;
00515         while (*q++ = *p++);
00516         q--;
00517         return dst;
00518 }
00519 
00520 basename(str, dst)
00521         char *str;
00522         register char *dst;
00523 {
00524         register char *p1 = str;
00525         register char *p2 = p1;
00526 
00527         while (*p1)
00528                 if (*p1++ == '/')
00529                         p2 = p1;
00530         p1--;
00531         while (*p1 != '.' && p1 > p2) p1--;
00532         if (*p1 == '.') {
00533                 *p1 = '\0';
00534                 while (*dst++ = *p2++);
00535                 *p1 = '.';
00536         }
00537         else
00538                 while (*dst++ = *p2++);
00539 }
00540 
00541 char *
00542 extension(fln)
00543         char *fln;
00544 {
00545         register char *fn = fln;
00546 
00547         while (*fn) fn++;
00548         while (fn > fln && *fn != '.') fn--;
00549         if (fn != fln) return fn+1;
00550         return (char *)0;
00551 }
00552 
00553 runvec(vec, pass, in, out)
00554         struct arglist *vec;
00555         struct passinfo *pass;
00556         char *in, *out;
00557 {
00558         int pid, status;
00559         int shifted = 0;
00560 
00561         if (
00562                 strncmp(vec->al_argv[1], "/usr/", 5) == 0
00563                 &&
00564                 access(vec->al_argv[1] + 4, 1) == 0
00565         ) {
00566                 vec->al_argv[1] += 4;
00567                 shifted = 1;
00568         }
00569 
00570         if (v_flag) {
00571                 pr_vec(vec);
00572                 if (pass->p_flags & STDIN) {
00573                         prs(" <");
00574                         prs(in);
00575                 }
00576                 if (pass->p_flags & STDOUT && !E_flag) {
00577                         prs(" >");
00578                         prs(out);
00579                 }
00580                 prs("\n");
00581         }
00582         if (noexec) {
00583                 if (shifted) vec->al_argv[1] -= 4;
00584                 clean(vec);
00585                 return 1;
00586         }
00587         if ((pid = fork()) == 0) {      /* start up the process */
00588                 if (pass->p_flags & STDIN && strcmp(in, "-") != 0) {
00589                         /* redirect standard input */
00590                         close(0);
00591                         if (open(in, 0) != 0)
00592                                 panic("cannot open input file\n");
00593                 }
00594                 if (pass->p_flags & STDOUT && !E_flag) {
00595                         /* redirect standard output */
00596                         close(1);
00597                         if (creat(out, 0666) != 1)
00598                                 panic("cannot create output file\n");
00599                 }
00600                 ex_vec(vec);
00601         }
00602         if (pid == -1)
00603                 panic("no more processes\n");
00604         kids = pid;
00605         wait(&status);
00606         if (status) switch(status & 0177) {
00607         case SIGHUP:
00608         case SIGINT:
00609         case SIGQUIT:
00610         case SIGTERM:
00611         case 0:
00612                 break;
00613         default:
00614                 if (E_flag && (status & 0177) == SIGPIPE) break;
00615                 prs(vec->al_argv[1]);
00616                 prs(" died with signal ");
00617                 prnum(status & 0177);
00618                 prs("\n");
00619         }
00620         if (shifted) vec->al_argv[1] -= 4;
00621         clean(vec);
00622         kids = -1;
00623         return status ? ((RET_CODE = 1), 0) : 1;
00624 }
00625 
00626 prnum(x)
00627         register unsigned x;
00628 {
00629         static char numbuf[8];                  /* though it prints at most 3 characters */
00630         register char *cp = numbuf + sizeof(numbuf) - 1;
00631 
00632         *cp = '\0';
00633         while (x >= 10) {
00634                 *--cp = (x % 10) + '0';
00635                 x /= 10;
00636         }
00637         *--cp = x + '0';
00638         prs(cp);
00639 
00640 }
00641 
00642 prs(str)
00643         char *str;
00644 {
00645         if (str && *str)
00646                 write(2, str, strlen(str));
00647 }
00648 
00649 panic(str)
00650         char *str;
00651 {
00652         prs(str);
00653         trapcc(SIGINT);
00654 }
00655 
00656 pr_vec(vec)
00657         register struct arglist *vec;
00658 {
00659         register char **ap = &vec->al_argv[1];
00660         
00661         vec->al_argv[vec->al_argc] = 0;
00662         prs(*ap);
00663         while (*++ap) {
00664                 prs(" ");
00665                 if (strlen(*ap))
00666                         prs(*ap);
00667                 else
00668                         prs("(empty)");
00669         }
00670 }
00671 
00672 ex_vec(vec)
00673         register struct arglist *vec;
00674 {
00675         extern int errno;
00676 
00677         vec->al_argv[vec->al_argc] = 0;
00678         execv(vec->al_argv[1], &(vec->al_argv[1]));
00679         if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
00680                 vec->al_argv[0] = SHELL;
00681                 execv(SHELL, &(vec->al_argv[0]));
00682         }
00683         if (access(vec->al_argv[1], 1) == 0) {
00684                 /* File is executable. */
00685                 prs("Cannot execute ");
00686                 prs(vec->al_argv[1]);
00687                 prs(". Not enough memory.\n");
00688                 prs("Reduce the memory use of your system and try again\n");
00689         } else {
00690                 prs(vec->al_argv[1]);
00691                 prs(" is not executable\n");
00692         }
00693         exit(1);
00694 }
00695 
00696 mktempname(nm)
00697         register char *nm;
00698 {
00699         register int i;
00700         register int pid = getpid();
00701 
00702         mkstr(nm, tmpdir, "/", compbase->c_callname);
00703         while (*nm) nm++;
00704 
00705         for (i = 9; i > 3; i--) {
00706                 *nm++ = (pid % 10) + '0';
00707                 pid /= 10;
00708         }
00709         *nm++ = '.';
00710         *nm++ = '\0'; /* null termination */
00711 }
00712 
00713 mkbase()
00714 {
00715         register struct compile *p = passes;
00716         USTRING callname;
00717         register int len;
00718 
00719         basename(ProgCall, callname);
00720         len = strlen(callname);
00721         while (p->c_suffix) {
00722                 if (strcmp(p->c_callname, callname+len-strlen(p->c_callname)) == 0) {
00723                         compbase = p;
00724                         mkloader();
00725                         return;
00726                 }
00727                 p++;
00728         }
00729         /* we should not get here */
00730         panic("internal error\n");
00731 }
00732 
00733 mkloader()
00734 {
00735         register struct passinfo *p = passinfo;
00736         register struct pass *pass;
00737 
00738         while (!(p->p_flags & LOADER)) p++;
00739         loaderinfo = p;
00740         pass = &(compbase->c_passes[0]);
00741         while (strcmp(pass->pp_name, p->p_name)) pass++;
00742         loader = pass;
00743 }
00744 
00745 needsprep(name)
00746         char *name;
00747 {
00748         int file;
00749         char fc;
00750 
00751         file = open(name,0);
00752         if (file <0) return 0;
00753         if (read(file, &fc, 1) != 1) fc = 0;
00754         close(file);
00755         return fc == '#';
00756 }
00757 
00758 cfile(name)
00759         char *name;
00760 {
00761         while (*name != '\0' && *name != '.')
00762                 name++;
00763 
00764         if (*name == '\0') return 0;
00765         return (*++name == 'c' && *++name == '\0');
00766 }
00767 
00768 char *
00769 apply(pinf, cp, name, passindex, noremove, first, resultname)
00770         register struct passinfo *pinf;
00771         register struct compile *cp;
00772         char *name, *resultname;
00773 {
00774         /*      Apply a pass, indicated by "pinf", with args in 
00775                 cp->c_passes[passindex], to name "name", leaving the result
00776                 in a file with name "resultname", concatenated with result
00777                 suffix.
00778                 When neccessary, the preprocessor is run first.
00779                 If "noremove" is NOT set, the file "name" is removed.
00780         */
00781 
00782         struct arglist *call = &CALLVEC;
00783         struct pass *pass = &(cp->c_passes[passindex]);
00784         char *outname;
00785 
00786         if ( /* this pass is the first pass */
00787              first
00788            &&
00789              ( /* preprocessor always needed */
00790                (pinf->p_flags & PREPALWAYS)
00791              ||/* or only when "needsprep" says so */
00792                ( (pinf->p_flags & PREPCOND) && needsprep(name))
00793              )
00794            ) {
00795                 mkstr(newfil, tmpname, passinfo[0].p_to, "");
00796                 mkvec(call, name, newfil,
00797                         (pinf->p_flags & PREPNOLN) ? &prepnoln : &preprocessor,
00798                         &passinfo[0]);
00799                 if (! runvec(call, &passinfo[0], name, newfil)) {
00800                         cleanup(newfil);
00801                         return 0;
00802                 }
00803 
00804                 /* A .c file must always be mishandled by irrel. */
00805                 if (cfile(name)) {
00806                         /* newfil is OK */
00807                         mkvec(call, newfil, newfil, &irrel, &passinfo[1]);
00808                         if (! runvec(call, &passinfo[1], newfil, newfil)) {
00809                                 cleanup(newfil);
00810                                 return 0;
00811                         }
00812                 }
00813                 strcpy(curfil, newfil);
00814                 newfil[0] = '\0';
00815                 name = curfil;
00816                 noremove = 0;
00817         }
00818         if (pinf->p_to) outname = mkstr(newfil, resultname, pinf->p_to, "");
00819         else outname = o_FILE;
00820         mkvec(call, name, outname, pass, pinf);
00821         if (! runvec(call, pinf, name, outname)) {
00822                 if (! (pinf->p_flags & NOCLEAN)) cleanup(outname);
00823                 if (! noremove) cleanup(name);
00824                 return 0;
00825         }
00826         if (! noremove) cleanup(name);
00827         strcpy(curfil, newfil);
00828         newfil[0] = '\0';
00829         return curfil;
00830 }
00831 
00832 int
00833 applicable(pinf, suffix)
00834         struct passinfo *pinf;
00835         char *suffix;
00836 {
00837         /*      Return one if the pass indicated by "pinfo" is applicable to
00838                 a file with suffix "suffix".
00839         */
00840         register char *sfx = pinf->p_from;
00841         int l;
00842 
00843         if (! suffix) return 0;
00844         l = strlen(suffix);
00845         while (*sfx) {
00846                 register char *p = sfx;
00847 
00848                 while (*p && *p != ',') p++;
00849                 if (l == p - sfx && strncmp(sfx, suffix, l) == 0) {
00850                         return 1;
00851                 }
00852                 if (*p == ',') sfx = p+1;
00853                 else sfx = p;
00854         }
00855         return 0;
00856 }
00857                 
00858 char *
00859 process(name, noremove)
00860         char *name;
00861 {
00862         register struct compile *cp = passes;
00863         char *suffix = extension(name);
00864         USTRING base;
00865         register struct pass *pass;
00866         register struct passinfo *pinf;
00867 
00868         if (E_flag) {
00869                 /* -E uses the cpp pass. */
00870                 suffix = "CPP";
00871         }
00872 
00873         if (! suffix) return name;
00874 
00875         basename(name, base);
00876 
00877         while (cp->c_suffix) {
00878                 if ((cp->c_flags & DEFLANG) &&
00879                     strcmp(cp->c_suffix, suffix) == 0)
00880                         break;
00881                 cp++;
00882         }
00883         if (! cp->c_suffix) cp = compbase;
00884         pass = cp->c_passes;
00885         while (pass->pp_name) {
00886                 int first = 1;
00887 
00888                 for (pinf=passinfo; strcmp(pass->pp_name,pinf->p_name);pinf++)
00889                         ;
00890                 if (! (pinf->p_flags & LOADER) && applicable(pinf, suffix)) {
00891                         int cont = ! stopsuffix || ! pinf->p_to ||
00892                                         strcmp(stopsuffix, pinf->p_to) != 0;
00893                         name = apply(pinf,
00894                                      cp,
00895                                      name,
00896                                      (int) (pass - cp->c_passes),
00897                                      noremove,
00898                                      first,
00899                                      applicable(loaderinfo, pinf->p_to) ||
00900                                       !cont ?
00901                                         strcat(base, ".") :
00902                                         tmpname);
00903                         first = noremove = 0;
00904                         suffix = pinf->p_to;
00905                         if (!cont || !name) break;
00906                 }
00907                 pass++;
00908         }
00909         if (!noremove && name)
00910                 append(&GEN_LDFILES, name);
00911         return name;
00912 }
00913 
00914 mkvec(call, in, out, pass, pinf)
00915         struct arglist *call;
00916         char *in, *out;
00917         struct pass *pass;
00918         register struct passinfo *pinf;
00919 {
00920         register int i;
00921 
00922         init(call);
00923         append(call, pinf->p_path);
00924         scanflags(call, pinf);
00925         if (pass) for (i = 0; i < MAXHEAD; i++)
00926                 if (pass->pp_head[i])
00927                         append(call, pass->pp_head[i]);
00928                 else    break;
00929         if (pinf->p_flags & INPUT && strcmp(in, "-") != 0)
00930                 append(call, in);
00931         if (pinf->p_flags & OUTPUT)
00932                 append(call, out);
00933         if (pinf->p_flags & O_OUTPUT) {
00934                 append(call, "-o");
00935                 append(call, out);
00936         }
00937         if (pass) for (i = 0; i < MAXTAIL; i++)
00938                 if (pass->pp_tail[i])
00939                         append(call, pass->pp_tail[i]);
00940                 else    break;
00941 }
00942 
00943 callld(in, out, pass, pinf)
00944         struct arglist *in;
00945         char *out;
00946         struct pass *pass;
00947         register struct passinfo *pinf;
00948 {
00949         struct arglist *call = &CALLVEC;
00950         register int i;
00951 
00952         init(call);
00953         append(call, pinf->p_path);
00954         scanflags(call, pinf);
00955         append(call, "-o");
00956         append(call, out);
00957         for (i = 0; i < MAXHEAD; i++)
00958                 if (pass->pp_head[i])
00959                         append(call, pass->pp_head[i]);
00960                 else    break;
00961         if (pinf->p_flags & INPUT)
00962                 concat(call, in);
00963         if (pinf->p_flags & OUTPUT)
00964                 append(call, out);
00965         for (i = 0; i < MAXTAIL; i++) {
00966                 if (pass->pp_tail[i]) {
00967                         if (pass->pp_tail[i][0] == '-' &&
00968                             pass->pp_tail[i][1] == 'l') {
00969                                 append(call, library(&(pass->pp_tail[i][2])));
00970                         }
00971                         else if (*(pass->pp_tail[i]) != '*')
00972                                 append(call, pass->pp_tail[i]);
00973                         else if (fp_lib)
00974                                 append(call, library("fp"));
00975                 } else  break;
00976         }
00977         if (! runvec(call, pinf, (char *) 0, out)) {
00978                 cleanup(out);
00979                 RET_CODE = 1;
00980         }
00981 }
00982 
00983 clean(c)
00984         register struct arglist *c;
00985 {
00986         register int i;
00987 
00988         for (i = 1; i < c->al_argc; i++) {
00989                 free(c->al_argv[i]);
00990                 c->al_argv[i] = 0;
00991         }
00992         c->al_argc = 0;
00993 }
00994 
00995 scanflags(call, pinf)
00996         struct arglist *call;
00997         struct passinfo *pinf;
00998 {
00999         /*      Find out which flags from FLAGS must be passed to pass "pinf",
01000                 and how. 
01001                 Append them to "call"
01002         */
01003         register int i;
01004         USTRING flg;
01005 
01006         for (i = 0; i < FLAGS.al_argc; i++) {
01007                 register char *q = pinf->p_acceptflags;
01008 
01009                 while (*q)  {
01010                         register char *p = FLAGS.al_argv[i] + 1;
01011 
01012                         while (*q && *q == *p) {
01013                                 q++; p++;
01014                         }
01015                         if (*q == ',' || !*q) {
01016                                 if (! *p) {
01017                                         /* append literally */
01018                                         append(call, FLAGS.al_argv[i]);
01019                                 }
01020                                 break;
01021                         }
01022                         if (*q == '*') {
01023                                 register char *s = flg;
01024 
01025                                 if (*++q != '=') {
01026                                         /* append literally */
01027                                         append(call, FLAGS.al_argv[i]);
01028                                         break;
01029                                 }
01030                                 *s++ = '-';
01031                                 if (*q) q++;    /* skip ',' */
01032                                 while (*q && *q != ',' && *q != '*') {
01033                                         /* copy replacement flag */
01034                                         *s++ = *q++;
01035                                 }
01036                                 if (*q == '*') {
01037                                         /* copy rest */
01038                                         while (*p) *s++ = *p++;
01039                                 }
01040                                 *s = 0;
01041                                 append(call, flg);
01042                                 break;
01043                         }
01044                         if (*q == '=') {
01045                                 /* copy replacement */
01046                                 register char *s = flg;
01047 
01048                                 *s++ = '-';
01049                                 q++;
01050                                 while (*q && *q != ',') *s++ = *q++;
01051                                 *s = 0;
01052                                 append(call, flg);
01053                                 break;
01054                         }
01055                         while (*q && *q++ != ',')
01056                                 ;
01057                 }
01058         }
01059 }

Generated on Fri Apr 14 22:56:56 2006 for minix by  doxygen 1.4.6