wchar support

This commit is contained in:
Stephan Vedder
2018-07-01 20:59:37 +02:00
committed by jD91mZM2
parent fb09b03acf
commit cc210361d6
34 changed files with 840 additions and 669 deletions
+1
View File
@@ -29,6 +29,7 @@ pub extern crate sys_utsname;
pub extern crate sys_wait;
pub extern crate time;
pub extern crate unistd;
pub extern crate wchar;
pub extern crate wctype;
#[cfg(not(any(test, target_os = "redox")))]
+2 -2
View File
@@ -44,8 +44,8 @@ pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;
pub type wchar_t = i16;
pub type wint_t = i32;
pub type wchar_t = i32;
pub type wint_t = u32;
pub type wctype_t = i64;
pub type off_t = i64;
+1 -1
View File
@@ -12,5 +12,5 @@ platform = { path = "../platform" }
va_list = { path = "../../va_list", features = ["no_std"] }
fcntl = { path = "../fcntl" }
string = { path = "../string" }
stdlib = { path = "../stdlib" }
ralloc = { path = "../../ralloc", default-features = false }
errno = { path = "../errno"}
+2 -2
View File
@@ -1,5 +1,5 @@
use super::{internal, BUFSIZ, FILE, UNGET};
use stdlib::calloc;
use ralloc;
use core::{mem, ptr};
use core::sync::atomic::AtomicBool;
use platform::types::*;
@@ -62,7 +62,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
flags |= F_APP;
}
let file = calloc(mem::size_of::<FILE>() + BUFSIZ + UNGET, 1) as *mut FILE;
let file = ralloc::alloc(mem::size_of::<FILE>() + BUFSIZ + UNGET, 1) as *mut FILE;
// Allocate the file
(*file) = FILE {
flags: flags,
+16 -10
View File
@@ -8,12 +8,11 @@ extern crate alloc;
extern crate errno;
extern crate fcntl;
extern crate platform;
extern crate stdlib;
extern crate ralloc;
extern crate string;
extern crate va_list as vl;
use core::str;
use core::ptr;
use core::{str,ptr,mem};
use core::fmt::{self, Error, Result};
use core::fmt::Write as WriteFmt;
use core::sync::atomic::{AtomicBool, Ordering};
@@ -23,8 +22,8 @@ use platform::{c_str, errno, Read, Write};
use errno::STR_ERROR;
use vl::VaList as va_list;
mod scanf;
mod printf;
mod scanf;
mod default;
pub use default::*;
@@ -219,13 +218,16 @@ pub extern "C" fn cuserid(s: *mut c_char) -> *mut c_char {
/// prior to using this function.
#[no_mangle]
pub extern "C" fn fclose(stream: &mut FILE) -> c_int {
use stdlib::free;
use ralloc::free;
flockfile(stream);
let r = helpers::fflush_unlocked(stream) | platform::close(stream.fd);
if stream.flags & constants::F_PERM == 0 {
// Not one of stdin, stdout or stderr
unsafe {
free(stream as *mut _ as *mut _);
free(
stream as *mut _ as *mut _,
mem::size_of::<FILE>() + BUFSIZ + UNGET,
);
}
}
r
@@ -720,7 +722,7 @@ pub extern "C" fn putc_unlocked(c: c_int, stream: &mut FILE) -> c_int {
c
}
} else {
if stream.wend.is_null() && stream.can_write() {
if stream.wend.is_null() && !stream.can_write() {
-1
} else if c as i8 != stream.buf_char && stream.wpos < stream.wend {
unsafe {
@@ -808,10 +810,10 @@ pub unsafe extern "C" fn setvbuf(
size: usize,
) -> c_int {
// TODO: Check correctness
use stdlib::calloc;
use ralloc::alloc;
let mut buf = buf;
if buf.is_null() && mode != _IONBF {
buf = calloc(size, 1) as *mut c_char;
buf = alloc(size, 1) as *mut c_char;
}
(*stream).buf_size = size;
(*stream).buf_char = -1;
@@ -907,5 +909,9 @@ pub unsafe extern "C" fn vscanf(format: *const c_char, ap: va_list) -> c_int {
#[no_mangle]
pub unsafe extern "C" fn vsscanf(s: *const c_char, format: *const c_char, ap: va_list) -> c_int {
scanf::scanf(&mut platform::UnsafeStringReader(s as *const u8), format, ap)
scanf::scanf(
&mut platform::UnsafeStringReader(s as *const u8),
format,
ap,
)
}
+2
View File
@@ -14,3 +14,5 @@ ctype = { path = "../ctype" }
errno = { path = "../errno" }
rand = { version = "0.5.2", default-features = false }
time = { path = "../time" }
wchar = { path = "../wchar" }
string = { path = "../string" }
+62 -42
View File
@@ -9,12 +9,16 @@ extern crate platform;
extern crate ralloc;
extern crate rand;
extern crate time;
extern crate wchar;
extern crate string;
use core::{ptr, str};
use rand::{Rng, SeedableRng};
use rand::{Rng, SeedableRng};
use rand::rngs::JitterRng;
use rand::prng::XorShiftRng;
use rand::distributions::Alphanumeric;
use wchar::*;
use string::*;
use errno::*;
use platform::types::*;
@@ -28,6 +32,11 @@ pub const EXIT_FAILURE: c_int = 1;
pub const EXIT_SUCCESS: c_int = 0;
pub const RAND_MAX: c_int = 2147483647;
//Maximum number of bytes in a multibyte character for the current locale
pub const MB_CUR_MAX: c_int = 4;
//Maximum number of bytes in a multibyte characters for any locale
pub const MB_LEN_MAX: c_int = 4;
static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32];
static mut RNG: Option<XorShiftRng> = None;
@@ -101,7 +110,7 @@ pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
}
macro_rules! dec_num_from_ascii {
($s: expr, $t: ty) => {
($s:expr, $t:ty) => {
unsafe {
let mut s = $s;
// Iterate past whitespace
@@ -351,8 +360,19 @@ pub unsafe extern "C" fn memalign(alignment: size_t, size: size_t) -> *mut c_voi
}
#[no_mangle]
pub extern "C" fn mblen(s: *const c_char, n: size_t) -> c_int {
unimplemented!();
pub unsafe extern "C" fn mblen(s: *const c_char, n: size_t) -> c_int {
let mut wc : wchar_t = 0;
let mut state : mbstate_t = mbstate_t { };
let result : usize = mbrtowc(&mut wc, s, n, &mut state);
if result == -1isize as usize {
return -1;
}
if result == -2isize as usize {
return -1;
}
result as i32
}
#[no_mangle]
@@ -370,16 +390,13 @@ pub extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
use core::slice;
use core::iter;
use core::mem;
extern "C" {
fn strlen(s: *const c_char) -> size_t;
}
let len = unsafe { strlen(name) };
if len < 6 {
unsafe { platform::errno = errno::EINVAL };
unsafe { *name = 0 };
return name;
}
for i in len-6..len {
for i in len - 6..len {
if unsafe { *name.offset(i as isize) } != b'X' as c_char {
unsafe { platform::errno = errno::EINVAL };
unsafe { *name = 0 };
@@ -392,11 +409,9 @@ pub extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
let mut retries = 100;
loop {
let mut char_iter = iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
.take(6);
let mut char_iter = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(6);
unsafe {
for (i,c) in char_iter.enumerate() {
for (i, c) in char_iter.enumerate() {
*name.offset(len as isize - i as isize - 1) = c as c_char
}
}
@@ -404,13 +419,17 @@ pub extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
unsafe {
let mut st: stat = mem::uninitialized();
if platform::stat(name, &mut st) != 0 {
if platform::errno != ENOENT { *name = 0; }
if platform::errno != ENOENT {
*name = 0;
}
return name;
}
mem::forget(st);
}
retries = retries -1;
if retries == 0 { break; }
retries = retries - 1;
if retries == 0 {
break;
}
}
unsafe { platform::errno = EEXIST };
unsafe { *name = 0 };
@@ -421,11 +440,10 @@ fn get_nstime() -> u64 {
use core::mem;
use time::constants::CLOCK_MONOTONIC;
let mut ts: timespec = unsafe { mem::uninitialized() };
platform::clock_gettime(CLOCK_MONOTONIC, &mut ts);
platform::clock_gettime(CLOCK_MONOTONIC, &mut ts);
unsafe { ts.tv_nsec as u64 }
}
#[no_mangle]
pub extern "C" fn mkstemp(name: *mut c_char) -> c_int {
unimplemented!();
@@ -639,7 +657,8 @@ pub fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize,
if val == -1 || val as c_int >= base {
break;
} else {
if let Some(res) = num.checked_mul(base as c_ulong)
if let Some(res) = num
.checked_mul(base as c_ulong)
.and_then(|num| num.checked_add(val as c_ulong))
{
num = res;
@@ -665,13 +684,7 @@ pub fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize,
#[macro_export]
macro_rules! strto_impl {
(
$rettype:ty,
$signed:expr,
$maxval:expr,
$minval:expr,
$s:ident,
$endptr:ident,
$base:ident
$rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident
) => {{
// ensure these are constants
const CHECK_SIGN: bool = $signed;
@@ -721,9 +734,8 @@ macro_rules! strto_impl {
// convert the string to a number
let num_str = $s.offset(idx);
let res = match $base {
0 => detect_base(num_str).and_then(|($base, i)| {
convert_integer(num_str.offset(i), $base)
}),
0 => detect_base(num_str)
.and_then(|($base, i)| convert_integer(num_str.offset(i), $base)),
8 => convert_octal(num_str),
16 => convert_hex(num_str),
_ => convert_integer(num_str, $base),
@@ -770,15 +782,15 @@ macro_rules! strto_impl {
set_endptr(idx);
num
}}
}};
}
#[no_mangle]
pub unsafe extern "C" fn strtoul(s: *const c_char,
endptr: *mut *mut c_char,
base: c_int)
-> c_ulong {
pub unsafe extern "C" fn strtoul(
s: *const c_char,
endptr: *mut *mut c_char,
base: c_int,
) -> c_ulong {
strto_impl!(
c_ulong,
false,
@@ -791,10 +803,7 @@ pub unsafe extern "C" fn strtoul(s: *const c_char,
}
#[no_mangle]
pub unsafe extern "C" fn strtol(s: *const c_char,
endptr: *mut *mut c_char,
base: c_int)
-> c_long {
pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
strto_impl!(
c_long,
true,
@@ -835,11 +844,22 @@ pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
}
#[no_mangle]
pub extern "C" fn wcstombs(s: *mut c_char, pwcs: *const wchar_t, n: size_t) -> size_t {
unimplemented!();
pub extern "C" fn wcstombs(s: *mut c_char, pwcs: *mut *const wchar_t, n: size_t) -> size_t {
let mut state: mbstate_t = mbstate_t {};
wcsrtombs(s, pwcs, n, &mut state)
}
#[no_mangle]
pub extern "C" fn wctomb(s: *mut c_char, wchar: wchar_t) -> c_int {
unimplemented!();
pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: wchar_t) -> c_int {
let mut state : mbstate_t = mbstate_t {};
let result: usize = wcrtomb(s, wc, &mut state);
if result == -1isize as usize {
return -1;
}
if result == -2isize as usize {
return -1;
}
result as c_int
}
+1 -1
View File
@@ -9,5 +9,5 @@ cbindgen = { path = "../../cbindgen" }
[dependencies]
platform = { path = "../platform" }
stdlib = { path = "../stdlib" }
ralloc = { path = "../../ralloc", default-features = false }
errno = { path = "../errno" }
+2 -3
View File
@@ -1,10 +1,9 @@
//! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
#![no_std]
extern crate errno;
extern crate platform;
extern crate stdlib;
extern crate ralloc;
use platform::types::*;
use errno::*;
@@ -193,7 +192,7 @@ pub unsafe extern "C" fn strndup(s1: *const c_char, size: usize) -> *mut c_char
let len = strnlen(s1, size);
// the "+ 1" is to account for the NUL byte
let buffer = stdlib::malloc(len + 1) as *mut c_char;
let buffer = ralloc::alloc(len + 1, 1) as *mut c_char;
if buffer.is_null() {
platform::errno = ENOMEM as c_int;
} else {
-377
View File
@@ -1,377 +0,0 @@
pub type wchar_t = libc::c_int;
pub type wint_t = libc::c_uint;
#[no_mangle]
pub extern "C" fn btowc(c: libc::c_int) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fwprintf(stream: *mut FILE, format: *const wchar_t, ...)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fwscanf(stream: *mut FILE, format: *const wchar_t, ...)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswalnum(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswalpha(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswcntrl(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswdigit(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswgraph(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswlower(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswprint(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswpunct(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswspace(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswupper(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn iswxdigit(wc: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fgetwc(stream: *mut FILE) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fgetws(ws: *mut wchar_t, n: libc::c_int,
stream: *mut FILE) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fputwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fputws(ws: *const wchar_t, stream: *mut FILE)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fwide(stream: *mut FILE, mode: libc::c_int)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn getwc(stream: *mut FILE) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn getwchar() -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn mbsinit(ps: *const mbstate_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn mbrlen(s: *const libc::c_char, n: usize,
ps: *mut mbstate_t) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn mbrtowc(pwc: *mut wchar_t, s: *const libc::c_char,
n: usize, ps: *mut mbstate_t) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn mbsrtowcs(dst: *mut wchar_t,
src: *mut *const libc::c_char, len: usize,
ps: *mut mbstate_t) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn putwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn putwchar(wc: wchar_t) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn swprintf(s: *mut wchar_t, n: usize,
format: *const wchar_t, ...) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn swscanf(s: *const wchar_t, format: *const wchar_t, ...)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn towlower(wc: wint_t) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn towupper(wc: wint_t) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn ungetwc(wc: wint_t, stream: *mut FILE) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn vfwprintf(stream: *mut FILE, format: *const wchar_t,
arg: va_list) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn vwprintf(format: *const wchar_t, arg: va_list)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn vswprintf(s: *mut wchar_t, n: usize, format: *const wchar_t,
arg: va_list) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcrtomb(s: *mut libc::c_char, wc: wchar_t,
ps: *mut mbstate_t) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcscat(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcschr(ws1: *const wchar_t, ws2: wchar_t)
-> *mut libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcscmp(ws1: *const wchar_t, ws2: *const wchar_t)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcscoll(ws1: *const wchar_t, ws2: *const wchar_t)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcscpy(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcscspn(ws1: *const wchar_t, ws2: *const wchar_t) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsftime(wcs: *mut wchar_t, maxsize: usize, format: *const wchar_t,
timptr: *mut tm) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcslen(ws: *const wchar_t) -> libc::c_ulong {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsncat(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize)
-> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsncmp(ws1: *const wchar_t, ws2: *const wchar_t, n: usize)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsncpy(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize)
-> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcspbrk(ws1: *const wchar_t, ws2: *const wchar_t)
-> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsrchr(ws1: *const wchar_t, ws2: wchar_t) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsrtombs(dst: *mut libc::c_char,
src: *mut *const wchar_t, len: usize,
ps: *mut mbstate_t) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsspn(ws1: *const wchar_t, ws2: *const wchar_t) -> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcstod(nptr: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcstok(ws1: *mut wchar_t, ws2: *const wchar_t,
ptr: *mut *mut wchar_t) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcstol(nptr: *const wchar_t, endptr: *mut *mut wchar_t,
base: libc::c_int) -> libc::c_long {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcstoul(nptr: *const wchar_t, endptr: *mut *mut wchar_t,
base: libc::c_int) -> libc::c_ulong {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcswcs(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcswidth(pwcs: *const wchar_t, n: usize)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcsxfrm(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize)
-> usize {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wctob(c: wint_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wcwidth(wc: wchar_t) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wmemchr(ws: *const wchar_t, wc: wchar_t, n: usize)
-> *mut libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wmemcmp(ws1: *const wchar_t, ws2: *const wchar_t, n: usize)
-> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wmemcpy(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize)
-> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wmemmove(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize)
-> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wmemset(ws1: *mut wchar_t, ws2: wchar_t, n: usize)
-> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wprintf(format: *const wchar_t, ...) -> libc::c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wscanf(format: *const wchar_t, ...) -> libc::c_int {
unimplemented!();
}
+18
View File
@@ -0,0 +1,18 @@
[package]
name = "wchar"
version = "0.1.0"
authors = ["Stephan Vedder <stephan.vedder@gmail.com>"]
build = "build.rs"
[build-dependencies]
cbindgen = { path = "../../cbindgen" }
[features]
str_internals = []
[dependencies]
platform = { path = "../platform" }
stdio = { path = "../stdio" }
errno = { path = "../errno" }
time = { path = "../time" }
va_list = { path = "../../va_list", features = ["no_std"] }
+11
View File
@@ -0,0 +1,11 @@
extern crate cbindgen;
use std::{env, fs};
fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
fs::create_dir_all("../../target/include").expect("failed to create include directory");
cbindgen::generate(crate_dir)
.expect("failed to generate bindings")
.write_to_file("../../target/include/wchar.h");
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = ["stddef.h", "stdint.h", "time.h", "stdio.h" ]
include_guard = "_WCHAR_H"
header = "#include <bits/wchar.h>"
language = "C"
[enum]
prefix_with_name = true
+183 -130
View File
@@ -1,55 +1,84 @@
//! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
//! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wchar.h.html
#![no_std]
#![feature(str_internals)]
extern crate errno;
extern crate platform;
extern crate stdlib;
extern crate string;
extern crate stdio;
extern crate time;
extern crate va_list as vl;
use platform::types::*;
use errno::*;
use time::*;
use core::cmp;
use core::usize;
use core::ptr;
use core::mem;
use string::*;
use stdio::*;
use vl::VaList as va_list;
pub type wint_t = i32;
mod utf8;
const WEOF: wint_t = 0xFFFFFFFFu32;
//Maximum number of bytes in a multibyte character for the current locale
const MB_CUR_MAX: c_int = 4;
//Maximum number of bytes in a multibyte characters for any locale
const MB_LEN_MAX: c_int = 4;
#[repr(C)]
pub struct mbstate_t {
pub mbs_count: c_int,
pub mbs_length: c_int,
pub mbs_wch: wint_t,
}
#[derive(Clone, Copy)]
pub struct mbstate_t {}
#[no_mangle]
pub unsafe extern "C" fn btowc(c: c_int) -> wint_t {
//Check for EOF
if c == -1 {
return -1;
if c as wint_t == WEOF {
return WEOF;
}
let uc = c as u8;
let c = uc as c_char;
let mut ps: mbstate_t = mbstate_t {
mbs_count: 0,
mbs_length: 0,
mbs_wch: 0,
};
let mut ps: mbstate_t = mbstate_t {};
let mut wc: wchar_t = 0;
let saved_errno = platform::errno;
let status = mbrtowc(&mut wc, &c as (*const c_char), 1, &mut ps);
if status == usize::max_value() || status == usize::max_value() - 1 {
platform::errno = saved_errno;
return platform::errno;
return WEOF;
}
return wc as wint_t;
}
#[no_mangle]
pub unsafe extern "C" fn fputwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
//Convert wchar_t to multibytes first
static mut INTERNAL: mbstate_t = mbstate_t {};
let mut bytes: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize];
let amount = wcrtomb(bytes.as_mut_ptr(), wc, &mut INTERNAL);
for i in 0..amount {
fputc(bytes[i] as c_int, &mut *stream);
}
wc as wint_t
}
#[no_mangle]
pub extern "C" fn fputws(ws: *const wchar_t, stream: *mut FILE) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn fwide(stream: *mut FILE, mode: c_int) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn getwc(stream: *mut FILE) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn getwchar() -> wint_t {
unimplemented!();
@@ -57,24 +86,21 @@ pub extern "C" fn getwchar() -> wint_t {
#[no_mangle]
pub unsafe extern "C" fn mbsinit(ps: *const mbstate_t) -> c_int {
if ps.is_null() || (*ps).mbs_count == 0 {
return 1;
//Add a check for the state maybe
if ps.is_null() {
1
} else {
return 0;
0
}
}
#[no_mangle]
pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut mbstate_t) -> usize {
static mut internal: mbstate_t = mbstate_t {
mbs_count: 0,
mbs_length: 0,
mbs_wch: 0,
};
return mbrtowc(ptr::null_mut(), s, n, &mut internal);
static mut INTERNAL: mbstate_t = mbstate_t {};
mbrtowc(ptr::null_mut(), s, n, &mut INTERNAL)
}
//Only works for utf8!
//Only works for UTF8 at the moment
#[no_mangle]
pub unsafe extern "C" fn mbrtowc(
pwc: *mut wchar_t,
@@ -82,123 +108,85 @@ pub unsafe extern "C" fn mbrtowc(
n: usize,
ps: *mut mbstate_t,
) -> usize {
static mut internal: mbstate_t = mbstate_t {
mbs_count: 0,
mbs_length: 0,
mbs_wch: 0,
};
static mut INTERNAL: mbstate_t = mbstate_t {};
if ps.is_null() {
let ps = &mut internal;
let ps = &mut INTERNAL;
}
if s.is_null() {
let xs: [c_char; 1] = [0];
utf8_mbrtowc(pwc, &xs[0] as *const c_char, 1, ps);
return utf8::mbrtowc(pwc, &xs[0] as *const c_char, 1, ps);
} else {
return utf8::mbrtowc(pwc, s, n, ps);
}
return utf8_mbrtowc(pwc, s, n, ps);
}
//Convert a multibyte string to a wide string with a limited amount of bytes
//Required for in POSIX.1-2008
#[no_mangle]
unsafe extern "C" fn utf8_mbrtowc(
pwc: *mut wchar_t,
s: *const c_char,
n: usize,
pub unsafe extern "C" fn mbsnrtowcs(
dst_ptr: *mut wchar_t,
src_ptr: *mut *const c_char,
src_len: usize,
dst_len: usize,
ps: *mut mbstate_t,
) -> usize {
let mut i: usize = 0;
static mut INTERNAL: mbstate_t = mbstate_t {};
while !(i > 0 && (*ps).mbs_count == 0) {
if (n <= i) {
return -2isize as usize;
}
let c = s.offset(i as isize);
let uc = c as u8;
if ps.is_null() {
let ps = &mut INTERNAL;
}
if (*ps).mbs_count == 0 {
//1 byte sequence - 007F
if (uc & 0b10000000) == 0b00000000 {
(*ps).mbs_count = 0;
(*ps).mbs_length = 1;
(*ps).mbs_wch = (uc as wchar_t & 0b1111111) as wint_t;
}
//2 byte sequence - C2DF
else if (uc & 0b11100000) == 0b11000000 {
(*ps).mbs_count = 1;
(*ps).mbs_length = 2;
(*ps).mbs_wch = (uc as wchar_t & 0b11111) as wint_t;
}
//3 byte sequence - E0EF
else if (uc & 0b11110000) == 0b11100000 {
(*ps).mbs_count = 2;
(*ps).mbs_length = 3;
(*ps).mbs_wch = (uc as wchar_t & 0b1111) as wint_t;
}
//4 byte sequence - F0F4
else if (uc & 0b11111000) == 0b11110000 {
(*ps).mbs_count = 3;
(*ps).mbs_length = 4;
(*ps).mbs_wch = (uc as wchar_t & 0b111) as wint_t;
} else {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
} else {
if (uc & 0b11000000) != 0b10000000 {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
let mut src = *src_ptr;
(*ps).mbs_wch = (*ps).mbs_wch << 6 | (uc & 0b00111111) as wint_t;
(*ps).mbs_count -= 1;
let mut dst_offset: usize = 0;
let mut src_offset: usize = 0;
while (dst_ptr.is_null() || dst_offset < dst_len) && src_offset < src_len {
let ps_copy = *ps;
let mut wc: wchar_t = 0;
let amount = mbrtowc(
&mut wc,
src.offset(src_offset as isize),
src_len - src_offset,
ps,
);
// Stop in the event a decoding error occured.
if amount == -1isize as usize {
*src_ptr = src.offset(src_offset as isize);
return 1isize as usize;
}
i += 1;
// Stop decoding early in the event we encountered a partial character.
if amount == -2isize as usize {
*ps = ps_copy;
break;
}
// Store the decoded wide character in the destination buffer.
if !dst_ptr.is_null() {
*dst_ptr.offset(dst_offset as isize) = wc;
}
// Stop decoding after decoding a null character and return a NULL
// source pointer to the caller, not including the null character in the
// number of characters stored in the destination buffer.
if wc == 0 {
src = ptr::null();
src_offset = 0;
break;
}
dst_offset += 1;
src_offset += amount;
}
// Reject the character if it was produced with an overly long sequence.
if (*ps).mbs_length == 1 && 1 << 7 <= (*ps).mbs_wch {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
if (*ps).mbs_length == 2 && 1 << (5 + 1 * 6) <= (*ps).mbs_wch {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
if (*ps).mbs_length == 3 && 1 << (5 + 2 * 6) <= (*ps).mbs_wch {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
if (*ps).mbs_length == 4 && 1 << (5 + 3 * 6) <= (*ps).mbs_wch {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
// The definition of UTF-8 prohibits encoding character numbers between
// U+D800 and U+DFFF, which are reserved for use with the UTF-16 encoding
// form (as surrogate pairs) and do not directly represent characters.
if 0xD800 <= (*ps).mbs_wch && (*ps).mbs_wch <= 0xDFFF {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
// RFC 3629 limits UTF-8 to 0x0 through 0x10FFFF.
if 0x10FFFF <= (*ps).mbs_wch {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
let result: wchar_t = (*ps).mbs_wch as wchar_t;
if !pwc.is_null() {
*pwc = result;
}
(*ps).mbs_length = 0;
(*ps).mbs_wch = 0;
return if result != 0 { i } else { 0 };
*src_ptr = src.offset(src_offset as isize);
return dst_offset;
}
//Convert a multibyte string to a wide string
#[no_mangle]
pub extern "C" fn mbsrtowcs(
dst: *mut wchar_t,
@@ -206,11 +194,31 @@ pub extern "C" fn mbsrtowcs(
len: usize,
ps: *mut mbstate_t,
) -> usize {
unsafe { mbsnrtowcs(dst, src, usize::max_value(), len, ps) }
}
#[no_mangle]
pub unsafe extern "C" fn putwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
fputwc(wc, &mut *stream)
}
#[no_mangle]
pub unsafe extern "C" fn putwchar(wc: wchar_t) -> wint_t {
fputwc(wc, &mut *__stdout())
}
#[no_mangle]
pub extern "C" fn swprintf(
s: *mut wchar_t,
n: usize,
format: *const wchar_t,
mut ap: va_list,
) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn putwchar(wc: wchar_t) -> wint_t {
pub extern "C" fn swscanf(s: *const wchar_t, format: *const wchar_t, mut ap: va_list) -> c_int {
unimplemented!();
}
@@ -225,10 +233,45 @@ pub extern "C" fn towupper(wc: wint_t) -> wint_t {
}
#[no_mangle]
pub extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> usize {
pub extern "C" fn ungetwc(wc: wint_t, stream: *mut FILE) -> wint_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn vfwprintf(stream: *mut FILE, format: *const wchar_t, arg: va_list) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn vwprintf(format: *const wchar_t, arg: va_list) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn vswprintf(
s: *mut wchar_t,
n: usize,
format: *const wchar_t,
arg: va_list,
) -> c_int {
unimplemented!();
}
//widechar to multibyte
#[no_mangle]
pub extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> usize {
let mut buffer: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize];
let mut wc_cpy = wc;
let mut s_cpy = s;
if s.is_null() {
wc_cpy = 0;
s_cpy = buffer.as_mut_ptr();
}
unsafe { utf8::wcrtomb(s_cpy, wc_cpy, ps) }
}
#[no_mangle]
pub extern "C" fn wcscat(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t {
unimplemented!();
@@ -392,3 +435,13 @@ pub extern "C" fn wmemmove(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize) ->
pub extern "C" fn wmemset(ws1: *mut wchar_t, ws2: wchar_t, n: usize) -> *mut wchar_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wprintf(format: *const wchar_t, mut ap: va_list) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn wscanf(format: *const wchar_t, mut ap: va_list) -> c_int {
unimplemented!();
}
+59
View File
@@ -0,0 +1,59 @@
//UTF implementation parts for wchar.h.
//Partially ported from the Sortix libc
#![no_std]
extern crate errno;
extern crate platform;
use platform::types::*;
use mbstate_t;
use core::{slice,str,usize,char};
//It's guaranteed that we don't have any nullpointers here
pub unsafe fn mbrtowc(pwc: *mut wchar_t, s: *const c_char, n: usize, ps: *mut mbstate_t) -> usize {
let mut size = str::utf8_char_width(*s as u8);
if size > n {
platform::errno = errno::EILSEQ;
return -2isize as usize;
}
if size == 0 {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
let slice = slice::from_raw_parts(s as *const u8, size);
let decoded = str::from_utf8(slice);
if decoded.is_err() {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
let wc = decoded.unwrap();
let result: wchar_t = wc.chars().next().unwrap() as wchar_t;
if !pwc.is_null() {
*pwc = result;
}
return if result != 0 { size } else { 0 };
}
//It's guaranteed that we don't have any nullpointers here
pub unsafe fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> usize {
let dc = char::from_u32(wc as u32);
if dc.is_none() {
platform::errno = errno::EILSEQ;
return -1isize as usize;
}
let c = dc.unwrap();
let size = c.len_utf8();
let mut slice = slice::from_raw_parts_mut(s as *mut u8, size);
c.encode_utf8(slice);
size
}