diff --git a/Cargo.toml b/Cargo.toml index 52f08025..338a99ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,8 +31,10 @@ path = "src/main.rs" cast = "0.2.2" clap = "2.26.0" either = "1.0.3" +env_logger = "~0.5" error-chain = "0.11.0" inflections = "1.1.0" +log = { version = "~0.4", features = ["std"] } quote = "0.3.15" svd-parser = "0.7.0" syn = "0.11.11" diff --git a/src/generate/peripheral.rs b/src/generate/peripheral.rs index 020f70e3..9cb88c68 100644 --- a/src/generate/peripheral.rs +++ b/src/generate/peripheral.rs @@ -7,6 +7,7 @@ use crate::svd::{ }; use quote::{ToTokens, Tokens}; use syn::{self, Ident}; +use log::warn; use crate::errors::*; use crate::util::{self, ToSanitizedSnakeCase, ToSanitizedUpperCase, BITS_PER_BYTE}; @@ -442,8 +443,8 @@ impl FieldRegions { r.fields.len() > 1 && (idents.iter().filter(|ident| **ident == r.ident).count() > 1) }) .inspect(|r| { - eprintln!( - "WARNING: Found type name conflict with region {:?}, renamed to {:?}", + warn!( + "Found type name conflict with region {:?}, renamed to {:?}", r.ident, r.shortest_ident() ) @@ -485,8 +486,8 @@ fn register_or_cluster_block_stable( let pad = if let Some(pad) = reg_block_field.offset.checked_sub(offset) { pad } else { - eprintln!( - "WARNING {:?} overlaps with another register block at offset {}. \ + warn!( + "{:?} overlaps with another register block at offset {}. \ Ignoring.", reg_block_field.field.ident, reg_block_field.offset ); @@ -574,8 +575,8 @@ fn register_or_cluster_block_nightly( if reg_block_field.offset != region.offset { // TODO: need to emit padding for this case. // Happens for freescale_mkl43z4 - eprintln!( - "WARNING: field {:?} has different offset {} than its union container {}", + warn!( + "field {:?} has different offset {} than its union container {}", reg_block_field.field.ident, reg_block_field.offset, region.offset ); } diff --git a/src/generate/register.rs b/src/generate/register.rs index 10c63452..2e0e5a2d 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -51,8 +51,8 @@ pub fn render( for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W { let bits = self.register.get(); - let r = R { bits: bits }; - let mut w = W { bits: bits }; + let r = R { bits }; + let mut w = W { bits }; f(&r, &mut w); self.register.set(w.bits); } diff --git a/src/lib.rs b/src/lib.rs index 823280d6..9192acb0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -463,7 +463,7 @@ pub enum SvdError { pub fn generate(xml: &str, target: Target, nightly: bool) -> Result { use std::fmt::Write; - let device = svd::parse(xml).expect("//TODO(AJM)"); + let device = svd::parse(xml).unwrap(); //TODO(AJM) let mut device_x = String::new(); let items = generate::device::render(&device, target, nightly, &mut device_x) .or(Err(SvdError::Render))?; diff --git a/src/main.rs b/src/main.rs index 42086e3f..9324a9b7 100755 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ #[macro_use] extern crate error_chain; #[macro_use] +extern crate log; +#[macro_use] extern crate quote; use svd_parser as svd; @@ -43,12 +45,25 @@ fn run() -> Result<()> { .long("nightly") .help("Enable features only available to nightly rustc"), ) + .arg( + Arg::with_name("log_level") + .long("log") + .short("l") + .help(&format!( + "Choose which messages to log (overrides {})", + env_logger::DEFAULT_FILTER_ENV + )) + .takes_value(true) + .possible_values(&["off", "error", "warn", "info", "debug", "trace"]) + ) .version(concat!( env!("CARGO_PKG_VERSION"), include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) )) .get_matches(); + setup_logging(&matches); + let target = matches .value_of("target") .map(|s| Target::parse(s)) @@ -71,7 +86,7 @@ fn run() -> Result<()> { } } - let device = svd::parse(xml).expect("//TODO(AJM)"); + let device = svd::parse(xml).unwrap(); //TODO(AJM) let nightly = matches.is_present("nightly_features"); @@ -88,21 +103,46 @@ fn run() -> Result<()> { Ok(()) } -fn main() { - if let Err(e) = &run() { - let stderr = io::stderr(); - let mut stderr = stderr.lock(); +fn setup_logging(matches: &clap::ArgMatches) { + // * Log at info by default. + // * Allow users the option of setting complex logging filters using + // env_logger's `RUST_LOG` environment variable. + // * Override both of those if the logging level is set via the `--log` + // command line argument. + let env = env_logger::Env::default() + .filter_or(env_logger::DEFAULT_FILTER_ENV, "info"); + let mut builder = env_logger::Builder::from_env(env); + builder.default_format_timestamp(false); + + let log_lvl_from_env = + std::env::var_os(env_logger::DEFAULT_FILTER_ENV).is_some(); + + if log_lvl_from_env { + log::set_max_level(log::LevelFilter::Trace); + } else { + let level = match matches.value_of("log_level") { + Some(lvl) => lvl.parse().unwrap(), + None => log::LevelFilter::Info, + }; + log::set_max_level(level); + builder.filter_level(level); + } - writeln!(stderr, "error: {}", e).ok(); + builder.init(); +} + +fn main() { + if let Err(ref e) = run() { + error!("{}", e); for e in e.iter().skip(1) { - writeln!(stderr, "caused by: {}", e).ok(); + error!("caused by: {}", e); } if let Some(backtrace) = e.backtrace() { - writeln!(stderr, "backtrace: {:?}", backtrace).ok(); + error!("backtrace: {:?}", backtrace); } else { - writeln!(stderr, "note: run with `RUST_BACKTRACE=1` for a backtrace").ok(); + error!("note: run with `RUST_BACKTRACE=1` for a backtrace") } process::exit(1);