Skip to content

Commit

Permalink
support string literal constants in com-scrape
Browse files Browse the repository at this point in the history
  • Loading branch information
glowcoil committed Jun 9, 2023
1 parent d97b3eb commit f17c2bc
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 35 deletions.
96 changes: 68 additions & 28 deletions com-scrape/src/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,30 +243,8 @@ impl<'a> Cursor<'a> {
unsafe { clang_CXXMethod_isVirtual(self.cursor) != 0 }
}

pub fn evaluate(&self) -> Option<EvalResult> {
unsafe {
let result = clang_Cursor_Evaluate(self.cursor);

let result_type = clang_EvalResult_getKind(result);
#[allow(non_upper_case_globals)]
let value = match result_type {
CXEval_Int => {
if clang_EvalResult_isUnsignedInt(result) != 0 {
EvalResult::Unsigned(clang_EvalResult_getAsUnsigned(result))
} else {
EvalResult::Signed(clang_EvalResult_getAsLongLong(result))
}
}
CXEval_Float => EvalResult::Float(clang_EvalResult_getAsDouble(result)),
_ => {
return None;
}
};

clang_EvalResult_dispose(result);

Some(value)
}
pub fn evaluate(&self) -> EvalResult<'a> {
unsafe { EvalResult::from_raw(clang_Cursor_Evaluate(self.cursor)) }
}

pub fn tokens(&self) -> Tokens<'a> {
Expand Down Expand Up @@ -616,10 +594,72 @@ impl<'a> Drop for StringRef<'a> {
}
}

pub enum EvalResult {
Unsigned(c_ulonglong),
Signed(c_longlong),
Float(f64),
pub enum EvalResultKind {
Int,
Float,
StrLiteral,
Other,
}

pub struct EvalResult<'a> {
result: CXEvalResult,
_marker: PhantomData<&'a ()>,
}

impl<'a> EvalResult<'a> {
unsafe fn from_raw(result: CXEvalResult) -> EvalResult<'a> {
EvalResult {
result,
_marker: PhantomData,
}
}

pub fn kind(&self) -> EvalResultKind {
let kind = unsafe { clang_EvalResult_getKind(self.result) };

#[allow(non_upper_case_globals)]
match kind {
CXEval_Int => EvalResultKind::Int,
CXEval_Float => EvalResultKind::Float,
CXEval_StrLiteral => EvalResultKind::StrLiteral,
_ => EvalResultKind::Other,
}
}

pub fn is_unsigned_int(&self) -> bool {
unsafe { clang_EvalResult_isUnsignedInt(self.result) != 0 }
}

pub fn as_unsigned(&self) -> c_ulonglong {
unsafe { clang_EvalResult_getAsUnsigned(self.result) }
}

pub fn as_long_long(&self) -> c_longlong {
unsafe { clang_EvalResult_getAsLongLong(self.result) }
}

pub fn as_double(&self) -> f64 {
unsafe { clang_EvalResult_getAsDouble(self.result) }
}

pub fn as_str(&self) -> Option<&CStr> {
unsafe {
let ptr = clang_EvalResult_getAsStr(self.result);
if !ptr.is_null() {
Some(CStr::from_ptr(ptr))
} else {
None
}
}
}
}

impl<'a> Drop for EvalResult<'a> {
fn drop(&mut self) {
unsafe {
clang_EvalResult_dispose(self.result);
}
}
}

pub struct Tokens<'a> {
Expand Down
23 changes: 17 additions & 6 deletions com-scrape/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ pub enum Value {
Signed(i64),
Unsigned(u64),
Float(f64),
Str(String),
}

struct Parser<'a> {
Expand Down Expand Up @@ -253,13 +254,23 @@ impl<'a> Parser<'a> {
CursorKind::VarDecl => {
let type_ = cursor.type_().unwrap();
if type_.is_const() {
if let Some(eval_result) = cursor.evaluate() {
let value = match eval_result {
EvalResult::Unsigned(value) => Value::Unsigned(value),
EvalResult::Signed(value) => Value::Signed(value),
EvalResult::Float(value) => Value::Float(value),
};
let eval_result = cursor.evaluate();
let value = match eval_result.kind() {
EvalResultKind::Int => {
if eval_result.is_unsigned_int() {
Some(Value::Unsigned(eval_result.as_unsigned()))
} else {
Some(Value::Signed(eval_result.as_long_long()))
}
}
EvalResultKind::Float => Some(Value::Float(eval_result.as_double())),
EvalResultKind::StrLiteral => Some(Value::Str(
eval_result.as_str().unwrap().to_str().unwrap().to_string(),
)),
EvalResultKind::Other => None,
};

if let Some(value) = value {
let type_ = self.parse_type(type_, cursor.location())?;
namespace.constants.push(Constant {
name: cursor.name().to_str().unwrap().to_string(),
Expand Down
6 changes: 5 additions & 1 deletion com-scrape/src/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,14 @@ impl<'a, W: Write> RustPrinter<'a, W> {
let name = &constant.name;
write!(self.sink, "{indent}pub const {name}: ")?;
self.print_type(&constant.type_)?;
match constant.value {
match &constant.value {
Value::Signed(value) => writeln!(self.sink, " = {value:?};")?,
Value::Unsigned(value) => writeln!(self.sink, " = {value:?};")?,
Value::Float(value) => writeln!(self.sink, " = {value:?};")?,
Value::Str(value) => writeln!(
self.sink,
" = b\"{value}\\0\".as_ptr() as *const ::std::ffi::c_char;"
)?,
}
}

Expand Down

0 comments on commit f17c2bc

Please sign in to comment.