From 44077e37a816c0b80af1def174594182e0755e5f Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 24 Feb 2025 02:42:27 +0100 Subject: [PATCH] expr: Do not parse arguments using clap --- src/uu/expr/src/expr.rs | 31 ++++++++++++++++++++++--------- src/uu/expr/src/syntax_tree.rs | 22 +++++++++++----------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/uu/expr/src/expr.rs b/src/uu/expr/src/expr.rs index 4b9f6b9d6..99ae27e4a 100644 --- a/src/uu/expr/src/expr.rs +++ b/src/uu/expr/src/expr.rs @@ -94,16 +94,29 @@ pub fn uu_app() -> Command { pub fn uumain(args: impl uucore::Args) -> UResult<()> { // For expr utility we do not want getopts. // The following usage should work without escaping hyphens: `expr -15 = 1 + 2 \* \( 3 - -4 \)` - let matches = uu_app().try_get_matches_from(args)?; - let token_strings: Vec<&str> = matches - .get_many::(options::EXPRESSION) - .map(|v| v.into_iter().map(|s| s.as_ref()).collect::>()) - .unwrap_or_default(); + let args: Vec = args + .skip(1) // Skip binary name + .map(|a| a.to_string_lossy().to_string()) + .collect(); - let res: String = AstNode::parse(&token_strings)?.eval()?.eval_as_string(); - println!("{res}"); - if !is_truthy(&res.into()) { - return Err(1.into()); + if args.len() == 1 && args[0] == "--help" { + let _ = uu_app().print_help(); + } else if args.len() == 1 && args[0] == "--version" { + println!("{} {}", uucore::util_name(), crate_version!()) + } else { + // The first argument may be "--" and should be be ignored. + let args = if !args.is_empty() && args[0] == "--" { + &args[1..] + } else { + &args + }; + + let res: String = AstNode::parse(args)?.eval()?.eval_as_string(); + println!("{res}"); + if !is_truthy(&res.into()) { + return Err(1.into()); + } } + Ok(()) } diff --git a/src/uu/expr/src/syntax_tree.rs b/src/uu/expr/src/syntax_tree.rs index 008cd5307..149f24bb2 100644 --- a/src/uu/expr/src/syntax_tree.rs +++ b/src/uu/expr/src/syntax_tree.rs @@ -365,7 +365,7 @@ pub enum AstNode { } impl AstNode { - pub fn parse(input: &[&str]) -> ExprResult { + pub fn parse(input: &[impl AsRef]) -> ExprResult { Parser::new(input).parse() } @@ -427,13 +427,13 @@ impl AstNode { } } -struct Parser<'a> { - input: &'a [&'a str], +struct Parser<'a, S: AsRef> { + input: &'a [S], index: usize, } -impl<'a> Parser<'a> { - fn new(input: &'a [&'a str]) -> Self { +impl<'a, S: AsRef> Parser<'a, S> { + fn new(input: &'a [S]) -> Self { Self { input, index: 0 } } @@ -441,19 +441,19 @@ impl<'a> Parser<'a> { let next = self.input.get(self.index); if let Some(next) = next { self.index += 1; - Ok(next) + Ok(next.as_ref()) } else { // The indexing won't panic, because we know that the input size // is greater than zero. Err(ExprError::MissingArgument( - self.input[self.index - 1].into(), + self.input[self.index - 1].as_ref().into(), )) } } fn accept(&mut self, f: impl Fn(&str) -> Option) -> Option { let next = self.input.get(self.index)?; - let tok = f(next); + let tok = f(next.as_ref()); if let Some(tok) = tok { self.index += 1; Some(tok) @@ -468,7 +468,7 @@ impl<'a> Parser<'a> { } let res = self.parse_expression()?; if let Some(arg) = self.input.get(self.index) { - return Err(ExprError::UnexpectedArgument(arg.to_string())); + return Err(ExprError::UnexpectedArgument(arg.as_ref().into())); } Ok(res) } @@ -556,12 +556,12 @@ impl<'a> Parser<'a> { // at `self.index - 1`. So this indexing won't panic. Ok(_) => { return Err(ExprError::ExpectedClosingBraceInsteadOf( - self.input[self.index - 1].into(), + self.input[self.index - 1].as_ref().into(), )); } Err(ExprError::MissingArgument(_)) => { return Err(ExprError::ExpectedClosingBraceAfter( - self.input[self.index - 1].into(), + self.input[self.index - 1].as_ref().into(), )); } Err(e) => return Err(e),