Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ugrep for openSUSE:Factory checked in at 2026-04-22 17:02:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ugrep (Old) and /work/SRC/openSUSE:Factory/.ugrep.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ugrep" Wed Apr 22 17:02:05 2026 rev:89 rq:1348752 version:7.7.0 Changes: -------- --- /work/SRC/openSUSE:Factory/ugrep/ugrep.changes 2026-03-06 18:19:20.838032496 +0100 +++ /work/SRC/openSUSE:Factory/.ugrep.new.11940/ugrep.changes 2026-04-22 17:02:40.143608606 +0200 @@ -1,0 +2,14 @@ +Wed Apr 22 08:40:36 UTC 2026 - Andreas Stieger <[email protected]> + +- Update to version 7.7.0: + * support TUI search on slow and incomplete standard input pipes + e.g. from tail -f #540 + * update options -m (--max-count) and -K (--max-line) to stop + reading input upon reaching the stopping criterium, then exit + without draining the standard input pipe like GNU grep + * improve binary file detection for huge mixed files + * local config files located in the working directory are only + read when owned by the user running the ugrep process + * fix lzma 7zip api memory leak + +------------------------------------------------------------------- Old: ---- ugrep-7.6.0.obscpio New: ---- ugrep-7.7.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ugrep.spec ++++++ --- /var/tmp/diff_new_pack.urNPdn/_old 2026-04-22 17:02:41.107647139 +0200 +++ /var/tmp/diff_new_pack.urNPdn/_new 2026-04-22 17:02:41.111647299 +0200 @@ -23,7 +23,7 @@ %bcond_without fish %endif Name: ugrep -Version: 7.6.0 +Version: 7.7.0 Release: 0 Summary: Universal grep: a feature-rich grep implementation with focus on speed License: BSD-3-Clause ++++++ _service ++++++ --- /var/tmp/diff_new_pack.urNPdn/_old 2026-04-22 17:02:41.179650016 +0200 +++ /var/tmp/diff_new_pack.urNPdn/_new 2026-04-22 17:02:41.187650336 +0200 @@ -5,7 +5,7 @@ <param name="changesgenerate">enable</param> <param name="filename">ugrep</param> <param name="versionformat">@PARENT_TAG@</param> - <param name="revision">v7.6.0</param> + <param name="revision">v7.7.0</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.urNPdn/_old 2026-04-22 17:02:41.235652255 +0200 +++ /var/tmp/diff_new_pack.urNPdn/_new 2026-04-22 17:02:41.243652575 +0200 @@ -1,7 +1,7 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/Genivia/ugrep.git</param> - <param name="changesrevision">c701fb852c8fe5ea48143bf809596470d5e2b248</param> + <param name="changesrevision">5bfa7623a98e71c4ec1f2bd3046cb084a09ff82b</param> </service> </servicedata> (No newline at EOF) ++++++ ugrep-7.6.0.obscpio -> ugrep-7.7.0.obscpio ++++++ Binary files old/ugrep-7.6.0/bin/win32/ug.exe and new/ugrep-7.7.0/bin/win32/ug.exe differ Binary files old/ugrep-7.6.0/bin/win32/ugrep-indexer.exe and new/ugrep-7.7.0/bin/win32/ugrep-indexer.exe differ Binary files old/ugrep-7.6.0/bin/win32/ugrep.exe and new/ugrep-7.7.0/bin/win32/ugrep.exe differ Binary files old/ugrep-7.6.0/bin/win64/ug.exe and new/ugrep-7.7.0/bin/win64/ug.exe differ Binary files old/ugrep-7.6.0/bin/win64/ugrep-indexer.exe and new/ugrep-7.7.0/bin/win64/ugrep-indexer.exe differ Binary files old/ugrep-7.6.0/bin/win64/ugrep.exe and new/ugrep-7.7.0/bin/win64/ugrep.exe differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/bash/ug new/ugrep-7.7.0/completions/bash/ug --- old/ugrep-7.6.0/completions/bash/ug 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/bash/ug 2026-04-21 19:29:26.000000000 +0200 @@ -285,7 +285,7 @@ -J NUM, --jobs=NUM Specifies the number of threads spawned to search files. -j, --smart-case Perform case insensitive matching, unless a pattern is specified with a literal upper case letter. --json Output file matches in JSON. --K [MIN,][MAX], --range=[MIN,][MAX], --min-line=MIN, --max-line=MAX Start searching at line MIN, stop at line MAX when specified. +-K [MIN,][MAX], --range=[MIN,][MAX], --min-line=MIN, --max-line=MAX Start searching at line MIN, stop reading input after line MAX. -k, --column-number The column number of a pattern match is displayed in front of the respective matched line, starting at column 1. -L, --files-without-match Only the names of files not containing selected lines are written to standard output. -l, --files-with-matches Only the names of files containing selected lines are written to standard output. @@ -293,7 +293,7 @@ --line-buffered Force output to be line buffered instead of block buffered. --lines Boolean line matching mode for option --bool, the default mode. -M MAGIC, --file-magic=MAGIC Only search files matching the magic signature pattern MAGIC. --m [MIN,][MAX], --min-count=MIN, --max-count=MAX Require MIN matches, stop after MAX matches when specified. +-m [MIN,][MAX], --min-count=MIN, --max-count=MAX Require MIN matches, stop reading input upon MAX matches. --match Match all lines. --max-files=NUM Restrict the number of files matched to NUM. --max-size=MAX Only search files whose physical size does not exceed MAX bytes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/fish/ug+.fish new/ugrep-7.7.0/completions/fish/ug+.fish --- old/ugrep-7.6.0/completions/fish/ug+.fish 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/fish/ug+.fish 2026-04-21 19:29:26.000000000 +0200 @@ -63,7 +63,7 @@ complete -c ug+ -s J -r -l jobs -d 'Specifies the number of threads spawned to search files' complete -c ug+ -s j -l smart-case -d 'Perform case insensitive matching, unless a pattern is specified with a literal upper case letter' complete -c ug+ -l json -d 'Output file matches in JSON' -complete -c ug+ -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop at line MAX when specified' +complete -c ug+ -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop reading input after line MAX' complete -c ug+ -s k -l column-number -d 'The column number of a pattern match is displayed in front of the respective matched line, starting at column 1' complete -c ug+ -s L -l files-without-match -d 'Only the names of files not containing selected lines are written to standard output' complete -c ug+ -s l -l files-with-matches -d 'Only the names of files containing selected lines are written to standard output' @@ -71,7 +71,7 @@ complete -c ug+ -l line-buffered -d 'Force output to be line buffered instead of block buffered' complete -c ug+ -l lines -d 'Boolean line matching mode for option --bool, the default mode' complete -c ug+ -s M -r -l file-magic -d 'Only search files matching the magic signature pattern MAGIC' -complete -c ug+ -s m -r -l min-count -l max-count -d 'Require MIN matches, stop after MAX matches when specified' +complete -c ug+ -s m -r -l min-count -l max-count -d 'Require MIN matches, stop reading input upon MAX matches' complete -c ug+ -l match -d 'Match all lines' complete -c ug+ -l max-files -d 'Restrict the number of files matched to NUM' complete -c ug+ -l max-size -d 'Only search files whose physical size does not exceed MAX bytes' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/fish/ug.fish new/ugrep-7.7.0/completions/fish/ug.fish --- old/ugrep-7.6.0/completions/fish/ug.fish 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/fish/ug.fish 2026-04-21 19:29:26.000000000 +0200 @@ -63,7 +63,7 @@ complete -c ug -s J -r -l jobs -d 'Specifies the number of threads spawned to search files' complete -c ug -s j -l smart-case -d 'Perform case insensitive matching, unless a pattern is specified with a literal upper case letter' complete -c ug -l json -d 'Output file matches in JSON' -complete -c ug -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop at line MAX when specified' +complete -c ug -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop reading input after line MAX' complete -c ug -s k -l column-number -d 'The column number of a pattern match is displayed in front of the respective matched line, starting at column 1' complete -c ug -s L -l files-without-match -d 'Only the names of files not containing selected lines are written to standard output' complete -c ug -s l -l files-with-matches -d 'Only the names of files containing selected lines are written to standard output' @@ -71,7 +71,7 @@ complete -c ug -l line-buffered -d 'Force output to be line buffered instead of block buffered' complete -c ug -l lines -d 'Boolean line matching mode for option --bool, the default mode' complete -c ug -s M -r -l file-magic -d 'Only search files matching the magic signature pattern MAGIC' -complete -c ug -s m -r -l min-count -l max-count -d 'Require MIN matches, stop after MAX matches when specified' +complete -c ug -s m -r -l min-count -l max-count -d 'Require MIN matches, stop reading input upon MAX matches' complete -c ug -l match -d 'Match all lines' complete -c ug -l max-files -d 'Restrict the number of files matched to NUM' complete -c ug -l max-size -d 'Only search files whose physical size does not exceed MAX bytes' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/fish/ugrep+.fish new/ugrep-7.7.0/completions/fish/ugrep+.fish --- old/ugrep-7.6.0/completions/fish/ugrep+.fish 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/fish/ugrep+.fish 2026-04-21 19:29:26.000000000 +0200 @@ -63,7 +63,7 @@ complete -c ugrep+ -s J -r -l jobs -d 'Specifies the number of threads spawned to search files' complete -c ugrep+ -s j -l smart-case -d 'Perform case insensitive matching, unless a pattern is specified with a literal upper case letter' complete -c ugrep+ -l json -d 'Output file matches in JSON' -complete -c ugrep+ -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop at line MAX when specified' +complete -c ugrep+ -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop reading input after line MAX' complete -c ugrep+ -s k -l column-number -d 'The column number of a pattern match is displayed in front of the respective matched line, starting at column 1' complete -c ugrep+ -s L -l files-without-match -d 'Only the names of files not containing selected lines are written to standard output' complete -c ugrep+ -s l -l files-with-matches -d 'Only the names of files containing selected lines are written to standard output' @@ -71,7 +71,7 @@ complete -c ugrep+ -l line-buffered -d 'Force output to be line buffered instead of block buffered' complete -c ugrep+ -l lines -d 'Boolean line matching mode for option --bool, the default mode' complete -c ugrep+ -s M -r -l file-magic -d 'Only search files matching the magic signature pattern MAGIC' -complete -c ugrep+ -s m -r -l min-count -l max-count -d 'Require MIN matches, stop after MAX matches when specified' +complete -c ugrep+ -s m -r -l min-count -l max-count -d 'Require MIN matches, stop reading input upon MAX matches' complete -c ugrep+ -l match -d 'Match all lines' complete -c ugrep+ -l max-files -d 'Restrict the number of files matched to NUM' complete -c ugrep+ -l max-size -d 'Only search files whose physical size does not exceed MAX bytes' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/fish/ugrep.fish new/ugrep-7.7.0/completions/fish/ugrep.fish --- old/ugrep-7.6.0/completions/fish/ugrep.fish 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/fish/ugrep.fish 2026-04-21 19:29:26.000000000 +0200 @@ -63,7 +63,7 @@ complete -c ugrep -s J -r -l jobs -d 'Specifies the number of threads spawned to search files' complete -c ugrep -s j -l smart-case -d 'Perform case insensitive matching, unless a pattern is specified with a literal upper case letter' complete -c ugrep -l json -d 'Output file matches in JSON' -complete -c ugrep -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop at line MAX when specified' +complete -c ugrep -s K -r -l range -l min-line -l max-line -d 'Start searching at line MIN, stop reading input after line MAX' complete -c ugrep -s k -l column-number -d 'The column number of a pattern match is displayed in front of the respective matched line, starting at column 1' complete -c ugrep -s L -l files-without-match -d 'Only the names of files not containing selected lines are written to standard output' complete -c ugrep -s l -l files-with-matches -d 'Only the names of files containing selected lines are written to standard output' @@ -71,7 +71,7 @@ complete -c ugrep -l line-buffered -d 'Force output to be line buffered instead of block buffered' complete -c ugrep -l lines -d 'Boolean line matching mode for option --bool, the default mode' complete -c ugrep -s M -r -l file-magic -d 'Only search files matching the magic signature pattern MAGIC' -complete -c ugrep -s m -r -l min-count -l max-count -d 'Require MIN matches, stop after MAX matches when specified' +complete -c ugrep -s m -r -l min-count -l max-count -d 'Require MIN matches, stop reading input upon MAX matches' complete -c ugrep -l match -d 'Match all lines' complete -c ugrep -l max-files -d 'Restrict the number of files matched to NUM' complete -c ugrep -l max-size -d 'Only search files whose physical size does not exceed MAX bytes' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/zsh/_ug new/ugrep-7.7.0/completions/zsh/_ug --- old/ugrep-7.6.0/completions/zsh/_ug 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/zsh/_ug 2026-04-21 19:29:26.000000000 +0200 @@ -70,7 +70,7 @@ {-J,--jobs=-}'[Specifies the number of threads spawned to search files]:NUM:( )' {-j,--smart-case}'[Perform case insensitive matching, unless a pattern is specified with a literal upper case letter]' --json'[Output file matches in JSON]' -{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop at line MAX when specified]:MIN,MAX:( )' +{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop reading input after line MAX]:MIN,MAX:( )' {-k,--column-number}'[The column number of a pattern match is displayed in front of the respective matched line, starting at column 1]' {-L,--files-without-match}'[Only the names of files not containing selected lines are written to standard output]' {-l,--files-with-matches}'[Only the names of files containing selected lines are written to standard output]' @@ -78,7 +78,7 @@ --line-buffered'[Force output to be line buffered instead of block buffered]' --lines'[Boolean line matching mode for option --bool, the default mode]' '(1)*'{-M,--file-magic=-}'[Only search files matching the magic signature pattern MAGIC]:PATTERN:( )' -{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop after MAX matches when specified]:MIN,MAX:( )::(1 1, 1,10)' +{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop reading input upon MAX matches]:MIN,MAX:( )::(1 1, 1,10)' --match'[Match all lines]' --max-files=-'[Restrict the number of files matched to NUM]' --max-size=-'[Only search files whose physical size does not exceed MAX bytes]' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/zsh/_ug+ new/ugrep-7.7.0/completions/zsh/_ug+ --- old/ugrep-7.6.0/completions/zsh/_ug+ 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/zsh/_ug+ 2026-04-21 19:29:26.000000000 +0200 @@ -70,7 +70,7 @@ {-J,--jobs=-}'[Specifies the number of threads spawned to search files]:NUM:( )' {-j,--smart-case}'[Perform case insensitive matching, unless a pattern is specified with a literal upper case letter]' --json'[Output file matches in JSON]' -{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop at line MAX when specified]:MIN,MAX:( )' +{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop reading input after line MAX]:MIN,MAX:( )' {-k,--column-number}'[The column number of a pattern match is displayed in front of the respective matched line, starting at column 1]' {-L,--files-without-match}'[Only the names of files not containing selected lines are written to standard output]' {-l,--files-with-matches}'[Only the names of files containing selected lines are written to standard output]' @@ -78,7 +78,7 @@ --line-buffered'[Force output to be line buffered instead of block buffered]' --lines'[Boolean line matching mode for option --bool, the default mode]' '(1)*'{-M,--file-magic=-}'[Only search files matching the magic signature pattern MAGIC]:PATTERN:( )' -{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop after MAX matches when specified]:MIN,MAX:( )::(1 1, 1,10)' +{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop reading input upon MAX matches]:MIN,MAX:( )::(1 1, 1,10)' --match'[Match all lines]' --max-files=-'[Restrict the number of files matched to NUM]' --max-size=-'[Only search files whose physical size does not exceed MAX bytes]' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/zsh/_ugrep new/ugrep-7.7.0/completions/zsh/_ugrep --- old/ugrep-7.6.0/completions/zsh/_ugrep 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/zsh/_ugrep 2026-04-21 19:29:26.000000000 +0200 @@ -70,7 +70,7 @@ {-J,--jobs=-}'[Specifies the number of threads spawned to search files]:NUM:( )' {-j,--smart-case}'[Perform case insensitive matching, unless a pattern is specified with a literal upper case letter]' --json'[Output file matches in JSON]' -{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop at line MAX when specified]:MIN,MAX:( )' +{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop reading input after line MAX]:MIN,MAX:( )' {-k,--column-number}'[The column number of a pattern match is displayed in front of the respective matched line, starting at column 1]' {-L,--files-without-match}'[Only the names of files not containing selected lines are written to standard output]' {-l,--files-with-matches}'[Only the names of files containing selected lines are written to standard output]' @@ -78,7 +78,7 @@ --line-buffered'[Force output to be line buffered instead of block buffered]' --lines'[Boolean line matching mode for option --bool, the default mode]' '(1)*'{-M,--file-magic=-}'[Only search files matching the magic signature pattern MAGIC]:PATTERN:( )' -{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop after MAX matches when specified]:MIN,MAX:( )::(1 1, 1,10)' +{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop reading input upon MAX matches]:MIN,MAX:( )::(1 1, 1,10)' --match'[Match all lines]' --max-files=-'[Restrict the number of files matched to NUM]' --max-size=-'[Only search files whose physical size does not exceed MAX bytes]' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/completions/zsh/_ugrep+ new/ugrep-7.7.0/completions/zsh/_ugrep+ --- old/ugrep-7.6.0/completions/zsh/_ugrep+ 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/completions/zsh/_ugrep+ 2026-04-21 19:29:26.000000000 +0200 @@ -70,7 +70,7 @@ {-J,--jobs=-}'[Specifies the number of threads spawned to search files]:NUM:( )' {-j,--smart-case}'[Perform case insensitive matching, unless a pattern is specified with a literal upper case letter]' --json'[Output file matches in JSON]' -{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop at line MAX when specified]:MIN,MAX:( )' +{-K,--range=-,--min-line=-,--max-line=-}'[Start searching at line MIN, stop reading input after line MAX]:MIN,MAX:( )' {-k,--column-number}'[The column number of a pattern match is displayed in front of the respective matched line, starting at column 1]' {-L,--files-without-match}'[Only the names of files not containing selected lines are written to standard output]' {-l,--files-with-matches}'[Only the names of files containing selected lines are written to standard output]' @@ -78,7 +78,7 @@ --line-buffered'[Force output to be line buffered instead of block buffered]' --lines'[Boolean line matching mode for option --bool, the default mode]' '(1)*'{-M,--file-magic=-}'[Only search files matching the magic signature pattern MAGIC]:PATTERN:( )' -{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop after MAX matches when specified]:MIN,MAX:( )::(1 1, 1,10)' +{-m,--min-count=-,--max-count=-}'[Require MIN matches, stop reading input upon MAX matches]:MIN,MAX:( )::(1 1, 1,10)' --match'[Match all lines]' --max-files=-'[Restrict the number of files matched to NUM]' --max-size=-'[Only search files whose physical size does not exceed MAX bytes]' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/configure new/ugrep-7.7.0/configure --- old/ugrep-7.6.0/configure 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/configure 2026-04-21 19:29:26.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for ugrep 7.6.0. +# Generated by GNU Autoconf 2.72 for ugrep 7.7.0. # # Report bugs to <https://github.com/Genivia/ugrep/issues>. # @@ -12,7 +12,7 @@ # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # -# Copyright (C) 2019-2025 Robert van Engelen, Genivia Inc. +# Copyright (C) 2019-2026 Robert van Engelen, Genivia Inc. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## @@ -606,8 +606,8 @@ # Identity of this package. PACKAGE_NAME='ugrep' PACKAGE_TARNAME='ugrep' -PACKAGE_VERSION='7.6.0' -PACKAGE_STRING='ugrep 7.6.0' +PACKAGE_VERSION='7.7.0' +PACKAGE_STRING='ugrep 7.7.0' PACKAGE_BUGREPORT='https://github.com/Genivia/ugrep/issues' PACKAGE_URL='https://ugrep.com' @@ -791,6 +791,7 @@ enable_dependency_tracking enable_sse2 enable_avx2 +enable_avx512 enable_neon with_pcre2 with_boost_regex @@ -1382,7 +1383,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures ugrep 7.6.0 to adapt to many kinds of systems. +'configure' configures ugrep 7.7.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1453,7 +1454,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ugrep 7.6.0:";; + short | recursive ) echo "Configuration of ugrep 7.7.0:";; esac cat <<\_ACEOF @@ -1467,9 +1468,10 @@ do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build - --disable-sse2 disable SSE2 CPU extensions - --disable-avx2 disable AVX2/AVX512BW CPU extensions - --disable-neon disable NEON/AArch64 CPU extensions + --disable-sse2 disable all SIMD SSE2/AVX2/AVX512 CPU extensions + --disable-avx2 disable SIMD AVX2/AVX512BW CPU extensions, keep SSE2 + --disable-avx512 disable SIMD AVX512BW CPU extensions, keep SSE2/AVX2 + --disable-neon disable SIMD NEON/AArch64 CPU extensions --disable-7zip to disable 7zip and no longer search .7z files (7z requires more memory and takes long to decompress) --enable-static build static ugrep binaries @@ -1630,14 +1632,14 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ugrep configure 7.6.0 +ugrep configure 7.7.0 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. -Copyright (C) 2019-2025 Robert van Engelen, Genivia Inc. +Copyright (C) 2019-2026 Robert van Engelen, Genivia Inc. _ACEOF exit fi @@ -2184,7 +2186,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ugrep $as_me 7.6.0, which was +It was created by ugrep $as_me 7.7.0, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -3694,7 +3696,7 @@ # Define the identity of the package. PACKAGE='ugrep' - VERSION='7.6.0' + VERSION='7.7.0' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -8853,7 +8855,7 @@ # Use SIMD CPU extensions and manage cross compilation ################################################################################ -# --disable-sse2 fallback option if cross compilation fails to disable SSE2 CPU extensions +# --disable-sse2 fallback option if cross compilation fails, disables SSE2/AVX2/AVX512BW CPU extensions # Check whether --enable-sse2 was given. if test ${enable_sse2+y} then : @@ -8864,7 +8866,7 @@ fi -# --disable-avx2 fallback option if cross compilation fails to disable AVX2/AVX512BW CPU extensions +# --disable-avx2 fallback option if cross compilation fails, disables AVX2/AVX512BW CPU extensions # Check whether --enable-avx2 was given. if test ${enable_avx2+y} then : @@ -8875,6 +8877,17 @@ fi +# --disable-avx512 fallback option if cross compilation fails, disables AVX512BW CPU extensions +# Check whether --enable-avx512 was given. +if test ${enable_avx512+y} +then : + enableval=$enable_avx512; with_no_avx512="yes" +else case e in #( + e) with_no_avx512="no" ;; +esac +fi + + # --disable-neon fallback option if cross compilation fails to disable NEON/AArch64 CPU extensions # Check whether --enable-neon was given. if test ${enable_neon+y} @@ -8932,8 +8945,9 @@ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${CXX} supports AVX2/AVX512BW intrinsics" >&5 printf %s "checking whether ${CXX} supports AVX2/AVX512BW intrinsics... " >&6; } save_CXXFLAGS=$CXXFLAGS - CXXFLAGS="-mavx512bw" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if ! test "x$with_no_avx512" = "xyes"; then + CXXFLAGS="-mavx512bw" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <immintrin.h> int @@ -8952,10 +8966,36 @@ esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - if test "x$mavx_ok" = "xyes"; then - SIMD_FLAGS="-msse2 -DHAVE_AVX512BW" - SIMD_AVX2_FLAGS="-mavx2" - SIMD_AVX512BW_FLAGS="-mavx512bw" + if test "x$mavx_ok" = "xyes"; then + SIMD_FLAGS="-msse2 -DHAVE_AVX512BW" + SIMD_AVX2_FLAGS="-mavx2" + SIMD_AVX512BW_FLAGS="-mavx512bw" + else + CXXFLAGS="-mavx2" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <immintrin.h> +int +main (void) +{ +__m256i n = _mm256_set1_epi8(42); (void)_mm256_movemask_epi8(_mm256_and_si256(n, n)); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + mavx_ok=yes +else case e in #( + e) mavx_ok=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + if test "x$mavx_ok" = "xyes"; then + SIMD_FLAGS="-msse2 -DHAVE_AVX2" + SIMD_AVX2_FLAGS="-mavx2" + fi + fi else CXXFLAGS="-mavx2" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11835,7 +11875,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ugrep $as_me 7.6.0, which was +This file was extended by ugrep $as_me 7.7.0, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -11908,7 +11948,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -ugrep config.status 7.6.0 +ugrep config.status 7.7.0 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/configure.ac new/ugrep-7.7.0/configure.ac --- old/ugrep-7.6.0/configure.ac 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/configure.ac 2026-04-21 19:29:26.000000000 +0200 @@ -1,7 +1,7 @@ -AC_INIT([ugrep],[7.6.0],[https://github.com/Genivia/ugrep/issues],[ugrep],[https://ugrep.com]) +AC_INIT([ugrep],[7.7.0],[https://github.com/Genivia/ugrep/issues],[ugrep],[https://ugrep.com]) AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz no-dist-gzip]) AC_CONFIG_HEADERS([config.h]) -AC_COPYRIGHT([Copyright (C) 2019-2025 Robert van Engelen, Genivia Inc.]) +AC_COPYRIGHT([Copyright (C) 2019-2026 Robert van Engelen, Genivia Inc.]) AC_CONFIG_MACRO_DIR([m4]) @@ -65,24 +65,31 @@ # Use SIMD CPU extensions and manage cross compilation ################################################################################ -# --disable-sse2 fallback option if cross compilation fails to disable SSE2 CPU extensions +# --disable-sse2 fallback option if cross compilation fails, disables SSE2/AVX2/AVX512BW CPU extensions AC_ARG_ENABLE(sse2, [AS_HELP_STRING([--disable-sse2], - [disable SSE2 CPU extensions])], + [disable all SIMD SSE2/AVX2/AVX512 CPU extensions])], [with_no_sse2="yes"], [with_no_sse2="no"]) -# --disable-avx2 fallback option if cross compilation fails to disable AVX2/AVX512BW CPU extensions +# --disable-avx2 fallback option if cross compilation fails, disables AVX2/AVX512BW CPU extensions AC_ARG_ENABLE(avx2, [AS_HELP_STRING([--disable-avx2], - [disable AVX2/AVX512BW CPU extensions])], + [disable SIMD AVX2/AVX512BW CPU extensions, keep SSE2])], [with_no_avx2="yes"], [with_no_avx2="no"]) +# --disable-avx512 fallback option if cross compilation fails, disables AVX512BW CPU extensions +AC_ARG_ENABLE(avx512, + [AS_HELP_STRING([--disable-avx512], + [disable SIMD AVX512BW CPU extensions, keep SSE2/AVX2])], + [with_no_avx512="yes"], + [with_no_avx512="no"]) + # --disable-neon fallback option if cross compilation fails to disable NEON/AArch64 CPU extensions AC_ARG_ENABLE(neon, [AS_HELP_STRING([--disable-neon], - [disable NEON/AArch64 CPU extensions])], + [disable SIMD NEON/AArch64 CPU extensions])], [with_no_neon="yes"], [with_no_neon="no"]) @@ -113,14 +120,25 @@ if ! test "x$with_no_avx2" = "xyes"; then AC_MSG_CHECKING([whether ${CXX} supports AVX2/AVX512BW intrinsics]) save_CXXFLAGS=$CXXFLAGS - CXXFLAGS="-mavx512bw" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <immintrin.h>]], [[__m512i n = _mm512_set1_epi8(42); (void)_mm512_cmpeq_epi8_mask(n, n);]])], - [mavx_ok=yes], - [mavx_ok=no]) - if test "x$mavx_ok" = "xyes"; then - SIMD_FLAGS="-msse2 -DHAVE_AVX512BW" - SIMD_AVX2_FLAGS="-mavx2" - SIMD_AVX512BW_FLAGS="-mavx512bw" + if ! test "x$with_no_avx512" = "xyes"; then + CXXFLAGS="-mavx512bw" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <immintrin.h>]], [[__m512i n = _mm512_set1_epi8(42); (void)_mm512_cmpeq_epi8_mask(n, n);]])], + [mavx_ok=yes], + [mavx_ok=no]) + if test "x$mavx_ok" = "xyes"; then + SIMD_FLAGS="-msse2 -DHAVE_AVX512BW" + SIMD_AVX2_FLAGS="-mavx2" + SIMD_AVX512BW_FLAGS="-mavx512bw" + else + CXXFLAGS="-mavx2" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <immintrin.h>]], [[__m256i n = _mm256_set1_epi8(42); (void)_mm256_movemask_epi8(_mm256_and_si256(n, n));]])], + [mavx_ok=yes], + [mavx_ok=no]) + if test "x$mavx_ok" = "xyes"; then + SIMD_FLAGS="-msse2 -DHAVE_AVX2" + SIMD_AVX2_FLAGS="-mavx2" + fi + fi else CXXFLAGS="-mavx2" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <immintrin.h>]], [[__m256i n = _mm256_set1_epi8(42); (void)_mm256_movemask_epi8(_mm256_and_si256(n, n));]])], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/include/reflex/input.h new/ugrep-7.7.0/include/reflex/input.h --- old/ugrep-7.6.0/include/reflex/input.h 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/include/reflex/input.h 2026-04-21 19:29:26.000000000 +0200 @@ -632,7 +632,7 @@ return static_cast<unsigned char>(c); return EOF; } - /// Copy character sequence data into buffer. + /// Read and copy input character sequence data into buffer. size_t get( char *s, ///< points to the string buffer to fill with input size_t n) ///< size of buffer pointed to by s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/lib/input.cpp new/ugrep-7.7.0/lib/input.cpp --- old/ugrep-7.6.0/lib/input.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/lib/input.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -1033,6 +1033,7 @@ #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) return !ferror(file_); #else + int fd = fileno(file_); if (ferror(file_)) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) @@ -1042,7 +1043,7 @@ if (errno == EAGAIN) { struct stat buf; - if (fstat(fileno(file_), &buf) == 0 && S_ISREG(buf.st_mode)) + if (fstat(fd, &buf) == 0 && S_ISREG(buf.st_mode)) return false; } #endif @@ -1053,13 +1054,13 @@ fd_set rfds, efds; FD_ZERO(&rfds); FD_ZERO(&efds); - FD_SET(0, &rfds); - FD_SET(0, &efds); + FD_SET(fd, &rfds); + FD_SET(fd, &efds); tv.tv_sec = 0; - tv.tv_usec = 1000; // 1ms timeout - clearerr(file_); // unset EAGAIN etc - if (::select(fileno(file_) + 1, &rfds, NULL, &efds, &tv) >= 0) - return FD_ISSET(fileno(file_), &efds) == 0; + tv.tv_usec = 10000; // 10ms timeout + clearerr(file_); // unset EAGAIN etc + if (::select(fd + 1, &rfds, NULL, &efds, &tv) >= 0) + return FD_ISSET(fd, &efds) == 0; if (errno != EINTR) return false; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/lib/pattern.cpp new/ugrep-7.7.0/lib/pattern.cpp --- old/ugrep-7.6.0/lib/pattern.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/lib/pattern.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -4423,7 +4423,7 @@ // find min between 0 and Const::BITS min_ = Const::BITS; std::set<DFA::State*> prev, next(states); - for (size_t level = 0; level < min_; ++level) + for (uint16_t level = 0; level < min_; ++level) { bool none = true; prev.clear(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/lib/simd_avx2.cpp new/ugrep-7.7.0/lib/simd_avx2.cpp --- old/ugrep-7.6.0/lib/simd_avx2.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/lib/simd_avx2.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -78,7 +78,7 @@ #endif } -// Partially check if valid UTF-8 encoding +// Check if valid UTF-8 encoding and does not include a NUL, but pass surrogates and 3/4 byte overlongs bool simd_isutf8_avx2(const char *& b, const char *e) { #if defined(HAVE_AVX2) || defined(HAVE_AVX512BW) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/lzma/C/viizip.c new/ugrep-7.7.0/lzma/C/viizip.c --- old/ugrep-7.6.0/lzma/C/viizip.c 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/lzma/C/viizip.c 2026-04-21 19:29:26.000000000 +0200 @@ -250,6 +250,7 @@ if (viizip == NULL) return; + ISzAlloc_Free(&viizip->alloc_main, viizip->look.buf); ISzAlloc_Free(&viizip->alloc_main, viizip->buf); SzFree(NULL, viizip->tmp); SzArEx_Free(&viizip->db, &viizip->alloc_main); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/man/ug.1 new/ugrep-7.7.0/man/ug.1 --- old/ugrep-7.6.0/man/ug.1 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/man/ug.1 2026-04-21 19:29:26.000000000 +0200 @@ -1,4 +1,4 @@ -.TH UGREP "1" "March 05, 2026" "ugrep 7.6.0" "User Commands" +.TH UGREP "1" "April 21, 2026" "ugrep 7.7.0" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS @@ -602,7 +602,7 @@ additional values are output. See also options \fB\-\-format\fR and \fB\-u\fR. .TP \fB\-K\fR [\fIMIN\fR,][\fIMAX\fR], \fB\-\-range\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-\-min\-line\fR=\fIMIN\fR, \fB\-\-max\-line\fR=\fIMAX\fR -Start searching at line MIN, stop at line MAX when specified. +Start searching at line MIN, stop reading input after line MAX. .TP \fB\-k\fR, \fB\-\-column\-number\fR The column number of a pattern match is displayed in front of the @@ -617,10 +617,9 @@ .TP \fB\-l\fR, \fB\-\-files\-with\-matches\fR Only the names of files containing selected lines are written to -standard output. ugrep will only search a file until a match has -been found, making searches potentially less expensive. Pathnames -are listed once per file searched. If the standard input is -searched, the string ``(standard input)'' is written. +standard output. Pathnames are listed once per file searched. If +the standard input is searched, the string ``(standard input)'' is +written. Stop reading input upon the first match. .TP \fB\-\-label\fR=\fILABEL\fR Displays the LABEL value when input is read from standard input @@ -644,7 +643,7 @@ making recursive searches potentially more expensive. .TP \fB\-m\fR [\fIMIN\fR,][\fIMAX\fR], \fB\-\-min\-count\fR=\fIMIN\fR, \fB\-\-max\-count\fR=\fIMAX\fR -Require MIN matches, stop after MAX matches when specified. Output +Require MIN matches, stop reading input upon MAX matches. Output MIN to MAX matches. For example, \fB\-m\fR1 outputs the first match and \fB\-c\fRm1, (with a comma) counts nonzero matches. When \fB\-u\fR or \fB\-\-ungroup\fR is specified, each individual match counts. See also option \fB\-K\fR. @@ -971,8 +970,7 @@ xz (.xz, .txz) and lzma (requires suffix .lzma, .tlz), zstd (.zst, .zstd, .tzst), lz4 (requires suffix .lz4), -brotli (requires suffix .br), -bzip3 (requires suffix .bz3). +brotli (requires suffix .br). .TP \fB\-\-zmax\fR=\fINUM\fR When used with option \fB\-z\fR or \fB\-\-decompress\fR, searches the contents of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/man/ugrep-indexer.1 new/ugrep-7.7.0/man/ugrep-indexer.1 --- old/ugrep-7.6.0/man/ugrep-indexer.1 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/man/ugrep-indexer.1 2026-04-21 19:29:26.000000000 +0200 @@ -1,4 +1,4 @@ -.TH UGREP-INDEXER "1" "March 05, 2026" "ugrep-indexer 7.6.0" "User Commands" +.TH UGREP-INDEXER "1" "April 21, 2026" "ugrep-indexer 7.7.0" "User Commands" .SH NAME \fBugrep-indexer\fR -- file indexer to accelerate recursive searching .SH SYNOPSIS @@ -147,8 +147,7 @@ lzma and xz (requires suffix .lzma, .tlz, .xz, .txz), lz4 (requires suffix .lz4), zstd (requires suffix .zst, .zstd, .tzst), -brotli (requires suffix .br), -bzip3 (requires suffix .bz3). +brotli (requires suffix .br). .TP \fB\-\-zmax\fR=\fINUM\fR When used with option \fB\-z\fR (\fB\-\-decompress\fR), indexes the contents of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/man/ugrep.1 new/ugrep-7.7.0/man/ugrep.1 --- old/ugrep-7.6.0/man/ugrep.1 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/man/ugrep.1 2026-04-21 19:29:26.000000000 +0200 @@ -1,4 +1,4 @@ -.TH UGREP "1" "March 05, 2026" "ugrep 7.6.0" "User Commands" +.TH UGREP "1" "April 21, 2026" "ugrep 7.7.0" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS @@ -602,7 +602,7 @@ additional values are output. See also options \fB\-\-format\fR and \fB\-u\fR. .TP \fB\-K\fR [\fIMIN\fR,][\fIMAX\fR], \fB\-\-range\fR=[\fIMIN\fR,][\fIMAX\fR], \fB\-\-min\-line\fR=\fIMIN\fR, \fB\-\-max\-line\fR=\fIMAX\fR -Start searching at line MIN, stop at line MAX when specified. +Start searching at line MIN, stop reading input after line MAX. .TP \fB\-k\fR, \fB\-\-column\-number\fR The column number of a pattern match is displayed in front of the @@ -617,10 +617,9 @@ .TP \fB\-l\fR, \fB\-\-files\-with\-matches\fR Only the names of files containing selected lines are written to -standard output. ugrep will only search a file until a match has -been found, making searches potentially less expensive. Pathnames -are listed once per file searched. If the standard input is -searched, the string ``(standard input)'' is written. +standard output. Pathnames are listed once per file searched. If +the standard input is searched, the string ``(standard input)'' is +written. Stop reading input upon the first match. .TP \fB\-\-label\fR=\fILABEL\fR Displays the LABEL value when input is read from standard input @@ -644,7 +643,7 @@ making recursive searches potentially more expensive. .TP \fB\-m\fR [\fIMIN\fR,][\fIMAX\fR], \fB\-\-min\-count\fR=\fIMIN\fR, \fB\-\-max\-count\fR=\fIMAX\fR -Require MIN matches, stop after MAX matches when specified. Output +Require MIN matches, stop reading input upon MAX matches. Output MIN to MAX matches. For example, \fB\-m\fR1 outputs the first match and \fB\-c\fRm1, (with a comma) counts nonzero matches. When \fB\-u\fR or \fB\-\-ungroup\fR is specified, each individual match counts. See also option \fB\-K\fR. @@ -971,8 +970,7 @@ xz (.xz, .txz) and lzma (requires suffix .lzma, .tlz), zstd (.zst, .zstd, .tzst), lz4 (requires suffix .lz4), -brotli (requires suffix .br), -bzip3 (requires suffix .bz3). +brotli (requires suffix .br). .TP \fB\-\-zmax\fR=\fINUM\fR When used with option \fB\-z\fR or \fB\-\-decompress\fR, searches the contents of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/output.cpp new/ugrep-7.7.0/src/output.cpp --- old/ugrep-7.6.0/src/output.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/output.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -256,7 +256,7 @@ size_t columno = flag_column_number && matcher != NULL ? matcher->columno() + 1 : 1; // -Q: mark pathname with three \0 markers in headings, unless -a - bool nul = heading && flag_query && !flag_text; + bool nul = flag_query && heading && !flag_text; if (nul) chr('\0'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/query.cpp new/ugrep-7.7.0/src/query.cpp --- old/ugrep-7.6.0/src/query.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/query.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -581,7 +581,7 @@ void Query::disp(int row) { Screen::normal(); - if (row < rows_) + if (row < rows_ + append_) { if (selected_[row]) Screen::select(); @@ -683,7 +683,7 @@ } else { - // do not show dots + // reset to 4 to do not show dots tick_ = 4; if (error_ == -1) @@ -698,7 +698,7 @@ if (row_ < 0) row_ = 0; - int end = row_ + maxrows_ - 2; + int end = row_ + append_ + maxrows_ - 2; for (int i = row_; i < end; ++i) disp(i); @@ -851,13 +851,9 @@ #else signal(SIGINT, sigint); - signal(SIGQUIT, sigint); - signal(SIGTERM, sigint); - signal(SIGPIPE, SIG_IGN); - signal(SIGWINCH, sigwinch); #endif @@ -890,7 +886,7 @@ VKey::cleanup(); Screen::cleanup(); - // check TTY again for color support, this time without --query + // check TTY a final time for color support to print results, if any, this time without --query flag_query = false; terminal(); @@ -909,16 +905,14 @@ // close the stdin pipe if (flag_stdin && Static::source != stdin && Static::source != NULL) - { - fclose(Static::source); - Static::source = NULL; - } + fclose(Static::source); // close source but don't reset to NULL, source is used by the search thread // join the search thread if (search_thread_.joinable()) search_thread_.join(); // join the stdin sender thread + stdin_stop = true; if (stdin_thread_.joinable()) stdin_thread_.join(); } @@ -1482,6 +1476,8 @@ // start a new search, cancel the previous search when still running void Query::search() { + stop_stdin(); + bool cancel = !eof_; if (cancel) @@ -1494,6 +1490,22 @@ Static::cancel_ugrep(); } + if (search_thread_.joinable()) + { + if (cancel && error_ == -1) + { + const int banlen = 256; + char banner[banlen]; + snprintf(banner, banlen, "restarting: please be patient while I cancel searching large files...%*s", banlen - 70, ""); + Screen::normal(); + Screen::invert(); + Screen::put(maxrows_ - 1, 0, banner); + Screen::normal(); + } + + search_thread_.join(); + } + #ifdef OS_WIN hPipe_ = nonblocking_pipe(search_pipe_); @@ -1522,23 +1534,8 @@ #endif - if (search_thread_.joinable()) - { - if (cancel && error_ == -1) - { - const int banlen = 256; - char banner[banlen]; - snprintf(banner, banlen, "restarting: please be patient while I cancel searching large files...%*s", banlen - 70, ""); - Screen::normal(); - Screen::invert(); - Screen::put(maxrows_ - 1, 0, banner); - Screen::normal(); - } - - search_thread_.join(); - } - eof_ = false; + append_ = false; row_ = 0; rows_ = 0; skip_ = 0; @@ -1568,7 +1565,7 @@ set_flags(); - set_stdin(); + start_stdin(); if (error_ == -1) { @@ -1667,32 +1664,29 @@ // fetch viewable portion plus one up to two screenfuls more fetch(row_ - (row_ % Screen::rows) + 2 * Screen::rows); + int end = rows_ + append_; + // display the viewable portion when updated - if (rows_ > begin && begin < row_ + maxrows_ - 2) + if (end > begin && begin < row_ + maxrows_ - 2) { Screen::normal(); - if (begin + maxrows_ - 2 > rows_) - begin = rows_ - maxrows_ + 2; + if (begin + maxrows_ - 2 > end) + begin = end - maxrows_ + 2; if (begin < 0) begin = 0; if (begin < row_) begin = row_; - int end = rows_; - - if (end > row_ + maxrows_ - 2) - end = row_ + maxrows_ - 2; - - for (int i = begin; i < end; ++i) + for (int i = begin; i < std::min(end, row_ + maxrows_ - 2); ++i) disp(i); } if (error_ == -1) { - if (tick_ < 8 && rows_ < row_ + maxrows_ - 2) + if (tick_ < 8 && end < row_ + maxrows_ - 2) { - int row = rows_ - row_ + 1; + int row = end - row_ + 1; // no dots and clear below when we hit eof if (eof_) @@ -1913,7 +1907,8 @@ if (!incomplete) { // added another row - ++rows_; + if (++rows_ < static_cast<int>(view_.size())) + view_[rows_].clear(); // skip \n if (nlptr < buffer_ + buflen_) @@ -1923,9 +1918,8 @@ // append the next chunk of text from the buffer append_ = incomplete; + // shift the buffer to make room buflen_ -= nlptr - buffer_; - - // shift the buffer memmove(buffer_, nlptr, buflen_); } } @@ -2488,13 +2482,6 @@ if (found) { - - Screen::clear(); - Screen::put("Waiting on "); - Screen::put(command.c_str()); - Screen::put(" to finish"); - Screen::home(); - // -n: add +line_number if (line_number > 0) command.append(" +").append(std::to_string(line_number)); @@ -2534,23 +2521,44 @@ catch (...) { // this should never happen, but just in case we ignore errors + Screen::alert(); + return; } } } else { - // view file in the pager using system() call - command.append(" \"").append(filename).append("\""); - #ifdef OS_WIN + if (filename.empty() || filename.at(0) == '/' || filename.find('"') != std::string::npos) + { + // illegal filename in Windows, should never happen, but just in case + Screen::alert(); + return; + } + // view file in the pager using Windows _wsystem() call + command.append(" \"").append(filename).append("\""); // Windows system() does not support non-ASCII, instead we use a wide string with _wsystem() wcommand = utf8_decode(command); - // flush before calling _wsystem(), according to the Window's system API documentation // _flushall(); removed because this may cause the TUI to freeze +#else + if (filename.find('\'') != std::string::npos) + { + // incorrect filename + Screen::alert(); + return; + } + // view file in the pager using system() call, double -- ends options + command.append(" -- '").append(filename).append("'"); #endif } + Screen::clear(); + Screen::put("Waiting on "); + Screen::put(command.c_str()); + Screen::put(" to finish"); + Screen::home(); + // pipe to pager was OK or executing the command is OK bool ok; @@ -4112,37 +4120,26 @@ void Query::get_stdin() { - // if standard input is searched, then buffer all its text + // if standard input is searched, then dynamically buffer the input to search if (flag_stdin) { - reflex::BufferedInput input(stdin, flag_encoding_type); +#ifndef OS_WIN + // make stdin non-blocking to read and buffer dynamically + fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); +#endif - while (true) - { - size_t len = input.get(buffer_, QUERY_BUFFER_SIZE); - if (len == 0) - break; - stdin_buffer_.append(buffer_, len); - } + stdin_input_ = stdin; + stdin_input_.file_encoding(flag_encoding_type); + stdin_buffer_.clear(); } } -void Query::set_stdin() +// start a new stdin sender thread and pipe from sender to the search engine +void Query::start_stdin() { // if standard input is searched, start thread to reproduce its text on demand if (flag_stdin) { - // close the stdin pipe when open - if (Static::source != stdin && Static::source != NULL) - { - fclose(Static::source); - Static::source = NULL; - } - - // join the stdin_sender - if (stdin_thread_.joinable()) - stdin_thread_.join(); - // create a new pipe if (pipe(stdin_pipe_) < 0) { @@ -4156,19 +4153,68 @@ Static::source = fdopen(stdin_pipe_[0], "rb"); // run stdin_sender in the background to push buffered standard input down the pipe + stdin_stop = false; stdin_thread_ = std::thread(Query::stdin_sender, stdin_pipe_[1]); } } +// stop stdin sender thread +void Query::stop_stdin() +{ + if (flag_stdin) + { + // close the stdin pipe when open + if (Static::source != stdin && Static::source != NULL) + fclose(Static::source); // close source but don't reset to NULL, source is used by the search thread + + // join the stdin_sender + stdin_stop = true; + if (stdin_thread_.joinable()) + stdin_thread_.join(); + } +} + // push standard input down the specified pipe fd -ssize_t Query::stdin_sender(int fd) +void Query::stdin_sender(int fd) { - // write the stdin data all at once, we can ignore the return value - ssize_t nwritten = write(fd, stdin_buffer_.c_str(), stdin_buffer_.size()); + // write the stdin data all at once to the search pipe + char buf[QUERY_BUFFER_SIZE]; + ssize_t len = stdin_buffer_.size(), nwritten = write(fd, stdin_buffer_.c_str(), len); - close(fd); + // when more stdin input arrives, buffer it and write it to the search pipe + while (!stdin_stop && !feof(stdin) && nwritten == len) + { + len = stdin_input_.file_get(buf, QUERY_BUFFER_SIZE); + + if (len == 0) + { + if (feof(stdin)) + break; + +#ifndef OS_WIN + struct timeval tv; + fd_set rfds, efds; + FD_ZERO(&rfds); + FD_ZERO(&efds); + FD_SET(0, &rfds); + FD_SET(0, &efds); + tv.tv_sec = 0; + tv.tv_usec = 10000; // 10ms timeout + clearerr(stdin); + if (::select(0 + 1, &rfds, NULL, &efds, &tv) >= 0 && FD_ISSET(0, &efds) != 0) + break; +#endif - return nwritten; + nwritten = 0; + } + else + { + stdin_buffer_.append(buf, len); + nwritten = write(fd, buf, len); + } + } + + close(fd); } // true if view_[ref] has a valid filename/filepath identified by three \0 markers and differs from the given filename, then assigns filename @@ -4413,9 +4459,11 @@ char Query::buffer_[QUERY_BUFFER_SIZE]; int Query::search_pipe_[2]; std::thread Query::search_thread_; +reflex::Input Query::stdin_input_; std::string Query::stdin_buffer_; int Query::stdin_pipe_[2]; std::thread Query::stdin_thread_; +std::atomic_bool Query::stdin_stop; size_t Query::searched_ = 0; size_t Query::found_ = 0; int Query::tick_ = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/query.hpp new/ugrep-7.7.0/src/query.hpp --- old/ugrep-7.6.0/src/query.hpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/query.hpp 2026-04-21 19:29:26.000000000 +0200 @@ -263,9 +263,10 @@ static void get_stdin(); - static void set_stdin(); + static void start_stdin(); + static void stop_stdin(); - static ssize_t stdin_sender(int fd); + static void stdin_sender(int fd); static bool find_filename(int ref, std::string& filename, bool compare_dir = false, bool find_path = false, std::string *partname = NULL); @@ -310,14 +311,16 @@ static std::vector<std::string> view_; // search output text to display, incrementally fetched static std::vector<bool> selected_; // marked lines in view_[] selected in selection mode static bool eof_; // end of results, no more results can be fetched - static bool append_; + static bool append_; // flag to append search output to the last incomplete line static size_t buflen_; static char buffer_[QUERY_BUFFER_SIZE]; static int search_pipe_[2]; static std::thread search_thread_; + static reflex::Input stdin_input_; static std::string stdin_buffer_; static int stdin_pipe_[2]; static std::thread stdin_thread_; + static std::atomic_bool stdin_stop; static size_t searched_; // last update number of files searched static size_t found_; // last update number of files found static int tick_; // 100ms tick 0 to 7 or steady 8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/stats.cpp new/ugrep-7.7.0/src/stats.cpp --- old/ugrep-7.6.0/src/stats.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/stats.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -43,6 +43,10 @@ { size_t sf = searched_files(); size_t sd = searched_dirs(); + size_t si = searched_indexed(); + size_t ss = searched_skipped(); + size_t sc = searched_changed(); + size_t sa = searched_added(); size_t sl = searched_lines(); size_t ff = found_files(); size_t fp = found_parts(); @@ -71,17 +75,17 @@ if (flag_index && indexed > 0) { - fprintf(output, "Skipped %zu file%s of %zu (%.4g%%) not matching %zu indexes\n", skipped, (skipped == 1 ? "" : "s"), sf - ff, 100.0 * skipped / (sf - ff), indexed); - if (changed > 0 || added > 0) + fprintf(output, "Skipped %zu file%s of %zu (%.4g%%) not matching %zu indexes\n", ss, (ss == 1 ? "" : "s"), sf - ff, 100.0 * ss / (sf - ff), si); + if (sc > 0 || sa > 0) { fprintf(output, "Detected outdated or missing index files, run ugrep-indexer to re-index:\n"); - if (changed > 1) - fprintf(output, " searched %zu changed files\n", changed); - else if (changed == 1) + if (sc > 1) + fprintf(output, " searched %zu changed files\n", sc); + else if (sc == 1) fprintf(output, " searched 1 changed file\n"); - if (added > 1) - fprintf(output, " searched %zu new files\n", added); - else if (added == 1) + if (sa > 1) + fprintf(output, " searched %zu new files\n", sa); + else if (sa == 1) fprintf(output, " searched 1 new file\n"); } } @@ -200,12 +204,12 @@ } reflex::timer_type Stats::timer; -size_t Stats::files = 0; -size_t Stats::dirs = 0; -size_t Stats::indexed = 0; -size_t Stats::skipped = 0; -size_t Stats::changed = 0; -size_t Stats::added = 0; +std::atomic_size_t Stats::files; +std::atomic_size_t Stats::dirs; +std::atomic_size_t Stats::indexed; +std::atomic_size_t Stats::skipped; +std::atomic_size_t Stats::changed; +std::atomic_size_t Stats::added; std::atomic_size_t Stats::fileno; std::atomic_size_t Stats::partno; std::atomic_size_t Stats::matchno; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/stats.hpp new/ugrep-7.7.0/src/stats.hpp --- old/ugrep-7.6.0/src/stats.hpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/stats.hpp 2026-04-21 19:29:26.000000000 +0200 @@ -126,6 +126,30 @@ return dirs; } + // number of indexed files visited + static size_t searched_indexed() + { + return indexed; + } + + // numbder of indexed files skipped from search + static size_t searched_skipped() + { + return skipped; + } + + // number of indexed files changed and searched (stale index file) + static size_t searched_changed() + { + return changed; + } + + // number of non-indexed files added and searched (stale index file) + static size_t searched_added() + { + return added; + } + // number of lines searched static size_t searched_lines() { @@ -190,12 +214,12 @@ protected: static reflex::timer_type timer; // elapsed wall-clock time in milli seconds (ms) - static size_t files; // number of files searched, excluding files in archives - static size_t dirs; // number of directories searched - static size_t indexed; // number of files found to be indexed - static size_t skipped; // number of files found to be indexed that were skipped as not matching - static size_t changed; // number of files found to be indexed but changed (stale index file) - static size_t added; // number of files found to be added (stale index file) + static std::atomic_size_t files; // number of files searched, excluding files in archives + static std::atomic_size_t dirs; // number of directories searched + static std::atomic_size_t indexed; // number of files found to be indexed + static std::atomic_size_t skipped; // number of files found to be indexed that were skipped as not matching + static std::atomic_size_t changed; // number of files found to be indexed but changed (stale index file) + static std::atomic_size_t added; // number of files found to be added (stale index file) static std::atomic_size_t fileno; // number of matching files, excluding files in archives, atomic for GrepWorker::search() update static std::atomic_size_t partno; // number of matching files, including files in archives, atomic for GrepWorker::search() update static std::atomic_size_t lineno; // number of lines searched cummulatively diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/ugrep-indexer.cpp new/ugrep-7.7.0/src/ugrep-indexer.cpp --- old/ugrep-7.6.0/src/ugrep-indexer.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/ugrep-indexer.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -35,7 +35,7 @@ */ // DO NOT ALTER THIS LINE: updated by makemake.sh and we need it physically here for MSVC++ build from source -#define UGREP_VERSION "7.6.0" +#define UGREP_VERSION "7.7.0" // use a task-parallel thread to decompress the stream into a pipe to search, also handles nested archives #define WITH_DECOMPRESSION_THREAD diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/ugrep.cpp new/ugrep-7.7.0/src/ugrep.cpp --- old/ugrep-7.6.0/src/ugrep.cpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/ugrep.cpp 2026-04-21 19:29:26.000000000 +0200 @@ -132,6 +132,8 @@ #include <stringapiset.h> // internationalization #include <direct.h> // directory access #include <winsock.h> // gethostname() for --hyperlink +#include <securitybaseapi.h> // GetTokenInformation() +#include <aclapi.h> // GetSecurityInfo() #pragma comment(lib, "Ws2_32.lib") #else @@ -2269,6 +2271,26 @@ #endif + // extend the reflex::Input::Handler to handle detection of binary input like GNU grep (check for NULs) + struct BinaryHandler : public reflex::Input::Handler { + + BinaryHandler(Grep& grep) + : + grep(grep) + { } + + Grep& grep; + + size_t operator()(FILE*, char *buf, size_t len) + { + // simpler form of binary file detection without Unicode UTF-8 validation, check for NULs like GNU grep + grep.binfile = grep.binfile || (memchr(buf, 0, len) != NULL); + + return len; + } + + }; + #ifndef OS_WIN // extend the reflex::Input::Handler to handle non-blocking input from a character device (TTY) or from a pipe @@ -2295,7 +2317,7 @@ } else if (!flag_text && !flag_hex && !flag_with_hex && flag_encoding_type != reflex::Input::file_encoding::null_data && !grep.binfile) { - // simpler form of binary file detection without Unicode UTF-8 validation, like GNU grep + // simpler form of binary file detection without Unicode UTF-8 validation, check for NULs like GNU grep grep.binfile = (memchr(buf, 0, len) != NULL); } @@ -3211,7 +3233,8 @@ out(file), matcher(matcher), matchers(matchers), - file_in(NULL) + file_in(NULL), + bin_handler(*this) #ifndef OS_WIN , stdin_handler(*this) #endif @@ -3897,8 +3920,9 @@ #if defined(WITH_STDIN_DRAIN) && !defined(OS_WIN) - // drain stdin when non-seekable file such as a pipe until eof - if (file_in == stdin && !feof(stdin) && fseek(stdin, 0, SEEK_END) < 0 && errno != EINVAL) + // drain stdin when non-seekable file such as a pipe until eof, unless option -q is used + if (file_in == stdin && !flag_quiet && !flag_files_with_matches && flag_max_count == 0 && flag_max_line == 0 && + !feof(stdin) && fseek(stdin, 0, SEEK_END) < 0 && errno != EINVAL) { char buf[16384]; while (input.get(buf, sizeof(buf)) > 0) @@ -3961,19 +3985,23 @@ #endif } - // when non-blocking do not check init_is_binary(), wait until handler detects binary files that have NUL bytes + // interactive: do not check init_is_binary(), wait until handler detects binary files that have NUL bytes if (!interactive) { + // otherwise, check if the file is a binary file if (flag_binary_without_match) { // -I: do not match binary files if (init_is_binary()) return false; } - else if (!flag_quiet && !flag_files_with_matches && !flag_count && flag_format == NULL && !flag_text && !flag_hex && !flag_with_hex) + else if (!flag_quiet && !flag_files_with_matches && !flag_count && flag_format == NULL && !flag_text && !flag_hex && !flag_with_hex && flag_encoding_type != reflex::Input::file_encoding::null_data) { - // not -q, -l, -c, --format, -a -X, -W: check if initial part of the file is binary + // not -q, -l, -c, --format, -a, -X, -W, -00: check if initial part of the file is binary binfile = init_is_binary(); + + // detect binary input dynamically when more input is read after checking the inital input + matcher->in.set_handler(&bin_handler); } } @@ -4089,6 +4117,7 @@ bool binary; // the match is binary as per option -X or -W size_t matches; // number of matches bool stop; // stop searching when --max-files max reached + BinaryHandler bin_handler; // a handler to detect binary input like GNU grep #ifndef OS_WIN StdInHandler stdin_handler; // a handler to handle non-blocking input from a TTY or a slow pipe #endif @@ -4779,10 +4808,59 @@ std::string config_file(flag_config); FILE *file = NULL; - if (home || fopen_smart(&file, flag_config, "r") != 0) + if (!home) { - file = NULL; + // try opening a config file in the working directory + if (fopen_smart(&file, flag_config, "r") == 0) + { + if (file != NULL && file != stdin) + { + // check if we own this config file located in the working directory +#ifdef OS_WIN + HANDLE hFile = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(file))); + PSID pSidOwner = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + if (GetSecurityInfo(hFile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD) == ERROR_SUCCESS) + { + HANDLE hToken = NULL; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + DWORD dwBufferSize = 0; + GetTokenInformation(hToken, TokenUser, NULL, 0, &dwBufferSize); + PTOKEN_USER pTokenUser = reinterpret_cast<PTOKEN_USER>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize)); + if (pTokenUser != NULL) + { + if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwBufferSize, &dwBufferSize) || + !EqualSid(pSidOwner, pTokenUser->User.Sid)) + { + fclose(file); + file = NULL; + } + HeapFree(GetProcessHeap(), 0, pTokenUser); + } + CloseHandle(hToken); + } + if (pSD) + LocalFree(pSD); + } +#else + struct stat buf; + if (fstat(fileno(file), &buf) == 0 && buf.st_uid != getuid()) + { + fclose(file); + file = NULL; + } +#endif + } + } + else + { + file = NULL; + } + } + if (file == NULL) + { // if not in the working directory, then check the home directory if (Static::home_dir != NULL && *flag_config != '~' && *flag_config != PATHSEPCHR) { @@ -14369,7 +14447,7 @@ Output file matches in JSON. When -H, -n, -k, or -b is specified,\n\ additional values are output. See also options --format and -u.\n\ -K [MIN,][MAX], --range=[MIN,][MAX], --min-line=MIN, --max-line=MAX\n\ - Start searching at line MIN, stop at line MAX when specified.\n\ + Start searching at line MIN, stop reading input after line MAX.\n\ -k, --column-number\n\ The column number of a pattern match is displayed in front of the\n\ respective matched line, starting at column 1. Tabs are expanded\n\ @@ -14381,10 +14459,9 @@ is written.\n\ -l, --files-with-matches\n\ Only the names of files containing selected lines are written to\n\ - standard output. ugrep will only search a file until a match has\n\ - been found, making searches potentially less expensive. Pathnames\n\ - are listed once per file searched. If the standard input is\n\ - searched, the string ``(standard input)'' is written.\n\ + standard output. Pathnames are listed once per file searched. If\n\ + the standard input is searched, the string ``(standard input)'' is\n\ + written. Stop reading input upon the first match.\n\ --label=LABEL\n\ Displays the LABEL value when input is read from standard input\n\ where a file name would normally be printed in the output.\n\ @@ -14403,7 +14480,7 @@ with options -O and -t. Every file on the search path is read,\n\ making recursive searches potentially more expensive.\n\ -m [MIN,][MAX], --min-count=MIN, --max-count=MAX\n\ - Require MIN matches, stop after MAX matches when specified. Output\n\ + Require MIN matches, stop reading input upon MAX matches. Output\n\ MIN to MAX matches. For example, -m1 outputs the first match and\n\ -cm1, (with a comma) counts nonzero matches. When -u or --ungroup\n\ is specified, each individual match counts. See also option -K.\n\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.6.0/src/ugrep.hpp new/ugrep-7.7.0/src/ugrep.hpp --- old/ugrep-7.6.0/src/ugrep.hpp 2026-03-05 20:19:48.000000000 +0100 +++ new/ugrep-7.7.0/src/ugrep.hpp 2026-04-21 19:29:26.000000000 +0200 @@ -38,7 +38,7 @@ #define UGREP_HPP // DO NOT ALTER THIS LINE: updated by makemake.sh and we need it physically here for MSVC++ build from source -#define UGREP_VERSION "7.6.0" +#define UGREP_VERSION "7.7.0" // disable mmap because mmap is almost always slower than the file reading speed improvements since 3.0.0 #define WITH_NO_MMAP ++++++ ugrep.obsinfo ++++++ --- /var/tmp/diff_new_pack.urNPdn/_old 2026-04-22 17:02:43.935760176 +0200 +++ /var/tmp/diff_new_pack.urNPdn/_new 2026-04-22 17:02:43.967761455 +0200 @@ -1,5 +1,5 @@ name: ugrep -version: 7.6.0 -mtime: 1772738388 -commit: c701fb852c8fe5ea48143bf809596470d5e2b248 +version: 7.7.0 +mtime: 1776792566 +commit: 5bfa7623a98e71c4ec1f2bd3046cb084a09ff82b
