1 #include <u.h>
2 #include <libc.h>
3
4 /*
5 POSIX standard c89
6
7 standard options: -c, -D name[=val], -E (preprocess to stdout),
8 -g, -L dir, -o outfile, -O, -s, -U name
9 (and operands can have -l lib interspersed)
10
11 nonstandard but specified options: -S (assembly language left in .s),
12 -Wx,arg1[,arg2...] (pass arg(s) to phase x, where x is p (cpp)
13 0 (compiler), or l (loader)
14 nonstandard options: -v (echo real commands to stdout as they execute)
15 -A: turn on ANSI prototype warnings
16 */
17
18 typedef struct Objtype {
19 char *name;
20 char *cc;
21 char *ld;
22 char *o;
23 char *oname; /* compatibility with pcc.c; unused */
24 } Objtype;
25
26 /* sync with /sys/src/cmd/pcc.c */
27 Objtype objtype[] = {
28 {"spim", "0c", "0l", "0", "0.out"},
29 {"arm", "5c", "5l", "5", "5.out"},
30 {"amd64", "6c", "6l", "6", "6.out"},
31 {"386", "8c", "8l", "8", "8.out"},
32 {"power64", "9c", "9l", "9", "9.out"},
33 {"sparc", "kc", "kl", "k", "k.out"},
34 {"power", "qc", "ql", "q", "q.out"},
35 {"mips", "vc", "vl", "v", "v.out"},
36 };
37 char *allos = "05689kqv";
38
39 enum {
40 Nobjs = (sizeof objtype)/(sizeof objtype[0]),
41 Maxlist = 2000,
42 };
43
44 typedef struct List {
45 char *strings[Maxlist];
46 int n;
47 } List;
48
49 List srcs, objs, cpp, cc, ld, ldargs, srchlibs;
50 int cflag, vflag, Eflag, Sflag, Aflag;
51
52 void append(List *, char *);
53 char *changeext(char *, char *);
54 void doexec(char *, List *);
55 void dopipe(char *, List *, char *, List *);
56 void fatal(char *);
57 Objtype *findoty(void);
58 void printlist(List *);
59 char *searchlib(char *, char*);
60
61 void
main(int argc,char * argv[])62 main(int argc, char *argv[])
63 {
64 char *s, *suf, *ccpath, *lib;
65 char *oname;
66 int haveoname = 0;
67 int i, cppn, ccn;
68 Objtype *ot;
69
70 ot = findoty();
71 oname = "a.out";
72 append(&cpp, "cpp");
73 append(&cpp, "-D__STDC__=1"); /* ANSI says so */
74 append(&cpp, "-D_POSIX_SOURCE=");
75 append(&cpp, "-N"); /* turn off standard includes */
76 append(&cc, ot->cc);
77 append(&ld, ot->ld);
78 append(&srchlibs, smprint("/%s/lib/ape", ot->name));
79 while(argc > 0) {
80 ARGBEGIN {
81 case 'c':
82 cflag = 1;
83 break;
84 case 'l':
85 lib = searchlib(ARGF(), ot->name);
86 if(!lib)
87 fprint(2, "cc: can't find library for -l\n");
88 else
89 append(&objs, lib);
90 break;
91 case 'o':
92 oname = ARGF();
93 haveoname = 1;
94 if(!oname)
95 fatal("cc: no -o argument");
96 break;
97 case 'D':
98 case 'I':
99 case 'U':
100 append(&cpp, smprint("-%c%s", ARGC(), ARGF()));
101 break;
102 case 'E':
103 Eflag = 1;
104 cflag = 1;
105 break;
106 case 's':
107 case 'g':
108 break;
109 case 'L':
110 lib = ARGF();
111 if(!lib)
112 fprint(2, "cc: no -L argument\n");
113 else
114 append(&srchlibs, lib);
115 break;
116 case 'N':
117 case 'T':
118 case 'w':
119 append(&cc, smprint("-%c", ARGC()));
120 break;
121 case 'O':
122 break;
123 case 'W':
124 s = ARGF();
125 if(s && s[1]==',') {
126 switch (s[0]) {
127 case 'p':
128 append(&cpp, s+2);
129 break;
130 case '0':
131 append(&cc, s+2);
132 break;
133 case 'l':
134 append(&ldargs, s+2);
135 break;
136 default:
137 fprint(2, "cc: pass letter after -W should be one of p0l; ignored\n");
138 }
139 } else
140 fprint(2, "cc: bad option after -W; ignored\n");
141 break;
142 case 'v':
143 vflag = 1;
144 append(&ldargs, "-v");
145 break;
146 case 'A':
147 Aflag = 1;
148 break;
149 case 'S':
150 Sflag = 1;
151 break;
152 default:
153 fprint(2, "cc: flag -%c ignored\n", ARGC());
154 break;
155 } ARGEND
156 if(!Aflag) {
157 append(&cc, "-J"); /* old/new decl mixture hack */
158 append(&cc, "-B"); /* turn off non-prototype warnings */
159 }
160 if(argc > 0) {
161 s = argv[0];
162 suf = utfrrune(s, '.');
163 if(suf) {
164 suf++;
165 if(strcmp(suf, "c") == 0) {
166 append(&srcs, s);
167 append(&objs, changeext(s, "o"));
168 } else if(strcmp(suf, "o") == 0 ||
169 strcmp(suf, ot->o) == 0 ||
170 strcmp(suf, "a") == 0 ||
171 (suf[0] == 'a' && strcmp(suf+1, ot->o) == 0)) {
172 append(&objs, s);
173 } else if(utfrune(allos, suf[0]) != 0) {
174 fprint(2, "cc: argument %s ignored: wrong architecture\n",
175 s);
176 }
177 }
178 }
179 }
180 if(objs.n == 0)
181 fatal("no files to compile or load");
182 ccpath = smprint("/bin/%s", ot->cc);
183 append(&cpp, smprint("-I/%s/include/ape", ot->name));
184 append(&cpp, "-I/sys/include/ape");
185 cppn = cpp.n;
186 ccn = cc.n;
187 for(i = 0; i < srcs.n; i++) {
188 append(&cpp, srcs.strings[i]);
189 if(Eflag)
190 doexec("/bin/cpp", &cpp);
191 else {
192 if(Sflag)
193 append(&cc, "-S");
194 else {
195 append(&cc, "-o");
196 if (haveoname && cflag)
197 append(&cc, oname);
198 else
199 append(&cc, changeext(srcs.strings[i], "o"));
200 }
201 dopipe("/bin/cpp", &cpp, ccpath, &cc);
202 }
203 cpp.n = cppn;
204 cc.n = ccn;
205 }
206 if(!cflag) {
207 append(&ld, "-o");
208 append(&ld, oname);
209 for(i = 0; i < ldargs.n; i++)
210 append(&ld, ldargs.strings[i]);
211 for(i = 0; i < objs.n; i++)
212 append(&ld, objs.strings[i]);
213 append(&ld, smprint("/%s/lib/ape/libap.a", ot->name));
214 doexec(smprint("/bin/%s", ot->ld), &ld);
215 if(objs.n == 1)
216 remove(objs.strings[0]);
217 }
218
219 exits(0);
220 }
221
222 char *
searchlib(char * s,char * objtype)223 searchlib(char *s, char *objtype)
224 {
225 char *l;
226 int i;
227
228 if(!s)
229 return 0;
230 for(i = srchlibs.n-1; i>=0; i--) {
231 l = smprint("%s/lib%s.a", srchlibs.strings[i], s);
232 if(access(l, 0) >= 0)
233 return l;
234 }
235 if(s[1] == 0)
236 switch(s[0]) {
237 case 'c':
238 l = smprint("/%s/lib/ape/libap.a", objtype);
239 break;
240 case 'm':
241 l = smprint("/%s/lib/ape/libap.a", objtype);
242 break;
243 case 'l':
244 l = smprint("/%s/lib/ape/libl.a", objtype);
245 break;
246 case 'y':
247 l = smprint("/%s/lib/ape/liby.a", objtype);
248 break;
249 default:
250 l = 0;
251 }
252 else
253 l = 0;
254 return l;
255 }
256
257 void
append(List * l,char * s)258 append(List *l, char *s)
259 {
260 if(l->n >= Maxlist-1)
261 fatal("too many arguments");
262 l->strings[l->n++] = s;
263 l->strings[l->n] = 0;
264 }
265
266 void
doexec(char * c,List * a)267 doexec(char *c, List *a)
268 {
269 Waitmsg *w;
270
271 if(vflag) {
272 printlist(a);
273 fprint(2, "\n");
274 }
275 switch(fork()) {
276 case -1:
277 fatal("fork failed");
278 case 0:
279 exec(c, a->strings);
280 fatal("exec failed");
281 }
282 if((w = wait()) == nil)
283 fatal("wait failed");
284 if(w->msg[0])
285 fatal(smprint("%s: %s", a->strings[0], w->msg));
286 free(w);
287 }
288
289 void
dopipe(char * c1,List * a1,char * c2,List * a2)290 dopipe(char *c1, List *a1, char *c2, List *a2)
291 {
292 Waitmsg *w;
293 int pid1, got;
294 int fd[2];
295
296 if(vflag) {
297 printlist(a1);
298 fprint(2, " | ");
299 printlist(a2);
300 fprint(2, "\n");
301 }
302 if(pipe(fd) < 0)
303 fatal("pipe failed");
304 switch((pid1 = fork())) {
305 case -1:
306 fatal("fork failed");
307 case 0:
308 dup(fd[0], 0);
309 close(fd[0]);
310 close(fd[1]);
311 exec(c2, a2->strings);
312 fatal("exec failed");
313 }
314 switch(fork()) {
315 case -1:
316 fatal("fork failed");
317 case 0:
318 close(0);
319 dup(fd[1], 1);
320 close(fd[0]);
321 close(fd[1]);
322 exec(c1, a1->strings);
323 fatal("exec failed");
324 }
325 close(fd[0]);
326 close(fd[1]);
327 for(got = 0; got < 2; got++) {
328 if((w = wait()) == nil)
329 fatal("wait failed");
330 if(w->msg[0])
331 fatal(smprint("%s: %s", (w->pid == pid1) ? a1->strings[0] : a2->strings[0], w->msg));
332 free(w);
333 }
334 }
335
336 Objtype *
findoty(void)337 findoty(void)
338 {
339 char *o;
340 Objtype *oty;
341
342 o = getenv("objtype");
343 if(!o)
344 fatal("no $objtype in environment");
345 for(oty = objtype; oty < &objtype[Nobjs]; oty++)
346 if(strcmp(o, oty->name) == 0)
347 return oty;
348 fatal("unknown $objtype");
349 return 0; /* shut compiler up */
350 }
351
352 void
fatal(char * msg)353 fatal(char *msg)
354 {
355 fprint(2, "cc: %s\n", msg);
356 exits(msg);
357 }
358
359 /* src ends in .something; return copy of basename with .ext added */
360 char *
changeext(char * src,char * ext)361 changeext(char *src, char *ext)
362 {
363 char *b, *e, *ans;
364
365 b = utfrrune(src, '/');
366 if(b)
367 b++;
368 else
369 b = src;
370 e = utfrrune(src, '.');
371 if(!e)
372 return 0;
373 *e = 0;
374 ans = smprint("%s.%s", b, ext);
375 *e = '.';
376 return ans;
377 }
378
379 void
printlist(List * l)380 printlist(List *l)
381 {
382 int i;
383
384 for(i = 0; i < l->n; i++) {
385 fprint(2, "%s", l->strings[i]);
386 if(i < l->n - 1)
387 fprint(2, " ");
388 }
389 }
390