From ceb2ee16c46515dbd46267c2c93f5cb8f8d7ea47 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Wed, 14 Apr 2021 15:45:45 -0600 Subject: use full pattern matching for $(x:y%z=z%a) macro substitution --- src/makefile/macro.rs | 60 +++++++++++++++++++++++++++++++++++++++++++-------- src/makefile/mod.rs | 5 ++--- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/makefile/macro.rs b/src/makefile/macro.rs index af7e354..9b52206 100644 --- a/src/makefile/macro.rs +++ b/src/makefile/macro.rs @@ -6,6 +6,7 @@ use std::fmt; use std::rc::Rc; use eyre::{bail, Result, WrapErr}; +#[cfg(not(feature = "full"))] use regex::Regex; #[cfg(feature = "full")] @@ -238,15 +239,40 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { let macro_value = match replacement { Some((subst1, subst2)) => { let subst1 = self.expand(subst1)?; - let subst1_suffix = regex::escape(&subst1); - let subst1_suffix = Regex::new(&format!(r"{}(\s|$)", subst1_suffix)) - .context("formed invalid regex somehow")?; - let subst2 = self.expand(subst2)?; - subst1_suffix - .replace_all(¯o_value, |c: ®ex::Captures| { - format!("{}{}", subst2, c.get(1).unwrap().as_str()) - }) - .to_string() + #[cfg(feature = "full")] + { + let (subst1, subst2) = if subst1.contains('%') { + (subst1, subst2.clone()) + } else { + let mut real_subst2 = TokenString::text("%"); + real_subst2.extend(subst2.clone()); + (format!("%{}", subst1), real_subst2) + }; + let args = [ + TokenString::text(subst1), + subst2, + TokenString::text(macro_value), + ]; + functions::expand_call( + "patsubst", + &args, + self, + Some(Rc::clone(&self.to_eval)), + )? + } + #[cfg(not(feature = "full"))] + { + let subst1_suffix = regex::escape(&subst1); + let subst1_suffix = + Regex::new(&format!(r"{}(\s|$)", subst1_suffix)) + .context("formed invalid regex somehow")?; + let subst2 = self.expand(subst2)?; + subst1_suffix + .replace_all(¯o_value, |c: ®ex::Captures| { + format!("{}{}", subst2, c.get(1).unwrap().as_str()) + }) + .to_string() + } } None => macro_value, }; @@ -421,4 +447,20 @@ mod test { assert_eq!(macros.expand(&"$(oof:;=?)".parse()?)?, "bruh? swag? yeet?"); Ok(()) } + + #[test] + #[cfg(feature = "full")] + fn hell_subst() -> R { + let mut macros = Set::new(); + macros.set( + "m".to_owned(), + Macro { + source: ItemSource::FunctionCall, + text: TokenString::text("conf"), + eagerly_expanded: false, + }, + ); + assert_eq!(macros.expand(&"$(m:%=%-objs)".parse()?)?, "conf-objs"); + Ok(()) + } } diff --git a/src/makefile/mod.rs b/src/makefile/mod.rs index 8c50f41..1d4873e 100644 --- a/src/makefile/mod.rs +++ b/src/makefile/mod.rs @@ -203,7 +203,7 @@ impl<'a> Makefile<'a> { .filter(|rule| rule.matches(name).unwrap_or(false)); for rule in inference_rule_candidates { log::trace!( - "{:>58} considering rule to build {:?} from {:?}", + "{} considering rule to build {:?} from {:?}", name, &rule.products, &rule.prerequisites @@ -211,7 +211,6 @@ impl<'a> Makefile<'a> { // whose prerequisite file ($*.s2) exists. let prereq_paths = rule .prereqs(name)? - .inspect(|x| log::trace!("{:>58} prereq {}", name, x)) .map(|prereq_path_name| { if name == prereq_path_name || banned_names.contains(&&*prereq_path_name) { // we can't build this based on itself! fuck outta here @@ -250,7 +249,7 @@ impl<'a> Makefile<'a> { }) .collect::>>(); if let Some(prereqs) = prereq_paths { - log::trace!("oh {} is a {:#?}", name, rule); + log::trace!("oh {} is a {}", name, rule); new_target = Some(Target { name: name.into(), prerequisites: prereqs, -- cgit v1.2.3