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