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-08-06 16:26:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ugrep (Old) and /work/SRC/openSUSE:Factory/.ugrep.new.16738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ugrep" Thu Aug 6 16:26:10 2026 rev:94 rq:1369831 version:7.8.4 Changes: -------- --- /work/SRC/openSUSE:Factory/ugrep/ugrep.changes 2026-08-01 18:33:44.488940589 +0200 +++ /work/SRC/openSUSE:Factory/.ugrep.new.16738/ugrep.changes 2026-08-06 16:28:27.357515759 +0200 @@ -1,0 +2,7 @@ +Wed Aug 5 16:45:36 UTC 2026 - Andreas Stieger <[email protected]> + +- Update to version 7.8.4: + * portability fixes + * fail fast when DFA position sets exceed complexity limits + +------------------------------------------------------------------- Old: ---- ugrep-7.8.3.obscpio New: ---- ugrep-7.8.4.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ugrep.spec ++++++ --- /var/tmp/diff_new_pack.O7RG5u/_old 2026-08-06 16:28:27.961536604 +0200 +++ /var/tmp/diff_new_pack.O7RG5u/_new 2026-08-06 16:28:27.961536604 +0200 @@ -23,7 +23,7 @@ %bcond_without fish %endif Name: ugrep -Version: 7.8.3 +Version: 7.8.4 Release: 0 Summary: Universal grep: a feature-rich grep implementation with focus on speed License: BSD-3-Clause ++++++ _service ++++++ --- /var/tmp/diff_new_pack.O7RG5u/_old 2026-08-06 16:28:27.997537847 +0200 +++ /var/tmp/diff_new_pack.O7RG5u/_new 2026-08-06 16:28:28.001537985 +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.8.3</param> + <param name="revision">v7.8.4</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.O7RG5u/_old 2026-08-06 16:28:28.025538813 +0200 +++ /var/tmp/diff_new_pack.O7RG5u/_new 2026-08-06 16:28:28.029538951 +0200 @@ -1,7 +1,7 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/Genivia/ugrep.git</param> - <param name="changesrevision">8cda03ed0dc8e97274d15c94d59327597cac15e5</param> + <param name="changesrevision">550599a6434fc5315fb6ecd415a5d859e6d846a8</param> </service> </servicedata> (No newline at EOF) ++++++ ugrep-7.8.3.obscpio -> ugrep-7.8.4.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/.github/workflows/codeql.yml new/ugrep-7.8.4/.github/workflows/codeql.yml --- old/ugrep-7.8.3/.github/workflows/codeql.yml 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/.github/workflows/codeql.yml 2026-08-05 16:31:46.000000000 +0200 @@ -27,16 +27,16 @@ uses: actions/checkout@v7 - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/[email protected] with: languages: ${{ matrix.language }} config-file: .github/config.yml - name: Autobuild - uses: github/codeql-action/autobuild@v4 + uses: github/codeql-action/[email protected] - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/[email protected] with: upload: false # disable the upload here - we will upload in a different action output: sarif-results @@ -55,6 +55,6 @@ output: sarif-results/${{ matrix.language }}.sarif - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/[email protected] with: sarif_file: sarif-results/${{ matrix.language }}.sarif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/README.md new/ugrep-7.8.4/README.md --- old/ugrep-7.8.3/README.md 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/README.md 2026-08-05 16:31:46.000000000 +0200 @@ -5541,7 +5541,7 @@ BUGS Report bugs at: <https://github.com/Genivia/ugrep/issues> - ugrep 7.8.3 July 30, 2026 UGREP(1) + ugrep 7.8.4 August 5, 2026 UGREP(1) 🔝 [Back to table of contents](#toc) Binary files old/ugrep-7.8.3/bin/win32/ug.exe and new/ugrep-7.8.4/bin/win32/ug.exe differ Binary files old/ugrep-7.8.3/bin/win32/ugrep-indexer.exe and new/ugrep-7.8.4/bin/win32/ugrep-indexer.exe differ Binary files old/ugrep-7.8.3/bin/win32/ugrep.exe and new/ugrep-7.8.4/bin/win32/ugrep.exe differ Binary files old/ugrep-7.8.3/bin/win64/ug.exe and new/ugrep-7.8.4/bin/win64/ug.exe differ Binary files old/ugrep-7.8.3/bin/win64/ugrep-indexer.exe and new/ugrep-7.8.4/bin/win64/ugrep-indexer.exe differ Binary files old/ugrep-7.8.3/bin/win64/ugrep.exe and new/ugrep-7.8.4/bin/win64/ugrep.exe differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/config.h.in new/ugrep-7.8.4/config.h.in --- old/ugrep-7.8.3/config.h.in 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/config.h.in 2026-08-05 16:31:46.000000000 +0200 @@ -43,6 +43,9 @@ /* Define to 1 if you have `lzma' library (-llzma) */ #undef HAVE_LIBLZMA +/* Define to 1 if you have the 'ws2_32' library (-lws2_32). */ +#undef HAVE_LIBWS2_32 + /* Define to 1 if you have `z' library (-lz) */ #undef HAVE_LIBZ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/configure new/ugrep-7.8.4/configure --- old/ugrep-7.8.3/configure 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/configure 2026-08-05 16:31:46.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.73 for ugrep 7.8.3. +# Generated by GNU Autoconf 2.73 for ugrep 7.8.4. # # Report bugs to <https://github.com/Genivia/ugrep/issues>. # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='ugrep' PACKAGE_TARNAME='ugrep' -PACKAGE_VERSION='7.8.3' -PACKAGE_STRING='ugrep 7.8.3' +PACKAGE_VERSION='7.8.4' +PACKAGE_STRING='ugrep 7.8.4' PACKAGE_BUGREPORT='https://github.com/Genivia/ugrep/issues' PACKAGE_URL='https://ugrep.com' @@ -1369,7 +1369,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.8.3 to adapt to many kinds of systems. +'configure' configures ugrep 7.8.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1440,7 +1440,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ugrep 7.8.3:";; + short | recursive ) echo "Configuration of ugrep 7.8.4:";; esac cat <<\_ACEOF @@ -1618,7 +1618,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ugrep configure 7.8.3 +ugrep configure 7.8.4 generated by GNU Autoconf 2.73 Copyright (C) 2026 Free Software Foundation, Inc. @@ -2172,7 +2172,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.8.3, which was +It was created by ugrep $as_me 7.8.4, which was generated by GNU Autoconf 2.73. Invocation command line was $ $0$ac_configure_args_raw @@ -3786,7 +3786,7 @@ # Define the identity of the package. PACKAGE='ugrep' - VERSION='7.8.3' + VERSION='7.8.4' printf '%s\n' "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -5709,6 +5709,52 @@ fi +# For MinGW +{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking for WSAStartup in -lws2_32" >&5 +printf %s "checking for WSAStartup in -lws2_32... " >&6; } +if test ${ac_cv_lib_ws2_32_WSAStartup+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_check_lib_save_LIBS=$LIBS +LIBS="-lws2_32 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +namespace conftest { + extern "C" int WSAStartup (); +} +int +main (void) +{ +return conftest::WSAStartup (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO" +then : + ac_cv_lib_ws2_32_WSAStartup=yes +else case e in #( + e) ac_cv_lib_ws2_32_WSAStartup=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS ;; +esac +fi +{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ws2_32_WSAStartup" >&5 +printf '%s\n' "$ac_cv_lib_ws2_32_WSAStartup" >&6; } +if test "x$ac_cv_lib_ws2_32_WSAStartup" = xyes +then : + printf '%s\n' "#define HAVE_LIBWS2_32 1" >>confdefs.h + + LIBS="-lws2_32 $LIBS" + +fi + + @@ -11899,7 +11945,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.8.3, which was +This file was extended by ugrep $as_me 7.8.4, which was generated by GNU Autoconf 2.73. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -11972,7 +12018,7 @@ cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -ugrep config.status 7.8.3 +ugrep config.status 7.8.4 configured by $0, generated by GNU Autoconf 2.73, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/configure.ac new/ugrep-7.8.4/configure.ac --- old/ugrep-7.8.3/configure.ac 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/configure.ac 2026-08-05 16:31:46.000000000 +0200 @@ -1,4 +1,4 @@ -AC_INIT([ugrep],[7.8.3],[https://github.com/Genivia/ugrep/issues],[ugrep],[https://ugrep.com]) +AC_INIT([ugrep],[7.8.4],[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-2026 Robert van Engelen, Genivia Inc.]) @@ -30,6 +30,9 @@ AC_CHECK_FUNCS([strncasecmp strnicmp _strnicmp]) +# For MinGW +AC_CHECK_LIB([ws2_32], [WSAStartup]) + AX_PTHREAD # Check how thread affinity is set diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/include/reflex/pattern.h new/ugrep-7.8.4/include/reflex/pattern.h --- old/ugrep-7.8.3/include/reflex/pattern.h 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/include/reflex/pattern.h 2026-08-05 16:31:46.000000000 +0200 @@ -956,12 +956,14 @@ static const uint16_t MAX_DEPTH = 256; ///< analyze DFA up to states this deep to improve predict match static const Index MAX_STATES = Const::GMAX/3;///< maximum number of DFA states is constrained by opcode table size static const Index MAX_EDGES = 16*Const::GMAX;///< maximum number of DFA edges is constrained by opcode table size + static const Index MAX_POSITIONS = 4194304; ///< maximum accumulated positions over all DFA states static const Index DEAD_PATH = 1; ///< state marker "path always and only reaches backedges" (a dead end) static const Index KEEP_PATH = MAX_DEPTH; ///< state marker "required path" (from a newline edge) static const Index LOOP_PATH = MAX_DEPTH + 1; ///< state marker "path reaches a backedge" (collect lookback chars) DFA() : - next(ALLOC) + next(ALLOC), + pno(0) { } ~DFA() { @@ -974,6 +976,7 @@ delete[] *i; list.clear(); next = ALLOC; + pno = 0; } #ifdef WITH_TREE_DFA /// new DFA state. @@ -990,10 +993,11 @@ State *state(Positions& pos) { State *s = state(); + pno += pos.size(); s->swap(pos); return s; } - /// new DFA state with optional tree DFA node and positions, destroys pos. + /// new DFA state with optional tree DFA node and positions. State *state(State *tnode) { State *s = state(); @@ -1004,6 +1008,7 @@ State *state(State *tnode, Positions& pos) { State *s = state(tnode); + pno += pos.size(); s->swap(pos); return s; } @@ -1036,11 +1041,13 @@ list.push_back(new State[ALLOC]); next = 0; } + pno += pos.size(); return list.back()[next++].assign(node, pos); } #endif List list; ///< block allocation list uint16_t next; ///< block allocation, next available slot in last block + size_t pno; ///< total positions accumulated in DFA states, to check against MAX_POSITIONS }; /// Indexing hash finite state automaton for indexed file search. struct HFA { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/include/reflex/timer.h new/ugrep-7.8.4/include/reflex/timer.h --- old/ugrep-7.8.3/include/reflex/timer.h 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/include/reflex/timer.h 2026-08-05 16:31:46.000000000 +0200 @@ -40,7 +40,9 @@ #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__BORLANDC__) // disable min/max macros to use std::min and std::max +#ifndef NOMINMAX #define NOMINMAX +#endif #include <windows.h> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/lib/pattern.cpp new/ugrep-7.8.4/lib/pattern.cpp --- old/ugrep-7.8.3/lib/pattern.cpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/lib/pattern.cpp 2026-08-05 16:31:46.000000000 +0200 @@ -2255,7 +2255,7 @@ if (state->accept > 0 && state->accept <= end_.size()) acc_[state->accept - 1] = true; ++vno_; - if (vno_ > DFA::MAX_STATES || eno_ > DFA::MAX_EDGES) + if (vno_ > DFA::MAX_STATES || eno_ > DFA::MAX_EDGES || dfa_.pno > DFA::MAX_POSITIONS) error(regex_error::exceeds_limits, rex_.size()); } delete[] table; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/lzma/C/viizip.c new/ugrep-7.8.4/lzma/C/viizip.c --- old/ugrep-7.8.3/lzma/C/viizip.c 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/lzma/C/viizip.c 2026-08-05 16:31:46.000000000 +0200 @@ -43,7 +43,7 @@ #include "7zCrc.h" #include "7zFile.h" -#ifdef OS_WIN +#if defined(OS_WIN) || defined(__MINGW32__) || defined(__MINGW64__) #include <io.h> #endif @@ -220,7 +220,7 @@ viizip->buflen = 0; viizip->tmp = NULL; viizip->tmplen = 0; -#ifdef OS_WIN +#if defined(OS_WIN) || defined(__MINGW32__) || defined(__MINGW64__) viizip->stream.file.handle = (HANDLE)_get_osfhandle(_fileno(file)); #else viizip->stream.file.fd = fileno(file); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/lzma/C/viizip.h new/ugrep-7.8.4/lzma/C/viizip.h --- old/ugrep-7.8.3/lzma/C/viizip.h 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/lzma/C/viizip.h 2026-08-05 16:31:46.000000000 +0200 @@ -37,7 +37,7 @@ #ifndef VIIZIP_H #define VIIZIP_H -// check if we are compiling for a windows OS, but not Cygwin or MinGW +/* check if we are compiling for a windows OS, but not Cygwin or MinGW */ #if !defined(OS_WIN) && (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) # define OS_WIN #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/man/ug.1 new/ugrep-7.8.4/man/ug.1 --- old/ugrep-7.8.3/man/ug.1 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/man/ug.1 2026-08-05 16:31:46.000000000 +0200 @@ -1,4 +1,4 @@ -.TH UGREP "1" "July 30, 2026" "ugrep 7.8.3" "User Commands" +.TH UGREP "1" "August 05, 2026" "ugrep 7.8.4" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/man/ugrep-indexer.1 new/ugrep-7.8.4/man/ugrep-indexer.1 --- old/ugrep-7.8.3/man/ugrep-indexer.1 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/man/ugrep-indexer.1 2026-08-05 16:31:46.000000000 +0200 @@ -1,4 +1,4 @@ -.TH UGREP-INDEXER "1" "July 30, 2026" "ugrep-indexer 7.8.3" "User Commands" +.TH UGREP-INDEXER "1" "August 05, 2026" "ugrep-indexer 7.8.4" "User Commands" .SH NAME \fBugrep-indexer\fR -- file indexer to accelerate recursive searching .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/man/ugrep.1 new/ugrep-7.8.4/man/ugrep.1 --- old/ugrep-7.8.3/man/ugrep.1 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/man/ugrep.1 2026-08-05 16:31:46.000000000 +0200 @@ -1,4 +1,4 @@ -.TH UGREP "1" "July 30, 2026" "ugrep 7.8.3" "User Commands" +.TH UGREP "1" "August 05, 2026" "ugrep 7.8.4" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/glob.cpp new/ugrep-7.8.4/src/glob.cpp --- old/ugrep-7.8.3/src/glob.cpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/glob.cpp 2026-08-05 16:31:46.000000000 +0200 @@ -83,7 +83,7 @@ // a/** matches a/x, a/y, a/x/y but not a, b/x // a\?b matches a?b but not a, b, ab, axb, a/b -// check if we are natively compiling for a Windows OS (not Cygwin and not MinGW) +// check if we are natively compiling for a windows OS, but not Cygwin or MinGW #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) # define OS_WIN #endif @@ -92,7 +92,7 @@ #include <cstring> #include <cctype> -#ifdef OS_WIN +#ifdef OS_WIN // compiling for a windows OS, but not Cygwin or MinGW #define PATHSEP '\\' #else #define PATHSEP '/' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/query.cpp new/ugrep-7.8.4/src/query.cpp --- old/ugrep-7.8.3/src/query.cpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/query.cpp 2026-08-05 16:31:46.000000000 +0200 @@ -45,7 +45,7 @@ #include <chrono> #include <fcntl.h> -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW #include <direct.h> @@ -714,10 +714,10 @@ } } -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // CTRL-C/BREAK handler -BOOL WINAPI Query::sigint(DWORD signal) +BOOL WINAPI Query::sigint(DWORD) { VKey::cleanup(); Screen::cleanup(); @@ -844,7 +844,7 @@ abort("no ANSI terminal screen detected"); } -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // handle CTRL-C SetConsoleCtrlHandler(&sigint, TRUE); @@ -1005,7 +1005,7 @@ err = false; } -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW else { // detect screen size changes here for Windows (no SIGWINCH) @@ -1415,7 +1415,7 @@ break; case VKey::CTRL_BS: // CTRL-\: terminate -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); #else raise(SIGTERM); @@ -1503,7 +1503,7 @@ search_thread_.join(); } -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW hPipe_ = nonblocking_pipe(search_pipe_); @@ -1778,7 +1778,7 @@ // no newline and buffer is not full and not EOF reached yet, get more data if (buflen_ < QUERY_BUFFER_SIZE && !eof_) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // try to fetch more data from the non-blocking pipe when immediately available DWORD nread = 0; @@ -2454,7 +2454,7 @@ if (found) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW _WIN32_FILE_ATTRIBUTE_DATA attr_before; #else struct stat buf; @@ -2464,7 +2464,7 @@ if (!flag_stdin || filename != flag_label) { // check if the file exists and is a regular file, also get the file's last modification time -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW found = GetFileAttributesExW(utf8_decode(filename).c_str(), GetFileExInfoStandard, &attr_before); #else found = stat(filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode); @@ -2486,7 +2486,7 @@ FILE *pager = NULL; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW std::wstring wcommand; #endif @@ -2504,7 +2504,7 @@ Screen::normal(); Screen::setpos(1, 0); -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // normal tty mode VKey::cleanup(); #endif @@ -2554,7 +2554,7 @@ } else { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW if (filename.empty() || filename.at(0) == '/' || filename.find('"') != std::string::npos) { // illegal filename in Windows, should never happen, but just in case @@ -2600,14 +2600,14 @@ else { // execute command, check if OK -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW ok = (_wsystem(wcommand.c_str()) == 0); #else ok = (system(command.c_str()) == 0); #endif // check if file was changed by the pager (when it is an editor) -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW _WIN32_FILE_ATTRIBUTE_DATA attr_after; changed = GetFileAttributesExW(utf8_decode(filename).c_str(), GetFileExInfoStandard, &attr_after) == 0 || attr_before.ftLastWriteTime.dwLowDateTime != attr_after.ftLastWriteTime.dwLowDateTime || @@ -2625,7 +2625,7 @@ } } -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // resume RAW tty mode and flush the key buffer VKey::setup(VKey::TTYRAW); #else @@ -3168,7 +3168,7 @@ Screen::put(0, Screen::cols - 1, "?"); -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW while (true) { @@ -3227,7 +3227,7 @@ break; case VKey::CTRL_BS: -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); #else raise(SIGTERM); @@ -3727,7 +3727,7 @@ if (select_all_ && (!eof_ || buflen_ > 0)) { // reading the search pipe should block until data is received -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW blocking_ = true; pending_ = false; #else @@ -4158,7 +4158,7 @@ // if standard input is searched, then dynamically buffer the input to search if (flag_stdin) { -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // make stdin non-blocking to read and buffer dynamically fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); #endif @@ -4226,7 +4226,7 @@ if (feof(stdin)) break; -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW struct timeval tv; fd_set rfds, efds; FD_ZERO(&rfds); @@ -4514,7 +4514,7 @@ size_t Query::fuzzy_ = 1; bool Query::dotall_ = false; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW HANDLE Query::hPipe_; OVERLAPPED Query::overlapped_; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/query.hpp new/ugrep-7.8.4/src/query.hpp --- old/ugrep-7.8.3/src/query.hpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/query.hpp 2026-08-05 16:31:46.000000000 +0200 @@ -187,7 +187,7 @@ static void redraw(); -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW static BOOL WINAPI sigint(DWORD); @@ -336,7 +336,7 @@ static size_t fuzzy_; // saved --fuzzy fuzzy distance static bool dotall_; // saved --dotall flag -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW static HANDLE hPipe_; static OVERLAPPED overlapped_; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/screen.cpp new/ugrep-7.8.4/src/screen.cpp --- old/ugrep-7.8.3/src/screen.cpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/screen.cpp 2026-08-05 16:31:46.000000000 +0200 @@ -39,7 +39,7 @@ #include <string> #include <fcntl.h> -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW #include <signal.h> #endif @@ -86,7 +86,7 @@ // get the cursor position void Screen::getpos(int *row, int *col) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW CONSOLE_SCREEN_BUFFER_INFO info; if (GetConsoleScreenBufferInfo(hConOut, &info)) @@ -157,7 +157,7 @@ size_t Screen::getsize() { // get current window size from ioctl -#if defined(OS_WIN) +#if defined(OS_WIN_OR_MINGW) CONSOLE_SCREEN_BUFFER_INFO info; if (GetConsoleScreenBufferInfo(hConOut, &info)) { @@ -233,7 +233,7 @@ { good = true; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING @@ -318,7 +318,7 @@ // cleanup to restore main screen buffer void Screen::cleanup() { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW if (hConOut != INVALID_HANDLE_VALUE) { @@ -876,7 +876,7 @@ bool Screen::mono = false; // monochrome bool Screen::good = false; // true if all previous screen operations were successful after setup() -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // Windows console state HANDLE Screen::hConOut; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/screen.hpp new/ugrep-7.8.4/src/screen.hpp --- old/ugrep-7.8.3/src/screen.hpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/screen.hpp 2026-08-05 16:31:46.000000000 +0200 @@ -250,7 +250,7 @@ // emit text static void put(const char *text, size_t size) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW DWORD nwritten; good = WriteFile(hConOut, text, static_cast<DWORD>(size), &nwritten, NULL) && good; #else @@ -285,7 +285,7 @@ static bool mono; // monochrome static bool good; // true if all previous screen operations were successful after setup() -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // Windows console static HANDLE hConOut; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/ugrep-indexer.cpp new/ugrep-7.8.4/src/ugrep-indexer.cpp --- old/ugrep-7.8.3/src/ugrep-indexer.cpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/ugrep-indexer.cpp 2026-08-05 16:31:46.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.8.3" +#define UGREP_VERSION "7.8.4" // use a task-parallel thread to decompress the stream into a pipe to search, also handles nested archives #define WITH_DECOMPRESSION_THREAD @@ -43,9 +43,14 @@ // ignore hidden files and directories in archives, but ugrep will never find them anymore when searching hidden! #define WITH_SKIP_HIDDEN_ARCHIVES -// check if we are compiling for a windows OS, but not Cygwin or MinGW -#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) -# define OS_WIN +// check if we are compiling for a windows OS, but not Cygwin +#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) +# if defined(__MINGW32__) || defined(__MINGW64__) +# define OS_WIN_MINGW +# else +# define OS_WIN +# endif +# define OS_WIN_OR_MINGW #endif // 64 bits off_t and fseeko @@ -54,10 +59,12 @@ // PRId64 PRIu64 #define __STDC_FORMAT_MACROS -#ifdef OS_WIN // compiling for a windows OS +#ifdef OS_WIN_OR_MINGW // compiling for a windows OS, but not Cygwin // disable legacy min/max macros so we can use std::min and std::max -#define NOMINMAX +#ifndef NOMINMAX +# define NOMINMAX +#endif #include <windows.h> #include <tchar.h> @@ -72,6 +79,10 @@ #include <cstdint> #include <string> +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + // 64 bits off_t and fseeko #define off_t int64_t #define fseeko _fseeki64 @@ -81,8 +92,18 @@ #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -#define PATHSEPCHR '\\' -#define PATHSEPSTR "\\" +#ifdef OS_WIN +# define PATHSEPCHR '\\' +# define PATHSEPSTR "\\" +#else +# define PATHSEPCHR '/' +# define PATHSEPSTR "/" +#endif + +#ifdef OS_WIN +# define O_RDONLY _O_RDONLY +# define O_WRONLY _O_WRONLY +#endif // convert a wide Unicode string to an UTF-8 string std::string utf8_encode(const std::wstring &wstr) @@ -120,7 +141,7 @@ hFile = CreateFileW(wfilename.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return errno = (GetLastError() == ERROR_ACCESS_DENIED ? EACCES : ENOENT); - int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), _O_RDONLY); + int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), O_RDONLY); if (fd == -1) { CloseHandle(hFile); @@ -152,8 +173,8 @@ #include <signal.h> #include <dirent.h> -#include <sys/select.h> #include <sys/stat.h> +#include <fcntl.h> #include <unistd.h> #include <cerrno> #include <cstdlib> @@ -167,10 +188,6 @@ # include "config.h" #endif -#if defined(HAVE_F_RDAHEAD) -# include <fcntl.h> -#endif - #define PATHSEPCHR '/' #define PATHSEPSTR "/" @@ -1161,7 +1178,7 @@ last_time = 0; index_time = 0; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW WIN32_FIND_DATAW ffd; @@ -1182,6 +1199,8 @@ return; } + (void)num_links; // appease -Wunused + #else DIR *dir = opendir(pathname.c_str()); @@ -1225,7 +1244,7 @@ std::string entry_pathname; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW std::string cFileName; @@ -2053,7 +2072,7 @@ // where the magic happens int main(int argc, const char **argv) { -#if !defined(OS_WIN) && defined(HAVE_LIBZ) && defined(WITH_DECOMPRESSION_THREAD) +#if !defined(OS_WIN_OR_MINGW) && defined(HAVE_LIBZ) && defined(WITH_DECOMPRESSION_THREAD) // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/ugrep.cpp new/ugrep-7.8.4/src/ugrep.cpp --- old/ugrep-7.8.3/src/ugrep.cpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/ugrep.cpp 2026-08-05 16:31:46.000000000 +0200 @@ -95,9 +95,7 @@ #include <chrono> #include <sstream> -#ifdef OS_WIN - -// compiling for a windows OS, except Cygwin and MinGW +#ifdef OS_WIN_OR_MINGW // compiling for a windows OS, but not Cygwin // optionally enable --color=auto by default // #define WITH_COLOR @@ -134,11 +132,12 @@ #include <winsock.h> // gethostname() for --hyperlink #include <securitybaseapi.h> // GetTokenInformation() #include <aclapi.h> // GetSecurityInfo() -#pragma comment(lib, "Ws2_32.lib") -#else +#ifdef OS_WIN +#pragma comment(lib, "Ws2_32.lib") +#endif -// not compiling for a windows OS +#else // not compiling for a windows OS or for windows OS #include <signal.h> #include <dirent.h> @@ -237,7 +236,7 @@ const char *color_warning = ""; // stderr warning text const char *color_message = ""; // stderr error or warning message text -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // output file stat() result is available and S_ISREG (regular file) bool Static::output_stat_result = false; @@ -497,7 +496,7 @@ void open_pager(); void close_pager(); -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // CTRL-C handler BOOL WINAPI sigint(DWORD signal) @@ -540,7 +539,7 @@ { // set affinity -#if defined(OS_WIN) || defined(__CYGWIN__) +#if defined(OS_WIN_OR_MINGW) || defined(__CYGWIN__) (void)SetThreadAffinityMask(GetCurrentThread(), DWORD_PTR(1) << cpu); @@ -594,7 +593,7 @@ // set priority -#if defined(OS_WIN) || defined(__CYGWIN__) +#if defined(OS_WIN_OR_MINGW) || defined(__CYGWIN__) (void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); @@ -662,7 +661,7 @@ pclose(Static::output); } -// open a file where - means stdin/stdout and an initial ~ expands to home directory +// open a file where - means stdin (mode "r") or stdout (mode "a" or "w") and an initial ~ expands to home directory int fopen_smart(FILE **file, const char *filename, const char *mode) { *file = NULL; @@ -672,7 +671,7 @@ if (strcmp(filename, "-") == 0) { - *file = strchr(mode, 'w') == NULL ? stdin : stdout; + *file = strchr(mode, 'r') != NULL ? stdin : stdout; return 0; } @@ -722,7 +721,8 @@ // check if a file's inode is the current output file, to avoid searching the file we write to inline bool is_output(ino_t inode) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW + (void)inode; // appease -Wunused return false; // TODO check that two FILE* on Windows are the same, is this possible? #else return Static::output_stat_regular && inode == Static::output_stat.st_ino; @@ -1940,7 +1940,7 @@ uint64_t info; uint16_t cost; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // get modification time (micro seconds) from directory entry static uint64_t modified_time(const WIN32_FIND_DATAW& ffd) @@ -3235,7 +3235,7 @@ matchers(matchers), file_in(NULL), bin_handler(*this) -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW , stdin_handler(*this) #endif #ifdef HAVE_LIBZ @@ -3544,7 +3544,7 @@ input = reflex::Input(file_in, flag_encoding_type); #endif -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW if (!flag_decompress && !flag_quiet && !flag_files_with_matches && !flag_count) { int fd = fileno(file_in); @@ -3667,7 +3667,7 @@ int fd[2]; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // Windows CreateProcess requires an "inherited" pipe handle specific to Windows bool ok = (pipe_inherit(fd) == 0); #else @@ -3676,7 +3676,7 @@ if (ok) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW std::wstring wcommand(utf8_decode(command)); size_t pathname_pos = 0; @@ -3918,7 +3918,7 @@ #endif #endif -#if defined(WITH_STDIN_DRAIN) && !defined(OS_WIN) +#if defined(WITH_STDIN_DRAIN) && !defined(OS_WIN_OR_MINGW) // 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 && @@ -3978,7 +3978,7 @@ else #endif -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // set interactive search handler e.g. for slow stdin input if (interactive) matcher->in.set_handler(&stdin_handler); @@ -4118,7 +4118,7 @@ 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 +#ifndef OS_WIN_OR_MINGW StdInHandler stdin_handler; // a handler to handle non-blocking input from a TTY or a slow pipe #endif #ifdef HAVE_LIBZ @@ -4669,16 +4669,26 @@ { NULL, NULL, NULL, NULL } }; +#ifdef OS_WIN_OR_MINGW +// ugrep main() for windows to support wide string arguments and globbing #ifdef OS_WIN -// ugrep main() for Windows to support wide string arguments and globbing +// ugrep wmain() for VS int wmain(int argc, const wchar_t **wargv) #else -// ugrep main() +// ugrep main() for MinGW, pick up argc and wargv from CommandLineToArgvW() +int main() +#endif +#else +// ugrep main() for non-windows int main(int argc, const char **argv) #endif { +#ifdef OS_WIN_OR_MINGW -#ifdef OS_WIN +#ifdef OS_WIN_MINGW + int argc = 0; + wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); +#endif // store UTF-8 arguments for the duration of main() and convert Unicode command line arguments wargv[] to UTF-8 arguments argv[] const char **argv = new const char *[argc]; @@ -4744,7 +4754,7 @@ } } -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW delete[] argv; @@ -4817,7 +4827,7 @@ if (file != NULL && file != stdin) { // check if we own this config file located in the working directory -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW HANDLE hFile = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(file))); PSID pSidOwner = NULL; PSECURITY_DESCRIPTOR pSD = NULL; @@ -6421,7 +6431,7 @@ size_t len = strlen(program); -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // Windows: compare executable name up to a dot when present, e.g. "ug.exe" compares as "ug" const char *dot = strchr(program, '.'); if (dot != NULL) @@ -6797,6 +6807,9 @@ "Examples:\n" " ugrep \"PATTERN\" # match PATTERN\n" " ugrep -e \"-PATTERN\" # match -PATTERN (including the leading dash)\n" +#ifdef OS_WIN + " ugrep -e \"/PATTERN\" # match /PATTERN (including the leading slash)\n" +#endif " ugrep \"\" # match all lines\n" " ugrep --match # match all lines\n"); @@ -6952,7 +6965,7 @@ auto arg_file = Static::arg_files.begin(); while (arg_file != Static::arg_files.end()) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW DWORD attr = GetFileAttributesW(utf8_decode(*arg_file).c_str()); @@ -7519,7 +7532,7 @@ abort("option --filter-magic-label: ", error.what()); } -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) +#if defined(__CYGWIN__) // --filter: Cygwin forked process may hang when searching with multiple threads, force one worker thread if (!flag_filter.empty()) flag_jobs = 1; @@ -7539,7 +7552,7 @@ } else if (!flag_quiet) { -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // if not to a TTY, is output sent to a pager or to /dev/null? if (!flag_tty_term) @@ -7677,7 +7690,7 @@ } else { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW if (flag_tty_term) { @@ -7910,7 +7923,7 @@ // get host in hyperlink char host[80] = "localhost"; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW WSADATA w; if (WSAStartup(MAKEWORD(1, 1), &w) == 0) { @@ -9239,7 +9252,7 @@ } else { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW const DWORD attr = INVALID_FILE_ATTRIBUTES; #else const uint32_t attr = 0; @@ -9272,14 +9285,14 @@ case Type::DIRECTORY: if (flag_directories_action != Action::SKIP) { -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW if (flag_dereference) vino = visited.insert(inode); #endif recurse(1, pathname); -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW if (flag_dereference) visited.erase(vino.first); #endif @@ -9303,7 +9316,9 @@ if (*basename == '.' && !flag_hidden && !is_argument) return Type::SKIP; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW + + (void)type; (void)inode; (void)info; // appease -Wunused // use file attributes from FindFirstFileW() WIN32_FIND_DATAW dwFileAttributes otherwise attr == INVALID_FILE_ATTRIBUTES if (attr == INVALID_FILE_ATTRIBUTES) @@ -9780,7 +9795,7 @@ if (out.eof || out.cancelled()) return; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW WIN32_FIND_DATAW ffd; @@ -9880,7 +9895,7 @@ std::vector<Entry> dir_entries; std::string entry_pathname; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW std::string cFileName; uint64_t list = 0; @@ -10447,7 +10462,7 @@ if (out.eof || out.cancelled()) break; -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // -R: check if this directory was visited before std::pair<std::set<ino_t>::iterator,bool> vino; @@ -10463,7 +10478,7 @@ recurse(level + 1, entry.pathname.c_str()); -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW if (flag_dereference) visited.erase(vino.first); #endif @@ -14289,9 +14304,7 @@ #endif "\ When FILE is a `-', standard input is read. Empty files contain no\n\ - patterns; thus nothing is matched. This option may be repeated.\n" -#ifndef OS_WIN - "\ + patterns; thus nothing is matched. This option may be repeated.\n\ --files, -%%\n\ Boolean file matching mode, the opposite of --lines. When combined\n\ with option --bool, matches a file if all Boolean conditions are\n\ @@ -14320,9 +14333,7 @@ MAGIC regex pattern. Only files that have no filename extension\n\ are labeled, unless +LABEL is specified. When LABEL matches an\n\ extension specified in --filter=COMMANDS, the corresponding command\n\ - is invoked. This option may be repeated.\n" -#endif - "\ + is invoked. This option may be repeated.\n\ --format=FORMAT\n\ Output FORMAT-formatted matches. For example --format='%f:%n:%O%~'\n\ outputs matching lines `%O' with filename `%f` and line number `%n'\n\ @@ -14389,7 +14400,7 @@ with --hexdump. See also options -U, -W and -X.\n\ --hidden, -.\n\ Search " -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW "Windows system and " #endif "hidden files and directories\n\ @@ -14853,6 +14864,9 @@ ; if (flag_grep) out << "\nGrep compatibility mode: -Z and -z reassigned to --null and --null-data.\n"; +#ifdef OS_WIN + out << "\nWindows mode: short options may start with `-' or with `/'.\n"; +#endif out << "\n\ Long options may start with `--no-' to disable, when applicable.\n\ \n\ @@ -15317,18 +15331,20 @@ if (!flag_no_messages) { const char *errmsg = NULL; +#if defined(__STDC_LIB_EXT1__) || defined(OS_WIN_OR_MINGW) + char errbuf[256]; if (errno) { // use safe strerror_s() instead of strerror() when available -#if defined(__STDC_LIB_EXT1__) || defined(OS_WIN) - char errbuf[256]; strerror_s(errbuf, sizeof(errbuf), errno); errmsg = errbuf; + } + fprintf(Static::errout, "%sugrep: %swarning:%s %s%s%s%s%c%s %s%s%s\n", color_off, color_warning, color_off, color_high, message != NULL ? message : "", message != NULL ? " " : "", arg != NULL ? arg : "", errmsg != NULL ? ':' : ' ', color_off, color_message, errmsg != NULL ? errmsg : "", color_off); #else + if (errno) errmsg = strerror(errno); -#endif - } fprintf(Static::errout, "%sugrep: %swarning:%s %s%s%s%s%c%s %s%s%s\n", color_off, color_warning, color_off, color_high, message != NULL ? message : "", message != NULL ? " " : "", arg != NULL ? arg : "", errmsg != NULL ? ':' : ' ', color_off, color_message, errmsg != NULL ? errmsg : "", color_off); +#endif } ++Static::warnings; } @@ -15337,7 +15353,7 @@ void error(const char *message, const char *arg) { // use safe strerror_s() instead of strerror() when available -#if defined(__STDC_LIB_EXT1__) || defined(OS_WIN) +#if defined(__STDC_LIB_EXT1__) || defined(OS_WIN_OR_MINGW) char errmsg[256]; strerror_s(errmsg, sizeof(errmsg), errno); #else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/ugrep.hpp new/ugrep-7.8.4/src/ugrep.hpp --- old/ugrep-7.8.3/src/ugrep.hpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/ugrep.hpp 2026-08-05 16:31:46.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.8.3" +#define UGREP_VERSION "7.8.4" // disable mmap because mmap is almost always slower than the file reading speed improvements since 3.0.0 #define WITH_NO_MMAP @@ -66,15 +66,22 @@ // use $XDG_CONFIG_HOME/ugrep/config for ug (or ugrep --config) when no .ugrep files are found, migh be confusing! // #define WITH_XDG_CONFIG_HOME -// check if we are compiling for a windows OS, but not Cygwin or MinGW -#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) -# define OS_WIN +// check if we are natively compiling for a windows OS, but not Cygwin +#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) +# if defined(__MINGW32__) || defined(__MINGW64__) +# define OS_WIN_MINGW +# else +# define OS_WIN +# endif +# define OS_WIN_OR_MINGW #endif -#ifdef OS_WIN // compiling for a windows OS +#ifdef OS_WIN_OR_MINGW // compiling for a windows OS, but not Cygwin // disable legacy min/max macros so we can use std::min and std::max -#define NOMINMAX +#ifndef NOMINMAX +# define NOMINMAX +#endif #include <windows.h> #include <tchar.h> @@ -88,16 +95,30 @@ #include <string> #include <cstdint> +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -#define PATHSEPCHR '\\' -#define PATHSEPSTR "\\" -#define NEWLINESTR "\r\n" // Note: also hard-coded into Output class +#ifdef OS_WIN +# define PATHSEPCHR '\\' +# define PATHSEPSTR "\\" +# define NEWLINESTR "\r\n" // Note: also hard-coded into Output class +#else +# define PATHSEPCHR '/' +# define PATHSEPSTR "/" +# define NEWLINESTR "\n" // Note: Also hard-coded into Output class. +#endif +#ifdef OS_WIN +# define O_RDONLY _O_RDONLY +# define O_WRONLY _O_WRONLY // POSIX read() and write() return type is ssize_t typedef int ssize_t; +#endif // POSIX strcasecmp inline int strcasecmp(const char *s1, const char *s2) @@ -118,8 +139,8 @@ HANDLE pipe_w = NULL; if (CreatePipe(&pipe_r, &pipe_w, NULL, 0)) { - fd[0] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_r), _O_RDONLY); - fd[1] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_w), _O_WRONLY); + fd[0] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_r), O_RDONLY); + fd[1] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_w), O_WRONLY); return 0; } errno = GetLastError(); @@ -138,8 +159,8 @@ sa.lpSecurityDescriptor = NULL; if (CreatePipe(&pipe_r, &pipe_w, &sa, 0)) { - fd[0] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_r), _O_RDONLY); - fd[1] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_w), _O_WRONLY); + fd[0] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_r), O_RDONLY); + fd[1] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_w), O_WRONLY); if (SetHandleInformation(reinterpret_cast<HANDLE>(_get_osfhandle(fd[0])), HANDLE_FLAG_INHERIT, 0)) return 0; close(fd[0]); @@ -149,6 +170,8 @@ return -1; } +#ifdef OS_WIN + // POSIX popen() inline FILE *popen(const char *command, const char *mode) { @@ -161,6 +184,8 @@ return _pclose(stream); } +#endif + // wrap Windows _dupenv_s() inline int dupenv_s(char **ptr, const char *name) { @@ -229,7 +254,7 @@ hFile = CreateFileW(wfilename.c_str(), FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return errno = (GetLastError() == ERROR_ACCESS_DENIED ? EACCES : ENOENT); - int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), _O_RDONLY); + int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), O_RDONLY); if (fd == -1) { CloseHandle(hFile); @@ -244,7 +269,7 @@ return 0; } -#else // not compiling for a windows OS +#else // not compiling for a windows OS or for windows OS MinGW #define _FILE_OFFSET_BITS 64 @@ -253,6 +278,8 @@ #include <cstdio> #include <cstring> #include <cstdint> +#include <string> +#include <fcntl.h> #include <unistd.h> #include <sys/stat.h> @@ -296,8 +323,7 @@ # include <sys/resource.h> #endif -#if defined(HAVE_F_RDAHEAD) || defined(HAVE_O_NOATIME) -# include <fcntl.h> +#if defined(HAVE_F_RDAHEAD) # ifndef O_NOATIME # define O_NOATIME 0 # endif @@ -496,7 +522,6 @@ #include <condition_variable> #include <map> #include <set> -#include <string> #include <vector> // undefined size_t value @@ -524,7 +549,7 @@ // unique address and label to identify standard input path static const char *LABEL_STANDARD_INPUT; -#ifndef OS_WIN +#ifndef OS_WIN_OR_MINGW // output file stat() result is available and S_ISREG (regular file) static bool output_stat_result; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/vkey.cpp new/ugrep-7.8.4/src/vkey.cpp --- old/ugrep-7.8.3/src/vkey.cpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/vkey.cpp 2026-08-05 16:31:46.000000000 +0200 @@ -746,7 +746,7 @@ keybuf[1] = 0; keybuf[2] = 0; -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW FlushConsoleInputBuffer(hConIn); @@ -761,7 +761,7 @@ // setup vkey in VKey::NORMAL tty or VKey::TTYRAW raw tty mode (cfmakeraw), returns 0 on success <0 on failure bool VKey::setup(int mode) { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW hConIn = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); @@ -837,7 +837,7 @@ // release vkey resources and restore tty void VKey::cleanup() { -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW if (hConIn != INVALID_HANDLE_VALUE) { @@ -898,7 +898,7 @@ } } -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // Windows console state HANDLE VKey::hConIn; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/vkey.hpp new/ugrep-7.8.4/src/vkey.hpp --- old/ugrep-7.8.3/src/vkey.hpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/vkey.hpp 2026-08-05 16:31:46.000000000 +0200 @@ -192,7 +192,7 @@ #include "ugrep.hpp" -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW #ifdef ENABLE_VIRTUAL_TERMINAL_INPUT # define VKEY_WIN @@ -312,7 +312,7 @@ // translate ANSI escape sequences, FN, and DEL keys static int ansi_esc(int ch); -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW // Windows console state static HANDLE hConIn; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/src/zthread.hpp new/ugrep-7.8.4/src/zthread.hpp --- old/ugrep-7.8.3/src/zthread.hpp 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/src/zthread.hpp 2026-08-05 16:31:46.000000000 +0200 @@ -43,11 +43,16 @@ #include <mutex> #include <condition_variable> #include <thread> +#include <fcntl.h> -#ifdef OS_WIN +#ifdef OS_WIN_OR_MINGW +#ifdef OS_WIN +# define O_RDONLY _O_RDONLY +# define O_WRONLY _O_WRONLY // POSIX read() and write() return type is ssize_t typedef int ssize_t; +#endif // POSIX pipe() emulation inline int pipe(int fd[2]) @@ -56,8 +61,8 @@ HANDLE pipe_w = NULL; if (CreatePipe(&pipe_r, &pipe_w, NULL, 0)) { - fd[0] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_r), _O_RDONLY); - fd[1] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_w), _O_WRONLY); + fd[0] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_r), O_RDONLY); + fd[1] = _open_osfhandle(reinterpret_cast<intptr_t>(pipe_w), O_WRONLY); return 0; } errno = GetLastError(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ugrep-7.8.3/tests/verify.sh new/ugrep-7.8.4/tests/verify.sh --- old/ugrep-7.8.3/tests/verify.sh 2026-07-30 16:46:56.000000000 +0200 +++ new/ugrep-7.8.4/tests/verify.sh 2026-08-05 16:31:46.000000000 +0200 @@ -115,16 +115,24 @@ export GREP_COLORS='cx=hb:ms=hug:mc=ib+W:fn=h35:ln=32h:cn=1;32:bn=1;32:se=+36' -# set ERR and DIFF to compare and report +# set ERR to report function ERR() { echo "[1;31mError:[0m[1m ugrep --sort $1 [1;31mfailed[0m" exit 1 } -DIFF="diff -U1 -" +# set DIFF to compare and report, MinGW should ignore CRL<->LF and ignore "binary" characters -# prepare to test +if test "$OSTYPE" = "msys" || ( test "$OSTYPE" = "cygwin" && test ! -z "$MSYSTEM" ) ; then + DIFF="diff -a -b -U1 -" +else + DIFF="diff -U1 -" +fi + +# prepare to test, w/o MinGW dir tests (no symlinks) + +if test "$OSTYPE" != "msys" && ( test "$OSTYPE" != "cygwin" || test -z "$MSYSTEM" ) ; then rm -rf dir1/ dir2/ @@ -183,6 +191,8 @@ rm -rf dir1 dir2 +fi + for OPS in '' '-F' '-G' ; do printf . $UG $OPS -iwco -f lorem lorem.utf8.txt \ ++++++ ugrep.obsinfo ++++++ --- /var/tmp/diff_new_pack.O7RG5u/_old 2026-08-06 16:28:29.837601349 +0200 +++ /var/tmp/diff_new_pack.O7RG5u/_new 2026-08-06 16:28:29.845601625 +0200 @@ -1,5 +1,5 @@ name: ugrep -version: 7.8.3 -mtime: 1785422816 -commit: 8cda03ed0dc8e97274d15c94d59327597cac15e5 +version: 7.8.4 +mtime: 1785940306 +commit: 550599a6434fc5315fb6ecd415a5d859e6d846a8
