home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / os / minix / 4796 < prev    next >
Encoding:
Text File  |  1992-11-17  |  40.4 KB  |  1,696 lines

  1. Newsgroups: comp.os.minix
  2. Path: sparky!uunet!convex!news.utdallas.edu!wupost!uwm.edu!spool.mu.edu!agate!dog.ee.lbl.gov!news!cod!broman
  3. From: broman@nosc.mil (Vincent P. Broman)
  4. Subject: c386 compiler, patched for i80387, bootstrapped by bcc
  5. Message-ID: <1992Nov17.160026.7727@nosc.mil>
  6. Reply-To: broman@nosc.mil
  7. Organization: Naval Ocean Systems Center, San Diego
  8. Distribution: comp
  9. Date: Tue, 17 Nov 1992 16:00:26 GMT
  10. Lines: 1684
  11.  
  12. I've patched the c386 v4.1 Minix C compiler for 387 floating point operation,
  13. targeted to a backend of Bruce Evans' assembler and loader, instead
  14. of gas and gld, c386 being bootstrapped using bcc.  This combination was
  15. almost supported out of the box, but was evidently not tried by the authors.
  16.  
  17. The widely distributed version of Bruce Evans' assembler does not
  18. support 387 opcodes, but a newer version found at
  19. gipsy.vmars.tuwien.ac.at:/pub/minix/bruce/as.zip
  20. does.  Unfortunately, it no longer recognizes '|' as a comment character,
  21. implementing a logical or instead.  While there, get the new ld, too;
  22. you need it to get a source file as and ld share.  Don't throw away
  23. the old assembler, because the bcc FP emulation routines have names
  24. that collide with some 387 opcodes.  Sigh.
  25.  
  26. Correct operation of this kind of 387 code in a multitasking environment
  27. requires patching crtso.s to perform an finit and patching the
  28. kernel to save the 387 state in the process table on context switches.
  29. I haven't perfected that yet.  The compiler will generate calls to
  30. FP software emulation routines, but I haven't ported the emulation
  31. assembler code from gas to bas, yet.  I might never.
  32.  
  33. In the following shar archive:
  34.  
  35.   src.patch contains the changes required for targeting bas/bld, mostly
  36.   in out386_bas.c .  The Makefile gets munged, a NO_FLOAT_PRINTF
  37.   option is defined in config.h, so that if your printf cannot emit a .double
  38.   out386_bas will emit 1 or 2 .longs instead, address operands of FP ops
  39.   get length specifiers, and two typos were corrected, one critical.
  40.  
  41.   bcc.patch contains changes needed for bootstrapping with bcc,
  42.   essentially just replacing FP literal constants with cast integer literals.
  43.   bccfp is required to support this.
  44.  
  45.   alloca.s is a bas transcription of the distributed gas routine.
  46.  
  47.   c.c is a cc compiler driver, patched from that posted by CvW a while ago.
  48.   It is table driven and simultaneously supports several compilers and
  49.   compiler parts.  E.g. you may want a different cpp from my choice.
  50.   The c386 and c387 it knows about are both really c386, just with and
  51.   without the NOFLOAT option specified.  It's slick.
  52.  
  53. Vincent Broman,  code 572 bayside,                                  =   o     
  54. Naval Command Control and Ocean Surveillance Center, RDT&E Div.   =  _ /- _   
  55. San Diego, CA  92152-5000,  USA                                  =  (_)> (_)  
  56. Internet Email: broman@nosc.mil    Fax: +1 619 553 1635   Phone: +1 619 553 1641
  57. -------------------------------------------------------------------------------
  58.  
  59. : This is a shar archive.  Extract with sh, not csh.
  60. : The rest of this file will extract:
  61. : src.patch bcc.patch alloca.s c.c
  62. echo x src.patch
  63. sed 's/^X//' > src.patch << 'xEOF'
  64. Xdiff -c Makefile.orig Makefile
  65. X*** Makefile.orig    Thu Oct  8 21:20:02 1992
  66. X--- Makefile    Sat Oct 10 22:07:46 1992
  67. X***************
  68. X*** 4,12 ****
  69. X  #        according to the DEFINES set in config.h
  70. X  
  71. X  # Select either GCC or c68 or bcc to compile this  (not ACK!!)
  72. X! CC= cc68
  73. X! CFLAGS= -O -Qwarn=5
  74. X! LDFLAGS = -s -m250000
  75. X  
  76. X  HDR =     c.h cglbdec.h expr.h gen.h version.h config.h
  77. X  
  78. X--- 4,13 ----
  79. X  #        according to the DEFINES set in config.h
  80. X  
  81. X  # Select either GCC or c68 or bcc to compile this  (not ACK!!)
  82. X! CC= bcc -3
  83. X! CFLAGS= 
  84. X! LDFLAGS = -i
  85. X! LIB=
  86. X  
  87. X  HDR =     c.h cglbdec.h expr.h gen.h version.h config.h
  88. X  
  89. X***************
  90. X*** 15,20 ****
  91. X--- 16,23 ----
  92. X      stmt.c cmain.c genstmt.c memmgt.c msgout.c \
  93. X      symbol.c decl.c getsym.c genicode.c outgen.c
  94. X  #
  95. X+ SRCLIB = vfprintf.c
  96. X+ #
  97. X  SRC68K =config.c68 gen68k.c reg68k.c peep68k.c genffp.c genieee.c \
  98. X      out68k_ack.c out68k_cpm.c out68k_gas.c
  99. X  #
  100. X***************
  101. X*** 26,31 ****
  102. X--- 29,36 ----
  103. X      stmt.o cmain.o genstmt.o memmgt.o msgout.o \
  104. X      symbol.o decl.o getsym.o genicode.o outgen.o
  105. X  #
  106. X+ OBJLIB = vfprintf.o
  107. X+ #
  108. X  OBJ68K= gen68k.o reg68k.o peep68k.o genffp.o genieee.o \
  109. X      out68k_ack.o out68k_cpm.o out68k_gas.o
  110. X  #
  111. X***************
  112. X*** 39,56 ****
  113. X      @echo "    make c68"
  114. X      @echo "    make c386"
  115. X  
  116. X! c68:    config_check_c68 $(OBJ) $(OBJ68K) $(OBJ386)
  117. X!     $(CC) $(LDFLAGS) -o c68 $(OBJ) \
  118. X!             $(OBJ68K) \
  119. X!             $(OBJ386)
  120. X  
  121. X  config_check_c68:
  122. X      ./copy-if-change config.c68 config.h
  123. X  
  124. X! c386:    config_check_c386 $(OBJ) $(OBJ68K) $(OBJ386)
  125. X!     $(CC) $(LDFLAGS) -o c386 $(OBJ) \
  126. X!             $(OBJ68K) \
  127. X!             $(OBJ386)
  128. X  
  129. X  config_check_c386:
  130. X      ./copy-if-change config.c386 config.h
  131. X--- 44,62 ----
  132. X      @echo "    make c68"
  133. X      @echo "    make c386"
  134. X  
  135. X! c68:    config_check_c68 $(OBJ) $(OBJ68K) $(OBJ386) $(OBJLIB)
  136. X!     $(CC) $(LDFLAGS) -o c68 $(OBJ) \
  137. X!             $(OBJ68K) \
  138. X!             $(OBJ386) $(OBJLIB)
  139. X  
  140. X  config_check_c68:
  141. X      ./copy-if-change config.c68 config.h
  142. X  
  143. X! c386:    config_check_c386 $(OBJ) $(OBJ68K) $(OBJ386) $(OBJLIB)
  144. X!     $(CC) $(LDFLAGS) -o c386 $(OBJ) \
  145. X!             $(OBJ68K) \
  146. X!             $(OBJ386) $(OBJLIB) $(LIB)
  147. X!     chmem =200000 c386
  148. X  
  149. X  config_check_c386:
  150. X      ./copy-if-change config.c386 config.h
  151. X***************
  152. X*** 68,70 ****
  153. X--- 74,79 ----
  154. X  $(OBJ):        $(HDR)
  155. X  $(OBJ68K):    $(HDR)
  156. X  $(OBJ386):    $(HDR)
  157. X+ 
  158. X+ $(OBJLIB): $(HDR)
  159. X+     $(CC) $(CFLAGS) -c -DINTEL_32BITS `basename $@ .o`.c
  160. Xdiff -c config.c386.or config.c386
  161. X*** config.c386.or    Thu Oct  8 21:20:11 1992
  162. X--- config.c386    Sat Oct 10 07:55:33 1992
  163. X***************
  164. X*** 20,25 ****
  165. X--- 20,26 ----
  166. X  /* #define HAS_NLS 1    /* system supports message catalogues */
  167. X  #define HAS_STDARG 1    /* system supports stdarg.h */
  168. X  /* #define NOFLOAT 1     /* Do not generate floating point support */
  169. X+ #define NO_FLOAT_PRINTF    /* no FP printf for emitting float constants */
  170. X  /* #define NODOUBLE 1    /* Treat 'float' and 'double' as same (MFFP version) */
  171. X  /*
  172. X   *    These options tend not to be changed except when developing
  173. X***************
  174. X*** 50,55 ****
  175. X--- 51,63 ----
  176. X  #define INTEL_386 1    /* This is an Intel 386 compiler */
  177. X  #define SEPARATE_I_D 1    /* Separate I and D spaces */
  178. X  
  179. X+ /*
  180. X+  * if FUNCS_USE_387 is defined, extra library calls are generated if the
  181. X+  * nofpu option is in effect that allows to use code generated by
  182. X+  * this compiler to be linked with functions that return values
  183. X+  * on the 387 stack.
  184. X+  * there is no provision for returns on the ESP stack.
  185. X+  */
  186. X  #define FUNCS_USE_387 1    /* ... very special option */
  187. X  
  188. X  /* #define TARGET_GAS    /* Assembler Syntax is for GAS/Sun386i */
  189. X***************
  190. X*** 144,156 ****
  191. X  #define PROGNAME   "c386"
  192. X  #define LIST_NAME  "c386.list"
  193. X  #define ICODE_NAME "c386.icode"
  194. X- /*
  195. X-  * if FUNCS_USE_387 is defined, extra library calls are generated if the
  196. X-  * nofpu option is in effect that allows to use code generated by
  197. X-  * this compiler to be linked with functions that return values
  198. X-  * on the 387 stack
  199. X-  */
  200. X- #define FUNCS_USE_387
  201. X  #endif
  202. X  
  203. X  #ifndef CPU_DEFINED
  204. X--- 152,157 ----
  205. Xdiff -c msgout.c.orig msgout.c
  206. X*** msgout.c.orig    Thu Oct  8 21:21:40 1992
  207. X--- msgout.c    Fri Oct  9 21:29:39 1992
  208. X***************
  209. X*** 49,55 ****
  210. X  # define VA_START(a,s)    va_start(a,s)
  211. X  # ifdef __STDC__
  212. X  #  define P1(p1, p2)    (p1 p2, ...)
  213. X! #  define P2(p1, p2, p3, p4)    (p1 p2, p3, p4, ...)
  214. X  # else
  215. X  #  define P1(p1, p2)    (p2) p1 p2;
  216. X  #  define P2(p1, p2, p3, p4)    (p2, p4) p1 p2; p3 p4;
  217. X--- 49,55 ----
  218. X  # define VA_START(a,s)    va_start(a,s)
  219. X  # ifdef __STDC__
  220. X  #  define P1(p1, p2)    (p1 p2, ...)
  221. X! #  define P2(p1, p2, p3, p4)    (p1 p2, p3 p4, ...)
  222. X  # else
  223. X  #  define P1(p1, p2)    (p2) p1 p2;
  224. X  #  define P2(p1, p2, p3, p4)    (p2, p4) p1 p2; p3 p4;
  225. Xdiff -c out386_bas.ori out386_bas.c
  226. X*** out386_bas.ori    Thu Oct  8 21:18:54 1992
  227. X--- out386_bas.c    Sat Oct 10 06:03:46 1992
  228. X***************
  229. X*** 64,69 ****
  230. X--- 64,70 ----
  231. X  
  232. X  #define    BI    1
  233. X  #define SP    2
  234. X+ #define FP    4
  235. X  
  236. X  static struct oplst {
  237. X      char           *s;
  238. X***************
  239. X*** 71,76 ****
  240. X--- 72,78 ----
  241. X      int            sa;    /* special addressing modes:
  242. X                   *    BI    immediate is bracketed,
  243. X                   *    SP    size prefix needed.
  244. X+              *    FP    387 op
  245. X                   */
  246. X  }               opl[] =
  247. X  
  248. X***************
  249. X*** 119,139 ****
  250. X  "rep",        op_rep,        SP,
  251. X  "movs",        op_smov,    BI | SP,
  252. X  "test",        op_test,    BI | SP,
  253. X! "fadd",        op_fadd,    BI | SP,
  254. X! "fsub",        op_fsub,    BI | SP,
  255. X! "fsubr",    op_fsubr,    BI | SP,
  256. X! "fmul",        op_fmul,    BI | SP,
  257. X! "fdiv",        op_fdiv,    BI | SP,
  258. X! "fdivr",    op_fdivr,    BI | SP,
  259. X! "fchs",        op_fchs,    BI | SP,
  260. X! "fld",        op_fld,        BI | SP,
  261. X! "fild",        op_fild,    BI | SP,
  262. X! "fst",        op_fst,        BI | SP,
  263. X! "fstp",        op_fstp,    BI | SP,
  264. X! "fstp %st(0)",    op_fpop,    BI | SP,
  265. X! "fcompp",    op_fcompp,    BI | SP,
  266. X! "ftst",        op_ftst,    BI | SP,
  267. X! "fnstsw",    op_fnstsw,    BI | SP,
  268. X  "sahf",        op_sahf,    BI | SP,
  269. X  0,        0,        0
  270. X  };
  271. X--- 121,143 ----
  272. X  "rep",        op_rep,        SP,
  273. X  "movs",        op_smov,    BI | SP,
  274. X  "test",        op_test,    BI | SP,
  275. X! #ifndef NOFLOAT
  276. X! "fadd",        op_fadd,    BI | SP | FP,
  277. X! "fsub",        op_fsub,    BI | SP | FP,
  278. X! "fsubr",    op_fsubr,    BI | SP | FP,
  279. X! "fmul",        op_fmul,    BI | SP | FP,
  280. X! "fdiv",        op_fdiv,    BI | SP | FP,
  281. X! "fdivr",    op_fdivr,    BI | SP | FP,
  282. X! "fchs",        op_fchs,    BI | SP | FP,
  283. X! "fld",        op_fld,        BI | SP | FP,
  284. X! "fild",        op_fild,    BI | SP | FP,
  285. X! "fst",        op_fst,        BI | SP | FP,
  286. X! "fstp",        op_fstp,    BI | SP | FP,
  287. X! "fstp st(0)",    op_fpop,    BI | SP | FP,
  288. X! "fcompp",    op_fcompp,    BI | SP | FP,
  289. X! "ftst",        op_ftst,    BI | SP | FP,
  290. X! "fnstsw",    op_fnstsw,    BI | SP | FP,
  291. X! #endif
  292. X  "sahf",        op_sahf,    BI | SP,
  293. X  0,        0,        0
  294. X  };
  295. X***************
  296. X*** 257,262 ****
  297. X--- 261,276 ----
  298. X          break;
  299. X      }
  300. X      }    
  301. X+ #ifndef NOFLOAT
  302. X+     if (sa & FP) {
  303. X+     /* assume that st(n) never appears explicitly as an operand here */
  304. X+     if (len >= 8)
  305. X+         oprintf("qword ptr ");
  306. X+     else if (len >= 4)
  307. X+         oprintf("dword ptr ");
  308. X+     /* else fnstsw should not need a length? */
  309. X+     }
  310. X+ #endif
  311. X      switch (ap->mode) {
  312. X        case am_immed:
  313. X      oprintf("#");
  314. X***************
  315. X*** 290,296 ****
  316. X          oprintf("[%s+%s]",regname[ap->preg],regname[ap->sreg]);
  317. X          break;
  318. X        default:
  319. X!     fatal("out386_bas/putamdoe","illegal address mode %d",ap->mode);
  320. X      break;
  321. X      }
  322. X  }
  323. X--- 304,310 ----
  324. X          oprintf("[%s+%s]",regname[ap->preg],regname[ap->sreg]);
  325. X          break;
  326. X        default:
  327. X!     fatal("out386_bas/putamode","illegal address mode %d",ap->mode);
  328. X      break;
  329. X      }
  330. X  }
  331. X***************
  332. X*** 414,427 ****
  333. X  genfloat(val)
  334. X      double          val;
  335. X  {
  336. X!     oprintf("\t.float %20.15e\n",val);
  337. X  }
  338. X  
  339. X  void
  340. X  gendouble(val)
  341. X      double          val;
  342. X  {
  343. X!     oprintf("\t.double %20.15e\n",val);
  344. X  }
  345. X  #endif
  346. X  
  347. X--- 428,453 ----
  348. X  genfloat(val)
  349. X      double          val;
  350. X  {
  351. X! #ifndef NO_FLOAT_PRINTF
  352. X!     oprintf("\t.float %14.7e\n",val);
  353. X! #else
  354. X!     float fval;
  355. X!     fval = (float) val;
  356. X!     /* this type transfer won't cross compile, of course. */
  357. X!     oprintf("\t.long %d\n", ((long *)&fval)[0]);
  358. X! #endif
  359. X  }
  360. X  
  361. X  void
  362. X  gendouble(val)
  363. X      double          val;
  364. X  {
  365. X! #ifndef NO_FLOAT_PRINTF
  366. X!     oprintf("\t.double %23.16e\n",val);
  367. X! #else
  368. X!     /* this type transfer won't cross compile, of course. */
  369. X!     oprintf("\t.long %d, %d\n", ((long *)&val)[0], ((long *)&val)[1]);
  370. X! #endif
  371. X  }
  372. X  #endif
  373. X  
  374. xEOF
  375. echo x bcc.patch
  376. sed 's/^X//' > bcc.patch << 'xEOF'
  377. Xdiff -c expr.c expr.c.bcc
  378. X*** expr.c    Thu Oct  8 21:20:55 1992
  379. X--- expr.c.bcc    Fri Oct  9 21:59:04 1992
  380. X***************
  381. X*** 673,679 ****
  382. X          } else if (floating(tp)) {
  383. X              ep2 = mk_node(en_fcon, NIL_ENODE, NIL_ENODE);
  384. X  #ifndef NOFLOAT
  385. X!             ep2->v.f = 1.0;
  386. X  #endif
  387. X              if (tp->type == bt_float) {
  388. X              ep2->etype = tp_float.type;
  389. X--- 673,679 ----
  390. X          } else if (floating(tp)) {
  391. X              ep2 = mk_node(en_fcon, NIL_ENODE, NIL_ENODE);
  392. X  #ifndef NOFLOAT
  393. X!             ep2->v.f = ((double) 1);
  394. X  #endif
  395. X              if (tp->type == bt_float) {
  396. X              ep2->etype = tp_float.type;
  397. X***************
  398. X*** 890,896 ****
  399. X              if (floating(tp)) {
  400. X              ep2 = mk_node(en_fcon, NIL_ENODE, NIL_ENODE);
  401. X  #ifndef NOFLOAT
  402. X!             ep2->v.f = 1.0;
  403. X  #endif
  404. X              if (tp->type == bt_float) {
  405. X                  ep2->etype = tp_float.type;
  406. X--- 890,896 ----
  407. X              if (floating(tp)) {
  408. X              ep2 = mk_node(en_fcon, NIL_ENODE, NIL_ENODE);
  409. X  #ifndef NOFLOAT
  410. X!             ep2->v.f = ((double) 1);
  411. X  #endif
  412. X              if (tp->type == bt_float) {
  413. X                  ep2->etype = tp_float.type;
  414. Xdiff -c getsym.c getsym.c.bcc
  415. X*** getsym.c    Thu Oct  8 21:21:32 1992
  416. X--- getsym.c.bcc    Sat Oct 10 07:30:57 1992
  417. X***************
  418. X*** 439,452 ****
  419. X      register unsigned long i=0;
  420. X      register int    j;
  421. X  #ifndef NOFLOAT
  422. X!     register double r = 0.0;
  423. X  #endif
  424. X  
  425. X      while (isdigit(lastch)) {
  426. X      j = radix36(lastch);
  427. X      i = 10 * i + j;
  428. X  #ifndef NOFLOAT
  429. X!     r = 10.0 * r + (double) j;
  430. X  #endif
  431. X      getch();
  432. X      }
  433. X--- 439,452 ----
  434. X      register unsigned long i=0;
  435. X      register int    j;
  436. X  #ifndef NOFLOAT
  437. X!     register double r = ((double) 0);
  438. X  #endif
  439. X  
  440. X      while (isdigit(lastch)) {
  441. X      j = radix36(lastch);
  442. X      i = 10 * i + j;
  443. X  #ifndef NOFLOAT
  444. X!     r = ((double) 10) * r + (double) j;
  445. X  #endif
  446. X      getch();
  447. X      }
  448. X***************
  449. X*** 496,506 ****
  450. X  {
  451. X  #ifndef NOFLOAT
  452. X      double          frmul;
  453. X!     frmul = 10.0;
  454. X      while (isdigit(lastch)) {
  455. X      rval += (double) radix36(lastch) / frmul;
  456. X      getch();
  457. X!     frmul *= 10.0;
  458. X      }
  459. X  #endif
  460. X  }
  461. X--- 496,506 ----
  462. X  {
  463. X  #ifndef NOFLOAT
  464. X      double          frmul;
  465. X!     frmul = ((double) 10);
  466. X      while (isdigit(lastch)) {
  467. X      rval += (double) radix36(lastch) / frmul;
  468. X      getch();
  469. X!     frmul *= ((double) 10);
  470. X      }
  471. X  #endif
  472. X  }
  473. X***************
  474. X*** 526,538 ****
  475. X      switch (lastch) {
  476. X      case '-':
  477. X      getch();
  478. X!     multiplier = 1/10.0;
  479. X      break;
  480. X      case '+':
  481. X      getch();
  482. X      /* FALL THRU */
  483. X      default:
  484. X!     multiplier = 10.0;
  485. X      break;
  486. X      }
  487. X      getdecimal();
  488. X--- 526,538 ----
  489. X      switch (lastch) {
  490. X      case '-':
  491. X      getch();
  492. X!     multiplier = ((double) 1) / ((double) 10);
  493. X      break;
  494. X      case '+':
  495. X      getch();
  496. X      /* FALL THRU */
  497. X      default:
  498. X!     multiplier = ((double) 10);
  499. X      break;
  500. X      }
  501. X      getdecimal();
  502. X***************
  503. X*** 797,803 ****
  504. X          getch();
  505. X          if (isdigit(lastch)) {
  506. X  #ifndef NOFLOAT
  507. X!         rval = 0.0;
  508. X  #endif
  509. X          getfrac();
  510. X          lastst = rconst;
  511. X--- 797,803 ----
  512. X          getch();
  513. X          if (isdigit(lastch)) {
  514. X  #ifndef NOFLOAT
  515. X!         rval = ((double) 0);
  516. X  #endif
  517. X          getfrac();
  518. X          lastst = rconst;
  519. Xdiff -c optimize.c optimize.c.bcc
  520. X*** optimize.c    Sat Jul 25 13:12:46 1992
  521. X--- optimize.c.bcc    Fri Oct  9 22:01:16 1992
  522. X***************
  523. X*** 80,86 ****
  524. X              epf = ep0->v.f * ep1->v.f;
  525. X              break;
  526. X            case en_div:
  527. X!         if (ep1->v.f == 0.0) {
  528. X              message(GWARN_DIVZERO);
  529. X              ep->nodetype = en_div;
  530. X          } else {
  531. X--- 80,86 ----
  532. X              epf = ep0->v.f * ep1->v.f;
  533. X              break;
  534. X            case en_div:
  535. X!         if (ep1->v.f == ((double) 0)) {
  536. X              message(GWARN_DIVZERO);
  537. X              ep->nodetype = en_div;
  538. X          } else {
  539. xEOF
  540. echo x alloca.s
  541. sed 's/^X//' > alloca.s << 'xEOF'
  542. X    .text
  543. X    export alloca
  544. X    export __builtin_alloca
  545. Xalloca:
  546. X__builtin_alloca:
  547. X    pop    ecx
  548. X    mov    eax,[esp]
  549. X    add    eax,$3
  550. X    and    eax,$-4
  551. X    sub    esp,eax
  552. X    mov    eax,esp
  553. X    add    eax,$4
  554. X    jmp    [ecx]
  555. xEOF
  556. echo x c.c
  557. sed 's/^X//' > c.c << 'xEOF'
  558. X/*
  559. X * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
  560. X * See the copyright notice in the file "../Copyright".
  561. X */
  562. X
  563. X/*    Driver for Minix compilers.
  564. X    Written june 1987 by Ceriel J.H. Jacobs, partly derived from old
  565. X    cc-driver, written by Erik Baalbergen.
  566. X    This driver is mostly table-driven, the table being in the form of
  567. X    some global initialized structures.
  568. X*/
  569. X
  570. X/*
  571. X        extensions added by Christoph van Wuellen (this work begun to
  572. X        support my c68 68000 C-Compiler)
  573. X        
  574. X        - support of three alternate C compilers, selectable at runtime:
  575. X        - the default is: ACK compiling system with 16-bit ints
  576. X        - the -c68s option switches to c68 using 16-bit ints
  577. X        - the -c68l option switches to c68 using 32-bit ints
  578. X        - the -sozo option switches to the SOZOBON compiler with
  579. X              16-bit ints. The postoptimizer is always applied.
  580. X
  581. X        - two features selectable at compile time:
  582. X            - support of ACK floating point stuff (inclusion of a fpp pass)
  583. X            - support of the new MINIX linker posted to comp.os.minix
  584. X
  585. X*/
  586. X/*
  587. X    extensions added by Vincent Broman 1992:
  588. X    support driving bcc3, bcc0, c386 and c387.
  589. X */
  590. X    
  591. X#include <errno.h>
  592. X#include <signal.h>
  593. X
  594. X/*
  595. X * For all program paths (so not the other files, like libraries) that
  596. X * start with "/usr/" and are executable according to access(..., 1),
  597. X * the leading "/usr" is stripped off.
  598. X */
  599. X
  600. X#define SHELL        "/bin/sh"
  601. X
  602. X#define AS        "/usr/bin/as"
  603. X#define CEM        "/usr/lib/cem"
  604. X#define CG        "/usr/lib/cg"
  605. X#define PP        "/usr/lib/cpp"
  606. X#define CRT        "/usr/lib/crtso.o"
  607. X#define CRT32           "/usr/lib/crtso32.o"
  608. X#define CV        "/usr/lib/cv"
  609. X#define PC        "/usr/lib/em_pc"
  610. X#define END        "/usr/lib/end.o"
  611. X#define END32           "/usr/lib/end32.o"
  612. X#define LD        "/usr/lib/ld"
  613. X#define LIBC        "/usr/lib/liback.a"
  614. X#define LIBC68        "/usr/lib/libc68.a"
  615. X#define LIBC6832        "/usr/lib/libc68_32.a"
  616. X#define LIBSOZO        "/usr/lib/libsozo.a"
  617. X#define LIBP        "/usr/lib/libp.a"
  618. X#define OPT        "/usr/lib/opt"
  619. X#define PRT        "/usr/lib/prtso.o"
  620. X#define LIBPREFIX    "/usr/lib/lib"
  621. X
  622. X#define CCCP        "/local/bin/cccp"
  623. X#define DECUSCPP    "/local/bin/cpp"
  624. X#define C386        "/local/bin/c386"
  625. X#define C387        "/local/bin/c387"
  626. X#define SC        "/local/bin/sc"
  627. X#define BAS        "/local/bin/as"
  628. X#define BAS87        "/local/bin/as87"
  629. X#define BLD        "/local/bin/ld"
  630. X#define C386CRT        "/usr/local/lib/c386bas/crtso.o"
  631. X#define C386LIBC    "/usr/local/lib/c386bas/libc.a"
  632. X#define C387CRT        "/usr/local/lib/c387bas/crtso.o"
  633. X#define C387LIBC    "/usr/local/lib/c386bas/libc.a"  /* not separate yet */
  634. X#define B3CRT        "/usr/local/lib/i386/crtso.o"
  635. X#define B3LIBC        "/usr/local/lib/i386/libc.a"
  636. X#define B0CRT        "/usr/local/lib/i86/crtso.o"
  637. X#define B0LIBC        "/usr/local/lib/i86/libc.a"
  638. X
  639. X#define PEM        "-R/usr/lib/pem"
  640. X#define PC_ERR        "-r/usr/lib/pc_errors"
  641. X
  642. X#define C68        "/usr/lib/c68"
  643. X#define FPP        "/usr/lib/fpp"
  644. X#define HCC        "/usr/lib/hcc"
  645. X#define TOP        "/usr/lib/top"
  646. X#define NEW_LD        "/usr/bin/ld"
  647. X
  648. X
  649. X/*    every pass that this program knows about has associated with it
  650. X    a structure, containing such information as its name, where it
  651. X    resides, the flags it accepts, and the like.
  652. X*/
  653. Xstruct passinfo {
  654. X    char *p_name;        /* name of this pass */
  655. X    char *p_path;        /* where is it */
  656. X    char *p_from;        /* suffix of source (comma-separated list) */
  657. X    char *p_to;        /* suffix of destination */
  658. X    char *p_acceptflags;    /* comma separated list; format:
  659. X                       flag
  660. X                       flag*
  661. X                       flag=xxx
  662. X                    flag*=xxx[*]
  663. X                   where a star matches a, possibly empty, 
  664. X                   string
  665. X                */
  666. X    int  p_flags;
  667. X#define INPUT    01        /* needs input file as argument */
  668. X#define OUTPUT    02        /* needs output file as argument */
  669. X#define LOADER    04        /* this pass is the loader */
  670. X#define STDIN    010        /* reads from standard input */
  671. X#define STDOUT    020        /* writes on standard output */
  672. X#define SOURCE    040        /* give source file name as last argument
  673. X                   (hack for pc)
  674. X                */
  675. X#define O_OUTPUT 0100        /* -o outputfile, hack for as */
  676. X#define PREPALWAYS    0200    /* always to be preprocessed */
  677. X#define PREPCOND    0400    /* preprocessed when starting with '#' */
  678. X#define LD2STEPS    01000    /* ld followed by cv */
  679. X};
  680. X
  681. X#define MAXHEAD    7
  682. X#define MAXTAIL    4
  683. X/*
  684. X * MAXPASS used to be 7, but with FPP possibly defined there is an
  685. X * additional pass. If you choose the new linker, the number is again
  686. X * smaller since the new linker does the 'cv' job, too.
  687. X * A too high number does not matter, anyway.
  688. X */
  689. X#define MAXPASS    8
  690. X
  691. X/*    Every language handled by this program has a "compile" structure
  692. X    associated with it, describing the start-suffix, how the driver for
  693. X    this language is called, which passes must be called, which flags
  694. X    and arguments must be passed to these passes, etc.
  695. X    The language is determined by the suffix of the argument program.
  696. X    However, if this suffix does not determine a language (DEFLANG),
  697. X    the callname is used.
  698. X    Notice that the 's' suffix does not determine a language, because
  699. X    the input file could have been derived from f.i. a C-program.
  700. X    So, if you use "cc x.s", the C-runtime system will be used, but if
  701. X    you use "as x.s", it will not.
  702. X*/
  703. Xstruct compile {
  704. X    char *c_suffix;        /* starting suffix of this list of passes */
  705. X    char *c_callname;    /* affects runtime system loaded with program */
  706. X    struct pass {
  707. X        char *pp_name;        /* name of the pass */
  708. X        char *pp_head[MAXHEAD];    /* args in front of filename */
  709. X        char *pp_tail[MAXTAIL];    /* args after filename */
  710. X    } c_passes[MAXPASS];
  711. X    int  c_flags;
  712. X#define DEFLANG        010    /* this suffix determines a language */
  713. X};
  714. X
  715. Xstruct passinfo passinfo[] = {
  716. X    { "cpp", PP, 0, "i", "I*,D*,U*", INPUT|STDOUT },
  717. X#ifdef C68
  718. X    { "c68", C68, "i,c", "s", "Q*", INPUT|OUTPUT|PREPALWAYS },
  719. X#endif
  720. X
  721. X    { "cccp", CCCP, "c", "i", "D*,I*,U*,Wal*,ped*,tri*,nostdinc",
  722. X            INPUT|OUTPUT },
  723. X    { "decuscpp", DECUSCPP, "c", "i", "D*,I*,U*,C,E,N,P,T*,X*",
  724. X            INPUT|OUTPUT },
  725. X    { "app", DECUSCPP, "x", "s", "D*,I*,U*,E,N,P,T*,X*",
  726. X            INPUT|OUTPUT },
  727. X    { "c386", C386, "i", "s", "noopt,noreg,icode,list,warn*,nowarn,trad,noreg",
  728. X            INPUT|OUTPUT },
  729. X    { "c387", C387, "i", "s", "noopt,noreg,icode,list,warn*,nowarn,trad,noreg,nofpu",
  730. X            INPUT|OUTPUT },
  731. X    { "sc", SC, "i,c", "s", "D*,I*,d,p,t", STDIN|STDOUT },
  732. X    { "bas", BAS, "s", "o", "g,j,m", INPUT|O_OUTPUT },
  733. X    { "bas87", BAS87, "s", "o", "g,j,m", INPUT|O_OUTPUT },
  734. X    { "bld", BLD, "o", "out", "M,r,s", INPUT|O_OUTPUT|LOADER },
  735. X
  736. X#ifdef FPP
  737. X    { "fpp", FPP, "m",   "n", "", INPUT|OUTPUT },
  738. X#endif
  739. X#ifdef HCC
  740. X    { "hcc", HCC, "c", "x", "I*,D*,U*", STDIN|STDOUT },
  741. X#endif
  742. X#ifdef TOP
  743. X    { "top", TOP, "x", "s", "", INPUT|OUTPUT },
  744. X#endif
  745. X    { "cem", CEM, "i,c", "k", "R,p,w,T*,I*,D*,U*", INPUT|OUTPUT },
  746. X    { "pc", PC, "i,p", "k", "L,p,w,e,E,T*,{*", INPUT|OUTPUT|SOURCE|PREPCOND },
  747. X    { "opt", OPT, "k", "m", "LIB=L", STDIN|STDOUT },
  748. X#ifdef FPP
  749. X        /* cg processes fpp output */
  750. X    { "cg", CG, "n", "s", "O=p4", INPUT|OUTPUT },
  751. X#else
  752. X    { "cg", CG, "m", "s", "O=p4", INPUT|OUTPUT },
  753. X#endif
  754. X    { "as", AS, "i,s", "o", "T*", INPUT|O_OUTPUT|PREPCOND },
  755. X#ifdef NEW_LD
  756. X    { "ld", NEW_LD, "o", "out", "m*,r,s,u*,w", INPUT|O_OUTPUT|LOADER },
  757. X#else
  758. X    { "ld", LD, "o", "out", "r,s", INPUT|LOADER|LD2STEPS },
  759. X    { "cv", CV, "out", 0, "", INPUT|OUTPUT },    /* must come after loader */
  760. X#endif
  761. X    { 0}
  762. X};
  763. X
  764. Xstruct compile c68_short_pass =
  765. X{    "c", "cc",
  766. X    {    { "c68", {"-Qshort"}, {0} },
  767. X        { "as", {"-"}, {0} },
  768. X#ifdef NEW_LD
  769. X        { "ld", {"-X_","-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT},
  770. X            {LIBC68, END}},
  771. X#else
  772. X        { "ld", {"-c", "-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT}, 
  773. X              {LIBC68, END}},
  774. X        { "cv", {0}, {0} }
  775. X#endif
  776. X    },
  777. X    DEFLANG
  778. X};
  779. X
  780. Xstruct compile c68_long_pass =
  781. X{    "c", "cc",
  782. X    {    { "c68", {"-Qnoshort"}, {0} },
  783. X        { "as", {"-"}, {0} },
  784. X#ifdef NEW_LD
  785. X        { "ld", {"-X_","-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT32},
  786. X            {LIBC6832, END32}},
  787. X#else
  788. X        { "ld", {"-c", "-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT32}, 
  789. X              {LIBC6832, END32}},
  790. X        { "cv", {0}, {0} }
  791. X#endif
  792. X    },
  793. X    DEFLANG
  794. X};
  795. X
  796. Xstruct compile sozobon_pass =
  797. X{    "c", "cc",
  798. X    {    { "hcc", {0}, {0} },
  799. X        { "top", {0}, {0} },
  800. X        { "as", {"-"}, {0} },
  801. X#ifdef NEW_LD
  802. X        { "ld", {"-X_","-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT},
  803. X            {LIBSOZO, END}},
  804. X#else
  805. X        { "ld", {"-c", "-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT}, 
  806. X              {LIBSOZO, END}},
  807. X        { "cv", {0}, {0} }
  808. X#endif
  809. X    },
  810. X    DEFLANG
  811. X};
  812. X
  813. Xstruct compile bcc3_pass =
  814. X{    "c", "c",
  815. X    {    { "sc", {"-3"}, {0} },
  816. X        { "bas", {"-3", "-u", "-w"}, {0} },
  817. X        { "bld", {"-3","-i", B3CRT},
  818. X             {B3LIBC}}
  819. X    },
  820. X    DEFLANG
  821. X};
  822. X
  823. Xstruct compile bcc0_pass =
  824. X{    "c", "c",
  825. X    {    { "sc", {"-0"}, {0} },
  826. X        { "bas", {"-0", "-u", "-w"}, {0} },
  827. X        { "bld", {"-0","-i", B0CRT},
  828. X             {B0LIBC}}
  829. X    },
  830. X    DEFLANG
  831. X};
  832. X
  833. Xstruct compile c386_pass =
  834. X{    "c", "c",
  835. X    {
  836. X        { "cccp", {"-traditional"}, {0} },
  837. X        { "c386", {0}, {0} },
  838. X        { "bas", {"-3", "-j", "-u", "-w"}, {0} },
  839. X        { "bld", {"-3","-i", C386CRT}, {C386LIBC}}
  840. X    },
  841. X    DEFLANG
  842. X};
  843. X
  844. Xstruct compile c387_pass =
  845. X{    "c", "c",
  846. X    {
  847. X        { "decuscpp", {0}, {0} },
  848. X        { "c387", {0}, {0} },
  849. X        { "bas87", {"-3", "-j", "-u", "-w"}, {0} },
  850. X        { "bld", {"-3","-i", C387CRT}, {C387LIBC}}
  851. X    },
  852. X    DEFLANG
  853. X};
  854. X
  855. Xstruct compile ack_pass =
  856. X{    "c", "cc", 
  857. X    {    { "cem", {"-L"}, {0} },
  858. X        { "opt", {0}, {0} },
  859. X#ifdef FPP
  860. X        { "fpp", {0}, {0} },
  861. X#endif
  862. X        { "cg", {0}, {0} },
  863. X        { "as", {"-"}, {0} },
  864. X#ifdef NEW_LD
  865. X        { "ld", {"-X_","-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT},
  866. X            {LIBC, END}},
  867. X#else
  868. X        { "ld", {"-c", "-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT}, 
  869. X              {LIBC, END}},
  870. X         { "cv", {0}, {0} }
  871. X#endif
  872. X    },
  873. X    DEFLANG
  874. X};
  875. X
  876. X/*
  877. X * passes[C_ACK_PASS] has to be replaced by an alternate pass
  878. X * if an alternate compiler is to be used
  879. X */
  880. X#define C_ACK_PASS 0 /* look at the initialization of passes[] */
  881. X
  882. X        
  883. Xstruct compile passes[] = {
  884. X{    "c", "cc", 
  885. X    {    { "cem", {"-L"}, {0} },
  886. X        { "opt", {0}, {0} },
  887. X#ifdef FPP
  888. X        { "fpp", {0}, {0} },
  889. X#endif
  890. X        { "cg", {0}, {0} },
  891. X        { "as", {"-"}, {0} },
  892. X#ifdef NEW_LD
  893. X        { "ld", {"-X_","-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT},
  894. X            {LIBC, END}},
  895. X#else
  896. X        { "ld", {"-c", "-a0:2", "-a1:2", "-a2:2", "-a3:2", CRT}, 
  897. X              {LIBC, END}},
  898. X         { "cv", {0}, {0} }
  899. X#endif
  900. X    },
  901. X    DEFLANG
  902. X},
  903. X{    "p", "pc",
  904. X    {    { "pc", { PEM, PC_ERR, "-Vw2i2j2p2f8l4" }, {0} },
  905. X        { "opt", {0}, {0} },
  906. X        { "cg", {0}, {0} },
  907. X        { "as", {"-"}, {0} },
  908. X#ifdef NEW_LD
  909. X        { "ld", {"-X_","-a0:2", "-a1:2", "-a2:2", "-a3:2", PRT},
  910. X            {LIBP, LIBC, END}},
  911. X#else
  912. X        { "ld", {"-c", "-a0:2", "-a1:2", "-a2:2", "-a3:2", PRT}, 
  913. X              {LIBP, LIBC,
  914. X               END}},
  915. X        { "cv", {0}, {0} }
  916. X#endif
  917. X    },
  918. X    DEFLANG
  919. X},
  920. X{    "s", "as",
  921. X    {    { "as", {0}, {0}}},
  922. X    0
  923. X},
  924. X{    "x", "c",
  925. X    {    { "app", {"-P"}, {0}},
  926. X        { "as", {0}, {0}}
  927. X    },
  928. X    DEFLANG
  929. X},
  930. X{    0
  931. X}
  932. X};
  933. X
  934. X#define MAXARGC    128    /* maximum number of arguments allowed in a list */
  935. X#define USTR_SIZE    64    /* maximum length of string variable */
  936. X
  937. Xtypedef char USTRING[USTR_SIZE];
  938. X
  939. Xstruct arglist {
  940. X    int al_argc;
  941. X    char *al_argv[MAXARGC];
  942. X};
  943. X
  944. Xstruct arglist CALLVEC[2];
  945. X
  946. Xint kids[] = {-1, -1};
  947. X
  948. Xchar *o_FILE = "a.out"; /* default name for executable file */
  949. X
  950. X#define init(a)        ((a)->al_argc = 1)
  951. X#define cleanup(str)        (str && remove(str))
  952. X#define library(nm) \
  953. X    mkstr(alloc((unsigned int)strlen(nm) + strlen(LIBPREFIX) + 7), \
  954. X        LIBPREFIX, nm, ".a")
  955. X
  956. Xchar *ProgCall = 0;
  957. X
  958. Xint RET_CODE = 0;
  959. X
  960. Xchar *stopsuffix = 0;
  961. Xint v_flag = 0;
  962. Xint t_flag = 0;
  963. Xint noexec = 0;
  964. X
  965. Xchar *mkstr();
  966. Xchar *alloc();
  967. Xchar *process();
  968. Xchar *strcpy(), *strcat();
  969. X
  970. XUSTRING curfil;
  971. XUSTRING newfil;
  972. Xstruct arglist SRCFILES;
  973. Xstruct arglist LDFILES;
  974. Xstruct arglist GEN_LDFILES;
  975. Xstruct arglist FLAGS;
  976. X
  977. Xchar *tmpdir = "/tmp";
  978. Xchar tmpname[64];
  979. X
  980. Xstruct compile *compbase;
  981. Xstruct pass *loader;
  982. Xstruct passinfo *loaderinfo;
  983. Xchar *source;
  984. X
  985. Xtrapcc(sig)
  986. X    int sig;
  987. X{
  988. X    signal(sig, SIG_IGN);
  989. X    if (kids[0] != -1) kill(kids[0], sig);
  990. X    if (kids[1] != -1) kill(kids[1], sig);
  991. X    cleanup(newfil);
  992. X    cleanup(curfil);
  993. X    exit(1);
  994. X}
  995. X
  996. X/*
  997. X * trade in a nondefault compiler and
  998. X * ensure that the different C compilers are not called at the same time
  999. X */
  1000. Xvoid
  1001. Xswitch_c_compilers(compiler)
  1002. Xstruct compile compiler;
  1003. X{
  1004. X    static int    pass_changed = 0;
  1005. X    char    *err = 
  1006. X"c: the -bcc3 -bcc0 -c386 -c387 -ack, -sozo, -c68s and -c68l flags are exclusive\n";
  1007. X
  1008. X    if (pass_changed)
  1009. X    {
  1010. X        write(2,err,strlen(err));
  1011. X        exit(1);
  1012. X    }
  1013. X    pass_changed = 1;
  1014. X    passes[C_ACK_PASS] = compiler;
  1015. X}
  1016. X
  1017. Xmain(argc, argv)
  1018. X    char *argv[];
  1019. X{
  1020. X    char *str;
  1021. X    char **argvec;
  1022. X    int count;
  1023. X    char *file;
  1024. X
  1025. X    ProgCall = *argv++;
  1026. X
  1027. X    passes[C_ACK_PASS] = c386_pass;        /* initial default compiler */
  1028. X
  1029. X    signal(SIGHUP, trapcc);
  1030. X    signal(SIGINT, trapcc);
  1031. X    signal(SIGQUIT, trapcc);
  1032. X    while (--argc > 0) {
  1033. X        if (*(str = *argv++) != '-') {
  1034. X            append(&SRCFILES, str);
  1035. X            continue;
  1036. X        }
  1037. X
  1038. X        switch (str[1]) {
  1039. X
  1040. X        case 'a':
  1041. X            if (!strcmp(str,"-ack")) {
  1042. X                switch_c_compilers(ack_pass);
  1043. X            } else {
  1044. X                append(&FLAGS, str);
  1045. X            }
  1046. X            break;
  1047. X        case 'b':
  1048. X            if (!strcmp(str,"-bcc3")) {
  1049. X                switch_c_compilers(bcc3_pass);
  1050. X            } else if (!strcmp(str,"-bcc0")) {
  1051. X                switch_c_compilers(bcc0_pass);
  1052. X            } else {
  1053. X                append(&FLAGS, str);
  1054. X            }
  1055. X            break;
  1056. X        case 'c':
  1057. X            if (!strcmp(str,"-c68s")) {
  1058. X                switch_c_compilers(c68_short_pass);
  1059. X            } else if (!strcmp(str,"-c68l")) {
  1060. X                switch_c_compilers(c68_long_pass);
  1061. X            } else if (!strcmp(str,"-c386")) {
  1062. X                switch_c_compilers(c386_pass);
  1063. X            } else if (!strcmp(str,"-c387")) {
  1064. X                switch_c_compilers(c387_pass);
  1065. X            } else {
  1066. X                stopsuffix = "o";
  1067. X            }
  1068. X            break;
  1069. X        case 'F':
  1070. X            break;
  1071. X        case 'l':
  1072. X            append(&SRCFILES, library(&str[2]));
  1073. X            break;
  1074. X        case 'o':
  1075. X            if (argc-- >= 0)
  1076. X                o_FILE = *argv++;
  1077. X            break;
  1078. X        case 'S':
  1079. X            stopsuffix = "s";
  1080. X            break;
  1081. X        case 'v':
  1082. X            v_flag++;
  1083. X            if (str[2] == 'n')
  1084. X                noexec = 1;
  1085. X            break;
  1086. X        case 't':
  1087. X            /* save temporaries */
  1088. X            t_flag++;
  1089. X            break;
  1090. X        case 's':
  1091. X            if (!strcmp(str,"-sozo")) {
  1092. X                switch_c_compilers(sozobon_pass);
  1093. X            } else {
  1094. X                append(&FLAGS, str);
  1095. X            }
  1096. X            break;
  1097. X        case 'T':
  1098. X            tmpdir = &str[2];
  1099. X            /*FALLTHROUGH*/
  1100. X        default:
  1101. X            append(&FLAGS, str);
  1102. X
  1103. X        }
  1104. X    }
  1105. X
  1106. X/*
  1107. X * The call to mkbase has to be delayed until now since passes[]
  1108. X * is not initialized till now.
  1109. X */
  1110. X        mkbase();
  1111. X    mktempname(tmpname);
  1112. X
  1113. X    count = SRCFILES.al_argc;
  1114. X    argvec = &(SRCFILES.al_argv[0]);
  1115. X
  1116. X    while (count-- > 0) {
  1117. X
  1118. X        file = *argvec++;
  1119. X        source = file;
  1120. X
  1121. X        if (SRCFILES.al_argc > 1) {
  1122. X            write(1, file, strlen(file));
  1123. X            write(1, ":\n", 2);
  1124. X        }
  1125. X
  1126. X        file = process(file, 1);
  1127. X    
  1128. X        if (file && ! stopsuffix) append(&LDFILES, file);
  1129. X    }
  1130. X
  1131. X    clean(&SRCFILES);
  1132. X
  1133. X    /* loader ... */
  1134. X    if (RET_CODE == 0 && LDFILES.al_argc > 0) {
  1135. X        register struct passinfo *pp = passinfo;
  1136. X
  1137. X        while (!(pp->p_flags & LOADER)) pp++;
  1138. X        mkstr(newfil, tmpname, pp->p_to, "");
  1139. X        callld(&LDFILES, (pp->p_flags&LD2STEPS)? newfil: o_FILE,
  1140. X            loader, pp);
  1141. X        if (RET_CODE == 0) {
  1142. X            register int i = GEN_LDFILES.al_argc;
  1143. X
  1144. X            while (i-- > 0) {
  1145. X                remove(GEN_LDFILES.al_argv[i]);
  1146. X                free(GEN_LDFILES.al_argv[i]);
  1147. X            }
  1148. X            if (pp->p_flags&LD2STEPS) {
  1149. X                process(newfil, 0);
  1150. X            }
  1151. X        }
  1152. X    }
  1153. X    exit(RET_CODE);
  1154. X}
  1155. X
  1156. Xremove(str)
  1157. X    char *str;
  1158. X{
  1159. X    if (t_flag)
  1160. X        return;
  1161. X    if (v_flag) {
  1162. X        prs("rm ");
  1163. X        prs(str);
  1164. X        prs("\n");
  1165. X    }
  1166. X    if (noexec)
  1167. X        return;
  1168. X    unlink(str);
  1169. X}
  1170. X
  1171. Xchar *
  1172. Xalloc(u)
  1173. X    unsigned u;
  1174. X{
  1175. X    char *malloc();
  1176. X    register char *p = malloc(u);
  1177. X
  1178. X    if (p == 0) panic("no space\n");
  1179. X    return p;
  1180. X}
  1181. X
  1182. Xappend(al, arg)
  1183. X    struct arglist *al;
  1184. X    char *arg;
  1185. X{
  1186. X    char *a = alloc((unsigned) (strlen(arg) + 1));
  1187. X
  1188. X    strcpy(a, arg);
  1189. X    if (al->al_argc >= MAXARGC)
  1190. X        panic("argument list overflow\n");
  1191. X    al->al_argv[(al->al_argc)++] = a;
  1192. X}
  1193. X
  1194. Xconcat(al1, al2)
  1195. X    struct arglist *al1, *al2;
  1196. X{
  1197. X    register i = al2->al_argc;
  1198. X    register char **p = &(al1->al_argv[al1->al_argc]);
  1199. X    register char **q = &(al2->al_argv[0]);
  1200. X
  1201. X    if ((al1->al_argc += i) >= MAXARGC)
  1202. X        panic("argument list overflow\n");
  1203. X    while (i-- > 0)
  1204. X        *p++ = *q++;
  1205. X}
  1206. X
  1207. Xchar *
  1208. Xmkstr(dst, arg1, arg2, arg3)
  1209. X    char *dst, *arg1, *arg2, *arg3;
  1210. X{
  1211. X    register char *p;
  1212. X    register char *q = dst;
  1213. X
  1214. X    p = arg1;
  1215. X    while (*q++ = *p++);
  1216. X    q--;
  1217. X    p = arg2;
  1218. X    while (*q++ = *p++);
  1219. X    q--;
  1220. X    p = arg3;
  1221. X    while (*q++ = *p++);
  1222. X    q--;
  1223. X    return dst;
  1224. X}
  1225. X
  1226. Xbasename(str, dst)
  1227. X    char *str;
  1228. X    register char *dst;
  1229. X{
  1230. X    register char *p1 = str;
  1231. X    register char *p2 = p1;
  1232. X
  1233. X    while (*p1)
  1234. X        if (*p1++ == '/')
  1235. X            p2 = p1;
  1236. X    p1--;
  1237. X    if (*--p1 == '.') {
  1238. X        *p1 = '\0';
  1239. X        while (*dst++ = *p2++);
  1240. X        *p1 = '.';
  1241. X    }
  1242. X    else
  1243. X        while (*dst++ = *p2++);
  1244. X}
  1245. X
  1246. Xchar *
  1247. Xextension(fln)
  1248. X    char *fln;
  1249. X{
  1250. X    register char *fn = fln;
  1251. X
  1252. X    while (*fn) fn++;
  1253. X    while (fn > fln && *fn != '.') fn--;
  1254. X    if (fn != fln) return fn+1;
  1255. X    return (char *)0;
  1256. X}
  1257. X
  1258. Xrunvec(vec, pass, in, out)
  1259. X    struct arglist *vec;
  1260. X    struct passinfo *pass;
  1261. X    char *in, *out;
  1262. X{
  1263. X    int pid, status;
  1264. X
  1265. X    if (
  1266. X        strncmp(vec->al_argv[1], "/usr/", 5) == 0
  1267. X        &&
  1268. X        access(vec->al_argv[1] + 4, 1) == 0
  1269. X    )
  1270. X        strcpy(vec->al_argv[1], vec->al_argv[1] + 4);
  1271. X    if (v_flag) {
  1272. X        pr_vec(vec);
  1273. X        if (pass->p_flags & STDIN) {
  1274. X            prs(" <");
  1275. X            prs(in);
  1276. X        }
  1277. X        if (pass->p_flags & STDOUT) {
  1278. X            prs(" >");
  1279. X            prs(out);
  1280. X        }
  1281. X        prs("\n");
  1282. X    }
  1283. X    if (noexec)
  1284. X        return 1;
  1285. X    if ((pid = fork()) == 0) {    /* start up the process */
  1286. X        if (pass->p_flags & STDIN) { /* redirect standard input */
  1287. X            close(0);
  1288. X            if (open(in, 0) != 0)
  1289. X                panic("cannot open input file\n");
  1290. X        }
  1291. X        if (pass->p_flags & STDOUT) { /* redirect standard output */
  1292. X            close(1);
  1293. X            if (creat(out, 0666) != 1)
  1294. X                panic("cannot create output file\n");
  1295. X        }
  1296. X        ex_vec(vec);
  1297. X    }
  1298. X    if (pid == -1)
  1299. X        panic("no more processes\n");
  1300. X    kids[0] = pid;
  1301. X    clean(vec);
  1302. X    wait(&status);
  1303. X    kids[0] = -1;
  1304. X    return status ? ((RET_CODE = 1), 0) : 1;
  1305. X}
  1306. X
  1307. Xprs(str)
  1308. X    char *str;
  1309. X{
  1310. X    if (str && *str)
  1311. X        write(2, str, strlen(str));
  1312. X}
  1313. X
  1314. Xpanic(str)
  1315. X    char *str;
  1316. X{
  1317. X    prs(str);
  1318. X    trapcc(SIGINT);
  1319. X}
  1320. X
  1321. Xpr_vec(vec)
  1322. X    register struct arglist *vec;
  1323. X{
  1324. X    register char **ap = &vec->al_argv[1];
  1325. X    
  1326. X    vec->al_argv[vec->al_argc] = 0;
  1327. X    prs(*ap);
  1328. X    while (*++ap) {
  1329. X        prs(" ");
  1330. X        if (strlen(*ap))
  1331. X            prs(*ap);
  1332. X        else
  1333. X            prs("(empty)");
  1334. X    }
  1335. X}
  1336. X
  1337. Xex_vec(vec)
  1338. X    register struct arglist *vec;
  1339. X{
  1340. X    extern int errno;
  1341. X
  1342. X    vec->al_argv[vec->al_argc] = 0;
  1343. X    execv(vec->al_argv[1], &(vec->al_argv[1]));
  1344. X    if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
  1345. X        vec->al_argv[0] = SHELL;
  1346. X        execv(SHELL, &(vec->al_argv[0]));
  1347. X    }
  1348. X    if (access(vec->al_argv[1], 1) == 0) {
  1349. X        /* File is executable. */
  1350. X        prs("Cannot execute ");
  1351. X        prs(vec->al_argv[1]);
  1352. X        prs(". Not enough memory.\n");
  1353. X        prs("Use chmem to reduce its stack allocation\n");
  1354. X    } else {
  1355. X        prs(vec->al_argv[1]);
  1356. X        prs(" is not executable\n");
  1357. X    }
  1358. X    exit(1);
  1359. X}
  1360. X
  1361. Xmktempname(nm)
  1362. X    register char *nm;
  1363. X{
  1364. X    register int i;
  1365. X    register int pid = getpid();
  1366. X
  1367. X    strcpy(nm, tmpdir);
  1368. X    strcat(nm, "/");
  1369. X    strcat(nm, compbase->c_callname);
  1370. X    while (*nm) nm++;
  1371. X
  1372. X    for (i = 9; i > 3; i--) {
  1373. X        *nm++ = (pid % 10) + '0';
  1374. X        pid /= 10;
  1375. X    }
  1376. X    *nm++ = '.';
  1377. X    *nm++ = '\0'; /* null termination */
  1378. X}
  1379. X
  1380. Xmkbase()
  1381. X{
  1382. X    register struct compile *p = passes;
  1383. X    USTRING callname;
  1384. X
  1385. X    basename(ProgCall, callname);
  1386. X    while (p->c_suffix) {
  1387. X        if (strcmp(p->c_callname, callname) == 0) {
  1388. X            compbase = p;
  1389. X            mkloader();
  1390. X            return;
  1391. X        }
  1392. X        p++;
  1393. X    }
  1394. X    /* we should not get here */
  1395. X    panic("internal error\n");
  1396. X}
  1397. X
  1398. Xmkloader()
  1399. X{
  1400. X    register struct passinfo *p = passinfo;
  1401. X    register struct pass *pass;
  1402. X
  1403. X    while (!(p->p_flags & LOADER)) p++;
  1404. X    loaderinfo = p;
  1405. X    pass = &(compbase->c_passes[0]);
  1406. X    while (strcmp(pass->pp_name, p->p_name)) pass++;
  1407. X    loader = pass;
  1408. X}
  1409. X
  1410. Xneedsprep(name)
  1411. X    char *name;
  1412. X{
  1413. X    int file;
  1414. X    char fc;
  1415. X
  1416. X    file = open(name,0);
  1417. X    if (file <0) return 0;
  1418. X    if (read(file, &fc, 1) != 1) fc = 0;
  1419. X    close(file);
  1420. X    return fc == '#';
  1421. X}
  1422. X
  1423. Xchar *
  1424. Xapply(pinf, cp, name, passindex, noremove, first, resultname)
  1425. X    register struct passinfo *pinf;
  1426. X    register struct compile *cp;
  1427. X    char *name, *resultname;
  1428. X{
  1429. X    /*    Apply a pass, indicated by "pinf", with args in 
  1430. X        cp->c_passes[passindex], to name "name", leaving the result
  1431. X        in a file with name "resultname", concatenated with result
  1432. X        suffix.
  1433. X        When neccessary, the preprocessor is run first.
  1434. X        If "noremove" is NOT set, the file "name" is removed.
  1435. X    */
  1436. X
  1437. X    struct arglist *call = &CALLVEC[0];
  1438. X    struct pass *pass = &(cp->c_passes[passindex]);
  1439. X    char *outname;
  1440. X
  1441. X    if ( /* this pass is the first pass */
  1442. X         first
  1443. X       &&
  1444. X         ( /* preprocessor always needed */
  1445. X           (pinf->p_flags & PREPALWAYS)
  1446. X         ||/* or only when "needsprep" says so */
  1447. X           ( (pinf->p_flags & PREPCOND) && needsprep(name))
  1448. X         )
  1449. X       ) {
  1450. X        mkstr(newfil, tmpname, passinfo[0].p_to, "");
  1451. X        mkvec(call, name, newfil, (struct pass *) 0, &passinfo[0]);
  1452. X        if (! runvec(call, &passinfo[0], name, newfil)) {
  1453. X            cleanup(newfil);
  1454. X            return 0;
  1455. X        }
  1456. X        strcpy(curfil, newfil);
  1457. X        newfil[0] = '\0';
  1458. X        name = curfil;
  1459. X        noremove = 0;
  1460. X    }
  1461. X    if (pinf->p_to) outname = mkstr(newfil, resultname, pinf->p_to, "");
  1462. X    else outname = o_FILE;
  1463. X    mkvec(call, name, outname, pass, pinf);
  1464. X    if (! runvec(call, pinf, name, outname)) {
  1465. X        cleanup(outname);
  1466. X        if (! noremove) cleanup(name);
  1467. X        return 0;
  1468. X    }
  1469. X    if (! noremove) cleanup(name);
  1470. X    strcpy(curfil, newfil);
  1471. X    newfil[0] = '\0';
  1472. X    return curfil;
  1473. X}
  1474. X
  1475. Xint
  1476. Xapplicable(pinf, suffix)
  1477. X    struct passinfo *pinf;
  1478. X    char *suffix;
  1479. X{
  1480. X    /*    Return one if the pass indicated by "pinfo" is applicable to
  1481. X        a file with suffix "suffix".
  1482. X    */
  1483. X    register char *sfx = pinf->p_from;
  1484. X
  1485. X    if (! suffix) return 0;
  1486. X    while (*sfx) {
  1487. X        char c;
  1488. X        register char *p = sfx;
  1489. X
  1490. X        while (*p && *p != ',') p++;
  1491. X        c = *p; *p = 0;
  1492. X        if (strcmp(sfx, suffix) == 0) {
  1493. X            *p = c;
  1494. X            return 1;
  1495. X        }
  1496. X        *p = c;
  1497. X        if (*p == ',') sfx = p+1;
  1498. X        else sfx = p;
  1499. X    }
  1500. X    return 0;
  1501. X}
  1502. X        
  1503. Xchar *
  1504. Xprocess(name, noremove)
  1505. X    char *name;
  1506. X{
  1507. X    register struct compile *cp = passes;
  1508. X    char *suffix = extension(name);
  1509. X    USTRING base;
  1510. X    register struct pass *pass;
  1511. X    register struct passinfo *pinf;
  1512. X
  1513. X    if (! suffix) return name;
  1514. X
  1515. X    basename(name, base);
  1516. X
  1517. X    while (cp->c_suffix) {
  1518. X        if ((cp->c_flags & DEFLANG) &&
  1519. X            strcmp(cp->c_suffix, suffix) == 0)
  1520. X            break;
  1521. X        cp++;
  1522. X    }
  1523. X    if (! cp->c_suffix) cp = compbase;
  1524. X    pass = cp->c_passes;
  1525. X    while (pass->pp_name) {
  1526. X        int first = 1;
  1527. X
  1528. X        for (pinf=passinfo; strcmp(pass->pp_name,pinf->p_name);pinf++)
  1529. X            ;
  1530. X        if (! (pinf->p_flags & LOADER) && applicable(pinf, suffix)) {
  1531. X            int cont = ! stopsuffix || ! pinf->p_to ||
  1532. X                    strcmp(stopsuffix, pinf->p_to) != 0;
  1533. X            name = apply(pinf,
  1534. X                     cp,
  1535. X                     name,
  1536. X                     (int)(pass - cp->c_passes),
  1537. X                     noremove,
  1538. X                     first,
  1539. X                     applicable(loaderinfo, pinf->p_to) ||
  1540. X                      !cont ?
  1541. X                    strcat(base, ".") :
  1542. X                    tmpname);
  1543. X            first = noremove = 0;
  1544. X            suffix = pinf->p_to;
  1545. X            if (!cont || !name) break;
  1546. X        }
  1547. X        pass++;
  1548. X    }
  1549. X    if (!noremove && name)
  1550. X        append(&GEN_LDFILES, name);
  1551. X    return name;
  1552. X}
  1553. X
  1554. Xmkvec(call, in, out, pass, pinf)
  1555. X    struct arglist *call;
  1556. X    char *in, *out;
  1557. X    struct pass *pass;
  1558. X    register struct passinfo *pinf;
  1559. X{
  1560. X    register int i;
  1561. X
  1562. X    init(call);
  1563. X    append(call, pinf->p_path);
  1564. X    scanflags(call, pinf);
  1565. X    if (pass) for (i = 0; i < MAXHEAD; i++)
  1566. X        if (pass->pp_head[i])
  1567. X            append(call, pass->pp_head[i]);
  1568. X        else    break;
  1569. X    if (pinf->p_flags & INPUT)
  1570. X        append(call, in);
  1571. X    if (pinf->p_flags & OUTPUT)
  1572. X        append(call, out);
  1573. X    if (pinf->p_flags & O_OUTPUT) {
  1574. X        append(call, "-o");
  1575. X        append(call, out);
  1576. X    }
  1577. X    if (pass) for (i = 0; i < MAXTAIL; i++)
  1578. X        if (pass->pp_tail[i])
  1579. X            append(call, pass->pp_tail[i]);
  1580. X        else    break;
  1581. X    if (pinf->p_flags & SOURCE)
  1582. X        append(call, source);
  1583. X}
  1584. X
  1585. Xcallld(in, out, pass, pinf)
  1586. X    struct arglist *in;
  1587. X    char *out;
  1588. X    struct pass *pass;
  1589. X    register struct passinfo *pinf;
  1590. X{
  1591. X    struct arglist *call = &CALLVEC[0];
  1592. X    register int i;
  1593. X
  1594. X    init(call);
  1595. X    append(call, pinf->p_path);
  1596. X    scanflags(call, pinf);
  1597. X    append(call, "-o");
  1598. X    append(call, out);
  1599. X    for (i = 0; i < MAXHEAD; i++)
  1600. X        if (pass->pp_head[i])
  1601. X            append(call, pass->pp_head[i]);
  1602. X        else    break;
  1603. X    if (pinf->p_flags & INPUT)
  1604. X        concat(call, in);
  1605. X    if (pinf->p_flags & OUTPUT)
  1606. X        append(call, out);
  1607. X    for (i = 0; i < MAXTAIL; i++)
  1608. X        if (pass->pp_tail[i])
  1609. X            append(call, pass->pp_tail[i]);
  1610. X        else    break;
  1611. X    if (! runvec(call, pinf, (char *) 0, out)) {
  1612. X        cleanup(out);
  1613. X        RET_CODE = 1;
  1614. X    }
  1615. X    clean(call);
  1616. X}
  1617. X
  1618. Xclean(c)
  1619. X    register struct arglist *c;
  1620. X{
  1621. X    register int i;
  1622. X
  1623. X    for (i = 1; i < c->al_argc; i++) {
  1624. X        free(c->al_argv[i]);
  1625. X        c->al_argv[i] = 0;
  1626. X    }
  1627. X    c->al_argc = 0;
  1628. X}
  1629. X
  1630. Xscanflags(call, pinf)
  1631. X    struct arglist *call;
  1632. X    struct passinfo *pinf;
  1633. X{
  1634. X    /*    Find out which flags from FLAGS must be passed to pass "pinf",
  1635. X        and how. 
  1636. X        Append them to "call"
  1637. X    */
  1638. X    register int i;
  1639. X    USTRING flg;
  1640. X
  1641. X    for (i = 0; i < FLAGS.al_argc; i++) {
  1642. X        register char *q = pinf->p_acceptflags;
  1643. X
  1644. X        while (*q)  {
  1645. X            register char *p = FLAGS.al_argv[i] + 1;
  1646. X
  1647. X            while ((*q == *p) && *q) {
  1648. X                q++; p++;
  1649. X            }
  1650. X            if (*q == ',' || !*q) {
  1651. X                if (! *p) {
  1652. X                    /* append literally */
  1653. X                    append(call, FLAGS.al_argv[i]);
  1654. X                }
  1655. X                break;
  1656. X            }
  1657. X            if (*q == '*') {
  1658. X                register char *s = flg;
  1659. X
  1660. X                if (*++q != '=') {
  1661. X                    /* append literally */
  1662. X                    append(call, FLAGS.al_argv[i]);
  1663. X                    break;
  1664. X                }
  1665. X                *s++ = '-';
  1666. X                if (*q) q++;    /* skip ',' */
  1667. X                while (*q && *q != ',' && *q != '*') {
  1668. X                    /* copy replacement flag */
  1669. X                    *s++ = *q++;
  1670. X                }
  1671. X                if (*q == '*') {
  1672. X                    /* copy rest */
  1673. X                    while (*p) *s++ = *p++;
  1674. X                }
  1675. X                *s = 0;
  1676. X                append(call, flg);
  1677. X                break;
  1678. X            }
  1679. X            if (*q == '=') {
  1680. X                /* copy replacement */
  1681. X                register char *s = flg;
  1682. X
  1683. X                *s++ = '-';
  1684. X                q++;
  1685. X                while (*q && *q != ',') *s++ = *q++;
  1686. X                *s = 0;
  1687. X                append(call, flg);
  1688. X                break;
  1689. X            }
  1690. X            while (*q && *q++ != ',')
  1691. X                ;
  1692. X        }
  1693. X    }
  1694. X}
  1695. xEOF
  1696.