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.

805 lines
18 KiB

  1. /**********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1987-1999 **/
  4. /**********************************************************************/
  5. /*
  6. symtable.cxx
  7. MIDL Compiler Symbol Table Implementation
  8. This class centralizes access to the symbol table throughout the
  9. compiler.
  10. */
  11. /*
  12. FILE HISTORY :
  13. DonnaLi 08-25-1990 Created.
  14. */
  15. #pragma warning ( disable : 4514 )
  16. #include "nulldefs.h"
  17. extern "C" {
  18. #include <stdio.h>
  19. #include <string.h>
  20. }
  21. #include "common.hxx"
  22. #include "errors.hxx"
  23. #include "symtable.hxx"
  24. #include "tlgen.hxx"
  25. #include "mbcs.hxx"
  26. BOOL gfCaseSensitive = TRUE; // initialize things under case sensitive mode
  27. CaseStack gCaseStack;
  28. class named_node;
  29. /**********************************************************************\
  30. NAME: SymEntry
  31. SYNOPSIS: Defines an entry in the symbol table.
  32. INTERFACE:
  33. CAVEATS: This is an internal class used by the symbol table only.
  34. NOTES:
  35. HISTORY:
  36. Donnali 08-25-1990 Initial creation
  37. \**********************************************************************/
  38. class SymEntry : public SymKey
  39. {
  40. named_node * pTypeGraph; // pointer to type graph associated with entry
  41. SymTable * pNextScope; // pointer to next scope associated with entry
  42. public:
  43. SymEntry(void)
  44. {
  45. pTypeGraph = (named_node *)0;
  46. pNextScope = (SymTable *)0;
  47. }
  48. SymEntry( SymKey NewKey )
  49. : SymKey( &NewKey )
  50. {
  51. pTypeGraph = (named_node *)0;
  52. pNextScope = (SymTable *)0;
  53. }
  54. SymEntry(
  55. SymKey NewKey,
  56. SymTable * pNext,
  57. named_node * pNode) : SymKey( &NewKey )
  58. {
  59. pTypeGraph = pNode;
  60. pNextScope = pNext;
  61. }
  62. void SetTypeGraph (named_node * pNode)
  63. {
  64. pTypeGraph = pNode;
  65. }
  66. named_node * GetTypeGraph (void)
  67. {
  68. return pTypeGraph;
  69. }
  70. void SetNextScope (SymTable * pNext)
  71. {
  72. pNextScope = pNext;
  73. }
  74. SymTable * GetNextScope (void)
  75. {
  76. return pNextScope;
  77. }
  78. // here is the use of the private memory allocator
  79. private:
  80. static
  81. FreeListMgr MyFreeList;
  82. public:
  83. void * operator new (size_t size)
  84. {
  85. return (MyFreeList.Get (size));
  86. }
  87. void operator delete (void * pX)
  88. {
  89. MyFreeList.Put (pX);
  90. }
  91. } ;
  92. // initialize the memory allocator for SymEntry
  93. FreeListMgr
  94. SymEntry::MyFreeList( sizeof ( SymEntry ) );
  95. /**********************************************************************\
  96. NAME: PrintSymbol
  97. SYNOPSIS: Prints out the name of a symbol table entry.
  98. ENTRY: sym - the key to symbol table entry to be printed.
  99. EXIT:
  100. NOTES:
  101. HISTORY:
  102. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  103. \**********************************************************************/
  104. void
  105. SymTable::Print(
  106. void * sym
  107. )
  108. {
  109. printf ("%s", ((SymKey *)sym)->name);
  110. }
  111. /**********************************************************************\
  112. NAME: CompareSymbol
  113. SYNOPSIS: Compares keys to two symbol table entries.
  114. ENTRY: sym1 - the key to 1st symbol table entry to be compared.
  115. sym2 - the key to 2nd symbol table entry to be compared.
  116. EXIT: Returns a positive number if sym1 > sym2.
  117. Returns a negative number if sym1 < sym2.
  118. Returns 0 if sym1 = sym2.
  119. NOTES:
  120. Since all the strings are in the lex table, we can just compare
  121. pointers to do the string compares.
  122. HISTORY:
  123. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  124. \**********************************************************************/
  125. SSIZE_T
  126. SymTable::Compare(
  127. void * sym1,
  128. void * sym2
  129. )
  130. {
  131. int result;
  132. #ifdef unique_lextable
  133. // compare pointers into lex table
  134. result = ( (int)((SymKey *)sym1)->name )
  135. - ( (int)((SymKey *)sym2)->name );
  136. #else
  137. // compare names from keys
  138. // 1 refers to the value for the flag NORM_IGNORECASE
  139. result = CurrentCharSet.CompareDBCSString( ((SymKey *)sym1)->name,
  140. ((SymKey *)sym2)->name,
  141. gfCaseSensitive ? 0 : 1);
  142. #endif // unique_lextable
  143. if (!result)
  144. {
  145. return ( ( ((SymKey *)sym1)->kind & NAME_MASK )-
  146. ( ((SymKey *)sym2)->kind & NAME_MASK ) );
  147. }
  148. else
  149. {
  150. return result;
  151. }
  152. }
  153. /**********************************************************************\
  154. NAME: SymTable::SymInsert
  155. SYNOPSIS: Inserts a symbol into the symbol table.
  156. ENTRY: NewKey - identifies the symbol table entry.
  157. pNext - points to the next scope.
  158. pNode - points to the type graph.
  159. EXIT:
  160. NOTES:
  161. HISTORY:
  162. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  163. \**********************************************************************/
  164. named_node *
  165. SymTable::SymInsert(
  166. SymKey NewKey,
  167. SymTable * pNext,
  168. named_node * pNode
  169. )
  170. {
  171. SymEntry * NewSymbol;
  172. Dict_Status Status;
  173. NewSymbol = new SymEntry(NewKey, pNext, pNode);
  174. CaselessEntry * NewEntry = new CaselessEntry(NewSymbol);
  175. if (!gfCaseSensitive)
  176. {
  177. if (NULL != caseless_list.Find(NewEntry))
  178. {
  179. // it's allready entered into the caseless table
  180. // and we're in case insensitive mode so we
  181. // should fail here (duplicate identifier)
  182. delete NewSymbol;
  183. delete NewEntry;
  184. return NULL;
  185. }
  186. }
  187. Status = Dict_Insert(NewSymbol);
  188. if (Status == SUCCESS)
  189. {
  190. caseless_list.Add(NewEntry);
  191. return pNode;
  192. }
  193. delete NewSymbol;
  194. delete NewEntry;
  195. return (named_node *)0;
  196. }
  197. /**********************************************************************\
  198. NAME: SymTable::SymDelete
  199. SYNOPSIS: Deletes a symbol from the symbol table.
  200. ENTRY: OldKey - identifies the symbol table entry.
  201. EXIT: Returns the type graph associated with the entry.
  202. NOTES:
  203. HISTORY:
  204. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  205. \**********************************************************************/
  206. named_node *
  207. SymTable::SymDelete(
  208. SymKey OldKey
  209. )
  210. {
  211. SymEntry TempEntry( OldKey );
  212. CaselessEntry * OldEntry = new CaselessEntry(&TempEntry);
  213. SymEntry * OldSymbol;
  214. // make sure we delete the right symbol from both tables
  215. if (!gfCaseSensitive)
  216. {
  217. OldSymbol = (caseless_list.Delete(OldEntry))->pSymEntry;
  218. }
  219. else
  220. {
  221. OldSymbol = &TempEntry;
  222. caseless_list.DeleteExact(OldEntry);
  223. }
  224. named_node * pNode;
  225. Dict_Status Status;
  226. Status = Dict_Delete((void ** )&OldSymbol);
  227. if (Status == SUCCESS)
  228. {
  229. pNode = OldSymbol->GetTypeGraph();
  230. delete OldSymbol;
  231. #ifdef gajdebug3
  232. printf("\t\t--- deleting name from symbol table: %d - %s\n",
  233. OldKey.GetKind(), OldKey.GetString());
  234. #endif
  235. return pNode;
  236. }
  237. else
  238. {
  239. return (named_node *)0;
  240. }
  241. }
  242. /**********************************************************************\
  243. NAME: SymTable::SymSearch
  244. SYNOPSIS: Searches the symbol table for a symbol.
  245. ENTRY: OldKey - identifies the symbol table entry.
  246. EXIT: Returns the type graph associated with the entry.
  247. NOTES:
  248. HISTORY:
  249. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  250. \**********************************************************************/
  251. named_node *
  252. SymTable::SymSearch(
  253. SymKey OldKey
  254. )
  255. {
  256. Dict_Status Status;
  257. if (gfCaseSensitive)
  258. {
  259. Status = Dict_Find(&OldKey);
  260. if (Status == SUCCESS)
  261. {
  262. return ((SymEntry * )Dict_Curr_Item())->GetTypeGraph();
  263. }
  264. else
  265. {
  266. return NULL;
  267. }
  268. }
  269. else
  270. {
  271. SymEntry TempEntry(OldKey);
  272. CaselessEntry OldEntry(&TempEntry);
  273. CaselessEntry * pFound = caseless_list.Find(&OldEntry);
  274. if (pFound)
  275. {
  276. return pFound->pSymEntry->GetTypeGraph();
  277. }
  278. else
  279. {
  280. return NULL;
  281. }
  282. }
  283. }
  284. /**********************************************************************\
  285. NAME: SymTable::EnterScope
  286. SYNOPSIS: Transition from current scope to inner scope.
  287. ENTRY: key - identifies the symbol table entry.
  288. EXIT: ContainedDict - returns the inner scope.
  289. NOTES:
  290. HISTORY:
  291. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  292. \**********************************************************************/
  293. STATUS_T
  294. SymTable::EnterScope(
  295. SymKey key,
  296. SymTable ** ContainedDict
  297. )
  298. {
  299. SymEntry ContainerNode( key );
  300. Dict_Status Status;
  301. if (ContainedDict == (SymTable **)0)
  302. {
  303. return I_ERR_NULL_OUT_PARAM;
  304. }
  305. Status = Dict_Find(&ContainerNode);
  306. if (Status != SUCCESS)
  307. {
  308. return I_ERR_SYMBOL_NOT_FOUND;
  309. }
  310. else if (((SymEntry * )Dict_Curr_Item())->GetNextScope() == (SymTable *)0)
  311. {
  312. return I_ERR_NO_NEXT_SCOPE;
  313. }
  314. else
  315. {
  316. * ContainedDict = ((SymEntry * )Dict_Curr_Item())->GetNextScope();
  317. (*ContainedDict)->pPrevScope = this;
  318. return STATUS_OK;
  319. }
  320. }
  321. /**********************************************************************\
  322. NAME: SymTable::ExitScope
  323. SYNOPSIS: Transition from current scope to outer scope.
  324. ENTRY:
  325. EXIT: ContainerDict - returns the outer scope.
  326. NOTES:
  327. HISTORY:
  328. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  329. \**********************************************************************/
  330. STATUS_T
  331. SymTable::ExitScope(
  332. SymTable ** ContainerDict
  333. )
  334. {
  335. if (ContainerDict == (SymTable **)0)
  336. {
  337. return I_ERR_NULL_OUT_PARAM;
  338. }
  339. else if (pPrevScope == (SymTable *)0)
  340. {
  341. return I_ERR_NO_PREV_SCOPE;
  342. }
  343. else
  344. {
  345. * ContainerDict = pPrevScope;
  346. pPrevScope = (SymTable *)0;
  347. return STATUS_OK;
  348. }
  349. }
  350. /**********************************************************************\
  351. NAME: SymTable::DiscardScope
  352. SYNOPSIS: Discard all entries in the current scope (if no fwds).
  353. ENTRY:
  354. EXIT: .
  355. NOTES:
  356. HISTORY:
  357. \**********************************************************************/
  358. void
  359. SymTable::DiscardScope()
  360. {
  361. // do nothing if there are forwards
  362. if ( fHasFwds )
  363. return;
  364. SymEntry * pCurrent;
  365. // delete all the SymEntry's in this scope
  366. while ( ( pCurrent = (SymEntry *) Dict_Delete_One() ) != 0 )
  367. {
  368. delete pCurrent;
  369. }
  370. }
  371. CaselessEntry::CaselessEntry(SymEntry * pItem)
  372. {
  373. pSymEntry = pItem;
  374. // compute the hash value
  375. hash = 0;
  376. char ch;
  377. unsigned u = 0;
  378. while (0 != (ch = pSymEntry->name[u++]))
  379. {
  380. hash += ch | 32; // makes sure the hash value is case insensitive
  381. };
  382. }
  383. int CaselessEntry::Compare(CaselessEntry * pEntry2)
  384. {
  385. int rval = hash - pEntry2->hash;
  386. if (0 == rval)
  387. {
  388. rval = CurrentCharSet.CompareDBCSString(pSymEntry->name, pEntry2->pSymEntry->name, 1); // ignore case
  389. if (0 == rval)
  390. {
  391. rval = pSymEntry->kind - pEntry2->pSymEntry->kind;
  392. }
  393. }
  394. return rval;
  395. }
  396. CaselessEntry * CaselessList::Add(CaselessEntry * pEl)
  397. {
  398. CaselessListElement * pNew = new CaselessListElement(pEl);
  399. pNew->pNext = pHead;
  400. pHead = pNew;
  401. return pEl;
  402. }
  403. CaselessEntry * CaselessList::Find(CaselessEntry * pEntry)
  404. {
  405. CaselessListElement * pThis = pHead;
  406. while (pThis && 0 != pThis->pEntry->Compare(pEntry))
  407. {
  408. pThis = pThis->pNext;
  409. }
  410. if (pThis != NULL)
  411. return pThis->pEntry;
  412. else
  413. return NULL;
  414. }
  415. CaselessEntry * CaselessList::Delete(CaselessEntry * pEntry)
  416. {
  417. CaselessListElement ** ppThis = &pHead;
  418. while (*ppThis)
  419. {
  420. if (0 == (*ppThis)->pEntry->Compare(pEntry))
  421. {
  422. CaselessListElement * pFound = *ppThis;
  423. *ppThis = pFound->pNext;
  424. CaselessEntry * pReturn = pFound->pEntry;
  425. delete pFound;
  426. return pReturn;
  427. }
  428. ppThis = &((*ppThis)->pNext);
  429. }
  430. return NULL;
  431. }
  432. CaselessList::~CaselessList()
  433. {
  434. CaselessListElement * pNext;
  435. while(pHead);
  436. {
  437. pNext = pHead->pNext;
  438. delete pHead;
  439. pHead = pNext;
  440. }
  441. }
  442. CaselessEntry * CaselessList::DeleteExact(CaselessEntry * pEntry)
  443. {
  444. CaselessListElement ** ppThis = &pHead;
  445. while (*ppThis)
  446. {
  447. if ((*ppThis)->pEntry->hash == pEntry->hash)
  448. {
  449. if (0 == strcmp((*ppThis)->pEntry->pSymEntry->name, pEntry->pSymEntry->name))
  450. {
  451. if ((*ppThis)->pEntry->pSymEntry->kind == pEntry->pSymEntry->kind)
  452. {
  453. CaselessListElement * pFound = *ppThis;
  454. *ppThis = pFound->pNext;
  455. CaselessEntry * pReturn = pFound->pEntry;
  456. delete pFound;
  457. return pReturn;
  458. }
  459. }
  460. }
  461. ppThis = &((*ppThis)->pNext);
  462. }
  463. return NULL;
  464. }
  465. SSIZE_T
  466. CaselessDictionary::Compare(void * p1, void *p2)
  467. {
  468. return ((CaselessEntry *)p1)->Compare((CaselessEntry *) p2);
  469. }
  470. /**********************************************************************\
  471. NAME: GlobalSymTable::SymInsert
  472. SYNOPSIS: Inserts a symbol into the symbol table.
  473. ENTRY: NewKey - identifies the symbol table entry.
  474. pNext - points to the next scope.
  475. pNode - points to the type graph.
  476. EXIT:
  477. NOTES:
  478. HISTORY:
  479. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  480. \**********************************************************************/
  481. named_node *
  482. GlobalSymTable::SymInsert(
  483. SymKey NewKey,
  484. SymTable * pNext,
  485. named_node * pNode
  486. )
  487. {
  488. SymEntry * NewSymbol;
  489. Dict_Status Status;
  490. NewSymbol = new SymEntry(NewKey, pNext, pNode);
  491. CaselessEntry * NewEntry = new CaselessEntry(NewSymbol);
  492. if (!gfCaseSensitive)
  493. {
  494. Status = pCaselessDictionary->Dict_Find(NewEntry);
  495. if (SUCCESS == Status)
  496. {
  497. // it's allready entered into the caseless table
  498. // and we're in case insensitive mode so we
  499. // should fail here (duplicate identifier)
  500. delete NewSymbol;
  501. delete NewEntry;
  502. return NULL;
  503. }
  504. }
  505. Status = Dict_Insert(NewSymbol);
  506. if (Status == SUCCESS)
  507. {
  508. Status = pCaselessDictionary->Dict_Insert(NewEntry);
  509. if (SUCCESS != Status)
  510. {
  511. // We must be in case sensitive mode otherwise the
  512. // Dict_Find above would have succeeded and we would
  513. // have already returned failure to the caller.
  514. // Therefore, it doesn't really matter that this name
  515. // won't have an entry in the caseless table. Just
  516. // clean up the new entry and move on.
  517. delete NewEntry;
  518. }
  519. return pNode;
  520. }
  521. delete NewSymbol;
  522. delete NewEntry;
  523. return (named_node *)0;
  524. }
  525. /**********************************************************************\
  526. NAME: GlobalSymTable::SymDelete
  527. SYNOPSIS: Deletes a symbol from the symbol table.
  528. ENTRY: OldKey - identifies the symbol table entry.
  529. EXIT: Returns the type graph associated with the entry.
  530. NOTES: This operation could potentially mess up the case insensitive
  531. table because there is no guarantee that the symbol removed
  532. from the case insensitive table will match the symbol removed
  533. from the case sensitive table. However, since MIDL always
  534. re-adds the symbol to the symbol table immediately after
  535. deleting it (deletions only serve to replace forward references)
  536. it will effectively correct any inconsistencies between the
  537. two tables when it re-adds the symbol.
  538. HISTORY:
  539. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  540. \**********************************************************************/
  541. named_node *
  542. GlobalSymTable::SymDelete(
  543. SymKey OldKey
  544. )
  545. {
  546. SymEntry TempEntry( OldKey );
  547. CaselessEntry * OldEntry = new CaselessEntry(&TempEntry);
  548. SymEntry * OldSymbol;
  549. Dict_Status Status;
  550. Status = pCaselessDictionary->Dict_Delete((void **)&OldEntry);
  551. if (!gfCaseSensitive && SUCCESS == Status)
  552. {
  553. // make sure we delete the same symbol from the case
  554. // sensitive table
  555. OldSymbol = OldEntry->pSymEntry;
  556. }
  557. else
  558. {
  559. OldSymbol = &TempEntry;
  560. }
  561. named_node * pNode;
  562. Status = Dict_Delete((void ** )&OldSymbol);
  563. if (Status == SUCCESS)
  564. {
  565. pNode = OldSymbol->GetTypeGraph();
  566. delete OldSymbol;
  567. #ifdef gajdebug3
  568. printf("\t\t--- deleting name from symbol table: %d - %s\n",
  569. OldKey.GetKind(), OldKey.GetString());
  570. #endif
  571. return pNode;
  572. }
  573. else
  574. {
  575. return (named_node *)0;
  576. }
  577. }
  578. /**********************************************************************\
  579. NAME: GlobalSymTable::SymSearch
  580. SYNOPSIS: Searches the symbol table for a symbol.
  581. ENTRY: OldKey - identifies the symbol table entry.
  582. EXIT: Returns the type graph associated with the entry.
  583. NOTES:
  584. HISTORY:
  585. Donnali 08-06-1991 Move to LM/90 UI Coding Style
  586. \**********************************************************************/
  587. named_node *
  588. GlobalSymTable::SymSearch(
  589. SymKey OldKey
  590. )
  591. {
  592. Dict_Status Status;
  593. // DBCSDefaultToCaseSensitive() is introduced to handle the
  594. // equivalence of full width and half width characters in
  595. // far east languages; specifically Japanese
  596. if (gfCaseSensitive || CurrentCharSet.DBCSDefaultToCaseSensitive())
  597. {
  598. Status = Dict_Find(&OldKey);
  599. if (Status == SUCCESS)
  600. {
  601. return ((SymEntry * )Dict_Curr_Item())->GetTypeGraph();
  602. }
  603. else
  604. {
  605. return NULL;
  606. }
  607. }
  608. else
  609. {
  610. SymEntry TempEntry(OldKey);
  611. CaselessEntry OldEntry(&TempEntry);
  612. Status = pCaselessDictionary->Dict_Find(&OldEntry);
  613. if (Status == SUCCESS)
  614. {
  615. return ((CaselessEntry *)(pCaselessDictionary->Dict_Curr_Item()))->pSymEntry->GetTypeGraph();
  616. }
  617. else
  618. {
  619. return NULL;
  620. }
  621. }
  622. }