home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacGofer 0.22d / MacGofer Sources / machdep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-08  |  19.8 KB  |  808 lines  |  [TEXT/MPS ]

  1. /* --------------------------------------------------------------------------
  2.  * machdep.c:   Copyright (c) Mark P Jones 1991-1993.   All rights reserved.
  3.  *              See goferite.h for details and conditions of use etc...
  4.  *              Gofer version 2.28 January 1993
  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
  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 MPW
  55. #include <stdio.h>
  56. #include <types.h>
  57. #include <memory.h>
  58.  
  59. /* Replaces stat.h for the Mac    */
  60. #include <Time.h>
  61. // typedef long time_t;
  62.  
  63. struct stat
  64. {
  65.   time_t st_mtime;
  66.   long   st_size;
  67. };
  68.  
  69. #pragma segment Machdep
  70. #endif
  71.  
  72. #if MAC
  73. #define    ILLEGAL_WINDOW    (-1)    /* In mac.h, but we can't include that here! */
  74.  
  75. #include <CursorCtl.h>        /* For rotating cursors/GC cursor */
  76. #endif
  77.  
  78.  
  79. /* --------------------------------------------------------------------------
  80.  * Machine dependent code is used in each of:
  81.  *    - The gofer interpreter        MACHDEP_GOFER
  82.  *    - The gofer compiler        MACHDEP_GOFC
  83.  *    - The compiler runtime system    MACHDEP_RUNTIME
  84.  * In many cases, the the same code is used in each part.  The following
  85.  * sections of code are enclosed in suitable #if ... #endif directives to
  86.  * indicate which sections require particular parts of the code.  Each of
  87.  * the three systems above defines one of the three symbols on the right
  88.  * above as 1 and then #includes this file.  The following directives make
  89.  * sure that the other macros are set to the correct defaults.
  90.  * ------------------------------------------------------------------------*/
  91.  
  92. #ifndef MACHDEP_GOFER
  93. #define MACHDEP_GOFER   0
  94. #endif
  95. #ifndef MACHDEP_GOFC
  96. #define MACHDEP_GOFC    0
  97. #endif
  98. #ifndef MACHDEP_RUNTIME
  99. #define MACHDEP_RUNTIME 0
  100. #endif
  101.  
  102. /* --------------------------------------------------------------------------
  103.  * Find information about a file:
  104.  * ------------------------------------------------------------------------*/
  105.  
  106. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  107. #if RISCOS
  108. typedef struct { unsigned hi, lo; } Time;
  109. #define timeChanged(now,thn)    (now.hi!=thn.hi || now.lo!=thn.lo)
  110. #define timeSet(var,tm)        var.hi = tm.hi; var.lo = tm.lo
  111. #else
  112. typedef time_t Time;
  113. #define timeChanged(now,thn)    (now!=thn)
  114. #define timeSet(var,tm)        var = tm
  115. #endif
  116.  
  117. static Void local getFileInfo    Args((String, Time *, Long *));
  118.  
  119. static Void local getFileInfo(s,tm,sz)    /* find time stamp and size of file*/
  120. String s;
  121. Time   *tm;
  122. Long   *sz; {
  123. #if RISCOS                /* get file info for RISCOS -- JBS */
  124.     os_regset r;            /* RISCOS PRM p.850 and p.837       */
  125.     r.r[0] = 17;            /* Read catalogue, no path       */
  126.     r.r[1] = (int)s;
  127.     os_swi(OS_File, &r);
  128.     if(r.r[0] == 1 && (r.r[2] & 0xFFF00000) == 0xFFF00000) {
  129.     tm->hi = r.r[2] & 0xFF;        /* Load address (high byte)       */
  130.     tm->lo = r.r[3];        /* Execution address (low 4 bytes) */
  131.     }
  132.     else                /* Not found, or not time-stamped  */
  133.     tm->hi = tm->lo = 0;
  134.     *sz = (Long)(r.r[0] == 1 ? r.r[4] : 0);
  135. #else                    /* normally just use stat()       */
  136.     static struct stat scbuf;
  137.     stat(s,&scbuf);
  138.     *tm = scbuf.st_mtime;
  139.     *sz = (Long)(scbuf.st_size);
  140. #endif
  141. }
  142. #endif
  143.  
  144. #if RISCOS                /* RISCOS needs access()       */
  145. int access(char *s, int dummy) {    /* Give 1 iff cannot access file s */
  146.     os_regset r;            /* RISCOS PRM p.850    -- JBS       */
  147.     assert(dummy == 0);
  148.     r.r[0] = 17; /* Read catalogue, no path */
  149.     r.r[1] = (int)s;
  150.     os_swi(OS_File, &r);
  151.     return r.r[0] != 1;
  152. }
  153. #endif
  154.  
  155. /* --------------------------------------------------------------------------
  156.  * stat and chdir for MPW:
  157.  * ------------------------------------------------------------------------*/
  158.  
  159. #if MPW
  160.  
  161. #include <Values.h>
  162. #include <Types.h>          /*  Basic type definitions         */
  163. #include <Files.h>
  164. #if !THINKC
  165. #include <Strings.h>
  166. #endif
  167.  
  168. stat(file,sb)
  169. char *file;
  170. struct stat *sb;
  171. {
  172.   FileParam finfo;
  173.   short volnum;
  174.   
  175.   GetVol(NULL,&volnum);
  176.  
  177.   finfo.ioCompletion = NULL;
  178. #if THINKC
  179.   finfo.ioNamePtr = (StringPtr) c2pstr(file);
  180. #else
  181.   finfo.ioNamePtr = c2pstr(file);
  182. #endif
  183.   finfo.ioVRefNum = volnum;
  184.   finfo.ioFVersNum = 0;
  185.   finfo.ioFDirIndex = 0;
  186.   
  187.   PBGetFInfo((ParmBlkPtr)&finfo,FALSE);
  188.   
  189.   /* Use getfinfo to return the modification time for "file" */
  190.   sb->st_mtime = finfo.ioFlMdDat;
  191.   sb->st_size = finfo.ioFlLgLen;
  192.  
  193.  /* Now restore the string! */
  194.  p2cstr(file);
  195. }
  196.  
  197.  
  198. chdir(s)
  199. char *s;
  200. {
  201.   WDPBRec pb;
  202.   pb.ioCompletion = NULL;
  203.   c2pstr(s);
  204.   pb.ioNamePtr=(StringPtr)s;
  205.   pb.ioVRefNum = 0;
  206.   pb.ioWDDirID = 0;
  207.   PBHSetVol(&pb,FALSE);
  208.   p2cstr(s);
  209.  
  210.   /* Check whether the directory exists */
  211.   if(pb.ioResult == noErr)
  212.     {
  213. #if MAC
  214.       /* If so, get the volume reference and directory ID and save it */
  215.       PBHGetVol(&pb,FALSE);
  216.       savedir(pb.ioVRefNum,pb.ioWDDirID,FALSE);
  217. #endif
  218.       return(0);
  219.     }
  220.   else
  221.     return(1);
  222. }
  223. #endif
  224.  
  225.  
  226. /* --------------------------------------------------------------------------
  227.  * Get time/date stamp for inclusion in compiled files:
  228.  * ------------------------------------------------------------------------*/
  229.  
  230. #if MACHDEP_GOFC
  231. #include <time.h>
  232. String timeString() {            /* return time&date string       */
  233.     time_t clock;            /* must end with '\n' character       */
  234.     time(&clock);
  235.     return(ctime(&clock));
  236. }
  237. #endif
  238.  
  239. /* --------------------------------------------------------------------------
  240.  * Garbage collection notification:
  241.  * ------------------------------------------------------------------------*/
  242.  
  243. #if  (MACHDEP_GOFER | MACHDEP_GOFC)
  244. Bool gcMessages = FALSE;        /* TRUE => print GC messages       */
  245.  
  246. Void gcStarted() {            /* notify garbage collector start  */
  247.     if (gcMessages) {
  248.     printf("{{Gc");
  249.     fflush(stdout);
  250.     }
  251. }
  252.  
  253. Void gcScanning() {            /* notify garbage collector scans  */
  254.     if (gcMessages) {
  255.     putchar(':');
  256.     fflush(stdout);
  257.     }
  258. }
  259.  
  260. Void gcRecovered(recovered)        /* notify garbage collection done  */
  261. Int recovered; {
  262.     if (gcMessages) {
  263.     printf("%d}}",recovered);
  264.     fflush(stdout);
  265.     }
  266. }
  267.  
  268. Cell *CStackBase;            /* Retain start of C control stack */
  269.  
  270. #if RISCOS                /* Stack traversal for RISCOS       */
  271.  
  272. /* Warning: The following code is specific to the Acorn ARM under RISCOS
  273.    (and C4).  We must explicitly walk back through the stack frames, since
  274.    the stack is extended from the heap. (see PRM pp. 1757).  gcCStack must
  275.    not be modified, since the offset '5' assumes that only v1 is used inside
  276.    this function. Hence we do all the real work in gcARM.
  277. */
  278.           
  279. #define spreg 13 /* C3 has SP=R13 */
  280.  
  281. #define previousFrame(fp)    ((int *)((fp)[-3]))
  282. #define programCounter(fp)    ((int *)((*(fp)-12) & ~0xFC000003))
  283. #define isSubSPSP(w)        (((w)&dontCare) == doCare)
  284. #define doCare            (0xE24DD000)  /* SUB r13,r13,#0 */
  285. #define dontCare        (~0x00100FFF) /* S and # bits   */
  286. #define immediateArg(x)        ( ((x)&0xFF) << (((x)&0xF00)>>7) )
  287.  
  288. static void gcARM(int *fp) {
  289.     int si = *programCounter(fp);    /* Save instruction indicates how */
  290.                     /* many registers in this frame   */
  291.     int *regs = fp - 4;
  292.     if (si & (1<<0)) markWithoutMove(*regs--);
  293.     if (si & (1<<1)) markWithoutMove(*regs--);
  294.     if (si & (1<<2)) markWithoutMove(*regs--);
  295.     if (si & (1<<3)) markWithoutMove(*regs--);
  296.     if (si & (1<<4)) markWithoutMove(*regs--);
  297.     if (si & (1<<5)) markWithoutMove(*regs--);
  298.     if (si & (1<<6)) markWithoutMove(*regs--);
  299.     if (si & (1<<7)) markWithoutMove(*regs--);
  300.     if (si & (1<<8)) markWithoutMove(*regs--);
  301.     if (si & (1<<9)) markWithoutMove(*regs--);
  302.     if (previousFrame(fp)) {
  303.     /* The non-register stack space is for the previous frame is above
  304.        this fp, and not below the previous fp, because of the way stack
  305.        extension works. It seems the only way of discovering its size is
  306.        finding the SUB sp, sp, #? instruction by walking through the code
  307.        following the entry point.
  308.     */
  309.     int *oldpc = programCounter(previousFrame(fp));
  310.     int fsize = 0, i;
  311.     for(i = 1; i < 6; ++i)
  312.         if(isSubSPSP(oldpc[i])) fsize += immediateArg(oldpc[i]) / 4;
  313.     for(i=1; i<=fsize; ++i)
  314.         markWithoutMove(fp[i]);
  315.     }
  316. }
  317.  
  318. void gcCStack() {
  319.     int dummy;
  320.     int *fp = 5 + &dummy;
  321.     while (fp) {
  322.     gcARM(fp);
  323.     fp = previousFrame(fp);
  324.     }
  325. }
  326.  
  327. #else            /* Garbage collection for standard stack machines  */
  328.  
  329. /* 
  330.        The probability of this working on the Mac without chaining 
  331.        properly through A6 frames doesn't seem high.
  332.        
  333.        Format:
  334.                A7 -->  | ???              |
  335.                        |------------------|
  336.            A6 -->  | Prev Stack Frame |
  337.                    | Return Address   |
  338.                | values???        |
  339.                | ...              |
  340.                |------------------|
  341.                | Prev Stack Frame |
  342.                | ...              |
  343.                
  344.        If a non 4-byte value is passed anywhere on the C stack, then the 
  345.        test for legal cells will be invalid (since we'll be comparing junk
  346.        with cell values).  Result, misery.  (Illegal cells will be collected,
  347.        and the Mac version will sometimes crash horribly as a result of not
  348.        collecting the legal cells!).  If some values are held in registers,
  349.        the problems are potentially even worse.
  350.  
  351.        It might be more sensible to explicitly push and pop cells onto
  352.        an auxiliary stack. This is likely to fail for architectures other than 
  353.        the Mac, including Unix boxes, so it isn't entirely academic...
  354.  
  355.        KH
  356. */
  357.  
  358. Void gcCStack() {            /* Garbage collect elements off    */
  359.     Cell stackTop = NIL;        /* C stack               */
  360.     Cell *ptr = &stackTop;
  361.     if (((long)(ptr) - (long)(CStackBase))&(sizeof(Cell)-1))
  362.       {
  363. #if MAC
  364. //      DebugStr("Misaligned C Stack During GC");
  365.           AbortError("","Misaligned Macintosh Stack During GC");
  366. #else
  367.           fatal("gcCstack");
  368. #endif
  369.       }
  370.  
  371. #define StackGrowsDown    while (ptr<=CStackBase) markWithoutMove(*ptr++)
  372. #define StackGrowsUp    while (ptr>=CStackBase) markWithoutMove(*ptr--)
  373. #define GuessDirection    if (ptr>CStackBase) StackGrowsUp; else StackGrowsDown
  374. #if HPUX
  375.     GuessDirection;
  376. #else
  377.     StackGrowsDown;
  378. #endif
  379. #undef  StackGrowsDown
  380. #undef  StackGrowsUp
  381. #undef  GuessDirection
  382. }
  383. #endif
  384. #endif
  385.  
  386. /* --------------------------------------------------------------------------
  387.  * Terminal dependent stuff:
  388.  * ------------------------------------------------------------------------*/
  389.  
  390. #if   (TERMIO_IO | SGTTY_IO)
  391.  
  392. #if TERMIO_IO
  393. #include <termio.h>
  394. typedef  struct termio   TermParams;
  395. #define  getTerminal(tp) ioctl(fileno(stdin),TCGETA,&tp)
  396. #define  setTerminal(tp) ioctl(fileno(stdin),TCSETAF,&tp)
  397. #define  noEcho(tp)      tp.c_lflag    &= ~(ICANON | ECHO); \
  398.              tp.c_cc[VMIN]  = 1;            \
  399.              tp.c_cc[VTIME] = 0;
  400. #endif
  401.  
  402. #if SGTTY_IO
  403. #include <sgtty.h>
  404. typedef  struct sgttyb   TermParams;
  405. #define  getTerminal(tp) ioctl(fileno(stdin),TIOCGETP,&tp)
  406. #define  setTerminal(tp) ioctl(fileno(stdin),TIOCSETP,&tp)
  407. #if HPUX
  408. #define  noEcho(tp)      tp.sg_flags |= RAW; tp.sg_flags &= (~ECHO);
  409. #else
  410. #define  noEcho(tp)      tp.sg_flags |= CBREAK; tp.sg_flags &= (~ECHO);
  411. #endif
  412. #endif
  413.  
  414. static Bool messedWithTerminal = FALSE;
  415. static TermParams originalSettings;
  416.  
  417. Void normalTerminal() {            /* restore terminal initial state  */
  418.     if (messedWithTerminal)
  419.     setTerminal(originalSettings);
  420. }
  421.  
  422. Void noechoTerminal() {            /* set terminal into noecho mode   */
  423.     TermParams settings;
  424.  
  425.     if (!messedWithTerminal) {
  426.     getTerminal(originalSettings);
  427.     messedWithTerminal = TRUE;
  428.     }
  429.     getTerminal(settings);
  430.     noEcho(settings);
  431.     setTerminal(settings);
  432. }
  433.  
  434. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  435. Int getTerminalWidth() {        /* determine width of terminal       */
  436. #ifdef TIOCGWINSZ
  437. #ifdef _M_UNIX                /* SCO Unix 3.2.4 defines TIOCGWINSZ*/
  438. #include <sys/stream.h>            /* Required by sys/ptem.h       */
  439. #include <sys/ptem.h>            /* Required to declare winsize       */
  440. #endif
  441.     static struct winsize terminalSize;
  442.     ioctl(fileno(stdout),TIOCGWINSZ,&terminalSize);
  443.     return (terminalSize.ws_col==0)? 80 : terminalSize.ws_col;
  444. #else
  445.     return 80;
  446. #endif
  447. }
  448. #endif
  449.  
  450. Int readTerminalChar() {        /* read character from terminal       */
  451.     return getchar();            /* without echo, assuming that       */
  452. }                    /* noechoTerminal() is active...   */
  453. #endif
  454.  
  455. #if DOS_IO
  456. Bool terminalEchoReqd = TRUE;
  457.  
  458. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  459. Int getTerminalWidth() {        /* PC screen is fixed 80 chars       */
  460.     return 80;
  461. }
  462. #endif
  463.  
  464. Void normalTerminal() {            /* restore terminal initial state  */
  465.     terminalEchoReqd = TRUE;
  466. }
  467.  
  468. Void noechoTerminal() {            /* turn terminal echo on/off       */
  469.     terminalEchoReqd = FALSE;
  470. }
  471.  
  472. #if !MPW
  473. Int readTerminalChar() {        /* read character from terminal       */
  474.     if (terminalEchoReqd)
  475.     return getchar();
  476.     else {
  477.     Int c = getch();
  478.     return c=='\r' ? '\n' : c;
  479.     }
  480. }
  481. #else /* !MPW */
  482. Int readTerminalChar() {        /* read character from terminal       */
  483.     return getchar();
  484. }
  485. #endif
  486. #endif    /* DOS_IO */
  487.  
  488. #if RISCOS
  489. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  490. Int getTerminalWidth() {
  491.     int dummy, width;
  492.     (void) os_swi3r(OS_ReadModeVariable, -1, 1, 0, &dummy, &dummy, &width);
  493.     return width+1;
  494. }
  495. #endif
  496.  
  497. Void normalTerminal() {            /* restore terminal initial state  */
  498. }                    /* (not yet implemented)       */
  499.  
  500. Void noechoTerminal() {            /* turn terminal echo on/off       */
  501. }                    /* (not yet implemented)       */
  502.  
  503. Int readTerminalChar() {        /* read character from terminal       */
  504.     return getchar();
  505. }
  506. #endif    /* RISCOS */
  507.  
  508.  
  509. /* --------------------------------------------------------------------------
  510.  * Interrupt handling:
  511.  * ------------------------------------------------------------------------*/
  512.  
  513. #if (MACHDEP_GOFER | MACHDEP_GOFC)    /* runtime.c provides own version  */
  514. static  Bool broken    = FALSE;
  515. static  Bool breakReqd = FALSE;
  516. static  sigProto(ignoreBreak);
  517.  
  518. Bool breakOn(reqd)            /* set break trapping on if reqd,  */
  519. Bool reqd; {                /* or off otherwise, returning old */
  520.     Bool old  = breakReqd;
  521.  
  522.     breakReqd = reqd;
  523.     if (reqd) {
  524.     if (broken) {            /* repond to break signal received */
  525.         broken = FALSE;        /* whilst break trap disabled       */
  526.         sigRaise(breakHandler);
  527.     }
  528.     ctrlbrk(breakHandler);
  529.     }
  530.     else
  531.     ctrlbrk(ignoreBreak);
  532.  
  533.     return old;
  534. }
  535.  
  536. static sigHandler(ignoreBreak) {    /* record but don't respond to break*/
  537.     ctrlbrk(ignoreBreak);
  538.     broken = TRUE;
  539.     sigResume;
  540. }
  541. #endif
  542.  
  543. /* --------------------------------------------------------------------------
  544.  * Shell escapes:
  545.  * ------------------------------------------------------------------------*/
  546.  
  547. #if MACHDEP_GOFER
  548. Int shellEsc(s)                /* run a shell command (or shell)  */
  549. String s; {
  550. #if UNIX
  551.     if (s[0]=='\0')
  552.     s = fromEnv("SHELL","/bin/sh");
  553. #endif
  554.     return system(s);
  555. }
  556.  
  557. #if RISCOS                /* RISCOS also needs a chdir()       */
  558. int chdir(char *s) {            /* RISCOS PRM p. 885    -- JBS       */
  559.     return os_swi2(OS_FSControl + XOS_Bit, 0, (int)s) != NULL;
  560. }
  561. #endif
  562. #endif
  563.  
  564. /* --------------------------------------------------------------------------
  565.  * Floating point support:  See machine.c for why this is so contorted -- KH
  566.  * ------------------------------------------------------------------------*/
  567.  
  568. #if HAS_FLOATS
  569. #if !MPW
  570. #if BREAK_FLOATS
  571. static union {
  572.     Float  flVal;
  573.     struct {
  574.     Cell flPart1,flPart2;
  575.     }       clVal;
  576. } fudgeCoerce;
  577.  
  578. Cell part1Float(fl)
  579. FloatPro fl; {
  580.     fudgeCoerce.flVal = fl;
  581.     return fudgeCoerce.clVal.flPart1;
  582. }
  583.  
  584. Cell part2Float(fl)
  585. FloatPro fl; {
  586.     fudgeCoerce.flVal = fl;
  587.     return fudgeCoerce.clVal.flPart2;
  588. }
  589.  
  590. FloatPro floatFromParts(c1,c2)
  591. Cell c1, c2; {
  592.     fudgeCoerce.clVal.flPart1 = c1;
  593.     fudgeCoerce.clVal.flPart2 = c2;
  594.     return fudgeCoerce.flVal;
  595. }
  596.  
  597. Cell mkFloat(fl)
  598. FloatPro fl; {
  599.     Cell p1,p2;
  600.     fudgeCoerce.flVal = fl;
  601.     p1 = mkInt(fudgeCoerce.clVal.flPart1);
  602.     p2 = mkInt(fudgeCoerce.clVal.flPart2);
  603.     return pair(FLOATCELL,pair(p1,p2));
  604. }
  605.  
  606. FloatPro floatOf(c)
  607. Cell c; {
  608.     fudgeCoerce.clVal.flPart1 = intOf(fst(snd(c)));
  609.     fudgeCoerce.clVal.flPart2 = intOf(snd(snd(c)));
  610.     return fudgeCoerce.flVal;
  611. }
  612.  
  613. #if MACHDEP_RUNTIME & BREAK_FLOATS
  614. Cell safeMkFloat(fl)
  615. FloatPro fl; {
  616.     fudgeCoerce.flVal = fl;
  617.     needStack(2);
  618.     pushInt(fudgeCoerce.clVal.flPart2);
  619.     pushInt(fudgeCoerce.clVal.flPart1);
  620.     heap(2);
  621.     mkap();
  622.     topfun(FLOATCELL);
  623.     return pop();
  624. }
  625. #endif
  626.  
  627. #else /* !BREAK_FLOATS */
  628. static union {
  629.     Float flVal;
  630.     Cell  clVal;
  631. } fudgeCoerce;
  632.  
  633. Cell mkFloat(fl)
  634. FloatPro fl; {
  635.     fudgeCoerce.flVal = fl;
  636.     return pair(FLOATCELL,fudgeCoerce.clVal);
  637. }
  638.  
  639. Cell mkFloatFromStr(s)
  640. String s; {
  641.     return(mkFloat(stringToFloat(s)));
  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.  
  674. #else  /* !MPW */
  675.  
  676. static union {
  677.     float flVal;
  678.     Cell  clVal;
  679. } fudgeCoerce;
  680.  
  681. extern double atof Args((String));
  682.  
  683.  
  684. Cell mkFloat(fl)
  685. FloatPro fl; {
  686.     return pair(FLOATCELL,fl);
  687. }
  688.  
  689. Cell mkFloatFromStr(s)
  690. String s; {
  691.     return(mkFloat(stringToFloat(s)));
  692. }
  693.  
  694.  
  695. Float floatOf(c)
  696. Cell c; {
  697.     return(snd(c));
  698. }
  699.  
  700.  
  701. String floatToString(fl)            /* Make sure that floating   */
  702. FloatPro fl;                                    /* Point Values are output in */
  703. {
  704.     static char buffer1[32];            /* a form in which they could*/
  705.     static char buffer2[32];            /* also be entered as floats */
  706.     Int i=0, j=0;
  707.  
  708.     fudgeCoerce.clVal = fl;
  709.  
  710.     sprintf(buffer1,"%g",(double) fudgeCoerce.flVal);
  711.  
  712.     while (buffer1[i] && strchr("eE.",buffer1[i])==0)
  713.     buffer2[j++] = buffer1[i++];
  714.     if (buffer1[i]!='.') {
  715.         buffer2[j++] = '.';
  716.     buffer2[j++] = '0';
  717.     }
  718.     while (buffer2[j++]=buffer1[i++])
  719.     ;
  720.     return buffer2;
  721. }
  722.  
  723. Float stringToFloat(s)
  724. String s; {
  725.     double fld = atof(s);
  726.     fudgeCoerce.flVal = (float) fld;
  727.     return fudgeCoerce.clVal;
  728. }
  729.  
  730. #endif
  731.  
  732. #else    /* HAS_FLOATS */
  733.  
  734. Cell mkFloat(fl)
  735. FloatPro fl; {
  736.     internal("mkFloat");
  737.     return 0;/*NOTREACHED*/
  738. }
  739.  
  740. FloatPro floatOf(c)
  741. Cell c; {
  742.     internal("floatOf");
  743.     return 0;/*NOTREACHED*/
  744. }
  745.  
  746. String floatToString(fl)
  747. FloatPro fl; {
  748.     internal("floatToString");
  749.     return "";/*NOTREACHED*/
  750. }
  751.  
  752. FloatPro stringToFloat(s)
  753. String s; {
  754.     internal("stringToFloat");
  755.     return 0;
  756. }
  757.  
  758.  
  759. #endif        /* HAS_FLOATS */
  760.  
  761.  
  762. /* --------------------------------------------------------------------------
  763.  * Machine dependent control:
  764.  * ------------------------------------------------------------------------*/
  765.  
  766. #if (MACHDEP_GOFER | MACHDEP_GOFC)
  767. #if UNIX
  768. static sigHandler(panic) {        /* exit in a panic, on receipt of  */
  769.     everybody(EXIT);            /* an unexpected signal           */
  770.     fprintf(stderr,"Unexpected signal\n");
  771.     exit(1);
  772.     sigResume;/*NOTREACHED*/
  773. }
  774. #endif
  775.  
  776. Void machdep(what)            /* Handle machine specific       */
  777. Int what; {                /* initialisation etc..           */
  778.     switch (what) {
  779.         case MARK    : break;
  780. #if UNIX
  781.         case INSTALL :
  782. #ifdef SIGHUP
  783.                signal(SIGHUP,panic);
  784. #endif
  785. #ifdef SIGQUIT
  786.                signal(SIGQUIT,panic);
  787. #endif
  788. #ifdef SIGTERM
  789.                signal(SIGTERM,panic);
  790. #endif
  791. #ifdef SIGSEGV
  792.                signal(SIGSEGV,panic);
  793. #endif
  794. #ifdef SIGBUS
  795.                signal(SIGBUS,panic);
  796. #endif
  797.                break;
  798. #endif
  799.         case RESET   :
  800.     case BREAK   :
  801.     case EXIT    : normalTerminal();
  802.                break;
  803.     }
  804. }
  805. #endif
  806.  
  807. /*-------------------------------------------------------------------------*/
  808.