home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 138.lha / M4 / Sources / expr.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  12KB  |  559 lines

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