int _IO_new_file_underflow (_IO_FILE *fp) { _IO_ssize_t count; #if 0 /* SysV does not make this test; take it out for compatibility */ if (fp->_flags & _IO_EOF_SEEN) return (EOF); #endif if (fp->_flags & _IO_NO_READS) { fp->_flags |= _IO_ERR_SEEN; __set_errno (EBADF); return EOF; } if (fp->_IO_read_ptr < fp->_IO_read_end) return *(unsigned char *) fp->_IO_read_ptr; if (fp->_IO_buf_base == NULL) { /* Maybe we already have a push back pointer. */ if (fp->_IO_save_base != NULL) { free (fp->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_doallocbuf (fp); } /* Flush all line buffered files before reading. */ /* FIXME This can/should be moved to genops ?? */ if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) { #if 0 _IO_flush_all_linebuffered (); #else /* We used to flush all line-buffered stream. This really isn't required by any standard. My recollection is that traditional Unix systems did this for stdout. stderr better not be line buffered. So we do just that here explicitly. --drepper */ _IO_acquire_lock (_IO_stdout); if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF)) == (_IO_LINKED | _IO_LINE_BUF)) _IO_OVERFLOW (_IO_stdout, EOF); _IO_release_lock (_IO_stdout); #endif } _IO_switch_to_get_mode (fp); /* This is very tricky. We have to adjust those pointers before we call _IO_SYSREAD () since we may longjump () out while waiting for input. Those pointers may be screwed up. H.J. */ fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; fp->_IO_read_end = fp->_IO_buf_base; fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_buf_base; count = _IO_SYSREAD (fp, fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base); if (count <= 0) { if (count == 0) fp->_flags |= _IO_EOF_SEEN; else fp->_flags |= _IO_ERR_SEEN, count = 0; } fp->_IO_read_end += count; if (count == 0) { /* If a stream is read to EOF, the calling application may switch active handles. As a result, our offset cache would no longer be valid, so unset it. */ fp->_offset = _IO_pos_BAD; return EOF; } if (fp->_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_offset, count); return *(unsigned char *) fp->_IO_read_ptr; }
int attribute_compat_text_section _IO_old_file_underflow (_IO_FILE *fp) { _IO_ssize_t count; #if 0 /* SysV does not make this test; take it out for compatibility */ if (fp->_flags & _IO_EOF_SEEN) return (EOF); #endif if (fp->_flags & _IO_NO_READS) { fp->_flags |= _IO_ERR_SEEN; __set_errno (EBADF); return EOF; } if (fp->_IO_read_ptr < fp->_IO_read_end) return *(unsigned char *) fp->_IO_read_ptr; if (fp->_IO_buf_base == NULL) { /* Maybe we already have a push back pointer. */ if (fp->_IO_save_base != NULL) { free (fp->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_doallocbuf (fp); } /* Flush all line buffered files before reading. */ /* FIXME This can/should be moved to genops ?? */ if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) _IO_flush_all_linebuffered (); _IO_switch_to_get_mode (fp); /* This is very tricky. We have to adjust those pointers before we call _IO_SYSREAD () since we may longjump () out while waiting for input. Those pointers may be screwed up. H.J. */ fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; fp->_IO_read_end = fp->_IO_buf_base; fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_buf_base; count = _IO_SYSREAD (fp, fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base); if (count <= 0) { if (count == 0) fp->_flags |= _IO_EOF_SEEN; else fp->_flags |= _IO_ERR_SEEN, count = 0; } fp->_IO_read_end += count; if (count == 0) return EOF; if (fp->_old_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_old_offset, count); return *(unsigned char *) fp->_IO_read_ptr; }
wint_t _IO_wfile_underflow (_IO_FILE *fp) { struct _IO_codecvt *cd; enum __codecvt_result status; _IO_ssize_t count; if (__glibc_unlikely (fp->_flags & _IO_NO_READS)) { fp->_flags |= _IO_ERR_SEEN; __set_errno (EBADF); return WEOF; } if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) return *fp->_wide_data->_IO_read_ptr; cd = fp->_codecvt; /* Maybe there is something left in the external buffer. */ if (fp->_IO_read_ptr < fp->_IO_read_end) { /* There is more in the external. Convert it. */ const char *read_stop = (const char *) fp->_IO_read_ptr; fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_buf_base; status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, fp->_IO_read_ptr, fp->_IO_read_end, &read_stop, fp->_wide_data->_IO_read_ptr, fp->_wide_data->_IO_buf_end, &fp->_wide_data->_IO_read_end); fp->_IO_read_base = fp->_IO_read_ptr; fp->_IO_read_ptr = (char *) read_stop; /* If we managed to generate some text return the next character. */ if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) return *fp->_wide_data->_IO_read_ptr; if (status == __codecvt_error) { __set_errno (EILSEQ); fp->_flags |= _IO_ERR_SEEN; return WEOF; } /* Move the remaining content of the read buffer to the beginning. */ memmove (fp->_IO_buf_base, fp->_IO_read_ptr, fp->_IO_read_end - fp->_IO_read_ptr); fp->_IO_read_end = (fp->_IO_buf_base + (fp->_IO_read_end - fp->_IO_read_ptr)); fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; } else fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_buf_base; if (fp->_IO_buf_base == NULL) { /* Maybe we already have a push back pointer. */ if (fp->_IO_save_base != NULL) { free (fp->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_doallocbuf (fp); fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_buf_base; } fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_buf_base; if (fp->_wide_data->_IO_buf_base == NULL) { /* Maybe we already have a push back pointer. */ if (fp->_wide_data->_IO_save_base != NULL) { free (fp->_wide_data->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_wdoallocbuf (fp); } /* Flush all line buffered files before reading. */ /* FIXME This can/should be moved to genops ?? */ if (fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED)) { #if 0 _IO_flush_all_linebuffered (); #else /* We used to flush all line-buffered stream. This really isn't required by any standard. My recollection is that traditional Unix systems did this for stdout. stderr better not be line buffered. So we do just that here explicitly. --drepper */ _IO_acquire_lock (_IO_stdout); if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF)) == (_IO_LINKED | _IO_LINE_BUF)) _IO_OVERFLOW (_IO_stdout, EOF); _IO_release_lock (_IO_stdout); #endif } _IO_switch_to_get_mode (fp); fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_buf_base; fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_buf_base; fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base; const char *read_ptr_copy; char accbuf[MB_LEN_MAX]; size_t naccbuf = 0; again: count = _IO_SYSREAD (fp, fp->_IO_read_end, fp->_IO_buf_end - fp->_IO_read_end); if (count <= 0) { if (count == 0 && naccbuf == 0) { fp->_flags |= _IO_EOF_SEEN; fp->_offset = _IO_pos_BAD; } else fp->_flags |= _IO_ERR_SEEN, count = 0; } fp->_IO_read_end += count; if (count == 0) { if (naccbuf != 0) /* There are some bytes in the external buffer but they don't convert to anything. */ __set_errno (EILSEQ); return WEOF; } if (fp->_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_offset, count); /* Now convert the read input. */ fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_IO_read_base = fp->_IO_read_ptr; const char *from = fp->_IO_read_ptr; const char *to = fp->_IO_read_end; size_t to_copy = count; if (__glibc_unlikely (naccbuf != 0)) { to_copy = MIN (sizeof (accbuf) - naccbuf, count); to = __mempcpy (&accbuf[naccbuf], from, to_copy); naccbuf += to_copy; from = accbuf; } status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, from, to, &read_ptr_copy, fp->_wide_data->_IO_read_end, fp->_wide_data->_IO_buf_end, &fp->_wide_data->_IO_read_end); if (__glibc_unlikely (naccbuf != 0)) fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]); else fp->_IO_read_ptr = (char *) read_ptr_copy; if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base) { if (status == __codecvt_error) { out_eilseq: __set_errno (EILSEQ); fp->_flags |= _IO_ERR_SEEN; return WEOF; } /* The read bytes make no complete character. Try reading again. */ assert (status == __codecvt_partial); if (naccbuf == 0) { if (fp->_IO_read_base < fp->_IO_read_ptr) { /* Partially used the buffer for some input data that produces no output. */ size_t avail = fp->_IO_read_end - fp->_IO_read_ptr; memmove (fp->_IO_read_base, fp->_IO_read_ptr, avail); fp->_IO_read_ptr = fp->_IO_read_base; fp->_IO_read_end -= avail; goto again; } naccbuf = fp->_IO_read_end - fp->_IO_read_ptr; if (naccbuf >= sizeof (accbuf)) goto out_eilseq; memcpy (accbuf, fp->_IO_read_ptr, naccbuf); } else { size_t used = read_ptr_copy - accbuf; if (used > 0) { memmove (accbuf, read_ptr_copy, naccbuf - used); naccbuf -= used; } if (naccbuf == sizeof (accbuf)) goto out_eilseq; } fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_read_base; goto again; } return *fp->_wide_data->_IO_read_ptr; }