Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

575 lines
14 KiB

/*----------------------------------------------------------------------------
* *
* PARSEBLD.C *
* *
* Copyright (C) Microsoft Corporation 1989. *
* All Rights reserved. *
* *
*----------------------------------------------------------------------------*
* *
* Program Description: *
* This contains the function related to building the Build Expression *
* from string(i.e reverse polish expression ) and evaluating Build *
* expression( i.e reverse polish expression. ) *
* *
* *
*----------------------------------------------------------------------------*
* *
* Revision History: *
* *
* *
*----------------------------------------------------------------------------*
* *
* Known Bugs: *
* *
*---------------------------------------------------------------------------*/
#include "stdafx.h"
#pragma hdrstop
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
const int MAX_STACK = 30;
const int MAX_POLISH = 30;
const int MAX_BUILDTAG = 32;
const int MAX_FOOTBLDTAGS = 30;
typedef enum {
tokOpenBrace,
tokCloseBrace,
tokTag,
tokAnd,
tokOr,
tokNot,
tokVoidToken,
tokValidToken,
tokInvalidToken,
} TOKEN;
#define VALID_EXPRESSION TRUE
#define INVALID_EXPRESSION FALSE
// Rank values for different token
static int rgiRankValue[] = { // Rank Table
0, // OPENBARCE
0, // CLOSEBRACE
1, // TAG
-1, // AND
-1, // OR
0 // NOT
};
typedef int PREC;
typedef struct{
PREC precInput;
PREC precOutput;
} PRECENT, * QPRECENT;
// Input/Output precedence of various operators
static PRECENT PrecTab[] = {
9, 0, // OPENBARCE
0, 0, // CLOSEBRACE
7, 8, // TAG
3, 4, // AND
1, 2, // OR
6, 5 // NOT , right to left
};
typedef struct ENTRY {
TOKEN tok;
int iTokValue;
} STACK, * PSTACK;
static STACK rgstackPolish[MAX_POLISH];
static int iPolishTop;
static PSTR szExpPtr;
static INLINE BOOL FGetStackTop(PSTACK, int, PSTACK);
static INLINE BOOL FMatchTag(int, int*, int);
static INLINE BOOL FOutToPolishExp(PSTACK);
static BOOL FPopStack(PSTACK, int*, PSTACK);
static BOOL FPushStack(PSTACK, int*, PSTACK);
static INLINE PREC PrecForTok(TOKEN, BOOL);
static INLINE TOKEN TokDoToken(int);
static TOKEN TokGetBldToken(int*);
/*-----------------------------------------------------------------------------
* FBuildPolishExpFromSz()
*
* Description:
* This function builds the reversh polish expression from the given
* string. If it is a valid expression, returns TRUE else returns FALSE.
*
* Arguments:
* Build expression string.
*
* Returns;
* TRUE, if a valid expression.
* else FALSE
*-----------------------------------------------------------------------------*/
BOOL STDCALL FBuildPolishExpFromSz(PSTR szExp)
{
int iTokValue, iBldRank, iRetVal = VALID_EXPRESSION;
int iStackTop;
TOKEN tok;
PREC precCur, precStackTop;
STACK rgstackBld[MAX_STACK], stackTemp;
PSTACK pstackTemp = &stackTemp;
szExpPtr = szExp; // initialise line pointer
strcat(szExp, ")"); // append the close brace to expression
// Initialize stack and rank
iPolishTop = iStackTop = iBldRank = 0;
pstackTemp->tok = tokOpenBrace;
pstackTemp -> iTokValue = '(';
FPushStack(rgstackBld, &iStackTop, pstackTemp);
while(iRetVal == VALID_EXPRESSION) {
tok = TokGetBldToken(&iTokValue);
if (tok == tokVoidToken)
break;
else if (tok != tokInvalidToken) {
if (iStackTop < 1)
iRetVal = INVALID_EXPRESSION;
else {
precCur = PrecForTok(tok, TRUE); // Get input precedence
while(TRUE) {
FGetStackTop(rgstackBld, iStackTop, pstackTemp);
precStackTop = PrecForTok(pstackTemp->tok, FALSE);
// Output prec
if (precCur >= precStackTop)
break;
if (!FPopStack(rgstackBld, &iStackTop, pstackTemp))
return(INVALID_EXPRESSION);
if (!FOutToPolishExp(pstackTemp)) {
VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
return(INVALID_EXPRESSION);
}
iBldRank += rgiRankValue[pstackTemp->tok];
if (iBldRank < 1) {
iRetVal = INVALID_EXPRESSION;
break;
}
}
if (iRetVal != INVALID_EXPRESSION) {
// Check for matching parentheses
if (precCur != precStackTop) {
pstackTemp->tok = tok;
pstackTemp->iTokValue = iTokValue;
if (!FPushStack(rgstackBld, &iStackTop, pstackTemp)) {
VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
return(INVALID_EXPRESSION);
}
}
else {
if (!FPopStack(rgstackBld, &iStackTop, pstackTemp))
return(INVALID_EXPRESSION);
}
}
}
}
else
iRetVal = INVALID_EXPRESSION;
}
// Check for validation of expression
if (iRetVal != INVALID_EXPRESSION) {
if (iStackTop != 0 || iBldRank != 1)
iRetVal = INVALID_EXPRESSION;
}
return iRetVal;
}
/*-----------------------------------------------------------------------------
* PrecForToken()
*
* Description:
* This function returns the input/output precedence of the given
* depending on the flag.
*
* Arguments:
* 1. tok - token type.
* 2. fInput - if TRUE, return input precedence.
* else return FALSE.
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static INLINE PREC PrecForTok(TOKEN tok, BOOL fInput)
{
PRECENT* qprecTemp = &(PrecTab[tok]);
if (fInput)
return qprecTemp->precInput;
else
return qprecTemp->precOutput;
}
/*-----------------------------------------------------------------------------
* FPushStack()
*
* Description:
* This function stores the info about the token into the stack table in
* the ith entry and increments the table index for the next free entry.
*
* Arguments:
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static BOOL FPushStack(PSTACK qstackTab, int* qiTop, PSTACK qstackInfo)
{
if (*qiTop < MAX_STACK) {
memcpy((qstackTab + *qiTop), qstackInfo, sizeof(STACK));
(*qiTop) ++;
return TRUE;
}
else
return FALSE;
}
/*-----------------------------------------------------------------------------
* FPopStack()
*
* Description:
* This function returns the info about the token from the stack table
* for the ith entry and decrements the table index pointing to the next
* valid entry.
*
* Arguments:
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static BOOL FPopStack(PSTACK qstackTab, int* qiTop, PSTACK qstackInfo)
{
if (*qiTop > 0) {
(*qiTop) --;
memcpy(qstackInfo, (qstackTab + *qiTop), sizeof(STACK));
return TRUE;
}
else
return FALSE;
}
/*-----------------------------------------------------------------------------
* FGetStackTop()
*
* Description:
* This function returns the info from the ith entry of the stack
* table.
*
* Arguments:
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static INLINE BOOL FGetStackTop(PSTACK qstackTab, int iTop, PSTACK qstackInfo)
{
if (iTop > 0) {
memcpy(qstackInfo, (qstackTab + (iTop-1)), sizeof(STACK));
return TRUE;
}
else
return FALSE;
}
/*-----------------------------------------------------------------------------
* TokGetBldToken()
*
* Description:
* This function returns the token and token value by scanning the
* footnote string pointed by the global variable szExpPtr.
*
* Arguments:
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static TOKEN TokGetBldToken(int* pTokValue)
{
int iTemp;
TOKEN tok;
BOOL fContinue = TRUE, fSpecialToken = TRUE;
char szBuildToken[256];
PSTR pszToken;
pszToken = szBuildToken;
*pTokValue = -1;
ASSERT(szExpPtr);
szExpPtr = FirstNonSpace(szExpPtr, options.fDBCS); // skip the leading blanks
if (*szExpPtr == '\0')
return(tokVoidToken);
while (fContinue) {
switch(iTemp = *szExpPtr++) {
case '&':
case '|':
case '~':
case '(':
case ')':
case ' ':
case '\n':
case '\t':
if (fSpecialToken) {
*pTokValue = iTemp;
tok = TokDoToken(iTemp);
}
else { // return the token
tok = tokTag;
szExpPtr--;
}
fContinue = FALSE;
break;
default:
*pszToken++ = CharAnsiUpper(iTemp);
fSpecialToken = FALSE;
break;
}
}
*pszToken = '\0';
if (tok == tokTag) {
// Is the string token valid?
if (!ptblBuildtags ||
!(*pTokValue = ptblBuildtags->IsStringInTable(szBuildToken)))
tok = tokInvalidToken;
}
return(tok);
}
/*-----------------------------------------------------------------------------
* TokDoToken()
*
* Description:
* This function returns the token for the given integer value.
*
* Arguments:
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static INLINE TOKEN TokDoToken(int iTokenValue)
{
switch(iTokenValue) {
case '&':
return tokAnd;
case '|':
return tokOr;
case '~':
return tokNot;
case '(':
return tokOpenBrace;
case ')':
return tokCloseBrace;
default:
return tokInvalidToken;
}
}
/*-----------------------------------------------------------------------------
* FOutPolishExp()
*
* Description:
* This function pushes the stack info into the output polish stack and
* increments the stack pointer.
*
* Arguments:
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static INLINE BOOL FOutToPolishExp(PSTACK qstackInfo)
{
if (iPolishTop < MAX_STACK) {
memcpy(&(rgstackPolish[iPolishTop]), qstackInfo, sizeof(STACK));
iPolishTop++;
return TRUE;
}
else
return FALSE;
}
/***************************************************************************
*
- Name: FEvalBldExpSz
-
* Purpose:
* Evaluates the build expression for the given list of build tags.
*
* Arguments:
* pszTag: Semicolon separated list of build tags.
* perr: Pointer to error information. NULL if errors are not
* to be printed.
*
* Returns:
* Result of evaluating the build expression with the given build tags.
*
* Globals:
* Accesses global build expression stack.
*
***************************************************************************/
// REVIEW: 02-Sep-1993 [ralphw] This is pretty screwy. Rewrite when we
// have a sample file to test it on.
BOOL STDCALL FEvalBldExpSz(PSTR pszTag, PERR perr)
{
TOKEN tok;
int iCount, iTokValue, iT, iEvalTop = 0, iInpBldTag;
STACK rgstackEval[MAX_STACK], stackInfo1, stackInfo2;
PSTACK qstackInfo1, qstackInfo2;
int rgiTag[MAX_FOOTBLDTAGS], iInpTagCount = 0;
int* qiTag;
char szTagBuf[MAX_BUILDTAG + 1];
if (fBldChk == -1) // invalid build expression
return TRUE;
if (!fBldChk) {
if (perr != NULL)
VReportError(HCERR_BUILD_MISSING, &errHpj);
fBldChk = -1; // Don't give multiple error messages
return TRUE; // no Build check is to be made
}
if (!ptblBuildtags) {
if (perr != NULL)
VReportError(HCERR_BUILD_TAG_MISSING, &errHpj);
return TRUE;
}
while(*pszTag) {
pszTag = SzGetKeySz(pszTag, szTagBuf, MAX_BUILDTAG, &iCount);
if (iCount > MAX_BUILDTAG) {
if (perr != NULL)
VReportError(HCERR_BUILD_TAG_TOO_LONG, &errHpj, pszTag);
continue;
}
iInpBldTag = ptblBuildtags->IsStringInTable(szTagBuf);
if (!iInpBldTag) {
if (perr != NULL)
VReportError(HCERR_BUILD_ERROR, &errHpj);
}
else {
// See if the build tag is not duplicated in the build footnote
for (iT = 0, qiTag = rgiTag; iT < iInpTagCount; qiTag++, iT++) {
if (*qiTag == iInpBldTag)
break;
}
if (iInpTagCount >= MAX_FOOTBLDTAGS) {
VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
return FALSE;
}
if (iT == iInpTagCount)
rgiTag[iInpTagCount++] = iInpBldTag;
}
}
if (!iInpTagCount)
return TRUE;
qstackInfo1 = &stackInfo1;
qstackInfo2 = &stackInfo2;
for (iT = 1; iT <= iPolishTop; iT++) {
FGetStackTop(rgstackPolish, iT, qstackInfo1);
switch(qstackInfo1 -> tok) {
case tokTag:
qstackInfo1 -> iTokValue = FMatchTag(qstackInfo1 -> iTokValue,
rgiTag, iInpTagCount);
if (!FPushStack(rgstackEval, &iEvalTop, qstackInfo1)) {
ASSERT(FALSE);
VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
return FALSE;
}
break;
case tokNot:
if (!FPopStack(rgstackEval, &iEvalTop, qstackInfo2))
ASSERT(FALSE);
ASSERT(qstackInfo2 -> tok == tokTag);
if (qstackInfo2 -> iTokValue)
qstackInfo2 -> iTokValue = FALSE;
else qstackInfo2 -> iTokValue = TRUE;
if (!FPushStack(rgstackEval, &iEvalTop, qstackInfo2))
ASSERT(FALSE);
break;
case tokAnd:
case tokOr:
if (!FPopStack(rgstackEval, &iEvalTop, qstackInfo2))
ASSERT(FALSE);
tok = qstackInfo2 -> tok;
iTokValue = qstackInfo2 -> iTokValue;
ASSERT(tok == tokTag);
if (!FPopStack(rgstackEval, &iEvalTop, qstackInfo2))
ASSERT(FALSE);
if (qstackInfo1 -> tok == tokAnd)
qstackInfo2 -> iTokValue &= iTokValue;
else
qstackInfo2 -> iTokValue |= iTokValue;
if (!FPushStack(rgstackEval, &iEvalTop, qstackInfo2))
ASSERT(FALSE);
break;
default:
break;
}
}
ASSERT(iEvalTop == 1);
ConfirmOrDie(FPopStack(rgstackEval, &iEvalTop, qstackInfo1));
return(qstackInfo1 -> iTokValue);
}
/*-----------------------------------------------------------------------------
* FMatchTag()
*
* Description:
* This function matches the tag with the tag table formed from the
* build tag footnote and returns TRUE if found else returns FALSE.
*
* Arguments:
*
* Returns;
* precedence value for the given token.
*-----------------------------------------------------------------------------*/
static INLINE BOOL FMatchTag(int iTag, int* pTag, int iInpTagCount)
{
for (int i = 0; i < iInpTagCount; i++, pTag++) {
if (*pTag == iTag)
return TRUE;
}
return FALSE;
}