diff options
| author | Melody Horn <melody@boringcactus.com> | 2021-04-14 15:45:45 -0600 | 
|---|---|---|
| committer | Melody Horn <melody@boringcactus.com> | 2021-04-14 15:45:45 -0600 | 
| commit | ceb2ee16c46515dbd46267c2c93f5cb8f8d7ea47 (patch) | |
| tree | 18b7d7abc575fc0934ad2646c63a151006f8e577 | |
| parent | a17224fa6300452800c7162e9eb8948025a5dbb1 (diff) | |
| download | makers-ceb2ee16c46515dbd46267c2c93f5cb8f8d7ea47.tar.gz makers-ceb2ee16c46515dbd46267c2c93f5cb8f8d7ea47.zip | |
use full pattern matching for $(x:y%z=z%a) macro substitution
| -rw-r--r-- | src/makefile/macro.rs | 60 | ||||
| -rw-r--r-- | 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::<Option<Vec<String>>>();              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, |