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.

177 lines
7.0 KiB

  1. /*****************************************************************************
  2. *
  3. * divert.h
  4. *
  5. * Diversions
  6. *
  7. *****************************************************************************/
  8. /*****************************************************************************
  9. *
  10. * Diversions
  11. *
  12. * A DIV (diversion) is a place where characters are thrown. There are
  13. * two kinds of diversions, corresponding to how data come out of them.
  14. * Although the same basic functions operate on diversions, the two types
  15. * are used for quite different purposes.
  16. *
  17. * File diversions are managed by the `divert' and `undivert' builtins
  18. * and hold data that will be regurgitated later all at one go,
  19. * possibly into another diversion. File diversions consists of a
  20. * fixed-size holding buffer, which when filled is dumped to a
  21. * temporary file. When the diversion is regurgitated, the file is
  22. * closed, rewound, and spit back. (Watch out! for the degenerate
  23. * case where a file is undiverted back into itself.) Note that small
  24. * file diversions may never actually result in a file being created.
  25. * The name of the temporary file must be held so that the file can
  26. * be deleted once it is no longer needed. (If this were UNIX, we
  27. * could use the open/unlink trick...)
  28. *
  29. * Memory diversions hold data that will be managed in a last in
  30. * first out (stack-like) manner. Memory diversions consist of a
  31. * dynamically-sized holding buffer, whose size grows to accomodate
  32. * the amount of stuff thrown into it. Since memory diversions
  33. * can be reallocated, you have to be careful about holding pointers
  34. * into the buffer.
  35. *
  36. * Thus was born the concept of `snapping'. Tokens which live inside
  37. * a diversion live their lives as `unsnapped' tokens, which means that
  38. * they refer to bytes in a manner that is not sensitive to potential
  39. * reallocations of their associated diversion. However, accessing
  40. * `unsnapped' tokens is relatively slow, so you can `snap' a token
  41. * into its diversion, which speeds up access to the token, but the
  42. * penalty is that the diversion cannot be reallocated while it contains
  43. * any snapped tokens, which means that you cannot add new characters
  44. * to the diversion.
  45. *
  46. * The cSnap field in a memory diversion records how many snapped tokens
  47. * still refer to the diversion. Only when the snap count drops to zero
  48. * can the diversion be modified.
  49. *
  50. *****************************************************************************/
  51. typedef struct DIVERSION {
  52. D(SIG sig;) /* Signature */
  53. PTCH ptchCur; /* Current free character in diversion buffer */
  54. PTCH ptchMax; /* One past end of diversion buffer */
  55. PTCH ptchMin; /* Beginning of diversion buffer */
  56. HF hf; /* File handle or hNil */
  57. PTCH ptchName; /* Name of temp file (0 if memory diversion) */
  58. D(int cSnap;)
  59. } DIV, *PDIV;
  60. typedef CONST DIV *PCDIV;
  61. #define ctchGrow 2048 /* Amount by which holds grow */
  62. #define sigDiv sigABCD('D', 'i', 'v', 'n')
  63. #define AssertPdiv(pdiv) AssertPNm(pdiv, Div)
  64. #define fFilePdiv(pdiv) ((pdiv)->ptchName)
  65. /*****************************************************************************
  66. *
  67. * ctchPdiv
  68. *
  69. * Returns the number of characters in the diversion buffer. Note
  70. * that this is relatively useless for file diversions since part
  71. * of the data may be on disk.
  72. *
  73. *****************************************************************************/
  74. INLINE CTCH
  75. ctchPdiv(PCDIV pdiv)
  76. {
  77. return (CTCH)(pdiv->ptchCur - pdiv->ptchMin);
  78. }
  79. /*****************************************************************************
  80. *
  81. * ctchAvailPdiv
  82. *
  83. * Returns the number of characters available in the diversion buffer.
  84. *
  85. *****************************************************************************/
  86. INLINE CTCH
  87. ctchAvailPdiv(PCDIV pdiv)
  88. {
  89. return (CTCH)(pdiv->ptchMax - pdiv->ptchCur);
  90. }
  91. /*****************************************************************************
  92. *
  93. * DesnapPdiv
  94. *
  95. * Destroy a snapped token. You can't just throw it away because that
  96. * messes up the snap-ness bookkeeping. NOTE! that a desnapped token
  97. * becomes invalid the moment you add something new to the diversion.
  98. *
  99. *****************************************************************************/
  100. INLINE void
  101. DesnapPdiv(PDIV pdiv)
  102. {
  103. AssertPdiv(pdiv);
  104. D(pdiv->cSnap--);
  105. }
  106. void STDCALL UnbufferPdiv(PDIV pdiv);
  107. void STDCALL FlushPdiv(PDIV pdiv);
  108. PDIV STDCALL pdivAlloc(void);
  109. void STDCALL OpenPdivPtok(PDIV pdiv, PTOK ptok);
  110. void STDCALL AddPdivPtok(PDIV pdiv, PTOK ptok);
  111. void STDCALL AddPdivTch(PDIV pdiv, TCH tch);
  112. void STDCALL ClosePdivPtok(PDIV pdiv, PTOK ptok);
  113. void STDCALL PopPdivPtok(PDIV pdiv, PTOK ptok);
  114. PTCH STDCALL ptchPdivPtok(PDIV pdiv, PTOK ptok);
  115. void STDCALL SnapPdivPtok(PDIV pdiv, PTOK ptok);
  116. void STDCALL UnsnapPdivPtok(PDIV pdiv, PTOK ptok);
  117. typedef void (STDCALL *DIVOP)(PDIV pdiv, PTOK ptok);
  118. void STDCALL CsopPdivDopPdivPtok(PDIV pdivSrc, DIVOP op, PDIV pdivDst, PTOK ptok);
  119. /*
  120. * Some predefined holds and ways to get to them.
  121. *
  122. * The most important hold is the `Arg' hold. This is where
  123. * macro parameters are collected and parsed. Note! that the
  124. * `Arg' hold is snapped during macro expansion.
  125. *
  126. * Another popular hold is the `Exp' hold. This is where
  127. * macro expansions are held until a final home can be found.
  128. *
  129. * This would be a lot easier if we supported currying...
  130. *
  131. */
  132. extern PDIV g_pdivArg;
  133. #define OpenArgPtok(ptok) OpenPdivPtok(g_pdivArg, ptok)
  134. #define CloseArgPtok(ptok) ClosePdivPtok(g_pdivArg, ptok)
  135. #define AddArgPtok(ptok) AddPdivPtok(g_pdivArg, ptok)
  136. #define AddArgTch(tch) AddPdivTch(g_pdivArg, tch)
  137. #define ptchArgPtok(ptok) ptchPdivPtok(g_pdivArg, ptok)
  138. #define SnapArgPtok(ptok) SnapPdivPtok(g_pdivArg, ptok)
  139. #define UnsnapArgPtok(ptok) UnsnapPdivPtok(g_pdivArg, ptok)
  140. #define DesnapArg() DesnapPdiv(g_pdivArg)
  141. #define PopArgPtok(ptok) PopPdivPtok(g_pdivArg, ptok)
  142. #define CsopArgDopPdivPtok(op, pdiv, ptok) \
  143. CsopPdivDopPdivPtok(g_pdivArg, op, pdiv, ptok)
  144. extern PDIV g_pdivExp;
  145. #define OpenExpPtok(ptok) OpenPdivPtok(g_pdivExp, ptok)
  146. #define CloseExpPtok(ptok) ClosePdivPtok(g_pdivExp, ptok)
  147. #define AddExpPtok(ptok) AddPdivPtok(g_pdivExp, ptok)
  148. #define AddExpTch(tch) AddPdivTch(g_pdivExp, tch)
  149. #define ptchExpPtok(ptok) ptchPdivPtok(g_pdivExp, ptok)
  150. #define SnapExpPtok(ptok) SnapPdivPtok(g_pdivExp, ptok)
  151. #define UnsnapExpPtok(ptok) UnsnapPdivPtok(g_pdivExp, ptok)
  152. #define DesnapExp() DesnapPdiv(g_pdivExp)
  153. #define PopExpPtok(ptok) PopPdivPtok(g_pdivExp, ptok)
  154. #define CsopExpDopPdivPtok(op, pdiv, ptok) \
  155. CsopPdivDopPdivPtok(g_pdivExp, op, pdiv, ptok)
  156. extern PDIV g_pdivErr;
  157. extern PDIV g_pdivOut;
  158. extern PDIV g_pdivNul;
  159. extern PDIV g_pdivCur;