Add support for multiple unget at the same time

According to the standards, only one ungetc may be guaranteed however
glibc allows more than one of those, and to be glibc compatiable, one
needs to be able to do the same, allowing only 1 ungetc may trigger bug
while compiling gcc as ungetc is used there alot
This commit is contained in:
oddcoder
2020-05-22 23:05:49 +02:00
parent 4c94dfac00
commit 7a6f96373e
3 changed files with 19 additions and 19 deletions
+2 -1
View File
@@ -2,6 +2,7 @@ use super::{constants, Buffer, BUFSIZ, FILE};
use core::{cell::UnsafeCell, ptr};
use crate::{fs::File, io::LineWriter, platform::types::*, sync::Mutex};
use alloc::vec::Vec;
pub struct GlobalFile(UnsafeCell<FILE>);
impl GlobalFile {
@@ -16,7 +17,7 @@ impl GlobalFile {
read_buf: Buffer::Owned(vec![0; BUFSIZ as usize]),
read_pos: 0,
read_size: 0,
unget: None,
unget: Vec::new(),
writer,
pid: None,
+3 -3
View File
@@ -1,5 +1,6 @@
use alloc::boxed::Box;
use super::{constants::*, Buffer, FILE};
use crate::{
fs::File,
header::{errno, fcntl::*, string::strchr},
@@ -7,8 +8,7 @@ use crate::{
platform::{self, types::*},
sync::Mutex,
};
use super::{constants::*, Buffer, FILE};
use alloc::vec::Vec;
/// Parse mode flags as a string and output a mode flags integer
pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 {
@@ -72,7 +72,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
read_buf: Buffer::Owned(vec![0; BUFSIZ as usize]),
read_pos: 0,
read_size: 0,
unget: None,
unget: Vec::new(),
writer,
pid: None,
+14 -15
View File
@@ -6,6 +6,7 @@ use alloc::{
vec::Vec,
};
use core::{
cmp,
ffi::VaList as va_list,
fmt::{self, Write as WriteFmt},
mem,
@@ -76,7 +77,7 @@ pub struct FILE {
read_buf: Buffer<'static>,
read_pos: usize,
read_size: usize,
unget: Option<u8>,
unget: Vec<u8>,
// pub for stdio_ext
pub(crate) writer: LineWriter<File>,
@@ -86,11 +87,12 @@ pub struct FILE {
impl Read for FILE {
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
if !out.is_empty() {
if let Some(c) = self.unget.take() {
out[0] = c;
return Ok(1);
}
let unget_read_size = cmp::min(out.len(), self.unget.len());
for i in 0..unget_read_size {
out[i] = self.unget.pop().unwrap();
}
if unget_read_size != 0 {
return Ok(unget_read_size);
}
let len = {
@@ -311,11 +313,12 @@ pub unsafe extern "C" fn fgets(
let mut wrote = false;
if left >= 1 {
if let Some(c) = stream.unget.take() {
*out = c as c_char;
let unget_read_size = cmp::min(left, stream.unget.len());
for _ in 0..unget_read_size {
*out = stream.unget.pop().unwrap() as i8;
out = out.offset(1);
left -= 1;
}
left -= unget_read_size;
}
loop {
@@ -533,7 +536,7 @@ pub unsafe extern "C" fn fseeko(stream: *mut FILE, mut off: off_t, whence: c_int
stream.flags &= !(F_EOF | F_ERR);
stream.read_pos = 0;
stream.read_size = 0;
stream.unget = None;
stream.unget = Vec::new();
0
}
@@ -990,11 +993,7 @@ unsafe extern "C" fn tmpnam_inner(buf: *mut c_char, offset: usize) -> *mut c_cha
#[no_mangle]
pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
let mut stream = (*stream).lock();
if stream.unget.is_some() {
platform::errno = errno::EIO;
return EOF;
}
stream.unget = Some(c as u8);
stream.unget.push(c as u8);
c
}