fcc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. /* fcc
  2. Driver for fast cc-compatible ACK C compiler.
  3. Derived from the C compiler driver from Minix.
  4. Compile this file with
  5. cc -O -I<EM home dir>/config driver.c
  6. Install the resulting binaries in the EM bin directory.
  7. Suggested name: fcc
  8. */
  9. #ifdef sun3
  10. #define MACHNAME "m68020"
  11. #define SYSNAME "sun3"
  12. #endif
  13. #ifdef vax4
  14. #define MACHNAME "vax4"
  15. #define SYSNAME "vax4"
  16. #endif
  17. #include <errno.h>
  18. #include <signal.h>
  19. #include <varargs.h>
  20. #include <stdio.h>
  21. #include <em_path.h>
  22. /*
  23. Version producing cc-compatible .o files in one pass.
  24. */
  25. #define MAXARGC 256 /* maximum number of arguments allowed in a list */
  26. #define USTR_SIZE 128 /* maximum length of string variable */
  27. typedef char USTRING[USTR_SIZE];
  28. struct arglist {
  29. int al_argc;
  30. char *al_argv[MAXARGC];
  31. };
  32. #define CPP_NAME "$H/lib.bin/cpp"
  33. #define LD_NAME "/bin/ld"
  34. #define AS_NAME "/bin/as"
  35. #define SHELL "/bin/sh"
  36. char *CPP;
  37. char *COMP;
  38. int kids = -1;
  39. int ecount = 0;
  40. struct arglist CPP_FLAGS = {
  41. 7,
  42. {
  43. "-Dunix",
  44. "-D_EM_WSIZE=4",
  45. "-D_EM_PSIZE=4",
  46. "-D_EM_SSIZE=2",
  47. "-D_EM_LSIZE=4",
  48. "-D_EM_FSIZE=4",
  49. "-D_EM_DSIZE=8",
  50. }
  51. };
  52. struct arglist LD_HEAD = {
  53. #ifdef sun3
  54. 8,
  55. {
  56. "-dc",
  57. "-dp",
  58. "-e",
  59. "start",
  60. "-X",
  61. "-L/usr/lib/fsoft",
  62. "/usr/lib/crt0.o",
  63. "/usr/lib/Fcrt1.o"
  64. }
  65. #endif
  66. #ifdef vax4
  67. 2,
  68. {
  69. "-X",
  70. "/lib/crt0.o"
  71. }
  72. #endif
  73. };
  74. struct arglist LD_TAIL = {
  75. 2,
  76. {
  77. "$H/lib/$S/tail_ext",
  78. "-lc"
  79. }
  80. };
  81. struct arglist LD_FLAGS;
  82. struct arglist COMP_FLAGS;
  83. char *o_FILE = "a.out"; /* default name for executable file */
  84. #define remove(str) ((noexec || unlink(str)), (str)[0] = '\0')
  85. #define cleanup(str) (str && str[0] && remove(str))
  86. #define init(al) ((al)->al_argc = 1)
  87. char ProgCall[128];
  88. struct arglist SRCFILES;
  89. struct arglist LDFILES;
  90. int RET_CODE = 0;
  91. struct arglist CALL_VEC;
  92. int o_flag = 0;
  93. int c_flag = 0;
  94. int v_flag = 0;
  95. int O_flag = 0;
  96. char *mkstr();
  97. char *malloc();
  98. char *alloc();
  99. char *extension();
  100. char *expand_string();
  101. USTRING ofile;
  102. USTRING BASE;
  103. USTRING tmp_file;
  104. int noexec = 0;
  105. extern char *strcat(), *strcpy(), *mktemp(), *strchr();
  106. trapcc(sig)
  107. int sig;
  108. {
  109. signal(sig, SIG_IGN);
  110. if (kids != -1) kill(kids, sig);
  111. cleanup(ofile);
  112. cleanup(tmp_file);
  113. exit(1);
  114. }
  115. #define lang_suffix() "c"
  116. #define comp_name() "$H/lib.bin/c_cccompat"
  117. int
  118. lang_opt(str)
  119. char *str;
  120. {
  121. switch(str[1]) {
  122. case '-': /* debug options */
  123. case 'R': /* strict K&R */
  124. case 'w': /* disable warnings */
  125. append(&COMP_FLAGS, str);
  126. return 1;
  127. }
  128. return 0;
  129. }
  130. main(argc, argv)
  131. char *argv[];
  132. {
  133. char *str;
  134. char **argvec;
  135. int count;
  136. char *ext;
  137. register struct arglist *call = &CALL_VEC;
  138. char *file;
  139. char *ldfile;
  140. int compile_cnt = 0;
  141. setbuf(stdout, (char *) 0);
  142. basename(*argv++,ProgCall);
  143. COMP = expand_string(comp_name());
  144. CPP = expand_string(CPP_NAME);
  145. #ifdef vax4
  146. append(&CPP_FLAGS, "-Dvax");
  147. #endif
  148. #ifdef sun3
  149. append(&CPP_FLAGS, "-Dsun");
  150. append(&CPP_FLAGS, "-Dmc68020");
  151. append(&CPP_FLAGS, "-Dmc68000");
  152. #endif
  153. if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  154. signal(SIGHUP, trapcc);
  155. if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  156. signal(SIGINT, trapcc);
  157. if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  158. signal(SIGQUIT, trapcc);
  159. while (--argc > 0) {
  160. if (*(str = *argv++) != '-') {
  161. append(&SRCFILES, str);
  162. continue;
  163. }
  164. if (lang_opt(str)) {
  165. }
  166. else switch (str[1]) {
  167. case 'c': /* stop after producing .o files */
  168. c_flag = 1;
  169. break;
  170. case 'D': /* preprocessor #define */
  171. case 'U': /* preprocessor #undef */
  172. append(&CPP_FLAGS, str);
  173. break;
  174. case 'I': /* include directory */
  175. append(&CPP_FLAGS, str);
  176. break;
  177. case 'g': /* debugger support */
  178. append(&COMP_FLAGS, str);
  179. break;
  180. case 'o': /* target file */
  181. if (argc-- >= 0) {
  182. o_flag = 1;
  183. o_FILE = *argv++;
  184. ext = extension(o_FILE);
  185. if (ext != o_FILE && ! strcmp(ext, lang_suffix())
  186. ) {
  187. error("-o would overwrite %s", o_FILE);
  188. }
  189. }
  190. break;
  191. case 'u': /* mark identifier as undefined */
  192. append(&LD_FLAGS, str);
  193. if (argc-- >= 0)
  194. append(&LD_FLAGS, *argv++);
  195. break;
  196. case 'O': /* use built in peephole optimizer */
  197. O_flag = 1;
  198. break;
  199. case 'v': /* verbose */
  200. v_flag++;
  201. if (str[2] == 'n')
  202. noexec = 1;
  203. break;
  204. case 'l': /* library file */
  205. append(&SRCFILES, str);
  206. break;
  207. case 't': /* -target? */
  208. if (! strcmp(str, "-target")) {
  209. if (argc-- >= 0) argv++;
  210. break;
  211. }
  212. warning("%s flag ignored", str);
  213. break;
  214. case 'M': /* use other compiler (for testing) */
  215. strcpy(COMP, str+2);
  216. break;
  217. case 's': /* strip, -sun3? */
  218. if (! strcmp(str, "-sun3")) {
  219. break;
  220. }
  221. /* fall through */
  222. case 'n': /* text not read-only */
  223. case 'N': /* text read-only */
  224. case 'r': /* relocation produced */
  225. case 'S': /* strip, but leave locals and globals */
  226. if (str[2] == '\0') {
  227. append(&LD_FLAGS, str);
  228. break;
  229. }
  230. /* fall through */
  231. default:
  232. warning("%s flag ignored", str);
  233. break;
  234. }
  235. }
  236. if (ecount) exit(1);
  237. count = SRCFILES.al_argc;
  238. argvec = &(SRCFILES.al_argv[0]);
  239. while (count-- > 0) {
  240. ext = extension(*argvec);
  241. if (*argvec[0] != '-' &&
  242. ext != *argvec++ && (! strcmp(ext, lang_suffix())
  243. )) {
  244. compile_cnt++;
  245. }
  246. }
  247. if (compile_cnt > 1 && c_flag && o_flag) {
  248. warning("-o flag ignored");
  249. o_flag = 0;
  250. }
  251. append(&COMP_FLAGS, "-L");
  252. count = SRCFILES.al_argc;
  253. argvec = &(SRCFILES.al_argv[0]);
  254. while (count-- > 0) {
  255. register char *f;
  256. basename(file = *argvec++, BASE);
  257. ext = extension(file);
  258. if (file[0] != '-' &&
  259. ext != file && (!strcmp(ext, lang_suffix())
  260. )) {
  261. if (compile_cnt > 1) printf("%s\n", file);
  262. ldfile = c_flag ? ofile : alloc((unsigned)strlen(BASE)+3);
  263. if (
  264. !strcmp(ext, "s") &&
  265. needsprep(file)) {
  266. strcpy(tmp_file, TMP_DIR);
  267. strcat(tmp_file, "/F_XXXXXX");
  268. mktemp(tmp_file);
  269. init(call);
  270. append(call, CPP);
  271. concat(call, &CPP_FLAGS);
  272. append(call, file);
  273. if (runvec(call, tmp_file)) {
  274. file = tmp_file;
  275. }
  276. else {
  277. remove(tmp_file);
  278. tmp_file[0] = '\0';
  279. continue;
  280. }
  281. }
  282. init(call);
  283. if (o_flag && c_flag) {
  284. f = o_FILE;
  285. }
  286. else f = mkstr(ldfile, BASE, ".", "o", (char *)0);
  287. if (strcmp(ext, "s")) {
  288. append(call, COMP);
  289. concat(call, &CPP_FLAGS);
  290. concat(call, &COMP_FLAGS);
  291. append(call, file);
  292. append(call, f);
  293. }
  294. else {
  295. append(call, AS_NAME);
  296. append(call, "-o");
  297. append(call, f);
  298. #ifdef sun3
  299. append(call, "-mc68020");
  300. #endif
  301. append(call, file);
  302. }
  303. if (runvec(call, (char *) 0)) {
  304. file = f;
  305. }
  306. else {
  307. remove(f);
  308. continue;
  309. }
  310. cleanup(tmp_file);
  311. tmp_file[0] = '\0';
  312. }
  313. else if (file[0] != '-' &&
  314. strcmp(ext, "o") && strcmp(ext, "a")) {
  315. warning("file with unknown suffix (%s) passed to the loader", ext);
  316. }
  317. if (c_flag)
  318. continue;
  319. append(&LDFILES, file);
  320. }
  321. /* *.s to a.out */
  322. if (RET_CODE == 0 && LDFILES.al_argc > 0) {
  323. init(call);
  324. expand(&LD_HEAD);
  325. expand(&LD_TAIL);
  326. append(call, expand_string(LD_NAME));
  327. concat(call, &LD_FLAGS);
  328. append(call, "-o");
  329. append(call, o_FILE);
  330. concat(call, &LD_HEAD);
  331. concat(call, &LDFILES);
  332. concat(call, &LD_TAIL);
  333. if (! runvec(call, (char *) 0)) {
  334. exit(RET_CODE);
  335. }
  336. }
  337. exit(RET_CODE);
  338. }
  339. needsprep(name)
  340. char *name;
  341. {
  342. int file;
  343. char fc;
  344. file = open(name,0);
  345. if (file < 0) return 0;
  346. if (read(file, &fc, 1) != 1) fc = 0;
  347. close(file);
  348. return fc == '#';
  349. }
  350. char *
  351. alloc(u)
  352. unsigned u;
  353. {
  354. char *p = malloc(u);
  355. if (p == 0)
  356. panic("no space");
  357. return p;
  358. }
  359. char *
  360. expand_string(s)
  361. char *s;
  362. {
  363. char buf[1024];
  364. register char *p = s;
  365. register char *q = &buf[0];
  366. int expanded = 0;
  367. if (!p) return p;
  368. while (*p) {
  369. if (*p == '$') {
  370. p++;
  371. expanded = 1;
  372. switch(*p++) {
  373. case 'H':
  374. strcpy(q, EM_DIR);
  375. break;
  376. case 'M':
  377. strcpy(q, MACHNAME);
  378. break;
  379. case 'S':
  380. strcpy(q, SYSNAME);
  381. break;
  382. default:
  383. panic("internal error");
  384. break;
  385. }
  386. while (*q) q++;
  387. }
  388. else *q++ = *p++;
  389. }
  390. if (! expanded) return s;
  391. *q++ = '\0';
  392. p = alloc((unsigned int) (q - buf));
  393. return strcpy(p, buf);
  394. }
  395. append(al, arg)
  396. register struct arglist *al;
  397. char *arg;
  398. {
  399. if (!arg || !*arg) return;
  400. if (al->al_argc >= MAXARGC)
  401. panic("argument list overflow");
  402. al->al_argv[(al->al_argc)++] = arg;
  403. }
  404. expand(al)
  405. register struct arglist *al;
  406. {
  407. register int i = al->al_argc;
  408. register char **p = &(al->al_argv[0]);
  409. while (i-- > 0) {
  410. *p = expand_string(*p);
  411. p++;
  412. }
  413. }
  414. concat(al1, al2)
  415. struct arglist *al1, *al2;
  416. {
  417. register i = al2->al_argc;
  418. register char **p = &(al1->al_argv[al1->al_argc]);
  419. register char **q = &(al2->al_argv[0]);
  420. if ((al1->al_argc += i) >= MAXARGC)
  421. panic("argument list overflow");
  422. while (i-- > 0) {
  423. *p++ = *q++;
  424. }
  425. }
  426. /*VARARGS*/
  427. char *
  428. mkstr(va_alist)
  429. va_dcl
  430. {
  431. va_list ap;
  432. char *dst;
  433. va_start(ap);
  434. {
  435. register char *p;
  436. register char *q;
  437. dst = q = va_arg(ap, char *);
  438. p = va_arg(ap, char *);
  439. while (p) {
  440. while (*q++ = *p++);
  441. q--;
  442. p = va_arg(ap, char *);
  443. }
  444. }
  445. va_end(ap);
  446. return dst;
  447. }
  448. basename(str, dst)
  449. char *str;
  450. register char *dst;
  451. {
  452. register char *p1 = str;
  453. register char *p2 = p1;
  454. while (*p1)
  455. if (*p1++ == '/')
  456. p2 = p1;
  457. p1--;
  458. while (*p1 != '.' && p1 >= p2) p1--;
  459. if (p1 >= p2) {
  460. *p1 = '\0';
  461. while (*dst++ = *p2++);
  462. *p1 = '.';
  463. }
  464. else
  465. while (*dst++ = *p2++);
  466. }
  467. char *
  468. extension(fn)
  469. char *fn;
  470. {
  471. register char *c = fn;
  472. while (*c++) ;
  473. while (*--c != '.' && c >= fn) { }
  474. if (c++ < fn || !*c) return fn;
  475. return c;
  476. }
  477. runvec(vec, outp)
  478. struct arglist *vec;
  479. char *outp;
  480. {
  481. int pid, status;
  482. if (v_flag) {
  483. pr_vec(vec);
  484. putc('\n', stderr);
  485. }
  486. if ((pid = fork()) == 0) { /* start up the process */
  487. if (outp) { /* redirect standard output */
  488. close(1);
  489. if (creat(outp, 0666) != 1)
  490. panic("cannot create output file");
  491. }
  492. ex_vec(vec);
  493. }
  494. if (pid == -1)
  495. panic("no more processes");
  496. kids = pid;
  497. wait(&status);
  498. if (status) switch(status & 0177) {
  499. case SIGHUP:
  500. case SIGINT:
  501. case SIGQUIT:
  502. case SIGTERM:
  503. case 0:
  504. break;
  505. default:
  506. error("%s died with signal %d\n", vec->al_argv[1], status&0177);
  507. }
  508. kids = -1;
  509. return status ? ((RET_CODE = 1), 0) : 1;
  510. }
  511. /*VARARGS1*/
  512. error(str, s1, s2)
  513. char *str, *s1, *s2;
  514. {
  515. fprintf(stderr, "%s: ", ProgCall);
  516. fprintf(stderr, str, s1, s2);
  517. putc('\n', stderr);
  518. ecount++;
  519. }
  520. /*VARARGS1*/
  521. warning(str, s1, s2)
  522. char *str, *s1, *s2;
  523. {
  524. fprintf(stderr, "%s: (warning) ", ProgCall);
  525. fprintf(stderr, str, s1, s2);
  526. putc('\n', stderr);
  527. }
  528. panic(str)
  529. char *str;
  530. {
  531. error(str);
  532. trapcc(SIGINT);
  533. }
  534. pr_vec(vec)
  535. register struct arglist *vec;
  536. {
  537. register char **ap = &vec->al_argv[1];
  538. vec->al_argv[vec->al_argc] = 0;
  539. fprintf(stderr, "%s", *ap);
  540. while (*++ap) {
  541. fprintf(stderr, " %s", *ap);
  542. }
  543. }
  544. extern int errno;
  545. ex_vec(vec)
  546. register struct arglist *vec;
  547. {
  548. if (noexec)
  549. exit(0);
  550. vec->al_argv[vec->al_argc] = 0;
  551. execv(vec->al_argv[1], &(vec->al_argv[1]));
  552. if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
  553. vec->al_argv[0] = SHELL;
  554. execv(SHELL, &(vec->al_argv[0]));
  555. }
  556. if (access(vec->al_argv[1], 1) == 0) {
  557. /* File is executable. */
  558. error("cannot execute %s", vec->al_argv[1]);
  559. } else {
  560. error("%s is not executable", vec->al_argv[1]);
  561. }
  562. exit(1);
  563. }