mirror of
https://github.com/uutils/grep.git
synced 2026-06-10 16:15:11 -07:00
grep: emit GNU's 'Invalid range end' for reversed bracket ranges
A reversed range like [b-a] makes oniguruma fail with 'empty range in char class', which uu_grep wrapped as 'invalid pattern "[b-a]": ...'. GNU grep instead prints the bare POSIX diagnostic 'Invalid range end' and exits 2. Translate the oniguruma error code (ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS) to GNU's wording, leaving other compile errors to fall back to oniguruma's text. Fixes the GNU testsuite 'reversed-range-endpoints' test.
This commit is contained in:
+22
-2
@@ -8,7 +8,9 @@ use onig::{
|
||||
EncodedBytes, Regex, RegexOptions, Region, SearchOptions, Syntax, SyntaxBehavior,
|
||||
SyntaxOperator,
|
||||
};
|
||||
use onig_sys::{OnigEncCtype_ONIGENC_CTYPE_WORD, OnigEncodingUTF8};
|
||||
use onig_sys::{
|
||||
ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS, OnigEncCtype_ONIGENC_CTYPE_WORD, OnigEncodingUTF8,
|
||||
};
|
||||
use uucore::error::{UResult, USimpleError};
|
||||
|
||||
pub struct Matcher<'a> {
|
||||
@@ -240,7 +242,12 @@ impl CompiledPattern {
|
||||
|
||||
fn compile_with(pattern: &str, syntax: &Syntax, options: RegexOptions) -> UResult<Regex> {
|
||||
Regex::with_options_and_encoding(pattern, options, syntax).map_err(|err| {
|
||||
USimpleError::new(2, format!("invalid pattern \"{pattern}\": {err}"))
|
||||
// Prefer GNU grep's wording for the errors it has a dedicated
|
||||
// message for; fall back to oniguruma's text otherwise.
|
||||
match gnu_error_message(err.code()) {
|
||||
Some(msg) => USimpleError::new(2, msg.to_string()),
|
||||
None => USimpleError::new(2, format!("invalid pattern \"{pattern}\": {err}")),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -296,6 +303,19 @@ impl CompiledPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Map an oniguruma compile-error code to GNU grep's wording for the same
|
||||
/// condition, when one exists. GNU emits a bare POSIX-style diagnostic (e.g.
|
||||
/// `Invalid range end`) rather than oniguruma's phrasing, so translating keeps
|
||||
/// us byte-compatible. Returns `None` for errors with no GNU equivalent, where
|
||||
/// the caller falls back to oniguruma's own message.
|
||||
fn gnu_error_message(code: i32) -> Option<&'static str> {
|
||||
match code {
|
||||
// e.g. `[b-a]`: a range whose end precedes its start.
|
||||
ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS => Some("Invalid range end"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reject the confusing `[:name:]` bracket form the way GNU grep does.
|
||||
///
|
||||
/// A bracket expression like `[:space:]` is almost always a misspelled
|
||||
|
||||
@@ -180,6 +180,19 @@ fn lookalike_brackets_are_not_confusing() {
|
||||
.no_output();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reversed_range_uses_gnu_wording() {
|
||||
// A range like `[b-a]` is an error; GNU prints the bare POSIX diagnostic
|
||||
// "Invalid range end" (not oniguruma's phrasing) and exits 2.
|
||||
for args in [&["[b-a]"][..], &["-E", "[b-a]"][..]] {
|
||||
let (_s, mut c) = ucmd();
|
||||
c.args(args)
|
||||
.pipe_in("x\n")
|
||||
.fails_with_code(2)
|
||||
.stderr_is("grep: Invalid range end\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixed_string_is_literal() {
|
||||
// Metacharacters are not interpreted.
|
||||
|
||||
Reference in New Issue
Block a user