diff options
-rw-r--r-- | src/bin/bindgen.rs | 4 | ||||
-rw-r--r-- | src/gen.rs | 72 | ||||
-rw-r--r-- | src/lib.rs | 9 | ||||
-rw-r--r-- | tests/support.rs | 15 | ||||
-rw-r--r-- | tests/test_decl.rs | 2 | ||||
-rw-r--r-- | tests/test_enum.rs | 63 | ||||
-rw-r--r-- | tests/test_extern.rs | 2 | ||||
-rw-r--r-- | tests/test_func.rs | 10 | ||||
-rw-r--r-- | tests/test_struct.rs | 24 | ||||
-rw-r--r-- | tests/test_union.rs | 12 |
10 files changed, 157 insertions, 56 deletions
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index d4593a5e..fe17b2f6 100644 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -97,6 +97,10 @@ fn parse_args(args: &[String]) -> ParseResult { options.builtins = true; ix += 1; } + "-no-rust-enums" => { + options.rust_enums = false; + ix += 1; + } "-allow-unknown-types" => { options.fail_on_unknown_type = false; ix += 1; @@ -20,7 +20,7 @@ use syntax::attr::mk_attr_id; use syntax::ptr::P; use syntax::print::pprust::tts_to_string; -use super::LinkType; +use super::{BindgenOptions, LinkType}; use types::*; struct GenCtx<'r> { @@ -115,7 +115,11 @@ fn enum_name(name: &str) -> String { format!("Enum_{}", name) } -pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> Vec<P<ast::Item>> { +pub fn gen_mod( + options: &BindgenOptions, + globs: Vec<Global>, + span: Span) + -> Vec<P<ast::Item>> { // Create a dummy ExtCtxt. We only need this for string interning and that uses TLS. let mut features = Features::new(); features.allow_quote = true; @@ -180,8 +184,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> for g in gs.into_iter() { match g { GType(ti) => { - let t = ti.borrow().clone(); - defs.extend(ctypedef_to_rs(&mut ctx, t.name.clone(), &t.ty).into_iter()) + let t = ti.borrow(); + defs.extend(ctypedef_to_rs( + &mut ctx, + options.rust_enums, + t.name.clone(), &t.ty)) }, GCompDecl(ci) => { { @@ -214,7 +221,10 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> e.name = unnamed_name(&mut ctx, e.name.clone()); } let e = ei.borrow(); - defs.extend(cenum_to_rs(&mut ctx, enum_name(&e.name), e.kind, e.layout, &e.items).into_iter()) + defs.extend(cenum_to_rs( + &mut ctx, + options.rust_enums, + enum_name(&e.name), e.kind, e.layout, &e.items)); }, GVar(vi) => { let v = vi.borrow(); @@ -269,11 +279,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> }; if !Vec::is_empty(&vars) { - defs.push(mk_extern(&mut ctx, links, vars, abi::Abi::C)); + defs.push(mk_extern(&mut ctx, &options.links, vars, abi::Abi::C)); } for (abi, funcs) in funcs.into_iter() { - defs.push(mk_extern(&mut ctx, links, funcs, abi)); + defs.push(mk_extern(&mut ctx, &options.links, funcs, abi)); } //let attrs = vec!(mk_attr_list(&mut ctx, "allow", ["dead_code", "non_camel_case_types", "uppercase_variables"])); @@ -439,7 +449,12 @@ fn tag_dup_decl(gs: Vec<Global>) -> Vec<Global> { res } -fn ctypedef_to_rs(ctx: &mut GenCtx, name: String, ty: &Type) -> Vec<P<ast::Item>> { +fn ctypedef_to_rs( + ctx: &mut GenCtx, + rust_enums: bool, + name: String, + ty: &Type) + -> Vec<P<ast::Item>> { fn mk_item(ctx: &mut GenCtx, name: String, ty: &Type) -> P<ast::Item> { let rust_name = rust_type_id(ctx, name); let rust_ty = cty_to_rs(ctx, ty); @@ -478,7 +493,7 @@ fn ctypedef_to_rs(ctx: &mut GenCtx, name: String, ty: &Type) -> Vec<P<ast::Item> if is_empty { ei.borrow_mut().name = name.clone(); let e = ei.borrow(); - cenum_to_rs(ctx, name, e.kind, e.layout, &e.items) + cenum_to_rs(ctx, rust_enums, name, e.kind, e.layout, &e.items) } else { vec!(mk_item(ctx, name, ty)) } @@ -749,20 +764,41 @@ fn cenum_value_to_int_lit( } } - -fn cenum_to_rs(ctx: &mut GenCtx, - name: String, - kind: IKind, - layout: Layout, - enum_items: &[EnumItem]) - -> Vec<P<ast::Item>> { +fn cenum_to_rs( + ctx: &mut GenCtx, + rust_enums: bool, + name: String, + kind: IKind, + layout: Layout, + enum_items: &[EnumItem]) + -> Vec<P<ast::Item>> { let enum_name = ctx.ext_cx.ident_of(&name); let enum_ty = ctx.ext_cx.ty_ident(ctx.span, enum_name); let enum_is_signed = kind.is_signed(); + let enum_repr = enum_size_to_rust_type_name(enum_is_signed, layout.size); + let mut items = vec![]; + + if !rust_enums { + items.push(ctx.ext_cx.item_ty( + ctx.span, + enum_name, + ctx.ext_cx.ty_ident( + ctx.span, + ctx.ext_cx.ident_of(enum_repr)))); + for item in enum_items { + let value = cenum_value_to_int_lit( + ctx, enum_is_signed, layout.size, item.val); + items.push(ctx.ext_cx.item_const( + ctx.span, + ctx.ext_cx.ident_of(&item.name), + enum_ty.clone(), + value)); + } + return items; + } let mut variants = vec![]; let mut found_values = HashMap::new(); - let mut items = vec![]; for item in enum_items { let name = ctx.ext_cx.ident_of(&item.name); @@ -794,7 +830,7 @@ fn cenum_to_rs(ctx: &mut GenCtx, })); } - let enum_repr = InternedString::new(enum_size_to_rust_type_name(enum_is_signed, layout.size)); + let enum_repr = InternedString::new(enum_repr); let repr_arg = ctx.ext_cx.meta_word(ctx.span, enum_repr); let repr_list = ctx.ext_cx.meta_list(ctx.span, InternedString::new("repr"), vec![repr_arg]); @@ -76,6 +76,11 @@ impl<'a> Builder<'a> { self } + pub fn rust_enums(&mut self, value: bool) -> &mut Self { + self.options.rust_enums = value; + self + } + pub fn log(&mut self, logger: &'a Logger) -> &mut Self { self.logger = Some(logger); self @@ -100,6 +105,7 @@ impl<'a> Default for Builder<'a> { pub struct BindgenOptions { pub match_pat: Vec<String>, pub builtins: bool, + pub rust_enums: bool, pub links: Vec<(String, LinkType)>, pub emit_ast: bool, pub fail_on_unknown_type: bool, @@ -112,6 +118,7 @@ impl Default for BindgenOptions { BindgenOptions { match_pat: Vec::new(), builtins: false, + rust_enums: true, links: Vec::new(), emit_ast: false, fail_on_unknown_type: false, @@ -159,7 +166,7 @@ impl Bindings { let module = ast::Mod { inner: span, - items: gen::gen_mod(&options.links[..], globals, span) + items: gen::gen_mod(options, globals, span) }; Ok(Bindings { diff --git a/tests/support.rs b/tests/support.rs index 620a8429..a82529fe 100644 --- a/tests/support.rs +++ b/tests/support.rs @@ -1,8 +1,6 @@ use bindgen; use bindgen::{Logger, BindgenOptions}; -use std::default::Default; - use syntax::ast; use syntax::codemap; use syntax::codemap::DUMMY_SP; @@ -23,8 +21,9 @@ impl Logger for TestLogger { } } -pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> { - let mut options:BindgenOptions = Default::default(); +pub fn generate_bindings(mut options: BindgenOptions, + filename: &str) + -> Result<Vec<P<ast::Item>>, ()> { if filename.ends_with("hpp") { options.clang_args.push("-std=c++11".to_string()); options.clang_args.push("-Wno-narrowing".to_string()); @@ -35,10 +34,12 @@ pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> { Ok(try!(bindgen::Bindings::generate(&options, Some(&logger as &Logger), None)).into_ast()) } -pub fn assert_bind_eq(filename: &str, reference_items_str: &str) -{ +pub fn assert_bind_eq(options: BindgenOptions, + filename: &str, + reference_items_str: &str) { let ext_cx = mk_dummy_ext_ctxt(); - let generated_items = generate_bindings(&format!("tests/{}", filename)[..]).unwrap(); + let generated_items = + generate_bindings(options, &format!("tests/{}", filename)[..]).unwrap(); let mut parser = parse::new_parser_from_source_str(ext_cx.parse_sess(), ext_cx.cfg(), "".to_string(), reference_items_str.to_string()); let mut reference_items = Vec::new(); diff --git a/tests/test_decl.rs b/tests/test_decl.rs index 22cba6c5..6858d416 100644 --- a/tests/test_decl.rs +++ b/tests/test_decl.rs @@ -2,7 +2,7 @@ use support::assert_bind_eq; #[test] fn ptr_to_array() { - assert_bind_eq("headers/decl_ptr_to_array.h", " + assert_bind_eq(Default::default(), "headers/decl_ptr_to_array.h", " extern \"C\" { pub static mut foo: [::std::os::raw::c_int; 1usize]; } diff --git a/tests/test_enum.rs b/tests/test_enum.rs index 66cde668..bde750a6 100644 --- a/tests/test_enum.rs +++ b/tests/test_enum.rs @@ -1,8 +1,13 @@ +use bindgen::BindgenOptions; use support::assert_bind_eq; +fn default_without_rust_enums() -> BindgenOptions { + BindgenOptions { rust_enums: false, .. Default::default() } +} + #[test] fn with_simple_enum() { - assert_bind_eq("headers/enum.h", " + assert_bind_eq(Default::default(), "headers/enum.h", " #[derive(Clone, Copy)] #[repr(u32)] pub enum Enum_Foo { Bar = 0, Qux = 1, } @@ -10,11 +15,19 @@ fn with_simple_enum() { #[repr(i32)] pub enum Enum_Neg { MinusOne = -1, One = 1, } "); + assert_bind_eq(default_without_rust_enums(), "headers/enum.h", " + type Enum_Foo = u32; + const Bar: Enum_Foo = 0; + const Qux: Enum_Foo = 1; + type Enum_Neg = i32; + const MinusOne: Enum_Neg = -1; + const One: Enum_Neg = 1; + "); } #[test] fn with_packed_enums() { - assert_bind_eq("headers/enum_packed.h", " + assert_bind_eq(Default::default(), "headers/enum_packed.h", " #[derive(Clone, Copy)] #[repr(u8)] pub enum Enum_Foo { Bar = 0, Qux = 1, } @@ -25,21 +38,37 @@ fn with_packed_enums() { #[repr(u16)] pub enum Enum_Bigger { Much = 255, Larger = 256, } "); + assert_bind_eq(default_without_rust_enums(), "headers/enum_packed.h", " + type Enum_Foo = u8; + const Bar: Enum_Foo = 0; + const Qux: Enum_Foo = 1; + type Enum_Neg = i8; + const MinusOne: Enum_Neg = -1; + const One: Enum_Neg = 1; + type Enum_Bigger = u16; + const Much: Enum_Bigger = 255; + const Larger: Enum_Bigger = 256; + "); } #[test] fn with_duplicate_enum_value() { - assert_bind_eq("headers/enum_dupe.h", " + assert_bind_eq(Default::default(), "headers/enum_dupe.h", " pub const Dupe: Enum_Foo = Enum_Foo::Bar; #[derive(Clone, Copy)] #[repr(u32)] pub enum Enum_Foo { Bar = 1, } "); + assert_bind_eq(default_without_rust_enums(), "headers/enum_dupe.h", " + type Enum_Foo = u32; + const Bar: Enum_Foo = 1; + const Dupe: Enum_Foo = 1; + "); } #[test] fn with_explicitly_typed_cxx_enum() { - assert_bind_eq("headers/enum_explicit_type.hpp", " + assert_bind_eq(Default::default(), "headers/enum_explicit_type.hpp", " #[derive(Clone, Copy)] #[repr(u8)] pub enum Enum_Foo { Bar = 0, Qux = 1, } @@ -56,11 +85,26 @@ fn with_explicitly_typed_cxx_enum() { #[repr(u64)] pub enum Enum_MuchLongLong { MuchHigh = 4294967296, } "); + assert_bind_eq(default_without_rust_enums(), "headers/enum_explicit_type.hpp", " + type Enum_Foo = u8; + const Bar: Enum_Foo = 0; + const Qux: Enum_Foo = 1; + type Enum_Neg = i8; + const MinusOne: Enum_Neg = -1; + const One: Enum_Neg = 1; + type Enum_Bigger = u16; + const Much: Enum_Bigger = 255; + const Larger: Enum_Bigger = 256; + type Enum_MuchLong = i64; + const MuchLow: Enum_MuchLong = -4294967296; + type Enum_MuchLongLong = u64; + const MuchHigh: Enum_MuchLongLong = 4294967296; + "); } #[test] fn with_overflowed_enum_value() { - assert_bind_eq("headers/overflowed_enum.hpp", " + assert_bind_eq(Default::default(), "headers/overflowed_enum.hpp", " #[derive(Clone, Copy)] #[repr(u32)] pub enum Enum_Foo { @@ -72,4 +116,13 @@ fn with_overflowed_enum_value() { #[repr(u16)] pub enum Enum_Bar { One = 1, Big = 2, } "); + assert_bind_eq(default_without_rust_enums(), "headers/overflowed_enum.hpp", " + type Enum_Foo = u32; + const BAP_ARM: Enum_Foo = 9698489; + const BAP_X86: Enum_Foo = 11960045; + const BAP_X86_64: Enum_Foo = 3128633167; + type Enum_Bar = u16; + const One: Enum_Bar = 1; + const Big: Enum_Bar = 2; + "); } diff --git a/tests/test_extern.rs b/tests/test_extern.rs index c39e8a59..25b06f0a 100644 --- a/tests/test_extern.rs +++ b/tests/test_extern.rs @@ -2,7 +2,7 @@ use support::assert_bind_eq; #[test] fn extern_c_in_hpp() { - assert_bind_eq("headers/extern.hpp", " + assert_bind_eq(Default::default(), "headers/extern.hpp", " pub type foo = extern \"C\" fn(bar: ::std::os::raw::c_int) -> ::std::os::raw::c_int; "); } diff --git a/tests/test_func.rs b/tests/test_func.rs index 4260ad16..e0b80d68 100644 --- a/tests/test_func.rs +++ b/tests/test_func.rs @@ -2,7 +2,7 @@ use support::assert_bind_eq; #[test] fn func_ptr() { - assert_bind_eq("headers/func_ptr.h", " + assert_bind_eq(Default::default(), "headers/func_ptr.h", " extern \"C\" { pub static mut foo: ::std::option::Option< extern \"C\" fn(x: ::std::os::raw::c_int, @@ -13,7 +13,7 @@ fn func_ptr() { #[test] fn func_ptr_in_struct() { - assert_bind_eq("headers/func_ptr_in_struct.h", " + assert_bind_eq(Default::default(), "headers/func_ptr_in_struct.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -35,14 +35,14 @@ fn func_ptr_in_struct() { #[test] fn func_proto() { - assert_bind_eq("headers/func_proto.h", " + assert_bind_eq(Default::default(), "headers/func_proto.h", " pub type foo = extern \"C\" fn(bar: ::std::os::raw::c_int) -> ::std::os::raw::c_int; "); } #[test] fn with_func_ptr_arg() { - assert_bind_eq("headers/func_with_func_ptr_arg.h", " + assert_bind_eq(Default::default(), "headers/func_with_func_ptr_arg.h", " extern \"C\" { pub fn foo(bar: ::std::option::Option<extern \"C\" fn()>); } @@ -51,7 +51,7 @@ fn with_func_ptr_arg() { #[test] fn with_array_arg() { - assert_bind_eq("headers/func_with_array_arg.h", " + assert_bind_eq(Default::default(), "headers/func_with_array_arg.h", " extern \"C\" { pub fn f(x: *mut ::std::os::raw::c_int); } diff --git a/tests/test_struct.rs b/tests/test_struct.rs index 7c24f94d..4539be83 100644 --- a/tests/test_struct.rs +++ b/tests/test_struct.rs @@ -2,7 +2,7 @@ use support::assert_bind_eq; #[test] fn with_anon_struct() { - assert_bind_eq("headers/struct_with_anon_struct.h", " + assert_bind_eq(Default::default(), "headers/struct_with_anon_struct.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -33,7 +33,7 @@ fn with_anon_struct() { #[test] fn with_anon_struct_array() { - assert_bind_eq("headers/struct_with_anon_struct_array.h", " + assert_bind_eq(Default::default(), "headers/struct_with_anon_struct_array.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -86,7 +86,7 @@ fn with_anon_struct_array() { #[test] fn with_anon_struct_pointer() { - assert_bind_eq("headers/struct_with_anon_struct_pointer.h", " + assert_bind_eq(Default::default(), "headers/struct_with_anon_struct_pointer.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -117,7 +117,7 @@ fn with_anon_struct_pointer() { #[test] fn with_anon_union() { - assert_bind_eq("headers/struct_with_anon_union.h", " + assert_bind_eq(Default::default(), "headers/struct_with_anon_union.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -156,7 +156,7 @@ fn with_anon_union() { #[test] fn with_anon_unnamed_struct() { - assert_bind_eq("headers/struct_with_anon_unnamed_struct.h", " + assert_bind_eq(Default::default(), "headers/struct_with_anon_unnamed_struct.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -184,7 +184,7 @@ fn with_anon_unnamed_struct() { #[test] fn with_anon_unnamed_union() { - assert_bind_eq("headers/struct_with_anon_unnamed_union.h", " + assert_bind_eq(Default::default(), "headers/struct_with_anon_unnamed_union.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -212,7 +212,7 @@ fn with_anon_unnamed_union() { #[test] fn with_nesting() { - assert_bind_eq("headers/struct_with_nesting.h", " + assert_bind_eq(Default::default(), "headers/struct_with_nesting.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -261,7 +261,7 @@ fn with_nesting() { #[test] fn containing_fwd_decl_struct() { - assert_bind_eq("headers/struct_containing_forward_declared_struct.h", " + assert_bind_eq(Default::default(), "headers/struct_containing_forward_declared_struct.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -296,7 +296,7 @@ fn containing_fwd_decl_struct() { #[test] fn with_bitfields() { - assert_bind_eq("headers/struct_with_bitfields.h", " + assert_bind_eq(Default::default(), "headers/struct_with_bitfields.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -319,7 +319,7 @@ fn with_bitfields() { #[test] fn with_fwd_decl_struct() { - assert_bind_eq("headers/forward_declared_struct.h", " + assert_bind_eq(Default::default(), "headers/forward_declared_struct.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] @@ -350,7 +350,7 @@ fn with_fwd_decl_struct() { #[test] fn packed_struct() { - assert_bind_eq("headers/struct_with_packing.h", " + assert_bind_eq(Default::default(), "headers/struct_with_packing.h", " #[repr(C, packed)] #[derive(Copy)] #[derive(Debug)] @@ -369,7 +369,7 @@ fn packed_struct() { #[test] fn derive_debug_big_array() { - assert_bind_eq("headers/struct_with_derive_debug.h", " + assert_bind_eq(Default::default(), "headers/struct_with_derive_debug.h", " #[repr(C)] #[derive(Copy)] #[derive(Debug)] diff --git a/tests/test_union.rs b/tests/test_union.rs index 011440a7..2e1869ac 100644 --- a/tests/test_union.rs +++ b/tests/test_union.rs @@ -2,7 +2,7 @@ use support::assert_bind_eq; #[test] fn with_anon_struct() { - assert_bind_eq("headers/union_with_anon_struct.h", " + assert_bind_eq(Default::default(), "headers/union_with_anon_struct.h", " #[repr(C)] #[derive(Copy)] pub struct Union_foo { @@ -38,7 +38,7 @@ fn with_anon_struct() { #[test] fn with_anon_struct_bitfield() { - assert_bind_eq("headers/union_with_anon_struct_bitfield.h", " + assert_bind_eq(Default::default(), "headers/union_with_anon_struct_bitfield.h", " #[repr(C)] #[derive(Copy)] pub struct Union_foo { @@ -64,7 +64,7 @@ fn with_anon_struct_bitfield() { #[test] fn with_anon_union() { - assert_bind_eq("headers/union_with_anon_union.h", " + assert_bind_eq(Default::default(), "headers/union_with_anon_union.h", " #[repr(C)] #[derive(Copy)] pub struct Union_foo { @@ -108,7 +108,7 @@ fn with_anon_union() { #[test] fn with_anon_unnamed_struct() { - assert_bind_eq("headers/union_with_anon_unnamed_struct.h", " + assert_bind_eq(Default::default(), "headers/union_with_anon_unnamed_struct.h", " #[repr(C)] #[derive(Copy)] pub struct Union_pixel { @@ -147,7 +147,7 @@ fn with_anon_unnamed_struct() { #[test] fn with_anon_unnamed_union() { - assert_bind_eq("headers/union_with_anon_unnamed_union.h", " + assert_bind_eq(Default::default(), "headers/union_with_anon_unnamed_union.h", " #[repr(C)] #[derive(Copy)] pub struct Union_foo { @@ -178,7 +178,7 @@ fn with_anon_unnamed_union() { #[test] fn with_nesting() { - assert_bind_eq("headers/union_with_nesting.h", " + assert_bind_eq(Default::default(), "headers/union_with_nesting.h", " #[repr(C)] #[derive(Copy)] pub struct Union_foo { |