mod args; mod errors; pub use args::Args; pub use errors::*; use crate::{ exit, EX_USAGE, }; use libc::{ c_int, strlen, }; use libc_print::libc_eprintln; ///Converts C string to Rust's, verifying it is UTF-8 /// ///It is UB to pass non-C string as it requires \0 pub unsafe fn c_str_to_rust( ptr: *const u8 ) -> Result<&'static str, core::str::Utf8Error> { let len = strlen(ptr as *const i8); let parts = core::slice::from_raw_parts(ptr, len); core::str::from_utf8(parts) } ///Converts C string to Rust's one assuming it is UTF-8 /// ///It is UB to pass non-C string as it requires \0 pub unsafe fn c_str_to_rust_unchecked(ptr: *const u8) -> &'static str { let len = strlen(ptr as *const i8); let parts = core::slice::from_raw_parts(ptr, len); core::str::from_utf8_unchecked(parts) } extern "Rust" { fn rust_main(args: args::Args) -> Result; } #[doc(hidden)] #[cfg(not(test))] #[no_mangle] pub unsafe extern fn main(argc: c_int, argv: *const *const u8) -> c_int { match Args::new(argc as isize, argv) { Ok(args) => { let argv0 = &args .into_iter() .next() .unwrap_or_else(|| { libc_eprintln!("Unable to ascertain argv[0]."); exit(71); }); rust_main(args).unwrap_or_else(|err| { if err.code == EX_USAGE { libc_eprintln!("Usage: {} {}", argv0, err.message); } else { libc_eprintln!("{}: {}", argv0, err.message); } err.code }) as _ }, Err(_) => { libc_eprintln!("Arguments are not valid UTF-8."); 65 }, } }