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.

340 lines
8.9 KiB

  1. /*****************************************************************************
  2. *
  3. * stream.c
  4. *
  5. * Management of input streams.
  6. *
  7. *****************************************************************************/
  8. #include "m4.h"
  9. #define tsCur 0
  10. #define tsNormal 0
  11. /*****************************************************************************
  12. *
  13. * FreePstm
  14. *
  15. * Free the memory associated with a stream.
  16. *
  17. *****************************************************************************/
  18. void STDCALL
  19. FreePstm(PSTM pstm)
  20. {
  21. AssertPstm(pstm);
  22. Assert(pstm->hf == hfNil);
  23. if (pstm->ptchName) {
  24. FreePv(pstm->ptchName);
  25. }
  26. FreePv(pstm->ptchMin);
  27. FreePv(pstm);
  28. }
  29. /*****************************************************************************
  30. *
  31. * Reading from the stream
  32. *
  33. *****************************************************************************/
  34. /*****************************************************************************
  35. *
  36. * ptchFindPtchCtchTch
  37. *
  38. * Locate the first occurrence of a character in a buffer.
  39. * Returns 0 if the character is not found.
  40. *
  41. *****************************************************************************/
  42. #ifdef UNICODE
  43. PTCH STDCALL
  44. ptchFindPtchCtchTch(PCTCH ptch, CTCH ctch, TCH tch)
  45. {
  46. for ( ; ctch; ptch++, ctch--) {
  47. if (*ptch == tch) {
  48. return ptch;
  49. }
  50. }
  51. return 0;
  52. }
  53. #else
  54. #define ptchFindPtchCtchTch(ptch, ctch, tch) memchr(ptch, tch, ctch)
  55. #endif
  56. /*****************************************************************************
  57. *
  58. * ctchDemagicPstmCtch
  59. *
  60. * Quote all occurences of tchMagic in the stream. This is called only
  61. * when you're probably already in trouble, so performance is not an issue.
  62. *
  63. * Entry:
  64. *
  65. * pstm->ptchMin -> Beginning of buffer
  66. * pstm->ptchMax -> End of buffer
  67. * ctch = number of characters to convert
  68. *
  69. * Returns:
  70. *
  71. * number of characters converted and left in the buffer
  72. * pstm->ptchMin -> Beginning of buffer
  73. * pstm->ptchMax -> End of buffer
  74. *
  75. * NOTE! that this procedure may reallocate the buffer.
  76. *
  77. *****************************************************************************/
  78. /* SOMEDAY! - This causes NULs to come out as tchzero, whatever that is! */
  79. CTCH STDCALL
  80. ctchDemagicPstmCtch(PSTM pstm, CTCH ctch)
  81. {
  82. PTCH ptchIn, ptchOut, ptchMax, ptchNew;
  83. AssertPstm(pstm);
  84. ptchNew = ptchAllocCtch(ctch * 2); /* Worst-case output buffer */
  85. ptchMax = pstm->ptchMin + ctch;
  86. ptchOut = ptchNew;
  87. ptchIn = pstm->ptchMin;
  88. while (ptchIn < ptchMax) {
  89. if (*ptchIn == tchMagic) {
  90. *ptchOut++ = tchMagic;
  91. }
  92. *ptchOut++ = *ptchIn++;
  93. }
  94. FreePv(pstm->ptchMin);
  95. pstm->ptchMin = ptchNew;
  96. pstm->ptchMax = ptchNew + ctch * 2;
  97. return (CTCH)(ptchOut - pstm->ptchMin);
  98. }
  99. /*****************************************************************************
  100. *
  101. * fFillPstm
  102. *
  103. * Refill a stream from its file, if possible.
  104. *
  105. * Each file ends with an artificial EOF token, so that we can detect
  106. * bad things like files that end with incomplete comments or quotes,
  107. * and so that the last word of one file does not adjoin the first word
  108. * of the next.
  109. *
  110. *****************************************************************************/
  111. BOOL STDCALL
  112. fFillPstm(PSTM pstm)
  113. {
  114. AssertPstm(pstm);
  115. if (pstm->hf != hfNil) {
  116. CB cb;
  117. CTCH ctch;
  118. Assert(pstm->ptchMax - pstm->ptchMin >= ctchFile);
  119. cb = cbReadHfPvCb(pstm->hf, pstm->ptchMin, cbCtch(ctchFile));
  120. if (cb == cbErr) {
  121. Die("error reading file");
  122. }
  123. ctch = ctchCb(cb);
  124. if (cbCtch(ctch) != cb) {
  125. Die("odd number of bytes in UNICODE file");
  126. }
  127. if (ctch) {
  128. if (ptchFindPtchCtchTch(pstm->ptchMin, ctch, tchMagic)) {
  129. ctch = ctchDemagicPstmCtch(pstm, ctch);
  130. }
  131. pstm->ptchCur = pstm->ptchMax - ctch;
  132. MovePtchPtchCtch(g_pstmCur->ptchCur, g_pstmCur->ptchMin, ctch);
  133. } else { /* EOF reached */
  134. CloseHf(pstm->hf);
  135. pstm->hf = hfNil;
  136. PushPtok(&tokEof); /* Eek! Does this actually work? */
  137. }
  138. return 1;
  139. } else {
  140. return 0;
  141. }
  142. }
  143. /*****************************************************************************
  144. *
  145. * tchPeek
  146. *
  147. * Fetch but do not consume the next character in the stream.
  148. *
  149. *****************************************************************************/
  150. TCH STDCALL
  151. tchPeek(void)
  152. {
  153. AssertPstm(g_pstmCur);
  154. while (g_pstmCur->ptchCur >= g_pstmCur->ptchMax) { /* Rarely */
  155. Assert(g_pstmCur->ptchCur == g_pstmCur->ptchMax);
  156. if (!fFillPstm(g_pstmCur)) {
  157. PSTM pstmNew = g_pstmCur->pstmNext;
  158. Assert(pstmNew != 0);
  159. FreePstm(g_pstmCur); /* Closes file, etc */
  160. g_pstmCur = pstmNew;
  161. }
  162. }
  163. return *g_pstmCur->ptchCur;
  164. }
  165. /*****************************************************************************
  166. *
  167. * tchGet
  168. *
  169. * Fetch and consume the next character in the stream.
  170. *
  171. * LATER - update line number
  172. *
  173. *****************************************************************************/
  174. TCH STDCALL
  175. tchGet(void)
  176. {
  177. TCH tch = tchPeek();
  178. Assert(*g_pstmCur->ptchCur == tch);
  179. g_pstmCur->ptchCur++;
  180. return tch;
  181. }
  182. /*****************************************************************************
  183. *
  184. * Pushing
  185. *
  186. *****************************************************************************/
  187. /*****************************************************************************
  188. *
  189. * UngetTch
  190. *
  191. * Ungetting a character is the same as pushing it, except that it goes
  192. * onto the file stream rather than onto the string stream.
  193. *
  194. * LATER - update line number
  195. *
  196. *****************************************************************************/
  197. void STDCALL
  198. UngetTch(TCH tch)
  199. {
  200. AssertPstm(g_pstmCur);
  201. Assert(g_pstmCur->ptchCur <= g_pstmCur->ptchMax);
  202. Assert(g_pstmCur->ptchCur > g_pstmCur->ptchMin);
  203. g_pstmCur->ptchCur--;
  204. Assert(*g_pstmCur->ptchCur == tch);
  205. }
  206. /*****************************************************************************
  207. *
  208. * pstmPushStringCtch
  209. *
  210. * Push a fresh string stream of the requested size.
  211. *
  212. *****************************************************************************/
  213. PSTM STDCALL
  214. pstmPushStringCtch(CTCH ctch)
  215. {
  216. PSTM pstm;
  217. Assert(ctch);
  218. pstm = pvAllocCb(sizeof(STM));
  219. pstm->pstmNext = g_pstmCur;
  220. pstm->hf = hfNil;
  221. pstm->ptchName = 0;
  222. pstm->ptchMin = ptchAllocCtch(ctch);
  223. pstm->ptchCur = pstm->ptchMax = pstm->ptchMin + ctch;
  224. D(pstm->sig = sigStm);
  225. g_pstmCur = pstm;
  226. return pstm;
  227. }
  228. /*****************************************************************************
  229. *
  230. * pstmPushHfPtch
  231. *
  232. * Push a fresh file stream with the indicated name.
  233. *
  234. *****************************************************************************/
  235. PSTM STDCALL
  236. pstmPushHfPtch(HFILE hf, PTCH ptch)
  237. {
  238. PSTM pstm = pstmPushStringCtch(ctchFile);
  239. pstm->hf = hf;
  240. pstm->ptchName = ptch;
  241. return pstm;
  242. }
  243. /*****************************************************************************
  244. *
  245. * PushPtok
  246. * PushZPtok
  247. *
  248. * Push a token buffer onto the stream, possibly allocating a new
  249. * top-of-stream if the current top-of-stream isn't big enough to
  250. * handle it.
  251. *
  252. * PushZPtok takes a dummy pdiv argument.
  253. *
  254. * LATER - Should also alloc new tos if current tos is a file.
  255. * This keeps line numbers happy.
  256. *
  257. *****************************************************************************/
  258. void STDCALL
  259. PushPtok(PCTOK ptok)
  260. {
  261. AssertPstm(g_pstmCur);
  262. /* Assert(tsCur == tsNormal); */ /* Make sure tokenizer is quiet */
  263. if (ctchSPtok(ptok) > (CTCH)(g_pstmCur->ptchCur - g_pstmCur->ptchMin)) {
  264. pstmPushStringCtch(max(ctchSPtok(ptok), ctchMinPush));
  265. }
  266. g_pstmCur->ptchCur -= ctchSPtok(ptok);
  267. Assert(g_pstmCur->ptchCur >= g_pstmCur->ptchMin); /* Buffer underflow! */
  268. CopyPtchPtchCtch(g_pstmCur->ptchCur, ptchPtok(ptok), ctchSPtok(ptok));
  269. }
  270. void STDCALL
  271. PushZPtok(PDIV pdiv, PCTOK ptok)
  272. {
  273. PushPtok(ptok);
  274. }
  275. /*****************************************************************************
  276. *
  277. * PushTch
  278. *
  279. * Push a single character. We do this by creating a scratch token.
  280. *
  281. *****************************************************************************/
  282. void STDCALL
  283. PushTch(TCH tch)
  284. {
  285. TOK tok;
  286. SetStaticPtokPtchCtch(&tok, &tch, 1);
  287. PushPtok(&tok);
  288. }
  289. /*****************************************************************************
  290. *
  291. * PushQuotedPtok
  292. *
  293. * Push a token buffer onto the stream, quoted.
  294. *
  295. *****************************************************************************/
  296. void STDCALL
  297. PushQuotedPtok(PCTOK ptok)
  298. {
  299. /* Assert(tsCur == tsNormal); */ /* Make sure tokenizer is quiet */
  300. /* SOMEDAY -- should be ptokLquo and ptokRquo once we support changing quotes */
  301. PushTch(tchRquo);
  302. PushPtok(ptok);
  303. PushTch(tchLquo);
  304. }