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 {"386", "8c", "8l", "8"}, 27 {"68020", "2c", "2l", "2"}, 28 {"alpha", "7c", "7l", "7"}, 29 {"mips", "vc", "vl", "v"}, 30 {"arm", "5c", "5l", "5"}, 31 {"mips2", "4c", "4l", "4"}, 32 {"power", "qc", "ql", "q"}, 33 {"sparc", "kc", "kl", "k"}, 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 = "2478kqv"; 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 append(&cc, "-N"); 116 break; 117 case 'O': 118 break; 119 case 'W': 120 s = ARGF(); 121 if(s && s[1]==',') { 122 switch (s[0]) { 123 case 'p': 124 append(&cpp, s+2); 125 break; 126 case '0': 127 append(&cc, s+2); 128 break; 129 case 'l': 130 append(&ldargs, s+2); 131 break; 132 default: 133 fprint(2, "cc: pass letter after -W should be one of p0l; ignored\n"); 134 } 135 } else 136 fprint(2, "cc: bad option after -W; ignored\n"); 137 break; 138 case 'v': 139 vflag = 1; 140 append(&ldargs, "-v"); 141 break; 142 case 'w': 143 append(&cc, "-w"); 144 break; 145 case 'A': 146 Aflag = 1; 147 break; 148 case 'S': 149 Sflag = 1; 150 break; 151 default: 152 fprint(2, "cc: flag -%c ignored\n", ARGC()); 153 break; 154 } ARGEND 155 if(!Aflag) { 156 append(&cc, "-J"); /* old/new decl mixture hack */ 157 append(&cc, "-B"); /* turn off non-prototype warnings */ 158 } 159 if(argc > 0) { 160 s = argv[0]; 161 suf = utfrrune(s, '.'); 162 if(suf) { 163 suf++; 164 if(strcmp(suf, "c") == 0) { 165 append(&srcs, s); 166 append(&objs, changeext(s, "o")); 167 } else if(strcmp(suf, "o") == 0 || 168 strcmp(suf, ot->o) == 0 || 169 strcmp(suf, "a") == 0 || 170 (suf[0] == 'a' && strcmp(suf+1, ot->o) == 0)) { 171 append(&objs, s); 172 } else if(utfrune(allos, suf[0]) != 0) { 173 fprint(2, "cc: argument %s ignored: wrong architecture\n", 174 s); 175 } 176 } 177 } 178 } 179 if(objs.n == 0) 180 fatal("no files to compile or load"); 181 ccpath = smprint("/bin/%s", ot->cc); 182 append(&cpp, smprint("-I/%s/include/ape", ot->name)); 183 append(&cpp, "-I/sys/include/ape"); 184 cppn = cpp.n; 185 ccn = cc.n; 186 for(i = 0; i < srcs.n; i++) { 187 append(&cpp, srcs.strings[i]); 188 if(Eflag) 189 doexec("/bin/cpp", &cpp); 190 else { 191 if(Sflag) 192 append(&cc, "-S"); 193 else { 194 append(&cc, "-o"); 195 if (haveoname && cflag) 196 append(&cc, oname); 197 else 198 append(&cc, changeext(srcs.strings[i], "o")); 199 } 200 dopipe("/bin/cpp", &cpp, ccpath, &cc); 201 } 202 cpp.n = cppn; 203 cc.n = ccn; 204 } 205 if(!cflag) { 206 append(&ld, "-o"); 207 append(&ld, oname); 208 for(i = 0; i < ldargs.n; i++) 209 append(&ld, ldargs.strings[i]); 210 for(i = 0; i < objs.n; i++) 211 append(&ld, objs.strings[i]); 212 append(&ld, smprint("/%s/lib/ape/libap.a", ot->name)); 213 doexec(smprint("/bin/%s", ot->ld), &ld); 214 if(objs.n == 1) 215 remove(objs.strings[0]); 216 } 217 218 exits(0); 219 } 220 221 char * 222 searchlib(char *s, char *objtype) 223 { 224 char *l; 225 int i; 226 227 if(!s) 228 return 0; 229 for(i = srchlibs.n-1; i>=0; i--) { 230 l = smprint("%s/lib%s.a", srchlibs.strings[i], s); 231 if(access(l, 0) >= 0) 232 return l; 233 } 234 if(s[1] == 0) 235 switch(s[0]) { 236 case 'c': 237 l = smprint("/%s/lib/ape/libap.a", objtype); 238 break; 239 case 'm': 240 l = smprint("/%s/lib/ape/libap.a", objtype); 241 break; 242 case 'l': 243 l = smprint("/%s/lib/ape/libl.a", objtype); 244 break; 245 case 'y': 246 l = smprint("/%s/lib/ape/liby.a", objtype); 247 break; 248 default: 249 l = 0; 250 } 251 else 252 l = 0; 253 return l; 254 } 255 256 void 257 append(List *l, char *s) 258 { 259 if(l->n >= Maxlist-1) 260 fatal("too many arguments"); 261 l->strings[l->n++] = s; 262 l->strings[l->n] = 0; 263 } 264 265 void 266 doexec(char *c, List *a) 267 { 268 Waitmsg *w; 269 270 if(vflag) { 271 printlist(a); 272 fprint(2, "\n"); 273 } 274 switch(fork()) { 275 case -1: 276 fatal("fork failed"); 277 case 0: 278 exec(c, a->strings); 279 fatal("exec failed"); 280 } 281 if((w = wait()) == nil) 282 fatal("wait failed"); 283 if(w->msg[0]) 284 fatal(smprint("%s: %s", a->strings[0], w->msg)); 285 free(w); 286 } 287 288 void 289 dopipe(char *c1, List *a1, char *c2, List *a2) 290 { 291 Waitmsg *w; 292 int pid1, got; 293 int fd[2]; 294 295 if(vflag) { 296 printlist(a1); 297 fprint(2, " | "); 298 printlist(a2); 299 fprint(2, "\n"); 300 } 301 if(pipe(fd) < 0) 302 fatal("pipe failed"); 303 switch((pid1 = fork())) { 304 case -1: 305 fatal("fork failed"); 306 case 0: 307 dup(fd[0], 0); 308 close(fd[0]); 309 close(fd[1]); 310 exec(c2, a2->strings); 311 fatal("exec failed"); 312 } 313 switch(fork()) { 314 case -1: 315 fatal("fork failed"); 316 case 0: 317 close(0); 318 dup(fd[1], 1); 319 close(fd[0]); 320 close(fd[1]); 321 exec(c1, a1->strings); 322 fatal("exec failed"); 323 } 324 close(fd[0]); 325 close(fd[1]); 326 for(got = 0; got < 2; got++) { 327 if((w = wait()) == nil) 328 fatal("wait failed"); 329 if(w->msg[0]) 330 fatal(smprint("%s: %s", (w->pid == pid1) ? a1->strings[0] : a2->strings[0], w->msg)); 331 free(w); 332 } 333 } 334 335 Objtype * 336 findoty(void) 337 { 338 char *o; 339 Objtype *oty; 340 341 o = getenv("objtype"); 342 if(!o) 343 fatal("no $objtype in environment"); 344 for(oty = objtype; oty < &objtype[Nobjs]; oty++) 345 if(strcmp(o, oty->name) == 0) 346 return oty; 347 fatal("unknown $objtype"); 348 return 0; /* shut compiler up */ 349 } 350 351 void 352 fatal(char *msg) 353 { 354 fprint(2, "cc: %s\n", msg); 355 exits(msg); 356 } 357 358 /* src ends in .something; return copy of basename with .ext added */ 359 char * 360 changeext(char *src, char *ext) 361 { 362 char *b, *e, *ans; 363 364 b = utfrrune(src, '/'); 365 if(b) 366 b++; 367 else 368 b = src; 369 e = utfrrune(src, '.'); 370 if(!e) 371 return 0; 372 *e = 0; 373 ans = smprint("%s.%s", b, ext); 374 *e = '.'; 375 return ans; 376 } 377 378 void 379 printlist(List *l) 380 { 381 int i; 382 383 for(i = 0; i < l->n; i++) { 384 fprint(2, "%s", l->strings[i]); 385 if(i < l->n - 1) 386 fprint(2, " "); 387 } 388 } 389