cc.c 7.2 KB

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