//! This would've been called `io`, but rust-analyzer refuses to see //! the submodules of this module when it's named `io`. #![allow(unused_variables)] use core::{ ffi::{CStr, VaList, c_char, c_int, c_long, c_size_t, c_void}, ptr::null_mut, }; use alloc::string::String; use log::{info, warn}; use printf_compat::output::fmt_write; use crate::ffi::{ inout::file::{FILE, STDERR, STDOUT}, string::__xkbc_memcpy, }; pub mod dir; pub mod file; // File management #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE { warn!( "The xkbcommon library is attempting to open a file at path: {:?}", unsafe { CStr::from_ptr(filename) } ); null_mut() } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_fclose(file: *mut FILE) -> c_int { todo!() } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int { todo!() } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_ftell(stream: *mut FILE) -> c_long { todo!() } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_fread( ptr: *mut c_void, size: c_size_t, nobj: c_size_t, stream: *mut FILE, ) -> c_size_t { todo!() } #[unsafe(no_mangle)] unsafe extern "C" fn __xkbc_fputs(s: *const c_char, stream: *mut FILE) -> c_int { todo!() } // Printing #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_fprintf( stream: *mut FILE, format: *const c_char, mut args: ... ) -> c_int { unsafe { __xkbc_vfprintf(stream, format, args.as_va_list()) } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __spre_fprintf( stream: *mut FILE, format: *const c_char, mut args: ... ) -> c_int { unsafe { __xkbc_fprintf(stream, format) } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_vfprintf( stream: *mut FILE, format: *const c_char, ap: VaList, ) -> c_int { if stream == STDOUT || stream == STDERR { let string = ::alloc::format!( "vfprintf({:?}, {:?}, {:?})", stream, unsafe { CStr::from_ptr(format) }, ap ); info!("{}", string); string.len() as c_int } else { -1 } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_vasprintf( strp: *mut *mut c_char, fmt: *const c_char, ap: VaList, ) -> c_int { todo!() } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_snprintf( string: *mut c_char, size: c_size_t, format: *const c_char, mut args: ... ) -> c_int { unsafe { __xkbc_vsnprintf(string, size, format, args.as_va_list()) } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_vsnprintf( string: *mut c_char, // Length in bytes **including the terminating null byte**. size: c_size_t, format: *const c_char, ap: VaList, ) -> c_int { if size == 0 { return 0; } let mut rust_buffer = String::new(); unsafe { printf_compat::format(format, ap, fmt_write(&mut rust_buffer)); let string_length = core::cmp::min(rust_buffer.len(), size - 1); // __xkbc_strncpy would be preferrable, if it was available __xkbc_memcpy( string as *mut _, rust_buffer.as_ptr() as *mut _, string_length, ); *string.add(string_length) = 0; // Add terminating null byte. string_length as c_int } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __spre_sprintf( string: *mut c_char, format: *const c_char, mut args: ... ) -> c_int { unsafe { vsprintf(string, format, args.as_va_list()) } } pub unsafe fn vsprintf(string: *mut c_char, format: *const c_char, ap: VaList) -> c_int { let mut rust_buffer = String::new(); unsafe { printf_compat::format(format, ap, fmt_write(&mut rust_buffer)); // __xkbc_strncpy would be preferrable, if it was available __xkbc_memcpy( string as *mut _, rust_buffer.as_ptr() as *mut _, rust_buffer.len(), ); *string.add(rust_buffer.len()) = 0; // Add terminating null byte. rust_buffer.len() as c_int } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __spre_vsnprintf( string: *mut c_char, // Length in bytes **including the terminating null byte**. size: c_size_t, format: *const c_char, ap: VaList, ) -> c_int { unsafe { __xkbc_vsnprintf(string, size, format, ap) } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __spre_sscanf(s: *const c_char, format: *const c_char, ...) -> c_int { todo!() }