Skip to content

Commit

Permalink
Move syslog out of common, implement %ll{u,d} (#317)
Browse files Browse the repository at this point in the history
* Move syslog out of common

* Handle escaped percent sign (%%)

* Handle long longs
  • Loading branch information
bugadani authored Oct 31, 2023
1 parent c4ad329 commit 34b8181
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 185 deletions.
3 changes: 2 additions & 1 deletion esp-wifi/src/common_adapter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::binary::include::esp_timer_get_time;
use crate::binary::include::esp_timer_handle_t;

use crate::compat::common::*;
use crate::compat::syslog::syslog;
use crate::compat::timer_compat::*;

use crate::hal;
Expand Down Expand Up @@ -222,7 +223,7 @@ pub unsafe extern "C" fn sprintf(dst: *mut u8, format: *const u8, args: ...) ->
let str = str_from_c(format);
trace!("sprintf format: {}", str);

let len = crate::compat::common::vsnprintf(dst, 512, format, args);
let len = crate::compat::syslog::vsnprintf(dst, 512, format, args);

let s = str_from_c(dst);
trace!("sprintf result: {}", s);
Expand Down
183 changes: 0 additions & 183 deletions esp-wifi/src/compat/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,194 +37,11 @@ static mut MUTEX_IDX_CURRENT: usize = 0;
static mut FAKE_WIFI_QUEUE: &SimpleQueue<[u8; 8], 200> = unsafe { &REAL_WIFI_QUEUE };
static mut REAL_WIFI_QUEUE: SimpleQueue<[u8; 8], 200> = SimpleQueue::new(); // first there is a ptr to the real queue - driver checks it's not null

pub struct StrWriter {
dst: *mut u8,
capacity: usize,
len: usize,
}

impl StrWriter {
pub fn new(dst: *mut u8, capacity: usize) -> Self {
Self {
dst,
capacity,
len: 0,
}
}

pub fn len(&self) -> usize {
self.len
}

fn space(&self) -> usize {
self.capacity - self.len
}

fn write(&mut self, byte: u8) {
unsafe {
self.dst.write(byte);
self.dst = self.dst.add(1);
}
}

pub fn append_char(&mut self, c: char) {
let mut buf = [0u8; 4];
let char = c.encode_utf8(&mut buf);
self.append(char);
}

pub fn append(&mut self, s: &str) {
// Write as many bytes as possible. We're writing a c string which means we don't have
// to deal with utf8 character boundaries, so this should be fine.
let len = s.len().min(self.space());
for byte in &s.as_bytes()[..len] {
self.write(*byte);
}

// vsnprintf's semantics: it counts unwritten bytes, too
self.len += s.len();
}

pub fn append_byte(&mut self, b: u8) {
if self.space() >= 1 {
self.write(b);
}

// vsnprintf's semantics: it counts unwritten bytes, too
self.len += 1;
}
}

impl Write for StrWriter {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
self.append(s);
Ok(())
}
}

pub unsafe fn str_from_c<'a>(s: *const u8) -> &'a str {
let c_str = core::ffi::CStr::from_ptr(s.cast());
core::str::from_utf8_unchecked(c_str.to_bytes())
}

pub unsafe extern "C" fn syslog(_priority: u32, format: *const u8, mut args: VaListImpl) {
#[cfg(feature = "wifi-logs")]
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "riscv32", all(target_arch = "xtensa", xtensa_has_vaarg)))]
{
let mut buf = [0u8; 512];
vsnprintf(&mut buf as *mut u8, 512, format, args);
let res_str = str_from_c(&buf as *const u8);
info!("{}", res_str);
}
else
{
let res_str = str_from_c(format);
info!("{}", res_str);
}
}
}

/// Returns the number of character that would have been written if the buffer was big enough.
pub(crate) unsafe fn vsnprintf(
dst: *mut u8,
capacity: u32,
format: *const u8,
mut args: VaListImpl,
) -> i32 {
let mut res_str = StrWriter::new(dst, capacity as usize - 1);

let s = str_from_c(format);

let mut format_char = ' ';
let mut is_long = false;
let mut found = false;
for c in s.chars().into_iter() {
if !found {
if c == '%' {
found = true;
}

if !found {
res_str.append_char(c);
}
} else {
if c.is_numeric() || c == '-' || c == 'l' {
if c == 'l' {
is_long = true;
}
// ignore
} else {
// a format char
format_char = c;
}
}

if found && format_char != ' ' {
// have to format an arg
match format_char {
'd' => {
// FIXME: This is sus - both branches have the same impl
if is_long {
let v = args.arg::<i32>();
write!(res_str, "{}", v).ok();
} else {
let v = args.arg::<i32>();
write!(res_str, "{}", v).ok();
}
}

'u' => {
let v = args.arg::<u32>();
write!(res_str, "{}", v).ok();
}

'p' => {
let v = args.arg::<u32>();
write!(res_str, "0x{:x}", v).ok();
}

'X' => {
let v = args.arg::<u32>();
write!(res_str, "{:02x}", (v & 0xff000000) >> 24).ok();
}

'x' => {
let v = args.arg::<u32>();
write!(res_str, "{:02x}", v).ok();
}

's' => {
let v = args.arg::<u32>() as *const u8;
let vbuf = str_from_c(v);
res_str.append(vbuf);
}

'c' => {
let v = args.arg::<u8>();
if v != 0 {
res_str.append_byte(v);
}
}

_ => {
write!(res_str, "<UNKNOWN{}>", format_char).ok();
}
}

format_char = ' ';
found = false;
is_long = false;
}
}

let chars_written = res_str.len();
let terminating_at = chars_written.min(capacity as usize - 1);
dst.add(terminating_at).write(0);

chars_written as i32
}

#[no_mangle]
unsafe extern "C" fn strnlen(chars: *const u8, maxlen: usize) -> usize {
let mut len = 0;
Expand Down
1 change: 1 addition & 0 deletions esp-wifi/src/compat/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod common;
pub mod malloc;
pub mod syslog;
pub mod task_runner;
pub mod timer_compat;

Expand Down
Loading

0 comments on commit 34b8181

Please sign in to comment.