extern "C" wint_t __cdecl _ungetwc_nolock(wint_t const c, FILE* const public_stream) { __crt_stdio_stream const stream(public_stream); // Ungetting WEOF is expressly forbidden: if (c == WEOF) return WEOF; // To unget, the stream must currently be in read mode, _or_ it must be open // for update (read and write) and must not _currently_ be in write mode: bool const is_in_read_mode = stream.has_all_of(_IOREAD); bool const is_in_update_mode = stream.has_all_of(_IOUPDATE); bool const is_in_write_mode = stream.has_all_of(_IOWRITE); if (!is_in_read_mode && !(is_in_update_mode && !is_in_write_mode)) return WEOF; // If the stream is currently unbuffered, buffer it: if (stream->_base == nullptr) __acrt_stdio_allocate_buffer_nolock(stream.public_stream()); // If the stream is file-backed and is open in text mode, we need to perform // text mode translations: if (!stream.is_string_backed() && (_osfile_safe(_fileno(stream.public_stream())) & FTEXT) != 0) { return ungetwc_text_mode_nolock(c, stream); } // Otherwise, the stream is string-backed or is a file-backed file open in // binary mode; we can simply push the character back into the stream: return ungetwc_binary_mode_nolock(c, stream); }
int __cdecl _filwbuf ( FILE *str ) { REG1 FILE *stream; _ASSERTE(str != NULL); /* Init pointer to _iob2 entry. */ stream = str; if (!inuse(stream) || stream->_flag & _IOSTRG) return(WEOF); if (stream->_flag & _IOWRT) { stream->_flag |= _IOERR; return(WEOF); } stream->_flag |= _IOREAD; /* Get a buffer, if necessary. */ if (!anybuf(stream)) _getbuf(stream); else stream->_ptr = stream->_base; stream->_cnt = _read(_fileno(stream), stream->_base, stream->_bufsiz); if ((stream->_cnt == 0) || (stream->_cnt == 1) || stream->_cnt == -1) { stream->_flag |= stream->_cnt ? _IOERR : _IOEOF; stream->_cnt = 0; return(WEOF); } if ( !(stream->_flag & (_IOWRT|_IORW)) && ((_osfile_safe(_fileno(stream)) & (FTEXT|FEOFLAG)) == (FTEXT|FEOFLAG)) ) stream->_flag |= _IOCTRLZ; /* Check for small _bufsiz (_SMALL_BUFSIZ). If it is small and if it is our buffer, then this must be the first _filbuf after an fseek on a read-access-only stream. Restore _bufsiz to its larger value (_INTERNAL_BUFSIZ) so that the next _filbuf call, if one is made, will fill the whole buffer. */ if ( (stream->_bufsiz == _SMALL_BUFSIZ) && (stream->_flag & _IOMYBUF) && !(stream->_flag & _IOSETVBUF) ) { stream->_bufsiz = _INTERNAL_BUFSIZ; } stream->_cnt -= sizeof(wchar_t); return (0xffff & *((wchar_t *)(stream->_ptr))++); }
static int __cdecl common_refill_and_read_nolock(__crt_stdio_stream const stream) throw() { typedef __acrt_stdio_char_traits<Character> stdio_traits; _VALIDATE_RETURN(stream.valid(), EINVAL, stdio_traits::eof); if (!stream.is_in_use() || stream.is_string_backed()) return stdio_traits::eof; if (stream.has_all_of(_IOWRITE)) { stream.set_flags(_IOERROR); return stdio_traits::eof; } stream.set_flags(_IOREAD); // Get a buffer, if necessary: if (!stream.has_any_buffer()) __acrt_stdio_allocate_buffer_nolock(stream.public_stream()); auto const context = get_context_nolock(stream, Character()); stream->_ptr = stream->_base; stream->_cnt = _read(_fileno(stream.public_stream()), stream->_base, stream->_bufsiz); if (!is_buffer_valid_nolock(stream, Character())) { stream.set_flags(stream->_cnt != 0 ? _IOERROR : _IOEOF); stream->_cnt = 0; return stdio_traits::eof; } if (!stream.has_any_of(_IOWRITE | _IOUPDATE) && ((_osfile_safe(_fileno(stream.public_stream())) & (FTEXT | FEOFLAG)) == (FTEXT | FEOFLAG))) { stream.set_flags(_IOCTRLZ); } // Check for small _bufsiz (_SMALL_BUFSIZ). If it is small and if it is our // buffer, then this must be the first call to this function after an fseek // on a read-access-only stream. Restore _bufsiz to its larger value // (_INTERNAL_BUFSIZ) so that the next call to this function, if one is made, // will fill the whole buffer. if (stream->_bufsiz == _SMALL_BUFSIZ && stream.has_crt_buffer() && !stream.has_all_of(_IOBUFFER_SETVBUF)) { stream->_bufsiz = _INTERNAL_BUFSIZ; } return read_character_nolock(stream, context, Character()); }
void __cdecl rewind ( FILE *str ) { REG1 FILE *stream; REG2 int fd; _VALIDATE_RETURN_VOID( (str != NULL), EINVAL); /* Init stream pointer */ stream = str; fd = _fileno(stream); /* Lock the file */ _lock_str(stream); __try { /* Flush the stream */ _flush(stream); /* Clear errors */ stream->_flag &= ~(_IOERR|_IOEOF); _osfile_safe(fd) &= ~(FEOFLAG); /* Set flags */ /* [note: _flush set _cnt=0 and _ptr=_base] */ if (stream->_flag & _IORW) stream->_flag &= ~(_IOREAD|_IOWRT); /* Position to beginning of file */ if(_lseek(fd,0L,0)==-1) { stream->_flag |= _IOERR; } } __finally { /* unlock stream */ _unlock_str(stream); } }
wint_t __cdecl fputwc ( wint_t ch, FILE *str ) { #endif /* _MT */ if (!(str->_flag & _IOSTRG) && (_osfile_safe(_fileno(str)) & FTEXT)) { int size; char mbc[4]; /* text (multi-byte) mode */ if ((size = wctomb(mbc, ch)) == -1) { /* * Conversion failed! Set errno and return * failure. */ errno = EILSEQ; return WEOF; } else if ( size == 1 ) { if ( _putc_lk(mbc[0], str) == EOF ) return WEOF; return (wint_t)(0xffff & ch); } else { /* size == 2 */ if ( (_putc_lk(mbc[0], str) == EOF) || (_putc_lk(mbc[1], str) == EOF) ) return WEOF; return (wint_t)(0xffff & ch); } } /* binary (Unicode) mode */ if ( (str->_cnt -= sizeof(wchar_t)) >= 0 ) return (wint_t) (0xffff & (*((wchar_t *)(str->_ptr))++ = (wchar_t)ch)); else return (wint_t) _flswbuf(ch, str); }
void __cdecl clearerr ( FILE *stream ) { _ASSERTE(stream != NULL); _lock_str(stream); /* Clear stdio level flags */ stream->_flag &= ~(_IOERR|_IOEOF); /* Clear lowio level flags */ #ifdef _WIN32 _osfile_safe(_fileno(stream)) &= ~(FEOFLAG); #else /* _WIN32 */ _osfile[_fileno(stream)] &= ~(FEOFLAG); #endif /* _WIN32 */ _unlock_str(stream); }
int __cdecl _filwbuf ( FILE *str ) #endif /* _UNICODE */ { REG1 FILE *stream=NULL; /* In safecrt, we assume we always have a buffer */ _VALIDATE_RETURN(str != NULL, EINVAL, _TEOF); /* Init pointer to _iob2 entry. */ stream = str; if (!inuse(stream) || stream->_flag & _IOSTRG) return(_TEOF); if (stream->_flag & _IOWRT) { stream->_flag |= _IOERR; return(_TEOF); } stream->_flag |= _IOREAD; /* Get a buffer, if necessary. */ if (!anybuf(stream)) { #ifndef _SAFECRT_IMPL _getbuf(stream); #else /* _SAFECRT_IMPL */ /* In safecrt, we assume we always have a buffer */ _VALIDATE_RETURN(FALSE, EINVAL, _TEOF); #endif /* _SAFECRT_IMPL */ } else { stream->_ptr = stream->_base; } stream->_cnt = _read(_fileno(stream), stream->_base, stream->_bufsiz); #ifndef _UNICODE if ((stream->_cnt == 0) || (stream->_cnt == -1)) { #else /* _UNICODE */ if ((stream->_cnt == 0) || (stream->_cnt == 1) || stream->_cnt == -1) { #endif /* _UNICODE */ stream->_flag |= stream->_cnt ? _IOERR : _IOEOF; stream->_cnt = 0; return(_TEOF); } if ( !(stream->_flag & (_IOWRT|_IORW)) && ((_osfile_safe(_fileno(stream)) & (FTEXT|FEOFLAG)) == (FTEXT|FEOFLAG)) ) stream->_flag |= _IOCTRLZ; /* Check for small _bufsiz (_SMALL_BUFSIZ). If it is small and if it is our buffer, then this must be the first _filbuf after an fseek on a read-access-only stream. Restore _bufsiz to its larger value (_INTERNAL_BUFSIZ) so that the next _filbuf call, if one is made, will fill the whole buffer. */ if ( (stream->_bufsiz == _SMALL_BUFSIZ) && (stream->_flag & _IOMYBUF) && !(stream->_flag & _IOSETVBUF) ) { stream->_bufsiz = _INTERNAL_BUFSIZ; } #ifndef _UNICODE stream->_cnt--; return(0xff & *stream->_ptr++); #else /* _UNICODE */ stream->_cnt -= sizeof(wchar_t); return (0xffff & *((wchar_t *)(stream->_ptr))++); #endif /* _UNICODE */ }
int __cdecl _flswbuf ( int ch, FILE *str ) #endif /* _UNICODE */ { REG1 FILE *stream; REG2 int charcount; REG3 int written; int fh; _ASSERTE(str != NULL); /* Init file handle and pointers */ stream = str; fh = _fileno(stream); if (!(stream->_flag & (_IOWRT|_IORW))) { errno = EBADF; stream->_flag |= _IOERR; return(_TEOF); } else if ((stream->_flag & _IOSTRG)) { errno = ERANGE; stream->_flag |= _IOERR; return(_TEOF); } /* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note that _IOREAD and IOEOF both being set implies switching from read to write at end-of-file, which is allowed by ANSI. Note that resetting the _cnt and _ptr fields amounts to doing an fflush() on the stream in this case. Note also that the _cnt field has to be reset to 0 for the error path as well (i.e., _IOREAD set but _IOEOF not set) as well as the non-error path. */ if (stream->_flag & _IOREAD) { stream->_cnt = 0; if (stream->_flag & _IOEOF) { stream->_ptr = stream->_base; stream->_flag &= ~_IOREAD; } else { stream->_flag |= _IOERR; return(_TEOF); } } stream->_flag |= _IOWRT; stream->_flag &= ~_IOEOF; written = charcount = stream->_cnt = 0; /* Get a buffer for this stream, if necessary. */ if (!anybuf(stream)) { /* Do NOT get a buffer if (1) stream is stdout/stderr, and (2) stream is NOT a tty. [If stdout/stderr is a tty, we do NOT set up single char buffering. This is so that later temporary buffering will not be thwarted by the _IONBF bit being set (see _stbuf/_ftbuf usage).] */ if (!( ((stream==stdout) || (stream==stderr)) && (_isatty(fh)) )) _getbuf(stream); } /* end !anybuf() */ /* If big buffer is assigned to stream... */ if (bigbuf(stream)) { _ASSERTE(("inconsistent IOB fields", stream->_ptr - stream->_base >= 0)); charcount = (int)(stream->_ptr - stream->_base); stream->_ptr = stream->_base + sizeof(TCHAR); stream->_cnt = stream->_bufsiz - (int)sizeof(TCHAR); if (charcount > 0) written = _write(fh, stream->_base, charcount); else if (_osfile_safe(fh) & FAPPEND) { if( _lseeki64(fh,0L,SEEK_END)==-1) { stream->_flag |= _IOERR; return(_TEOF); } } #ifndef _UNICODE *stream->_base = (char)ch; #else /* _UNICODE */ *(wchar_t *)(stream->_base) = (wchar_t)(ch & 0xffff); #endif /* _UNICODE */ } /* Perform single character output (either _IONBF or no buffering) */ else { charcount = sizeof(TCHAR); #ifndef _UNICODE written = _write(fh, &ch, charcount); #else /* _UNICODE */ { char mbc[4]; *(wchar_t *)mbc = (wchar_t)(ch & 0xffff); written = _write(fh, mbc, charcount); } #endif /* _UNICODE */ } /* See if the _write() was successful. */ if (written != charcount) { stream->_flag |= _IOERR; return(_TEOF); } #ifndef _UNICODE return(ch & 0xff); #else /* _UNICODE */ return(ch & 0xffff); #endif /* _UNICODE */ }
wint_t __cdecl ungetwc ( wint_t ch, FILE *str ) { #endif /* _MT */ _ASSERTE(str != NULL); /* * Requirements for success: * * 1. Character to be pushed back on the stream must not be WEOF. * * 2. The stream must currently be in read mode, or must be open for * update (i.e., read/write) and must NOT currently be in write * mode. */ if ( (ch != WEOF) && ( (str->_flag & _IOREAD) || ((str->_flag & _IORW) && !(str->_flag & _IOWRT)) ) ) { /* If stream is unbuffered, get one. */ if (str->_base == NULL) _getbuf(str); if (!(str->_flag & _IOSTRG) && (_osfile_safe(_fileno(str)) & FTEXT)) { /* * Text mode, sigh... Convert the wc to a mbc. */ int size; char mbc[4]; if ((size = wctomb(mbc, ch)) == -1) { /* * Conversion failed! Set errno and return * failure. */ errno = EILSEQ; return WEOF; } /* we know _base != NULL; since file is buffered */ if (str->_ptr == str->_base) { if (str->_cnt) /* my back is against the wall; i've already done * ungetwc, and there's no room for this one */ return WEOF; str->_ptr += size; } if ( size == 1 ) { *--str->_ptr = mbc[0]; } else /* size == 2 */ { *--str->_ptr = mbc[1]; *--str->_ptr = mbc[0]; } str->_cnt += size; str->_flag &= ~_IOEOF; str->_flag |= _IOREAD; /* may already be set */ return (wint_t) (0x0ffff & ch); } /* * Binary mode - push back the wide char. */ /* we know _base != NULL; since file is buffered */ if (str->_ptr == str->_base) { if (str->_cnt) /* my back is against the wall; i've already done * ungetc, and there's no room for this one */ return WEOF; str->_ptr += sizeof(wchar_t); } str->_cnt += sizeof(wchar_t); str->_flag &= ~_IOEOF; str->_flag |= _IOREAD; /* may already be set */ return (wint_t) (*--((wchar_t *)(str->_ptr)) = (wchar_t)(ch & 0xffff)); } return WEOF; }
int __cdecl _filwbuf ( FILE *str ) #endif /* _UNICODE */ { #ifdef _NTSUBSET_ return(_TEOF); #else /* ndef _NTSUBSET_ */ REG1 FILE *stream; _ASSERTE(str != NULL); /* Init pointer to _iob2 entry. */ stream = str; if (!inuse(stream) || stream->_flag & _IOSTRG) return(_TEOF); if (stream->_flag & _IOWRT) { #ifdef _POSIX_ errno = EBADF; #endif stream->_flag |= _IOERR; return(_TEOF); } stream->_flag |= _IOREAD; /* Get a buffer, if necessary. */ if (!anybuf(stream)) _getbuf(stream); else stream->_ptr = stream->_base; #ifdef _POSIX_ stream->_cnt = read(fileno(stream), stream->_base, stream->_bufsiz); #else stream->_cnt = _read(_fileno(stream), stream->_base, stream->_bufsiz); #endif #ifndef _UNICODE if ((stream->_cnt == 0) || (stream->_cnt == -1)) { #else /* _UNICODE */ if ((stream->_cnt == 0) || (stream->_cnt == 1) || stream->_cnt == -1) { #endif /* _UNICODE */ stream->_flag |= stream->_cnt ? _IOERR : _IOEOF; stream->_cnt = 0; return(_TEOF); } #ifndef _POSIX_ if ( !(stream->_flag & (_IOWRT|_IORW)) && ((_osfile_safe(_fileno(stream)) & (FTEXT|FEOFLAG)) == (FTEXT|FEOFLAG)) ) stream->_flag |= _IOCTRLZ; #endif /* Check for small _bufsiz (_SMALL_BUFSIZ). If it is small and if it is our buffer, then this must be the first _filbuf after an fseek on a read-access-only stream. Restore _bufsiz to its larger value (_INTERNAL_BUFSIZ) so that the next _filbuf call, if one is made, will fill the whole buffer. */ if ( (stream->_bufsiz == _SMALL_BUFSIZ) && (stream->_flag & _IOMYBUF) && !(stream->_flag & _IOSETVBUF) ) { stream->_bufsiz = _INTERNAL_BUFSIZ; } #ifndef _UNICODE stream->_cnt--; return(0xff & *stream->_ptr++); #else /* _UNICODE */ stream->_cnt -= sizeof(wchar_t); return (0xffff & *((wchar_t *)(stream->_ptr))++); #endif /* _UNICODE */ #endif /* _NTSUBSET_ */ } #else /* ndef _WIN32 */ #if defined(_M_MPPC) || defined(_M_M68K) #include <cruntime.h> #include <stdio.h> #include <file2.h> #include <io.h> #include <dbgint.h> #include <malloc.h> #include <internal.h> #include <msdos.h> /*** *int _filbuf(stream) - fill buffer and get first character * *Purpose: * get a buffer if the file doesn't have one, read into it, return first * char. try to get a buffer, if a user buffer is not assigned. called * only from getc; intended for use only within library. assume no input * stream is to remain unbuffered when memory is available unless it is * marked _IONBF. at worst, give it a single char buffer. the need for a * buffer, no matter how small, becomes evident when we consider the * ungetc's necessary in scanf * *Entry: * FILE *stream - stream to read from * *Exit: * returns first character from buffer (next character to be read) * returns EOF if the FILE is actually a string, or not open for reading, * or if open for writing or if no more chars to read. * all fields in FILE structure may be changed except _file. * *Exceptions: * *******************************************************************************/ int __cdecl _filbuf ( FILE *str ) { REG1 FILE *stream; _ASSERTE(str != NULL); /* Init pointer to _iob2 entry. */ stream = str; if (!inuse(stream) || stream->_flag & _IOSTRG) return(EOF); if (stream->_flag & _IOWRT) { stream->_flag |= _IOERR; return(EOF); } stream->_flag |= _IOREAD; /* Get a buffer, if necessary. */ if (!anybuf(stream)) _getbuf(stream); else stream->_ptr = stream->_base; stream->_cnt = _read(_fileno(stream), stream->_base, stream->_bufsiz); if ((stream->_cnt == 0) || (stream->_cnt == -1)) { stream->_flag |= stream->_cnt ? _IOERR : _IOEOF; stream->_cnt = 0; return(EOF); } if ( !(stream->_flag & (_IOWRT|_IORW)) && ((_osfile[_fileno(stream)] & (FTEXT|FEOFLAG)) == (FTEXT|FEOFLAG)) ) stream->_flag |= _IOCTRLZ; stream->_cnt--; return(0xff & *stream->_ptr++); }
extern "C" wint_t __cdecl _fgetwc_nolock(FILE* const public_stream) { __crt_stdio_stream const stream(public_stream); // If the stream is backed by a real file and is open in a Unicode text mode, // we need to read two bytes (note that we read two bytes for both UTF-8 and // UTF-16 backed streams, since lowio translates UTF-8 to UTF-16 when we read. if (!stream.is_string_backed() && _textmode_safe(_fileno(stream.public_stream())) != __crt_lowio_text_mode::ansi) { wchar_t wc; // Compose the wide character by reading byte-by-byte from the stream: char* const wc_first = reinterpret_cast<char*>(&wc); char* const wc_last = wc_first + sizeof(wc); for (char* it = wc_first; it != wc_last; ++it) { int const c = _getc_nolock(stream.public_stream()); if (c == EOF) return WEOF; *it = static_cast<char>(c); } return wc; } if (!stream.is_string_backed() && (_osfile_safe(_fileno(stream.public_stream())) & FTEXT)) { int size = 1; int ch; char mbc[4]; wchar_t wch; /* text (multi-byte) mode */ if ((ch = _getc_nolock(stream.public_stream())) == EOF) return WEOF; mbc[0] = static_cast<char>(ch); if (isleadbyte(static_cast<unsigned char>(mbc[0]))) { if ((ch = _getc_nolock(stream.public_stream())) == EOF) { ungetc(mbc[0], stream.public_stream()); return WEOF; } mbc[1] = static_cast<char>(ch); size = 2; } if (mbtowc(&wch, mbc, size) == -1) { // Conversion failed! Set errno and return failure: errno = EILSEQ; return WEOF; } return wch; } // binary (Unicode) mode if (stream->_cnt >= static_cast<int>(sizeof(wchar_t))) { stream->_cnt -= static_cast<int>(sizeof(wchar_t)); return *reinterpret_cast<wchar_t*&>(stream->_ptr)++; } else { return static_cast<wint_t>(__acrt_stdio_refill_and_read_wide_nolock(stream.public_stream())); } }