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:
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user