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.

330 lines
8.9 KiB

  1. /*****************************************************************************
  2. *
  3. * divert.c
  4. *
  5. * Diversions.
  6. *
  7. *****************************************************************************/
  8. #include "m4.h"
  9. /*****************************************************************************
  10. *
  11. * fFlushPdiv
  12. *
  13. * Flush a file diversion.
  14. *
  15. *****************************************************************************/
  16. TCH ptszTmpDir[MAX_PATH];
  17. void STDCALL
  18. FlushPdiv(PDIV pdiv)
  19. {
  20. AssertPdiv(pdiv);
  21. Assert(fFilePdiv(pdiv));
  22. if (pdiv->hf == hfNil) {
  23. pdiv->ptchName = ptchAllocCtch(MAX_PATH);
  24. if (GetTempFileName(ptszTmpDir, TEXT("m4-"), 0, pdiv->ptchName)) {
  25. pdiv->hf = hfCreatPtch(pdiv->ptchName);
  26. if (pdiv->hf == hfNil) {
  27. Die("cannot create temp file");
  28. }
  29. } else {
  30. Die("cannot create temp file");
  31. }
  32. }
  33. WriteHfPtchCtch(pdiv->hf, pdiv->ptchMin, ctchPdiv(pdiv));
  34. pdiv->ptchCur = pdiv->ptchMin;
  35. }
  36. #if 0
  37. cbCtch(pdiv->ptchMax - pdiv->ptchMin));
  38. if (cb == cbErr || cb != cbCtch(pdiv->ptchMax - pdiv->ptchMin)) {
  39. Die("error writing file");
  40. }
  41. #endif
  42. /*****************************************************************************
  43. *
  44. * UnbufferPdiv
  45. *
  46. * Make a diversion unbuffered. This is done to stdout when input
  47. * is coming from an interactive device.
  48. *
  49. *****************************************************************************/
  50. void STDCALL
  51. UnbufferPdiv(PDIV pdiv)
  52. {
  53. AssertPdiv(pdiv);
  54. Assert(fFilePdiv(pdiv));
  55. FreePv(pdiv->ptchMin);
  56. pdiv->ptchMin = 0;
  57. pdiv->ptchCur = 0;
  58. pdiv->ptchMax = 0;
  59. }
  60. /*****************************************************************************
  61. *
  62. * GrowPdivCtch
  63. *
  64. * Extend a hold to have at least ctch free characters.
  65. *
  66. *****************************************************************************/
  67. void STDCALL
  68. GrowPdivCtch(PDIV pdiv, CTCH ctch)
  69. {
  70. PTCH ptch;
  71. AssertPdiv(pdiv);
  72. Assert(pdiv->ptchCur >= pdiv->ptchMin);
  73. Assert(pdiv->ptchCur <= pdiv->ptchMax);
  74. ctch = (CTCH)ROUNDUP(((UINT_PTR)(pdiv->ptchMax - pdiv->ptchMin)) + ctch, ctchGrow);
  75. ptch = ptchReallocPtchCtch(pdiv->ptchMin, ctch);
  76. pdiv->ptchCur = (pdiv->ptchCur - pdiv->ptchMin) + ptch;
  77. pdiv->ptchMax = ptch + ctch;
  78. pdiv->ptchMin = ptch;
  79. }
  80. /*****************************************************************************
  81. *
  82. * RoomifyPdivCtch
  83. *
  84. * Try to make room in a diversion for ctch characters, either by
  85. * extending it or by flushing it.
  86. *
  87. * File diversions are flushed to make room, but if that proves
  88. * not enough, we return even though the required amount of space
  89. * is not available. It is the caller's duty to check for this
  90. * case and recover accordingly.
  91. *
  92. * Memory diversions are reallocated.
  93. *
  94. *****************************************************************************/
  95. void STDCALL
  96. RoomifyPdivCtch(PDIV pdiv, CTCH ctch)
  97. {
  98. AssertPdiv(pdiv);
  99. if (fFilePdiv(pdiv)) {
  100. FlushPdiv(pdiv);
  101. } else {
  102. GrowPdivCtch(pdiv, ctch);
  103. }
  104. }
  105. /*****************************************************************************
  106. *
  107. * pdivAlloc
  108. *
  109. *****************************************************************************/
  110. PDIV STDCALL
  111. pdivAlloc(void)
  112. {
  113. PDIV pdiv = pvAllocCb(sizeof(DIV));
  114. pdiv->ptchMin = ptchAllocCtch(ctchGrow);
  115. pdiv->ptchCur = pdiv->ptchMin;
  116. pdiv->ptchMax = pdiv->ptchMin + ctchGrow;
  117. pdiv->ptchName = 0;
  118. pdiv->hf = hfNil;
  119. D(pdiv->cSnap = 0);
  120. D(pdiv->sig = sigDiv);
  121. return pdiv;
  122. }
  123. /*****************************************************************************
  124. *
  125. * OpenPdivPtok
  126. *
  127. * Prepare to load a new token into the diversion. The ptok is
  128. * partially initialized to record the point at which it began.
  129. *
  130. * The diversion must be unsnapped and must be a memory diversion.
  131. * (Data in file diversion buffers can go away when the diversion
  132. * is flushed.)
  133. *
  134. *****************************************************************************/
  135. void STDCALL
  136. OpenPdivPtok(PDIV pdiv, PTOK ptok)
  137. {
  138. #ifdef DEBUG
  139. AssertPdiv(pdiv);
  140. Assert(!pdiv->cSnap);
  141. Assert(!fFilePdiv(pdiv));
  142. D(ptok->sig = sigUPtok);
  143. ptok->tsfl = 0;
  144. ptok->ctch = (CTCH)-1; /* Keep people honest */
  145. #endif
  146. SetPtokItch(ptok, ctchPdiv(pdiv));
  147. }
  148. /*****************************************************************************
  149. *
  150. * AddPdivPtok
  151. * AddPdivTch
  152. *
  153. * Append a (snapped) token or character to the diversion.
  154. *
  155. * Note that in the file diversion case, we need to watch out
  156. * for tokens which are larger than our diversion buffer.
  157. *
  158. *****************************************************************************/
  159. void STDCALL
  160. AddPdivPtok(PDIV pdiv, PTOK ptok)
  161. {
  162. AssertPdiv(pdiv);
  163. AssertSPtok(ptok);
  164. if (ctchSPtok(ptok) > ctchAvailPdiv(pdiv)) {
  165. RoomifyPdivCtch(pdiv, ctchSPtok(ptok));
  166. if (ctchSPtok(ptok) > ctchAvailPdiv(pdiv)) {
  167. Assert(fFilePdiv(pdiv));
  168. WriteHfPtchCtch(pdiv->hf, ptchPtok(ptok), ctchSPtok(ptok));
  169. return;
  170. }
  171. }
  172. CopyPtchPtchCtch(pdiv->ptchCur, ptchPtok(ptok), ctchSPtok(ptok));
  173. pdiv->ptchCur += ctchSPtok(ptok);
  174. Assert(pdiv->ptchCur <= pdiv->ptchMax);
  175. }
  176. void STDCALL
  177. AddPdivTch(PDIV pdiv, TCHAR tch)
  178. {
  179. AssertPdiv(pdiv);
  180. if (pdiv->ptchCur >= pdiv->ptchMax) {
  181. RoomifyPdivCtch(pdiv, 1);
  182. }
  183. *pdiv->ptchCur++ = tch;
  184. Assert(pdiv->ptchCur <= pdiv->ptchMax);
  185. }
  186. /*****************************************************************************
  187. *
  188. * ClosePdivPtok
  189. *
  190. * Conclude the collection of a token in a diversion. The token
  191. * that is returned is not snapped.
  192. *
  193. *****************************************************************************/
  194. void STDCALL
  195. ClosePdivPtok(PDIV pdiv, PTOK ptok)
  196. {
  197. AssertPdiv(pdiv);
  198. AssertUPtok(ptok);
  199. Assert(!fClosedPtok(ptok));
  200. SetPtokCtch(ptok, ctchPdiv(pdiv) - itchPtok(ptok));
  201. }
  202. /*****************************************************************************
  203. *
  204. * PopPdivPtok
  205. *
  206. * Pop a snapped token off a memory diversion. Anything snapped after
  207. * the token is also popped away.
  208. *
  209. * Note that if the token has been modified, this will not necessarily
  210. * pop off everything.
  211. *
  212. *****************************************************************************/
  213. void STDCALL
  214. PopPdivPtok(PDIV pdiv, PTOK ptok)
  215. {
  216. AssertPdiv(pdiv);
  217. AssertSPtok(ptok);
  218. Assert(!fHeapPtok(ptok));
  219. Assert(ptchPtok(ptok) >= pdiv->ptchMin);
  220. Assert(ptchPtok(ptok) <= pdiv->ptchCur);
  221. pdiv->ptchCur = ptchPtok(ptok);
  222. D(pdiv->cSnap = 0);
  223. }
  224. /*****************************************************************************
  225. *
  226. * ptchPdivPtok
  227. *
  228. * Return a pointer to the first character of a diversion-relative
  229. * unsnapped token.
  230. *
  231. *****************************************************************************/
  232. PTCH STDCALL
  233. ptchPdivPtok(PDIV pdiv, PTOK ptok)
  234. {
  235. AssertPdiv(pdiv);
  236. AssertUPtok(ptok);
  237. return pdiv->ptchMin + itchPtok(ptok);
  238. }
  239. /*****************************************************************************
  240. *
  241. * SnapPdivPtok
  242. *
  243. * Convert an unsnapped hold-relative token to a snapped token.
  244. *
  245. *****************************************************************************/
  246. void STDCALL
  247. SnapPdivPtok(PDIV pdiv, PTOK ptok)
  248. {
  249. AssertPdiv(pdiv);
  250. AssertUPtok(ptok);
  251. SetPtokPtch(ptok, ptchPdivPtok(pdiv, ptok));
  252. D(pdiv->cSnap++);
  253. }
  254. /*****************************************************************************
  255. *
  256. * UnsnapPdivPtok
  257. *
  258. * Convert a snapped token back to an unsnapped hold-relative token.
  259. *
  260. *****************************************************************************/
  261. void STDCALL
  262. UnsnapPdivPtok(PDIV pdiv, PTOK ptok)
  263. {
  264. ITCH itch;
  265. AssertPdiv(pdiv);
  266. AssertSPtok(ptok);
  267. itch = (ITCH)(ptchPtok(ptok) - pdiv->ptchMin);
  268. D(ptok->sig = sigUPtok);
  269. SetPtokItch(ptok, itch);
  270. D(pdiv->cSnap--);
  271. }
  272. /*****************************************************************************
  273. *
  274. * CsopPdivDopPdivPtok
  275. *
  276. * A common idiom is
  277. *
  278. * CloseXxxPtok(ptok);
  279. * SnapXxxPtok(&tok);
  280. * Op(Yyy, &tok);
  281. * PopXxxPtok(&tok);
  282. *
  283. * so the Csop (csop = close, snap, op, pop) function does it all for you.
  284. *
  285. *****************************************************************************/
  286. void STDCALL
  287. CsopPdivDopPdivPtok(PDIV pdivSrc, DIVOP op, PDIV pdivDst, PTOK ptok)
  288. {
  289. AssertPdiv(pdivSrc);
  290. AssertUPtok(ptok);
  291. ClosePdivPtok(pdivSrc, ptok);
  292. SnapPdivPtok(pdivSrc, ptok);
  293. op(pdivDst, ptok);
  294. PopPdivPtok(pdivSrc, ptok);
  295. }