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.

241 lines
8.6 KiB

  1. /***
  2. *_sftbuf.c - temporary buffering initialization and flushing
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * temporary buffering initialization and flushing. if stdout/err is
  8. * unbuffered, buffer it temporarily so that string is sent to kernel as
  9. * a batch of chars, not char-at-a-time. if appropriate, make buffering
  10. * permanent.
  11. *
  12. * [NOTE 1: These routines assume that the temporary buffering is only
  13. * used for output. In particular, note that _stbuf() sets _IOWRT.]
  14. *
  15. * [NOTE 2: It is valid for this module to assign a value directly to
  16. * _flag instead of simply twiddling bits since we are initializing the
  17. * buffer data base.]
  18. *
  19. *Revision History:
  20. * 09-01-83 RN initial version
  21. * 06-26-85 TC added code to _stbuf to allow variable buffer lengths
  22. * ??-??-?? TC fixed case in _flbuf where flag is off, but a temporary
  23. * buffer still needs to be fflushed.
  24. * 05-27-87 JCR protect mode does not know about stdprn.
  25. * 06-26-87 JCR Conditionalized out code in _ftbuf that caused
  26. * redirected stdout to be flushed on every call.
  27. * 07-01-87 JCR Put in code to support re-entrant calling from
  28. * interrupt level (MSC only).
  29. * 08-06-87 JCR Fixed a _ftbuf() problem pertaining to stderr/stdprn
  30. * when _bufout is being used by stdout.
  31. * 08-07-87 JCR (1) When assigning _bufout to an _iob, we now set the
  32. * _IOWRT flag. This fixes a bug involving freopen()
  33. * issued against one of the std handles.
  34. * (2) Removed some annoying commented out code.
  35. * 08-13-87 JCR _ftbuf() does NOT clear _IOWRT now. Fixes a bug where
  36. * _getstream() would reassign stdout because none of the
  37. * flags were set.
  38. * 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
  39. * 11-05-87 JCR Re-written for multi-thread support and simplicity
  40. * 01-11-88 JCR Merged mthread version into normal version
  41. * 01-13-88 SKS Changed bogus "_fileno_lk" to "fileno"
  42. * 06-06-88 JCR Optimized _iob2 references
  43. * 06-10-88 JCR Use near pointer to reference _iob[] entries
  44. * 06-27-88 JCR Added stdprn temporary buffering support (DOS only),
  45. * and made buffer allocation dynamic; also added _IOFLRTN
  46. * (flush stream on per routine basis).
  47. * 08-25-88 GJF Modified to also work for the 386 (small model only).
  48. * 06-20-89 PHG Changed return value to void
  49. * 08-28-89 JCR Removed _NEAR_ for 386
  50. * 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
  51. * indents.
  52. * 03-16-90 GJF Made calling type _CALLTYPE1, added #include
  53. * <cruntime.h> and removed #include <register.h>. Also,
  54. * removed some leftover 16-bit DOS support.
  55. * 03-27-90 GJF Added #include <io.h>.
  56. * 05-29-90 SBM Use _flush, not [_]fflush[_lk]
  57. * 07-23-90 SBM Replaced <assertm.h> by <assert.h>
  58. * 10-03-90 GJF New-style function declarator.
  59. * 01-22-91 GJF ANSI naming.
  60. * 03-27-92 DJM POSIX support.
  61. * 08-26-92 GJF Include unistd.h for POSIX build.
  62. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  63. * 05-11-93 GJF Replaced BUFSIZ with _INTERNAL_BUFSIZ.
  64. * 04-05-94 GJF #ifdef-ed out _cflush reference for msvcrt*.dll, it
  65. * is unnecessary. Also, replaced MTHREAD with _MT.
  66. * 01-10-95 CFW Debug CRT allocs.
  67. * 02-06-94 CFW assert -> _ASSERTE.
  68. * 02-17-95 GJF Merged in Mac version.
  69. * 02-07-97 GJF Changed _stbuf() to use _charbuf when malloc fails.
  70. * Also, detab-ed.
  71. * 05-17-99 PML Remove all Macintosh support.
  72. *
  73. *******************************************************************************/
  74. #include <cruntime.h>
  75. #ifdef _POSIX_
  76. #include <unistd.h>
  77. #endif
  78. #include <stdio.h>
  79. #include <file2.h>
  80. #include <io.h>
  81. #include <internal.h>
  82. #include <malloc.h>
  83. #ifdef _MT
  84. #include <mtdll.h>
  85. #endif
  86. #include <dbgint.h>
  87. /* Buffer pointers for stdout and stderr */
  88. void *_stdbuf[2] = { NULL, NULL};
  89. /***
  90. *int _stbuf(stream) - set temp buffer on stdout, stdprn, stderr
  91. *
  92. *Purpose:
  93. * if stdout/stderr is still unbuffered, buffer it.
  94. * this function works intimately with _ftbuf, and accompanies it in
  95. * bracketing normally unbuffered output. these functions intended for
  96. * library use only.
  97. *
  98. * Multi-thread: It is assumed that the caller has already aquired the
  99. * stream lock.
  100. *
  101. *Entry:
  102. * FILE *stream - stream to temp buffer
  103. *
  104. *Exit:
  105. * returns 1 if buffer initialized, 0 if not
  106. * sets fields in stdout or stderr to indicate buffering
  107. *
  108. *Exceptions:
  109. *
  110. *******************************************************************************/
  111. int __cdecl _stbuf (
  112. FILE *str
  113. )
  114. {
  115. REG1 FILE *stream;
  116. int index;
  117. _ASSERTE(str != NULL);
  118. /* Init near stream pointer */
  119. stream = str;
  120. /* do nothing if not a tty device */
  121. #ifdef _POSIX_
  122. if (!isatty(fileno(stream)))
  123. #else
  124. if (!_isatty(_fileno(stream)))
  125. #endif
  126. return(0);
  127. /* Make sure stream is stdout/stderr and init _stdbuf index */
  128. if (stream == stdout)
  129. index = 0;
  130. else if (stream == stderr)
  131. index = 1;
  132. else
  133. return(0);
  134. #ifndef CRTDLL
  135. /* force library pre-termination procedure */
  136. _cflush++;
  137. #endif /* CRTDLL */
  138. /* Make sure the stream is not already buffered. */
  139. if (anybuf(stream))
  140. return(0);
  141. /* Allocate a buffer for this stream if we haven't done so yet. */
  142. if ( (_stdbuf[index] == NULL) &&
  143. ((_stdbuf[index]=_malloc_crt(_INTERNAL_BUFSIZ)) == NULL) ) {
  144. /* Cannot allocate buffer. Use _charbuf this time */
  145. stream->_ptr = stream->_base = (void *)&(stream->_charbuf);
  146. stream->_cnt = stream->_bufsiz = 2;
  147. }
  148. else {
  149. /* Set up the buffer */
  150. stream->_ptr = stream->_base = _stdbuf[index];
  151. stream->_cnt = stream->_bufsiz = _INTERNAL_BUFSIZ;
  152. }
  153. stream->_flag |= (_IOWRT | _IOYOURBUF | _IOFLRTN);
  154. return(1);
  155. }
  156. /***
  157. *void _ftbuf(flag, stream) - take temp buffering off a stream
  158. *
  159. *Purpose:
  160. * If stdout/stderr is being buffered and it is a device, _flush and
  161. * dismantle the buffer. if it's not a device, leave the buffering on.
  162. * This function works intimately with _stbuf, and accompanies it in
  163. * bracketing normally unbuffered output. these functions intended for
  164. * library use only
  165. *
  166. * Multi-thread: It is assumed that the caller has already aquired the
  167. * stream lock.
  168. *
  169. *Entry:
  170. * int flag - a flag to tell whether to dismantle temp buffering on a
  171. * stream
  172. * FILE *stream - the stream
  173. *
  174. *Exit:
  175. * no return value
  176. * sets fields in stdout/stderr
  177. *
  178. *Exceptions:
  179. *
  180. *******************************************************************************/
  181. void __cdecl _ftbuf (
  182. int flag,
  183. FILE *str
  184. )
  185. {
  186. REG1 FILE *stream;
  187. _ASSERTE(flag == 0 || flag == 1);
  188. /* Init near stream pointers */
  189. stream = str;
  190. if (flag) {
  191. if (stream->_flag & _IOFLRTN) {
  192. /* Flush the stream and tear down temp buffering. */
  193. _flush(stream);
  194. stream->_flag &= ~(_IOYOURBUF | _IOFLRTN);
  195. stream->_bufsiz = 0;
  196. stream->_base = stream->_ptr = NULL;
  197. }
  198. /* Note: If we expand the functionality of the _IOFLRTN bit to
  199. include other streams, we may want to clear that bit here under
  200. an 'else' clause (i.e., clear bit in the case that we leave the
  201. buffer permanently assigned. Given our current use of the bit,
  202. the extra code is not needed. */
  203. } /* end flag = 1 */
  204. #ifndef _MT
  205. /* NOTE: Currently, writing to the same string at interrupt level does not
  206. work in multi-thread programs. */
  207. /* The following code is needed if an interrupt occurs between calls
  208. to _stbuf/_ftbuf and the interrupt handler also calls _stbuf/_ftbuf. */
  209. else
  210. if (stream->_flag & _IOFLRTN)
  211. _flush(stream);
  212. #endif /* _MT */
  213. }