diff options
author | Edward Barnard <eabarnard@gmail.com> | 2014-12-23 20:46:13 +0100 |
---|---|---|
committer | Edward Barnard <eabarnard@gmail.com> | 2014-12-23 20:46:13 +0100 |
commit | fbdb913b31d572bf9c67ec080b73aafe42db7e3e (patch) | |
tree | 5f6cf85b66cf39b643c19f27226388fcf4072177 | |
parent | a4ec65f0484f11ed8a1aea7b96d25882b8302c67 (diff) |
Improve public api
-rw-r--r-- | src/bin/bindgen.rs | 49 | ||||
-rw-r--r-- | src/gen.rs | 14 | ||||
-rw-r--r-- | src/lib.rs | 82 | ||||
-rw-r--r-- | src/macro.rs | 14 | ||||
-rw-r--r-- | tests/util.rs | 2 |
5 files changed, 101 insertions, 60 deletions
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index a0a189d2..01ed456c 100644 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -6,14 +6,10 @@ extern crate bindgen; #[phase(plugin, link)] extern crate log; extern crate syntax; -use bindgen::{Logger, generate_bindings, BindgenOptions}; +use bindgen::{Bindings, BindgenOptions, LinkType, Logger}; use std::{io, os, path}; use std::default::Default; -use std::io::{fs, IoResult}; -use syntax::ast; -use syntax::codemap::DUMMY_SP; -use syntax::print::pprust; -use syntax::print::pp::eof; +use std::io::fs; struct StdLogger; @@ -46,7 +42,7 @@ fn parse_args(args: &[String]) -> ParseResult { let mut ix = 0u; while ix < args_len { if args[ix].len() > 2 && args[ix].as_slice().slice_to(2) == "-l" { - options.links.push((args[ix].as_slice().slice_from(2).to_string(), None)); + options.links.push((args[ix].as_slice().slice_from(2).to_string(), LinkType::Default)); ix += 1u; } else { match args[ix].as_slice() { @@ -72,21 +68,21 @@ fn parse_args(args: &[String]) -> ParseResult { if ix + 1u >= args_len { return ParseResult::ParseErr("Missing link name".to_string()); } - options.links.push((args[ix + 1u].clone(), None)); + options.links.push((args[ix + 1u].clone(), LinkType::Default)); ix += 2u; } "-static-link" => { if ix + 1u >= args_len { return ParseResult::ParseErr("Missing link name".to_string()); } - options.links.push((args[ix + 1u].clone(), Some("static".to_string()))); + options.links.push((args[ix + 1u].clone(), LinkType::Static)); ix += 2u; } "-framework-link" => { if ix + 1u >= args_len { return ParseResult::ParseErr("Missing link name".to_string()); } - options.links.push((args[ix + 1u].clone(), Some("framework".to_string()))); + options.links.push((args[ix + 1u].clone(), LinkType::Framework)); ix += 2u; } "-match" => { @@ -166,17 +162,6 @@ Options: io::stdio::print(s.as_slice()); } -fn try_pprint(module: &ast::Mod, out: Box<io::Writer+'static>) -> IoResult<()> { - let mut ps = pprust::rust_printer(out); - try!(ps.s.out.write("/* automatically generated by rust-bindgen */\n\n".as_bytes())); - - try!(ps.print_mod(module, &[])); - try!(ps.print_remaining_comments()); - try!(eof(&mut ps.s)); - - ps.s.out.flush() -} - #[main] pub fn main() { let mut bind_args = os::args(); @@ -185,22 +170,14 @@ pub fn main() { match parse_args(bind_args.as_slice()) { ParseResult::ParseErr(e) => panic!(e), ParseResult::CmdUsage => print_usage(bin), - ParseResult::ParseOk(options, out) => { + ParseResult::ParseOk(options, mut out) => { let logger = StdLogger; - match generate_bindings(options, Some(&logger as &Logger), DUMMY_SP) { - Ok(items) => { - let module = ast::Mod { - inner: DUMMY_SP, - view_items: Vec::new(), - items: items, - }; - - match try_pprint(&module, out) { - Err(e) => logger.error(format!("Unable to write bindings to file. {}", e).as_slice()), - _ => () - } - } - Err(_) => () + match Bindings::generate(&options, Some(&logger as &Logger), None) { + Ok(bindings) => match bindings.write(&mut out) { + Ok(()) => (), + Err(e) => logger.error(format!("Unable to write bindings to file. {}", e).as_slice()) + }, + Err(()) => () } } } @@ -18,6 +18,7 @@ use syntax::parse; use syntax::attr::mk_attr_id; use syntax::ptr::P; +use super::LinkType; use types::*; struct GenCtx<'r> { @@ -112,7 +113,7 @@ fn enum_name(name: &String) -> String { format!("Enum_{}", name) } -pub fn gen_mod(links: &[(String, Option<String>)], globs: Vec<Global>, span: Span) -> Vec<P<ast::Item>> { +pub fn gen_mod(links: &[(String, LinkType)], 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 cfg = ExpansionConfig { deriving_hash_type_parameter: false, @@ -247,13 +248,18 @@ pub fn gen_mod(links: &[(String, Option<String>)], globs: Vec<Global>, span: Spa defs } -fn mk_extern(ctx: &mut GenCtx, links: &[(String, Option<String>)], +fn mk_extern(ctx: &mut GenCtx, links: &[(String, LinkType)], foreign_items: Vec<P<ast::ForeignItem>>, abi: abi::Abi) -> P<ast::Item> { let attrs = if links.is_empty() { Vec::new() } else { links.iter().map(|&(ref l, ref k)| { + let k = match k { + &LinkType::Default => None, + &LinkType::Static => Some("static"), + &LinkType::Framework => Some("framework") + }; let link_name = P(respan(ctx.span, ast::MetaNameValue( to_intern_str(ctx, "name".to_string()), respan(ctx.span, ast::LitStr( @@ -262,8 +268,8 @@ fn mk_extern(ctx: &mut GenCtx, links: &[(String, Option<String>)], )) ))); let link_args = match k { - &None => vec!(link_name), - &Some(ref k) => vec!(link_name, P(respan(ctx.span, ast::MetaNameValue( + None => vec!(link_name), + Some(ref k) => vec!(link_name, P(respan(ctx.span, ast::MetaNameValue( to_intern_str(ctx, "kind".to_string()), respan(ctx.span, ast::LitStr( to_intern_str(ctx, k.to_string()), @@ -9,9 +9,12 @@ extern crate libc; use std::collections::HashSet; use std::default::Default; +use std::io::IoResult; use syntax::ast; -use syntax::codemap::Span; +use syntax::codemap::{DUMMY_SP, Span}; +use syntax::print::{pp, pprust}; +use syntax::print::pp::eof; use syntax::ptr::P; use rustc::plugin::Registry; @@ -24,6 +27,7 @@ mod gen; mod parser; mod macro; +#[doc(hidden)] #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("bindgen", macro::bindgen_macro); @@ -32,7 +36,7 @@ pub fn plugin_registrar(reg: &mut Registry) { pub struct BindgenOptions { pub match_pat: Vec<String>, pub builtins: bool, - pub links: Vec<(String, Option<String>)>, + pub links: Vec<(String, LinkType)>, pub emit_ast: bool, pub fail_on_bitfield: bool, pub fail_on_unknown_type: bool, @@ -55,23 +59,77 @@ impl Default for BindgenOptions { } } +pub enum LinkType { + Default, + Static, + Framework +} + pub trait Logger { fn error(&self, msg: &str); fn warn(&self, msg: &str); } -pub fn generate_bindings(options: BindgenOptions, logger: Option<&Logger>, span: Span) -> Result<Vec<P<ast::Item>>, ()> { - let l = DummyLogger; - let logger = match logger { - Some(l) => l, - None => { - &l as &Logger - } - }; - let globals = try!(parse_headers(&options, logger)); - Ok(gen::gen_mod(options.links.as_slice(), globals, span)) +pub struct Bindings +{ + module: ast::Mod } +impl Bindings +{ + pub fn generate(options: &BindgenOptions, logger: Option<&Logger>, span: Option<Span>) -> Result<Bindings, ()> { + let l = DummyLogger; + let logger = match logger { + Some(l) => l, + None => &l as &Logger + }; + + let span = match span { + Some(s) => s, + None => DUMMY_SP + }; + + let globals = try!(parse_headers(options, logger)); + + let module = ast::Mod { + inner: span, + view_items: Vec::new(), + items: gen::gen_mod(options.links.as_slice(), globals, span) + }; + + Ok(Bindings { + module: module + }) + } + + pub fn into_ast(self) -> Vec<P<ast::Item>> { + self.module.items + } + + pub fn to_string(&self) -> String { + pprust::to_string(|s| { + s.s = pp::mk_printer(box Vec::new(), 80); + + try!(s.print_mod(&self.module, &[])); + s.print_remaining_comments() + }) + } + + pub fn write(&self, writer: &mut (Writer + 'static)) -> IoResult<()> { + try!(writer.write("/* automatically generated by rust-bindgen */\n\n".as_bytes())); + + // This is safe as the Box<Writer> does not outlive ps or this function + // Without this the interface is quite nasty + let writer = unsafe { ::std::mem::transmute(writer) }; + let mut ps = pprust::rust_printer(writer); + try!(ps.print_mod(&self.module, &[])); + try!(ps.print_remaining_comments()); + try!(eof(&mut ps.s)); + ps.s.out.flush() + } +} + + struct DummyLogger; impl Logger for DummyLogger { diff --git a/src/macro.rs b/src/macro.rs index 6f16955a..cffb7cdd 100644 --- a/src/macro.rs +++ b/src/macro.rs @@ -9,7 +9,7 @@ use syntax::parse::token; use syntax::ptr::P; use syntax::util::small_vector::SmallVector; -use super::{generate_bindings, BindgenOptions, Logger}; +use super::{Bindings, BindgenOptions, LinkType, Logger}; pub fn bindgen_macro(cx: &mut base::ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<base::MacResult+'static> { let mut visit = BindgenArgsVisitor { @@ -45,9 +45,9 @@ pub fn bindgen_macro(cx: &mut base::ExtCtxt, sp: codemap::Span, tts: &[ast::Toke let logger = MacroLogger { sp: short_span, cx: cx }; - let ret = match generate_bindings(visit.options, Some(&logger as &Logger), short_span) { - Ok(items) => { - box BindgenResult { items: Some(SmallVector::many(items)) } as Box<base::MacResult> + let ret = match Bindings::generate(&visit.options, Some(&logger as &Logger), Some(short_span)) { + Ok(bindings) => { + box BindgenResult { items: Some(SmallVector::many(bindings.into_ast())) } as Box<base::MacResult> } Err(_) => base::DummyResult::any(sp) }; @@ -77,9 +77,9 @@ impl MacroArgsVisitor for BindgenArgsVisitor { if name.is_some() { self.seen_named = true; } else if !self.seen_named { name = Some("clang_args") } match name { - Some("link") => self.options.links.push((val.to_string(), None)), - Some("link_static") => self.options.links.push((val.to_string(), Some("static".to_string()))), - Some("link_framework") => self.options.links.push((val.to_string(), Some("framework".to_string()))), + Some("link") => self.options.links.push((val.to_string(), LinkType::Default)), + Some("link_static") => self.options.links.push((val.to_string(), LinkType::Static)), + Some("link_framework") => self.options.links.push((val.to_string(), LinkType::Framework)), Some("match") => self.options.match_pat.push(val.to_string()), Some("clang_args") => self.options.clang_args.push(val.to_string()), _ => return false diff --git a/tests/util.rs b/tests/util.rs index 360fbb8d..8ee3d213 100644 --- a/tests/util.rs +++ b/tests/util.rs @@ -28,7 +28,7 @@ pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> { options.clang_args.push(filename.to_string()); let logger = TestLogger; - bindgen::generate_bindings(options, Some(&logger as &Logger), DUMMY_SP) + Ok(try!(bindgen::Bindings::generate(&options, Some(&logger as &Logger), None)).into_ast()) } pub fn generate_unpretty_output(filename: &str) -> String { |