From e84322e5c45c5bc44a228e7912b5d50d7e91b841 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sat, 3 Apr 2021 18:27:36 -0600 Subject: finally fix newlines & peeking until something else breaks, at least --- src/makefile/input.rs | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/makefile/input.rs b/src/makefile/input.rs index 3a3508f..7c699f1 100644 --- a/src/makefile/input.rs +++ b/src/makefile/input.rs @@ -140,6 +140,8 @@ pub struct MakefileReader<'a, 'parent, R: BufRead> { pub first_non_special_target: Option, args: &'a Args, lines_iter: Peekable>>, + // join with escaped_newline_replacement to get the actual line + pending_line: Option<(usize, Vec)>, #[cfg(feature = "full")] conditional_stack: Vec, } @@ -167,6 +169,7 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { first_non_special_target: None, args, lines_iter: source.lines().line_numbered().peekable(), + pending_line: None, #[cfg(feature = "full")] conditional_stack: Vec::new(), }; @@ -175,7 +178,7 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { } fn read_all(&mut self) -> Result<()> { - while let Some((line_number, line)) = self.next_line(" ") { + while let Some((line_number, line)) = self.next_line(" ", false) { let line = line?; // handle include lines @@ -253,7 +256,14 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { fn next_line( &mut self, escaped_newline_replacement: &'static str, + peeking: bool, ) -> Option<(usize, Result)> { + if let Some((line_number, line)) = self.pending_line.take() { + if peeking { + self.pending_line = Some((line_number, line.clone())); + } + return Some((line_number, Ok(line.join(escaped_newline_replacement)))); + } while let Some((line_number, line)) = self.lines_iter.next() { let mut line = match line { Ok(x) => x, @@ -261,17 +271,18 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { }; // handle escaped newlines - while line.ends_with('\\') { - line.pop(); - line.push_str(escaped_newline_replacement); + let mut line_pieces = vec![line]; + while line_pieces.last().map_or(false, |p| p.ends_with('\\')) { + line_pieces.last_mut().map(|x| x.pop()); if let Some((n, x)) = self.lines_iter.next() { let x = match x { Ok(x) => x, Err(err) => return Some((n, Err(err))), }; - line.push_str(x.trim_start()) + line_pieces.push(x.trim_start().to_string()); } } + line = line_pieces.join(escaped_newline_replacement); // handle comments lazy_static! { @@ -310,6 +321,9 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { } } + if peeking { + self.pending_line = Some((line_number, line_pieces)); + } return Some((line_number, Ok(line))); } None @@ -322,8 +336,8 @@ impl<'a, 'parent, R: BufRead> MakefileReader<'a, 'parent, R> { escaped_newline_replacement: &'static str, predicate: impl FnOnce(&(usize, Result)) -> bool, ) -> Option<(usize, Result)> { - if predicate(self.lines_iter.peek()?) { - self.next_line(escaped_newline_replacement) + if predicate(&self.next_line(escaped_newline_replacement, true)?) { + self.next_line(escaped_newline_replacement, false) } else { None } @@ -446,7 +460,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(" ") { + while let Some((_, line)) = self.next_line(" ", false) { let line = line?; if line == "endef" { break; @@ -594,6 +608,21 @@ endif Ok(()) } + #[cfg(feature = "full")] + #[test] + fn condition_in_rule() -> R { + let file = " +a: +ifeq (1,1) +\tfoo +endif + "; + let args = Args::empty(); + let makefile = MakefileReader::read(&args, MacroSet::new(), Cursor::new(file))?; + assert_eq!(makefile.targets["a"].commands.len(), 1); + Ok(()) + } + #[cfg(feature = "full")] #[test] fn define_syntax() -> R { -- cgit v1.2.3