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 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 * 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 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 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 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 * 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 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 * 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 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