diff options
author | Melody Horn <melody@boringcactus.com> | 2021-03-28 00:36:23 -0600 |
---|---|---|
committer | Melody Horn <melody@boringcactus.com> | 2021-03-28 00:36:23 -0600 |
commit | 40920ea9d255f704116064d0b831666c7416caf2 (patch) | |
tree | bd0021cec78eb94cb2cb998c638d6b4cb52e3484 /src/makefile/mod.rs | |
parent | 2cd4d0f968c8097566edc0c6fbee10baf4b2647a (diff) | |
download | makers-40920ea9d255f704116064d0b831666c7416caf2.tar.gz makers-40920ea9d255f704116064d0b831666c7416caf2.zip |
add (& somewhat test!) GNUful conditionals
Diffstat (limited to 'src/makefile/mod.rs')
-rw-r--r-- | src/makefile/mod.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/makefile/mod.rs b/src/makefile/mod.rs index 2f73c70..0d4cded 100644 --- a/src/makefile/mod.rs +++ b/src/makefile/mod.rs @@ -13,11 +13,13 @@ use regex::Regex; use crate::args::Args; mod command_line; +mod conditional; mod inference_rules; mod target; mod token; use command_line::CommandLine; +use conditional::{ConditionalLine, ConditionalState}; use inference_rules::InferenceRule; use target::Target; use token::{tokenize, Token, TokenString}; @@ -151,6 +153,7 @@ impl<'a> Makefile<'a> { pub(crate) fn and_read(&mut self, source: impl BufRead) { let mut lines_iter = source.lines().enumerate().peekable(); + let mut conditional_stack: Vec<ConditionalState> = vec![]; while let Some((line_number, line)) = lines_iter.next() { // TODO handle I/O errors at all let mut line = line.expect("failed to read line of makefile!"); @@ -170,6 +173,14 @@ impl<'a> Makefile<'a> { } let line = COMMENT.replace(&line, "").into_owned(); + // skip lines if we need to + if conditional_stack + .last() + .map_or(false, ConditionalState::skipping) + { + continue; + } + // handle include lines if let Some(line) = line.strip_prefix("include ") { // remove extra leading space @@ -181,6 +192,14 @@ impl<'a> Makefile<'a> { for field in fields { self.and_read_file(field); } + } else if let Some(line) = ConditionalLine::from(&line, |t| self.expand_macros(t, None)) + { + line.action( + conditional_stack.last(), + |name| self.macros.contains_key(name), + |t| self.expand_macros(t, None), + ) + .apply_to(&mut conditional_stack); } else if line.trim().is_empty() { // handle blank lines continue; @@ -728,3 +747,38 @@ fn builtin_targets() -> Vec<Target> { already_updated: Cell::new(false), }] } + +#[cfg(test)] +mod test { + use super::*; + + use std::io::Cursor; + + fn empty_makefile(args: &Args) -> Makefile { + Makefile { + inference_rules: vec![], + macros: HashMap::new(), + targets: RefCell::new(HashMap::new()), + first_non_special_target: None, + args, + } + } + + #[test] + fn basic_conditionals() { + let file = " +ifeq (1,1) +worked = yes +else ifeq (2,2) +worked = no +endif + "; + let args = Args::empty(); + let mut makefile = empty_makefile(&args); + makefile.and_read(Cursor::new(file)); + assert_eq!( + makefile.expand_macros(&"$(worked)".parse().unwrap(), None), + "yes" + ); + } +} |