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