1#![warn(missing_docs)]
3#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
4#![no_std]
5
6mod sys;
7pub use sys::*;
8
9#[cfg(feature = "libc")]
10pub mod locale;
11#[cfg(all(feature = "libc", feature = "memory"))]
12pub mod memory;
13#[cfg(all(feature = "libc", feature = "memory"))]
14pub mod env;
15#[cfg(feature = "libc")]
16pub mod process;
17pub mod args;
18pub use args::Args;
19
20#[cfg(feature = "libc")]
21#[allow(non_camel_case_types)]
22pub type int = libc::c_int;
26#[cfg(not(feature = "libc"))]
27#[allow(non_camel_case_types)]
28pub type int = i32;
30
31pub unsafe fn c_str_to_rust(ptr: *const u8) -> Result<&'static str, core::str::Utf8Error> {
35 let len = strlen(ptr as *const i8);
36 let parts = core::slice::from_raw_parts(ptr, len);
37 core::str::from_utf8(parts)
38}
39
40pub unsafe fn c_str_to_rust_unchecked(ptr: *const u8) -> &'static str {
44 let len = strlen(ptr as *const i8);
45 let parts = core::slice::from_raw_parts(ptr, len);
46 core::str::from_utf8_unchecked(parts)
47}
48
49#[cfg(any(windows, unix, target_env = "wasi", target_os = "wasi", target_os = "vxworks", target_os = "fuchsia"))]
50#[doc(hidden)]
51#[cold]
52#[inline(never)]
53pub unsafe fn invalid_cli_args_error() -> int {
54 #[cfg_attr(all(windows, target_env="msvc"), link(name="legacy_stdio_definitions", kind="dylib"))]
55 extern "C" {
56 pub fn printf(format: *const i8, ...) -> int;
57 }
58
59 printf(c_lit!("Unable to use non-utf8 arguments\n").as_ptr() as _);
60 1
61}
62
63#[cfg(not(any(windows, unix, target_env = "wasi", target_os = "wasi", target_os = "vxworks", target_os = "fuchsia")))]
64#[doc(hidden)]
65#[cold]
66#[inline(never)]
67pub unsafe fn invalid_cli_args_error() -> int {
68 panic!("Unable to use non-utf8 arguments");
69}
70
71#[macro_export]
73macro_rules! c_lit {
74 ($e:expr) => {
75 core::concat!($e, "\0")
76 };
77 ($($e:tt)+) => {
78 core::concat!($($e)+, "\0")
79 };
80}
81
82#[macro_export]
118macro_rules! c_main {
119 ($runner:ident) => {
120 use $crate::int;
121 $crate::c_main!($runner -> int);
122 };
123 ($runner:ident -> $int:ident) => {
124 #[no_mangle]
125 pub unsafe extern fn main(argc: $int, argv: *const *const u8) -> $int {
126 match $crate::Args::new(argc as isize, argv) {
127 Ok(args) => $runner(args).into(),
128 Err(_) => $crate::invalid_cli_args_error(),
129 }
130 }
131 }
132}