expr.c

Go to the documentation of this file.
00001 /*
00002  *      expression evaluator: performs a standard recursive
00003  *      descent parse to evaluate any expression permissible
00004  *      within the following grammar:
00005  *
00006  *      expr    :       query EOS
00007  *      query   :       lor
00008  *              |       lor "?" query ":" query
00009  *      lor     :       land { "||" land }
00010  *      land    :       bor { "&&" bor }
00011  *      bor     :       bxor { "|" bxor }
00012  *      bxor    :       band { "^" band }
00013  *      band    :       eql { "&" eql }
00014  *      eql     :       relat { eqrel relat }
00015  *      relat   :       shift { rel shift }
00016  *      shift   :       primary { shop primary }
00017  *      primary :       term { addop term }
00018  *      term    :       unary { mulop unary }
00019  *      unary   :       factor
00020  *              |       unop unary
00021  *      factor  :       constant
00022  *              |       "(" query ")"
00023  *      constant:       num
00024  *              |       "'" CHAR "'"
00025  *      num     :       decnum
00026  *              |       "0" octnum
00027  *              |       "0x" hexnum
00028  *      octnum  :       OCTDIGIT
00029  *              |       OCTDIGIT octnum
00030  *      decnum  :       DECDIGIT
00031  *              |       DECDIGIT decnum
00032  *      hexnum  :       HEXDIGIT
00033  *              |       HEXDIGIT hexnum
00034  *      shop    :       "<<"
00035  *              |       ">>"
00036  *      eqlrel  :       "="
00037  *              |       "=="
00038  *              |       "!="
00039  *      rel     :       "<"
00040  *              |       ">"
00041  *              |       "<="
00042  *              |       ">="
00043  *
00044  *
00045  *      This expression evaluator is lifted from a public-domain
00046  *      C Pre-Processor included with the DECUS C Compiler distribution.
00047  *      It is hacked somewhat to be suitable for m4.
00048  *
00049  *      Originally by:  Mike Lutz
00050  *                      Bob Harper
00051  */
00052  
00053 #include "mdef.h"
00054 
00055 #define TRUE    1
00056 #define FALSE   0
00057 #define EOS     (char) 0
00058 #define EQL     0
00059 #define NEQ     1
00060 #define LSS     2
00061 #define LEQ     3
00062 #define GTR     4
00063 #define GEQ     5
00064  
00065 static char *nxtch;     /* Parser scan pointer */
00066  
00067 /*
00068  * For longjmp
00069  */
00070 #include <setjmp.h>
00071 static jmp_buf  expjump;
00072  
00073 /*
00074  * macros:
00075  *
00076  *      ungetch - Put back the last character examined.
00077  *      getch   - return the next character from expr string.
00078  */
00079 #define ungetch()       nxtch--
00080 #define getch()         *nxtch++
00081  
00082 int expr(expbuf)
00083 char *expbuf;
00084 {
00085         register int rval;
00086  
00087         nxtch = expbuf;
00088         if (setjmp(expjump) != 0)
00089                 return (FALSE);
00090         rval = query();
00091         if (skipws() == EOS)
00092                 return(rval);
00093         experr("Ill-formed expression");
00094         /* NOTREACHED */
00095         return(0);
00096 }
00097  
00098 /*
00099  * query : lor | lor '?' query ':' query
00100  *
00101  */
00102 int query()
00103 {
00104         register int bool, true_val, false_val;
00105  
00106         bool = lor();
00107         if (skipws() != '?') {
00108                 ungetch();
00109                 return(bool);
00110         }
00111  
00112         true_val = query();
00113         if (skipws() != ':')
00114                 experr("Bad query");
00115  
00116         false_val = query();
00117         return(bool ? true_val : false_val);
00118 }
00119  
00120 /*
00121  * lor : land { '||' land }
00122  *
00123  */
00124 int lor()
00125 {
00126         register int c, vl, vr;
00127  
00128         vl = land();
00129         while ((c = skipws()) == '|' && getch() == '|') {
00130                 vr = land();
00131                 vl = vl || vr;
00132         }
00133  
00134         if (c == '|')
00135                 ungetch();
00136         ungetch();
00137         return(vl);
00138 }
00139  
00140 /*
00141  * land : bor { '&&' bor }
00142  *
00143  */
00144 int land()
00145 {
00146         register int c, vl, vr;
00147  
00148         vl = bor();
00149         while ((c = skipws()) == '&' && getch() == '&') {
00150                 vr = bor();
00151                 vl = vl && vr;
00152         }
00153  
00154         if (c == '&')
00155                 ungetch();
00156         ungetch();
00157         return(vl);
00158 }
00159  
00160 /*
00161  * bor : bxor { '|' bxor }
00162  *
00163  */
00164 int bor()
00165 {
00166         register int vl, vr, c;
00167  
00168         vl = bxor();
00169         while ((c = skipws()) == '|' && getch() != '|') {
00170                 ungetch();
00171                 vr = bxor();
00172                 vl |= vr;
00173         }
00174  
00175         if (c == '|')
00176                 ungetch();
00177         ungetch();
00178         return(vl);
00179 }
00180  
00181 /*
00182  * bxor : band { '^' band }
00183  *
00184  */
00185 int bxor()
00186 {
00187         register int vl, vr;
00188  
00189         vl = band();
00190         while (skipws() == '^') {
00191                 vr = band();
00192                 vl ^= vr;
00193         }
00194  
00195         ungetch();
00196         return(vl);
00197 }
00198  
00199 /*
00200  * band : eql { '&' eql }
00201  *
00202  */
00203 int band()
00204 {
00205         register int vl, vr, c;
00206  
00207         vl = eql();
00208         while ((c = skipws()) == '&' && getch() != '&') {
00209                 ungetch();
00210                 vr = eql();
00211                 vl &= vr;
00212         }
00213  
00214         if (c == '&')
00215                 ungetch();
00216         ungetch();
00217         return(vl);
00218 }
00219  
00220 /*
00221  * eql : relat { eqrel relat }
00222  *
00223  */
00224 int eql()
00225 {
00226         register int vl, vr, rel;
00227  
00228         vl = relat();
00229         while ((rel = geteql()) != -1) {
00230                 vr = relat();
00231  
00232                 switch (rel) {
00233  
00234                 case EQL:
00235                         vl = (vl == vr);
00236                         break;
00237                 case NEQ:
00238                         vl = (vl != vr);
00239                         break;
00240                 }
00241         }
00242         return(vl);
00243 }
00244  
00245 /*
00246  * relat : shift { rel shift }
00247  *
00248  */
00249 int relat()
00250 {
00251         register int vl, vr, rel;
00252  
00253         vl = shift();
00254         while ((rel = getrel()) != -1) {
00255  
00256                 vr = shift();
00257                 switch (rel) {
00258  
00259                 case LEQ:
00260                         vl = (vl <= vr);
00261                         break;
00262                 case LSS:
00263                         vl = (vl < vr);
00264                         break;
00265                 case GTR:
00266                         vl = (vl > vr);
00267                         break;
00268                 case GEQ:
00269                         vl = (vl >= vr);
00270                         break;
00271                 }
00272         }
00273         return(vl);
00274 }
00275  
00276 /*
00277  * shift : primary { shop primary }
00278  *
00279  */
00280 int shift()
00281 {
00282         register int vl, vr, c;
00283  
00284         vl = primary();
00285         while (((c = skipws()) == '<' || c == '>') && c == getch()) {
00286                 vr = primary();
00287  
00288                 if (c == '<')
00289                         vl <<= vr;
00290                 else
00291                         vl >>= vr;
00292         }
00293  
00294         if (c == '<' || c == '>')
00295                 ungetch();
00296         ungetch();
00297         return(vl);
00298 }
00299  
00300 /*
00301  * primary : term { addop term }
00302  *
00303  */
00304 int primary()
00305 {
00306         register int c, vl, vr;
00307  
00308         vl = term();
00309         while ((c = skipws()) == '+' || c == '-') {
00310                 vr = term();
00311                 if (c == '+')
00312                         vl += vr;
00313                 else
00314                         vl -= vr;
00315         }
00316  
00317         ungetch();
00318         return(vl);
00319 }
00320  
00321 /*
00322  * <term> := <unary> { <mulop> <unary> }
00323  *
00324  */
00325 int term()
00326 {
00327         register int c, vl, vr;
00328  
00329         vl = unary();
00330         while ((c = skipws()) == '*' || c == '/' || c == '%') {
00331                 vr = unary();
00332  
00333                 switch (c) {
00334                 case '*':
00335                         vl *= vr;
00336                         break;
00337                 case '/':
00338                         vl /= vr;
00339                         break;
00340                 case '%':
00341                         vl %= vr;
00342                         break;
00343                 }
00344         }
00345         ungetch();
00346         return(vl);
00347 }
00348  
00349 /*
00350  * unary : factor | unop unary
00351  *
00352  */
00353 int unary()
00354 {
00355         register int val, c;
00356  
00357         if ((c = skipws()) == '!' || c == '~' || c == '-') {
00358                 val = unary();
00359  
00360                 switch (c) {
00361                 case '!':
00362                         return(! val);
00363                 case '~':
00364                         return(~ val);
00365                 case '-':
00366                         return(- val);
00367                 }
00368         }
00369  
00370         ungetch();
00371         return(factor());
00372 }
00373  
00374 /*
00375  * factor : constant | '(' query ')'
00376  *
00377  */
00378 int factor()
00379 {
00380         register int val;
00381  
00382         if (skipws() == '(') {
00383                 val = query();
00384                 if (skipws() != ')')
00385                         experr("Bad factor");
00386                 return(val);
00387         }
00388  
00389         ungetch();
00390         return(constant());
00391 }
00392  
00393 /*
00394  * constant: num | 'char'
00395  *
00396  */
00397 int constant()
00398 {
00399         /*
00400          * Note: constant() handles multi-byte constants
00401          */
00402  
00403         register int    i;
00404         register int    value;
00405         register char   c;
00406         int             v[sizeof (int)];
00407  
00408         if (skipws() != '\'') {
00409                 ungetch();
00410                 return(num());
00411         }
00412         for (i = 0; i < sizeof(int); i++) {
00413                 if ((c = getch()) == '\'') {
00414                         ungetch();
00415                         break;
00416                 }
00417                 if (c == '\\') {
00418                         switch (c = getch()) {
00419                         case '0':
00420                         case '1':
00421                         case '2':
00422                         case '3':
00423                         case '4':
00424                         case '5':
00425                         case '6':
00426                         case '7':
00427                                 ungetch();
00428                                 c = num();
00429                                 break;
00430                         case 'n':
00431                                 c = 012;
00432                                 break;
00433                         case 'r':
00434                                 c = 015;
00435                                 break;
00436                         case 't':
00437                                 c = 011;
00438                                 break;
00439                         case 'b':
00440                                 c = 010;
00441                                 break;
00442                         case 'f':
00443                                 c = 014;
00444                                 break;
00445                         }
00446                 }
00447                 v[i] = c;
00448         }
00449         if (i == 0 || getch() != '\'')
00450                 experr("Illegal character constant");
00451         for (value = 0; --i >= 0;) {
00452                 value <<= 8;
00453                 value += v[i];
00454         }
00455         return(value);
00456 }
00457  
00458 /*
00459  * num : digit | num digit
00460  *
00461  */
00462 int num()
00463 {
00464         register int rval, c, base;
00465         int ndig;
00466  
00467         ndig = 0;
00468         if ((c = skipws()) == '0') {
00469                 c = getch ();
00470                 if (c == 'x' || c == 'X') {
00471                         base = 16;
00472                         c = getch ();
00473                 } else {
00474                         base = 8;
00475                         ndig = 1;
00476                 }
00477         } else {
00478                 base = 10;
00479         }
00480         rval = 0;
00481         for (;;) {
00482                 if (isdigit(c))         c -= '0';
00483                 else if (isupper (c))   c -= ('A' - 10);
00484                 else if (islower (c))   c -= ('a' - 10);
00485                 else                    break;
00486                 if (c < 0 || c >= base)
00487                         break;
00488 
00489                 rval *= base;
00490                 rval += c;
00491                 c = getch();
00492                 ndig++;
00493         }
00494         ungetch();
00495         if (ndig)
00496                 return(rval);
00497         experr("Bad constant");
00498         /* NOTREACHED */
00499         return(0);
00500 }
00501  
00502 /*
00503  * eqlrel : '=' | '==' | '!='
00504  *
00505  */
00506 int geteql()
00507 {
00508         register int c1, c2;
00509  
00510         c1 = skipws();
00511         c2 = getch();
00512  
00513         switch (c1) {
00514  
00515         case '=':
00516                 if (c2 != '=')
00517                         ungetch();
00518                 return(EQL);
00519  
00520         case '!':
00521                 if (c2 == '=')
00522                         return(NEQ);
00523                 ungetch();
00524                 ungetch();
00525                 return(-1);
00526  
00527         default:
00528                 ungetch();
00529                 ungetch();
00530                 return(-1);
00531         }
00532 }
00533  
00534 /*
00535  * rel : '<' | '>' | '<=' | '>='
00536  *
00537  */
00538 int getrel()
00539 {
00540         register int c1, c2;
00541  
00542         c1 = skipws();
00543         c2 = getch();
00544  
00545         switch (c1) {
00546  
00547         case '<':
00548                 if (c2 == '=')
00549                         return(LEQ);
00550                 ungetch();
00551                 return(LSS);
00552  
00553         case '>':
00554                 if (c2 == '=')
00555                         return(GEQ);
00556                 ungetch();
00557                 return(GTR);
00558  
00559         default:
00560                 ungetch();
00561                 ungetch();
00562                 return(-1);
00563         }
00564 }
00565  
00566 /*
00567  * Skip over any white space and return terminating char.
00568  */
00569 int skipws()
00570 {
00571         register char c;
00572  
00573         while ((c = getch()) <= ' ' && c > EOS)
00574                 ;
00575         return(c);
00576 }
00577  
00578 /*
00579  * Error handler - resets environment to eval(), prints an error,
00580  * and returns FALSE.
00581  */
00582 int experr(msg)
00583 char *msg;
00584 {
00585         printf("mp: %s\n",msg);
00586         longjmp(expjump, -1);          /* Force eval() to return FALSE */
00587 }

Generated on Fri Apr 14 22:56:39 2006 for minix by  doxygen 1.4.6