diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index 2e31983e1f..4a90b3dc35 100644 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -18,11 +18,11 @@ struct StdLogger; impl Logger for StdLogger { fn error(&self, msg: &str) { - error!("{}", msg); + println!("{}", msg); } fn warn(&self, msg: &str) { - warn!("{}", msg); + println!("{}", msg); } } @@ -99,6 +99,10 @@ fn parse_args(args: &[String]) -> ParseResult { options.builtins = true; ix += 1; } + "-ignore-functions" => { + options.ignore_functions = true; + ix += 1; + } "-allow-unknown-types" => { options.fail_on_unknown_type = false; ix += 1; @@ -138,6 +142,8 @@ Options: matching any rule are bound to. -builtins Output bindings for builtin definitions (for example __builtin_va_list) + -ignore-functions Don't generate bindings for functions and methods. + This is useful when you only care about struct layouts. -allow-unknown-types Don't fail if we encounter types we do not support, instead treat them as void -emit-clang-ast Output the ast (for debugging purposes) diff --git a/src/gen.rs b/src/gen.rs index ae56e3af97..310db2bddd 100644 --- a/src/gen.rs +++ b/src/gen.rs @@ -24,7 +24,6 @@ use types::*; struct GenCtx<'r> { ext_cx: base::ExtCtxt<'r>, - unnamed_ty: usize, span: Span } @@ -76,32 +75,11 @@ fn rust_type_id(ctx: &mut GenCtx, name: String) -> String { s.push_str(&name); s } else { - match name.as_str() { - "int8_t" => "i8".to_string(), - "uint8_t" => "u8".to_string(), - "int16_t" => "i16".to_string(), - "uint16_t" => "u16".to_string(), - "int32_t" => "i32".to_string(), - "uint32_t" => "u32".to_string(), - "int64_t" => "i64".to_string(), - "uint64_t" => "u64".to_string(), - _ => { - let (n, _) = rust_id(ctx, name); - n - } - } + let (n, _) = rust_id(ctx, name); + n } } -fn unnamed_name(ctx: &mut GenCtx, name: String, filename: String) -> String { - return if name.is_empty() { - ctx.unnamed_ty += 1; - format!("{}_unnamed_{}", filename, ctx.unnamed_ty) - } else { - name - }; -} - fn comp_name(kind: CompKind, name: &String) -> String { match kind { CompKind::Struct => struct_name(name), @@ -262,7 +240,6 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec, span: Span) -> let mut feature_gated_cfgs = vec![]; let mut ctx = GenCtx { ext_cx: base::ExtCtxt::new(sess, Vec::new(), cfg, &mut feature_gated_cfgs), - unnamed_ty: 0, span: span }; ctx.ext_cx.bt_push(ExpnInfo { @@ -312,35 +289,19 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec, span: Span) -> defs.extend(ctypedef_to_rs(&mut ctx, t.name.clone(), t.comment.clone(), &t.ty).into_iter()) }, GCompDecl(ci) => { - { - let mut c = ci.borrow_mut(); - c.name = unnamed_name(&mut ctx, c.name.clone(), c.filename.clone()); - } let c = ci.borrow().clone(); defs.push(opaque_to_rs(&mut ctx, comp_name(c.kind, &c.name))); }, GComp(ci) => { - { - let mut c = ci.borrow_mut(); - c.name = unnamed_name(&mut ctx, c.name.clone(), c.filename.clone()); - } let c = ci.borrow().clone(); defs.extend(comp_to_rs(&mut ctx, comp_name(c.kind, &c.name), c).into_iter()) }, GEnumDecl(ei) => { - { - let mut e = ei.borrow_mut(); - e.name = unnamed_name(&mut ctx, e.name.clone(), e.filename.clone()); - } let e = ei.borrow().clone(); defs.push(opaque_to_rs(&mut ctx, enum_name(&e.name))); }, GEnum(ei) => { - { - let mut e = ei.borrow_mut(); - e.name = unnamed_name(&mut ctx, e.name.clone(), e.filename.clone()); - } let e = ei.borrow().clone(); defs.extend(cenum_to_rs(&mut ctx, enum_name(&e.name), e.comment, e.items, e.layout).into_iter()) }, @@ -671,24 +632,12 @@ fn ctypedef_to_rs(ctx: &mut GenCtx, name: String, comment: String, ty: &Type) -> return match *ty { TComp(ref ci) => { - let is_empty = ci.borrow().name.is_empty(); - if is_empty { - ci.borrow_mut().name = name.clone(); - let c = ci.borrow().clone(); - comp_to_rs(ctx, name, c) - } else { - vec!(mk_item(ctx, name, comment, ty)) - } + assert!(!ci.borrow().name.is_empty()); + vec!(mk_item(ctx, name, comment, ty)) }, TEnum(ref ei) => { - let is_empty = ei.borrow().name.is_empty(); - if is_empty { - ei.borrow_mut().name = name.clone(); - let e = ei.borrow().clone(); - cenum_to_rs(ctx, name, e.comment, e.items, e.layout) - } else { - vec!(mk_item(ctx, name, comment, ty)) - } + assert!(!ei.borrow().name.is_empty()); + vec!(mk_item(ctx, name, comment, ty)) }, _ => vec!(mk_item(ctx, name, comment, ty)) } @@ -810,7 +759,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: String, ci: CompInfo) -> Vec), + ty: quote_ty!(&ctx.ext_cx, ::std::marker::PhantomData<$inner_type>), attrs: vec!(), })); } @@ -1132,10 +1081,18 @@ fn cenum_to_rs(ctx: &mut GenCtx, name: String, comment: String, items: Vec) -> ast::ImplItem { + field_type: &Type, bitfields: &[(String, u32)]) -> ast::ImplItem { let field_type = cty_to_rs(ctx, field_type, false); let mut args = vec!(); + let mut unnamed: usize = 0; for &(ref name, width) in bitfields.iter() { + let ident = if name.is_empty() { + unnamed += 1; + let dummy = format!("unnamed_bitfield{}", unnamed); + ctx.ext_cx.ident_of(&dummy) + } else { + ctx.ext_cx.ident_of(name) + }; args.push(ast::Arg { ty: P(type_for_bitfield_width(ctx, width)), pat: P(ast::Pat { id: ast::DUMMY_NODE_ID, node: ast::PatIdent( ast::BindingMode::ByValue(ast::MutImmutable), - respan(ctx.span, ctx.ext_cx.ident_of(name)), + respan(ctx.span, ident), None ), span: ctx.span @@ -1318,8 +1283,15 @@ fn gen_fullbitfield_method(ctx: &mut GenCtx, bindgen_name: &String, let mut offset = 0; let mut exprs = quote_expr!(&ctx.ext_cx, 0); + let mut unnamed: usize = 0; for &(ref name, width) in bitfields.iter() { - let name_ident = ctx.ext_cx.ident_of(&name); + let name_ident = if name.is_empty() { + unnamed += 1; + let dummy = format!("unnamed_bitfield{}", unnamed); + ctx.ext_cx.ident_of(&dummy) + } else { + ctx.ext_cx.ident_of(name) + }; exprs = quote_expr!(&ctx.ext_cx, $exprs | (($name_ident as $field_type) << $offset) ); @@ -1618,16 +1590,14 @@ fn cty_to_rs(ctx: &mut GenCtx, ty: &Type, allow_bool: bool) -> ast::Ty { mk_ty(ctx, false, vec!(id)) }, &TComp(ref ci) => { - let mut c = ci.borrow_mut(); - c.name = unnamed_name(ctx, c.name.clone(), c.filename.clone()); + let mut c = ci.borrow(); let args = c.args.iter().map(|gt| { P(cty_to_rs(ctx, gt, allow_bool)) }).collect(); mk_ty_args(ctx, false, vec!(comp_name(c.kind, &c.name)), args) }, &TEnum(ref ei) => { - let mut e = ei.borrow_mut(); - e.name = unnamed_name(ctx, e.name.clone(), e.filename.clone()); + let mut e = ei.borrow(); mk_ty(ctx, false, vec!(enum_name(&e.name))) } }; diff --git a/src/lib.rs b/src/lib.rs index cd73860bf0..304b2f881c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,7 @@ pub struct BindgenOptions { pub builtins: bool, pub links: Vec<(String, LinkType)>, pub emit_ast: bool, + pub ignore_functions: bool, pub fail_on_unknown_type: bool, pub override_enum_ty: String, pub clang_args: Vec, @@ -116,6 +117,7 @@ impl Default for BindgenOptions { builtins: false, links: Vec::new(), emit_ast: false, + ignore_functions: false, fail_on_unknown_type: true, override_enum_ty: "".to_string(), clang_args: Vec::new() @@ -224,6 +226,7 @@ fn parse_headers(options: &BindgenOptions, logger: &Logger) -> Result, pub emit_ast: bool, pub fail_on_unknown_type: bool, + pub ignore_functions: bool, pub override_enum_ty: Option, pub clang_args: Vec, } @@ -590,6 +591,10 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, ci.base_members += 1; } CXCursor_CXXMethod => { + if ctx.options.ignore_functions { + return CXChildVisit_Continue; + } + let linkage = cursor.linkage(); if linkage != CXLinkage_External { return CXChildVisit_Continue; diff --git a/src/types.rs b/src/types.rs index 64adeeb32c..7f389462e2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -194,11 +194,22 @@ pub struct CompInfo { pub layout: Layout, } +static mut UNNAMED_COUNTER: u32 = 0; + +fn unnamed_name(name: String, filename: &String) -> String { + return if name.is_empty() { + let n = unsafe { UNNAMED_COUNTER += 1; UNNAMED_COUNTER }; + format!("{}_unnamed_{}", filename, n) + } else { + name + }; +} + impl CompInfo { pub fn new(name: String, filename: String, comment: String, kind: CompKind, members: Vec, layout: Layout) -> CompInfo { CompInfo { kind: kind, - name: name, + name: unnamed_name(name, &filename), filename: filename, comment: comment, members: members, @@ -253,7 +264,7 @@ pub struct EnumInfo { impl EnumInfo { pub fn new(name: String, filename: String, kind: IKind, items: Vec, layout: Layout) -> EnumInfo { EnumInfo { - name: name, + name: unnamed_name(name, &filename), comment: String::new(), filename: filename, items: items, diff --git a/tests/support.rs b/tests/support.rs index a83bbc0230..f2a5abb14a 100644 --- a/tests/support.rs +++ b/tests/support.rs @@ -38,7 +38,7 @@ pub fn assert_bind_eq(filename: &str, reference_items_str: &str) 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(); - while let Some(item) = parser.parse_item() { + while let Ok(Some(item)) = parser.parse_item() { reference_items.push(item); } @@ -47,7 +47,7 @@ pub fn assert_bind_eq(filename: &str, reference_items_str: &str) // rendered versions, which is not beautiful, but should work. let reference_rendered = render_items(&reference_items); let generated_rendered = render_items(&generated_items); - + if reference_rendered != generated_rendered { println!("Generated bindings for {} do not match the reference bindings.", filename); println!("");