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.

417 lines
7.8 KiB

  1. //
  2. // Copyright (c) Microsoft Corporation 1995
  3. //
  4. // symtab.c
  5. //
  6. // This file contains the symbol table functions.
  7. //
  8. // History:
  9. // 04-30-95 ScottH Created
  10. //
  11. #include "proj.h"
  12. #define SYMTAB_SIZE_GROW 10 // in elements
  13. //
  14. // Symbol table entry routines
  15. //
  16. /*----------------------------------------------------------
  17. Purpose: Create a symbol table entry
  18. Returns: RES_OK
  19. RES_E_OUTOFMEMORY
  20. RES_E_INVALIDPARAM
  21. Cond: --
  22. */
  23. RES PUBLIC STE_Create(
  24. PSTE * ppste,
  25. LPCSTR pszIdent,
  26. DATATYPE dt)
  27. {
  28. RES res;
  29. PSTE pste;
  30. ASSERT(ppste);
  31. ASSERT(pszIdent);
  32. pste = GAllocType(STE);
  33. if (pste)
  34. {
  35. res = RES_OK; // assume success
  36. if ( !GSetString(&pste->pszIdent, pszIdent) )
  37. res = RES_E_OUTOFMEMORY;
  38. else
  39. {
  40. pste->dt = dt;
  41. }
  42. }
  43. else
  44. res = RES_E_OUTOFMEMORY;
  45. // Did anything above fail?
  46. if (RFAILED(res))
  47. {
  48. // Yes; clean up
  49. STE_Destroy(pste);
  50. pste = NULL;
  51. }
  52. *ppste = pste;
  53. return res;
  54. }
  55. /*----------------------------------------------------------
  56. Purpose: Destroy the STE element
  57. Returns: --
  58. Cond: --
  59. */
  60. void CALLBACK STE_DeletePAPtr(
  61. LPVOID pv,
  62. LPARAM lparam)
  63. {
  64. STE_Destroy(pv);
  65. }
  66. /*----------------------------------------------------------
  67. Purpose: Destroys symbol table entry
  68. Returns: RES_OK
  69. RES_E_INVALIDPARAM
  70. Cond: --
  71. */
  72. RES PUBLIC STE_Destroy(
  73. PSTE this)
  74. {
  75. RES res;
  76. if (this)
  77. {
  78. if (this->pszIdent)
  79. GSetString(&this->pszIdent, NULL); // free
  80. // (The evalres field should not be freed. It is
  81. // a copy from somewhere else.)
  82. GFree(this);
  83. res = RES_OK;
  84. }
  85. else
  86. res = RES_E_INVALIDPARAM;
  87. return res;
  88. }
  89. /*----------------------------------------------------------
  90. Purpose: Retrieves the symbol table entry value. The type
  91. depends on the datatype.
  92. Returns: RES_OK
  93. RES_E_FAIL (for a type that does not have a value)
  94. RES_E_INVALIDPARAM
  95. Cond: --
  96. */
  97. RES PUBLIC STE_GetValue(
  98. PSTE this,
  99. PEVALRES per)
  100. {
  101. RES res;
  102. ASSERT(this);
  103. ASSERT(per);
  104. if (this && per)
  105. {
  106. res = RES_OK; // assume success
  107. switch (this->dt)
  108. {
  109. case DATA_INT:
  110. case DATA_BOOL:
  111. case DATA_STRING:
  112. case DATA_LABEL:
  113. case DATA_PROC:
  114. per->dw = this->er.dw;
  115. break;
  116. default:
  117. ASSERT(0);
  118. res = RES_E_FAIL;
  119. break;
  120. }
  121. }
  122. else
  123. res = RES_E_INVALIDPARAM;
  124. return res;
  125. }
  126. //
  127. // Symbol Table functions
  128. //
  129. /*----------------------------------------------------------
  130. Purpose: Creates a symbol table
  131. Returns: RES_OK
  132. RES_E_OUTOFMEMORY
  133. RES_E_INVALIDPARAM
  134. Cond: --
  135. */
  136. RES PUBLIC Symtab_Create(
  137. PSYMTAB * ppst,
  138. PSYMTAB pstNext) // May be NULL
  139. {
  140. RES res;
  141. PSYMTAB pst;
  142. ASSERT(ppst);
  143. pst = GAllocType(SYMTAB);
  144. if (pst)
  145. {
  146. if (PACreate(&pst->hpaSTE, SYMTAB_SIZE_GROW))
  147. {
  148. pst->pstNext = pstNext;
  149. res = RES_OK;
  150. }
  151. else
  152. res = RES_E_OUTOFMEMORY;
  153. }
  154. else
  155. res = RES_E_INVALIDPARAM;
  156. // Did anything above fail?
  157. if (RFAILED(res) && pst)
  158. {
  159. // Yes; clean up
  160. Symtab_Destroy(pst);
  161. pst = NULL;
  162. }
  163. *ppst = pst;
  164. return res;
  165. }
  166. /*----------------------------------------------------------
  167. Purpose: Destroys a symbol table
  168. Returns: RES_OK
  169. RES_E_INVALIDPARAM
  170. Cond: --
  171. */
  172. RES PUBLIC Symtab_Destroy(
  173. PSYMTAB this)
  174. {
  175. RES res;
  176. if (this)
  177. {
  178. if (this->hpaSTE)
  179. {
  180. PADestroyEx(this->hpaSTE, STE_DeletePAPtr, 0);
  181. }
  182. GFree(this);
  183. res = RES_OK;
  184. }
  185. else
  186. res = RES_E_INVALIDPARAM;
  187. return res;
  188. }
  189. /*----------------------------------------------------------
  190. Purpose: Compare symbol table entries by name.
  191. Returns:
  192. Cond: --
  193. */
  194. int CALLBACK Symtab_Compare(
  195. LPVOID pv1,
  196. LPVOID pv2,
  197. LPARAM lParam)
  198. {
  199. PSTE pste1 = pv1;
  200. PSTE pste2 = pv2;
  201. return lstrcmpi(pste1->pszIdent, pste2->pszIdent);
  202. }
  203. /*----------------------------------------------------------
  204. Purpose: Looks for pszIdent in the symbol table entry.
  205. If STFF_IMMEDIATEONLY is not set, this function will
  206. look in successive scopes if the symbol is not found
  207. within this immediate scope.
  208. Symbol table entry is returned in *psteOut.
  209. Returns: RES_OK (if found)
  210. RES_FALSE (if not found)
  211. RES_E_INVALIDPARAM
  212. Cond: --
  213. */
  214. RES PUBLIC Symtab_FindEntry(
  215. PSYMTAB this,
  216. LPCSTR pszIdent,
  217. DWORD dwFlags,
  218. PSTE * ppsteOut, // May be NULL
  219. PSYMTAB * ppstScope) // May be NULL
  220. {
  221. RES res;
  222. // Default return values to NULL
  223. if (ppsteOut)
  224. *ppsteOut = NULL;
  225. if (ppstScope)
  226. *ppstScope = NULL;
  227. if (this && pszIdent)
  228. {
  229. DWORD iste;
  230. STE ste;
  231. // Peform a binary search. Find a match?
  232. ste.pszIdent = (LPSTR)pszIdent;
  233. iste = PASearch(this->hpaSTE, &ste, 0, Symtab_Compare, (LPARAM)this, PAS_SORTED);
  234. if (PA_ERR != iste)
  235. {
  236. // Yes
  237. PSTE pste = PAFastGetPtr(this->hpaSTE, iste);
  238. if (ppsteOut)
  239. *ppsteOut = pste;
  240. if (ppstScope)
  241. *ppstScope = this;
  242. res = RES_OK;
  243. }
  244. // Check other scopes?
  245. else if (IsFlagClear(dwFlags, STFF_IMMEDIATEONLY) && this->pstNext)
  246. {
  247. // Yes
  248. res = Symtab_FindEntry(this->pstNext, pszIdent, dwFlags, ppsteOut, ppstScope);
  249. }
  250. else
  251. res = RES_FALSE;
  252. }
  253. else
  254. res = RES_E_INVALIDPARAM;
  255. return res;
  256. }
  257. /*----------------------------------------------------------
  258. Purpose: Insert the given symbol table entry into the symbol
  259. table. This function does not prevent duplicate symbols.
  260. Returns: RES_OK
  261. RES_E_OUTOFMEMORY
  262. Cond: --
  263. */
  264. RES PUBLIC Symtab_InsertEntry(
  265. PSYMTAB this,
  266. PSTE pste)
  267. {
  268. RES res;
  269. ASSERT(this);
  270. ASSERT(pste);
  271. if (PAInsertPtr(this->hpaSTE, PA_APPEND, pste))
  272. {
  273. PASort(this->hpaSTE, Symtab_Compare, (LPARAM)this);
  274. res = RES_OK;
  275. }
  276. else
  277. res = RES_E_OUTOFMEMORY;
  278. return res;
  279. }
  280. /*----------------------------------------------------------
  281. Purpose: This function generates a unique label name.
  282. Returns: RES_OK
  283. RES_INVALIDPARAM
  284. Cond: Caller must free *ppszIdent.
  285. */
  286. RES PUBLIC Symtab_NewLabel(
  287. PSYMTAB this,
  288. LPSTR pszIdentBuf) // must be size MAX_BUF_KEYWORD
  289. {
  290. static int s_nSeed = 0;
  291. #pragma data_seg(DATASEG_READONLY)
  292. const static char c_szLabelPrefix[] = "__ssh%u";
  293. #pragma data_seg()
  294. RES res;
  295. char sz[MAX_BUF_KEYWORD];
  296. PSTE pste;
  297. ASSERT(pszIdentBuf);
  298. do
  299. {
  300. // Generate name
  301. wsprintf(sz, c_szLabelPrefix, s_nSeed++);
  302. // Is this unique?
  303. res = Symtab_FindEntry(this, sz, STFF_DEFAULT, NULL, NULL);
  304. if (RES_FALSE == res)
  305. {
  306. // Yes
  307. res = STE_Create(&pste, sz, DATA_LABEL);
  308. if (RSUCCEEDED(res))
  309. {
  310. res = Symtab_InsertEntry(this, pste);
  311. if (RSUCCEEDED(res))
  312. {
  313. lstrcpyn(pszIdentBuf, sz, MAX_BUF_KEYWORD);
  314. res = RES_FALSE; // break out of this loop
  315. }
  316. }
  317. }
  318. }
  319. while(RES_OK == res);
  320. if (RES_FALSE == res)
  321. res = RES_OK;
  322. return res;
  323. }