diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e38d132959a5c8bde9b8894da74abdcf2891b9e2..628873551f959d0205198db1da08ce4fbd5f53cb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,27 +1,51 @@ -image: "rust:latest" +image: "rustlang/rust:nightly" + +stages: + - build + - test before_script: - git submodule update --init --recursive - - rustup toolchain add nightly - - rustup target add x86_64-unknown-redox --toolchain nightly + - rustup toolchain add "$(cat rust-toolchain)" + - rustup target add x86_64-unknown-redox --toolchain "$(cat rust-toolchain)" - rustup show # Print version info for debugging +cache: + untracked: true + build:linux: + stage: build script: - make all -#build:redox: -# script: -# - make all +build:redox: + stage: build + variables: + TARGET: x86_64-unknown-redox + script: + # Install x86_64-unknown-redox-gcc + # This can't be in before_script because that overrides + # the global before_script. + - apt-get update -qq + - apt-get install -qq apt-transport-https build-essential curl git gnupg software-properties-common + - apt-key adv --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F + - add-apt-repository 'deb https://static.redox-os.org/toolchain/apt /' + - apt-get update -qq && apt-get install -qq x86-64-unknown-redox-gcc + + # Main script + - make all test:linux: + stage: test + dependencies: + - build:linux script: - make test + - cd tests && make verify fmt: + stage: test script: - rustup component add rustfmt-preview - ./fmt.sh -- --check - -# TODO: Set up a docker image with a redox vm that would allow to -# run things like tests under redox + allow_failure: true diff --git a/Cargo.lock b/Cargo.lock index fa1be69c666916affd388ad2123c0518f2ceee60..23d4c6e1aa570dae5904c6e4457dea1cd16bf1dc 100644 --- a/Cargo.lock +++ b/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", ] @@ -418,7 +419,9 @@ dependencies = [ "platform 0.1.0", "ralloc 1.0.0", "rand 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.0", "time 0.1.0", + "wchar 0.1.0", ] [[package]] @@ -428,7 +431,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 +609,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" diff --git a/Cargo.toml b/Cargo.toml index b64015bdad3e2207d9a35d5daa17fbf9e156b04b..9514720270cdd499596efb0a759e22f6a1d1bed7 100644 --- a/Cargo.toml +++ b/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] diff --git a/Makefile b/Makefile index 8ffd601d91c99da1d08080c2eb616fadf2a6ba80..39d1183a56e2142bab1012a0e7c492bf1fff0cf4 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,11 @@ ifneq ($(TARGET),) endif ifeq ($(TARGET),aarch64-unknown-linux-gnu) - CC="aarch64-linux-gnu-gcc" + CC=aarch64-linux-gnu-gcc endif ifeq ($(TARGET),x86_64-unknown-redox) - CC="x86_64-unknown-redox-gcc" + CC=x86_64-unknown-redox-gcc endif SRC=\ diff --git a/fmt.sh b/fmt.sh index 4e2cf0508534331239b0478c7240b15f8f6eef0d..cb5a928a33df8657a51debf0a0eb73b84cc3d5c7 100755 --- a/fmt.sh +++ b/fmt.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash ARGS=() for crate in relibc $(find src -name Cargo.toml | cut -d '/' -f2 | grep -v template) diff --git a/include/bits/unistd.h b/include/bits/unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..a7167d047a4988f8fce0372e674c4a4514663fb1 --- /dev/null +++ b/include/bits/unistd.h @@ -0,0 +1,7 @@ +#ifndef _BITS_UNISTD_H +#define _BITS_UNISTD_H + +int execl(const char *path, const char* argv0, ...); +int execle(const char *path, const char* argv0, ...); + +#endif diff --git a/include/bits/wchar.h b/include/bits/wchar.h index 98216dfb0fa5e22d686cd577f52e3fcd123faedf..eed486f1bcf3c6b39fc8b7bb55efbba72b98bbcb 100644 --- a/include/bits/wchar.h +++ b/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 */ diff --git a/include/stddef.h b/include/stddef.h index fa0bc7daf528f082aab9958c1054fa0f716e9a03..1dc7f60fc1f57381b7323237c472de81c6cc86ed 100644 --- a/include/stddef.h +++ b/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; diff --git a/include/stdint.h b/include/stdint.h index cbe5e37fe71a6271f17dc5e55f78e85a93930f2b..3a578783fa770e858d7bf2b25463f6ac62715438 100644 --- a/include/stdint.h +++ b/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 */ diff --git a/rustfmt.toml b/rustfmt.toml index d52a68e960ed52d6efadc8fdbc63907b8f2c1069..5780cc6e08c5d0a433f49497d1c1b6b214a50ddc 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -9,19 +9,13 @@ fn_single_line = false where_single_line = false imports_indent = "Visual" imports_layout = "Mixed" -reorder_extern_crates = true -reorder_extern_crates_in_group = true reorder_imports = false -reorder_imported_names = true -spaces_within_parens_and_brackets = false -remove_blank_lines_at_start_or_end_of_block = true fn_args_density = "Tall" brace_style = "SameLineWhere" trailing_comma = "Vertical" blank_lines_upper_bound = 1 blank_lines_lower_bound = 0 force_explicit_abi = true -write_mode = "Overwrite" disable_all_formatting = false skip_children = false hide_parse_errors = false diff --git a/include/bits/exec.h b/src/c/unistd.c similarity index 83% rename from include/bits/exec.h rename to src/c/unistd.c index 94024518ba8fd7999a7b8902e357810504a1191f..a2a78ce727dc9d161c8d6c55213bcd0c72a24bcf 100644 --- a/include/bits/exec.h +++ b/src/c/unistd.c @@ -1,5 +1,7 @@ -#ifndef _BITS_EXEC_H -#define _BITS_EXEC_H +#include <stdarg.h> +#include <stddef.h> + +int execv(const char *path, char *const *argv); int execl(const char *path, const char* argv0, ...) { @@ -22,6 +24,8 @@ int execl(const char *path, const char* argv0, ...) } } +int execve(const char *path, char *const *argv, char *const *envp); + int execle(const char *path, const char* argv0, ...) { int argc; diff --git a/src/inttypes/src/lib.rs b/src/inttypes/src/lib.rs index 0ceb7bc55bab48d76beee4e7ed006ac2feceb045..ff2007a2138743c26a33e97bfc720d0164a1126b 100644 --- a/src/inttypes/src/lib.rs +++ b/src/inttypes/src/lib.rs @@ -1,3 +1,5 @@ +#![no_std] + #[macro_use] extern crate stdlib; extern crate ctype; extern crate errno; diff --git a/src/lib.rs b/src/lib.rs index 7c9f060b592f915d747a2a50246bfa5168d86175..558f7764d8ae759a39038fd085579f18d3096b10 100644 --- a/src/lib.rs +++ b/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(test))] diff --git a/src/platform/Cargo.toml b/src/platform/Cargo.toml index dd5ba725ac56ffd3eb4431e3df80d7b94791eff0..e25b8251c0c6bb44761c2f5a8af2e7eda0c70881 100644 --- a/src/platform/Cargo.toml +++ b/src/platform/Cargo.toml @@ -8,6 +8,3 @@ sc = "0.2" [target.'cfg(target_os = "redox")'.dependencies] redox_syscall = "0.1" - -[dependencies] -ralloc = { path = "../../ralloc" } diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs index 185354ff856fdeb481e9b678eac235bed344ffa9..1838b29edd05177f16eaa3d985a158f888e6fc0a 100644 --- a/src/platform/src/lib.rs +++ b/src/platform/src/lib.rs @@ -2,8 +2,6 @@ #![no_std] #![allow(non_camel_case_types)] -#![feature(alloc)] -#![feature(global_allocator)] //TODO #![feature(thread_local)] #[cfg(all(not(feature = "no_std"), target_os = "linux"))] @@ -24,17 +22,12 @@ mod sys; #[path = "redox/mod.rs"] mod sys; -extern crate alloc; -extern crate ralloc; - pub mod types; use core::fmt; use types::*; -#[global_allocator] -static ALLOCATOR: ralloc::Allocator = ralloc::Allocator; //TODO #[thread_local] #[allow(non_upper_case_globals)] #[no_mangle] diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index 71019375f7c9f4400a34fe805bb1e8ac77a4a02e..b72e5d72b6c054cfa436297bce67183a75d2837d 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -1,7 +1,6 @@ use core::ptr; use core::slice; use core::mem; -use alloc::Vec; use syscall; use syscall::flag::*; use syscall::data::TimeSpec as redox_timespec; @@ -68,58 +67,6 @@ pub fn dup2(fd1: c_int, fd2: c_int) -> c_int { e(syscall::dup2(fd1 as usize, fd2 as usize, &[])) as c_int } -pub fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { - unsafe { - let mut env = envp; - while !(*env).is_null() { - let slice = c_str(*env); - // Should always contain a =, but worth checking - if let Some(sep) = slice.iter().position(|&c| c == b'=') { - // If the environment variable has no name, do not attempt - // to add it to the env. - if sep > 0 { - let mut path = b"env:".to_vec(); - path.extend_from_slice(&slice[..sep]); - match syscall::open(&path, O_WRONLY | O_CREAT) { - Ok(fd) => { - // If the environment variable has no value, there - // is no need to write anything to the env scheme. - if sep + 1 < slice.len() { - let n = match syscall::write(fd, &slice[sep + 1..]) { - Ok(n) => n, - err => { - return e(err) as c_int; - } - }; - } - // Cleanup after adding the variable. - match syscall::close(fd) { - Ok(_) => (), - err => { - return e(err) as c_int; - } - } - } - err => { - return e(err) as c_int; - } - } - } - } - env = env.offset(1); - } - - let mut args: Vec<[usize; 2]> = Vec::new(); - let mut arg = argv; - while !(*arg).is_null() { - args.push([*arg as usize, c_str(*arg).len()]); - arg = arg.offset(1); - } - - e(syscall::execve(c_str(path), &args)) as c_int - } -} - pub fn exit(status: c_int) -> ! { let _ = syscall::exit(status as usize); loop {} diff --git a/src/platform/src/types.rs b/src/platform/src/types.rs index 29ed354d1b543470513c0f47cc2844176358fa06..61b1fea30dee89c0496232c9275a1f3205a288c1 100644 --- a/src/platform/src/types.rs +++ b/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; diff --git a/src/setjmp/src/impl/bin/.gitignore b/src/setjmp/src/impl/bin/.gitignore deleted file mode 100644 index d6b7ef32c8478a48c3994dcadc86837f4371184d..0000000000000000000000000000000000000000 --- a/src/setjmp/src/impl/bin/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/src/stdio/Cargo.toml b/src/stdio/Cargo.toml index 1f2f2794e94243c98145156a658c5ccd28095b98..27fbe42bc7eaccfac21d736d8b85de209f2a8a36 100644 --- a/src/stdio/Cargo.toml +++ b/src/stdio/Cargo.toml @@ -12,7 +12,7 @@ errno = { path = "../errno"} fcntl = { path = "../fcntl" } lazy_static = { version = "*", features = ["nightly", "spin_no_std"] } platform = { path = "../platform" } -ralloc = { path = "../../ralloc" } +ralloc = { path = "../../ralloc", default-features = false } string = { path = "../string" } stdlib = { path = "../stdlib" } va_list = { path = "../../va_list", features = ["no_std"] } diff --git a/src/stdio/src/helpers.rs b/src/stdio/src/helpers.rs index 242e83f1ec4e164b004748bff093bca85169eae2..3e898a24b5cd8fabed410ce0e5e32bdd90a4446a 100644 --- a/src/stdio/src/helpers.rs +++ b/src/stdio/src/helpers.rs @@ -1,4 +1,6 @@ -use super::{BUFSIZ, FILE, UNGET}; +use super::{internal, BUFSIZ, FILE, UNGET}; +use ralloc; +use core::{mem, ptr}; use core::sync::atomic::AtomicBool; use platform::types::*; use super::constants::*; @@ -62,8 +64,8 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> { flags |= F_APP; } + let f = ralloc::alloc(mem::size_of::<FILE>(), 1) as *mut FILE; // Allocate the file - let f = malloc(size_of::<FILE>()) as *mut FILE; if f.is_null() { None } else { diff --git a/src/stdio/src/lib.rs b/src/stdio/src/lib.rs index e3e23d8c21625c3e7417b678871bbec9f5d8813c..317d5c9a980370c12494ae9f51c09bfd796d6dc9 100644 --- a/src/stdio/src/lib.rs +++ b/src/stdio/src/lib.rs @@ -12,12 +12,11 @@ extern crate fcntl; #[macro_use] extern crate lazy_static; 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}; @@ -28,8 +27,8 @@ use platform::{c_str, errno, Read, Write}; use alloc::vec::Vec; use vl::VaList as va_list; -mod scanf; mod printf; +mod scanf; mod default; pub use default::*; @@ -214,13 +213,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, + ); } } else { funlockfile(stream); @@ -897,5 +899,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, + ) } diff --git a/src/stdlib/Cargo.toml b/src/stdlib/Cargo.toml index 97ed4e9dfe4237934303f1326c68d5fe088b66ac..1122990e1d1261c12f2659f63406591b1878548c 100644 --- a/src/stdlib/Cargo.toml +++ b/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" } \ No newline at end of file diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs index ff5404d56dc1307331fbc3db06798a47645e8eb6..50eadb2eec0490bdb5619d6717dcf4ed2d3e9253 100644 --- a/src/stdlib/src/lib.rs +++ b/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 } diff --git a/src/string/Cargo.toml b/src/string/Cargo.toml index 9bf1d9dc99edd2d756c893a1efa89690858ce757..f134d7ff7a43a9a6ba5c93beeb21c917895af4be 100644 --- a/src/string/Cargo.toml +++ b/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" } diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index 681bbe2b8f9d6c1585213e5910fb30b434089447..601b3385d80c913194c02600bb3018868a272544 100644 --- a/src/string/src/lib.rs +++ b/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 { diff --git a/src/sys_utsname/src/lib.rs b/src/sys_utsname/src/lib.rs index a0792dd564fef80c4c2b5c3882dfb11aca623f83..0bb0da2ed372eaca9fa0a57c8d39df6dcbcc8f1e 100644 --- a/src/sys_utsname/src/lib.rs +++ b/src/sys_utsname/src/lib.rs @@ -1,28 +1,32 @@ //! sys/utsname implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html #![no_std] -#![cfg(target_os = "linux")] -extern crate platform; +#[cfg(target_os = "linux")] +mod inner { + extern crate platform; -use core::ptr; -use platform::types::*; + use core::ptr; + use self::platform::types::*; -const LENGTH: usize = 65; + const LENGTH: usize = 65; -#[allow(non_camel_case)] -#[no_mangle] -#[repr(C)] -pub struct utsname { - pub sysname: [c_char; LENGTH], - pub nodename: [c_char; LENGTH], - pub release: [c_char; LENGTH], - pub version: [c_char; LENGTH], - pub machine: [c_char; LENGTH], - pub domainname: [c_char; LENGTH] -} + #[allow(non_camel_case)] + #[no_mangle] + #[repr(C)] + pub struct utsname { + pub sysname: [c_char; LENGTH], + pub nodename: [c_char; LENGTH], + pub release: [c_char; LENGTH], + pub version: [c_char; LENGTH], + pub machine: [c_char; LENGTH], + pub domainname: [c_char; LENGTH] + } -#[no_mangle] -pub unsafe extern "C" fn uname(uts: *mut utsname) -> c_int { - platform::uname(uts as usize) + #[no_mangle] + pub unsafe extern "C" fn uname(uts: *mut utsname) -> c_int { + platform::uname(uts as usize) + } } +#[cfg(target_os = "linux")] +pub use inner::*; diff --git a/src/todo/wchar/lib.rs b/src/todo/wchar/lib.rs deleted file mode 100644 index b760fba7aafb1f9ed785fcd6c99086d359816c3e..0000000000000000000000000000000000000000 --- a/src/todo/wchar/lib.rs +++ /dev/null @@ -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!(); -} diff --git a/src/unistd/cbindgen.toml b/src/unistd/cbindgen.toml index ef4ad8123a3ed5aed99c7d22f7187965d2a72dca..a10250c6ddd2b485719f28ee675929235850f5c4 100644 --- a/src/unistd/cbindgen.toml +++ b/src/unistd/cbindgen.toml @@ -1,6 +1,6 @@ -sys_includes = ["stddef.h", "stdint.h", "sys/types.h", "stdarg.h", "bits/exec.h"] +sys_includes = ["stddef.h", "stdint.h", "sys/types.h"] include_guard = "_UNISTD_H" -trailer = "#include <bits/fcntl.h>" +trailer = "#include <bits/fcntl.h>\n#include <bits/unistd.h>" language = "C" [enum] diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs index db90a9feafd2f975a00f343166e92f7196d9a9b8..b673671f8df73c515dab194d79417e10da86e26e 100644 --- a/src/unistd/src/lib.rs +++ b/src/unistd/src/lib.rs @@ -1,7 +1,9 @@ //! unistd implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html #![no_std] +#![cfg_attr(target_os = "redox", feature(alloc))] +#[cfg(target_os = "redox")] extern crate alloc; extern crate platform; extern crate stdio; extern crate string; @@ -33,7 +35,7 @@ pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; #[no_mangle] -pub static mut environ: *const *mut c_char = 0 as *const *mut c_char; +pub static mut environ: *const *mut c_char = ptr::null(); #[no_mangle] pub extern "C" fn _exit(status: c_int) { @@ -120,17 +122,80 @@ pub extern "C" fn encrypt(block: [c_char; 64], edflag: c_int) { // } #[no_mangle] -pub extern "C" fn execv(path: *const c_char, argv: *const *mut c_char) -> c_int { - unsafe { execve(path, argv, environ) } +pub unsafe extern "C" fn execv(path: *const c_char, argv: *const *mut c_char) -> c_int { + execve(path, argv, environ) } #[no_mangle] -pub extern "C" fn execve( +pub unsafe extern "C" fn execve( path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int { - platform::execve(path, argv, envp) + #[cfg(target_os = "linux")] { + platform::execve(path, argv, envp) + } + #[cfg(target_os = "redox")] { + use alloc::Vec; + use platform::{c_str, e}; + use platform::syscall::flag::*; + + let mut env = envp; + while !(*env).is_null() { + let slice = c_str(*env); + // Should always contain a =, but worth checking + if let Some(sep) = slice.iter().position(|&c| c == b'=') { + // If the environment variable has no name, do not attempt + // to add it to the env. + if sep > 0 { + let mut path = b"env:".to_vec(); + path.extend_from_slice(&slice[..sep]); + match platform::syscall::open(&path, O_WRONLY | O_CREAT) { + Ok(fd) => { + // If the environment variable has no value, there + // is no need to write anything to the env scheme. + if sep + 1 < slice.len() { + let n = match platform::syscall::write(fd, &slice[sep + 1..]) { + Ok(n) => n, + err => { + return e(err) as c_int; + } + }; + } + // Cleanup after adding the variable. + match platform::syscall::close(fd) { + Ok(_) => (), + err => { + return e(err) as c_int; + } + } + } + err => { + return e(err) as c_int; + } + } + } + } + env = env.offset(1); + } + + let mut len = 0; + for i in 0.. { + if (*argv.offset(i)).is_null() { + len = i; + break; + } + } + + let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize); + let mut arg = argv; + while !(*arg).is_null() { + args.push([*arg as usize, c_str(*arg).len()]); + arg = arg.offset(1); + } + + e(platform::syscall::execve(c_str(path), &args)) as c_int + } } #[no_mangle] @@ -235,25 +300,25 @@ pub unsafe extern "C" fn gethostname(mut name: *mut c_char, len: size_t) -> c_in name = name.offset(1); } - 0 } #[cfg(target_os = "redox")] { - use platform::{FileReader, Read}; + use platform::{e, FileReader, Read}; use platform::syscall::flag::*; - let fd = platform::open("/etc/hostname\0",as_ptr(), 0, O_RDONLY); + let fd = e(platform::syscall::open("/etc/hostname", O_RDONLY)) as i32; if fd < 0 { return fd; } - let reader = FileReader(fd); + let mut reader = FileReader(fd); for _ in 0..len { - if !reader.read_u8(&mut *name) { + if !reader.read_u8(&mut *(name as *mut u8)) { *name = 0; break; } name = name.offset(1); } } + 0 } #[no_mangle] diff --git a/src/wchar/Cargo.toml b/src/wchar/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..97e412f20d966296a739e19c3859e811782901b9 --- /dev/null +++ b/src/wchar/Cargo.toml @@ -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"] } \ No newline at end of file diff --git a/src/wchar/build.rs b/src/wchar/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..5b64a17833ecbbf57ae8892cffdbceb1f2cc1fe8 --- /dev/null +++ b/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"); +} diff --git a/src/wchar/cbindgen.toml b/src/wchar/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..0e0aa10c843a41423844ef34faa5749a87c5041a --- /dev/null +++ b/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 diff --git a/src/wchar/src/lib.rs b/src/wchar/src/lib.rs index 96bb95d1feafac03a8534a38f674584eb8b9ec4a..31ae9667f56506b0d260c50b127439ac15e33093 100644 --- a/src/wchar/src/lib.rs +++ b/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!(); +} diff --git a/src/wchar/src/utf8.rs b/src/wchar/src/utf8.rs new file mode 100644 index 0000000000000000000000000000000000000000..52166210f67741a07af25bbb4b484e4adbb80896 --- /dev/null +++ b/src/wchar/src/utf8.rs @@ -0,0 +1,57 @@ +//UTF implementation parts for wchar.h. +//Partially ported from the Sortix libc + +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 +} diff --git a/tests/.gitignore b/tests/.gitignore index c60d7feecf6720f05e8ee899c0f6ba2fe3a4f2ab..e2242ca6a691e06861fcc4b710cd1e059094cf01 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -54,6 +54,10 @@ /unistd/getopt /unlink /waitpid +/wchar/mbrtowc +/wchar/mbsrtowcs +/wchar/putwchar +/wchar/wcrtomb /write /time /gmtime diff --git a/tests/Makefile b/tests/Makefile index dbe6063de243a036f087e7555b016eb0b2bb2970..3588a66a5b164d4eaa9e81e6388aba3f01e1d5a2 100644 --- a/tests/Makefile +++ b/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 "$@" diff --git a/tests/exec.c b/tests/exec.c index 4a09e743b59e80de89fbf221a3115cbac6f78af4..213df7f8d325de98c78367e592cfae730e3a48c9 100644 --- a/tests/exec.c +++ b/tests/exec.c @@ -1,4 +1,5 @@ #include <unistd.h> +#include <stdio.h> int main(int argc, char** argv) { char *const args[1] = {"arg"}; diff --git a/tests/expected/exec.stderr b/tests/expected/exec.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/exec.stdout b/tests/expected/exec.stdout new file mode 100644 index 0000000000000000000000000000000000000000..980a0d5f19a64b4b30a87d4206aade58726b60e3 --- /dev/null +++ b/tests/expected/exec.stdout @@ -0,0 +1 @@ +Hello World! diff --git a/tests/expected/wchar/mbrtowc.stderr b/tests/expected/wchar/mbrtowc.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/wchar/mbrtowc.stdout b/tests/expected/wchar/mbrtowc.stdout new file mode 100644 index 0000000000000000000000000000000000000000..ae1d1cd6f9abcd8ba435cfd8efe9960655aeb1ae --- /dev/null +++ b/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 ] diff --git a/tests/expected/wchar/mbsrtowcs.stderr b/tests/expected/wchar/mbsrtowcs.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/wchar/mbsrtowcs.stdout b/tests/expected/wchar/mbsrtowcs.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e8f8258f2edcc440863f3ac05f1f49d0f7723258 --- /dev/null +++ b/tests/expected/wchar/mbsrtowcs.stdout @@ -0,0 +1 @@ +The length, including '\0': 5 diff --git a/tests/expected/wchar/putwchar.stderr b/tests/expected/wchar/putwchar.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/wchar/putwchar.stdout b/tests/expected/wchar/putwchar.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/wchar/wcrtomb.stderr b/tests/expected/wchar/wcrtomb.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/wchar/wcrtomb.stdout b/tests/expected/wchar/wcrtomb.stdout new file mode 100644 index 0000000000000000000000000000000000000000..d41045ed2b49e1f52c6aef455fc8fca00b689451 --- /dev/null +++ b/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 ] diff --git a/tests/wchar/mbrtowc.c b/tests/wchar/mbrtowc.c new file mode 100644 index 0000000000000000000000000000000000000000..4487d2273192ce2b38c98e2eac6ef054b34d1c82 --- /dev/null +++ b/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("]"); +} \ No newline at end of file diff --git a/tests/wchar/mbsrtowcs.c b/tests/wchar/mbsrtowcs.c new file mode 100644 index 0000000000000000000000000000000000000000..1ee1560a9f7c27dc13369a6694fbb2ce61543cf5 --- /dev/null +++ b/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); +} \ No newline at end of file diff --git a/tests/wchar/putwchar.c b/tests/wchar/putwchar.c new file mode 100644 index 0000000000000000000000000000000000000000..f9f7ea41236ce5bbbf85d1cbd1ed318b67a0ea71 --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/tests/wchar/wcrtomb.c b/tests/wchar/wcrtomb.c new file mode 100644 index 0000000000000000000000000000000000000000..27b05cef6b3bbfb9b383867c11ec5f185cc65f02 --- /dev/null +++ b/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("]"); +} \ No newline at end of file