20 Commits

Author SHA1 Message Date
Wondr e925ff4ac8 grep: honor GNU buffer anchors (#56) 2026-06-05 17:33:23 +02:00
Leonard Hecker 265a562c26 grep: Simplify session_finalize 2026-06-05 17:04:29 +02:00
Wondr 55a7b0180b grep: suppress EOF output in quiet mode (#41) 2026-06-05 16:48:36 +02:00
Wondr d556159952 grep: let dot match newline in null-data mode (#45) 2026-06-05 16:25:04 +02:00
Wondr 7c79cb4e3a grep: keep invalid UTF-8 text under -I (#49) 2026-06-05 16:06:49 +02:00
Sylvestre Ledru b4980df814 Merge pull request #16 from uutils/literal-fast-path
perf: buffer-at-a-time search for literal patterns
2026-06-05 08:28:04 +02:00
Sylvestre Ledru e9825e3503 Merge pull request #12 from uutils/grep-initial-tab-empty-line
grep: don't emit the -T alignment tab on empty lines
2026-06-05 08:27:43 +02:00
Sylvestre Ledru f5d5f6c063 Merge pull request #40 from koopatroopa787/issue-34-perl-single-pattern
fix: reject multiple patterns when -P/--perl-regexp is used
2026-06-05 08:25:18 +02:00
Wondr ad7595ffe6 grep: select zero-width matches under -w and -x 2026-06-05 04:39:22 +01:00
Kanishk Sachan e3d80f59e2 fix: reject multiple patterns when -P/--perl-regexp is used
GNU grep's PCRE backend supports only a single pattern. Supplying
multiple patterns via repeated -e flags, or a pattern string that
contains a literal newline, must exit 2 with the message:

    the -P option only supports a single pattern

Add the validation immediately after patterns are collected, before
regex-mode selection. Add a test covering:
  - two separate -e flags with -P
  - a newline-embedded pattern string with -P
  - single -e with -P still works normally

Closes #34
2026-06-05 01:25:22 +01:00
Sylvestre Ledru 28186e9ec3 perf: buffer-at-a-time search for literal patterns
Literal searches were ~50-70x slower than GNU grep because every line
paid per-line costs (terminator scan, NUL scan, dispatch) even when a
buffer held no match. Add a buffer-at-a-time driver that scans whole
chunks with a substring searcher and only locates line boundaries
around the matches it finds; a chunk with no match costs a single
vectorized sweep and no per-line work.

The driver activates only for plain ASCII literal patterns (case
sensitive, no metacharacters) in the simpler output modes: -c, -l, -L,
-q, and plain line printing with -n/-b/filename/-m. Anything needing
match positions, context, inversion, color, or special binary handling
falls back to the unchanged line-at-a-time path. Output stays
byte-identical to that path, including binary/invalid-UTF-8 behavior.

- line_buffer: read_chunk() yields the largest span of complete lines.
- matcher: expose per-pattern memmem searchers when every pattern is a
  plain literal (plain_literal()).
- searcher: eligible_for_fast_path(), fast_locate(), fast_print().

All scanning rides on the memchr crate (SIMD memchr/memrchr/memmem).
Unit tests for read_chunk and plain_literal; integration tests for
prefixes, -m, and multi-chunk line-number correctness.

Benchmarks (31 MB corpus) vs prior release:
  -F (no match):  232ms -> 15ms  (15.9x; now faster than GNU)
  -c literal:     229ms -> 15ms  (15.2x)
  plain print:    248ms -> 18ms  (13.5x)
Regex and -i paths are unchanged (still the line-at-a-time engine).
2026-06-04 22:24:27 +02:00
rifatx f4798cb6d0 fix -l and -L to be mutually exclusive so that last one wins (#30) 2026-06-04 22:14:12 +02:00
Sylvestre Ledru 96762f26ca Add Default impl for GlobSet to satisfy clippy 2026-05-31 10:18:32 +02:00
codspeed-hq[bot] 079619ee44 Add CodSpeed performance benchmarks 2026-05-31 07:59:22 +00:00
Sylvestre Ledru a7b15320af grep: don't emit the -T alignment tab on empty lines
With -T, grep pads the prefix with a tab so line content lands on a tab
stop. GNU omits that tab when the line has no content: an empty line
prints just its prefix (a whitespace-only line still gets the tab).
uu_grep always wrote the tab, so empty matched lines gained a spurious
trailing tab. Gate the tab on non-empty content. Fixes the GNU testsuite
'initial-tab' test.
2026-05-30 19:13:52 +02:00
Sylvestre Ledru ff918e4a63 grep: strip trailing (os error N) from file error messages to match GNU (#6) 2026-05-29 22:24:20 +02:00
Sylvestre Ledru c50c0458cb fix: accept repeated options like GNU grep (#2)
GNU grep tolerates options given more than once (boolean flags are
idempotent, value options take the last occurrence), but clap rejected
them with "cannot be used multiple times" (exit 2). Set
args_override_self(true) so clap replaces rather than errors; args with
ArgAction::Append (-e/-f/--include/--exclude) still accumulate.

Found by the differential fuzzer (e.g. `grep -e .* -E -n -o -n -x`).

Add a regression test covering repeated booleans, repeated value options
(last wins), and that -e still accumulates patterns.
2026-05-29 22:21:27 +02:00
Leonard Hecker 05d167b8d5 Fix support for Python-style named backreferences 2026-05-29 21:12:19 +02:00
Sylvestre Ledru 79db36edbe add license headers 2026-05-29 10:12:38 +02:00
Leonard Hecker 9bff77613e Initial import 2026-05-28 20:19:53 +02:00