driver.c 18 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  1. /* fcc/fm2/fpc
  2. Driver for fast ACK compilers.
  3. Derived from the C compiler driver from Minix.
  4. You can create cc-compatible versions by compiling with
  5. cc -O '-DFASTDIR="<this directory>"' -DF?? driver.c
  6. where F?? is either FCC, FM2, or FPC.
  7. Install resulting binaries in a public place (f.i. /usr/local/bin).
  8. Suggested names: fcc, fm2, and fpc.
  9. If you have ACK, you can create ACK-compatible versions by compiling
  10. this file with
  11. cc -O -DACK_BIN -I<ACK home directory>/h -DF?? driver.c
  12. where F?? is either FCC, FPC, or FM2.
  13. Install the resulting binaries in the EM bin directory.
  14. Suggested names: afcc, afm2, and afpc.
  15. The ACK compatible version afpc is not compatible with the 4th
  16. ACK distribution, and thus is not on the tape.
  17. */
  18. #ifndef vax
  19. #ifndef sun
  20. In this case, no fast ACK compiler available
  21. #endif
  22. #endif
  23. #if FM2+FPC+FCC > 1
  24. Something wrong here! Only one of FM2, FPC, or FCC must be defined
  25. #endif
  26. #include <errno.h>
  27. #include <signal.h>
  28. #include <varargs.h>
  29. #include <stdio.h>
  30. #ifdef ACK_BIN
  31. #include <em_path.h>
  32. #define M2DEF "/lib/m2"
  33. #define FASTDIR EM_DIR
  34. #else
  35. #define M2DEF "/def"
  36. #define TMP_DIR "/tmp"
  37. #endif ACK_BIN
  38. #ifndef ACK_BIN
  39. #define BINDIR "/bin/"
  40. #define LIBDIR "/lib/"
  41. #else ACK_BIN
  42. #define BINDIR "/lib/"
  43. #ifdef sun
  44. #define LIBDIR "/lib/sun3/"
  45. #endif sun
  46. #ifdef vax
  47. #define LIBDIR "/lib/vax4/"
  48. #endif vax
  49. #define CCINCL "/include/_tail_cc"
  50. #endif ACK_BIN
  51. char *ROOT_DIR = FASTDIR;
  52. /*
  53. #ifndef ACK_BIN
  54. Version producing VAX or SUN .o files in one pass.
  55. #else ACK_BIN
  56. Version producing ACK .o files in one pass.
  57. #endif ACK_BIN
  58. */
  59. #define MAXARGC 256 /* maximum number of arguments allowed in a list */
  60. #define USTR_SIZE 128 /* maximum length of string variable */
  61. typedef char USTRING[USTR_SIZE];
  62. USTRING INCLUDE = "-I";
  63. struct arglist {
  64. int al_argc;
  65. char *al_argv[MAXARGC];
  66. };
  67. #define LD "/bin/ld"
  68. #define AS "/bin/as"
  69. #define CPP "*cpp"
  70. #if ACK_BIN && !vax
  71. #undef LD
  72. #undef AS
  73. #define LD "*em_led"
  74. #define CV "~cv" /* machine dependent; resides in lib directory */
  75. #endif ACK_BIN && !vax
  76. #define SHELL "/bin/sh"
  77. /* flags passed to linker */
  78. #define TO_LD "dnNrsSi"
  79. #if ACK_BIN && !vax
  80. #undef TO_LD
  81. #define TO_LD "rs"
  82. #endif ACK_BIN && !vax
  83. int kids = -1;
  84. int ecount = 0;
  85. struct arglist CPP_FLAGS = {
  86. #ifdef vax
  87. 8,
  88. #endif
  89. #ifdef sun
  90. 10,
  91. #endif
  92. {
  93. "-Dunix",
  94. "-DEM_WSIZE=4",
  95. "-DEM_PSIZE=4",
  96. "-DEM_SSIZE=2",
  97. "-DEM_LSIZE=4",
  98. "-DEM_FSIZE=4",
  99. "-DEM_DSIZE=8",
  100. #ifdef vax
  101. "-Dvax"
  102. #endif
  103. #ifdef sun
  104. "-Dmc68000",
  105. "-Dsun",
  106. "-Dmc68020"
  107. #endif
  108. }
  109. };
  110. struct arglist COMP_FLAGS;
  111. #ifdef FCC
  112. struct arglist LD_HEAD = {
  113. #ifdef ACK_BIN
  114. 2,
  115. {
  116. "~head_em",
  117. "~head_cc"
  118. }
  119. #else ACK_BIN
  120. #ifdef sun
  121. #ifdef SunOs4
  122. 7,
  123. #else
  124. 5,
  125. #endif
  126. {
  127. "-e",
  128. "start",
  129. "-X",
  130. #ifdef SunOs4
  131. "-L/usr/lib/fsoft",
  132. "-Bstatic",
  133. #endif
  134. "/lib/crt0.o",
  135. "/lib/Fcrt1.o"
  136. }
  137. #endif
  138. #ifdef vax
  139. 2,
  140. {
  141. "-X",
  142. "/lib/crt0.o"
  143. }
  144. #endif
  145. #endif ACK_BIN
  146. };
  147. struct arglist LD_TAIL = {
  148. #ifdef ACK_BIN
  149. #ifdef sun
  150. 6,
  151. {
  152. "~tail_cc.1s",
  153. "~tail_cc.2g",
  154. "*m68020/tail_fp",
  155. "*m68020/tail_em",
  156. "~tail_mon",
  157. "*m68020/end_em"
  158. }
  159. #endif sun
  160. #ifdef vax
  161. 4,
  162. {
  163. "~tail_cc.1s",
  164. "~tail_cc.2g",
  165. "~tail_em",
  166. "~tail_mon"
  167. }
  168. #endif vax
  169. #else ACK_BIN
  170. #ifdef sun
  171. 2,
  172. {
  173. "~tail_ext",
  174. "-lc"
  175. }
  176. #endif
  177. #ifdef vax
  178. 2,
  179. {
  180. "~tail_em",
  181. "-lc"
  182. }
  183. #endif
  184. #endif ACK_BIN
  185. };
  186. #endif FCC
  187. #ifdef FPC
  188. struct arglist LD_HEAD = {
  189. #ifdef ACK_BIN
  190. 2,
  191. {
  192. "~head_em",
  193. #ifdef vax
  194. "~head_pc"
  195. #endif
  196. #ifdef sun
  197. "*m68020/head_pc"
  198. #endif
  199. }
  200. #else ACK_BIN
  201. #ifdef sun
  202. #ifdef SunOs4
  203. 7,
  204. #else
  205. 5,
  206. #endif
  207. {
  208. "-e",
  209. "begtext",
  210. "-X",
  211. #ifdef SunOs4
  212. "-L/usr/lib/fsoft",
  213. "-Bstatic",
  214. #endif
  215. "~head_em",
  216. "~head_pc"
  217. }
  218. #endif sun
  219. #ifdef vax
  220. 3,
  221. {
  222. "-X",
  223. "~head_em",
  224. "~head_pc"
  225. }
  226. #endif vax
  227. #endif ACK_BIN
  228. };
  229. struct arglist LD_TAIL = {
  230. #ifndef ACK_BIN
  231. #ifdef sun
  232. 3,
  233. {
  234. "~tail_pc",
  235. "~tail_ext",
  236. "-lc"
  237. }
  238. #endif sun
  239. #ifdef vax
  240. 3,
  241. {
  242. "~tail_pc",
  243. "~tail_em",
  244. "-lc"
  245. }
  246. #endif vax
  247. #else ACK_BIN
  248. #ifdef sun
  249. 5,
  250. {
  251. "*m68020/tail_pc",
  252. "*m68020/tail_fp",
  253. "*m68020/tail_em",
  254. "~tail_mon",
  255. "*m68020/end_em"
  256. }
  257. #endif sun
  258. #ifdef vax
  259. 3,
  260. {
  261. "~tail_pc",
  262. "~tail_em",
  263. "~tail_mon"
  264. }
  265. #endif vax
  266. #endif ACK_BIN
  267. };
  268. #endif FPC
  269. #ifdef FM2
  270. struct arglist LD_HEAD = {
  271. #ifdef ACK_BIN
  272. 2,
  273. {
  274. "~head_em",
  275. "~head_m2"
  276. }
  277. #else ACK_BIN
  278. #ifdef sun
  279. #ifdef SunOs4
  280. 7,
  281. #else
  282. 5,
  283. #endif
  284. {
  285. "-e",
  286. "begtext",
  287. "-X",
  288. #ifdef SunOs4
  289. "-L/usr/lib/fsoft",
  290. "-Bstatic",
  291. #endif
  292. "~head_em",
  293. "~head_m2"
  294. }
  295. #endif sun
  296. #ifdef vax
  297. 3,
  298. {
  299. "-X",
  300. "~head_em",
  301. "~head_m2"
  302. }
  303. #endif vax
  304. #endif ACK_BIN
  305. };
  306. struct arglist LD_TAIL = {
  307. #ifndef ACK_BIN
  308. #ifdef sun
  309. 3,
  310. {
  311. "~tail_m2",
  312. "~tail_ext",
  313. "-lc"
  314. }
  315. #endif sun
  316. #ifdef vax
  317. 3,
  318. {
  319. "~tail_m2",
  320. "~tail_em",
  321. "-lc"
  322. }
  323. #endif vax
  324. #else ACK_BIN
  325. #ifdef sun
  326. 5,
  327. {
  328. "~tail_m2",
  329. "*m68020/tail_fp",
  330. "*m68020/tail_em",
  331. "~tail_mon",
  332. "*m68020/end_em"
  333. }
  334. #endif sun
  335. #ifdef vax
  336. 3,
  337. {
  338. "~tail_m2",
  339. "~tail_em",
  340. "~tail_mon"
  341. }
  342. #endif vax
  343. #endif ACK_BIN
  344. };
  345. #endif FM2
  346. #if ACK_BIN && !vax
  347. #ifdef sun
  348. struct arglist def_align = {
  349. 5,
  350. {
  351. "-a0:4",
  352. "-a1:4",
  353. "-a2:0x20000",
  354. "-a3:4",
  355. "-b0:0x2020"
  356. }
  357. };
  358. struct arglist n_align = {
  359. 5,
  360. {
  361. "-a0:4",
  362. "-a1:4",
  363. "-a2:0x20000",
  364. "-a3:4",
  365. "-b0:0x2000"
  366. }
  367. };
  368. struct arglist N_align = {
  369. 5,
  370. {
  371. "-a0:4",
  372. "-a1:4",
  373. "-a2:4",
  374. "-a3:4",
  375. "-b0:0x2000"
  376. }
  377. };
  378. #endif sun
  379. struct arglist *sect_align = &def_align;
  380. #endif ACK_BIN && !vax
  381. char *o_FILE = "a.out"; /* default name for executable file */
  382. #define remove(str) ((noexec || unlink(str)), (str)[0] = '\0')
  383. #define cleanup(str) (str && str[0] && remove(str))
  384. #define init(al) ((al)->al_argc = 1)
  385. char ProgCall[128];
  386. struct arglist SRCFILES;
  387. struct arglist LDFILES;
  388. struct arglist GEN_LDFILES;
  389. int RET_CODE = 0;
  390. struct arglist LD_FLAGS;
  391. struct arglist CALL_VEC;
  392. int o_flag = 0;
  393. int c_flag = 0;
  394. int v_flag = 0;
  395. int O_flag = 0;
  396. char *mkstr();
  397. char *malloc();
  398. char *alloc();
  399. char *extension();
  400. USTRING ofile;
  401. USTRING BASE;
  402. USTRING tmp_file;
  403. int noexec = 0;
  404. extern char *strcat(), *strcpy(), *mktemp(), *strchr();
  405. trapcc(sig)
  406. int sig;
  407. {
  408. signal(sig, SIG_IGN);
  409. if (kids != -1) kill(kids, sig);
  410. cleanup(ofile);
  411. cleanup(tmp_file);
  412. exit(1);
  413. }
  414. #ifdef FCC
  415. #define lang_suffix() "c"
  416. #ifndef ACK_BIN
  417. #define comp_name() "*cemcom_ce"
  418. #else
  419. #ifdef vax
  420. #define comp_name() "~cemcom_ce"
  421. #endif
  422. #ifdef sun
  423. #define comp_name() "*m68020/cemcom_ce"
  424. #endif
  425. #endif ACK_BIN
  426. #endif FCC
  427. #ifdef FM2
  428. #define lang_suffix() "mod"
  429. #ifndef ACK_BIN
  430. #define comp_name() "*m2_ce"
  431. #else
  432. #ifdef vax
  433. #define comp_name() "~m2_ce"
  434. #endif
  435. #ifdef sun
  436. #define comp_name() "*m68020/m2_ce"
  437. #endif
  438. #endif ACK_BIN
  439. #endif FM2
  440. #ifdef FPC
  441. #define lang_suffix() "p"
  442. #ifndef ACK_BIN
  443. #define comp_name() "*pc_ce"
  444. #else
  445. #ifdef vax
  446. #define comp_name() "~pc_ce"
  447. #endif
  448. #ifdef sun
  449. #define comp_name() "*m68020/pc_ce"
  450. #endif
  451. #endif ACK_BIN
  452. #endif FPC
  453. #ifdef FCC
  454. int
  455. lang_opt(str)
  456. char *str;
  457. {
  458. switch(str[1]) {
  459. case '-': /* debug options */
  460. case 'w': /* disable warnings */
  461. case 'R': /* strict K&R C. */
  462. append(&COMP_FLAGS, str);
  463. return 1;
  464. }
  465. return 0;
  466. }
  467. #endif FCC
  468. #ifdef FM2
  469. int
  470. lang_opt(str)
  471. char *str;
  472. {
  473. switch(str[1]) {
  474. case '-': /* debug options */
  475. case 'w': /* disable warnings */
  476. case 'R': /* no runtime checks */
  477. case 'W': /* add warnings */
  478. case 'L': /* no line numbers */
  479. case 'A': /* extra array bound checks */
  480. case '3': /* only accept 3rd edition Modula-2 */
  481. append(&COMP_FLAGS, str);
  482. return 1;
  483. case 'I':
  484. append(&COMP_FLAGS, str);
  485. break; /* !!! */
  486. case 'U': /* underscores in identifiers allowed */
  487. if (str[2] == '\0') {
  488. append(&COMP_FLAGS, str);
  489. return 1;
  490. }
  491. break;
  492. case 'e': /* local extension for Modula-2 compiler:
  493. procedure constants
  494. */
  495. str[1] = 'l';
  496. append(&COMP_FLAGS, str);
  497. return 1;
  498. }
  499. return 0;
  500. }
  501. #endif FM2
  502. #ifdef FPC
  503. int
  504. lang_opt(str)
  505. char *str;
  506. {
  507. switch(str[1]) {
  508. case '-': /* debug options */
  509. case 'a': /* enable assertions */
  510. case 'd': /* allow doubles (longs) */
  511. case 'i': /* set size of integer sets */
  512. case 't': /* tracing */
  513. case 'w': /* disable warnings */
  514. case 'A': /* extra array bound checks */
  515. case 'C': /* distinguish between lower case and upper case */
  516. case 'L': /* no FIL and LIN instructions */
  517. case 'R': /* no runtime checks */
  518. append(&COMP_FLAGS, str);
  519. return 1;
  520. case 'u':
  521. case 'U':
  522. /* underscores in identifiers */
  523. case 's':
  524. /* only compile standard pascal */
  525. case 'c':
  526. /* C type strings */
  527. if (str[2] == '+' && str[3] == '\0') {
  528. str[2] = 0;
  529. append(&COMP_FLAGS, str);
  530. return 1;
  531. }
  532. }
  533. return 0;
  534. }
  535. #endif FPC
  536. main(argc, argv)
  537. char *argv[];
  538. {
  539. char *str;
  540. char **argvec;
  541. int count;
  542. char *ext;
  543. register struct arglist *call = &CALL_VEC;
  544. char *file;
  545. char *ldfile = 0;
  546. USTRING COMP;
  547. int compile_cnt = 0;
  548. setbuf(stdout, (char *) 0);
  549. basename(*argv++,ProgCall);
  550. strcat(INCLUDE, ROOT_DIR);
  551. #ifdef FM2
  552. strcat(INCLUDE, M2DEF);
  553. #endif FM2
  554. #ifdef FCC
  555. #ifdef ACK_BIN
  556. strcat(INCLUDE, CCINCL);
  557. #else
  558. INCLUDE[0] = '\0';
  559. #endif ACK_BIN
  560. #endif FCC
  561. #ifdef FPC
  562. INCLUDE[0] = '\0';
  563. #endif FPC
  564. strcpy(COMP,comp_name());
  565. if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  566. signal(SIGHUP, trapcc);
  567. if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  568. signal(SIGINT, trapcc);
  569. if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  570. signal(SIGQUIT, trapcc);
  571. while (--argc > 0) {
  572. if (*(str = *argv++) != '-') {
  573. append(&SRCFILES, str);
  574. continue;
  575. }
  576. if (lang_opt(str)) {
  577. }
  578. else switch (str[1]) {
  579. case 'c': /* stop after producing .o files */
  580. c_flag = 1;
  581. break;
  582. case 'D': /* preprocessor #define */
  583. case 'U': /* preprocessor #undef */
  584. append(&CPP_FLAGS, str);
  585. break;
  586. case 'I': /* include directory */
  587. append(&CPP_FLAGS, str);
  588. break;
  589. case 'o': /* target file */
  590. if (argc-- >= 0) {
  591. o_flag = 1;
  592. o_FILE = *argv++;
  593. ext = extension(o_FILE);
  594. if (ext != o_FILE && ! strcmp(ext, lang_suffix())
  595. #ifndef ACK_BIN
  596. || !strcmp(ext, "s")
  597. #endif
  598. ) {
  599. error("-o would overwrite %s", o_FILE);
  600. }
  601. }
  602. break;
  603. case 'u': /* mark identifier as undefined */
  604. append(&LD_FLAGS, str);
  605. if (argc-- >= 0)
  606. append(&LD_FLAGS, *argv++);
  607. break;
  608. case 'O': /* use built in peephole optimizer */
  609. if (! O_flag) strcat(COMP, "opt");
  610. O_flag = 1;
  611. break;
  612. case 'v': /* verbose */
  613. v_flag++;
  614. if (str[2] == 'n')
  615. noexec = 1;
  616. break;
  617. case 'l': /* library file */
  618. append(&SRCFILES, str);
  619. break;
  620. case 'M': /* use other compiler (for testing) */
  621. strcpy(COMP, str+2);
  622. break;
  623. #if ACK_BIN && !vax
  624. case 'n': /* text portion sharable, read-only. No
  625. demand paging
  626. */
  627. sect_align = &n_align;
  628. break;
  629. case 'N': /* text portion not sharable, not read-only */
  630. sect_align = &N_align;
  631. break;
  632. case 'd': /* force definition of common storage */
  633. append(&LD_FLAGS, "-c");
  634. break;
  635. #endif ACK_BIN && !vax
  636. default:
  637. #ifdef sun
  638. if (! strcmp(str, "-sun3")) {
  639. /* SunOs4.0 make passes this flag to
  640. $(CC). Ignore it silently.
  641. */
  642. break;
  643. }
  644. #endif
  645. if (strchr(TO_LD, str[1]) == 0)
  646. warning("%s flag ignored", str);
  647. else {
  648. append(&LD_FLAGS, str);
  649. }
  650. break;
  651. }
  652. }
  653. if (ecount) exit(1);
  654. #if FCC && !ACK_BIN
  655. append(&COMP_FLAGS, "-L"); /* disable line number and filename admin */
  656. #endif FCC && !ACK_BIN
  657. count = SRCFILES.al_argc;
  658. argvec = &(SRCFILES.al_argv[0]);
  659. while (count-- > 0) {
  660. ext = extension(*argvec);
  661. if (*argvec[0] != '-' &&
  662. ext != *argvec++ && (! strcmp(ext, lang_suffix())
  663. #ifndef ACK_BIN
  664. || !strcmp(ext, "s")
  665. #endif
  666. )) {
  667. compile_cnt++;
  668. }
  669. }
  670. if (compile_cnt > 1 && c_flag && o_flag) {
  671. warning("-o flag ignored");
  672. o_flag = 0;
  673. }
  674. count = SRCFILES.al_argc;
  675. argvec = &(SRCFILES.al_argv[0]);
  676. while (count-- > 0) {
  677. register char *f;
  678. basename(file = *argvec++, BASE);
  679. ext = extension(file);
  680. if (file[0] != '-' &&
  681. ext != file && (!strcmp(ext, lang_suffix())
  682. #ifndef ACK_BIN
  683. || !strcmp(ext, "s")
  684. #endif
  685. )) {
  686. #ifndef ACK_BIN
  687. if (compile_cnt > 1)
  688. printf("%s:\n", file);
  689. #else
  690. printf("%s\n", file);
  691. #endif
  692. ldfile = c_flag ? ofile : alloc((unsigned)strlen(BASE)+3);
  693. if (
  694. #ifdef FCC
  695. !strcmp(ext, "s") &&
  696. #endif
  697. needsprep(file)) {
  698. strcpy(tmp_file, TMP_DIR);
  699. strcat(tmp_file, "/F_XXXXXX");
  700. mktemp(tmp_file);
  701. init(call);
  702. append(call, CPP);
  703. concat(call, &CPP_FLAGS);
  704. append(call, INCLUDE);
  705. append(call, file);
  706. if (runvec(call, tmp_file)) {
  707. file = tmp_file;
  708. }
  709. else {
  710. remove(tmp_file);
  711. tmp_file[0] = '\0';
  712. continue;
  713. }
  714. }
  715. init(call);
  716. if (o_flag && c_flag) {
  717. f = o_FILE;
  718. }
  719. else f = mkstr(ldfile, BASE, ".o", (char *)0);
  720. #ifndef ACK_BIN
  721. if (strcmp(ext, "s")) {
  722. #endif
  723. append(call, COMP);
  724. #ifdef FCC
  725. concat(call, &CPP_FLAGS);
  726. #endif
  727. concat(call, &COMP_FLAGS);
  728. #if FM2 || FCC
  729. append(call, INCLUDE);
  730. #endif
  731. append(call, file);
  732. append(call, f);
  733. #ifndef ACK_BIN
  734. }
  735. else {
  736. append(call, AS);
  737. append(call, "-o");
  738. append(call, f);
  739. #ifdef sun
  740. append(call, "-mc68020");
  741. #endif
  742. append(call, file);
  743. }
  744. #endif
  745. if (runvec(call, (char *) 0)) {
  746. file = f;
  747. }
  748. else {
  749. remove(f);
  750. continue;
  751. }
  752. cleanup(tmp_file);
  753. tmp_file[0] = '\0';
  754. }
  755. else if (file[0] != '-' &&
  756. strcmp(ext, "o") && strcmp(ext, "a")) {
  757. warning("file with unknown suffix (%s) passed to the loader", ext);
  758. }
  759. if (c_flag)
  760. continue;
  761. append(&LDFILES, file);
  762. if (ldfile) {
  763. append(&GEN_LDFILES, ldfile);
  764. ldfile = 0;
  765. }
  766. }
  767. /* *.s to a.out */
  768. if (RET_CODE == 0 && LDFILES.al_argc > 0) {
  769. #ifndef ACK_BIN
  770. if (compile_cnt > 1) {
  771. printf("Linking:\n");
  772. }
  773. #endif
  774. init(call);
  775. append(call, LD);
  776. concat(call, &LD_HEAD);
  777. concat(call, &LD_FLAGS);
  778. append(call, "-o");
  779. #if ACK_BIN && !vax
  780. strcpy(tmp_file, TMP_DIR);
  781. strcat(tmp_file, "/LF_XXXXXX");
  782. mktemp(tmp_file);
  783. append(call, tmp_file);
  784. concat(call, sect_align);
  785. #else ACK_BIN && !vax
  786. append(call, o_FILE);
  787. #endif ACK_BIN && !vax
  788. concat(call, &LDFILES);
  789. concat(call, &LD_TAIL);
  790. #if ACK_BIN && !vax
  791. if (! runvec(call, (char *) 0)) {
  792. cleanup(tmp_file);
  793. exit(RET_CODE);
  794. }
  795. init(call);
  796. append(call, CV);
  797. append(call, tmp_file);
  798. append(call, o_FILE);
  799. #endif ACK_BIN && !vax
  800. if (runvec(call, (char *) 0) && GEN_LDFILES.al_argc == 1)
  801. #ifdef ACK_BIN
  802. ;
  803. #else
  804. remove(GEN_LDFILES.al_argv[0]);
  805. #endif ACK_BIN
  806. #if ACK_BIN && !vax
  807. cleanup(tmp_file);
  808. #endif ACK_BIN && !vax
  809. }
  810. exit(RET_CODE);
  811. }
  812. needsprep(name)
  813. char *name;
  814. {
  815. int file;
  816. char fc;
  817. file = open(name,0);
  818. if (file < 0) return 0;
  819. if (read(file, &fc, 1) != 1) fc = 0;
  820. close(file);
  821. return fc == '#';
  822. }
  823. char *
  824. alloc(u)
  825. unsigned u;
  826. {
  827. char *p = malloc(u);
  828. if (p == 0)
  829. panic("no space");
  830. return p;
  831. }
  832. append(al, arg)
  833. struct arglist *al;
  834. char *arg;
  835. {
  836. if (!arg || !*arg) return;
  837. if (al->al_argc >= MAXARGC)
  838. panic("argument list overflow");
  839. if (*arg == '~' || *arg == '*') {
  840. char *p;
  841. char *lb = *arg == '~' ? LIBDIR : BINDIR;
  842. p = alloc((unsigned)strlen(ROOT_DIR)+strlen(lb)+strlen(arg+1)+1);
  843. strcpy(p, ROOT_DIR);
  844. strcat(p, lb);
  845. strcat(p, arg+1);
  846. arg = p;
  847. }
  848. al->al_argv[(al->al_argc)++] = arg;
  849. }
  850. concat(al1, al2)
  851. struct arglist *al1, *al2;
  852. {
  853. register i = al2->al_argc;
  854. register char **p = &(al1->al_argv[al1->al_argc]);
  855. register char **q = &(al2->al_argv[0]);
  856. if ((al1->al_argc += i) >= MAXARGC)
  857. panic("argument list overflow");
  858. while (i-- > 0) {
  859. if (**q == '~' || **q == '*') {
  860. char *lb = **q == '~' ? LIBDIR : BINDIR;
  861. *p = alloc((unsigned)strlen(ROOT_DIR)+strlen(lb)+strlen(*q+1)+2);
  862. strcpy(*p, ROOT_DIR);
  863. strcat(*p, lb);
  864. strcat(*p++, *q+1);
  865. q++;
  866. }
  867. else *p++ = *q++;
  868. }
  869. }
  870. /*VARARGS*/
  871. char *
  872. mkstr(va_alist)
  873. va_dcl
  874. {
  875. va_list ap;
  876. char *dst;
  877. va_start(ap);
  878. {
  879. register char *p;
  880. register char *q;
  881. dst = q = va_arg(ap, char *);
  882. p = va_arg(ap, char *);
  883. while (p) {
  884. while (*q++ = *p++);
  885. q--;
  886. p = va_arg(ap, char *);
  887. }
  888. }
  889. va_end(ap);
  890. return dst;
  891. }
  892. basename(str, dst)
  893. char *str;
  894. register char *dst;
  895. {
  896. register char *p1 = str;
  897. register char *p2 = p1;
  898. while (*p1)
  899. if (*p1++ == '/')
  900. p2 = p1;
  901. p1--;
  902. while (*p1 != '.' && p1 >= p2) p1--;
  903. if (p1 >= p2) {
  904. *p1 = '\0';
  905. while (*dst++ = *p2++);
  906. *p1 = '.';
  907. }
  908. else
  909. while (*dst++ = *p2++);
  910. }
  911. char *
  912. extension(fn)
  913. char *fn;
  914. {
  915. register char *c = fn;
  916. while (*c++) ;
  917. while (*--c != '.' && c >= fn) { }
  918. if (c++ < fn || !*c) return fn;
  919. return c;
  920. }
  921. runvec(vec, outp)
  922. struct arglist *vec;
  923. char *outp;
  924. {
  925. int pid, status;
  926. if (v_flag) {
  927. pr_vec(vec);
  928. putc('\n', stderr);
  929. }
  930. if ((pid = fork()) == 0) { /* start up the process */
  931. if (outp) { /* redirect standard output */
  932. close(1);
  933. if (creat(outp, 0666) != 1)
  934. panic("cannot create output file");
  935. }
  936. ex_vec(vec);
  937. }
  938. if (pid == -1)
  939. panic("no more processes");
  940. kids = pid;
  941. wait(&status);
  942. if (status) switch(status & 0177) {
  943. case SIGHUP:
  944. case SIGINT:
  945. case SIGQUIT:
  946. case SIGTERM:
  947. case 0:
  948. break;
  949. default:
  950. error("%s died with signal %d\n", vec->al_argv[1], status&0177);
  951. }
  952. kids = -1;
  953. return status ? ((RET_CODE = 1), 0) : 1;
  954. }
  955. /*VARARGS1*/
  956. error(str, s1, s2)
  957. char *str, *s1, *s2;
  958. {
  959. fprintf(stderr, "%s: ", ProgCall);
  960. fprintf(stderr, str, s1, s2);
  961. putc('\n', stderr);
  962. ecount++;
  963. }
  964. /*VARARGS1*/
  965. warning(str, s1, s2)
  966. char *str, *s1, *s2;
  967. {
  968. fprintf(stderr, "%s: (warning) ", ProgCall);
  969. fprintf(stderr, str, s1, s2);
  970. putc('\n', stderr);
  971. }
  972. panic(str)
  973. char *str;
  974. {
  975. error(str);
  976. trapcc(SIGINT);
  977. }
  978. pr_vec(vec)
  979. register struct arglist *vec;
  980. {
  981. register char **ap = &vec->al_argv[1];
  982. vec->al_argv[vec->al_argc] = 0;
  983. fputs(*ap, stderr);
  984. while (*++ap) {
  985. putc(' ', stderr);
  986. fputs(*ap, stderr);
  987. }
  988. }
  989. extern int errno;
  990. ex_vec(vec)
  991. register struct arglist *vec;
  992. {
  993. if (noexec)
  994. exit(0);
  995. vec->al_argv[vec->al_argc] = 0;
  996. execv(vec->al_argv[1], &(vec->al_argv[1]));
  997. if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
  998. vec->al_argv[0] = SHELL;
  999. execv(SHELL, &(vec->al_argv[0]));
  1000. }
  1001. if (access(vec->al_argv[1], 1) == 0) {
  1002. /* File is executable. */
  1003. error("cannot execute %s", vec->al_argv[1]);
  1004. } else {
  1005. error("%s is not executable", vec->al_argv[1]);
  1006. }
  1007. exit(1);
  1008. }