aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-04-13 17:32:18 -0600
committerMelody Horn <melody@boringcactus.com>2021-04-13 17:32:18 -0600
commitaf8b16fa1f54494eaec594ddb5212620111c887c (patch)
treef9bebedc38f15b995af8fa8a1d89e38f3b74623a /src
parentb25fb845280bf3717644371efd7f4f73705ec808 (diff)
downloadmakers-af8b16fa1f54494eaec594ddb5212620111c887c.tar.gz
makers-af8b16fa1f54494eaec594ddb5212620111c887c.zip
correctly handle comments and non-comments
Diffstat (limited to 'src')
-rw-r--r--src/makefile/input.rs95
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(())
}