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