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 } 388