home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / GOFER2,03aBugFix.LHA / Gofer230a / src / machdep.c < prev   
Encoding:
C/C++ Source or Header  |  1994-09-04  |  19.4 KB  |  745 lines

  1. /* --------------------------------------------------------------------------
  2.  * machdep.c:   Copyright (c) Mark P Jones 1991-1994.   All rights reserved.
  3.  *              See goferite.h for details and conditions of use etc...
  4.  *              Gofer version 2.30 March 1994
  5.  *
  6.  * Machine dependent code
  7.  * RISCOS specific code provided by Bryan Scatergood, JBS
  8.  * ------------------------------------------------------------------------*/
  9.  
  10. #if UNIX
  11. #include <signal.h>
  12. #include <sys/ioctl.h>
  13. #include <fcntl.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #endif
  17.  
  18. #if (TURBOC | BCC)
  19. #include <dos.h>
  20. #include <conio.h>
  21. #include <io.h>
  22. #include <stdlib.h>
  23. #include <mem.h>
  24. #include <sys\stat.h>
  25. #include <time.h>
  26. extern unsigned _stklen = 8000;        /* Allocate an 8k stack segment       */
  27. #endif
  28.  
  29. #if (ZTC | WATCOM)
  30. #include <stdlib.h>
  31. #include <signal.h>
  32. #include <fcntl.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #endif
  36.  
  37. #if DJGPP
  38. #include <dos.h>
  39. #include <stdlib.h>
  40. #include <std.h>
  41. #include <signal.h>
  42. #include <fcntl.h>
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #endif
  46.  
  47. #if RISCOS
  48. #include <assert.h>
  49. #include <signal.h>
  50. #include "swis.h"
  51. #include "os.h"
  52. #endif
  53.  
  54. #if ATARI
  55. #include <signal.h>
  56. #include <fcntl.h>
  57. #include <sys/types.h>
  58. #include <sys/stat.h>
  59. #endif
  60.  
  61. #if (S_AMISAS | R_AMISAS | L_AMISAS)
  62. #include <exec/types.h>
  63. #include <stdlib.h>
  64. #include <stdio.h>
  65. #include <signal.h>
  66. #include <fcntl.h>
  67. #include <sys/types.h>
  68. #include <sys/stat.h>
  69. #include <dos.h>
  70. #ifndef MACHDEP_RUNTIME
  71. __near long __stack = 25000L;
  72. unsigned char amigabreak = 0;
  73. #endif
  74. #endif
  75.  
  76. /* --------------------------------------------------------------------------
  77.  * Machine dependent code is used in each of:
  78.  *    - The gofer interpreter        MACHDEP_GOFER
  79.  *    - The gofer compiler        MACHDEP_GOFC
  80.  *    - The compiler runtime system    MACHDEP_RUNTIME
  81.  * In many cases, the the same code is used in each part.  The following
  82.  * sections of code are enclosed in suitable #if ... #endif directives to
  83.  * indicate which sections require particular parts of the code.  Each of
  84.  * the three systems above defines one of the three symbols on the right
  85.  * above as 1 and then #includes this file.  The following directives make
  86.  * sure that the other macros are set to the correct defaults.
  87.  * ------------------------------------------------------------------------*/
  88.  
  89. #ifndef MACHDEP_GOFER
  90. #define MACHDEP_GOFER   0
  91. #endif
  92. #ifndef MACHDEP_GOFC
  93. #define MACHDEP_GOFC    0
  94. #endif
  95. #ifndef MACHDEP_RUNTIME
  96. #define MACHDEP_RUNTIME 0
  97. #endif
  98.  
  99. /* --------------------------------------------------------------------------
  100.  * Find information about a file:
  101.  * ------------------------------------------------------------------------*/
  102.  
  103. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  104. #if RISCOS
  105. typedef struct { unsigned hi, lo; } Time;
  106. #define timeChanged(now,thn)    (now.hi!=thn.hi || now.lo!=thn.lo)
  107. #define timeSet(var,tm)        var.hi = tm.hi; var.lo = tm.lo
  108. #else
  109. typedef time_t Time;
  110. #define timeChanged(now,thn)    (now!=thn)
  111. #define timeSet(var,tm)        var = tm
  112. #endif
  113.  
  114. static Void local getFileInfo    Args((String, Time *, Long *));
  115.  
  116. static Void local getFileInfo(s,tm,sz)    /* find time stamp and size of file*/
  117. String s;
  118. Time   *tm;
  119. Long   *sz; {
  120. #if RISCOS                /* get file info for RISCOS -- JBS */
  121.     os_regset r;            /* RISCOS PRM p.850 and p.837       */
  122.     r.r[0] = 17;            /* Read catalogue, no path       */
  123.     r.r[1] = (int)s;
  124.     os_swi(OS_File, &r);
  125.     if(r.r[0] == 1 && (r.r[2] & 0xFFF00000) == 0xFFF00000) {
  126.     tm->hi = r.r[2] & 0xFF;        /* Load address (high byte)       */
  127.     tm->lo = r.r[3];        /* Execution address (low 4 bytes) */
  128.     }
  129.     else                /* Not found, or not time-stamped  */
  130.     tm->hi = tm->lo = 0;
  131.     *sz = (Long)(r.r[0] == 1 ? r.r[4] : 0);
  132. #else                    /* normally just use stat()       */
  133.     static struct stat scbuf;
  134.     stat(s,&scbuf);
  135.     *tm = scbuf.st_mtime;
  136.     *sz = (Long)(scbuf.st_size);
  137. #endif
  138. }
  139. #endif
  140.  
  141. #if RISCOS                /* RISCOS needs access()       */
  142. int access(char *s, int dummy) {    /* Give 1 iff cannot access file s */
  143.     os_regset r;            /* RISCOS PRM p.850    -- JBS       */
  144.     assert(dummy == 0);
  145.     r.r[0] = 17; /* Read catalogue, no path */
  146.     r.r[1] = (int)s;
  147.     os_swi(OS_File, &r);
  148.     return r.r[0] != 1;
  149. }
  150.  
  151. int namecmp(char *filename, char *spec){/* For filename extension hacks       */
  152.     while(*spec)
  153.         if  (tolower(*filename) != *spec++)
  154.         return 0;
  155.     else
  156.         ++filename;
  157.     return *filename == '.';
  158. }
  159. #endif
  160.  
  161. /* --------------------------------------------------------------------------
  162.  * Get time/date stamp for inclusion in compiled files:
  163.  * ------------------------------------------------------------------------*/
  164.  
  165. #if MACHDEP_GOFC
  166. #include <time.h>
  167. String timeString() {            /* return time&date string       */
  168.     time_t clock;            /* must end with '\n' character       */
  169.     time(&clock);
  170.     return(ctime(&clock));
  171. }
  172. #endif
  173.  
  174. /* --------------------------------------------------------------------------
  175.  * Garbage collection notification:
  176.  * ------------------------------------------------------------------------*/
  177.  
  178. #if  (MACHDEP_GOFER | MACHDEP_GOFC)
  179. Bool gcMessages = FALSE;        /* TRUE => print GC messages       */
  180.  
  181. Void gcStarted() {            /* notify garbage collector start  */
  182.     if (gcMessages) {
  183.     printf("{{Gc");
  184.     fflush(stdout);
  185.     }
  186. }
  187.  
  188. Void gcScanning() {            /* notify garbage collector scans  */
  189.     if (gcMessages) {
  190.     putchar(':');
  191.     fflush(stdout);
  192.     }
  193. }
  194.  
  195. Void gcRecovered(recovered)        /* notify garbage collection done  */
  196. Int recovered; {
  197.     if (gcMessages) {
  198.     printf("%d}}",recovered);
  199.     fflush(stdout);
  200.     }
  201. }
  202.  
  203. Cell *CStackBase;            /* Retain start of C control stack */
  204.  
  205. #if RISCOS                /* Stack traversal for RISCOS       */
  206.  
  207. /* Warning: The following code is specific to the Acorn ARM under RISCOS
  208.    (and C4).  We must explicitly walk back through the stack frames, since
  209.    the stack is extended from the heap. (see PRM pp. 1757).  gcCStack must
  210.    not be modified, since the offset '5' assumes that only v1 is used inside
  211.    this function. Hence we do all the real work in gcARM.
  212. */
  213.           
  214. #define spreg 13 /* C3 has SP=R13 */
  215.  
  216. #define previousFrame(fp)    ((int *)((fp)[-3]))
  217. #define programCounter(fp)    ((int *)((*(fp)-12) & ~0xFC000003))
  218. #define isSubSPSP(w)        (((w)&dontCare) == doCare)
  219. #define doCare            (0xE24DD000)  /* SUB r13,r13,#0 */
  220. #define dontCare        (~0x00100FFF) /* S and # bits   */
  221. #define immediateArg(x)        ( ((x)&0xFF) << (((x)&0xF00)>>7) )
  222.  
  223. static void gcARM(int *fp) {
  224.     int si = *programCounter(fp);    /* Save instruction indicates how */
  225.                     /* many registers in this frame   */
  226.     int *regs = fp - 4;
  227.     if (si & (1<<0)) markWithoutMove(*regs--);
  228.     if (si & (1<<1)) markWithoutMove(*regs--);
  229.     if (si & (1<<2)) markWithoutMove(*regs--);
  230.     if (si & (1<<3)) markWithoutMove(*regs--);
  231.     if (si & (1<<4)) markWithoutMove(*regs--);
  232.     if (si & (1<<5)) markWithoutMove(*regs--);
  233.     if (si & (1<<6)) markWithoutMove(*regs--);
  234.     if (si & (1<<7)) markWithoutMove(*regs--);
  235.     if (si & (1<<8)) markWithoutMove(*regs--);
  236.     if (si & (1<<9)) markWithoutMove(*regs--);
  237.     if (previousFrame(fp)) {
  238.     /* The non-register stack space is for the previous frame is above
  239.        this fp, and not below the previous fp, because of the way stack
  240.        extension works. It seems the only way of discovering its size is
  241.        finding the SUB sp, sp, #? instruction by walking through the code
  242.        following the entry point.
  243.     */
  244.     int *oldpc = programCounter(previousFrame(fp));
  245.     int fsize = 0, i;
  246.     for(i = 1; i < 6; ++i)
  247.         if(isSubSPSP(oldpc[i])) fsize += immediateArg(oldpc[i]) / 4;
  248.     for(i=1; i<=fsize; ++i)
  249.         markWithoutMove(fp[i]);
  250.     }
  251. }
  252.  
  253. void gcCStack() {
  254.     int dummy;
  255.     int *fp = 5 + &dummy;
  256.     while (fp) {
  257.     gcARM(fp);
  258.     fp = previousFrame(fp);
  259.     }
  260. }
  261.  
  262. #else            /* Garbage collection for standard stack machines  */
  263.  
  264. Void gcCStack() {            /* Garbage collect elements off    */
  265.     Cell stackTop = NIL;        /* C stack               */
  266.     Cell *ptr = &stackTop;
  267. #if SMALL_GOFER
  268.     if (((long)(ptr) - (long)(CStackBase))&1)
  269.     fatal("gcCStack");
  270. #else 
  271.     if (((long)(ptr) - (long)(CStackBase))&3)
  272.     fatal("gcCStack");
  273. #endif
  274.  
  275. #define StackGrowsDown    while (ptr<=CStackBase) markWithoutMove(*ptr++)
  276. #define StackGrowsUp    while (ptr>=CStackBase) markWithoutMove(*ptr--)
  277. #define GuessDirection    if (ptr>CStackBase) StackGrowsUp; else StackGrowsDown
  278. #if HPUX
  279.     GuessDirection;
  280. #else
  281.     StackGrowsDown;
  282. #endif
  283. #undef  StackGrowsDown
  284. #undef  StackGrowsUp
  285. #undef  GuessDirection
  286. }
  287. #endif
  288. #endif
  289.  
  290. /* --------------------------------------------------------------------------
  291.  * Terminal dependent stuff:
  292.  * ------------------------------------------------------------------------*/
  293.  
  294. #if   (TERMIO_IO | SGTTY_IO | TERMIOS_IO)
  295.  
  296. #if TERMIO_IO
  297. #include <termio.h>
  298. typedef  struct termio   TermParams;
  299. #define  getTerminal(tp) ioctl(fileno(stdin),TCGETA,&tp)
  300. #define  setTerminal(tp) ioctl(fileno(stdin),TCSETAF,&tp)
  301. #define  noEcho(tp)      tp.c_lflag    &= ~(ICANON | ECHO); \
  302.              tp.c_cc[VMIN]  = 1;            \
  303.              tp.c_cc[VTIME] = 0;
  304. #endif
  305.  
  306. #if SGTTY_IO
  307. #include <sgtty.h>
  308. typedef  struct sgttyb   TermParams;
  309. #define  getTerminal(tp) ioctl(fileno(stdin),TIOCGETP,&tp)
  310. #define  setTerminal(tp) ioctl(fileno(stdin),TIOCSETP,&tp)
  311. #if HPUX
  312. #define  noEcho(tp)      tp.sg_flags |= RAW; tp.sg_flags &= (~ECHO);
  313. #else
  314. #define  noEcho(tp)      tp.sg_flags |= CBREAK; tp.sg_flags &= (~ECHO);
  315. #endif
  316. #endif
  317.  
  318. #if TERMIOS_IO
  319. #include <termios.h>
  320. typedef  struct termios  TermParams;
  321. #define  getTerminal(tp) tcgetattr(fileno(stdin), &tp)
  322. #define  setTerminal(tp) tcsetattr(fileno(stdin), TCSAFLUSH, &tp)
  323. #define  noEcho(tp)      tp.c_lflag    &= ~(ICANON | ECHO); \
  324.              tp.c_cc[VMIN]  = 1;                \
  325.              tp.c_cc[VTIME] = 0;
  326. #endif
  327.  
  328. static Bool messedWithTerminal = FALSE;
  329. static TermParams originalSettings;
  330.  
  331. Void normalTerminal() {            /* restore terminal initial state  */
  332.     if (messedWithTerminal)
  333.     setTerminal(originalSettings);
  334. }
  335.  
  336. Void noechoTerminal() {            /* set terminal into noecho mode   */
  337.     TermParams settings;
  338.  
  339.     if (!messedWithTerminal) {
  340.     getTerminal(originalSettings);
  341.     messedWithTerminal = TRUE;
  342.     }
  343.     getTerminal(settings);
  344.     noEcho(settings);
  345.     setTerminal(settings);
  346. }
  347.  
  348. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  349. Int getTerminalWidth() {        /* determine width of terminal       */
  350. #ifdef TIOCGWINSZ
  351. #ifdef _M_UNIX                /* SCO Unix 3.2.4 defines TIOCGWINSZ*/
  352. #include <sys/stream.h>            /* Required by sys/ptem.h       */
  353. #include <sys/ptem.h>            /* Required to declare winsize       */
  354. #endif
  355.     static struct winsize terminalSize;
  356.     ioctl(fileno(stdout),TIOCGWINSZ,&terminalSize);
  357.     return (terminalSize.ws_col==0)? 80 : terminalSize.ws_col;
  358. #else
  359.     return 80;
  360. #endif
  361. }
  362. #endif
  363.  
  364. Int readTerminalChar() {        /* read character from terminal       */
  365.     return getchar();            /* without echo, assuming that       */
  366. }                    /* noechoTerminal() is active...   */
  367. #endif
  368.  
  369. #if DOS_IO
  370. static Bool terminalEchoReqd = TRUE;
  371.  
  372. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  373. #if (S_AMISAS | R_AMISAS | L_AMISAS)
  374. Int getTerminalWidth() {
  375.     int lm, rm;
  376.     int c;
  377.     static char *nosizecheck = NULL;
  378.     static int check = 1;
  379.  
  380.     /* If the environment variable GOFERNOWIDTH exists,
  381.      * Gofer will abstain from trying to determine the
  382.      * width of the ternminal.
  383.      * Use it if you run Gofer from inside GNU Emacs;
  384.      * the FIFO device used to communicate lies to both
  385.      * isatty() and rawcon() and claims it is interactive.
  386.      */
  387.  
  388.     if (check) {
  389.         /* Only the first time getTerminalWidth() is called */        
  390.         nosizecheck = getenv("GOFERNOWIDTH");
  391.         check = 0;
  392.     }
  393.  
  394.     if (!nosizecheck && isatty(fileno(stdin)) > 0 && rawcon(1) == 0) {
  395.         printf("%c%s",0x9B,"0 q");    /* Request window size report. */
  396.     /*
  397.      * Now read the size report.
  398.      * <CSI>1;1;<bottom>;<right>r
  399.      */
  400.     c = getchar();
  401.     for (;;) {
  402.             if (c != 0x9B) {        /* <CSI>                       */
  403.                 c = getchar();
  404.                 continue;
  405.             }
  406.             if (!isdigit(c = getchar()))
  407.             continue;        /* Top margin (not used).      */
  408.         while (isdigit(c = getchar()))
  409.             ;
  410.         if (c != ';')
  411.                 continue;        /* ';' seperator.              */
  412.         if (!isdigit(c = getchar()))
  413.             continue;        /* Left margin.                */
  414.             lm = c - '0';
  415.             while (isdigit(c = getchar()))
  416.                 lm = lm * 10 + c - '0';
  417.             if (c != ';')
  418.                 continue;        /* ';' seperator.              */
  419.             if (!isdigit(c = getchar()))
  420.                 continue;        /* Bottom margin (not used).   */
  421.             while (isdigit(c = getchar()))
  422.                 ;
  423.             if (c != ';')
  424.                 continue;        /* ';' seperator.              */
  425.             if (!isdigit(c = getchar()))
  426.                 continue;        /* Right margin.               */
  427.             rm = c - '0';
  428.             while (isdigit(c = getchar()))
  429.                 rm = rm * 10 + c - '0';
  430.             if (c != ' ')
  431.                 continue;        /* " r" terminator.            */
  432.             if ((c = getchar()) != 'r')
  433.                 continue;
  434.         break;
  435.         }
  436.         if (terminalEchoReqd) rawcon(0);
  437.         return rm - lm + 1;
  438.     }
  439.     else
  440.         return 77;            /* Anybody's guess...           */
  441. }
  442. #else
  443. Int getTerminalWidth() {        /* PC screen is fixed 80 chars       */
  444.     return 80;
  445. }
  446. #endif
  447. #endif
  448.  
  449. #if (S_AMISAS | R_AMISAS | L_AMISAS)
  450.  
  451. Void normalTerminal() {            /* restore terminal initial state  */
  452.     terminalEchoReqd = TRUE;
  453.     rawcon(0);
  454. }
  455.  
  456. Void noechoTerminal() {            /* turn terminal echo on/off       */
  457.     terminalEchoReqd = FALSE;
  458.     rawcon(1);
  459. }
  460.  
  461. Int readTerminalChar() {        /* read character from terminal       */
  462.     Int c = getchar();
  463.     /*
  464.      * This circumvents a problem with
  465.      * Gofer code like  'run (map toUpper)'
  466.      */
  467.     if (c == 3) {            /* Ctrl-C is swallowed raw        */
  468.         normalTerminal();        /* turn echo on                   */
  469.     raise(SIGINT);
  470.     c = '\n';            /* is this reasonable?            */
  471.     }
  472.     return c=='\r' ? '\n' : c;
  473. }
  474.  
  475. #else
  476.  
  477. Void normalTerminal() {            /* restore terminal initial state  */
  478.     terminalEchoReqd = TRUE;
  479. }
  480.  
  481. Void noechoTerminal() {            /* turn terminal echo on/off       */
  482.     terminalEchoReqd = FALSE;
  483. }
  484.  
  485. Int readTerminalChar() {        /* read character from terminal       */
  486.     if (terminalEchoReqd)
  487.     return getchar();
  488.     else {
  489.     Int c = getch();
  490.     return c=='\r' ? '\n' : c;
  491.     }
  492. }
  493. #endif
  494.  
  495. #if RISCOS
  496. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  497. Int getTerminalWidth() {
  498.     int dummy, width;
  499.     (void) os_swi3r(OS_ReadModeVariable, -1, 1, 0, &dummy, &dummy, &width);
  500.     return width+1;
  501. }
  502. #endif
  503.  
  504. Void normalTerminal() {            /* restore terminal initial state  */
  505. }                    /* (not yet implemented)       */
  506.  
  507. Void noechoTerminal() {            /* turn terminal echo on/off       */
  508. }                    /* (not yet implemented)       */
  509.  
  510. Int readTerminalChar() {        /* read character from terminal       */
  511.     return getchar();
  512. }
  513. #endif
  514.  
  515. /* --------------------------------------------------------------------------
  516.  * Interrupt handling:
  517.  * ------------------------------------------------------------------------*/
  518.  
  519. #if (MACHDEP_GOFER | MACHDEP_GOFC)    /* runtime.c provides own version  */
  520. static  Bool broken    = FALSE;
  521. static  Bool breakReqd = FALSE;
  522. static  sigProto(ignoreBreak);
  523.  
  524. Bool breakOn(reqd)            /* set break trapping on if reqd,  */
  525. Bool reqd; {                /* or off otherwise, returning old */
  526.     Bool old  = breakReqd;
  527.  
  528.     breakReqd = reqd;
  529.     if (reqd) {
  530.     if (broken) {            /* repond to break signal received */
  531.         broken = FALSE;        /* whilst break trap disabled       */
  532.         sigRaise(breakHandler);
  533.     }
  534.     ctrlbrk(breakHandler);
  535.     }
  536.     else
  537.     ctrlbrk(ignoreBreak);
  538.  
  539.     return old;
  540. }
  541.  
  542. static sigHandler(ignoreBreak) {    /* record but don't respond to break*/
  543.     ctrlbrk(ignoreBreak);
  544.     broken = TRUE;
  545.     sigResume;
  546. }
  547. #endif
  548.  
  549. /* --------------------------------------------------------------------------
  550.  * Shell escapes:
  551.  * ------------------------------------------------------------------------*/
  552.  
  553. #if MACHDEP_GOFER
  554. Int shellEsc(s)                /* run a shell command (or shell)  */
  555. String s; {
  556. #if UNIX
  557.     if (s[0]=='\0')
  558.     s = fromEnv("SHELL","/bin/sh");
  559. #endif
  560.     return system(s);
  561. }
  562.  
  563. #if RISCOS                /* RISCOS also needs a chdir()       */
  564. int chdir(char *s) {            /* RISCOS PRM p. 885    -- JBS       */
  565.     return os_swi2(OS_FSControl + XOS_Bit, 0, (int)s) != NULL;
  566. }
  567. #endif
  568. #endif
  569.  
  570. /* --------------------------------------------------------------------------
  571.  * Floating point support:
  572.  * ------------------------------------------------------------------------*/
  573.  
  574. #if HAS_FLOATS
  575. #if BREAK_FLOATS
  576. static union {
  577.     Float  flVal;
  578.     struct {
  579.     Cell flPart1,flPart2;
  580.     }       clVal;
  581. } fudgeCoerce;
  582.  
  583. Cell part1Float(fl)
  584. FloatPro fl; {
  585.     fudgeCoerce.flVal = fl;
  586.     return fudgeCoerce.clVal.flPart1;
  587. }
  588.  
  589. Cell part2Float(fl)
  590. FloatPro fl; {
  591.     fudgeCoerce.flVal = fl;
  592.     return fudgeCoerce.clVal.flPart2;
  593. }
  594.  
  595. FloatPro floatFromParts(c1,c2)
  596. Cell c1, c2; {
  597.     fudgeCoerce.clVal.flPart1 = c1;
  598.     fudgeCoerce.clVal.flPart2 = c2;
  599.     return fudgeCoerce.flVal;
  600. }
  601.  
  602. Cell mkFloat(fl)
  603. FloatPro fl; {
  604.     Cell p1,p2;
  605.     fudgeCoerce.flVal = fl;
  606.     p1 = mkInt(fudgeCoerce.clVal.flPart1);
  607.     p2 = mkInt(fudgeCoerce.clVal.flPart2);
  608.     return pair(FLOATCELL,pair(p1,p2));
  609. }
  610.  
  611. FloatPro floatOf(c)
  612. Cell c; {
  613.     fudgeCoerce.clVal.flPart1 = intOf(fst(snd(c)));
  614.     fudgeCoerce.clVal.flPart2 = intOf(snd(snd(c)));
  615.     return fudgeCoerce.flVal;
  616. }
  617.  
  618. #if MACHDEP_RUNTIME & BREAK_FLOATS
  619. Cell safeMkFloat(fl)
  620. FloatPro fl; {
  621.     fudgeCoerce.flVal = fl;
  622.     needStack(2);
  623.     pushInt(fudgeCoerce.clVal.flPart2);
  624.     pushInt(fudgeCoerce.clVal.flPart1);
  625.     heap(2);
  626.     mkap();
  627.     topfun(FLOATCELL);
  628.     return pop();
  629. }
  630. #endif
  631.  
  632. #else /* !BREAK_FLOATS */
  633. static union {
  634.     Float flVal;
  635.     Cell  clVal;
  636. } fudgeCoerce;
  637.  
  638. Cell mkFloat(fl)
  639. FloatPro fl; {
  640.     fudgeCoerce.flVal = fl;
  641.     return pair(FLOATCELL,fudgeCoerce.clVal);
  642. }
  643.  
  644. FloatPro floatOf(c)
  645. Cell c; {
  646.     fudgeCoerce.clVal = snd(c);
  647.     return fudgeCoerce.flVal;
  648. }
  649. #endif
  650.  
  651. String floatToString(fl)            /* Make sure that floating   */
  652. FloatPro fl; {                    /* point values print out in */
  653.     static char buffer1[32];            /* a form in which they could*/
  654.     static char buffer2[32];            /* also be entered as floats */
  655.     Int i=0, j=0;
  656.  
  657.     sprintf(buffer1,FloatFMT,fl);
  658.     while (buffer1[i] && strchr("eE.",buffer1[i])==0)
  659.     buffer2[j++] = buffer1[i++];
  660.     if (buffer1[i]!='.') {
  661.         buffer2[j++] = '.';
  662.     buffer2[j++] = '0';
  663.     }
  664.     while (buffer2[j++]=buffer1[i++])
  665.     ;
  666.     return buffer2;
  667. }
  668.  
  669. FloatPro stringToFloat(s)
  670. String s; {
  671.     return atof(s);
  672. }
  673. #else
  674. Cell mkFloat(fl)
  675. FloatPro fl; {
  676.     internal("mkFloat");
  677.     return 0;/*NOTREACHED*/
  678. }
  679.  
  680. FloatPro floatOf(c)
  681. Cell c; {
  682.     internal("floatOf");
  683.     return 0;/*NOTREACHED*/
  684. }
  685.  
  686. String floatToString(fl)
  687. FloatPro fl; {
  688.     internal("floatToString");
  689.     return "";/*NOTREACHED*/
  690. }
  691.  
  692. FloatPro stringToFloat(s)
  693. String s; {
  694.     internal("stringToFloat");
  695.     return 0;
  696. }
  697. #endif
  698.  
  699. /* --------------------------------------------------------------------------
  700.  * Machine dependent control:
  701.  * ------------------------------------------------------------------------*/
  702.  
  703. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  704. #if UNIX
  705. static sigHandler(panic) {        /* exit in a panic, on receipt of  */
  706.     everybody(EXIT);            /* an unexpected signal           */
  707.     fprintf(stderr,"Unexpected signal\n");
  708.     exit(1);
  709.     sigResume;/*NOTREACHED*/
  710. }
  711. #endif
  712.  
  713. Void machdep(what)            /* Handle machine specific       */
  714. Int what; {                /* initialisation etc..           */
  715.     switch (what) {
  716.         case MARK    : break;
  717. #if UNIX
  718.         case INSTALL :
  719. #ifdef SIGHUP
  720.                signal(SIGHUP,panic);
  721. #endif
  722. #ifdef SIGQUIT
  723.                signal(SIGQUIT,panic);
  724. #endif
  725. #ifdef SIGTERM
  726.                signal(SIGTERM,panic);
  727. #endif
  728. #ifdef SIGSEGV
  729.                signal(SIGSEGV,panic);
  730. #endif
  731. #ifdef SIGBUS
  732.                signal(SIGBUS,panic);
  733. #endif
  734.                break;
  735. #endif
  736.         case RESET   :
  737.     case BREAK   :
  738.     case EXIT    : normalTerminal();
  739.                break;
  740.     }
  741. }
  742. #endif
  743.  
  744. /*-------------------------------------------------------------------------*/
  745.