#include #include /* grammar: Start = Expr ';' Expr = Or | Or '?' Expr ':' Expr Or = And | Or '||' And And = Eq | And '&&' Eq Eq = Rel | Eq '==' Rel | Eq '!=' Rel Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add Add = Mul | Add '+' Mul | Add '-' Mul Mul = Term | Mul '*' Term | Mul '/' Term | Mul '%' Term Term = '(' Expr ')' | '!' Term | decimal | 'n' internals: recursive descent expression evaluator with stack depth limit. eval* functions return the value of the subexpression and set the current string pointer to the next non-space char. */ struct st { const char *s; unsigned long n; int err; }; static const char *skipspace(const char *s) { while (isspace(*s)) s++; return s; } static unsigned long fail(struct st *st) { st->err = 1; return 0; } static unsigned long evalexpr(struct st *st, int d); static unsigned long evalterm(struct st *st, int d) { unsigned long a; char *e; if (--d < 0) return fail(st); st->s = skipspace(st->s); if (*st->s == '!') { st->s++; return !evalterm(st, d); } if (*st->s == '(') { st->s++; a = evalexpr(st, d); if (*st->s != ')') return fail(st); st->s = skipspace(st->s + 1); return a; } if (*st->s == 'n') { st->s = skipspace(st->s + 1); return st->n; } a = strtoul(st->s, &e, 10); if (!isdigit(*st->s) || e == st->s || a == -1) return fail(st); st->s = skipspace(e); return a; } static unsigned long binop(struct st *st, int op, unsigned long a, unsigned long b) { switch (op&0xff) { case 0: return a||b; case 1: return a&&b; case 2: return a==b; case 3: return a!=b; case 4: return a>=b; case 5: return a<=b; case 6: return a>b; case 7: return as == opch[i]) { p = prec[i]<<8; if (i<6 && st->s[1] == opch[i+12]) { st->s+=2; return i | p; } if (i>=4) { st->s++; return i+2 | p; } return 0; } return 0; } static unsigned long evalbinop2(struct st *st, int op, unsigned long a, int d) { unsigned long a2; int op2, highprec; d--; for (;;) { a2 = evalterm(st, d); op2 = parseop(st); highprec = op2>>8 > op>>8; if (highprec) a2 = evalbinop2(st, op2, a2, d); a = binop(st, op, a, a2); if (!op2 || highprec) return a; op = op2; } } static unsigned long evalbinop(struct st *st, int d) { unsigned long a; int op; a = evalterm(st, d); op = parseop(st); if (!op) return a; return evalbinop2(st, op, a, d); } static unsigned long evalexpr(struct st *st, int d) { unsigned long a1, a2, a3; if (--d < 0) return fail(st); a1 = evalbinop(st, d); if (*st->s != '?') return a1; st->s++; a2 = evalexpr(st, d); if (*st->s != ':') return fail(st); st->s++; a3 = evalexpr(st, d); return a1 ? a2 : a3; } unsigned long __pleval(const char *s, unsigned long n) { unsigned long a; struct st st; st.s = s; st.n = n; st.err = 0; a = evalexpr(&st, 100); if (st.err || *st.s != ';') return -1; return a; }