diff options
author | Jyun-Yan You <jyyou.tw@gmail.com> | 2015-07-10 11:38:37 +0800 |
---|---|---|
committer | Jyun-Yan You <jyyou.tw@gmail.com> | 2015-07-10 11:38:37 +0800 |
commit | a80623333305ea75a3d3e6a2248e5103f69a3a53 (patch) | |
tree | aa6b4c332a4ad152ab3e11fe9a957e53f9354766 | |
parent | 1cd7d980509fa934ba11ba39b301ff5a8bb1ce4c (diff) | |
parent | 9684646d7bb3ba8b64c927d09abbeb012e033afe (diff) |
Merge pull request #224 from luser/int-consts
Add support for generating consts for integer constants. Fixes #145.
-rw-r--r-- | src/clang.rs | 37 | ||||
-rw-r--r-- | src/gen.rs | 82 | ||||
-rw-r--r-- | src/parser.rs | 39 | ||||
-rw-r--r-- | src/types.rs | 3 |
4 files changed, 127 insertions, 34 deletions
diff --git a/src/clang.rs b/src/clang.rs index 3b1878f7..da4b9dae 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -39,6 +39,12 @@ impl Cursor { } } + pub fn extent(&self) -> CXSourceRange { + unsafe { + clang_getCursorExtent(self.x) + } + } + pub fn cur_type(&self) -> Type { unsafe { Type { x: clang_getCursorType(self.x) } @@ -351,6 +357,12 @@ impl Index { } } +// Token +pub struct Token { + pub kind: CXTokenKind, + pub spelling: String, +} + // TranslationUnit pub struct TranslationUnit { x: CXTranslationUnit @@ -358,7 +370,7 @@ pub struct TranslationUnit { impl TranslationUnit { pub fn parse(ix: &Index, file: &str, cmd_args: &[String], - unsaved: &[UnsavedFile], opts: usize) -> TranslationUnit { + unsaved: &[UnsavedFile], opts: ::libc::c_uint) -> TranslationUnit { let _fname = CString::new(file.as_bytes()).unwrap(); let fname = _fname.as_ptr(); let _c_args: Vec<CString> = cmd_args.iter().map(|s| CString::new(s.as_bytes()).unwrap()).collect(); @@ -370,7 +382,7 @@ impl TranslationUnit { c_args.len() as c_int, c_unsaved.as_mut_ptr(), c_unsaved.len() as c_uint, - opts as c_uint) + opts) }; TranslationUnit { x: tu } } @@ -412,6 +424,27 @@ impl TranslationUnit { pub fn is_null(&self) -> bool { self.x.is_null() } + + pub fn tokens(&self, cursor: &Cursor) -> Option<Vec<Token>> { + let range = cursor.extent(); + let mut tokens = vec![]; + unsafe { + let mut token_ptr = ::std::ptr::null_mut(); + let mut num_tokens : c_uint = 0; + clang_tokenize(self.x, range, &mut token_ptr, &mut num_tokens); + if token_ptr.is_null() { + return None; + } + let token_array = ::std::slice::from_raw_parts(token_ptr, num_tokens as usize); + for &token in token_array.iter() { + let kind = clang_getTokenKind(token); + let spelling = String_ { x: clang_getTokenSpelling(self.x, token) }.to_string(); + tokens.push(Token { kind: kind, spelling: spelling }); + } + clang_disposeTokens(self.x, token_ptr, num_tokens); + } + return Some(tokens); + } } // Diagnostic @@ -151,7 +151,22 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> match g { GOther => {} GFunc(_) => fs.push(g), - GVar(_) => vs.push(g), + GVar(_) => { + let is_int_const = { + match g { + GVar(ref vi) => { + let v = vi.borrow(); + v.is_const && v.val.is_some() + } + _ => unreachable!() + } + }; + if is_int_const { + gs.push(g); + } else { + vs.push(g); + } + } _ => gs.push(g) } } @@ -198,6 +213,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> let e = ei.borrow().clone(); defs.extend(cenum_to_rs(&mut ctx, enum_name(&e.name), e.kind, e.items).into_iter()) }, + GVar(vi) => { + let v = vi.borrow(); + let ty = cty_to_rs(&mut ctx, &v.ty); + defs.push(const_to_rs(&mut ctx, v.name.clone(), v.val.unwrap(), ty)); + }, _ => { } } } @@ -643,6 +663,28 @@ fn cunion_to_rs(ctx: &mut GenCtx, name: String, layout: Layout, members: Vec<Com items } +fn const_to_rs(ctx: &mut GenCtx, name: String, val: i64, val_ty: ast::Ty) -> P<ast::Item> { + let int_lit = ast::LitInt( + val.abs() as u64, + ast::UnsuffixedIntLit(if val < 0 { ast::Minus } else { ast::Plus }) + ); + + let cst = ast::ItemConst( + P(val_ty), + ctx.ext_cx.expr_lit(ctx.span, int_lit) + ); + + let id = first(rust_id(ctx, name.clone())); + P(ast::Item { + ident: ctx.ext_cx.ident_of(&id[..]), + attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, + node: cst, + vis: ast::Public, + span: ctx.span + }) +} + fn cenum_to_rs(ctx: &mut GenCtx, name: String, kind: IKind, items: Vec<EnumItem>) -> Vec<P<ast::Item>> { let ty = TInt(kind, Layout::zero()); let ty_id = rust_type_id(ctx, name); @@ -651,27 +693,7 @@ fn cenum_to_rs(ctx: &mut GenCtx, name: String, kind: IKind, items: Vec<EnumItem> let mut def = ty_def; for it in items.iter() { - let int_lit = ast::LitInt( - it.val.abs() as u64, - ast::UnsuffixedIntLit(if it.val < 0 { ast::Minus } else { ast::Plus }) - ); - - let cst = ast::ItemConst( - P(val_ty.clone()), - ctx.ext_cx.expr_lit(ctx.span, int_lit) - ); - - let id = first(rust_id(ctx, it.name.clone())); - let val_def = P(ast::Item { - ident: ctx.ext_cx.ident_of(&id[..]), - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: cst, - vis: ast::Public, - span: ctx.span - }); - - def.push(val_def); + def.push(const_to_rs(ctx, it.name.clone(), it.val, val_ty.clone())); } return def; @@ -849,14 +871,16 @@ fn cvar_to_rs(ctx: &mut GenCtx, name: String, attrs.push(mk_link_name_attr(ctx, name)); } + let val_ty = P(cty_to_rs(ctx, ty)); + return P(ast::ForeignItem { - ident: ctx.ext_cx.ident_of(&rust_name[..]), - attrs: attrs, - node: ast::ForeignItemStatic(P(cty_to_rs(ctx, ty)), !is_const), - id: ast::DUMMY_NODE_ID, - span: ctx.span, - vis: ast::Public, - }); + ident: ctx.ext_cx.ident_of(&rust_name[..]), + attrs: attrs, + node: ast::ForeignItemStatic(val_ty, !is_const), + id: ast::DUMMY_NODE_ID, + span: ctx.span, + vis: ast::Public, + }); } fn cfuncty_to_rs(ctx: &mut GenCtx, diff --git a/src/parser.rs b/src/parser.rs index ee566124..b8e4e72a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -451,8 +451,37 @@ fn visit_enum(cursor: &Cursor, return CXChildVisit_Continue; } +fn visit_literal(cursor: &Cursor, unit: &TranslationUnit) -> Option<i64> { + if cursor.kind() == CXCursor_IntegerLiteral { + return match unit.tokens(cursor) { + None => None, + Some(tokens) => { + if tokens.len() == 0 || tokens[0].kind != CXToken_Literal { + None + } else { + let ref s = tokens[0].spelling; + let parsed = { + //TODO: try to preserve hex literals? + if s.starts_with("0x") { + i64::from_str_radix(&s[2..], 16) + } else { + s.parse() + } + }; + match parsed { + Ok(i) => Some(i), + Err(_) => None, + } + } + } + } + } + return None; +} + fn visit_top<'r>(cursor: &Cursor, - ctx: &mut ClangParserCtx) -> Enum_CXVisitorResult { + ctx: &mut ClangParserCtx, + unit: &TranslationUnit) -> Enum_CXVisitorResult { if !match_pattern(ctx, cursor) { return CXChildVisit_Continue; } @@ -509,6 +538,10 @@ fn visit_top<'r>(cursor: &Cursor, let mut vi = vi.borrow_mut(); vi.ty = ty.clone(); vi.is_const = cursor.cur_type().is_const(); + cursor.visit(|c, _: &Cursor| { + vi.val = visit_literal(c, unit); + CXChildVisit_Continue + }); ctx.globals.push(var); return CXChildVisit_Continue; @@ -586,11 +619,11 @@ pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<Vec<Global> cursor.visit(|cur, _: &Cursor| ast_dump(cur, 0)); } - cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx)); + cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx, &unit)); while !ctx.builtin_defs.is_empty() { let c = ctx.builtin_defs.remove(0); - visit_top(&c.definition(), &mut ctx); + visit_top(&c.definition(), &mut ctx, &unit); } unit.dispose(); diff --git a/src/types.rs b/src/types.rs index 88b73e51..27cc0b03 100644 --- a/src/types.rs +++ b/src/types.rs @@ -281,6 +281,8 @@ impl fmt::Debug for TypeInfo { pub struct VarInfo { pub name: String, pub ty: Type, + //TODO: support non-integer constants + pub val: Option<i64>, pub is_const: bool } @@ -289,6 +291,7 @@ impl VarInfo { VarInfo { name: name, ty: ty, + val: None, is_const: false } } |