Selaa lähdekoodia

wchar support

Stephan Vedder 6 vuotta sitten
vanhempi
commit
cc210361d6

+ 16 - 2
Cargo.lock

@@ -304,6 +304,7 @@ dependencies = [
  "sys_wait 0.1.0",
  "time 0.1.0",
  "unistd 0.1.0",
+ "wchar 0.1.0",
  "wctype 0.1.0",
 ]
 
@@ -403,7 +404,7 @@ dependencies = [
  "errno 0.1.0",
  "fcntl 0.1.0",
  "platform 0.1.0",
- "stdlib 0.1.0",
+ "ralloc 1.0.0",
  "string 0.1.0",
  "va_list 0.1.0",
 ]
@@ -419,6 +420,7 @@ dependencies = [
  "ralloc 1.0.0",
  "rand 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.0",
+ "wchar 0.1.0",
 ]
 
 [[package]]
@@ -428,7 +430,7 @@ dependencies = [
  "cbindgen 0.5.2",
  "errno 0.1.0",
  "platform 0.1.0",
- "stdlib 0.1.0",
+ "ralloc 1.0.0",
 ]
 
 [[package]]
@@ -606,6 +608,18 @@ name = "vec_map"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "wchar"
+version = "0.1.0"
+dependencies = [
+ "cbindgen 0.5.2",
+ "errno 0.1.0",
+ "platform 0.1.0",
+ "stdio 0.1.0",
+ "time 0.1.0",
+ "va_list 0.1.0",
+]
+
 [[package]]
 name = "wctype"
 version = "0.1.0"

+ 1 - 0
Cargo.toml

@@ -39,6 +39,7 @@ sys_utsname = { path = "src/sys_utsname" }
 sys_wait = { path = "src/sys_wait" }
 time = { path = "src/time" }
 unistd = { path = "src/unistd" }
+wchar = { path = "src/wchar" }
 wctype = { path = "src/wctype" }
 
 [dependencies.compiler_builtins]

+ 5 - 2
include/bits/wchar.h

@@ -1,7 +1,10 @@
 #ifndef _BITS_WCHAR_H
 #define _BITS_WCHAR_H
+#include <stdint.h>
 
-typedef signed short wchar_t;
-typedef signed int wint_t;
+#define WEOF (0xFFFFFFFFu)
+
+typedef int32_t wchar_t;
+typedef uint32_t wint_t;
 
 #endif /* _BITS_WCHAR_H */

+ 2 - 1
include/stddef.h

@@ -1,11 +1,12 @@
 #ifndef _STDDEF_H
 #define _STDDEF_H
+#include <stdint.h>
 
 #define NULL 0
 
 typedef signed long long ptrdiff_t;
 
-typedef unsigned char wchar_t;
+typedef int32_t wchar_t;
 
 typedef unsigned long long size_t;
 

+ 359 - 122
include/stdint.h

@@ -1,130 +1,367 @@
+/* Copyright (C) 2008-2018 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/*
+ * ISO C Standard:  7.18  Integer types  <stdint.h>
+ */
+
 #ifndef _STDINT_H
 #define _STDINT_H
 
-#define INT8_C(value) ((int8_t) value)
-#define INT8_MIN -0x80
-#define INT8_MAX 0x7F
-typedef signed char int8_t;
-
-#define INT_LEAST8_MIN -0x80
-#define INT_LEAST8_MAX 0x7F
-typedef signed char int_least8_t;
-
-#define INT_FAST8_MIN -0x80
-#define INT_FAST8_MAX 0x7F
-typedef signed char int_fast8_t;
-
-#define UINT8_C(value) ((uint8_t) value ## U)
-#define UINT8_MIN 0x00
-#define UINT8_MAX 0xFF
-typedef unsigned char uint8_t;
-
-#define UINT_LEAST8_MIN 0x00
-#define UINT_LEAST8_MAX 0xFF
-typedef unsigned char uint_least8_t;
-
-#define UINT_FAST8_MIN 0x00
-#define UINT_FAST8_MAX 0xFF
-typedef unsigned char uint_fast8_t;
-
-#define INT16_C(value) value
-#define INT16_MIN -0x8000
-#define INT16_MAX 0x7FFF
-typedef signed short int16_t;
-
-#define INT_LEAST16_MIN -0x8000
-#define INT_LEAST16_MAX 0x7FFF
-typedef signed short int_least16_t;
-
-#define INT_FAST16_MIN -0x8000
-#define INT_FAST16_MAX 0x7FFF
-typedef signed short int_fast16_t;
-
-#define UINT16_C(value) value ## U
-#define UINT16_MIN 0x0000
-#define UINT16_MAX 0xFFFF
-typedef unsigned short uint16_t;
-
-#define UINT_LEAST16_MIN 0x0000
-#define UINT_LEAST16_MAX 0xFFFF
-typedef unsigned short uint_least16_t;
-
-#define UINT_FAST16_MIN 0x0000
-#define UINT_FAST16_MAX 0xFFFF
-typedef unsigned short uint_fast16_t;
-
-#define INT32_C(value) value ## L
-#define INT32_MIN -0x80000000
-#define INT32_MAX 0x7FFFFFFF
-typedef signed long int32_t;
-
-#define INT_LEAST32_MIN -0x80000000
-#define INT_LEAST32_MAX 0x7FFFFFFF
-typedef signed long int_least32_t;
-
-#define INT_FAST32_MIN -0x80000000
-#define INT_FAST32_MAX 0x7FFFFFFF
-typedef signed long int_fast32_t;
-
-#define UINT32_C(value) value ## UL
-#define UINT32_MIN 0x00000000
-#define UINT32_MAX 0xFFFFFFFF
-typedef unsigned long uint32_t;
-
-#define UINT_LEAST32_MIN 0x00000000
-#define UINT_LEAST32_MAX 0xFFFFFFFF
-typedef unsigned long uint_least32_t;
-
-#define UINT_FAST32_MIN 0x00000000
-#define UINT_FAST32_MAX 0xFFFFFFFF
-typedef unsigned long uint_fast32_t;
-
-#define INT64_C(value) value ## LL
-#define INT64_MIN -0x8000000000000000
-#define INT64_MAX 0x7FFFFFFFFFFFFFFF
-typedef signed long long int64_t;
-
-#define INT_LEAST64_MIN -0x8000000000000000
-#define INT_LEAST64_MAX 0x7FFFFFFFFFFFFFFF
-typedef signed long long int_least64_t;
-
-#define INT_FAST64_MIN -0x8000000000000000
-#define INT_FAST64_MAX 0x7FFFFFFFFFFFFFFF
-typedef signed long long int_fast64_t;
-
-#define UINT64_C(value) value ## ULL
-#define UINT64_MIN 0x0000000000000000
-#define UINT64_MAX 0xFFFFFFFFFFFFFFFF
-typedef unsigned long long uint64_t;
-
-#define UINT_LEAST64_MIN 0x0000000000000000
-#define UINT_LEAST64_MAX 0xFFFFFFFFFFFFFFFF
-typedef unsigned long long uint_least64_t;
-
-#define UINT_FAST64_MIN 0x0000000000000000
-#define UINT_FAST64_MAX 0xFFFFFFFFFFFFFFFF
-typedef unsigned long long uint_fast64_t;
-
-#define INTMAX_C(value) value ## LL
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-typedef int64_t intmax_t;
-
-#define UINTMAX_C(value) value ## ULL
-#define UINTMAX_MIN UINT64_MIN
-#define UINTMAX_MAX UINT64_MAX
-typedef uint64_t uintmax_t;
-
-#define INTPTR_MIN INT64_MIN
-#define INTPTR_MAX INT64_MAX
-typedef int64_t intptr_t;
-
-#define UINTPTR_MIN UINT64_MIN
-#define UINTPTR_MAX UINT64_MAX
-typedef uint64_t uintptr_t;
+/* 7.8.1.1 Exact-width integer types */
+
+#ifdef __INT8_TYPE__
+typedef __INT8_TYPE__ int8_t;
+#endif
+#ifdef __INT16_TYPE__
+typedef __INT16_TYPE__ int16_t;
+#endif
+#ifdef __INT32_TYPE__
+typedef __INT32_TYPE__ int32_t;
+#endif
+#ifdef __INT64_TYPE__
+typedef __INT64_TYPE__ int64_t;
+#endif
+#ifdef __UINT8_TYPE__
+typedef __UINT8_TYPE__ uint8_t;
+#endif
+#ifdef __UINT16_TYPE__
+typedef __UINT16_TYPE__ uint16_t;
+#endif
+#ifdef __UINT32_TYPE__
+typedef __UINT32_TYPE__ uint32_t;
+#endif
+#ifdef __UINT64_TYPE__
+typedef __UINT64_TYPE__ uint64_t;
+#endif
+
+/* 7.8.1.2 Minimum-width integer types */
+
+typedef __INT_LEAST8_TYPE__ int_least8_t;
+typedef __INT_LEAST16_TYPE__ int_least16_t;
+typedef __INT_LEAST32_TYPE__ int_least32_t;
+typedef __INT_LEAST64_TYPE__ int_least64_t;
+typedef __UINT_LEAST8_TYPE__ uint_least8_t;
+typedef __UINT_LEAST16_TYPE__ uint_least16_t;
+typedef __UINT_LEAST32_TYPE__ uint_least32_t;
+typedef __UINT_LEAST64_TYPE__ uint_least64_t;
+
+/* 7.8.1.3 Fastest minimum-width integer types */
+
+typedef __INT_FAST8_TYPE__ int_fast8_t;
+typedef __INT_FAST16_TYPE__ int_fast16_t;
+typedef __INT_FAST32_TYPE__ int_fast32_t;
+typedef __INT_FAST64_TYPE__ int_fast64_t;
+typedef __UINT_FAST8_TYPE__ uint_fast8_t;
+typedef __UINT_FAST16_TYPE__ uint_fast16_t;
+typedef __UINT_FAST32_TYPE__ uint_fast32_t;
+typedef __UINT_FAST64_TYPE__ uint_fast64_t;
+
+/* 7.8.1.4 Integer types capable of holding object pointers */
+
+#ifdef __INTPTR_TYPE__
+typedef __INTPTR_TYPE__ intptr_t;
+#endif
+#ifdef __UINTPTR_TYPE__
+typedef __UINTPTR_TYPE__ uintptr_t;
+#endif
+
+/* 7.8.1.5 Greatest-width integer types */
+
+typedef __INTMAX_TYPE__ intmax_t;
+typedef __UINTMAX_TYPE__ uintmax_t;
+
+#if (!defined __cplusplus || __cplusplus >= 201103L \
+     || defined __STDC_LIMIT_MACROS)
+
+/* 7.18.2 Limits of specified-width integer types */
+
+#ifdef __INT8_MAX__
+# undef INT8_MAX
+# define INT8_MAX __INT8_MAX__
+# undef INT8_MIN
+# define INT8_MIN (-INT8_MAX - 1)
+#endif
+#ifdef __UINT8_MAX__
+# undef UINT8_MAX
+# define UINT8_MAX __UINT8_MAX__
+#endif
+#ifdef __INT16_MAX__
+# undef INT16_MAX
+# define INT16_MAX __INT16_MAX__
+# undef INT16_MIN
+# define INT16_MIN (-INT16_MAX - 1)
+#endif
+#ifdef __UINT16_MAX__
+# undef UINT16_MAX
+# define UINT16_MAX __UINT16_MAX__
+#endif
+#ifdef __INT32_MAX__
+# undef INT32_MAX
+# define INT32_MAX __INT32_MAX__
+# undef INT32_MIN
+# define INT32_MIN (-INT32_MAX - 1)
+#endif
+#ifdef __UINT32_MAX__
+# undef UINT32_MAX
+# define UINT32_MAX __UINT32_MAX__
+#endif
+#ifdef __INT64_MAX__
+# undef INT64_MAX
+# define INT64_MAX __INT64_MAX__
+# undef INT64_MIN
+# define INT64_MIN (-INT64_MAX - 1)
+#endif
+#ifdef __UINT64_MAX__
+# undef UINT64_MAX
+# define UINT64_MAX __UINT64_MAX__
+#endif
+
+#undef INT_LEAST8_MAX
+#define INT_LEAST8_MAX __INT_LEAST8_MAX__
+#undef INT_LEAST8_MIN
+#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
+#undef UINT_LEAST8_MAX
+#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
+#undef INT_LEAST16_MAX
+#define INT_LEAST16_MAX __INT_LEAST16_MAX__
+#undef INT_LEAST16_MIN
+#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
+#undef UINT_LEAST16_MAX
+#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
+#undef INT_LEAST32_MAX
+#define INT_LEAST32_MAX __INT_LEAST32_MAX__
+#undef INT_LEAST32_MIN
+#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
+#undef UINT_LEAST32_MAX
+#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
+#undef INT_LEAST64_MAX
+#define INT_LEAST64_MAX __INT_LEAST64_MAX__
+#undef INT_LEAST64_MIN
+#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
+#undef UINT_LEAST64_MAX
+#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
+
+#undef INT_FAST8_MAX
+#define INT_FAST8_MAX __INT_FAST8_MAX__
+#undef INT_FAST8_MIN
+#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
+#undef UINT_FAST8_MAX
+#define UINT_FAST8_MAX __UINT_FAST8_MAX__
+#undef INT_FAST16_MAX
+#define INT_FAST16_MAX __INT_FAST16_MAX__
+#undef INT_FAST16_MIN
+#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
+#undef UINT_FAST16_MAX
+#define UINT_FAST16_MAX __UINT_FAST16_MAX__
+#undef INT_FAST32_MAX
+#define INT_FAST32_MAX __INT_FAST32_MAX__
+#undef INT_FAST32_MIN
+#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
+#undef UINT_FAST32_MAX
+#define UINT_FAST32_MAX __UINT_FAST32_MAX__
+#undef INT_FAST64_MAX
+#define INT_FAST64_MAX __INT_FAST64_MAX__
+#undef INT_FAST64_MIN
+#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
+#undef UINT_FAST64_MAX
+#define UINT_FAST64_MAX __UINT_FAST64_MAX__
+
+#ifdef __INTPTR_MAX__
+# undef INTPTR_MAX
+# define INTPTR_MAX __INTPTR_MAX__
+# undef INTPTR_MIN
+# define INTPTR_MIN (-INTPTR_MAX - 1)
+#endif
+#ifdef __UINTPTR_MAX__
+# undef UINTPTR_MAX
+# define UINTPTR_MAX __UINTPTR_MAX__
+#endif
+
+#undef INTMAX_MAX
+#define INTMAX_MAX __INTMAX_MAX__
+#undef INTMAX_MIN
+#define INTMAX_MIN (-INTMAX_MAX - 1)
+#undef UINTMAX_MAX
+#define UINTMAX_MAX __UINTMAX_MAX__
+
+/* 7.18.3 Limits of other integer types */
+
+#undef PTRDIFF_MAX
+#define PTRDIFF_MAX __PTRDIFF_MAX__
+#undef PTRDIFF_MIN
+#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
+
+#undef SIG_ATOMIC_MAX
+#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
+#undef SIG_ATOMIC_MIN
+#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__
+
+#undef SIZE_MAX
+#define SIZE_MAX __SIZE_MAX__
+
+#undef WCHAR_MAX
+#define WCHAR_MAX __WCHAR_MAX__
+#undef WCHAR_MIN
+#define WCHAR_MIN __WCHAR_MIN__
+
+#undef WINT_MAX
+#define WINT_MAX __WINT_MAX__
+#undef WINT_MIN
+#define WINT_MIN __WINT_MIN__
+
+#endif /* (!defined __cplusplus || __cplusplus >= 201103L
+	   || defined __STDC_LIMIT_MACROS)  */
+
+#if (!defined __cplusplus || __cplusplus >= 201103L \
+     || defined __STDC_CONSTANT_MACROS)
+
+#undef INT8_C
+#define INT8_C(c) __INT8_C(c)
+#undef INT16_C
+#define INT16_C(c) __INT16_C(c)
+#undef INT32_C
+#define INT32_C(c) __INT32_C(c)
+#undef INT64_C
+#define INT64_C(c) __INT64_C(c)
+#undef UINT8_C
+#define UINT8_C(c) __UINT8_C(c)
+#undef UINT16_C
+#define UINT16_C(c) __UINT16_C(c)
+#undef UINT32_C
+#define UINT32_C(c) __UINT32_C(c)
+#undef UINT64_C
+#define UINT64_C(c) __UINT64_C(c)
+#undef INTMAX_C
+#define INTMAX_C(c) __INTMAX_C(c)
+#undef UINTMAX_C
+#define UINTMAX_C(c) __UINTMAX_C(c)
+
+#endif /* (!defined __cplusplus || __cplusplus >= 201103L
+	   || defined __STDC_CONSTANT_MACROS) */
+
+#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
+/* TS 18661-1 widths of integer types.  */
+
+#ifdef __INT8_TYPE__
+# undef INT8_WIDTH
+# define INT8_WIDTH 8
+#endif
+#ifdef __UINT8_TYPE__
+# undef UINT8_WIDTH
+# define UINT8_WIDTH 8
+#endif
+#ifdef __INT16_TYPE__
+# undef INT16_WIDTH
+# define INT16_WIDTH 16
+#endif
+#ifdef __UINT16_TYPE__
+# undef UINT16_WIDTH
+# define UINT16_WIDTH 16
+#endif
+#ifdef __INT32_TYPE__
+# undef INT32_WIDTH
+# define INT32_WIDTH 32
+#endif
+#ifdef __UINT32_TYPE__
+# undef UINT32_WIDTH
+# define UINT32_WIDTH 32
+#endif
+#ifdef __INT64_TYPE__
+# undef INT64_WIDTH
+# define INT64_WIDTH 64
+#endif
+#ifdef __UINT64_TYPE__
+# undef UINT64_WIDTH
+# define UINT64_WIDTH 64
+#endif
+
+#undef INT_LEAST8_WIDTH
+#define INT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
+#undef UINT_LEAST8_WIDTH
+#define UINT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
+#undef INT_LEAST16_WIDTH
+#define INT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
+#undef UINT_LEAST16_WIDTH
+#define UINT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
+#undef INT_LEAST32_WIDTH
+#define INT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
+#undef UINT_LEAST32_WIDTH
+#define UINT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
+#undef INT_LEAST64_WIDTH
+#define INT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
+#undef UINT_LEAST64_WIDTH
+#define UINT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
+
+#undef INT_FAST8_WIDTH
+#define INT_FAST8_WIDTH __INT_FAST8_WIDTH__
+#undef UINT_FAST8_WIDTH
+#define UINT_FAST8_WIDTH __INT_FAST8_WIDTH__
+#undef INT_FAST16_WIDTH
+#define INT_FAST16_WIDTH __INT_FAST16_WIDTH__
+#undef UINT_FAST16_WIDTH
+#define UINT_FAST16_WIDTH __INT_FAST16_WIDTH__
+#undef INT_FAST32_WIDTH
+#define INT_FAST32_WIDTH __INT_FAST32_WIDTH__
+#undef UINT_FAST32_WIDTH
+#define UINT_FAST32_WIDTH __INT_FAST32_WIDTH__
+#undef INT_FAST64_WIDTH
+#define INT_FAST64_WIDTH __INT_FAST64_WIDTH__
+#undef UINT_FAST64_WIDTH
+#define UINT_FAST64_WIDTH __INT_FAST64_WIDTH__
+
+#ifdef __INTPTR_TYPE__
+# undef INTPTR_WIDTH
+# define INTPTR_WIDTH __INTPTR_WIDTH__
+#endif
+#ifdef __UINTPTR_TYPE__
+# undef UINTPTR_WIDTH
+# define UINTPTR_WIDTH __INTPTR_WIDTH__
+#endif
+
+#undef INTMAX_WIDTH
+#define INTMAX_WIDTH __INTMAX_WIDTH__
+#undef UINTMAX_WIDTH
+#define UINTMAX_WIDTH __INTMAX_WIDTH__
+
+#undef PTRDIFF_WIDTH
+#define PTRDIFF_WIDTH __PTRDIFF_WIDTH__
+
+#undef SIG_ATOMIC_WIDTH
+#define SIG_ATOMIC_WIDTH __SIG_ATOMIC_WIDTH__
+
+#undef SIZE_WIDTH
+#define SIZE_WIDTH __SIZE_WIDTH__
+
+#undef WCHAR_WIDTH
+#define WCHAR_WIDTH __WCHAR_WIDTH__
+
+#undef WINT_WIDTH
+#define WINT_WIDTH __WINT_WIDTH__
 
 #define SIZE_MAX UINT64_MAX
+#endif
 
 typedef long sig_atomic_t;
 
-#endif /* _STDINT_H */
+#endif /* _GCC_STDINT_H */

+ 1 - 0
src/lib.rs

@@ -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
src/platform/src/types.rs

@@ -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
src/stdio/Cargo.toml

@@ -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
src/stdio/src/helpers.rs

@@ -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
src/stdio/src/lib.rs

@@ -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 - 0
src/stdlib/Cargo.toml

@@ -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
src/stdlib/src/lib.rs

@@ -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
src/string/Cargo.toml

@@ -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
src/string/src/lib.rs

@@ -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 {

+ 0 - 377
src/todo/wchar/lib.rs

@@ -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 - 0
src/wchar/Cargo.toml

@@ -0,0 +1,18 @@
+[package]
+name = "wchar"
+version = "0.1.0"
+authors = ["Stephan Vedder <[email protected]>"]
+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 - 0
src/wchar/build.rs

@@ -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 - 0
src/wchar/cbindgen.toml

@@ -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

+ 182 - 129
src/wchar/src/lib.rs

@@ -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).mbs_count == 0 {
-            //1 byte sequence - 00–7F
-            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 - C2–DF
-            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 - E0–EF
-            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 - F0–F4
-            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;
-            }
-
-            (*ps).mbs_wch = (*ps).mbs_wch << 6 | (uc & 0b00111111) as wint_t;
-            (*ps).mbs_count -= 1;
-        }
-
-        i += 1;
+    if ps.is_null() {
+        let ps = &mut INTERNAL;
     }
 
-    // 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;
-    }
+    let mut src = *src_ptr;
+
+    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;
+        }
 
-    // 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;
-    }
+        // Stop decoding early in the event we encountered a partial character.
+        if amount == -2isize as usize {
+            *ps = ps_copy;
+            break;
+        }
 
-    let result: wchar_t = (*ps).mbs_wch as wchar_t;
+        // Store the decoded wide character in the destination buffer.
+        if !dst_ptr.is_null() {
+            *dst_ptr.offset(dst_offset as isize) = wc;
+        }
 
-    if !pwc.is_null() {
-        *pwc = result;
-    }
+        // 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;
+        }
 
-    (*ps).mbs_length = 0;
-    (*ps).mbs_wch = 0;
+        dst_offset += 1;
+        src_offset += amount;
+    }
 
-    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 - 0
src/wchar/src/utf8.rs

@@ -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
+}

+ 4 - 0
tests/.gitignore

@@ -54,6 +54,10 @@
 /unistd/getopt
 /unlink
 /waitpid
+/wchar/mbrtowc
+/wchar/mbsrtowcs
+/wchar/putwchar
+/wchar/wcrtomb
 /write
 /time
 /gmtime

+ 5 - 1
tests/Makefile

@@ -44,6 +44,10 @@ EXPECT_BINS=\
 	string/strtok_r \
 	unistd/getopt \
 	waitpid \
+	wchar/mbrtowc \
+	wchar/mbsrtowcs \
+	wchar/putwchar \
+	wchar/wcrtomb \
 	write \
 	time \
 	gmtime \
@@ -112,4 +116,4 @@ TAILLIBS=\
 	../target/openlibm/libopenlibm.a
 
 %: %.c $(HEADLIBS) $(TAILLIBS)
-	gcc -fno-stack-protector -Wall $(CFLAGS) $(HEADLIBS) "$<" $(TAILLIBS) -o "$@"
+	gcc -fno-stack-protector -Wall -g $(CFLAGS) $(HEADLIBS) "$<" $(TAILLIBS) -o "$@"

+ 0 - 0
tests/expected/wchar/mbrtowc.stderr


+ 2 - 0
tests/expected/wchar/mbrtowc.stdout

@@ -0,0 +1,2 @@
+Processing 11 UTF-8 code units: [ 7a c3 9f e6 b0 b4 f0 9f 8d 8c 0 ]
+into 5 wchar_t units: [ 7a df 6c34 1f34c 0 ]

+ 0 - 0
tests/expected/wchar/mbsrtowcs.stderr


+ 1 - 0
tests/expected/wchar/mbsrtowcs.stdout

@@ -0,0 +1 @@
+The length, including '\0': 5 

+ 0 - 0
tests/expected/wchar/putwchar.stderr


+ 0 - 0
tests/expected/wchar/putwchar.stdout


+ 0 - 0
tests/expected/wchar/wcrtomb.stderr


+ 2 - 0
tests/expected/wchar/wcrtomb.stdout

@@ -0,0 +1,2 @@
+Processing 5 wchar_t units: [ 7a df 6c34 1f34c 0 ]
+into 11 UTF-8 code units: [ 7a c3 9f e6 b0 b4 f0 9f 8d 8c 0 ]

+ 30 - 0
tests/wchar/mbrtowc.c

@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+ 
+int main(void)
+{
+    mbstate_t state;
+    memset(&state, 0, sizeof state);
+    char in[] = u8"z\u00df\u6c34\U0001F34C"; // or u8"zß水🍌"
+    size_t in_sz = sizeof in / sizeof *in;
+ 
+    printf("Processing %zu UTF-8 code units: [ ", in_sz); //Should be 11 regular chars
+    for(size_t n = 0; n < in_sz; ++n) printf("%#x ", (unsigned char)in[n]);
+    puts("]");
+ 
+    wchar_t out[in_sz];
+    char *p_in = in, *end = in + in_sz;
+    wchar_t *p_out = out;
+    int rc;
+    while((rc = mbrtowc(p_out, p_in, end - p_in, &state)) > 0)
+    {
+        p_in += rc;
+        p_out += 1;
+    }
+ 
+    size_t out_sz = p_out - out + 1;
+    printf("into %zu wchar_t units: [ ", out_sz); //Should be 5 wchars
+    for(size_t x = 0; x < out_sz; ++x) printf("%#x ", out[x]);
+    puts("]");
+}

+ 23 - 0
tests/wchar/mbsrtowcs.c

@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <wchar.h>
+ 
+void print_as_wide(const char* mbstr)
+{
+    mbstate_t state;
+    memset(&state, 0, sizeof state);
+    size_t len = 1 + mbsrtowcs(NULL, &mbstr, 0, &state);
+    wchar_t wstr[len];
+    mbsrtowcs(&wstr[0], &mbstr, len, &state);
+
+    //Should be 5
+    printf("The length, including '\\0': %i \n",len);
+
+    //missing wprintf to print this wide string
+    //wprintf(L"The wide string: %ls \n", &wstr[0]);
+}
+ 
+int main()
+{
+    const char* mbstr = u8"z\u00df\u6c34\U0001f34c"; // or u8"zß水🍌"
+    print_as_wide(mbstr);
+}

+ 21 - 0
tests/wchar/putwchar.c

@@ -0,0 +1,21 @@
+#include <string.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <stdlib.h>
+
+int main(void)
+{
+    wchar_t *wcs = L"zß水🍌";
+
+    int i;
+    for (i = 0; wcs[i] != L'\0'; i++)
+    {
+        if (0xFFFFFFFFu == putwchar(wcs[i]))
+        {
+            printf("Unable to putwchar() the wide character.\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    return 0;
+}

+ 29 - 0
tests/wchar/wcrtomb.c

@@ -0,0 +1,29 @@
+#include <string.h>  
+#include <stdio.h>  
+#include <wchar.h> 
+#include <stdlib.h>
+  
+int main( void )  
+{  
+    mbstate_t state;
+    memset(&state, 0, sizeof state);
+    wchar_t in[] = L"zß水🍌"; // or "z\u00df\u6c34\U0001F34C"
+    size_t in_sz = sizeof in / sizeof *in;
+ 
+    printf("Processing %zu wchar_t units: [ ", in_sz);
+    for(size_t n = 0; n < in_sz; ++n) printf("%#x ", (unsigned int)in[n]);
+    puts("]");
+ 
+    char out[MB_CUR_MAX * in_sz];
+    char *p = out;
+    for(size_t n = 0; n < in_sz; ++n) {
+        int rc = wcrtomb(p, in[n], &state); 
+        if(rc == -1) break;
+        p += rc;
+    }
+ 
+    size_t out_sz = p - out;
+    printf("into %zu UTF-8 code units: [ ", out_sz);
+    for(size_t x = 0; x < out_sz; ++x) printf("%#x ", +(unsigned char)out[x]);
+    puts("]");
+}