summaryrefslogtreecommitdiff
path: root/src/macro_processor/macro_processor.rs
diff options
context:
space:
mode:
authorQrius <[email protected]>2024-09-26 00:11:05 +0200
committerQrius <[email protected]>2024-09-26 00:11:05 +0200
commitb3d8f9033955440d49a4826591db713d5a86bf3a (patch)
treed56d2989a7a57ae9e989a3e8cd1e697b4d8218c0 /src/macro_processor/macro_processor.rs
parentd238af270d54aa96e2cb5a19b13bb2023c82a9e0 (diff)
downloadskaldpress-b3d8f9033955440d49a4826591db713d5a86bf3a.tar.gz
skaldpress-b3d8f9033955440d49a4826591db713d5a86bf3a.zip
Add propagation of warnings from SMP
Diffstat (limited to 'src/macro_processor/macro_processor.rs')
-rw-r--r--src/macro_processor/macro_processor.rs123
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(&timestamp)
- .map_err(|_| SMPError::UnknownError(87, None))?;
+ let dt = match chrono::DateTime::parse_from_rfc3339(&timestamp) {
+ 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