From 217d3d5fd38e6d326856a89289507c1c9caa72e4 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Wed, 22 Oct 2025 20:27:40 +0800 Subject: [PATCH] fix(windows): improve backslash handling in command lexer Handle multiple backslashes before quotes correctly by counting them and applying Windows command line parsing rules. Even number of backslashes before quote are treated as escape sequences, odd number as literal quotes. --- wfassoc/src/extra/windows.rs | 43 +++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/wfassoc/src/extra/windows.rs b/wfassoc/src/extra/windows.rs index 2175e05..0de5b6b 100644 --- a/wfassoc/src/extra/windows.rs +++ b/wfassoc/src/extra/windows.rs @@ -251,26 +251,33 @@ impl> Iterator for CmdLexer { // Handle backslash '\\' => { - if let Some(pc) = self.chars.peek().copied() { - match pc { - '\\' => { - // Double backslash are treated as single backslash - self.chars.next(); - token.push(pc); - } - '"' => { - // Backslash with an quote is interpreted as an literal quote - self.chars.next(); - token.push(pc); - } - _ => { - // Treated as normal backslash - token.push(c); - } + // Eat backslash as much as possible and count it. + let mut backslashes: usize = 1; + while self.chars.peek().copied() == Some('\\') { + self.chars.next(); + backslashes += 1; + } + + if self.chars.peek().copied() == Some('"') { + // Rule: backslashes before a double quote are special + + // consume the " + let quote = self.chars.next().unwrap(); + + // Even number: backslashes become half, quote is delimiter + // Odd number: backslashes become half, quote is literal + let num_slashes = backslashes / 2; + let is_literal_quote = backslashes % 2 != 0; + + token.push_str(&"\\".repeat(num_slashes)); + if is_literal_quote { + token.push(quote); + } else { + in_quotes = !in_quotes; } } else { - // There is no more chars, treat it as normal. - token.push(c); + // Not followed by quote: treat all backslashes literally + token.push_str(&"\\".repeat(backslashes)); } }