Commit | Line | Data |
---|---|---|
8a6fc7e1 TL |
1 | # |
2 | # include <stdio.h> | |
3 | # include <ctype.h> | |
4 | # include <signal.h> | |
5 | /* C command */ | |
6 | ||
7 | # define SBSIZE 10000 | |
8 | # define MAXINC 10 | |
9 | # define MAXFIL 100 | |
10 | # define MAXLIB 100 | |
11 | # define MAXOPT 100 | |
12 | char *tmp0; | |
13 | char *tmp1; | |
14 | char *tmp2; | |
15 | char *tmp3; | |
16 | char *tmp4; | |
17 | char *tmp5; | |
18 | char *outfile; | |
19 | char *copy(),*setsuf(); | |
20 | # define CHSPACE 1000 | |
21 | char ts[CHSPACE+50]; | |
22 | char *tsa = ts; | |
23 | char *tsp = ts; | |
24 | char *av[50]; | |
25 | char *clist[MAXFIL]; | |
26 | char *llist[MAXLIB]; | |
27 | char *alist[20]; | |
28 | int dflag; | |
29 | int pflag; | |
30 | int sflag; | |
31 | int cflag; | |
32 | int eflag; | |
33 | int gflag; | |
34 | int exflag; | |
35 | int oflag; | |
36 | int proflag; | |
37 | int noflflag; | |
38 | int exfail; | |
39 | char *chpass ; | |
40 | char *npassname ; | |
41 | char pass0[40] = "/lib/ccom"; | |
42 | char pass2[20] = "/lib/c2"; | |
43 | char passp[20] = "/lib/cpp"; | |
44 | char *pref = "/lib/crt0.o"; | |
45 | ||
46 | main(argc, argv) | |
47 | char *argv[]; { | |
48 | char *t; | |
49 | char *savetsp; | |
50 | char *assource; | |
51 | char **pv, *ptemp[MAXOPT], **pvt; | |
52 | int nc, nl, i, j, c, f20, nxo, na; | |
53 | int idexit(); | |
54 | ||
55 | i = nc = nl = f20 = nxo = 0; | |
56 | pv = ptemp; | |
57 | while(++i < argc) { | |
58 | if(*argv[i] == '-') switch (argv[i][1]) { | |
59 | default: | |
60 | goto passa; | |
61 | case 'S': | |
62 | sflag++; | |
63 | cflag++; | |
64 | break; | |
65 | case 'o': | |
66 | if (++i < argc) { | |
67 | outfile = argv[i]; | |
68 | if ((t=getsuf(outfile))=='c'||t=='o') { | |
69 | error("Would overwrite %s", outfile); | |
70 | exit(8); | |
71 | } | |
72 | } | |
73 | break; | |
74 | case 'O': | |
75 | oflag++; | |
76 | break; | |
77 | case 'p': | |
78 | proflag++; | |
79 | break; | |
80 | case 'g': | |
81 | gflag++; | |
82 | break; | |
83 | case 'E': | |
84 | exflag++; | |
85 | case 'P': | |
86 | pflag++; | |
87 | if (argv[i][1]=='P') | |
88 | fprintf(stderr, "(Warning): -P option obsolete\n"); | |
89 | *pv++ = argv[i]; | |
90 | case 'c': | |
91 | cflag++; | |
92 | break; | |
93 | ||
94 | case 'f': | |
95 | noflflag++; | |
96 | if (npassname || chpass) | |
97 | error("-f overwrites earlier option",0); | |
98 | npassname = "/lib/f"; | |
99 | chpass = "12"; | |
100 | break; | |
101 | ||
102 | case '2': | |
103 | if(argv[i][2] == '\0') | |
104 | pref = "/lib/crt2.o"; | |
105 | else { | |
106 | pref = "/lib/crt20.o"; | |
107 | f20 = 1; | |
108 | } | |
109 | break; | |
110 | case 'D': | |
111 | case 'I': | |
112 | case 'U': | |
113 | case 'C': | |
114 | *pv++ = argv[i]; | |
115 | if (pv >= ptemp+MAXOPT) | |
116 | { | |
117 | error("Too many DIUC options", 0); | |
118 | --pv; | |
119 | } | |
120 | break; | |
121 | case 't': | |
122 | if (chpass) | |
123 | error("-t overwrites earlier option",0); | |
124 | chpass = argv[i]+2; | |
125 | if (chpass[0]==0) | |
126 | chpass = "012p"; | |
127 | break; | |
128 | ||
129 | case 'B': | |
130 | if (npassname) | |
131 | error("-B overwrites earlier option", 0); | |
132 | npassname = argv[i]+2; | |
133 | if (npassname[0]==0) | |
134 | npassname = "/usr/c/o"; | |
135 | break; | |
136 | ||
137 | case 'd': | |
138 | dflag++; | |
139 | strcpyn(alist, argv[i], 19); | |
140 | break; | |
141 | } else { | |
142 | passa: | |
143 | t = argv[i]; | |
144 | if((c=getsuf(t))=='c' || c=='s'|| exflag) { | |
145 | clist[nc++] = t; | |
146 | if (nc>=MAXFIL) | |
147 | { | |
148 | error("Too many source files",0); | |
149 | exit(1); | |
150 | } | |
151 | t = setsuf(t, 'o'); | |
152 | } | |
153 | if (nodup(llist, t)) { | |
154 | llist[nl++] = t; | |
155 | if (nl >= MAXLIB) | |
156 | { | |
157 | error("Too many object/library files",0); | |
158 | exit(1); | |
159 | } | |
160 | if (getsuf(t)=='o') | |
161 | nxo++; | |
162 | } | |
163 | } | |
164 | } | |
165 | if (gflag) oflag = 0; | |
166 | if (npassname && chpass ==0) | |
167 | chpass = "012p"; | |
168 | if (chpass && npassname==0) | |
169 | npassname = "/usr/c/"; | |
170 | if (chpass) | |
171 | for (t=chpass; *t; t++) | |
172 | { | |
173 | switch (*t) | |
174 | { | |
175 | case '0': | |
176 | strcpy (pass0, npassname); | |
177 | strcat (pass0, "ccom"); | |
178 | continue; | |
179 | case '2': | |
180 | strcpy (pass2, npassname); | |
181 | strcat (pass2, "c2"); | |
182 | continue; | |
183 | case 'p': | |
184 | strcpy (passp, npassname); | |
185 | strcat (passp, "cpp"); | |
186 | continue; | |
187 | } | |
188 | } | |
189 | if (noflflag) | |
190 | pref = proflag ? "/lib/fmcrt0.o" : "/lib/fcrt0.o"; | |
191 | else if (proflag) | |
192 | pref = "/lib/mcrt0.o"; | |
193 | if(nc==0) | |
194 | goto nocom; | |
195 | if (pflag==0) { | |
196 | tmp0 = copy("/tmp/ctm0a"); | |
197 | while((c=fopen(tmp0, "r")) != NULL) { | |
198 | fclose(c); | |
199 | tmp0[9]++; | |
200 | } | |
201 | while((creat(tmp0, 0400))<0) | |
202 | tmp0[9]++; | |
203 | } | |
204 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */ | |
205 | signal(SIGINT, idexit); | |
206 | if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */ | |
207 | signal(SIGTERM, idexit); | |
208 | (tmp1 = copy(tmp0))[8] = '1'; | |
209 | (tmp2 = copy(tmp0))[8] = '2'; | |
210 | (tmp3 = copy(tmp0))[8] = '3'; | |
211 | if (oflag) | |
212 | (tmp5 = copy(tmp0))[8] = '5'; | |
213 | if (pflag==0) | |
214 | (tmp4 = copy(tmp0))[8] = '4'; | |
215 | pvt = pv; | |
216 | for (i=0; i<nc; i++) { | |
217 | if (nc>1) | |
218 | printf("%s:\n", clist[i]); | |
219 | if (getsuf(clist[i])=='s') { | |
220 | assource = clist[i]; | |
221 | goto assemble; | |
222 | } else | |
223 | assource = tmp3; | |
224 | if (pflag) | |
225 | tmp4 = setsuf(clist[i], 'i'); | |
226 | savetsp = tsp; | |
227 | av[0] = "cpp"; | |
228 | av[1] = clist[i]; | |
229 | av[2] = exflag ? "-" : tmp4; | |
230 | na = 3; | |
231 | for(pv=ptemp; pv <pvt; pv++) | |
232 | av[na++] = *pv; | |
233 | av[na++]=0; | |
234 | if (callsys(passp, av)) | |
235 | {exfail++; eflag++;} | |
236 | av[1] =tmp4; | |
237 | tsp = savetsp; | |
238 | av[0]= "ccom"; | |
239 | if (pflag || exfail) | |
240 | { | |
241 | cflag++; | |
242 | continue; | |
243 | } | |
244 | if(sflag) | |
245 | assource = tmp3 = setsuf(clist[i], 's'); | |
246 | av[2] = tmp3; | |
247 | if(oflag) | |
248 | av[2] = tmp5; | |
249 | if (proflag) { | |
250 | av[3] = "-XP"; | |
251 | av[4] = 0; | |
252 | } else | |
253 | av[3] = 0; | |
254 | if (gflag) { | |
255 | int i; | |
256 | i = av[3] ? 4 : 3; | |
257 | av[i++] = "-Xg"; | |
258 | av[i] = 0; | |
259 | } | |
260 | if (callsys(pass0, av)) { | |
261 | cflag++; | |
262 | eflag++; | |
263 | continue; | |
264 | } | |
265 | if (oflag) { | |
266 | av[0] = "c2"; | |
267 | av[1] = tmp5; | |
268 | av[2] = tmp3; | |
269 | av[3] = 0; | |
270 | if (callsys(pass2, av)) { | |
271 | unlink(tmp3); | |
272 | tmp3 = assource = tmp5; | |
273 | } else | |
274 | unlink(tmp5); | |
275 | } | |
276 | if (sflag) | |
277 | continue; | |
278 | assemble: | |
279 | av[0] = "as"; | |
280 | av[1] = "-o"; | |
281 | av[2] = setsuf(clist[i], 'o'); | |
282 | av[3] = assource; | |
283 | if (dflag) { | |
284 | av[4] = alist; | |
285 | av[5] = 0; | |
286 | } else | |
287 | av[4] = 0; | |
288 | cunlink(tmp1); | |
289 | cunlink(tmp2); | |
290 | cunlink(tmp4); | |
291 | if (callsys("/bin/as", av) > 1) { | |
292 | cflag++; | |
293 | eflag++; | |
294 | continue; | |
295 | } | |
296 | } | |
297 | nocom: | |
298 | if (cflag==0 && nl!=0) { | |
299 | i = 0; | |
300 | av[0] = "ld"; | |
301 | av[1] = "-X"; | |
302 | av[2] = pref; | |
303 | j = 3; | |
304 | if (outfile) { | |
305 | av[j++] = "-o"; | |
306 | av[j++] = outfile; | |
307 | } | |
308 | while(i<nl) | |
309 | av[j++] = llist[i++]; | |
310 | if (gflag) | |
311 | av[j++] = "-lg"; | |
312 | if(f20) | |
313 | av[j++] = "-l2"; | |
314 | else { | |
315 | av[j++] = "/lib/libc.a"; | |
316 | av[j++] = "-l"; | |
317 | } | |
318 | av[j++] = 0; | |
319 | eflag |= callsys("/bin/ld", av); | |
320 | if (nc==1 && nxo==1 && eflag==0) | |
321 | cunlink(setsuf(clist[0], 'o')); | |
322 | } | |
323 | dexit(); | |
324 | } | |
325 | ||
326 | idexit() | |
327 | { | |
328 | eflag = 100; | |
329 | dexit(); | |
330 | } | |
331 | ||
332 | dexit() | |
333 | { | |
334 | if (!pflag) { | |
335 | cunlink(tmp1); | |
336 | cunlink(tmp2); | |
337 | if (sflag==0) | |
338 | cunlink(tmp3); | |
339 | cunlink(tmp4); | |
340 | cunlink(tmp5); | |
341 | cunlink(tmp0); | |
342 | } | |
343 | exit(eflag); | |
344 | } | |
345 | ||
346 | error(s, x) | |
347 | { | |
348 | fprintf(exflag?stderr:stdout , s, x); | |
349 | putc('\n', exflag? stderr : stdout); | |
350 | exfail++; | |
351 | cflag++; | |
352 | eflag++; | |
353 | } | |
354 | ||
355 | ||
356 | ||
357 | ||
358 | getsuf(as) | |
359 | char as[]; | |
360 | { | |
361 | register int c; | |
362 | register char *s; | |
363 | register int t; | |
364 | ||
365 | s = as; | |
366 | c = 0; | |
367 | while(t = *s++) | |
368 | if (t=='/') | |
369 | c = 0; | |
370 | else | |
371 | c++; | |
372 | s -= 3; | |
373 | if (c<=14 && c>2 && *s++=='.') | |
374 | return(*s); | |
375 | return(0); | |
376 | } | |
377 | ||
378 | char * | |
379 | setsuf(as, ch) | |
380 | char as[]; | |
381 | { | |
382 | register char *s, *s1; | |
383 | ||
384 | s = s1 = copy(as); | |
385 | while(*s) | |
386 | if (*s++ == '/') | |
387 | s1 = s; | |
388 | s[-1] = ch; | |
389 | return(s1); | |
390 | } | |
391 | ||
392 | callsys(f, v) | |
393 | char f[], *v[]; { | |
394 | int t, status; | |
395 | ||
396 | if ((t=fork())==0) { | |
397 | execv(f, v); | |
398 | printf("Can't find %s\n", f); | |
399 | exit(100); | |
400 | } else | |
401 | if (t == -1) { | |
402 | printf("Try again\n"); | |
403 | return(100); | |
404 | } | |
405 | while(t!=wait(&status)); | |
406 | if ((t=(status&0377)) != 0 && t!=14) { | |
407 | if (t!=2) /* interrupt */ | |
408 | { | |
409 | printf("Fatal error in %s\n", f); | |
410 | eflag = 8; | |
411 | } | |
412 | dexit(); | |
413 | } | |
414 | return((status>>8) & 0377); | |
415 | } | |
416 | ||
417 | char * | |
418 | copy(as) | |
419 | char as[]; | |
420 | { | |
421 | register char *otsp, *s; | |
422 | int i; | |
423 | ||
424 | otsp = tsp; | |
425 | s = as; | |
426 | while(*tsp++ = *s++); | |
427 | if (tsp >tsa+CHSPACE) | |
428 | { | |
429 | tsp = tsa = i = calloc(CHSPACE+50,1); | |
430 | if (i== -1){ | |
431 | error("no space for file names"); | |
432 | dexit(8); | |
433 | } | |
434 | } | |
435 | return(otsp); | |
436 | } | |
437 | ||
438 | nodup(l, os) | |
439 | char **l, *os; | |
440 | { | |
441 | register char *t, *s; | |
442 | register int c; | |
443 | ||
444 | s = os; | |
445 | if (getsuf(s) != 'o') | |
446 | return(1); | |
447 | while(t = *l++) { | |
448 | while(c = *s++) | |
449 | if (c != *t++) | |
450 | break; | |
451 | if (*t=='\0' && c=='\0') | |
452 | return(0); | |
453 | s = os; | |
454 | } | |
455 | return(1); | |
456 | } | |
457 | ||
458 | cunlink(f) | |
459 | char *f; | |
460 | { | |
461 | if (f==0) | |
462 | return(0); | |
463 | return(unlink(f)); | |
464 | } |