diff options
Diffstat (limited to 'src/macro_processor')
-rw-r--r-- | src/macro_processor/macro_processor.rs | 123 |
1 files changed, 118 insertions, 5 deletions
diff --git a/src/macro_processor/macro_processor.rs b/src/macro_processor/macro_processor.rs index 2e8675f..b36783b 100644 --- a/src/macro_processor/macro_processor.rs +++ b/src/macro_processor/macro_processor.rs @@ -38,6 +38,12 @@ fn smp_builtin_define( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 1 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 1"), + )); return Ok(macro_name.to_string()); } let arg0 = smp.process_input(&args[0])?; @@ -57,6 +63,12 @@ fn smp_builtin_ifdef( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 2 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 2"), + )); return Ok(macro_name.to_string()); } // We need to expand the first argument here as well, but we need to make the parser @@ -77,6 +89,12 @@ fn smp_builtin_ifndef( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 2 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 2"), + )); return Ok(macro_name.to_string()); } // We need to expand the first argument here as well, but we need to make the parser @@ -97,6 +115,12 @@ fn smp_builtin_ifeq( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 3 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 3"), + )); return Ok(macro_name.to_string()); } let arg0 = smp.process_input(&args[0])?; @@ -117,6 +141,12 @@ fn smp_builtin_ifneq( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 3 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 3"), + )); return Ok(macro_name.to_string()); } let arg0 = smp.process_input(&args[0])?; @@ -137,6 +167,12 @@ fn smp_builtin_include( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 1 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 1"), + )); return Ok(macro_name.to_string()); } let arg0 = smp.process_input(&args[0])?; @@ -151,6 +187,12 @@ fn smp_builtin_include_verbatim( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 1 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 1"), + )); return Ok(macro_name.to_string()); } let arg0 = smp.process_input(&args[0])?; @@ -164,6 +206,12 @@ fn smp_builtin_shell( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 1 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 1"), + )); return Ok(macro_name.to_string()); } let arg0 = smp.process_input(&args[0])?; @@ -171,7 +219,15 @@ fn smp_builtin_shell( match res { Ok(output) => String::from_utf8(output.stdout) .map_err(|e| SMPError::ShellCommandError(1, Box::new(e))), - Err(_) => Ok(String::new()), + Err(e) => { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Error running shell command ({})", e), + )); + Ok(String::new()) + } } } @@ -182,6 +238,12 @@ fn smp_builtin_expr( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 1 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 1"), + )); return Ok(macro_name.to_string()); } @@ -189,11 +251,20 @@ fn smp_builtin_expr( *arg = smp.process_input(&arg)?; } - let res = Command::new("expr").args(args).output(); + let args = args.to_vec(); + let res = Command::new("expr").args(args.clone()).output(); match res { Ok(output) => String::from_utf8(output.stdout) .map_err(|e| SMPError::ShellCommandError(1, Box::new(e))), - Err(_) => Ok(String::new()), + Err(e) => { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + &args, + format!("Error running shell command ({})", e), + )); + Ok(String::new()) + } } } @@ -225,11 +296,27 @@ fn smp_builtin_format_time( args: &mut [String], ) -> Result<String, SMPError> { if args.len() < 2 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected at least 2"), + )); return Ok(macro_name.to_string()); } let timestamp = smp.process_input(&args[1])?; - let dt = chrono::DateTime::parse_from_rfc3339(×tamp) - .map_err(|_| SMPError::UnknownError(87, None))?; + let dt = match chrono::DateTime::parse_from_rfc3339(×tamp) { + Ok(dt) => dt, + Err(e) => { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Could not parse datetime {} ({})", timestamp, e), + )); + return Ok(timestamp); + } + }; Ok(format!("{}", dt.format(&args[0]))) } @@ -258,6 +345,29 @@ enum ParserState { DNL, } +#[derive(Clone, Debug)] +pub struct MacroProcessorWarning { + pub description: String, +} + +impl MacroProcessorWarning { + pub fn new(description: String) -> Self { + MacroProcessorWarning { description } + } + + pub fn from_macro_invocation(macro_name: &str, args: &[String], description: String) -> Self { + let mut desc = format!("{}(", macro_name); + for (i, arg) in args.iter().enumerate() { + desc.push_str(arg); + if i < (args.len() - 1) { + desc.push(','); + } + } + desc.push_str(&format!(") -> {}", description)); + MacroProcessorWarning { description: desc } + } +} + /// Defines a MacroProcessor object, with it's associated state /// the state mostly includes the defined macros #[derive(Clone)] @@ -266,6 +376,8 @@ pub struct MacroProcessor { pub macros: HashMap<String, MacroType>, /// All macro invocations that has happened pub macro_invocations: Vec<(String, Vec<String>)>, + /// Emitted warnings + pub warnings: Vec<MacroProcessorWarning>, } impl MacroProcessor { @@ -273,6 +385,7 @@ impl MacroProcessor { let mut smp = Self { macros: HashMap::new(), macro_invocations: Vec::new(), + warnings: Vec::new(), }; smp.define_builtins(); smp |