/* ************************************************************ ACRL Expression evaluator ************************************************************ W. Lemiszki 9 Jan 1982 Filename: aexp.c BDS C v1.50 */ #include "acrl.h" /* Scans the next expression from the input line and returns its value. The global 'xrel' is set TRUE if the expression is relocatable. This routine (and expr(), and operand()) assumes that the first token has already been scanned. expr() takes a precedence argument and scans recursively until it finds an operator that has lower precedence. operand() scans operands and handles unary operators and parenthesized sub expressions. */ int expression() { return (expr(0)); /* start with precedence 0 */ } int expr(lprec) byte lprec; { byte op, rprec, urel; int u, v; u = operand(); /* scan an operand */ while (class == OPERATOR && (rprec = prec(type)) > lprec) { op = type; /* save operator type */ urel = xrel; /* save reloc attr */ scan(); /* next token */ v = expr(rprec); /* get right 'operand' */ xrel = opreloc(op, urel, xrel); /* compute reloc atribute */ u = operate(op, u, v); /* perform operator */ } return (u); } /* * Return the precedence of an operator * ------------------------------------ */ byte prec(op) byte op; { switch (op) { case '*': case '/': case opMOD: case opSHL: case opSHR: return (6); case '+': case '-': return (4); case opAND: return (2); default: return (1); } } /* * Compute the relocatability of an operation * ------------------------------------------ */ int opreloc(op, urel, vrel) byte op; /* the operator */ byte urel; /* reloc. atr. of left operand */ byte vrel; /* reloc. atr. of right operand */ { if (!urel && !vrel) /* both absolute */ return FALSE; if (op == '-' && urel && vrel) /* rel - rel */ return FALSE; if (op == '+' && !urel && vrel) /* abs + rel */ return TRUE; if ((op == '+' || op == '-') && urel && !vrel) return TRUE; /* rel +/- abs */ error('T'); /* all others illegal */ return FALSE; } /* * Perform an operator function * ---------------------------- */ int operate(op, u, v) byte op; /* the operator */ int u; /* left operand */ int v; /* right operand */ { switch (op) { case '+': return (u + v); case '-': return (u - v); case '*': return (u * v); case '/': return (u / v); case opAND: return (u & v); case opOR: return (u | v); case opXOR: return (u ^ v); case opMOD: return (u % v); case opSHR: return (u >> v); case opSHL: return (u << v); } } /* * Operand Scanning * ---------------- */ int operand() { int v; if (type == '-') /* if '-' operator... */ class = OPERAND; /* make it unary minus */ if (class == IDENT) /* if identifier... */ { if (type == idUND) /* check for errors */ error ('U'); /* undefined */ if (type == idFUNC) error ('X'); /* external error */ class = OPERAND; /* then make it ok */ type = NUMBER; } if (class == STRING && tokbuf[1] == EOS) /* if 1 char string... */ { value = *tokbuf; /* use its ASCII code */ class = OPERAND; type = NUMBER; } if (class != OPERAND) /* if not an operand... */ { error('E'); /* expression error */ return (0); } switch (type) { case '-': /* unary - */ v = -unary(); break; case opNOT: /* unary NOT */ v = ~unary(); break; case opHIGH: /* unary HIGH */ v = unary() >> 8; break; case opLOW: /* unary LOW */ v = unary() & 0xFF; break; case '$': /* location counter */ if (!infunc) error('E'); /* expression error */ v = floc; xrel = TRUE; scan(); break; case '(': /* subexpression */ scan(); v = expression(); if (type != ')') error('B'); /* balance error */ scan(); break; default: v = value; /* current token params */ xrel = reloc; scan(); } return (v); } /* Prepare for unary operation */ int unary() { int v; scan(); v = operand(); if (xrel) /* unarys illegal on relocs */ { error('T'); /* type error */ xrel = 0; } return (v); } /*EOF*/