summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bin/bindgen.rs228
1 files changed, 114 insertions, 114 deletions
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs
index 1e92ee6d..1b9d4806 100755
--- a/src/bin/bindgen.rs
+++ b/src/bin/bindgen.rs
@@ -4,17 +4,16 @@
extern crate bindgen;
extern crate env_logger;
#[macro_use]
-extern crate docopt;
-#[macro_use]
extern crate log;
extern crate clang_sys;
extern crate rustc_serialize;
use bindgen::{Bindings, BindgenOptions, LinkType};
+use std::default::Default;
use std::io;
use std::path;
+use std::process;
use std::env;
-use std::default::Default;
use std::fs;
const USAGE: &'static str = "
@@ -23,9 +22,7 @@ Usage:
[--link=<lib>...] \
[--static-link=<lib>...] \
[--framework-link=<framework>...] \
- [--match=<name>...] \
[--raw-line=<raw>...] \
- [--dtor-attr=<attr>...] \
[--opaque-type=<type>...] \
[--blacklist-type=<type>...] \
[--whitelist-type=<type>...] \
@@ -50,11 +47,6 @@ Options:
-o=<output-rust-file> Write bindings to <output-rust-file>
(defaults to stdout)
- --match=<name> Only output bindings for definitions from
- files whose name contains <name>. If multiple
- match options are provided, files matching any
- rule are bound to.
-
--builtins Output bindings for builtin definitions (for
example __builtin_va_list)
@@ -62,6 +54,8 @@ Options:
methods. This is useful when you only care
about struct layouts.
+ --ignore-methods Avoid generating all kind of methods.
+
--enable-cxx-namespaces Enable support for C++ namespaces.
--no-type-renaming Don't rename types.
@@ -74,25 +68,9 @@ Options:
--use-msvc-mangling Handle MSVC C++ ABI mangling; requires that
target be set to (i686|x86_64)-pc-win32
- --override-enum-type=<type> Override enum type, type name could be
- uchar
- schar
- ushort
- sshort
- uint
- sint
- ulong
- slong
- ulonglong
- slonglong
-
--raw-line=<raw> Add a raw line at the beginning of the output.
- --dtor-attr=<attr> Attributes to add to structures with destructor.
- --no-class-constants Avoid generating class constants.
--no-unstable-rust Avoid generating unstable rust.
- --no-namespaced-constants Avoid generating constants right under namespaces.
--no-bitfield-methods Avoid generating methods for bitfield access.
- --ignore-methods Avoid generating all kind of methods.
--opaque-type=<type> Mark a type as opaque.
--blacklist-type=<type> Mark a type as hidden.
--whitelist-type=<type> Whitelist the type. If this set or any other
@@ -110,91 +88,119 @@ Options:
directly through to clang.
";
-#[derive(Debug, RustcDecodable)]
-struct Args {
- arg_input_header: String,
- flag_link: Vec<String>,
- flag_static_link: Vec<String>,
- flag_framework_link: Vec<String>,
- flag_o: Option<String>,
- flag_match: Vec<String>,
- flag_builtins: bool,
- flag_ignore_functions: bool,
- flag_enable_cxx_namespaces: bool,
- flag_no_type_renaming: bool,
- flag_allow_unknown_types: bool,
- flag_emit_clang_ast: bool,
- flag_use_msvc_mangling: bool,
- flag_override_enum_type: String,
- flag_raw_line: Vec<String>,
- flag_dtor_attr: Vec<String>,
- flag_no_class_constants: bool,
- flag_no_unstable_rust: bool,
- flag_no_namespaced_constants: bool,
- flag_no_bitfield_methods: bool,
- flag_ignore_methods: bool,
- flag_opaque_type: Vec<String>,
- flag_blacklist_type: Vec<String>,
- flag_whitelist_type: Vec<String>,
- flag_whitelist_function: Vec<String>,
- flag_whitelist_var: Vec<String>,
- arg_clang_args: Vec<String>,
-}
-
-type ParseResult<T> = Result<T, String>;
-
-impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
- fn into(mut self) -> Result<(BindgenOptions, Box<io::Write>), String> {
- let mut options: BindgenOptions = Default::default();
-
- for lib in self.flag_link.drain(..) {
- options.links.push((lib, LinkType::Default));
- }
+// FIXME(emilio): Replace this with docopt if/when they fix their exponential
+// algorithm for argument parsing.
+fn parse_args_or_exit(args: Vec<String>) -> (BindgenOptions, Box<io::Write>) {
+ let mut options = BindgenOptions::default();
+ let mut dest_file = None;
+ let mut source_file = None;
+
+ let mut iter = args.into_iter().skip(1);
+ loop {
+ let next = match iter.next() {
+ Some(arg) => arg,
+ _ => break,
+ };
- for lib in self.flag_static_link.drain(..) {
- options.links.push((lib, LinkType::Static));
+ match &*next {
+ "-h" | "--help" => {
+ println!("{}", USAGE);
+ process::exit(0);
+ }
+ "-l" | "--link" => {
+ let lib = iter.next().expect("--link needs an argument");
+ options.links.push((lib, LinkType::Default));
+ }
+ "--static-link" => {
+ let lib = iter.next().expect("--static-link needs an argument");
+ options.links.push((lib, LinkType::Static));
+ }
+ "--framework-link" => {
+ let lib = iter.next().expect("--framework-link needs an argument");
+ options.links.push((lib, LinkType::Framework));
+ }
+ "--raw-line" => {
+ let line = iter.next().expect("--raw-line needs an argument");
+ options.raw_lines.push(line);
+ }
+ "--opaque-type" => {
+ let ty_canonical_name = iter.next().expect("--opaque-type expects a type");
+ options.opaque_types.insert(ty_canonical_name);
+ }
+ "--blacklist-type" => {
+ let ty_canonical_name = iter.next().expect("--blacklist-type expects a type");
+ options.hidden_types.insert(ty_canonical_name);
+ }
+ "--whitelist-type" => {
+ let ty_pat = iter.next().expect("--whitelist-type expects a type pattern");
+ options.whitelisted_types.insert(&ty_pat);
+ }
+ "--whitelist-function" => {
+ let function_pat = iter.next().expect("--whitelist-function expects a pattern");
+ options.whitelisted_functions.insert(&function_pat);
+ }
+ "--whitelist-var" => {
+ let var_pat = iter.next().expect("--whitelist-var expects a pattern");
+ options.whitelisted_vars.insert(&var_pat);
+ }
+ "--" => {
+ while let Some(clang_arg) = iter.next() {
+ options.clang_args.push(clang_arg);
+ }
+ }
+ "--output" | "-o" => {
+ let out_name = iter.next().expect("-o expects a file name");
+ dest_file = Some(out_name);
+ }
+ "--builtins" => {
+ options.builtins = true;
+ }
+ "--ignore-functions" => {
+ options.ignore_functions = true;
+ }
+ "--no-bitfield-methods" => {
+ options.gen_bitfield_methods = false;
+ }
+ "--ignore-methods" => {
+ options.ignore_methods = true;
+ }
+ "--enable-cxx-namespaces" => {
+ options.enable_cxx_namespaces = true;
+ }
+ "--no-type-renaming" => {
+ options.rename_types = false;
+ }
+ "--no-unstable-rust" => {
+ options.unstable_rust = false;
+ }
+ "--emit-clang-ast" => {
+ options.emit_ast = true;
+ }
+ "--use-msvc-mangling" => {
+ options.msvc_mangling = true;
+ }
+ other if source_file.is_none() => {
+ source_file = Some(other.into());
+ }
+ other => {
+ panic!("Unknown option: \"{}\"", other);
+ }
}
+ }
- for lib in self.flag_framework_link.drain(..) {
- options.links.push((lib, LinkType::Framework));
- }
+ if let Some(source_file) = source_file.take() {
+ options.clang_args.push(source_file);
+ }
- let out = if let Some(ref path_name) = self.flag_o {
- let path = path::Path::new(path_name);
- let file = try!(fs::File::create(path).map_err(|_| {
- format!("Opening {} failed", path_name)
- }));
- Box::new(io::BufWriter::new(file)) as Box<io::Write>
- } else {
- Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
- };
+ let out = if let Some(ref path_name) = dest_file {
+ let path = path::Path::new(path_name);
+ let file = fs::File::create(path).expect("Opening out file failed");
+ Box::new(io::BufWriter::new(file)) as Box<io::Write>
+ } else {
+ Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
+ };
- options.match_pat.extend(self.flag_match.drain(..));
- options.builtins = self.flag_builtins;
- options.ignore_functions = self.flag_ignore_functions;
- options.enable_cxx_namespaces = self.flag_enable_cxx_namespaces;
- options.rename_types = !self.flag_no_type_renaming;
- options.fail_on_unknown_type = !self.flag_allow_unknown_types;
- options.emit_ast = self.flag_emit_clang_ast;
- options.msvc_mangling = self.flag_use_msvc_mangling;
- options.override_enum_ty = self.flag_override_enum_type;
- options.raw_lines.extend(self.flag_raw_line.drain(..));
- options.dtor_attrs.extend(self.flag_dtor_attr.drain(..));
- options.class_constants = !self.flag_no_class_constants;
- options.unstable_rust = !self.flag_no_unstable_rust;
- options.namespaced_constants = !self.flag_no_namespaced_constants;
- options.gen_bitfield_methods = !self.flag_no_bitfield_methods;
- options.ignore_methods = self.flag_ignore_methods;
- options.opaque_types.extend(self.flag_opaque_type.drain(..));
- options.hidden_types.extend(self.flag_blacklist_type.drain(..));
- options.whitelisted_types.extend(self.flag_whitelist_type.drain(..));
- options.whitelisted_functions.extend(self.flag_whitelist_function.drain(..));
- options.whitelisted_vars.extend(self.flag_whitelist_var.drain(..));
- options.clang_args.extend(self.arg_clang_args.drain(..));
- options.clang_args.push(self.arg_input_header);
-
- Ok((options, out))
- }
+ (options, out)
}
pub fn main() {
@@ -227,17 +233,11 @@ pub fn main() {
}
}
- let args: Args = docopt::Docopt::new(USAGE)
- .and_then(|d| d.argv(bind_args.iter()).decode())
- .unwrap_or_else(|e| e.exit());
-
- let result: ParseResult<_> = args.into();
- let (options, out) = result.unwrap_or_else(|msg| {
- panic!("Failed to generate_bindings: {:?}", msg);
- });
+ let (options, out) = parse_args_or_exit(bind_args);
let bindings = Bindings::generate(options, None)
.expect("Unable to generate bindings");
+
bindings.write(out)
.expect("Unable to write bindings to file.");
}