cem.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. /* $Header$ */
  2. /*
  3. Driver for the CEMCOM compiler: works like /bin/cc and accepts the
  4. options accepted by /bin/cc and /usr/em/bin/ack.
  5. Date written: dec 4, 1985
  6. Author: Erik Baalbergen
  7. */
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <errno.h>
  12. #include <signal.h>
  13. #define MAXARGC 256 /* maximum number of arguments allowed in a list */
  14. #define USTR_SIZE 1024 /* maximum length of string variable */
  15. struct arglist {
  16. int al_argc;
  17. char *al_argv[MAXARGC];
  18. };
  19. /* some system-dependent variables */
  20. char *PP = "/lib/cpp";
  21. char *CEM = "/user1/erikb/bin/cemcom";
  22. char *AS_FIX = "/user1/erikb/bin/mcomm";
  23. char *ENCODE = "/usr/em/lib/em_encode";
  24. char *DECODE = "/usr/em/lib/em_decode";
  25. char *OPT = "/usr/em/lib/em_opt";
  26. char *CG = "/usr/em/lib/vax4/cg";
  27. char *AS = "/bin/as";
  28. char *LD = "/bin/ld";
  29. char *SHELL = "/bin/sh";
  30. char *LIBDIR = "/user1/cem/lib";
  31. char *V_FLAG = "-Vs2.2w4.4i4.4l4.4f4.4d8.4p4.4";
  32. struct arglist LD_HEAD = {
  33. 2,
  34. {
  35. "/usr/em/lib/vax4/head_em",
  36. "/usr/em/lib/vax4/head_cc"
  37. }
  38. };
  39. struct arglist LD_TAIL = {
  40. 4,
  41. {
  42. "/user1/cem/lib/libc.a",
  43. "/user1/cem/lib/stb.o",
  44. "/usr/em/lib/vax4/tail_mon",
  45. "/usr/em/lib/vax4/tail_em"
  46. }
  47. };
  48. char *o_FILE = "a.out";
  49. #define remove(str) (((t_flag == 0) && unlink(str)), (str)[0] = '\0')
  50. #define cleanup(str) (str && remove(str))
  51. #define mkname(dst, s1, s2) mkstr(dst, (s1), (s2), 0)
  52. #define init(al) (al)->al_argc = 1
  53. #define library(nm) \
  54. mkstr(alloc((unsigned int)strlen(nm) + strlen(LIBDIR) + 7), \
  55. LIBDIR, "/lib", nm, ".a", 0)
  56. char *ProgCall = 0;
  57. struct arglist SRCFILES;
  58. struct arglist LDFILES;
  59. struct arglist GEN_LDFILES;
  60. struct arglist PP_FLAGS;
  61. struct arglist CEM_FLAGS;
  62. int debug = 0;
  63. int exec = 1;
  64. int RET_CODE = 0;
  65. struct arglist OPT_FLAGS;
  66. struct arglist DECODE_FLAGS;
  67. struct arglist ENCODE_FLAGS;
  68. struct arglist CG_FLAGS;
  69. struct arglist AS_FLAGS;
  70. struct arglist LD_FLAGS;
  71. struct arglist O_FLAGS;
  72. struct arglist DEBUG_FLAGS;
  73. struct arglist CALL_VEC;
  74. int e_flag = 0;
  75. int E_flag = 0;
  76. int c_flag = 0;
  77. int k_flag = 0;
  78. int m_flag = 0;
  79. int o_flag = 0;
  80. int S_flag = 0;
  81. int t_flag = 0;
  82. int v_flag = 0;
  83. int P_flag = 0;
  84. struct prog {
  85. char *p_name;
  86. char **p_task;
  87. struct arglist *p_flags;
  88. } ProgParts[] = {
  89. { "cpp", &PP, &PP_FLAGS },
  90. { "cem", &CEM, &CEM_FLAGS },
  91. { "opt", &OPT, &OPT_FLAGS },
  92. { "decode", &DECODE, &DECODE_FLAGS },
  93. { "encode", &ENCODE, &ENCODE_FLAGS },
  94. { "be", &CG, &CG_FLAGS },
  95. { "cg", &CG, &CG_FLAGS },
  96. { "as", &AS, &AS_FLAGS },
  97. { "ld", &LD, &LD_FLAGS },
  98. { 0, 0, 0 }
  99. };
  100. int trap();
  101. char *mkstr();
  102. char *alloc();
  103. long sizeof_file();
  104. main(argc, argv)
  105. char *argv[];
  106. {
  107. char *str;
  108. char **argvec;
  109. int count;
  110. int ext;
  111. char Nfile[USTR_SIZE];
  112. char kfile[USTR_SIZE];
  113. char sfile[USTR_SIZE];
  114. char mfile[USTR_SIZE];
  115. char ofile[USTR_SIZE];
  116. register struct arglist *call = &CALL_VEC;
  117. char BASE[USTR_SIZE];
  118. char *file;
  119. char *ldfile = 0;
  120. set_traps(trap);
  121. ProgCall = *argv++;
  122. while (--argc > 0) {
  123. if (*(str = *argv++) != '-') {
  124. append(&SRCFILES, str);
  125. continue;
  126. }
  127. switch (str[1]) {
  128. case '-':
  129. switch (str[2]) {
  130. case 'C':
  131. case 'E':
  132. case 'P':
  133. E_flag = 1;
  134. append(&PP_FLAGS, str);
  135. PP = CEM;
  136. P_flag = (str[2] == 'P');
  137. break;
  138. default:
  139. append(&DEBUG_FLAGS, str);
  140. break;
  141. }
  142. break;
  143. case 'B':
  144. PP = CEM = &str[2];
  145. break;
  146. case 'C':
  147. case 'E':
  148. case 'P':
  149. E_flag = 1;
  150. append(&PP_FLAGS, str);
  151. P_flag = (str[1] == 'P');
  152. break;
  153. case 'c':
  154. if (str[2] == '.') {
  155. switch (str[3]) {
  156. case 's':
  157. S_flag = 1;
  158. break;
  159. case 'k':
  160. k_flag = 1;
  161. break;
  162. case 'o':
  163. c_flag = 1;
  164. break;
  165. case 'm':
  166. m_flag = 1;
  167. break;
  168. case 'e':
  169. e_flag = 1;
  170. break;
  171. default:
  172. bad_option(str);
  173. }
  174. }
  175. else
  176. if (str[2] == '\0')
  177. c_flag = 1;
  178. else
  179. bad_option(str);
  180. break;
  181. case 'D':
  182. case 'I':
  183. case 'U':
  184. append(&PP_FLAGS, str);
  185. break;
  186. case 'k':
  187. k_flag = 1;
  188. break;
  189. case 'l':
  190. if (str[2] == '\0') /* no standard libraries */
  191. LD_HEAD.al_argc = LD_TAIL.al_argc = 0;
  192. else /* use library from library directory */
  193. append(&SRCFILES, library(&str[2]));
  194. break;
  195. case 'L': /* change default library directory */
  196. LIBDIR = &str[2];
  197. break;
  198. case 'm':
  199. m_flag = 1;
  200. break;
  201. case 'o':
  202. o_flag = 1;
  203. if (argc-- < 0)
  204. bad_option(str);
  205. else
  206. o_FILE = *argv++;
  207. break;
  208. case 'O':
  209. append(&O_FLAGS, "-O");
  210. break;
  211. case 'p':
  212. append(&CEM_FLAGS, "-p");
  213. break;
  214. case 'R':
  215. if (str[2] == '\0')
  216. append(&CEM_FLAGS, str);
  217. else
  218. Roption(str);
  219. break;
  220. case 'S':
  221. S_flag = 1;
  222. break;
  223. case 't':
  224. t_flag = 1;
  225. break;
  226. case 'v': /* set debug switches */
  227. v_flag = 1;
  228. switch (str[2]) {
  229. case 'd':
  230. debug = 1;
  231. break;
  232. case 'n': /* no execute */
  233. exec = 0;
  234. break;
  235. }
  236. break;
  237. case 'V':
  238. V_FLAG = str;
  239. break;
  240. case 'e':
  241. case 'F':
  242. case 'd':
  243. case 'n':
  244. case 'N':
  245. case 'r':
  246. case 's':
  247. case 'u':
  248. case 'x':
  249. case 'X':
  250. case 'z':
  251. append(&LD_FLAGS, str);
  252. break;
  253. default:
  254. append(&CEM_FLAGS, str);
  255. }
  256. }
  257. if (debug)
  258. report("Note: debug output");
  259. if (exec == 0)
  260. report("Note: no execution");
  261. count = SRCFILES.al_argc;
  262. argvec = &(SRCFILES.al_argv[0]);
  263. Nfile[0] = '\0';
  264. while (count-- > 0) {
  265. basename(file = *argvec++, BASE);
  266. if (E_flag) {
  267. char ifile[USTR_SIZE];
  268. init(call);
  269. append(call, PP);
  270. concat(call, &DEBUG_FLAGS);
  271. concat(call, &PP_FLAGS);
  272. append(call, file);
  273. runvec(call, P_flag ? mkname(ifile, BASE, ".i") : 0);
  274. continue;
  275. }
  276. ext = extension(file);
  277. /* .c to .k and .N */
  278. if (ext == 'c' || ext == 'i') {
  279. init(call);
  280. append(call, CEM);
  281. concat(call, &DEBUG_FLAGS);
  282. append(call, V_FLAG);
  283. concat(call, &CEM_FLAGS);
  284. concat(call, &PP_FLAGS);
  285. append(call, file);
  286. append(call, mkname(kfile, BASE, ".k"));
  287. append(call, mkname(Nfile, BASE, ".N"));
  288. if (runvec(call, (char *)0)) {
  289. file = kfile;
  290. ext = 'k';
  291. if (sizeof_file(Nfile) <= 0L)
  292. remove(Nfile);
  293. }
  294. else {
  295. remove(kfile);
  296. remove(Nfile);
  297. continue;
  298. }
  299. }
  300. /* .e to .k */
  301. if (ext == 'e') {
  302. init(call);
  303. append(call, ENCODE);
  304. concat(call, &ENCODE_FLAGS);
  305. append(call, file);
  306. append(call, mkname(kfile, BASE, ".k"));
  307. if (runvec(call, (char *)0) == 0)
  308. continue;
  309. file = kfile;
  310. ext = 'k';
  311. }
  312. if (k_flag)
  313. continue;
  314. /* decode .k or .m */
  315. if (e_flag && (ext == 'k' || ext == 'm')) {
  316. char efile[USTR_SIZE];
  317. init(call);
  318. append(call, DECODE);
  319. concat(call, &DECODE_FLAGS);
  320. append(call, file);
  321. append(call, mkname(efile, BASE, ".e"));
  322. runvec(call, (char *)0);
  323. cleanup(kfile);
  324. continue;
  325. }
  326. /* .k to .m */
  327. if (ext == 'k') {
  328. init(call);
  329. append(call, OPT);
  330. concat(call, &OPT_FLAGS);
  331. append(call, file);
  332. if (runvec(call, mkname(mfile, BASE, ".m")) == 0)
  333. continue;
  334. file = mfile;
  335. ext = 'm';
  336. cleanup(kfile);
  337. }
  338. if (m_flag)
  339. continue;
  340. /* .m to .s */
  341. if (ext == 'm') {
  342. init(call);
  343. append(call, CG);
  344. concat(call, &CG_FLAGS);
  345. append(call, file);
  346. append(call, mkname(sfile, BASE, ".s"));
  347. if (runvec(call, (char *)0) == 0)
  348. continue;
  349. if (Nfile[0] != '\0') {
  350. init(call);
  351. append(call, AS_FIX);
  352. append(call, Nfile);
  353. append(call, sfile);
  354. runvec(call, (char *)0);
  355. remove(Nfile);
  356. }
  357. cleanup(mfile);
  358. file = sfile;
  359. ext = 's';
  360. }
  361. if (S_flag)
  362. continue;
  363. /* .s to .o */
  364. if (ext == 's') {
  365. ldfile = c_flag ?
  366. ofile :
  367. alloc((unsigned)strlen(BASE) + 3);
  368. init(call);
  369. append(call, AS);
  370. concat(call, &AS_FLAGS);
  371. append(call, "-o");
  372. append(call, mkname(ldfile, BASE, ".o"));
  373. append(call, file);
  374. if (runvec(call, (char *)0) == 0)
  375. continue;
  376. file = ldfile;
  377. ext = 'o';
  378. cleanup(sfile);
  379. }
  380. if (c_flag)
  381. continue;
  382. append(&LDFILES, file);
  383. if (ldfile) {
  384. append(&GEN_LDFILES, ldfile);
  385. ldfile = 0;
  386. }
  387. }
  388. /* *.o to a.out */
  389. if (RET_CODE == 0 && LDFILES.al_argc > 0) {
  390. init(call);
  391. append(call, LD);
  392. concat(call, &LD_FLAGS);
  393. append(call, "-o");
  394. append(call, o_FILE);
  395. concat(call, &LD_HEAD);
  396. concat(call, &LDFILES);
  397. concat(call, &LD_TAIL);
  398. if (runvec(call, (char *)0)) {
  399. register i = GEN_LDFILES.al_argc;
  400. while (i-- > 0)
  401. remove(GEN_LDFILES.al_argv[i]);
  402. }
  403. }
  404. exit(RET_CODE);
  405. }
  406. char *
  407. alloc(u)
  408. unsigned u;
  409. {
  410. #define BUFSIZE (USTR_SIZE * MAXARGC)
  411. static char buf[BUFSIZE];
  412. static char *bufptr = &buf[0];
  413. register char *p = bufptr;
  414. if ((bufptr += u) >= &buf[BUFSIZE])
  415. panic("no space");
  416. return p;
  417. }
  418. append(al, arg)
  419. struct arglist *al;
  420. char *arg;
  421. {
  422. if (al->al_argc >= MAXARGC)
  423. panic("argument list overflow");
  424. al->al_argv[(al->al_argc)++] = arg;
  425. }
  426. concat(al1, al2)
  427. struct arglist *al1, *al2;
  428. {
  429. register i = al2->al_argc;
  430. register char **p = &(al1->al_argv[al1->al_argc]);
  431. register char **q = &(al2->al_argv[0]);
  432. if ((al1->al_argc += i) >= MAXARGC)
  433. panic("argument list overflow");
  434. while (i-- > 0)
  435. *p++ = *q++;
  436. }
  437. /* The next function is a dirty old one, taking a variable number of
  438. arguments.
  439. Take care that the last argument is a null-valued pointer!
  440. */
  441. /*VARARGS1*/
  442. char *
  443. mkstr(dst, arg)
  444. char *dst, *arg;
  445. {
  446. char **vec = (char **) &arg;
  447. register char *p;
  448. register char *q = dst;
  449. while (p = *vec++) {
  450. while (*q++ = *p++);
  451. q--;
  452. }
  453. return dst;
  454. }
  455. Roption(str)
  456. char *str; /* of the form "prog=/-arg" */
  457. {
  458. char *eq;
  459. char *prog, *arg;
  460. char bc;
  461. char *cindex();
  462. prog = &str[2];
  463. if (eq = cindex(prog, '='))
  464. bc = '=';
  465. else
  466. if (eq = cindex(prog, '-'))
  467. bc = '-';
  468. else {
  469. bad_option(str);
  470. return;
  471. }
  472. *eq++ = '\0';
  473. if (arg = eq) {
  474. char *opt = 0;
  475. struct prog *pp = &ProgParts[0];
  476. if (bc == '-') {
  477. opt = mkstr(alloc((unsigned)strlen(arg) + 2),
  478. "-", arg, 0);
  479. }
  480. while (pp->p_name) {
  481. if (strcmp(prog, pp->p_name) == 0) {
  482. if (opt)
  483. append(pp->p_flags, opt);
  484. else
  485. *(pp->p_task) = arg;
  486. return;
  487. }
  488. pp++;
  489. }
  490. }
  491. bad_option(str);
  492. }
  493. basename(str, dst)
  494. char *str;
  495. register char *dst;
  496. {
  497. register char *p1 = str;
  498. register char *p2 = p1;
  499. while (*p1)
  500. if (*p1++ == '/')
  501. p2 = p1;
  502. p1--;
  503. if (*--p1 == '.')
  504. *p1 = '\0';
  505. while (*dst++ = *p2++);
  506. *p1 = '.';
  507. }
  508. int
  509. extension(fn)
  510. register char *fn;
  511. {
  512. char c;
  513. while (*fn++) ;
  514. fn--;
  515. c = *--fn;
  516. return (*--fn == '.') ? c : 0;
  517. }
  518. long
  519. sizeof_file(nm)
  520. char *nm;
  521. {
  522. struct stat stbuf;
  523. if (stat(nm, &stbuf) == 0)
  524. return stbuf.st_size;
  525. return -1;
  526. }
  527. char * sysmsg[] = {
  528. 0,
  529. "Hangup",
  530. "Interrupt",
  531. "Quit",
  532. "Illegal instruction",
  533. "Trace/BPT trap",
  534. "IOT trap",
  535. "EMT trap",
  536. "Floating exception",
  537. "Killed",
  538. "Bus error",
  539. "Memory fault",
  540. "Bad system call",
  541. "Broken pipe",
  542. "Alarm call",
  543. "Terminated",
  544. "Signal 16"
  545. };
  546. runvec(vec, outp)
  547. struct arglist *vec;
  548. char *outp;
  549. {
  550. int status, fd;
  551. char *task = vec->al_argv[1];
  552. vec->al_argv[vec->al_argc] = 0;
  553. if (v_flag)
  554. print_vec(vec);
  555. if (exec == 0)
  556. return 1;
  557. if (fork() == 0) { /* start up the process */
  558. extern int errno;
  559. if (outp) { /* redirect standard output */
  560. if ((fd = creat(outp, 0666)) < 0)
  561. panic("cannot create %s", outp);
  562. if (dup2(fd, 1) == -1)
  563. panic("dup failure");
  564. close(fd);
  565. }
  566. if (debug) report("exec %s", task);
  567. execv(task, &(vec->al_argv[1]));
  568. /* not an a.out file, let's try it with the SHELL */
  569. if (debug) report("try it with %s", SHELL);
  570. if (errno == ENOEXEC) {
  571. vec->al_argv[0] = SHELL;
  572. execv(SHELL, &(vec->al_argv[0]));
  573. }
  574. /* failed, so ... */
  575. panic("cannot execute %s", task);
  576. exit(1);
  577. }
  578. else {
  579. int loworder, highorder, sig;
  580. wait(&status);
  581. loworder = status & 0377;
  582. highorder = (status >> 8) & 0377;
  583. if (loworder == 0) {
  584. if (highorder)
  585. report("%s: exit status %d", task, highorder);
  586. return highorder ? ((RET_CODE = 1), 0) : 1;
  587. }
  588. else {
  589. sig = loworder & 0177;
  590. if (sig == 0177)
  591. report("%s: stopped by ptrace", task);
  592. else
  593. if (sysmsg[sig])
  594. report("%s: %s%s", task, sysmsg[sig],
  595. (loworder & 0200)
  596. ? " - core dumped"
  597. : "");
  598. RET_CODE = 1;
  599. return 0;
  600. }
  601. }
  602. /*NOTREACHED*/
  603. }
  604. bad_option(str)
  605. char *str;
  606. {
  607. report("bad option %s", str);
  608. }
  609. /*VARARGS1*/
  610. report(fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  611. char *fmt;
  612. {
  613. fprintf(stderr, "%s: ", ProgCall);
  614. fprintf(stderr, fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  615. fprintf(stderr, "\n");
  616. }
  617. /*VARARGS1*/
  618. panic(fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  619. char *fmt;
  620. {
  621. fprintf(stderr, "%s: ", ProgCall);
  622. fprintf(stderr, fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  623. fprintf(stderr, "\n");
  624. exit(1);
  625. }
  626. set_traps(f)
  627. int (*f)();
  628. {
  629. signal(SIGHUP, f);
  630. signal(SIGINT, f);
  631. signal(SIGQUIT, f);
  632. signal(SIGALRM, f);
  633. signal(SIGTERM, f);
  634. }
  635. /*ARGSUSED*/
  636. trap(sig)
  637. {
  638. set_traps(SIG_IGN);
  639. panic("Trapped");
  640. }
  641. print_vec(vec)
  642. struct arglist *vec;
  643. {
  644. register i;
  645. for (i = 1; i < vec->al_argc; i++)
  646. printf("%s ", vec->al_argv[i]);
  647. printf("\n");
  648. }
  649. char *
  650. cindex(s, c)
  651. char *s, c;
  652. {
  653. while (*s)
  654. if (*s++ == c)
  655. return s - 1;
  656. return (char *) 0;
  657. }