aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-04-03 13:42:49 -0600
committerMelody Horn <melody@boringcactus.com>2021-04-03 13:42:49 -0600
commit94049a42a0f61ab9f3ec7a0ea109a2e0ac9edfcc (patch)
treee1252c7ba2b863fec75469de25b898199c19cc23
parent101c96b03ecf180af986bc20b7161b0933ae47cf (diff)
downloadmakers-94049a42a0f61ab9f3ec7a0ea109a2e0ac9edfcc.tar.gz
makers-94049a42a0f61ab9f3ec7a0ea109a2e0ac9edfcc.zip
correctly inherit macros
-rw-r--r--src/main.rs8
-rw-r--r--src/makefile/input.rs63
-rw-r--r--src/makefile/macro.rs6
-rw-r--r--src/makefile/mod.rs5
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<T, E: StdError + Send + Sync + 'static, I: Iterator<Item = Result<T, E>>> I
{
}
-pub struct MakefileReader<'a, R: BufRead> {
+pub struct MakefileReader<'a, 'parent, R: BufRead> {
pub inference_rules: Vec<InferenceRule>,
- pub macros: MacroSet<'static, 'static>,
+ pub macros: MacroSet<'parent, 'static>,
pub targets: HashMap<String, Target>,
pub first_non_special_target: Option<String>,
args: &'a Args,
@@ -141,21 +141,25 @@ pub struct MakefileReader<'a, R: BufRead> {
conditional_stack: Vec<ConditionalState>,
}
-impl<'a> MakefileReader<'a, BufReader<File>> {
- pub fn read_file(args: &'a Args, path: impl AsRef<Path>) -> Result<Self> {
+impl<'a, 'parent> MakefileReader<'a, 'parent, BufReader<File>> {
+ pub fn read_file(
+ args: &'a Args,
+ macros: MacroSet<'parent, 'static>,
+ path: impl AsRef<Path>,
+ ) -> Result<Self> {
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<Self> {
+impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> {
+ pub fn read(args: &'a Args, macros: MacroSet<'parent, 'static>, source: R) -> Result<Self> {
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<R2: BufRead>(&mut self, new: MakefileReader<R2>) {
+ 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<InferenceRule>,
+ pub macros: HashMap<String, (MacroSource, TokenString)>,
+ pub targets: HashMap<String, Target>,
+ pub first_non_special_target: Option<String>,
+}
+
#[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<F: for<'a> Fn(&'a str) -> Result<String>> LookupInternal for F {}
#[derive(Clone)]
pub struct Set<'parent, 'lookup> {
parent: Option<&'parent Set<'parent, 'lookup>>,
- data: HashMap<String, (Source, TokenString)>,
+ pub data: HashMap<String, (Source, TokenString)>,
lookup_internal: Option<&'lookup dyn LookupInternal>,
#[cfg(feature = "full")]
pub to_eval: Rc<RefCell<Vec<String>>>,
@@ -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<String, (Source, TokenString)>) {
+ self.data.extend(other);
}
pub fn expand(&self, text: &TokenString) -> Result<String> {
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<InferenceRule>,
- macros: MacroSet<'static, 'static>,
+ pub macros: MacroSet<'static, 'static>,
targets: RefCell<HashMap<String, Rc<RefCell<Target>>>>,
pub first_non_special_target: Option<String>,
args: &'a Args,
@@ -76,7 +77,7 @@ impl<'a> Makefile<'a> {
}
}
- pub fn extend<R: std::io::BufRead>(&mut self, new: MakefileReader<R>) {
+ pub fn extend(&mut self, new: FinishedMakefileReader) {
self.inference_rules.extend(new.inference_rules);
self.macros.extend(new.macros);
self.targets.borrow_mut().extend(