home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / hugs101.zip / hugs101sc.zip / hugsdist / src / machdep.c < prev    next >
C/C++ Source or Header  |  1995-03-02  |  15KB  |  579 lines

  1. /* --------------------------------------------------------------------------
  2.  * machdep.c:   Copyright (c) Mark P Jones 1991-1994.   All rights reserved.
  3.  *              See NOTICE for details and conditions of use etc...
  4.  *              Hugs version 1.0 August 1994, derived from Gofer 2.30a
  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 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 BCC32
  30. #include <stdlib.h>
  31. #include <signal.h>
  32. #include <conio.h>
  33. #include <fcntl.h>
  34. #include <dos.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #endif
  38.  
  39. #if  WATCOM
  40. #include <stdlib.h>
  41. #include <signal.h>
  42. #include <fcntl.h>
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #endif
  46.  
  47. #if DJGPP
  48. #include <dos.h>
  49. #include <stdlib.h>
  50. #include <std.h>
  51. #include <signal.h>
  52. #include <fcntl.h>
  53. #include <sys/types.h>
  54. #include <sys/stat.h>
  55. #endif
  56.  
  57. #if RISCOS
  58. #include <assert.h>
  59. #include <signal.h>
  60. #include "swis.h"
  61. #include "os.h"
  62. #endif
  63.  
  64. #if ATARI
  65. #include <signal.h>
  66. #include <fcntl.h>
  67. #include <sys/types.h>
  68. #include <sys/stat.h>
  69. #endif
  70.  
  71. /* --------------------------------------------------------------------------
  72.  * Find information about a file:
  73.  * ------------------------------------------------------------------------*/
  74.  
  75. #if RISCOS
  76. typedef struct { unsigned hi, lo; } Time;
  77. #define timeChanged(now,thn)    (now.hi!=thn.hi || now.lo!=thn.lo)
  78. #define timeSet(var,tm)        var.hi = tm.hi; var.lo = tm.lo
  79. #else
  80. typedef time_t Time;
  81. #define timeChanged(now,thn)    (now!=thn)
  82. #define timeSet(var,tm)        var = tm
  83. #endif
  84.  
  85. static Void local getFileInfo    Args((String, Time *, Long *));
  86.  
  87. static Void local getFileInfo(s,tm,sz)    /* find time stamp and size of file*/
  88. String s;
  89. Time   *tm;
  90. Long   *sz; {
  91. #if RISCOS                /* get file info for RISCOS -- JBS */
  92.     os_regset r;            /* RISCOS PRM p.850 and p.837       */
  93.     r.r[0] = 17;            /* Read catalogue, no path       */
  94.     r.r[1] = (int)s;
  95.     os_swi(OS_File, &r);
  96.     if(r.r[0] == 1 && (r.r[2] & 0xFFF00000) == 0xFFF00000) {
  97.     tm->hi = r.r[2] & 0xFF;        /* Load address (high byte)       */
  98.     tm->lo = r.r[3];        /* Execution address (low 4 bytes) */
  99.     }
  100.     else                /* Not found, or not time-stamped  */
  101.     tm->hi = tm->lo = 0;
  102.     *sz = (Long)(r.r[0] == 1 ? r.r[4] : 0);
  103. #else                    /* normally just use stat()       */
  104.     static struct stat scbuf;
  105.     stat(s,&scbuf);
  106.     *tm = scbuf.st_mtime;
  107.     *sz = (Long)(scbuf.st_size);
  108. #endif
  109. }
  110.  
  111. #if RISCOS                /* RISCOS needs access()       */
  112. int access(char *s, int dummy) {    /* Give 1 iff cannot access file s */
  113.     os_regset r;            /* RISCOS PRM p.850    -- JBS       */
  114.     assert(dummy == 0);
  115.     r.r[0] = 17; /* Read catalogue, no path */
  116.     r.r[1] = (int)s;
  117.     os_swi(OS_File, &r);
  118.     return r.r[0] != 1;
  119. }
  120.  
  121. int namecmp(char *filename, char *spec){/* For filename extension hacks       */
  122.     while(*spec)
  123.         if  (tolower(*filename) != *spec++)
  124.         return 0;
  125.     else
  126.         ++filename;
  127.     return *filename == '.';
  128. }
  129. #endif
  130.  
  131. /* --------------------------------------------------------------------------
  132.  * Garbage collection notification:
  133.  * ------------------------------------------------------------------------*/
  134.  
  135. Bool gcMessages = FALSE;        /* TRUE => print GC messages       */
  136.  
  137. Void gcStarted() {            /* notify garbage collector start  */
  138.     if (gcMessages) {
  139.     printf("{{Gc");
  140.     fflush(stdout);
  141.     }
  142. }
  143.  
  144. Void gcScanning() {            /* notify garbage collector scans  */
  145.     if (gcMessages) {
  146.     putchar(':');
  147.     fflush(stdout);
  148.     }
  149. }
  150.  
  151. Void gcRecovered(recovered)        /* notify garbage collection done  */
  152. Int recovered; {
  153.     if (gcMessages) {
  154.     printf("%d}}",recovered);
  155.     fflush(stdout);
  156.     }
  157. }
  158.  
  159. Cell *CStackBase;            /* Retain start of C control stack */
  160.  
  161. #if RISCOS                /* Stack traversal for RISCOS       */
  162.  
  163. /* Warning: The following code is specific to the Acorn ARM under RISCOS
  164.    (and C4).  We must explicitly walk back through the stack frames, since
  165.    the stack is extended from the heap. (see PRM pp. 1757).  gcCStack must
  166.    not be modified, since the offset '5' assumes that only v1 is used inside
  167.    this function. Hence we do all the real work in gcARM.
  168. */
  169.           
  170. #define spreg 13 /* C3 has SP=R13 */
  171.  
  172. #define previousFrame(fp)    ((int *)((fp)[-3]))
  173. #define programCounter(fp)    ((int *)((*(fp)-12) & ~0xFC000003))
  174. #define isSubSPSP(w)        (((w)&dontCare) == doCare)
  175. #define doCare            (0xE24DD000)  /* SUB r13,r13,#0 */
  176. #define dontCare        (~0x00100FFF) /* S and # bits   */
  177. #define immediateArg(x)        ( ((x)&0xFF) << (((x)&0xF00)>>7) )
  178.  
  179. static void gcARM(int *fp) {
  180.     int si = *programCounter(fp);    /* Save instruction indicates how */
  181.                     /* many registers in this frame   */
  182.     int *regs = fp - 4;
  183.     if (si & (1<<0)) markWithoutMove(*regs--);
  184.     if (si & (1<<1)) markWithoutMove(*regs--);
  185.     if (si & (1<<2)) markWithoutMove(*regs--);
  186.     if (si & (1<<3)) markWithoutMove(*regs--);
  187.     if (si & (1<<4)) markWithoutMove(*regs--);
  188.     if (si & (1<<5)) markWithoutMove(*regs--);
  189.     if (si & (1<<6)) markWithoutMove(*regs--);
  190.     if (si & (1<<7)) markWithoutMove(*regs--);
  191.     if (si & (1<<8)) markWithoutMove(*regs--);
  192.     if (si & (1<<9)) markWithoutMove(*regs--);
  193.     if (previousFrame(fp)) {
  194.     /* The non-register stack space is for the previous frame is above
  195.        this fp, and not below the previous fp, because of the way stack
  196.        extension works. It seems the only way of discovering its size is
  197.        finding the SUB sp, sp, #? instruction by walking through the code
  198.        following the entry point.
  199.     */
  200.     int *oldpc = programCounter(previousFrame(fp));
  201.     int fsize = 0, i;
  202.     for(i = 1; i < 6; ++i)
  203.         if(isSubSPSP(oldpc[i])) fsize += immediateArg(oldpc[i]) / 4;
  204.     for(i=1; i<=fsize; ++i)
  205.         markWithoutMove(fp[i]);
  206.     }
  207. }
  208.  
  209. void gcCStack() {
  210.     int dummy;
  211.     int *fp = 5 + &dummy;
  212.     while (fp) {
  213.     gcARM(fp);
  214.     fp = previousFrame(fp);
  215.     }
  216. }
  217.  
  218. #else            /* Garbage collection for standard stack machines  */
  219.  
  220. Void gcCStack() {            /* Garbage collect elements off    */
  221.     Cell stackTop = NIL;        /* C stack               */
  222.     Cell *ptr = &stackTop;
  223. #if SMALL_HUGS
  224.     if (((long)(ptr) - (long)(CStackBase))&1)
  225.     fatal("gcCStack");
  226. #else 
  227.     if (((long)(ptr) - (long)(CStackBase))&3)
  228.     fatal("gcCStack");
  229. #endif
  230.  
  231. #define StackGrowsDown    while (ptr<=CStackBase) markWithoutMove(*ptr++)
  232. #define StackGrowsUp    while (ptr>=CStackBase) markWithoutMove(*ptr--)
  233. #define GuessDirection    if (ptr>CStackBase) StackGrowsUp; else StackGrowsDown
  234. #if HPUX
  235.     GuessDirection;
  236. #else
  237.     StackGrowsDown;
  238. #endif
  239. #undef  StackGrowsDown
  240. #undef  StackGrowsUp
  241. #undef  GuessDirection
  242. }
  243. #endif
  244.  
  245. /* --------------------------------------------------------------------------
  246.  * Terminal dependent stuff:
  247.  * ------------------------------------------------------------------------*/
  248.  
  249. #if   (TERMIO_IO | SGTTY_IO | TERMIOS_IO)
  250.  
  251. #if TERMIO_IO
  252. #include <termio.h>
  253. typedef  struct termio   TermParams;
  254. #define  getTerminal(tp) ioctl(fileno(stdin),TCGETA,&tp)
  255. #define  setTerminal(tp) ioctl(fileno(stdin),TCSETAF,&tp)
  256. #define  noEcho(tp)      tp.c_lflag    &= ~(ICANON | ECHO); \
  257.              tp.c_cc[VMIN]  = 1;            \
  258.              tp.c_cc[VTIME] = 0;
  259. #endif
  260.  
  261. #if SGTTY_IO
  262. #include <sgtty.h>
  263. typedef  struct sgttyb   TermParams;
  264. #define  getTerminal(tp) ioctl(fileno(stdin),TIOCGETP,&tp)
  265. #define  setTerminal(tp) ioctl(fileno(stdin),TIOCSETP,&tp)
  266. #if HPUX
  267. #define  noEcho(tp)      tp.sg_flags |= RAW; tp.sg_flags &= (~ECHO);
  268. #else
  269. #define  noEcho(tp)      tp.sg_flags |= CBREAK; tp.sg_flags &= (~ECHO);
  270. #endif
  271. #endif
  272.  
  273. #if TERMIOS_IO
  274. #include <termios.h>
  275. typedef  struct termios  TermParams;
  276. #define  getTerminal(tp) tcgetattr(fileno(stdin), &tp)
  277. #define  setTerminal(tp) tcsetattr(fileno(stdin), TCSAFLUSH, &tp)
  278. #define  noEcho(tp)      tp.c_lflag    &= ~(ICANON | ECHO); \
  279.              tp.c_cc[VMIN]  = 1;                \
  280.              tp.c_cc[VTIME] = 0;
  281. #endif
  282.  
  283. static Bool messedWithTerminal = FALSE;
  284. static TermParams originalSettings;
  285.  
  286. Void normalTerminal() {            /* restore terminal initial state  */
  287.     if (messedWithTerminal)
  288.     setTerminal(originalSettings);
  289. }
  290.  
  291. Void noechoTerminal() {            /* set terminal into noecho mode   */
  292.     TermParams settings;
  293.  
  294.     if (!messedWithTerminal) {
  295.     getTerminal(originalSettings);
  296.     messedWithTerminal = TRUE;
  297.     }
  298.     getTerminal(settings);
  299.     noEcho(settings);
  300.     setTerminal(settings);
  301. }
  302.  
  303. Int getTerminalWidth() {        /* determine width of terminal       */
  304. #ifdef TIOCGWINSZ
  305. #ifdef _M_UNIX                /* SCO Unix 3.2.4 defines TIOCGWINSZ*/
  306. #include <sys/stream.h>            /* Required by sys/ptem.h       */
  307. #include <sys/ptem.h>            /* Required to declare winsize       */
  308. #endif
  309.     static struct winsize terminalSize;
  310.     ioctl(fileno(stdout),TIOCGWINSZ,&terminalSize);
  311.     return (terminalSize.ws_col==0)? 80 : terminalSize.ws_col;
  312. #else
  313.     return 80;
  314. #endif
  315. }
  316.  
  317. Int readTerminalChar() {        /* read character from terminal       */
  318.     return getchar();            /* without echo, assuming that       */
  319. }                    /* noechoTerminal() is active...   */
  320. #endif
  321.  
  322. #if DOS_IO
  323. static Bool terminalEchoReqd = TRUE;
  324.  
  325. Int getTerminalWidth() {        /* PC screen is fixed 80 chars       */
  326.     return 80;
  327. }
  328.  
  329. Void normalTerminal() {            /* restore terminal initial state  */
  330.     terminalEchoReqd = TRUE;
  331. }
  332.  
  333. Void noechoTerminal() {            /* turn terminal echo on/off       */
  334.     terminalEchoReqd = FALSE;
  335. }
  336.  
  337. Int readTerminalChar() {        /* read character from terminal       */
  338.     if (terminalEchoReqd)
  339.     return getchar();
  340.     else {
  341.     Int c = getch();
  342.     return c=='\r' ? '\n' : c;
  343.     }
  344. }
  345. #endif
  346.  
  347. #if RISCOS
  348. Int getTerminalWidth() {
  349.     int dummy, width;
  350.     (void) os_swi3r(OS_ReadModeVariable, -1, 1, 0, &dummy, &dummy, &width);
  351.     return width+1;
  352. }
  353.  
  354. Void normalTerminal() {            /* restore terminal initial state  */
  355. }                    /* (not yet implemented)       */
  356.  
  357. Void noechoTerminal() {            /* turn terminal echo on/off       */
  358. }                    /* (not yet implemented)       */
  359.  
  360. Int readTerminalChar() {        /* read character from terminal       */
  361.     return getchar();
  362. }
  363. #endif
  364.  
  365. /* --------------------------------------------------------------------------
  366.  * Interrupt handling:
  367.  * ------------------------------------------------------------------------*/
  368.  
  369. Bool    broken         = FALSE;
  370. static  Bool breakReqd = FALSE;
  371. static  sigProto(ignoreBreak);
  372.  
  373. Bool breakOn(reqd)            /* set break trapping on if reqd,  */
  374. Bool reqd; {                /* or off otherwise, returning old */
  375.     Bool old  = breakReqd;
  376.  
  377.     breakReqd = reqd;
  378.     if (reqd) {
  379.     if (broken) {            /* repond to break signal received */
  380.         broken = FALSE;        /* whilst break trap disabled       */
  381.         sigRaise(breakHandler);
  382.     }
  383. #if (BCC32 | WATCOM)
  384.     ctrlbrk(ignoreBreak);
  385. #else
  386.     ctrlbrk(breakHandler);
  387. #endif
  388.     }
  389.     else
  390.     ctrlbrk(ignoreBreak);
  391.  
  392.     return old;
  393. }
  394.  
  395. static sigHandler(ignoreBreak) {    /* record but don't respond to break*/
  396.     ctrlbrk(ignoreBreak);
  397.     broken = TRUE;
  398.     sigResume;
  399. }
  400.  
  401. /* --------------------------------------------------------------------------
  402.  * Shell escapes:
  403.  * ------------------------------------------------------------------------*/
  404.  
  405. Int shellEsc(s)                /* run a shell command (or shell)  */
  406. String s; {
  407. #if UNIX
  408.     if (s[0]=='\0')
  409.     s = fromEnv("SHELL","/bin/sh");
  410. #endif
  411.     return system(s);
  412. }
  413.  
  414. #if RISCOS                /* RISCOS also needs a chdir()       */
  415. int chdir(char *s) {            /* RISCOS PRM p. 885    -- JBS       */
  416.     return os_swi2(OS_FSControl + XOS_Bit, 0, (int)s) != NULL;
  417. }
  418. #endif
  419.  
  420. /* --------------------------------------------------------------------------
  421.  * Floating point support:
  422.  * ------------------------------------------------------------------------*/
  423.  
  424. #if HAS_FLOATS
  425. #if BREAK_FLOATS
  426. static union {
  427.     Float  flVal;
  428.     struct {
  429.     Cell flPart1,flPart2;
  430.     }       clVal;
  431. } fudgeCoerce;
  432.  
  433. Cell part1Float(fl)
  434. FloatPro fl; {
  435.     fudgeCoerce.flVal = fl;
  436.     return fudgeCoerce.clVal.flPart1;
  437. }
  438.  
  439. Cell part2Float(fl)
  440. FloatPro fl; {
  441.     fudgeCoerce.flVal = fl;
  442.     return fudgeCoerce.clVal.flPart2;
  443. }
  444.  
  445. FloatPro floatFromParts(c1,c2)
  446. Cell c1, c2; {
  447.     fudgeCoerce.clVal.flPart1 = c1;
  448.     fudgeCoerce.clVal.flPart2 = c2;
  449.     return fudgeCoerce.flVal;
  450. }
  451.  
  452. Cell mkFloat(fl)
  453. FloatPro fl; {
  454.     Cell p1,p2;
  455.     fudgeCoerce.flVal = fl;
  456.     p1 = mkInt(fudgeCoerce.clVal.flPart1);
  457.     p2 = mkInt(fudgeCoerce.clVal.flPart2);
  458.     return pair(FLOATCELL,pair(p1,p2));
  459. }
  460.  
  461. FloatPro floatOf(c)
  462. Cell c; {
  463.     fudgeCoerce.clVal.flPart1 = intOf(fst(snd(c)));
  464.     fudgeCoerce.clVal.flPart2 = intOf(snd(snd(c)));
  465.     return fudgeCoerce.flVal;
  466. }
  467.  
  468. #else /* !BREAK_FLOATS */
  469. static union {
  470.     Float flVal;
  471.     Cell  clVal;
  472. } fudgeCoerce;
  473.  
  474. Cell mkFloat(fl)
  475. FloatPro fl; {
  476.     fudgeCoerce.flVal = fl;
  477.     return pair(FLOATCELL,fudgeCoerce.clVal);
  478. }
  479.  
  480. FloatPro floatOf(c)
  481. Cell c; {
  482.     fudgeCoerce.clVal = snd(c);
  483.     return fudgeCoerce.flVal;
  484. }
  485. #endif
  486.  
  487. String floatToString(fl)            /* Make sure that floating   */
  488. FloatPro fl; {                    /* point values print out in */
  489.     static char buffer1[32];            /* a form in which they could*/
  490.     static char buffer2[32];            /* also be entered as floats */
  491.     Int i=0, j=0;
  492.  
  493.     sprintf(buffer1,FloatFMT,fl);
  494.     while (buffer1[i] && strchr("eE.",buffer1[i])==0)
  495.     buffer2[j++] = buffer1[i++];
  496.     if (buffer1[i]!='.') {
  497.         buffer2[j++] = '.';
  498.     buffer2[j++] = '0';
  499.     }
  500.     while (buffer2[j++]=buffer1[i++])
  501.     ;
  502.     return buffer2;
  503. }
  504.  
  505. FloatPro stringToFloat(s)
  506. String s; {
  507.     return atof(s);
  508. }
  509. #else
  510. Cell mkFloat(fl)
  511. FloatPro fl; {
  512.     internal("mkFloat");
  513.     return 0;/*NOTREACHED*/
  514. }
  515.  
  516. FloatPro floatOf(c)
  517. Cell c; {
  518.     internal("floatOf");
  519.     return 0;/*NOTREACHED*/
  520. }
  521.  
  522. String floatToString(fl)
  523. FloatPro fl; {
  524.     internal("floatToString");
  525.     return "";/*NOTREACHED*/
  526. }
  527.  
  528. FloatPro stringToFloat(s)
  529. String s; {
  530.     internal("stringToFloat");
  531.     return 0;
  532. }
  533. #endif
  534.  
  535. /* --------------------------------------------------------------------------
  536.  * Machine dependent control:
  537.  * ------------------------------------------------------------------------*/
  538.  
  539. #if UNIX
  540. static sigHandler(panic) {        /* exit in a panic, on receipt of  */
  541.     everybody(EXIT);            /* an unexpected signal           */
  542.     fprintf(stderr,"\nUnexpected signal\n");
  543.     exit(1);
  544.     sigResume;/*NOTREACHED*/
  545. }
  546. #endif
  547.  
  548. Void machdep(what)            /* Handle machine specific       */
  549. Int what; {                /* initialisation etc..           */
  550.     switch (what) {
  551.         case MARK    : break;
  552. #if UNIX
  553.         case INSTALL :
  554. #ifdef SIGHUP
  555.                signal(SIGHUP,panic);
  556. #endif
  557. #ifdef SIGQUIT
  558.                signal(SIGQUIT,panic);
  559. #endif
  560. #ifdef SIGTERM
  561.                signal(SIGTERM,panic);
  562. #endif
  563. #ifdef SIGSEGV
  564.                signal(SIGSEGV,panic);
  565. #endif
  566. #ifdef SIGBUS
  567.                signal(SIGBUS,panic);
  568. #endif
  569.                break;
  570. #endif
  571.         case RESET   :
  572.     case BREAK   :
  573.     case EXIT    : normalTerminal();
  574.                break;
  575.     }
  576. }
  577.  
  578. /*-------------------------------------------------------------------------*/
  579.