aboutsummaryrefslogtreecommitdiff
path: root/src/makefile/input.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/makefile/input.rs')
-rw-r--r--src/makefile/input.rs63
1 files changed, 43 insertions, 20 deletions
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(())
}