#include "precomp.h" #pragma hdrstop #ifdef SYMTAB_STATS UINT SymbolCount; #endif /* ** Purpose: ** Creates a new Symbol Table. ** Arguments: ** szName - Name of the INF file ** Returns: ** fFalse if the initialization failed because it could not allocate ** the memory it needed. ** fTrue if the initialization succeeded. ** **************************************************************************/ PINFTEMPINFO APIENTRY CreateInfTempInfo( pPermInfo ) PINFPERMINFO pPermInfo; { PINFTEMPINFO pTempInfo; // // Allocate space for context data // pTempInfo = (PINFTEMPINFO)SAlloc( (CB)sizeof(INFTEMPINFO) ); if ( pTempInfo ) { if ( !(pTempInfo->SymTab = SymTabAlloc())) { SFree(pTempInfo); pTempInfo = NULL; } else if ( !(pTempInfo->pParsedInf = ParsedInfAlloc( pPermInfo )) ) { FFreeSymTab( pTempInfo->SymTab ); SFree(pTempInfo); pTempInfo = NULL; } else { pTempInfo->pInfPermInfo = pPermInfo; pTempInfo->cRef = 1; // // Add to chain. // if ( pLocalContext() ) { pTempInfo->pPrev = pLocalInfTempInfo(); } else { pTempInfo->pPrev = NULL; } pTempInfo->pNext = pTempInfo->pPrev ? (pTempInfo->pPrev)->pNext : NULL; if ( pTempInfo->pPrev ) { (pTempInfo->pPrev)->pNext = pTempInfo; } if ( pTempInfo->pNext ) { (pTempInfo->pNext)->pPrev = pTempInfo; } } } return pTempInfo; } #ifdef SYMTAB_STATS void ContextDump( FILE*); void TempInfoDump( FILE*); void PermInfoDump( FILE*); void SymTabDump( FILE*, PSYMTAB); void SymTabStatDump(void) { FILE *statfile; statfile = fopen("D:\\SYMTAB.TXT","wt"); ContextDump( statfile ); TempInfoDump( statfile ); PermInfoDump( statfile ); fclose(statfile); } void ContextDump( FILE* f ) { PINFCONTEXT pContext; UINT i = 0; fprintf( f, "CONTEXT STACK DUMP\n"); fprintf( f, "------------------\n"); pContext = pLocalContext(); while ( pContext ) { fprintf( f, "\n\n\n"); fprintf( f, "Context #%u.- Line: %8u INF Name: %s\n", i, pContext->CurrentLine, pContext->pInfTempInfo->pInfPermInfo->szName ); fprintf( f, "Local Symbol Table:\n"); SymTabDump( f, pContext->SymTab ); i++; pContext = pContext->pNext; } fprintf( f, "\n\n\n"); } void TempInfoDump( FILE* f ) { PINFPERMINFO pPermInfo; PINFTEMPINFO pTempInfo; fprintf( f, "\n\n\n"); fprintf( f, "INF TEMPORARY INFO DUMP\n"); fprintf( f, "-----------------------\n"); pTempInfo = pGlobalContext()->pInfTempInfo; while ( pTempInfo ) { pPermInfo = pTempInfo->pInfPermInfo; fprintf( f, "\n\n\n" ); fprintf( f, "INF Name: %s\n", pPermInfo->szName ); fprintf( f, "INF Id: %8u\n", pPermInfo->InfId ); fprintf( f, "Reference Count: %8u\n", pTempInfo->cRef ); fprintf( f, "Line Count: %8u\n", pTempInfo->MasterLineCount ); fprintf( f, "File Size: %8u\n", pTempInfo->MasterFileSize ); fprintf( f, "Static Symbol Table:\n"); SymTabDump( f, pTempInfo->SymTab ); pTempInfo = pTempInfo->pNext; } fprintf( f, "\n\n\n"); } void PermInfoDump( FILE* f ) { PINFPERMINFO pPermInfo; fprintf( f, "\n\n\n"); fprintf( f, "INF PERMANENT INFO DUMP\n"); fprintf( f, "-----------------------\n\n"); pPermInfo = pInfPermInfoHead; while ( pPermInfo ) { fprintf( f, "INF Name: %s\n", pPermInfo->szName ); pPermInfo = pPermInfo->pNext; } fprintf( f, "\n\n\n"); } void SymTabDump( FILE* f, PSYMTAB pSymTab ) { UINT i; PSTE p; fprintf( f, "\n"); for(i=0; iHashBucket[i]; fprintf( f, "\n\tBucket # %u (%u items):\n",i,pSymTab->BucketCount[i]); while(p) { fprintf( f, "\n\t Symbol = %s\n\t Value = %s\n",p->szSymbol,p->szValue); p = p->psteNext; } } } #endif /* ** Purpose: ** Allocates an STE structure and returns it. ** Arguments: ** none ** Returns: ** NULL if the allocation failed. ** Pointer to the allocated STE structure. +++ ** Notes: ** A linked list of unused STEs is maintained with FFreePste() ** placing unused STEs into it. If this linked list (psteUnused) ** is empty then a block of cStePerSteb STEs is allocated at once ** and added to the unused list with one being returned by this ** routine. ** **************************************************************************/ PSTE APIENTRY PsteAlloc(VOID) { PSTE pste; if (GLOBAL(psteUnused) == (PSTE)NULL) { PSTEB psteb; USHORT us; if ((psteb = (PSTEB)SAlloc((CB)sizeof(STEB))) == (PSTEB)NULL) return((PSTE)NULL); psteb->pstebNext = GLOBAL(pstebAllocatedBlocks); GLOBAL(pstebAllocatedBlocks) = psteb; GLOBAL(psteUnused) = &(psteb->rgste[0]); for (us = 1; us < cStePerSteb; us++) (psteb->rgste[us - 1]).psteNext = &(psteb->rgste[us]); (psteb->rgste[cStePerSteb - 1]).psteNext = (PSTE)NULL; } pste = GLOBAL(psteUnused); GLOBAL(psteUnused) = pste->psteNext; pste->szSymbol = (SZ)NULL; pste->szValue = (SZ)NULL; #ifdef SYMTAB_STATS SymbolCount++; #endif return(pste); } /* ** Purpose: ** Frees an STE structure. ** Arguments: ** pste: non-NULL STE structure to be freed. ** Returns: ** fFalse if either of the string fields of the STE structure or the ** STE itself could not be successfully freed. ** fTrue if both string fields of the STE structure and the structure ** itself are successfully freed. ** **************************************************************************/ BOOL APIENTRY FFreePste(pste) PSTE pste; { BOOL fAnswer = fTrue; ChkArg(pste != (PSTE)NULL, 1, fFalse); if (pste->szSymbol != (SZ)NULL) SFree(pste->szSymbol); if (pste->szValue != (SZ)NULL) SFree(pste->szValue); pste->szSymbol = pste->szValue = (SZ)NULL; pste->psteNext = GLOBAL(psteUnused); GLOBAL(psteUnused) = pste; #ifdef SYMTAB_STATS SymbolCount--; #endif return(fAnswer); } /* ** Purpose: ** Decrements the reference count of a symbol table, freeing its ** memory if the reference count reaches zero ** Arguments: ** none ** Returns: ** fFalse if all the STE structures and their string fields cannot be ** successfully freed. ** fTrue if all the STE structures and their string fields can be ** successfully freed. ** **************************************************************************/ BOOL APIENTRY FFreeInfTempInfo( PVOID p ) { BOOL fAnswer = fTrue; PINFTEMPINFO pTempInfo = (PINFTEMPINFO)p; AssertDataSeg(); if ( pTempInfo->cRef > 1 ) { pTempInfo->cRef--; } else { // // Free static symbol table // FFreeSymTab( pTempInfo->SymTab ); // // Free preparsed INF // FFreeParsedInf( pTempInfo->pParsedInf ); // // Remove from chain // if ( pTempInfo->pPrev ) { (pTempInfo->pPrev)->pNext = pTempInfo->pNext; } if ( pTempInfo->pNext ) { (pTempInfo->pNext)->pPrev = pTempInfo->pPrev; } SFree(p); // // bugbug ramonsa - should we free PSTE blocks here? // } return(fAnswer); } /* ** Purpose: ** Calculates a hash value for a zero terminated string of bytes ** (characters) which is used by the Symbol Table to divide the ** symbols into separate buckets to improve the search efficiency. ** Arguments: ** pb: non-NULL, non-empty zero terminated string of bytes. ** Returns: ** -1 for an error. ** A number between 0 and cHashBuckets. ** **************************************************************************/ USHORT APIENTRY UsHashFunction( pb ) register PB pb; { register USHORT usValue = 0; register PB pbMax = pb + cbBytesToSumForHash ; ChkArg(pb != (PB)NULL && *pb != '\0', 1, (USHORT)(-1)); while ( *pb && pb < pbMax ) { usValue = (usValue << 1) ^ (USHORT) *pb++ ; } return(usValue % (USHORT)cHashBuckets); } /* ** Purpose: ** Finds a corresponding STE structure if the symbol is already in ** the Symbol Table or else points to where it should be inserted. ** Arguments: ** szSymbol: non-NULL, non-empty zero terminated string containing ** the value of the symbol to be searched for. ** Notes: ** Requires that the Symbol Table was initialized with a successful ** call to FInitSymTab(). ** Returns: ** NULL in an error. ** Non-NULL pointer to a pointer to an STE structure. If szSymbol is ** in the Symbol Table, then (*PPSTE)->szSymbol is it. If szSymbol ** is not in the Symbol Table, then *PPSTE is the PSTE to insert ** its record at. ** **************************************************************************/ PPSTE APIENTRY PpsteFindSymbol(pSymTab, szSymbol) PSYMTAB pSymTab; SZ szSymbol; { PPSTE ppste; USHORT usHashValue; PreCondSymTabInit((PPSTE)NULL); ChkArg( szSymbol != (SZ)NULL && *szSymbol != '\0', 1, (PPSTE)NULL); usHashValue = UsHashFunction(szSymbol); ppste = &(pSymTab->HashBucket[usHashValue]); AssertRet(ppste != (PPSTE)NULL, (PPSTE)NULL); AssertRet(*ppste == (PSTE)NULL || ((*ppste)->szSymbol != (SZ)NULL && *((*ppste)->szSymbol) != '\0' && (*ppste)->szValue != (SZ)NULL), (PPSTE)NULL); while ( *ppste != (PSTE)NULL && lstrcmp(szSymbol, (*ppste)->szSymbol) > 0 ) { ppste = &((*ppste)->psteNext); AssertRet(ppste != (PPSTE)NULL, (PPSTE)NULL); AssertRet(*ppste == (PSTE)NULL || ((*ppste)->szSymbol != (SZ)NULL && *((*ppste)->szSymbol) != '\0' && (*ppste)->szValue != (SZ)NULL), (PPSTE)NULL); } return(ppste); } /* ** Purpose: ** Inserts a new symbol-value pair into the Symbol Table or replaces ** an existing value associated with the symbol if it already exists ** in the Symbol Table. ** Arguments: ** szSymbol: non-NULL, non-empty string symbol value. ** szValue: string value to associate with szSymbol, replacing and ** freeing any current value. If it is NULL then the empty string ** is used in its place. There are two types of values - simple ** and list. A simple value is any string of characters which is ** not a list. A list is a string which starts with a '{', and ends ** with a '}' and contains doubly quoted items, separated by commas ** with no extraneous whitespace. So examples of lists are: ** {} ** {"item1"} ** {"item1","item2"} ** {"item 1","item 2","item 3","item 4"} ** Examples of non-lists are: ** {item1} ** {"item1", "item2"} ** Notes: ** Requires that the Symbol Table was initialized with a successful ** call to FInitSymTab(). ** Returns: ** fFalse if an existing value cannot be freed or if space cannot be ** allocated to create the needed STE structure or duplicate the ** szValue. ** fTrue if szValue is associated with szSymbol in the Symbol Table. ** **************************************************************************/ BOOL APIENTRY FAddSymbolValueToSymTab(szSymbol, szValue) SZ szSymbol; SZ szValue; { PPSTE ppste; SZ szValueNew; SZ szRealSymbol; PSYMTAB pSymTab; AssertDataSeg(); PreCondSymTabInit(fFalse); ChkArg(szSymbol != (SZ)NULL && *szSymbol != '\0' && !FWhiteSpaceChp(*szSymbol), 1, fFalse); if (szValue == (SZ)NULL) szValue = ""; if ((szValueNew = SzDupl(szValue)) == (SZ)NULL) return(fFalse); if ( !(pSymTab = PInfSymTabFind( szSymbol, &szRealSymbol ))) { return(fFalse); } ppste = PpsteFindSymbol( pSymTab, szRealSymbol); AssertRet(ppste != (PPSTE)NULL, fFalse); AssertRet(*ppste == (PSTE)NULL || ((*ppste)->szSymbol != (SZ)NULL && *((*ppste)->szSymbol) != '\0' && (*ppste)->szValue != (SZ)NULL), fFalse); if (*ppste != (PSTE)NULL && CrcStringCompare((*ppste)->szSymbol, szRealSymbol) == crcEqual) { AssertRet((*ppste)->szValue != (SZ)NULL, fFalse); SFree((*ppste)->szValue); (*ppste)->szValue = (SZ)NULL; } else { PSTE pste; if ((pste = PsteAlloc()) == (PSTE)NULL || (pste->szSymbol = SzDupl(szRealSymbol)) == (SZ)NULL) { if (pste != (PSTE)NULL) EvalAssert(FFreePste(pste)); SFree(szValueNew); return(fFalse); } #ifdef SYMTAB_STATS pSymTab->BucketCount[UsHashFunction(szRealSymbol)]++; #endif pste->szValue = (SZ)NULL; pste->psteNext = *ppste; *ppste = pste; } AssertRet(ppste != (PPSTE)NULL && *ppste != (PSTE)NULL && (*ppste)->szValue == (SZ)NULL && (*ppste)->szSymbol != (SZ)NULL && *((*ppste)->szSymbol) != '\0' && CrcStringCompare((*ppste)->szSymbol, szRealSymbol) == crcEqual, fFalse); (*ppste)->szValue = szValueNew; return(fTrue); } /* ** Purpose: ** Finds the associated string value for a given symbol from the ** Symbol Table if such exists. ** Arguments: ** szSymbol: non-NULL, non-empty string symbol value. ** Notes: ** Requires that the Symbol Table was initialized with a successful ** call to FInitSymTab(). ** Returns: ** NULL if error or szSymbol could not be found in the Symbol Table. ** Non-NULL pointer to the associated string value in the Symbol ** Table. This value must not be mucked but should be duplicated ** before changing it. Changing it directly will change the value ** associated with the symbol. If it is changed, be sure the new ** value has the same length as the old. ** **************************************************************************/ SZ APIENTRY SzFindSymbolValueInSymTab(szSymbol) SZ szSymbol; { register PSTE pste; PSYMTAB pSymTab; SZ szValue = NULL ; SZ szRealSymbol ; int i ; PreCondSymTabInit((SZ)NULL); if ( !(pSymTab = PInfSymTabFind( szSymbol, & szRealSymbol ))) return NULL ; pste = pSymTab->HashBucket[ UsHashFunction( szRealSymbol ) ] ; do { if ( pste == NULL ) break ; if ( pste->szSymbol == NULL ) break ; if ( pste->szSymbol[0] == 0 ) break; if ( pste->szValue == NULL ) break; if ( (i = lstrcmp( szRealSymbol, pste->szSymbol )) == 0 ) szValue = pste->szValue ; } while ( i > 0 && (pste = pste->psteNext) ) ; return szValue ; } /* ** Purpose: ** Removes and frees a symbols STE structure if it exists. ** Arguments: ** szSymbol: non-NULL, non-empty symbol string to remove from the ** Symbol Table which starts with a non-whitespace character. ** Notes: ** Requires that the Symbol Table was initialized with a successful ** call to FInitSymTab(). ** Returns: ** fFalse if szSymbol was found but its STE structure could not be freed. ** fTrue if either szSymbol never existed in the Symbol Table or it was ** found, unlinked, and successfully freed. ** **************************************************************************/ BOOL APIENTRY FRemoveSymbolFromSymTab(szSymbol) SZ szSymbol; { PPSTE ppste; PSTE pste; PSYMTAB pSymTab; SZ szRealSymbol; AssertDataSeg(); PreCondSymTabInit(fFalse); ChkArg(szSymbol != (SZ)NULL && *szSymbol != '\0' && !FWhiteSpaceChp(*szSymbol), 1, fFalse); if ( !(pSymTab = PInfSymTabFind( szSymbol, &szRealSymbol ))) { return(fFalse); } ppste = PpsteFindSymbol( pSymTab, szRealSymbol); AssertRet(ppste != (PPSTE)NULL, fFalse); if (*ppste == (PSTE)NULL || CrcStringCompare(szRealSymbol, (*ppste)->szSymbol) != crcEqual) return(fTrue); pste = *ppste; *ppste = pste->psteNext; return(FFreePste(pste)); } PSYMTAB APIENTRY SymTabAlloc(VOID) { PSYMTAB pSymTab; USHORT iHashBucket; if ( pSymTab = (PSYMTAB)SAlloc( sizeof( SYMTAB ) ) ) { for (iHashBucket = 0; iHashBucket < cHashBuckets; iHashBucket++) { pSymTab->HashBucket[iHashBucket] = NULL; #ifdef SYMTAB_STATS pSymTab->BucketCount[iHashBucket] = 0; #endif } } return pSymTab; } BOOL APIENTRY FFreeSymTab(PSYMTAB pSymTab) { USHORT iHashBucket; BOOL fAnswer = fTrue; // Free symbol table space // for (iHashBucket = 0; iHashBucket < cHashBuckets; iHashBucket++) { PSTE pste = pSymTab->HashBucket[iHashBucket]; while (pste != (PSTE)NULL) { PSTE psteSav = pste->psteNext; fAnswer &= FFreePste(pste); pste = psteSav; } } SFree(pSymTab); return fAnswer; } BOOL APIENTRY FCheckSymTab(PSYMTAB pSymTab) { USHORT iHashBucket; for (iHashBucket = 0; iHashBucket < cHashBuckets; iHashBucket++) { PSTE pste = pSymTab->HashBucket[iHashBucket]; SZ szPrev = ""; while (pste != (PSTE)NULL) { if (pste->szSymbol == (SZ)NULL || *(pste->szSymbol) == '\0' || FWhiteSpaceChp(*(pste->szSymbol))) AssertRet(fFalse, fFalse); if (UsHashFunction((PB)(pste->szSymbol)) != iHashBucket) AssertRet(fFalse, fFalse); if (CrcStringCompare(szPrev, pste->szSymbol) != crcSecondHigher) AssertRet(fFalse, fFalse); if (pste->szValue == (SZ)NULL) AssertRet(fFalse, fFalse); pste = pste->psteNext; } } return fTrue; } /* ** Purpose: ** Ensures that the Symbol Table is valid. It checks that the ** Symbol Table has been initialized and that each STE structure ** is in the correct hash bucket and that the symbols are in ** ascending order within each hash bucket and that each has a ** non-NULL value string associated with it. ** Arguments: ** none ** Notes: ** Requires that the Symbol Table was initialized with a successful ** call to FInitSymTab(). ** Returns: ** fFalse if the Symbol Table has not been initialized or if an STE ** structure is in the wrong hash bucket or if each STE linked ** list is not in ascending order or if each symbol does not have ** a non-NULL string value associated with it. ** fTrue if the Symbol Table has been initialized and if every STE ** structure is in the correct hash bucket and if each STE linked ** list is in ascending order and if each symbol does have a ** non-NULL string value associated with it. ** **************************************************************************/ BOOL APIENTRY FCheckSymTabIntegrity(VOID) { PINFTEMPINFO pTempInfo; AssertDataSeg(); PreCondSymTabInit(fFalse); pTempInfo = pGlobalContext()->pInfTempInfo; while ( pTempInfo ) { if ( !FCheckSymTab( pTempInfo->SymTab ) ) { return fFalse; } pTempInfo = pTempInfo->pNext; } return(fTrue); } BOOL DumpSymbolTableToFile( IN PCSTR Filename ) { FILE *OutFile; UINT HashBucket; PSTE pste; PINFCONTEXT InfContext; #define MAX_SYMTAB 1000 PVOID SymbolTables[MAX_SYMTAB]; PVOID InfNames[MAX_SYMTAB]; UINT SymbolTableCount; UINT i; BOOL Found; // // Handle preconditions. // PreCondSymTabInit(fFalse); FCheckSymTabIntegrity(); // // Open/create the dump file. // SetFileAttributes(Filename,FILE_ATTRIBUTE_NORMAL); OutFile = fopen(Filename,"w"); if(!OutFile) { return(FALSE); } // // Iterate through all inf file contexts. // Unfortunately there is no good way to simply iterate symbol tables // we'll track the ones we've done and skip them if encountered again. // SymbolTableCount = 0; for(InfContext=pContextTop; InfContext; InfContext=InfContext->pNext) { if(SymbolTableCount < MAX_SYMTAB) { Found = FALSE; for(i=0; iSymTab) { Found = TRUE; break; } } if(!Found) { SymbolTables[SymbolTableCount] = InfContext->SymTab; InfNames[SymbolTableCount] = InfContext->pInfTempInfo->pInfPermInfo->szName; SymbolTableCount++; } } } for(i=0; iHashBucket[HashBucket]; pste; pste=pste->psteNext) { fprintf(OutFile,"[%s] = [%s]\n",pste->szSymbol,pste->szValue); } } fprintf(OutFile,"\n\n"); } fclose(OutFile); return(TRUE); } #define cListItemsMax 0x07FF #define ItemSizeIncr 0x2000 /* ** Purpose: ** Determines if a string is a list value. ** Arguments: ** szValue: non-NULL, zero terminated string to be tested. ** Returns: ** fTrue if a list; fFalse otherwise. ** **************************************************************************/ BOOL APIENTRY FListValue( IN SZ szValue ) { ChkArg(szValue != (SZ)NULL, 1, fFalse); if(*szValue++ != '{') { return(fFalse); } while((*szValue != '}') && *szValue) { if(*szValue++ != '"') { return(fFalse); } while(*szValue) { if(*szValue != '"') { szValue++; } else if(*(szValue + 1) == '"') { szValue += 2; } else { break; } } if(*szValue++ != '"') { return(fFalse); } if(*szValue == ',') { if(*(++szValue) == '}') { return(fFalse); } } } if(*szValue != '}') { return(fFalse); } return(fTrue); } /* ** Purpose: ** Converts a list value into an RGSZ. ** Arguments: ** szListValue: non-NULL, zero terminated string to be converted. ** Returns: ** NULL if an error occurred. ** Non-NULL RGSZ if the conversion was successful. ** **************************************************************************/ RGSZ APIENTRY RgszFromSzListValue( SZ szListValue ) { USHORT cItems; SZ szCur; RGSZ rgsz; DWORD ValueBufferSize; DWORD BytesLeftInValueBuffer; ChkArg(szListValue != (SZ)NULL, 1, (RGSZ)NULL); if(!FListValue(szListValue)) { if((rgsz = (RGSZ)SAlloc((CB)(2 * sizeof(SZ)))) == (RGSZ)NULL || (rgsz[0] = SzDupl(szListValue)) == (SZ)NULL) { return((RGSZ)NULL); } rgsz[1] = (SZ)NULL; return(rgsz); } if((rgsz = (RGSZ)SAlloc((CB)((cListItemsMax + 1) * sizeof(SZ)))) == (RGSZ)NULL) { return((RGSZ)NULL); } cItems = 0; szCur = szListValue + 1; while((*szCur != '}') && (*szCur != '\0') && (cItems < cListItemsMax)) { SZ szValue; SZ szAddPoint; AssertRet(*szCur == '"', (RGSZ)NULL); szCur++; // // Allocate an initial buffer. // ValueBufferSize = ItemSizeIncr+1; BytesLeftInValueBuffer = ItemSizeIncr; if((szValue = (SZ)SAlloc(ValueBufferSize)) == (SZ)NULL) { rgsz[cItems] = (SZ)NULL; FFreeRgsz(rgsz); return((RGSZ)NULL); } szAddPoint = szValue; while(*szCur) { if(*szCur == '"') { // // Got a quote. If the next character is a double quote, then // we've got a literal double quote, and we want to store a // single double quote in the target. If the next char is not // a double-quote, then we've reached the string-ending double-quote. // // Advance szCur either way because: // In the former case, szCur will now point to the second // double-quote, and we can fall through the the ordinary // character (ie, non-quote) case. // In the latter case, we will break out of the loop, and want // szCur advanced past the end of the string. // if(*(++szCur) != '"') { break; } } if(!BytesLeftInValueBuffer) { SZ szSave = szValue; if(szValue = SRealloc(szValue,ValueBufferSize+ItemSizeIncr)) { szAddPoint = (SZ)((PUCHAR)szValue + ValueBufferSize - 1); BytesLeftInValueBuffer = ItemSizeIncr; ValueBufferSize += ItemSizeIncr; } else { SFree(szSave); rgsz[cItems] = (SZ)NULL; FFreeRgsz(rgsz); return((RGSZ)NULL); } } BytesLeftInValueBuffer--; *szAddPoint++ = *szCur++; } *szAddPoint = 0; if((szAddPoint = SzDupl(szValue)) == NULL) { SFree(szValue); rgsz[cItems] = (SZ)NULL; FFreeRgsz(rgsz); return((RGSZ)NULL); } SFree(szValue); if (*szCur == ',') { szCur++; } rgsz[cItems++] = szAddPoint; } rgsz[cItems] = (SZ)NULL; if((*szCur != '}') || (cItems >= cListItemsMax)) { FFreeRgsz(rgsz); return((RGSZ)NULL); } if (cItems < cListItemsMax) { rgsz = (RGSZ)SRealloc( (PB)rgsz, (CB)((cItems + 1) * sizeof(SZ)) ); } return(rgsz); } #define cbListMax (CB)0x2000 VOID GrowValueBuffer( SZ *pszBuffer, PDWORD pSize, PDWORD pLeft, DWORD dwWanted, SZ *pszPointer ); #define VERIFY_SIZE(s) \ if ( dwSizeLeft < (s) ) { \ GrowValueBuffer( &szValue, &dwValueSize, &dwSizeLeft, (s), &szAddPoint ); \ } /* ** Purpose: ** Converts an RGSZ into a list value. ** Arguments: ** rgsz: non-NULL, NULL-terminated array of zero-terminated strings to ** be converted. ** Returns: ** NULL if an error occurred. ** Non-NULL SZ if the conversion was successful. ** **************************************************************************/ SZ APIENTRY SzListValueFromRgsz(rgsz) RGSZ rgsz; { SZ szValue; SZ szAddPoint; SZ szItem; BOOL fFirstItem = fTrue; DWORD dwValueSize; DWORD dwSizeLeft; UINT rgszIndex = 0; ChkArg(rgsz != (RGSZ)NULL, 1, (SZ)NULL); if ((szAddPoint = szValue = (SZ)SAlloc(cbListMax)) == (SZ)NULL) { return((SZ)NULL); } dwValueSize = dwSizeLeft = cbListMax; *szAddPoint++ = '{'; dwSizeLeft--; while(szItem = rgsz[rgszIndex]) { VERIFY_SIZE(2); if (fFirstItem) { fFirstItem = fFalse; } else { *szAddPoint++ = ','; dwSizeLeft--; } *szAddPoint++ = '"'; dwSizeLeft--; while (*szItem) { VERIFY_SIZE(1); dwSizeLeft--; if((*szAddPoint++ = *szItem++) == '"') { VERIFY_SIZE(1); dwSizeLeft--; *szAddPoint++ = '"'; } } VERIFY_SIZE(1); *szAddPoint++ = '"'; dwSizeLeft--; rgszIndex++; } VERIFY_SIZE(2); *szAddPoint++ = '}'; *szAddPoint = '\0'; dwSizeLeft -= 2; // AssertRet(strlen(szValue) < dwValueSize, (SZ)NULL); szItem = SzDupl(szValue); SFree(szValue); return(szItem); } VOID GrowValueBuffer( SZ *pszBuffer, PDWORD pSize, PDWORD pLeft, DWORD dwWanted, SZ *pszPointer ) { if ( *pLeft < dwWanted ) { DWORD_PTR Offset = *pszPointer - *pszBuffer; *pszBuffer = SRealloc( *pszBuffer, *pSize + cbListMax ); EvalAssert( *pszBuffer ); *pSize += cbListMax; *pLeft += cbListMax; *pszPointer = *pszBuffer + Offset; } } static BOOL APIENTRY FSymbol(SZ sz) { ChkArg(sz != (SZ)NULL, 1, fFalse); if (*sz++ != '$' || *sz++ != '(' || FWhiteSpaceChp(*sz) || *sz == ')') return(fFalse); while (*sz != ')' && *sz != '\0') sz = SzNextChar(sz); return(*sz == ')'); } /* ** Purpose: ** Substitutes values from the Symbol Table for symbols of the form ** '$( )' in the source string. ** Arguments: ** szSrc: non-NULL string in which to substitute symbol values. ** Notes: ** Requires that the Symbol Table was initialized with a successful ** call to FInitSymTab(). ** A successful return value must be freed by the caller. ** Returns: ** NULL if any of the alloc operations fail or if the substituted ** string is larger than 8KB bytes (cchpFieldMax). ** non-NULL string with values substituted for symbols if all of the ** alloc operations succeed. ** **************************************************************************/ SZ APIENTRY SzGetSubstitutedValue(SZ szSrc) { SZ szDest; PCHP pchpDestCur; CCHP cchpDest = (CCHP)0; AssertDataSeg(); PreCondSymTabInit(NULL); ChkArg(szSrc != (SZ)NULL, 1, (SZ)NULL); if ((szDest = pchpDestCur = (SZ)SAlloc((CB)cchpFieldMax)) == (SZ)NULL) return((SZ)NULL); while (*szSrc != '\0') { if (FSymbol(szSrc)) { SZ szSymEnd; SZ szValue; Assert(*szSrc == '$'); szSrc++; Assert(*szSrc == '('); szSymEnd = ++szSrc; Assert(*szSrc != '\0' && *szSrc != ')'); while (*szSymEnd != ')') { Assert(*szSymEnd != '\0'); szSymEnd = SzNextChar(szSymEnd); } Assert(*szSymEnd == ')'); *szSymEnd = '\0'; szValue = SzFindSymbolValueInSymTab(szSrc); *szSymEnd = ')'; szSrc = SzNextChar(szSymEnd); if (szValue == (SZ)NULL) continue; if (cchpDest + strlen(szValue) >= cchpFieldMax || strcpy(pchpDestCur, szValue) != pchpDestCur) { SFree(szDest); return((SZ)NULL); } pchpDestCur += strlen(szValue); Assert(*pchpDestCur == '\0'); cchpDest += strlen(szValue); Assert(cchpDest < cchpFieldMax); } else { SZ szNext = SzNextChar(szSrc); while (szSrc < szNext) { *pchpDestCur++ = *szSrc++; if (++cchpDest >= cchpFieldMax) { SFree(szDest); return((SZ)NULL); } } } } Assert(cchpDest < cchpFieldMax); *(szDest + cchpDest++) = '\0'; if (cchpDest < cchpFieldMax) szDest = SRealloc(szDest,cchpFieldMax); return(szDest); } // // Routines exported from the legacy setup dll to allow // direct manipulation of the inf symtab table. // PCSTR LegacyInfLookUpSymbol( IN PCSTR SymbolName ) { return(SzFindSymbolValueInSymTab((SZ)SymbolName)); } BOOL LegacyInfSetSymbolValue( IN PCSTR SymbolName, IN PCSTR SymbolValue ) { return(FAddSymbolValueToSymTab((SZ)SymbolName,(SZ)SymbolValue)); } BOOL LegacyInfRemoveInfSymbol( IN PCSTR SymbolName ) { return(FRemoveSymbolFromSymTab((SZ)SymbolName)); }