From af8b16fa1f54494eaec594ddb5212620111c887c Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Tue, 13 Apr 2021 17:32:18 -0600 Subject: correctly handle comments and non-comments --- src/makefile/input.rs | 95 ++++++++++++++++++++++++++++++++++++++++----------- 1 file 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>> 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, @@ -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)> { + fn next_line(&mut self, settings: NextLineSettings) -> Option<(usize, Result)> { + 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)) -> bool, ) -> Option<(usize, Result)> { - 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::>(); - 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(()) } -- cgit v1.2.3