Use core::ffi::VaList

This commit is contained in:
Dan Robertson
2018-12-04 01:59:41 +00:00
committed by jD91mZM2
parent 29e1c780aa
commit fa94f1b6d5
8 changed files with 142 additions and 144 deletions
Generated
-15
View File
@@ -278,7 +278,6 @@ dependencies = [
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
"sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"va_list 0.1.0",
]
[[package]]
@@ -500,20 +499,6 @@ name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "va_list"
version = "0.1.0"
dependencies = [
"va_list-helper 0.0.2",
]
[[package]]
name = "va_list-helper"
version = "0.0.2"
dependencies = [
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "vec_map"
version = "0.8.1"
-1
View File
@@ -21,7 +21,6 @@ lazy_static = { version = "1.2.0", features = ["nightly", "spin_no_std"] }
memoffset = "0.3.0"
posix-regex = { path = "posix-regex", features = ["no_std"] }
rand = { version = "0.5.5", default-features = false }
va_list = { path = "va_list", features = ["no_std"] }
[dependencies.goblin]
version = "0.0.21"
+1 -1
View File
@@ -1,7 +1,7 @@
#!/bin/bash
set -ex
./fmt.sh -- --write-mode=diff
./fmt.sh -- --check
if [ -z "$TARGET" ]
then
make all
+1 -1
View File
@@ -6,7 +6,7 @@ use alloc::vec::Vec;
use core::fmt::Write as WriteFmt;
use core::ops::{Deref, DerefMut};
use core::{fmt, mem, ptr, slice, str};
use va_list::VaList as va_list;
use core::ffi::VaList as va_list;
use c_str::CStr;
use fs::File;
+129 -115
View File
@@ -3,11 +3,11 @@ use alloc::string::ToString;
use alloc::vec::Vec;
use core::ops::Range;
use core::{fmt, slice};
use core::ffi::VaList as va_list;
use io::{self, Write};
use platform;
use platform::types::*;
use va_list::{VaList, VaPrimitive};
#[derive(PartialEq, Eq)]
enum IntKind {
@@ -21,104 +21,108 @@ enum IntKind {
Size,
}
trait IntoUsize {
fn into_usize(self) -> usize;
fn from_usize(i: usize) -> Self;
}
macro_rules! impl_intousize {
($($kind:tt;)*) => {
$(impl IntoUsize for $kind {
fn into_usize(self) -> usize {
self as usize
}
fn from_usize(i: usize) -> Self {
i as Self
}
})*
}
}
impl_intousize! {
i32;
u32;
i64;
u64;
isize;
usize;
}
impl<T> IntoUsize for *const T {
fn into_usize(self) -> usize {
self as usize
}
fn from_usize(i: usize) -> Self {
i as Self
}
}
impl<T> IntoUsize for *mut T {
fn into_usize(self) -> usize {
self as usize
}
fn from_usize(i: usize) -> Self {
i as Self
}
}
impl IntoUsize for f32 {
fn into_usize(self) -> usize {
self.to_bits() as usize
}
fn from_usize(i: usize) -> Self {
Self::from_bits(i as u32)
}
}
impl IntoUsize for f64 {
fn into_usize(self) -> usize {
self.to_bits() as usize
}
fn from_usize(i: usize) -> Self {
Self::from_bits(i as u64)
}
enum ArgType {
Byte,
Short,
Int,
Long,
LongLong,
PtrDiff,
Size,
IntMax,
Double,
CharPtr,
VoidPtr,
IntPtr,
ArgDefault
}
struct BufferedVaList {
list: VaList,
buf: Vec<usize>,
#[derive(Clone, Copy)]
union VaArg {
byte: c_char,
short: c_short,
int: c_int,
long: c_long,
longlong: c_longlong,
ptrdiff: ptrdiff_t,
size: ssize_t,
intmax: intmax_t,
double: c_double,
char_ptr: *const c_char,
void_ptr: *const c_void,
int_ptr: *mut c_int,
arg_default: usize
}
struct BufferedVaList<'a> {
list: va_list<'a>,
buf: Vec<VaArg>,
i: usize,
}
impl BufferedVaList {
fn new(list: VaList) -> Self {
impl<'a> BufferedVaList<'a> {
fn new(list: va_list<'a>) -> Self {
Self {
list,
buf: Vec::new(),
i: 0,
}
}
unsafe fn get<T: VaPrimitive + IntoUsize>(&mut self, i: Option<usize>) -> T {
match i {
None => self.next(),
Some(i) => self.index(i),
unsafe fn get_arg(&mut self, ty: ArgType) -> VaArg {
match ty {
ArgType::Byte => VaArg { byte: self.list.arg::<c_char>() },
ArgType::Short => VaArg { short: self.list.arg::<c_short>() },
ArgType::Int => VaArg { int: self.list.arg::<c_int>() },
ArgType::Long => VaArg { long: self.list.arg::<c_long>() },
ArgType::LongLong => VaArg { longlong: self.list.arg::<c_longlong>() },
ArgType::PtrDiff => VaArg { ptrdiff: self.list.arg::<ptrdiff_t>() },
ArgType::Size => VaArg { size: self.list.arg::<ssize_t>() },
ArgType::IntMax => VaArg { intmax: self.list.arg::<intmax_t>() },
ArgType::Double => VaArg { double: self.list.arg::<c_double>() },
ArgType::CharPtr => VaArg { char_ptr: self.list.arg::<*const c_char>() },
ArgType::VoidPtr => VaArg { void_ptr: self.list.arg::<*const c_void>() },
ArgType::IntPtr => VaArg { int_ptr: self.list.arg::<*mut c_int>() },
ArgType::ArgDefault => VaArg { arg_default: self.list.arg::<usize>() }
}
}
unsafe fn next<T: VaPrimitive + IntoUsize>(&mut self) -> T {
if self.i >= self.buf.len() {
self.buf.push(self.list.get::<T>().into_usize());
unsafe fn get(&mut self, ty: ArgType, i: Option<usize>) -> VaArg {
match i {
None => self.next(ty),
Some(i) => self.index(ty, i),
}
let arg = T::from_usize(self.buf[self.i]);
}
unsafe fn next(&mut self, ty: ArgType) -> VaArg {
if self.i >= self.buf.len() {
let arg = self.get_arg(ty);
self.buf.push(arg);
}
let arg = self.buf[self.i];
self.i += 1;
arg
}
unsafe fn index<T: VaPrimitive + IntoUsize>(&mut self, i: usize) -> T {
while self.buf.len() < i {
// Getting a usize here most definitely isn't sane, however,
// there's no way to know the type!
// Just take this for example:
//
// printf("%*4$d\n", "hi", 0, "hello", 10);
//
// This chooses the width 10. How does it know the type of 0 and "hello"?
// It clearly can't.
self.buf.push(self.list.get::<usize>());
unsafe fn index(&mut self, ty: ArgType, i: usize) -> VaArg {
if self.i >= self.buf.len() {
while self.buf.len() < (i - 1) {
// Getting a usize here most definitely isn't sane, however,
// there's no way to know the type!
// Just take this for example:
//
// printf("%*4$d\n", "hi", 0, "hello", 10);
//
// This chooses the width 10. How does it know the type of 0 and "hello"?
// It clearly can't.
let arg = self.get_arg(ArgType::ArgDefault);
self.buf.push(arg);
}
let arg = self.get_arg(ty);
self.buf.push(arg);
}
T::from_usize(self.buf[i - 1])
self.buf[i - 1]
}
}
@@ -134,6 +138,7 @@ unsafe fn pop_int_raw(format: &mut *const u8) -> Option<usize> {
}
int
}
unsafe fn pop_int(format: &mut *const u8, ap: &mut BufferedVaList) -> Option<usize> {
if **format == b'*' {
*format = format.offset(1);
@@ -143,15 +148,16 @@ unsafe fn pop_int(format: &mut *const u8, ap: &mut BufferedVaList) -> Option<usi
if let Some(i) = pop_int_raw(&mut format2) {
if *format2 == b'$' {
*format = format2.offset(1);
return Some(ap.index::<usize>(i));
return Some(ap.index(ArgType::ArgDefault, i).arg_default);
}
}
Some(ap.next::<usize>())
Some(ap.next(ArgType::ArgDefault).arg_default)
} else {
pop_int_raw(format)
}
}
unsafe fn fmt_int<I>(fmt: u8, i: I) -> String
where
I: fmt::Display + fmt::Octal + fmt::LowerHex + fmt::UpperHex,
@@ -164,6 +170,7 @@ where
_ => panic!("fmt_int should never be called with the fmt {}", fmt),
}
}
fn pad<W: Write>(
w: &mut W,
current_side: bool,
@@ -177,6 +184,7 @@ fn pad<W: Write>(
}
Ok(())
}
fn float_string(float: c_double, precision: usize, trim: bool) -> String {
let mut string = format!("{:.p$}", float, p = precision);
if trim {
@@ -192,6 +200,7 @@ fn float_string(float: c_double, precision: usize, trim: bool) -> String {
}
string
}
fn fmt_float_exp<W: Write>(
w: &mut W,
exp_fmt: u8,
@@ -244,6 +253,7 @@ fn fmt_float_exp<W: Write>(
Ok(true)
}
fn fmt_float_normal<W: Write>(
w: &mut W,
trim: bool,
@@ -268,7 +278,8 @@ fn fmt_float_normal<W: Write>(
Ok(string.len())
}
unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io::Result<c_int> {
unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: va_list) -> io::Result<c_int> {
let w = &mut platform::CountingWriter::new(w);
let mut ap = BufferedVaList::new(ap);
let mut format = format as *const u8;
@@ -356,17 +367,21 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
b'%' => w.write_all(&[b'%'])?,
b'd' | b'i' => {
let string = match kind {
// VaList does not seem to support these two:
// IntKind::Byte => ap.get::<c_char>(index).to_string(),
// IntKind::Short => ap.get::<c_short>(index).to_string(),
IntKind::Byte => (ap.get::<c_int>(index) as c_char).to_string(),
IntKind::Short => (ap.get::<c_int>(index) as c_short).to_string(),
IntKind::Int => ap.get::<c_int>(index).to_string(),
IntKind::Long => ap.get::<c_long>(index).to_string(),
IntKind::LongLong => ap.get::<c_longlong>(index).to_string(),
IntKind::PtrDiff => ap.get::<ptrdiff_t>(index).to_string(),
IntKind::Size => ap.get::<ssize_t>(index).to_string(),
IntKind::IntMax => ap.get::<intmax_t>(index).to_string(),
// Per the C standard using va_arg with a type with a size
// less than that of an int for integers and double for floats
// is invalid. As a result any arguments smaller than an int or
// double passed to a function will be promoted to the smallest
// possible size. The va_list::arg function will handle this
// automagically.
IntKind::Byte => ap.get(ArgType::Byte, index).byte.to_string(),
IntKind::Short => ap.get(ArgType::Short, index).short.to_string(),
// Types that will not be promoted
IntKind::Int => ap.get(ArgType::Int, index).int.to_string(),
IntKind::Long => ap.get(ArgType::Long, index).long.to_string(),
IntKind::LongLong => ap.get(ArgType::LongLong, index).longlong.to_string(),
IntKind::PtrDiff => ap.get(ArgType::PtrDiff, index).ptrdiff.to_string(),
IntKind::Size => ap.get(ArgType::Size, index).size.to_string(),
IntKind::IntMax => ap.get(ArgType::IntMax, index).intmax.to_string(),
};
let positive = !string.starts_with('-');
let zero = precision == Some(0) && string == "0";
@@ -405,17 +420,15 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
b'o' | b'u' | b'x' | b'X' => {
let fmt = *format;
let string = match kind {
// VaList does not seem to support these two:
// IntKind::Byte => fmt_int(kind ap.get::<c_char>(index)),
// IntKind::Short => fmt_int(kind ap.get::<c_short>(index)),
IntKind::Byte => fmt_int(fmt, ap.get::<c_uint>(index) as c_uchar),
IntKind::Short => fmt_int(fmt, ap.get::<c_uint>(index) as c_ushort),
IntKind::Int => fmt_int(fmt, ap.get::<c_uint>(index)),
IntKind::Long => fmt_int(fmt, ap.get::<c_ulong>(index)),
IntKind::LongLong => fmt_int(fmt, ap.get::<c_ulonglong>(index)),
IntKind::PtrDiff => fmt_int(fmt, ap.get::<ptrdiff_t>(index)),
IntKind::Size => fmt_int(fmt, ap.get::<size_t>(index)),
IntKind::IntMax => fmt_int(fmt, ap.get::<uintmax_t>(index)),
// va_list will promote the following two to a c_int
IntKind::Byte => fmt_int(fmt, ap.get(ArgType::Byte, index).byte),
IntKind::Short => fmt_int(fmt, ap.get(ArgType::Short, index).short),
IntKind::Int => fmt_int(fmt, ap.get(ArgType::Int, index).int),
IntKind::Long => fmt_int(fmt, ap.get(ArgType::Long, index).long),
IntKind::LongLong => fmt_int(fmt, ap.get(ArgType::LongLong, index).longlong),
IntKind::PtrDiff => fmt_int(fmt, ap.get(ArgType::PtrDiff, index).ptrdiff),
IntKind::Size => fmt_int(fmt, ap.get(ArgType::Size, index).size),
IntKind::IntMax => fmt_int(fmt, ap.get(ArgType::IntMax, index).intmax),
};
let zero = precision == Some(0) && string == "0";
@@ -460,7 +473,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
}
b'e' | b'E' => {
let exp_fmt = *format;
let mut float = ap.get::<c_double>(index);
let mut float = ap.get(ArgType::Double, index).double;
let precision = precision.unwrap_or(6);
fmt_float_exp(
@@ -468,14 +481,14 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
)?;
}
b'f' | b'F' => {
let mut float = ap.get::<c_double>(index);
let mut float = ap.get(ArgType::Double, index).double;
let precision = precision.unwrap_or(6);
fmt_float_normal(w, false, precision, float, left, pad_space, pad_zero)?;
}
b'g' | b'G' => {
let exp_fmt = b'E' | (*format & 32);
let mut float = ap.get::<c_double>(index);
let mut float = ap.get(ArgType::Double, index).double;
let precision = precision.unwrap_or(6);
if !fmt_float_exp(
@@ -495,7 +508,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
b's' => {
// if kind == IntKind::Long || kind == IntKind::LongLong, handle *const wchar_t
let ptr = ap.get::<*const c_char>(index);
let ptr = ap.get(ArgType::CharPtr, index).char_ptr;
if ptr.is_null() {
w.write_all(b"(null)")?;
@@ -515,14 +528,14 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
b'c' => {
// if kind == IntKind::Long || kind == IntKind::LongLong, handle wint_t
let c = ap.get::<c_int>(index) as c_char;
let c = ap.get(ArgType::Byte, index).byte;
pad(w, !left, b' ', 1..pad_space)?;
w.write_all(&[c as u8])?;
pad(w, left, b' ', 1..pad_space)?;
}
b'p' => {
let ptr = ap.get::<*const c_void>(index);
let ptr = ap.get(ArgType::VoidPtr, index).int_ptr;
let mut len = 1;
if ptr.is_null() {
@@ -544,7 +557,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
pad(w, left, b' ', len..pad_space)?;
}
b'n' => {
let ptr = ap.get::<*mut c_int>(index);
let ptr = ap.get(ArgType::IntPtr, index).int_ptr;
*ptr = w.written as c_int;
}
_ => return Ok(-1),
@@ -554,6 +567,7 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> io:
}
Ok(w.written as c_int)
}
pub unsafe fn printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> c_int {
pub unsafe fn printf<W: Write>(w: W, format: *const c_char, ap: va_list) -> c_int {
inner_printf(w, format, ap).unwrap_or(-1)
}
+9 -9
View File
@@ -2,7 +2,7 @@ use alloc::string::String;
use alloc::vec::Vec;
use io::Read;
use platform::types::*;
use va_list::VaList;
use core::ffi::VaList as va_list;
#[derive(PartialEq, Eq)]
enum IntKind {
@@ -30,7 +30,7 @@ unsafe fn next_byte(string: &mut *const c_char) -> Result<u8, c_int> {
unsafe fn inner_scanf<R: Read>(
mut r: R,
mut format: *const c_char,
mut ap: VaList,
mut ap: va_list,
) -> Result<c_int, c_int> {
let mut matched = 0;
let mut byte = 0;
@@ -231,7 +231,7 @@ unsafe fn inner_scanf<R: Read>(
n.parse::<$type>().map_err(|_| 0)?
};
if !ignore {
*ap.get::<*mut $type>() = n;
*ap.arg::<*mut $type>() = n;
matched += 1;
}
}};
@@ -251,7 +251,7 @@ unsafe fn inner_scanf<R: Read>(
$type::from_str_radix(&n, radix).map_err(|_| 0)?
};
if !ignore {
*ap.get::<*mut $final>() = n as $final;
*ap.arg::<*mut $final>() = n as $final;
matched += 1;
}
}};
@@ -329,7 +329,7 @@ unsafe fn inner_scanf<R: Read>(
}
}
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
while width.map(|w| w > 0).unwrap_or(true) && !(byte as char).is_whitespace() {
if let Some(ref mut ptr) = ptr {
@@ -349,7 +349,7 @@ unsafe fn inner_scanf<R: Read>(
}
}
b'c' => {
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
for i in 0..width.unwrap_or(1) {
if let Some(ptr) = ptr {
@@ -400,7 +400,7 @@ unsafe fn inner_scanf<R: Read>(
}
}
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.get()) };
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
// While we haven't used up all the width, and it matches
while width.map(|w| w > 0).unwrap_or(true) && !invert == matches.contains(&byte) {
@@ -425,7 +425,7 @@ unsafe fn inner_scanf<R: Read>(
},
b'n' => {
if !ignore {
*ap.get::<*mut c_int>() = count as c_int;
*ap.arg::<*mut c_int>() = count as c_int;
}
}
_ => return Err(-1),
@@ -444,7 +444,7 @@ unsafe fn inner_scanf<R: Read>(
}
Ok(matched)
}
pub unsafe fn scanf<R: Read>(r: R, format: *const c_char, ap: VaList) -> c_int {
pub unsafe fn scanf<R: Read>(r: R, format: *const c_char, ap: va_list) -> c_int {
match inner_scanf(r, format, ap) {
Ok(n) => n,
Err(n) => n,
+1 -1
View File
@@ -1,7 +1,7 @@
//! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wchar.h.html
use core::{mem, ptr, usize};
use va_list::VaList as va_list;
use core::ffi::VaList as va_list;
use header::stdio::*;
use header::stdlib::MB_CUR_MAX;
+1 -1
View File
@@ -5,6 +5,7 @@
#![feature(alloc)]
#![feature(allocator_api)]
#![feature(asm)]
#![feature(c_variadic)]
#![feature(const_fn)]
#![feature(const_raw_ptr_deref)]
#![feature(const_str_as_bytes)]
@@ -33,7 +34,6 @@ extern crate lazy_static;
extern crate memoffset;
extern crate posix_regex;
extern crate rand;
extern crate va_list;
#[cfg(target_os = "linux")]
#[macro_use]