This is basically a subset of type, so we might as well.
To be clear this is `command -s` and friends, if you do `command grep` that's
handled as a keyword.
One issue here is that we can't get "one path or not" because I don't
know how to translate a maybe_t? Do we need to make it a shared_ptr instead?
Most of it is duplicated, hence untested.
Functions like mbrtowc are not exposed by the libc crate, so declare them
ourselves.
Since we don't know the definition of C macros, add two big hacks to make
this work:
1. Replace MB_LEN_MAX and mbstate_t with values (resp types) that should
be large enough for any implementation.
2. Detect the definition of MB_CUR_MAX in the build script. This requires
more changes for each new libc. We could also use this approach for 1.
Additionally, this commit brings a small behavior change to
read_unquoted_escape(): we cannot decode surrogate code points like \UDE01
into a Rust char, so use � (\UFFFD, replacement character) instead.
Previously, we added such code points to a wcstring; looks like they were
ignored when printed.
wcs2string converts a wide string to a narrow one. The result is
null-terminated and may also contain interior null-characters.
std::string allows this.
Rust's null-terminated string, CString, does not like interior null-characters.
This means we will need to use Vec<u8> or OsString for the places where we
use interior null-characters.
On the other hand, we want to use CString for places that require a
null-terminator, because other Rust types don't guarantee the null-terminator.
Turns out there is basically no overlap between the two use cases, so make
it two functions. Their equivalents in Rust will have the same name, so
we'll only need to adjust the type when porting.
Existing C++ code didn't use a function for this but simply added
ENCODE_DIRECT_BASE. In Rust that's more verbose because char won't do
arithmetics, hence the function.
We'll add a dual function for decoding, so let's rename this.
BTW we should get rid of the "wchar" naming, it's just "char" in Rust.
Prior to this change, wcstoi("0x") would fail with missing digits.
However strtoul will "backtrack" to return just the 0 and leave the x as
the remainder. Implement this behavior.
Prior to this change, wcstoi() would return an error if the requested
type were unsigned, and the input had a leading minus sign. However this
causes problems for printf, which expects strtoul behavior.
Add "modulo base" behavior which wraps the negative value to positive.
Factor this into an option; the default is False (but code which
previously used strtoull directly should set it to true).
fish_wcstoi_partial is like fish_wcstoi: it converts from a string to an
int optionally inferring the radix. fish_wcstoi_partial also returns the
number of characters consumed.
Unfortunately we cannot use wide string literals in match statements
(not sure if there's an easy fix).
Because of this, I converted the input to UTF-8 so we could use the match
statement. This conversion is confusing, let's skip it.
Everything but signal handlers has been changed to use `Signal` instead of
`c_int` or `i32` signal values.
Event handlers are using `usize` to match C++, at least for now.
Signal is a newtype around NonZeroI32. We could use NonZeroU8 since all signal
values comfortably fit, but using i32 lets us avoid a fallible attempt at
narrowing values returned from the system as integers to the narrower u8 type.
Known signals are explicitly defined as constants and can be matched against
with equality or with pattern matching in a `match` block. Unknown signal values
are passed-through without causing any issues.
We're using per-OS targeting to enable certain libc SIGXXX values - we could
change this to dynamically detecting what's available in build.rs but then it
might not match what libc exposes, still giving us build failures.