From 050a3b166123be17c8dfdbd47e1b439040101884 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sun, 4 Apr 2021 15:17:12 -0600 Subject: don't assume something's an inference rule unless it's on the suffix list --- src/makefile/input.rs | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/makefile/input.rs b/src/makefile/input.rs index b02cdb6..5afecc6 100644 --- a/src/makefile/input.rs +++ b/src/makefile/input.rs @@ -63,10 +63,16 @@ impl LineType { } } +#[derive(Debug)] +struct InferenceMatch<'a> { + s1: &'a str, + s2: &'a str, +} + fn inference_match<'a>( targets: &[&'a str], prerequisites: &[String], -) -> Option> { +) -> Option> { lazy_static! { static ref INFERENCE_RULE: Regex = Regex::new(r"^(?P(\.[^/.]+)?)(?P\.[^/.]+)$").unwrap(); @@ -81,7 +87,10 @@ fn inference_match<'a>( && inference_match.is_some() && special_target_match.is_none(); if inference_rule { - inference_match + inference_match.map(|x| InferenceMatch { + s1: x.name("s1").unwrap().as_str(), + s2: x.name("s2").unwrap().as_str(), + }) } else { None } @@ -343,6 +352,15 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { } } + fn special_target_has_prereq(&self, target: &str, name: &str) -> bool { + match self.targets.get(target) { + Some(target) => { + target.prerequisites.is_empty() || target.prerequisites.iter().any(|e| e == name) + } + None => false, + } + } + fn read_rule(&mut self, line_tokens: &TokenString, line_number: usize) -> Result<()> { let (targets, not_targets) = line_tokens .split_once(':') @@ -407,10 +425,23 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { return Ok(()); } + // don't interpret things like `.tmp: ; mkdir -p $@` as single-suffix rules + let inference_match = inference_match.and_then(|inference| { + if (inference.s1.is_empty() + || self.special_target_has_prereq(".SUFFIXES", inference.s1)) + && (inference.s2.is_empty() + || self.special_target_has_prereq(".SUFFIXES", inference.s2)) + { + Some(inference) + } else { + None + } + }); + if let Some(inference_match) = inference_match { let new_rule = InferenceRule::new_suffix( - inference_match.name("s1").unwrap().as_str().to_owned(), - inference_match.name("s2").unwrap().as_str().to_owned(), + inference_match.s1.to_owned(), + inference_match.s2.to_owned(), commands, ); log::trace!( -- cgit v1.2.3