diff --git a/src/header/stdio/default.rs b/src/header/stdio/default.rs index b86115e2d6f33caf73831d1704aee07ad360c87e..90aa709b025c848085fdbe4110debd96f74bcfb4 100644 --- a/src/header/stdio/default.rs +++ b/src/header/stdio/default.rs @@ -21,6 +21,8 @@ impl GlobalFile { writer, pid: None, + + orientation: 0, })) } pub fn get(&self) -> *mut FILE { diff --git a/src/header/stdio/helpers.rs b/src/header/stdio/helpers.rs index 6d5d9da8414e1dcb7bb84153a978ca08a296c3a6..be7aa9fa0bb83cd3c203c8aca6d296e4d34ec384 100644 --- a/src/header/stdio/helpers.rs +++ b/src/header/stdio/helpers.rs @@ -76,5 +76,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> { writer, pid: None, + + orientation: 0, }))) } diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 7693cd2157255e5cce08876fbaa9f5b9f4ea907d..b6c9c916a71a62e962a02e51e719d3e5220de525 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -9,7 +9,7 @@ use core::{ cmp, ffi::VaList as va_list, fmt::{self, Write as WriteFmt}, - mem, + i32, mem, ops::{Deref, DerefMut}, ptr, slice, str, }; @@ -85,6 +85,9 @@ pub struct FILE { // Optional pid for use with popen/pclose pid: Option<c_int>, + + // wchar support + pub(crate) orientation: c_int, } impl Read for FILE { @@ -169,6 +172,18 @@ impl FILE { } LockGuard(self) } + + pub fn try_set_orientation(&mut self, mode: c_int) -> c_int { + let mut stream = self.lock(); + if stream.0.orientation == 0 { + stream.0.orientation = match mode { + 1..=i32::MAX => 1, + i32::MIN..=-1 => -1, + 0 => stream.0.orientation, + }; + } + stream.0.orientation + } } pub struct LockGuard<'a>(&'a mut FILE); diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index 4c4a281bbd97a1e4f3736176b87d48be8fdc2de5..cde6a5e85bbaccabe79fd808e5b5e7828bbc8f3a 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -89,9 +89,9 @@ pub unsafe extern "C" fn fputws(ws: *const wchar_t, stream: *mut FILE) -> c_int } } -// #[no_mangle] -pub extern "C" fn fwide(stream: *mut FILE, mode: c_int) -> c_int { - unimplemented!(); +#[no_mangle] +pub unsafe extern "C" fn fwide(stream: *mut FILE, mode: c_int) -> c_int { + (*stream).try_set_orientation(mode) } #[no_mangle] diff --git a/src/platform/types.rs b/src/platform/types.rs index 85e3ba3aafbb9ca64627ba4ebc70baccb106552d..5d604d383a0f3e8a995aaad7c7a8f05caab30c7b 100644 --- a/src/platform/types.rs +++ b/src/platform/types.rs @@ -1,3 +1,5 @@ +use core::i32; + // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable // more optimization opportunities around it recognizing things like // malloc/free. diff --git a/tests/Makefile b/tests/Makefile index fde26810307dc8de69790d4f76e1e7e619577db7..a1f07bb9a2e11141e64e18a217e716132b0cd32f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -100,6 +100,7 @@ EXPECT_NAMES=\ unistd/swab \ unistd/write \ waitpid \ + wchar/fwide \ wchar/mbrtowc \ wchar/mbsrtowcs \ wchar/printf-on-wchars \ diff --git a/tests/expected/wchar/fwide.stderr b/tests/expected/wchar/fwide.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/wchar/fwide.stdout b/tests/expected/wchar/fwide.stdout new file mode 100644 index 0000000000000000000000000000000000000000..bb0b1cf658d18a1b6001d4344351d3abd3829104 --- /dev/null +++ b/tests/expected/wchar/fwide.stdout @@ -0,0 +1,3 @@ +0 +0 +0 diff --git a/tests/wchar/fwide.c b/tests/wchar/fwide.c new file mode 100644 index 0000000000000000000000000000000000000000..4338d02c36eaedd4eb0754c4f66fd7c1683f30da --- /dev/null +++ b/tests/wchar/fwide.c @@ -0,0 +1,47 @@ +#include <assert.h> +#include <stdio.h> +#include <wchar.h> + +int test_initial_orientation(void) { + FILE *f = tmpfile(); + assert(fwide(f, 0) == 0); + return 0; +} + +int test_manual_byte_orientation(void) { + FILE *f = tmpfile(); + + // set manually to byte orientation + assert(fwide(f, -483) == -1); + + // Cannot change to wchar orientation + assert(fwide(f, 1) == -1); + + fclose(f); + return 0; +} + +int test_manual_wchar_orientation(void) { + FILE *f = tmpfile(); + + // set manually to wchar orientation + assert(fwide(f, 483) == 1); + + // Cannot change to byte orientation + assert(fwide(f, -1) == 1); + + fclose(f); + return 0; +} + +int main() { + int(*tests[])(void) = { + &test_initial_orientation, + &test_manual_byte_orientation, + &test_manual_wchar_orientation, + }; + for(int i=0; i<sizeof(tests)/sizeof(int(*)(void)); i++) { + printf("%d\n", (*tests[i])()); + } +} +