|
6 | 6 | // spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction |
7 | 7 |
|
8 | 8 | pub mod native_int_str; |
9 | | -pub mod parse_error; |
10 | 9 | pub mod split_iterator; |
11 | 10 | pub mod string_expander; |
12 | 11 | pub mod string_parser; |
@@ -40,6 +39,42 @@ use uucore::line_ending::LineEnding; |
40 | 39 | use uucore::signals::signal_by_name_or_value; |
41 | 40 | use uucore::{format_usage, help_about, help_section, help_usage, show_warning}; |
42 | 41 |
|
| 42 | +use thiserror::Error; |
| 43 | + |
| 44 | +#[derive(Debug, Error, PartialEq)] |
| 45 | +pub enum EnvError { |
| 46 | + #[error("no terminating quote in -S string")] |
| 47 | + EnvMissingClosingQuote(usize, char), |
| 48 | + #[error("invalid backslash at end of string in -S")] |
| 49 | + EnvInvalidBackslashAtEndOfStringInMinusS(usize, String), |
| 50 | + #[error("'\\c' must not appear in double-quoted -S string")] |
| 51 | + EnvBackslashCNotAllowedInDoubleQuotes(usize), |
| 52 | + #[error("invalid sequence '\\{}' in -S",.1)] |
| 53 | + EnvInvalidSequenceBackslashXInMinusS(usize, char), |
| 54 | + #[error("Missing closing brace")] |
| 55 | + EnvParsingOfVariableMissingClosingBrace(usize), |
| 56 | + #[error("Missing variable name")] |
| 57 | + EnvParsingOfMissingVariable(usize), |
| 58 | + #[error("Missing closing brace after default value at {}",.0)] |
| 59 | + EnvParsingOfVariableMissingClosingBraceAfterValue(usize), |
| 60 | + #[error("Unexpected character: '{}', expected variable name must not start with 0..9",.1)] |
| 61 | + EnvParsingOfVariableUnexpectedNumber(usize, String), |
| 62 | + #[error("Unexpected character: '{}', expected a closing brace ('}}') or colon (':')",.1)] |
| 63 | + EnvParsingOfVariableExceptedBraceOrColon(usize, String), |
| 64 | + #[error("")] |
| 65 | + EnvReachedEnd, |
| 66 | + #[error("")] |
| 67 | + EnvContinueWithDelimiter, |
| 68 | + #[error("{}{:?}",.0,.1)] |
| 69 | + EnvInternalError(usize, string_parser::Error), |
| 70 | +} |
| 71 | + |
| 72 | +impl From<string_parser::Error> for EnvError { |
| 73 | + fn from(value: string_parser::Error) -> Self { |
| 74 | + EnvError::EnvInternalError(value.peek_position, value) |
| 75 | + } |
| 76 | +} |
| 77 | + |
43 | 78 | const ABOUT: &str = help_about!("env.md"); |
44 | 79 | const USAGE: &str = help_usage!("env.md"); |
45 | 80 | const AFTER_HELP: &str = help_section!("after help", "env.md"); |
@@ -273,20 +308,28 @@ pub fn uu_app() -> Command { |
273 | 308 |
|
274 | 309 | pub fn parse_args_from_str(text: &NativeIntStr) -> UResult<Vec<NativeIntString>> { |
275 | 310 | split_iterator::split(text).map_err(|e| match e { |
276 | | - parse_error::ParseError::BackslashCNotAllowedInDoubleQuotes { pos: _ } => { |
277 | | - USimpleError::new(125, "'\\c' must not appear in double-quoted -S string") |
| 311 | + EnvError::EnvBackslashCNotAllowedInDoubleQuotes(_) => USimpleError::new(125, e.to_string()), |
| 312 | + EnvError::EnvInvalidBackslashAtEndOfStringInMinusS(_, _) => { |
| 313 | + USimpleError::new(125, e.to_string()) |
| 314 | + } |
| 315 | + EnvError::EnvInvalidSequenceBackslashXInMinusS(_, _) => { |
| 316 | + USimpleError::new(125, e.to_string()) |
| 317 | + } |
| 318 | + EnvError::EnvMissingClosingQuote(_, _) => USimpleError::new(125, e.to_string()), |
| 319 | + EnvError::EnvParsingOfVariableMissingClosingBrace(pos) => { |
| 320 | + USimpleError::new(125, format!("variable name issue (at {pos}): {}", e)) |
278 | 321 | } |
279 | | - parse_error::ParseError::InvalidBackslashAtEndOfStringInMinusS { pos: _, quoting: _ } => { |
280 | | - USimpleError::new(125, "invalid backslash at end of string in -S") |
| 322 | + EnvError::EnvParsingOfMissingVariable(pos) => { |
| 323 | + USimpleError::new(125, format!("variable name issue (at {pos}): {}", e)) |
281 | 324 | } |
282 | | - parse_error::ParseError::InvalidSequenceBackslashXInMinusS { pos: _, c } => { |
283 | | - USimpleError::new(125, format!("invalid sequence '\\{c}' in -S")) |
| 325 | + EnvError::EnvParsingOfVariableMissingClosingBraceAfterValue(pos) => { |
| 326 | + USimpleError::new(125, format!("variable name issue (at {pos}): {}", e)) |
284 | 327 | } |
285 | | - parse_error::ParseError::MissingClosingQuote { pos: _, c: _ } => { |
286 | | - USimpleError::new(125, "no terminating quote in -S string") |
| 328 | + EnvError::EnvParsingOfVariableUnexpectedNumber(pos, _) => { |
| 329 | + USimpleError::new(125, format!("variable name issue (at {pos}): {}", e)) |
287 | 330 | } |
288 | | - parse_error::ParseError::ParsingOfVariableNameFailed { pos, msg } => { |
289 | | - USimpleError::new(125, format!("variable name issue (at {pos}): {msg}",)) |
| 331 | + EnvError::EnvParsingOfVariableExceptedBraceOrColon(pos, _) => { |
| 332 | + USimpleError::new(125, format!("variable name issue (at {pos}): {}", e)) |
290 | 333 | } |
291 | 334 | _ => USimpleError::new(125, format!("Error: {e:?}")), |
292 | 335 | }) |
@@ -771,4 +814,68 @@ mod tests { |
771 | 814 | parse_args_from_str(&NCvt::convert(r#"-i A='B \' C'"#)).unwrap() |
772 | 815 | ); |
773 | 816 | } |
| 817 | + |
| 818 | + #[test] |
| 819 | + fn test_error_cases() { |
| 820 | + // Test EnvBackslashCNotAllowedInDoubleQuotes |
| 821 | + let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo \c""#)); |
| 822 | + assert!(result.is_err()); |
| 823 | + assert_eq!( |
| 824 | + result.unwrap_err().to_string(), |
| 825 | + "'\\c' must not appear in double-quoted -S string" |
| 826 | + ); |
| 827 | + |
| 828 | + // Test EnvInvalidBackslashAtEndOfStringInMinusS |
| 829 | + let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo \"#)); |
| 830 | + assert!(result.is_err()); |
| 831 | + assert_eq!( |
| 832 | + result.unwrap_err().to_string(), |
| 833 | + "no terminating quote in -S string" |
| 834 | + ); |
| 835 | + |
| 836 | + // Test EnvInvalidSequenceBackslashXInMinusS |
| 837 | + let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo \x""#)); |
| 838 | + assert!(result.is_err()); |
| 839 | + assert!( |
| 840 | + result |
| 841 | + .unwrap_err() |
| 842 | + .to_string() |
| 843 | + .contains("invalid sequence '\\x' in -S") |
| 844 | + ); |
| 845 | + |
| 846 | + // Test EnvMissingClosingQuote |
| 847 | + let result = parse_args_from_str(&NCvt::convert(r#"sh -c "echo "#)); |
| 848 | + assert!(result.is_err()); |
| 849 | + assert_eq!( |
| 850 | + result.unwrap_err().to_string(), |
| 851 | + "no terminating quote in -S string" |
| 852 | + ); |
| 853 | + |
| 854 | + // Test variable-related errors |
| 855 | + let result = parse_args_from_str(&NCvt::convert(r#"echo ${FOO"#)); |
| 856 | + assert!(result.is_err()); |
| 857 | + assert!( |
| 858 | + result |
| 859 | + .unwrap_err() |
| 860 | + .to_string() |
| 861 | + .contains("variable name issue (at 10): Missing closing brace") |
| 862 | + ); |
| 863 | + |
| 864 | + let result = parse_args_from_str(&NCvt::convert(r#"echo ${FOO:-value"#)); |
| 865 | + assert!(result.is_err()); |
| 866 | + assert!( |
| 867 | + result |
| 868 | + .unwrap_err() |
| 869 | + .to_string() |
| 870 | + .contains("variable name issue (at 17): Missing closing brace after default value") |
| 871 | + ); |
| 872 | + |
| 873 | + let result = parse_args_from_str(&NCvt::convert(r#"echo ${1FOO}"#)); |
| 874 | + assert!(result.is_err()); |
| 875 | + assert!(result.unwrap_err().to_string().contains("variable name issue (at 7): Unexpected character: '1', expected variable name must not start with 0..9")); |
| 876 | + |
| 877 | + let result = parse_args_from_str(&NCvt::convert(r#"echo ${FOO?}"#)); |
| 878 | + assert!(result.is_err()); |
| 879 | + assert!(result.unwrap_err().to_string().contains("variable name issue (at 10): Unexpected character: '?', expected a closing brace ('}') or colon (':')")); |
| 880 | + } |
774 | 881 | } |
0 commit comments