summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Barnard <eabarnard@gmail.com>2014-12-23 20:46:13 +0100
committerEdward Barnard <eabarnard@gmail.com>2014-12-23 20:46:13 +0100
commitfbdb913b31d572bf9c67ec080b73aafe42db7e3e (patch)
tree5f6cf85b66cf39b643c19f27226388fcf4072177
parenta4ec65f0484f11ed8a1aea7b96d25882b8302c67 (diff)
Improve public api
-rw-r--r--src/bin/bindgen.rs49
-rw-r--r--src/gen.rs14
-rw-r--r--src/lib.rs82
-rw-r--r--src/macro.rs14
-rw-r--r--tests/util.rs2
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(()) => ()
}
}
}
diff --git a/src/gen.rs b/src/gen.rs
index 2af39253..a08d8aeb 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -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()),
diff --git a/src/lib.rs b/src/lib.rs
index 274f33e6..5bd7ed6a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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 {