Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libcc2rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ libcc2rs-macros = { path = "../libcc2rs-macros", version = "0.1.0" }
libc = "0.2"
nix = { version = "0.30", features = ["socket", "net", "fs", "poll", "time", "user", "dir", "term", "event", "hostname"] }
jiff = "0.2"
sprintf = "0.4"
64 changes: 64 additions & 0 deletions libcc2rs/src/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

use sprintf::parser::{ConversionType, FormatElement, parse_format_string};
use sprintf::{Printf, vsprintfp};

use crate::va_args::{VaArg, VaArgGet};

pub fn format_c(fmt: &str, va: &[VaArg]) -> String {
let elements = match parse_format_string(fmt) {
Ok(elements) => elements,
Err(e) => panic!("format_c: cannot parse {fmt:?}: {e:?}"),
};
let mut args: Vec<Box<dyn Printf>> = Vec::new();
let mut pos = 0;
for element in &elements {
if let FormatElement::Format(spec) = element {
if spec.conversion_type == ConversionType::PercentSign {
continue;
}
let arg = &va[pos];
args.push(match spec.conversion_type {
ConversionType::DecInt => match arg {
VaArg::Int(v) => Box::new(*v),
VaArg::UInt(v) => Box::new(*v),
VaArg::Long(v) => Box::new(*v),
VaArg::ULong(v) => Box::new(*v),
_ => panic!("format_c: integer conversion expects an integer argument"),
},
ConversionType::OctInt
| ConversionType::HexIntLower
| ConversionType::HexIntUpper => match arg {
VaArg::Int(v) => Box::new(*v as u32),
VaArg::UInt(v) => Box::new(*v),
VaArg::Long(v) => Box::new(*v as u64),
VaArg::ULong(v) => Box::new(*v),
VaArg::Ptr(p) => Box::new(p.to_int()),
VaArg::RawPtr(v) => Box::new(*v as usize),
VaArg::Double(_) => {
panic!("format_c: integer conversion expects an integer argument")
}
},
ConversionType::Char => Box::new(i32::get(arg) as u8 as char),
ConversionType::String => match arg {
VaArg::Ptr(v) => Box::new(v.reinterpret_cast::<u8>().to_rust_string()),
_ => panic!("format_c: %s expects a string argument"),
},
ConversionType::DecFloatLower
| ConversionType::DecFloatUpper
| ConversionType::SciFloatLower
| ConversionType::SciFloatUpper
| ConversionType::CompactFloatLower
| ConversionType::CompactFloatUpper => Box::new(f64::get(arg)),
ConversionType::PercentSign => panic!("format_c: %% consumes no argument"),
});
pos += 1;
}
}
let refs: Vec<&dyn Printf> = args.iter().map(|arg| arg.as_ref()).collect();
match vsprintfp(&elements, &refs) {
Ok(s) => s,
Err(e) => panic!("format_c: cannot format {fmt:?}: {e:?}"),
}
}
3 changes: 3 additions & 0 deletions libcc2rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ pub use compat::*;
mod va_args;
pub use va_args::*;

mod format;
pub use format::*;

pub use libcc2rs_macros::{goto, goto_block, switch};
17 changes: 10 additions & 7 deletions rules/stdio/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,16 @@ fn f19(a0: Ptr<::std::fs::File>, a1: i64, a2: i32) -> i32 {
}

fn f21(a0: Ptr<u8>, a1: usize, a2: Ptr<u8>, va: &[VaArg]) -> i32 {
panic!(
"snprintf is not supported in the refcount model (buf_is_null={}, size={}, fmt={:?}, varargs={})",
a0.is_null(),
a1,
a2.to_rust_string(),
va.len()
)
let __s = libcc2rs::format_c(&a2.to_rust_string(), va);
let __b = __s.as_bytes();
if a1 > 0 {
let __n = ::std::cmp::min(__b.len(), a1 - 1);
a0.with_slice_mut(__n + 1, |__dst| {
__dst[..__n].copy_from_slice(&__b[..__n]);
__dst[__n] = 0;
});
}
__b.len() as i32
}

fn f22(a0: Ptr<u8>, a1: Ptr<u8>) -> i32 {
Expand Down
Loading
Loading