aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-04-03 18:27:36 -0600
committerMelody Horn <melody@boringcactus.com>2021-04-03 18:27:36 -0600
commite84322e5c45c5bc44a228e7912b5d50d7e91b841 (patch)
treea7f19ffbce12eb2b58fbafa7115cbdf1a49117cf
parent13b90ab94dd884be95207e3004c65657db815ffa (diff)
downloadmakers-e84322e5c45c5bc44a228e7912b5d50d7e91b841.tar.gz
makers-e84322e5c45c5bc44a228e7912b5d50d7e91b841.zip
finally fix newlines & peeking
until something else breaks, at least
-rw-r--r--src/makefile/input.rs45
1 files 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<String>,
args: &'a Args,
lines_iter: Peekable<LineNumbers<String, IoError, Lines<R>>>,
+ // join with escaped_newline_replacement to get the actual line
+ pending_line: Option<(usize, Vec<String>)>,
#[cfg(feature = "full")]
conditional_stack: Vec<ConditionalState>,
}
@@ -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<String>)> {
+ 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<String>)) -> bool,
) -> Option<(usize, Result<String>)> {
- 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;
@@ -596,6 +610,21 @@ endif
#[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 {
let file = "
define foo =