Advertisement
Guest User

Mouse-2002 fixed interpreter

a guest
Dec 8th, 2015
288
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 78.95 KB | None | 0 0
  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /*                               M O U S E                                   */
  4. /*                                                                           */
  5. /*  Program:      MOUSE                                                      */
  6. /*                                                                           */
  7. /*  Programmer:   David G. Simpson                                           */
  8. /*                Laurel, Maryland                                           */
  9. /*                February 3, 2002                                           */
  10. /*                                                                           */
  11. /*  Language:     C                                                          */
  12. /*                                                                           */
  13. /*  Description:  This is an interpreter for the Mouse-2002 programming      */
  14. /*                language.                                                  */
  15. /*                                                                           */
  16. /*  Version:      19  (April 1, 2007)                                        */
  17. /*                                                                           */
  18. /*  Notes:        This interpreter is based on the original Pascal           */
  19. /*                implementation in "Mouse: A Language for Microcomputers"   */
  20. /*                by Peter Grogono.                                          */
  21. /*                                                                           */
  22. /*                Syntax:   MOUSE  <filename>                                */
  23. /*                                                                           */
  24. /*                If no file extension is given, an extension of ".mou" is   */
  25. /*                assumed.                                                   */
  26. /*                                                                           */
  27. /*****************************************************************************/
  28.  
  29. /*****************************************************************************/
  30. /*  #includes                                                                */
  31. /*****************************************************************************/
  32.  
  33. #include <stdio.h>                          /* standard i/o                  */
  34. #include <stdlib.h>                         /* standard library              */
  35. #include <string.h>                         /* string functions              */
  36. #include <ctype.h>                          /* character functions           */
  37. #include <math.h>                           /* mathematical functions        */
  38. #include <time.h>                           /* time functions                */
  39.  
  40.  
  41.  
  42. /*****************************************************************************/
  43. /*  #defines                                                                 */
  44. /*****************************************************************************/
  45.  
  46. #define  MAXPROGLEN   10000                 /* max length of Mouse program   */
  47. #define  MAXPROGLINELEN 132                 /* max length of interactive line*/
  48. #define  STACKSIZE     1024                 /* maximum depth of calc stack   */
  49. #define  ENVSTACKSIZE  1024                 /* maximum depth of env stack    */
  50. #define  LOCSIZE         26                 /* size of local variable space  */
  51. #define  MAXADDR       1300                 /* 50 local variable spaces      */
  52. #define  HALFWIDTH       39                 /* a number < half screen width  */
  53. #define  MOUSE_EXT    ".mou"                /* default source file extension */
  54. #define  ARRAYSIZE     1000                 /* size of universal array       */
  55. #define  MAXFILES        10                 /* max number of files open      */
  56.  
  57. #define  BACKSPACE     charpos--            /* backspace one char in program */
  58. #define  VALUE(digit)  (digit - '0')        /* convert char to corresp digit */
  59. #define  UPPERCASE     ch = toupper(ch)     /* convert ch to uppercase       */
  60.  
  61. #define  TOLERANCE     1.0e-6
  62.  
  63. #ifndef  PI
  64. #define  PI  3.14159265358979323846264338327950288419716939937510582097494459230
  65. #endif
  66.  
  67. #define  SPEED_OF_LIGHT  299792458.0                   /* m/s                */
  68. #define  ELEMENTARY_CHG  1.60217653e-19                /* C                  */
  69. #define  GRAV_ACCEL      9.80665                       /* m s**-2            */
  70. #define  GRAV_CONST      6.6742e-11                    /* m**3 kg**-1 s**-2  */
  71. #define  PLANCK          6.6260693e-34                 /* J s                */
  72. #define  H_BAR           1.05457168e-34                /* J s                */
  73. #define  PERMEABILITY    (4.0e-7*PI)                   /* N A**-2            */
  74. #define  PERMITTIVITY    (1.0/(PERMEABILITY*SPEED_OF_LIGHT*SPEED_OF_LIGHT))
  75. #define  MASS_ELECTRON   9.1093826e-31                 /* kg                 */
  76. #define  MASS_PROTON     1.67262171e-27                /* kg                 */
  77. #define  MASS_NEUTRON    1.67492728e-27                /* kg                 */
  78. #define  AVAGADRO        6.0221415e23                  /* mol**-1            */
  79. #define  BOLTZMANN       1.3806505e-23                 /* J/K                */
  80.  
  81. #define  AU              1.49597870e11                 /* m                  */
  82. #define  GM_EARTH        3.9860005e14                  /* m**3 s**-2         */
  83. #define  GM_SUN          1.32712438e20                 /* m**3 s**-2         */
  84. #define  R_EARTH         6.378140e6                    /* m                  */
  85.  
  86. #define  LB_KG           0.45359237
  87. #define  IN_CM           2.54
  88. #define  GAL_L           3.7854118
  89.  
  90.  
  91. #define  DEFAULT_ANGLE_FACTOR    1.0
  92. #define  DEFAULT_DISPLAY_MODE    2
  93. #define  DEFAULT_DISPLAY_DIGITS  15
  94. #define  DEFAULT_DISPLAY_WIDTH   0
  95. #define  DEFAULT_WORDSIZE        32
  96. #define  DEFAULT_OCTHEX_DIGITS   ((DEFAULT_WORDSIZE-1)/4+1)
  97.  
  98. #define  VERSION         19
  99. #define  PROMPT          "\n> "
  100.  
  101.  
  102. /*****************************************************************************/
  103. /*  type definitions                                                         */
  104. /*****************************************************************************/
  105.  
  106. enum  tagtype {macro, parameter, loop};     /* tag type for environmnt stack */
  107.  
  108. typedef struct {                            /* environment stack entry type  */
  109.    enum tagtype  tag;                       /* type of entry                 */
  110.    long     charpos;                        /* instruction pointer           */
  111.    long     offset;                         /* variable offset level         */
  112.    } environment;
  113.  
  114.  
  115.  
  116. /*****************************************************************************/
  117. /*  global variables                                                         */
  118. /*****************************************************************************/
  119.  
  120. FILE         *progfile;                     /* pointer to Mouse source file  */
  121.  
  122. char         prog[MAXPROGLEN];              /* array to hold program         */
  123. char         prog_line[MAXPROGLINELEN+2];
  124. double       stack[STACKSIZE];              /* calculation stack             */
  125. environment  envstack[ENVSTACKSIZE];        /* environment stack             */
  126. double       data[MAXADDR];                 /* variables                     */
  127. long         macdefs[26];                   /* macro definitions             */
  128.  
  129. char         ch;                            /* current character in program  */
  130. long         charpos;                       /* instruction pointer           */
  131. long         proglen;                       /* total length of program code  */
  132. long         sp;                            /* calculation stack pointer     */
  133. long         esp;                           /* environment stack pointer     */
  134. long         tsp;                           /* temporary stack pointer       */
  135. long         offset;                        /* variable offset               */
  136. long         nextfree;                      /* next free variable address    */
  137. double       temp, temp2, temp3;            /* temporary doubles             */
  138. long         itemp, itemp2;                 /* temporary integers            */
  139. long         parbal;                        /* matches pairs in env stack    */
  140. long         parnum;                        /* macro parameter number        */
  141. int          tracing;                       /* tracing on/off flag           */
  142. int          disaster;                      /* disaster flag; 1=disaster     */
  143. int          j;                             /* loop index                    */
  144. char         filename[101];                 /* Mouse source file name        */
  145. char         format_str[11];                /* printf format string          */
  146. long         ntemp;                         /* temporary integer             */
  147. int          done;                          /* 1=exit interactive mode       */
  148. char         line[133];                     /* input line                    */
  149. int          source;                        /* 0=compile, 1=interactive      */
  150. double       array[ARRAYSIZE];              /* array for &sto and &rcl       */
  151. int          error_flag;                    /* error flag                    */
  152. FILE         *fp[MAXFILES];                 /* array of file pointers        */
  153. char         filename_str[13];              /* i/o filename                  */
  154. char         filenum_str[4];                /* file numbers string (000-999) */
  155. char         filemode_str[3];               /* file mode string (r,w,rb,wb)  */
  156. char         temp_str[25];                  /* temporary string              */
  157. enum tagtype envtag;                        /* tag from environment stack    */
  158.  
  159. double       angle_factor = DEFAULT_ANGLE_FACTOR;      /* "to radians" factor*/
  160. long         display_mode = DEFAULT_DISPLAY_MODE;      /* 0=fix, 1=sci, 2=gen*/
  161. long         display_digits = DEFAULT_DISPLAY_DIGITS;  /* #digits to show    */
  162. long         display_width = DEFAULT_DISPLAY_WIDTH;    /* print width        */
  163. long         wordsize = DEFAULT_WORDSIZE;              /* word size (bits)   */
  164. long         octhex_digits = DEFAULT_OCTHEX_DIGITS;    /* octal/hex digits   */
  165. long         octhex_mask = 0xFFFFFFFF;                 /* octal/hex mask     */
  166.  
  167.  
  168. /*****************************************************************************/
  169. /*  function prototypes                                                      */
  170. /*****************************************************************************/
  171.  
  172. void chomp (char *str);                     /* remove final \n from a string */
  173. void display (long charpos);                /* display an environment        */
  174. void error (short code);                    /* report error; stop interpreter*/
  175. void Getchar(void);                         /* get next character in program */
  176. void push (double datum);                   /* push item onto calc stack     */
  177. double pop (void);                          /* pop item from calc stack      */
  178. void skipstring(void);                      /* skip over a string            */
  179. void skip (char lch, char rch);             /* skip bracketed sequences      */
  180. void skip2 (char lch, char rch1,char rch2); /* skip bracketed sequences      */
  181. void pushenv (enum tagtype tag);            /* push an environment on env stk*/
  182. void popenv (void);                         /* pop an environmnt from env stk*/
  183. void load (void);                           /* loader: loads program code    */
  184. void makedeftable (void);                   /* create macro definition table */
  185. void interpret (void);                      /* interpreter: runs program code*/
  186. void process_amp(char *str);                /* process & functions           */
  187. double Int (double f);                      /* integer part                  */
  188. double Frac (double f);                     /* fractional part               */
  189. int Round(double x);                       /* Round to nearest integer      */
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197. /*****************************************************************************/
  198. /*                                                                           */
  199. /*  main()                                                                   */
  200. /*                                                                           */
  201. /*****************************************************************************/
  202.  
  203. int main (int argc, char *argv[])
  204. {
  205. /*---------------------------------------------------------------------------*/
  206. /*  Check command-line arguments.                                            */
  207. /*---------------------------------------------------------------------------*/
  208.  
  209. if (argc == 1)                              /* check for 1 cmd line argument */
  210.    {
  211.    source = 1;
  212.    done = 0;
  213.    printf("Mouse-2002 Interpreter Version %d\n", VERSION);
  214.    sp = -1;                                 /* init stack pointer            */
  215.    esp = -1;                                /* init environ stack pointer    */
  216.    do {
  217.       printf(PROMPT);
  218.       fgets(line,132,stdin);
  219.       load();
  220.       interpret();
  221.       } while (!done);
  222.    exit(0);                                 /* and return to oper system     */
  223.    }
  224.  
  225.  
  226. /*---------------------------------------------------------------------------*/
  227. /*  If not interactive mode (source from file), set source flag to 0.        */
  228. /*---------------------------------------------------------------------------*/
  229.  
  230. source = 0;
  231.  
  232.  
  233. /*---------------------------------------------------------------------------*/
  234. /*  If no file extension given, add the default extension to filename.       */
  235. /*---------------------------------------------------------------------------*/
  236.  
  237. strcpy(filename, argv[1]);                  /* copy cmd line argument        */
  238. if (strchr(filename, (int)'.') == NULL)     /* if no file extension given..  */
  239.    strcat(filename, MOUSE_EXT);             /* ..append default extension    */
  240.  
  241.  
  242. /*---------------------------------------------------------------------------*/
  243. /*  Open mouse source file.                                                  */
  244. /*---------------------------------------------------------------------------*/
  245.  
  246. if ((progfile=fopen(filename,"rb"))==NULL)  /* open Mouse source file        */
  247.    {
  248.    printf("Error opening file %s\n",        /* if open error, print err msg  */
  249.           filename);
  250.    exit(1);                                 /* and return to operating sys   */
  251.    }
  252.  
  253. /*---------------------------------------------------------------------------*/
  254. /*  Load Mouse source file into memory, then close the source file.          */
  255. /*---------------------------------------------------------------------------*/
  256.  
  257. load();                                     /* load program into memory      */
  258. fclose(progfile);                           /* close Mouse source file       */
  259.  
  260. /*---------------------------------------------------------------------------*/
  261. /*  If load went OK, then define macros and run the interpreter.             */
  262. /*---------------------------------------------------------------------------*/
  263.  
  264. if (!disaster)                              /* if no load problems..         */
  265.    {
  266.    makedeftable();                          /* create macro definition table */
  267.    interpret();                             /* and run interpreter           */
  268.    }
  269.  
  270. /*---------------------------------------------------------------------------*/
  271. /*  All done.  Return to operating system.                                   */
  272. /*---------------------------------------------------------------------------*/
  273.  
  274. return 0;                                   /* return to operating system    */
  275.  
  276. }                                           /* end MouseInterpreter          */
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283. /*****************************************************************************/
  284. /*                                                                           */
  285. /*  display()                                                                */
  286. /*                                                                           */
  287. /*  Display an environment; used for reporting errors and tracing.           */
  288. /*  This routine displays a line of code centered on the given pointer, with */
  289. /*  a ^ pointing to the character at the pointer.                            */
  290. /*                                                                           */
  291. /*****************************************************************************/
  292.  
  293. void display (long charpos)
  294. {
  295. long  pos;                                  /* loop index                    */
  296. char  *prog_ptr;
  297.  
  298.  
  299. if (source == 0)
  300.    prog_ptr = prog;
  301. else
  302.    prog_ptr = prog_line;
  303.  
  304. for (j=0; j<4; j++)                         /* print stack                   */
  305.    {
  306.    if (j > sp)
  307.       printf("  ..........");
  308.    else
  309.       printf("%12.4e", stack[sp-j]);
  310.    }
  311. printf("      ");
  312.  
  313. for (pos = charpos - HALFWIDTH;             /* for HALFWIDTH chars centered..*/
  314.      pos <= charpos + HALFWIDTH; pos++)     /*..on current position..        */
  315.    {
  316.    if ((pos >= 0) && (pos < proglen)        /* if within program bounds..    */
  317.               && (prog_ptr[pos] >= ' '))    /*..and printable character..    */
  318.       printf("%c", prog_ptr[pos]);          /* print program character       */
  319.    else                                     /* otherwise,                    */
  320.       printf(" ");                          /* just print a space            */
  321.    }
  322.  
  323. printf ("\n");                              /* end of line                   */
  324. for (j=0; j<HALFWIDTH+54; j++)              /* print spaces to position ^    */
  325.    printf(" ");
  326. printf("^\n");                              /* print ^ pointer               */
  327. }                                           /* end display                   */
  328.  
  329.  
  330.  
  331.  
  332.  
  333. /*****************************************************************************/
  334. /*                                                                           */
  335. /*  error()                                                                  */
  336. /*                                                                           */
  337. /*  Report an error and set "disaster" flag to stop the interpreter.         */
  338. /*                                                                           */
  339. /*****************************************************************************/
  340.  
  341. void error (short code)
  342. {
  343. short  tsp;                                 /* loop counter                  */
  344.  
  345.  
  346. printf("\nEnvironment:\n");                 /* start new line                */
  347. for (tsp = 0; tsp < esp; tsp++)             /* for each entry in env stack.. */
  348.    display(envstack[tsp].charpos);          /* display the code at that entry*/
  349.  
  350. printf("Instruction pointer:\n");           /* display code at instruct ptr  */
  351. display(charpos);
  352.  
  353. printf("Stack:");                           /* display stack contents        */
  354. for (tsp = 0; tsp <= sp; tsp++)
  355.    printf(" [%17.10E] ", stack[tsp]);
  356. printf("\n");
  357.  
  358. printf ("***** Error %d: ", code);          /* print error message           */
  359. switch (code)                               /* select err message from list  */
  360.    {
  361.    case  1 : printf("Ran off end of program");            break;
  362.    case  2 : printf("Calculation stack overflowed");      break;
  363.    case  3 : printf("Calculation stack underflowed");     break;
  364.    case  4 : printf("Attempted to divide by zero");       break;
  365.    case  5 : printf("Attempted to find modulus by zero"); break;
  366.    case  6 : printf("Undefined macro");                   break;
  367.    case  7 : printf("Illegal character follows \"#\"");   break;
  368.    case  8 : printf("Environment stack overflowed");      break;
  369.    case  9 : printf("Environment stack underflowed");     break;
  370.    case 10 : printf("Data space exhausted");              break;
  371.    case 11 : printf("Illegal character %d", ch);          break;
  372.    case 12 : printf("Invalid argument for &acos");        break;
  373.    case 13 : printf("Invalid argument for &acosh");       break;
  374.    case 14 : printf("Invalid argument for &asin");        break;
  375.    case 15 : printf("Invalid argument for &atanh");       break;
  376.    case 16 : printf("Invalid argument for &ln");          break;
  377.    case 17 : printf("Invalid argument for &log2");        break;
  378.    case 18 : printf("Invalid argument for &log10");       break;
  379.    case 19 : printf("Invalid argument for &recip");       break;
  380.    case 20 : printf("Invalid argument for &sqrt");        break;
  381.    case 21 : printf("Invalid argument for &!");           break;
  382.    case 22 : printf("Invalid word size");                 break;
  383.    case 23 : printf("Invalid arguments for &cnr");        break;
  384.    case 24 : printf("Invalid arguments for &pnr");        break;
  385.    case 25 : printf("Array index out of bounds");         break;
  386.    case 26 : printf("Invalid argument for ` or &power");  break;
  387.    case 27 : printf("Invalid arguments for &root");       break;
  388.    case 28 : printf("Error opening file");                break;
  389.    case 29 : printf("Invalid & function name");           break;
  390.    case 30 : printf("Invalid argument for &cubert");      break;
  391.    case 31 : printf("Invalid argument for &4thrt");       break;
  392.    }  /* end case */
  393. printf("\n");
  394. disaster = 1;                               /* set disaster flag             */
  395. sp = -1;                                    /* clear stack                   */
  396. }                                           /* end error                     */
  397.  
  398.  
  399.  
  400.  
  401.  
  402. /*****************************************************************************/
  403. /*                                                                           */
  404. /*  Getchar()                                                                */
  405. /*                                                                           */
  406. /*  Get next character from program buffer and check for end of program.     */
  407. /*                                                                           */
  408. /*****************************************************************************/
  409.  
  410. void Getchar(void)
  411. {
  412. if (charpos < proglen-1)                    /* if next chr is within program */
  413.    {
  414.    charpos++;                               /* increment instruction pointer */
  415.    if (source == 0)
  416.       ch = prog[charpos];                   /* put next char into ch         */
  417.    else
  418.       ch = prog_line[charpos];
  419.    }
  420. else                                        /* else ran off end of program   */
  421.    error(1);                                /* print error message           */
  422. }                                           /* end Getchar                   */
  423.  
  424.  
  425.  
  426.  
  427.  
  428. /*****************************************************************************/
  429. /*                                                                           */
  430. /*  push()                                                                   */
  431. /*                                                                           */
  432. /*  Push an item onto the calculation stack and check for stack overflow.    */
  433. /*                                                                           */
  434. /*****************************************************************************/
  435.  
  436. void push (double datum)
  437. {
  438. if (sp < STACKSIZE-1)                       /* if enough room on calc stack..*/
  439.    {
  440.    sp++;                                    /* increment stack pointer       */
  441.    stack[sp] = datum;                       /* store data item on stack      */
  442.    }
  443. else                                        /* else calc stack filled up     */
  444.    error(2);                                /* print error message           */
  445. }                                           /* end push                      */
  446.  
  447.  
  448.  
  449.  
  450.  
  451. /*****************************************************************************/
  452. /*                                                                           */
  453. /*  pop()                                                                    */
  454. /*                                                                           */
  455. /*  Pop an item from the calculation stack; check for underflow.             */
  456. /*                                                                           */
  457. /*****************************************************************************/
  458.  
  459. double pop (void)
  460. {
  461. double result;                              /* returned stack value          */
  462.  
  463. if (sp >= 0)                                /* if an item is avail on stack..*/
  464.    {
  465.    result = stack[sp];                      /* get value on top of stack     */
  466.    sp--;                                    /* decrement stack pointer       */
  467.    }
  468. else                                        /* otherwise stack underflow     */
  469.    error(3);                                /* print error message           */
  470. return result;
  471. }                                           /* end pop                       */
  472.  
  473.  
  474.  
  475.  
  476.  
  477. /*****************************************************************************/
  478. /*                                                                           */
  479. /*  skipstring()                                                             */
  480. /*                                                                           */
  481. /*  Skip over a string; " has been scanned on entry.                         */
  482. /*                                                                           */
  483. /*****************************************************************************/
  484.  
  485. void skipstring(void)
  486. {
  487. do {                                        /* do until we find ending "     */
  488.    Getchar();                               /* read program character        */
  489.    } while (ch != '"');                     /* stop when ending " found      */
  490. }                                           /* end skipstring                */
  491.  
  492.  
  493.  
  494.  
  495.  
  496. /*****************************************************************************/
  497. /*                                                                           */
  498. /*  skip()                                                                   */
  499. /*                                                                           */
  500. /*  Skip bracketed sequences; lch has been scanned on entry.                 */
  501. /*                                                                           */
  502. /*****************************************************************************/
  503.  
  504. void skip (char lch, char rch)
  505. {
  506. short  count;                               /* counter used for matching     */
  507.  
  508. count = 1;                                  /* one bracket already read      */
  509. do {                                        /* do until matching end bracket */
  510.    Getchar();                               /* read program character        */
  511.    if (ch == '"')                           /* if it starts a string..       */
  512.       skipstring();                         /* ..then skip to end of string  */
  513.    else if (ch == lch)                      /* if another 'left' character.. */
  514.       count++;                              /* ..then increment counter      */
  515.    else if (ch == rch)                      /* if closing 'right' character..*/
  516.       count--;                              /* ..then decrement counter      */
  517.    } while (count != 0);                    /* repeat until matching right ch*/
  518. }                                           /* end skip                      */
  519.  
  520.  
  521.  
  522.  
  523.  
  524. /*****************************************************************************/
  525. /*                                                                           */
  526. /*  skip2()                                                                  */
  527. /*                                                                           */
  528. /*  Skip bracketed sequences; lch has been scanned on entry.                 */
  529. /*  End bracket is either rch1 or rch2.                                      */
  530. /*                                                                           */
  531. /*****************************************************************************/
  532.  
  533. void skip2 (char lch, char rch1, char rch2)
  534. {
  535. short  count;                               /* counter used for matching     */
  536.  
  537. count = 1;                                  /* one bracket already read      */
  538. do {                                        /* do until matching end bracket */
  539.    Getchar();                               /* read program character        */
  540.    if (ch == '"')                           /* if it starts a string..       */
  541.       skipstring();                         /* ..then skip to end of string  */
  542.    else if (ch == lch)                      /* if another 'left' character.. */
  543.       count++;                              /* ..then increment counter      */
  544.    else if (ch == rch1 || ch == rch2)       /* if closing 'right' character..*/
  545.       count--;                              /* ..then decrement counter      */
  546.    } while (count != 0);                    /* repeat until matching right ch*/
  547. }                                           /* end skip                      */
  548.  
  549.  
  550.  
  551.  
  552.  
  553. /*****************************************************************************/
  554. /*                                                                           */
  555. /*  pushenv()                                                                */
  556. /*                                                                           */
  557. /*  Push an environment; check for environment stack overflow.               */
  558. /*                                                                           */
  559. /*****************************************************************************/
  560.  
  561. void pushenv (enum tagtype tag)
  562.    {
  563. if (esp < ENVSTACKSIZE-1)                   /* if room avail on env stack..  */
  564.    {
  565.    esp++;                                   /* ..increment env stack pointer */
  566.    envstack[esp].tag = tag;                 /* save tag type                 */
  567.    envstack[esp].charpos = charpos;         /* save instruction pointer      */
  568.    envstack[esp].offset = offset;           /* save variable offset          */
  569.    }
  570. else                                        /* otherwise, env stack overflow */
  571.    error(8);                                /* print error message           */
  572. }                                           /* end pushenv                   */
  573.  
  574.  
  575.  
  576.  
  577.  
  578. /*****************************************************************************/
  579. /*                                                                           */
  580. /*  popenv()                                                                 */
  581. /*                                                                           */
  582. /*  Pop an environment; check for environment stack underflow.               */
  583. /*                                                                           */
  584. /*****************************************************************************/
  585.  
  586. void popenv(void)
  587. {
  588. if (esp >= 0)                               /* if item avail on env stack..  */
  589.    {
  590.    envtag = envstack[esp].tag;              /* pop tag type                  */
  591.    charpos = envstack[esp].charpos;         /* pop instruction pointer       */
  592.    offset = envstack[esp].offset;           /* pop variable offset           */
  593.    esp--;                                   /* decrement stack pointer       */
  594.    }
  595. else                                        /* otherwise stack underflow     */
  596.    error(9);                                /* print error message           */
  597. }                                           /* end popenv                    */
  598.  
  599.  
  600.  
  601.  
  602.  
  603. /*****************************************************************************/
  604. /*                                                                           */
  605. /*  load()                                                                   */
  606. /*                                                                           */
  607. /*  The Loader.                                                              */
  608. /*  This version of the loader has been optimized to remove all spaces       */
  609. /*  except for spaces within strings and spaces separating numbers (for      */
  610. /*  which all but one space is removed).  It also eliminates all CR/LF       */
  611. /*  characters.  Optimizing the loader to eliminate all unnecessary          */
  612. /*  characters greatly improves the execution speed of the interpreter.      */
  613. /*                                                                           */
  614. /*****************************************************************************/
  615.  
  616. void load (void)
  617. {
  618. char  lastchr;                              /* previously loaded character   */
  619. char  in = 0;                               /* 1=within a string             */
  620. char  in_amp = 0;                           /* 1 = processing & string       */
  621. char  *p;
  622. char  *prog_ptr;
  623. long  maxlen;
  624.  
  625.  
  626. if (source == 0)
  627.    {
  628.    for (charpos = 0; charpos<MAXPROGLEN;    /* init entire program array..   */
  629.      charpos++)
  630.        prog[charpos] = ' ';                 /* ..to all spaces               */
  631.    rewind(progfile);                        /* position to beginning of file */
  632.    prog_ptr = prog;
  633.    maxlen = MAXPROGLEN;
  634.    }
  635. else
  636.    {
  637.    p = line;
  638.    prog_ptr = prog_line;
  639.    maxlen = MAXPROGLINELEN;
  640.    }
  641. charpos = -1;                               /* init ptr to start of memory   */
  642. disaster = 0;                               /* clear disaster flag           */
  643. ch = '~';                                   /* init first character to ~     */
  644. while (!disaster)                           /* while loading OK..            */
  645.    {
  646.    lastchr = ch;                            /* save previously loaded char   */
  647.    if (source == 0)
  648.       {
  649.       fread(&ch, 1, 1, progfile);           /* read one char from Mouse file */
  650.       if (feof(progfile))                   /* if end of Mouse file..        */
  651.          break;                             /* then break out of loop        */
  652.       }
  653.    else
  654.       {
  655.       ch = *p++;
  656.       if (ch=='\0' || ch=='\n')
  657.          break;
  658.       }
  659.    if (ch == '~')                           /* if start of comment..         */
  660.       {
  661.       if (source == 0)
  662.          do {
  663.             fread(&ch, 1, 1, progfile);     /* ..read characters..           */
  664.             } while (ch != '\n');           /* ..until next newline          */
  665.       else
  666.          break;
  667.       }
  668.    else if (charpos < maxlen-1)             /* else if program memory left.. */
  669.       {
  670.       charpos++;                            /* increment pointer to memory   */
  671.       prog_ptr[charpos] = ch;               /* save read character to memory */
  672.       if (ch == '\"')                       /* if current char is " ..       */
  673.          in = !in;                          /* ..then toggle quote flag      */
  674.       if (ch=='&' && !in)                   /* if current char is & ..       */
  675.          in_amp = 1;                        /* ..then set & processing flag  */
  676.       if (ch==10 || ch==13 || ch=='\n'      /* if CR or LF or newline..      */
  677.           || ch=='\t' || ch=='\r')          /* ..or tab or \r..              */
  678.          prog_ptr[charpos] = ch = ' ';      /* ..replace with space          */
  679.       if (in_amp && ch==' ')                /* if end of & string..          */
  680.          {
  681.          prog_ptr[charpos] = ch = '&';      /* ..replace final space w/ &    */
  682.          in_amp = 0;                        /* turn off & processing flag    */
  683.          }
  684.       if (in_amp && ch==';')                /* if end of & string (found ;)  */
  685.          {
  686.          prog_ptr[charpos] = ch = '&';      /* ..insert final & correctly    */
  687.          charpos++;
  688.          prog_ptr[charpos] = ch = ';';
  689.          in_amp = 0;                        /* turn off & processing flag    */
  690.          }
  691.       if (ch==' ' && !in &&                 /* if a space not in string..    */
  692.            !isdigit(lastchr) &&             /* ..and not after a number..    */
  693.            (lastchr != '\''))               /* ..and not after a '..         */
  694.          {
  695.          charpos--;                         /* then backspace pointer        */
  696.          ch = prog_ptr[charpos];            /* update last read character    */
  697.          }
  698.       else if (!in && lastchr == ' ' &&     /* if last char was a space and..*/
  699.             !isdigit(ch) && ch != '\"'      /*..this char isn't a digit..    */
  700.             && prog_ptr[charpos-2] != '\'') /*..and it isn't a quote-space.. */
  701.          prog_ptr[--charpos] = ch;          /* then remove the last space    */
  702.       }
  703.    else                                     /* if no program memory left..   */
  704.       {
  705.       printf("Program is too long\n");      /* print error message           */
  706.       disaster = 1;                         /* and set disaster flag         */
  707.       }
  708.    }                                        /* end while                     */
  709. proglen = charpos + 1;                      /* set total program length      */
  710. if (source==1)
  711.    {
  712.    prog_ptr[charpos+1] = '$';
  713.    charpos++;
  714.    proglen = charpos + 1;
  715.    }
  716.  
  717. }                                           /* end load                      */
  718.  
  719.  
  720.  
  721.  
  722.  
  723. /*****************************************************************************/
  724. /*                                                                           */
  725. /*  makedeftable()                                                           */
  726. /*                                                                           */
  727. /*  Construct macro definition table.                                        */
  728. /*                                                                           */
  729. /*****************************************************************************/
  730.  
  731. void makedeftable (void)
  732. {
  733. for (ch = 'A' ; ch <= 'Z'; ch++)            /* for all macro table entries.. */
  734.    macdefs[ch-'A'] = 0;                     /*..initialize all entries to 0  */
  735. charpos = -1;                               /* init ptr to start of memory   */
  736. do {                                        /* for all program characters    */
  737.    Getchar();                               /* read next program character   */
  738.    if (ch=='$' && charpos < proglen-1)      /* if this is a $ (macro defn..  */
  739.       {                                     /* ..or end of program           */
  740.       Getchar();                            /* read next char (macro letter) */
  741.       UPPERCASE;                            /* convert it to uppercase       */
  742.       if ((ch >= 'A') && (ch <= 'Z'))       /* if it's a macro definition..  */
  743.          macdefs[ch-'A'] = charpos;         /* save pointer in macro def tbl */
  744.       }
  745.    } while (charpos < proglen-1);           /* repeat until end of program   */
  746. }                                           /* end makedeftable              */
  747.  
  748.  
  749.  
  750.  
  751.  
  752. /*****************************************************************************/
  753. /*                                                                           */
  754. /*  interpret()                                                              */
  755. /*                                                                           */
  756. /*  The Interpreter.                                                         */
  757. /*                                                                           */
  758. /*****************************************************************************/
  759.  
  760. void interpret (void)
  761. {
  762. char         amp_str[11];                   /* & function string             */
  763. char         *p;                            /* character pointer             */
  764. char instr[26];                             /* input string                  */
  765.  
  766.  
  767. charpos = -1;                               /* init instruction pointer      */
  768. if (source==0)
  769.    {
  770.    sp = -1;                                 /* init stack pointer            */
  771.    esp = -1;                                /* init environ stack pointer    */
  772.    }
  773. offset = 0;                                 /* init variable offset          */
  774. nextfree = LOCSIZE;                         /* init next free variable addr  */
  775.  
  776. do {                                        /* repeat until end of program   */
  777.    Getchar();                               /* read next program character   */
  778.    if (ch == ' ')                           /* if it's a space..             */
  779.       continue;                             /* ..skip to end of loop         */
  780.  
  781.    if (tracing)                             /* if tracing on..               */
  782.       display(charpos);                     /* ..display code w/ curr posn   */
  783.  
  784.    if (isdigit(ch))                         /* if char is a digit..          */
  785.       {                                     /* ..encode a decimal number     */
  786.       temp = 0;                             /* init decimal number to 0      */
  787.       while (isdigit(ch))                   /* repeat for each digit         */
  788.          {
  789.          temp = 10 * temp + VALUE(ch);      /* add digit to number           */
  790.          Getchar();                         /* get next character            */
  791.          }                                  /* end while                     */
  792.       if (ch == '.')
  793.          {
  794.          Getchar();
  795.          temp2 = 1.0;
  796.          while (isdigit(ch))
  797.             {
  798.             temp2 /= 10.0;
  799.             temp += temp2 * VALUE(ch);
  800.             Getchar();
  801.             }
  802.          }
  803.       push(temp);                           /* push final number onto stack  */
  804.       BACKSPACE;                            /* backspace to last digit       */
  805.       }
  806.  
  807.    else if ((ch >= 'A') && (ch <= 'Z'))     /* if A to Z..                   */
  808.       push(ch - 'A');                       /* put 0 to 25 on stack          */
  809.  
  810.    else if ((ch >= 'a') && (ch <= 'z'))     /* if a to z..                   */
  811.       push(ch - 'a' + offset);              /* put 0 to 25 + offset on stack */
  812.  
  813.    else                                     /* if not alphanumeric..         */
  814.  
  815.       switch (ch)                           /* big switch on current char    */
  816.          {
  817.  
  818.          case '$' :                         /*  $   macro defn / end of prog */
  819.             break;                          /*         no action             */
  820.  
  821.          case '_' :                         /*  _   change sign              */
  822.             push(-pop());
  823.             break;
  824.  
  825.          case '+' :                         /*  +   add                      */
  826.             push(pop() + pop());
  827.             break;
  828.  
  829.          case  '-' :                        /*  -   subtract                 */
  830.             temp = pop();
  831.             push(pop() - temp);
  832.             break;
  833.  
  834.          case '*' :                         /*  *   multiply                 */
  835.             push(pop() * pop());
  836.             break;
  837.  
  838.          case '/' :                         /*  /   divide with zero check   */
  839.             temp = pop();
  840.             if (temp != 0)                  /*         check for div by zero */
  841.                push(pop() / temp);          /*         push if not div by 0  */
  842.             else
  843.                error(4);                    /*         error if div by zero  */
  844.             break;
  845.  
  846.          case '\\' :                        /*  \   remainder w/ zero check  */
  847.             temp = pop();
  848.             if (temp != 0)                  /*         check for rem by zero */
  849.                push((long)pop() %           /*         push if not rem by 0  */
  850.                     (long)temp);
  851.             else
  852.                error(5);                    /*         error if rem by zero  */
  853.             break;
  854.  
  855.          case '?' :                         /*  ?   read from keyboard       */
  856.             Getchar();
  857.             if (ch == '\'')                 /*  ?'   read character          */
  858.                {
  859.                fgets(instr, 2, stdin);      /*         read as a string      */
  860.                chomp(instr);                /*         remove \n             */
  861.                sscanf(instr, "%c", &ch);    /*         read character        */
  862.                push((double)ch);
  863.                }
  864.             else                            /*  ?    read number             */
  865.                {
  866.                fgets(instr, 25, stdin);     /*         read as a string      */
  867.                chomp(instr);                /*         remove \n             */
  868.                sscanf(instr, "%lf", &temp); /*         read number           */
  869.                push(temp);
  870.                BACKSPACE;
  871.                }
  872.             break;
  873.  
  874.          case '!' :                         /*  !   display on screen        */
  875.             Getchar();
  876.             if (ch == '\'')                 /*  !'   display character       */
  877.                printf("%c", Round(pop()));
  878.             else                            /*  !    display number          */
  879.                {
  880.                sprintf(format_str, "%%%d.", /*         create format string  */
  881.                   display_width);
  882.                sprintf(temp_str, "%d",
  883.                   display_digits);
  884.                strcat(format_str,temp_str);
  885.                if (display_mode == 0)       /*         if fixed mode         */
  886.                   strcat(format_str,"f");
  887.                else if (display_mode == 1)  /*         if sci mode           */
  888.                   strcat(format_str,"E");
  889.                else                         /*         if general mode       */
  890.                   strcat(format_str,"G");
  891.                printf(format_str, pop());   /*         print number          */
  892.                BACKSPACE;
  893.                }
  894.             break;
  895.  
  896.          case '"' :                         /*  "   display string on screen */
  897.             do {
  898.                Getchar();
  899.                if (ch == '!')               /*         check for newline     */
  900.                   printf("\n");             /*         print newline         */
  901.                else if (ch != '"')          /*         check for end of str  */
  902.                   printf ("%c", ch);        /*         print if not "        */
  903.                } while (ch != '"');
  904.             break;
  905.  
  906.          case ':' :                         /*  :   assignment               */
  907.             temp = pop();
  908.             data[Round(temp)] = pop();
  909.             break;
  910.  
  911.          case '.' :                         /*  .   dereference              */
  912.             push(data[Round(pop())]);
  913.             break;
  914.  
  915.          case '<' :                         /*  <   less than                */
  916.             temp = pop();
  917.             push ((pop() < temp) ? 1 : 0);
  918.             break;
  919.  
  920.          case '=' :                         /*  =   equal to                 */
  921.             push ((pop()==pop()) ? 1 : 0);
  922.             break;
  923.  
  924.          case '>' :                         /*  >   greater than             */
  925.             temp = pop();
  926.             push ((pop() > temp) ? 1 : 0);
  927.             break;
  928.  
  929.          case '[' :                         /*  [   conditional statement    */
  930.             if (pop() <= 0)                 /*         true if > 0           */
  931.                skip2('[','|',']');
  932.             break;
  933.  
  934.          case ']' :                         /*  ]   end of conditional       */
  935.             break;                          /*         no action             */
  936.  
  937.          case '|':                          /*  |   else                     */
  938.             skip('[',']');
  939.             break;
  940.  
  941.          case '(' :                         /*  (   begin loop               */
  942.             pushenv(loop);
  943.             break;
  944.  
  945.          case ')' :                         /*  )   end loop                 */
  946.             charpos=envstack[esp].charpos;
  947.             break;
  948.  
  949.          case '^' :                         /*  ^   exit loop                */
  950.             if (pop() <= 0)
  951.                {
  952.                popenv();
  953.                skip('(',')');
  954.                }
  955.             break;
  956.  
  957.          case '#':                          /*  #   macro call               */
  958.             Getchar();                      /*         get macro letter      */
  959.             UPPERCASE;                      /*         convert to uppercase  */
  960.             if ((ch>='A') && (ch<='Z'))     /*         if A to Z..           */
  961.                {
  962.                if (macdefs[ch-'A'] > 0)     /*         if macro defined..    */
  963.                   {
  964.                   pushenv(macro);           /*         push env stack frame  */
  965.                   charpos=macdefs[ch-'A'];  /*         instruct ptr to macro */
  966.                   if (nextfree + LOCSIZE    /*         if variables avail..  */
  967.                           <= MAXADDR)
  968.                      {
  969.                      offset = nextfree;     /*         increment offset      */
  970.                      nextfree += LOCSIZE;   /*         increment nextfree    */
  971.                      }
  972.                   else                      /*         out of variable space */
  973.                      error(10);             /*         print error message   */
  974.                   }
  975.                else                         /*         macro not defined     */
  976.                   error(6);                 /*         print error message   */
  977.                }
  978.             else                            /*         invalid char after #  */
  979.                error(7);                    /*         print error message   */
  980.             break;
  981.  
  982.          case '@':                          /*  @   return from macro        */
  983.             do {                            /*         loop to discard loops */
  984.                popenv();                    /*         pop env stack frame   */
  985.                } while (envtag != macro);   /*         repeat til macro found*/
  986.             skip('#',';');                  /*         skip to ;             */
  987.             nextfree -= LOCSIZE;            /*         decrement nextfree    */
  988.             break;
  989.  
  990.          case '%':                          /*  %   replace formal by actual */
  991.             pushenv(parameter);             /*         push stack frame      */
  992.             parbal = 1;                     /*         1 stack already pushed*/
  993.             tsp = esp;                      /*         temp env stack pointer*/
  994.             do {                            /*         loop thru env stack   */
  995.                tsp--;                       /*         decrement stack ptr   */
  996.                switch (envstack[tsp].tag)   /*         check tag type        */
  997.                   {
  998.                   case macro :              /*         if macro (#)..        */
  999.                      parbal--;              /*         decrement counter     */
  1000.                      break;
  1001.                   case parameter :          /*         if parameter (%)..    */
  1002.                      parbal++;              /*         nest another level    */
  1003.                      break;
  1004.                   case loop :               /*         if loop [ ( ]..       */
  1005.                      break;                 /*         keep searching        */
  1006.                   }
  1007.                } while (parbal != 0);       /*        til calling macro found*/
  1008.             charpos=envstack[tsp].charpos;  /*        update instruct ptr    */
  1009.             offset = envstack[tsp].offset;  /*        pt to new variable set */
  1010.             parnum = pop();                 /*        get parameter number   */
  1011.             do {                            /*        look for actual param  */
  1012.                Getchar();                   /*        read program character */
  1013.                if (ch == '"')               /*         param contains string */
  1014.                   skipstring();             /*         skip string           */
  1015.                else if (ch == '#')          /*         param has macro call  */
  1016.                   skip('#',';');            /*         skip to end of macro  */
  1017.                else if (ch == ',')          /*         count commas          */
  1018.                   parnum--;                 /*         decrement comma ctr   */
  1019.                else if (ch == ';')          /*         param doesn't exist   */
  1020.                   {
  1021.                   parnum = 0;               /*         stop loop             */
  1022.                   popenv();                 /*         null parameter        */
  1023.                   }
  1024.                } while (parnum != 0);       /*         loop until param found*/
  1025.             break;
  1026.  
  1027.          case ',' :                         /*  ,   end of actual parameter  */
  1028.          case ';' :                         /*  ;   end of macro call        */
  1029.             popenv();
  1030.             break;
  1031.  
  1032.          case '\''  :                       /*  '   stack next character     */
  1033.             Getchar();
  1034.             push(ch);
  1035.             break;
  1036.  
  1037.          case '{' :                         /*  {   trace on                 */
  1038.             tracing = 1;
  1039.             break;
  1040.  
  1041.          case '}' :                         /*  }   trace off                */
  1042.             tracing = 0;
  1043.             break;
  1044.  
  1045.          case '&':                          /*  &   & function               */
  1046.             p = amp_str;
  1047.             Getchar();                      /*         read 1st char after & */
  1048.             while (ch!='&' && ch!='$')      /*         loop until end & or $ */
  1049.                {
  1050.                *p++ = tolower(ch);          /*         copy char to amp_str  */
  1051.                Getchar();                   /*         read next char        */
  1052.                }
  1053.             *p = '\0';                      /*         add end-of-string     */
  1054.             process_amp(amp_str);           /*         call & subroutine     */
  1055.             break;
  1056.  
  1057.          default :                          /*      unused character         */
  1058.             error(11);                      /*         print error message   */
  1059.             break;
  1060.          }                                  /* end switch                    */
  1061.  
  1062.    } while (!((ch == '$') || disaster));    /* loop until end of program ($) */
  1063. }                                           /* end interpret                 */
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069. /*****************************************************************************/
  1070. /*                                                                           */
  1071. /*  process_amp()                                                            */
  1072. /*                                                                           */
  1073. /*  Process & functions.                                                     */
  1074. /*                                                                           */
  1075. /*****************************************************************************/
  1076.  
  1077. void process_amp(char *str)
  1078. {
  1079. long i, j;                                  /* loop counters                 */
  1080. double  hr, min, sec;
  1081. struct tm *systime;
  1082. time_t  t;
  1083. char instr[26];                             /* input string                  */
  1084.  
  1085.  
  1086. if (!strcmp(str,"2x"))                      /* &2x                           */
  1087.    push(pow(2.0,pop()));
  1088.  
  1089. else if (!strcmp(str,"4th"))                /* &4th                          */
  1090.    {
  1091.    temp = pop();
  1092.    push(temp*temp*temp*temp);
  1093.    }
  1094.  
  1095. else if (!strcmp(str,"4thrt"))              /* &4thrt                        */
  1096.    {
  1097.    temp = pop();
  1098.    if (temp >= 0.0)
  1099.       push(sqrt(sqrt(temp)));
  1100.    else
  1101.       error(31);
  1102.    }
  1103.  
  1104. else if (!strcmp(str,"10x"))                /* &10x                          */
  1105.    push(pow(10.0,pop()));
  1106.  
  1107. else if (!strcmp(str,"abs"))                /* &abs                          */
  1108.    push(fabs(pop()));
  1109.  
  1110. else if (!strcmp(str,"acos"))               /* &acos                         */
  1111.    {
  1112.    temp = pop();
  1113.    if (fabs(temp) <= 1.0)
  1114.       push(acos(temp)/angle_factor);
  1115.    else
  1116.       error(12);
  1117.    }
  1118.  
  1119. else if (!strcmp(str,"acosh"))              /* &acosh                        */
  1120.    {
  1121.    temp = pop();
  1122.    if (temp >= 1.0)
  1123.       push(log(temp+sqrt(temp*temp-1.0)));
  1124.    else
  1125.       error(13);
  1126.    }
  1127.  
  1128. else if (!strcmp(str,"and"))                /* &and                          */
  1129.    {
  1130.    itemp = Round(pop());
  1131.    itemp2 = Round(pop());
  1132.    push((double)(itemp & itemp2));
  1133.    }
  1134.  
  1135. else if (!strcmp(str,"asin"))               /* &asin                         */
  1136.    {
  1137.    temp = pop();
  1138.    if (fabs(temp) <= 1.0)
  1139.       push(asin(temp)/angle_factor);
  1140.    else
  1141.       error(14);
  1142.    }
  1143.  
  1144. else if (!strcmp(str,"asinh"))              /* &asinh                        */
  1145.    {
  1146.    temp = pop();
  1147.    push(log(temp+sqrt(temp*temp+1.0)));
  1148.    }
  1149.  
  1150. else if (!strcmp(str,"atan"))               /* &atan                         */
  1151.    push(atan(pop())/angle_factor);
  1152.  
  1153. else if (!strcmp(str,"atan2"))              /* &atan2                        */
  1154.    {
  1155.    temp = pop();
  1156.    push(atan2(pop(),temp)/angle_factor);
  1157.    }
  1158.  
  1159. else if (!strcmp(str,"atanh"))              /* &atanh                        */
  1160.    {
  1161.    temp = pop();
  1162.    if (fabs(temp) < 1.0)
  1163.       push(0.5*log((1.0+temp)/(1.0-temp)));
  1164.    else
  1165.       error(15);
  1166.    }
  1167.  
  1168. else if (!strcmp(str,"au"))                 /* &au                           */
  1169.    push(AU);
  1170.  
  1171. else if (!strcmp(str,"beep"))               /* &beep                         */
  1172.    printf("BEEP\n");
  1173.    //printf("\a");
  1174.  
  1175. else if (!strcmp(str,"c"))                  /* &c                            */
  1176.    push(SPEED_OF_LIGHT);
  1177.  
  1178. else if (!strcmp(str,"clrstk"))             /* &clrstk                       */
  1179.    sp = -1;
  1180.  
  1181. else if (!strcmp(str,"cm>in"))              /* &cm>in                        */
  1182.    push(pop()/IN_CM);
  1183.  
  1184. else if (!strcmp(str,"cnr"))                /* &cnr                          */
  1185.    {
  1186.    itemp = Round(pop());
  1187.    itemp2 = Round(pop());
  1188.    if ((itemp>=0) && (itemp2>=0) &&
  1189.        (itemp<=itemp2))
  1190.       {
  1191.       temp = 1.0;
  1192.       for (i=itemp2, j=(itemp2-itemp);
  1193.            j>=1; i--, j--)
  1194.          temp *= (double)i/(double)j;
  1195.       push(temp);
  1196.       }
  1197.    else
  1198.       error(23);
  1199.    }
  1200.  
  1201. else if (!strcmp(str,"cont"))               /* &cont                         */
  1202.    charpos=envstack[esp].charpos;
  1203.  
  1204. else if (!strcmp(str,"cos"))                /* &cos                          */
  1205.    push(cos(pop()*angle_factor));
  1206.  
  1207. else if (!strcmp(str,"cosh"))               /* &cosh                         */
  1208.    push(cosh(pop()));
  1209.  
  1210. else if (!strcmp(str,"cube"))               /* &cube                         */
  1211.    {
  1212.    temp = pop();
  1213.    push(temp*temp*temp);
  1214.    }
  1215.  
  1216. else if (!strcmp(str,"cubert"))             /* &cubert                       */
  1217.    {
  1218.    temp = pop();
  1219.    if (temp > 0.0)
  1220.       push(pow(temp, 1.0/3.0));
  1221.    else if (temp == 0.0)
  1222.       push(0.0);
  1223.    else
  1224.       error(30);
  1225.    }
  1226.  
  1227. else if (!strcmp(str,"c>f"))                /* &c>f                          */
  1228.    push(pop()*9.0/5.0+32.0);
  1229.  
  1230. else if (!strcmp(str,"deg"))                /* &deg                          */
  1231.    angle_factor = PI/180.0;
  1232.  
  1233. else if (!strcmp(str,"dom"))                /* &dom                          */
  1234.    {
  1235.    t = time(NULL);
  1236.    systime = localtime(&t);
  1237.    push((double)systime->tm_mday);
  1238.    }
  1239.  
  1240. else if (!strcmp(str,"dow"))                /* &dow                          */
  1241.    {
  1242.    t = time(NULL);
  1243.    systime = localtime(&t);
  1244.    push((double)(systime->tm_wday+1));
  1245.    }
  1246.  
  1247. else if (!strcmp(str,"doy"))                /* &doy                          */
  1248.    {
  1249.    t = time(NULL);
  1250.    systime = localtime(&t);
  1251.    push((double)(systime->tm_yday+1));
  1252.    }
  1253.  
  1254. else if (!strcmp(str,"drop"))               /* &drop                         */
  1255.    pop();
  1256.  
  1257. else if (!strcmp(str,"dup"))                /* &dup                          */
  1258.    {
  1259.    temp = pop();
  1260.    push(temp);
  1261.    push(temp);
  1262.    }
  1263.  
  1264. else if (!strcmp(str,"d>r"))                /* &d>r                          */
  1265.    push(pop()*PI/180.0);
  1266.  
  1267. else if (!strcmp(str,"e"))                  /* &e                            */
  1268.    push(ELEMENTARY_CHG);
  1269.  
  1270. else if (!strcmp(str,"eex"))                /* &eex                          */
  1271.    {
  1272.    temp = pop();
  1273.    push(pop()*pow(10.0,temp));
  1274.    }
  1275.  
  1276. else if (!strcmp(str,"eps0"))               /* &eps0                         */
  1277.    push(PERMITTIVITY);
  1278.  
  1279. else if (!strcmp(str,"exit"))               /* &exit                         */
  1280.    done = 1;
  1281.  
  1282. else if (!strcmp(str,"exp"))                /* &exp                          */
  1283.    push(exp(pop()));
  1284.  
  1285. else if (!strcmp(str,"fact"))               /* &fact                         */
  1286.    {
  1287.    ntemp = Round(pop());
  1288.    if (ntemp >= 0)
  1289.       {
  1290.       temp = 1.0;
  1291.       for (i=2; i<=ntemp; i++)
  1292.          temp *= (double)i;
  1293.       push(temp);
  1294.       }
  1295.    else
  1296.       error(21);
  1297.    }
  1298.  
  1299. else if (!strcmp(str,"fclose"))             /* &fclose                       */
  1300.    fclose(fp[Round(pop())]);
  1301.  
  1302. else if (!strcmp(str,"feof"))               /* &feof                         */
  1303.    push(feof(fp[Round(pop())]) ? 1 : 0);
  1304.  
  1305. else if (!strcmp(str,"fix"))                /* &fix                          */
  1306.    {
  1307.    display_mode = 0;
  1308.    display_digits = Round(pop());
  1309.    }
  1310.  
  1311. else if (!strcmp(str,"fopen"))              /* &fopen                        */
  1312.    {
  1313.    itemp = Round(pop());
  1314.    itemp2 = Round(pop());
  1315.    sprintf(filenum_str,"%03d",itemp2);
  1316.    strcpy(filename_str,"mouse.");
  1317.    strcat(filename_str, filenum_str);
  1318.    switch ((int)itemp)
  1319.       {
  1320.       case 0:  strcpy(filemode_str,"r");
  1321.                break;
  1322.       case 1:  strcpy(filemode_str,"w");
  1323.                break;
  1324.       case 2:  strcpy(filemode_str,"rb");
  1325.                break;
  1326.       case 3:  strcpy(filemode_str,"wb");
  1327.                break;
  1328.       }
  1329.    if ((fp[itemp2] = fopen(filename_str,
  1330.         filemode_str))==NULL)
  1331.       {
  1332.       error(28);
  1333.       return;
  1334.       }
  1335.    }
  1336.  
  1337. else if (!strcmp(str,"frac"))               /* &frac                         */
  1338.    push(Frac(pop()));
  1339.  
  1340. else if (!strcmp(str,"frewind"))            /* &frewind                      */
  1341.    rewind(fp[Round(pop())]);
  1342.  
  1343. else if (!strcmp(str,"f>c"))                /* &f>c                          */
  1344.    push((pop()-32.0)*5.0/9.0);
  1345.  
  1346. else if (!strcmp(str,"f?"))                 /* &f?                           */
  1347.    {
  1348.    fscanf(fp[Round(pop())],"%lf", &temp);
  1349.    push(temp);
  1350.    }
  1351.  
  1352. else if (!strcmp(str,"f?'"))                /* &f?'                          */
  1353.    {
  1354.    fscanf(fp[Round(pop())],"%c", &ch);
  1355.    push((double)ch);
  1356.    }
  1357.  
  1358. else if (!strcmp(str,"f!"))                 /* &f!                           */
  1359.    {
  1360.    sprintf(format_str, "%%%d.",             /*         create format string  */
  1361.       display_width);
  1362.    sprintf(temp_str, "%d",
  1363.       display_digits);
  1364.    strcat(format_str,temp_str);
  1365.    if (display_mode == 0)                   /*         if fixed mode         */
  1366.       strcat(format_str,"f");
  1367.    else if (display_mode == 1)              /*         if sci mode           */
  1368.       strcat(format_str,"E");
  1369.    else                                     /*         if general mode       */
  1370.       strcat(format_str,"G");
  1371.    itemp = Round(pop());
  1372.    fprintf(fp[itemp],format_str,pop());     /*         print number          */
  1373.    }
  1374.  
  1375. else if (!strcmp(str,"f!'"))                /* &f!'                          */
  1376.    {
  1377.    itemp = Round(pop());
  1378.    fprintf(fp[itemp],"%c", Round(pop()));
  1379.    }
  1380.  
  1381. else if (!strcmp(str,"f\""))                /* &f"                           */
  1382.    {
  1383.    itemp = Round(pop());
  1384.    do {
  1385.       Getchar();
  1386.       if (ch == '!')                        /*         check for newline     */
  1387.          fprintf(fp[itemp],"\n");           /*         print newline         */
  1388.       else if (ch != '"')                   /*         check for end of str  */
  1389.          fprintf (fp[itemp],"%c", ch);      /*         print if not "        */
  1390.       } while (ch != '"');
  1391.    }
  1392.  
  1393. else if (!strcmp(str,"g"))                  /* &g                            */
  1394.    push(GRAV_CONST);
  1395.  
  1396. else if (!strcmp(str,"g0"))                 /* &g0                           */
  1397.    push(GRAV_ACCEL);
  1398.  
  1399. else if (!strcmp(str,"gal>l"))              /* &gal>l                        */
  1400.    push(pop()*GAL_L);
  1401.  
  1402. else if (!strcmp(str,"ge"))                 /* &ge                           */
  1403.    {
  1404.    temp = pop();
  1405.    push ((pop() >= temp) ? 1 : 0);
  1406.    }
  1407.  
  1408. else if (!strcmp(str,"gen"))                /* &gen                          */
  1409.    {
  1410.    display_mode = 2;
  1411.    display_digits = Round(pop());
  1412.    }
  1413.  
  1414. else if (!strcmp(str,"gmearth"))            /* &gmearth                      */
  1415.    push(GM_EARTH);
  1416.  
  1417. else if (!strcmp(str,"gmsun"))              /* &gmsun                        */
  1418.    push(GM_SUN);
  1419.  
  1420. else if (!strcmp(str,"grad"))               /* &grad                         */
  1421.    angle_factor = PI/200.0;
  1422.  
  1423. else if (!strcmp(str,"h"))                  /* &h                            */
  1424.    push(PLANCK);
  1425.  
  1426. else if (!strcmp(str,"halfpi"))             /* &halfpi                          */
  1427.    push(0.5*PI);
  1428.  
  1429. else if (!strcmp(str,"hbar"))               /* &hbar                         */
  1430.    push(H_BAR);
  1431.  
  1432. else if (!strcmp(str,"hms>h"))              /* &hms>h                        */
  1433.    {
  1434.    temp = pop();
  1435.    hr = Int(temp);
  1436.    min = Int(100.0*Frac(temp));
  1437.    sec = 100.0*Frac(100.0*temp);
  1438.    push(hr + min/60.0 + sec/3600.0);
  1439.    }
  1440.  
  1441. else if (!strcmp(str,"hour"))               /* &hour                         */
  1442.    {
  1443.    t = time(NULL);
  1444.    systime = localtime(&t);
  1445.    push((double)systime->tm_hour);
  1446.    }
  1447.  
  1448. else if (!strcmp(str,"h>hms"))              /* &h>hms                        */
  1449.    {
  1450.    temp = pop();
  1451.    hr = Int(temp);
  1452.    min = Int(60.0*Frac(temp));
  1453.    sec = 60.0*Frac(60.0*temp);
  1454.    push(hr + min/100.0 + sec/10000.0);
  1455.    }
  1456.  
  1457. else if (!strcmp(str,"int"))                /* &int                          */
  1458.    push(Int(pop()));
  1459.  
  1460. else if (!strcmp(str,"in>cm"))              /* &in>cm                        */
  1461.    push(pop()*IN_CM);
  1462.  
  1463. else if (!strcmp(str,"kb"))                 /* &kb                           */
  1464.    push(BOLTZMANN);
  1465.  
  1466. else if (!strcmp(str,"kg>lb"))              /* &kg>lb                        */
  1467.    push(pop()/LB_KG);
  1468.  
  1469. else if (!strcmp(str,"lb>kg"))              /* &lb>kg                        */
  1470.    push(pop()*LB_KG);
  1471.  
  1472. else if (!strcmp(str,"le"))                 /* &le                           */
  1473.    {
  1474.    temp = pop();
  1475.    push ((pop() <= temp) ? 1 : 0);
  1476.    }
  1477.  
  1478. else if (!strcmp(str,"ln"))                 /* &ln                           */
  1479.    {
  1480.    temp = pop();
  1481.    if (temp > 0.0)
  1482.       push(log(temp));
  1483.    else
  1484.       error(16);
  1485.    }
  1486.  
  1487. else if (!strcmp(str,"log"))                /* &log                          */
  1488.    {
  1489.    temp = pop();
  1490.    if (temp > 0.0)
  1491.       push(log(temp));
  1492.    else
  1493.       error(16);
  1494.    }
  1495.  
  1496. else if (!strcmp(str,"log2"))               /* &log2                         */
  1497.    {
  1498.    temp = pop();
  1499.    if (temp > 0.0)
  1500.       push(log(temp)/log(2.0));
  1501.    else
  1502.       error(17);
  1503.    }
  1504.  
  1505. else if (!strcmp(str,"log10"))              /* &log10                        */
  1506.    {
  1507.    temp = pop();
  1508.    if (temp > 0.0)
  1509.       push(log10(temp));
  1510.    else
  1511.       error(18);
  1512.    }
  1513.  
  1514. else if (!strcmp(str,"l>gal"))              /* &l>gal                        */
  1515.    push(pop()/GAL_L);
  1516.  
  1517. else if (!strcmp(str,"me"))                 /* &me                           */
  1518.    push(MASS_ELECTRON);
  1519.  
  1520. else if (!strcmp(str,"min"))                /* &min                          */
  1521.    {
  1522.    t = time(NULL);
  1523.    systime = localtime(&t);
  1524.    push((double)systime->tm_min);
  1525.    }
  1526.  
  1527. else if (!strcmp(str,"mn"))                 /* &mn                           */
  1528.    push(MASS_NEUTRON);
  1529.  
  1530. else if (!strcmp(str,"month"))              /* &month                        */
  1531.    {
  1532.    t = time(NULL);
  1533.    systime = localtime(&t);
  1534.    push((double)(systime->tm_mon+1));
  1535.    }
  1536.  
  1537. else if (!strcmp(str,"mp"))                 /* &mp                           */
  1538.    push(MASS_PROTON);
  1539.  
  1540. else if (!strcmp(str,"mu0"))                /* &mu0                          */
  1541.    push(PERMEABILITY);
  1542.  
  1543. else if (!strcmp(str,"na"))                 /* &na                           */
  1544.    push(AVAGADRO);
  1545.  
  1546. else if (!strcmp(str,"ne"))                 /* &ne                           */
  1547.    {
  1548.    temp = pop();
  1549.    push ((pop() != temp) ? 1 : 0);
  1550.    }
  1551.  
  1552. else if (!strcmp(str,"nip"))                /* &nip                          */
  1553.    {
  1554.    temp = pop();
  1555.    pop();
  1556.    push(temp);
  1557.    }
  1558.  
  1559. else if (!strcmp(str,"not"))                /* &not                          */
  1560.    {
  1561.    itemp = Round(pop());
  1562.    push((double)(~itemp));
  1563.    }
  1564.  
  1565. else if (!strcmp(str,"or"))                 /* &or                           */
  1566.    {
  1567.    itemp = Round(pop());
  1568.    itemp2 = Round(pop());
  1569.    push((double)(itemp | itemp2));
  1570.    }
  1571.  
  1572. else if (!strcmp(str,"over"))               /* &over                         */
  1573.    {
  1574.    temp = pop();
  1575.    temp2 = pop();
  1576.    push(temp2);
  1577.    push(temp);
  1578.    push(temp2);
  1579.    }
  1580.  
  1581. else if (!strcmp(str,"pi"))                 /* &pi                           */
  1582.    push(PI);
  1583.  
  1584. else if (!strcmp(str,"pnr"))                /* &pnr                          */
  1585.    {
  1586.    itemp = Round(pop());
  1587.    itemp2 = Round(pop());
  1588.    if ((itemp>=0) && (itemp2>=0) &&
  1589.        (itemp<=itemp2))
  1590.       {
  1591.       temp = 1.0;
  1592.       for (i=itemp2;
  1593.            i>=(itemp2-itemp+1);
  1594.            i--)
  1595.          temp *= (double)i;
  1596.       push(temp);
  1597.       }
  1598.    else
  1599.       error(24);
  1600.    }
  1601.  
  1602. else if (!strcmp(str,"pow"))                /* &pow                          */
  1603.    {
  1604.    temp = pop();
  1605.    temp2 = pop();
  1606.    error_flag = ((temp2==0.0) &&
  1607.       (temp<=0.0)) ||
  1608.       ((temp2<0) &&
  1609.       (temp!=Round(temp)));
  1610.    if (!error_flag)
  1611.       push(pow(temp2, temp));
  1612.    else
  1613.       error(26);
  1614.    }
  1615.  
  1616. else if (!strcmp(str,"p>r"))                /* &p>r                          */
  1617.    {
  1618.    temp = pop();
  1619.    temp2 = pop();
  1620.    push(temp*cos(temp2*angle_factor));
  1621.    push(temp*sin(temp2*angle_factor));
  1622.    }
  1623.  
  1624. else if (!strcmp(str,"quit"))               /* &quit                         */
  1625.    done = 1;
  1626.  
  1627. else if (!strcmp(str,"rad"))                /* &rad                          */
  1628.    angle_factor = 1.0;
  1629.  
  1630. else if (!strcmp(str,"rand"))               /* &rand                         */
  1631.    push((double)rand()/(double)RAND_MAX);
  1632.  
  1633. else if (!strcmp(str,"rcl"))                /* &rcl                          */
  1634.    {
  1635.    itemp = Round(pop());
  1636.    if ((itemp>=0) && (itemp<ARRAYSIZE))
  1637.       push(array[itemp]);
  1638.    else
  1639.       error(25);
  1640.    }
  1641.  
  1642. else if (!strcmp(str,"rearth"))             /* &rearth                       */
  1643.    push(R_EARTH);
  1644.  
  1645. else if (!strcmp(str,"recip"))              /* &recip                        */
  1646.    {
  1647.    temp = pop();
  1648.    if (temp != 0.0)
  1649.       push(1.0/temp);
  1650.    else
  1651.       error(19);
  1652.    }
  1653.  
  1654. else if (!strcmp(str,"rev"))                /* &rev                          */
  1655.    angle_factor = PI+PI;
  1656.  
  1657. else if (!strcmp(str,"root"))               /* &root                         */
  1658.    {
  1659.    temp = pop();
  1660.    temp2 = pop();
  1661.    error_flag = (temp==0.0) ||
  1662.       ((temp2==0.0) && (temp<=0.0)) ||
  1663.       ((temp2<0) &&
  1664.       ((1.0/temp)!=Round(1.0/temp)));
  1665.    if (!error_flag)
  1666.       push(pow(temp2, 1.0/temp));
  1667.    else
  1668.       error(27);
  1669.    }
  1670.  
  1671. else if (!strcmp(str,"rot"))                /* &rot                          */
  1672.    {
  1673.    temp = pop();
  1674.    temp2 = pop();
  1675.    temp3 = pop();
  1676.    push(temp2);
  1677.    push(temp);
  1678.    push(temp3);
  1679.    }
  1680.  
  1681. else if (!strcmp(str,"Round"))              /* &Round                        */
  1682.    push((double)Round(pop()));
  1683.  
  1684. else if (!strcmp(str,"r>d"))                /* &r>d                          */
  1685.    push(pop()*180.0/PI);
  1686.  
  1687. else if (!strcmp(str,"r>p"))                /* &r>p                          */
  1688.    {
  1689.    temp = pop();
  1690.    temp2 = pop();
  1691.    push(atan2(temp2,temp)/angle_factor);
  1692.    push(sqrt(temp*temp + temp2*temp2));
  1693.    }
  1694.  
  1695. else if (!strcmp(str,"sci"))                /* &sci                          */
  1696.    {
  1697.    display_mode = 1;
  1698.    display_digits = Round(pop());
  1699.    }
  1700.  
  1701. else if (!strcmp(str,"sec"))                /* &sec                          */
  1702.    {
  1703.    t = time(NULL);
  1704.    systime = localtime(&t);
  1705.    push((double)systime->tm_sec);
  1706.    }
  1707.  
  1708. else if (!strcmp(str,"seed"))               /* &seed                         */
  1709.    srand(Round(pop()));
  1710.  
  1711. else if (!strcmp(str,"shl"))                /* &shl                          */
  1712.    {
  1713.    itemp = Round(pop());
  1714.    itemp2 = Round(pop());
  1715.    push((double)(itemp2 << itemp));
  1716.    }
  1717.  
  1718. else if (!strcmp(str,"shr"))                /* &shr                          */
  1719.    {
  1720.    itemp = Round(pop());
  1721.    itemp2 = Round(pop());
  1722.    push((double)(itemp2 >> itemp));
  1723.    }
  1724.  
  1725. else if (!strcmp(str,"sin"))                /* &sin                          */
  1726.    push(sin(pop()*angle_factor));
  1727.  
  1728. else if (!strcmp(str,"sinh"))               /* &sinh                         */
  1729.    push(sinh(pop()));
  1730.  
  1731. else if (!strcmp(str,"sqr"))                /* &sqr                          */
  1732.    {
  1733.    temp = pop();
  1734.    push(temp*temp);
  1735.    }
  1736.  
  1737. else if (!strcmp(str,"sqrt"))               /* &sqrt                         */
  1738.    {
  1739.    temp = pop();
  1740.    if (temp >= 0.0)
  1741.       push(sqrt(temp));
  1742.    else
  1743.       error(20);
  1744.    }
  1745.  
  1746. else if (!strcmp(str,"sto"))                /* &sto                          */
  1747.    {
  1748.    itemp = Round(pop());
  1749.    if ((itemp>=0) && (itemp<ARRAYSIZE))
  1750.       array[itemp] = pop();
  1751.    else
  1752.       error(25);
  1753.    }
  1754.  
  1755. else if (!strcmp(str,"swap"))               /* &swap                         */
  1756.    {
  1757.    temp = pop();
  1758.    temp2 = pop();
  1759.    push(temp);
  1760.    push(temp2);
  1761.    }
  1762.  
  1763. else if (!strcmp(str,"tan"))                /* &tan                          */
  1764.    push(tan(pop()*angle_factor));
  1765.  
  1766. else if (!strcmp(str,"tanh"))               /* &tanh                         */
  1767.    push(tanh(pop()));
  1768.  
  1769. else if (!strcmp(str,"time"))               /* &time                         */
  1770.    push((double)time(NULL));
  1771.  
  1772. else if (!strcmp(str,"tuck"))               /* &tuck                         */
  1773.    {
  1774.    temp = pop();
  1775.    temp2 = pop();
  1776.    push(temp);
  1777.    push(temp2);
  1778.    push(temp);
  1779.    }
  1780.  
  1781. else if (!strcmp(str,"twopi"))              /* &twopi                           */
  1782.    push(PI+PI);
  1783.  
  1784. else if (!strcmp(str,"ver"))                /* &ver                          */
  1785.    push(VERSION);
  1786.  
  1787. else if (!strcmp(str,"width"))              /* &width                        */
  1788.    display_width = Round(pop());
  1789.  
  1790. else if (!strcmp(str,"wsize"))              /* &wsize                        */
  1791.    {
  1792.    if ((wordsize >= 1) && (wordsize <= 32))
  1793.       wordsize = Round(pop());
  1794.    else
  1795.       error(22);
  1796.    }
  1797.  
  1798. else if (!strcmp(str,"xor"))                /* &xor                          */
  1799.    {
  1800.    itemp = Round(pop());
  1801.    itemp2 = Round(pop());
  1802.    push((double)(itemp ^ itemp2));
  1803.    }
  1804.  
  1805. else if (!strcmp(str,"y2x"))                /* &y2x                          */
  1806.    {
  1807.    temp = pop();
  1808.    push(pop()*pow(2.0,temp));
  1809.    }
  1810.  
  1811. else if (!strcmp(str,"year"))               /* &year                         */
  1812.    {
  1813.    t = time(NULL);
  1814.    systime = localtime(&t);
  1815.    push((double)(systime->tm_year+1900));
  1816.    }
  1817.  
  1818. else if (!strcmp(str,"?hex"))               /* &?hex                         */
  1819.    {
  1820.    fgets(instr, 25, stdin);                 /*         read as a string      */
  1821.    chomp(instr);                            /*         remove \n             */
  1822.    sscanf(instr, "%lx", &itemp);            /*         read number           */
  1823.    push((double)itemp);
  1824.    }
  1825.  
  1826. else if (!strcmp(str,"?oct"))               /* &?oct                         */
  1827.    {
  1828.    fgets(instr, 25, stdin);                 /*         read as a string      */
  1829.    chomp(instr);                            /*         remove \n             */
  1830.    sscanf(instr, "%lo", &itemp);            /*         read number           */
  1831.    push((double)itemp);
  1832.    }
  1833.  
  1834. else if (!strcmp(str,"!dec"))               /* &!dec                         */
  1835.    {
  1836.    sprintf(format_str, "%%%d.",
  1837.       display_width);
  1838.    sprintf(temp_str,"%dd",display_width);
  1839.    strcat(format_str,temp_str);
  1840.    printf(format_str,
  1841.          (long)pop());
  1842.    }
  1843.  
  1844. else if (!strcmp(str,"!hex"))               /* &!hex                         */
  1845.    {
  1846.    octhex_digits = ((wordsize-1)/4)+1;
  1847.    if (wordsize == 32)
  1848.       octhex_mask = 0xFFFFFFFF;
  1849.    else
  1850.       octhex_mask = (1L << wordsize) - 1;
  1851.    sprintf(format_str, "%%%d.",
  1852.       octhex_digits);
  1853.    sprintf(temp_str,"%dX",octhex_digits);
  1854.    strcat(format_str,temp_str);
  1855.    printf(format_str,
  1856.          (long)pop() & octhex_mask);
  1857.    }
  1858.  
  1859. else if (!strcmp(str,"!oct"))               /* &!oct                         */
  1860.    {
  1861.    octhex_digits = ((wordsize-1)/3)+1;
  1862.    if (wordsize == 32)
  1863.       octhex_mask = 0xFFFFFFFF;
  1864.    else
  1865.       octhex_mask = (1L << wordsize) - 1;
  1866.    sprintf(format_str, "%%%d.",
  1867.       octhex_digits);
  1868.    sprintf(temp_str,"%do",octhex_digits);
  1869.    strcat(format_str,temp_str);
  1870.    printf(format_str,
  1871.          (long)pop() & octhex_mask);
  1872.    }
  1873.  
  1874. else if (!strcmp(str,"!stk"))               /* &!stk                         */
  1875.    {
  1876.    sprintf(format_str, "%%%d.",             /*         create format string  */
  1877.       display_width);
  1878.    sprintf(temp_str, "%d",
  1879.       display_digits);
  1880.    strcat(format_str,temp_str);
  1881.    if (display_mode == 0)                   /*         if fixed mode         */
  1882.       strcat(format_str,"f\n");
  1883.    else if (display_mode == 1)              /*         if sci mode           */
  1884.       strcat(format_str,"E\n");
  1885.    else                                     /*         if general mode       */
  1886.       strcat(format_str,"G\n");
  1887.    if (sp < 0)
  1888.       printf("Stack empty");
  1889.    else
  1890.       for (i=0; i<=sp; i++)
  1891.          printf(format_str, stack[i]);
  1892.    }
  1893.  
  1894. else
  1895.    error(29);
  1896. }
  1897.  
  1898.  
  1899.  
  1900.  
  1901.  
  1902. /*****************************************************************************/
  1903. /*  chomp()                                                                  */
  1904. /*                                                                           */
  1905. /*  Remove final \n from end of string.                                      */
  1906. /*****************************************************************************/
  1907.  
  1908. void chomp (char *str)
  1909. {
  1910. int  len;                                   /* length of str (incl \n)       */
  1911.  
  1912. len = strlen (str);                         /* get length of str incl \n     */
  1913. if (str[len-1] == '\n')                     /* if final char is \n ..        */
  1914.    str[len-1] = '\0';                       /* ..then remove it              */
  1915. }
  1916.  
  1917.  
  1918.  
  1919.  
  1920.  
  1921. /*****************************************************************************/
  1922. /*                                                                           */
  1923. /*  Int()                                                                    */
  1924. /*                                                                           */
  1925. /*****************************************************************************/
  1926.  
  1927. double Int (double f)
  1928. {
  1929. return ((long)(f));
  1930. }
  1931.  
  1932.  
  1933.  
  1934.  
  1935.  
  1936. /*****************************************************************************/
  1937. /*                                                                           */
  1938. /*  Frac()                                                                   */
  1939. /*                                                                           */
  1940. /*****************************************************************************/
  1941.  
  1942. double Frac (double f)
  1943. {
  1944. return (f - (long)(f));
  1945. }
  1946.  
  1947.  
  1948.  
  1949.  
  1950.  
  1951. /*****************************************************************************/
  1952. /*                                                                           */
  1953. /*  Round()                                                                  */
  1954. /*                                                                           */
  1955. /*  Round a double to the nearest integer.                                   */
  1956. /*                                                                           */
  1957. /*****************************************************************************/
  1958.  
  1959. int Round(double x) {
  1960. int result;
  1961.  
  1962. if (x < 0.0)
  1963.    result = (int)(x-0.5);
  1964. else
  1965.    result = (int)(x+0.5);
  1966. return result;
  1967. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement