~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/tools/lcc/etc/lcc.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert
  • Date: 2007-01-20 12:28:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070120122809-2yza5ojt7nqiyiam
Tags: upstream-0.6.0
ImportĀ upstreamĀ versionĀ 0.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lcc [ option ]... [ file | -llib ]...
 
3
 * front end for the ANSI C compiler
 
4
 */
 
5
static char rcsid[] = "Id: dummy rcsid";
 
6
 
 
7
#include <stdio.h>
 
8
#include <stdarg.h>
 
9
#include <stdlib.h>
 
10
#include <string.h>
 
11
#include <assert.h>
 
12
#include <ctype.h>
 
13
#include <signal.h>
 
14
#include <unistd.h>
 
15
 
 
16
#ifndef TEMPDIR
 
17
#define TEMPDIR "/tmp"
 
18
#endif
 
19
 
 
20
typedef struct list *List;
 
21
struct list {           /* circular list nodes: */
 
22
        char *str;              /* option or file name */
 
23
        List link;              /* next list element */
 
24
};
 
25
 
 
26
static void *alloc(int);
 
27
static List append(char *,List);
 
28
extern char *basename(char *);
 
29
static int callsys(char *[]);
 
30
extern char *concat(char *, char *);
 
31
static int compile(char *, char *);
 
32
static void compose(char *[], List, List, List);
 
33
static void error(char *, char *);
 
34
static char *exists(char *);
 
35
static char *first(char *);
 
36
static int filename(char *, char *);
 
37
static List find(char *, List);
 
38
static void help(void);
 
39
static void initinputs(void);
 
40
static void interrupt(int);
 
41
static void opt(char *);
 
42
static List path2list(const char *);
 
43
extern int main(int, char *[]);
 
44
extern char *replace(const char *, int, int);
 
45
static void rm(List);
 
46
extern char *strsave(const char *);
 
47
extern char *stringf(const char *, ...);
 
48
extern int suffix(char *, char *[], int);
 
49
extern char *tempname(char *);
 
50
 
 
51
#ifndef __sun
 
52
extern int getpid(void);
 
53
#endif
 
54
 
 
55
extern char *cpp[], *include[], *com[], *as[],*ld[], inputs[], *suffixes[];
 
56
extern int option(char *);
 
57
 
 
58
static int errcnt;              /* number of errors */
 
59
static int Eflag;               /* -E specified */
 
60
static int Sflag = 1;           /* -S specified */ //for Q3 we always generate asm
 
61
static int cflag;               /* -c specified */
 
62
static int verbose;             /* incremented for each -v */
 
63
static List llist[2];           /* loader files, flags */
 
64
static List alist;              /* assembler flags */
 
65
static List clist;              /* compiler flags */
 
66
static List plist;              /* preprocessor flags */
 
67
static List ilist;              /* list of additional includes from LCCINPUTS */
 
68
static List rmlist;             /* list of files to remove */
 
69
static char *outfile;           /* ld output file or -[cS] object file */
 
70
static int ac;                  /* argument count */
 
71
static char **av;               /* argument vector */
 
72
char *tempdir = TEMPDIR;        /* directory for temporary files */
 
73
static char *progname;
 
74
static List lccinputs;          /* list of input directories */
 
75
 
 
76
extern void UpdatePaths( const char *lccBinary );
 
77
 
 
78
int main(int argc, char *argv[]) {
 
79
        int i, j, nf;
 
80
 
 
81
        progname = argv[0];
 
82
 
 
83
        UpdatePaths( progname );
 
84
 
 
85
        ac = argc + 50;
 
86
        av = alloc(ac*sizeof(char *));
 
87
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 
88
                signal(SIGINT, interrupt);
 
89
        if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
 
90
                signal(SIGTERM, interrupt);
 
91
#ifdef SIGHUP
 
92
        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 
93
                signal(SIGHUP, interrupt);
 
94
#endif
 
95
        if (getenv("TMP"))
 
96
                tempdir = getenv("TMP");
 
97
        else if (getenv("TEMP"))
 
98
                tempdir = getenv("TEMP");
 
99
        else if (getenv("TMPDIR"))
 
100
                tempdir = getenv("TMPDIR");
 
101
        assert(tempdir);
 
102
        i = strlen(tempdir);
 
103
        for (; (i > 0 && tempdir[i-1] == '/') || tempdir[i-1] == '\\'; i--)
 
104
                tempdir[i-1] = '\0';
 
105
        if (argc <= 1) {
 
106
                help();
 
107
                exit(0);
 
108
        }
 
109
        plist = append("-D__LCC__", 0);
 
110
        initinputs();
 
111
        if (getenv("LCCDIR"))
 
112
                option(stringf("-lccdir=%s", getenv("LCCDIR")));
 
113
        for (nf = 0, i = j = 1; i < argc; i++) {
 
114
                if (strcmp(argv[i], "-o") == 0) {
 
115
                        if (++i < argc) {
 
116
                                if (suffix(argv[i], suffixes, 2) >= 0) {
 
117
                                        error("-o would overwrite %s", argv[i]);
 
118
                                        exit(8);
 
119
                                }
 
120
                                outfile = argv[i];
 
121
                                continue;
 
122
                        } else {
 
123
                                error("unrecognized option `%s'", argv[i-1]);
 
124
                                exit(8);
 
125
                        }
 
126
                } else if (strcmp(argv[i], "-target") == 0) {
 
127
                        if (argv[i+1] && *argv[i+1] != '-')
 
128
                                i++;
 
129
                        continue;
 
130
                } else if (*argv[i] == '-' && argv[i][1] != 'l') {
 
131
                        opt(argv[i]);
 
132
                        continue;
 
133
                } else if (*argv[i] != '-' && suffix(argv[i], suffixes, 3) >= 0)
 
134
                        nf++;
 
135
                argv[j++] = argv[i];
 
136
        }
 
137
        if ((cflag || Sflag) && outfile && nf != 1) {
 
138
                fprintf(stderr, "%s: -o %s ignored\n", progname, outfile);
 
139
                outfile = 0;
 
140
        }
 
141
        argv[j] = 0;
 
142
        for (i = 0; include[i]; i++)
 
143
                plist = append(include[i], plist);
 
144
        if (ilist) {
 
145
                List b = ilist;
 
146
                do {
 
147
                        b = b->link;
 
148
                        plist = append(b->str, plist);
 
149
                } while (b != ilist);
 
150
        }
 
151
        ilist = 0;
 
152
        for (i = 1; argv[i]; i++)
 
153
                if (*argv[i] == '-')
 
154
                        opt(argv[i]);
 
155
                else {
 
156
                        char *name = exists(argv[i]);
 
157
                        if (name) {
 
158
                                if (strcmp(name, argv[i]) != 0
 
159
                                || (nf > 1 && suffix(name, suffixes, 3) >= 0))
 
160
                                        fprintf(stderr, "%s:\n", name);
 
161
                                filename(name, 0);
 
162
                        } else
 
163
                                error("can't find `%s'", argv[i]);
 
164
                }
 
165
        if (errcnt == 0 && !Eflag && !Sflag && !cflag && llist[1]) {
 
166
                compose(ld, llist[0], llist[1],
 
167
                        append(outfile ? outfile : concat("a", first(suffixes[4])), 0));
 
168
                if (callsys(av))
 
169
                        errcnt++;
 
170
        }
 
171
        rm(rmlist);     
 
172
        return errcnt ? EXIT_FAILURE : EXIT_SUCCESS;
 
173
}
 
174
 
 
175
/* alloc - allocate n bytes or die */
 
176
static void *alloc(int n) {
 
177
        static char *avail, *limit;
 
178
        
 
179
        n = (n + sizeof(char *) - 1)&~(sizeof(char *) - 1);
 
180
        if (n >= limit - avail) {
 
181
                avail = malloc(n + 4*1024);
 
182
                assert(avail);
 
183
                limit = avail + n + 4*1024;
 
184
        }
 
185
        avail += n;
 
186
        return avail - n;
 
187
}
 
188
 
 
189
/* append - append a node with string str onto list, return new list */ 
 
190
static List append(char *str, List list) {
 
191
        List p = alloc(sizeof *p);
 
192
 
 
193
        p->str = str;
 
194
        if (list) {
 
195
                p->link = list->link;
 
196
                list->link = p;
 
197
        } else
 
198
                p->link = p;
 
199
        return p;
 
200
}
 
201
 
 
202
/* basename - return base name for name, e.g. /usr/drh/foo.c => foo */
 
203
char *basename(char *name) {
 
204
        char *s, *b, *t = 0;
 
205
 
 
206
        for (b = s = name; *s; s++)
 
207
                if (*s == '/' || *s == '\\') {
 
208
                        b = s + 1;
 
209
                        t = 0;
 
210
                } else if (*s == '.')
 
211
                        t = s;
 
212
        s = strsave(b);
 
213
        if (t)
 
214
                s[t-b] = 0;
 
215
        return s;
 
216
}
 
217
 
 
218
#ifdef WIN32
 
219
#include <process.h>
 
220
#else
 
221
#define _P_WAIT 0
 
222
#ifndef __sun
 
223
extern int fork(void);
 
224
#endif
 
225
extern int wait(int *);
 
226
 
 
227
static int _spawnvp(int mode, const char *cmdname, char *argv[]) {
 
228
        int pid, n, status;
 
229
 
 
230
        switch (pid = fork()) {
 
231
        case -1:
 
232
                fprintf(stderr, "%s: no more processes\n", progname);
 
233
                return 100;
 
234
        case 0:
 
235
                // TTimo removing hardcoded paths, searching in $PATH
 
236
                execvp(cmdname, argv);
 
237
                fprintf(stderr, "%s: ", progname);
 
238
                perror(cmdname);
 
239
                fflush(stdout);
 
240
                exit(100);
 
241
        }
 
242
        while ((n = wait(&status)) != pid && n != -1)
 
243
                ;
 
244
        if (n == -1)
 
245
                status = -1;
 
246
        if (status&0377) {
 
247
                fprintf(stderr, "%s: fatal error in %s\n", progname, cmdname);
 
248
                status |= 0400;
 
249
        }
 
250
        return (status>>8)&0377;
 
251
}
 
252
#endif
 
253
 
 
254
/* callsys - execute the command described by av[0...], return status */
 
255
static int callsys(char **av) {
 
256
        int i, status = 0;
 
257
        static char **argv;
 
258
        static int argc;
 
259
        char *executable;
 
260
 
 
261
        for (i = 0; av[i] != NULL; i++)
 
262
                ;
 
263
        if (i + 1 > argc) {
 
264
                argc = i + 1;
 
265
                if (argv == NULL)
 
266
                        argv = malloc(argc*sizeof *argv);
 
267
                else
 
268
                        argv = realloc(argv, argc*sizeof *argv);
 
269
                assert(argv);
 
270
        }
 
271
        for (i = 0; status == 0 && av[i] != NULL; ) {
 
272
                int j = 0;
 
273
                char *s = NULL;
 
274
                for ( ; av[i] != NULL && (s = strchr(av[i], '\n')) == NULL; i++)
 
275
                        argv[j++] = av[i];
 
276
                if (s != NULL) {
 
277
                        if (s > av[i])
 
278
                                argv[j++] = stringf("%.*s", s - av[i], av[i]);
 
279
                        if (s[1] != '\0')
 
280
                                av[i] = s + 1;
 
281
                        else
 
282
                                i++;
 
283
                }
 
284
                argv[j] = NULL;
 
285
                executable = strsave( argv[0] );
 
286
                argv[0] = stringf( "\"%s\"", argv[0] );
 
287
                if (verbose > 0) {
 
288
                        int k;
 
289
                        fprintf(stderr, "%s", argv[0]);
 
290
                        for (k = 1; argv[k] != NULL; k++)
 
291
                                fprintf(stderr, " %s", argv[k]);
 
292
                        fprintf(stderr, "\n");
 
293
                }
 
294
                if (verbose < 2)
 
295
#ifndef WIN32
 
296
                        status = _spawnvp(_P_WAIT, executable, argv);
 
297
#else
 
298
                        status = _spawnvp(_P_WAIT, executable, (const char* const*)argv);
 
299
#endif
 
300
                if (status == -1) {
 
301
                        fprintf(stderr, "%s: ", progname);
 
302
                        perror(argv[0]);
 
303
                }
 
304
        }
 
305
        return status;
 
306
}
 
307
 
 
308
/* concat - return concatenation of strings s1 and s2 */
 
309
char *concat(char *s1, char *s2) {
 
310
        int n = strlen(s1);
 
311
        char *s = alloc(n + strlen(s2) + 1);
 
312
 
 
313
        strcpy(s, s1);
 
314
        strcpy(s + n, s2);
 
315
        return s;
 
316
}
 
317
 
 
318
/* compile - compile src into dst, return status */
 
319
static int compile(char *src, char *dst) {
 
320
        compose(com, clist, append(src, 0), append(dst, 0));
 
321
        return callsys(av);
 
322
}
 
323
 
 
324
/* compose - compose cmd into av substituting a, b, c for $1, $2, $3, resp. */
 
325
static void compose(char *cmd[], List a, List b, List c) {
 
326
        int i, j;
 
327
        List lists[3];
 
328
 
 
329
        lists[0] = a;
 
330
        lists[1] = b;
 
331
        lists[2] = c;
 
332
        for (i = j = 0; cmd[i]; i++) {
 
333
                char *s = strchr(cmd[i], '$');
 
334
                if (s && isdigit(s[1])) {
 
335
                        int k = s[1] - '0';
 
336
                        assert(k >=1 && k <= 3);
 
337
                        if ((b = lists[k-1])) {
 
338
                                b = b->link;
 
339
                                av[j] = alloc(strlen(cmd[i]) + strlen(b->str) - 1);
 
340
                                strncpy(av[j], cmd[i], s - cmd[i]);
 
341
                                av[j][s-cmd[i]] = '\0';
 
342
                                strcat(av[j], b->str);
 
343
                                strcat(av[j++], s + 2);
 
344
                                while (b != lists[k-1]) {
 
345
                                        b = b->link;
 
346
                                        assert(j < ac);
 
347
                                        av[j++] = b->str;
 
348
                                };
 
349
                        }
 
350
                } else if (*cmd[i]) {
 
351
                        assert(j < ac);
 
352
                        av[j++] = cmd[i];
 
353
                }
 
354
        }
 
355
        av[j] = NULL;
 
356
}
 
357
 
 
358
/* error - issue error msg according to fmt, bump error count */
 
359
static void error(char *fmt, char *msg) {
 
360
        fprintf(stderr, "%s: ", progname);
 
361
        fprintf(stderr, fmt, msg);
 
362
        fprintf(stderr, "\n");
 
363
        errcnt++;
 
364
}
 
365
 
 
366
/* exists - if `name' readable return its path name or return null */
 
367
static char *exists(char *name) {
 
368
        List b;
 
369
 
 
370
        if ( (name[0] == '/' || name[0] == '\\' || name[2] == ':')
 
371
        && access(name, 4) == 0)
 
372
                return name;
 
373
        if (!(name[0] == '/' || name[0] == '\\' || name[2] == ':')
 
374
        && (b = lccinputs))             
 
375
                do {
 
376
                        b = b->link;
 
377
                        if (b->str[0]) {
 
378
                                char buf[1024];
 
379
                                sprintf(buf, "%s/%s", b->str, name);
 
380
                                if (access(buf, 4) == 0)
 
381
                                        return strsave(buf);
 
382
                        } else if (access(name, 4) == 0)
 
383
                                return name;
 
384
                } while (b != lccinputs);
 
385
        if (verbose > 1)
 
386
                return name;
 
387
        return 0;
 
388
}
 
389
 
 
390
/* first - return first component in semicolon separated list */
 
391
static char *first(char *list) {
 
392
        char *s = strchr(list, ';');
 
393
 
 
394
        if (s) {
 
395
                char buf[1024];
 
396
                strncpy(buf, list, s-list);
 
397
                buf[s-list] = '\0';
 
398
                return strsave(buf);
 
399
        } else
 
400
                return list;
 
401
}
 
402
 
 
403
/* filename - process file name argument `name', return status */
 
404
static int filename(char *name, char *base) {
 
405
        int status = 0;
 
406
        static char *stemp, *itemp;
 
407
 
 
408
        if (base == 0)
 
409
                base = basename(name);
 
410
        switch (suffix(name, suffixes, 4)) {
 
411
        case 0: /* C source files */
 
412
                compose(cpp, plist, append(name, 0), 0);
 
413
                if (Eflag) {
 
414
                        status = callsys(av);
 
415
                        break;
 
416
                }
 
417
                if (itemp == NULL)
 
418
                        itemp = tempname(first(suffixes[1]));
 
419
                compose(cpp, plist, append(name, 0), append(itemp, 0));
 
420
                status = callsys(av);
 
421
                if (status == 0)
 
422
                        return filename(itemp, base);
 
423
                break;
 
424
        case 1: /* preprocessed source files */
 
425
                if (Eflag)
 
426
                        break;
 
427
                if (Sflag)
 
428
                        status = compile(name, outfile ? outfile : concat(base, first(suffixes[2])));
 
429
                else if ((status = compile(name, stemp?stemp:(stemp=tempname(first(suffixes[2]))))) == 0)
 
430
                        return filename(stemp, base);
 
431
                break;
 
432
        case 2: /* assembly language files */
 
433
                if (Eflag)
 
434
                        break;
 
435
                if (!Sflag) {
 
436
                        char *ofile;
 
437
                        if (cflag && outfile)
 
438
                                ofile = outfile;
 
439
                        else if (cflag)
 
440
                                ofile = concat(base, first(suffixes[3]));
 
441
                        else
 
442
                                ofile = tempname(first(suffixes[3]));
 
443
                        compose(as, alist, append(name, 0), append(ofile, 0));
 
444
                        status = callsys(av);
 
445
                        if (!find(ofile, llist[1]))
 
446
                                llist[1] = append(ofile, llist[1]);
 
447
                }
 
448
                break;
 
449
        case 3: /* object files */
 
450
                if (!find(name, llist[1]))
 
451
                        llist[1] = append(name, llist[1]);
 
452
                break;
 
453
        default:
 
454
                if (Eflag) {
 
455
                        compose(cpp, plist, append(name, 0), 0);
 
456
                        status = callsys(av);
 
457
                }
 
458
                llist[1] = append(name, llist[1]);
 
459
                break;
 
460
        }
 
461
        if (status)
 
462
                errcnt++;
 
463
        return status;
 
464
}
 
465
 
 
466
/* find - find 1st occurrence of str in list, return list node or 0 */
 
467
static List find(char *str, List list) {
 
468
        List b;
 
469
        
 
470
        if ((b = list))
 
471
                do {
 
472
                        if (strcmp(str, b->str) == 0)
 
473
                                return b;
 
474
                } while ((b = b->link) != list);
 
475
        return 0;
 
476
}
 
477
 
 
478
/* help - print help message */
 
479
static void help(void) {
 
480
        static char *msgs[] = {
 
481
"", " [ option | file ]...\n",
 
482
"       except for -l, options are processed left-to-right before files\n",
 
483
"       unrecognized options are taken to be linker options\n",
 
484
"-A     warn about nonANSI usage; 2nd -A warns more\n",
 
485
"-b     emit expression-level profiling code; see bprint(1)\n",
 
486
#ifdef sparc
 
487
"-Bstatic -Bdynamic     specify static or dynamic libraries\n",
 
488
#endif
 
489
"-Bdir/ use the compiler named `dir/rcc'\n",
 
490
"-c     compile only\n",
 
491
"-dn    set switch statement density to `n'\n",
 
492
"-Dname -Dname=def      define the preprocessor symbol `name'\n",
 
493
"-E     run only the preprocessor on the named C programs and unsuffixed files\n",
 
494
"-g     produce symbol table information for debuggers\n",
 
495
"-help or -?    print this message\n",
 
496
"-Idir  add `dir' to the beginning of the list of #include directories\n",      
 
497
"-lx    search library `x'\n",
 
498
"-N     do not search the standard directories for #include files\n",
 
499
"-n     emit code to check for dereferencing zero pointers\n",
 
500
"-O     is ignored\n",
 
501
"-o file        leave the output in `file'\n",
 
502
"-P     print ANSI-style declarations for globals\n",
 
503
"-p -pg emit profiling code; see prof(1) and gprof(1)\n",
 
504
"-S     compile to assembly language\n",
 
505
#ifdef linux
 
506
"-static        specify static libraries (default is dynamic)\n",
 
507
#endif
 
508
"-t -tname      emit function tracing calls to printf or to `name'\n",
 
509
"-target name   is ignored\n",
 
510
"-tempdir=dir   place temporary files in `dir/'", "\n"
 
511
"-Uname undefine the preprocessor symbol `name'\n",
 
512
"-v     show commands as they are executed; 2nd -v suppresses execution\n",
 
513
"-w     suppress warnings\n",
 
514
"-Woarg specify system-specific `arg'\n",
 
515
"-W[pfal]arg    pass `arg' to the preprocessor, compiler, assembler, or linker\n",
 
516
        0 };
 
517
        int i;
 
518
        char *s;
 
519
 
 
520
        msgs[0] = progname;
 
521
        for (i = 0; msgs[i]; i++) {
 
522
                fprintf(stderr, "%s", msgs[i]);
 
523
                if (strncmp("-tempdir", msgs[i], 8) == 0 && tempdir)
 
524
                        fprintf(stderr, "; default=%s", tempdir);
 
525
        }
 
526
#define xx(v) if ((s = getenv(#v))) fprintf(stderr, #v "=%s\n", s)
 
527
        xx(LCCINPUTS);
 
528
        xx(LCCDIR);
 
529
#ifdef WIN32
 
530
        xx(include);
 
531
        xx(lib);
 
532
#endif
 
533
#undef xx
 
534
}
 
535
 
 
536
/* initinputs - if LCCINPUTS or include is defined, use them to initialize various lists */
 
537
static void initinputs(void) {
 
538
        char *s = getenv("LCCINPUTS");
 
539
        List b;
 
540
#ifdef WIN32
 
541
        List list;
 
542
#endif
 
543
 
 
544
        if (s == 0 || (s = inputs)[0] == 0)
 
545
                s = ".";
 
546
        if (s) {
 
547
                lccinputs = path2list(s);
 
548
                if ((b = lccinputs))
 
549
                        do {
 
550
                                b = b->link;
 
551
                                if (strcmp(b->str, ".") != 0) {
 
552
                                        ilist = append(concat("-I", b->str), ilist);
 
553
                                        if (strstr(com[1], "win32") == NULL)
 
554
                                                llist[0] = append(concat("-L", b->str), llist[0]);
 
555
                                } else
 
556
                                        b->str = "";
 
557
                        } while (b != lccinputs);
 
558
        }
 
559
#ifdef WIN32
 
560
        if ((list = b = path2list(getenv("include"))))
 
561
                do {
 
562
                        b = b->link;
 
563
                        ilist = append(stringf("-I\"%s\"", b->str), ilist);
 
564
                } while (b != list);
 
565
#endif
 
566
}
 
567
 
 
568
/* interrupt - catch interrupt signals */
 
569
static void interrupt(int n) {
 
570
        rm(rmlist);
 
571
        exit(n = 100);
 
572
}
 
573
 
 
574
/* opt - process option in arg */
 
575
static void opt(char *arg) {
 
576
        switch (arg[1]) {       /* multi-character options */
 
577
        case 'W':       /* -Wxarg */
 
578
                if (arg[2] && arg[3])
 
579
                        switch (arg[2]) {
 
580
                        case 'o':
 
581
                                if (option(&arg[3]))
 
582
                                        return;
 
583
                                break;
 
584
                        case 'p':
 
585
                                plist = append(&arg[3], plist);
 
586
                                return;
 
587
                        case 'f':
 
588
                                if (strcmp(&arg[3], "-C") || option("-b")) {
 
589
                                        clist = append(&arg[3], clist);
 
590
                                        return;
 
591
                                }
 
592
                                break; /* and fall thru */
 
593
                        case 'a':
 
594
                                alist = append(&arg[3], alist);
 
595
                                return;
 
596
                        case 'l':
 
597
                                llist[0] = append(&arg[3], llist[0]);
 
598
                                return;
 
599
                        }
 
600
                fprintf(stderr, "%s: %s ignored\n", progname, arg);
 
601
                return;
 
602
        case 'd':       /* -dn */
 
603
                arg[1] = 's';
 
604
                clist = append(arg, clist);
 
605
                return;
 
606
        case 't':       /* -t -tname -tempdir=dir */
 
607
                if (strncmp(arg, "-tempdir=", 9) == 0)
 
608
                        tempdir = arg + 9;
 
609
                else
 
610
                        clist = append(arg, clist);
 
611
                return;
 
612
        case 'p':       /* -p -pg */
 
613
                if (option(arg))
 
614
                        clist = append(arg, clist);
 
615
                else
 
616
                        fprintf(stderr, "%s: %s ignored\n", progname, arg);
 
617
                return;
 
618
        case 'D':       /* -Dname -Dname=def */
 
619
        case 'U':       /* -Uname */
 
620
        case 'I':       /* -Idir */
 
621
                plist = append(arg, plist);
 
622
                return;
 
623
        case 'B':       /* -Bdir -Bstatic -Bdynamic */
 
624
#ifdef sparc
 
625
                if (strcmp(arg, "-Bstatic") == 0 || strcmp(arg, "-Bdynamic") == 0)
 
626
                        llist[1] = append(arg, llist[1]);
 
627
                else
 
628
#endif  
 
629
                {
 
630
                static char *path;
 
631
                if (path)
 
632
                        error("-B overwrites earlier option", 0);
 
633
                path = arg + 2;
 
634
                if (strstr(com[1], "win32") != NULL)
 
635
                        com[0] = concat(replace(path, '/', '\\'), concat("rcc", first(suffixes[4])));
 
636
                else
 
637
                        com[0] = concat(path, "rcc");
 
638
                if (path[0] == 0)
 
639
                        error("missing directory in -B option", 0);
 
640
                }
 
641
                return;
 
642
        case 'h':
 
643
                if (strcmp(arg, "-help") == 0) {
 
644
                        static int printed = 0;
 
645
        case '?':
 
646
                        if (!printed)
 
647
                                help();
 
648
                        printed = 1;
 
649
                        return;
 
650
                }
 
651
#ifdef linux
 
652
        case 's':
 
653
                if (strcmp(arg,"-static") == 0) {
 
654
                        if (!option(arg))
 
655
                                fprintf(stderr, "%s: %s ignored\n", progname, arg);
 
656
                        return;
 
657
                }
 
658
#endif         
 
659
        }
 
660
        if (arg[2] == 0)
 
661
                switch (arg[1]) {       /* single-character options */
 
662
                case 'S':
 
663
                        Sflag++;
 
664
                        return;
 
665
                case 'O':
 
666
                        fprintf(stderr, "%s: %s ignored\n", progname, arg);
 
667
                        return;
 
668
                case 'A': case 'n': case 'w': case 'P':
 
669
                        clist = append(arg, clist);
 
670
                        return;
 
671
                case 'g': case 'b':
 
672
                        if (option(arg))
 
673
                                clist = append(arg[1] == 'g' ? "-g2" : arg, clist);
 
674
                        else
 
675
                                fprintf(stderr, "%s: %s ignored\n", progname, arg);
 
676
                        return;
 
677
                case 'G':
 
678
                        if (option(arg)) {
 
679
                                clist = append("-g3", clist);
 
680
                                llist[0] = append("-N", llist[0]);
 
681
                        } else
 
682
                                fprintf(stderr, "%s: %s ignored\n", progname, arg);
 
683
                        return;
 
684
                case 'E':
 
685
                        Eflag++;
 
686
                        return;
 
687
                case 'c':
 
688
                        cflag++;
 
689
                        return;
 
690
                case 'N':
 
691
                        if (strcmp(basename(cpp[0]), "gcc-cpp") == 0)
 
692
                                plist = append("-nostdinc", plist);
 
693
                        include[0] = 0;
 
694
                        ilist = 0;
 
695
                        return;
 
696
                case 'v':
 
697
                        if (verbose++ == 0) {
 
698
                                if (strcmp(basename(cpp[0]), "gcc-cpp") == 0)
 
699
                                        plist = append(arg, plist);
 
700
                                clist = append(arg, clist);
 
701
                                fprintf(stderr, "%s %s\n", progname, rcsid);
 
702
                        }
 
703
                        return;
 
704
                }
 
705
        if (cflag || Sflag || Eflag)
 
706
                fprintf(stderr, "%s: %s ignored\n", progname, arg);
 
707
        else
 
708
                llist[1] = append(arg, llist[1]);
 
709
}
 
710
 
 
711
/* path2list - convert a colon- or semicolon-separated list to a list */
 
712
static List path2list(const char *path) {
 
713
        List list = NULL;
 
714
        char sep = ':';
 
715
 
 
716
        if (path == NULL)
 
717
                return NULL;
 
718
        if (strchr(path, ';'))
 
719
                sep = ';';
 
720
        while (*path) {
 
721
                char *p, buf[512];
 
722
                if ((p = strchr(path, sep))) {
 
723
                        assert(p - path < sizeof buf);
 
724
                        strncpy(buf, path, p - path);
 
725
                        buf[p-path] = '\0';
 
726
                } else {
 
727
                        assert(strlen(path) < sizeof buf);
 
728
                        strcpy(buf, path);
 
729
                }
 
730
                if (!find(buf, list))
 
731
                        list = append(strsave(buf), list);
 
732
                if (p == 0)
 
733
                        break;
 
734
                path = p + 1;
 
735
        }
 
736
        return list;
 
737
}
 
738
 
 
739
/* replace - copy str, then replace occurrences of from with to, return the copy */
 
740
char *replace(const char *str, int from, int to) {
 
741
        char *s = strsave(str), *p = s;
 
742
 
 
743
        for ( ; (p = strchr(p, from)) != NULL; p++)
 
744
                *p = to;
 
745
        return s;
 
746
}
 
747
 
 
748
/* rm - remove files in list */
 
749
static void rm(List list) {
 
750
        if (list) {
 
751
                List b = list;
 
752
                if (verbose)
 
753
                        fprintf(stderr, "rm");
 
754
                do {
 
755
                        if (verbose)
 
756
                                fprintf(stderr, " %s", b->str);
 
757
                        if (verbose < 2)
 
758
                                remove(b->str);
 
759
                } while ((b = b->link) != list);
 
760
                if (verbose)
 
761
                        fprintf(stderr, "\n");
 
762
        }
 
763
}
 
764
 
 
765
/* strsave - return a saved copy of string str */
 
766
char *strsave(const char *str) {
 
767
        return strcpy(alloc(strlen(str)+1), str);
 
768
}
 
769
 
 
770
/* stringf - format and return a string */
 
771
char *stringf(const char *fmt, ...) {
 
772
        char buf[1024];
 
773
        va_list ap;
 
774
        int n;
 
775
 
 
776
        va_start(ap, fmt);
 
777
        n = vsprintf(buf, fmt, ap);
 
778
        va_end(ap);
 
779
        return strsave(buf);
 
780
}
 
781
 
 
782
/* suffix - if one of tails[0..n-1] holds a proper suffix of name, return its index */
 
783
int suffix(char *name, char *tails[], int n) {
 
784
        int i, len = strlen(name);
 
785
 
 
786
        for (i = 0; i < n; i++) {
 
787
                char *s = tails[i], *t;
 
788
                for ( ; (t = strchr(s, ';')); s = t + 1) {
 
789
                        int m = t - s;
 
790
                        if (len > m && strncmp(&name[len-m], s, m) == 0)
 
791
                                return i;
 
792
                }
 
793
                if (*s) {
 
794
                        int m = strlen(s);
 
795
                        if (len > m && strncmp(&name[len-m], s, m) == 0)
 
796
                                return i;
 
797
                }
 
798
        }
 
799
        return -1;
 
800
}
 
801
 
 
802
/* tempname - generate a temporary file name in tempdir with given suffix */
 
803
char *tempname(char *suffix) {
 
804
        static int n;
 
805
        char *name = stringf("%s/lcc%d%d%s", tempdir, getpid(), n++, suffix);
 
806
 
 
807
        if (strstr(com[1], "win32") != NULL)
 
808
                name = replace(name, '/', '\\');
 
809
        rmlist = append(name, rmlist);
 
810
        return name;
 
811
}