home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
131_01
/
aexp.c
< prev
next >
Wrap
Text File
|
1985-03-10
|
5KB
|
255 lines
/*
************************************************************
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*/