112a9d9c8Sopenharmony_ci//! Intermediate representation of variables. 212a9d9c8Sopenharmony_ci 312a9d9c8Sopenharmony_ciuse super::super::codegen::MacroTypeVariation; 412a9d9c8Sopenharmony_ciuse super::context::{BindgenContext, TypeId}; 512a9d9c8Sopenharmony_ciuse super::dot::DotAttributes; 612a9d9c8Sopenharmony_ciuse super::function::cursor_mangling; 712a9d9c8Sopenharmony_ciuse super::int::IntKind; 812a9d9c8Sopenharmony_ciuse super::item::Item; 912a9d9c8Sopenharmony_ciuse super::ty::{FloatKind, TypeKind}; 1012a9d9c8Sopenharmony_ciuse crate::callbacks::{ItemInfo, ItemKind, MacroParsingBehavior}; 1112a9d9c8Sopenharmony_ciuse crate::clang; 1212a9d9c8Sopenharmony_ciuse crate::clang::ClangToken; 1312a9d9c8Sopenharmony_ciuse crate::parse::{ClangSubItemParser, ParseError, ParseResult}; 1412a9d9c8Sopenharmony_ciuse cexpr; 1512a9d9c8Sopenharmony_ciuse std::io; 1612a9d9c8Sopenharmony_ciuse std::num::Wrapping; 1712a9d9c8Sopenharmony_ci 1812a9d9c8Sopenharmony_ci/// The type for a constant variable. 1912a9d9c8Sopenharmony_ci#[derive(Debug)] 2012a9d9c8Sopenharmony_cipub enum VarType { 2112a9d9c8Sopenharmony_ci /// A boolean. 2212a9d9c8Sopenharmony_ci Bool(bool), 2312a9d9c8Sopenharmony_ci /// An integer. 2412a9d9c8Sopenharmony_ci Int(i64), 2512a9d9c8Sopenharmony_ci /// A floating point number. 2612a9d9c8Sopenharmony_ci Float(f64), 2712a9d9c8Sopenharmony_ci /// A character. 2812a9d9c8Sopenharmony_ci Char(u8), 2912a9d9c8Sopenharmony_ci /// A string, not necessarily well-formed utf-8. 3012a9d9c8Sopenharmony_ci String(Vec<u8>), 3112a9d9c8Sopenharmony_ci} 3212a9d9c8Sopenharmony_ci 3312a9d9c8Sopenharmony_ci/// A `Var` is our intermediate representation of a variable. 3412a9d9c8Sopenharmony_ci#[derive(Debug)] 3512a9d9c8Sopenharmony_cipub struct Var { 3612a9d9c8Sopenharmony_ci /// The name of the variable. 3712a9d9c8Sopenharmony_ci name: String, 3812a9d9c8Sopenharmony_ci /// The mangled name of the variable. 3912a9d9c8Sopenharmony_ci mangled_name: Option<String>, 4012a9d9c8Sopenharmony_ci /// The type of the variable. 4112a9d9c8Sopenharmony_ci ty: TypeId, 4212a9d9c8Sopenharmony_ci /// The value of the variable, that needs to be suitable for `ty`. 4312a9d9c8Sopenharmony_ci val: Option<VarType>, 4412a9d9c8Sopenharmony_ci /// Whether this variable is const. 4512a9d9c8Sopenharmony_ci is_const: bool, 4612a9d9c8Sopenharmony_ci} 4712a9d9c8Sopenharmony_ci 4812a9d9c8Sopenharmony_ciimpl Var { 4912a9d9c8Sopenharmony_ci /// Construct a new `Var`. 5012a9d9c8Sopenharmony_ci pub fn new( 5112a9d9c8Sopenharmony_ci name: String, 5212a9d9c8Sopenharmony_ci mangled_name: Option<String>, 5312a9d9c8Sopenharmony_ci ty: TypeId, 5412a9d9c8Sopenharmony_ci val: Option<VarType>, 5512a9d9c8Sopenharmony_ci is_const: bool, 5612a9d9c8Sopenharmony_ci ) -> Var { 5712a9d9c8Sopenharmony_ci assert!(!name.is_empty()); 5812a9d9c8Sopenharmony_ci Var { 5912a9d9c8Sopenharmony_ci name, 6012a9d9c8Sopenharmony_ci mangled_name, 6112a9d9c8Sopenharmony_ci ty, 6212a9d9c8Sopenharmony_ci val, 6312a9d9c8Sopenharmony_ci is_const, 6412a9d9c8Sopenharmony_ci } 6512a9d9c8Sopenharmony_ci } 6612a9d9c8Sopenharmony_ci 6712a9d9c8Sopenharmony_ci /// Is this variable `const` qualified? 6812a9d9c8Sopenharmony_ci pub fn is_const(&self) -> bool { 6912a9d9c8Sopenharmony_ci self.is_const 7012a9d9c8Sopenharmony_ci } 7112a9d9c8Sopenharmony_ci 7212a9d9c8Sopenharmony_ci /// The value of this constant variable, if any. 7312a9d9c8Sopenharmony_ci pub fn val(&self) -> Option<&VarType> { 7412a9d9c8Sopenharmony_ci self.val.as_ref() 7512a9d9c8Sopenharmony_ci } 7612a9d9c8Sopenharmony_ci 7712a9d9c8Sopenharmony_ci /// Get this variable's type. 7812a9d9c8Sopenharmony_ci pub fn ty(&self) -> TypeId { 7912a9d9c8Sopenharmony_ci self.ty 8012a9d9c8Sopenharmony_ci } 8112a9d9c8Sopenharmony_ci 8212a9d9c8Sopenharmony_ci /// Get this variable's name. 8312a9d9c8Sopenharmony_ci pub fn name(&self) -> &str { 8412a9d9c8Sopenharmony_ci &self.name 8512a9d9c8Sopenharmony_ci } 8612a9d9c8Sopenharmony_ci 8712a9d9c8Sopenharmony_ci /// Get this variable's mangled name. 8812a9d9c8Sopenharmony_ci pub fn mangled_name(&self) -> Option<&str> { 8912a9d9c8Sopenharmony_ci self.mangled_name.as_deref() 9012a9d9c8Sopenharmony_ci } 9112a9d9c8Sopenharmony_ci} 9212a9d9c8Sopenharmony_ci 9312a9d9c8Sopenharmony_ciimpl DotAttributes for Var { 9412a9d9c8Sopenharmony_ci fn dot_attributes<W>( 9512a9d9c8Sopenharmony_ci &self, 9612a9d9c8Sopenharmony_ci _ctx: &BindgenContext, 9712a9d9c8Sopenharmony_ci out: &mut W, 9812a9d9c8Sopenharmony_ci ) -> io::Result<()> 9912a9d9c8Sopenharmony_ci where 10012a9d9c8Sopenharmony_ci W: io::Write, 10112a9d9c8Sopenharmony_ci { 10212a9d9c8Sopenharmony_ci if self.is_const { 10312a9d9c8Sopenharmony_ci writeln!(out, "<tr><td>const</td><td>true</td></tr>")?; 10412a9d9c8Sopenharmony_ci } 10512a9d9c8Sopenharmony_ci 10612a9d9c8Sopenharmony_ci if let Some(ref mangled) = self.mangled_name { 10712a9d9c8Sopenharmony_ci writeln!( 10812a9d9c8Sopenharmony_ci out, 10912a9d9c8Sopenharmony_ci "<tr><td>mangled name</td><td>{}</td></tr>", 11012a9d9c8Sopenharmony_ci mangled 11112a9d9c8Sopenharmony_ci )?; 11212a9d9c8Sopenharmony_ci } 11312a9d9c8Sopenharmony_ci 11412a9d9c8Sopenharmony_ci Ok(()) 11512a9d9c8Sopenharmony_ci } 11612a9d9c8Sopenharmony_ci} 11712a9d9c8Sopenharmony_ci 11812a9d9c8Sopenharmony_cifn default_macro_constant_type(ctx: &BindgenContext, value: i64) -> IntKind { 11912a9d9c8Sopenharmony_ci if value < 0 || 12012a9d9c8Sopenharmony_ci ctx.options().default_macro_constant_type == 12112a9d9c8Sopenharmony_ci MacroTypeVariation::Signed 12212a9d9c8Sopenharmony_ci { 12312a9d9c8Sopenharmony_ci if value < i32::min_value() as i64 || value > i32::max_value() as i64 { 12412a9d9c8Sopenharmony_ci IntKind::I64 12512a9d9c8Sopenharmony_ci } else if !ctx.options().fit_macro_constants || 12612a9d9c8Sopenharmony_ci value < i16::min_value() as i64 || 12712a9d9c8Sopenharmony_ci value > i16::max_value() as i64 12812a9d9c8Sopenharmony_ci { 12912a9d9c8Sopenharmony_ci IntKind::I32 13012a9d9c8Sopenharmony_ci } else if value < i8::min_value() as i64 || 13112a9d9c8Sopenharmony_ci value > i8::max_value() as i64 13212a9d9c8Sopenharmony_ci { 13312a9d9c8Sopenharmony_ci IntKind::I16 13412a9d9c8Sopenharmony_ci } else { 13512a9d9c8Sopenharmony_ci IntKind::I8 13612a9d9c8Sopenharmony_ci } 13712a9d9c8Sopenharmony_ci } else if value > u32::max_value() as i64 { 13812a9d9c8Sopenharmony_ci IntKind::U64 13912a9d9c8Sopenharmony_ci } else if !ctx.options().fit_macro_constants || 14012a9d9c8Sopenharmony_ci value > u16::max_value() as i64 14112a9d9c8Sopenharmony_ci { 14212a9d9c8Sopenharmony_ci IntKind::U32 14312a9d9c8Sopenharmony_ci } else if value > u8::max_value() as i64 { 14412a9d9c8Sopenharmony_ci IntKind::U16 14512a9d9c8Sopenharmony_ci } else { 14612a9d9c8Sopenharmony_ci IntKind::U8 14712a9d9c8Sopenharmony_ci } 14812a9d9c8Sopenharmony_ci} 14912a9d9c8Sopenharmony_ci 15012a9d9c8Sopenharmony_ci/// Parses tokens from a CXCursor_MacroDefinition pointing into a function-like 15112a9d9c8Sopenharmony_ci/// macro, and calls the func_macro callback. 15212a9d9c8Sopenharmony_cifn handle_function_macro( 15312a9d9c8Sopenharmony_ci cursor: &clang::Cursor, 15412a9d9c8Sopenharmony_ci callbacks: &dyn crate::callbacks::ParseCallbacks, 15512a9d9c8Sopenharmony_ci) { 15612a9d9c8Sopenharmony_ci let is_closing_paren = |t: &ClangToken| { 15712a9d9c8Sopenharmony_ci // Test cheap token kind before comparing exact spellings. 15812a9d9c8Sopenharmony_ci t.kind == clang_sys::CXToken_Punctuation && t.spelling() == b")" 15912a9d9c8Sopenharmony_ci }; 16012a9d9c8Sopenharmony_ci let tokens: Vec<_> = cursor.tokens().iter().collect(); 16112a9d9c8Sopenharmony_ci if let Some(boundary) = tokens.iter().position(is_closing_paren) { 16212a9d9c8Sopenharmony_ci let mut spelled = tokens.iter().map(ClangToken::spelling); 16312a9d9c8Sopenharmony_ci // Add 1, to convert index to length. 16412a9d9c8Sopenharmony_ci let left = spelled.by_ref().take(boundary + 1); 16512a9d9c8Sopenharmony_ci let left = left.collect::<Vec<_>>().concat(); 16612a9d9c8Sopenharmony_ci if let Ok(left) = String::from_utf8(left) { 16712a9d9c8Sopenharmony_ci let right: Vec<_> = spelled.collect(); 16812a9d9c8Sopenharmony_ci callbacks.func_macro(&left, &right); 16912a9d9c8Sopenharmony_ci } 17012a9d9c8Sopenharmony_ci } 17112a9d9c8Sopenharmony_ci} 17212a9d9c8Sopenharmony_ci 17312a9d9c8Sopenharmony_ciimpl ClangSubItemParser for Var { 17412a9d9c8Sopenharmony_ci fn parse( 17512a9d9c8Sopenharmony_ci cursor: clang::Cursor, 17612a9d9c8Sopenharmony_ci ctx: &mut BindgenContext, 17712a9d9c8Sopenharmony_ci ) -> Result<ParseResult<Self>, ParseError> { 17812a9d9c8Sopenharmony_ci use cexpr::expr::EvalResult; 17912a9d9c8Sopenharmony_ci use cexpr::literal::CChar; 18012a9d9c8Sopenharmony_ci use clang_sys::*; 18112a9d9c8Sopenharmony_ci match cursor.kind() { 18212a9d9c8Sopenharmony_ci CXCursor_MacroDefinition => { 18312a9d9c8Sopenharmony_ci for callbacks in &ctx.options().parse_callbacks { 18412a9d9c8Sopenharmony_ci match callbacks.will_parse_macro(&cursor.spelling()) { 18512a9d9c8Sopenharmony_ci MacroParsingBehavior::Ignore => { 18612a9d9c8Sopenharmony_ci return Err(ParseError::Continue); 18712a9d9c8Sopenharmony_ci } 18812a9d9c8Sopenharmony_ci MacroParsingBehavior::Default => {} 18912a9d9c8Sopenharmony_ci } 19012a9d9c8Sopenharmony_ci 19112a9d9c8Sopenharmony_ci if cursor.is_macro_function_like() { 19212a9d9c8Sopenharmony_ci handle_function_macro(&cursor, callbacks.as_ref()); 19312a9d9c8Sopenharmony_ci // We handled the macro, skip macro processing below. 19412a9d9c8Sopenharmony_ci return Err(ParseError::Continue); 19512a9d9c8Sopenharmony_ci } 19612a9d9c8Sopenharmony_ci } 19712a9d9c8Sopenharmony_ci 19812a9d9c8Sopenharmony_ci let value = parse_macro(ctx, &cursor); 19912a9d9c8Sopenharmony_ci 20012a9d9c8Sopenharmony_ci let (id, value) = match value { 20112a9d9c8Sopenharmony_ci Some(v) => v, 20212a9d9c8Sopenharmony_ci None => return Err(ParseError::Continue), 20312a9d9c8Sopenharmony_ci }; 20412a9d9c8Sopenharmony_ci 20512a9d9c8Sopenharmony_ci assert!(!id.is_empty(), "Empty macro name?"); 20612a9d9c8Sopenharmony_ci 20712a9d9c8Sopenharmony_ci let previously_defined = ctx.parsed_macro(&id); 20812a9d9c8Sopenharmony_ci 20912a9d9c8Sopenharmony_ci // NB: It's important to "note" the macro even if the result is 21012a9d9c8Sopenharmony_ci // not an integer, otherwise we might loose other kind of 21112a9d9c8Sopenharmony_ci // derived macros. 21212a9d9c8Sopenharmony_ci ctx.note_parsed_macro(id.clone(), value.clone()); 21312a9d9c8Sopenharmony_ci 21412a9d9c8Sopenharmony_ci if previously_defined { 21512a9d9c8Sopenharmony_ci let name = String::from_utf8(id).unwrap(); 21612a9d9c8Sopenharmony_ci warn!("Duplicated macro definition: {}", name); 21712a9d9c8Sopenharmony_ci return Err(ParseError::Continue); 21812a9d9c8Sopenharmony_ci } 21912a9d9c8Sopenharmony_ci 22012a9d9c8Sopenharmony_ci // NOTE: Unwrapping, here and above, is safe, because the 22112a9d9c8Sopenharmony_ci // identifier of a token comes straight from clang, and we 22212a9d9c8Sopenharmony_ci // enforce utf8 there, so we should have already panicked at 22312a9d9c8Sopenharmony_ci // this point. 22412a9d9c8Sopenharmony_ci let name = String::from_utf8(id).unwrap(); 22512a9d9c8Sopenharmony_ci let (type_kind, val) = match value { 22612a9d9c8Sopenharmony_ci EvalResult::Invalid => return Err(ParseError::Continue), 22712a9d9c8Sopenharmony_ci EvalResult::Float(f) => { 22812a9d9c8Sopenharmony_ci (TypeKind::Float(FloatKind::Double), VarType::Float(f)) 22912a9d9c8Sopenharmony_ci } 23012a9d9c8Sopenharmony_ci EvalResult::Char(c) => { 23112a9d9c8Sopenharmony_ci let c = match c { 23212a9d9c8Sopenharmony_ci CChar::Char(c) => { 23312a9d9c8Sopenharmony_ci assert_eq!(c.len_utf8(), 1); 23412a9d9c8Sopenharmony_ci c as u8 23512a9d9c8Sopenharmony_ci } 23612a9d9c8Sopenharmony_ci CChar::Raw(c) => { 23712a9d9c8Sopenharmony_ci assert!(c <= ::std::u8::MAX as u64); 23812a9d9c8Sopenharmony_ci c as u8 23912a9d9c8Sopenharmony_ci } 24012a9d9c8Sopenharmony_ci }; 24112a9d9c8Sopenharmony_ci 24212a9d9c8Sopenharmony_ci (TypeKind::Int(IntKind::U8), VarType::Char(c)) 24312a9d9c8Sopenharmony_ci } 24412a9d9c8Sopenharmony_ci EvalResult::Str(val) => { 24512a9d9c8Sopenharmony_ci let char_ty = Item::builtin_type( 24612a9d9c8Sopenharmony_ci TypeKind::Int(IntKind::U8), 24712a9d9c8Sopenharmony_ci true, 24812a9d9c8Sopenharmony_ci ctx, 24912a9d9c8Sopenharmony_ci ); 25012a9d9c8Sopenharmony_ci for callbacks in &ctx.options().parse_callbacks { 25112a9d9c8Sopenharmony_ci callbacks.str_macro(&name, &val); 25212a9d9c8Sopenharmony_ci } 25312a9d9c8Sopenharmony_ci (TypeKind::Pointer(char_ty), VarType::String(val)) 25412a9d9c8Sopenharmony_ci } 25512a9d9c8Sopenharmony_ci EvalResult::Int(Wrapping(value)) => { 25612a9d9c8Sopenharmony_ci let kind = ctx 25712a9d9c8Sopenharmony_ci .options() 25812a9d9c8Sopenharmony_ci .last_callback(|c| c.int_macro(&name, value)) 25912a9d9c8Sopenharmony_ci .unwrap_or_else(|| { 26012a9d9c8Sopenharmony_ci default_macro_constant_type(ctx, value) 26112a9d9c8Sopenharmony_ci }); 26212a9d9c8Sopenharmony_ci 26312a9d9c8Sopenharmony_ci (TypeKind::Int(kind), VarType::Int(value)) 26412a9d9c8Sopenharmony_ci } 26512a9d9c8Sopenharmony_ci }; 26612a9d9c8Sopenharmony_ci 26712a9d9c8Sopenharmony_ci let ty = Item::builtin_type(type_kind, true, ctx); 26812a9d9c8Sopenharmony_ci 26912a9d9c8Sopenharmony_ci Ok(ParseResult::New( 27012a9d9c8Sopenharmony_ci Var::new(name, None, ty, Some(val), true), 27112a9d9c8Sopenharmony_ci Some(cursor), 27212a9d9c8Sopenharmony_ci )) 27312a9d9c8Sopenharmony_ci } 27412a9d9c8Sopenharmony_ci CXCursor_VarDecl => { 27512a9d9c8Sopenharmony_ci let mut name = cursor.spelling(); 27612a9d9c8Sopenharmony_ci if cursor.linkage() == CXLinkage_External { 27712a9d9c8Sopenharmony_ci if let Some(nm) = ctx.options().last_callback(|callbacks| { 27812a9d9c8Sopenharmony_ci callbacks.generated_name_override(ItemInfo { 27912a9d9c8Sopenharmony_ci name: name.as_str(), 28012a9d9c8Sopenharmony_ci kind: ItemKind::Var, 28112a9d9c8Sopenharmony_ci }) 28212a9d9c8Sopenharmony_ci }) { 28312a9d9c8Sopenharmony_ci name = nm; 28412a9d9c8Sopenharmony_ci } 28512a9d9c8Sopenharmony_ci } 28612a9d9c8Sopenharmony_ci // No more changes to name 28712a9d9c8Sopenharmony_ci let name = name; 28812a9d9c8Sopenharmony_ci 28912a9d9c8Sopenharmony_ci if name.is_empty() { 29012a9d9c8Sopenharmony_ci warn!("Empty constant name?"); 29112a9d9c8Sopenharmony_ci return Err(ParseError::Continue); 29212a9d9c8Sopenharmony_ci } 29312a9d9c8Sopenharmony_ci 29412a9d9c8Sopenharmony_ci let ty = cursor.cur_type(); 29512a9d9c8Sopenharmony_ci 29612a9d9c8Sopenharmony_ci // TODO(emilio): do we have to special-case constant arrays in 29712a9d9c8Sopenharmony_ci // some other places? 29812a9d9c8Sopenharmony_ci let is_const = ty.is_const() || 29912a9d9c8Sopenharmony_ci ([CXType_ConstantArray, CXType_IncompleteArray] 30012a9d9c8Sopenharmony_ci .contains(&ty.kind()) && 30112a9d9c8Sopenharmony_ci ty.elem_type() 30212a9d9c8Sopenharmony_ci .map_or(false, |element| element.is_const())); 30312a9d9c8Sopenharmony_ci 30412a9d9c8Sopenharmony_ci let ty = match Item::from_ty(&ty, cursor, None, ctx) { 30512a9d9c8Sopenharmony_ci Ok(ty) => ty, 30612a9d9c8Sopenharmony_ci Err(e) => { 30712a9d9c8Sopenharmony_ci assert!( 30812a9d9c8Sopenharmony_ci matches!(ty.kind(), CXType_Auto | CXType_Unexposed), 30912a9d9c8Sopenharmony_ci "Couldn't resolve constant type, and it \ 31012a9d9c8Sopenharmony_ci wasn't an nondeductible auto type or unexposed \ 31112a9d9c8Sopenharmony_ci type!" 31212a9d9c8Sopenharmony_ci ); 31312a9d9c8Sopenharmony_ci return Err(e); 31412a9d9c8Sopenharmony_ci } 31512a9d9c8Sopenharmony_ci }; 31612a9d9c8Sopenharmony_ci 31712a9d9c8Sopenharmony_ci // Note: Ty might not be totally resolved yet, see 31812a9d9c8Sopenharmony_ci // tests/headers/inner_const.hpp 31912a9d9c8Sopenharmony_ci // 32012a9d9c8Sopenharmony_ci // That's fine because in that case we know it's not a literal. 32112a9d9c8Sopenharmony_ci let canonical_ty = ctx 32212a9d9c8Sopenharmony_ci .safe_resolve_type(ty) 32312a9d9c8Sopenharmony_ci .and_then(|t| t.safe_canonical_type(ctx)); 32412a9d9c8Sopenharmony_ci 32512a9d9c8Sopenharmony_ci let is_integer = canonical_ty.map_or(false, |t| t.is_integer()); 32612a9d9c8Sopenharmony_ci let is_float = canonical_ty.map_or(false, |t| t.is_float()); 32712a9d9c8Sopenharmony_ci 32812a9d9c8Sopenharmony_ci // TODO: We could handle `char` more gracefully. 32912a9d9c8Sopenharmony_ci // TODO: Strings, though the lookup is a bit more hard (we need 33012a9d9c8Sopenharmony_ci // to look at the canonical type of the pointee too, and check 33112a9d9c8Sopenharmony_ci // is char, u8, or i8 I guess). 33212a9d9c8Sopenharmony_ci let value = if is_integer { 33312a9d9c8Sopenharmony_ci let kind = match *canonical_ty.unwrap().kind() { 33412a9d9c8Sopenharmony_ci TypeKind::Int(kind) => kind, 33512a9d9c8Sopenharmony_ci _ => unreachable!(), 33612a9d9c8Sopenharmony_ci }; 33712a9d9c8Sopenharmony_ci 33812a9d9c8Sopenharmony_ci let mut val = cursor.evaluate().and_then(|v| v.as_int()); 33912a9d9c8Sopenharmony_ci if val.is_none() || !kind.signedness_matches(val.unwrap()) { 34012a9d9c8Sopenharmony_ci val = get_integer_literal_from_cursor(&cursor); 34112a9d9c8Sopenharmony_ci } 34212a9d9c8Sopenharmony_ci 34312a9d9c8Sopenharmony_ci val.map(|val| { 34412a9d9c8Sopenharmony_ci if kind == IntKind::Bool { 34512a9d9c8Sopenharmony_ci VarType::Bool(val != 0) 34612a9d9c8Sopenharmony_ci } else { 34712a9d9c8Sopenharmony_ci VarType::Int(val) 34812a9d9c8Sopenharmony_ci } 34912a9d9c8Sopenharmony_ci }) 35012a9d9c8Sopenharmony_ci } else if is_float { 35112a9d9c8Sopenharmony_ci cursor 35212a9d9c8Sopenharmony_ci .evaluate() 35312a9d9c8Sopenharmony_ci .and_then(|v| v.as_double()) 35412a9d9c8Sopenharmony_ci .map(VarType::Float) 35512a9d9c8Sopenharmony_ci } else { 35612a9d9c8Sopenharmony_ci cursor 35712a9d9c8Sopenharmony_ci .evaluate() 35812a9d9c8Sopenharmony_ci .and_then(|v| v.as_literal_string()) 35912a9d9c8Sopenharmony_ci .map(VarType::String) 36012a9d9c8Sopenharmony_ci }; 36112a9d9c8Sopenharmony_ci 36212a9d9c8Sopenharmony_ci let mangling = cursor_mangling(ctx, &cursor); 36312a9d9c8Sopenharmony_ci let var = Var::new(name, mangling, ty, value, is_const); 36412a9d9c8Sopenharmony_ci 36512a9d9c8Sopenharmony_ci Ok(ParseResult::New(var, Some(cursor))) 36612a9d9c8Sopenharmony_ci } 36712a9d9c8Sopenharmony_ci _ => { 36812a9d9c8Sopenharmony_ci /* TODO */ 36912a9d9c8Sopenharmony_ci Err(ParseError::Continue) 37012a9d9c8Sopenharmony_ci } 37112a9d9c8Sopenharmony_ci } 37212a9d9c8Sopenharmony_ci } 37312a9d9c8Sopenharmony_ci} 37412a9d9c8Sopenharmony_ci 37512a9d9c8Sopenharmony_ci/// Try and parse a macro using all the macros parsed until now. 37612a9d9c8Sopenharmony_cifn parse_macro( 37712a9d9c8Sopenharmony_ci ctx: &BindgenContext, 37812a9d9c8Sopenharmony_ci cursor: &clang::Cursor, 37912a9d9c8Sopenharmony_ci) -> Option<(Vec<u8>, cexpr::expr::EvalResult)> { 38012a9d9c8Sopenharmony_ci use cexpr::expr; 38112a9d9c8Sopenharmony_ci 38212a9d9c8Sopenharmony_ci let cexpr_tokens = cursor.cexpr_tokens(); 38312a9d9c8Sopenharmony_ci 38412a9d9c8Sopenharmony_ci let parser = expr::IdentifierParser::new(ctx.parsed_macros()); 38512a9d9c8Sopenharmony_ci 38612a9d9c8Sopenharmony_ci match parser.macro_definition(&cexpr_tokens) { 38712a9d9c8Sopenharmony_ci Ok((_, (id, val))) => Some((id.into(), val)), 38812a9d9c8Sopenharmony_ci _ => None, 38912a9d9c8Sopenharmony_ci } 39012a9d9c8Sopenharmony_ci} 39112a9d9c8Sopenharmony_ci 39212a9d9c8Sopenharmony_cifn parse_int_literal_tokens(cursor: &clang::Cursor) -> Option<i64> { 39312a9d9c8Sopenharmony_ci use cexpr::expr; 39412a9d9c8Sopenharmony_ci use cexpr::expr::EvalResult; 39512a9d9c8Sopenharmony_ci 39612a9d9c8Sopenharmony_ci let cexpr_tokens = cursor.cexpr_tokens(); 39712a9d9c8Sopenharmony_ci 39812a9d9c8Sopenharmony_ci // TODO(emilio): We can try to parse other kinds of literals. 39912a9d9c8Sopenharmony_ci match expr::expr(&cexpr_tokens) { 40012a9d9c8Sopenharmony_ci Ok((_, EvalResult::Int(Wrapping(val)))) => Some(val), 40112a9d9c8Sopenharmony_ci _ => None, 40212a9d9c8Sopenharmony_ci } 40312a9d9c8Sopenharmony_ci} 40412a9d9c8Sopenharmony_ci 40512a9d9c8Sopenharmony_cifn get_integer_literal_from_cursor(cursor: &clang::Cursor) -> Option<i64> { 40612a9d9c8Sopenharmony_ci use clang_sys::*; 40712a9d9c8Sopenharmony_ci let mut value = None; 40812a9d9c8Sopenharmony_ci cursor.visit(|c| { 40912a9d9c8Sopenharmony_ci match c.kind() { 41012a9d9c8Sopenharmony_ci CXCursor_IntegerLiteral | CXCursor_UnaryOperator => { 41112a9d9c8Sopenharmony_ci value = parse_int_literal_tokens(&c); 41212a9d9c8Sopenharmony_ci } 41312a9d9c8Sopenharmony_ci CXCursor_UnexposedExpr => { 41412a9d9c8Sopenharmony_ci value = get_integer_literal_from_cursor(&c); 41512a9d9c8Sopenharmony_ci } 41612a9d9c8Sopenharmony_ci _ => (), 41712a9d9c8Sopenharmony_ci } 41812a9d9c8Sopenharmony_ci if value.is_some() { 41912a9d9c8Sopenharmony_ci CXChildVisit_Break 42012a9d9c8Sopenharmony_ci } else { 42112a9d9c8Sopenharmony_ci CXChildVisit_Continue 42212a9d9c8Sopenharmony_ci } 42312a9d9c8Sopenharmony_ci }); 42412a9d9c8Sopenharmony_ci value 42512a9d9c8Sopenharmony_ci} 426