1 #include <u.h> 2 #include <libc.h> 3 4 5 typedef struct Objtype { 6 char *name; 7 char *cc; 8 char *ld; 9 char *o; 10 char *oname; 11 } Objtype; 12 13 /* sync with /sys/src/ape/cmd/cc.c */ 14 Objtype objtype[] = { 15 {"spim", "0c", "0l", "0", "0.out"}, 16 {"arm", "5c", "5l", "5", "5.out"}, 17 {"amd64", "6c", "6l", "6", "6.out"}, 18 {"386", "8c", "8l", "8", "8.out"}, 19 {"power64", "9c", "9l", "9", "9.out"}, 20 {"sparc", "kc", "kl", "k", "k.out"}, 21 {"power", "qc", "ql", "q", "q.out"}, 22 {"mips", "vc", "vl", "v", "v.out"}, 23 }; 24 char *allos = "05689kqv"; 25 26 enum { 27 Nobjs = (sizeof objtype)/(sizeof objtype[0]), 28 Maxlist = 2000, 29 }; 30 31 typedef struct List { 32 char *strings[Maxlist]; 33 int n; 34 } List; 35 36 List srcs, objs, cpp, cc, ld, ldargs; 37 int cflag, vflag, Eflag, Pflag; 38 39 void append(List *, char *); 40 char *changeext(char *, char *); 41 void doexec(char *, List *); 42 void dopipe(char *, List *, char *, List *); 43 void fatal(char *); 44 Objtype *findoty(void); 45 void printlist(List *); 46 47 void 48 main(int argc, char *argv[]) 49 { 50 Objtype *ot; 51 char *s, *suf, *ccpath; 52 char *oname; 53 int i, cppn, ccn, oflag; 54 55 oflag = 0; 56 ot = findoty(); 57 oname = ot->oname; 58 append(&cpp, "cpp"); 59 append(&cpp, "-D__STDC__=1"); /* ANSI says so */ 60 append(&cpp, "-N"); /* turn off standard includes */ 61 append(&cc, ot->cc); 62 append(&ld, ot->ld); 63 while(argc > 0) { 64 ARGBEGIN { 65 case '+': 66 append(&cpp, smprint("-%c", ARGC())); 67 break; 68 case 'c': 69 cflag = 1; 70 break; 71 case 'l': 72 append(&objs, smprint("/%s/lib/ape/lib%s.a", ot->name, ARGF())); 73 break; 74 case 'o': 75 oflag = 1; 76 oname = ARGF(); 77 if(!oname) 78 fatal("no -o argument"); 79 break; 80 case 'w': 81 case 'B': 82 case 'F': 83 case 'N': 84 case 'S': 85 case 'T': 86 case 'V': 87 case 'W': 88 append(&cc, smprint("-%c", ARGC())); 89 break; 90 case 's': 91 append(&cc, smprint("-s%s", ARGF())); 92 break; 93 case 'D': 94 case 'I': 95 case 'U': 96 append(&cpp, smprint("-%c%s", ARGC(), ARGF())); 97 break; 98 case 'v': 99 vflag = 1; 100 append(&ldargs, "-v"); 101 break; 102 case 'P': 103 Pflag = 1; 104 cflag = 1; 105 break; 106 case 'E': 107 Eflag = 1; 108 cflag = 1; 109 break; 110 case 'p': 111 append(&ldargs, "-p"); 112 break; 113 case 'f': 114 if(strcmp(ot->name, "arm") == 0) 115 append(&ldargs, "-f"); 116 break; 117 case 'x': 118 s = ARGF(); 119 if(s == nil || *s == '-') 120 fatal("no -x argument"); 121 append(&ldargs, smprint("-x %s", s)); 122 break; 123 case 'a': 124 /* hacky look inside ARGBEGIN insides, to see if we have -aa */ 125 if(*_args == 'a') { 126 append(&cc, "-aa"); 127 _args++; 128 } else 129 append(&cc, "-a"); 130 cflag = 1; 131 break; 132 default: 133 fprint(2, "pcc: flag -%c ignored\n", ARGC()); 134 break; 135 } ARGEND 136 if(argc > 0) { 137 s = argv[0]; 138 suf = utfrrune(s, '.'); 139 if(suf) { 140 suf++; 141 if(strcmp(suf, "c") == 0) { 142 append(&srcs, s); 143 append(&objs, changeext(s, ot->o)); 144 } else if(strcmp(suf, ot->o) == 0 || 145 strcmp(suf, "a") == 0 || 146 (suf[0] == 'a' && strcmp(suf+1, ot->o) == 0)) { 147 append(&objs, s); 148 } else if(utfrune(allos, suf[0]) != 0) { 149 fprint(2, "pcc: argument %s ignored: wrong architecture\n", 150 s); 151 } 152 } 153 } 154 } 155 if(objs.n == 0) 156 fatal("no files to compile or load"); 157 ccpath = smprint("/bin/%s", ot->cc); 158 append(&cpp, smprint("-I/%s/include/ape", ot->name)); 159 append(&cpp, "-I/sys/include/ape"); 160 cppn = cpp.n; 161 ccn = cc.n; 162 for(i = 0; i < srcs.n; i++) { 163 append(&cpp, srcs.strings[i]); 164 if(Pflag) 165 append(&cpp, changeext(objs.strings[i], "i")); 166 if(Eflag || Pflag) 167 doexec("/bin/cpp", &cpp); 168 else { 169 append(&cc, "-o"); 170 if(oflag && cflag) 171 append(&cc, oname); 172 else 173 append(&cc, changeext(srcs.strings[i], ot->o)); 174 dopipe("/bin/cpp", &cpp, ccpath, &cc); 175 } 176 cpp.n = cppn; 177 cc.n = ccn; 178 } 179 if(!cflag) { 180 append(&ld, "-o"); 181 append(&ld, oname); 182 for(i = 0; i < ldargs.n; i++) 183 append(&ld, ldargs.strings[i]); 184 for(i = 0; i < objs.n; i++) 185 append(&ld, objs.strings[i]); 186 append(&ld, smprint("/%s/lib/ape/libap.a", ot->name)); 187 doexec(smprint("/bin/%s", ot->ld), &ld); 188 if(objs.n == 1){ 189 /* prevent removal of a library */ 190 if(strstr(objs.strings[0], ".a") == 0) 191 remove(objs.strings[0]); 192 } 193 } 194 195 exits(0); 196 } 197 198 void 199 append(List *l, char *s) 200 { 201 if(l->n >= Maxlist-1) 202 fatal("too many arguments"); 203 l->strings[l->n++] = s; 204 l->strings[l->n] = 0; 205 } 206 207 void 208 doexec(char *c, List *a) 209 { 210 Waitmsg *w; 211 212 if(vflag) { 213 printlist(a); 214 fprint(2, "\n"); 215 } 216 switch(fork()) { 217 case -1: 218 fatal("fork failed"); 219 case 0: 220 exec(c, a->strings); 221 fatal("exec failed"); 222 } 223 w = wait(); 224 if(w == nil) 225 fatal("wait failed"); 226 if(w->msg[0]) 227 fatal(smprint("%s: %s", a->strings[0], w->msg)); 228 free(w); 229 } 230 231 void 232 dopipe(char *c1, List *a1, char *c2, List *a2) 233 { 234 Waitmsg *w; 235 int pid1, got; 236 int fd[2]; 237 238 if(vflag) { 239 printlist(a1); 240 fprint(2, " | "); 241 printlist(a2); 242 fprint(2, "\n"); 243 } 244 if(pipe(fd) < 0) 245 fatal("pipe failed"); 246 switch((pid1 = fork())) { 247 case -1: 248 fatal("fork failed"); 249 case 0: 250 dup(fd[0], 0); 251 close(fd[0]); 252 close(fd[1]); 253 exec(c2, a2->strings); 254 fatal("exec failed"); 255 } 256 switch(fork()) { 257 case -1: 258 fatal("fork failed"); 259 case 0: 260 close(0); 261 dup(fd[1], 1); 262 close(fd[0]); 263 close(fd[1]); 264 exec(c1, a1->strings); 265 fatal("exec failed"); 266 } 267 close(fd[0]); 268 close(fd[1]); 269 for(got = 0; got < 2; got++) { 270 w = wait(); 271 if(w == nil) 272 fatal("wait failed"); 273 if(w->msg[0]) 274 fatal(smprint("%s: %s", 275 (w->pid == pid1) ? a1->strings[0] : a2->strings[0], w->msg)); 276 free(w); 277 } 278 } 279 280 Objtype * 281 findoty(void) 282 { 283 char *o; 284 Objtype *oty; 285 286 o = getenv("objtype"); 287 if(!o) 288 fatal("no $objtype in environment"); 289 for(oty = objtype; oty < &objtype[Nobjs]; oty++) 290 if(strcmp(o, oty->name) == 0) 291 return oty; 292 fatal("unknown $objtype"); 293 return 0; /* shut compiler up */ 294 } 295 296 void 297 fatal(char *msg) 298 { 299 fprint(2, "pcc: %s\n", msg); 300 exits(msg); 301 } 302 303 /* src ends in .something; return copy of basename with .ext added */ 304 char * 305 changeext(char *src, char *ext) 306 { 307 char *b, *e, *ans; 308 309 b = utfrrune(src, '/'); 310 if(b) 311 b++; 312 else 313 b = src; 314 e = utfrrune(src, '.'); 315 if(!e) 316 return 0; 317 *e = 0; 318 ans = smprint("%s.%s", b, ext); 319 *e = '.'; 320 return ans; 321 } 322 323 void 324 printlist(List *l) 325 { 326 int i; 327 328 for(i = 0; i < l->n; i++) { 329 fprint(2, "%s", l->strings[i]); 330 if(i < l->n - 1) 331 fprint(2, " "); 332 } 333 } 334