home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
c
/
library
/
xplatfrm
/
motxas
/
eval.c
< prev
next >
Wrap
Text File
|
1990-07-14
|
7KB
|
232 lines
/*
* eval --- evaluate expression
*
* an expression is constructed like this:
*
* expr ::= expr + term |
* expr - term |
* expr * term |
* expr / term |
* expr | term |
* expr & term |
* expr % term |
* expr ^ term ;
*
* term ::= symbol |
* * | <-- program counter at start of current line
* constant ;
*
* symbol ::= string of alphanumerics with initial alpha char,
* underscore, or period ;
*
* constant ::= hex constant |
* binary constant |
* octal constant |
* decimal constant |
* ascii constant ;
*
* hex constant ::= $<hex digits> ;
*
* octal constant ::= @<octal digits> ;
*
* binary constant ::= %<binary digits> ;
*
* decimal constant ::= <decimal digits> ;
*
* ascii constant ::= '<any printing char> ;
*
*/
eval()
{
int left,right; /* left and right terms for expression */
char o; /* operator character */
#ifdef DEBUG
printf("Evaluating %s\n",Optr);
#endif
Force_byte = NO;
Force_word = NO;
Result = 0;
if(*Optr=='<'){
Force_byte++;
Optr++;
}
else if(*Optr=='>'){
Force_word++;
Optr++;
}
left = get_term(); /* pickup first part of expression */
if( Term_err ) return(NO);
while( is_op(*Optr) ) {
o = *Optr++; /* pickup connector and skip */
right = get_term(); /* pickup current rightmost side */
if( Term_err ) {
Result = 0;
return(NO);
}
switch(o){
case '+': left += right; break;
case '-': left -= right; break;
case '*': left *= right; break;
case '/': left /= right; break;
case '|': left |= right; break;
case '&': left &= right; break;
case '%': left %= right; break;
case '^': left = left^right; break;
}
}
Result= left;
#ifdef DEBUG
printf("Result=%x\n",Result);
printf("Force_byte=%d Force_word=%d\n",Force_byte,Force_word);
#endif
if( !any( *Optr, " \t\n,;" ) && *Optr!=EOS ) {
error( "Improper character in expression" );
return(NO);
}
return(YES);
}
/*
* is_op --- is character an expression operator?
*/
is_op(c)
char c;
{
if( any(c,"+-*/&%|^"))
return(YES);
return(NO);
}
/*
* get_term --- evaluate a single item in an expression
*/
get_term()
{
char hold[MAXBUF];
char *tmp;
int val = 0; /* local value being built */
int minus; /* unary minus flag */
struct nlist *lookup(),*pointer;
struct link *pnt,*bpnt;
Term_err = NO;
if( *Optr == '-' ){
Optr++;
minus =YES;
}
else
minus = NO;
while( *Optr == '#' ) Optr++;
if( *Optr == '-' ) { /* allow - on either side of # */
if( minus == NO ) {
Optr++;
minus = YES;
}
else { /* don't allow - on both sides of # */
error("Minus signs on both sides of #");
Term_err = YES;
return(val);
}
}
/* look at rest of expression */
if(*Optr=='%'){ /* binary constant */
Optr++;
while( any(*Optr,"01"))
val = (val * 2) + ( (*Optr++)-'0');
}
else if(*Optr=='@'){ /* octal constant */
Optr++;
while( any(*Optr,"01234567"))
val = (val * 8) + ((*Optr++)-'0');
}
else if(*Optr=='$'){ /* hex constant */
Optr++;
while( any(*Optr,"0123456789abcdefABCDEF")) {
if( *Optr > '9' )
val = (val * 16) + 10 + (mapdn(*Optr++)-'a');
else
val = (val * 16) + ((*Optr++)-'0');
}
}
else if( any(*Optr,"0123456789")){ /* decimal constant */
while(*Optr >= '0' && *Optr <= '9')
val = (val * 10) + ( (*Optr++)-'0');
}
else if(*Optr=='*'){ /* current location counter */
Optr++;
val = Old_pc;
}
else if(*Optr=='\''){ /* character literal */
Optr++;
if(*Optr == EOS) {
error("NULL character constant not allowed");
val = 0;
Term_err = YES;
}
else {
val = *Optr++;
if(*Optr=='\'') Optr++; /* allow closing quote */
}
}
else if( alpha(*Optr) ){ /* a symbol */
tmp = hold; /* collect symbol name */
while(alphan(*Optr))
*tmp++ = *Optr++;
*tmp = EOS;
pointer = lookup(hold);
if (pointer != NULL)
{
if (Pass == 2)
{
pnt = pointer->L_list;
bpnt = NULL;
while (pnt != NULL)
{
bpnt = pnt;
pnt = pnt->next;
}
pnt = (struct link *) alloc(sizeof(struct link));
if (bpnt == NULL)
pointer->L_list = pnt;
else bpnt->next = pnt;
pnt->L_num = Line_num;
pnt->next = NULL;
}
val = Last_sym;
}
else{
if(Pass==1){ /* forward ref here */
fwdmark();
if( !Force_byte )
Force_word++;
val = 0;
}
}
if(Pass==2 && Line_num==F_ref && Cfn==Ffn){
if( !Force_byte )
Force_word++;
fwdnext();
}
}
else { /* none of the above */
if( white(*Optr) ) error("Whitespace not allowed in expression");
else error("Missing or unidentifiable operand ");
val = 0;
Term_err = YES;
}
if(minus)
return(-val);
else
return(val);
}