Skip to content

Commit 5affca0

Browse files
committed
Merge pull request rust-lang#280 from nox/rust-enums
Introduce -no-rust-enums (fixes rust-lang#276)
2 parents 3d418de + 4b931e7 commit 5affca0

File tree

11 files changed

+176
-73
lines changed

11 files changed

+176
-73
lines changed

src/bin/bindgen.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ fn parse_args(args: &[String]) -> ParseResult {
9797
options.builtins = true;
9898
ix += 1;
9999
}
100+
"-no-rust-enums" => {
101+
options.rust_enums = false;
102+
ix += 1;
103+
}
100104
"-allow-unknown-types" => {
101105
options.fail_on_unknown_type = false;
102106
ix += 1;

src/gen.rs

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use syntax::attr::mk_attr_id;
2020
use syntax::ptr::P;
2121
use syntax::print::pprust::tts_to_string;
2222

23-
use super::LinkType;
23+
use super::{BindgenOptions, LinkType};
2424
use types::*;
2525

2626
struct GenCtx<'r> {
@@ -115,7 +115,11 @@ fn enum_name(name: &str) -> String {
115115
format!("Enum_{}", name)
116116
}
117117

118-
pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> Vec<P<ast::Item>> {
118+
pub fn gen_mod(
119+
options: &BindgenOptions,
120+
globs: Vec<Global>,
121+
span: Span)
122+
-> Vec<P<ast::Item>> {
119123
// Create a dummy ExtCtxt. We only need this for string interning and that uses TLS.
120124
let mut features = Features::new();
121125
features.allow_quote = true;
@@ -180,8 +184,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) ->
180184
for g in gs.into_iter() {
181185
match g {
182186
GType(ti) => {
183-
let t = ti.borrow().clone();
184-
defs.extend(ctypedef_to_rs(&mut ctx, t.name.clone(), &t.ty).into_iter())
187+
let t = ti.borrow();
188+
defs.extend(ctypedef_to_rs(
189+
&mut ctx,
190+
options.rust_enums,
191+
t.name.clone(), &t.ty))
185192
},
186193
GCompDecl(ci) => {
187194
{
@@ -214,7 +221,10 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) ->
214221
e.name = unnamed_name(&mut ctx, e.name.clone());
215222
}
216223
let e = ei.borrow();
217-
defs.extend(cenum_to_rs(&mut ctx, enum_name(&e.name), e.kind, e.layout, &e.items).into_iter())
224+
defs.extend(cenum_to_rs(
225+
&mut ctx,
226+
options.rust_enums,
227+
enum_name(&e.name), e.kind, e.layout, &e.items));
218228
},
219229
GVar(vi) => {
220230
let v = vi.borrow();
@@ -269,11 +279,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) ->
269279
};
270280

271281
if !Vec::is_empty(&vars) {
272-
defs.push(mk_extern(&mut ctx, links, vars, abi::Abi::C));
282+
defs.push(mk_extern(&mut ctx, &options.links, vars, abi::Abi::C));
273283
}
274284

275285
for (abi, funcs) in funcs.into_iter() {
276-
defs.push(mk_extern(&mut ctx, links, funcs, abi));
286+
defs.push(mk_extern(&mut ctx, &options.links, funcs, abi));
277287
}
278288

279289
//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> {
439449
res
440450
}
441451

442-
fn ctypedef_to_rs(ctx: &mut GenCtx, name: String, ty: &Type) -> Vec<P<ast::Item>> {
452+
fn ctypedef_to_rs(
453+
ctx: &mut GenCtx,
454+
rust_enums: bool,
455+
name: String,
456+
ty: &Type)
457+
-> Vec<P<ast::Item>> {
443458
fn mk_item(ctx: &mut GenCtx, name: String, ty: &Type) -> P<ast::Item> {
444459
let rust_name = rust_type_id(ctx, name);
445460
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>
478493
if is_empty {
479494
ei.borrow_mut().name = name.clone();
480495
let e = ei.borrow();
481-
cenum_to_rs(ctx, name, e.kind, e.layout, &e.items)
496+
cenum_to_rs(ctx, rust_enums, name, e.kind, e.layout, &e.items)
482497
} else {
483498
vec!(mk_item(ctx, name, ty))
484499
}
@@ -700,22 +715,6 @@ fn const_to_rs(ctx: &mut GenCtx, name: String, val: i64, val_ty: ast::Ty) -> P<a
700715
})
701716
}
702717

703-
fn enum_kind_is_signed(kind: IKind) -> bool {
704-
match kind {
705-
IBool => false,
706-
ISChar => true,
707-
IUChar => false,
708-
IShort => true,
709-
IUShort => false,
710-
IInt => true,
711-
IUInt => false,
712-
ILong => true,
713-
IULong => false,
714-
ILongLong => true,
715-
IULongLong => false,
716-
}
717-
}
718-
719718
fn enum_size_to_rust_type_name(signed: bool, size: usize) -> &'static str {
720719
match (signed, size) {
721720
(true, 1) => "i8",
@@ -765,20 +764,41 @@ fn cenum_value_to_int_lit(
765764
}
766765
}
767766

768-
769-
fn cenum_to_rs(ctx: &mut GenCtx,
770-
name: String,
771-
kind: IKind,
772-
layout: Layout,
773-
enum_items: &[EnumItem])
774-
-> Vec<P<ast::Item>> {
767+
fn cenum_to_rs(
768+
ctx: &mut GenCtx,
769+
rust_enums: bool,
770+
name: String,
771+
kind: IKind,
772+
layout: Layout,
773+
enum_items: &[EnumItem])
774+
-> Vec<P<ast::Item>> {
775775
let enum_name = ctx.ext_cx.ident_of(&name);
776776
let enum_ty = ctx.ext_cx.ty_ident(ctx.span, enum_name);
777-
let enum_is_signed = enum_kind_is_signed(kind);
777+
let enum_is_signed = kind.is_signed();
778+
let enum_repr = enum_size_to_rust_type_name(enum_is_signed, layout.size);
779+
let mut items = vec![];
780+
781+
if !rust_enums {
782+
items.push(ctx.ext_cx.item_ty(
783+
ctx.span,
784+
enum_name,
785+
ctx.ext_cx.ty_ident(
786+
ctx.span,
787+
ctx.ext_cx.ident_of(enum_repr))));
788+
for item in enum_items {
789+
let value = cenum_value_to_int_lit(
790+
ctx, enum_is_signed, layout.size, item.val);
791+
items.push(ctx.ext_cx.item_const(
792+
ctx.span,
793+
ctx.ext_cx.ident_of(&item.name),
794+
enum_ty.clone(),
795+
value));
796+
}
797+
return items;
798+
}
778799

779800
let mut variants = vec![];
780801
let mut found_values = HashMap::new();
781-
let mut items = vec![];
782802

783803
for item in enum_items {
784804
let name = ctx.ext_cx.ident_of(&item.name);
@@ -810,7 +830,7 @@ fn cenum_to_rs(ctx: &mut GenCtx,
810830
}));
811831
}
812832

813-
let enum_repr = InternedString::new(enum_size_to_rust_type_name(enum_is_signed, layout.size));
833+
let enum_repr = InternedString::new(enum_repr);
814834

815835
let repr_arg = ctx.ext_cx.meta_word(ctx.span, enum_repr);
816836
let repr_list = ctx.ext_cx.meta_list(ctx.span, InternedString::new("repr"), vec![repr_arg]);

src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ impl<'a> Builder<'a> {
7676
self
7777
}
7878

79+
pub fn rust_enums(&mut self, value: bool) -> &mut Self {
80+
self.options.rust_enums = value;
81+
self
82+
}
83+
7984
pub fn log(&mut self, logger: &'a Logger) -> &mut Self {
8085
self.logger = Some(logger);
8186
self
@@ -100,6 +105,7 @@ impl<'a> Default for Builder<'a> {
100105
pub struct BindgenOptions {
101106
pub match_pat: Vec<String>,
102107
pub builtins: bool,
108+
pub rust_enums: bool,
103109
pub links: Vec<(String, LinkType)>,
104110
pub emit_ast: bool,
105111
pub fail_on_unknown_type: bool,
@@ -112,6 +118,7 @@ impl Default for BindgenOptions {
112118
BindgenOptions {
113119
match_pat: Vec::new(),
114120
builtins: false,
121+
rust_enums: true,
115122
links: Vec::new(),
116123
emit_ast: false,
117124
fail_on_unknown_type: false,
@@ -159,7 +166,7 @@ impl Bindings {
159166

160167
let module = ast::Mod {
161168
inner: span,
162-
items: gen::gen_mod(&options.links[..], globals, span)
169+
items: gen::gen_mod(options, globals, span)
163170
};
164171

165172
Ok(Bindings {

src/types.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,24 @@ pub enum IKind {
174174
IULongLong
175175
}
176176

177+
impl IKind {
178+
pub fn is_signed(self) -> bool {
179+
match self {
180+
IBool => false,
181+
ISChar => true,
182+
IUChar => false,
183+
IShort => true,
184+
IUShort => false,
185+
IInt => true,
186+
IUInt => false,
187+
ILong => true,
188+
IULong => false,
189+
ILongLong => true,
190+
IULongLong => false,
191+
}
192+
}
193+
}
194+
177195
#[derive(Copy, Clone, PartialEq)]
178196
pub enum FKind {
179197
FFloat,

tests/support.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use bindgen;
22
use bindgen::{Logger, BindgenOptions};
33

4-
use std::default::Default;
5-
64
use syntax::ast;
75
use syntax::codemap;
86
use syntax::codemap::DUMMY_SP;
@@ -23,8 +21,9 @@ impl Logger for TestLogger {
2321
}
2422
}
2523

26-
pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> {
27-
let mut options:BindgenOptions = Default::default();
24+
pub fn generate_bindings(mut options: BindgenOptions,
25+
filename: &str)
26+
-> Result<Vec<P<ast::Item>>, ()> {
2827
if filename.ends_with("hpp") {
2928
options.clang_args.push("-std=c++11".to_string());
3029
options.clang_args.push("-Wno-narrowing".to_string());
@@ -35,10 +34,12 @@ pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> {
3534
Ok(try!(bindgen::Bindings::generate(&options, Some(&logger as &Logger), None)).into_ast())
3635
}
3736

38-
pub fn assert_bind_eq(filename: &str, reference_items_str: &str)
39-
{
37+
pub fn assert_bind_eq(options: BindgenOptions,
38+
filename: &str,
39+
reference_items_str: &str) {
4040
let ext_cx = mk_dummy_ext_ctxt();
41-
let generated_items = generate_bindings(&format!("tests/{}", filename)[..]).unwrap();
41+
let generated_items =
42+
generate_bindings(options, &format!("tests/{}", filename)[..]).unwrap();
4243

4344
let mut parser = parse::new_parser_from_source_str(ext_cx.parse_sess(), ext_cx.cfg(), "".to_string(), reference_items_str.to_string());
4445
let mut reference_items = Vec::new();

tests/test_decl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use support::assert_bind_eq;
22

33
#[test]
44
fn ptr_to_array() {
5-
assert_bind_eq("headers/decl_ptr_to_array.h", "
5+
assert_bind_eq(Default::default(), "headers/decl_ptr_to_array.h", "
66
extern \"C\" {
77
pub static mut foo: [::std::os::raw::c_int; 1usize];
88
}

0 commit comments

Comments
 (0)