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