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.

275 lines
6.6 KiB

  1. /*****************************************************************************
  2. *
  3. * obj.c
  4. *
  5. * Mid-level memory management -- objects.
  6. *
  7. *****************************************************************************/
  8. #include "m4.h"
  9. /*****************************************************************************
  10. *
  11. * FreePtok
  12. *
  13. * Free the memory associated with a token.
  14. *
  15. *****************************************************************************/
  16. INLINE void
  17. FreePtok(PTOK ptok)
  18. {
  19. AssertSPtok(ptok);
  20. Assert(fHeapPtok(ptok));
  21. FreePv(ptchPtok(ptok));
  22. D(ptok->sig = 0);
  23. D(ptok->tsfl = 0);
  24. }
  25. /*****************************************************************************
  26. *
  27. * PopdefPmac
  28. *
  29. * Pop the topmost value node (definition) off a macro.
  30. *
  31. *****************************************************************************/
  32. void STDCALL
  33. PopdefPmac(PMAC pmac)
  34. {
  35. PVAL pval;
  36. AssertPmac(pmac);
  37. AssertPval(pmac->pval);
  38. pval = pmac->pval->pvalPrev;
  39. FreePtok(&pmac->pval->tok);
  40. FreePv(pmac->pval);
  41. pmac->pval = pval;
  42. }
  43. /*****************************************************************************
  44. *
  45. * ptchDupPtok
  46. *
  47. * Copy a token into the heap as a C-style string, returning a pointer
  48. * to the copy.
  49. *
  50. *****************************************************************************/
  51. PTCH STDCALL
  52. ptchDupPtok(PCTOK ptok)
  53. {
  54. PTCH ptch;
  55. AssertSPtok(ptok);
  56. ptch = ptchAllocCtch(ctchSPtok(ptok) + 1);
  57. if (ptch) {
  58. CopyPtchPtchCtch(ptch, ptchPtok(ptok), ctchSPtok(ptok));
  59. ptch[ctchSPtok(ptok)] = '\0';
  60. }
  61. return ptch;
  62. }
  63. /*****************************************************************************
  64. *
  65. * ptchDupPtch
  66. *
  67. * Duplicate a null-terminated string onto the heap. This doesn't
  68. * happen often, so speed is not an issue.
  69. *
  70. *****************************************************************************/
  71. PTCH STDCALL
  72. ptchDupPtch(PCTCH ptch)
  73. {
  74. TOK tok;
  75. SetStaticPtokPtchCtch(&tok, ptch, strlen(ptch));
  76. return ptchDupPtok(&tok);
  77. }
  78. /*****************************************************************************
  79. *
  80. * DupPtokPtok
  81. *
  82. * Copy a token into the heap, returning the new token location in
  83. * the first argument. (Remember, first argument is always destination;
  84. * second argument is always source.)
  85. *
  86. *****************************************************************************/
  87. void STDCALL
  88. DupPtokPtok(PTOK ptokDst, PCTOK ptokSrc)
  89. {
  90. Assert(ptokDst != ptokSrc);
  91. AssertSPtok(ptokSrc);
  92. D(ptokDst->sig = sigSPtok);
  93. ptokDst->u.ptch = ptchAllocCtch(ctchSPtok(ptokSrc));
  94. ptokDst->ctch = ctchSPtok(ptokSrc);
  95. D(ptokDst->tsfl = tsflClosed | tsflHeap);
  96. CopyPtchPtchCtch(ptchPtok(ptokDst), ptchPtok(ptokSrc), ctchSPtok(ptokSrc));
  97. }
  98. /*****************************************************************************
  99. *
  100. * PushdefPmacPtok
  101. *
  102. * Push a new value node (definition) onto a macro.
  103. *
  104. * The ptok is cloned.
  105. *
  106. *****************************************************************************/
  107. void STDCALL
  108. PushdefPmacPtok(PMAC pmac, PCTOK ptok)
  109. {
  110. PVAL pval;
  111. AssertPmac(pmac);
  112. pval = pvAllocCb(sizeof(VAL));
  113. D(pval->sig = sigPval);
  114. pval->fTrace = 0; /* Redefinition resets trace */
  115. DupPtokPtok(&pval->tok, ptok);
  116. pval->pvalPrev = pmac->pval;
  117. pmac->pval = pval;
  118. }
  119. /*****************************************************************************
  120. *
  121. * FreePmac
  122. *
  123. * Free a macro structure and all its dependents. Also removes it from the
  124. * hash table.
  125. *
  126. * Macros are not freed often, so we can afford to be slow.
  127. *
  128. *****************************************************************************/
  129. void STDCALL
  130. FreePmac(PMAC pmac)
  131. {
  132. HASH hash;
  133. PMAC pmacDad;
  134. AssertPmac(pmac);
  135. hash = hashPtok(&pmac->tokName);
  136. pmacDad = pvSubPvCb(&mphashpmac[hash], offsetof(MAC, pmacNext));
  137. AssertPmac(pmacDad->pmacNext);
  138. while (pmacDad->pmacNext != pmac) {
  139. Assert(pmacDad->pmacNext); /* Macro not in hash table */
  140. pmacDad = pmacDad->pmacNext;
  141. AssertPmac(pmacDad->pmacNext);
  142. }
  143. pmacDad->pmacNext = pmac->pmacNext; /* Unlink */
  144. while (pmac->pval) { /* Free any values */
  145. PopdefPmac(pmac);
  146. }
  147. FreePtok(&pmac->tokName);
  148. FreePv(pmac);
  149. }
  150. /*****************************************************************************
  151. *
  152. * pmacFindPtok
  153. *
  154. * Locate a macro node corresponding to the supplied token. If no such
  155. * macro exists, then return 0.
  156. *
  157. *****************************************************************************/
  158. PMAC STDCALL
  159. pmacFindPtok(PCTOK ptok)
  160. {
  161. PMAC pmac;
  162. for (pmac = mphashpmac[hashPtok(ptok)]; pmac; pmac = pmac->pmacNext) {
  163. if (fEqPtokPtok(&pmac->tokName, ptok)) {
  164. break;
  165. }
  166. }
  167. return pmac;
  168. }
  169. /*****************************************************************************
  170. *
  171. * pmacGetPtok
  172. *
  173. * Locate a macro node corresponding to the supplied token. If no such
  174. * macro exists, create one.
  175. *
  176. * This happens only during macro definition, so it can be slow.
  177. *
  178. *****************************************************************************/
  179. PMAC STDCALL
  180. pmacGetPtok(PCTOK ptok)
  181. {
  182. PMAC pmac = pmacFindPtok(ptok);
  183. if (!pmac) {
  184. HASH hash;
  185. pmac = pvAllocCb(sizeof(MAC));
  186. D(pmac->sig = sigPmac);
  187. pmac->pval = 0;
  188. DupPtokPtok(&pmac->tokName, ptok);
  189. hash = hashPtok(ptok);
  190. pmac->pmacNext = mphashpmac[hash];
  191. mphashpmac[hash] = pmac;
  192. }
  193. return pmac;
  194. }
  195. /*****************************************************************************
  196. *
  197. * fEqPtokPtok
  198. *
  199. * Determine whether two tokens are completely identical.
  200. *
  201. * The tokens must be snapped.
  202. *
  203. *****************************************************************************/
  204. F STDCALL
  205. fEqPtokPtok(PCTOK ptok1, PCTOK ptok2)
  206. {
  207. AssertSPtok(ptok1);
  208. AssertSPtok(ptok2);
  209. return (ctchSPtok(ptok1) == ctchSPtok(ptok2)) &&
  210. fEqPtchPtchCtch(ptchPtok(ptok1), ptchPtok(ptok2), ctchSPtok(ptok1));
  211. }
  212. /*****************************************************************************
  213. *
  214. * fIdentPtok
  215. *
  216. * Determine whether the token is a valid identifier.
  217. *
  218. * The token must be snapped.
  219. *
  220. *****************************************************************************/
  221. /* SOMEDAY! not quite right; thinks that `0' is an identifier */
  222. F STDCALL
  223. fIdentPtok(PCTOK ptok)
  224. {
  225. AssertSPtok(ptok);
  226. if (ctchSPtok(ptok)) {
  227. PTCH ptch = ptchPtok(ptok);
  228. do {
  229. if (!fIdentTch(*ptch)) {
  230. return 0;
  231. }
  232. } while (++ptch < ptchMaxPtok(ptok));
  233. return 1;
  234. } else {
  235. return 0;
  236. }
  237. }