Lots of changes

This commit is contained in:
Matthias Schiffer 2020-04-04 01:47:30 +02:00
parent 9aae18d764
commit 52b4984945
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
6 changed files with 135 additions and 50 deletions

8
Cargo.lock generated
View file

@ -2,15 +2,13 @@
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.60" version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
[[package]] [[package]]
name = "neco" name = "neco"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc",
] ]
[metadata]
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"

View file

@ -5,7 +5,7 @@ authors = ["Matthias Schiffer <mschiffer@universe-factory.net>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
libc = { version = "0.2.54", default-features = false } libc = { version = "0.2.68", default-features = false }
[profile.dev] [profile.dev]
panic = "abort" panic = "abort"

View file

@ -1,8 +1,7 @@
extern "C" { extern "C" {
pub fn strndup(cs: *const libc::c_char, n: libc::size_t) -> *mut libc::c_char; pub fn strndup(cs: *const libc::c_char, n: libc::size_t) -> *mut libc::c_char;
pub static mut stdin: *mut libc::FILE; // pub static stdin: *mut libc::FILE;
pub static mut stdout: *mut libc::FILE; pub static stdout: *mut libc::FILE;
pub static mut stderr: *mut libc::FILE; pub static stderr: *mut libc::FILE;
} }

View file

@ -7,8 +7,12 @@ pub struct OStream {
file: *mut libc::FILE file: *mut libc::FILE
} }
pub fn stdout() -> OStream { pub unsafe fn stdout() -> OStream {
OStream { file: unsafe { posix::stdout } } OStream { file: posix::stdout }
}
pub unsafe fn stderr() -> OStream {
OStream { file: posix::stderr }
} }
impl OStream { impl OStream {

View file

@ -3,18 +3,20 @@ use core::{mem, ptr, slice};
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
fn must_succeed<T>(p: *mut T) -> *mut T { fn must_succeed<T>(p: *mut T) -> *mut T {
if p.is_null() { assert!(!p.is_null(), "allocation failure");
panic!("allocation failure");
}
p p
} }
fn malloc<T>() -> *mut T { fn zst<T>(count: usize) -> bool {
let size = mem::size_of::<T>(); mem::size_of::<T>() == 0 || count == 0
let align = mem::align_of::<T>(); }
if size == 0 {
return align as *mut T; fn alloc<T>(count: usize) -> *mut T {
if zst::<T>(count) {
return ptr::null_mut();
} }
let size = count * mem::size_of::<T>();
let align = mem::align_of::<T>();
must_succeed( must_succeed(
unsafe { unsafe {
libc::memalign(align as libc::size_t, size as libc::size_t) as *mut T libc::memalign(align as libc::size_t, size as libc::size_t) as *mut T
@ -22,18 +24,23 @@ fn malloc<T>() -> *mut T {
) )
} }
pub struct CBox<T>(*mut T); fn dangling<T>() -> *mut T {
mem::align_of::<T>() as *mut T
}
impl<T> CBox<T> { fn check_ptr<T>(p: *const T, len: usize) {
pub fn new(value: T) -> CBox<T> { debug_assert!((p as usize) % mem::align_of::<T>() == 0, "unaligned ptr");
let p = malloc(); assert!(zst::<T>(len) || !p.is_null(), "NULL ptr");
unsafe { }
ptr::write(p, value);
CBox::from_raw(p)
}
}
pub const unsafe fn from_raw(p: *mut T) -> CBox<T> { fn slice_len<T>(p: *const [T]) -> usize {
unsafe { mem::transmute::<*const [T], [usize; 2]>(p)[1] }
}
pub struct CBox<T: ?Sized>(*mut T);
impl<T: ?Sized> CBox<T> {
pub unsafe fn from_raw_unchecked(p: *mut T) -> CBox<T> {
CBox(p) CBox(p)
} }
@ -43,7 +50,7 @@ impl<T> CBox<T> {
p p
} }
pub const fn as_ptr(&self) -> *const T { pub fn as_ptr(&self) -> *const T {
self.0 self.0
} }
@ -52,14 +59,57 @@ impl<T> CBox<T> {
} }
} }
impl<T> Drop for CBox<T> { impl<T> CBox<T> {
fn drop(&mut self) { pub fn new(value: T) -> CBox<T> {
unsafe { ptr::drop_in_place(self.0); } let p = alloc(1);
if mem::size_of::<T>() != 0 {
unsafe { unsafe {
libc::free(self.0 as *mut libc::c_void); ptr::write(p, value);
CBox::from_raw_unchecked(p)
} }
} }
pub unsafe fn from_raw(p: *mut T) -> CBox<T> {
check_ptr(p, 1);
CBox(p)
}
pub unsafe fn slice_from_raw_parts_unchecked(p: *mut T, len: usize) -> CBox<[T]> {
CBox(ptr::slice_from_raw_parts_mut(p, len))
}
pub unsafe fn slice_from_raw_parts(p: *mut T, len: usize) -> CBox<[T]> {
check_ptr(p, len);
CBox::slice_from_raw_parts_unchecked(p, len)
}
fn safe_ptr(&self) -> *mut T {
if self.0.is_null() {
debug_assert!(zst::<T>(1), "NULL ptr");
return dangling();
}
self.0
}
}
impl<T> CBox<[T]> {
fn safe_ptr(&self) -> *mut [T] {
if self.0.is_null() {
let len = slice_len(self.0);
debug_assert!(zst::<T>(len), "NULL ptr");
return ptr::slice_from_raw_parts_mut(dangling(), len);
}
self.0
}
}
impl<T: ?Sized> Drop for CBox<T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(self.0);
libc::free(self.0 as *mut libc::c_void);
}
} }
} }
@ -67,13 +117,27 @@ impl<T> Deref for CBox<T> {
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
unsafe { &*self.0 } unsafe { &*self.safe_ptr() }
} }
} }
impl<T> DerefMut for CBox<T> { impl<T> DerefMut for CBox<T> {
fn deref_mut(&mut self) -> &mut T { fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.0 } unsafe { &mut *self.safe_ptr() }
}
}
impl<T> Deref for CBox<[T]> {
type Target = [T];
fn deref(&self) -> &[T] {
unsafe { &*self.safe_ptr() }
}
}
impl<T> DerefMut for CBox<[T]> {
fn deref_mut(&mut self) -> &mut [T] {
unsafe { &mut *self.safe_ptr() }
} }
} }
@ -82,16 +146,26 @@ impl<T> DerefMut for CBox<T> {
pub struct CStr { inner: libc::c_char } pub struct CStr { inner: libc::c_char }
impl CStr { impl CStr {
pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr { pub unsafe fn from_ptr_unchecked<'a>(p: *const libc::c_char) -> &'a CStr {
&*(p as *const CStr) &*(p as *const CStr)
} }
pub unsafe fn from_ptr_mut<'a>(p: *mut libc::c_char) -> &'a mut CStr { pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr {
check_ptr(p, 1);
CStr::from_ptr_unchecked(p)
}
pub unsafe fn from_mut_ptr_unchecked<'a>(p: *mut libc::c_char) -> &'a mut CStr {
&mut *(p as *mut CStr) &mut *(p as *mut CStr)
} }
pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr {
check_ptr(p, 1);
CStr::from_mut_ptr_unchecked(p)
}
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
CStr::from_ptr(bytes.as_ptr() as *const libc::c_char) CStr::from_ptr_unchecked(bytes.as_ptr() as *const libc::c_char)
} }
// TODO // TODO
@ -117,7 +191,7 @@ impl CStr {
) } ) }
} }
pub fn as_bytes_mut(&mut self) -> &mut [u8] { pub fn as_mut_bytes(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut( unsafe { slice::from_raw_parts_mut(
self.as_mut_ptr() as *mut u8, self.as_mut_ptr() as *mut u8,
self.len(), self.len(),
@ -139,6 +213,10 @@ macro_rules! cstr {
pub struct CString { inner: CBox<libc::c_char> } pub struct CString { inner: CBox<libc::c_char> }
impl CString { impl CString {
pub unsafe fn from_raw_unchecked(p: *mut libc::c_char) -> CString {
CString { inner: CBox::from_raw_unchecked(p) }
}
pub unsafe fn from_raw(p: *mut libc::c_char) -> CString { pub unsafe fn from_raw(p: *mut libc::c_char) -> CString {
CString { inner: CBox::from_raw(p) } CString { inner: CBox::from_raw(p) }
} }
@ -158,14 +236,14 @@ impl Deref for CString {
impl DerefMut for CString { impl DerefMut for CString {
fn deref_mut(&mut self) -> &mut CStr { fn deref_mut(&mut self) -> &mut CStr {
unsafe { CStr::from_ptr_mut(&mut *self.inner) } unsafe { CStr::from_mut_ptr(&mut *self.inner) }
} }
} }
impl From<&[u8]> for CString { impl From<&[u8]> for CString {
fn from(s: &[u8]) -> CString { fn from(s: &[u8]) -> CString {
unsafe { unsafe {
CString::from_raw(must_succeed(posix::strndup( CString::from_raw_unchecked(must_succeed(posix::strndup(
s.as_ptr() as *const libc::c_char, s.as_ptr() as *const libc::c_char,
s.len() as libc::size_t, s.len() as libc::size_t,
))) )))
@ -182,7 +260,7 @@ impl From<&str> for CString {
impl From<&CStr> for CString { impl From<&CStr> for CString {
fn from(s: &CStr) -> CString { fn from(s: &CStr) -> CString {
unsafe { unsafe {
CString::from_raw(must_succeed(libc::strdup(s.as_ptr()))) CString::from_raw_unchecked(must_succeed(libc::strdup(s.as_ptr())))
} }
} }
} }

View file

@ -9,16 +9,22 @@ use core::fmt::Write;
#[no_mangle] #[no_mangle]
pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) -> libc::c_int { pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) -> libc::c_int {
let mut stdout = unsafe { c::stdio::stdout() };
let x = c::string::CString::from("foo"); let x = c::string::CString::from("foo");
let y = c::string::CBox::new(x); let l = x.len();
let y = x.into_raw();
let z = unsafe {
c::string::CBox::slice_from_raw_parts(y, l)
};
//let y = unsafe { c::string::CBox::from_raw(x) };
//let foo = cstr!("Foo! %p\n"); //let foo = cstr!("Foo! %p\n");
//c::stdio::stdout().puts(foo); //c::stdio::stdout().puts(foo);
let mut stdout = c::stdio::stdout(); let _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]);
writeln!(stdout, "Foo: {}", 42);
0 0
} }
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(info: &core::panic::PanicInfo) -> ! {
let _ = writeln!(unsafe { c::stdio::stderr() }, "Panic: {}", info);
unsafe { libc::abort() } unsafe { libc::abort() }
} }