mirror of
https://github.com/Noratrieb/libuwuc.git
synced 2026-01-14 11:45:05 +01:00
start strtok
This commit is contained in:
parent
4d4af78afe
commit
dfdf45b5c7
17 changed files with 158 additions and 76 deletions
|
|
@ -1,17 +1,17 @@
|
|||
use core::{ffi::CStr, ptr::NonNull};
|
||||
|
||||
use crate::{println, utils::SharedThinCstr};
|
||||
use crate::{println, utils::CStrRef};
|
||||
|
||||
mod global {
|
||||
use core::{cell::UnsafeCell, ptr::NonNull};
|
||||
|
||||
use crate::utils::{SharedThinCstr, SyncUnsafeCell};
|
||||
use crate::utils::{CStrRef, SyncUnsafeCell};
|
||||
|
||||
use super::EnvP;
|
||||
|
||||
static ENVP: SyncUnsafeCell<EnvP> = SyncUnsafeCell(UnsafeCell::new(EnvP(None)));
|
||||
|
||||
pub(super) unsafe fn init(envp: *mut Option<SharedThinCstr<'static>>) {
|
||||
pub(super) unsafe fn init(envp: *mut Option<CStrRef<'static>>) {
|
||||
assert!((*ENVP.0.get()).0.is_none());
|
||||
*ENVP.0.get() = EnvP(Some(NonNull::new(envp).unwrap()));
|
||||
}
|
||||
|
|
@ -23,21 +23,21 @@ mod global {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn init(envp: *mut Option<SharedThinCstr<'static>>) {
|
||||
pub(crate) unsafe fn init(envp: *mut Option<CStrRef<'static>>) {
|
||||
global::init(envp);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct EnvP(Option<NonNull<Option<SharedThinCstr<'static>>>>);
|
||||
struct EnvP(Option<NonNull<Option<CStrRef<'static>>>>);
|
||||
|
||||
unsafe impl Sync for EnvP {}
|
||||
|
||||
impl Iterator for EnvP {
|
||||
type Item = SharedThinCstr<'static>;
|
||||
type Item = CStrRef<'static>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
let value: Option<SharedThinCstr<'static>> = self.0.unwrap().as_ptr().read();
|
||||
let value: Option<CStrRef<'static>> = self.0.unwrap().as_ptr().read();
|
||||
|
||||
value.map(|value| {
|
||||
self.0 = Some(NonNull::new_unchecked(self.0.unwrap().as_ptr().add(1)));
|
||||
|
|
@ -57,11 +57,11 @@ pub(crate) fn debug_env() {
|
|||
println!("end vars");
|
||||
}
|
||||
|
||||
pub fn getenv(name: SharedThinCstr<'_>) -> Option<SharedThinCstr<'static>> {
|
||||
pub fn getenv(name: CStrRef<'_>) -> Option<CStrRef<'static>> {
|
||||
getenv_inner(global::get(), name)
|
||||
}
|
||||
|
||||
fn getenv_inner(mut envp: EnvP, name: SharedThinCstr<'_>) -> Option<SharedThinCstr<'static>> {
|
||||
fn getenv_inner(mut envp: EnvP, name: CStrRef<'_>) -> Option<CStrRef<'static>> {
|
||||
let mut eq_idx = 0;
|
||||
envp.find(|env| {
|
||||
// Find ENV
|
||||
|
|
@ -99,7 +99,7 @@ mod tests {
|
|||
use std::string::ToString;
|
||||
use std::{ffi::CString, vec::Vec};
|
||||
|
||||
use crate::utils::{cstr, SharedThinCstr};
|
||||
use crate::utils::{cstr, CStrRef};
|
||||
|
||||
use super::EnvP;
|
||||
|
||||
|
|
@ -109,9 +109,9 @@ mod tests {
|
|||
.map(|s| CString::new(s.to_string()).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut envs: Vec<Option<SharedThinCstr<'static>>> = cstrs
|
||||
let mut envs: Vec<Option<CStrRef<'static>>> = cstrs
|
||||
.iter()
|
||||
.map(|cstr| unsafe { Some(SharedThinCstr::from_raw(cstr.as_ptr() as _)) })
|
||||
.map(|cstr| unsafe { Some(CStrRef::from_raw(cstr.as_ptr() as _)) })
|
||||
.collect();
|
||||
envs.push(None);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use core::ffi::{c_int, c_long};
|
||||
|
||||
use crate::{error::Error, utils::SharedThinCstr};
|
||||
use crate::{error::Error, utils::CStrRef};
|
||||
|
||||
pub fn parse_long<'a>(
|
||||
str: SharedThinCstr<'a>,
|
||||
endptr: Option<&mut Option<SharedThinCstr<'a>>>,
|
||||
str: CStrRef<'a>,
|
||||
endptr: Option<&mut Option<CStrRef<'a>>>,
|
||||
base: c_int,
|
||||
) -> Result<c_long, Error> {
|
||||
if base != 10 {
|
||||
|
|
@ -83,9 +83,9 @@ pub fn parse_long<'a>(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{cstr, utils::SharedThinCstr};
|
||||
use crate::{cstr, utils::CStrRef};
|
||||
|
||||
fn test_strtol(str: SharedThinCstr<'_>, expected: i64, base: i32, parsed_len: usize) {
|
||||
fn test_strtol(str: CStrRef<'_>, expected: i64, base: i32, parsed_len: usize) {
|
||||
let mut end = None;
|
||||
let result = super::parse_long(str, Some(&mut end), base).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use core::ffi::VaList;
|
||||
|
||||
use crate::{io::IoWrite, utils::SharedThinCstr, error::Error};
|
||||
use crate::{io::IoWrite, utils::CStrRef, error::Error};
|
||||
|
||||
pub unsafe fn printf_generic(
|
||||
mut sink: impl IoWrite,
|
||||
format: SharedThinCstr<'_>,
|
||||
format: CStrRef<'_>,
|
||||
mut args: VaList<'_, '_>,
|
||||
) -> Result<(), Error> {
|
||||
let mut chars = format.into_iter();
|
||||
|
|
@ -47,11 +47,11 @@ mod tests {
|
|||
use std::string::String;
|
||||
use std::vec::Vec;
|
||||
|
||||
use crate::utils::{cstr, SharedThinCstr};
|
||||
use crate::utils::{cstr, CStrRef};
|
||||
|
||||
use super::printf_generic;
|
||||
|
||||
unsafe extern "C" fn test_printf(expected: &str, fmt: SharedThinCstr<'_>, mut args: ...) {
|
||||
unsafe extern "C" fn test_printf(expected: &str, fmt: CStrRef<'_>, mut args: ...) {
|
||||
let mut sink = Vec::new();
|
||||
|
||||
printf_generic(&mut sink, fmt, args.as_va_list()).unwrap();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
use crate::{
|
||||
error::{Error, SyscallResultExt},
|
||||
utils::SharedThinCstr,
|
||||
utils::CStrRef,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
pub struct Fd(pub i32);
|
||||
|
||||
pub fn open(arg: SharedThinCstr<'_>, flags: i32) -> Result<Fd, Error> {
|
||||
pub fn open(arg: CStrRef<'_>, flags: i32) -> Result<Fd, Error> {
|
||||
sys_open(arg, flags)
|
||||
}
|
||||
|
||||
pub fn sys_open(arg: SharedThinCstr<'_>, flags: i32) -> Result<Fd, Error> {
|
||||
pub fn sys_open(arg: CStrRef<'_>, flags: i32) -> Result<Fd, Error> {
|
||||
unsafe {
|
||||
crate::syscall::syscall!(crate::syscall::SYS_OPEN, arg.as_raw(), flags).syscall_resultify()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{io::fd, utils::SharedThinCstr};
|
||||
use crate::{io::fd, utils::CStrRef};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum OpenMode {
|
||||
|
|
@ -22,7 +22,7 @@ impl OpenMode {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(str: SharedThinCstr<'_>) -> Result<OpenMode, &'static str> {
|
||||
pub fn parse(str: CStrRef<'_>) -> Result<OpenMode, &'static str> {
|
||||
let mut buf = [0; 2];
|
||||
let mut i = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
alloc,
|
||||
error::Error,
|
||||
io::{fd, stream::file::OpenMode},
|
||||
utils::SharedThinCstr,
|
||||
utils::CStrRef,
|
||||
};
|
||||
|
||||
use super::{fd::Fd, IoWrite, EOF};
|
||||
|
|
@ -32,8 +32,8 @@ impl IoWrite for &FileStream {
|
|||
}
|
||||
|
||||
pub unsafe fn fopen<'a>(
|
||||
pathname: SharedThinCstr<'_>,
|
||||
mode: SharedThinCstr<'_>,
|
||||
pathname: CStrRef<'_>,
|
||||
mode: CStrRef<'_>,
|
||||
) -> Result<&'a FileStream, Error> {
|
||||
let Ok(mode) = OpenMode::parse(mode) else {
|
||||
return Err(Error::INVAL);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ pub mod io;
|
|||
pub mod mem;
|
||||
pub mod misc;
|
||||
pub mod start;
|
||||
pub mod string;
|
||||
mod stubs;
|
||||
mod sys;
|
||||
pub mod utils;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::utils::SharedThinCstr;
|
||||
use crate::utils::CStrRef;
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn memset(ptr: *mut u8, constant: u8, len: usize) {
|
||||
|
|
@ -59,13 +59,13 @@ pub unsafe fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn strcmp(s1: SharedThinCstr<'_>, s2: SharedThinCstr<'_>) -> i32 {
|
||||
pub unsafe fn strcmp(s1: CStrRef<'_>, s2: CStrRef<'_>) -> i32 {
|
||||
s1.into_iter().cmp(s2) as i8 as i32
|
||||
}
|
||||
|
||||
// This technically violates the safety precondition of SharedThinCstr but that's fine, we're careful.
|
||||
#[inline]
|
||||
pub unsafe fn strncmp(s1: SharedThinCstr<'_>, s2: SharedThinCstr<'_>, size: usize) -> i32 {
|
||||
pub unsafe fn strncmp(s1: CStrRef<'_>, s2: CStrRef<'_>, size: usize) -> i32 {
|
||||
s1.into_iter().take(size).cmp(s2.into_iter().take(size)) as i8 as i32
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ pub unsafe fn strlen(mut s: *const u8) -> usize {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{cstr, utils::SharedThinCstr};
|
||||
use crate::{cstr, utils::CStrRef};
|
||||
|
||||
#[test]
|
||||
fn memcpy_null() {
|
||||
|
|
@ -270,8 +270,8 @@ mod tests {
|
|||
#[test]
|
||||
fn strncmp_no_null_term() {
|
||||
// Note: this is violating the safety invariant of SharedThinCstr but thats fine, we're careful.
|
||||
let a = unsafe { SharedThinCstr::from_raw(b"0000".as_ptr()) };
|
||||
let b = unsafe { SharedThinCstr::from_raw(b"0001".as_ptr()) };
|
||||
let a = unsafe { CStrRef::from_raw(b"0000".as_ptr()) };
|
||||
let b = unsafe { CStrRef::from_raw(b"0001".as_ptr()) };
|
||||
let result = unsafe { super::strncmp(a, b, 4) };
|
||||
assert_eq!(result, -1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use crate::utils::SharedThinCstr;
|
||||
use crate::utils::CStrRef;
|
||||
use core::fmt::Write;
|
||||
|
||||
pub fn assert_failed(
|
||||
assertion: SharedThinCstr<'_>,
|
||||
file: SharedThinCstr<'_>,
|
||||
assertion: CStrRef<'_>,
|
||||
file: CStrRef<'_>,
|
||||
line: u32,
|
||||
_function: Option<SharedThinCstr<'_>>,
|
||||
_function: Option<CStrRef<'_>>,
|
||||
) -> ! {
|
||||
let _ = writeln!(
|
||||
crate::io::Printer(crate::io::STDERR),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use core::ffi::{c_char, c_int};
|
||||
|
||||
use crate::utils::SharedThinCstr;
|
||||
use crate::utils::CStrRef;
|
||||
|
||||
/// The entrypoint of the program.
|
||||
/// This is called by a bit of assembly handling architecture-specific _start.
|
||||
pub(crate) unsafe extern "C" fn start(rsp: u64) -> ! {
|
||||
let argc = (rsp as *const u64).read();
|
||||
let argv = (rsp + 8) as *const *const c_char;
|
||||
let envp = (8 + 8 * argc + rsp + 8) as *mut Option<SharedThinCstr<'static>>;
|
||||
let envp = (8 + 8 * argc + rsp + 8) as *mut Option<CStrRef<'static>>;
|
||||
|
||||
crate::env::init(envp);
|
||||
|
||||
|
|
|
|||
59
libuwuc/src/string.rs
Normal file
59
libuwuc/src/string.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use crate::utils::CStrRef;
|
||||
|
||||
pub unsafe fn strtok(str: *mut u8, delim: CStrRef<'_>, saveptr: *mut *mut u8) -> *const u8 {
|
||||
if !str.is_null() {
|
||||
saveptr.write(str);
|
||||
}
|
||||
let start = saveptr.read();
|
||||
|
||||
let mut end = saveptr.read();
|
||||
while end.read() != 0 || !delim.into_iter().any(|c| c == end.read()) {
|
||||
end = end.add(1);
|
||||
}
|
||||
|
||||
end.write(0);
|
||||
|
||||
if start == end {
|
||||
core::ptr::null()
|
||||
} else {
|
||||
start
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate std;
|
||||
use std::borrow::ToOwned;
|
||||
use std::vec::Vec;
|
||||
|
||||
use crate::{cstr, utils::CStrRef};
|
||||
|
||||
fn test_strtok(string: &str, delim: CStrRef<'_>, expected: &[CStrRef<'_>]) {
|
||||
unsafe {
|
||||
let mut str = string.to_owned().into_bytes();
|
||||
str.push(0);
|
||||
|
||||
let mut saveptr = core::ptr::null_mut();
|
||||
|
||||
let mut out = Vec::new();
|
||||
loop {
|
||||
let s = super::strtok(str.as_mut_ptr(), delim, &mut saveptr);
|
||||
if s.is_null() {
|
||||
break;
|
||||
}
|
||||
out.push(CStrRef::from_raw(s));
|
||||
}
|
||||
|
||||
assert_eq!(out, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strtok_manpage_example() {
|
||||
test_strtok(
|
||||
"a/bbb///cc;xxxx:yyy:",
|
||||
cstr!(":;"),
|
||||
&[cstr!("a/bbbb///cc"), cstr!("xxx"), cstr!("yyy")],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,13 @@ use core::{cell::UnsafeCell, ffi::CStr, fmt::Debug, marker::PhantomData, ptr::No
|
|||
|
||||
#[repr(transparent)]
|
||||
#[derive(Default)]
|
||||
pub(crate) struct SyncUnsafeCell<T>(pub(crate) UnsafeCell<T>);
|
||||
pub struct SyncUnsafeCell<T>(pub UnsafeCell<T>);
|
||||
|
||||
unsafe impl<T: Sync> Sync for SyncUnsafeCell<T> {}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
pub struct SharedThinCstr<'a>(NonNull<u8>, PhantomData<&'a CStr>);
|
||||
pub struct CStrRef<'a>(NonNull<u8>, PhantomData<&'a CStr>);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cstr {
|
||||
|
|
@ -16,14 +16,14 @@ macro_rules! cstr {
|
|||
let s = concat!($value, "\0");
|
||||
#[allow(unused_unsafe)]
|
||||
unsafe {
|
||||
$crate::utils::SharedThinCstr::from_raw(s.as_ptr().cast())
|
||||
$crate::utils::CStrRef::from_raw(s.as_ptr().cast())
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub use cstr;
|
||||
|
||||
impl<'a> SharedThinCstr<'a> {
|
||||
impl<'a> CStrRef<'a> {
|
||||
pub unsafe fn from_raw(ptr: *const u8) -> Self {
|
||||
Self(NonNull::new_unchecked(ptr as *mut u8), PhantomData)
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ impl<'a> SharedThinCstr<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for SharedThinCstr<'a> {
|
||||
impl<'a> IntoIterator for CStrRef<'a> {
|
||||
type Item = u8;
|
||||
|
||||
type IntoIter = CStrIter<'a>;
|
||||
|
|
@ -60,7 +60,7 @@ impl<'a> IntoIterator for SharedThinCstr<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CStrIter<'a>(SharedThinCstr<'a>);
|
||||
pub struct CStrIter<'a>(CStrRef<'a>);
|
||||
|
||||
impl<'a> Iterator for CStrIter<'a> {
|
||||
type Item = u8;
|
||||
|
|
@ -78,10 +78,10 @@ impl<'a> Iterator for CStrIter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> Send for SharedThinCstr<'a> {}
|
||||
unsafe impl<'a> Sync for SharedThinCstr<'a> {}
|
||||
unsafe impl<'a> Send for CStrRef<'a> {}
|
||||
unsafe impl<'a> Sync for CStrRef<'a> {}
|
||||
|
||||
impl<'a> Debug for SharedThinCstr<'a> {
|
||||
impl<'a> Debug for CStrRef<'a> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let str = <&CStr>::from(*self).to_str();
|
||||
match str {
|
||||
|
|
@ -91,22 +91,22 @@ impl<'a> Debug for SharedThinCstr<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<SharedThinCstr<'a>> for &'a CStr {
|
||||
fn from(value: SharedThinCstr<'a>) -> Self {
|
||||
impl<'a> From<CStrRef<'a>> for &'a CStr {
|
||||
fn from(value: CStrRef<'a>) -> Self {
|
||||
unsafe { CStr::from_ptr(value.0.as_ptr().cast()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq for SharedThinCstr<'a> {
|
||||
impl<'a> PartialEq for CStrRef<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.into_iter().eq(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Eq for SharedThinCstr<'a> {}
|
||||
impl<'a> Eq for CStrRef<'a> {}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct SyncPtr<T>(pub(crate) *mut T);
|
||||
pub struct SyncPtr<T>(pub *mut T);
|
||||
|
||||
unsafe impl<T> Send for SyncPtr<T> {}
|
||||
unsafe impl<T> Sync for SyncPtr<T> {}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use libuwuc::{error::IntoOkOrErrno, utils::SharedThinCstr, io::fd::Fd};
|
||||
use libuwuc::{error::IntoOkOrErrno, utils::CStrRef, io::fd::Fd};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn open(path: SharedThinCstr<'_>, flags: i32) -> Fd {
|
||||
pub unsafe extern "C" fn open(path: CStrRef<'_>, flags: i32) -> Fd {
|
||||
libuwuc::io::fd::open(path, flags).into_ok_or_errno()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use core::ffi::c_uint;
|
||||
|
||||
use libuwuc::utils::SharedThinCstr;
|
||||
use libuwuc::utils::CStrRef;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __stack_chk_fail() -> ! {
|
||||
|
|
@ -23,9 +23,9 @@ pub unsafe extern "C" fn __assert_fail(
|
|||
function: *const u8,
|
||||
) -> ! {
|
||||
libuwuc::misc::assert_failed(
|
||||
SharedThinCstr::from_raw(assertion),
|
||||
SharedThinCstr::from_raw(file),
|
||||
CStrRef::from_raw(assertion),
|
||||
CStrRef::from_raw(file),
|
||||
line,
|
||||
SharedThinCstr::from_nullable(function),
|
||||
CStrRef::from_nullable(function),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use core::ffi::{c_char, c_int};
|
|||
use libuwuc::{
|
||||
error::IntoOkOrErrno,
|
||||
io::{stream::FileStream, traits::WriteCounter, STDERR, STDIN, STDOUT},
|
||||
utils::SharedThinCstr,
|
||||
utils::CStrRef,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
|
|
@ -24,7 +24,7 @@ pub unsafe extern "C" fn __printf_chk(_flag: c_int, format: *const u8, mut args:
|
|||
|
||||
let result = libuwuc::fmt::printf::printf_generic(
|
||||
&mut sink,
|
||||
SharedThinCstr::from_raw(format),
|
||||
CStrRef::from_raw(format),
|
||||
args.as_va_list(),
|
||||
);
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ pub unsafe extern "C" fn printf(format: *const u8, mut args: ...) -> c_int {
|
|||
|
||||
let result = libuwuc::fmt::printf::printf_generic(
|
||||
&mut sink,
|
||||
SharedThinCstr::from_raw(format),
|
||||
CStrRef::from_raw(format),
|
||||
args.as_va_list(),
|
||||
);
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ pub unsafe extern "C" fn __fprintf_chk(
|
|||
|
||||
let result = libuwuc::fmt::printf::printf_generic(
|
||||
&mut sink,
|
||||
SharedThinCstr::from_raw(format),
|
||||
CStrRef::from_raw(format),
|
||||
args.as_va_list(),
|
||||
);
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ pub unsafe extern "C" fn fprintf(file: &FileStream, format: *const u8, mut args:
|
|||
|
||||
let result = libuwuc::fmt::printf::printf_generic(
|
||||
&mut sink,
|
||||
SharedThinCstr::from_raw(format),
|
||||
CStrRef::from_raw(format),
|
||||
args.as_va_list(),
|
||||
);
|
||||
|
||||
|
|
@ -86,8 +86,8 @@ pub static stderr: &FileStream = &FileStream::from_raw_fd(STDERR);
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fopen<'a>(
|
||||
pathname: SharedThinCstr<'_>,
|
||||
mode: SharedThinCstr<'_>,
|
||||
pathname: CStrRef<'_>,
|
||||
mode: CStrRef<'_>,
|
||||
) -> Option<&'a FileStream> {
|
||||
libuwuc::io::stream::fopen(pathname, mode)
|
||||
.map_err(|err| libuwuc::error::set_errno(err.0))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use core::ffi::{c_int, c_long};
|
||||
|
||||
use libuwuc::{error::IntoOkOrErrno, utils::SharedThinCstr};
|
||||
use libuwuc::{error::IntoOkOrErrno, utils::CStrRef};
|
||||
|
||||
// Allocation functions
|
||||
|
||||
|
|
@ -35,10 +35,10 @@ pub unsafe extern "C" fn reallocarray(ptr: *mut u8, nmemb: usize, size: usize) -
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strtol(nptr: *const u8, endptr: *mut *const u8, base: c_int) -> c_long {
|
||||
let str = SharedThinCstr::from_raw(nptr);
|
||||
let str = CStrRef::from_raw(nptr);
|
||||
libuwuc::fmt::parse::parse_long(
|
||||
str,
|
||||
core::mem::transmute::<*mut *const u8, Option<&mut Option<SharedThinCstr<'_>>>>(endptr),
|
||||
core::mem::transmute::<*mut *const u8, Option<&mut Option<CStrRef<'_>>>>(endptr),
|
||||
base,
|
||||
)
|
||||
.into_ok_or_errno()
|
||||
|
|
@ -53,8 +53,8 @@ pub unsafe extern "C" fn strtoll(nptr: *const u8, endptr: *mut *const u8, base:
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn getenv(name: *const u8) -> *const u8 {
|
||||
libuwuc::env::getenv(SharedThinCstr::from_raw(name))
|
||||
.map(SharedThinCstr::as_raw)
|
||||
libuwuc::env::getenv(CStrRef::from_raw(name))
|
||||
.map(CStrRef::as_raw)
|
||||
.unwrap_or(core::ptr::null())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
use libuwuc::{error::Error, utils::SharedThinCstr};
|
||||
use core::cell::UnsafeCell;
|
||||
|
||||
use libuwuc::{
|
||||
error::Error,
|
||||
utils::{CStrRef, SyncPtr, SyncUnsafeCell},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memset(ptr: *mut u8, constant: u8, len: usize) {
|
||||
|
|
@ -26,13 +31,13 @@ pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, size: usize) -> i32
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strcmp(s1: SharedThinCstr<'_>, s2: SharedThinCstr<'_>) -> i32 {
|
||||
pub unsafe extern "C" fn strcmp(s1: CStrRef<'_>, s2: CStrRef<'_>) -> i32 {
|
||||
libuwuc::mem::strcmp(s1, s2)
|
||||
}
|
||||
|
||||
// This technically violates the safety precondition of SharedThinCstr but that's fine, we're careful.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strncmp(s1: SharedThinCstr<'_>, s2: SharedThinCstr<'_>, n: usize) -> i32 {
|
||||
pub unsafe extern "C" fn strncmp(s1: CStrRef<'_>, s2: CStrRef<'_>, n: usize) -> i32 {
|
||||
libuwuc::mem::strncmp(s1, s2, n)
|
||||
}
|
||||
|
||||
|
|
@ -47,3 +52,20 @@ pub unsafe extern "C" fn strerror(errnum: Error) -> *const u8 {
|
|||
.map(str::as_ptr)
|
||||
.unwrap_or(core::ptr::null())
|
||||
}
|
||||
|
||||
static STRTOK_GLOBAL: SyncUnsafeCell<SyncPtr<u8>> =
|
||||
SyncUnsafeCell(UnsafeCell::new(SyncPtr(core::ptr::null_mut())));
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strtok(str: *mut u8, delim: *const u8) -> *const u8 {
|
||||
strtok_r(str, delim, STRTOK_GLOBAL.0.get().cast::<*const u8>())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strtok_r<'a>(
|
||||
str: *mut u8,
|
||||
delim: *const u8,
|
||||
saveptr: *mut *const u8,
|
||||
) -> *const u8 {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue