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

  1. /***
  2. *_flsbuf.c - flush buffer and output character.
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _flsbuf() - flush a file buffer and output a character.
  8. *       defines _flswbuf() - flush a file buffer and output a wide character.
  9. *       If no buffer, make one.
  10. *
  11. *******************************************************************************/
  12.  
  13. #ifdef _WIN32
  14.  
  15.  
  16. #include <cruntime.h>
  17. #include <stdio.h>
  18. #include <file2.h>
  19. #include <io.h>
  20. #include <dbgint.h>
  21. #include <malloc.h>
  22. #include <msdos.h>
  23. #include <wchar.h>
  24. #include <internal.h>
  25. #ifdef _MT
  26. #include <mtdll.h>
  27. #endif  /* _MT */
  28. #include <tchar.h>
  29.  
  30. #ifndef _UNICODE
  31.  
  32. /***
  33. *int _flsbuf(ch, stream) - flush buffer and output character.
  34. *
  35. *Purpose:
  36. *       flush a buffer if this stream has one. if not, try to get one. put the
  37. *       next output char (ch) into the buffer (or output it immediately if this
  38. *       stream can't have a buffer). called only from putc. intended for use
  39. *       only within library.
  40. *
  41. *       [NOTE: Multi-thread - It is assumed that the caller has aquired
  42. *       the stream lock.]
  43. *
  44. *Entry:
  45. *       FILE *stream - stream to flish and write on
  46. *       int ch - character to output.
  47. *
  48. *Exit:
  49. *       returns -1 if FILE is actually a string, or if can't write ch to
  50. *       unbuffered file, or if we flush a buffer but the number of chars
  51. *       written doesn't agree with buffer size.  Otherwise returns ch.
  52. *       all fields in FILE struct can be affected except _file.
  53. *
  54. *Exceptions:
  55. *
  56. *******************************************************************************/
  57.  
  58. int __cdecl _flsbuf (
  59.         int ch,
  60.         FILE *str
  61.         )
  62.  
  63. #else  /* _UNICODE */
  64.  
  65. /***
  66. *int _flswbuf(ch, stream) - flush buffer and output wide character.
  67. *
  68. *Purpose:
  69. *       flush a buffer if this stream has one. if not, try to get one. put the
  70. *       next output wide char (ch) into the buffer (or output it immediately if this
  71. *       stream can't have a buffer). called only from putwc. intended for use
  72. *       only within library.
  73. *
  74. *       [NOTE: Multi-thread - It is assumed that the caller has aquired
  75. *       the stream lock.]
  76. *
  77. *Entry:
  78. *       FILE *stream - stream to flish and write on
  79. *       int ch - wide character to output.
  80. *
  81. *Exit:
  82. *       returns -1 if FILE is actually a string, or if can't write ch to
  83. *       unbuffered file, or if we flush a buffer but the number of wide chars
  84. *       written doesn't agree with buffer size.  Otherwise returns ch.
  85. *       all fields in FILE struct can be affected except _file.
  86. *
  87. *Exceptions:
  88. *
  89. *******************************************************************************/
  90.  
  91. int __cdecl _flswbuf (
  92.         int ch,
  93.         FILE *str
  94.         )
  95.  
  96. #endif  /* _UNICODE */
  97.  
  98. {
  99.  
  100.         REG1 FILE *stream;
  101.         REG2 int charcount;
  102.         REG3 int written;
  103.         int fh;
  104.  
  105.         _ASSERTE(str != NULL);
  106.  
  107.         /* Init file handle and pointers */
  108.         stream = str;
  109.         fh = _fileno(stream);
  110.  
  111.         if (!(stream->_flag & (_IOWRT|_IORW)) || (stream->_flag & _IOSTRG)) {
  112.                 stream->_flag |= _IOERR;
  113.                 return(_TEOF);
  114.         }
  115.  
  116.         /* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note
  117.            that _IOREAD and IOEOF both being set implies switching from read to
  118.            write at end-of-file, which is allowed by ANSI. Note that resetting
  119.            the _cnt and _ptr fields amounts to doing an fflush() on the stream
  120.            in this case. Note also that the _cnt field has to be reset to 0 for
  121.            the error path as well (i.e., _IOREAD set but _IOEOF not set) as
  122.            well as the non-error path. */
  123.  
  124.         if (stream->_flag & _IOREAD) {
  125.                 stream->_cnt = 0;
  126.                 if (stream->_flag & _IOEOF) {
  127.                         stream->_ptr = stream->_base;
  128.                         stream->_flag &= ~_IOREAD;
  129.                 }
  130.                 else {
  131.                         stream->_flag |= _IOERR;
  132.                         return(_TEOF);
  133.                 }
  134.         }
  135.  
  136.         stream->_flag |= _IOWRT;
  137.         stream->_flag &= ~_IOEOF;
  138.         written = charcount = stream->_cnt = 0;
  139.  
  140.         /* Get a buffer for this stream, if necessary. */
  141.         if (!anybuf(stream)) {
  142.  
  143.                 /* Do NOT get a buffer if (1) stream is stdout/stderr, and
  144.                    (2) stream is NOT a tty.
  145.                    [If stdout/stderr is a tty, we do NOT set up single char
  146.                    buffering. This is so that later temporary buffering will
  147.                    not be thwarted by the _IONBF bit being set (see
  148.                    _stbuf/_ftbuf usage).]
  149.                 */
  150.                 if (!( ((stream==stdout) || (stream==stderr))
  151.                 && (_isatty(fh)) ))
  152.  
  153.                         _getbuf(stream);
  154.  
  155.         } /* end !anybuf() */
  156.  
  157.         /* If big buffer is assigned to stream... */
  158.         if (bigbuf(stream)) {
  159.  
  160.                 _ASSERTE(("inconsistent IOB fields", stream->_ptr - stream->_base >= 0));
  161.  
  162.                 charcount = stream->_ptr - stream->_base;
  163.                 stream->_ptr = stream->_base + sizeof(TCHAR);
  164.                 stream->_cnt = stream->_bufsiz - sizeof(TCHAR);
  165.  
  166.                 if (charcount > 0)
  167.                         written = _write(fh, stream->_base, charcount);
  168.                 else
  169.                         if (_osfile_safe(fh) & FAPPEND)
  170.                                 _lseek(fh,0L,SEEK_END);
  171.  
  172. #ifndef _UNICODE
  173.                 *stream->_base = (char)ch;
  174. #else  /* _UNICODE */
  175.                 *(wchar_t *)(stream->_base) = (wchar_t)(ch & 0xffff);
  176. #endif  /* _UNICODE */
  177.         }
  178.  
  179.     /* Perform single character output (either _IONBF or no buffering) */
  180.         else {
  181.                 charcount = sizeof(TCHAR);
  182. #ifndef _UNICODE
  183.                 written = _write(fh, &ch, charcount);
  184. #else  /* _UNICODE */
  185.                 {
  186.                         char mbc[4];
  187.  
  188.                         *(wchar_t *)mbc = (wchar_t)(ch & 0xffff);
  189.                         written = _write(fh, mbc, charcount);
  190.                 }
  191. #endif  /* _UNICODE */
  192.         }
  193.  
  194.         /* See if the _write() was successful. */
  195.         if (written != charcount) {
  196.                 stream->_flag |= _IOERR;
  197.                 return(_TEOF);
  198.         }
  199.  
  200. #ifndef _UNICODE
  201.         return(ch & 0xff);
  202. #else  /* _UNICODE */
  203.         return(ch & 0xffff);
  204. #endif  /* _UNICODE */
  205.  
  206. }
  207.  
  208.  
  209. #else  /* _WIN32 */
  210.  
  211. #if defined (_M_MPPC) || defined (_M_M68K)
  212.  
  213.  
  214. #include <cruntime.h>
  215. #include <stdio.h>
  216. #include <file2.h>
  217. #include <io.h>
  218. #include <dbgint.h>
  219. #include <malloc.h>
  220. #include <msdos.h>
  221. #include <internal.h>
  222.  
  223. /***
  224. *int _flsbuf(ch, stream) - flush buffer and output character.
  225. *
  226. *Purpose:
  227. *       flush a buffer if this stream has one. if not, try to get one. put the
  228. *       next output char (ch) into the buffer (or output it immediately if this
  229. *       stream can't have a buffer). called only from putc. intended for use
  230. *       only within library.
  231. *
  232. *Entry:
  233. *       FILE *stream - stream to flish and write on
  234. *       char ch - character to output.
  235. *
  236. *Exit:
  237. *       returns -1 if FILE is actually a string, or if can't write ch to
  238. *       unbuffered file, or if we flush a buffer but the number of chars
  239. *       written doesn't agree with buffer size.  Otherwise returns ch.
  240. *       all fields in FILE struct can be affected except _file.
  241. *
  242. *Exceptions:
  243. *
  244. *******************************************************************************/
  245.  
  246. int __cdecl _flsbuf (
  247.         int ch,
  248.         FILE *str
  249.         )
  250. {
  251.         REG1 FILE *stream;
  252.         REG2 int charcount;
  253.         REG3 int written;
  254.         int fh;
  255.         char chbuf;
  256.  
  257.         _ASSERTE(str != NULL);
  258.  
  259.         /* Init file handle and pointers */
  260.         stream = str;
  261.         fh = _fileno(stream);
  262.  
  263.         if (!(stream->_flag & (_IOWRT|_IORW)) || (stream->_flag & _IOSTRG)) {
  264.                 stream->_flag |= _IOERR;
  265.                 return(-1);
  266.         }
  267.  
  268.         /* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note
  269.            that _IOREAD and IOEOF both being set implies switching from read to
  270.            write at end-of-file, which is allowed by ANSI. Note that resetting
  271.            the _cnt and _ptr fields amounts to doing an fflush() on the stream
  272.            in this case. Note also that the _cnt field has to be reset to 0 for
  273.            the error path as well (i.e., _IOREAD set but _IOEOF not set) as
  274.            well as the non-error path. */
  275.  
  276.         if (stream->_flag & _IOREAD) {
  277.                 stream->_cnt = 0;
  278.                 if (stream->_flag & _IOEOF) {
  279.                         stream->_ptr = stream->_base;
  280.                         stream->_flag &= ~_IOREAD;
  281.                 }
  282.                 else {
  283.                         stream->_flag |= _IOERR;
  284.                         return(-1);
  285.                 }
  286.         }
  287.  
  288.         stream->_flag |= _IOWRT;
  289.         stream->_flag &= ~_IOEOF;
  290.         written = charcount = stream->_cnt = 0;
  291.  
  292.         /* Get a buffer for this stream, if necessary. */
  293.         if (!anybuf(stream)) {
  294.  
  295.                 /* Do NOT get a buffer if (1) stream is stdout/stderr, and
  296.                    (2) stream is NOT a tty.
  297.                    [If stdout/stderr is a tty, we do NOT set up single char
  298.                    buffering. This is so that later temporary buffering will
  299.                    not be thwarted by the _IONBF bit being set (see
  300.                    _stbuf/_ftbuf usage).]
  301.                 */
  302.                 if (!( ((stream==stdout) || (stream==stderr))
  303.                 && (_isatty(fh)) ))
  304.  
  305.                         _getbuf(stream);
  306.  
  307.         } /* end !anybuf() */
  308.  
  309.         /* If big buffer is assigned to stream... */
  310.         if (bigbuf(stream)) {
  311.  
  312.                 _ASSERTE(("inconsistent IOB fields", stream->_ptr - stream->_base >= 0));
  313.  
  314.                 charcount = stream->_ptr - stream->_base;
  315.                 stream->_ptr = stream->_base + 1;
  316.                 stream->_cnt = stream->_bufsiz - 1;
  317.  
  318.                 if (charcount > 0)
  319.                         written = _write(fh, stream->_base, charcount);
  320.                 else
  321.                         if (_osfile[fh] & FAPPEND)
  322.                                 _lseek(fh,0L,SEEK_END);
  323.  
  324.                 *stream->_base = (char)ch;
  325.         }
  326.  
  327.         /* Perform single character output (either _IONBF or no buffering) */
  328.         else {
  329.                 charcount = 1;
  330.                 chbuf = (char)ch;
  331.                 written = _write(fh, &chbuf, charcount);
  332.         }
  333.  
  334.         /* See if the _write() was successful. */
  335.         if (written != charcount) {
  336.                 stream->_flag |= _IOERR;
  337.                 return(-1);
  338.         }
  339.  
  340.         return(ch & 0xff);
  341. }
  342.  
  343.  
  344. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  345.  
  346. #endif  /* _WIN32 */
  347.