driver.c 12 KB

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