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