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

  1. /***
  2. *ungetc.c - unget a character from a stream
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines ungetc() - pushes a character back onto an input stream
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <stdio.h>
  13. #include <file2.h>
  14. #include <dbgint.h>
  15. #include <internal.h>
  16. #include <mtdll.h>
  17.  
  18. #ifdef _MT
  19.  
  20. /***
  21. *int ungetc(ch, stream) - put a character back onto a stream
  22. *
  23. *Purpose:
  24. *       Guaranteed one char pushback on a stream as long as open for reading.
  25. *       More than one char pushback in a row is not guaranteed, and will fail
  26. *       if it follows an ungetc which pushed the first char in buffer. Failure
  27. *       causes return of EOF.
  28. *
  29. *Entry:
  30. *       char ch - character to push back
  31. *       FILE *stream - stream to push character onto
  32. *
  33. *Exit:
  34. *       returns ch
  35. *       returns EOF if tried to push EOF, stream not opened for reading or
  36. *       or if we have already ungetc'd back to beginning of buffer.
  37. *
  38. *Exceptions:
  39. *
  40. *******************************************************************************/
  41.  
  42. int __cdecl ungetc (
  43.         REG2 int ch,
  44.         REG1 FILE *stream
  45.         )
  46. {
  47.         int retval;
  48.  
  49.         _ASSERTE(stream != NULL);
  50.  
  51.         _lock_str(stream);
  52.  
  53.         retval = _ungetc_lk (ch, stream);
  54.  
  55.         _unlock_str(stream);
  56.  
  57.         return(retval);
  58. }
  59.  
  60. /***
  61. *_ungetc_lk() -  Ungetc() core routine (locked version)
  62. *
  63. *Purpose:
  64. *       Core ungetc() routine; assumes stream is already locked.
  65. *
  66. *       [See ungetc() above for more info.]
  67. *
  68. *Entry: [See ungetc()]
  69. *
  70. *Exit:  [See ungetc()]
  71. *
  72. *Exceptions:
  73. *
  74. *******************************************************************************/
  75.  
  76. int __cdecl _ungetc_lk (
  77.         REG2 int ch,
  78.         FILE *str
  79.         )
  80.  
  81. {
  82.  
  83. #else  /* _MT */
  84.  
  85. int __cdecl ungetc (
  86.         REG2 int ch,
  87.         FILE *str
  88.         )
  89.  
  90. {
  91.  
  92. #endif  /* _MT */
  93.  
  94.         REG1 FILE *stream;
  95.  
  96.         _ASSERTE(str != NULL);
  97.  
  98.         /* Init stream pointer and file descriptor */
  99.         stream = str;
  100.  
  101.         /* Stream must be open for read and can NOT be currently in write mode.
  102.            Also, ungetc() character cannot be EOF. */
  103.  
  104.         if (
  105.               (ch == EOF) ||
  106.               !(
  107.                 (stream->_flag & _IOREAD) ||
  108.                 ((stream->_flag & _IORW) && !(stream->_flag & _IOWRT))
  109.                )
  110.            )
  111.                 return(EOF);
  112.  
  113.         /* If stream is unbuffered, get one. */
  114.  
  115.         if (stream->_base == NULL)
  116.                 _getbuf(stream);
  117.  
  118.         /* now we know _base != NULL; since file must be buffered */
  119.  
  120.         if (stream->_ptr == stream->_base) {
  121.                 if (stream->_cnt)
  122.                         /* my back is against the wall; i've already done
  123.                          * ungetc, and there's no room for this one
  124.                          */
  125.                         return(EOF);
  126.  
  127.                 stream->_ptr++;
  128.         }
  129.  
  130.         if (stream->_flag & _IOSTRG) {
  131.             /* If stream opened by sscanf do not modify buffer */
  132.                 if (*--stream->_ptr != (char)ch) {
  133.                         ++stream->_ptr;
  134.                         return(EOF);
  135.                 }
  136.         } else
  137.                 *--stream->_ptr = (char)ch;
  138.  
  139.         stream->_cnt++;
  140.         stream->_flag &= ~_IOEOF;
  141.         stream->_flag |= _IOREAD;       /* may already be set */
  142.  
  143.         return(0xff & ch);
  144. }
  145.