home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / m4 / expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-20  |  13.2 KB  |  601 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Ozan Yigit.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)expr.c    5.3 (Berkeley) 2/26/91";
  39. #endif /* not lint */
  40.  
  41. #include <setjmp.h>
  42. #include <stdio.h>
  43.  
  44. /*
  45.  *      expression evaluator: performs a standard recursive
  46.  *      descent parse to evaluate any expression permissible
  47.  *      within the following grammar:
  48.  *
  49.  *      expr    :       query EOS
  50.  *      query   :       lor
  51.  *              |       lor "?" query ":" query
  52.  *      lor     :       land { "||" land }
  53.  *      land    :       bor { "&&" bor }
  54.  *      bor     :       bxor { "|" bxor }
  55.  *      bxor    :       band { "^" band }
  56.  *      band    :       eql { "&" eql }
  57.  *      eql     :       relat { eqrel relat }
  58.  *      relat   :       shift { rel shift }
  59.  *      shift   :       primary { shop primary }
  60.  *      primary :       term { addop term }
  61.  *      term    :       unary { mulop unary }
  62.  *      unary   :       factor
  63.  *              |       unop unary
  64.  *      factor  :       constant
  65.  *              |       "(" query ")"
  66.  *      constant:       num
  67.  *              |       "'" CHAR "'"
  68.  *      num     :       DIGIT
  69.  *              |       DIGIT num
  70.  *      shop    :       "<<"
  71.  *              |       ">>"
  72.  *      eqlrel  :       "="
  73.  *              |       "=="
  74.  *              |       "!="
  75.  *      rel     :       "<"
  76.  *              |       ">"
  77.  *              |       "<="
  78.  *              |       ">="
  79.  *
  80.  *
  81.  *      This expression evaluator is lifted from a public-domain
  82.  *      C Pre-Processor included with the DECUS C Compiler distribution.
  83.  *      It is hacked somewhat to be suitable for m4.
  84.  *
  85.  *      Originally by:  Mike Lutz
  86.  *                      Bob Harper
  87.  */
  88.  
  89. #define TRUE    1
  90. #define FALSE   0
  91. #define EOS     (char) 0
  92. #define EQL     0
  93. #define NEQ     1
  94. #define LSS     2
  95. #define LEQ     3
  96. #define GTR     4
  97. #define GEQ     5
  98. #define OCTAL   8
  99. #define DECIMAL 10
  100.  
  101. static char *nxtch;     /* Parser scan pointer */
  102.  
  103. /*
  104.  * For longjmp
  105.  */
  106. static jmp_buf  expjump;
  107.  
  108. /*
  109.  * macros:
  110.  *
  111.  *      ungetch - Put back the last character examined.
  112.  *      getch   - return the next character from expr string.
  113.  */
  114. #define ungetch()       nxtch--
  115. #define getch()         *nxtch++
  116.  
  117. expr(expbuf)
  118. char *expbuf;
  119. {
  120.         register int rval;
  121.  
  122.         nxtch = expbuf;
  123.         if (setjmp(expjump) != 0)
  124.                 return (FALSE);
  125.         rval = query();
  126.         if (skipws() == EOS)
  127.                 return(rval);
  128.         experr("Ill-formed expression");
  129. }
  130.  
  131. /*
  132.  * query : lor | lor '?' query ':' query
  133.  *
  134.  */
  135. query()
  136. {
  137.         register int bool, true_val, false_val;
  138.  
  139.         bool = lor();
  140.         if (skipws() != '?') {
  141.                 ungetch();
  142.                 return(bool);
  143.         }
  144.  
  145.         true_val = query();
  146.         if (skipws() != ':')
  147.                 experr("Bad query");
  148.  
  149.         false_val = query();
  150.         return(bool ? true_val : false_val);
  151. }
  152.  
  153. /*
  154.  * lor : land { '||' land }
  155.  *
  156.  */
  157. lor()
  158. {
  159.         register int c, vl, vr;
  160.  
  161.         vl = land();
  162.         while ((c = skipws()) == '|' && getch() == '|') {
  163.                 vr = land();
  164.                 vl = vl || vr;
  165.         }
  166.  
  167.         if (c == '|')
  168.                 ungetch();
  169.         ungetch();
  170.         return(vl);
  171. }
  172.  
  173. /*
  174.  * land : bor { '&&' bor }
  175.  *
  176.  */
  177. land()
  178. {
  179.         register int c, vl, vr;
  180.  
  181.         vl = bor();
  182.         while ((c = skipws()) == '&' && getch() == '&') {
  183.                 vr = bor();
  184.                 vl = vl && vr;
  185.         }
  186.  
  187.         if (c == '&')
  188.                 ungetch();
  189.         ungetch();
  190.         return(vl);
  191. }
  192.  
  193. /*
  194.  * bor : bxor { '|' bxor }
  195.  *
  196.  */
  197. bor()
  198. {
  199.         register int vl, vr, c;
  200.  
  201.         vl = bxor();
  202.         while ((c = skipws()) == '|' && getch() != '|') {
  203.                 ungetch();
  204.                 vr = bxor();
  205.                 vl |= vr;
  206.         }
  207.  
  208.         if (c == '|')
  209.                 ungetch();
  210.         ungetch();
  211.         return(vl);
  212. }
  213.  
  214. /*
  215.  * bxor : band { '^' band }
  216.  *
  217.  */
  218. bxor()
  219. {
  220.         register int vl, vr;
  221.  
  222.         vl = band();
  223.         while (skipws() == '^') {
  224.                 vr = band();
  225.                 vl ^= vr;
  226.         }
  227.  
  228.         ungetch();
  229.         return(vl);
  230. }
  231.  
  232. /*
  233.  * band : eql { '&' eql }
  234.  *
  235.  */
  236. band()
  237. {
  238.         register int vl, vr, c;
  239.  
  240.         vl = eql();
  241.         while ((c = skipws()) == '&' && getch() != '&') {
  242.                 ungetch();
  243.                 vr = eql();
  244.                 vl &= vr;
  245.         }
  246.  
  247.         if (c == '&')
  248.                 ungetch();
  249.         ungetch();
  250.         return(vl);
  251. }
  252.  
  253. /*
  254.  * eql : relat { eqrel relat }
  255.  *
  256.  */
  257. eql()
  258. {
  259.         register int vl, vr, rel;
  260.  
  261.         vl = relat();
  262.         while ((rel = geteql()) != -1) {
  263.                 vr = relat();
  264.  
  265.                 switch (rel) {
  266.  
  267.                 case EQL:
  268.                         vl = (vl == vr);
  269.                         break;
  270.                 case NEQ:
  271.                         vl = (vl != vr);
  272.                         break;
  273.                 }
  274.         }
  275.         return(vl);
  276. }
  277.  
  278. /*
  279.  * relat : shift { rel shift }
  280.  *
  281.  */
  282. relat()
  283. {
  284.         register int vl, vr, rel;
  285.  
  286.         vl = shift();
  287.         while ((rel = getrel()) != -1) {
  288.  
  289.                 vr = shift();
  290.                 switch (rel) {
  291.  
  292.                 case LEQ:
  293.                         vl = (vl <= vr);
  294.                         break;
  295.                 case LSS:
  296.                         vl = (vl < vr);
  297.                         break;
  298.                 case GTR:
  299.                         vl = (vl > vr);
  300.                         break;
  301.                 case GEQ:
  302.                         vl = (vl >= vr);
  303.                         break;
  304.                 }
  305.         }
  306.         return(vl);
  307. }
  308.  
  309. /*
  310.  * shift : primary { shop primary }
  311.  *
  312.  */
  313. shift()
  314. {
  315.         register int vl, vr, c;
  316.  
  317.         vl = primary();
  318.         while (((c = skipws()) == '<' || c == '>') && c == getch()) {
  319.                 vr = primary();
  320.  
  321.                 if (c == '<')
  322.                         vl <<= vr;
  323.                 else
  324.                         vl >>= vr;
  325.         }
  326.  
  327.         if (c == '<' || c == '>')
  328.                 ungetch();
  329.         ungetch();
  330.         return(vl);
  331. }
  332.  
  333. /*
  334.  * primary : term { addop term }
  335.  *
  336.  */
  337. primary()
  338. {
  339.         register int c, vl, vr;
  340.  
  341.         vl = term();
  342.         while ((c = skipws()) == '+' || c == '-') {
  343.                 vr = term();
  344.                 if (c == '+')
  345.                         vl += vr;
  346.                 else
  347.                         vl -= vr;
  348.         }
  349.  
  350.         ungetch();
  351.         return(vl);
  352. }
  353.  
  354. /*
  355.  * <term> := <unary> { <mulop> <unary> }
  356.  *
  357.  */
  358. term()
  359. {
  360.         register int c, vl, vr;
  361.  
  362.         vl = unary();
  363.         while ((c = skipws()) == '*' || c == '/' || c == '%') {
  364.                 vr = unary();
  365.  
  366.                 switch (c) {
  367.                 case '*':
  368.                         vl *= vr;
  369.                         break;
  370.                 case '/':
  371.                         vl /= vr;
  372.                         break;
  373.                 case '%':
  374.                         vl %= vr;
  375.                         break;
  376.                 }
  377.         }
  378.         ungetch();
  379.         return(vl);
  380. }
  381.  
  382. /*
  383.  * unary : factor | unop unary
  384.  *
  385.  */
  386. unary()
  387. {
  388.         register int val, c;
  389.  
  390.         if ((c = skipws()) == '!' || c == '~' || c == '-') {
  391.                 val = unary();
  392.  
  393.                 switch (c) {
  394.                 case '!':
  395.                         return(! val);
  396.                 case '~':
  397.                         return(~ val);
  398.                 case '-':
  399.                         return(- val);
  400.                 }
  401.         }
  402.  
  403.         ungetch();
  404.         return(factor());
  405. }
  406.  
  407. /*
  408.  * factor : constant | '(' query ')'
  409.  *
  410.  */
  411. factor()
  412. {
  413.         register int val;
  414.  
  415.         if (skipws() == '(') {
  416.                 val = query();
  417.                 if (skipws() != ')')
  418.                         experr("Bad factor");
  419.                 return(val);
  420.         }
  421.  
  422.         ungetch();
  423.         return(constant());
  424. }
  425.  
  426. /*
  427.  * constant: num | 'char'
  428.  *
  429.  */
  430. constant()
  431. {
  432.         /*
  433.          * Note: constant() handles multi-byte constants
  434.          */
  435.  
  436.         register int    i;
  437.         register int    value;
  438.         register char   c;
  439.         int             v[sizeof (int)];
  440.  
  441.         if (skipws() != '\'') {
  442.                 ungetch();
  443.                 return(num());
  444.         }
  445.         for (i = 0; i < sizeof(int); i++) {
  446.                 if ((c = getch()) == '\'') {
  447.                         ungetch();
  448.                         break;
  449.                 }
  450.                 if (c == '\\') {
  451.                         switch (c = getch()) {
  452.                         case '0':
  453.                         case '1':
  454.                         case '2':
  455.                         case '3':
  456.                         case '4':
  457.                         case '5':
  458.                         case '6':
  459.                         case '7':
  460.                                 ungetch();
  461.                                 c = num();
  462.                                 break;
  463.                         case 'n':
  464.                                 c = 012;
  465.                                 break;
  466.                         case 'r':
  467.                                 c = 015;
  468.                                 break;
  469.                         case 't':
  470.                                 c = 011;
  471.                                 break;
  472.                         case 'b':
  473.                                 c = 010;
  474.                                 break;
  475.                         case 'f':
  476.                                 c = 014;
  477.                                 break;
  478.                         }
  479.                 }
  480.                 v[i] = c;
  481.         }
  482.         if (i == 0 || getch() != '\'')
  483.                 experr("Illegal character constant");
  484.         for (value = 0; --i >= 0;) {
  485.                 value <<= 8;
  486.                 value += v[i];
  487.         }
  488.         return(value);
  489. }
  490.  
  491. /*
  492.  * num : digit | num digit
  493.  *
  494.  */
  495. num()
  496. {
  497.         register int rval, c, base;
  498.         int ndig;
  499.  
  500.         base = ((c = skipws()) == '0') ? OCTAL : DECIMAL;
  501.         rval = 0;
  502.         ndig = 0;
  503.         while (c >= '0' && c <= (base == OCTAL ? '7' : '9')) {
  504.                 rval *= base;
  505.                 rval += (c - '0');
  506.                 c = getch();
  507.                 ndig++;
  508.         }
  509.         ungetch();
  510.         if (ndig)
  511.                 return(rval);
  512.         experr("Bad constant");
  513. }
  514.  
  515. /*
  516.  * eqlrel : '=' | '==' | '!='
  517.  *
  518.  */
  519. geteql()
  520. {
  521.         register int c1, c2;
  522.  
  523.         c1 = skipws();
  524.         c2 = getch();
  525.  
  526.         switch (c1) {
  527.  
  528.         case '=':
  529.                 if (c2 != '=')
  530.                         ungetch();
  531.                 return(EQL);
  532.  
  533.         case '!':
  534.                 if (c2 == '=')
  535.                         return(NEQ);
  536.                 ungetch();
  537.                 ungetch();
  538.                 return(-1);
  539.  
  540.         default:
  541.                 ungetch();
  542.                 ungetch();
  543.                 return(-1);
  544.         }
  545. }
  546.  
  547. /*
  548.  * rel : '<' | '>' | '<=' | '>='
  549.  *
  550.  */
  551. getrel()
  552. {
  553.         register int c1, c2;
  554.  
  555.         c1 = skipws();
  556.         c2 = getch();
  557.  
  558.         switch (c1) {
  559.  
  560.         case '<':
  561.                 if (c2 == '=')
  562.                         return(LEQ);
  563.                 ungetch();
  564.                 return(LSS);
  565.  
  566.         case '>':
  567.                 if (c2 == '=')
  568.                         return(GEQ);
  569.                 ungetch();
  570.                 return(GTR);
  571.  
  572.         default:
  573.                 ungetch();
  574.                 ungetch();
  575.                 return(-1);
  576.         }
  577. }
  578.  
  579. /*
  580.  * Skip over any white space and return terminating char.
  581.  */
  582. skipws()
  583. {
  584.         register char c;
  585.  
  586.         while ((c = getch()) <= ' ' && c > EOS)
  587.                 ;
  588.         return(c);
  589. }
  590.  
  591. /*
  592.  * Error handler - resets environment to eval(), prints an error,
  593.  * and returns FALSE.
  594.  */
  595. experr(msg)
  596. char *msg;
  597. {
  598.         printf("mp: %s\n",msg);
  599.         longjmp(expjump, -1);          /* Force eval() to return FALSE */
  600. }
  601.