From 865b7962a14f009f42b9408fb88a103233c4cb77 Mon Sep 17 00:00:00 2001 From: Wren Turkal <wt@penguintechs.org> Date: Wed, 8 Jul 2020 00:07:03 -0700 Subject: [PATCH] Add implmentation for fwide posix function. This function is used to set the orientation of a stream to either byte-oriented or wchar-oriented. More info on this function is here: https://man7.org/linux/man-pages/man3/fwide.3p.html This implementation only impmlemnts the manual switching and does not yet guard against using a byte-oriented stream with wchar functions and vice versa. Those step will come in additional commits. Signed-off-by: Wren Turkal <wt@penguintechs.org> --- src/header/stdio/default.rs | 2 ++ src/header/stdio/helpers.rs | 2 ++ src/header/stdio/mod.rs | 17 ++++++++++- src/header/wchar/mod.rs | 6 ++-- src/platform/types.rs | 2 ++ tests/Makefile | 1 + tests/expected/wchar/fwide.stderr | 0 tests/expected/wchar/fwide.stdout | 3 ++ tests/wchar/fwide.c | 47 +++++++++++++++++++++++++++++++ 9 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 tests/expected/wchar/fwide.stderr create mode 100644 tests/expected/wchar/fwide.stdout create mode 100644 tests/wchar/fwide.c diff --git a/src/header/stdio/default.rs b/src/header/stdio/default.rs index b86115e2..90aa709b 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 6d5d9da8..be7aa9fa 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 7693cd21..b6c9c916 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 4c4a281b..cde6a5e8 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 85e3ba3a..5d604d38 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 fde26810..a1f07bb9 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 00000000..e69de29b diff --git a/tests/expected/wchar/fwide.stdout b/tests/expected/wchar/fwide.stdout new file mode 100644 index 00000000..bb0b1cf6 --- /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 00000000..4338d02c --- /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])()); + } +} + -- GitLab