Add impl for asctime_r

This commit is contained in:
Steve Akinyemi 2018-12-11 17:05:07 +01:00
parent 2b81d88b58
commit 6f632e615f
2 changed files with 64 additions and 9 deletions

View File

@ -384,6 +384,11 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"_asctime", "_asctime",
ImportValue::Func(time::_asctime as _), ImportValue::Func(time::_asctime as _),
); );
import_object.set(
"env",
"_asctime_r",
ImportValue::Func(time::_asctime_r as _),
);
import_object.set( import_object.set(
"env", "env",
"_localtime", "_localtime",

View File

@ -90,7 +90,6 @@ pub extern "C" fn _asctime(time: u32, instance: &mut Instance) -> u32 {
let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
let months = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; let months = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
let year = 1900 + date.tm_year; let year = 1900 + date.tm_year;
let time_str = format!( let time_str = format!(
@ -105,11 +104,6 @@ pub extern "C" fn _asctime(time: u32, instance: &mut Instance) -> u32 {
year year
); );
// NOTE: asctime_r is specced to behave in an undefined manner if the algorithm would attempt
// to write out more than 26 bytes (including the null terminator).
// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html
// Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator.
let time_str_ptr = time_str[0..26].as_ptr() as _; let time_str_ptr = time_str[0..26].as_ptr() as _;
let time_str_offset = copy_cstr_into_wasm(instance, time_str_ptr); let time_str_offset = copy_cstr_into_wasm(instance, time_str_ptr);
@ -117,11 +111,66 @@ pub extern "C" fn _asctime(time: u32, instance: &mut Instance) -> u32 {
// use std::ffi::CStr; // use std::ffi::CStr;
// debug!("#### cstr = {:?}", CStr::from_ptr(c_str)); // debug!("#### cstr = {:?}", CStr::from_ptr(c_str));
// std::mem::forget(time_str);
time_str_offset time_str_offset
} }
} }
// TODO
// fn asctime_fmt() -> *const c_char {
// }
// MOVE to utils.rs
extern "C" fn write_to_buf(string: *const c_char, buf: u32, max: u32, instance: &mut Instance) -> u32 {
let buf_addr = instance.memory_offset_addr(0, buf as _) as *mut c_char;
unsafe {
for i in 0..max {
*buf_addr.add(i as _) = *string.add(i as _);
}
}
buf
}
/// emscripten: _asctime_r
pub extern "C" fn _asctime_r(time: u32, buf: u32, instance: &mut Instance) -> u32 {
debug!("emscripten::_asctime {}", time);
unsafe {
let date = &*(instance.memory_offset_addr(0, time as _) as *mut guest_tm);
let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
let months = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
let year = 1900 + date.tm_year;
let time_str = format!(
// NOTE: The 14 accompanying chars are needed for some reason
"{} {} {:2} {:02}:{:02}:{:02} {:4}\n\0\0\0\0\0\0\0\0\0\0\0\0\0",
days[date.tm_wday as usize],
months[date.tm_mon as usize],
date.tm_mday,
date.tm_hour,
date.tm_min,
date.tm_sec,
year
);
// NOTE: asctime_r is specced to behave in an undefined manner if the algorithm would attempt
// to write out more than 26 bytes (including the null terminator).
// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html
// Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator.
let time_str_ptr = time_str[0..26].as_ptr() as _;
write_to_buf(time_str_ptr, buf, 26, instance)
// let c_str = instance.memory_offset_addr(0, time_str_offset as _) as *mut i8;
// use std::ffi::CStr;
// debug!("#### cstr = {:?}", CStr::from_ptr(c_str));
}
}
/// emscripten: _tvset /// emscripten: _tvset
pub extern "C" fn _tvset() { pub extern "C" fn _tvset() {
debug!("emscripten::_tvset UNIMPLEMENTED"); debug!("emscripten::_tvset UNIMPLEMENTED");
@ -157,7 +206,7 @@ pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int {
(*tm_struct_ptr).tm_gmtoff = tm_struct.tm_gmtoff as i32; (*tm_struct_ptr).tm_gmtoff = tm_struct.tm_gmtoff as i32;
(*tm_struct_ptr).tm_zone = copy_cstr_into_wasm(instance, tm_struct.tm_zone) as i32; (*tm_struct_ptr).tm_zone = copy_cstr_into_wasm(instance, tm_struct.tm_zone) as i32;
tm_struct_offset as c_int tm_struct_offset as _
} }
} }
/// emscripten: _localtime_r /// emscripten: _localtime_r
@ -199,7 +248,8 @@ pub extern "C" fn _localtime_r(time_p: u32, result: u32, instance: &mut Instance
(*result_addr).tm_gmtoff = tm_struct.tm_gmtoff as _; (*result_addr).tm_gmtoff = tm_struct.tm_gmtoff as _;
(*result_addr).tm_zone = copy_cstr_into_wasm(instance, tm_struct.tm_zone) as _; (*result_addr).tm_zone = copy_cstr_into_wasm(instance, tm_struct.tm_zone) as _;
result as _ result;
0
} }
} }