VirtualBox

Changeset 3537 in kBuild


Ignore:
Timestamp:
Dec 21, 2021 12:19:11 PM (3 years ago)
Author:
bird
Message:

grep: Rewrote the console output speed hack, making it even faster and more correct. Changed the default locale codepage to UTF-8, adding an --codepage=NUM option for overriding this if one needs to grep non-UTF8 files.

Location:
trunk/src/grep
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/grep/Makefile.kmk

    r3536 r3537  
    5656PROGRAMS += kmk_grep
    5757kmk_grep_TEMPLATE = BINC99
    58 kmk_grep_DEPS = \
    59         $(kmk_grep_0_OUTDIR)/config.h \
    60         $(kmk_grep_0_OUTDIR)/configmake.h
    61 kmk_grep_DEPS.win = \
    62         $(kmk_grep_0_OUTDIR)/getopt-cdefs.h \
    63         $(kmk_grep_0_OUTDIR)/getopt.h \
    64         $(kmk_grep_0_OUTDIR)/unistd.h \
    65        $(kmk_grep_0_OUTDIR)/sigsegv.h \
    66        $(kmk_grep_0_OUTDIR)/fnmatch.h
    67 kmk_grep_CLEAN = $(kmk_grep_DEPS)
     58kmk_grep_DEFS = \
     59        KMK_GREP \
     60        HAVE_CONFIG_H
    6861kmk_grep_CFLAGS.solaris = -std=gnu99
    6962kmk_grep_CFLAGS.win += -wd4018 # grep.c(797): warning C4018: '<': signed/unsigned mismatch [lots of size_t / ptrdiff_t mixups]
     
    7265kmk_grep_CFLAGS.win += -wd4146 # fnmatch_loop.c(1067): warning C4146: unary minus operator applied to unsigned type, result still unsigned
    7366kmk_grep_CFLAGS.win += -wd4308 # fnmatch_loop.c(1067): warning C4308: negative integral constant converted to unsigned type
     67ifdef KBUILD_SOLARIS_10
     68 kmk_grep_CFLAGS += -std=gnu99
     69endif
    7470kmk_grep_INCS = \
    7571        $(kmk_grep_0_OUTDIR) \
    7672        . \
    7773        lib
    78 kmk_grep_DEFS = \
    79         KMK_GREP \
    80         HAVE_CONFIG_H
    81 ifdef KBUILD_SOLARIS_10
    82  kmk_grep_CFLAGS += -std=gnu99
    83 endif
    8474kmk_grep_SOURCES = \
    8575        src/grep.c \
     
    153143        ../lib/nt/fts-nt.c
    154144
    155 #src/pcresearch.c
    156 
    157 #kmk_grep_SOURCES.darwin = \
    158 #       lib/strverscmp.c \
    159 #       lib/obstack.c \
    160 #       lib/getline.c
    161 #kmk_grep_SOURCES.dragonfly = \
    162 #       lib/strverscmp.c \
    163 #       lib/obstack.c \
    164 #       lib/getline.c
    165 #kmk_grep_SOURCES.freebsd = \
    166 #       lib/strverscmp.c \
    167 #       lib/obstack.c \
    168 #       lib/getline.c
    169 #kmk_grep_SOURCES.haiku = \
    170 #       lib/strverscmp.c \
    171 #       lib/obstack.c
    172 #kmk_grep_SOURCES.netbsd = \
    173 #       lib/strverscmp.c \
    174 #       lib/obstack.c \
    175 #       lib/getline.c
    176 #kmk_grep_SOURCES.openbsd = \
    177 #       lib/strverscmp.c \
    178 #       lib/obstack.c \
    179 #       lib/getline.c
    180 #kmk_grep_SOURCES.solaris = \
    181 #       lib/strverscmp.c \
    182 #       lib/obstack.c \
    183 #       lib/getline.c
    184 #kmk_grep_SOURCES.win = \
    185 #       lib/strverscmp.c \
    186 #       lib/obstack.c \
    187 #       lib/mkstemp.c \
    188 #       lib/getline.c \
    189 #       ../lib/startuphacks-win.c
    190 
    191 #kmk_grep_LIBS.win = $(LIB_KUTIL) # for stdout optimizations.
    192 
    193 MAKEFILE_GREP := $(MAKEFILE_CURRENT)
    194 
    195 include $(FILE_KBUILD_SUB_FOOTER)
    196 
    197 #
     145#TODO use:      ../lib/startuphacks-win.c
     146
     147#
     148# We generate a few files.
     149#
     150kmk_grep_DEPS = \
     151        $(kmk_grep_0_OUTDIR)/config.h \
     152        $(kmk_grep_0_OUTDIR)/configmake.h
     153kmk_grep_DEPS.win = \
     154        $(kmk_grep_0_OUTDIR)/getopt-cdefs.h \
     155        $(kmk_grep_0_OUTDIR)/getopt.h \
     156        $(kmk_grep_0_OUTDIR)/unistd.h \
     157        $(kmk_grep_0_OUTDIR)/sigsegv.h \
     158        $(kmk_grep_0_OUTDIR)/fnmatch.h
     159
     160kmk_grep_CLEAN = $(kmk_grep_DEPS)
     161kmk_grep_CLEAN.win = $(kmk_grep_DEPS.win) $(kmk_grep_LNK_DEPS.win)
     162
    198163# Use checked in config.h instead of running ./configure for it.
    199 #
    200 kmk_grep_config.h.$(KBUILD_TARGET) := $(kmk_grep_DEFPATH)/config.h.$(KBUILD_TARGET)
    201 
    202 $(kmk_grep_0_OUTDIR)/config.h: $(kmk_grep_DEFPATH)/config.$(KBUILD_TARGET).h | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     164$$(kmk_grep_0_OUTDIR)/config.h: $(PATH_SUB_CURRENT)/config.$(KBUILD_TARGET).h | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    203165        $(CP) -f -- "$^" "$@"
    204166
    205 $(kmk_grep_0_OUTDIR)/configmake.h: $(MAKEFILE_GREP) | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     167# This shouldn't be used with NLS disabled, so the paths doesn't matter I hope.
     168$$(kmk_grep_0_OUTDIR)/configmake.h: $(MAKEFILE_CURRENT) | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    206169        $(APPEND) -tn "$@" \
    207170                '#define PREFIX         "kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/"'; \
     
    234197                '#define PKGLIBEXECDIR  "kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/"';
    235198
    236 #
    237 # Stuff Windows needs.
    238 #
    239 $(kmk_grep_0_OUTDIR)/getopt-cdefs.h: $(kmk_grep_DEFPATH)/lib/getopt-cdefs.in.h \
    240                 $(MAKEFILE_GREP) | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     199# Windows needs a few more things:
     200$$(kmk_grep_0_OUTDIR)/getopt-cdefs.h: $(PATH_SUB_CURRENT)/lib/getopt-cdefs.in.h \
     201                $(MAKEFILE_CURRENT) | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    241202        $(SED) \
    242203        -e 's,@HAVE_SYS_CDEFS_H@,0,' \
     
    244205               $(qdeps sh,$@,1)
    245206
    246 $(kmk_grep_0_OUTDIR)/getopt.h: $(kmk_grep_DEFPATH)/lib/getopt.in.h \
    247                 $(MAKEFILE_GREP) | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     207$$(kmk_grep_0_OUTDIR)/getopt.h: $(PATH_SUB_CURRENT)/lib/getopt.in.h \
     208                $(MAKEFILE_CURRENT) | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    248209        $(SED) \
    249210        -e 's,@GUARD_PREFIX@,GNULIB,' \
     
    257218               $(qdeps sh,$@,1)
    258219
    259 $(kmk_grep_0_OUTDIR)/fnmatch.h: $(kmk_grep_DEFPATH)/lib/fnmatch.in.h \
    260                 $(MAKEFILE_GREP) | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     220$$(kmk_grep_0_OUTDIR)/fnmatch.h: $(PATH_SUB_CURRENT)/lib/fnmatch.in.h \
     221                $(MAKEFILE_CURRENT) | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    261222        $(SED) \
    262223        -e 's,@GUARD_PREFIX@,GNULIB,' \
     
    271232               $(qdeps sh,$@,1)
    272233
    273 $(kmk_grep_0_OUTDIR)/unistd.h: $(MAKEFILE_GREP) | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     234$$(kmk_grep_0_OUTDIR)/unistd.h: $(MAKEFILE_CURRENT) | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    274235        $(APPEND) -tn "$@" \
    275236                'extern int getpagesize(void);' \
    276237                'extern int fchdir(int);'
    277238
    278 $(kmk_grep_0_OUTDIR)/sigsegv.h: $(kmk_grep_DEFPATH)/lib/sigsegv.in.h | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     239$$(kmk_grep_0_OUTDIR)/sigsegv.h: $(PATH_SUB_CURRENT)/lib/sigsegv.in.h | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    279240        $(CP) -f -- "$^" "$@"
    280241
    281 # Not needed for VCC142:
    282 $(kmk_grep_0_OUTDIR)/inttypes.h: $(kmk_grep_DEFPATH)/lib/inttypes.in.h $(MAKEFILE_GREP) | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
    283         $(SED) \
    284         -e '/@PRAGMA_SYSTEM_HEADER@/d' \
    285         -e '/@PRAGMA_COLUMNS@/d' \
    286                 -e 's,@HAVE_INTTYPES_H@,0,' \
    287                 -e '/@INCLUDE_NEXT@/d' \
    288                 -e 's,@APPLE_UNIVERSAL_BUILD@,0,' \
    289                 -e 's,@INT64_MAX_EQ_LONG_MAX@,0/*not-on-win*/,' \
    290                 -e 's,@INT64_MAX_EQ_ULONG_MAX@,0/*not-on-win*/,' \
    291                 -e 's,@INT32_MAX_LT_INTMAX_MAX@,0,' \
    292                 -e 's,@UINT32_MAX_LT_UINTMAX_MAX@,0,' \
    293                 -e 's,@UINT64_MAX_EQ_ULONG_MAX@,1,' \
    294                 -e 's,@PRIPTR_PREFIX@,"ll" /*fixme*/,' \
    295                 -e 's,@GNULIB_IMAXABS@,0,' \
    296                 -e 's,@HAVE_DECL_IMAXABS@,0,' \
    297                 -e 's,@GNULIB_IMAXDIV@,0,' \
    298                 -e 's,@HAVE_IMAXDIV_T@,0,' \
    299                 -e 's,@HAVE_DECL_IMAXDIV@,0,' \
    300                 -e 's,@GNULIB_STRTOIMAX@,0,' \
    301                 -e 's,@REPLACE_STRTOIMAX@,0,' \
    302                 -e 's,@HAVE_DECL_STRTOIMAX@,0,' \
    303                 -e 's,@GNULIB_STRTOUMAX@,0,' \
    304                 -e 's,@REPLACE_STRTOUMAX@,0,' \
    305                 -e 's,@HAVE_DECL_STRTOUMAX@,0,' \
    306                 --output "$@" \
    307                $(qdeps sh,$@,1)
    308 
    309 $(kmk_grep_0_OUTDIR)/stdbool.h: $(MAKEFILE_GREP) | $(call DIRDEP,$(kmk_grep_0_OUTDIR))
     242if 1 # Add a manifest making UTF-8 as the active code page.
     243kmk_grep_LNK_DEPS.win = \
     244        $(kmk_grep_0_OUTDIR)/kmk_grep.manifest
     245
     246$$(kmk_grep_0_OUTDIR)/kmk_grep.manifest: $(MAKEFILE_CURRENT) | $$(call DIRDEP,$$(kmk_grep_0_OUTDIR))
    310247        $(APPEND) -tn "$@" \
    311                 '#ifndef ___STDBOOL_H___' \
    312                 '#define ___STDBOOL_H___' \
    313                 'typedef unsigned char bool;' \
    314                 '#define true  (1)' \
    315                 '#define false (0)' \
    316                 '#endif'
    317 
     248                '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' \
     249                '<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">' \
     250                '  <assemblyIdentity type="win32" name="kmk_grep.exe" version="3.7.0.0"/>' \
     251                '  <application>' \
     252                '    <windowsSettings>' \
     253                '      <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>' \
     254                '    </windowsSettings>' \
     255                '  </application>' \
     256                '</assembly>'
     257
     258# HACK ALERT! Using kmk_builting_redirect here to bypass some shell quoting
     259#             issue.  Also, no idea why we need to escape the hash (\#1).
     260kmk_grep_POST_CMDS.win = \
     261        $(REDIRECT) -- $(PATH_SDK_WINSDK10-UM_BIN)/mt.exe \
     262                -manifest "$(subst /,\\,$(kmk_grep_0_OUTDIR)/kmk_grep.manifest)" \
     263                '-outputresource:$(subst /,\\,$(out));\#1'
     264endif
     265
     266
     267include $(FILE_KBUILD_SUB_FOOTER)
     268
  • trunk/src/grep/src/grep.c

    r3536 r3537  
    443443static int stdout_errno;
    444444
    445 #if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS)
    446 # include <assert.h>
     445#ifdef KMK_GREP
     446# ifdef KBUILD_OS_WINDOWS
     447#  include <assert.h>
    447448static void fwrite_errno (void const *, size_t, size_t);
     449static int g_fStdOutIsConsole = -1; /* TRUE or FALSE; -1 if not initialize. */
    448450#endif
     451
     452/* Attempts to set the code page, leave the rest of the locale as default. */
     453static void kmk_grep_set_codepage (const char *pszCodepage)
     454{
     455# ifdef KBUILD_OS_WINDOWS
     456  /* Make sure it starts with a dot: */
     457  char szDot[256];
     458  if (pszCodepage[0] != '.')
     459    {
     460      snprintf (szDot, sizeof(szDot), ".%s", pszCodepage);
     461      pszCodepage = szDot;
     462    }
     463
     464  if (setlocale (LC_ALL, pszCodepage) == NULL)
     465    error (0, errno, _("warning: setlocale (LC_ALL, \"%s\") failed"),
     466           pszCodepage);
     467
     468  g_fStdOutIsConsole = -1; /* ensure this is reinitialized. */
     469# endif
     470}
     471#endif /* KMK_GREP */
    449472
    450473static void
     
    494517  /*
    495518   * This trick reduces the runtime of 'grep -r GNU .' in the grep source dir
    496    * from just above 11 seconds to just below 1.2 seconds.
    497    * Note! s_is_console is for keeping output to file speedy.
     519   * from just above 11 seconds to around 0.8 seconds.
     520   *
     521   * The trouble with the microsoft CRTs (both the old and the new UCRT), is
     522   * that we end up writing one char at the time when writing to the console,
     523   * which is a total performance killer. write_double_translated_ansi_nolock()
     524   * and write_requires_double_translation_nolock() in lowio/write.cpp in the
     525   * UCRT sources have further details.
    498526   */
    499   static int s_is_console = -1;
    500   if (s_is_console != -1)
     527  static HANDLE s_hStdOut = INVALID_HANDLE_VALUE;
     528  if (g_fStdOutIsConsole != -1)
    501529    { /* likely*/ }
    502530  else
    503     s_is_console = is_console (fileno (stdout));
    504   if (  s_is_console
    505       ? maybe_con_fwrite (ptr, size, nmemb, stdout) != nmemb
    506       : fwrite (ptr, size, nmemb, stdout) != nmemb)
    507 #else
     531    {
     532      DWORD fModeIgnored;
     533      s_hStdOut          = (HANDLE)_get_osfhandle (fileno (stdout));
     534      g_fStdOutIsConsole = GetConsoleMode (s_hStdOut, &fModeIgnored)
     535                         ? TRUE : FALSE;
     536      if (getenv("KMK_GREP_CONSOLE_DEBUG"))
     537        fprintf(stderr, "kmk_grep: g_fStdOutIsConsole=%d s_hStdOut=%p codepage=%u\n",
     538                g_fStdOutIsConsole, s_hStdOut, ___lc_codepage_func());
     539    }
     540  if (g_fStdOutIsConsole == TRUE && size && nmemb)
     541    {
     542      size_t const cbToWrite = size * nmemb;
     543      if (   cbToWrite < (size_t)INT_MAX / 4
     544          && cbToWrite >= size
     545          && cbToWrite >= nmemb)
     546        {
     547          /* ASSUME that one input byte won't be translated to more than one
     548             surrogate pair, or two compound UTF-16 codepoints. */
     549          wchar_t        awcBuf[1024];
     550          wchar_t       *pawcFree = NULL;
     551          wchar_t       *pawcBuf;
     552          size_t         cwcBuf = cbToWrite * 2 + 16;
     553          if (cwcBuf < sizeof(awcBuf) / sizeof(wchar_t))
     554            {
     555              cwcBuf = sizeof(awcBuf) / sizeof(wchar_t);
     556              pawcBuf = awcBuf;
     557            }
     558          else
     559              pawcFree = pawcBuf = (wchar_t *)malloc(cwcBuf * sizeof(wchar_t));
     560          if (pawcBuf)
     561            {
     562              int cwcToWrite = MultiByteToWideChar(___lc_codepage_func(),
     563                                                   0 /*dwFlags*/,
     564                                                   ptr, (int)cbToWrite,
     565                                                   pawcBuf, (int)(cwcBuf - 1));
     566              if (cwcToWrite > 0)
     567                {
     568                  pawcBuf[cwcToWrite] = '\0';
     569
     570                  /* Let the CRT do the rest.  At least the Visual C++ 2010 CRT
     571                     sources indicates _cputws will do the right thing.  */
     572                  fflush(stdout);
     573                  int rc = _cputws(pawcBuf);
     574                  if (pawcFree)
     575                    free(pawcFree);
     576                  if (rc != 0)
     577                    stdout_errno = errno;
     578                  return;
     579                }
     580              free(pawcFree);
     581            }
     582        }
     583    }
     584#endif
    508585  if (fwrite (ptr, size, nmemb, stdout) != nmemb)
    509 #endif
    510586    stdout_errno = errno;
    511587}
     
    536612  LINE_BUFFERED_OPTION,
    537613  LABEL_OPTION,
     614#ifdef KMK_GREP
     615  UTF8_OPTION,
     616  CODEPAGE_OPTION,
     617#endif
    538618  NO_IGNORE_CASE_OPTION
    539619};
     
    593673  {"with-filename", no_argument, NULL, 'H'},
    594674  {"word-regexp", no_argument, NULL, 'w'},
     675#ifdef KMK_GREP
     676  {"utf8", no_argument, NULL, UTF8_OPTION},
     677  {"cp", required_argument, NULL, CODEPAGE_OPTION},
     678  {"codepage", required_argument, NULL, CODEPAGE_OPTION},
     679#endif
    595680  {0, 0, 0, 0}
    596681};
     
    20972182  -U, --binary              do not strip CR characters at EOL (MSDOS/Windows)\n\
    20982183\n"));
     2184#ifdef KMK_GREP
     2185      printf (_("\
     2186kmk_grep extensions:\n\
     2187  --codepage=NUM            switches the locale to the given codepage, \n\
     2188                            affecting how input files are treated and outputted\n\
     2189                            windows only, ignored elsewhere\n\
     2190  --utf8                    shorthand for --codepage=UTF8\n\
     2191\n"));
     2192#endif
    20992193      printf (_("\
    21002194When FILE is '-', read standard input.  With no FILE, read '.' if\n\
     
    25412635  /* Internationalization. */
    25422636#if defined HAVE_SETLOCALE
    2543   setlocale (LC_ALL, "");
     2637# if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS)
     2638  if (getenv ("KMK_GREP_CODEPAGE"))
     2639    kmk_grep_set_codepage (getenv ("KMK_GREP_CODEPAGE"));
     2640  else
     2641# endif
     2642    setlocale (LC_ALL, "");
    25442643#endif
    25452644#if defined ENABLE_NLS
     
    28602959        break;
    28612960
     2961#ifdef KMK_GREP
     2962      /* The --utf8 and --codepage <cp> options are mainly for windows where
     2963         UCRT doesn't check any of the standard locale selecting environment
     2964         variables and we have to give it directly to setlocale if we want
     2965         any control beyond the Windows defaults.
     2966
     2967         The UCRT setlocale has a nice feature of allowing us to set just
     2968         the codepage, omitting the rest of the locale spec. */
     2969      case UTF8_OPTION:
     2970        kmk_grep_set_codepage (".UTF-8");
     2971        break;
     2972      case CODEPAGE_OPTION:
     2973        kmk_grep_set_codepage (optarg);
     2974        break;
     2975#endif
     2976
    28622977      case 0:
    28632978        /* long options */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette