From 3ebe9a333c2cc2314ec5182d4f450e02d211bd7f Mon Sep 17 00:00:00 2001
From: Ryan Hunt <rhunt@eqrion.net>
Date: Thu, 13 Apr 2017 01:02:17 -0400
Subject: [PATCH] Use log and allow specifying verbosity

---
 Cargo.lock             |  7 ++++++
 Cargo.toml             |  1 +
 src/bindgen/library.rs | 33 +++++++++++++-------------
 src/logging.rs         | 54 ++++++++++++++++++++++++++++++++++++++++++
 src/main.rs            | 12 ++++++++++
 src/rust_lib.rs        |  6 ++---
 6 files changed, 92 insertions(+), 21 deletions(-)
 create mode 100644 src/logging.rs

diff --git a/Cargo.lock b/Cargo.lock
index a8734cd..6efac30 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,6 +3,7 @@ name = "cbindgen"
 version = "0.1.0"
 dependencies = [
  "clap 2.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -55,6 +56,11 @@ name = "libc"
 version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "log"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "quote"
 version = "0.3.14"
@@ -130,6 +136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum clap 2.23.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf1114886d7cde2d6448517161d7db8d681a9a1c09f7d210f0b0864e48195f6"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
+"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
 "checksum quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7375cf7ad34a92e8fd18dd9c42f58b9a11def59ab48bec955bf359a788335592"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)" = "37c279fb816210c9bb28b2c292664581e7b87b4561e86b94df462664d8620bb8"
diff --git a/Cargo.toml b/Cargo.toml
index bb247b5..8f58942 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ exclude = ["examples/**"]
 
 [dependencies]
 clap = "2.23.2"
+log = "0.3"
 
 [dependencies.syn]
 version = "0.11.8"
diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs
index dd12d84..50ca687 100644
--- a/src/bindgen/library.rs
+++ b/src/bindgen/library.rs
@@ -1,4 +1,3 @@
-use std::io;
 use std::io::Write;
 use std::collections::BTreeMap;
 use std::cmp::Ordering;
@@ -86,12 +85,12 @@ impl Library {
                         if item.is_no_mangle() && abi.is_c() {
                             match Function::convert(item.ident.to_string(), item.is_wr_destructor_safe(), decl) {
                                 Ok(func) => {
-                                    writeln!(io::stderr(), "take {}::{}", mod_name, &item.ident).unwrap();
+                                    info!("take {}::{}", mod_name, &item.ident);
 
                                     library.functions.insert(func.name.clone(), func);
                                 }
                                 Err(msg) => {
-                                    writeln!(io::stderr(), "skip {}::{} - ({})", mod_name, &item.ident, msg).unwrap();
+                                    info!("skip {}::{} - ({})", mod_name, &item.ident, msg);
                                 },
                             }
                         }
@@ -103,18 +102,18 @@ impl Library {
                         if item.is_repr_c() {
                             match Struct::convert(struct_name.clone(), variant, generics) {
                                 Ok(st) => {
-                                    writeln!(io::stderr(), "take {}::{}", mod_name, &item.ident).unwrap();
+                                    info!("take {}::{}", mod_name, &item.ident);
                                     library.structs.insert(struct_name,
                                                            st);
                                 }
                                 Err(msg) => {
-                                    writeln!(io::stderr(), "take {}::{} - opaque ({})", mod_name, &item.ident, msg).unwrap();
+                                    info!("take {}::{} - opaque ({})", mod_name, &item.ident, msg);
                                     library.opaque_structs.insert(struct_name.clone(),
                                                                   OpaqueStruct::new(struct_name));
                                 }
                             }
                         } else {
-                            writeln!(io::stderr(), "take {}::{} - opaque (not marked as repr(C))", mod_name, &item.ident).unwrap();
+                            info!("take {}::{} - opaque (not marked as repr(C))", mod_name, &item.ident);
                             library.opaque_structs.insert(struct_name.clone(),
                                                           OpaqueStruct::new(struct_name));
                         }
@@ -123,7 +122,7 @@ impl Library {
                         if !generics.lifetimes.is_empty() ||
                            !generics.ty_params.is_empty() ||
                            !generics.where_clause.predicates.is_empty() {
-                            writeln!(io::stderr(), "skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident).unwrap();
+                            info!("skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident);
                             continue;
                         }
 
@@ -132,22 +131,22 @@ impl Library {
 
                             match Enum::convert(enum_name.clone(), variants) {
                                 Ok(en) => {
-                                    writeln!(io::stderr(), "take {}::{}", mod_name, &item.ident).unwrap();
+                                    info!("take {}::{}", mod_name, &item.ident);
                                     library.enums.insert(enum_name, en);
                                 }
                                 Err(msg) => {
-                                    writeln!(io::stderr(), "skip {}::{} - ({})", mod_name, &item.ident, msg).unwrap();
+                                    info!("skip {}::{} - ({})", mod_name, &item.ident, msg);
                                 }
                             }
                         } else {
-                            writeln!(io::stderr(), "skip {}::{} - (not marked as repr(u32)", mod_name, &item.ident).unwrap();
+                            info!("skip {}::{} - (not marked as repr(u32)", mod_name, &item.ident);
                         }
                     }
                     ItemKind::Ty(ref ty, ref generics) => {
                         if !generics.lifetimes.is_empty() ||
                            !generics.ty_params.is_empty() ||
                            !generics.where_clause.predicates.is_empty() {
-                            writeln!(io::stderr(), "skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident).unwrap();
+                            info!("skip {}::{} - (has generics or lifetimes or where bounds)", mod_name, &item.ident);
                             continue;
                         }
 
@@ -155,7 +154,7 @@ impl Library {
 
                         let fail1 = match Specialization::convert(alias_name.clone(), ty) {
                             Ok(spec) => {
-                                writeln!(io::stderr(), "take {}::{}", mod_name, &item.ident).unwrap();
+                                info!("take {}::{}", mod_name, &item.ident);
                                 library.specializations.insert(alias_name, spec);
                                 continue;
                             }
@@ -163,13 +162,13 @@ impl Library {
                         };
                         let fail2 = match Typedef::convert(alias_name.clone(), ty) {
                             Ok(typedef) => {
-                                writeln!(io::stderr(), "take {}::{}", mod_name, &item.ident).unwrap();
+                                info!("take {}::{}", mod_name, &item.ident);
                                 library.typedefs.insert(alias_name, typedef);
                                 continue;
                             }
                             Err(msg) => msg,
                         };
-                        writeln!(io::stderr(), "skip {}::{} - ({} and {})", mod_name, &item.ident, fail1, fail2).unwrap();
+                        info!("skip {}::{} - ({} and {})", mod_name, &item.ident, fail1, fail2);
                     }
                     _ => {}
                 }
@@ -207,7 +206,7 @@ impl Library {
                 out.push(value);
             }
         } else {
-            writeln!(io::stderr(), "warning: can't find {}", p).unwrap();
+            warn!("can't find {}", p);
         }
     }
 
@@ -215,7 +214,7 @@ impl Library {
         if let Some(value) = self.resolve_path(p) {
             value.add_deps(self, out);
         } else {
-            writeln!(io::stderr(), "warning: can't find {}", p).unwrap();
+            warn!("can't find {}", p);
         }
     }
 
@@ -245,7 +244,7 @@ impl Library {
                             result.items.push(value);
                         }
                         Err(msg) => {
-                            writeln!(io::stderr(), "error: specializing {} failed - ({})", dep.name(), msg).unwrap();
+                            warn!("specializing {} failed - ({})", dep.name(), msg);
                         }
                     }
                     continue;
diff --git a/src/logging.rs b/src/logging.rs
new file mode 100644
index 0000000..c880949
--- /dev/null
+++ b/src/logging.rs
@@ -0,0 +1,54 @@
+use std::io;
+use std::io::Write;
+
+use log;
+use log::*;
+
+pub struct WarnLogger;
+pub struct InfoLogger;
+
+impl WarnLogger {
+    pub fn init() -> Result<(), SetLoggerError> {
+        log::set_logger(|max_log_level| {
+            max_log_level.set(LogLevelFilter::Warn);
+            Box::new(WarnLogger)
+        })
+    }
+}
+impl log::Log for WarnLogger {
+    fn enabled(&self, metadata: &LogMetadata) -> bool {
+        metadata.level() <= LogLevel::Warn
+    }
+
+    fn log(&self, record: &LogRecord) {
+        if self.enabled(record.metadata()) {
+            writeln!(io::stderr(),
+                   "{}: {}",
+                   record.level(),
+                   record.args()).unwrap();
+        }
+    }
+}
+
+impl InfoLogger {
+    pub fn init() -> Result<(), SetLoggerError> {
+        log::set_logger(|max_log_level| {
+            max_log_level.set(LogLevelFilter::Info);
+            Box::new(InfoLogger)
+        })
+    }
+}
+impl log::Log for InfoLogger {
+    fn enabled(&self, metadata: &LogMetadata) -> bool {
+        metadata.level() <= LogLevel::Info
+    }
+
+    fn log(&self, record: &LogRecord) {
+        if self.enabled(record.metadata()) {
+            writeln!(io::stderr(),
+                   "{}: {}",
+                   record.level(),
+                   record.args()).unwrap();
+        }
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index cc38605..c4530ba 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,11 +1,14 @@
 use std::io;
 use std::fs::File;
 
+#[macro_use]
+extern crate log;
 extern crate syn;
 extern crate clap;
 
 use clap::{Arg, App};
 
+mod logging;
 mod config;
 mod rust_lib;
 mod bindgen;
@@ -21,6 +24,9 @@ fn main() {
                          .long("config")
                          .value_name("CONFIG")
                          .help("the config to use. currently either `wr`, or `default`"))
+                    .arg(Arg::with_name("v")
+                         .short("v")
+                         .help("whether to print verbose logs"))
                     .arg(Arg::with_name("INPUT")
                          .help("the crate or source file to generate bindings for")
                          .required(true)
@@ -31,6 +37,12 @@ fn main() {
                          .index(2))
                     .get_matches();
 
+    if matches.is_present("v") {
+        logging::InfoLogger::init().unwrap();
+    } else {
+        logging::WarnLogger::init().unwrap();
+    }
+
     let input = matches.value_of("INPUT").unwrap();
     let config = match matches.value_of("config") {
         Some(c) => Config::load(c).expect("unknown config"),
diff --git a/src/rust_lib.rs b/src/rust_lib.rs
index f15d4d8..69c07d9 100644
--- a/src/rust_lib.rs
+++ b/src/rust_lib.rs
@@ -1,7 +1,5 @@
 use std::fs::File;
-use std::io;
 use std::io::Read;
-use std::io::Write;
 use std::path::PathBuf;
 
 use syn;
@@ -86,7 +84,7 @@ fn parse_mod<F>(crate_dir: PathBuf,
                               next_mod_path2,
                               items_callback);
                 } else {
-                    writeln!(io::stderr(), "warning, can't find a mod's file").unwrap();
+                    warn!("can't find mod {} in crate {}", next_mod_name, crate_name);
                 }
             }
             syn::ItemKind::ExternCrate(_) => {
@@ -96,7 +94,7 @@ fn parse_mod<F>(crate_dir: PathBuf,
                 let next_crate_path = crate_parent.join(next_crate_name.clone());
 
                 if !next_crate_path.exists() {
-                    writeln!(io::stderr(), "warning, can't find an extern crate {}", next_crate_name.clone()).unwrap();
+                    warn!("can't find extern crate {}", next_crate_name.clone());
                     continue;
                 }
 
-- 
GitLab