diff --git a/Cargo.lock b/Cargo.lock index c7af9f99..e81a6f12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,12 +196,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" [[package]] name = "cfg-if" @@ -501,6 +498,7 @@ dependencies = [ "bincode", "bstr", "byteorder", + "cc", "chrono", "clap", "clap_complete", diff --git a/Cargo.toml b/Cargo.toml index 3e9b10b7..0f21b60f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ repc = "0.1.1" anyhow = "1.0.79" bstr = { version = "1.9.0", default-features = false, features = ["std"] } shaderc = "0.8.3" +cc = "1.0.86" #[profile.dev.build-override] #opt-level = 3 diff --git a/build/build.rs b/build/build.rs index 85580ae8..8c86deb9 100644 --- a/build/build.rs +++ b/build/build.rs @@ -24,6 +24,7 @@ use std::{ mod egl; mod enums; +mod logging; mod tokens; mod vulkan; mod wire; @@ -49,6 +50,7 @@ fn main() -> anyhow::Result<()> { enums::main()?; egl::main()?; vulkan::main()?; + logging::main()?; println!("cargo:rerun-if-changed=build/build.rs"); Ok(()) diff --git a/build/logging.rs b/build/logging.rs new file mode 100644 index 00000000..4b228d1e --- /dev/null +++ b/build/logging.rs @@ -0,0 +1,5 @@ +pub fn main() -> anyhow::Result<()> { + println!("cargo:rerun-if-changed=src/bridge.c"); + cc::Build::new().file("src/bridge.c").compile("bridge"); + Ok(()) +} diff --git a/src/bridge.c b/src/bridge.c new file mode 100644 index 00000000..15390afc --- /dev/null +++ b/src/bridge.c @@ -0,0 +1,49 @@ +#define _GNU_SOURCE + +#include +#include +#include + +static char *fmt(const char *format, va_list args) { + char *line; + int ret = vasprintf(&line, format, args); + if (ret < 0) { + return 0; + } else { + return line; + } +} + +void jay_libinput_log_handler( + void *libinput, + int priority, + const char *line +); + +void jay_libinput_log_handler_bridge( + void *libinput, + int priority, + const char *format, + va_list args +) { + char *line = fmt(format, args); + jay_libinput_log_handler(libinput, priority, line); + free(line); +} + +void jay_xkbcommon_log_handler( + void *ctx, + int xkb_log_level, + const char *line +); + +void jay_xkbcommon_log_handler_bridge( + void *ctx, + int xkb_log_level, + const char *format, + va_list args +) { + char *line = fmt(format, args); + jay_xkbcommon_log_handler(ctx, xkb_log_level, line); + free(line); +} diff --git a/src/libinput.rs b/src/libinput.rs index fc637456..1723d3db 100644 --- a/src/libinput.rs +++ b/src/libinput.rs @@ -22,16 +22,11 @@ use { }, }, udev::UdevError, - utils::{ - errorfmt::ErrorFmt, oserror::OsError, ptr_ext::PtrExt, trim::AsciiTrim, - vasprintf::vasprintf_, - }, + utils::{errorfmt::ErrorFmt, oserror::OsError, ptr_ext::PtrExt, trim::AsciiTrim}, }, bstr::ByteSlice, - std::{ - ffi::{CStr, VaList}, - rc::Rc, - }, + isnt::std_1::primitive::IsntConstPtrExt, + std::{ffi::CStr, rc::Rc}, thiserror::Error, uapi::{c, Errno, IntoUstr, OwnedFd}, }; @@ -91,6 +86,10 @@ pub struct LibInput { li: *mut libinput, } +extern "C" { + fn jay_libinput_log_handler_bridge(); +} + impl LibInput { pub fn new(adapter: Rc) -> Result { let mut ud = Box::new(UserData { adapter }); @@ -101,7 +100,7 @@ impl LibInput { return Err(LibInputError::New); } unsafe { - libinput_log_set_handler(li, log_handler); + libinput_log_set_handler(li, jay_libinput_log_handler_bridge); let priority = if log::log_enabled!(log::Level::Debug) { LIBINPUT_LOG_PRIORITY_DEBUG } else if log::log_enabled!(log::Level::Info) { @@ -167,19 +166,14 @@ impl Drop for LibInput { } } -unsafe extern "C" fn log_handler( +#[no_mangle] +unsafe extern "C" fn jay_libinput_log_handler( _libinput: *mut libinput, priority: libinput_log_priority, - format: *const c::c_char, - args: VaList, + line: *const c::c_char, ) { - let str = match vasprintf_(format, args) { - Some(s) => s, - _ => { - log::error!("Could not format log message"); - return; - } - }; + assert!(line.is_not_null()); + let str = CStr::from_ptr(line); let priority = match LogPriority(priority as _) { LIBINPUT_LOG_PRIORITY_DEBUG => log::Level::Debug, LIBINPUT_LOG_PRIORITY_INFO => log::Level::Info, diff --git a/src/libinput/sys.rs b/src/libinput/sys.rs index e3308fdb..acd9dc7b 100644 --- a/src/libinput/sys.rs +++ b/src/libinput/sys.rs @@ -1,13 +1,8 @@ -use {std::ffi::VaList, uapi::c}; +use uapi::c; include!(concat!(env!("OUT_DIR"), "/libinput_tys.rs")); -pub type libinput_log_handler = unsafe extern "C" fn( - libinput: *mut libinput, - priority: libinput_log_priority, - format: *const c::c_char, - args: VaList, -); +pub type libinput_log_handler = unsafe extern "C" fn(); #[repr(transparent)] pub struct libinput(u8); diff --git a/src/main.rs b/src/main.rs index 097432d9..e22cbc93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,3 @@ -#![feature( - c_variadic, // https://github.com/rust-lang/rust/issues/44930 -)] #![allow( clippy::len_zero, clippy::needless_lifetimes, diff --git a/src/utils.rs b/src/utils.rs index c345a3a3..13a84df6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -39,7 +39,6 @@ pub mod toplevel_identifier; pub mod tri; pub mod trim; pub mod unlink_on_drop; -pub mod vasprintf; pub mod vec_ext; pub mod vecstorage; pub mod windows; diff --git a/src/utils/vasprintf.rs b/src/utils/vasprintf.rs deleted file mode 100644 index e7a0dac1..00000000 --- a/src/utils/vasprintf.rs +++ /dev/null @@ -1,42 +0,0 @@ -use { - std::{ - ffi::{CStr, VaList}, - ops::Deref, - ptr, - }, - uapi::c, -}; - -extern "C" { - fn vasprintf(strp: *mut *mut c::c_char, fmt: *const c::c_char, ap: VaList) -> c::c_int; -} - -pub struct OwnedCStr { - val: &'static CStr, -} - -impl Deref for OwnedCStr { - type Target = CStr; - - fn deref(&self) -> &Self::Target { - self.val - } -} - -impl Drop for OwnedCStr { - fn drop(&mut self) { - unsafe { - c::free(self.val.as_ptr() as _); - } - } -} - -pub unsafe fn vasprintf_(fmt: *const c::c_char, ap: VaList) -> Option { - let mut res = ptr::null_mut(); - if vasprintf(&mut res, fmt, ap) == -1 { - return None; - } - Some(OwnedCStr { - val: CStr::from_ptr(res), - }) -} diff --git a/src/xkbcommon.rs b/src/xkbcommon.rs index 9088ee5a..0fba7212 100644 --- a/src/xkbcommon.rs +++ b/src/xkbcommon.rs @@ -7,13 +7,8 @@ include!(concat!(env!("OUT_DIR"), "/xkbcommon_tys.rs")); pub use consts::*; use { bstr::{BStr, ByteSlice}, - std::{ - ffi::{CStr, VaList}, - io::Write, - ops::Deref, - ptr, - rc::Rc, - }, + isnt::std_1::primitive::IsntConstPtrExt, + std::{ffi::CStr, io::Write, ops::Deref, ptr, rc::Rc}, }; use { @@ -69,15 +64,7 @@ extern "C" { fn xkb_context_new(flags: xkb_context_flags) -> *mut xkb_context; fn xkb_context_unref(context: *mut xkb_context); fn xkb_context_set_log_verbosity(context: *mut xkb_context, verbosity: c::c_int); - fn xkb_context_set_log_fn( - context: *mut xkb_context, - log_fn: unsafe extern "C" fn( - context: *mut xkb_context, - level: xkb_log_level, - format: *const c::c_char, - args: VaList, - ), - ); + fn xkb_context_set_log_fn(context: *mut xkb_context, log_fn: unsafe extern "C" fn()); fn xkb_keymap_new_from_buffer( context: *mut xkb_context, buffer: *const u8, @@ -116,6 +103,10 @@ pub struct XkbContext { context: *mut xkb_context, } +extern "C" { + fn jay_xkbcommon_log_handler_bridge(); +} + impl XkbContext { pub fn new() -> Result { let res = unsafe { xkb_context_new(XKB_CONTEXT_NO_FLAGS.raw() as _) }; @@ -124,7 +115,7 @@ impl XkbContext { } unsafe { xkb_context_set_log_verbosity(res, 10); - xkb_context_set_log_fn(res, xkbcommon_logger); + xkb_context_set_log_fn(res, jay_xkbcommon_log_handler_bridge); } Ok(Self { context: res }) } @@ -303,22 +294,14 @@ impl Drop for XkbState { } } -unsafe extern "C" fn xkbcommon_logger( +#[no_mangle] +unsafe extern "C" fn jay_xkbcommon_log_handler( _ctx: *mut xkb_context, level: xkb_log_level, - format: *const c::c_char, - args: VaList, + line: *const c::c_char, ) { - extern "C" { - fn vasprintf(buf: *mut *mut c::c_char, fmt: *const c::c_char, args: VaList) -> c::c_int; - } - let mut buf = ptr::null_mut(); - let res = vasprintf(&mut buf, format, args); - if res < 0 { - log::error!("Could not vasprintf"); - return; - } - let buf = std::slice::from_raw_parts(buf as *const u8, res as usize); + assert!(line.is_not_null()); + let buf = CStr::from_ptr(line); let level = match XkbLogLevel(level) { XKB_LOG_LEVEL_CRITICAL | XKB_LOG_LEVEL_ERROR => log::Level::Error, XKB_LOG_LEVEL_WARNING => log::Level::Warn, @@ -326,5 +309,5 @@ unsafe extern "C" fn xkbcommon_logger( XKB_LOG_LEVEL_DEBUG => log::Level::Debug, _ => log::Level::Error, }; - log::log!(level, "xkbcommon: {}", buf.trim_end().as_bstr()); + log::log!(level, "xkbcommon: {}", buf.to_bytes().trim_end().as_bstr()); }