#![no_std]
#[macro_export]
macro_rules! ctor_decl {
($($tt: tt)*) => {
#[cfg(not(any(target_os = "linux", target_os = "android",
target_os = "freebsd", target_os = "netbsd",
target_os = "openbsd", target_os = "dragonfly",
target_os = "illumos", target_os = "haiku",
target_os = "windows",
target_os = "macos", target_os = "ios")))]
compile_error!("ctor don't support the current target_os");
#[cfg_attr(
any(target_os = "linux", target_os = "android",
target_os = "freebsd", target_os = "netbsd",
target_os = "openbsd", target_os = "dragonfly",
target_os = "illumos", target_os = "haiku"),
link_section = ".init_array")]
#[cfg_attr(
any(target_os = "macos", target_os = "ios"),
link_section = "__DATA,__mod_init_func")]
#[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
$($tt)*
}
}
#[macro_export]
macro_rules! dtor_decl {
($($tt: tt)*) => {
#[cfg(not(any(target_os = "linux", target_os = "android",
target_os = "freebsd", target_os = "netbsd",
target_os = "openbsd", target_os = "dragonfly",
target_os = "illumos", target_os = "haiku",
target_os = "macos", target_os = "ios")))]
compile_error!("dtor don't support the current target_os");
#[cfg_attr(
any(target_os = "linux", target_os = "android",
target_os = "freebsd", target_os = "netbsd",
target_os = "openbsd", target_os = "dragonfly",
target_os = "illumos", target_os = "haiku"),
link_section = ".fini_array")]
#[cfg_attr(
any(target_os = "macos", target_os = "ios"),
link_section = "__DATA,__mod_term_func")]
$($tt)*
}
}
#[macro_export]
macro_rules! ctor {
($init: ident) => {
$crate::ctor!($init, $init);
};
($mod_name: ident, $init: ident) => {
mod $mod_name {
$crate::ctor_decl!{
#[used]
static INIT: unsafe fn() = super::$init;
}
}
};
}
#[macro_export]
macro_rules! ctor_args {
($init: ident) => {
$crate::ctor_args!($init, $init);
};
($mod_name: ident, $init: ident) => {
mod $mod_name {
$crate::ctor_decl!{
#[used]
static INIT: unsafe extern "C" fn(i32, *const *const i8) = super::$init;
}
}
};
}
#[macro_export]
macro_rules! ctor_custom {
($init: ident) => {
$crate::ctor_custom!($init, $init);
};
($mod_name: ident, $init: ident) => {
mod $mod_name {
#[repr(transparent)]
struct InitFunc {
init: *const (),
}
unsafe impl Sync for InitFunc {}
$crate::ctor_decl!{
#[used]
static INIT: InitFunc = InitFunc { init: super::$init as *const (), };
}
}
};
}
#[macro_export]
macro_rules! dtor {
($fini: ident) => {
$crate::dtor!($fini, $fini);
};
($mod_name: ident, $fini: ident) => {
mod $mod_name {
use super::$fini;
$crate::dtor_decl!{
#[used]
static FINI: unsafe fn() = $fini;
}
}
};
}
static mut ARGS: Option<&'static [*const i8]> = None;
unsafe extern "C" fn init_args(argc: i32, argv: *const *const i8) {
let args = core::slice::from_raw_parts(argv, argc as usize);
ARGS = Some(args);
}
ctor_args!(init_args);
#[inline(always)]
pub fn args() -> &'static [*const i8] {
unsafe { ARGS.unwrap() }
}
pub fn program_invocation_name() -> &'static str {
let args = args();
let name = args[0];
let mut n = 0;
loop {
let c = unsafe { name.add(n).read() };
if c == 0 {
let bytes = unsafe { core::slice::from_raw_parts(args[0].cast::<u8>(), n) };
return unsafe { core::str::from_utf8_unchecked(bytes) };
}
n += 1;
}
}
pub fn program_invocation_short_name() -> &'static str {
let name = program_invocation_name().as_bytes();
let name = name.rsplit(|b| *b == b'/' || *b == b'\\').next().unwrap();
unsafe { core::str::from_utf8_unchecked(name) }
}