Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1528 lines
50 KiB

// Copyright (c) 1996-1999 Microsoft Corporation
/*
* state1.c - implements the state machine to track constructs
*/
#include "gpdparse.h"
// ---- functions defined in state1.c ---- //
BOOL BInterpretTokens(
PTKMAP ptkmap, // pointer to tokenmap
BOOL bFirstPass, // is this the first or 2nd time around?
PGLOBL pglobl
) ;
BOOL BprocessSpecialKeyword(
PTKMAP ptkmap, // pointer to tokenmap
BOOL bFirstPass, // is this the first or 2nd time around?
PGLOBL pglobl
) ;
BOOL BprocessSymbolKeyword(
PTKMAP ptkmap, // pointer to current entry in tokenmap
PGLOBL pglobl
) ;
VOID VinitAllowedTransitions(
PGLOBL pglobl
);
BOOL BpushState(
PTKMAP ptkmap, // pointer to current entry in tokenmap
BOOL bFirstPass,
PGLOBL pglobl
) ;
BOOL BchangeState(
PTKMAP ptkmap, // pointer to construct in tokenmap
CONSTRUCT eConstruct, // this will induce a transition to NewState
STATE stOldState,
BOOL bSymbol, // should dwValue be saved as a SymbolID ?
BOOL bFirstPass,
PGLOBL pglobl
) ;
DWORD DWregisterSymbol(
PABSARRAYREF paarSymbol, // the symbol string to register
CONSTRUCT eConstruct , // type of construct determines class of symbol.
BOOL bCopy, // shall we copy paarSymbol to heap? May set
DWORD dwFeatureID, // if you are registering an option symbol
PGLOBL pglobl
) ;
BOOL BaddAARtoHeap(
PABSARRAYREF paarSrc,
PARRAYREF parDest,
DWORD dwAlign,
PGLOBL pglobl) ;
BOOL BwriteToHeap(
OUT PDWORD pdwDestOff, // heap offset of dest string
PBYTE pubSrc, // points to src string
DWORD dwCnt, // num bytes to copy from src to dest.
DWORD dwAlign,
PGLOBL pglobl) ;
DWORD DWsearchSymbolListForAAR(
PABSARRAYREF paarSymbol,
DWORD dwNodeIndex,
PGLOBL pglobl) ;
DWORD DWsearchSymbolListForID(
DWORD dwSymbolID, // find node containing this ID.
DWORD dwNodeIndex,
PGLOBL pglobl
) ;
BOOL BCmpAARtoAR(
PABSARRAYREF paarStr1,
PARRAYREF parStr2,
PGLOBL pglobl
) ;
BOOL BpopState(
PGLOBL pglobl
) ;
VOID VinitDictionaryIndex(
PGLOBL pglobl
) ;
VOID VcharSubstitution(
PABSARRAYREF paarStr,
BYTE ubTgt,
BYTE ubReplcmnt,
PGLOBL pglobl
) ;
VOID VIgnoreBlock(
PTKMAP ptkmap,
BOOL bIgnoreBlock,
PGLOBL pglobl
) ;
// ---------------------------------------------------- //
BOOL BInterpretTokens(
PTKMAP ptkmap, // pointer to tokenmap
BOOL bFirstPass, // is this the first or 2nd time around?
PGLOBL pglobl
)
{
DWORD dwKeywordID ;
KEYWORD_TYPE eType;
WORD wEntry ;
BOOL bStatus = FALSE ;
if(bFirstPass)
{
// This bit of code creates a synthesized inputslot
// which the UI code will interpret as the UseFormToTrayTable
// BUG_BUG!!!: should be replaced by preprocessing
// shortcuts etc. Or by an option in stdnames.gpd
ABSARRAYREF aarSymbol ;
DWORD dwFeaID ;
aarSymbol.pub = "InputBin" ; // no way to keep this in ssync
// with the global table.
aarSymbol.dw = strlen(aarSymbol.pub) ;
dwFeaID = DWregisterSymbol(&aarSymbol, CONSTRUCT_FEATURE,
TRUE, INVALID_SYMBOLID, pglobl) ;
if(dwFeaID != INVALID_SYMBOLID)
{
aarSymbol.pub = "FORMSOURCE" ; // no way to keep this in ssync
// with the global table.
aarSymbol.dw = strlen(aarSymbol.pub) ;
dwFeaID = DWregisterSymbol(&aarSymbol, CONSTRUCT_OPTION,
TRUE, dwFeaID, pglobl) ;
ASSERT(dwFeaID == 0); // this option must be first.
}
}
else
{
ARRAYREF arStrValue ;
BOOL bPrevsExists ;
if(!BwriteToHeap(&arStrValue.loOffset, "\0\0", 2, 4, pglobl) )
{
bStatus = FALSE ; // heap overflow start over.
}
arStrValue.dwCount = 0 ; // create a NULL unicode string.
BexchangeArbDataInFOATNode(
0 , // dwFea
0, // dwOption,
offsetof(DFEATURE_OPTIONS, atrOptDisplayName ),
sizeof(ARRAYREF),
NULL, // previous contents of attribute node
(PBYTE)&arStrValue, // new contents of attribute node.
&bPrevsExists, // previous contents existed.
FALSE, // access synthetic features
pglobl
) ;
}
for(wEntry = 0 ; geErrorSev < ERRSEV_RESTART ; wEntry++)
{
// These ID's must be processed separately
// because they do not index into the mainKeyword table.
// The code for generic ID's will fail.
dwKeywordID = ptkmap[wEntry].dwKeywordID ;
if (dwKeywordID == gdwID_IgnoreBlock)
{
VIgnoreBlock(ptkmap + wEntry, TRUE, pglobl) ;
continue ;
}
switch(dwKeywordID)
{
case (ID_EOF):
{
// BUG_BUG!!! Cleanup code here
// integrity checking code:
// check to see mdwCurStsPtr == 0
// and any other loose ends are tied.
bStatus = (mdwCurStsPtr) ? (FALSE) : (TRUE);
return(bStatus) ;
}
case (ID_NULLENTRY):
{
continue ; // does this work?
// should drop to bottom of FOREVER for loop.
}
case (ID_SYMBOL):
{
bStatus = BprocessSymbolKeyword(ptkmap + wEntry, pglobl) ;
continue ; // uses TKMF_SYMBOL_REGISTERED to track passes
}
case (ID_UNRECOGNIZED):
{ // if identified on first pass, won't pass this way again!
if(bStatus = BidentifyAttributeKeyword(ptkmap + wEntry, pglobl) )
{
dwKeywordID = ptkmap[wEntry].dwKeywordID ;
break ; // fall out of switch statement
// and into next switch.
}
if(bFirstPass)
{
vIdentifySource(ptkmap + wEntry, pglobl) ;
ERR(("Warning, unrecognized keyword: %0.*s\n", \
ptkmap[wEntry].aarKeyword.dw, \
ptkmap[wEntry].aarKeyword.pub));
VIgnoreBlock(ptkmap + wEntry, FALSE, pglobl) ;
// if this keyword is immediately
// followed by open brace, ignore all
// statements from there until the matching closing
// brace.
}
continue ;
}
default :
break ;
}
eType = mMainKeywordTable[dwKeywordID].eType ;
switch (eType)
{
case (TY_CONSTRUCT):
{
if( CONSTRUCT_CLOSEBRACE ==
(CONSTRUCT)(mMainKeywordTable[dwKeywordID].dwSubType))
{
bStatus = BpopState(pglobl) ;
if(!bStatus)
{
vIdentifySource(ptkmap + wEntry, pglobl) ;
ERR(("Unmatched closing brace!\n"));
}
}
else
{
bStatus = BpushState(ptkmap + wEntry, bFirstPass, pglobl) ;
if(!bStatus)
{
vIdentifySource(ptkmap + wEntry, pglobl) ;
// ERR(("Fatal error parsing construct.\n"));
// stack is now invalid.
// in the future make parser smarter -
// eject contents between braces.
// geErrorType = ERRTY_SYNTAX ;
// geErrorSev = ERRSEV_FATAL ;
}
}
break ;
}
case (TY_ATTRIBUTE) :
{
if(!bFirstPass) // must wait till all attribute
{ // buffers are allocated.
bStatus = BprocessAttribute(ptkmap + wEntry, pglobl) ;
if(!bStatus)
{
vIdentifySource(ptkmap + wEntry, pglobl) ;
}
}
break ;
}
case (TY_SPECIAL) :
{
bStatus = BprocessSpecialKeyword(ptkmap + wEntry,
bFirstPass, pglobl) ; // don't really know if 2 passes
{ // are needed.
if(!bStatus)
{
vIdentifySource(ptkmap + wEntry, pglobl) ;
}
}
break ;
}
default:
{
vIdentifySource(ptkmap + wEntry, pglobl) ;
ERR(("Internal Error: unrecognized keyword type! %0.*s.\n",
ptkmap[wEntry].aarKeyword.dw,
ptkmap[wEntry].aarKeyword.pub));
geErrorSev = ERRSEV_FATAL ;
geErrorType = ERRTY_CODEBUG ;
break ;
}
}
}
if(geErrorSev >= ERRSEV_RESTART)
bStatus = FALSE ;
return(bStatus) ;
}
BOOL BprocessSpecialKeyword(
PTKMAP ptkmap, // pointer to tokenmap
BOOL bFirstPass, // is this the first or 2nd time around?
PGLOBL pglobl
)
{
DWORD dwKeywordID, dwOffset ;
CONSTRUCT eSubType ;
BOOL bStatus = FALSE ;
STATE stState ;
dwKeywordID = ptkmap->dwKeywordID ;
eSubType = (SPECIAL)(mMainKeywordTable[dwKeywordID].dwSubType) ;
dwOffset = mMainKeywordTable[dwKeywordID].dwOffset ;
if(mdwCurStsPtr)
stState = mpstsStateStack[mdwCurStsPtr - 1].stState ;
else
stState = STATE_ROOT ;
switch(eSubType)
{
// note: for the record I despise special casing these
// shortcuts. Ideally I could preprocess them
// to convert
// *TTFS: "font name" : <fontID>
// into
// *TTFontSub: <unique value symbol>
// {
// *TTFontName: "font name"
// *DevFontID: <fontID>
// }
// the only glitch with this is if the same font is listed
// multiple times in the GPD file, it will appear
// in the TTFontSubTable multiple times.
#if 0
case SPEC_FONTSUB :
{
ARRAYREF arFontname ;
ABSARRAYREF aarFontname ;
if(stState != STATE_ROOT)
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("The *TTFS keyword must reside at the root level.\n"));
return(FALSE) ;
}
if(bFirstPass)
{
// parse string value and register as a symbol.
if((ptkmap->dwFlags & TKMF_NOVALUE ) ||
!BparseString(&ptkmap->aarValue, &arFontname) )
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("*TTFS fontname is not a valid string value.\n"));
return(FALSE) ;
}
if(ptkmap->aarValue.pub[0] != ':')
{
ERR(("Colon delimiter expected after parsing fontname string for *TTFontSub.\n")) ;
return(FALSE) ;
}
// a keyword with a composite value
(VOID)BeatDelimiter(&ptkmap->aarValue, ":") ;
// I know this will succeed!
// paarValue should now contain the integer
// fontID. Leave this for the 2nd pass.
// convert arFontname to aar suitable for
// Font registration.
aarFontname.dw = arFontname.dwCount ;
aarFontname.pub = arFontname.loOffset + mpubOffRef;
// New version of DWregisterSymbol registers the entire
// string - whitespaces and all.
//
// Note suppress copying symbol into Heap since
// ParseString has already done that.
ptkmap->dwValue = DWregisterSymbol(&aarFontname,
CONSTRUCT_TTFONTSUBS, FALSE, pglobl ) ;
if(ptkmap->dwValue != INVALID_SYMBOLID)
{
ptkmap->dwFlags |= TKMF_SYMBOL_REGISTERED ;
}
else
{
return(FALSE) ;
}
}
else if(ptkmap->dwFlags & TKMF_SYMBOL_REGISTERED)
// second pass, TTFONTSUBTABLE arrays allocated
// for all successfully registered entrants.
{
PSYMBOLNODE psn ;
DWORD dwDevFontID ;
PTTFONTSUBTABLE pttft ;
DWORD dwTTFontNameIndex ;
psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
pttft = (PTTFONTSUBTABLE)
gMasterTable[MTI_TTFONTSUBTABLE].pubStruct;
pttft += ptkmap->dwValue ; // index correct element.
dwTTFontNameIndex = DWsearchSymbolListForID(ptkmap->dwValue,
mdwTTFontSymbols, pglobl) ;
ASSERT(dwTTFontNameIndex != INVALID_INDEX) ;
pttft->arTTFontName = psn[dwTTFontNameIndex].arSymbolName ;
// if structure assignment is supported.
bStatus = BparseInteger(&ptkmap->aarValue, &dwDevFontID,
VALUE_INTEGER) ;
if(bStatus)
pttft->dwDevFontID = dwDevFontID ;
else
{
// BUG_BUG! : Error parsing TTFontSub table entry
// syntax error in devID. Dead codepath who cares?
pttft->dwDevFontID = 0 ; // is this a good fallback?
}
}
break;
}
#endif
case SPEC_INVALID_COMBO:
{
if(bFirstPass)
{
bStatus = TRUE ;
break; // do nothing on the FirstPass
}
bStatus = BparseInvalidCombination(&ptkmap->aarValue, dwOffset, pglobl) ;
break;
}
case SPEC_INVALID_INS_COMBO:
{
if(bFirstPass)
{
bStatus = TRUE ;
break; // do nothing on the FirstPass
}
bStatus = BparseInvalidInstallableCombination1(&ptkmap->aarValue,
dwOffset, pglobl) ;
break;
}
case SPEC_MEM_CONFIG_KB: // should already be replaced
case SPEC_MEM_CONFIG_MB: // at parseKeyword
default:
{
break ;
}
}
return(bStatus) ;
}
BOOL BprocessSymbolKeyword(
PTKMAP ptkmap, // pointer to current entry in tokenmap
PGLOBL pglobl
)
{
// registering the TTFontNames as symbols allows
// me to count the number of unique names and reserve
// the proper amount of TTFONTSUBTABLE elements and
// eliminates multiple instances of the same name.
BOOL bStatus = FALSE ;
STATE stState ;
if(mdwCurStsPtr)
stState = mpstsStateStack[mdwCurStsPtr - 1].stState ;
else
stState = STATE_ROOT ;
switch (stState)
{
// note TTFontSubs now has its own keyword.
// and is handled as a Special Keyword.
default:
{
// assume its just VALUEMACRO state
// or user-defined symbols from an undefined
// keyword.
// ignore these.
bStatus = TRUE ;
break ;
}
}
return(bStatus);
}
VOID VinitAllowedTransitions(
PGLOBL pglobl)
{
PSTATE pst ;
PBOOL pb ;
WORD wS, wC, wA ;
// default initializer is STATE_INVALID
for(wS = 0 ; wS < STATE_LAST ; wS++)
{
for(wC = 0 ; wC < CONSTRUCT_LAST ; wC++)
gastAllowedTransitions[wS][wC] = STATE_INVALID ;
}
pst = gastAllowedTransitions[STATE_ROOT] ;
pst[CONSTRUCT_UIGROUP] = STATE_UIGROUP;
pst[CONSTRUCT_FEATURE] = STATE_FEATURE;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_ROOT;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_FONTCART] = STATE_FONTCART;
pst[CONSTRUCT_TTFONTSUBS] = STATE_TTFONTSUBS;
pst[CONSTRUCT_OEM] = STATE_OEM;
pst = gastAllowedTransitions[STATE_UIGROUP] ;
pst[CONSTRUCT_UIGROUP] = STATE_UIGROUP;
pst[CONSTRUCT_FEATURE] = STATE_FEATURE;
pst = gastAllowedTransitions[STATE_FEATURE] ;
pst[CONSTRUCT_OPTION] = STATE_OPTIONS;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_FEATURE;
pst = gastAllowedTransitions[STATE_OPTIONS] ;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_OPTION;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_OEM] = STATE_OEM;
pst = gastAllowedTransitions[STATE_SWITCH_ROOT] ;
pst[CONSTRUCT_CASE] = STATE_CASE_ROOT;
pst[CONSTRUCT_DEFAULT] = STATE_DEFAULT_ROOT;
pst = gastAllowedTransitions[STATE_SWITCH_FEATURE] ;
pst[CONSTRUCT_CASE] = STATE_CASE_FEATURE;
pst[CONSTRUCT_DEFAULT] = STATE_DEFAULT_FEATURE;
pst = gastAllowedTransitions[STATE_SWITCH_OPTION] ;
pst[CONSTRUCT_CASE] = STATE_CASE_OPTION;
pst[CONSTRUCT_DEFAULT] = STATE_DEFAULT_OPTION;
pst = gastAllowedTransitions[STATE_CASE_ROOT] ;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_ROOT;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_OEM] = STATE_OEM;
pst = gastAllowedTransitions[STATE_DEFAULT_ROOT] ;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_ROOT;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_OEM] = STATE_OEM;
pst = gastAllowedTransitions[STATE_CASE_FEATURE] ;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_FEATURE;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_OEM] = STATE_OEM;
pst = gastAllowedTransitions[STATE_DEFAULT_FEATURE] ;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_FEATURE;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_OEM] = STATE_OEM;
pst = gastAllowedTransitions[STATE_CASE_OPTION] ;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_OPTION;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_OEM] = STATE_OEM;
pst = gastAllowedTransitions[STATE_DEFAULT_OPTION] ;
pst[CONSTRUCT_SWITCH] = STATE_SWITCH_OPTION;
pst[CONSTRUCT_COMMAND] = STATE_COMMAND;
pst[CONSTRUCT_OEM] = STATE_OEM;
// ------------------------------------------------------ //
// now initialize allowed attributes table:
// which attributes are allowed in each state.
// default initializer is FALSE -- No attributes are allowed
// in any state.
for(wS = 0 ; wS < STATE_LAST ; wS++)
{
for(wA = 0 ; wA < ATT_LAST ; wA++)
{
gabAllowedAttributes[wS][wA] = FALSE ;
}
}
pb = gabAllowedAttributes[STATE_ROOT] ;
pb[ATT_GLOBAL_ONLY] = TRUE ;
pb[ATT_GLOBAL_FREEFLOAT] = TRUE ;
pb = gabAllowedAttributes[STATE_CASE_ROOT] ;
pb[ATT_GLOBAL_FREEFLOAT] = TRUE ;
pb = gabAllowedAttributes[STATE_DEFAULT_ROOT] ;
pb[ATT_GLOBAL_FREEFLOAT] = TRUE ;
pb = gabAllowedAttributes[STATE_OPTIONS] ;
pb[ATT_GLOBAL_FREEFLOAT] = TRUE ;
pb[ATT_LOCAL_FEATURE_FF] = TRUE ;
pb[ATT_LOCAL_OPTION_ONLY] = TRUE ;
pb[ATT_LOCAL_OPTION_FF] = TRUE ;
pb = gabAllowedAttributes[STATE_CASE_OPTION] ;
pb[ATT_GLOBAL_FREEFLOAT] = TRUE ;
pb[ATT_LOCAL_FEATURE_FF] = TRUE ;
pb[ATT_LOCAL_OPTION_FF] = TRUE ;
pb = gabAllowedAttributes[STATE_DEFAULT_OPTION] ;
pb[ATT_GLOBAL_FREEFLOAT] = TRUE ;
pb[ATT_LOCAL_FEATURE_FF] = TRUE ;
pb[ATT_LOCAL_OPTION_FF] = TRUE ;
pb = gabAllowedAttributes[STATE_FEATURE] ;
pb[ATT_LOCAL_FEATURE_ONLY] = TRUE ;
pb[ATT_LOCAL_FEATURE_FF] = TRUE ;
pb = gabAllowedAttributes[STATE_CASE_FEATURE] ;
pb[ATT_LOCAL_FEATURE_FF] = TRUE ;
pb = gabAllowedAttributes[STATE_DEFAULT_FEATURE] ;
pb[ATT_LOCAL_FEATURE_FF] = TRUE ;
pb = gabAllowedAttributes[STATE_COMMAND] ;
pb[ATT_LOCAL_COMMAND_ONLY] = TRUE ;
pb = gabAllowedAttributes[STATE_FONTCART] ;
pb[ATT_LOCAL_FONTCART_ONLY] = TRUE ;
pb = gabAllowedAttributes[STATE_TTFONTSUBS] ;
pb[ATT_LOCAL_TTFONTSUBS_ONLY] = TRUE ;
pb = gabAllowedAttributes[STATE_OEM] ;
pb[ATT_LOCAL_OEM_ONLY] = TRUE ;
}
BOOL BpushState(
PTKMAP ptkmap, // pointer to current entry in tokenmap
BOOL bFirstPass,
PGLOBL pglobl
)
{
// this function assumes (eType == TY_CONSTRUCT)
DWORD dwKeywordID ;
CONSTRUCT eSubType ;
BOOL bStatus = FALSE ;
STATE stOldState, stNewState ;
if(mdwCurStsPtr >= mdwMaxStackDepth)
{
if(ERRSEV_RESTART > geErrorSev)
{
ERR(("Exceeded max state stack depth. Restarting\n"));
geErrorSev = ERRSEV_RESTART ;
geErrorType = ERRTY_MEMORY_ALLOCATION ;
gdwMasterTabIndex = MTI_STSENTRY ;
}
return(FALSE);
}
dwKeywordID = ptkmap->dwKeywordID ;
eSubType = (CONSTRUCT)(mMainKeywordTable[dwKeywordID].dwSubType) ;
if(mdwCurStsPtr)
stOldState = mpstsStateStack[mdwCurStsPtr - 1].stState ;
else
stOldState = STATE_ROOT ;
switch (eSubType)
{
// note CONSTRUCT_CLOSEBRACE already processed
// by PopState().
case (CONSTRUCT_OPENBRACE):
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("OpenBrace encountered without accompanying construct keyword.\n"));
geErrorType = ERRTY_SYNTAX ;
geErrorSev = ERRSEV_FATAL ;
break ;
}
case (CONSTRUCT_FEATURE):
case (CONSTRUCT_OPTION):
case (CONSTRUCT_SWITCH):
case (CONSTRUCT_COMMAND): // commandID's already registered.
case (CONSTRUCT_CASE):
case (CONSTRUCT_FONTCART):
case (CONSTRUCT_TTFONTSUBS):
{
bStatus = BchangeState(ptkmap, eSubType, stOldState, TRUE,
bFirstPass, pglobl) ;
break ;
}
case (CONSTRUCT_UIGROUP):
{
// BUG_BUG!!!!! incomplete. no reqest for this.
}
case (CONSTRUCT_DEFAULT):
case (CONSTRUCT_OEM):
{
bStatus = BchangeState(ptkmap, eSubType, stOldState, FALSE,
bFirstPass, pglobl) ;
break ;
}
default:
{
bStatus = TRUE ; // its ok to ignore some keywords.
break ;
}
}
return(bStatus) ;
}
/*
dead code.
VOID VsetbTTFontSubs(
IN PABSARRAYREF paarValue)
{
// BUG_BUG!!!!!:
// exactly what is supposed to happen ? register
// synthesized symbol ?
gbTTFontSubs = FALSE ;
if( BeatSurroundingWhiteSpaces(paarValue) )
{
if(paarValue->dw == 2 && ! strncmp(paarValue->pub, "ON", 2))
gbTTFontSubs = TRUE ;
else if(paarValue->dw != 3 || strncmp(paarValue->pub, "OFF", 3))
{
BUG_BUG!: value must be either "ON" or "OFF".
}
}
}
*/
BOOL BchangeState(
PTKMAP ptkmap, // pointer to construct in tokenmap
CONSTRUCT eConstruct, // this will induce a transition to NewState
STATE stOldState,
BOOL bSymbol, // should dwValue be saved as a SymbolID ?
BOOL bFirstPass,
PGLOBL pglobl
)
{
BOOL bStatus = FALSE ;
STATE stNewState ;
// was checked in PushState, but never hurts to check
// in the same function that consumes the resource.
if(mdwCurStsPtr >= mdwMaxStackDepth)
{
if(ERRSEV_RESTART > geErrorSev)
{
geErrorSev = ERRSEV_RESTART ;
geErrorType = ERRTY_MEMORY_ALLOCATION ;
gdwMasterTabIndex = MTI_STSENTRY ;
}
return(FALSE);
}
stNewState = gastAllowedTransitions[stOldState][eConstruct] ;
if(stNewState == STATE_INVALID)
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("the Construct %0.*s is not allowed within the state: %s\n",
ptkmap->aarKeyword.dw, ptkmap->aarKeyword.pub,
gpubStateNames[stOldState]));
// (convert stOldState
// and eConstruct to meaningful string)
// This is a fatal error since parser cannot second
// guess the problem. The parser's job is to report
// as many legitemate problems as possible not to
// create as useable binary in spite of all the syntax
// errors.
if(ERRSEV_FATAL > geErrorSev)
{
geErrorSev = ERRSEV_FATAL ;
geErrorType = ERRTY_SYNTAX ;
}
return(FALSE);
}
else
{
if(bFirstPass)
{ // verify open brace follows construct and discard it.
DWORD dwKeywordID ;
PTKMAP ptkmapTmp = ptkmap + 1 ;
dwKeywordID = ptkmapTmp->dwKeywordID ;
while(dwKeywordID == ID_NULLENTRY) // skip nulls, comments etc.
{
dwKeywordID = (++ptkmapTmp)->dwKeywordID ;
}
if(dwKeywordID < ID_SPECIAL &&
mMainKeywordTable[dwKeywordID].eType == TY_CONSTRUCT &&
mMainKeywordTable[dwKeywordID].dwSubType ==
CONSTRUCT_OPENBRACE )
{
ptkmapTmp->dwKeywordID = ID_NULLENTRY ;
}
else
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("open brace expected after construct: %0.*s but was not found\n",
ptkmap->aarKeyword.dw , ptkmap->aarKeyword.pub )) ;
geErrorType = ERRTY_SYNTAX ;
geErrorSev = ERRSEV_FATAL ;
return(FALSE);
}
}
if(bSymbol)
{
// BUG_BUG: verify tokenmap.dwFlags set to SYMBOLID before
// assuming dwValue is a symbol. An error here
// is a parser bug.
// dwValue is initialized when dwFlag is set.
// further assert is pointless.
// perform multiple passes. The first pass
// registers symbols and counts number of arrays
// to allocate, 2nd pass fills arrays. SymbolID
// now serves as array index.
if(!(ptkmap->dwFlags & TKMF_SYMBOL_REGISTERED))
{
if(!bFirstPass)
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("symbol registration failed twice for: *%0.*s.\n",
ptkmap->aarValue.dw,
ptkmap->aarValue.pub));
return(FALSE) ; // retry
}
if((ptkmap->dwFlags & TKMF_NOVALUE ) ||
! BeatSurroundingWhiteSpaces(&ptkmap->aarValue) )
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("syntax error in symbol name.\n"));
ptkmap->dwValue = INVALID_SYMBOLID ;
return(FALSE) ;
}
ptkmap->dwValue = DWregisterSymbol(&ptkmap->aarValue,
eConstruct, TRUE, INVALID_SYMBOLID, pglobl) ;
if(ptkmap->dwValue != INVALID_SYMBOLID)
{
ptkmap->dwFlags |= TKMF_SYMBOL_REGISTERED ;
}
else
{
vIdentifySource(ptkmap, pglobl) ;
ERR(("symbol registration failed: *%0.*s.\n",
ptkmap->aarValue.dw,
ptkmap->aarValue.pub));
return(FALSE) ; // retry
}
}
else // second pass, DFEATURE_OPTION arrays allocated.
{
if(eConstruct == CONSTRUCT_SWITCH)
{
PDFEATURE_OPTIONS pfo ;
pfo = (PDFEATURE_OPTIONS)
gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct ;
pfo[ptkmap->dwValue].bReferenced = TRUE ;
// this tells me this Feature is being referenced
// by switch statement, hence the feature had better
// be PICKONE. Sanity checks will later verify
// this assumption.
}
if(eConstruct == CONSTRUCT_FEATURE ||
eConstruct == CONSTRUCT_SWITCH)
{
// BUG_BUG!!!!!: (DCR 454049)
// Note, the same Feature symbol cannot appear
// twice in the stack for any reason.
// A sanity check is needed.
// if duplicate symbol found in stack,
// "a Nested Switch Construct refers to the
// same feature as an enclosing switch or Feature
// construct. This makes no sense."
}
}
bStatus = TRUE ;
mpstsStateStack[mdwCurStsPtr].dwSymbolID = ptkmap->dwValue ;
}
else
bStatus = TRUE ;
if(bStatus)
{
mpstsStateStack[mdwCurStsPtr].stState = stNewState ;
mdwCurStsPtr++ ;
}
}
return(bStatus) ;
}
DWORD DWregisterSymbol(
PABSARRAYREF paarSymbol, // the symbol string to register
CONSTRUCT eConstruct , // type of construct determines class of symbol.
BOOL bCopy, // shall we copy paarSymbol to heap? May set
// to FALSE only if paarSymbol already points
// to a heap object!
DWORD dwFeatureID, // if you are registering an option symbol
// and you already know the feature , pass it in
// here. Otherwise set to INVALID_SYMBOLID
PGLOBL pglobl
)
/* this function registers the entire string specified
in paarSymbol. The caller must isolate the string.
*/
{
// returns SymbolID, a zero indexed ordinal
// for extra speed we may hash string
PSYMBOLNODE psn ;
DWORD dwCurNode, dwSymbolID = INVALID_SYMBOLID;
// bCopy = TRUE; //check. Force BUDs to be the same.
if(!paarSymbol->dw)
{
ERR(("DWregisterSymbol: No symbol value supplied.\n"));
return(INVALID_SYMBOLID); // report failure.
}
psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
switch(eConstruct)
{
case CONSTRUCT_FEATURE : // since forward references are allowed
case CONSTRUCT_SWITCH : // it cannot be assumed that references
case CONSTRUCT_FONTCART: // will be to registered symbols .
case CONSTRUCT_COMMAND:
case CONSTRUCT_TTFONTSUBS:
case CONSTRUCT_BLOCKMACRO:
case CONSTRUCT_MACROS:
case CONSTRUCT_PREPROCESSOR:
{
PDWORD pdwSymbolClass ;
pdwSymbolClass = (PDWORD)gMasterTable[MTI_SYMBOLROOT].pubStruct ;
if(eConstruct == CONSTRUCT_FONTCART)
pdwSymbolClass += SCL_FONTCART ;
else if(eConstruct == CONSTRUCT_TTFONTSUBS)
pdwSymbolClass += SCL_TTFONTNAMES ;
else if(eConstruct == CONSTRUCT_COMMAND)
pdwSymbolClass += SCL_COMMANDNAMES ;
else if(eConstruct == CONSTRUCT_BLOCKMACRO)
pdwSymbolClass += SCL_BLOCKMACRO;
else if(eConstruct == CONSTRUCT_MACROS)
pdwSymbolClass += SCL_VALUEMACRO;
else if(eConstruct == CONSTRUCT_PREPROCESSOR)
pdwSymbolClass += SCL_PPDEFINES;
else
pdwSymbolClass += SCL_FEATURES ;
if(*pdwSymbolClass == INVALID_INDEX)
{
// register this symbol now.
if(!BallocElementFromMasterTable(MTI_SYMBOLTREE, &dwCurNode, pglobl))
{
// we have run out of symbol nodes!
return(INVALID_SYMBOLID); // report failure.
}
if(bCopy)
{
if(!BaddAARtoHeap(paarSymbol,
&(psn[dwCurNode].arSymbolName), 1, pglobl))
return(INVALID_SYMBOLID); // report failure.
}
else
{
// derive one from the other.
psn[dwCurNode].arSymbolName.dwCount = paarSymbol->dw ;
psn[dwCurNode].arSymbolName.loOffset =
(DWORD)(paarSymbol->pub - mpubOffRef);
}
dwSymbolID = psn[dwCurNode].dwSymbolID = 0 ; // first symbol
// in list.
psn[dwCurNode].dwNextSymbol = INVALID_INDEX ; // no previous
// symbols exist.
psn[dwCurNode].dwSubSpaceIndex = INVALID_INDEX ; // no
// option symbols exist.
*pdwSymbolClass = dwCurNode ; // now we have a registered
// symbol
}
else
{
// search list for matching symbol.
dwSymbolID = DWsearchSymbolListForAAR(paarSymbol, *pdwSymbolClass, pglobl) ;
if(dwSymbolID != INVALID_SYMBOLID) // found
; // nothing else is needed, just return.
else // not found, must register.
{
if(!BallocElementFromMasterTable(MTI_SYMBOLTREE,
&dwCurNode, pglobl))
{
return(INVALID_SYMBOLID); // report failure.
}
// tack new symbol onto head of list.
if(bCopy)
{
if(!BaddAARtoHeap(paarSymbol,
&(psn[dwCurNode].arSymbolName), 1, pglobl) )
return(INVALID_SYMBOLID); // report failure.
}
else
{
// derive one from the other.
psn[dwCurNode].arSymbolName.dwCount = paarSymbol->dw ;
psn[dwCurNode].arSymbolName.loOffset =
(DWORD)(paarSymbol->pub - mpubOffRef);
}
dwSymbolID = psn[dwCurNode].dwSymbolID =
psn[*pdwSymbolClass].dwSymbolID + 1;
// increment last ID
psn[dwCurNode].dwNextSymbol = *pdwSymbolClass ;
// link to previous symbols.
psn[dwCurNode].dwSubSpaceIndex = INVALID_INDEX ; // no
// option symbols exist.
*pdwSymbolClass = dwCurNode ; // points to most recent
// symbol
}
}
break;
}
case CONSTRUCT_OPTION :
case CONSTRUCT_CASE :
{
DWORD
dwFeatureIndex, // node containing this symbolID.
dwRootOptions ; // root of option symbols.
#if PARANOID
if(mdwCurStsPtr)
{
// this safety check almost superfluous.
stPrevsState = mpstsStateStack[mdwCurStsPtr - 1].State ;
if(eConstruct == CONSTRUCT_OPTION &&
stPrevsState != STATE_FEATURE)
{
ERR(("DWregisterSymbol: option or case construct is not enclosed within feature or switch !\n"));
return(INVALID_SYMBOLID); // report failure.
}
if(eConstruct == CONSTRUCT_CASE &&
(stPrevsState != STATE_SWITCH_ROOT ||
(stPrevsState != STATE_SWITCH_FEATURE ||
(stPrevsState != STATE_SWITCH_OPTION ) )
{
ERR(("DWregisterSymbol: case construct is not enclosed within switch !\n"));
return(INVALID_SYMBOLID); // report failure.
}
#endif
// Boldly assume top of stack contains a featureID.
// see paranoid code for all assumptions made.
if(dwFeatureID == INVALID_SYMBOLID)
dwFeatureID = mpstsStateStack[mdwCurStsPtr - 1].dwSymbolID ;
dwFeatureIndex = DWsearchSymbolListForID(dwFeatureID,
mdwFeatureSymbols, pglobl) ;
// PARANOID BUG_BUG: coding error if symbolID isn't found!
ASSERT(dwFeatureIndex != INVALID_INDEX) ;
dwRootOptions = psn[dwFeatureIndex].dwSubSpaceIndex ;
// found root of option symbols!
if(dwRootOptions == INVALID_INDEX)
{
if(!BallocElementFromMasterTable(MTI_SYMBOLTREE, &dwCurNode, pglobl))
{
return(INVALID_SYMBOLID); // report failure.
}
// register this symbol now.
if(bCopy)
{
if(!BaddAARtoHeap(paarSymbol, &(psn[dwCurNode].arSymbolName), 1, pglobl) )
return(INVALID_SYMBOLID); // report failure.
}
else
{
// derive one from the other.
psn[dwCurNode].arSymbolName.dwCount = paarSymbol->dw ;
psn[dwCurNode].arSymbolName.loOffset =
(DWORD)(paarSymbol->pub - mpubOffRef);
}
dwSymbolID = psn[dwCurNode].dwSymbolID = 0 ;
// first symbol in list.
psn[dwCurNode].dwNextSymbol = INVALID_INDEX ;
// no previous symbols exist.
psn[dwCurNode].dwSubSpaceIndex = INVALID_INDEX ;
// option symbols have no subspace.
psn[dwFeatureIndex].dwSubSpaceIndex = dwRootOptions =
dwCurNode ; // now we have a registered symbol
}
else
{
// search list for matching symbol.
dwSymbolID = DWsearchSymbolListForAAR(paarSymbol,
dwRootOptions, pglobl) ;
if(dwSymbolID != INVALID_SYMBOLID) // found
; // nothing else is needed, just return.
else // not found, must register.
{
if(!BallocElementFromMasterTable(MTI_SYMBOLTREE,
&dwCurNode, pglobl))
{
return(INVALID_SYMBOLID); // report failure.
}
// tack new symbol onto head of list.
if(bCopy)
{
if(!BaddAARtoHeap(paarSymbol,
&(psn[dwCurNode].arSymbolName), 1, pglobl) )
return(INVALID_SYMBOLID); // report failure.
}
else
{
// derive one from the other.
psn[dwCurNode].arSymbolName.dwCount =
paarSymbol->dw ;
psn[dwCurNode].arSymbolName.loOffset =
(DWORD)(paarSymbol->pub - mpubOffRef);
}
dwSymbolID = psn[dwCurNode].dwSymbolID =
psn[dwRootOptions].dwSymbolID + 1; // increment last ID
psn[dwCurNode].dwNextSymbol = dwRootOptions ;
// link to previous symbols.
psn[dwCurNode].dwSubSpaceIndex = INVALID_INDEX ;
// option symbols have no subspace.
psn[dwFeatureIndex].dwSubSpaceIndex = dwRootOptions =
dwCurNode ; // points to most recent symbol
}
}
#if PARANOID
}
else
{
// BUG_BUG:
ERR(("DWregisterSymbol: option or case construct is not enclosed within feature or switch !\n"));
return(INVALID_SYMBOLID); // report failure.
}
#endif
break;
}
default:
{
// PARANOID BUG_BUG:
ERR(("DWregisterSymbol: construct has no symbol class.\n"));
return(INVALID_SYMBOLID); // report failure.
}
}
return(dwSymbolID) ;
}
BOOL BaddAARtoHeap(
PABSARRAYREF paarSrc,
PARRAYREF parDest,
DWORD dwAlign, // write data to address that is a multiple of dwAlign
PGLOBL pglobl)
// this function copies a non NULL terminated string fragment
// referenced by an 'aar'
// into the communal STRINGHEAP and returns an 'ar'
// which describes the location of the copy.
{
PBYTE pubSrc, pubDest ;
DWORD dwCnt ; // num bytes to copy.
// legal values for dwAlign are 1 and 4.
mloCurHeap = (mloCurHeap + dwAlign - 1) / dwAlign ;
mloCurHeap *= dwAlign ;
pubSrc = paarSrc->pub ;
dwCnt = paarSrc->dw ;
pubDest = mpubOffRef + mloCurHeap ;
// is there enough room in the heap ?
// don't forget the NULL.
if(mloCurHeap + dwCnt + 1 > mdwMaxHeap)
{
// log error to debug output.
// register error so appropriate action is taken.
if(ERRSEV_RESTART > geErrorSev)
{
geErrorSev = ERRSEV_RESTART ;
geErrorType = ERRTY_MEMORY_ALLOCATION ;
gdwMasterTabIndex = MTI_STRINGHEAP ;
}
return(FALSE);
}
parDest->dwCount = dwCnt ;
parDest->loOffset = mloCurHeap; // offset only!
memcpy(pubDest, pubSrc, dwCnt);
// the copy may also fail for random reasons!
pubDest[dwCnt] = '\0' ; // Add Null termination.
mloCurHeap += (dwCnt + 1); // update heap ptr.
return(TRUE) ;
}
BOOL BwriteToHeap(
OUT PDWORD pdwDestOff, // heap offset of dest string
PBYTE pubSrc, // points to src string
DWORD dwCnt, // num bytes to copy from src to dest.
DWORD dwAlign, // write data to address that is a multiple of dwAlign
PGLOBL pglobl)
// this function copies dwCnt bytes from pubSrc to
// top of heap and writes the offset of the destination string
// to pdwDestOff. Nothing is changed if FAILS.
// Warning! No Null termination is added to string.
{
PBYTE pubDest ;
// legal values for dwAlign are 1 and 4.
mloCurHeap = (mloCurHeap + dwAlign - 1) / dwAlign ;
mloCurHeap *= dwAlign ;
pubDest = mpubOffRef + mloCurHeap ;
// is there enough room in the heap ?
if(mloCurHeap + dwCnt > mdwMaxHeap)
{
// log error to debug output.
// register error so appropriate action is taken.
ERR(("BwriteToHeap: out of heap - restarting.\n"));
if(ERRSEV_RESTART > geErrorSev)
{
geErrorSev = ERRSEV_RESTART ;
geErrorType = ERRTY_MEMORY_ALLOCATION ;
gdwMasterTabIndex = MTI_STRINGHEAP ;
}
return(FALSE);
}
memcpy(pubDest, pubSrc, dwCnt);
// the copy may also fail for random reasons!
*pdwDestOff = mloCurHeap ;
mloCurHeap += (dwCnt); // update heap ptr.
return(TRUE) ;
}
DWORD DWsearchSymbolListForAAR(
PABSARRAYREF paarSymbol,
DWORD dwNodeIndex,
PGLOBL pglobl)
// given a 'aar' to a string representing a symbol, search
// the SymbolList beginning at dwNodeIndex for this symbol.
// Return its symbolID if found, else return the INVALID_SYMBOLID.
{
PSYMBOLNODE psn ;
psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
for( ; dwNodeIndex != INVALID_INDEX ;
dwNodeIndex = psn[dwNodeIndex].dwNextSymbol)
{
if(BCmpAARtoAR(paarSymbol, &(psn[dwNodeIndex].arSymbolName), pglobl) )
return(psn[dwNodeIndex].dwSymbolID); // string matches !
}
return(INVALID_SYMBOLID);
}
DWORD DWsearchSymbolListForID(
DWORD dwSymbolID, // find node containing this ID.
DWORD dwNodeIndex, // start search here.
PGLOBL pglobl)
// given a symbolID, search the SymbolList beginning at dwNodeIndex
// for this symbol.
// If found return the node index which contains the requested symbolID,
// else return INVALID_INDEX.
{
PSYMBOLNODE psn ;
psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
for( ; dwNodeIndex != INVALID_INDEX ;
dwNodeIndex = psn[dwNodeIndex].dwNextSymbol)
{
if(psn[dwNodeIndex].dwSymbolID == dwSymbolID)
return(dwNodeIndex); // ID matches !
}
return(INVALID_INDEX);
}
BOOL BCmpAARtoAR(
PABSARRAYREF paarStr1,
PARRAYREF parStr2,
PGLOBL pglobl)
// Compares two strings, one referenced by 'aar' the other
// referenced by 'ar'. Returns TRUE if they match, FALSE
// otherwise.
{
if(paarStr1->dw != parStr2->dwCount)
return(FALSE) ; // Lengths don't even match!
if(strncmp(paarStr1->pub, mpubOffRef + parStr2->loOffset , paarStr1->dw))
return(FALSE) ;
return(TRUE) ;
}
BOOL BpopState(
PGLOBL pglobl)
{
if(mdwCurStsPtr)
{
mdwCurStsPtr-- ;
return(TRUE);
}
else
{
// ERR(("Unmatched closing brace!\n"));
// message moved to caller.
// in the future make parser smarter.
geErrorType = ERRTY_SYNTAX ;
geErrorSev = ERRSEV_FATAL ;
return(FALSE);
}
}
VOID VinitDictionaryIndex(
PGLOBL pglobl)
/*
MainKeywordTable[] is assumed to be divided into
a NonAttributes section and several Attributes sections
with pstrKeyword = NULL dividing the sections.
The end of the table is also terminated by a NULL entry.
This function initializes the grngDictionary[]
which serves as an index into the main keyword Table.
*/
{
DWORD dwI, // keywordTable Index
dwSect ; // RNGDICTIONARY Index
PRANGE prng ;
prng = (PRANGE)(gMasterTable[MTI_RNGDICTIONARY].pubStruct) ;
for(dwI = dwSect = 0 ; dwSect < END_ATTR ; dwSect++, dwI++)
{
prng[dwSect].dwStart = dwI ;
for( ; mMainKeywordTable[dwI].pstrKeyword ; dwI++ )
;
prng[dwSect].dwEnd = dwI ; // one past the last entry
}
}
VOID VcharSubstitution(
PABSARRAYREF paarStr,
BYTE ubTgt,
BYTE ubReplcmnt,
PGLOBL pglobl)
{
DWORD dwI ;
for(dwI = 0 ; dwI < paarStr->dw ; dwI++)
{
if(paarStr->pub[dwI] == ubTgt)
paarStr->pub[dwI] = ubReplcmnt ;
}
}
VOID VIgnoreBlock(
PTKMAP ptkmap,
BOOL bIgnoreBlock,
PGLOBL pglobl)
// This boolean determines the message that will be issued.
{
/* Should we ignore? check that first non-NULL entry
after wCurEntry is open brace if so
ignore all entries up to EOF or matching closing
brace. */
DWORD dwKeywordID, dwDepth ; // depth relative to *IgnoreBlock
ptkmap->dwKeywordID = ID_NULLENTRY ; // neutralize keyword regardless.
ptkmap++ ;
dwKeywordID = ptkmap->dwKeywordID ;
while(dwKeywordID == ID_NULLENTRY) // skip nulls, comments etc.
{
dwKeywordID = (++ptkmap)->dwKeywordID ;
}
if(dwKeywordID < ID_SPECIAL &&
mMainKeywordTable[dwKeywordID].eType == TY_CONSTRUCT &&
mMainKeywordTable[dwKeywordID].dwSubType ==
CONSTRUCT_OPENBRACE )
{
ptkmap->dwKeywordID = ID_NULLENTRY ;
dwDepth = 1 ;
ptkmap++ ;
if(bIgnoreBlock)
{
if(gdwVerbosity >= 4)
ERR(("Note: Ignoring block following *IgnoreBlock.\n"));
}
else
ERR(("Ignoring block following unrecognized keyword.\n"));
}
else
{
if(bIgnoreBlock && gdwVerbosity >= 2)
ERR(("Note: Brace delimited block not found after *IgnoreBlock.\n"));
return ; // do nothing.
}
while(dwDepth)
{
dwKeywordID = ptkmap->dwKeywordID ;
if(dwKeywordID == ID_EOF)
{
ERR(("Ignoring Block: EOF encountered before closing brace.\n"));
return ; // stop regardless!
}
if(dwKeywordID < ID_SPECIAL)
{
KEYWORD_TYPE eType;
CONSTRUCT eSubType ;
eType = mMainKeywordTable[dwKeywordID].eType ;
if(eType == TY_CONSTRUCT)
{
eSubType = (CONSTRUCT)(mMainKeywordTable[dwKeywordID].dwSubType) ;
if(eSubType == CONSTRUCT_OPENBRACE)
dwDepth++ ;
else if( eSubType == CONSTRUCT_CLOSEBRACE)
dwDepth-- ;
}
}
ptkmap->dwKeywordID = ID_NULLENTRY ;
ptkmap++ ;
}
return ;
}