diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index 52655c061d4ae673d0cbea8c3a1b26a826854140..514666110e0fecb05f77933cbc827acebdb4c7d9 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -4,9 +4,10 @@ use core::{char, ffi::VaList as va_list, mem, ptr, slice, usize}; use crate::{ header::{ - ctype::isspace, errno::ERANGE, stdio::*, stdlib::MB_CUR_MAX, string, time::*, wctype::*, + ctype::isspace, errno::{ERANGE, EILSEQ}, stdio::*, + stdlib::MB_CUR_MAX, string, time::*, wctype::*, }, - platform::{self, types::*}, + platform::{self, errno, types::*}, }; mod utf8; @@ -38,8 +39,45 @@ pub unsafe extern "C" fn btowc(c: c_int) -> wint_t { #[no_mangle] pub unsafe extern "C" fn fgetwc(stream: *mut FILE) -> wint_t { - //TODO: Real multibyte - btowc(fgetc(stream)) + // TODO: Process locale + let mut buf: [c_uchar; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize]; + let mut encoded_length = 0; + let mut bytes_read = 0; + let mut wc: wchar_t = 0; + + loop { + let nread = fread(buf[bytes_read..bytes_read+1].as_mut_ptr() as *mut c_void, 1, 1, stream); + + if nread != 1 { + errno = EILSEQ; + return WEOF; + } + + bytes_read += 1; + + if bytes_read == 1 { + encoded_length = if buf[0] >> 7 == 0 { + 1 + } else if buf[0] >> 5 == 6 { + 2 + } else if buf[0] >> 4 == 0xe { + 3 + } else if buf[0] >> 3 == 0x1e { + 4 + } else { + errno = EILSEQ; + return WEOF; + }; + } + + if bytes_read >= encoded_length { + break; + } + } + + mbrtowc(&mut wc, buf.as_ptr() as *const c_char, encoded_length, ptr::null_mut()); + + wc as wint_t } #[no_mangle] diff --git a/tests/expected/bins_static/wchar/fgetwc.stderr b/tests/expected/bins_static/wchar/fgetwc.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/bins_static/wchar/fgetwc.stdout b/tests/expected/bins_static/wchar/fgetwc.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e7cabf537eb68c3c10a494f39fc28b1009114358 --- /dev/null +++ b/tests/expected/bins_static/wchar/fgetwc.stdout @@ -0,0 +1,3 @@ +êçã +こんにちは世界 +Привет мир \ No newline at end of file diff --git a/tests/wchar/fgetwc.c b/tests/wchar/fgetwc.c new file mode 100644 index 0000000000000000000000000000000000000000..1aeeff16ffc1f3f0231bf8be9be6a2c3a9bcdcbd --- /dev/null +++ b/tests/wchar/fgetwc.c @@ -0,0 +1,19 @@ +#include <stdio.h> +#include <wchar.h> +#include <locale.h> + +int main(void) +{ + setlocale(LC_ALL, ""); + wint_t wc; + FILE *fp = fopen("wchar/fgetwc.in", "r"); + if (!fp) { + return 1; + } + + while (WEOF != (wc = fgetwc(fp))) + printf("%lc", wc); + + fclose(fp); + return 0; +} diff --git a/tests/wchar/fgetwc.in b/tests/wchar/fgetwc.in new file mode 100644 index 0000000000000000000000000000000000000000..e7cabf537eb68c3c10a494f39fc28b1009114358 --- /dev/null +++ b/tests/wchar/fgetwc.in @@ -0,0 +1,3 @@ +êçã +こんにちは世界 +Привет мир \ No newline at end of file