//! 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 regex;
#[macro_use]
extern crate lazy_static;

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

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

// A macro to declare an internal module for which we *must* provide
// documentation for. If we are building with the "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 = "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 chooser;

#[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, Mutex};

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,
}

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

    /// Generate nothing.
    pub fn nothing() -> Self {
        CodegenConfig {
            functions: false,
            types: false,
            vars: false,
            methods: false,
            constructors: 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 {
    /// Set the input C/C++ header.
    pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
        let header = header.into();
        self.options.input_header = Some(header);
        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`).
    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
    }

    /// 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
    }

    /// 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 `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 auto-namespacing of names if namespaces are disabled.
    ///
    /// By default, if namespaces are disabled, bindgen tries to mangle the
    /// names to from `foo::bar::Baz` to look like `foo_bar_Baz`, instead of
    /// just `Baz`.
    ///
    /// This option disables that behavior.
    ///
    /// Note that this intentionally doesn't change the names using for
    /// whitelisting and blacklisting, that should still be mangled with the
    /// namespaces.
    ///
    /// Note, also, that using this option may cause duplicated names to be
    /// generated.
    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
    }

    /// 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 `TypeChooser`
    /// documentation.
    pub fn type_chooser(mut self, cb: Box<chooser::TypeChooser>) -> Self {
        self.options.type_chooser = Some(cb);
        self
    }

    /// Choose what to generate using a CodegenConfig.
    pub fn with_codegen_config(mut self, config: CodegenConfig) -> Self {
        self.options.codegen_config = config;
        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 shold derive Debug trait implementations for C/C++ structures
    /// and types.
    pub derive_debug: bool,

    /// True if we shold 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>,

    /// 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 type chooser to allow customizing different kinds of
    /// situations.
    pub type_chooser: Option<Box<chooser::TypeChooser>>,

    /// 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,

    /// 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,
}

/// 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,
            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,
            dummy_uses: None,
            type_chooser: None,
            codegen_config: CodegenConfig::all(),
            conservative_inline_namespaces: false,
            generate_comments: true,
            whitelist_recursively: true,
            objc_extern_crate: false,
        }
    }
}

/// 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: Mutex<Option<Arc<clang_sys::SharedLibrary>>> = {
            Mutex::new(None)
        };
    }

    let mut libclang = LIBCLANG.lock().unwrap();
    if !clang_sys::is_loaded() {
        if libclang.is_none() {
            // TODO(emilio): Return meaningful error (breaking).
            clang_sys::load().expect("Unable to find libclang");
            *libclang = Some(clang_sys::get_library()
                .expect("We just loaded libclang and it had \
                                     better still be here!"));
        } else {
            clang_sys::set_library(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.
                for path in clang.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())
        }

        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 {
    let (file, _, _, _) = cursor.location().location();

    match file.name() {
        None => ctx.options().builtins,
        Some(..) => true,
    }
}

/// 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 {
        cursor.visit(|cur| clang::ast_dump(&cur, 0));
    }

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