home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Product / Product.zip / sc621_3.zip / src / lex.c < prev    next >
C/C++ Source or Header  |  1993-11-10  |  15KB  |  746 lines

  1. /*    SC    A Spreadsheet Calculator
  2.  *        Lexical analyser
  3.  *
  4.  *        original by James Gosling, September 1982
  5.  *        modifications by Mark Weiser and Bruce Israel,
  6.  *            University of Maryland
  7.  *
  8.  *              More mods Robert Bond, 12/86
  9.  *        More mods by Alan Silverstein, 3/88, see list of changes.
  10.  *        $Revision: 6.21 $
  11.  *
  12.  */
  13.  
  14.  
  15. #include <sys/types.h>
  16. #ifdef BSD42
  17. #include <strings.h>
  18. #else
  19. #ifndef SYSIII
  20. #include <string.h>
  21. #endif
  22. #endif
  23.  
  24. #if defined(BSD42) || defined(BSD43)
  25. #include <sys/ioctl.h>
  26. #endif 
  27.  
  28. #ifdef IEEE_MATH
  29. #include <ieeefp.h>
  30. #endif /* IEEE_MATH */
  31.  
  32. #include <curses.h>
  33. #include <signal.h>
  34. #include <setjmp.h>
  35. #include "sc.h"
  36. #include <ctype.h>
  37.  
  38. #ifdef NONOTIMEOUT
  39. #define    notimeout(a1, a2)
  40. #endif
  41.  
  42. #ifdef VMS
  43. #include "gram_tab.h"
  44. typedef union {
  45.     int ival;
  46.     double fval;
  47.     struct ent *ent;
  48.     struct enode *enode;
  49.     char *sval;
  50.     struct range_s rval;
  51. } YYSTYPE;
  52. extern YYSTYPE yylval;
  53. extern int VMS_read_raw;   /*sigh*/
  54. #else    /* VMS */
  55. #if defined(MSDOS)
  56. #include "y_tab.h"
  57. #else
  58. #include "y.tab.h"
  59. #endif /* MSDOS */
  60. #endif /* VMS */
  61.  
  62. #ifdef hpux
  63. extern YYSTYPE yylval;
  64. #endif /* hpux */
  65.  
  66. char *strtof();
  67.  
  68. jmp_buf wakeup;
  69. jmp_buf fpe_buf;
  70.  
  71. #ifdef SIGVOID
  72. void
  73. #endif
  74. fpe_trap(signo)
  75. int signo;
  76. {
  77. #if defined(i386) && !defined(M_XENIX)
  78.     asm("    fnclex");
  79.     asm("    fwait");
  80. #else
  81. #ifdef IEEE_MATH
  82.     (void)fpsetsticky((fp_except)0);    /* Clear exception */
  83. #endif /* IEEE_MATH */
  84. #ifdef PC
  85.     _fpreset();
  86. #endif
  87. #endif
  88.     longjmp(fpe_buf, 1);
  89. }
  90.  
  91. struct key {
  92.     char *key;
  93.     int val;
  94. };
  95.  
  96. struct key experres[] = {
  97. #include "experres.h"
  98.     0, 0};
  99.  
  100. struct key statres[] = {
  101. #include "statres.h"
  102.     0, 0};
  103.  
  104. int
  105. yylex ()
  106. {
  107.     register char *p = line+linelim;
  108.     int ret;
  109.     while (isspace(*p)) p++;
  110.     if (*p == '\0') ret = -1;
  111.     else if (isalpha(*p)) {
  112.     char *tokenst = p;
  113.     register tokenl;
  114.     register struct key *tblp;
  115.     tokenl = 0;
  116.     /*
  117.      * This picks up either 1 or 2 alpha characters (a column) or
  118.      * tokens with at least three leading alphas and '_' or digits
  119.      * (a function or token or command or a range name)
  120.     */
  121.     while (isalpha(*p) || ((*p == '_') || isdigit(*p)) && (tokenl > 2)) {
  122.         p++;
  123.         tokenl++;
  124.     }
  125.     if (tokenl <= 2) { /* a COL is 1 or 2 char alpha
  126.         (but not pi, ln, fv, pv, if -- this should be fixed!) */
  127.         if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') {
  128.         ret = K_PI;
  129.         } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') {
  130.         ret = K_LN;
  131.         } else if (tokenl == 2 && tokenst[0] == 'f' && tokenst[1] == 'v') {
  132.         ret = K_FV;
  133.         } else if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'v') {
  134.         ret = K_PV;
  135.         } else if (tokenl == 2 && tokenst[0] == 'i' && tokenst[1] == 'f') {
  136.         ret = K_IF;
  137.  
  138.         } else {
  139.         ret = COL;
  140.         yylval.ival = atocol (tokenst, tokenl);
  141.         }
  142.     } else {
  143.         ret = WORD;
  144.         for (tblp = linelim ? experres : statres; tblp->key; tblp++)
  145.             if (((tblp->key[0]^tokenst[0])&0137)==0
  146.              && tblp->key[tokenl]==0) {
  147.             register i = 1;
  148.             while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0)
  149.                 i++;
  150.             if (i>=tokenl) {
  151.                 ret = tblp->val;
  152.                 break;
  153.             }
  154.             }
  155.         if (ret==WORD) { 
  156.         struct range *r;
  157.         if (r = find_range(tokenst, tokenl,
  158.                    (struct ent *)0, (struct ent *)0)) {
  159.             yylval.rval.left = r->r_left;
  160.             yylval.rval.right = r->r_right;
  161.             if (r->r_is_range)
  162.                 ret = RANGE;
  163.             else
  164.             ret = VAR;
  165.         } else {
  166.             linelim = p-line;
  167.             yyerror ("Unintelligible word");
  168.         }
  169.         }
  170.     }
  171.     } else if ((*p == '.') || isdigit(*p)) {
  172. #ifdef SIGVOID
  173.     void (*sig_save)();
  174. #else
  175.     int (*sig_save)();
  176. #endif
  177.     double v = 0.0;
  178.     int temp;
  179.     char *nstart = p;
  180.  
  181.     sig_save = signal(SIGFPE, fpe_trap);
  182.     if (setjmp(fpe_buf)) {
  183.         (void) signal(SIGFPE, sig_save);
  184.         yylval.fval = v;
  185.         error("Floating point exception\n");
  186.         return FNUMBER;
  187.     }
  188.  
  189.     if (*p != '.') {
  190.         do v = v*10.0 + (double) ((unsigned) *p - '0');
  191.         while (isdigit(*++p));
  192.     }
  193.     if (*p=='.' || *p == 'e' || *p == 'E') {
  194.         ret = FNUMBER;
  195.         p = strtof(nstart, &yylval.fval);
  196.     } else {
  197.         /* A NUMBER must hold at least MAXROW and MAXCOL */
  198.         /* This is consistent with a short row and col in struct ent */
  199.         if (v > (double)32767 || v < (double)-32768) {
  200.         ret = FNUMBER;
  201.         yylval.fval = v;
  202.         } else {
  203.         temp = (int)v;
  204.         if((double)temp != v) {
  205.             ret = FNUMBER;
  206.             yylval.fval = v;
  207.         } else {
  208.             ret = NUMBER;
  209.             yylval.ival = temp;
  210.         }
  211.         }
  212.     }
  213.     (void) signal(SIGFPE, sig_save);
  214.     } else if (*p=='"') {
  215.     char *ptr;
  216.         ptr = p+1;    /* "string" or "string\"quoted\"" */
  217.         while(*ptr && ((*ptr != '"') || (*(ptr-1) == '\\')))
  218.         ptr++;
  219.         ptr = scxmalloc((unsigned)(ptr-p));
  220.     yylval.sval = ptr;
  221.     p += 1;
  222.     while (*p && ((*p != '"') || (*(p-1) == '\\')))
  223.         *ptr++ = *p++;
  224.     *ptr = 0;
  225.     if (*p)
  226.         p += 1;
  227.     ret = STRING;
  228.     } else if (*p=='[') {
  229.     while (*p && *p!=']')
  230.         p++;
  231.     if (*p)
  232.         p++;
  233.     linelim = p-line;
  234.     return yylex();
  235.     } else ret = *p++;
  236.     linelim = p-line;
  237.     return ret;
  238. }
  239.  
  240.  
  241. /*
  242.  * Given a token string starting with a symbolic column name and its valid
  243.  * length, convert column name ("A"-"Z" or "AA"-"ZZ") to a column number (0-N).
  244.  * Never mind if the column number is illegal (too high).  The procedure's name
  245.  * and function are the inverse of coltoa().
  246.  * 
  247.  * Case-insensitivity is done crudely, by ignoring the 040 bit.
  248.  */
  249.  
  250. int
  251. atocol (string, len)
  252.     char    *string;
  253.     int    len;
  254. {
  255.     register int col;
  256.  
  257.     col = (string [0] & 0137) - 'A';
  258.  
  259.     if (len == 2)        /* has second char */
  260.         col = ((col + 1) * 26) + ((string [1] & 0137) - 'A');
  261.  
  262.     return (col);
  263. }
  264.  
  265.  
  266. #ifdef SIMPLE
  267.  
  268. void
  269. initkbd()
  270. {}
  271.  
  272. void
  273. kbd_again()
  274. {}
  275.  
  276. void
  277. resetkbd()
  278. {}
  279.  
  280. #ifndef VMS
  281.  
  282. int
  283. nmgetch()
  284. {
  285.     return (toascii(getchar()));
  286. }
  287.  
  288. #else /* VMS */
  289.  
  290. int
  291. nmgetch()
  292. /*
  293.    This is not perfect, it doesn't move the cursor when goraw changes
  294.    over to deraw, but it works well enough since the whole sc package
  295.    is incredibly stable (loop constantly positions cursor).
  296.  
  297.    Question, why didn't the VMS people just implement cbreak?
  298.  
  299.    NOTE: During testing it was discovered that the DEBUGGER and curses
  300.    and this method of reading would collide (the screen was not updated
  301.    when continuing from screen mode in the debugger).
  302. */
  303. {
  304.     short c;
  305.     static int key_id=0;
  306.     int status;
  307. #define VMScheck(a) {if (~(status = (a)) & 1) VMS_MSG (status);}
  308.  
  309.     if (VMS_read_raw) {
  310.       VMScheck(smg$read_keystroke (&stdkb->_id, &c, 0, 0, 0));
  311.     }
  312.     else
  313.        c = getchar();
  314.  
  315.     switch (c) {
  316.     case SMG$K_TRM_LEFT:  c = ctl('b'); break;
  317.     case SMG$K_TRM_RIGHT: c = ctl('f'); break;
  318.     case SMG$K_TRM_UP:    c = ctl('p'); break;
  319.     case SMG$K_TRM_DOWN:  c = ctl('n'); break;
  320.     default:   c = c & A_CHARTEXT;
  321.     }
  322.     return (c);
  323. }
  324.  
  325.  
  326. VMS_MSG (status)
  327. int status;
  328. /*
  329.    Routine to put out the VMS operating system error (if one occurs).
  330. */
  331. {
  332. #include <descrip.h>
  333.    char errstr[81], buf[120];
  334.    $DESCRIPTOR(errdesc, errstr);
  335.    short int length;
  336. #define err_out(msg) fprintf (stderr,msg)
  337.  
  338. /* Check for no error or standard error */
  339.  
  340.    if (~status & 1) {
  341.       status = status & 0x8000 ? status & 0xFFFFFFF : status & 0xFFFF;
  342.       if (SYS$GETMSG(status, &length, &errdesc, 1, 0) == SS$_NORMAL) {
  343.      errstr[length] = '\0';
  344.      (void) sprintf (buf, "<0x%x> %s", status, errdesc.dsc$a_pointer);
  345.      err_out (buf);
  346.       }
  347.       else
  348.          err_out ("System error");
  349.    }
  350. }
  351. #endif /* VMS */
  352.  
  353. #else /*SIMPLE*/
  354.  
  355. #if defined(BSD42) || defined (SYSIII) || defined(BSD43)
  356.  
  357. #define N_KEY 4
  358.  
  359. struct key_map {
  360.     char *k_str;
  361.     char k_val;
  362.     char k_index;
  363. }; 
  364.  
  365. struct key_map km[N_KEY];
  366.  
  367. char keyarea[N_KEY*30];
  368.  
  369. char *tgetstr();
  370. char *getenv();
  371. char *ks;
  372. char ks_buf[20];
  373. char *ke;
  374. char ke_buf[20];
  375.  
  376. #ifdef TIOCSLTC
  377. struct ltchars old_chars, new_chars;
  378. #endif
  379.  
  380. char dont_use[] = {
  381.     ctl('['), ctl('a'), ctl('b'), ctl('c'), ctl('e'), ctl('f'), ctl('g'), ctl('h'),
  382.     ctl('i'), ctl('j'),  ctl('l'), ctl('m'), ctl('n'), ctl('p'), ctl('q'),
  383.     ctl('r'), ctl('s'), ctl('t'), ctl('u'), ctl('v'),  ctl('w'), ctl('x'),
  384.     ctl('z'), 0
  385. };
  386.  
  387. void
  388. charout(c)
  389. int c;
  390. {
  391.     (void)putchar(c);
  392. }
  393.  
  394. void
  395. initkbd()
  396. {
  397.     register struct key_map *kp;
  398.     register i,j;
  399.     char *p = keyarea;
  400.     char *ktmp;
  401.     static char buf[1024]; /* Why do I have to do this again? */
  402.  
  403.     if (!(ktmp = getenv("TERM"))) {
  404.     (void) fprintf(stderr, "TERM environment variable not set\n");
  405.     exit (1);
  406.     }
  407.     if (tgetent(buf, ktmp) <= 0)
  408.     return;
  409.  
  410.     km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl('b');
  411.     km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl('f');
  412.     km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl('p');
  413.     km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl('n');
  414.  
  415.     ktmp = tgetstr("ks",&p);
  416.     if (ktmp)  {
  417.     (void) strcpy(ks_buf, ktmp);
  418.     ks = ks_buf;
  419.     tputs(ks, 1, charout);
  420.     }
  421.     ktmp = tgetstr("ke",&p);
  422.     if (ktmp)  {
  423.     (void) strcpy(ke_buf, ktmp);
  424.     ke = ke_buf;
  425.     }
  426.  
  427.     /* Unmap arrow keys which conflict with our ctl keys   */
  428.     /* Ignore unset, longer than length 1, and 1-1 mapped keys */
  429.  
  430.     for (i = 0; i < N_KEY; i++) {
  431.     kp = &km[i];
  432.     if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val))
  433.         for (j = 0; dont_use[j] != 0; j++)
  434.             if (kp->k_str[0] == dont_use[j]) {
  435.              kp->k_str = (char *)0;
  436.              break;
  437.         }
  438.     }
  439.  
  440.  
  441. #ifdef TIOCSLTC
  442.     (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
  443.     new_chars = old_chars;
  444.     if (old_chars.t_lnextc == ctl('v'))
  445.     new_chars.t_lnextc = -1;
  446.     if (old_chars.t_rprntc == ctl('r'))
  447.     new_chars.t_rprntc = -1;
  448.     (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  449. #endif
  450. }
  451.  
  452. void
  453. kbd_again()
  454. {
  455.     if (ks) 
  456.     tputs(ks, 1, charout);
  457.  
  458. #ifdef TIOCSLTC
  459.     (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  460. #endif
  461. }
  462.  
  463. void
  464. resetkbd()
  465. {
  466.     if (ke) 
  467.     tputs(ke, 1, charout);
  468.  
  469. #ifdef TIOCSLTC
  470.     (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars);
  471. #endif
  472. }
  473.  
  474. int
  475. nmgetch() 
  476. {
  477.     register int c;
  478.     register struct key_map *kp;
  479.     register struct key_map *biggest;
  480.     register int i;
  481.     int almost;
  482.     int maybe;
  483.  
  484.     static char dumpbuf[10];
  485.     static char *dumpindex;
  486.  
  487. #ifdef SIGVOID
  488.     void time_out();
  489. #else
  490.     int time_out();
  491. #endif
  492.  
  493.     if (dumpindex && *dumpindex)
  494.         return (*dumpindex++);
  495.  
  496.     c = toascii(getchar());
  497.     biggest = 0;
  498.     almost = 0;
  499.  
  500.     for (kp = &km[0]; kp < &km[N_KEY]; kp++) {
  501.     if (!kp->k_str)
  502.         continue;
  503.     if (c == kp->k_str[kp->k_index]) {
  504.         almost = 1;
  505.         kp->k_index++;
  506.         if (kp->k_str[kp->k_index] == 0) {
  507.         c = kp->k_val;
  508.             for (kp = &km[0]; kp < &km[N_KEY]; kp++)
  509.                 kp->k_index = 0;
  510.             return(c);
  511.         }
  512.     }
  513.     if (!biggest && kp->k_index)
  514.         biggest = kp;
  515.         else if (kp->k_index && biggest->k_index < kp->k_index)
  516.         biggest = kp;
  517.     }
  518.  
  519.     if (almost) { 
  520.         (void) signal(SIGALRM, time_out);
  521.         (void) alarm(1);
  522.  
  523.     if (setjmp(wakeup) == 0) { 
  524.         maybe = nmgetch();
  525.         (void) alarm(0);
  526.         return(maybe);
  527.     }
  528.     }
  529.     
  530.     if (biggest) {
  531.     for (i = 0; i<biggest->k_index; i++) 
  532.         dumpbuf[i] = biggest->k_str[i];
  533.     if (!almost)
  534.         dumpbuf[i++] = c;
  535.     dumpbuf[i] = '\0';
  536.     dumpindex = &dumpbuf[1];
  537.     for (kp = &km[0]; kp < &km[N_KEY]; kp++)
  538.         kp->k_index = 0;
  539.     return (dumpbuf[0]);
  540.     }
  541.  
  542.     return(c);
  543. }
  544.  
  545. #endif
  546.  
  547. #if defined(SYSV2) || defined(SYSV3) || defined(MSDOS) || defined(__OS2__)
  548.  
  549. void
  550. initkbd()
  551. {
  552.     keypad(stdscr, TRUE);
  553.     notimeout(stdscr,TRUE);
  554. }
  555.  
  556. void
  557. kbd_again()
  558. {
  559.     keypad(stdscr, TRUE);
  560.     notimeout(stdscr,TRUE);
  561. }
  562.  
  563. void
  564. resetkbd()
  565. {
  566.     keypad(stdscr, FALSE);
  567.     notimeout(stdscr, FALSE);
  568. }
  569.  
  570. int
  571. nmgetch()
  572. {
  573.     register int c;
  574.  
  575.     c = wgetch(stdscr);
  576.     switch (c) {
  577. #ifdef KEY_LEFT
  578.     case KEY_LEFT:  c = ctl('b'); break;
  579. #endif
  580. #ifdef KEY_RIGHT
  581.     case KEY_RIGHT: c = ctl('f'); break;
  582. #endif
  583. #ifdef KEY_UP
  584.     case KEY_UP:    c = ctl('p'); break;
  585. #endif
  586. #ifdef KEY_DOWN
  587.     case KEY_DOWN:  c = ctl('n'); break;
  588. #endif
  589. #ifdef KEY_BACKSPACE
  590.     case KEY_BACKSPACE:  c = ctl('h'); break;
  591. #endif
  592. #ifdef KEY_NPAGE
  593.     case KEY_NPAGE:    break;
  594. #endif
  595. #ifdef KEY_PPAGE
  596.     case KEY_PPAGE:    break;
  597. #endif
  598. #ifdef KEY_HOME
  599.     case KEY_HOME:    break;
  600. #endif
  601. #ifdef KEY_DC
  602.     case KEY_DC:    c = 'x'; break;
  603. #endif
  604. #ifdef KEY_FIND
  605.     case KEY_FIND:  c = 'g'; break;
  606. #endif
  607. #ifdef KEY_HELP
  608.     case KEY_HELP:  c = '?'; break;
  609. #endif
  610. #ifdef KEY_SELECT
  611.     case KEY_SELECT:c = 'm'; break;
  612. #endif
  613. #ifdef KEY_C1
  614. /* This stuff works for a wyse wy75 in ANSI mode under 5.3.  Good luck. */
  615. /* It is supposed to map the curses keypad back to the numeric equiv. */
  616.     case KEY_C1:    c = '0'; break;
  617.     case KEY_A1:    c = '1'; break;
  618.     case KEY_B2:    c = '2'; break;
  619.     case KEY_A3:    c = '3'; break;
  620.     case KEY_F(5):  c = '4'; break;
  621.     case KEY_F(6):  c = '5'; break;
  622.     case KEY_F(7):  c = '6'; break;
  623.     case KEY_F(9):  c = '7'; break;
  624.     case KEY_F(10): c = '8'; break;
  625.     case KEY_F0:    c = '9'; break;
  626.     case KEY_C3:    c = '.'; break;
  627.     case KEY_ENTER: c = ctl('m'); break;
  628. #endif
  629.     default:        c = toascii(c); 
  630.     break;
  631.     }
  632.     return (c);
  633. }
  634.  
  635. #endif /* SYSV2 || SYSV3 */
  636.  
  637. #endif /* SIMPLE */
  638.  
  639. #ifdef SIGVOID
  640. void
  641. #else
  642. int
  643. #endif
  644. time_out(signo)
  645. int signo;
  646. {
  647.     longjmp(wakeup, 1);
  648. }
  649.  
  650. /*
  651.  * This converts a floating point number of the form
  652.  * [s]ddd[.d*][esd*]  where s can be a + or - and e is E or e.
  653.  * to floating point. 
  654.  * p is advanced.
  655.  */
  656.  
  657. char *
  658. strtof(p, res)
  659. register char *p;
  660. double *res;
  661. {
  662.     double acc;
  663.     int sign;
  664.     double fpos;
  665.     int exp;
  666.     int exps;
  667. #ifdef SIGVOID
  668.     void (*sig_save)();
  669. #else
  670.     int (*sig_save)();
  671. #endif
  672.     sig_save = signal(SIGFPE, fpe_trap);
  673.     if (setjmp(fpe_buf)) {
  674.     error("Floating point exception\n");
  675.     *res = 0.0; 
  676.         (void) signal(SIGFPE, sig_save);
  677.     return(p);
  678.     }
  679.     acc = 0.0;
  680.     sign = 1;
  681.     exp = 0;
  682.     exps = 1;
  683.     if (*p == '+')
  684.         p++;
  685.     else if (*p == '-') {
  686.         p++;
  687.         sign = -1;
  688.     }
  689.     while (isdigit(*p)) {
  690.         acc = acc * 10.0 + (double)(*p - '0');
  691.         p++;
  692.     }
  693.     if (*p == 'e' || *p == 'E') {
  694.         p++;
  695.         if (*p == '+')
  696.         p++;
  697.         else if (*p == '-') {
  698.         p++;
  699.         exps = -1;
  700.         }
  701.         while(isdigit(*p)) {
  702.         exp = exp * 10 + (*p - '0');
  703.         p++;
  704.         }
  705.     }
  706.     if (*p == '.') {
  707.     fpos = 1.0/10.0;
  708.     p++;
  709.     while(isdigit(*p)) {
  710.         acc += (*p - '0') * fpos;
  711.         fpos *= 1.0/10.0;
  712.         p++;
  713.     }
  714.     }
  715.     if (*p == 'e' || *p == 'E') {
  716.     exp = 0;
  717.     exps = 1;
  718.         p++;
  719.     if (*p == '+')
  720.         p++;
  721.     else if (*p == '-') {
  722.         p++;
  723.         exps = -1;
  724.     }
  725.     while(isdigit(*p)) {
  726.         exp = exp * 10 + (*p - '0');
  727.         p++;
  728.     }
  729.     }
  730.     if (exp) {
  731.     if (exps > 0)
  732.         while (exp--)
  733.         acc *= 10.0;
  734.     else
  735.         while (exp--)
  736.         acc *= 1.0/10.0;
  737.     }
  738.     if (sign > 0)
  739.         *res = acc;
  740.     else
  741.     *res = -acc;
  742.  
  743.     (void) signal(SIGFPE, sig_save);
  744.     return(p);
  745. }
  746.