mirror of
https://github.com/XunilGroup/libxunil.git
synced 2026-04-25 11:39:02 +02:00
Upload current libxunil, to be used as a submodule
This commit is contained in:
662
src/lib.rs
Normal file
662
src/lib.rs
Normal file
@@ -0,0 +1,662 @@
|
||||
#![no_std]
|
||||
#![feature(c_variadic)]
|
||||
use core::{
|
||||
ffi::VaList,
|
||||
fmt::{Error, Result, Write},
|
||||
ptr::{addr_of_mut, null, null_mut},
|
||||
usize,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
mem::{malloc, memcpy},
|
||||
syscall::{DRAW_BUFFER, DRAW_PIXEL, EXIT, FRAMEBUFFER_SWAP, WRITE, syscall0, syscall3},
|
||||
};
|
||||
|
||||
pub mod file;
|
||||
pub mod heap;
|
||||
pub mod mem;
|
||||
pub mod syscall;
|
||||
pub mod time;
|
||||
pub mod util;
|
||||
|
||||
static mut ERRNO: core::ffi::c_int = 0;
|
||||
|
||||
static TOUPPER_TABLE: [i32; 384] = {
|
||||
let mut table = [0i32; 384];
|
||||
let mut i = 0usize;
|
||||
while i < 384 {
|
||||
let c = i.wrapping_sub(128) as u8;
|
||||
table[i] = if c.is_ascii_lowercase() {
|
||||
(c - 0x20) as i32
|
||||
} else {
|
||||
c as i32
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
table
|
||||
};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn write(fd: i32, buf: *const u8, count: usize) -> isize {
|
||||
unsafe { syscall3(WRITE, fd as isize, buf as isize, count as isize) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn exit(code: i32) -> ! {
|
||||
unsafe { syscall3(EXIT, code as isize, 0, 0) };
|
||||
loop {
|
||||
unsafe { core::arch::asm!("nop") };
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn strlen(s: *const u8) -> usize {
|
||||
let mut len = 0usize;
|
||||
while unsafe { *s.add(len) } != 0 {
|
||||
len += 1;
|
||||
}
|
||||
len
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn puts(s: *const u8) -> i32 {
|
||||
write(1, s, strlen(s));
|
||||
write(1, b"\n\0".as_ptr(), 1);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn putchar(c: i32) -> i32 {
|
||||
let b = c as u8;
|
||||
write(1, core::ptr::addr_of!(b), 1);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn abs(n: i32) -> i32 {
|
||||
n.abs()
|
||||
}
|
||||
|
||||
struct BufWriter {
|
||||
buf: *mut u8,
|
||||
max: usize,
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl Write for BufWriter {
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
for byte in s.bytes() {
|
||||
if self.pos >= self.max {
|
||||
return Err(Error);
|
||||
}
|
||||
unsafe {
|
||||
*self.buf.add(self.pos) = byte;
|
||||
}
|
||||
self.pos += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct StdoutWriter {
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl Write for StdoutWriter {
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
self.size += s.len();
|
||||
write(1, s.as_ptr(), s.len());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn write_c_formatted(fmt: *const u8, args: &mut VaList, writer: &mut impl Write) {
|
||||
let mut fi = 0usize;
|
||||
|
||||
loop {
|
||||
let ch = unsafe { *fmt.add(fi) };
|
||||
fi += 1;
|
||||
if ch == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
if ch != b'%' {
|
||||
let _ = writer.write_char(ch as char);
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut precision: Option<usize> = None;
|
||||
let mut next_byte = unsafe { *fmt.add(fi) };
|
||||
|
||||
if next_byte == b'.' {
|
||||
fi += 1;
|
||||
let mut p_val = 0usize;
|
||||
loop {
|
||||
let digit = unsafe { *fmt.add(fi) };
|
||||
if digit >= b'0' && digit <= b'9' {
|
||||
p_val = p_val * 10 + (digit - b'0') as usize;
|
||||
fi += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
precision = Some(p_val);
|
||||
next_byte = unsafe { *fmt.add(fi) };
|
||||
}
|
||||
|
||||
let spec = next_byte;
|
||||
fi += 1;
|
||||
|
||||
unsafe {
|
||||
match spec {
|
||||
b'd' | b'i' => {
|
||||
let v: i32 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:01$}", v, p);
|
||||
} else {
|
||||
let _ = write!(writer, "{}", v);
|
||||
}
|
||||
}
|
||||
b'u' => {
|
||||
let v: u32 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:01$}", v, p);
|
||||
} else {
|
||||
let _ = write!(writer, "{}", v);
|
||||
}
|
||||
}
|
||||
b'x' => {
|
||||
let v: u32 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:01$x}", v, p);
|
||||
} else {
|
||||
let _ = write!(writer, "{:x}", v);
|
||||
}
|
||||
}
|
||||
b'X' => {
|
||||
let v: u32 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:01$X}", v, p);
|
||||
} else {
|
||||
let _ = write!(writer, "{:X}", v);
|
||||
}
|
||||
}
|
||||
b'o' => {
|
||||
let v: u32 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:01$o}", v, p);
|
||||
} else {
|
||||
let _ = write!(writer, "{:o}", v);
|
||||
}
|
||||
}
|
||||
b'p' => {
|
||||
let v: *const u8 = args.arg();
|
||||
if v.is_null() {
|
||||
let _ = writer.write_str("(null)");
|
||||
} else {
|
||||
let _ = write!(writer, "0x{:x}", v as usize);
|
||||
}
|
||||
}
|
||||
b'c' => {
|
||||
let v: i32 = args.arg();
|
||||
let _ = writer.write_char((v as u8) as char);
|
||||
}
|
||||
b's' => {
|
||||
let ptr: *const u8 = args.arg();
|
||||
if ptr.is_null() {
|
||||
let _ = writer.write_str("(null)");
|
||||
} else {
|
||||
let mut si = 0usize;
|
||||
loop {
|
||||
let c = *ptr.add(si);
|
||||
if c == 0 {
|
||||
break;
|
||||
}
|
||||
if let Some(p) = precision {
|
||||
if si >= p {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let _ = writer.write_char(c as char);
|
||||
si += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
b'f' | b'F' | b'g' | b'G' => {
|
||||
let v: f64 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:.*}", p, v);
|
||||
} else {
|
||||
let _ = write!(writer, "{}", v);
|
||||
}
|
||||
}
|
||||
b'l' => {
|
||||
let next_spec = *fmt.add(fi);
|
||||
fi += 1;
|
||||
match next_spec {
|
||||
b'd' | b'i' => {
|
||||
let v: i64 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:01$}", v, p);
|
||||
} else {
|
||||
let _ = write!(writer, "{}", v);
|
||||
}
|
||||
}
|
||||
b'u' => {
|
||||
let v: u64 = args.arg();
|
||||
if let Some(p) = precision {
|
||||
let _ = write!(writer, "{:01$}", v, p);
|
||||
} else {
|
||||
let _ = write!(writer, "{}", v);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let _ = writer.write_char('%');
|
||||
let _ = writer.write_char('l');
|
||||
let _ = writer.write_char(next_spec as char);
|
||||
}
|
||||
}
|
||||
}
|
||||
b'%' => {
|
||||
let _ = writer.write_char('%');
|
||||
}
|
||||
_ => {
|
||||
let _ = writer.write_char('%');
|
||||
let _ = writer.write_char(spec as char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn printf(fmt: *const u8, mut args: ...) -> i32 {
|
||||
let mut writer = StdoutWriter { size: 0 };
|
||||
|
||||
unsafe { write_c_formatted(fmt, &mut args, &mut writer) };
|
||||
|
||||
writer.size as i32
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn vsnprintf(
|
||||
buf: *mut u8,
|
||||
size: usize,
|
||||
fmt: *const u8,
|
||||
mut args: VaList,
|
||||
) -> i32 {
|
||||
if buf.is_null() || size == 0 || fmt.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let max = size - 1;
|
||||
let mut writer = BufWriter { buf, max, pos: 0 };
|
||||
|
||||
unsafe { write_c_formatted(fmt, &mut args, &mut writer) };
|
||||
|
||||
unsafe {
|
||||
*buf.add(writer.pos) = 0;
|
||||
}
|
||||
|
||||
writer.pos as i32
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn snprintf(buf: *mut u8, size: usize, fmt: *const u8, mut args: ...) -> i32 {
|
||||
if buf.is_null() || size == 0 || fmt.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let max = size - 1;
|
||||
let mut writer = BufWriter { buf, max, pos: 0 };
|
||||
|
||||
unsafe { write_c_formatted(fmt, &mut args, &mut writer) };
|
||||
|
||||
unsafe {
|
||||
*buf.add(writer.pos) = 0;
|
||||
}
|
||||
|
||||
writer.pos as i32
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
fn main(argc: i32, argv: *const *const u8) -> i32;
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn __stack_chk_fail() -> ! {
|
||||
exit(127)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn __stack_chk_fail_local() -> ! {
|
||||
__stack_chk_fail()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
let code = unsafe { main(0, null()) };
|
||||
|
||||
exit(code as i32);
|
||||
}
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn atoi(mut c: *const u8) -> i32 {
|
||||
let mut value: i32 = 0;
|
||||
let mut sign: i32 = 1;
|
||||
unsafe {
|
||||
while (*c).is_ascii_whitespace() {
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
if (*c) == b'+' || (*c) == b'-' {
|
||||
if *c == b'-' {
|
||||
sign = -1;
|
||||
}
|
||||
c = c.add(1);
|
||||
}
|
||||
while (*c).is_ascii_digit() {
|
||||
value *= 10;
|
||||
value += ((*c) - b'0') as i32;
|
||||
c = c.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
value * sign
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pow10_i32(exp: i32) -> f64 {
|
||||
let mut e = exp;
|
||||
let mut scale: f64 = 1.0;
|
||||
|
||||
if e > 0 {
|
||||
while e > 0 {
|
||||
scale *= 10.0;
|
||||
e -= 1;
|
||||
}
|
||||
} else if e < 0 {
|
||||
while e < 0 {
|
||||
scale *= 0.1;
|
||||
e += 1;
|
||||
}
|
||||
}
|
||||
|
||||
scale
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn atof(mut c: *const u8) -> f64 {
|
||||
let mut sign: f64 = 1.0;
|
||||
unsafe {
|
||||
while (*c).is_ascii_whitespace() {
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
if (*c) == b'+' || (*c) == b'-' {
|
||||
if *c == b'-' {
|
||||
sign = -1.0;
|
||||
}
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
let mut int_part: i64 = 0;
|
||||
while (*c).is_ascii_digit() {
|
||||
int_part = int_part * 10 + ((*c) - b'0') as i64;
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
let mut result: f64 = int_part as f64;
|
||||
|
||||
if *c == b'.' {
|
||||
c = c.add(1);
|
||||
let mut factor = 0.1;
|
||||
while (*c).is_ascii_digit() {
|
||||
result += ((*c) - b'0') as f64 * factor;
|
||||
factor *= 0.1;
|
||||
c = c.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
if *c == b'e' || *c == b'E' {
|
||||
c = c.add(1);
|
||||
|
||||
let mut exp_sign = 1;
|
||||
let mut exp_value = 0;
|
||||
|
||||
if (*c) == b'+' || (*c) == b'-' {
|
||||
if *c == b'-' {
|
||||
exp_sign = -1;
|
||||
}
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
while (*c).is_ascii_digit() {
|
||||
exp_value *= 10;
|
||||
exp_value += ((*c) - b'0') as i64;
|
||||
c = c.add(1);
|
||||
}
|
||||
|
||||
result *= pow10_i32((exp_sign * exp_value) as i32);
|
||||
}
|
||||
|
||||
sign * result
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare_str(str_1: *const u8, str_2: *const u8, ignore_case: bool, n: usize) -> i32 {
|
||||
let mut len = 0;
|
||||
while len < n {
|
||||
let mut c_1 = unsafe { *str_1.add(len) };
|
||||
let mut c_2 = unsafe { *str_2.add(len) };
|
||||
if ignore_case {
|
||||
c_1 = c_1.to_ascii_lowercase();
|
||||
c_2 = c_2.to_ascii_lowercase();
|
||||
}
|
||||
if c_1 != c_2 {
|
||||
return (c_1 as i32) - (c_2 as i32);
|
||||
}
|
||||
if c_1 == 0 {
|
||||
return 0;
|
||||
}
|
||||
len += 1;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strcasecmp(str_1: *const u8, str_2: *const u8) -> i32 {
|
||||
compare_str(str_1, str_2, true, usize::MAX)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strcmp(str_1: *const u8, str_2: *const u8) -> i32 {
|
||||
compare_str(str_1, str_2, false, usize::MAX)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strncasecmp(str_1: *const u8, str_2: *const u8, n: usize) -> i32 {
|
||||
compare_str(str_1, str_2, true, n)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strncmp(str_1: *const u8, str_2: *const u8, n: usize) -> i32 {
|
||||
compare_str(str_1, str_2, false, n)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn draw_pixel(x: u32, y: u32, color: u32) -> i32 {
|
||||
unsafe {
|
||||
return syscall3(DRAW_PIXEL, x as isize, y as isize, color as isize) as i32;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn draw_buffer(buffer: *const u32, width: u32, height: u32) -> i32 {
|
||||
unsafe {
|
||||
return syscall3(
|
||||
DRAW_BUFFER,
|
||||
buffer as isize,
|
||||
width as isize,
|
||||
height as isize,
|
||||
) as i32;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn framebuffer_swap() -> i32 {
|
||||
unsafe {
|
||||
return syscall0(FRAMEBUFFER_SWAP) as i32;
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn strncpy(dest: *mut u8, source: *const u8, n: usize) -> *mut u8 {
|
||||
let mut i = 0usize;
|
||||
while i < n {
|
||||
let b = unsafe { *source.add(i) };
|
||||
unsafe { *dest.add(i) = b };
|
||||
|
||||
if b == 0 {
|
||||
let mut j = i + 1;
|
||||
while j < n {
|
||||
unsafe { *dest.add(j) = 0 };
|
||||
j += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
dest
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strdup(s: *const u8) -> *mut u8 {
|
||||
let len = strlen(s);
|
||||
let memory = malloc((len + 1) as u64);
|
||||
if memory.is_null() {
|
||||
return null_mut();
|
||||
}
|
||||
unsafe { memcpy(memory, s, len + 1) };
|
||||
memory
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *const u8 {
|
||||
if haystack.is_null() || needle.is_null() {
|
||||
return null();
|
||||
}
|
||||
|
||||
let mut h = haystack;
|
||||
|
||||
unsafe {
|
||||
if *needle == 0 {
|
||||
return haystack;
|
||||
}
|
||||
|
||||
while *h != 0 {
|
||||
if *h == *needle {
|
||||
let mut h2 = h;
|
||||
let mut n2 = needle;
|
||||
|
||||
while *n2 != 0 && *h2 != 0 && *h2 == *n2 {
|
||||
h2 = h2.add(1);
|
||||
n2 = n2.add(1);
|
||||
}
|
||||
|
||||
if *n2 == 0 {
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
h = h.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
null()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strchr(s: *const u8, ch: i32) -> *const u8 {
|
||||
if s.is_null() {
|
||||
return null();
|
||||
}
|
||||
|
||||
let mut i = 0usize;
|
||||
|
||||
unsafe {
|
||||
while *s.add(i) != 0 {
|
||||
if *s.add(i) == ch as u8 {
|
||||
return s.add(i);
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
null()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn strrchr(s: *const u8, ch: u8) -> *const u8 {
|
||||
let mut n = 0;
|
||||
let mut last: *const u8 = null();
|
||||
|
||||
if ch == 0 {
|
||||
while unsafe { *s.add(n) } != 0 {
|
||||
n += 1;
|
||||
}
|
||||
return unsafe { s.add(n + 1) };
|
||||
} else {
|
||||
while unsafe { *s.add(n) } != 0 {
|
||||
let cur_ch = unsafe { s.add(n) };
|
||||
if unsafe { *cur_ch == ch } {
|
||||
last = cur_ch;
|
||||
}
|
||||
n += 1;
|
||||
}
|
||||
|
||||
last
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn toupper(char: i32) -> i32 {
|
||||
(char as u8).to_ascii_uppercase() as i32
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn tolower(char: i32) -> i32 {
|
||||
(char as u8).to_ascii_lowercase() as i32
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn system(cmd: *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn __ctype_toupper_loc() -> *const u8 {
|
||||
TOUPPER_TABLE.as_ptr() as *const u8
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn __isoc23_sscanf() -> ! {
|
||||
panic!("sscanf not implemented");
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn sscanf(str: *mut u8, fmt: *const u8, args: ...) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn __errno_location() -> *mut core::ffi::c_int {
|
||||
addr_of_mut!(ERRNO)
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(error: &core::panic::PanicInfo) -> ! {
|
||||
exit(-1)
|
||||
}
|
||||
Reference in New Issue
Block a user