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

336 lines
7.7 KiB
C

/***********************************************************************
* Microsoft (R) Windows (R) Resource Compiler
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* File Comments:
*
*
***********************************************************************/
#include "rc.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 ) {
fatal(1012, L"("); /* missing left paren */
}
} else if( Currtok != L_NOTOKEN ) {
warning(4067, PPifel_str);
}
if( Parencnt > 0 ) {
fatal(4012, L")"); /* 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;
long PrimVal;
val = prim();
for(;;) {
if( nextis(L_MULT) )
val *= prim();
else if( nextis(L_DIV) ) {
PrimVal = prim();
if (PrimVal)
val /= PrimVal;
else
val = PrimVal;
}
else if( nextis(L_MOD) ) {
PrimVal = prim();
if (PrimVal)
val %= PrimVal;
else
val = 0;
}
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 {
fatal(1012, L")");
}
} else if( ! nextis(L_CINTEGER) ) {
fatal(1017); /* invalid integer constant expression */
}
return(Currval);
}