Annotation of 43BSDReno/pgrm/m4/expr.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.