Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!seismo!mcvax!botter!erikb From: erikb@botter.UUCP Newsgroups: comp.os.minix Subject: expr(1) source Message-ID: <1133@botter.cs.vu.nl> Date: Fri, 3-Apr-87 01:17:58 EST Article-I.D.: botter.1133 Posted: Fri Apr 3 01:17:58 1987 Date-Received: Sun, 5-Apr-87 04:41:09 EST Sender: remote@cs.vu.nl Reply-To: erikb@cs.vu.nl (Erik Baalbergen) Distribution: world Organization: V.U. Informatica, Amsterdam Lines: 189 Here's the source for expr(1). Like test(1), this program was not part of the Minix distribution. Unfortunately, I didn't have time to implement the ':' operator. Maybe there's someone else out there who will do the job... Erik Baalbergen -- cut here -- /* expr(1) -- author Erik Baalbergen */ /* expr accepts the following grammar: expr ::= expr operator expr | "(" expr ")" ; where the priority of the operators is taken care of. The resulting value is printed on stdout. Note that the ":"-operator is not implemented. */ #define EOI 0 #define OR 1 #define AND 2 #define LT 3 #define LE 4 #define EQ 5 #define NE 6 #define GE 7 #define GT 8 #define PLUS 9 #define MINUS 10 #define TIMES 11 #define DIV 12 #define MOD 13 #define COLON 14 #define LPAREN 15 #define RPAREN 16 #define OPERAND 20 #define MAXPRIO 6 struct op { char *op_text; short op_num, op_prio; } ops[] = { {"|", OR, 6}, {"&", AND, 5}, {"<", LT, 4}, {"<=", LE, 4}, {"=", EQ, 4}, {"!=", NE, 4}, {">=", GE, 4}, {">", GT, 4}, {"+", PLUS, 3}, {"-", MINUS, 3}, {"*", TIMES, 2}, {"/", DIV, 2}, {"%", MOD, 2}, /* {":", COLON, 1}, */ {"(", LPAREN, 0}, {")", RPAREN, 0}, {0, 0, 0} }; long eval(), expr(); char *prog; char **ip; struct op *ip_op; main(argc, argv) char *argv[]; { long res; prog = argv[0]; ip = &argv[1]; res = expr(lex(*ip), MAXPRIO); if (*++ip != 0) syntax(); printf("%ld\n", res); exit(0); } lex(s) register char *s; { register struct op *op = ops; if (s == 0) { ip_op = 0; return EOI; } while (op->op_text) { if (strcmp(s, op->op_text) == 0) { ip_op = op; return op->op_num; } op++; } ip_op = 0; return OPERAND; } long num(s) register char *s; { long l = 0; long sign = 1; if (*s == '\0') syntax(); if (*s == '-') { sign = -1; s++; } while (*s >= '0' && *s <= '9') l = l * 10 + *s++ - '0'; if (*s != '\0') syntax(); return sign * l; } syntax() { write(2, prog, strlen(prog)); write(2, ": syntax error\n", 15); exit(1); } long expr(n, prio) { long res; if (n == EOI) syntax(); if (n == LPAREN) { res = expr(lex(*++ip), MAXPRIO); if (lex(*++ip) != RPAREN) syntax(); return res; } if (n != OPERAND) syntax(); if (prio == 0) return num(*ip); res = expr(n, prio - 1); while ((n = lex(*++ip)) && ip_op && ip_op->op_prio == prio) res = eval(res, n, expr(lex(*++ip), prio - 1)); ip--; return res; } long eval(l1, op, l2) long l1, l2; { switch (op) { case OR: return l1 ? l1 : l2; case AND: return (l1 && l2) ? l1 : 0; case LT: return l1 < l2; case LE: return l1 <= l2; case EQ: return l1 == l2; case NE: return l1 != l2; case GE: return l1 >= l2; case GT: return l1 > l2; case PLUS: return l1 + l2; case MINUS: return l1 - l2; case TIMES: return l1 * l2; case DIV: return l1 / l2; case MOD: return l1 % l2; } fatal(); } fatal() { write(2, "fatal\n", 6); exit(1); }