home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / monitor / expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-24  |  9.3 KB  |  589 lines

  1. # include    <ingres.h>
  2. # include    <sccs.h>
  3.  
  4. SCCSID(@(#)expr.c    8.1    12/31/84)
  5.  
  6.  
  7.  
  8. /*
  9. **  EXPR -- evaluate expression
  10. **
  11. **    This module evaluates an expression in somewhat standard
  12. **    infix notation.  Several restrictions apply.  There are
  13. **    no variables, since this can be simulated with the macro
  14. **    processor.  No numeric overflow is checked.  There may be
  15. **    no spaces, tabs, or newlines in the expression.
  16. **
  17. **    The text of the expression is read from 'macgetch', so
  18. **    that must be initialized before calling this routine.
  19. **
  20. **    Operators accepted are + - * / < > >= <= = != % ( )
  21. **    & |.
  22. **    Operands may be signed integers.
  23. **    Standard precedence applies.
  24. **
  25. **    An expression can be viewed as a sequence of operands,
  26. **    and operators.  If the terminator is considered to be
  27. **    an operator, then the sequence must be composed
  28. **     of n matched pairs of operators and operands.  NOT and
  29. **    Negation are considered to be part of the operand and
  30. **    are treated as such.  Thus to evaluate an expression,
  31. **    n pairs are read until the terminator is found as the
  32. **    last operator.
  33. **
  34. **    Parameters:
  35. **        none
  36. **
  37. **    Returns:
  38. **        value of the expression.  Undetermined value
  39. **        on error.
  40. **
  41. **    Side Effects:
  42. **        Macro processing can occur.
  43. **
  44. **    Trace Flags:
  45. **        none
  46. */
  47.  
  48.  
  49.  
  50. # undef        STACKSIZE
  51. # define     STACKSIZE       50
  52. # define    RIGHTP        21
  53. # define    END        22
  54. # define    SEPERATOR    0
  55. # define    OR        1
  56. # define    AND        2
  57. # define    EQUALS        3
  58. # define    NEQ        4
  59. # define    LESS        5
  60. # define    LEQ        6
  61. # define    GREATER        7
  62. # define    GEQ        8
  63. # define    ADD        9
  64. # define     SUBTRACT    10
  65. # define    MULTIPLY    11
  66. # define    DIVIDE        12
  67. # define    MOD        13
  68.  
  69.  
  70. int     ExprPrec[] =            /* Precedence table */
  71. {
  72.     0,    /* filler */
  73.     1,    /* 1 -- OR */
  74.     2,    /* 2 -- AND */
  75.     3,    /* 3 -- EQUALS */
  76.     3,    /* 4 -- NEQ */
  77.     4,    /* 5 -- LESS */
  78.     4,    /* 6 -- LEQ */
  79.     4,    /* 7 -- GREATER */
  80.     4,    /* 8 -- GEQ */
  81.     5,    /* 9 -- ADD */
  82.     5,    /* 10 -- SUBTRACT */
  83.     6,    /* 11 -- MULTIPLY */
  84.     6,    /* 12 -- DIVIDE */
  85.     6    /* 13 -- MOD */
  86. };
  87.  
  88.  
  89. int    ExprNstack[STACKSIZE];
  90. int    *ExprNptr;
  91. int    ExprOstack[STACKSIZE];
  92. int    *ExprOptr;
  93. int    ExprError;
  94. char    ExprPeek;
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106. expr()
  107. {
  108.     ExprNptr = ExprNstack;
  109.     ExprOptr = ExprOstack;
  110.     ExprError = FALSE;
  111.     ExprPeek = -1;
  112.     return(valof(END));
  113. }
  114. /*
  115. **  VALOF -- compute value of expression
  116. **
  117. **    This is the real expression processor.  It handles sequencing
  118. **    and precedence.
  119. **
  120. **    Parameters:
  121. **        terminator -- the symbol which should terminate
  122. **            the expression.
  123. **
  124. **    Returns:
  125. **        The value of the expression.
  126. **
  127. **    Side Effects:
  128. **        Gobbles input.
  129. **
  130. **    Requires:
  131. **        exprfind -- to read operands.
  132. **        opfind -- to read operators.
  133. **        exp_op -- to perform operations.
  134. **
  135. **    Called By:
  136. **        expr
  137. **
  138. **    Diagnostics:
  139. **        Extra Parenthesis found: assumed typo
  140. **            An unmatched right parenthesis was read.
  141. **            It was thrown away.
  142. **        Insufficient parenthesis found: assumed zero.
  143. **            An unmatched left parenthesis was left
  144. **            in the operator stack at the end of the
  145. **            expression.  The value zero was taken
  146. **            for the expression.
  147. **
  148. **    Syserrs:
  149. **        none
  150. */
  151.  
  152. valof(terminator)
  153. int    terminator;
  154. {
  155.     register int    number;
  156.     register int    operator;
  157.  
  158.     pushop(SEPERATOR);        /* initialize the stack */
  159.  
  160.     for(;;)
  161.     {
  162.         number = exprfind();
  163.         if (ExprError) 
  164.             return(0);
  165.         operator = opfind();
  166.         if (ExprError)
  167.             return(0);
  168.  
  169.         if (operator == RIGHTP || operator == END)
  170.             break;
  171.  
  172.         /* Do all previous operations with a higher precedence */
  173.         while (ExprPrec[operator] <= ExprPrec[ExprOptr[-1]])    
  174.             number = exp_op(popop(), popnum(), number);
  175.         pushop(operator);
  176.         pushnum(number);
  177.     }
  178.     if (operator != terminator)        /* ExprError in operators */
  179.         if (operator == RIGHTP)
  180.             printf("Extra parenthesis found: assumed typo.\n");
  181.         else
  182.         {
  183.             ExprError = TRUE;
  184.             printf("Insufficient parenthesis found: Assumed zero.\n");
  185.             return(0);
  186.         }
  187.     /* Empty stack for this call of valof */
  188.     while ((operator = popop()) != SEPERATOR)
  189.         number = exp_op(operator, popnum(), number);
  190.  
  191.     return(number);
  192. }
  193. /*
  194. **  EXPRFIND -- find and chomp operand
  195. **
  196. **    This routine reads the next operand.  It generally just
  197. **    reads numbers, except it also knows about unary operators
  198. **    ! and - (where it calls itself recursively), and paren-
  199. **    theses (where it calls valof recursively).
  200. **
  201. **    Parameters:
  202. **        none
  203. **
  204. **    Returns:
  205. **        value of operand.
  206. **
  207. **    Side Effects:
  208. **        Gobbles input.
  209. **
  210. **    Requires:
  211. **        numberget -- to read numbers.
  212. **        exprgch.
  213. **
  214. **    Called By:
  215. **        valof
  216. **        exprfind (recursively)
  217. **
  218. **    Trace Flags:
  219. **        none
  220. **
  221. **    Diagnostics:
  222. **        Expression expected: end of expression found.
  223. **            Nothing was found.  Zero is returned.
  224. **        Expression expected: %c found; assumed zero.
  225. **            A syntax error -- nothing was found
  226. **            which was acceptable.
  227. */
  228.  
  229.  
  230.  
  231. exprfind()
  232. {
  233.     register int    result;
  234.     register int    c;
  235.  
  236.     c = exprgch();
  237.  
  238.     switch(c)
  239.     {
  240.  
  241.       case '0':
  242.       case '1':
  243.       case '2':
  244.       case '3':
  245.       case '4':
  246.       case '5':
  247.       case '6':
  248.       case '7':
  249.       case '8':
  250.       case '9':
  251.         return(numberget(c));
  252.  
  253.       case '!':
  254.         result = exprfind();
  255.         return(ExprError ? 0 : (result <= 0));
  256.  
  257.       case '-':
  258.         result = exprfind();
  259.         return(ExprError ? 0 : -result);
  260.  
  261.       case '(':
  262.         return(valof(RIGHTP));
  263.  
  264.       case ' ':
  265.       case '\n':
  266.       case '\t':
  267.       case '\0':
  268.         printf("Expression expected: end of expression found.\n");
  269.         ExprError = TRUE;
  270.         return(0);
  271.  
  272.       default:
  273.         printf("Expression expected; '%c' found: Assumed zero.\n", c);
  274.         ExprError = TRUE;
  275.         return(0);
  276.     }
  277. }
  278. /*
  279. **  OPFIND -- find and translate operator
  280. **
  281. **    This reads the next operator from the input stream and
  282. **    returns the internal code for it.
  283. **
  284. **    Parameters:
  285. **        none
  286. **
  287. **    Returns:
  288. **        The code for the next operator.
  289. **        Zero on error.
  290. **
  291. **    Side Effects:
  292. **        Gobbles input.
  293. **
  294. **    Requires:
  295. **        exprgch.
  296. **
  297. **    Called By:
  298. **        valof
  299. **
  300. **    Trace Flags:
  301. **        none
  302. **
  303. **    Diagnostics:
  304. **        Operator expected: '%c' found.
  305. **            Gibberish in input.
  306. */
  307.  
  308. opfind()
  309. {
  310.     register int    c;
  311.  
  312.     c = exprgch();
  313.  
  314.     switch(c)
  315.     {
  316.       
  317.       case '/':
  318.         return(DIVIDE);
  319.  
  320.       case '=':
  321.         return(EQUALS);
  322.  
  323.       case  '&':
  324.         return(AND);
  325.  
  326.       case '|':
  327.         return(OR);
  328.  
  329.       case '+':
  330.         return(ADD);
  331.  
  332.       case '-':
  333.         return(SUBTRACT);
  334.  
  335.       case '*':
  336.         return(MULTIPLY);
  337.  
  338.       case '<':
  339.         c = exprgch();
  340.         if (c == '=')
  341.         {
  342.             return(LEQ);
  343.         }
  344.         ExprPeek = c;
  345.         return(LESS);
  346.  
  347.       case '>':
  348.         c = exprgch();
  349.         if (c == '=')
  350.         {
  351.             return(GEQ);
  352.         }
  353.         ExprPeek = c;
  354.         return(GREATER);
  355.  
  356.       case '%':
  357.         return(MOD);
  358.  
  359.       case '!':
  360.         c = exprgch();
  361.         if (c == '=')
  362.         {
  363.             return(NEQ);
  364.         }
  365.         else
  366.         {
  367.             printf("Operator expected: '!%c' found.\n", c);
  368.             ExprError = TRUE;
  369.             return(0);
  370.         }
  371.  
  372.       case ')':
  373.         return(RIGHTP);
  374.  
  375.       case ' ':
  376.         case '\t':
  377.       case '\n':
  378.       case '\0':
  379.         return(END);
  380.  
  381.       default:
  382.         printf("Operator expected: '%c' found.\n", c);
  383.         ExprError = TRUE;
  384.         return(0);
  385.         
  386.     }
  387. }
  388. /*
  389. **  EXP_OP -- perform operation
  390. **
  391. **    Performs an operation between two values.
  392. **
  393. **    Parameters:
  394. **        op -- the operation to perform.
  395. **        lv -- the left operand.
  396. **        rv -- the right operand.
  397. **
  398. **    Returns:
  399. **        The value of the operation.
  400. **
  401. **    Side Effects:
  402. **        none
  403. **
  404. **    Requires:
  405. **        none
  406. **
  407. **    Called By:
  408. **        valof.
  409. **
  410. **    Trace Flags:
  411. **        none
  412. **
  413. **    Diagnostics:
  414. **        none
  415. */
  416.  
  417. exp_op(op, lv, rv)
  418. int    op;
  419. int    lv;
  420. int    rv;
  421. {
  422.     switch(op)
  423.     {
  424.  
  425.       case OR:
  426.         return((lv > 0) || (rv > 0));
  427.  
  428.       case AND:
  429.         return((lv > 0) && (rv > 0));
  430.  
  431.       case EQUALS:
  432.         return(lv == rv);
  433.  
  434.       case NEQ:
  435.         return(lv != rv);
  436.  
  437.       case LESS:
  438.         return(lv < rv);
  439.  
  440.       case LEQ:
  441.         return(lv <= rv);
  442.  
  443.       case GREATER:
  444.         return(lv > rv);
  445.  
  446.       case GEQ:
  447.         return(lv >= rv);
  448.  
  449.       case ADD:
  450.         return(lv + rv);
  451.  
  452.       case SUBTRACT:
  453.         return(lv - rv);
  454.  
  455.       case MULTIPLY:
  456.         return(lv * rv);
  457.  
  458.       case DIVIDE:
  459.         if (rv == 0) 
  460.         {
  461.             printf("Divide by zero: zero assumed.\n");
  462.             return(0);
  463.         }
  464.         else
  465.             return(lv / rv);
  466.  
  467.       case MOD:
  468.         return(lv % rv);
  469.  
  470.       default:
  471.         syserr("exp_op: bad op %d", op);
  472.  
  473.     }
  474. }
  475. /*
  476. **  NUMBERGET -- read and convert a number
  477. **
  478. **    Reads and converts a signed integer.
  479. **
  480. **    Parameters:
  481. **        none
  482. **
  483. **    Returns:
  484. **        The next number in the input stream.
  485. **
  486. **    Side Effects:
  487. **        Gobbles input.
  488. **
  489. **    Requires:
  490. **        exprgch.
  491. **
  492. **    Called By:
  493. **        exprfind.
  494. */
  495.  
  496. numberget(cx)
  497. char    cx;
  498. {
  499.     register int    result;
  500.     register int    c;
  501.  
  502.     c = cx;
  503.  
  504.     result = 0;
  505.     do
  506.     {
  507.         result = result * 10 + c - '0';
  508.         c = exprgch();
  509.     } while (c >= '0' && c <= '9');
  510.     ExprPeek = c;
  511.     return(result);
  512. }
  513. /*
  514. **  EXPRGCH -- expression character get
  515. **
  516. **    Gets the next character from the expression input.  Takes
  517. **    a character out of ExprPeek first.  Also maps spaces, tabs,
  518. **    and newlines into zero bytes.
  519. **
  520. **    Parameters:
  521. **        none
  522. **
  523. **    Returns:
  524. **        Next character.
  525. **
  526. **    Side Effects:
  527. **        Gobbles input.
  528. **        Clears ExprPeek if set.
  529. **
  530. **    Requires:
  531. **        ExprPeek -- the peek character.
  532. **        macgetch -- to get the next character if ExprPeek
  533. **            is not set.
  534. */
  535.  
  536. exprgch()
  537. {
  538.     register int    c;
  539.  
  540.     c = ExprPeek;
  541.     if (c < 0)
  542.         c = macgetch();
  543.     ExprPeek = -1;
  544.     if (c == ' ' || c == '\n' || c == '\t')
  545.         c = 0;
  546.     return (c);
  547. }
  548. /*
  549. **  Stack operations.
  550. */
  551.  
  552.  
  553. /* Popop returns the top of the operator stack and decrements this stack. */
  554. popop()
  555. {
  556.     if (ExprOptr <= ExprOstack)
  557.         syserr("popop: underflow");
  558.     return(*--ExprOptr);
  559. }
  560.  
  561.  
  562.  
  563. /* Pushop increments the stack pointer and pushes op on the stack. */
  564. pushop(op)
  565. int    op;
  566. {
  567.     *ExprOptr++ = op;
  568. }
  569.  
  570.  
  571.  
  572. /* Popnum returns the top of the number stack and decrements the stack pointer. */
  573. popnum()
  574. {
  575.     if (ExprNptr <= ExprNstack)
  576.         syserr("popnum: underflow");
  577.     return(*--ExprNptr);
  578. }
  579.  
  580.  
  581.  
  582.  
  583. /* Pushnum increments the stack pointer and pushes num onto the stack */
  584. pushnum(num)
  585. int     num;
  586. {
  587.     *ExprNptr++ = num;
  588. }
  589.