Source code of Windows XP (NT5)
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.

1317 lines
31 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #ifdef SYMTAB_STATS
  4. UINT SymbolCount;
  5. #endif
  6. /*
  7. ** Purpose:
  8. ** Creates a new Symbol Table.
  9. ** Arguments:
  10. ** szName - Name of the INF file
  11. ** Returns:
  12. ** fFalse if the initialization failed because it could not allocate
  13. ** the memory it needed.
  14. ** fTrue if the initialization succeeded.
  15. **
  16. **************************************************************************/
  17. PINFTEMPINFO APIENTRY CreateInfTempInfo( pPermInfo )
  18. PINFPERMINFO pPermInfo;
  19. {
  20. PINFTEMPINFO pTempInfo;
  21. //
  22. // Allocate space for context data
  23. //
  24. pTempInfo = (PINFTEMPINFO)SAlloc( (CB)sizeof(INFTEMPINFO) );
  25. if ( pTempInfo ) {
  26. if ( !(pTempInfo->SymTab = SymTabAlloc())) {
  27. SFree(pTempInfo);
  28. pTempInfo = NULL;
  29. } else if ( !(pTempInfo->pParsedInf = ParsedInfAlloc( pPermInfo )) ) {
  30. FFreeSymTab( pTempInfo->SymTab );
  31. SFree(pTempInfo);
  32. pTempInfo = NULL;
  33. } else {
  34. pTempInfo->pInfPermInfo = pPermInfo;
  35. pTempInfo->cRef = 1;
  36. //
  37. // Add to chain.
  38. //
  39. if ( pLocalContext() ) {
  40. pTempInfo->pPrev = pLocalInfTempInfo();
  41. } else {
  42. pTempInfo->pPrev = NULL;
  43. }
  44. pTempInfo->pNext = pTempInfo->pPrev ? (pTempInfo->pPrev)->pNext : NULL;
  45. if ( pTempInfo->pPrev ) {
  46. (pTempInfo->pPrev)->pNext = pTempInfo;
  47. }
  48. if ( pTempInfo->pNext ) {
  49. (pTempInfo->pNext)->pPrev = pTempInfo;
  50. }
  51. }
  52. }
  53. return pTempInfo;
  54. }
  55. #ifdef SYMTAB_STATS
  56. void ContextDump( FILE*);
  57. void TempInfoDump( FILE*);
  58. void PermInfoDump( FILE*);
  59. void SymTabDump( FILE*, PSYMTAB);
  60. void
  61. SymTabStatDump(void)
  62. {
  63. FILE *statfile;
  64. statfile = fopen("D:\\SYMTAB.TXT","wt");
  65. ContextDump( statfile );
  66. TempInfoDump( statfile );
  67. PermInfoDump( statfile );
  68. fclose(statfile);
  69. }
  70. void
  71. ContextDump( FILE* f )
  72. {
  73. PINFCONTEXT pContext;
  74. UINT i = 0;
  75. fprintf( f, "CONTEXT STACK DUMP\n");
  76. fprintf( f, "------------------\n");
  77. pContext = pLocalContext();
  78. while ( pContext ) {
  79. fprintf( f, "\n\n\n");
  80. fprintf( f, "Context #%u.- Line: %8u INF Name: %s\n",
  81. i,
  82. pContext->CurrentLine, pContext->pInfTempInfo->pInfPermInfo->szName );
  83. fprintf( f, "Local Symbol Table:\n");
  84. SymTabDump( f, pContext->SymTab );
  85. i++;
  86. pContext = pContext->pNext;
  87. }
  88. fprintf( f, "\n\n\n");
  89. }
  90. void
  91. TempInfoDump( FILE* f )
  92. {
  93. PINFPERMINFO pPermInfo;
  94. PINFTEMPINFO pTempInfo;
  95. fprintf( f, "\n\n\n");
  96. fprintf( f, "INF TEMPORARY INFO DUMP\n");
  97. fprintf( f, "-----------------------\n");
  98. pTempInfo = pGlobalContext()->pInfTempInfo;
  99. while ( pTempInfo ) {
  100. pPermInfo = pTempInfo->pInfPermInfo;
  101. fprintf( f, "\n\n\n" );
  102. fprintf( f, "INF Name: %s\n", pPermInfo->szName );
  103. fprintf( f, "INF Id: %8u\n", pPermInfo->InfId );
  104. fprintf( f, "Reference Count: %8u\n", pTempInfo->cRef );
  105. fprintf( f, "Line Count: %8u\n", pTempInfo->MasterLineCount );
  106. fprintf( f, "File Size: %8u\n", pTempInfo->MasterFileSize );
  107. fprintf( f, "Static Symbol Table:\n");
  108. SymTabDump( f, pTempInfo->SymTab );
  109. pTempInfo = pTempInfo->pNext;
  110. }
  111. fprintf( f, "\n\n\n");
  112. }
  113. void
  114. PermInfoDump( FILE* f )
  115. {
  116. PINFPERMINFO pPermInfo;
  117. fprintf( f, "\n\n\n");
  118. fprintf( f, "INF PERMANENT INFO DUMP\n");
  119. fprintf( f, "-----------------------\n\n");
  120. pPermInfo = pInfPermInfoHead;
  121. while ( pPermInfo ) {
  122. fprintf( f, "INF Name: %s\n", pPermInfo->szName );
  123. pPermInfo = pPermInfo->pNext;
  124. }
  125. fprintf( f, "\n\n\n");
  126. }
  127. void
  128. SymTabDump( FILE* f, PSYMTAB pSymTab )
  129. {
  130. UINT i;
  131. PSTE p;
  132. fprintf( f, "\n");
  133. for(i=0; i<cHashBuckets; i++) {
  134. p = pSymTab->HashBucket[i];
  135. fprintf( f, "\n\tBucket # %u (%u items):\n",i,pSymTab->BucketCount[i]);
  136. while(p) {
  137. fprintf( f, "\n\t Symbol = %s\n\t Value = %s\n",p->szSymbol,p->szValue);
  138. p = p->psteNext;
  139. }
  140. }
  141. }
  142. #endif
  143. /*
  144. ** Purpose:
  145. ** Allocates an STE structure and returns it.
  146. ** Arguments:
  147. ** none
  148. ** Returns:
  149. ** NULL if the allocation failed.
  150. ** Pointer to the allocated STE structure.
  151. +++
  152. ** Notes:
  153. ** A linked list of unused STEs is maintained with FFreePste()
  154. ** placing unused STEs into it. If this linked list (psteUnused)
  155. ** is empty then a block of cStePerSteb STEs is allocated at once
  156. ** and added to the unused list with one being returned by this
  157. ** routine.
  158. **
  159. **************************************************************************/
  160. PSTE APIENTRY PsteAlloc(VOID)
  161. {
  162. PSTE pste;
  163. if (GLOBAL(psteUnused) == (PSTE)NULL)
  164. {
  165. PSTEB psteb;
  166. USHORT us;
  167. if ((psteb = (PSTEB)SAlloc((CB)sizeof(STEB))) == (PSTEB)NULL)
  168. return((PSTE)NULL);
  169. psteb->pstebNext = GLOBAL(pstebAllocatedBlocks);
  170. GLOBAL(pstebAllocatedBlocks) = psteb;
  171. GLOBAL(psteUnused) = &(psteb->rgste[0]);
  172. for (us = 1; us < cStePerSteb; us++)
  173. (psteb->rgste[us - 1]).psteNext = &(psteb->rgste[us]);
  174. (psteb->rgste[cStePerSteb - 1]).psteNext = (PSTE)NULL;
  175. }
  176. pste = GLOBAL(psteUnused);
  177. GLOBAL(psteUnused) = pste->psteNext;
  178. pste->szSymbol = (SZ)NULL;
  179. pste->szValue = (SZ)NULL;
  180. #ifdef SYMTAB_STATS
  181. SymbolCount++;
  182. #endif
  183. return(pste);
  184. }
  185. /*
  186. ** Purpose:
  187. ** Frees an STE structure.
  188. ** Arguments:
  189. ** pste: non-NULL STE structure to be freed.
  190. ** Returns:
  191. ** fFalse if either of the string fields of the STE structure or the
  192. ** STE itself could not be successfully freed.
  193. ** fTrue if both string fields of the STE structure and the structure
  194. ** itself are successfully freed.
  195. **
  196. **************************************************************************/
  197. BOOL APIENTRY FFreePste(pste)
  198. PSTE pste;
  199. {
  200. BOOL fAnswer = fTrue;
  201. ChkArg(pste != (PSTE)NULL, 1, fFalse);
  202. if (pste->szSymbol != (SZ)NULL)
  203. SFree(pste->szSymbol);
  204. if (pste->szValue != (SZ)NULL)
  205. SFree(pste->szValue);
  206. pste->szSymbol = pste->szValue = (SZ)NULL;
  207. pste->psteNext = GLOBAL(psteUnused);
  208. GLOBAL(psteUnused) = pste;
  209. #ifdef SYMTAB_STATS
  210. SymbolCount--;
  211. #endif
  212. return(fAnswer);
  213. }
  214. /*
  215. ** Purpose:
  216. ** Decrements the reference count of a symbol table, freeing its
  217. ** memory if the reference count reaches zero
  218. ** Arguments:
  219. ** none
  220. ** Returns:
  221. ** fFalse if all the STE structures and their string fields cannot be
  222. ** successfully freed.
  223. ** fTrue if all the STE structures and their string fields can be
  224. ** successfully freed.
  225. **
  226. **************************************************************************/
  227. BOOL APIENTRY FFreeInfTempInfo( PVOID p )
  228. {
  229. BOOL fAnswer = fTrue;
  230. PINFTEMPINFO pTempInfo = (PINFTEMPINFO)p;
  231. AssertDataSeg();
  232. if ( pTempInfo->cRef > 1 ) {
  233. pTempInfo->cRef--;
  234. } else {
  235. //
  236. // Free static symbol table
  237. //
  238. FFreeSymTab( pTempInfo->SymTab );
  239. //
  240. // Free preparsed INF
  241. //
  242. FFreeParsedInf( pTempInfo->pParsedInf );
  243. //
  244. // Remove from chain
  245. //
  246. if ( pTempInfo->pPrev ) {
  247. (pTempInfo->pPrev)->pNext = pTempInfo->pNext;
  248. }
  249. if ( pTempInfo->pNext ) {
  250. (pTempInfo->pNext)->pPrev = pTempInfo->pPrev;
  251. }
  252. SFree(p);
  253. //
  254. // bugbug ramonsa - should we free PSTE blocks here?
  255. //
  256. }
  257. return(fAnswer);
  258. }
  259. /*
  260. ** Purpose:
  261. ** Calculates a hash value for a zero terminated string of bytes
  262. ** (characters) which is used by the Symbol Table to divide the
  263. ** symbols into separate buckets to improve the search efficiency.
  264. ** Arguments:
  265. ** pb: non-NULL, non-empty zero terminated string of bytes.
  266. ** Returns:
  267. ** -1 for an error.
  268. ** A number between 0 and cHashBuckets.
  269. **
  270. **************************************************************************/
  271. USHORT APIENTRY UsHashFunction( pb )
  272. register PB pb;
  273. {
  274. register USHORT usValue = 0;
  275. register PB pbMax = pb + cbBytesToSumForHash ;
  276. ChkArg(pb != (PB)NULL &&
  277. *pb != '\0', 1, (USHORT)(-1));
  278. while ( *pb && pb < pbMax )
  279. {
  280. usValue = (usValue << 1) ^ (USHORT) *pb++ ;
  281. }
  282. return(usValue % (USHORT)cHashBuckets);
  283. }
  284. /*
  285. ** Purpose:
  286. ** Finds a corresponding STE structure if the symbol is already in
  287. ** the Symbol Table or else points to where it should be inserted.
  288. ** Arguments:
  289. ** szSymbol: non-NULL, non-empty zero terminated string containing
  290. ** the value of the symbol to be searched for.
  291. ** Notes:
  292. ** Requires that the Symbol Table was initialized with a successful
  293. ** call to FInitSymTab().
  294. ** Returns:
  295. ** NULL in an error.
  296. ** Non-NULL pointer to a pointer to an STE structure. If szSymbol is
  297. ** in the Symbol Table, then (*PPSTE)->szSymbol is it. If szSymbol
  298. ** is not in the Symbol Table, then *PPSTE is the PSTE to insert
  299. ** its record at.
  300. **
  301. **************************************************************************/
  302. PPSTE APIENTRY PpsteFindSymbol(pSymTab, szSymbol)
  303. PSYMTAB pSymTab;
  304. SZ szSymbol;
  305. {
  306. PPSTE ppste;
  307. USHORT usHashValue;
  308. PreCondSymTabInit((PPSTE)NULL);
  309. ChkArg( szSymbol != (SZ)NULL
  310. && *szSymbol != '\0', 1, (PPSTE)NULL);
  311. usHashValue = UsHashFunction(szSymbol);
  312. ppste = &(pSymTab->HashBucket[usHashValue]);
  313. AssertRet(ppste != (PPSTE)NULL, (PPSTE)NULL);
  314. AssertRet(*ppste == (PSTE)NULL ||
  315. ((*ppste)->szSymbol != (SZ)NULL &&
  316. *((*ppste)->szSymbol) != '\0' &&
  317. (*ppste)->szValue != (SZ)NULL), (PPSTE)NULL);
  318. while ( *ppste != (PSTE)NULL &&
  319. lstrcmp(szSymbol, (*ppste)->szSymbol) > 0 )
  320. {
  321. ppste = &((*ppste)->psteNext);
  322. AssertRet(ppste != (PPSTE)NULL, (PPSTE)NULL);
  323. AssertRet(*ppste == (PSTE)NULL ||
  324. ((*ppste)->szSymbol != (SZ)NULL &&
  325. *((*ppste)->szSymbol) != '\0' &&
  326. (*ppste)->szValue != (SZ)NULL), (PPSTE)NULL);
  327. }
  328. return(ppste);
  329. }
  330. /*
  331. ** Purpose:
  332. ** Inserts a new symbol-value pair into the Symbol Table or replaces
  333. ** an existing value associated with the symbol if it already exists
  334. ** in the Symbol Table.
  335. ** Arguments:
  336. ** szSymbol: non-NULL, non-empty string symbol value.
  337. ** szValue: string value to associate with szSymbol, replacing and
  338. ** freeing any current value. If it is NULL then the empty string
  339. ** is used in its place. There are two types of values - simple
  340. ** and list. A simple value is any string of characters which is
  341. ** not a list. A list is a string which starts with a '{', and ends
  342. ** with a '}' and contains doubly quoted items, separated by commas
  343. ** with no extraneous whitespace. So examples of lists are:
  344. ** {}
  345. ** {"item1"}
  346. ** {"item1","item2"}
  347. ** {"item 1","item 2","item 3","item 4"}
  348. ** Examples of non-lists are:
  349. ** {item1}
  350. ** {"item1", "item2"}
  351. ** Notes:
  352. ** Requires that the Symbol Table was initialized with a successful
  353. ** call to FInitSymTab().
  354. ** Returns:
  355. ** fFalse if an existing value cannot be freed or if space cannot be
  356. ** allocated to create the needed STE structure or duplicate the
  357. ** szValue.
  358. ** fTrue if szValue is associated with szSymbol in the Symbol Table.
  359. **
  360. **************************************************************************/
  361. BOOL APIENTRY FAddSymbolValueToSymTab(szSymbol, szValue)
  362. SZ szSymbol;
  363. SZ szValue;
  364. {
  365. PPSTE ppste;
  366. SZ szValueNew;
  367. SZ szRealSymbol;
  368. PSYMTAB pSymTab;
  369. AssertDataSeg();
  370. PreCondSymTabInit(fFalse);
  371. ChkArg(szSymbol != (SZ)NULL &&
  372. *szSymbol != '\0' &&
  373. !FWhiteSpaceChp(*szSymbol), 1, fFalse);
  374. if (szValue == (SZ)NULL)
  375. szValue = "";
  376. if ((szValueNew = SzDupl(szValue)) == (SZ)NULL)
  377. return(fFalse);
  378. if ( !(pSymTab = PInfSymTabFind( szSymbol, &szRealSymbol ))) {
  379. return(fFalse);
  380. }
  381. ppste = PpsteFindSymbol( pSymTab, szRealSymbol);
  382. AssertRet(ppste != (PPSTE)NULL, fFalse);
  383. AssertRet(*ppste == (PSTE)NULL ||
  384. ((*ppste)->szSymbol != (SZ)NULL &&
  385. *((*ppste)->szSymbol) != '\0' &&
  386. (*ppste)->szValue != (SZ)NULL), fFalse);
  387. if (*ppste != (PSTE)NULL &&
  388. CrcStringCompare((*ppste)->szSymbol, szRealSymbol) == crcEqual)
  389. {
  390. AssertRet((*ppste)->szValue != (SZ)NULL, fFalse);
  391. SFree((*ppste)->szValue);
  392. (*ppste)->szValue = (SZ)NULL;
  393. }
  394. else
  395. {
  396. PSTE pste;
  397. if ((pste = PsteAlloc()) == (PSTE)NULL ||
  398. (pste->szSymbol = SzDupl(szRealSymbol)) == (SZ)NULL)
  399. {
  400. if (pste != (PSTE)NULL)
  401. EvalAssert(FFreePste(pste));
  402. SFree(szValueNew);
  403. return(fFalse);
  404. }
  405. #ifdef SYMTAB_STATS
  406. pSymTab->BucketCount[UsHashFunction(szRealSymbol)]++;
  407. #endif
  408. pste->szValue = (SZ)NULL;
  409. pste->psteNext = *ppste;
  410. *ppste = pste;
  411. }
  412. AssertRet(ppste != (PPSTE)NULL &&
  413. *ppste != (PSTE)NULL &&
  414. (*ppste)->szValue == (SZ)NULL &&
  415. (*ppste)->szSymbol != (SZ)NULL &&
  416. *((*ppste)->szSymbol) != '\0' &&
  417. CrcStringCompare((*ppste)->szSymbol, szRealSymbol) == crcEqual, fFalse);
  418. (*ppste)->szValue = szValueNew;
  419. return(fTrue);
  420. }
  421. /*
  422. ** Purpose:
  423. ** Finds the associated string value for a given symbol from the
  424. ** Symbol Table if such exists.
  425. ** Arguments:
  426. ** szSymbol: non-NULL, non-empty string symbol value.
  427. ** Notes:
  428. ** Requires that the Symbol Table was initialized with a successful
  429. ** call to FInitSymTab().
  430. ** Returns:
  431. ** NULL if error or szSymbol could not be found in the Symbol Table.
  432. ** Non-NULL pointer to the associated string value in the Symbol
  433. ** Table. This value must not be mucked but should be duplicated
  434. ** before changing it. Changing it directly will change the value
  435. ** associated with the symbol. If it is changed, be sure the new
  436. ** value has the same length as the old.
  437. **
  438. **************************************************************************/
  439. SZ APIENTRY SzFindSymbolValueInSymTab(szSymbol)
  440. SZ szSymbol;
  441. {
  442. register PSTE pste;
  443. PSYMTAB pSymTab;
  444. SZ szValue = NULL ;
  445. SZ szRealSymbol ;
  446. int i ;
  447. PreCondSymTabInit((SZ)NULL);
  448. if ( !(pSymTab = PInfSymTabFind( szSymbol, & szRealSymbol )))
  449. return NULL ;
  450. pste = pSymTab->HashBucket[ UsHashFunction( szRealSymbol ) ] ;
  451. do
  452. {
  453. if ( pste == NULL )
  454. break ;
  455. if ( pste->szSymbol == NULL )
  456. break ;
  457. if ( pste->szSymbol[0] == 0 )
  458. break;
  459. if ( pste->szValue == NULL )
  460. break;
  461. if ( (i = lstrcmp( szRealSymbol, pste->szSymbol )) == 0 )
  462. szValue = pste->szValue ;
  463. } while ( i > 0 && (pste = pste->psteNext) ) ;
  464. return szValue ;
  465. }
  466. /*
  467. ** Purpose:
  468. ** Removes and frees a symbols STE structure if it exists.
  469. ** Arguments:
  470. ** szSymbol: non-NULL, non-empty symbol string to remove from the
  471. ** Symbol Table which starts with a non-whitespace character.
  472. ** Notes:
  473. ** Requires that the Symbol Table was initialized with a successful
  474. ** call to FInitSymTab().
  475. ** Returns:
  476. ** fFalse if szSymbol was found but its STE structure could not be freed.
  477. ** fTrue if either szSymbol never existed in the Symbol Table or it was
  478. ** found, unlinked, and successfully freed.
  479. **
  480. **************************************************************************/
  481. BOOL APIENTRY FRemoveSymbolFromSymTab(szSymbol)
  482. SZ szSymbol;
  483. {
  484. PPSTE ppste;
  485. PSTE pste;
  486. PSYMTAB pSymTab;
  487. SZ szRealSymbol;
  488. AssertDataSeg();
  489. PreCondSymTabInit(fFalse);
  490. ChkArg(szSymbol != (SZ)NULL &&
  491. *szSymbol != '\0' &&
  492. !FWhiteSpaceChp(*szSymbol), 1, fFalse);
  493. if ( !(pSymTab = PInfSymTabFind( szSymbol, &szRealSymbol ))) {
  494. return(fFalse);
  495. }
  496. ppste = PpsteFindSymbol( pSymTab, szRealSymbol);
  497. AssertRet(ppste != (PPSTE)NULL, fFalse);
  498. if (*ppste == (PSTE)NULL ||
  499. CrcStringCompare(szRealSymbol, (*ppste)->szSymbol) != crcEqual)
  500. return(fTrue);
  501. pste = *ppste;
  502. *ppste = pste->psteNext;
  503. return(FFreePste(pste));
  504. }
  505. PSYMTAB APIENTRY SymTabAlloc(VOID)
  506. {
  507. PSYMTAB pSymTab;
  508. USHORT iHashBucket;
  509. if ( pSymTab = (PSYMTAB)SAlloc( sizeof( SYMTAB ) ) ) {
  510. for (iHashBucket = 0; iHashBucket < cHashBuckets; iHashBucket++) {
  511. pSymTab->HashBucket[iHashBucket] = NULL;
  512. #ifdef SYMTAB_STATS
  513. pSymTab->BucketCount[iHashBucket] = 0;
  514. #endif
  515. }
  516. }
  517. return pSymTab;
  518. }
  519. BOOL APIENTRY FFreeSymTab(PSYMTAB pSymTab)
  520. {
  521. USHORT iHashBucket;
  522. BOOL fAnswer = fTrue;
  523. // Free symbol table space
  524. //
  525. for (iHashBucket = 0; iHashBucket < cHashBuckets; iHashBucket++) {
  526. PSTE pste = pSymTab->HashBucket[iHashBucket];
  527. while (pste != (PSTE)NULL) {
  528. PSTE psteSav = pste->psteNext;
  529. fAnswer &= FFreePste(pste);
  530. pste = psteSav;
  531. }
  532. }
  533. SFree(pSymTab);
  534. return fAnswer;
  535. }
  536. BOOL APIENTRY FCheckSymTab(PSYMTAB pSymTab)
  537. {
  538. USHORT iHashBucket;
  539. for (iHashBucket = 0; iHashBucket < cHashBuckets; iHashBucket++) {
  540. PSTE pste = pSymTab->HashBucket[iHashBucket];
  541. SZ szPrev = "";
  542. while (pste != (PSTE)NULL) {
  543. if (pste->szSymbol == (SZ)NULL ||
  544. *(pste->szSymbol) == '\0' ||
  545. FWhiteSpaceChp(*(pste->szSymbol)))
  546. AssertRet(fFalse, fFalse);
  547. if (UsHashFunction((PB)(pste->szSymbol)) != iHashBucket)
  548. AssertRet(fFalse, fFalse);
  549. if (CrcStringCompare(szPrev, pste->szSymbol) != crcSecondHigher)
  550. AssertRet(fFalse, fFalse);
  551. if (pste->szValue == (SZ)NULL)
  552. AssertRet(fFalse, fFalse);
  553. pste = pste->psteNext;
  554. }
  555. }
  556. return fTrue;
  557. }
  558. /*
  559. ** Purpose:
  560. ** Ensures that the Symbol Table is valid. It checks that the
  561. ** Symbol Table has been initialized and that each STE structure
  562. ** is in the correct hash bucket and that the symbols are in
  563. ** ascending order within each hash bucket and that each has a
  564. ** non-NULL value string associated with it.
  565. ** Arguments:
  566. ** none
  567. ** Notes:
  568. ** Requires that the Symbol Table was initialized with a successful
  569. ** call to FInitSymTab().
  570. ** Returns:
  571. ** fFalse if the Symbol Table has not been initialized or if an STE
  572. ** structure is in the wrong hash bucket or if each STE linked
  573. ** list is not in ascending order or if each symbol does not have
  574. ** a non-NULL string value associated with it.
  575. ** fTrue if the Symbol Table has been initialized and if every STE
  576. ** structure is in the correct hash bucket and if each STE linked
  577. ** list is in ascending order and if each symbol does have a
  578. ** non-NULL string value associated with it.
  579. **
  580. **************************************************************************/
  581. BOOL APIENTRY FCheckSymTabIntegrity(VOID)
  582. {
  583. PINFTEMPINFO pTempInfo;
  584. AssertDataSeg();
  585. PreCondSymTabInit(fFalse);
  586. pTempInfo = pGlobalContext()->pInfTempInfo;
  587. while ( pTempInfo ) {
  588. if ( !FCheckSymTab( pTempInfo->SymTab ) ) {
  589. return fFalse;
  590. }
  591. pTempInfo = pTempInfo->pNext;
  592. }
  593. return(fTrue);
  594. }
  595. BOOL
  596. DumpSymbolTableToFile(
  597. IN PCSTR Filename
  598. )
  599. {
  600. FILE *OutFile;
  601. UINT HashBucket;
  602. PSTE pste;
  603. PINFCONTEXT InfContext;
  604. #define MAX_SYMTAB 1000
  605. PVOID SymbolTables[MAX_SYMTAB];
  606. PVOID InfNames[MAX_SYMTAB];
  607. UINT SymbolTableCount;
  608. UINT i;
  609. BOOL Found;
  610. //
  611. // Handle preconditions.
  612. //
  613. PreCondSymTabInit(fFalse);
  614. FCheckSymTabIntegrity();
  615. //
  616. // Open/create the dump file.
  617. //
  618. SetFileAttributes(Filename,FILE_ATTRIBUTE_NORMAL);
  619. OutFile = fopen(Filename,"w");
  620. if(!OutFile) {
  621. return(FALSE);
  622. }
  623. //
  624. // Iterate through all inf file contexts.
  625. // Unfortunately there is no good way to simply iterate symbol tables
  626. // we'll track the ones we've done and skip them if encountered again.
  627. //
  628. SymbolTableCount = 0;
  629. for(InfContext=pContextTop; InfContext; InfContext=InfContext->pNext) {
  630. if(SymbolTableCount < MAX_SYMTAB) {
  631. Found = FALSE;
  632. for(i=0; i<SymbolTableCount; i++) {
  633. if(SymbolTables[i] == InfContext->SymTab) {
  634. Found = TRUE;
  635. break;
  636. }
  637. }
  638. if(!Found) {
  639. SymbolTables[SymbolTableCount] = InfContext->SymTab;
  640. InfNames[SymbolTableCount] = InfContext->pInfTempInfo->pInfPermInfo->szName;
  641. SymbolTableCount++;
  642. }
  643. }
  644. }
  645. for(i=0; i<SymbolTableCount; i++) {
  646. fprintf(OutFile,"*** Inf %s:\n\n",InfNames[i] ? InfNames[i] : "(unknown)");
  647. //
  648. // Dump symbols in each hash bucket.
  649. //
  650. for(HashBucket=0; HashBucket<cHashBuckets; HashBucket++) {
  651. for(pste=((PSYMTAB)(SymbolTables[i]))->HashBucket[HashBucket]; pste; pste=pste->psteNext) {
  652. fprintf(OutFile,"[%s] = [%s]\n",pste->szSymbol,pste->szValue);
  653. }
  654. }
  655. fprintf(OutFile,"\n\n");
  656. }
  657. fclose(OutFile);
  658. return(TRUE);
  659. }
  660. #define cListItemsMax 0x07FF
  661. #define ItemSizeIncr 0x2000
  662. /*
  663. ** Purpose:
  664. ** Determines if a string is a list value.
  665. ** Arguments:
  666. ** szValue: non-NULL, zero terminated string to be tested.
  667. ** Returns:
  668. ** fTrue if a list; fFalse otherwise.
  669. **
  670. **************************************************************************/
  671. BOOL
  672. APIENTRY
  673. FListValue(
  674. IN SZ szValue
  675. )
  676. {
  677. ChkArg(szValue != (SZ)NULL, 1, fFalse);
  678. if(*szValue++ != '{') {
  679. return(fFalse);
  680. }
  681. while((*szValue != '}') && *szValue) {
  682. if(*szValue++ != '"') {
  683. return(fFalse);
  684. }
  685. while(*szValue) {
  686. if(*szValue != '"') {
  687. szValue++;
  688. } else if(*(szValue + 1) == '"') {
  689. szValue += 2;
  690. } else {
  691. break;
  692. }
  693. }
  694. if(*szValue++ != '"') {
  695. return(fFalse);
  696. }
  697. if(*szValue == ',') {
  698. if(*(++szValue) == '}') {
  699. return(fFalse);
  700. }
  701. }
  702. }
  703. if(*szValue != '}') {
  704. return(fFalse);
  705. }
  706. return(fTrue);
  707. }
  708. /*
  709. ** Purpose:
  710. ** Converts a list value into an RGSZ.
  711. ** Arguments:
  712. ** szListValue: non-NULL, zero terminated string to be converted.
  713. ** Returns:
  714. ** NULL if an error occurred.
  715. ** Non-NULL RGSZ if the conversion was successful.
  716. **
  717. **************************************************************************/
  718. RGSZ
  719. APIENTRY
  720. RgszFromSzListValue(
  721. SZ szListValue
  722. )
  723. {
  724. USHORT cItems;
  725. SZ szCur;
  726. RGSZ rgsz;
  727. DWORD ValueBufferSize;
  728. DWORD BytesLeftInValueBuffer;
  729. ChkArg(szListValue != (SZ)NULL, 1, (RGSZ)NULL);
  730. if(!FListValue(szListValue)) {
  731. if((rgsz = (RGSZ)SAlloc((CB)(2 * sizeof(SZ)))) == (RGSZ)NULL ||
  732. (rgsz[0] = SzDupl(szListValue)) == (SZ)NULL)
  733. {
  734. return((RGSZ)NULL);
  735. }
  736. rgsz[1] = (SZ)NULL;
  737. return(rgsz);
  738. }
  739. if((rgsz = (RGSZ)SAlloc((CB)((cListItemsMax + 1) * sizeof(SZ)))) == (RGSZ)NULL) {
  740. return((RGSZ)NULL);
  741. }
  742. cItems = 0;
  743. szCur = szListValue + 1;
  744. while((*szCur != '}') && (*szCur != '\0') && (cItems < cListItemsMax)) {
  745. SZ szValue;
  746. SZ szAddPoint;
  747. AssertRet(*szCur == '"', (RGSZ)NULL);
  748. szCur++;
  749. //
  750. // Allocate an initial buffer.
  751. //
  752. ValueBufferSize = ItemSizeIncr+1;
  753. BytesLeftInValueBuffer = ItemSizeIncr;
  754. if((szValue = (SZ)SAlloc(ValueBufferSize)) == (SZ)NULL) {
  755. rgsz[cItems] = (SZ)NULL;
  756. FFreeRgsz(rgsz);
  757. return((RGSZ)NULL);
  758. }
  759. szAddPoint = szValue;
  760. while(*szCur) {
  761. if(*szCur == '"') {
  762. //
  763. // Got a quote. If the next character is a double quote, then
  764. // we've got a literal double quote, and we want to store a
  765. // single double quote in the target. If the next char is not
  766. // a double-quote, then we've reached the string-ending double-quote.
  767. //
  768. // Advance szCur either way because:
  769. // In the former case, szCur will now point to the second
  770. // double-quote, and we can fall through the the ordinary
  771. // character (ie, non-quote) case.
  772. // In the latter case, we will break out of the loop, and want
  773. // szCur advanced past the end of the string.
  774. //
  775. if(*(++szCur) != '"') {
  776. break;
  777. }
  778. }
  779. if(!BytesLeftInValueBuffer) {
  780. SZ szSave = szValue;
  781. if(szValue = SRealloc(szValue,ValueBufferSize+ItemSizeIncr)) {
  782. szAddPoint = (SZ)((PUCHAR)szValue + ValueBufferSize - 1);
  783. BytesLeftInValueBuffer = ItemSizeIncr;
  784. ValueBufferSize += ItemSizeIncr;
  785. } else {
  786. SFree(szSave);
  787. rgsz[cItems] = (SZ)NULL;
  788. FFreeRgsz(rgsz);
  789. return((RGSZ)NULL);
  790. }
  791. }
  792. BytesLeftInValueBuffer--;
  793. *szAddPoint++ = *szCur++;
  794. }
  795. *szAddPoint = 0;
  796. if((szAddPoint = SzDupl(szValue)) == NULL) {
  797. SFree(szValue);
  798. rgsz[cItems] = (SZ)NULL;
  799. FFreeRgsz(rgsz);
  800. return((RGSZ)NULL);
  801. }
  802. SFree(szValue);
  803. if (*szCur == ',') {
  804. szCur++;
  805. }
  806. rgsz[cItems++] = szAddPoint;
  807. }
  808. rgsz[cItems] = (SZ)NULL;
  809. if((*szCur != '}') || (cItems >= cListItemsMax)) {
  810. FFreeRgsz(rgsz);
  811. return((RGSZ)NULL);
  812. }
  813. if (cItems < cListItemsMax) {
  814. rgsz = (RGSZ)SRealloc(
  815. (PB)rgsz,
  816. (CB)((cItems + 1) * sizeof(SZ))
  817. );
  818. }
  819. return(rgsz);
  820. }
  821. #define cbListMax (CB)0x2000
  822. VOID
  823. GrowValueBuffer( SZ *pszBuffer, PDWORD pSize, PDWORD pLeft, DWORD dwWanted, SZ *pszPointer );
  824. #define VERIFY_SIZE(s) \
  825. if ( dwSizeLeft < (s) ) { \
  826. GrowValueBuffer( &szValue, &dwValueSize, &dwSizeLeft, (s), &szAddPoint ); \
  827. }
  828. /*
  829. ** Purpose:
  830. ** Converts an RGSZ into a list value.
  831. ** Arguments:
  832. ** rgsz: non-NULL, NULL-terminated array of zero-terminated strings to
  833. ** be converted.
  834. ** Returns:
  835. ** NULL if an error occurred.
  836. ** Non-NULL SZ if the conversion was successful.
  837. **
  838. **************************************************************************/
  839. SZ APIENTRY SzListValueFromRgsz(rgsz)
  840. RGSZ rgsz;
  841. {
  842. SZ szValue;
  843. SZ szAddPoint;
  844. SZ szItem;
  845. BOOL fFirstItem = fTrue;
  846. DWORD dwValueSize;
  847. DWORD dwSizeLeft;
  848. UINT rgszIndex = 0;
  849. ChkArg(rgsz != (RGSZ)NULL, 1, (SZ)NULL);
  850. if ((szAddPoint = szValue = (SZ)SAlloc(cbListMax)) == (SZ)NULL) {
  851. return((SZ)NULL);
  852. }
  853. dwValueSize = dwSizeLeft = cbListMax;
  854. *szAddPoint++ = '{';
  855. dwSizeLeft--;
  856. while(szItem = rgsz[rgszIndex]) {
  857. VERIFY_SIZE(2);
  858. if (fFirstItem) {
  859. fFirstItem = fFalse;
  860. } else {
  861. *szAddPoint++ = ',';
  862. dwSizeLeft--;
  863. }
  864. *szAddPoint++ = '"';
  865. dwSizeLeft--;
  866. while (*szItem) {
  867. VERIFY_SIZE(1);
  868. dwSizeLeft--;
  869. if((*szAddPoint++ = *szItem++) == '"') {
  870. VERIFY_SIZE(1);
  871. dwSizeLeft--;
  872. *szAddPoint++ = '"';
  873. }
  874. }
  875. VERIFY_SIZE(1);
  876. *szAddPoint++ = '"';
  877. dwSizeLeft--;
  878. rgszIndex++;
  879. }
  880. VERIFY_SIZE(2);
  881. *szAddPoint++ = '}';
  882. *szAddPoint = '\0';
  883. dwSizeLeft -= 2;
  884. // AssertRet(strlen(szValue) < dwValueSize, (SZ)NULL);
  885. szItem = SzDupl(szValue);
  886. SFree(szValue);
  887. return(szItem);
  888. }
  889. VOID
  890. GrowValueBuffer( SZ *pszBuffer, PDWORD pSize, PDWORD pLeft, DWORD dwWanted, SZ *pszPointer )
  891. {
  892. if ( *pLeft < dwWanted ) {
  893. DWORD_PTR Offset = *pszPointer - *pszBuffer;
  894. *pszBuffer = SRealloc( *pszBuffer, *pSize + cbListMax );
  895. EvalAssert( *pszBuffer );
  896. *pSize += cbListMax;
  897. *pLeft += cbListMax;
  898. *pszPointer = *pszBuffer + Offset;
  899. }
  900. }
  901. static BOOL APIENTRY FSymbol(SZ sz)
  902. {
  903. ChkArg(sz != (SZ)NULL, 1, fFalse);
  904. if (*sz++ != '$' ||
  905. *sz++ != '(' ||
  906. FWhiteSpaceChp(*sz) ||
  907. *sz == ')')
  908. return(fFalse);
  909. while (*sz != ')' &&
  910. *sz != '\0')
  911. sz = SzNextChar(sz);
  912. return(*sz == ')');
  913. }
  914. /*
  915. ** Purpose:
  916. ** Substitutes values from the Symbol Table for symbols of the form
  917. ** '$( <symbol> )' in the source string.
  918. ** Arguments:
  919. ** szSrc: non-NULL string in which to substitute symbol values.
  920. ** Notes:
  921. ** Requires that the Symbol Table was initialized with a successful
  922. ** call to FInitSymTab().
  923. ** A successful return value must be freed by the caller.
  924. ** Returns:
  925. ** NULL if any of the alloc operations fail or if the substituted
  926. ** string is larger than 8KB bytes (cchpFieldMax).
  927. ** non-NULL string with values substituted for symbols if all of the
  928. ** alloc operations succeed.
  929. **
  930. **************************************************************************/
  931. SZ APIENTRY SzGetSubstitutedValue(SZ szSrc)
  932. {
  933. SZ szDest;
  934. PCHP pchpDestCur;
  935. CCHP cchpDest = (CCHP)0;
  936. AssertDataSeg();
  937. PreCondSymTabInit(NULL);
  938. ChkArg(szSrc != (SZ)NULL, 1, (SZ)NULL);
  939. if ((szDest = pchpDestCur = (SZ)SAlloc((CB)cchpFieldMax)) == (SZ)NULL)
  940. return((SZ)NULL);
  941. while (*szSrc != '\0')
  942. {
  943. if (FSymbol(szSrc))
  944. {
  945. SZ szSymEnd;
  946. SZ szValue;
  947. Assert(*szSrc == '$');
  948. szSrc++;
  949. Assert(*szSrc == '(');
  950. szSymEnd = ++szSrc;
  951. Assert(*szSrc != '\0' && *szSrc != ')');
  952. while (*szSymEnd != ')')
  953. {
  954. Assert(*szSymEnd != '\0');
  955. szSymEnd = SzNextChar(szSymEnd);
  956. }
  957. Assert(*szSymEnd == ')');
  958. *szSymEnd = '\0';
  959. szValue = SzFindSymbolValueInSymTab(szSrc);
  960. *szSymEnd = ')';
  961. szSrc = SzNextChar(szSymEnd);
  962. if (szValue == (SZ)NULL)
  963. continue;
  964. if (cchpDest + strlen(szValue) >= cchpFieldMax ||
  965. strcpy(pchpDestCur, szValue) != pchpDestCur)
  966. {
  967. SFree(szDest);
  968. return((SZ)NULL);
  969. }
  970. pchpDestCur += strlen(szValue);
  971. Assert(*pchpDestCur == '\0');
  972. cchpDest += strlen(szValue);
  973. Assert(cchpDest < cchpFieldMax);
  974. }
  975. else
  976. {
  977. SZ szNext = SzNextChar(szSrc);
  978. while (szSrc < szNext)
  979. {
  980. *pchpDestCur++ = *szSrc++;
  981. if (++cchpDest >= cchpFieldMax)
  982. {
  983. SFree(szDest);
  984. return((SZ)NULL);
  985. }
  986. }
  987. }
  988. }
  989. Assert(cchpDest < cchpFieldMax);
  990. *(szDest + cchpDest++) = '\0';
  991. if (cchpDest < cchpFieldMax)
  992. szDest = SRealloc(szDest,cchpFieldMax);
  993. return(szDest);
  994. }
  995. //
  996. // Routines exported from the legacy setup dll to allow
  997. // direct manipulation of the inf symtab table.
  998. //
  999. PCSTR
  1000. LegacyInfLookUpSymbol(
  1001. IN PCSTR SymbolName
  1002. )
  1003. {
  1004. return(SzFindSymbolValueInSymTab((SZ)SymbolName));
  1005. }
  1006. BOOL
  1007. LegacyInfSetSymbolValue(
  1008. IN PCSTR SymbolName,
  1009. IN PCSTR SymbolValue
  1010. )
  1011. {
  1012. return(FAddSymbolValueToSymTab((SZ)SymbolName,(SZ)SymbolValue));
  1013. }
  1014. BOOL
  1015. LegacyInfRemoveInfSymbol(
  1016. IN PCSTR SymbolName
  1017. )
  1018. {
  1019. return(FRemoveSymbolFromSymTab((SZ)SymbolName));
  1020. }