home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d160 / m4.lha / M4 / Src / expr.c < prev    next >
C/C++ Source or Header  |  1988-10-02  |  12KB  |  560 lines

  1.  
  2. /*
  3.  *      expression evaluator: performs a standard recursive
  4.  *      descent parse to evaluate any expression permissible
  5.  *      within the following grammar:
  6.  *
  7.  *      expr    :       query EOS
  8.  *      query   :       lor
  9.  *              |       lor "?" query ":" query
  10.  *      lor     :       land { "||" land }
  11.  *      land    :       bor { "&&" bor }
  12.  *      bor     :       bxor { "|" bxor }
  13.  *      bxor    :       band { "^" band }
  14.  *      band    :       eql { "&" eql }
  15.  *      eql     :       relat { eqrel relat }
  16.  *      relat   :       shift { rel shift }
  17.  *      shift   :       primary { shop primary }
  18.  *      primary :       term { addop term }
  19.  *      term    :       unary { mulop unary }
  20.  *      unary   :       factor
  21.  *              |       unop unary
  22.  *      factor  :       constant
  23.  *              |       "(" query ")"
  24.  *      constant:       num
  25.  *              |       "'" CHAR "'"
  26.  *      num     :       DIGIT
  27.  *              |       DIGIT num
  28.  *      shop    :       "<<"
  29.  *              |       ">>"
  30.  *      eqlrel  :       "="
  31.  *              |       "=="
  32.  *              |       "!="
  33.  *      rel     :       "<"
  34.  *              |       ">"
  35.  *              |       "<="
  36.  *              |       ">="
  37.  *
  38.  *
  39.  *      This expression evaluator is lifted from a public-domain
  40.  *      C Pre-Processor included with the DECUS C Compiler distribution.
  41.  *      It is hacked somewhat to be suitable for m4.
  42.  *
  43.  *      Originally by:  Mike Lutz
  44.  *                      Bob Harper
  45.  */
  46.  
  47. #define TRUE    1
  48. #define FALSE   0
  49. #define EOS     (char) 0
  50. #define EQL     0
  51. #define NEQ     1
  52. #define LSS     2
  53. #define LEQ     3
  54. #define GTR     4
  55. #define GEQ     5
  56. #define OCTAL   8
  57. #define DECIMAL 10
  58.  
  59. static char *nxtch;     /* Parser scan pointer */
  60.  
  61. /*
  62.  * For longjmp
  63.  */
  64. #include <setjmp.h>
  65. static jmp_buf  expjump;
  66.  
  67. /*
  68.  * macros:
  69.  *
  70.  *      ungetch - Put back the last character examined.
  71.  *      getch   - return the next character from expr string.
  72.  */
  73. #define ungetch()       nxtch--
  74. #define getch()         *nxtch++
  75.  
  76. expr(expbuf)
  77. char *expbuf;
  78. {
  79.         register int rval;
  80.  
  81.         nxtch = expbuf;
  82.         if (setjmp(expjump) != 0)
  83.                 return (FALSE);
  84.         rval = query();
  85.         if (skipws() == EOS)
  86.                 return(rval);
  87.         experr("Ill-formed expression");
  88. }
  89.  
  90. /*
  91.  * query : lor | lor '?' query ':' query
  92.  *
  93.  */
  94. query()
  95. {
  96.         register int bool, true_val, false_val;
  97.  
  98.         bool = lor();
  99.         if (skipws() != '?') {
  100.                 ungetch();
  101.                 return(bool);
  102.         }
  103.  
  104.         true_val = query();
  105.         if (skipws() != ':')
  106.                 experr("Bad query");
  107.  
  108.         false_val = query();
  109.         return(bool ? true_val : false_val);
  110. }
  111.  
  112. /*
  113.  * lor : land { '||' land }
  114.  *
  115.  */
  116. lor()
  117. {
  118.         register int c, vl, vr;
  119.  
  120.         vl = land();
  121.         while ((c = skipws()) == '|' && getch() == '|') {
  122.                 vr = land();
  123.                 vl = vl || vr;
  124.         }
  125.  
  126.         if (c == '|')
  127.                 ungetch();
  128.         ungetch();
  129.         return(vl);
  130. }
  131.  
  132. /*
  133.  * land : bor { '&&' bor }
  134.  *
  135.  */
  136. land()
  137. {
  138.         register int c, vl, vr;
  139.  
  140.         vl = bor();
  141.         while ((c = skipws()) == '&' && getch() == '&') {
  142.                 vr = bor();
  143.                 vl = vl && vr;
  144.         }
  145.  
  146.         if (c == '&')
  147.                 ungetch();
  148.         ungetch();
  149.         return(vl);
  150. }
  151.  
  152. /*
  153.  * bor : bxor { '|' bxor }
  154.  *
  155.  */
  156. bor()
  157. {
  158.         register int vl, vr, c;
  159.  
  160.         vl = bxor();
  161.         while ((c = skipws()) == '|' && getch() != '|') {
  162.                 ungetch();
  163.                 vr = bxor();
  164.                 vl |= vr;
  165.         }
  166.  
  167.         if (c == '|')
  168.                 ungetch();
  169.         ungetch();
  170.         return(vl);
  171. }
  172.  
  173. /*
  174.  * bxor : band { '^' band }
  175.  *
  176.  */
  177. bxor()
  178. {
  179.         register int vl, vr;
  180.  
  181.         vl = band();
  182.         while (skipws() == '^') {
  183.                 vr = band();
  184.                 vl ^= vr;
  185.         }
  186.  
  187.         ungetch();
  188.         return(vl);
  189. }
  190.  
  191. /*
  192.  * band : eql { '&' eql }
  193.  *
  194.  */
  195. band()
  196. {
  197.         register int vl, vr, c;
  198.  
  199.         vl = eql();
  200.         while ((c = skipws()) == '&' && getch() != '&') {
  201.                 ungetch();
  202.                 vr = eql();
  203.                 vl &= vr;
  204.         }
  205.  
  206.         if (c == '&')
  207.                 ungetch();
  208.         ungetch();
  209.         return(vl);
  210. }
  211.  
  212. /*
  213.  * eql : relat { eqrel relat }
  214.  *
  215.  */
  216. eql()
  217. {
  218.         register int vl, vr, rel;
  219.  
  220.         vl = relat();
  221.         while ((rel = geteql()) != -1) {
  222.                 vr = relat();
  223.  
  224.                 switch (rel) {
  225.  
  226.                 case EQL:
  227.                         vl = (vl == vr);
  228.                         break;
  229.                 case NEQ:
  230.                         vl = (vl != vr);
  231.                         break;
  232.                 }
  233.         }
  234.         return(vl);
  235. }
  236.  
  237. /*
  238.  * relat : shift { rel shift }
  239.  *
  240.  */
  241. relat()
  242. {
  243.         register int vl, vr, rel;
  244.  
  245.         vl = shift();
  246.         while ((rel = getrel()) != -1) {
  247.  
  248.                 vr = shift();
  249.                 switch (rel) {
  250.  
  251.                 case LEQ:
  252.                         vl = (vl <= vr);
  253.                         break;
  254.                 case LSS:
  255.                         vl = (vl < vr);
  256.                         break;
  257.                 case GTR:
  258.                         vl = (vl > vr);
  259.                         break;
  260.                 case GEQ:
  261.                         vl = (vl >= vr);
  262.                         break;
  263.                 }
  264.         }
  265.         return(vl);
  266. }
  267.  
  268. /*
  269.  * shift : primary { shop primary }
  270.  *
  271.  */
  272. shift()
  273. {
  274.         register int vl, vr, c;
  275.  
  276.         vl = primary();
  277.         while (((c = skipws()) == '<' || c == '>') && c == getch()) {
  278.                 vr = primary();
  279.  
  280.                 if (c == '<')
  281.                         vl <<= vr;
  282.                 else
  283.                         vl >>= vr;
  284.         }
  285.  
  286.         if (c == '<' || c == '>')
  287.                 ungetch();
  288.         ungetch();
  289.         return(vl);
  290. }
  291.  
  292. /*
  293.  * primary : term { addop term }
  294.  *
  295.  */
  296. primary()
  297. {
  298.         register int c, vl, vr;
  299.  
  300.         vl = term();
  301.         while ((c = skipws()) == '+' || c == '-') {
  302.                 vr = term();
  303.                 if (c == '+')
  304.                         vl += vr;
  305.                 else
  306.                         vl -= vr;
  307.         }
  308.  
  309.         ungetch();
  310.         return(vl);
  311. }
  312.  
  313. /*
  314.  * <term> := <unary> { <mulop> <unary> }
  315.  *
  316.  */
  317. term()
  318. {
  319.         register int c, vl, vr;
  320.  
  321.         vl = unary();
  322.         while ((c = skipws()) == '*' || c == '/' || c == '%') {
  323.                 vr = unary();
  324.  
  325.                 switch (c) {
  326.                 case '*':
  327.                         vl *= vr;
  328.                         break;
  329.                 case '/':
  330.                         vl /= vr;
  331.                         break;
  332.                 case '%':
  333.                         vl %= vr;
  334.                         break;
  335.                 }
  336.         }
  337.         ungetch();
  338.         return(vl);
  339. }
  340.  
  341. /*
  342.  * unary : factor | unop unary
  343.  *
  344.  */
  345. unary()
  346. {
  347.         register int val, c;
  348.  
  349.         if ((c = skipws()) == '!' || c == '~' || c == '-') {
  350.                 val = unary();
  351.  
  352.                 switch (c) {
  353.                 case '!':
  354.                         return(! val);
  355.                 case '~':
  356.                         return(~ val);
  357.                 case '-':
  358.                         return(- val);
  359.                 }
  360.         }
  361.  
  362.         ungetch();
  363.         return(factor());
  364. }
  365.  
  366. /*
  367.  * factor : constant | '(' query ')'
  368.  *
  369.  */
  370. factor()
  371. {
  372.         register int val;
  373.  
  374.         if (skipws() == '(') {
  375.                 val = query();
  376.                 if (skipws() != ')')
  377.                         experr("Bad factor");
  378.                 return(val);
  379.         }
  380.  
  381.         ungetch();
  382.         return(constant());
  383. }
  384.  
  385. /*
  386.  * constant: num | 'char'
  387.  *
  388.  */
  389. constant()
  390. {
  391.         /*
  392.          * Note: constant() handles multi-byte constants
  393.          */
  394.  
  395.         register int    i;
  396.         register int    value;
  397.         register char   c;
  398.         int             v[sizeof (int)];
  399.  
  400.         if (skipws() != '\'') {
  401.                 ungetch();
  402.                 return(num());
  403.         }
  404.         for (i = 0; i < sizeof(int); i++) {
  405.                 if ((c = getch()) == '\'') {
  406.                         ungetch();
  407.                         break;
  408.                 }
  409.                 if (c == '\\') {
  410.                         switch (c = getch()) {
  411.                         case '0':
  412.                         case '1':
  413.                         case '2':
  414.                         case '3':
  415.                         case '4':
  416.                         case '5':
  417.                         case '6':
  418.                         case '7':
  419.                                 ungetch();
  420.                                 c = num();
  421.                                 break;
  422.                         case 'n':
  423.                                 c = 012;
  424.                                 break;
  425.                         case 'r':
  426.                                 c = 015;
  427.                                 break;
  428.                         case 't':
  429.                                 c = 011;
  430.                                 break;
  431.                         case 'b':
  432.                                 c = 010;
  433.                                 break;
  434.                         case 'f':
  435.                                 c = 014;
  436.                                 break;
  437.                         }
  438.                 }
  439.                 v[i] = c;
  440.         }
  441.         if (i == 0 || getch() != '\'')
  442.                 experr("Illegal character constant");
  443.         for (value = 0; --i >= 0;) {
  444.                 value <<= 8;
  445.                 value += v[i];
  446.         }
  447.         return(value);
  448. }
  449.  
  450. /*
  451.  * num : digit | num digit
  452.  *
  453.  */
  454. num()
  455. {
  456.         register int rval, c, base;
  457.         int ndig;
  458.  
  459.         base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
  460.         rval = 0;
  461.         ndig = 0;
  462.         while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
  463.                 rval *= base;
  464.                 rval += (c - '0');
  465.                 c = getch();
  466.                 ndig++;
  467.         }
  468.         ungetch();
  469.         if (ndig)
  470.                 return(rval);
  471.         experr("Bad constant");
  472. }
  473.  
  474. /*
  475.  * eqlrel : '=' | '==' | '!='
  476.  *
  477.  */
  478. geteql()
  479. {
  480.         register int c1, c2;
  481.  
  482.         c1 = skipws();
  483.         c2 = getch();
  484.  
  485.         switch (c1) {
  486.  
  487.         case '=':
  488.                 if (c2 != '=')
  489.                         ungetch();
  490.                 return(EQL);
  491.  
  492.         case '!':
  493.                 if (c2 == '=')
  494.                         return(NEQ);
  495.                 ungetch();
  496.                 ungetch();
  497.                 return(-1);
  498.  
  499.         default:
  500.                 ungetch();
  501.                 ungetch();
  502.                 return(-1);
  503.         }
  504. }
  505.  
  506. /*
  507.  * rel : '<' | '>' | '<=' | '>='
  508.  *
  509.  */
  510. getrel()
  511. {
  512.         register int c1, c2;
  513.  
  514.         c1 = skipws();
  515.         c2 = getch();
  516.  
  517.         switch (c1) {
  518.  
  519.         case '<':
  520.                 if (c2 == '=')
  521.                         return(LEQ);
  522.                 ungetch();
  523.                 return(LSS);
  524.  
  525.         case '>':
  526.                 if (c2 == '=')
  527.                         return(GEQ);
  528.                 ungetch();
  529.                 return(GTR);
  530.  
  531.         default:
  532.                 ungetch();
  533.                 ungetch();
  534.                 return(-1);
  535.         }
  536. }
  537.  
  538. /*
  539.  * Skip over any white space and return terminating char.
  540.  */
  541. skipws()
  542. {
  543.         register char c;
  544.  
  545.         while ((c = getch()) <= ' ' && c > EOS)
  546.                 ;
  547.         return(c);
  548. }
  549.  
  550. /*
  551.  * Error handler - resets environment to eval(), prints an error,
  552.  * and returns FALSE.
  553.  */
  554. int experr(msg)
  555. char *msg;
  556. {
  557.         printf("mp: %s\n",msg);
  558.         longjmp(expjump, -1);          /* Force eval() to return FALSE */
  559. }
  560.