Windows-Server-2003/sdktools/hivepp/p0expr.c

309 lines
7.4 KiB
C

/************************************************************************/
/* */
/* RCPP - Resource Compiler Pre-Processor for NT system */
/* */
/* P0EXPR.C - Expression routines for Pre-Processor */
/* */
/* AUTHOR - Ralph Ryan, Sept. 16, 1982 */
/* 06-Dec-90 w-BrianM Update for NT from PM SDK RCPP */
/* */
/************************************************************************/
/*
* DESCRIPTION
* Evaluate the constant expression. Since these routines are
* all recursively coupled, it is clearer NOT to document them
* with the standard header. Instead, BML (British Meta Language,
* a BNF like meta language) will be given for each "production"
* of this recursive descent parser.
*
* Note - Sure, yeah, right. Frankly, I'm frightened! (w-BrianM)
************************************************************************/
#include <stdio.h>
#include "rcpptype.h"
#include "rcppdecl.h"
#include "rcppext.h"
#include "grammar.h"
/************************************************************************/
/* Local Function Prototypes */
/************************************************************************/
long and(void);
long andif(void);
long constant(void);
long constexpr(void);
long eqset(void);
long mult(void);
long or(void);
long orelse(void);
long plus(void);
long prim(void);
long relation(void);
long shift(void);
long xor(void);
/************************************************************************/
/* File Global Variables */
/************************************************************************/
long Currval = 0;
static int Parencnt = 0;
/************************************************************************/
/* do_constexpr() */
/************************************************************************/
long do_constexpr(void)
{
REG long val;
Parencnt = 0;
Currtok = L_NOTOKEN;
val = constexpr();
if( Currtok == L_RPAREN ) {
if( Parencnt-- == 0 ) {
Msg_Temp = GET_MSG(1012);
SET_MSG (Msg_Text, Msg_Temp, "(");
fatal(1012); /* missing left paren */
}
}
else if( Currtok != L_NOTOKEN ) {
Msg_Temp = GET_MSG(4067);
SET_MSG (Msg_Text, Msg_Temp, PPifel_str);
warning(4067);
}
if( Parencnt > 0 ) {
Msg_Temp = GET_MSG(4012);
SET_MSG (Msg_Text, Msg_Temp, ")");
fatal(4012); /* missing right paren */
}
return(val);
}
/************************************************************************/
/* constexpr ::= orelse [ '?' orelse ':' orelse ]; */
/************************************************************************/
long constexpr(void)
{
REG long val;
REG long val1;
long val2;
val = orelse();
if( nextis(L_QUEST) ) {
val1 = orelse();
if( nextis(L_COLON) )
val2 = orelse();
return(val ? val1 : val2);
}
return(val);
}
/************************************************************************/
/* orelse ::= andif [ '||' andif ]* ; */
/************************************************************************/
long orelse(void)
{
REG long val;
val = andif();
while(nextis(L_OROR))
val = andif() || val;
return(val);
}
/************************************************************************/
/* andif ::= or [ '&&' or ]* ; */
/************************************************************************/
long andif(void)
{
REG long val;
val = or();
while(nextis(L_ANDAND))
val = or() && val;
return(val);
}
/************************************************************************/
/* or ::= xor [ '|' xor]* ; */
/************************************************************************/
long or(void)
{
REG long val;
val = xor();
while( nextis(L_OR) )
val |= xor();
return(val);
}
/************************************************************************/
/* xor ::= and [ '^' and]* ; */
/************************************************************************/
long xor(void)
{
REG long val;
val = and();
while( nextis(L_XOR) )
val ^= and();
return(val);
}
/************************************************************************/
/* and ::= eqset [ '&' eqset]* ; */
/************************************************************************/
long and(void)
{
REG long val;
val = eqset();
while( nextis(L_AND) )
val &= eqset();
return(val);
}
/************************************************************************/
/* eqset ::= relation [ ('==' | '!=') eqset] ; */
/************************************************************************/
long eqset(void)
{
REG long val;
val = relation();
if( nextis(L_EQUALS) )
return(val == relation());
if( nextis(L_NOTEQ) )
return(val != relation());
return(val);
}
/************************************************************************/
/* relation ::= shift [ ('<' | '>' | '<=' | '>=' ) shift] ; */
/************************************************************************/
long relation(void)
{
REG long val;
val = shift();
if( nextis(L_LT) )
return(val < shift());
if( nextis(L_GT) )
return(val > shift());
if( nextis(L_LTEQ) )
return(val <= shift());
if( nextis(L_GTEQ) )
return(val >= shift());
return(val);
}
/************************************************************************/
/* shift ::= plus [ ('<< | '>>') plus] ; */
/************************************************************************/
long shift(void)
{
REG long val;
val = plus();
if( nextis(L_RSHIFT) )
return(val >> plus());
if( nextis(L_LSHIFT) )
return(val << plus());
return(val);
}
/************************************************************************/
/* plus ::= mult [ ('+' | '-') mult ]* ; */
/************************************************************************/
long plus(void)
{
REG long val;
val = mult();
for(;;) {
if( nextis(L_PLUS) )
val += mult();
else if( nextis(L_MINUS) )
val -= mult();
else
break;
}
return(val);
}
/************************************************************************/
/* mult ::= prim [ ('*' | '/' | '%' ) prim ]* ; */
/************************************************************************/
long mult(void)
{
REG long val;
val = prim();
for(;;) {
if( nextis(L_MULT) )
val *= prim();
else if( nextis(L_DIV) )
val /= prim();
else if( nextis(L_MOD) )
val %= prim();
else
break;
}
return(val);
}
/************************************************************************/
/* prim ::= constant | ( '!' | '~' | '-' ) constant */
/************************************************************************/
long prim(void)
{
if( nextis(L_EXCLAIM) )
return( ! constant());
else if( nextis(L_TILDE) )
return( ~ constant() );
else if( nextis(L_MINUS) )
return(-constant());
else
return(constant());
}
/************************************************************************/
/* constant - at last, a terminal symbol | '(' constexpr ')' */
/************************************************************************/
long constant(void)
{
REG long val;
if( nextis(L_LPAREN) ) {
Parencnt++;
val = constexpr();
if( nextis(L_RPAREN) ) {
Parencnt--;
return(val);
}
else {
Msg_Temp = GET_MSG(1012);
SET_MSG (Msg_Text, Msg_Temp, ")");
fatal (1012);
}
}
else if( ! nextis(L_CINTEGER) ) {
Msg_Temp = GET_MSG(1017);
SET_MSG (Msg_Text, Msg_Temp);
fatal(1017); /* invalid integer constant expression */
}
return(Currval);
}