home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / ap / zsh / zsh-2.4 / zsh-2 / zsh-2.4.306 / src / math.c < prev    next >
C/C++ Source or Header  |  1994-04-08  |  15KB  |  898 lines

  1. /*
  2.  *
  3.  * math.c - mathematical expression evaluation
  4.  *
  5.  * This file is part of zsh, the Z shell.
  6.  *
  7.  * This software is Copyright 1992 by Paul Falstad
  8.  *
  9.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  10.  * use this software as long as: there is no monetary profit gained
  11.  * specifically from the use or reproduction of this software, it is not
  12.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  13.  * included prominently in any copy made.
  14.  *
  15.  * The author make no claims as to the fitness or correctness of this software
  16.  * for any use whatsoever, and it is provided as is. Any use of this software
  17.  * is at the user's own risk.
  18.  *
  19.  */
  20.  
  21. #include "zsh.h"
  22.  
  23. static char *ptr;
  24.  
  25. static long yyval;
  26. static LV yylval;
  27.  
  28. static int mlevel = 0;
  29.  
  30. /* != 0 means recognize unary plus, minus, etc. */
  31.  
  32. static int unary = 1;
  33.  
  34. void mathparse DCLPROTO((int));
  35.  
  36. /* LR = left-to-right associativity
  37.     RL = right-to-left associativity
  38.     BOO = short-circuiting boolean */
  39.  
  40. #define LR 0
  41. #define RL 1
  42. #define BOOL 2
  43.  
  44. #define M_INPAR 0
  45. #define M_OUTPAR 1
  46. #define NOT 2
  47. #define COMP 3
  48. #define POSTPLUS 4
  49. #define POSTMINUS 5
  50. #define UPLUS 6
  51. #define UMINUS 7
  52. #define AND 8
  53. #define XOR 9
  54. #define OR 10
  55. #define MUL 11
  56. #define DIV 12
  57. #define MOD 13
  58. #define PLUS 14
  59. #define MINUS 15
  60. #define SHLEFT 16
  61. #define SHRIGHT 17
  62. #define LES 18
  63. #define LEQ 19
  64. #define GRE 20
  65. #define GEQ 21
  66. #define DEQ 22
  67. #define NEQ 23
  68. #define DAND 24
  69. #define DOR 25
  70. #define DXOR 26
  71. #define QUEST 27
  72. #define COLON 28
  73. #define EQ 29
  74. #define PLUSEQ 30
  75. #define MINUSEQ 31
  76. #define MULEQ 32
  77. #define DIVEQ 33
  78. #define MODEQ 34
  79. #define ANDEQ 35
  80. #define XOREQ 36
  81. #define OREQ 37
  82. #define SHLEFTEQ 38
  83. #define SHRIGHTEQ 39
  84. #define DANDEQ 40
  85. #define DOREQ 41
  86. #define DXOREQ 42
  87. #define COMMA 43
  88. #define EOI 44
  89. #define PREPLUS 45
  90. #define PREMINUS 46
  91. #define NUM 47
  92. #define ID 48
  93. #define PARAM 49
  94. #define POWER 50
  95. #define CID 51
  96. #define CPARAM 52
  97. #define POWEREQ 53
  98. #define TOKCOUNT 54
  99.  
  100. /* precedences */
  101.  
  102. static int prec[TOKCOUNT] =
  103. {
  104.     1, 137, 2, 2, 2,
  105.     2, 2, 2, 4, 5,
  106.     6, 7, 7, 7, 8,
  107.     8, 3, 3, 9, 9,
  108.     9, 9, 10, 10, 11,
  109.     12, 12, 13, 13, 14,
  110.     14, 14, 14, 14, 14,
  111.     14, 14, 14, 14, 14,
  112.     14, 14, 14, 15, 200,
  113.     2, 2, 0, 0, 0,
  114.     8, 0, 0, 14
  115. };
  116.  
  117. #define TOPPREC 15
  118. #define ARGPREC (15-1)
  119.  
  120. static int type[TOKCOUNT] =
  121. {
  122.     LR, LR, RL, RL, RL,
  123.     RL, RL, RL, LR, LR,
  124.     LR, LR, LR, LR, LR,
  125.     LR, LR, LR, LR, LR,
  126.     LR, LR, LR, LR, BOOL,
  127.     BOOL, LR, RL, RL, RL,
  128.     RL, RL, RL, RL, RL,
  129.     RL, RL, RL, RL, RL,
  130.     BOOL, BOOL, RL, RL, RL,
  131.     RL, RL, LR, LR, LR,
  132.     RL, LR, LR, RL
  133. };
  134.  
  135. #define LVCOUNT 32
  136.  
  137. /* list of lvalues (variables) */
  138.  
  139. static int lvc;
  140. static char *lvals[LVCOUNT];
  141.  
  142. int zzlex()
  143. {                /**/
  144.     int cct = 0;
  145.  
  146.     for (;; cct = 0)
  147.     switch (*ptr++) {
  148.     case '+':
  149.         if (*ptr == '+' && (unary || !ialnum(*ptr))) {
  150.         ptr++;
  151.         return (unary) ? PREPLUS : POSTPLUS;
  152.         }
  153.         if (*ptr == '=') {
  154.         unary = 1;
  155.         ptr++;
  156.         return PLUSEQ;
  157.         }
  158.         return (unary) ? UPLUS : PLUS;
  159.     case '-':
  160.         if (*ptr == '-' && (unary || !ialnum(*ptr))) {
  161.         ptr++;
  162.         return (unary) ? PREMINUS : POSTMINUS;
  163.         }
  164.         if (*ptr == '=') {
  165.         unary = 1;
  166.         ptr++;
  167.         return MINUSEQ;
  168.         }
  169.         return (unary) ? UMINUS : MINUS;
  170.     case '(':
  171.         unary = 1;
  172.         return M_INPAR;
  173.     case ')':
  174.         return M_OUTPAR;
  175.     case '!':
  176.         if (*ptr == '=') {
  177.         unary = 1;
  178.         ptr++;
  179.         return NEQ;
  180.         }
  181.         return NOT;
  182.     case '~':
  183.         return COMP;
  184.     case '&':
  185.         unary = 1;
  186.         if (*ptr == '&') {
  187.         if (*++ptr == '=') {
  188.             ptr++;
  189.             return DANDEQ;
  190.         }
  191.         return DAND;
  192.         } else if (*ptr == '=') {
  193.         ptr++;
  194.         return ANDEQ;
  195.         }
  196.         return AND;
  197.     case '|':
  198.         unary = 1;
  199.         if (*ptr == '|') {
  200.         if (*++ptr == '=') {
  201.             ptr++;
  202.             return DOREQ;
  203.         }
  204.         return DOR;
  205.         } else if (*ptr == '=') {
  206.         ptr++;
  207.         return OREQ;
  208.         }
  209.         return OR;
  210.     case '^':
  211.         unary = 1;
  212.         if (*ptr == '^') {
  213.         if (*++ptr == '=') {
  214.             ptr++;
  215.             return DXOREQ;
  216.         }
  217.         return DXOR;
  218.         } else if (*ptr == '=') {
  219.         ptr++;
  220.         return XOREQ;
  221.         }
  222.         return XOR;
  223.     case '*':
  224.         unary = 1;
  225.         if (*ptr == '*') {
  226.         if (*++ptr == '=') {
  227.             ptr++;
  228.             return POWEREQ;
  229.         }
  230.         return POWER;
  231.         }
  232.         if (*ptr == '=') {
  233.         ptr++;
  234.         return MULEQ;
  235.         }
  236.         return MUL;
  237.     case '/':
  238.         unary = 1;
  239.         if (*ptr == '=') {
  240.         ptr++;
  241.         return DIVEQ;
  242.         }
  243.         return DIV;
  244.     case '%':
  245.         unary = 1;
  246.         if (*ptr == '=') {
  247.         ptr++;
  248.         return MODEQ;
  249.         }
  250.         return MOD;
  251.     case '<':
  252.         unary = 1;
  253.         if (*ptr == '<') {
  254.         if (*++ptr == '=') {
  255.             ptr++;
  256.             return SHLEFTEQ;
  257.         }
  258.         return SHLEFT;
  259.         } else if (*ptr == '=') {
  260.         ptr++;
  261.         return LEQ;
  262.         }
  263.         return LES;
  264.     case '>':
  265.         unary = 1;
  266.         if (*ptr == '>') {
  267.         if (*++ptr == '=') {
  268.             ptr++;
  269.             return SHRIGHTEQ;
  270.         }
  271.         return SHRIGHT;
  272.         } else if (*ptr == '=') {
  273.         ptr++;
  274.         return GEQ;
  275.         }
  276.         return GRE;
  277.     case '=':
  278.         unary = 1;
  279.         if (*ptr == '=') {
  280.         ptr++;
  281.         return DEQ;
  282.         }
  283.         return EQ;
  284.     case '?':
  285.         unary = 1;
  286.         return QUEST;
  287.     case ':':
  288.         unary = 1;
  289.         return COLON;
  290.     case ',':
  291.         unary = 1;
  292.         return COMMA;
  293.     case '\0':
  294.         unary = 1;
  295.         ptr--;
  296.         return EOI;
  297.     case '[':
  298.         unary = 0;
  299.         {
  300.         int base = zstrtol(ptr, &ptr, 10);
  301.  
  302.         if (*ptr == ']')
  303.             ptr++;
  304.         yyval = zstrtol(ptr, &ptr, lastbase = base);
  305.         return NUM;
  306.         }
  307.     case ' ':
  308.     case '\t':
  309.     case '\n':
  310.         break;
  311.     case '#':
  312.         if (*ptr == '\\') {
  313.         ptr++;
  314.         yyval = (long)*ptr++;
  315.         return NUM;
  316.         } else
  317.         cct = 1, *--ptr = '$', ptr++;
  318.     /* fall through */
  319.     default:
  320.         if (idigit(*--ptr)) {
  321.         unary = 0;
  322.         yyval = zstrtol(ptr, &ptr, 10);
  323.  
  324.         if (*ptr == '#') {
  325.             ptr++;
  326.             yyval = zstrtol(ptr, &ptr, lastbase = yyval);
  327.         }
  328.         return NUM;
  329.         }
  330.         if (iident(*ptr)) {
  331.         char *p, q;
  332.  
  333.         p = ptr;
  334.         if (lvc == LVCOUNT) {
  335.             zerr("too many identifiers (complain to author)", NULL, 0);
  336.             return EOI;
  337.         }
  338.         unary = 0;
  339.         while (iident(*++ptr));
  340.         q = *ptr;
  341.         *ptr = '\0';
  342.         lvals[yylval = lvc++] = ztrdup(p);
  343.         *ptr = q;
  344.         return cct ? CID : ID;
  345.         } else if (*ptr == '$') {
  346.         char *p, t;
  347.         int l;
  348.  
  349.         unary = 0;
  350.  
  351.         if (lvc == LVCOUNT) {
  352.             zerr("too many identifiers (complain to author)", NULL, 0);
  353.             return EOI;
  354.         }
  355.         p = ptr++;
  356.         *p = String;
  357.  
  358.         if (p[1] == '{') {
  359.             for (ptr++, l = 0; *ptr && (*ptr != '}' || l); ptr++) {
  360.             if (*ptr == '{')
  361.                 l++;
  362.             if (*ptr == '}')
  363.                 l--;
  364.             if (*ptr == '\\' && ptr[1])
  365.                 ptr++;
  366.             }
  367.             if (*ptr) {
  368.             ptr++;
  369.             t = *ptr;
  370.             *ptr = '\0';
  371.             lvals[yylval = lvc++] = ztrdup(p);
  372.             *ptr = t;
  373.             *p = '$';
  374.             return cct ? CPARAM : PARAM;
  375.             }
  376.             yyval = 0;
  377.             *p = '$';
  378.             return NUM;
  379.         } else if (p[1] == '(') {
  380.             for (ptr++, l = 0; *ptr && (*ptr != ')' || l); ptr++) {
  381.             if (*ptr == '(')
  382.                 l++;
  383.             if (*ptr == ')')
  384.                 l--;
  385.             if (*ptr == '\\' && ptr[1])
  386.                 ptr++;
  387.             }
  388.             if (*ptr) {
  389.             ptr++;
  390.             t = *ptr;
  391.             *ptr = '\0';
  392.             p[1] = Inpar;
  393.             ptr[-1] = Outpar;
  394.             lvals[yylval = lvc++] = ztrdup(p);
  395.             p[1] = '(';
  396.             ptr[-1] = ')';
  397.             *ptr = t;
  398.             *p = '$';
  399.             return cct ? CPARAM : PARAM;
  400.             }
  401.             yyval = 0;
  402.             *p = '$';
  403.             return NUM;
  404.         }
  405.         ptr++;
  406.         while (iident(*ptr) && *ptr != '[' &&
  407.                *ptr != ']' && *ptr != ',')
  408.             ptr++;
  409.         while (*ptr == '[') {
  410.             for (ptr++, l = 0; *ptr && (*ptr != ']' || l); ptr++) {
  411.             if (*ptr == '[')
  412.                 l++;
  413.             if (*ptr == ']')
  414.                 l--;
  415.             if (*ptr == '\\' && ptr[1])
  416.                 ptr++;
  417.             }
  418.             if (*ptr)
  419.             ptr++;
  420.         }
  421.         if (p < ptr) {
  422.             t = *ptr;
  423.             *ptr = '\0';
  424.             lvals[yylval = lvc++] = ztrdup(p);
  425.             *ptr = t;
  426.             *p = '$';
  427.             return cct ? CPARAM : PARAM;
  428.         }
  429.         yyval = 0;
  430.         *p = '$';
  431.         return NUM;
  432.         }
  433.         return EOI;
  434.     }
  435. }
  436.  
  437. /* the value stack */
  438.  
  439. #define STACKSZ 100
  440. int mtok;            /* last token */
  441. int sp = -1;            /* stack pointer */
  442. struct mathvalue {
  443.     LV lval;
  444.     long val;
  445. }
  446.  
  447. stack[STACKSZ];
  448.  
  449. SPROTO(void push, (long val, LV lval));
  450.  
  451. static void push(val, lval)
  452. long val;
  453. LV lval;
  454. {
  455.     if (sp == STACKSZ - 1)
  456.     zerr("stack overflow", NULL, 0);
  457.     else
  458.     sp++;
  459.     stack[sp].val = val;
  460.     stack[sp].lval = lval;
  461. }
  462.  
  463. long getvar(s)        /**/
  464. LV s;
  465. {
  466.     long t;
  467.  
  468.     if (!(t = getiparam(lvals[s])))
  469.     return 0;
  470.     return t;
  471. }
  472.  
  473. long getcvar(s)        /**/
  474. LV s;
  475. {
  476.     char *t;
  477.  
  478.     if (!(t = getsparam(lvals[s])))
  479.     return 0;
  480.     return (long)*t;
  481. }
  482.  
  483. long setvar(s, v)    /**/
  484. LV s;
  485. long v;
  486. {
  487.     if (s == -1 || s >= lvc) {
  488.     zerr("lvalue required", NULL, 0);
  489.     return 0;
  490.     }
  491.     if (noeval)
  492.     return v;
  493.     setiparam(lvals[s], v);
  494.     return v;
  495. }
  496.  
  497. int notzero(a)            /**/
  498. int a;
  499. {
  500.     if (a == 0) {
  501.     zerr("division by zero", NULL, 0);
  502.     return 0;
  503.     }
  504.     return 1;
  505. }
  506.  
  507. #define pop2() { b = stack[sp--].val; a = stack[sp--].val; }
  508. #define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;}
  509. #define nolval() {stack[sp].lval= -1;}
  510. #define pushv(X) { push(X,-1); }
  511. #define pop2lv() { pop2() lv = stack[sp+1].lval; }
  512. #define set(X) { push(setvar(lv,X),lv); }
  513.  
  514. void op(what)            /**/
  515. int what;
  516. {
  517.     long a, b, c;
  518.     LV lv;
  519.  
  520.     if (sp < 0) {
  521.     zerr("bad math expression: stack empty", NULL, 0);
  522.     return;
  523.     }
  524.     switch (what) {
  525.     case NOT:
  526.     stack[sp].val = !stack[sp].val;
  527.     nolval();
  528.     break;
  529.     case COMP:
  530.     stack[sp].val = ~stack[sp].val;
  531.     nolval();
  532.     break;
  533.     case POSTPLUS:
  534.     (void)setvar(stack[sp].lval, stack[sp].val + 1);
  535.     break;
  536.     case POSTMINUS:
  537.     (void)setvar(stack[sp].lval, stack[sp].val - 1);
  538.     break;
  539.     case UPLUS:
  540.     nolval();
  541.     break;
  542.     case UMINUS:
  543.     stack[sp].val = -stack[sp].val;
  544.     nolval();
  545.     break;
  546.     case AND:
  547.     pop2();
  548.     pushv(a & b);
  549.     break;
  550.     case XOR:
  551.     pop2();
  552.     pushv(a ^ b);
  553.     break;
  554.     case OR:
  555.     pop2();
  556.     pushv(a | b);
  557.     break;
  558.     case MUL:
  559.     pop2();
  560.     pushv(a * b);
  561.     break;
  562.     case DIV:
  563.     pop2();
  564.     if (notzero(b))
  565.         pushv(a / b);
  566.     break;
  567.     case MOD:
  568.     pop2();
  569.     if (notzero(b))
  570.         pushv(a % b);
  571.     break;
  572.     case PLUS:
  573.     pop2();
  574.     pushv(a + b);
  575.     break;
  576.     case MINUS:
  577.     pop2();
  578.     pushv(a - b);
  579.     break;
  580.     case SHLEFT:
  581.     pop2();
  582.     pushv(a << b);
  583.     break;
  584.     case SHRIGHT:
  585.     pop2();
  586.     pushv(a >> b);
  587.     break;
  588.     case LES:
  589.     pop2();
  590.     pushv((long)(a < b));
  591.     break;
  592.     case LEQ:
  593.     pop2();
  594.     pushv((long)(a <= b));
  595.     break;
  596.     case GRE:
  597.     pop2();
  598.     pushv((long)(a > b));
  599.     break;
  600.     case GEQ:
  601.     pop2();
  602.     pushv((long)(a >= b));
  603.     break;
  604.     case DEQ:
  605.     pop2();
  606.     pushv((long)(a == b));
  607.     break;
  608.     case NEQ:
  609.     pop2();
  610.     pushv((long)(a != b));
  611.     break;
  612.     case DAND:
  613.     pop2();
  614.     pushv((long)(a && b));
  615.     break;
  616.     case DOR:
  617.     pop2();
  618.     pushv((long)(a || b));
  619.     break;
  620.     case DXOR:
  621.     pop2();
  622.     pushv((long)((a && !b) || (!a && b)));
  623.     break;
  624.     case QUEST:
  625.     pop3();
  626.     pushv((a) ? b : c);
  627.     break;
  628.     case COLON:
  629.     break;
  630.     case EQ:
  631.     b = stack[sp].val;
  632.     sp -= 2;
  633.     lv = stack[sp + 1].lval;
  634.     set(b);
  635.     break;
  636.     case PLUSEQ:
  637.     pop2lv();
  638.     set(a + b);
  639.     break;
  640.     case MINUSEQ:
  641.     pop2lv();
  642.     set(a - b);
  643.     break;
  644.     case MULEQ:
  645.     pop2lv();
  646.     set(a * b);
  647.     break;
  648.     case DIVEQ:
  649.     pop2lv();
  650.     if (notzero(b))
  651.         set(a / b);
  652.     break;
  653.     case MODEQ:
  654.     pop2lv();
  655.     if (notzero(b))
  656.         set(a % b);
  657.     break;
  658.     case ANDEQ:
  659.     pop2lv();
  660.     set(a & b);
  661.     break;
  662.     case XOREQ:
  663.     pop2lv();
  664.     set(a ^ b);
  665.     break;
  666.     case OREQ:
  667.     pop2lv();
  668.     set(a | b);
  669.     break;
  670.     case SHLEFTEQ:
  671.     pop2lv();
  672.     set(a << b);
  673.     break;
  674.     case SHRIGHTEQ:
  675.     pop2lv();
  676.     set(a >> b);
  677.     break;
  678.     case DANDEQ:
  679.     pop2lv();
  680.     set((long)(a && b));
  681.     break;
  682.     case DOREQ:
  683.     pop2lv();
  684.     set((long)(a || b));
  685.     break;
  686.     case DXOREQ:
  687.     pop2lv();
  688.     set((long)((a && !b) || (!a && b)));
  689.     break;
  690.     case COMMA:
  691.     b = stack[sp].val;
  692.     sp -= 2;
  693.     pushv(b);
  694.     break;
  695.     case PREPLUS:
  696.     stack[sp].val = setvar(stack[sp].lval,
  697.                    stack[sp].val + 1);
  698.     break;
  699.     case PREMINUS:
  700.     stack[sp].val = setvar(stack[sp].lval,
  701.                    stack[sp].val - 1);
  702.     break;
  703.     case POWER:
  704.     pop2();
  705.     if (b < 0) {
  706.         zerr("can't handle negative exponents", NULL, 0);
  707.         return;
  708.     }
  709.     for (c = 1; b--; c *= a);
  710.     pushv(c);
  711.     break;
  712.     case POWEREQ:
  713.     pop2lv();
  714.     if (b < 0) {
  715.         zerr("can't handle negative exponents", NULL, 0);
  716.         return;
  717.     }
  718.     for (c = 1; b--; c *= a);
  719.     set(c);
  720.     break;
  721.     default:
  722.     zerr("out of integers", NULL, 0);
  723.     return;
  724.     }
  725. }
  726.  
  727. void bop(tk)            /**/
  728. int tk;
  729. {
  730.     switch (tk) {
  731.     case DAND:
  732.     case DANDEQ:
  733.     if (!stack[sp].val)
  734.         noeval++;
  735.     break;
  736.     case DOR:
  737.     case DOREQ:
  738.     if (stack[sp].val)
  739.         noeval++;
  740.     break;
  741.     };
  742. }
  743.  
  744. long mathevall(s, prek, ep)    /**/
  745. char *s;
  746. int prek;
  747. char **ep;
  748. {
  749.     int t0;
  750.     int xlastbase, xnoeval, xunary, xlvc;
  751.     char *xptr;
  752.     long xyyval;
  753.     LV xyylval;
  754.     char *xlvals[LVCOUNT];
  755.     int xmtok, xsp;
  756.     struct mathvalue xstack[STACKSZ];
  757.     long ret;
  758.  
  759.     xlastbase = xnoeval = xunary = xlvc = xyyval = xyylval = xsp = xmtok = 0;
  760.     xptr = NULL;
  761.     if (mlevel++) {
  762.     xlastbase = lastbase;
  763.     xnoeval = noeval;
  764.     xunary = unary;
  765.     xlvc = lvc;
  766.     xptr = ptr;
  767.     xyyval = yyval;
  768.     xyylval = yylval;
  769.     memcpy(xlvals, lvals, LVCOUNT * sizeof(char *));
  770.  
  771.     xmtok = mtok;
  772.     xsp = sp;
  773.     memcpy(xstack, stack, STACKSZ * sizeof(struct mathvalue));
  774.     }
  775.     lastbase = -1;
  776.     for (t0 = 0; t0 != LVCOUNT; t0++)
  777.     lvals[t0] = NULL;
  778.     lvc = 0;
  779.     ptr = s;
  780.     sp = -1;
  781.     unary = 1;
  782.     mathparse(prek);
  783.     *ep = ptr;
  784.     if (sp)
  785.     zerr("bad math expression: unbalanced stack", NULL, 0);
  786.     for (t0 = 0; t0 != lvc; t0++)
  787.     zsfree(lvals[t0]);
  788.  
  789.     ret = stack[0].val;
  790.  
  791.     if (--mlevel) {
  792.     lastbase = xlastbase;
  793.     noeval = xnoeval;
  794.     unary = xunary;
  795.     lvc = xlvc;
  796.     ptr = xptr;
  797.     yyval = xyyval;
  798.     yylval = xyylval;
  799.     memcpy(lvals, xlvals, LVCOUNT * sizeof(char *));
  800.  
  801.     sp = xsp;
  802.     mtok = xmtok;
  803.     memcpy(stack, xstack, STACKSZ * sizeof(struct mathvalue));
  804.     }
  805.     return ret;
  806. }
  807.  
  808. long matheval(s)        /**/
  809. char *s;
  810. {
  811.     char *junk;
  812.     long x;
  813.  
  814.     if (!*s)
  815.     return 0;
  816.     x = mathevall(s, TOPPREC, &junk);
  817.     if (*junk)
  818.     zerr("bad math expression: illegal character: %c", NULL, *junk);
  819.     return x;
  820. }
  821.  
  822. long mathevalarg(s, ss)        /**/
  823. char *s;
  824. char **ss;
  825. {
  826.     long x;
  827.  
  828.     x = mathevall(s, ARGPREC, ss);
  829.     if (mtok == COMMA)
  830.     (*ss)--;
  831.     return x;
  832. }
  833.  
  834. /* operator-precedence parse the string and execute */
  835.  
  836. void mathparse(pc)        /**/
  837. int pc;
  838. {
  839.     if (errflag)
  840.     return;
  841.     mtok = zzlex();
  842.     while (prec[mtok] <= pc) {
  843.     if (errflag)
  844.         return;
  845.     if (mtok == NUM)
  846.         push(yyval, -1);
  847.     else if (mtok == ID)
  848.         push(getvar(yylval), yylval);
  849.     else if (mtok == CID)
  850.         push(getcvar(yylval), yylval);
  851.     else if (mtok == PARAM) {
  852.         char *p = lvals[yylval];
  853.  
  854.         singsub(&p);
  855.         untokenize(p);
  856.         push(atol(p), -1);
  857.     } else if (mtok == CPARAM) {
  858.         char *p = lvals[yylval];
  859.  
  860.         singsub(&p);
  861.         untokenize(p);
  862.         push((long)*p, -1);
  863.     } else if (mtok == M_INPAR) {
  864.         mathparse(TOPPREC);
  865.         if (mtok != M_OUTPAR) {
  866.         if (!errflag)
  867.             zerr("')' expected", NULL, 0);
  868.         return;
  869.         }
  870.     } else if (mtok == QUEST) {
  871.         int q = stack[sp].val;
  872.  
  873.         if (!q)
  874.         noeval++;
  875.         mathparse(prec[QUEST] - 1);
  876.         if (!q)
  877.         noeval--;
  878.         else
  879.         noeval++;
  880.         mathparse(prec[QUEST]);
  881.         if (q)
  882.         noeval--;
  883.         op(QUEST);
  884.         continue;
  885.     } else {
  886.         int otok = mtok, onoeval = noeval;
  887.  
  888.         if (type[otok] == BOOL)
  889.         bop(otok);
  890.         mathparse(prec[otok] - (type[otok] != RL));
  891.         noeval = onoeval;
  892.         op(otok);
  893.         continue;
  894.     }
  895.     mtok = zzlex();
  896.     }
  897. }
  898.