588 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			588 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
 *      expression evaluator: performs a standard recursive
 | 
						|
 *      descent parse to evaluate any expression permissible
 | 
						|
 *      within the following grammar:
 | 
						|
 *
 | 
						|
 *      expr    :       query EOS
 | 
						|
 *      query   :       lor
 | 
						|
 *              |       lor "?" query ":" query
 | 
						|
 *      lor     :       land { "||" land }
 | 
						|
 *      land    :       bor { "&&" bor }
 | 
						|
 *      bor     :       bxor { "|" bxor }
 | 
						|
 *      bxor    :       band { "^" band }
 | 
						|
 *      band    :       eql { "&" eql }
 | 
						|
 *      eql     :       relat { eqrel relat }
 | 
						|
 *      relat   :       shift { rel shift }
 | 
						|
 *      shift   :       primary { shop primary }
 | 
						|
 *      primary :       term { addop term }
 | 
						|
 *      term    :       unary { mulop unary }
 | 
						|
 *      unary   :       factor
 | 
						|
 *              |       unop unary
 | 
						|
 *      factor  :       constant
 | 
						|
 *              |       "(" query ")"
 | 
						|
 *      constant:       num
 | 
						|
 *              |       "'" CHAR "'"
 | 
						|
 *      num     :       decnum
 | 
						|
 *              |       "0" octnum
 | 
						|
 *		|	"0x" hexnum
 | 
						|
 *	octnum	:	OCTDIGIT
 | 
						|
 *		|	OCTDIGIT octnum
 | 
						|
 *	decnum	:	DECDIGIT
 | 
						|
 *		|	DECDIGIT decnum
 | 
						|
 *	hexnum	:	HEXDIGIT
 | 
						|
 *		|	HEXDIGIT hexnum
 | 
						|
 *      shop    :       "<<"
 | 
						|
 *              |       ">>"
 | 
						|
 *      eqlrel  :       "="
 | 
						|
 *              |       "=="
 | 
						|
 *              |       "!="
 | 
						|
 *      rel     :       "<"
 | 
						|
 *              |       ">"
 | 
						|
 *              |       "<="
 | 
						|
 *              |       ">="
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *      This expression evaluator is lifted from a public-domain
 | 
						|
 *      C Pre-Processor included with the DECUS C Compiler distribution.
 | 
						|
 *      It is hacked somewhat to be suitable for m4.
 | 
						|
 *
 | 
						|
 *      Originally by:  Mike Lutz
 | 
						|
 *                      Bob Harper
 | 
						|
 */
 | 
						|
 
 | 
						|
#include "mdef.h"
 | 
						|
 | 
						|
#define TRUE    1
 | 
						|
#define FALSE   0
 | 
						|
#define EOS     (char) 0
 | 
						|
#define EQL     0
 | 
						|
#define NEQ     1
 | 
						|
#define LSS     2
 | 
						|
#define LEQ     3
 | 
						|
#define GTR     4
 | 
						|
#define GEQ     5
 | 
						|
 
 | 
						|
static char *nxtch;     /* Parser scan pointer */
 | 
						|
 
 | 
						|
/*
 | 
						|
 * For longjmp
 | 
						|
 */
 | 
						|
#include <setjmp.h>
 | 
						|
static jmp_buf  expjump;
 | 
						|
 
 | 
						|
/*
 | 
						|
 * macros:
 | 
						|
 *
 | 
						|
 *      ungetch - Put back the last character examined.
 | 
						|
 *      getch   - return the next character from expr string.
 | 
						|
 */
 | 
						|
#define ungetch()       nxtch--
 | 
						|
#define getch()         *nxtch++
 | 
						|
 
 | 
						|
int expr(expbuf)
 | 
						|
char *expbuf;
 | 
						|
{
 | 
						|
        register int rval;
 | 
						|
 
 | 
						|
        nxtch = expbuf;
 | 
						|
        if (setjmp(expjump) != 0)
 | 
						|
                return (FALSE);
 | 
						|
        rval = query();
 | 
						|
        if (skipws() == EOS)
 | 
						|
                return(rval);
 | 
						|
        experr("Ill-formed expression");
 | 
						|
	/* NOTREACHED */
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * query : lor | lor '?' query ':' query
 | 
						|
 *
 | 
						|
 */
 | 
						|
int query()
 | 
						|
{
 | 
						|
        register int bool, true_val, false_val;
 | 
						|
 
 | 
						|
        bool = lor();
 | 
						|
        if (skipws() != '?') {
 | 
						|
                ungetch();
 | 
						|
                return(bool);
 | 
						|
        }
 | 
						|
 
 | 
						|
        true_val = query();
 | 
						|
        if (skipws() != ':')
 | 
						|
                experr("Bad query");
 | 
						|
 
 | 
						|
        false_val = query();
 | 
						|
        return(bool ? true_val : false_val);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * lor : land { '||' land }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int lor()
 | 
						|
{
 | 
						|
        register int c, vl, vr;
 | 
						|
 
 | 
						|
        vl = land();
 | 
						|
        while ((c = skipws()) == '|' && getch() == '|') {
 | 
						|
                vr = land();
 | 
						|
                vl = vl || vr;
 | 
						|
        }
 | 
						|
 
 | 
						|
        if (c == '|')
 | 
						|
                ungetch();
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * land : bor { '&&' bor }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int land()
 | 
						|
{
 | 
						|
        register int c, vl, vr;
 | 
						|
 
 | 
						|
        vl = bor();
 | 
						|
        while ((c = skipws()) == '&' && getch() == '&') {
 | 
						|
                vr = bor();
 | 
						|
                vl = vl && vr;
 | 
						|
        }
 | 
						|
 
 | 
						|
        if (c == '&')
 | 
						|
                ungetch();
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * bor : bxor { '|' bxor }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int bor()
 | 
						|
{
 | 
						|
        register int vl, vr, c;
 | 
						|
 
 | 
						|
        vl = bxor();
 | 
						|
        while ((c = skipws()) == '|' && getch() != '|') {
 | 
						|
                ungetch();
 | 
						|
                vr = bxor();
 | 
						|
                vl |= vr;
 | 
						|
        }
 | 
						|
 
 | 
						|
        if (c == '|')
 | 
						|
                ungetch();
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * bxor : band { '^' band }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int bxor()
 | 
						|
{
 | 
						|
        register int vl, vr;
 | 
						|
 
 | 
						|
        vl = band();
 | 
						|
        while (skipws() == '^') {
 | 
						|
                vr = band();
 | 
						|
                vl ^= vr;
 | 
						|
        }
 | 
						|
 
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * band : eql { '&' eql }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int band()
 | 
						|
{
 | 
						|
        register int vl, vr, c;
 | 
						|
 
 | 
						|
        vl = eql();
 | 
						|
        while ((c = skipws()) == '&' && getch() != '&') {
 | 
						|
                ungetch();
 | 
						|
                vr = eql();
 | 
						|
                vl &= vr;
 | 
						|
        }
 | 
						|
 
 | 
						|
        if (c == '&')
 | 
						|
                ungetch();
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * eql : relat { eqrel relat }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int eql()
 | 
						|
{
 | 
						|
        register int vl, vr, rel;
 | 
						|
 
 | 
						|
        vl = relat();
 | 
						|
        while ((rel = geteql()) != -1) {
 | 
						|
                vr = relat();
 | 
						|
 
 | 
						|
                switch (rel) {
 | 
						|
 
 | 
						|
                case EQL:
 | 
						|
                        vl = (vl == vr);
 | 
						|
                        break;
 | 
						|
                case NEQ:
 | 
						|
                        vl = (vl != vr);
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
        }
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * relat : shift { rel shift }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int relat()
 | 
						|
{
 | 
						|
        register int vl, vr, rel;
 | 
						|
 
 | 
						|
        vl = shift();
 | 
						|
        while ((rel = getrel()) != -1) {
 | 
						|
 
 | 
						|
                vr = shift();
 | 
						|
                switch (rel) {
 | 
						|
 
 | 
						|
                case LEQ:
 | 
						|
                        vl = (vl <= vr);
 | 
						|
                        break;
 | 
						|
                case LSS:
 | 
						|
                        vl = (vl < vr);
 | 
						|
                        break;
 | 
						|
                case GTR:
 | 
						|
                        vl = (vl > vr);
 | 
						|
                        break;
 | 
						|
                case GEQ:
 | 
						|
                        vl = (vl >= vr);
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
        }
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * shift : primary { shop primary }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int shift()
 | 
						|
{
 | 
						|
        register int vl, vr, c;
 | 
						|
 
 | 
						|
        vl = primary();
 | 
						|
        while (((c = skipws()) == '<' || c == '>') && c == getch()) {
 | 
						|
                vr = primary();
 | 
						|
 
 | 
						|
                if (c == '<')
 | 
						|
                        vl <<= vr;
 | 
						|
                else
 | 
						|
                        vl >>= vr;
 | 
						|
        }
 | 
						|
 
 | 
						|
        if (c == '<' || c == '>')
 | 
						|
                ungetch();
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * primary : term { addop term }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int primary()
 | 
						|
{
 | 
						|
        register int c, vl, vr;
 | 
						|
 
 | 
						|
        vl = term();
 | 
						|
        while ((c = skipws()) == '+' || c == '-') {
 | 
						|
                vr = term();
 | 
						|
                if (c == '+')
 | 
						|
                        vl += vr;
 | 
						|
                else
 | 
						|
                        vl -= vr;
 | 
						|
        }
 | 
						|
 
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * <term> := <unary> { <mulop> <unary> }
 | 
						|
 *
 | 
						|
 */
 | 
						|
int term()
 | 
						|
{
 | 
						|
        register int c, vl, vr;
 | 
						|
 
 | 
						|
        vl = unary();
 | 
						|
        while ((c = skipws()) == '*' || c == '/' || c == '%') {
 | 
						|
                vr = unary();
 | 
						|
 
 | 
						|
                switch (c) {
 | 
						|
                case '*':
 | 
						|
                        vl *= vr;
 | 
						|
                        break;
 | 
						|
                case '/':
 | 
						|
                        vl /= vr;
 | 
						|
                        break;
 | 
						|
                case '%':
 | 
						|
                        vl %= vr;
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
        }
 | 
						|
        ungetch();
 | 
						|
        return(vl);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * unary : factor | unop unary
 | 
						|
 *
 | 
						|
 */
 | 
						|
int unary()
 | 
						|
{
 | 
						|
        register int val, c;
 | 
						|
 
 | 
						|
        if ((c = skipws()) == '!' || c == '~' || c == '-') {
 | 
						|
                val = unary();
 | 
						|
 
 | 
						|
                switch (c) {
 | 
						|
                case '!':
 | 
						|
                        return(! val);
 | 
						|
                case '~':
 | 
						|
                        return(~ val);
 | 
						|
                case '-':
 | 
						|
                        return(- val);
 | 
						|
                }
 | 
						|
        }
 | 
						|
 
 | 
						|
        ungetch();
 | 
						|
        return(factor());
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * factor : constant | '(' query ')'
 | 
						|
 *
 | 
						|
 */
 | 
						|
int factor()
 | 
						|
{
 | 
						|
        register int val;
 | 
						|
 
 | 
						|
        if (skipws() == '(') {
 | 
						|
                val = query();
 | 
						|
                if (skipws() != ')')
 | 
						|
                        experr("Bad factor");
 | 
						|
                return(val);
 | 
						|
        }
 | 
						|
 
 | 
						|
        ungetch();
 | 
						|
        return(constant());
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * constant: num | 'char'
 | 
						|
 *
 | 
						|
 */
 | 
						|
int constant()
 | 
						|
{
 | 
						|
        /*
 | 
						|
         * Note: constant() handles multi-byte constants
 | 
						|
         */
 | 
						|
 
 | 
						|
        register int    i;
 | 
						|
        register int    value;
 | 
						|
        register char   c;
 | 
						|
        int             v[sizeof (int)];
 | 
						|
 
 | 
						|
        if (skipws() != '\'') {
 | 
						|
                ungetch();
 | 
						|
                return(num());
 | 
						|
        }
 | 
						|
        for (i = 0; i < sizeof(int); i++) {
 | 
						|
                if ((c = getch()) == '\'') {
 | 
						|
                        ungetch();
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
                if (c == '\\') {
 | 
						|
                        switch (c = getch()) {
 | 
						|
                        case '0':
 | 
						|
                        case '1':
 | 
						|
                        case '2':
 | 
						|
                        case '3':
 | 
						|
                        case '4':
 | 
						|
                        case '5':
 | 
						|
                        case '6':
 | 
						|
                        case '7':
 | 
						|
                                ungetch();
 | 
						|
                                c = num();
 | 
						|
                                break;
 | 
						|
                        case 'n':
 | 
						|
                                c = 012;
 | 
						|
                                break;
 | 
						|
                        case 'r':
 | 
						|
                                c = 015;
 | 
						|
                                break;
 | 
						|
                        case 't':
 | 
						|
                                c = 011;
 | 
						|
                                break;
 | 
						|
                        case 'b':
 | 
						|
                                c = 010;
 | 
						|
                                break;
 | 
						|
                        case 'f':
 | 
						|
                                c = 014;
 | 
						|
                                break;
 | 
						|
                        }
 | 
						|
                }
 | 
						|
                v[i] = c;
 | 
						|
        }
 | 
						|
        if (i == 0 || getch() != '\'')
 | 
						|
                experr("Illegal character constant");
 | 
						|
        for (value = 0; --i >= 0;) {
 | 
						|
                value <<= 8;
 | 
						|
                value += v[i];
 | 
						|
        }
 | 
						|
        return(value);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * num : digit | num digit
 | 
						|
 *
 | 
						|
 */
 | 
						|
int num()
 | 
						|
{
 | 
						|
        register int rval, c, base;
 | 
						|
        int ndig;
 | 
						|
 
 | 
						|
        ndig = 0;
 | 
						|
        if ((c = skipws()) == '0') {
 | 
						|
        	c = getch ();
 | 
						|
        	if (c == 'x' || c == 'X') {
 | 
						|
        		base = 16;
 | 
						|
        		c = getch ();
 | 
						|
        	} else {
 | 
						|
        		base = 8;
 | 
						|
        		ndig = 1;
 | 
						|
        	}
 | 
						|
        } else {
 | 
						|
        	base = 10;
 | 
						|
        }
 | 
						|
        rval = 0;
 | 
						|
        for (;;) {
 | 
						|
		if (isdigit(c))         c -= '0';
 | 
						|
		else if (isupper (c))   c -= ('A' - 10);
 | 
						|
		else if (islower (c))   c -= ('a' - 10);
 | 
						|
		else                    break;
 | 
						|
		if (c < 0 || c >= base)
 | 
						|
			break;
 | 
						|
 | 
						|
                rval *= base;
 | 
						|
                rval += c;
 | 
						|
                c = getch();
 | 
						|
                ndig++;
 | 
						|
        }
 | 
						|
        ungetch();
 | 
						|
        if (ndig)
 | 
						|
                return(rval);
 | 
						|
        experr("Bad constant");
 | 
						|
	/* NOTREACHED */
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * eqlrel : '=' | '==' | '!='
 | 
						|
 *
 | 
						|
 */
 | 
						|
int geteql()
 | 
						|
{
 | 
						|
        register int c1, c2;
 | 
						|
 
 | 
						|
        c1 = skipws();
 | 
						|
        c2 = getch();
 | 
						|
 
 | 
						|
        switch (c1) {
 | 
						|
 
 | 
						|
        case '=':
 | 
						|
                if (c2 != '=')
 | 
						|
                        ungetch();
 | 
						|
                return(EQL);
 | 
						|
 
 | 
						|
        case '!':
 | 
						|
                if (c2 == '=')
 | 
						|
                        return(NEQ);
 | 
						|
                ungetch();
 | 
						|
                ungetch();
 | 
						|
                return(-1);
 | 
						|
 
 | 
						|
        default:
 | 
						|
                ungetch();
 | 
						|
                ungetch();
 | 
						|
                return(-1);
 | 
						|
        }
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * rel : '<' | '>' | '<=' | '>='
 | 
						|
 *
 | 
						|
 */
 | 
						|
int getrel()
 | 
						|
{
 | 
						|
        register int c1, c2;
 | 
						|
 
 | 
						|
        c1 = skipws();
 | 
						|
        c2 = getch();
 | 
						|
 
 | 
						|
        switch (c1) {
 | 
						|
 
 | 
						|
        case '<':
 | 
						|
                if (c2 == '=')
 | 
						|
                        return(LEQ);
 | 
						|
                ungetch();
 | 
						|
                return(LSS);
 | 
						|
 
 | 
						|
        case '>':
 | 
						|
                if (c2 == '=')
 | 
						|
                        return(GEQ);
 | 
						|
                ungetch();
 | 
						|
                return(GTR);
 | 
						|
 
 | 
						|
        default:
 | 
						|
                ungetch();
 | 
						|
                ungetch();
 | 
						|
                return(-1);
 | 
						|
        }
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * Skip over any white space and return terminating char.
 | 
						|
 */
 | 
						|
int skipws()
 | 
						|
{
 | 
						|
        register char c;
 | 
						|
 
 | 
						|
        while ((c = getch()) <= ' ' && c > EOS)
 | 
						|
                ;
 | 
						|
        return(c);
 | 
						|
}
 | 
						|
 
 | 
						|
/*
 | 
						|
 * Error handler - resets environment to eval(), prints an error,
 | 
						|
 * and returns FALSE.
 | 
						|
 */
 | 
						|
int experr(msg)
 | 
						|
char *msg;
 | 
						|
{
 | 
						|
        printf("mp: %s\n",msg);
 | 
						|
        longjmp(expjump, -1);          /* Force eval() to return FALSE */
 | 
						|
}
 |