bindgen 0.25.3

Automatically generates Rust FFI bindings to C and C++ libraries.
Documentation
//! Generate Rust bindings for C and C++ libraries.
//!
//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++
//! functions and use types defined in the header.
//!
//! See the [`Builder`](./struct.Builder.html) struct for usage.

#![deny(missing_docs)]
#![deny(warnings)]
#![deny(unused_extern_crates)]

// We internally use the deprecated BindgenOptions all over the place. Once we
// remove its `pub` declaration, we can un-deprecate it and remove this pragma.
#![allow(deprecated)]

// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]

#[macro_use]
#[allow(unused_extern_crates)]
extern crate cfg_if;
extern crate cexpr;
extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate peeking_take_while;
extern crate regex;
#[macro_use]
extern crate lazy_static;

#[cfg(feature = "logging")]
#[macro_use]
extern crate log;

#[cfg(not(feature = "logging"))]
#[macro_use]
mod log_stubs;

#[macro_use]
mod extra_assertions;

// A macro to declare an internal module for which we *must* provide
// documentation for. If we are building with the "testing_only_docs" feature,
// then the module is declared public, and our `#![deny(missing_docs)]` pragma
// applies to it. This feature is used in CI, so we won't let anything slip by
// undocumented. Normal builds, however, will leave the module private, so that
// we don't expose internals to library consumers.
macro_rules! doc_mod {
    ($m:ident, $doc_mod_name:ident) => {
        cfg_if! {
            if #[cfg(feature = "testing_only_docs")] {
                pub mod $doc_mod_name {
                    //! Autogenerated documentation module.
                    pub use super::$m::*;
                }
            } else {
            }
        }
    };
}

mod clang;
mod ir;
mod parse;
mod regex_set;
mod uses;

pub mod callbacks;

#[cfg(rustfmt)]
mod codegen;

doc_mod!(clang, clang_docs);
doc_mod!(ir, ir_docs);
doc_mod!(parse, parse_docs);
doc_mod!(regex_set, regex_set_docs);
doc_mod!(uses, uses_docs);

mod codegen {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
}

use ir::context::{BindgenContext, ItemId};
use ir::item::Item;
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;

use std::fs::OpenOptions;
use std::io::{self, Write};
use std::path::Path;
use std::sync::Arc;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::print::pp::eof;
use syntax::print::pprust;
use syntax::ptr::P;

/// A type used to indicate which kind of items do we have to generate.
///
/// TODO(emilio): Use `bitflags!`
#[derive(Debug, Clone)]
pub struct CodegenConfig {
    /// Whether to generate functions.
    pub functions: bool,
    /// Whether to generate types.
    pub types: bool,
    /// Whether to generate constants.
    pub vars: bool,
    /// Whether to generate methods.
    pub methods: bool,
    /// Whether to generate constructors.
    pub constructors: bool,
    /// Whether to generate destructors.
    pub destructors: bool,
}

impl CodegenConfig {
    /// Generate all kinds of items.
    pub fn all() -> Self {
        CodegenConfig {
            functions: true,
            types: true,
            vars: true,
            methods: true,
            constructors: true,
            destructors: true,
        }
    }

    /// Generate nothing.
    pub fn nothing() -> Self {
        CodegenConfig {
            functions: false,
            types: false,
            vars: false,
            methods: false,
            constructors: false,
            destructors: false,
        }
    }
}

impl Default for CodegenConfig {
    fn default() -> Self {
        CodegenConfig::all()
    }
}

/// Configure and generate Rust bindings for a C/C++ header.
///
/// This is the main entry point to the library.
///
/// ```ignore
/// use bindgen::builder;
///
/// // Configure and generate bindings.
/// let bindings = try!(builder().header("path/to/input/header")
///                              .whitelisted_type("SomeCoolClass")
///                              .whitelisted_function("do_some_cool_thing")
///                              .generate());
///
/// // Write the generated bindings to an output file.
/// try!(bindings.write_to_file("path/to/output.rs"));
/// ```
#[derive(Debug,Default)]
pub struct Builder {
    options: BindgenOptions,
}

/// Construct a new [`Builder`](./struct.Builder.html).
pub fn builder() -> Builder {
    Default::default()
}

impl Builder {
     /// Generates the command line flags use for creating `Builder`.
    pub fn command_line_flags(&self) -> Vec<String> {
        let mut output_vector: Vec<String> = Vec::new();

        if let Some(ref header) = self.options.input_header {
            //Positional argument 'header'
            output_vector.push(header.clone().into());
        }

        self.options
            .bitfield_enums
            .get_items()
            .iter()
            .map(|item| {
                     output_vector.push("--bitfield-enum".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        self.options
            .constified_enums
            .get_items()
            .iter()
            .map(|item| {
                     output_vector.push("--constified-enum".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        self.options
            .hidden_types
            .get_items()
            .iter()
            .map(|item| {
                     output_vector.push("--blacklist-type".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        if !self.options.layout_tests {
            output_vector.push("--no-layout-tests".into());
        }

        if !self.options.derive_debug {
            output_vector.push("--no-derive-debug".into());
        }

        if !self.options.derive_default {
            output_vector.push("--no-derive-default".into());
        } else {
            output_vector.push("--with-derive-default".into());
        }

        if !self.options.generate_comments {
            output_vector.push("--no-doc-comments".into());
        }

        if !self.options.whitelist_recursively {
            output_vector.push("--no-recursive-whitelist".into());
        }

        if self.options.objc_extern_crate {
            output_vector.push("--objc-extern-crate".into());
        }

        if self.options.builtins {
            output_vector.push("--builtins".into());
        }

        if let Some(ref prefix) = self.options.ctypes_prefix {
            output_vector.push("--ctypes-prefix".into());
            output_vector.push(prefix.clone());
        }

        if let Some(ref dummy) = self.options.dummy_uses {
            output_vector.push("--dummy-uses".into());
            output_vector.push(dummy.clone());
        }

        if self.options.emit_ast {
            output_vector.push("--emit-clang-ast".into());
        }

        if self.options.emit_ir {
            output_vector.push("--emit-ir".into());
        }
        if let Some(ref graph) = self.options.emit_ir_graphviz {
            output_vector.push("--emit-ir-graphviz".into());
            output_vector.push(graph.clone())
        }
        if self.options.enable_cxx_namespaces {
            output_vector.push("--enable-cxx-namespaces".into());
        }
        if self.options.disable_name_namespacing {
            output_vector.push("--disable-name-namespacing".into());
        }

        self.options
            .links
            .iter()
            .map(|&(ref item, _)| {
                     output_vector.push("--framework".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        if !self.options.codegen_config.functions {
            output_vector.push("--ignore-functions".into());
        }

        output_vector.push("--generate".into());

        //Temporary placeholder for below 4 options
        let mut options:Vec<String> = Vec::new();
        if self.options.codegen_config.functions {
            options.push("function".into());
        }
        if self.options.codegen_config.types {
            options.push("types".into());
        }
        if self.options.codegen_config.vars {
            options.push("vars".into());
        }
        if self.options.codegen_config.methods {
            options.push("methods".into());
        }
        if self.options.codegen_config.constructors {
            options.push("constructors".into());
        }
        if self.options.codegen_config.destructors {
            options.push("destructors".into());
        }

        output_vector.push(options.join(","));

        if !self.options.codegen_config.methods {
            output_vector.push("--ignore-methods".into());
        }

        self.options
            .links
            .iter()
            .map(|&(ref item, _)| {
                     output_vector.push("--clang-args".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        if !self.options.convert_floats {
            output_vector.push("--no-convert-floats".into());
        }

        if !self.options.prepend_enum_name {
            output_vector.push("--no-prepend-enum-name".into());
        }

        if !self.options.unstable_rust {
            output_vector.push("--no-unstable-rust".into());
        }

        self.options
            .opaque_types
            .get_items()
            .iter()
            .map(|item| {
                     output_vector.push("--opaque-type".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        self.options
            .raw_lines
            .iter()
            .map(|item| {
                     output_vector.push("--raw-line".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        self.options
            .links
            .iter()
            .map(|&(ref item, _)| {
                     output_vector.push("--static".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        if self.options.use_core {
            output_vector.push("--use-core".into());
        }

        if self.options.conservative_inline_namespaces {
            output_vector.push("--conservative-inline-namespaces".into());
        }

        self.options
            .whitelisted_functions
            .get_items()
            .iter()
            .map(|item| {
                     output_vector.push("--whitelist-function".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        self.options
            .whitelisted_types
            .get_items()
            .iter()
            .map(|item| {
                     output_vector.push("--whitelist-type".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        self.options
            .whitelisted_vars
            .get_items()
            .iter()
            .map(|item| {
                     output_vector.push("--whitelist-var".into());
                     output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into());
                 })
            .count();

        if !self.options.clang_args.is_empty() {
            output_vector.push("--".into());
            self.options
                .clang_args
                .iter()
                .cloned()
                .map(|item| {
                    output_vector.push(item);
                })
                .count();
        }

        output_vector
    }

    /// Add an input C/C++ header to generate bindings for.
    ///
    /// This can be used to generate bindings to a single header:
    ///
    /// ```ignore
    /// let bindings = bindgen::Builder::default()
    ///     .header("input.h")
    ///     .generate()
    ///     .unwrap();
    /// ```
    ///
    /// Or you can invoke it multiple times to generate bindings to multiple
    /// headers:
    ///
    /// ```ignore
    /// let bindings = bindgen::Builder::default()
    ///     .header("first.h")
    ///     .header("second.h")
    ///     .header("third.h")
    ///     .generate()
    ///     .unwrap();
    /// ```
    pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
        if let Some(prev_header) = self.options.input_header.take() {
            self.options.clang_args.push("-include".into());
            self.options.clang_args.push(prev_header);
        }

        let header = header.into();
        self.options.input_header = Some(header);
        self
    }

    /// Add `contents` as an input C/C++ header named `name`.
    ///
    /// The file `name` will be added to the clang arguments.
    pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
        self.options.input_unsaved_files.push(clang::UnsavedFile::new(name, contents));
        self
    }

    /// Set the output graphviz file.
    pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
        let path = path.into();
        self.options.emit_ir_graphviz = Some(path);
        self
    }

    /// Whether the generated bindings should contain documentation comments or
    /// not.
    ///
    /// This ideally will always be true, but it may need to be false until we
    /// implement some processing on comments to work around issues as described
    /// in:
    ///
    /// https://github.com/servo/rust-bindgen/issues/426
    pub fn generate_comments(mut self, doit: bool) -> Self {
        self.options.generate_comments = doit;
        self
    }

    /// Whether to whitelist types recursively or not. Defaults to true.
    ///
    /// This can be used to get bindgen to generate _exactly_ the types you want
    /// in your bindings, and then import other types manually via other means
    /// (like [`raw_line`](#method.raw_line)).
    pub fn whitelist_recursively(mut self, doit: bool) -> Self {
        self.options.whitelist_recursively = doit;
        self
    }

    /// Generate `#[macro_use] extern crate objc;` instead of `use objc;`
    /// in the prologue of the files generated from objective-c files
    pub fn objc_extern_crate(mut self, doit: bool) -> Self {
        self.options.objc_extern_crate = doit;
        self
    }

    /// Whether to use the clang-provided name mangling. This is true by default
    /// and probably needed for C++ features.
    ///
    /// However, some old libclang versions seem to return incorrect results in
    /// some cases for non-mangled functions, see [1], so we allow disabling it.
    ///
    /// [1]: https://github.com/servo/rust-bindgen/issues/528
    pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
        self.options.enable_mangling = doit;
        self
    }

    /// Generate a C/C++ file that includes the header and has dummy uses of
    /// every type defined in the header.
    pub fn dummy_uses<T: Into<String>>(mut self, dummy_uses: T) -> Builder {
        self.options.dummy_uses = Some(dummy_uses.into());
        self
    }

    /// Hide the given type from the generated bindings. Regular expressions are
    /// supported.
    pub fn hide_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
        self.options.hidden_types.insert(arg);
        self
    }

    /// Treat the given type as opaque in the generated bindings. Regular
    /// expressions are supported.
    pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
        self.options.opaque_types.insert(arg);
        self
    }

    /// Whitelist the given type so that it (and all types that it transitively
    /// refers to) appears in the generated bindings. Regular expressions are
    /// supported.
    pub fn whitelisted_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_types.insert(arg);
        self
    }

    /// Whitelist the given function so that it (and all types that it
    /// transitively refers to) appears in the generated bindings. Regular
    /// expressions are supported.
    pub fn whitelisted_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_functions.insert(arg);
        self
    }

    /// Whitelist the given variable so that it (and all types that it
    /// transitively refers to) appears in the generated bindings. Regular
    /// expressions are supported.
    pub fn whitelisted_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
        self.options.whitelisted_vars.insert(arg);
        self
    }

    /// Mark the given enum (or set of enums, if using a pattern) as being
    /// bitfield-like. Regular expressions are supported.
    ///
    /// This makes bindgen generate a type that isn't a rust `enum`. Regular
    /// expressions are supported.
    pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
        self.options.bitfield_enums.insert(arg);
        self
    }

    /// Mark the given enum (or set of enums, if using a pattern) as being
    /// constant.
    ///
    /// This makes bindgen generate constants instead of enums. Regular
    /// expressions are supported.
    pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
        self.options.constified_enums.insert(arg);
        self
    }

    /// Add a string to prepend to the generated bindings. The string is passed
    /// through without any modification.
    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.raw_lines.push(arg.into());
        self
    }

    /// Add an argument to be passed straight through to clang.
    pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.clang_args.push(arg.into());
        self
    }

    /// Add arguments to be passed straight through to clang.
    pub fn clang_args<I>(mut self, iter: I) -> Builder
        where I: IntoIterator,
              I::Item: AsRef<str> {
        for arg in iter {
            self = self.clang_arg(arg.as_ref())
        }
        self
    }

    /// Make the generated bindings link the given shared library.
    pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Default));
        self
    }

    /// Make the generated bindings link the given static library.
    pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Static));
        self
    }

    /// Make the generated bindings link the given framework.
    pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Framework));
        self
    }

    /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
    /// in the generated Rust.
    pub fn emit_builtins(mut self) -> Builder {
        self.options.builtins = true;
        self
    }

    /// Avoid converting floats to `f32`/`f64` by default.
    pub fn no_convert_floats(mut self) -> Self {
        self.options.convert_floats = false;
        self
    }

    /// Set whether layout tests should be generated.
    pub fn layout_tests(mut self, doit: bool) -> Self {
        self.options.layout_tests = doit;
        self
    }

    /// Set whether `Debug` should be derived by default.
    pub fn derive_debug(mut self, doit: bool) -> Self {
        self.options.derive_debug = doit;
        self
    }

    /// Set whether `Default` should be derived by default.
    pub fn derive_default(mut self, doit: bool) -> Self {
        self.options.derive_default = doit;
        self
    }

    /// Emit Clang AST.
    pub fn emit_clang_ast(mut self) -> Builder {
        self.options.emit_ast = true;
        self
    }

    /// Emit IR.
    pub fn emit_ir(mut self) -> Builder {
        self.options.emit_ir = true;
        self
    }

    /// Enable C++ namespaces.
    pub fn enable_cxx_namespaces(mut self) -> Builder {
        self.options.enable_cxx_namespaces = true;
        self
    }

    /// Disable name auto-namespacing.
    ///
    /// By default, bindgen mangles names like `foo::bar::Baz` to look like
    /// `foo_bar_Baz` instead of just `Baz`.
    ///
    /// This method disables that behavior.
    ///
    /// Note that this intentionally does not change the names used for
    /// whitelisting and blacklisting, which should still be mangled with the
    /// namespaces.
    ///
    /// Note, also, that this option may cause bindgen to generate duplicate
    /// names.
    pub fn disable_name_namespacing(mut self) -> Builder {
        self.options.disable_name_namespacing = true;
        self
    }

    /// Treat inline namespaces conservatively.
    ///
    /// This is tricky, because in C++ is technically legal to override an item
    /// defined in an inline namespace:
    ///
    /// ```cpp
    /// inline namespace foo {
    ///     using Bar = int;
    /// }
    /// using Bar = long;
    /// ```
    ///
    /// Even though referencing `Bar` is a compiler error.
    ///
    /// We want to support this (arguably esoteric) use case, but we don't want
    /// to make the rest of bindgen users pay an usability penalty for that.
    ///
    /// To support this, we need to keep all the inline namespaces around, but
    /// then bindgen usage is a bit more difficult, because you cannot
    /// reference, e.g., `std::string` (you'd need to use the proper inline
    /// namespace).
    ///
    /// We could complicate a lot of the logic to detect name collisions, and if
    /// not detected generate a `pub use inline_ns::*` or something like that.
    ///
    /// That's probably something we can do if we see this option is needed in a
    /// lot of cases, to improve it's usability, but my guess is that this is
    /// not going to be too useful.
    pub fn conservative_inline_namespaces(mut self) -> Builder {
        self.options.conservative_inline_namespaces = true;
        self
    }

    /// Whether inline functions should be generated or not.
    ///
    /// Note that they will usually not work. However you can use
    /// `-fkeep-inline-functions` or `-fno-inline-functions` if you are
    /// responsible of compiling the library to make them callable.
    pub fn generate_inline_functions(mut self, doit: bool) -> Self {
        self.options.generate_inline_functions = doit;
        self
    }

    /// Ignore functions.
    pub fn ignore_functions(mut self) -> Builder {
        self.options.codegen_config.functions = false;
        self
    }

    /// Ignore methods.
    pub fn ignore_methods(mut self) -> Builder {
        self.options.codegen_config.methods = false;
        self
    }

    /// Avoid generating any unstable Rust, such as Rust unions, in the generated bindings.
    pub fn no_unstable_rust(mut self) -> Builder {
        self.options.unstable_rust = false;
        self
    }

    /// Use core instead of libstd in the generated bindings.
    pub fn use_core(mut self) -> Builder {
        self.options.use_core = true;
        self
    }

    /// Use the given prefix for the raw types instead of `::std::os::raw`.
    pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
        self.options.ctypes_prefix = Some(prefix.into());
        self
    }

    /// Allows configuring types in different situations, see the
    /// [`ParseCallbacks`](./callbacks/trait.ParseCallbacks.html) documentation.
    pub fn parse_callbacks(mut self, cb: Box<callbacks::ParseCallbacks>) -> Self {
        self.options.parse_callbacks = Some(cb);
        self
    }

    /// Choose what to generate using a
    /// [`CodegenConfig`](./struct.CodegenConfig.html).
    pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self {
        self.options.codegen_config = config;
        self
    }

    /// Prepend the enum name to constant or bitfield variants.
    pub fn prepend_enum_name(mut self, doit: bool) -> Self {
        self.options.prepend_enum_name = doit;
        self
    }

    /// Generate the Rust bindings using the options built up thus far.
    pub fn generate<'ctx>(self) -> Result<Bindings<'ctx>, ()> {
        Bindings::generate(self.options, None)
    }
}

/// Configuration options for generated bindings.
///
/// Deprecated: use a `Builder` instead.
#[derive(Debug)]
#[deprecated]
pub struct BindgenOptions {
    /// The set of types that have been blacklisted and should not appear
    /// anywhere in the generated code.
    pub hidden_types: RegexSet,

    /// The set of types that should be treated as opaque structures in the
    /// generated code.
    pub opaque_types: RegexSet,

    /// The set of types that we should have bindings for in the generated
    /// code.
    ///
    /// This includes all types transitively reachable from any type in this
    /// set. One might think of whitelisted types/vars/functions as GC roots,
    /// and the generated Rust code as including everything that gets marked.
    pub whitelisted_types: RegexSet,

    /// Whitelisted functions. See docs for `whitelisted_types` for more.
    pub whitelisted_functions: RegexSet,

    /// Whitelisted variables. See docs for `whitelisted_types` for more.
    pub whitelisted_vars: RegexSet,

    /// The enum patterns to mark an enum as bitfield.
    pub bitfield_enums: RegexSet,

    /// The enum patterns to mark an enum as constant.
    pub constified_enums: RegexSet,

    /// Whether we should generate builtins or not.
    pub builtins: bool,

    /// The set of libraries we should link in the generated Rust code.
    pub links: Vec<(String, LinkType)>,

    /// True if we should dump the Clang AST for debugging purposes.
    pub emit_ast: bool,

    /// True if we should dump our internal IR for debugging purposes.
    pub emit_ir: bool,

    /// Output graphviz dot file.
    pub emit_ir_graphviz: Option<String>,

    /// True if we should emulate C++ namespaces with Rust modules in the
    /// generated bindings.
    pub enable_cxx_namespaces: bool,

    /// True if we should avoid mangling names with namespaces.
    pub disable_name_namespacing: bool,

    /// True if we should generate layout tests for generated structures.
    pub layout_tests: bool,

    /// True if we should derive Debug trait implementations for C/C++ structures
    /// and types.
    pub derive_debug: bool,

    /// True if we should derive Default trait implementations for C/C++ structures
    /// and types.
    pub derive_default: bool,

    /// True if we can use unstable Rust code in the bindings, false if we
    /// cannot.
    pub unstable_rust: bool,

    /// True if we should avoid using libstd to use libcore instead.
    pub use_core: bool,

    /// An optional prefix for the "raw" types, like `c_int`, `c_void`...
    pub ctypes_prefix: Option<String>,

    /// True if we should generate constant names that are **directly** under
    /// namespaces.
    pub namespaced_constants: bool,

    /// True if we should use MSVC name mangling rules.
    pub msvc_mangling: bool,

    /// Whether we should convert float types to f32/f64 types.
    pub convert_floats: bool,

    /// The set of raw lines to prepend to the generated Rust code.
    pub raw_lines: Vec<String>,

    /// The set of arguments to pass straight through to Clang.
    pub clang_args: Vec<String>,

    /// The input header file.
    pub input_header: Option<String>,

    /// Unsaved files for input.
    pub input_unsaved_files: Vec<clang::UnsavedFile>,

    /// Generate a dummy C/C++ file that includes the header and has dummy uses
    /// of all types defined therein. See the `uses` module for more.
    pub dummy_uses: Option<String>,

    /// A user-provided visitor to allow customizing different kinds of
    /// situations.
    pub parse_callbacks: Option<Box<callbacks::ParseCallbacks>>,

    /// Which kind of items should we generate? By default, we'll generate all
    /// of them.
    pub codegen_config: CodegenConfig,

    /// Whether to treat inline namespaces conservatively.
    ///
    /// See the builder method description for more details.
    pub conservative_inline_namespaces: bool,

    /// Wether to keep documentation comments in the generated output. See the
    /// documentation for more details.
    pub generate_comments: bool,

    /// Whether to generate inline functions. Defaults to false.
    pub generate_inline_functions: bool,

    /// Wether to whitelist types recursively. Defaults to true.
    pub whitelist_recursively: bool,

    /// Intead of emitting 'use objc;' to files generated from objective c files,
    /// generate '#[macro_use] extern crate objc;'
    pub objc_extern_crate: bool,

    /// Whether to use the clang-provided name mangling. This is true and
    /// probably needed for C++ features.
    ///
    /// However, some old libclang versions seem to return incorrect results in
    /// some cases for non-mangled functions, see [1], so we allow disabling it.
    ///
    /// [1]: https://github.com/servo/rust-bindgen/issues/528
    pub enable_mangling: bool,

    /// Whether to prepend the enum name to bitfield or constant variants.
    pub prepend_enum_name: bool,
}

/// TODO(emilio): This is sort of a lie (see the error message that results from
/// removing this), but since we don't share references across panic boundaries
/// it's ok.
impl ::std::panic::UnwindSafe for BindgenOptions {}

impl BindgenOptions {
    fn build(&mut self) {
        self.whitelisted_vars.build();
        self.whitelisted_types.build();
        self.whitelisted_functions.build();
        self.hidden_types.build();
        self.opaque_types.build();
        self.bitfield_enums.build();
        self.constified_enums.build();
    }
}

impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        BindgenOptions {
            hidden_types: Default::default(),
            opaque_types: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            bitfield_enums: Default::default(),
            constified_enums: Default::default(),
            builtins: false,
            links: vec![],
            emit_ast: false,
            emit_ir: false,
            emit_ir_graphviz: None,
            layout_tests: true,
            derive_debug: true,
            derive_default: false,
            enable_cxx_namespaces: false,
            disable_name_namespacing: false,
            unstable_rust: true,
            use_core: false,
            ctypes_prefix: None,
            namespaced_constants: true,
            msvc_mangling: false,
            convert_floats: true,
            raw_lines: vec![],
            clang_args: vec![],
            input_header: None,
            input_unsaved_files: vec![],
            dummy_uses: None,
            parse_callbacks: None,
            codegen_config: CodegenConfig::all(),
            conservative_inline_namespaces: false,
            generate_comments: true,
            generate_inline_functions: false,
            whitelist_recursively: true,
            objc_extern_crate: false,
            enable_mangling: true,
            prepend_enum_name: true,
        }
    }
}

/// The linking type to use with a given library.
///
/// TODO: #104: This is ignored at the moment, but shouldn't be.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LinkType {
    /// Use shared library linking. This is the default.
    Default,
    /// Use static linking.
    Static,
    /// The library is an OSX framework.
    Framework,
}

fn ensure_libclang_is_loaded() {
    if clang_sys::is_loaded() {
        return;
    }

    // XXX (issue #350): Ensure that our dynamically loaded `libclang`
    // doesn't get dropped prematurely, nor is loaded multiple times
    // across different threads.

    lazy_static! {
        static ref LIBCLANG: Arc<clang_sys::SharedLibrary> = {
            clang_sys::load().expect("Unable to find libclang");
            clang_sys::get_library()
                .expect("We just loaded libclang and it had better still be \
                        here!")
        };
    }

    clang_sys::set_library(Some(LIBCLANG.clone()));
}

/// Generated Rust bindings.
#[derive(Debug)]
pub struct Bindings<'ctx> {
    context: BindgenContext<'ctx>,
    module: ast::Mod,
}

impl<'ctx> Bindings<'ctx> {
    /// Generate bindings for the given options.
    ///
    /// Deprecated - use a `Builder` instead
    #[deprecated]
    pub fn generate(mut options: BindgenOptions,
                    span: Option<Span>)
                    -> Result<Bindings<'ctx>, ()> {
        let span = span.unwrap_or(DUMMY_SP);
        ensure_libclang_is_loaded();

        options.build();

        // TODO: Make this path fixup configurable?
        if let Some(clang) = clang_sys::support::Clang::find(None) {
            // If --target is specified, assume caller knows what they're doing
            // and don't mess with include paths for them
            let has_target_arg = options.clang_args
                .iter()
                .rposition(|arg| arg.starts_with("--target"))
                .is_some();
            if !has_target_arg {
                // TODO: distinguish C and C++ paths? C++'s should be enough, I
                // guess.
                if let Some(cpp_search_paths) = clang.cpp_search_paths {
                    for path in cpp_search_paths.into_iter() {
                        if let Ok(path) = path.into_os_string().into_string() {
                            options.clang_args.push("-isystem".to_owned());
                            options.clang_args.push(path);
                        }
                    }
                }
            }
        }

        if let Some(h) = options.input_header.as_ref() {
            options.clang_args.push(h.clone())
        }

        for f in options.input_unsaved_files.iter() {
            options.clang_args.push(f.name.to_str().unwrap().to_owned())
        }

        let mut context = BindgenContext::new(options);
        try!(parse(&mut context));

        let module = ast::Mod {
            inner: span,
            items: codegen::codegen(&mut context),
        };

        Ok(Bindings {
            context: context,
            module: module,
        })
    }

    /// Convert these bindings into a Rust AST.
    pub fn into_ast(self) -> Vec<P<ast::Item>> {
        self.module.items
    }

    /// Convert these bindings into source text (with raw lines prepended).
    pub fn to_string(&self) -> String {
        let mut mod_str = vec![];
        {
            let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
            self.write(ref_writer).expect("Could not write bindings to string");
        }
        String::from_utf8(mod_str).unwrap()
    }

    /// Write these bindings as source text to a file.
    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        let file = try!(OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(path));
        self.write(Box::new(file))
    }

    /// Write these bindings as source text to the given `Write`able.
    pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
        try!(writer.write("/* automatically generated by rust-bindgen */\n\n"
            .as_bytes()));

        for line in self.context.options().raw_lines.iter() {
            try!(writer.write(line.as_bytes()));
            try!(writer.write("\n".as_bytes()));
        }
        if !self.context.options().raw_lines.is_empty() {
            try!(writer.write("\n".as_bytes()));
        }

        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()
    }

    /// Generate and write dummy uses of all the types we parsed, if we've been
    /// requested to do so in the options.
    ///
    /// See the `uses` module for more information.
    pub fn write_dummy_uses(&mut self) -> io::Result<()> {
        let file = if let Some(ref dummy_path) =
            self.context.options().dummy_uses {
            Some(try!(OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(dummy_path)))
        } else {
            None
        };

        if let Some(file) = file {
            try!(uses::generate_dummy_uses(&mut self.context, file));
        }

        Ok(())
    }
}

/// Determines whether the given cursor is in any of the files matched by the
/// options.
fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
    ctx.options().builtins || !cursor.is_builtin()
}

/// Parse one `Item` from the Clang cursor.
pub fn parse_one(ctx: &mut BindgenContext,
                 cursor: clang::Cursor,
                 parent: Option<ItemId>)
                 -> clang_sys::CXChildVisitResult {
    if !filter_builtins(ctx, &cursor) {
        return CXChildVisit_Continue;
    }

    use clang_sys::CXChildVisit_Continue;
    match Item::parse(cursor, parent, ctx) {
        Ok(..) => {}
        Err(ParseError::Continue) => {}
        Err(ParseError::Recurse) => {
            cursor.visit(|child| parse_one(ctx, child, parent));
        }
    }
    CXChildVisit_Continue
}

/// Parse the Clang AST into our `Item` internal representation.
fn parse(context: &mut BindgenContext) -> Result<(), ()> {
    use clang_sys::*;

    let mut any_error = false;
    for d in context.translation_unit().diags().iter() {
        let msg = d.format();
        let is_err = d.severity() >= CXDiagnostic_Error;
        println!("{}, err: {}", msg, is_err);
        any_error |= is_err;
    }

    if any_error {
        return Err(());
    }

    let cursor = context.translation_unit().cursor();

    if context.options().emit_ast {

        fn dump_if_not_builtin(cur: &clang::Cursor) -> CXChildVisitResult {
            if !cur.is_builtin() {
                clang::ast_dump(&cur, 0)
            } else {
                CXChildVisit_Continue
            }
        }
        cursor.visit(|cur| dump_if_not_builtin(&cur));
    }

    let root = context.root_module();
    context.with_module(root, |context| {
        cursor.visit(|cursor| parse_one(context, cursor, None))
    });

    assert!(context.current_module() == context.root_module(),
            "How did this happen?");
    Ok(())
}

/// Extracted Clang version data
#[derive(Debug)]
pub struct ClangVersion {
    /// Major and minor semvar, if parsing was successful
    pub parsed: Option<(u32, u32)>,
    /// full version string
    pub full: String,
}

/// Get the major and the minor semvar numbers of Clang's version
pub fn clang_version() -> ClangVersion {
    if !clang_sys::is_loaded() {
        // TODO(emilio): Return meaningful error (breaking).
        clang_sys::load().expect("Unable to find libclang");
    }

    let raw_v: String = clang::extract_clang_version();
    let split_v: Option<Vec<&str>> = raw_v.split_whitespace()
        .nth(2)
        .map(|v| v.split('.').collect());
    match split_v {
        Some(v) => {
            if v.len() >= 2 {
                let maybe_major = v[0].parse::<u32>();
                let maybe_minor = v[1].parse::<u32>();
                match (maybe_major, maybe_minor) {
                    (Ok(major), Ok(minor)) => {
                        return ClangVersion {
                            parsed: Some((major, minor)),
                            full: raw_v.clone(),
                        }
                    }
                    _ => {}
                }
            }
        }
        None => {}
    };
    ClangVersion {
        parsed: None,
        full: raw_v.clone(),
    }
}

/// Test command_line_flag function.
#[test]
fn commandline_flag_unit_test_function() {
    //Test 1
    let bindings = ::builder();
    let command_line_flags = bindings.command_line_flags();

    let test_cases = vec!["--no-derive-default",
                          "--generate", "function,types,vars,methods,constructors,destructors"]
                    .iter()
                    .map(|&x| x.into())
                    .collect::<Vec<String>>();

    assert!(test_cases.iter().all(|ref x| command_line_flags.contains(x)) );

    //Test 2
    let bindings = ::builder().header("input_header")
                              .whitelisted_type("Distinct_Type")
                              .whitelisted_function("safe_function");

    let command_line_flags = bindings.command_line_flags();
    let test_cases = vec!["input_header",
                          "--no-derive-default",
                          "--generate", "function,types,vars,methods,constructors,destructors",
                          "--whitelist-type", "Distinct_Type",
                          "--whitelist-function", "safe_function"]
                    .iter()
                    .map(|&x| x.into())
                    .collect::<Vec<String>>();
    println!("{:?}", command_line_flags);

    assert!(test_cases.iter().all(|ref x| command_line_flags.contains(x)) );

}