diff options
author | Melody Horn <melody@boringcactus.com> | 2021-04-13 17:32:18 -0600 |
---|---|---|
committer | Melody Horn <melody@boringcactus.com> | 2021-04-13 17:32:18 -0600 |
commit | af8b16fa1f54494eaec594ddb5212620111c887c (patch) | |
tree | f9bebedc38f15b995af8fa8a1d89e38f3b74623a | |
parent | b25fb845280bf3717644371efd7f4f73705ec808 (diff) | |
download | makers-af8b16fa1f54494eaec594ddb5212620111c887c.tar.gz makers-af8b16fa1f54494eaec594ddb5212620111c887c.zip |
correctly handle comments and non-comments
-rw-r--r-- | src/makefile/input.rs | 95 |
1 files changed, 75 insertions, 20 deletions
diff --git a/src/makefile/input.rs b/src/makefile/input.rs index 0618109..7f49bef 100644 --- a/src/makefile/input.rs +++ b/src/makefile/input.rs @@ -144,6 +144,23 @@ impl<T, E: StdError + Send + Sync + 'static, I: Iterator<Item = Result<T, E>>> I { } +#[derive(Clone, Copy)] +struct NextLineSettings { + escaped_newline_replacement: &'static str, + peeking: bool, + strip_comments: bool, +} + +impl Default for NextLineSettings { + fn default() -> Self { + Self { + escaped_newline_replacement: " ", + peeking: false, + strip_comments: true, + } + } +} + pub struct MakefileReader<'a, 'parent, R: BufRead> { file_name: String, pub inference_rules: Vec<InferenceRule>, @@ -235,7 +252,11 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { } fn read_all(&mut self) -> Result<()> { - while let Some((line_number, line)) = self.next_line(" ", false) { + let topmost = NextLineSettings { + escaped_newline_replacement: " ", + ..Default::default() + }; + while let Some((line_number, line)) = self.next_line(topmost) { let line = line?; // handle include lines @@ -383,16 +404,28 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { Ok(()) } - fn next_line( - &mut self, - escaped_newline_replacement: &'static str, - peeking: bool, - ) -> Option<(usize, Result<String>)> { + fn next_line(&mut self, settings: NextLineSettings) -> Option<(usize, Result<String>)> { + lazy_static! { + static ref COMMENT: Regex = Regex::new(r"([^\\]|^)#.*$").unwrap(); + } + let escaped_newline_replacement = settings.escaped_newline_replacement; if let Some((line_number, line)) = self.pending_line.take() { - if peeking { + if settings.peeking { self.pending_line = Some((line_number, line.clone())); } - return Some((line_number, Ok(line.join(escaped_newline_replacement)))); + let line = line.join(escaped_newline_replacement); + let line = if settings.strip_comments { + // TODO only do this if we were in don't-strip-comments mode before + // TODO deduplicate + COMMENT + .replace(&line, "$1") + .replace(r"\#", "#") + .trim_end() + .to_owned() + } else { + line + }; + return Some((line_number, Ok(line))); } while let Some((line_number, line)) = self.lines_iter.next() { let line = match line { @@ -400,10 +433,15 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { Err(err) => return Some((line_number, Err(err))), }; // handle comments - lazy_static! { - static ref COMMENT: Regex = Regex::new("#.*$").unwrap(); - } - let line = COMMENT.replace(&line, "").trim_end().to_owned(); + let line = if settings.strip_comments { + COMMENT + .replace(&line, "$1") + .replace(r"\#", "#") + .trim_end() + .to_owned() + } else { + line + }; // handle escaped newlines let mut line_pieces = vec![line]; @@ -455,7 +493,7 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { } } - if peeking { + if settings.peeking { self.pending_line = Some((line_number, line_pieces)); } return Some((line_number, Ok(line))); @@ -467,11 +505,15 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { /// Doesn't apply the escaped newline replacement unless the predicate passes. fn next_line_if( &mut self, - escaped_newline_replacement: &'static str, + settings: NextLineSettings, predicate: impl FnOnce(&(usize, Result<String>)) -> bool, ) -> Option<(usize, Result<String>)> { - if predicate(&self.next_line(escaped_newline_replacement, true)?) { - self.next_line(escaped_newline_replacement, false) + let peek_settings = NextLineSettings { + peeking: true, + ..settings + }; + if predicate(&self.next_line(peek_settings)?) { + self.next_line(settings) } else { None } @@ -554,7 +596,12 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { .map(|x| x.into()) .collect::<Vec<String>>(); - while let Some((_, x)) = self.next_line_if("\\\n", |(_, x)| { + let settings = NextLineSettings { + escaped_newline_replacement: "\\\n", + strip_comments: false, + ..Default::default() + }; + while let Some((_, x)) = self.next_line_if(settings, |(_, x)| { x.as_ref() .ok() .map_or(false, |line| line.starts_with('\t') || line.is_empty()) @@ -695,7 +742,7 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { } let mut value = TokenString::empty(); // TODO what should be done with escaped newlines - while let Some((_, line)) = self.next_line(" ", false) { + while let Some((_, line)) = self.next_line(Default::default()) { let line = line?; if line == "endef" { break; @@ -980,7 +1027,6 @@ example: test\\#post info: \thello # there "; - eprintln!("{}", file); let args = Args::empty(); let makefile = MakefileReader::read(&args, MacroSet::new(), Cursor::new(file), "")?; let makefile = makefile.finish(); @@ -994,7 +1040,6 @@ info: already_updated: Cell::new(false) } ); - dbg!(&makefile.targets); assert_eq!( makefile.targets["example"], Target { @@ -1005,6 +1050,16 @@ info: already_updated: Cell::new(false) } ); + assert_eq!( + makefile.targets["info"], + Target { + name: "info".to_owned(), + prerequisites: vec![], + commands: vec![CommandLine::from(TokenString::text("hello # there")),], + stem: None, + already_updated: Cell::new(false) + } + ); Ok(()) } |