home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / _sftbuf.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  6KB  |  199 lines

  1. /***
  2. *_sftbuf.c - temporary buffering initialization and flushing
  3. *
  4. *       Copyright (c) 1985-1997, 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. *******************************************************************************/
  20.  
  21. #include <cruntime.h>
  22. #include <stdio.h>
  23. #include <file2.h>
  24. #include <io.h>
  25. #include <internal.h>
  26. #include <malloc.h>
  27. #ifdef _MT
  28. #include <mtdll.h>
  29. #endif  /* _MT */
  30. #include <dbgint.h>
  31.  
  32. /* Buffer pointers for stdout and stderr */
  33. void *_stdbuf[2] = { NULL, NULL};
  34.  
  35. /***
  36. *int _stbuf(stream) - set temp buffer on stdout, stdprn, stderr
  37. *
  38. *Purpose:
  39. *       if stdout/stderr is still unbuffered, buffer it.
  40. *       this function works intimately with _ftbuf, and accompanies it in
  41. *       bracketing normally unbuffered output. these functions intended for
  42. *       library use only.
  43. *
  44. *       Multi-thread: It is assumed that the caller has already aquired the
  45. *       stream lock.
  46. *
  47. *Entry:
  48. *       FILE *stream - stream to temp buffer
  49. *
  50. *Exit:
  51. *       returns 1 if buffer initialized, 0 if not
  52. *       sets fields in stdout or stderr to indicate buffering
  53. *
  54. *Exceptions:
  55. *
  56. *******************************************************************************/
  57.  
  58. int __cdecl _stbuf (
  59.         FILE *str
  60.         )
  61. {
  62.         REG1 FILE *stream;
  63.         int index;
  64.  
  65.         _ASSERTE(str != NULL);
  66.  
  67.         /* Init near stream pointer */
  68.         stream = str;
  69.  
  70.         /* do nothing if not a tty device */
  71.         if (!_isatty(_fileno(stream)))
  72.                 return(0);
  73.  
  74.         /* Make sure stream is stdout/stderr and init _stdbuf index */
  75.         if (stream == stdout)
  76.                 index = 0;
  77.         else if (stream == stderr)
  78.                 index = 1;
  79.         else
  80.                 return(0);
  81.  
  82. #ifndef CRTDLL
  83.         /* force library pre-termination procedure */
  84.         _cflush++;
  85. #endif  /* CRTDLL */
  86.  
  87.         /* Make sure the stream is not already buffered. */
  88.         if (anybuf(stream))
  89.                 return(0);
  90.  
  91.         /* Allocate a buffer for this stream if we haven't done so yet. */
  92.         if ( (_stdbuf[index] == NULL) &&
  93. #ifdef _WIN32
  94.              ((_stdbuf[index]=_malloc_crt(_INTERNAL_BUFSIZ)) == NULL) ) {
  95. #else  /* _WIN32 */
  96. #ifdef _MAC
  97.              ((_stdbuf[index]=_malloc_crt(BUFSIZ)) == NULL) ) {
  98. #endif  /* _MAC */
  99. #endif  /* _WIN32 */
  100.                 /* Cannot allocate buffer. Use _charbuf this time */
  101.                 stream->_ptr = stream->_base = (void *)&(stream->_charbuf);
  102. #ifdef _WIN32
  103.                 stream->_cnt = stream->_bufsiz = 2;
  104. #else  /* _WIN32 */
  105. #ifdef _MAC
  106.                 stream->_cnt = stream->_bufsiz = 1;
  107. #endif  /* _MAC */
  108. #endif  /* _WIN32 */
  109.         }
  110.         else {
  111.                 /* Set up the buffer */
  112.                 stream->_ptr = stream->_base = _stdbuf[index];
  113. #ifdef _WIN32
  114.                 stream->_cnt = stream->_bufsiz = _INTERNAL_BUFSIZ;
  115. #else  /* _WIN32 */
  116. #ifdef _MAC
  117.                 stream->_cnt = stream->_bufsiz = BUFSIZ;
  118. #endif  /* _MAC */
  119. #endif  /* _WIN32 */
  120.         }
  121.  
  122.         stream->_flag |= (_IOWRT | _IOYOURBUF | _IOFLRTN);
  123.  
  124.         return(1);
  125. }
  126.  
  127.  
  128. /***
  129. *void _ftbuf(flag, stream) - take temp buffering off a stream
  130. *
  131. *Purpose:
  132. *       If stdout/stderr is being buffered and it is a device, _flush and
  133. *       dismantle the buffer. if it's not a device, leave the buffering on.
  134. *       This function works intimately with _stbuf, and accompanies it in
  135. *       bracketing normally unbuffered output. these functions intended for
  136. *       library use only
  137. *
  138. *       Multi-thread: It is assumed that the caller has already aquired the
  139. *       stream lock.
  140. *
  141. *Entry:
  142. *       int flag     - a flag to tell whether to dismantle temp buffering on a
  143. *                      stream
  144. *       FILE *stream - the stream
  145. *
  146. *Exit:
  147. *       no return value
  148. *       sets fields in stdout/stderr
  149. *
  150. *Exceptions:
  151. *
  152. *******************************************************************************/
  153.  
  154. void __cdecl _ftbuf (
  155.         int flag,
  156.         FILE *str
  157.         )
  158. {
  159.         REG1 FILE *stream;
  160.  
  161.         _ASSERTE(flag == 0 || flag == 1);
  162.  
  163.         /* Init near stream pointers */
  164.         stream = str;
  165.  
  166.         if (flag) {
  167.  
  168.                 if (stream->_flag & _IOFLRTN) {
  169.  
  170.                         /* Flush the stream and tear down temp buffering. */
  171.                         _flush(stream);
  172.                         stream->_flag &= ~(_IOYOURBUF | _IOFLRTN);
  173.                         stream->_bufsiz = 0;
  174.                         stream->_base = stream->_ptr = NULL;
  175.                 }
  176.  
  177.                 /* Note: If we expand the functionality of the _IOFLRTN bit to
  178.                 include other streams, we may want to clear that bit here under
  179.                 an 'else' clause (i.e., clear bit in the case that we leave the
  180.                 buffer permanently assigned.  Given our current use of the bit,
  181.                 the extra code is not needed. */
  182.  
  183.         } /* end flag = 1 */
  184.  
  185. #ifndef _MT
  186. /* NOTE: Currently, writing to the same string at interrupt level does not
  187.    work in multi-thread programs. */
  188.  
  189. /* The following code is needed if an interrupt occurs between calls
  190.    to _stbuf/_ftbuf and the interrupt handler also calls _stbuf/_ftbuf. */
  191.  
  192.         else
  193.                 if (stream->_flag & _IOFLRTN)
  194.                         _flush(stream);
  195.  
  196. #endif  /* _MT */
  197.  
  198. }
  199.