Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

lcc.c

Go to the documentation of this file.
00001 /*
00002  * lcc [ option ]... [ file | -llib ]...
00003  * front end for the ANSI C compiler
00004  */
00005 static char rcsid[] = "Id: dummy rcsid";
00006 
00007 #include <stdio.h>
00008 #include <stdarg.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <assert.h>
00012 #include <ctype.h>
00013 #include <signal.h>
00014 
00015 #ifndef TEMPDIR
00016 #define TEMPDIR "/tmp"
00017 #endif
00018 
00019 typedef struct list *List;
00020 struct list {       /* circular list nodes: */
00021     char *str;      /* option or file name */
00022     List link;      /* next list element */
00023 };
00024 
00025 static void *alloc(int);
00026 static List append(char *,List);
00027 extern char *basepath(char *);
00028 static int callsys(char *[]);
00029 extern char *concat(char *, char *);
00030 static int compile(char *, char *);
00031 static void compose(char *[], List, List, List);
00032 static void error(char *, char *);
00033 static char *exists(char *);
00034 static char *first(char *);
00035 static int filename(char *, char *);
00036 static List find(char *, List);
00037 static void help(void);
00038 static void initinputs(void);
00039 static void interrupt(int);
00040 static void opt(char *);
00041 static List path2list(const char *);
00042 extern int main(int, char *[]);
00043 extern char *replace(const char *, int, int);
00044 static void rm(List);
00045 extern char *strsave(const char *);
00046 extern char *stringf(const char *, ...);
00047 extern int suffix(char *, char *[], int);
00048 extern char *tempname(char *);
00049 
00050 extern int access(char *, int);
00051 extern int getpid(void);
00052 
00053 extern char *cpp[], *include[], *com[], *as[],*ld[], inputs[], *suffixes[];
00054 extern int option(char *);
00055 
00056 static int errcnt;      /* number of errors */
00057 static int Eflag;       /* -E specified */
00058 static int Sflag;       /* -S specified */
00059 static int cflag;       /* -c specified */
00060 static int verbose;     /* incremented for each -v */
00061 static List llist[2];       /* loader files, flags */
00062 static List alist;      /* assembler flags */
00063 static List clist;      /* compiler flags */
00064 static List plist;      /* preprocessor flags */
00065 static List ilist;      /* list of additional includes from LCCINPUTS */
00066 static List rmlist;     /* list of files to remove */
00067 static char *outfile;       /* ld output file or -[cS] object file */
00068 static int ac;          /* argument count */
00069 static char **av;       /* argument vector */
00070 char *tempdir = TEMPDIR;    /* directory for temporary files */
00071 static char *progname;
00072 static List lccinputs;      /* list of input directories */
00073 
00074 main(int argc, char *argv[]) {
00075     int i, j, nf;
00076     
00077     progname = argv[0];
00078     ac = argc + 50;
00079     av = alloc(ac*sizeof(char *));
00080     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
00081         signal(SIGINT, interrupt);
00082     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
00083         signal(SIGTERM, interrupt);
00084 #ifdef SIGHUP
00085     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
00086         signal(SIGHUP, interrupt);
00087 #endif
00088     if (getenv("TMP"))
00089         tempdir = getenv("TMP");
00090     else if (getenv("TEMP"))
00091         tempdir = getenv("TEMP");
00092     else if (getenv("TMPDIR"))
00093         tempdir = getenv("TMPDIR");
00094     assert(tempdir);
00095     i = strlen(tempdir);
00096     for (; i > 0 && tempdir[i-1] == '/' || tempdir[i-1] == '\\'; i--)
00097         tempdir[i-1] = '\0';
00098     if (argc <= 1) {
00099         help();
00100         exit(0);
00101     }
00102     plist = append("-D__LCC__", 0);
00103     initinputs();
00104     if (getenv("LCCDIR"))
00105         option(stringf("-lccdir=%s", getenv("LCCDIR")));
00106     for (nf = 0, i = j = 1; i < argc; i++) {
00107         if (strcmp(argv[i], "-o") == 0) {
00108             if (++i < argc) {
00109                 if (suffix(argv[i], suffixes, 2) >= 0) {
00110                     error("-o would overwrite %s", argv[i]);
00111                     exit(8);
00112                 }
00113                 outfile = argv[i];
00114                 continue;
00115             } else {
00116                 error("unrecognized option `%s'", argv[i-1]);
00117                 exit(8);
00118             }
00119         } else if (strcmp(argv[i], "-target") == 0) {
00120             if (argv[i+1] && *argv[i+1] != '-')
00121                 i++;
00122             continue;
00123         } else if (*argv[i] == '-' && argv[i][1] != 'l') {
00124             opt(argv[i]);
00125             continue;
00126         } else if (*argv[i] != '-' && suffix(argv[i], suffixes, 3) >= 0)
00127             nf++;
00128         argv[j++] = argv[i];
00129     }
00130     if ((cflag || Sflag) && outfile && nf != 1) {
00131         fprintf(stderr, "%s: -o %s ignored\n", progname, outfile);
00132         outfile = 0;
00133     }
00134     argv[j] = 0;
00135     for (i = 0; include[i]; i++)
00136         plist = append(include[i], plist);
00137     if (ilist) {
00138         List b = ilist;
00139         do {
00140             b = b->link;
00141             plist = append(b->str, plist);
00142         } while (b != ilist);
00143     }
00144     ilist = 0;
00145     for (i = 1; argv[i]; i++)
00146         if (*argv[i] == '-')
00147             opt(argv[i]);
00148         else {
00149             char *name = exists(argv[i]);
00150             if (name) {
00151                 if (strcmp(name, argv[i]) != 0
00152                 || nf > 1 && suffix(name, suffixes, 3) >= 0)
00153                     fprintf(stderr, "%s:\n", name);
00154                 filename(name, 0);
00155             } else
00156                 error("can't find `%s'", argv[i]);
00157         }
00158     if (errcnt == 0 && !Eflag && !Sflag && !cflag && llist[1]) {
00159         compose(ld, llist[0], llist[1],
00160             append(outfile ? outfile : concat("a", first(suffixes[4])), 0));
00161         if (callsys(av))
00162             errcnt++;
00163     }
00164     rm(rmlist); 
00165     return errcnt ? EXIT_FAILURE : EXIT_SUCCESS;
00166 }
00167 
00168 /* alloc - allocate n bytes or die */
00169 static void *alloc(int n) {
00170     static char *avail, *limit;
00171     
00172     n = (n + sizeof(char *) - 1)&~(sizeof(char *) - 1);
00173     if (n >= limit - avail) {
00174         avail = malloc(n + 4*1024);
00175         assert(avail);
00176         limit = avail + n + 4*1024;
00177     }
00178     avail += n;
00179     return avail - n;
00180 }
00181 
00182 /* append - append a node with string str onto list, return new list */ 
00183 static List append(char *str, List list) {
00184     List p = alloc(sizeof *p);
00185 
00186     p->str = str;
00187     if (list) {
00188         p->link = list->link;
00189         list->link = p;
00190     } else
00191         p->link = p;
00192     return p;
00193 }
00194 
00195 /* basepath - return base name for name, e.g. /usr/drh/foo.c => foo */
00196 char *basepath(char *name) {
00197     char *s, *b, *t = 0;
00198 
00199     for (b = s = name; *s; s++)
00200         if (*s == '/' || *s == '\\') {
00201             b = s + 1;
00202             t = 0;
00203         } else if (*s == '.')
00204             t = s;
00205     s = strsave(b);
00206     if (t)
00207         s[t-b] = 0;
00208     return s;
00209 }
00210 
00211 #ifdef WIN32
00212 #include <process.h>
00213 #else
00214 #define _P_WAIT 0
00215 extern int fork(void);
00216 extern int wait(int *);
00217 extern void execv(const char *, char *[]);
00218 
00219 static int _spawnvp(int mode, const char *cmdname, char *argv[]) {
00220     int pid, n, status;
00221 
00222     switch (pid = fork()) {
00223     case -1:
00224         fprintf(stderr, "%s: no more processes\n", progname);
00225         return 100;
00226     case 0:
00227         // TTimo removing hardcoded paths, searching in $PATH
00228         execvp(cmdname, argv);
00229         fprintf(stderr, "%s: ", progname);
00230         perror(cmdname);
00231         fflush(stdout);
00232         exit(100);
00233     }
00234     while ((n = wait(&status)) != pid && n != -1)
00235         ;
00236     if (n == -1)
00237         status = -1;
00238     if (status&0377) {
00239         fprintf(stderr, "%s: fatal error in %s\n", progname, cmdname);
00240         status |= 0400;
00241     }
00242     return (status>>8)&0377;
00243 }
00244 #endif
00245 
00246 /* callsys - execute the command described by av[0...], return status */
00247 static int callsys(char **av) {
00248     int i, status = 0;
00249     static char **argv;
00250     static int argc;
00251 
00252     for (i = 0; av[i] != NULL; i++)
00253         ;
00254     if (i + 1 > argc) {
00255         argc = i + 1;
00256         if (argv == NULL)
00257             argv = malloc(argc*sizeof *argv);
00258         else
00259             argv = realloc(argv, argc*sizeof *argv);
00260         assert(argv);
00261     }
00262     for (i = 0; status == 0 && av[i] != NULL; ) {
00263         int j = 0;
00264         char *s;
00265         for ( ; av[i] != NULL && (s = strchr(av[i], '\n')) == NULL; i++)
00266             argv[j++] = av[i];
00267         if (s != NULL) {
00268             if (s > av[i])
00269                 argv[j++] = stringf("%.*s", s - av[i], av[i]);
00270             if (s[1] != '\0')
00271                 av[i] = s + 1;
00272             else
00273                 i++;
00274         }
00275         argv[j] = NULL;
00276         if (verbose > 0) {
00277             int k;
00278             fprintf(stderr, "%s", argv[0]);
00279             for (k = 1; argv[k] != NULL; k++)
00280                 fprintf(stderr, " %s", argv[k]);
00281             fprintf(stderr, "\n");
00282         }
00283         if (verbose < 2)
00284             status = _spawnvp(_P_WAIT, argv[0], argv);
00285         if (status == -1) {
00286             fprintf(stderr, "%s: ", progname);
00287             perror(argv[0]);
00288         }
00289     }
00290     return status;
00291 }
00292 
00293 /* concat - return concatenation of strings s1 and s2 */
00294 char *concat(char *s1, char *s2) {
00295     int n = strlen(s1);
00296     char *s = alloc(n + strlen(s2) + 1);
00297 
00298     strcpy(s, s1);
00299     strcpy(s + n, s2);
00300     return s;
00301 }
00302 
00303 /* compile - compile src into dst, return status */
00304 static int compile(char *src, char *dst) {
00305     compose(com, clist, append(src, 0), append(dst, 0));
00306     return callsys(av);
00307 }
00308 
00309 /* compose - compose cmd into av substituting a, b, c for $1, $2, $3, resp. */
00310 static void compose(char *cmd[], List a, List b, List c) {
00311     int i, j;
00312     List lists[3];
00313 
00314     lists[0] = a;
00315     lists[1] = b;
00316     lists[2] = c;
00317     for (i = j = 0; cmd[i]; i++) {
00318         char *s = strchr(cmd[i], '$');
00319         if (s && isdigit(s[1])) {
00320             int k = s[1] - '0';
00321             assert(k >=1 && k <= 3);
00322             if (b = lists[k-1]) {
00323                 b = b->link;
00324                 av[j] = alloc(strlen(cmd[i]) + strlen(b->str) - 1);
00325                 strncpy(av[j], cmd[i], s - cmd[i]);
00326                 av[j][s-cmd[i]] = '\0';
00327                 strcat(av[j], b->str);
00328                 strcat(av[j++], s + 2);
00329                 while (b != lists[k-1]) {
00330                     b = b->link;
00331                     assert(j < ac);
00332                     av[j++] = b->str;
00333                 };
00334             }
00335         } else if (*cmd[i]) {
00336             assert(j < ac);
00337             av[j++] = cmd[i];
00338         }
00339     }
00340     av[j] = NULL;
00341 }
00342 
00343 /* error - issue error msg according to fmt, bump error count */
00344 static void error(char *fmt, char *msg) {
00345     fprintf(stderr, "%s: ", progname);
00346     fprintf(stderr, fmt, msg);
00347     fprintf(stderr, "\n");
00348     errcnt++;
00349 }
00350 
00351 /* exists - if `name' readable return its path name or return null */
00352 static char *exists(char *name) {
00353     List b;
00354 
00355     if ( (name[0] == '/' || name[0] == '\\' || name[2] == ':')
00356     && access(name, 4) == 0)
00357         return name;
00358     if (!(name[0] == '/' || name[0] == '\\' || name[2] == ':')
00359     && (b = lccinputs))     
00360         do {
00361             b = b->link;
00362             if (b->str[0]) {
00363                 char buf[1024];
00364                 sprintf(buf, "%s/%s", b->str, name);
00365                 if (access(buf, 4) == 0)
00366                     return strsave(buf);
00367             } else if (access(name, 4) == 0)
00368                 return name;
00369         } while (b != lccinputs);
00370     if (verbose > 1)
00371         return name;
00372     return 0;
00373 }
00374 
00375 /* first - return first component in semicolon separated list */
00376 static char *first(char *list) {
00377     char *s = strchr(list, ';');
00378 
00379     if (s) {
00380         char buf[1024];
00381         strncpy(buf, list, s-list);
00382         buf[s-list] = '\0';
00383         return strsave(buf);
00384     } else
00385         return list;
00386 }
00387 
00388 /* filename - process file name argument `name', return status */
00389 static int filename(char *name, char *base) {
00390     int status = 0;
00391     static char *stemp, *itemp;
00392 
00393     if (base == 0)
00394         base = basepath(name);
00395     switch (suffix(name, suffixes, 4)) {
00396     case 0: /* C source files */
00397         compose(cpp, plist, append(name, 0), 0);
00398         if (Eflag) {
00399             status = callsys(av);
00400             break;
00401         }
00402         if (itemp == NULL)
00403             itemp = tempname(first(suffixes[1]));
00404         compose(cpp, plist, append(name, 0), append(itemp, 0));
00405         status = callsys(av);
00406         if (status == 0)
00407             return filename(itemp, base);
00408         break;
00409     case 1: /* preprocessed source files */
00410         if (Eflag)
00411             break;
00412         if (Sflag)
00413             status = compile(name, outfile ? outfile : concat(base, first(suffixes[2])));
00414         else if ((status = compile(name, stemp?stemp:(stemp=tempname(first(suffixes[2]))))) == 0)
00415             return filename(stemp, base);
00416         break;
00417     case 2: /* assembly language files */
00418         if (Eflag)
00419             break;
00420         if (!Sflag) {
00421             char *ofile;
00422             if (cflag && outfile)
00423                 ofile = outfile;
00424             else if (cflag)
00425                 ofile = concat(base, first(suffixes[3]));
00426             else
00427                 ofile = tempname(first(suffixes[3]));
00428             compose(as, alist, append(name, 0), append(ofile, 0));
00429             status = callsys(av);
00430             if (!find(ofile, llist[1]))
00431                 llist[1] = append(ofile, llist[1]);
00432         }
00433         break;
00434     case 3: /* object files */
00435         if (!find(name, llist[1]))
00436             llist[1] = append(name, llist[1]);
00437         break;
00438     default:
00439         if (Eflag) {
00440             compose(cpp, plist, append(name, 0), 0);
00441             status = callsys(av);
00442         }
00443         llist[1] = append(name, llist[1]);
00444         break;
00445     }
00446     if (status)
00447         errcnt++;
00448     return status;
00449 }
00450 
00451 /* find - find 1st occurrence of str in list, return list node or 0 */
00452 static List find(char *str, List list) {
00453     List b;
00454     
00455     if (b = list)
00456         do {
00457             if (strcmp(str, b->str) == 0)
00458                 return b;
00459         } while ((b = b->link) != list);
00460     return 0;
00461 }
00462 
00463 /* help - print help message */
00464 static void help(void) {
00465     static char *msgs[] = {
00466 "", " [ option | file ]...\n",
00467 "   except for -l, options are processed left-to-right before files\n",
00468 "   unrecognized options are taken to be linker options\n",
00469 "-A warn about nonANSI usage; 2nd -A warns more\n",
00470 "-b emit expression-level profiling code; see bprint(1)\n",
00471 #ifdef sparc
00472 "-Bstatic -Bdynamic specify static or dynamic libraries\n",
00473 #endif
00474 "-Bdir/ use the compiler named `dir/rcc'\n",
00475 "-c compile only\n",
00476 "-dn    set switch statement density to `n'\n",
00477 "-Dname -Dname=def  define the preprocessor symbol `name'\n",
00478 "-E run only the preprocessor on the named C programs and unsuffixed files\n",
00479 "-g produce symbol table information for debuggers\n",
00480 "-help or -?    print this message\n",
00481 "-Idir  add `dir' to the beginning of the list of #include directories\n",  
00482 "-lx    search library `x'\n",
00483 "-N do not search the standard directories for #include files\n",
00484 "-n emit code to check for dereferencing zero pointers\n",
00485 "-O is ignored\n",
00486 "-o file    leave the output in `file'\n",
00487 "-P print ANSI-style declarations for globals\n",
00488 "-p -pg emit profiling code; see prof(1) and gprof(1)\n",
00489 "-S compile to assembly language\n",
00490 #ifdef linux
00491 "-static    specify static libraries (default is dynamic)\n",
00492 #endif
00493 "-t -tname  emit function tracing calls to printf or to `name'\n",
00494 "-target name   is ignored\n",
00495 "-tempdir=dir   place temporary files in `dir/'", "\n"
00496 "-Uname undefine the preprocessor symbol `name'\n",
00497 "-v show commands as they are executed; 2nd -v suppresses execution\n",
00498 "-w suppress warnings\n",
00499 "-Woarg specify system-specific `arg'\n",
00500 "-W[pfal]arg    pass `arg' to the preprocessor, compiler, assembler, or linker\n",
00501     0 };
00502     int i;
00503     char *s;
00504 
00505     msgs[0] = progname;
00506     for (i = 0; msgs[i]; i++) {
00507         fprintf(stderr, "%s", msgs[i]);
00508         if (strncmp("-tempdir", msgs[i], 8) == 0 && tempdir)
00509             fprintf(stderr, "; default=%s", tempdir);
00510     }
00511 #define xx(v) if (s = getenv(#v)) fprintf(stderr, #v "=%s\n", s)
00512     xx(LCCINPUTS);
00513     xx(LCCDIR);
00514 #ifdef WIN32
00515     xx(include);
00516     xx(lib);
00517 #endif
00518 #undef xx
00519 }
00520 
00521 /* initinputs - if LCCINPUTS or include is defined, use them to initialize various lists */
00522 static void initinputs(void) {
00523     char *s = getenv("LCCINPUTS");
00524     List list, b;
00525 
00526     if (s == 0 || (s = inputs)[0] == 0)
00527         s = ".";
00528     if (s) {
00529         lccinputs = path2list(s);
00530         if (b = lccinputs)
00531             do {
00532                 b = b->link;
00533                 if (strcmp(b->str, ".") != 0) {
00534                     ilist = append(concat("-I", b->str), ilist);
00535                     if (strstr(com[1], "win32") == NULL)
00536                         llist[0] = append(concat("-L", b->str), llist[0]);
00537                 } else
00538                     b->str = "";
00539             } while (b != lccinputs);
00540     }
00541 #ifdef WIN32
00542     if (list = b = path2list(getenv("include")))
00543         do {
00544             b = b->link;
00545             ilist = append(stringf("-I\"%s\"", b->str), ilist);
00546         } while (b != list);
00547 #endif
00548 }
00549 
00550 /* interrupt - catch interrupt signals */
00551 static void interrupt(int n) {
00552     rm(rmlist);
00553     exit(n = 100);
00554 }
00555 
00556 /* opt - process option in arg */
00557 static void opt(char *arg) {
00558     switch (arg[1]) {   /* multi-character options */
00559     case 'W':   /* -Wxarg */
00560         if (arg[2] && arg[3])
00561             switch (arg[2]) {
00562             case 'o':
00563                 if (option(&arg[3]))
00564                     return;
00565                 break;
00566             case 'p':
00567                 plist = append(&arg[3], plist);
00568                 return;
00569             case 'f':
00570                 if (strcmp(&arg[3], "-C") || option("-b")) {
00571                     clist = append(&arg[3], clist);
00572                     return;
00573                 }
00574                 break; /* and fall thru */
00575             case 'a':
00576                 alist = append(&arg[3], alist);
00577                 return;
00578             case 'l':
00579                 llist[0] = append(&arg[3], llist[0]);
00580                 return;
00581             }
00582         fprintf(stderr, "%s: %s ignored\n", progname, arg);
00583         return;
00584     case 'd':   /* -dn */
00585         arg[1] = 's';
00586         clist = append(arg, clist);
00587         return;
00588     case 't':   /* -t -tname -tempdir=dir */
00589         if (strncmp(arg, "-tempdir=", 9) == 0)
00590             tempdir = arg + 9;
00591         else
00592             clist = append(arg, clist);
00593         return;
00594     case 'p':   /* -p -pg */
00595         if (option(arg))
00596             clist = append(arg, clist);
00597         else
00598             fprintf(stderr, "%s: %s ignored\n", progname, arg);
00599         return;
00600     case 'D':   /* -Dname -Dname=def */
00601     case 'U':   /* -Uname */
00602     case 'I':   /* -Idir */
00603         plist = append(arg, plist);
00604         return;
00605     case 'B':   /* -Bdir -Bstatic -Bdynamic */
00606 #ifdef sparc
00607         if (strcmp(arg, "-Bstatic") == 0 || strcmp(arg, "-Bdynamic") == 0)
00608             llist[1] = append(arg, llist[1]);
00609         else
00610 #endif  
00611         {
00612         static char *path;
00613         if (path)
00614             error("-B overwrites earlier option", 0);
00615         path = arg + 2;
00616         if (strstr(com[1], "win32") != NULL)
00617             com[0] = concat(replace(path, '/', '\\'), concat("rcc", first(suffixes[4])));
00618         else
00619             com[0] = concat(path, "rcc");
00620         if (path[0] == 0)
00621             error("missing directory in -B option", 0);
00622         }
00623         return;
00624     case 'h':
00625         if (strcmp(arg, "-help") == 0) {
00626             static int printed = 0;
00627     case '?':
00628             if (!printed)
00629                 help();
00630             printed = 1;
00631             return;
00632         }
00633 #ifdef linux
00634     case 's':
00635         if (strcmp(arg,"-static") == 0) {
00636             if (!option(arg))
00637                 fprintf(stderr, "%s: %s ignored\n", progname, arg);
00638             return;
00639         }
00640 #endif         
00641     }
00642     if (arg[2] == 0)
00643         switch (arg[1]) {   /* single-character options */
00644         case 'S':
00645             Sflag++;
00646             return;
00647         case 'O':
00648             fprintf(stderr, "%s: %s ignored\n", progname, arg);
00649             return;
00650         case 'A': case 'n': case 'w': case 'P':
00651             clist = append(arg, clist);
00652             return;
00653         case 'g': case 'b':
00654             if (option(arg))
00655                 clist = append(arg[1] == 'g' ? "-g2" : arg, clist);
00656             else
00657                 fprintf(stderr, "%s: %s ignored\n", progname, arg);
00658             return;
00659         case 'G':
00660             if (option(arg)) {
00661                 clist = append("-g3", clist);
00662                 llist[0] = append("-N", llist[0]);
00663             } else
00664                 fprintf(stderr, "%s: %s ignored\n", progname, arg);
00665             return;
00666         case 'E':
00667             Eflag++;
00668             return;
00669         case 'c':
00670             cflag++;
00671             return;
00672         case 'N':
00673             if (strcmp(basepath(cpp[0]), "gcc-cpp") == 0)
00674                 plist = append("-nostdinc", plist);
00675             include[0] = 0;
00676             ilist = 0;
00677             return;
00678         case 'v':
00679             if (verbose++ == 0) {
00680                 if (strcmp(basepath(cpp[0]), "gcc-cpp") == 0)
00681                     plist = append(arg, plist);
00682                 clist = append(arg, clist);
00683                 fprintf(stderr, "%s %s\n", progname, rcsid);
00684             }
00685             return;
00686         }
00687     if (cflag || Sflag || Eflag)
00688         fprintf(stderr, "%s: %s ignored\n", progname, arg);
00689     else
00690         llist[1] = append(arg, llist[1]);
00691 }
00692 
00693 /* path2list - convert a colon- or semicolon-separated list to a list */
00694 static List path2list(const char *path) {
00695     List list = NULL;
00696     char sep = ':';
00697 
00698     if (path == NULL)
00699         return NULL;
00700     if (strchr(path, ';'))
00701         sep = ';';
00702     while (*path) {
00703         char *p, buf[512];
00704         if (p = strchr(path, sep)) {
00705             assert(p - path < sizeof buf);
00706             strncpy(buf, path, p - path);
00707             buf[p-path] = '\0';
00708         } else {
00709             assert(strlen(path) < sizeof buf);
00710             strcpy(buf, path);
00711         }
00712         if (!find(buf, list))
00713             list = append(strsave(buf), list);
00714         if (p == 0)
00715             break;
00716         path = p + 1;
00717     }
00718     return list;
00719 }
00720 
00721 /* replace - copy str, then replace occurrences of from with to, return the copy */
00722 char *replace(const char *str, int from, int to) {
00723     char *s = strsave(str), *p = s;
00724 
00725     for ( ; (p = strchr(p, from)) != NULL; p++)
00726         *p = to;
00727     return s;
00728 }
00729 
00730 /* rm - remove files in list */
00731 static void rm(List list) {
00732     if (list) {
00733         List b = list;
00734         if (verbose)
00735             fprintf(stderr, "rm");
00736         do {
00737             if (verbose)
00738                 fprintf(stderr, " %s", b->str);
00739             if (verbose < 2)
00740                 remove(b->str);
00741         } while ((b = b->link) != list);
00742         if (verbose)
00743             fprintf(stderr, "\n");
00744     }
00745 }
00746 
00747 /* strsave - return a saved copy of string str */
00748 char *strsave(const char *str) {
00749     return strcpy(alloc(strlen(str)+1), str);
00750 }
00751 
00752 /* stringf - format and return a string */
00753 char *stringf(const char *fmt, ...) {
00754     char buf[1024];
00755     va_list ap;
00756     int n;
00757 
00758     va_start(ap, fmt);
00759     n = vsprintf(buf, fmt, ap);
00760     va_end(ap);
00761     return strsave(buf);
00762 }
00763 
00764 /* suffix - if one of tails[0..n-1] holds a proper suffix of name, return its index */
00765 int suffix(char *name, char *tails[], int n) {
00766     int i, len = strlen(name);
00767 
00768     for (i = 0; i < n; i++) {
00769         char *s = tails[i], *t;
00770         for ( ; t = strchr(s, ';'); s = t + 1) {
00771             int m = t - s;
00772             if (len > m && strncmp(&name[len-m], s, m) == 0)
00773                 return i;
00774         }
00775         if (*s) {
00776             int m = strlen(s);
00777             if (len > m && strncmp(&name[len-m], s, m) == 0)
00778                 return i;
00779         }
00780     }
00781     return -1;
00782 }
00783 
00784 /* tempname - generate a temporary file name in tempdir with given suffix */
00785 char *tempname(char *suffix) {
00786     static int n;
00787     char *name = stringf("%s/lcc%d%d%s", tempdir, getpid(), n++, suffix);
00788 
00789     if (strstr(com[1], "win32") != NULL)
00790         name = replace(name, '/', '\\');
00791     rmlist = append(name, rmlist);
00792     return name;
00793 }

Generated on Thu Aug 25 12:38:09 2005 for Quake III Arena by  doxygen 1.3.9.1