use crate::hostcall::{self, HostFd};
use core::fmt;
use core::sync::atomic::{AtomicUsize, Ordering};
struct HostWrite(HostFd);
pub const TRACE: bool = false;
static mut PRINT_INHIBITOR: AtomicUsize = AtomicUsize::new(1);
#[inline]
pub fn enable_printing() {
unsafe { PRINT_INHIBITOR.store(0, Ordering::Release) }
}
#[inline]
pub fn is_printing_enabled() -> bool {
unsafe { PRINT_INHIBITOR.load(Ordering::Acquire) == 0 }
}
pub struct PrintBarrier;
impl Default for PrintBarrier {
fn default() -> Self {
unsafe {
PRINT_INHIBITOR.fetch_add(1, Ordering::Release);
}
Self
}
}
impl Drop for PrintBarrier {
fn drop(&mut self) {
unsafe {
PRINT_INHIBITOR.fetch_sub(1, Ordering::Release);
}
}
}
impl fmt::Write for HostWrite {
#[inline(always)]
fn write_str(&mut self, s: &str) -> fmt::Result {
hostcall::shim_write_all(self.0, s.as_bytes()).map_err(|_| fmt::Error)?;
Ok(())
}
}
#[doc(hidden)]
#[inline(always)]
pub fn _print(args: fmt::Arguments) {
use fmt::Write;
if !is_printing_enabled() {
return;
}
HostWrite(unsafe { HostFd::from_raw_fd(libc::STDOUT_FILENO) })
.write_fmt(args)
.expect("Printing via Host fd 1 failed");
}
#[doc(hidden)]
#[inline(always)]
pub fn _eprint(args: fmt::Arguments) {
use fmt::Write;
if !is_printing_enabled() {
return;
}
HostWrite(unsafe { HostFd::from_raw_fd(libc::STDERR_FILENO) })
.write_fmt(args)
.expect("Printing via Host fd 2 failed");
}
#[macro_export]
macro_rules! print {
($($arg:tt)*) => {
if $crate::print::TRACE { $crate::print::_print(format_args!($($arg)*)); }
};
}
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($fmt:expr) => ($crate::print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => ($crate::print!(concat!($fmt, "\n"), $($arg)*));
}
#[macro_export]
macro_rules! eprint {
($($arg:tt)*) => {
if $crate::print::TRACE { $crate::print::_eprint(format_args!($($arg)*)) };
};
}
#[macro_export]
macro_rules! eprintln {
() => ($crate::eprint!("\n"));
($fmt:expr) => ($crate::eprint!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => ($crate::eprint!(concat!($fmt, "\n"), $($arg)*));
}
#[macro_export]
macro_rules! dbg {
() => {
$crate::eprintln!("[{}:{}]", file!(), line!());
};
($val:expr $(,)?) => {
match $val {
tmp => {
$crate::eprintln!("[{}:{}] {} = {:#?}",
file!(), line!(), stringify!($val), &tmp);
tmp
}
}
};
($($val:expr),+ $(,)?) => {
($($crate::dbg!($val)),+,)
};
}