From 94049a42a0f61ab9f3ec7a0ea109a2e0ac9edfcc Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sat, 3 Apr 2021 13:42:49 -0600 Subject: correctly inherit macros --- src/main.rs | 8 +++++-- src/makefile/input.rs | 63 +++++++++++++++++++++++++++++++++++---------------- src/makefile/macro.rs | 6 ++--- src/makefile/mod.rs | 5 ++-- 4 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/main.rs b/src/main.rs index 668d2e2..c5240fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,9 +61,13 @@ fn main() -> Result<()> { let mut makefile = Makefile::new(&args); for filename in &args.makefile { if filename == &PathBuf::from("-") { - makefile.extend(MakefileReader::read(&args, stdin().lock())?); + let macros = makefile.macros.with_overlay(); + let file = MakefileReader::read(&args, macros, stdin().lock())?.finish(); + makefile.extend(file); } else { - makefile.extend(MakefileReader::read_file(&args, filename)?); + let macros = makefile.macros.with_overlay(); + let file = MakefileReader::read_file(&args, macros, filename)?.finish(); + makefile.extend(file); }; } diff --git a/src/makefile/input.rs b/src/makefile/input.rs index aa744c8..42187f4 100644 --- a/src/makefile/input.rs +++ b/src/makefile/input.rs @@ -129,9 +129,9 @@ impl>> I { } -pub struct MakefileReader<'a, R: BufRead> { +pub struct MakefileReader<'a, 'parent, R: BufRead> { pub inference_rules: Vec, - pub macros: MacroSet<'static, 'static>, + pub macros: MacroSet<'parent, 'static>, pub targets: HashMap, pub first_non_special_target: Option, args: &'a Args, @@ -141,21 +141,25 @@ pub struct MakefileReader<'a, R: BufRead> { conditional_stack: Vec, } -impl<'a> MakefileReader<'a, BufReader> { - pub fn read_file(args: &'a Args, path: impl AsRef) -> Result { +impl<'a, 'parent> MakefileReader<'a, 'parent, BufReader> { + pub fn read_file( + args: &'a Args, + macros: MacroSet<'parent, 'static>, + path: impl AsRef, + ) -> Result { let file = File::open(path); // TODO handle errors let file = file.context("couldn't open makefile!")?; let file_reader = BufReader::new(file); - Self::read(args, file_reader) + Self::read(args, macros, file_reader) } } -impl<'a, R: BufRead> MakefileReader<'a, R> { - pub fn read(args: &'a Args, source: R) -> Result { +impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { + pub fn read(args: &'a Args, macros: MacroSet<'parent, 'static>, source: R) -> Result { let mut reader = Self { inference_rules: Vec::new(), - macros: MacroSet::new(), + macros, targets: HashMap::new(), first_non_special_target: None, args, @@ -181,10 +185,11 @@ impl<'a, R: BufRead> MakefileReader<'a, R> { // POSIX says we only have to handle a single filename, but GNU make // handles arbitrarily many filenames, and it's not like that's more work for field in fields { - self.extend( - MakefileReader::read_file(self.args, field) - .with_context(|| format!("while including {}", field))?, - ); + let child_macros = self.macros.with_overlay(); + let child = MakefileReader::read_file(self.args, child_macros, field) + .with_context(|| format!("while including {}", field))? + .finish(); + self.extend(child); } continue; } @@ -211,10 +216,12 @@ impl<'a, R: BufRead> MakefileReader<'a, R> { { let eval = self.macros.to_eval.take(); for eval in eval { - self.extend( - MakefileReader::read(self.args, Cursor::new(eval)) - .context("while evaling")?, - ); + let child_macros = self.macros.with_overlay(); + let child = + MakefileReader::read(self.args, child_macros, Cursor::new(eval)) + .context("while evaling")? + .finish(); + self.extend(child); } } let line_type = LineType::of(&line_tokens); @@ -501,7 +508,16 @@ impl<'a, R: BufRead> MakefileReader<'a, R> { self.macros.expand(text) } - fn extend(&mut self, new: MakefileReader) { + pub fn finish(self) -> FinishedMakefileReader { + FinishedMakefileReader { + inference_rules: self.inference_rules, + macros: self.macros.data, + targets: self.targets, + first_non_special_target: self.first_non_special_target, + } + } + + fn extend(&mut self, new: FinishedMakefileReader) { self.inference_rules.extend(new.inference_rules); self.macros.extend(new.macros); self.targets.extend(new.targets); @@ -511,6 +527,13 @@ impl<'a, R: BufRead> MakefileReader<'a, R> { } } +pub struct FinishedMakefileReader { + pub inference_rules: Vec, + pub macros: HashMap, + pub targets: HashMap, + pub first_non_special_target: Option, +} + #[cfg(test)] mod test { use super::*; @@ -530,7 +553,7 @@ worked = perhaps endif "; let args = Args::empty(); - let makefile = MakefileReader::read(&args, Cursor::new(file))?; + let makefile = MakefileReader::read(&args, MacroSet::new(), Cursor::new(file))?; assert_eq!( makefile.expand_macros(&TokenString::r#macro("worked"))?, "yes" @@ -548,7 +571,7 @@ baz endef "; let args = Args::empty(); - let makefile = MakefileReader::read(&args, Cursor::new(file))?; + let makefile = MakefileReader::read(&args, MacroSet::new(), Cursor::new(file))?; assert_eq!( makefile.expand_macros(&TokenString::r#macro("foo"))?, "bar\nbaz" @@ -593,7 +616,7 @@ clean: "; let args = Args::empty(); - let makefile = MakefileReader::read(&args, Cursor::new(file))?; + let makefile = MakefileReader::read(&args, MacroSet::new(), Cursor::new(file))?; assert!(makefile.targets.contains_key("server")); Ok(()) } diff --git a/src/makefile/macro.rs b/src/makefile/macro.rs index a1f2378..310994d 100644 --- a/src/makefile/macro.rs +++ b/src/makefile/macro.rs @@ -28,7 +28,7 @@ impl Fn(&'a str) -> Result> LookupInternal for F {} #[derive(Clone)] pub struct Set<'parent, 'lookup> { parent: Option<&'parent Set<'parent, 'lookup>>, - data: HashMap, + pub data: HashMap, lookup_internal: Option<&'lookup dyn LookupInternal>, #[cfg(feature = "full")] pub to_eval: Rc>>, @@ -93,8 +93,8 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { self.data.remove(name) } - pub fn extend(&mut self, other: Set) { - self.data.extend(other.data); + pub fn extend(&mut self, other: HashMap) { + self.data.extend(other); } pub fn expand(&self, text: &TokenString) -> Result { diff --git a/src/makefile/mod.rs b/src/makefile/mod.rs index 88a3abb..3d824b9 100644 --- a/src/makefile/mod.rs +++ b/src/makefile/mod.rs @@ -24,6 +24,7 @@ mod token; use command_line::CommandLine; use inference_rules::InferenceRule; +use input::FinishedMakefileReader; pub use input::MakefileReader; use r#macro::{Set as MacroSet, Source as MacroSource}; use target::Target; @@ -31,7 +32,7 @@ use token::TokenString; pub struct Makefile<'a> { inference_rules: Vec, - macros: MacroSet<'static, 'static>, + pub macros: MacroSet<'static, 'static>, targets: RefCell>>>, pub first_non_special_target: Option, args: &'a Args, @@ -76,7 +77,7 @@ impl<'a> Makefile<'a> { } } - pub fn extend(&mut self, new: MakefileReader) { + pub fn extend(&mut self, new: FinishedMakefileReader) { self.inference_rules.extend(new.inference_rules); self.macros.extend(new.macros); self.targets.borrow_mut().extend( -- cgit v1.2.3