diff options
Diffstat (limited to 'src/grep/src')
-rw-r--r-- | src/grep/src/Makefile.am | 70 | ||||
-rw-r--r-- | src/grep/src/Makefile.in | 2031 | ||||
-rw-r--r-- | src/grep/src/dfasearch.c | 590 | ||||
-rw-r--r-- | src/grep/src/die.h | 31 | ||||
-rw-r--r-- | src/grep/src/egrep.sh | 2 | ||||
-rw-r--r-- | src/grep/src/grep.c | 3173 | ||||
-rw-r--r-- | src/grep/src/grep.h | 34 | ||||
-rw-r--r-- | src/grep/src/kwsearch.c | 240 | ||||
-rw-r--r-- | src/grep/src/kwset.c | 929 | ||||
-rw-r--r-- | src/grep/src/kwset.h | 44 | ||||
-rw-r--r-- | src/grep/src/pcresearch.c | 352 | ||||
-rw-r--r-- | src/grep/src/search.h | 89 | ||||
-rw-r--r-- | src/grep/src/searchutils.c | 190 | ||||
-rw-r--r-- | src/grep/src/system.h | 132 |
14 files changed, 7907 insertions, 0 deletions
diff --git a/src/grep/src/Makefile.am b/src/grep/src/Makefile.am new file mode 100644 index 0000000..c2e6e9a --- /dev/null +++ b/src/grep/src/Makefile.am @@ -0,0 +1,70 @@ +## Process this file with automake to create Makefile.in +# Copyright 1997-1998, 2005-2021 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +LN = ln + +AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) $(PCRE_CFLAGS) + +# Tell the linker to omit references to unused shared libraries. +AM_LDFLAGS = $(IGNORE_UNUSED_LIBRARIES_CFLAGS) + +bin_PROGRAMS = grep +bin_SCRIPTS = egrep fgrep +grep_SOURCES = \ + dfasearch.c \ + die.h \ + grep.c \ + kwsearch.c \ + kwset.c \ + searchutils.c +if USE_PCRE +grep_SOURCES += pcresearch.c +endif + +noinst_HEADERS = grep.h kwset.h search.h system.h + +# Sometimes, the expansion of $(LIBINTL) includes -lc which may +# include modules defining variables like 'optind', so libgreputils.a +# must precede $(LIBINTL) in order to ensure we use GNU getopt. +# But libgreputils.a must also follow $(LIBINTL), since libintl uses +# replacement functions defined in libgreputils.a. +LDADD = \ + ../lib/libgreputils.a $(LIBINTL) ../lib/libgreputils.a $(LIBICONV) \ + $(LIBTHREAD) + +grep_LDADD = $(LDADD) $(PCRE_LIBS) $(LIBCSTACK) +localedir = $(datadir)/locale +AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib + +EXTRA_DIST = egrep.sh + +egrep fgrep: egrep.sh Makefile + $(AM_V_GEN)grep=`echo grep | sed -e '$(transform)'` && \ + case $@ in egrep) option=-E;; fgrep) option=-F;; esac && \ + shell_does_substrings='set x/y && d=$${1%/*} && test "$$d" = x' && \ + if $(SHELL) -c "$$shell_does_substrings" 2>/dev/null; then \ + edit_substring='s,X,X,'; \ + else \ + edit_substring='s,\$${0%/\*},`expr "X$$0" : '\''X\\(.*\\)/'\''`,g'; \ + fi && \ + sed -e 's|[@]SHELL@|$(SHELL)|g' \ + -e "$$edit_substring" \ + -e "s|[@]grep@|$$grep|g" \ + -e "s|[@]option@|$$option|g" <$(srcdir)/egrep.sh >$@-t + $(AM_V_at)chmod +x $@-t + $(AM_V_at)mv $@-t $@ + +CLEANFILES = egrep fgrep *-t diff --git a/src/grep/src/Makefile.in b/src/grep/src/Makefile.in new file mode 100644 index 0000000..668b484 --- /dev/null +++ b/src/grep/src/Makefile.in @@ -0,0 +1,2031 @@ +# Makefile.in generated by automake 1.16d from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright 1997-1998, 2005-2021 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = grep$(EXEEXT) +@USE_PCRE_TRUE@am__append_1 = pcresearch.c +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ + $(top_srcdir)/m4/__inline.m4 \ + $(top_srcdir)/m4/absolute-header.m4 $(top_srcdir)/m4/alloca.m4 \ + $(top_srcdir)/m4/arpa_inet_h.m4 \ + $(top_srcdir)/m4/asm-underscore.m4 $(top_srcdir)/m4/assert.m4 \ + $(top_srcdir)/m4/btowc.m4 $(top_srcdir)/m4/builtin-expect.m4 \ + $(top_srcdir)/m4/c-stack.m4 $(top_srcdir)/m4/calloc.m4 \ + $(top_srcdir)/m4/chdir-long.m4 $(top_srcdir)/m4/close.m4 \ + $(top_srcdir)/m4/closedir.m4 $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/configmake.m4 $(top_srcdir)/m4/ctype_h.m4 \ + $(top_srcdir)/m4/cycle-check.m4 $(top_srcdir)/m4/d-ino.m4 \ + $(top_srcdir)/m4/d-type.m4 $(top_srcdir)/m4/dirent_h.m4 \ + $(top_srcdir)/m4/dirfd.m4 \ + $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup.m4 \ + $(top_srcdir)/m4/dup2.m4 $(top_srcdir)/m4/eealloc.m4 \ + $(top_srcdir)/m4/environ.m4 $(top_srcdir)/m4/errno_h.m4 \ + $(top_srcdir)/m4/error.m4 $(top_srcdir)/m4/exponentd.m4 \ + $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fchdir.m4 \ + $(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl-safer.m4 \ + $(top_srcdir)/m4/fcntl.m4 $(top_srcdir)/m4/fcntl_h.m4 \ + $(top_srcdir)/m4/fdopen.m4 $(top_srcdir)/m4/fdopendir.m4 \ + $(top_srcdir)/m4/filenamecat.m4 $(top_srcdir)/m4/flexmember.m4 \ + $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fnmatch.m4 \ + $(top_srcdir)/m4/fnmatch_h.m4 $(top_srcdir)/m4/fopen.m4 \ + $(top_srcdir)/m4/fpending.m4 $(top_srcdir)/m4/fpieee.m4 \ + $(top_srcdir)/m4/free.m4 $(top_srcdir)/m4/fstat.m4 \ + $(top_srcdir)/m4/fstatat.m4 $(top_srcdir)/m4/ftruncate.m4 \ + $(top_srcdir)/m4/fts.m4 $(top_srcdir)/m4/getcwd.m4 \ + $(top_srcdir)/m4/getdtablesize.m4 $(top_srcdir)/m4/getopt.m4 \ + $(top_srcdir)/m4/getpagesize.m4 \ + $(top_srcdir)/m4/getprogname.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettimeofday.m4 \ + $(top_srcdir)/m4/gnulib-common.m4 \ + $(top_srcdir)/m4/gnulib-comp.m4 \ + $(top_srcdir)/m4/host-cpu-c-abi.m4 $(top_srcdir)/m4/i-ring.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/iconv_h.m4 \ + $(top_srcdir)/m4/iconv_open.m4 \ + $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/inet_pton.m4 \ + $(top_srcdir)/m4/inline.m4 \ + $(top_srcdir)/m4/intl-thread-locale.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax_t.m4 \ + $(top_srcdir)/m4/inttostr.m4 $(top_srcdir)/m4/inttypes.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/ioctl.m4 \ + $(top_srcdir)/m4/isatty.m4 $(top_srcdir)/m4/isblank.m4 \ + $(top_srcdir)/m4/iswblank.m4 $(top_srcdir)/m4/iswctype.m4 \ + $(top_srcdir)/m4/iswdigit.m4 $(top_srcdir)/m4/iswxdigit.m4 \ + $(top_srcdir)/m4/langinfo_h.m4 $(top_srcdir)/m4/largefile.m4 \ + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libsigsegv.m4 \ + $(top_srcdir)/m4/libunistring-base.m4 \ + $(top_srcdir)/m4/limits-h.m4 $(top_srcdir)/m4/localcharset.m4 \ + $(top_srcdir)/m4/locale-fr.m4 $(top_srcdir)/m4/locale-ja.m4 \ + $(top_srcdir)/m4/locale-tr.m4 $(top_srcdir)/m4/locale-zh.m4 \ + $(top_srcdir)/m4/locale_h.m4 $(top_srcdir)/m4/localeconv.m4 \ + $(top_srcdir)/m4/localename.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/lseek.m4 $(top_srcdir)/m4/lstat.m4 \ + $(top_srcdir)/m4/malloc.m4 $(top_srcdir)/m4/malloca.m4 \ + $(top_srcdir)/m4/manywarnings.m4 $(top_srcdir)/m4/mbchar.m4 \ + $(top_srcdir)/m4/mbiter.m4 $(top_srcdir)/m4/mbrlen.m4 \ + $(top_srcdir)/m4/mbrtowc.m4 $(top_srcdir)/m4/mbsinit.m4 \ + $(top_srcdir)/m4/mbslen.m4 $(top_srcdir)/m4/mbsrtowcs.m4 \ + $(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/mbtowc.m4 \ + $(top_srcdir)/m4/memchr.m4 $(top_srcdir)/m4/mempcpy.m4 \ + $(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/minmax.m4 \ + $(top_srcdir)/m4/mmap-anon.m4 $(top_srcdir)/m4/mode_t.m4 \ + $(top_srcdir)/m4/msvc-inval.m4 \ + $(top_srcdir)/m4/msvc-nothrow.m4 $(top_srcdir)/m4/multiarch.m4 \ + $(top_srcdir)/m4/musl.m4 $(top_srcdir)/m4/nanosleep.m4 \ + $(top_srcdir)/m4/netinet_in_h.m4 \ + $(top_srcdir)/m4/nl_langinfo.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/nocrash.m4 $(top_srcdir)/m4/obstack.m4 \ + $(top_srcdir)/m4/off_t.m4 $(top_srcdir)/m4/open-cloexec.m4 \ + $(top_srcdir)/m4/open-slash.m4 $(top_srcdir)/m4/open.m4 \ + $(top_srcdir)/m4/openat.m4 $(top_srcdir)/m4/opendir.m4 \ + $(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/pcre.m4 \ + $(top_srcdir)/m4/perl.m4 $(top_srcdir)/m4/perror.m4 \ + $(top_srcdir)/m4/pipe.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf.m4 \ + $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/pthread-thread.m4 \ + $(top_srcdir)/m4/pthread_h.m4 \ + $(top_srcdir)/m4/pthread_rwlock_rdlock.m4 \ + $(top_srcdir)/m4/pthread_sigmask.m4 $(top_srcdir)/m4/putenv.m4 \ + $(top_srcdir)/m4/quote.m4 $(top_srcdir)/m4/quotearg.m4 \ + $(top_srcdir)/m4/raise.m4 $(top_srcdir)/m4/rawmemchr.m4 \ + $(top_srcdir)/m4/read.m4 $(top_srcdir)/m4/readdir.m4 \ + $(top_srcdir)/m4/realloc.m4 $(top_srcdir)/m4/reallocarray.m4 \ + $(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/safe-read.m4 \ + $(top_srcdir)/m4/save-cwd.m4 $(top_srcdir)/m4/sched_h.m4 \ + $(top_srcdir)/m4/select.m4 $(top_srcdir)/m4/setenv.m4 \ + $(top_srcdir)/m4/setlocale.m4 \ + $(top_srcdir)/m4/setlocale_null.m4 \ + $(top_srcdir)/m4/sigaction.m4 $(top_srcdir)/m4/sigaltstack.m4 \ + $(top_srcdir)/m4/signal_h.m4 \ + $(top_srcdir)/m4/signalblocking.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/sleep.m4 \ + $(top_srcdir)/m4/snprintf.m4 $(top_srcdir)/m4/socketlib.m4 \ + $(top_srcdir)/m4/sockets.m4 $(top_srcdir)/m4/socklen.m4 \ + $(top_srcdir)/m4/sockpfaf.m4 $(top_srcdir)/m4/ssize_t.m4 \ + $(top_srcdir)/m4/stack-direction.m4 \ + $(top_srcdir)/m4/stat-time.m4 $(top_srcdir)/m4/stat.m4 \ + $(top_srcdir)/m4/stdalign.m4 $(top_srcdir)/m4/stdarg.m4 \ + $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \ + $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \ + $(top_srcdir)/m4/stpcpy.m4 $(top_srcdir)/m4/strdup.m4 \ + $(top_srcdir)/m4/strerror.m4 $(top_srcdir)/m4/strerror_r.m4 \ + $(top_srcdir)/m4/string_h.m4 $(top_srcdir)/m4/strnlen.m4 \ + $(top_srcdir)/m4/strstr.m4 $(top_srcdir)/m4/strtoimax.m4 \ + $(top_srcdir)/m4/strtoll.m4 $(top_srcdir)/m4/strtoull.m4 \ + $(top_srcdir)/m4/strtoumax.m4 $(top_srcdir)/m4/symlink.m4 \ + $(top_srcdir)/m4/sys_ioctl_h.m4 \ + $(top_srcdir)/m4/sys_select_h.m4 \ + $(top_srcdir)/m4/sys_socket_h.m4 \ + $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/sys_time_h.m4 \ + $(top_srcdir)/m4/sys_types_h.m4 $(top_srcdir)/m4/sys_uio_h.m4 \ + $(top_srcdir)/m4/thread.m4 $(top_srcdir)/m4/threadlib.m4 \ + $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/unistd-safer.m4 \ + $(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/unlocked-io.m4 \ + $(top_srcdir)/m4/vasnprintf.m4 $(top_srcdir)/m4/version-etc.m4 \ + $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/warn-on-use.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/m4/wchar_h.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wcrtomb.m4 \ + $(top_srcdir)/m4/wctob.m4 $(top_srcdir)/m4/wctomb.m4 \ + $(top_srcdir)/m4/wctype_h.m4 $(top_srcdir)/m4/wcwidth.m4 \ + $(top_srcdir)/m4/windows-stat-inodes.m4 \ + $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/wmemchr.m4 \ + $(top_srcdir)/m4/wmempcpy.m4 $(top_srcdir)/m4/xalloc.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/m4/xstrtol.m4 \ + $(top_srcdir)/m4/year2038.m4 $(top_srcdir)/m4/zzgnulib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__grep_SOURCES_DIST = dfasearch.c die.h grep.c kwsearch.c kwset.c \ + searchutils.c pcresearch.c +@USE_PCRE_TRUE@am__objects_1 = pcresearch.$(OBJEXT) +am_grep_OBJECTS = dfasearch.$(OBJEXT) grep.$(OBJEXT) \ + kwsearch.$(OBJEXT) kwset.$(OBJEXT) searchutils.$(OBJEXT) \ + $(am__objects_1) +grep_OBJECTS = $(am_grep_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = ../lib/libgreputils.a $(am__DEPENDENCIES_1) \ + ../lib/libgreputils.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +grep_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/dfasearch.Po ./$(DEPDIR)/grep.Po \ + ./$(DEPDIR)/kwsearch.Po ./$(DEPDIR)/kwset.Po \ + ./$(DEPDIR)/pcresearch.Po ./$(DEPDIR)/searchutils.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(grep_SOURCES) +DIST_SOURCES = $(am__grep_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +pkglibexecdir = @pkglibexecdir@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +COLORIZE_SOURCE = @COLORIZE_SOURCE@ +CONFIG_INCLUDE = @CONFIG_INCLUDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FLOAT_H = @FLOAT_H@ +FNMATCH_H = @FNMATCH_H@ +GETOPT_CDEFS_H = @GETOPT_CDEFS_H@ +GETOPT_H = @GETOPT_H@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GL_CFLAG_ALLOW_WARNINGS = @GL_CFLAG_ALLOW_WARNINGS@ +GL_CXXFLAG_ALLOW_WARNINGS = @GL_CXXFLAG_ALLOW_WARNINGS@ +GL_GNULIB_ACCEPT = @GL_GNULIB_ACCEPT@ +GL_GNULIB_ACCEPT4 = @GL_GNULIB_ACCEPT4@ +GL_GNULIB_ACCESS = @GL_GNULIB_ACCESS@ +GL_GNULIB_ALIGNED_ALLOC = @GL_GNULIB_ALIGNED_ALLOC@ +GL_GNULIB_ALPHASORT = @GL_GNULIB_ALPHASORT@ +GL_GNULIB_ATOLL = @GL_GNULIB_ATOLL@ +GL_GNULIB_BIND = @GL_GNULIB_BIND@ +GL_GNULIB_BTOWC = @GL_GNULIB_BTOWC@ +GL_GNULIB_CALLOC_POSIX = @GL_GNULIB_CALLOC_POSIX@ +GL_GNULIB_CANONICALIZE_FILE_NAME = @GL_GNULIB_CANONICALIZE_FILE_NAME@ +GL_GNULIB_CHDIR = @GL_GNULIB_CHDIR@ +GL_GNULIB_CHOWN = @GL_GNULIB_CHOWN@ +GL_GNULIB_CLOSE = @GL_GNULIB_CLOSE@ +GL_GNULIB_CLOSEDIR = @GL_GNULIB_CLOSEDIR@ +GL_GNULIB_CONNECT = @GL_GNULIB_CONNECT@ +GL_GNULIB_COPY_FILE_RANGE = @GL_GNULIB_COPY_FILE_RANGE@ +GL_GNULIB_CREAT = @GL_GNULIB_CREAT@ +GL_GNULIB_CTIME = @GL_GNULIB_CTIME@ +GL_GNULIB_DIRFD = @GL_GNULIB_DIRFD@ +GL_GNULIB_DPRINTF = @GL_GNULIB_DPRINTF@ +GL_GNULIB_DUP = @GL_GNULIB_DUP@ +GL_GNULIB_DUP2 = @GL_GNULIB_DUP2@ +GL_GNULIB_DUP3 = @GL_GNULIB_DUP3@ +GL_GNULIB_DUPLOCALE = @GL_GNULIB_DUPLOCALE@ +GL_GNULIB_ENVIRON = @GL_GNULIB_ENVIRON@ +GL_GNULIB_EUIDACCESS = @GL_GNULIB_EUIDACCESS@ +GL_GNULIB_EXECL = @GL_GNULIB_EXECL@ +GL_GNULIB_EXECLE = @GL_GNULIB_EXECLE@ +GL_GNULIB_EXECLP = @GL_GNULIB_EXECLP@ +GL_GNULIB_EXECV = @GL_GNULIB_EXECV@ +GL_GNULIB_EXECVE = @GL_GNULIB_EXECVE@ +GL_GNULIB_EXECVP = @GL_GNULIB_EXECVP@ +GL_GNULIB_EXECVPE = @GL_GNULIB_EXECVPE@ +GL_GNULIB_EXPLICIT_BZERO = @GL_GNULIB_EXPLICIT_BZERO@ +GL_GNULIB_FACCESSAT = @GL_GNULIB_FACCESSAT@ +GL_GNULIB_FCHDIR = @GL_GNULIB_FCHDIR@ +GL_GNULIB_FCHMODAT = @GL_GNULIB_FCHMODAT@ +GL_GNULIB_FCHOWNAT = @GL_GNULIB_FCHOWNAT@ +GL_GNULIB_FCLOSE = @GL_GNULIB_FCLOSE@ +GL_GNULIB_FCNTL = @GL_GNULIB_FCNTL@ +GL_GNULIB_FDATASYNC = @GL_GNULIB_FDATASYNC@ +GL_GNULIB_FDOPEN = @GL_GNULIB_FDOPEN@ +GL_GNULIB_FDOPENDIR = @GL_GNULIB_FDOPENDIR@ +GL_GNULIB_FFLUSH = @GL_GNULIB_FFLUSH@ +GL_GNULIB_FFSL = @GL_GNULIB_FFSL@ +GL_GNULIB_FFSLL = @GL_GNULIB_FFSLL@ +GL_GNULIB_FGETC = @GL_GNULIB_FGETC@ +GL_GNULIB_FGETS = @GL_GNULIB_FGETS@ +GL_GNULIB_FNMATCH = @GL_GNULIB_FNMATCH@ +GL_GNULIB_FOPEN = @GL_GNULIB_FOPEN@ +GL_GNULIB_FPRINTF = @GL_GNULIB_FPRINTF@ +GL_GNULIB_FPRINTF_POSIX = @GL_GNULIB_FPRINTF_POSIX@ +GL_GNULIB_FPURGE = @GL_GNULIB_FPURGE@ +GL_GNULIB_FPUTC = @GL_GNULIB_FPUTC@ +GL_GNULIB_FPUTS = @GL_GNULIB_FPUTS@ +GL_GNULIB_FREAD = @GL_GNULIB_FREAD@ +GL_GNULIB_FREE_POSIX = @GL_GNULIB_FREE_POSIX@ +GL_GNULIB_FREOPEN = @GL_GNULIB_FREOPEN@ +GL_GNULIB_FSCANF = @GL_GNULIB_FSCANF@ +GL_GNULIB_FSEEK = @GL_GNULIB_FSEEK@ +GL_GNULIB_FSEEKO = @GL_GNULIB_FSEEKO@ +GL_GNULIB_FSTAT = @GL_GNULIB_FSTAT@ +GL_GNULIB_FSTATAT = @GL_GNULIB_FSTATAT@ +GL_GNULIB_FSYNC = @GL_GNULIB_FSYNC@ +GL_GNULIB_FTELL = @GL_GNULIB_FTELL@ +GL_GNULIB_FTELLO = @GL_GNULIB_FTELLO@ +GL_GNULIB_FTRUNCATE = @GL_GNULIB_FTRUNCATE@ +GL_GNULIB_FUTIMENS = @GL_GNULIB_FUTIMENS@ +GL_GNULIB_FWRITE = @GL_GNULIB_FWRITE@ +GL_GNULIB_GETC = @GL_GNULIB_GETC@ +GL_GNULIB_GETCHAR = @GL_GNULIB_GETCHAR@ +GL_GNULIB_GETCWD = @GL_GNULIB_GETCWD@ +GL_GNULIB_GETDELIM = @GL_GNULIB_GETDELIM@ +GL_GNULIB_GETDOMAINNAME = @GL_GNULIB_GETDOMAINNAME@ +GL_GNULIB_GETDTABLESIZE = @GL_GNULIB_GETDTABLESIZE@ +GL_GNULIB_GETENTROPY = @GL_GNULIB_GETENTROPY@ +GL_GNULIB_GETGROUPS = @GL_GNULIB_GETGROUPS@ +GL_GNULIB_GETHOSTNAME = @GL_GNULIB_GETHOSTNAME@ +GL_GNULIB_GETLINE = @GL_GNULIB_GETLINE@ +GL_GNULIB_GETLOADAVG = @GL_GNULIB_GETLOADAVG@ +GL_GNULIB_GETLOGIN = @GL_GNULIB_GETLOGIN@ +GL_GNULIB_GETLOGIN_R = @GL_GNULIB_GETLOGIN_R@ +GL_GNULIB_GETOPT_POSIX = @GL_GNULIB_GETOPT_POSIX@ +GL_GNULIB_GETPAGESIZE = @GL_GNULIB_GETPAGESIZE@ +GL_GNULIB_GETPASS = @GL_GNULIB_GETPASS@ +GL_GNULIB_GETPEERNAME = @GL_GNULIB_GETPEERNAME@ +GL_GNULIB_GETSOCKNAME = @GL_GNULIB_GETSOCKNAME@ +GL_GNULIB_GETSOCKOPT = @GL_GNULIB_GETSOCKOPT@ +GL_GNULIB_GETSUBOPT = @GL_GNULIB_GETSUBOPT@ +GL_GNULIB_GETTIMEOFDAY = @GL_GNULIB_GETTIMEOFDAY@ +GL_GNULIB_GETUMASK = @GL_GNULIB_GETUMASK@ +GL_GNULIB_GETUSERSHELL = @GL_GNULIB_GETUSERSHELL@ +GL_GNULIB_GRANTPT = @GL_GNULIB_GRANTPT@ +GL_GNULIB_GROUP_MEMBER = @GL_GNULIB_GROUP_MEMBER@ +GL_GNULIB_ICONV = @GL_GNULIB_ICONV@ +GL_GNULIB_IMAXABS = @GL_GNULIB_IMAXABS@ +GL_GNULIB_IMAXDIV = @GL_GNULIB_IMAXDIV@ +GL_GNULIB_INET_NTOP = @GL_GNULIB_INET_NTOP@ +GL_GNULIB_INET_PTON = @GL_GNULIB_INET_PTON@ +GL_GNULIB_IOCTL = @GL_GNULIB_IOCTL@ +GL_GNULIB_ISATTY = @GL_GNULIB_ISATTY@ +GL_GNULIB_ISBLANK = @GL_GNULIB_ISBLANK@ +GL_GNULIB_ISWBLANK = @GL_GNULIB_ISWBLANK@ +GL_GNULIB_ISWCTYPE = @GL_GNULIB_ISWCTYPE@ +GL_GNULIB_ISWDIGIT = @GL_GNULIB_ISWDIGIT@ +GL_GNULIB_ISWXDIGIT = @GL_GNULIB_ISWXDIGIT@ +GL_GNULIB_LCHMOD = @GL_GNULIB_LCHMOD@ +GL_GNULIB_LCHOWN = @GL_GNULIB_LCHOWN@ +GL_GNULIB_LINK = @GL_GNULIB_LINK@ +GL_GNULIB_LINKAT = @GL_GNULIB_LINKAT@ +GL_GNULIB_LISTEN = @GL_GNULIB_LISTEN@ +GL_GNULIB_LOCALECONV = @GL_GNULIB_LOCALECONV@ +GL_GNULIB_LOCALENAME = @GL_GNULIB_LOCALENAME@ +GL_GNULIB_LOCALTIME = @GL_GNULIB_LOCALTIME@ +GL_GNULIB_LSEEK = @GL_GNULIB_LSEEK@ +GL_GNULIB_LSTAT = @GL_GNULIB_LSTAT@ +GL_GNULIB_MALLOC_POSIX = @GL_GNULIB_MALLOC_POSIX@ +GL_GNULIB_MBRLEN = @GL_GNULIB_MBRLEN@ +GL_GNULIB_MBRTOWC = @GL_GNULIB_MBRTOWC@ +GL_GNULIB_MBSCASECMP = @GL_GNULIB_MBSCASECMP@ +GL_GNULIB_MBSCASESTR = @GL_GNULIB_MBSCASESTR@ +GL_GNULIB_MBSCHR = @GL_GNULIB_MBSCHR@ +GL_GNULIB_MBSCSPN = @GL_GNULIB_MBSCSPN@ +GL_GNULIB_MBSINIT = @GL_GNULIB_MBSINIT@ +GL_GNULIB_MBSLEN = @GL_GNULIB_MBSLEN@ +GL_GNULIB_MBSNCASECMP = @GL_GNULIB_MBSNCASECMP@ +GL_GNULIB_MBSNLEN = @GL_GNULIB_MBSNLEN@ +GL_GNULIB_MBSNRTOWCS = @GL_GNULIB_MBSNRTOWCS@ +GL_GNULIB_MBSPBRK = @GL_GNULIB_MBSPBRK@ +GL_GNULIB_MBSPCASECMP = @GL_GNULIB_MBSPCASECMP@ +GL_GNULIB_MBSRCHR = @GL_GNULIB_MBSRCHR@ +GL_GNULIB_MBSRTOWCS = @GL_GNULIB_MBSRTOWCS@ +GL_GNULIB_MBSSEP = @GL_GNULIB_MBSSEP@ +GL_GNULIB_MBSSPN = @GL_GNULIB_MBSSPN@ +GL_GNULIB_MBSSTR = @GL_GNULIB_MBSSTR@ +GL_GNULIB_MBSTOK_R = @GL_GNULIB_MBSTOK_R@ +GL_GNULIB_MBTOWC = @GL_GNULIB_MBTOWC@ +GL_GNULIB_MDA_ACCESS = @GL_GNULIB_MDA_ACCESS@ +GL_GNULIB_MDA_CHDIR = @GL_GNULIB_MDA_CHDIR@ +GL_GNULIB_MDA_CHMOD = @GL_GNULIB_MDA_CHMOD@ +GL_GNULIB_MDA_CLOSE = @GL_GNULIB_MDA_CLOSE@ +GL_GNULIB_MDA_CREAT = @GL_GNULIB_MDA_CREAT@ +GL_GNULIB_MDA_DUP = @GL_GNULIB_MDA_DUP@ +GL_GNULIB_MDA_DUP2 = @GL_GNULIB_MDA_DUP2@ +GL_GNULIB_MDA_ECVT = @GL_GNULIB_MDA_ECVT@ +GL_GNULIB_MDA_EXECL = @GL_GNULIB_MDA_EXECL@ +GL_GNULIB_MDA_EXECLE = @GL_GNULIB_MDA_EXECLE@ +GL_GNULIB_MDA_EXECLP = @GL_GNULIB_MDA_EXECLP@ +GL_GNULIB_MDA_EXECV = @GL_GNULIB_MDA_EXECV@ +GL_GNULIB_MDA_EXECVE = @GL_GNULIB_MDA_EXECVE@ +GL_GNULIB_MDA_EXECVP = @GL_GNULIB_MDA_EXECVP@ +GL_GNULIB_MDA_EXECVPE = @GL_GNULIB_MDA_EXECVPE@ +GL_GNULIB_MDA_FCLOSEALL = @GL_GNULIB_MDA_FCLOSEALL@ +GL_GNULIB_MDA_FCVT = @GL_GNULIB_MDA_FCVT@ +GL_GNULIB_MDA_FDOPEN = @GL_GNULIB_MDA_FDOPEN@ +GL_GNULIB_MDA_FILENO = @GL_GNULIB_MDA_FILENO@ +GL_GNULIB_MDA_GCVT = @GL_GNULIB_MDA_GCVT@ +GL_GNULIB_MDA_GETCWD = @GL_GNULIB_MDA_GETCWD@ +GL_GNULIB_MDA_GETPID = @GL_GNULIB_MDA_GETPID@ +GL_GNULIB_MDA_GETW = @GL_GNULIB_MDA_GETW@ +GL_GNULIB_MDA_ISATTY = @GL_GNULIB_MDA_ISATTY@ +GL_GNULIB_MDA_LSEEK = @GL_GNULIB_MDA_LSEEK@ +GL_GNULIB_MDA_MEMCCPY = @GL_GNULIB_MDA_MEMCCPY@ +GL_GNULIB_MDA_MKDIR = @GL_GNULIB_MDA_MKDIR@ +GL_GNULIB_MDA_MKTEMP = @GL_GNULIB_MDA_MKTEMP@ +GL_GNULIB_MDA_OPEN = @GL_GNULIB_MDA_OPEN@ +GL_GNULIB_MDA_PUTENV = @GL_GNULIB_MDA_PUTENV@ +GL_GNULIB_MDA_PUTW = @GL_GNULIB_MDA_PUTW@ +GL_GNULIB_MDA_READ = @GL_GNULIB_MDA_READ@ +GL_GNULIB_MDA_RMDIR = @GL_GNULIB_MDA_RMDIR@ +GL_GNULIB_MDA_STRDUP = @GL_GNULIB_MDA_STRDUP@ +GL_GNULIB_MDA_SWAB = @GL_GNULIB_MDA_SWAB@ +GL_GNULIB_MDA_TEMPNAM = @GL_GNULIB_MDA_TEMPNAM@ +GL_GNULIB_MDA_TZSET = @GL_GNULIB_MDA_TZSET@ +GL_GNULIB_MDA_UMASK = @GL_GNULIB_MDA_UMASK@ +GL_GNULIB_MDA_UNLINK = @GL_GNULIB_MDA_UNLINK@ +GL_GNULIB_MDA_WCSDUP = @GL_GNULIB_MDA_WCSDUP@ +GL_GNULIB_MDA_WRITE = @GL_GNULIB_MDA_WRITE@ +GL_GNULIB_MEMCHR = @GL_GNULIB_MEMCHR@ +GL_GNULIB_MEMMEM = @GL_GNULIB_MEMMEM@ +GL_GNULIB_MEMPCPY = @GL_GNULIB_MEMPCPY@ +GL_GNULIB_MEMRCHR = @GL_GNULIB_MEMRCHR@ +GL_GNULIB_MKDIR = @GL_GNULIB_MKDIR@ +GL_GNULIB_MKDIRAT = @GL_GNULIB_MKDIRAT@ +GL_GNULIB_MKDTEMP = @GL_GNULIB_MKDTEMP@ +GL_GNULIB_MKFIFO = @GL_GNULIB_MKFIFO@ +GL_GNULIB_MKFIFOAT = @GL_GNULIB_MKFIFOAT@ +GL_GNULIB_MKNOD = @GL_GNULIB_MKNOD@ +GL_GNULIB_MKNODAT = @GL_GNULIB_MKNODAT@ +GL_GNULIB_MKOSTEMP = @GL_GNULIB_MKOSTEMP@ +GL_GNULIB_MKOSTEMPS = @GL_GNULIB_MKOSTEMPS@ +GL_GNULIB_MKSTEMP = @GL_GNULIB_MKSTEMP@ +GL_GNULIB_MKSTEMPS = @GL_GNULIB_MKSTEMPS@ +GL_GNULIB_MKTIME = @GL_GNULIB_MKTIME@ +GL_GNULIB_NANOSLEEP = @GL_GNULIB_NANOSLEEP@ +GL_GNULIB_NL_LANGINFO = @GL_GNULIB_NL_LANGINFO@ +GL_GNULIB_NONBLOCKING = @GL_GNULIB_NONBLOCKING@ +GL_GNULIB_OBSTACK_PRINTF = @GL_GNULIB_OBSTACK_PRINTF@ +GL_GNULIB_OBSTACK_PRINTF_POSIX = @GL_GNULIB_OBSTACK_PRINTF_POSIX@ +GL_GNULIB_OPEN = @GL_GNULIB_OPEN@ +GL_GNULIB_OPENAT = @GL_GNULIB_OPENAT@ +GL_GNULIB_OPENDIR = @GL_GNULIB_OPENDIR@ +GL_GNULIB_OVERRIDES_STRUCT_STAT = @GL_GNULIB_OVERRIDES_STRUCT_STAT@ +GL_GNULIB_PCLOSE = @GL_GNULIB_PCLOSE@ +GL_GNULIB_PERROR = @GL_GNULIB_PERROR@ +GL_GNULIB_PIPE = @GL_GNULIB_PIPE@ +GL_GNULIB_PIPE2 = @GL_GNULIB_PIPE2@ +GL_GNULIB_POPEN = @GL_GNULIB_POPEN@ +GL_GNULIB_POSIX_MEMALIGN = @GL_GNULIB_POSIX_MEMALIGN@ +GL_GNULIB_POSIX_OPENPT = @GL_GNULIB_POSIX_OPENPT@ +GL_GNULIB_PREAD = @GL_GNULIB_PREAD@ +GL_GNULIB_PRINTF = @GL_GNULIB_PRINTF@ +GL_GNULIB_PRINTF_POSIX = @GL_GNULIB_PRINTF_POSIX@ +GL_GNULIB_PSELECT = @GL_GNULIB_PSELECT@ +GL_GNULIB_PTHREAD_COND = @GL_GNULIB_PTHREAD_COND@ +GL_GNULIB_PTHREAD_MUTEX = @GL_GNULIB_PTHREAD_MUTEX@ +GL_GNULIB_PTHREAD_MUTEX_TIMEDLOCK = @GL_GNULIB_PTHREAD_MUTEX_TIMEDLOCK@ +GL_GNULIB_PTHREAD_ONCE = @GL_GNULIB_PTHREAD_ONCE@ +GL_GNULIB_PTHREAD_RWLOCK = @GL_GNULIB_PTHREAD_RWLOCK@ +GL_GNULIB_PTHREAD_SIGMASK = @GL_GNULIB_PTHREAD_SIGMASK@ +GL_GNULIB_PTHREAD_SPIN = @GL_GNULIB_PTHREAD_SPIN@ +GL_GNULIB_PTHREAD_THREAD = @GL_GNULIB_PTHREAD_THREAD@ +GL_GNULIB_PTHREAD_TSS = @GL_GNULIB_PTHREAD_TSS@ +GL_GNULIB_PTSNAME = @GL_GNULIB_PTSNAME@ +GL_GNULIB_PTSNAME_R = @GL_GNULIB_PTSNAME_R@ +GL_GNULIB_PUTC = @GL_GNULIB_PUTC@ +GL_GNULIB_PUTCHAR = @GL_GNULIB_PUTCHAR@ +GL_GNULIB_PUTENV = @GL_GNULIB_PUTENV@ +GL_GNULIB_PUTS = @GL_GNULIB_PUTS@ +GL_GNULIB_PWRITE = @GL_GNULIB_PWRITE@ +GL_GNULIB_QSORT_R = @GL_GNULIB_QSORT_R@ +GL_GNULIB_RAISE = @GL_GNULIB_RAISE@ +GL_GNULIB_RANDOM = @GL_GNULIB_RANDOM@ +GL_GNULIB_RANDOM_R = @GL_GNULIB_RANDOM_R@ +GL_GNULIB_RAWMEMCHR = @GL_GNULIB_RAWMEMCHR@ +GL_GNULIB_READ = @GL_GNULIB_READ@ +GL_GNULIB_READDIR = @GL_GNULIB_READDIR@ +GL_GNULIB_READLINK = @GL_GNULIB_READLINK@ +GL_GNULIB_READLINKAT = @GL_GNULIB_READLINKAT@ +GL_GNULIB_REALLOCARRAY = @GL_GNULIB_REALLOCARRAY@ +GL_GNULIB_REALLOC_POSIX = @GL_GNULIB_REALLOC_POSIX@ +GL_GNULIB_REALPATH = @GL_GNULIB_REALPATH@ +GL_GNULIB_RECV = @GL_GNULIB_RECV@ +GL_GNULIB_RECVFROM = @GL_GNULIB_RECVFROM@ +GL_GNULIB_REMOVE = @GL_GNULIB_REMOVE@ +GL_GNULIB_RENAME = @GL_GNULIB_RENAME@ +GL_GNULIB_RENAMEAT = @GL_GNULIB_RENAMEAT@ +GL_GNULIB_REWINDDIR = @GL_GNULIB_REWINDDIR@ +GL_GNULIB_RMDIR = @GL_GNULIB_RMDIR@ +GL_GNULIB_RPMATCH = @GL_GNULIB_RPMATCH@ +GL_GNULIB_SCANDIR = @GL_GNULIB_SCANDIR@ +GL_GNULIB_SCANF = @GL_GNULIB_SCANF@ +GL_GNULIB_SCHED_YIELD = @GL_GNULIB_SCHED_YIELD@ +GL_GNULIB_SECURE_GETENV = @GL_GNULIB_SECURE_GETENV@ +GL_GNULIB_SELECT = @GL_GNULIB_SELECT@ +GL_GNULIB_SEND = @GL_GNULIB_SEND@ +GL_GNULIB_SENDTO = @GL_GNULIB_SENDTO@ +GL_GNULIB_SETENV = @GL_GNULIB_SETENV@ +GL_GNULIB_SETHOSTNAME = @GL_GNULIB_SETHOSTNAME@ +GL_GNULIB_SETLOCALE = @GL_GNULIB_SETLOCALE@ +GL_GNULIB_SETLOCALE_NULL = @GL_GNULIB_SETLOCALE_NULL@ +GL_GNULIB_SETSOCKOPT = @GL_GNULIB_SETSOCKOPT@ +GL_GNULIB_SHUTDOWN = @GL_GNULIB_SHUTDOWN@ +GL_GNULIB_SIGABBREV_NP = @GL_GNULIB_SIGABBREV_NP@ +GL_GNULIB_SIGACTION = @GL_GNULIB_SIGACTION@ +GL_GNULIB_SIGDESCR_NP = @GL_GNULIB_SIGDESCR_NP@ +GL_GNULIB_SIGNAL_H_SIGPIPE = @GL_GNULIB_SIGNAL_H_SIGPIPE@ +GL_GNULIB_SIGPROCMASK = @GL_GNULIB_SIGPROCMASK@ +GL_GNULIB_SLEEP = @GL_GNULIB_SLEEP@ +GL_GNULIB_SNPRINTF = @GL_GNULIB_SNPRINTF@ +GL_GNULIB_SOCKET = @GL_GNULIB_SOCKET@ +GL_GNULIB_SPRINTF_POSIX = @GL_GNULIB_SPRINTF_POSIX@ +GL_GNULIB_STAT = @GL_GNULIB_STAT@ +GL_GNULIB_STDIO_H_NONBLOCKING = @GL_GNULIB_STDIO_H_NONBLOCKING@ +GL_GNULIB_STDIO_H_SIGPIPE = @GL_GNULIB_STDIO_H_SIGPIPE@ +GL_GNULIB_STPCPY = @GL_GNULIB_STPCPY@ +GL_GNULIB_STPNCPY = @GL_GNULIB_STPNCPY@ +GL_GNULIB_STRCASESTR = @GL_GNULIB_STRCASESTR@ +GL_GNULIB_STRCHRNUL = @GL_GNULIB_STRCHRNUL@ +GL_GNULIB_STRDUP = @GL_GNULIB_STRDUP@ +GL_GNULIB_STRERROR = @GL_GNULIB_STRERROR@ +GL_GNULIB_STRERRORNAME_NP = @GL_GNULIB_STRERRORNAME_NP@ +GL_GNULIB_STRERROR_R = @GL_GNULIB_STRERROR_R@ +GL_GNULIB_STRFTIME = @GL_GNULIB_STRFTIME@ +GL_GNULIB_STRNCAT = @GL_GNULIB_STRNCAT@ +GL_GNULIB_STRNDUP = @GL_GNULIB_STRNDUP@ +GL_GNULIB_STRNLEN = @GL_GNULIB_STRNLEN@ +GL_GNULIB_STRPBRK = @GL_GNULIB_STRPBRK@ +GL_GNULIB_STRPTIME = @GL_GNULIB_STRPTIME@ +GL_GNULIB_STRSEP = @GL_GNULIB_STRSEP@ +GL_GNULIB_STRSIGNAL = @GL_GNULIB_STRSIGNAL@ +GL_GNULIB_STRSTR = @GL_GNULIB_STRSTR@ +GL_GNULIB_STRTOD = @GL_GNULIB_STRTOD@ +GL_GNULIB_STRTOIMAX = @GL_GNULIB_STRTOIMAX@ +GL_GNULIB_STRTOK_R = @GL_GNULIB_STRTOK_R@ +GL_GNULIB_STRTOL = @GL_GNULIB_STRTOL@ +GL_GNULIB_STRTOLD = @GL_GNULIB_STRTOLD@ +GL_GNULIB_STRTOLL = @GL_GNULIB_STRTOLL@ +GL_GNULIB_STRTOUL = @GL_GNULIB_STRTOUL@ +GL_GNULIB_STRTOULL = @GL_GNULIB_STRTOULL@ +GL_GNULIB_STRTOUMAX = @GL_GNULIB_STRTOUMAX@ +GL_GNULIB_STRVERSCMP = @GL_GNULIB_STRVERSCMP@ +GL_GNULIB_SYMLINK = @GL_GNULIB_SYMLINK@ +GL_GNULIB_SYMLINKAT = @GL_GNULIB_SYMLINKAT@ +GL_GNULIB_SYSTEM_POSIX = @GL_GNULIB_SYSTEM_POSIX@ +GL_GNULIB_TIMEGM = @GL_GNULIB_TIMEGM@ +GL_GNULIB_TIMESPEC_GET = @GL_GNULIB_TIMESPEC_GET@ +GL_GNULIB_TIME_R = @GL_GNULIB_TIME_R@ +GL_GNULIB_TIME_RZ = @GL_GNULIB_TIME_RZ@ +GL_GNULIB_TMPFILE = @GL_GNULIB_TMPFILE@ +GL_GNULIB_TOWCTRANS = @GL_GNULIB_TOWCTRANS@ +GL_GNULIB_TRUNCATE = @GL_GNULIB_TRUNCATE@ +GL_GNULIB_TTYNAME_R = @GL_GNULIB_TTYNAME_R@ +GL_GNULIB_TZSET = @GL_GNULIB_TZSET@ +GL_GNULIB_UNISTD_H_GETOPT = @GL_GNULIB_UNISTD_H_GETOPT@ +GL_GNULIB_UNISTD_H_NONBLOCKING = @GL_GNULIB_UNISTD_H_NONBLOCKING@ +GL_GNULIB_UNISTD_H_SIGPIPE = @GL_GNULIB_UNISTD_H_SIGPIPE@ +GL_GNULIB_UNLINK = @GL_GNULIB_UNLINK@ +GL_GNULIB_UNLINKAT = @GL_GNULIB_UNLINKAT@ +GL_GNULIB_UNLOCKPT = @GL_GNULIB_UNLOCKPT@ +GL_GNULIB_UNSETENV = @GL_GNULIB_UNSETENV@ +GL_GNULIB_USLEEP = @GL_GNULIB_USLEEP@ +GL_GNULIB_UTIMENSAT = @GL_GNULIB_UTIMENSAT@ +GL_GNULIB_VASPRINTF = @GL_GNULIB_VASPRINTF@ +GL_GNULIB_VDPRINTF = @GL_GNULIB_VDPRINTF@ +GL_GNULIB_VFPRINTF = @GL_GNULIB_VFPRINTF@ +GL_GNULIB_VFPRINTF_POSIX = @GL_GNULIB_VFPRINTF_POSIX@ +GL_GNULIB_VFSCANF = @GL_GNULIB_VFSCANF@ +GL_GNULIB_VPRINTF = @GL_GNULIB_VPRINTF@ +GL_GNULIB_VPRINTF_POSIX = @GL_GNULIB_VPRINTF_POSIX@ +GL_GNULIB_VSCANF = @GL_GNULIB_VSCANF@ +GL_GNULIB_VSNPRINTF = @GL_GNULIB_VSNPRINTF@ +GL_GNULIB_VSPRINTF_POSIX = @GL_GNULIB_VSPRINTF_POSIX@ +GL_GNULIB_WCPCPY = @GL_GNULIB_WCPCPY@ +GL_GNULIB_WCPNCPY = @GL_GNULIB_WCPNCPY@ +GL_GNULIB_WCRTOMB = @GL_GNULIB_WCRTOMB@ +GL_GNULIB_WCSCASECMP = @GL_GNULIB_WCSCASECMP@ +GL_GNULIB_WCSCAT = @GL_GNULIB_WCSCAT@ +GL_GNULIB_WCSCHR = @GL_GNULIB_WCSCHR@ +GL_GNULIB_WCSCMP = @GL_GNULIB_WCSCMP@ +GL_GNULIB_WCSCOLL = @GL_GNULIB_WCSCOLL@ +GL_GNULIB_WCSCPY = @GL_GNULIB_WCSCPY@ +GL_GNULIB_WCSCSPN = @GL_GNULIB_WCSCSPN@ +GL_GNULIB_WCSDUP = @GL_GNULIB_WCSDUP@ +GL_GNULIB_WCSFTIME = @GL_GNULIB_WCSFTIME@ +GL_GNULIB_WCSLEN = @GL_GNULIB_WCSLEN@ +GL_GNULIB_WCSNCASECMP = @GL_GNULIB_WCSNCASECMP@ +GL_GNULIB_WCSNCAT = @GL_GNULIB_WCSNCAT@ +GL_GNULIB_WCSNCMP = @GL_GNULIB_WCSNCMP@ +GL_GNULIB_WCSNCPY = @GL_GNULIB_WCSNCPY@ +GL_GNULIB_WCSNLEN = @GL_GNULIB_WCSNLEN@ +GL_GNULIB_WCSNRTOMBS = @GL_GNULIB_WCSNRTOMBS@ +GL_GNULIB_WCSPBRK = @GL_GNULIB_WCSPBRK@ +GL_GNULIB_WCSRCHR = @GL_GNULIB_WCSRCHR@ +GL_GNULIB_WCSRTOMBS = @GL_GNULIB_WCSRTOMBS@ +GL_GNULIB_WCSSPN = @GL_GNULIB_WCSSPN@ +GL_GNULIB_WCSSTR = @GL_GNULIB_WCSSTR@ +GL_GNULIB_WCSTOK = @GL_GNULIB_WCSTOK@ +GL_GNULIB_WCSWIDTH = @GL_GNULIB_WCSWIDTH@ +GL_GNULIB_WCSXFRM = @GL_GNULIB_WCSXFRM@ +GL_GNULIB_WCTOB = @GL_GNULIB_WCTOB@ +GL_GNULIB_WCTOMB = @GL_GNULIB_WCTOMB@ +GL_GNULIB_WCTRANS = @GL_GNULIB_WCTRANS@ +GL_GNULIB_WCTYPE = @GL_GNULIB_WCTYPE@ +GL_GNULIB_WCWIDTH = @GL_GNULIB_WCWIDTH@ +GL_GNULIB_WMEMCHR = @GL_GNULIB_WMEMCHR@ +GL_GNULIB_WMEMCMP = @GL_GNULIB_WMEMCMP@ +GL_GNULIB_WMEMCPY = @GL_GNULIB_WMEMCPY@ +GL_GNULIB_WMEMMOVE = @GL_GNULIB_WMEMMOVE@ +GL_GNULIB_WMEMPCPY = @GL_GNULIB_WMEMPCPY@ +GL_GNULIB_WMEMSET = @GL_GNULIB_WMEMSET@ +GL_GNULIB_WRITE = @GL_GNULIB_WRITE@ +GL_GNULIB__EXIT = @GL_GNULIB__EXIT@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIBHEADERS_OVERRIDE_WINT_T = @GNULIBHEADERS_OVERRIDE_WINT_T@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_TEST_WARN_CFLAGS = @GNULIB_TEST_WARN_CFLAGS@ +GNULIB_WARN_CFLAGS = @GNULIB_WARN_CFLAGS@ +GREP = @GREP@ +HAVE_ACCEPT4 = @HAVE_ACCEPT4@ +HAVE_ALIGNED_ALLOC = @HAVE_ALIGNED_ALLOC@ +HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ +HAVE_ALPHASORT = @HAVE_ALPHASORT@ +HAVE_ARPA_INET_H = @HAVE_ARPA_INET_H@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_BTOWC = @HAVE_BTOWC@ +HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ +HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@ +HAVE_CRTDEFS_H = @HAVE_CRTDEFS_H@ +HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ +HAVE_DECL_ECVT = @HAVE_DECL_ECVT@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_EXECVPE = @HAVE_DECL_EXECVPE@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FCLOSEALL = @HAVE_DECL_FCLOSEALL@ +HAVE_DECL_FCVT = @HAVE_DECL_FCVT@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GCVT = @HAVE_DECL_GCVT@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN = @HAVE_DECL_GETLOGIN@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@ +HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@ +HAVE_DECL_INET_NTOP = @HAVE_DECL_INET_NTOP@ +HAVE_DECL_INET_PTON = @HAVE_DECL_INET_PTON@ +HAVE_DECL_INITSTATE = @HAVE_DECL_INITSTATE@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SETSTATE = @HAVE_DECL_SETSTATE@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@ +HAVE_DECL_TRUNCATE = @HAVE_DECL_TRUNCATE@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCSDUP = @HAVE_DECL_WCSDUP@ +HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DIRENT_H = @HAVE_DIRENT_H@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_DUPLOCALE = @HAVE_DUPLOCALE@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_EXECVPE = @HAVE_EXECVPE@ +HAVE_EXPLICIT_BZERO = @HAVE_EXPLICIT_BZERO@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FDOPENDIR = @HAVE_FDOPENDIR@ +HAVE_FEATURES_H = @HAVE_FEATURES_H@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FNMATCH = @HAVE_FNMATCH@ +HAVE_FNMATCH_H = @HAVE_FNMATCH_H@ +HAVE_FREELOCALE = @HAVE_FREELOCALE@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETENTROPY = @HAVE_GETENTROPY@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETOPT_H = @HAVE_GETOPT_H@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETPASS = @HAVE_GETPASS@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@ +HAVE_GETUMASK = @HAVE_GETUMASK@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_IMAXDIV_T = @HAVE_IMAXDIV_T@ +HAVE_INITSTATE = @HAVE_INITSTATE@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_ISBLANK = @HAVE_ISBLANK@ +HAVE_ISWBLANK = @HAVE_ISWBLANK@ +HAVE_ISWCNTRL = @HAVE_ISWCNTRL@ +HAVE_LANGINFO_ALTMON = @HAVE_LANGINFO_ALTMON@ +HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@ +HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@ +HAVE_LANGINFO_H = @HAVE_LANGINFO_H@ +HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@ +HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LIBSIGSEGV = @HAVE_LIBSIGSEGV@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ +HAVE_MBRLEN = @HAVE_MBRLEN@ +HAVE_MBRTOWC = @HAVE_MBRTOWC@ +HAVE_MBSINIT = @HAVE_MBSINIT@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ +HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MBTOWC = @HAVE_MBTOWC@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ +HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OPENDIR = @HAVE_OPENDIR@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_MEMALIGN = @HAVE_POSIX_MEMALIGN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PSELECT = @HAVE_PSELECT@ +HAVE_PTHREAD_ATTR_DESTROY = @HAVE_PTHREAD_ATTR_DESTROY@ +HAVE_PTHREAD_ATTR_GETDETACHSTATE = @HAVE_PTHREAD_ATTR_GETDETACHSTATE@ +HAVE_PTHREAD_ATTR_INIT = @HAVE_PTHREAD_ATTR_INIT@ +HAVE_PTHREAD_ATTR_SETDETACHSTATE = @HAVE_PTHREAD_ATTR_SETDETACHSTATE@ +HAVE_PTHREAD_CONDATTR_DESTROY = @HAVE_PTHREAD_CONDATTR_DESTROY@ +HAVE_PTHREAD_CONDATTR_INIT = @HAVE_PTHREAD_CONDATTR_INIT@ +HAVE_PTHREAD_COND_BROADCAST = @HAVE_PTHREAD_COND_BROADCAST@ +HAVE_PTHREAD_COND_DESTROY = @HAVE_PTHREAD_COND_DESTROY@ +HAVE_PTHREAD_COND_INIT = @HAVE_PTHREAD_COND_INIT@ +HAVE_PTHREAD_COND_SIGNAL = @HAVE_PTHREAD_COND_SIGNAL@ +HAVE_PTHREAD_COND_TIMEDWAIT = @HAVE_PTHREAD_COND_TIMEDWAIT@ +HAVE_PTHREAD_COND_WAIT = @HAVE_PTHREAD_COND_WAIT@ +HAVE_PTHREAD_CREATE = @HAVE_PTHREAD_CREATE@ +HAVE_PTHREAD_CREATE_DETACHED = @HAVE_PTHREAD_CREATE_DETACHED@ +HAVE_PTHREAD_DETACH = @HAVE_PTHREAD_DETACH@ +HAVE_PTHREAD_EQUAL = @HAVE_PTHREAD_EQUAL@ +HAVE_PTHREAD_EXIT = @HAVE_PTHREAD_EXIT@ +HAVE_PTHREAD_GETSPECIFIC = @HAVE_PTHREAD_GETSPECIFIC@ +HAVE_PTHREAD_H = @HAVE_PTHREAD_H@ +HAVE_PTHREAD_JOIN = @HAVE_PTHREAD_JOIN@ +HAVE_PTHREAD_KEY_CREATE = @HAVE_PTHREAD_KEY_CREATE@ +HAVE_PTHREAD_KEY_DELETE = @HAVE_PTHREAD_KEY_DELETE@ +HAVE_PTHREAD_MUTEXATTR_DESTROY = @HAVE_PTHREAD_MUTEXATTR_DESTROY@ +HAVE_PTHREAD_MUTEXATTR_GETROBUST = @HAVE_PTHREAD_MUTEXATTR_GETROBUST@ +HAVE_PTHREAD_MUTEXATTR_GETTYPE = @HAVE_PTHREAD_MUTEXATTR_GETTYPE@ +HAVE_PTHREAD_MUTEXATTR_INIT = @HAVE_PTHREAD_MUTEXATTR_INIT@ +HAVE_PTHREAD_MUTEXATTR_SETROBUST = @HAVE_PTHREAD_MUTEXATTR_SETROBUST@ +HAVE_PTHREAD_MUTEXATTR_SETTYPE = @HAVE_PTHREAD_MUTEXATTR_SETTYPE@ +HAVE_PTHREAD_MUTEX_DESTROY = @HAVE_PTHREAD_MUTEX_DESTROY@ +HAVE_PTHREAD_MUTEX_INIT = @HAVE_PTHREAD_MUTEX_INIT@ +HAVE_PTHREAD_MUTEX_LOCK = @HAVE_PTHREAD_MUTEX_LOCK@ +HAVE_PTHREAD_MUTEX_RECURSIVE = @HAVE_PTHREAD_MUTEX_RECURSIVE@ +HAVE_PTHREAD_MUTEX_ROBUST = @HAVE_PTHREAD_MUTEX_ROBUST@ +HAVE_PTHREAD_MUTEX_TIMEDLOCK = @HAVE_PTHREAD_MUTEX_TIMEDLOCK@ +HAVE_PTHREAD_MUTEX_TRYLOCK = @HAVE_PTHREAD_MUTEX_TRYLOCK@ +HAVE_PTHREAD_MUTEX_UNLOCK = @HAVE_PTHREAD_MUTEX_UNLOCK@ +HAVE_PTHREAD_ONCE = @HAVE_PTHREAD_ONCE@ +HAVE_PTHREAD_PROCESS_SHARED = @HAVE_PTHREAD_PROCESS_SHARED@ +HAVE_PTHREAD_RWLOCKATTR_DESTROY = @HAVE_PTHREAD_RWLOCKATTR_DESTROY@ +HAVE_PTHREAD_RWLOCKATTR_INIT = @HAVE_PTHREAD_RWLOCKATTR_INIT@ +HAVE_PTHREAD_RWLOCK_DESTROY = @HAVE_PTHREAD_RWLOCK_DESTROY@ +HAVE_PTHREAD_RWLOCK_INIT = @HAVE_PTHREAD_RWLOCK_INIT@ +HAVE_PTHREAD_RWLOCK_RDLOCK = @HAVE_PTHREAD_RWLOCK_RDLOCK@ +HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK = @HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK@ +HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK = @HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK@ +HAVE_PTHREAD_RWLOCK_TRYRDLOCK = @HAVE_PTHREAD_RWLOCK_TRYRDLOCK@ +HAVE_PTHREAD_RWLOCK_TRYWRLOCK = @HAVE_PTHREAD_RWLOCK_TRYWRLOCK@ +HAVE_PTHREAD_RWLOCK_UNLOCK = @HAVE_PTHREAD_RWLOCK_UNLOCK@ +HAVE_PTHREAD_RWLOCK_WRLOCK = @HAVE_PTHREAD_RWLOCK_WRLOCK@ +HAVE_PTHREAD_SELF = @HAVE_PTHREAD_SELF@ +HAVE_PTHREAD_SETSPECIFIC = @HAVE_PTHREAD_SETSPECIFIC@ +HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ +HAVE_PTHREAD_SPINLOCK_T = @HAVE_PTHREAD_SPINLOCK_T@ +HAVE_PTHREAD_SPIN_DESTROY = @HAVE_PTHREAD_SPIN_DESTROY@ +HAVE_PTHREAD_SPIN_INIT = @HAVE_PTHREAD_SPIN_INIT@ +HAVE_PTHREAD_SPIN_LOCK = @HAVE_PTHREAD_SPIN_LOCK@ +HAVE_PTHREAD_SPIN_TRYLOCK = @HAVE_PTHREAD_SPIN_TRYLOCK@ +HAVE_PTHREAD_SPIN_UNLOCK = @HAVE_PTHREAD_SPIN_UNLOCK@ +HAVE_PTHREAD_T = @HAVE_PTHREAD_T@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_QSORT_R = @HAVE_QSORT_R@ +HAVE_RAISE = @HAVE_RAISE@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READDIR = @HAVE_READDIR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALLOCARRAY = @HAVE_REALLOCARRAY@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_REWINDDIR = @HAVE_REWINDDIR@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SA_FAMILY_T = @HAVE_SA_FAMILY_T@ +HAVE_SCANDIR = @HAVE_SCANDIR@ +HAVE_SCHED_H = @HAVE_SCHED_H@ +HAVE_SCHED_YIELD = @HAVE_SCHED_YIELD@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SETSTATE = @HAVE_SETSTATE@ +HAVE_SIGABBREV_NP = @HAVE_SIGABBREV_NP@ +HAVE_SIGACTION = @HAVE_SIGACTION@ +HAVE_SIGDESCR_NP = @HAVE_SIGDESCR_NP@ +HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ +HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SIGSET_T = @HAVE_SIGSET_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRERRORNAME_NP = @HAVE_STRERRORNAME_NP@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOL = @HAVE_STRTOL@ +HAVE_STRTOLD = @HAVE_STRTOLD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOUL = @HAVE_STRTOUL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRUCT_SCHED_PARAM = @HAVE_STRUCT_SCHED_PARAM@ +HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@ +HAVE_STRUCT_SOCKADDR_STORAGE = @HAVE_STRUCT_SOCKADDR_STORAGE@ +HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY = @HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_CDEFS_H = @HAVE_SYS_CDEFS_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_IOCTL_H = @HAVE_SYS_IOCTL_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_SYS_UIO_H = @HAVE_SYS_UIO_H@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TIMESPEC_GET = @HAVE_TIMESPEC_GET@ +HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@ +HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WCPCPY = @HAVE_WCPCPY@ +HAVE_WCPNCPY = @HAVE_WCPNCPY@ +HAVE_WCRTOMB = @HAVE_WCRTOMB@ +HAVE_WCSCASECMP = @HAVE_WCSCASECMP@ +HAVE_WCSCAT = @HAVE_WCSCAT@ +HAVE_WCSCHR = @HAVE_WCSCHR@ +HAVE_WCSCMP = @HAVE_WCSCMP@ +HAVE_WCSCOLL = @HAVE_WCSCOLL@ +HAVE_WCSCPY = @HAVE_WCSCPY@ +HAVE_WCSCSPN = @HAVE_WCSCSPN@ +HAVE_WCSDUP = @HAVE_WCSDUP@ +HAVE_WCSFTIME = @HAVE_WCSFTIME@ +HAVE_WCSLEN = @HAVE_WCSLEN@ +HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@ +HAVE_WCSNCAT = @HAVE_WCSNCAT@ +HAVE_WCSNCMP = @HAVE_WCSNCMP@ +HAVE_WCSNCPY = @HAVE_WCSNCPY@ +HAVE_WCSNLEN = @HAVE_WCSNLEN@ +HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@ +HAVE_WCSPBRK = @HAVE_WCSPBRK@ +HAVE_WCSRCHR = @HAVE_WCSRCHR@ +HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@ +HAVE_WCSSPN = @HAVE_WCSSPN@ +HAVE_WCSSTR = @HAVE_WCSSTR@ +HAVE_WCSTOK = @HAVE_WCSTOK@ +HAVE_WCSWIDTH = @HAVE_WCSWIDTH@ +HAVE_WCSXFRM = @HAVE_WCSXFRM@ +HAVE_WCTRANS_T = @HAVE_WCTRANS_T@ +HAVE_WCTYPE_H = @HAVE_WCTYPE_H@ +HAVE_WCTYPE_T = @HAVE_WCTYPE_T@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE_WMEMCHR = @HAVE_WMEMCHR@ +HAVE_WMEMCMP = @HAVE_WMEMCMP@ +HAVE_WMEMCPY = @HAVE_WMEMCPY@ +HAVE_WMEMMOVE = @HAVE_WMEMMOVE@ +HAVE_WMEMPCPY = @HAVE_WMEMPCPY@ +HAVE_WMEMSET = @HAVE_WMEMSET@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE_XLOCALE_H = @HAVE_XLOCALE_H@ +HAVE__BOOL = @HAVE__BOOL@ +HAVE__EXIT = @HAVE__EXIT@ +HOST_CPU = @HOST_CPU@ +HOST_CPU_C_ABI = @HOST_CPU_C_ABI@ +ICONV_CONST = @ICONV_CONST@ +ICONV_H = @ICONV_H@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INET_PTON_LIB = @INET_PTON_LIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@ +INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBCSTACK = @LIBCSTACK@ +LIBGREPUTILS_LIBDEPS = @LIBGREPUTILS_LIBDEPS@ +LIBGREPUTILS_LTLIBDEPS = @LIBGREPUTILS_LTLIBDEPS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPMULTITHREAD = @LIBPMULTITHREAD@ +LIBPTHREAD = @LIBPTHREAD@ +LIBS = @LIBS@ +LIBSIGSEGV = @LIBSIGSEGV@ +LIBSIGSEGV_PREFIX = @LIBSIGSEGV_PREFIX@ +LIBSOCKET = @LIBSOCKET@ +LIBSTDTHREAD = @LIBSTDTHREAD@ +LIBTESTS_LIBDEPS = @LIBTESTS_LIBDEPS@ +LIBTHREAD = @LIBTHREAD@ +LIBUNISTRING_UNISTR_H = @LIBUNISTRING_UNISTR_H@ +LIBUNISTRING_UNITYPES_H = @LIBUNISTRING_UNITYPES_H@ +LIBUNISTRING_UNIWIDTH_H = @LIBUNISTRING_UNIWIDTH_H@ +LIB_HARD_LOCALE = @LIB_HARD_LOCALE@ +LIB_MBRTOWC = @LIB_MBRTOWC@ +LIB_NANOSLEEP = @LIB_NANOSLEEP@ +LIB_NL_LANGINFO = @LIB_NL_LANGINFO@ +LIB_PTHREAD = @LIB_PTHREAD@ +LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ +LIB_SCHED_YIELD = @LIB_SCHED_YIELD@ +LIB_SELECT = @LIB_SELECT@ +LIB_SETLOCALE = @LIB_SETLOCALE@ +LIB_SETLOCALE_NULL = @LIB_SETLOCALE_NULL@ +LIMITS_H = @LIMITS_H@ +LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ +LOCALENAME_ENHANCE_LOCALE_FUNCS = @LOCALENAME_ENHANCE_LOCALE_FUNCS@ +LOCALE_FR = @LOCALE_FR@ +LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ +LOCALE_JA = @LOCALE_JA@ +LOCALE_TR_UTF8 = @LOCALE_TR_UTF8@ +LOCALE_ZH_CN = @LOCALE_ZH_CN@ +LTLIBCSTACK = @LTLIBCSTACK@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBSIGSEGV = @LTLIBSIGSEGV@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NETINET_IN_H = @NETINET_IN_H@ +NEXT_ARPA_INET_H = @NEXT_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H = @NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_CTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_CTYPE_H@ +NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@ +NEXT_AS_FIRST_DIRECTIVE_FNMATCH_H = @NEXT_AS_FIRST_DIRECTIVE_FNMATCH_H@ +NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ +NEXT_AS_FIRST_DIRECTIVE_ICONV_H = @NEXT_AS_FIRST_DIRECTIVE_ICONV_H@ +NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@ +NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ +NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@ +NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H = @NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H@ +NEXT_AS_FIRST_DIRECTIVE_PTHREAD_H = @NEXT_AS_FIRST_DIRECTIVE_PTHREAD_H@ +NEXT_AS_FIRST_DIRECTIVE_SCHED_H = @NEXT_AS_FIRST_DIRECTIVE_SCHED_H@ +NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_STDARG_H = @NEXT_AS_FIRST_DIRECTIVE_STDARG_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@ +NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@ +NEXT_CTYPE_H = @NEXT_CTYPE_H@ +NEXT_DIRENT_H = @NEXT_DIRENT_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_FNMATCH_H = @NEXT_FNMATCH_H@ +NEXT_GETOPT_H = @NEXT_GETOPT_H@ +NEXT_ICONV_H = @NEXT_ICONV_H@ +NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ +NEXT_LANGINFO_H = @NEXT_LANGINFO_H@ +NEXT_LIMITS_H = @NEXT_LIMITS_H@ +NEXT_LOCALE_H = @NEXT_LOCALE_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_PTHREAD_H = @NEXT_PTHREAD_H@ +NEXT_SCHED_H = @NEXT_SCHED_H@ +NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_STDARG_H = @NEXT_STDARG_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_IOCTL_H = @NEXT_SYS_IOCTL_H@ +NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_SYS_UIO_H = @NEXT_SYS_UIO_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +NEXT_WCTYPE_H = @NEXT_WCTYPE_H@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCRE_CFLAGS = @PCRE_CFLAGS@ +PCRE_LIBS = @PCRE_LIBS@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PRIPTR_PREFIX = @PRIPTR_PREFIX@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +RANLIB = @RANLIB@ +REPLACE_ACCESS = @REPLACE_ACCESS@ +REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@ +REPLACE_BTOWC = @REPLACE_BTOWC@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ +REPLACE_CREAT = @REPLACE_CREAT@ +REPLACE_CTIME = @REPLACE_CTIME@ +REPLACE_DIRFD = @REPLACE_DIRFD@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@ +REPLACE_EXECL = @REPLACE_EXECL@ +REPLACE_EXECLE = @REPLACE_EXECLE@ +REPLACE_EXECLP = @REPLACE_EXECLP@ +REPLACE_EXECV = @REPLACE_EXECV@ +REPLACE_EXECVE = @REPLACE_EXECVE@ +REPLACE_EXECVP = @REPLACE_EXECVP@ +REPLACE_EXECVPE = @REPLACE_EXECVPE@ +REPLACE_FACCESSAT = @REPLACE_FACCESSAT@ +REPLACE_FCHMODAT = @REPLACE_FCHMODAT@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FFSLL = @REPLACE_FFSLL@ +REPLACE_FNMATCH = @REPLACE_FNMATCH@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREE = @REPLACE_FREE@ +REPLACE_FREELOCALE = @REPLACE_FREELOCALE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETPASS = @REPLACE_GETPASS@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_ICONV = @REPLACE_ICONV@ +REPLACE_ICONV_OPEN = @REPLACE_ICONV_OPEN@ +REPLACE_ICONV_UTF = @REPLACE_ICONV_UTF@ +REPLACE_INET_NTOP = @REPLACE_INET_NTOP@ +REPLACE_INET_PTON = @REPLACE_INET_PTON@ +REPLACE_INITSTATE = @REPLACE_INITSTATE@ +REPLACE_IOCTL = @REPLACE_IOCTL@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_ISWBLANK = @REPLACE_ISWBLANK@ +REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@ +REPLACE_ISWDIGIT = @REPLACE_ISWDIGIT@ +REPLACE_ISWXDIGIT = @REPLACE_ISWXDIGIT@ +REPLACE_ITOLD = @REPLACE_ITOLD@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALECONV = @REPLACE_LOCALECONV@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBRLEN = @REPLACE_MBRLEN@ +REPLACE_MBRTOWC = @REPLACE_MBRTOWC@ +REPLACE_MBSINIT = @REPLACE_MBSINIT@ +REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@ +REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@ +REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKFIFOAT = @REPLACE_MKFIFOAT@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKNODAT = @REPLACE_MKNODAT@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NEWLOCALE = @REPLACE_NEWLOCALE@ +REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_OPENDIR = @REPLACE_OPENDIR@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_POSIX_MEMALIGN = @REPLACE_POSIX_MEMALIGN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PSELECT = @REPLACE_PSELECT@ +REPLACE_PTHREAD_ATTR_DESTROY = @REPLACE_PTHREAD_ATTR_DESTROY@ +REPLACE_PTHREAD_ATTR_GETDETACHSTATE = @REPLACE_PTHREAD_ATTR_GETDETACHSTATE@ +REPLACE_PTHREAD_ATTR_INIT = @REPLACE_PTHREAD_ATTR_INIT@ +REPLACE_PTHREAD_ATTR_SETDETACHSTATE = @REPLACE_PTHREAD_ATTR_SETDETACHSTATE@ +REPLACE_PTHREAD_CONDATTR_DESTROY = @REPLACE_PTHREAD_CONDATTR_DESTROY@ +REPLACE_PTHREAD_CONDATTR_INIT = @REPLACE_PTHREAD_CONDATTR_INIT@ +REPLACE_PTHREAD_COND_BROADCAST = @REPLACE_PTHREAD_COND_BROADCAST@ +REPLACE_PTHREAD_COND_DESTROY = @REPLACE_PTHREAD_COND_DESTROY@ +REPLACE_PTHREAD_COND_INIT = @REPLACE_PTHREAD_COND_INIT@ +REPLACE_PTHREAD_COND_SIGNAL = @REPLACE_PTHREAD_COND_SIGNAL@ +REPLACE_PTHREAD_COND_TIMEDWAIT = @REPLACE_PTHREAD_COND_TIMEDWAIT@ +REPLACE_PTHREAD_COND_WAIT = @REPLACE_PTHREAD_COND_WAIT@ +REPLACE_PTHREAD_CREATE = @REPLACE_PTHREAD_CREATE@ +REPLACE_PTHREAD_DETACH = @REPLACE_PTHREAD_DETACH@ +REPLACE_PTHREAD_EQUAL = @REPLACE_PTHREAD_EQUAL@ +REPLACE_PTHREAD_EXIT = @REPLACE_PTHREAD_EXIT@ +REPLACE_PTHREAD_GETSPECIFIC = @REPLACE_PTHREAD_GETSPECIFIC@ +REPLACE_PTHREAD_JOIN = @REPLACE_PTHREAD_JOIN@ +REPLACE_PTHREAD_KEY_CREATE = @REPLACE_PTHREAD_KEY_CREATE@ +REPLACE_PTHREAD_KEY_DELETE = @REPLACE_PTHREAD_KEY_DELETE@ +REPLACE_PTHREAD_MUTEXATTR_DESTROY = @REPLACE_PTHREAD_MUTEXATTR_DESTROY@ +REPLACE_PTHREAD_MUTEXATTR_GETROBUST = @REPLACE_PTHREAD_MUTEXATTR_GETROBUST@ +REPLACE_PTHREAD_MUTEXATTR_GETTYPE = @REPLACE_PTHREAD_MUTEXATTR_GETTYPE@ +REPLACE_PTHREAD_MUTEXATTR_INIT = @REPLACE_PTHREAD_MUTEXATTR_INIT@ +REPLACE_PTHREAD_MUTEXATTR_SETROBUST = @REPLACE_PTHREAD_MUTEXATTR_SETROBUST@ +REPLACE_PTHREAD_MUTEXATTR_SETTYPE = @REPLACE_PTHREAD_MUTEXATTR_SETTYPE@ +REPLACE_PTHREAD_MUTEX_DESTROY = @REPLACE_PTHREAD_MUTEX_DESTROY@ +REPLACE_PTHREAD_MUTEX_INIT = @REPLACE_PTHREAD_MUTEX_INIT@ +REPLACE_PTHREAD_MUTEX_LOCK = @REPLACE_PTHREAD_MUTEX_LOCK@ +REPLACE_PTHREAD_MUTEX_TIMEDLOCK = @REPLACE_PTHREAD_MUTEX_TIMEDLOCK@ +REPLACE_PTHREAD_MUTEX_TRYLOCK = @REPLACE_PTHREAD_MUTEX_TRYLOCK@ +REPLACE_PTHREAD_MUTEX_UNLOCK = @REPLACE_PTHREAD_MUTEX_UNLOCK@ +REPLACE_PTHREAD_ONCE = @REPLACE_PTHREAD_ONCE@ +REPLACE_PTHREAD_RWLOCKATTR_DESTROY = @REPLACE_PTHREAD_RWLOCKATTR_DESTROY@ +REPLACE_PTHREAD_RWLOCKATTR_INIT = @REPLACE_PTHREAD_RWLOCKATTR_INIT@ +REPLACE_PTHREAD_RWLOCK_DESTROY = @REPLACE_PTHREAD_RWLOCK_DESTROY@ +REPLACE_PTHREAD_RWLOCK_INIT = @REPLACE_PTHREAD_RWLOCK_INIT@ +REPLACE_PTHREAD_RWLOCK_RDLOCK = @REPLACE_PTHREAD_RWLOCK_RDLOCK@ +REPLACE_PTHREAD_RWLOCK_TIMEDRDLOCK = @REPLACE_PTHREAD_RWLOCK_TIMEDRDLOCK@ +REPLACE_PTHREAD_RWLOCK_TIMEDWRLOCK = @REPLACE_PTHREAD_RWLOCK_TIMEDWRLOCK@ +REPLACE_PTHREAD_RWLOCK_TRYRDLOCK = @REPLACE_PTHREAD_RWLOCK_TRYRDLOCK@ +REPLACE_PTHREAD_RWLOCK_TRYWRLOCK = @REPLACE_PTHREAD_RWLOCK_TRYWRLOCK@ +REPLACE_PTHREAD_RWLOCK_UNLOCK = @REPLACE_PTHREAD_RWLOCK_UNLOCK@ +REPLACE_PTHREAD_RWLOCK_WRLOCK = @REPLACE_PTHREAD_RWLOCK_WRLOCK@ +REPLACE_PTHREAD_SELF = @REPLACE_PTHREAD_SELF@ +REPLACE_PTHREAD_SETSPECIFIC = @REPLACE_PTHREAD_SETSPECIFIC@ +REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@ +REPLACE_PTHREAD_SPIN_DESTROY = @REPLACE_PTHREAD_SPIN_DESTROY@ +REPLACE_PTHREAD_SPIN_INIT = @REPLACE_PTHREAD_SPIN_INIT@ +REPLACE_PTHREAD_SPIN_LOCK = @REPLACE_PTHREAD_SPIN_LOCK@ +REPLACE_PTHREAD_SPIN_TRYLOCK = @REPLACE_PTHREAD_SPIN_TRYLOCK@ +REPLACE_PTHREAD_SPIN_UNLOCK = @REPLACE_PTHREAD_SPIN_UNLOCK@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM = @REPLACE_RANDOM@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALLOCARRAY = @REPLACE_REALLOCARRAY@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_SCHED_YIELD = @REPLACE_SCHED_YIELD@ +REPLACE_SELECT = @REPLACE_SELECT@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SETSTATE = @REPLACE_SETSTATE@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERRORNAME_NP = @REPLACE_STRERRORNAME_NP@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRFTIME = @REPLACE_STRFTIME@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRTOL = @REPLACE_STRTOL@ +REPLACE_STRTOLD = @REPLACE_STRTOLD@ +REPLACE_STRTOLL = @REPLACE_STRTOLL@ +REPLACE_STRTOUL = @REPLACE_STRTOUL@ +REPLACE_STRTOULL = @REPLACE_STRTOULL@ +REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@ +REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ +REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TOWLOWER = @REPLACE_TOWLOWER@ +REPLACE_TRUNCATE = @REPLACE_TRUNCATE@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_TZSET = @REPLACE_TZSET@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCRTOMB = @REPLACE_WCRTOMB@ +REPLACE_WCSFTIME = @REPLACE_WCSFTIME@ +REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@ +REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@ +REPLACE_WCSTOK = @REPLACE_WCSTOK@ +REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@ +REPLACE_WCTOB = @REPLACE_WCTOB@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +REPLACE_WRITE = @REPLACE_WRITE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIGSEGV_H = @SIGSEGV_H@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +STDALIGN_H = @STDALIGN_H@ +STDARG_H = @STDARG_H@ +STDBOOL_H = @STDBOOL_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYS_IOCTL_H_HAVE_WINSOCK2_H = @SYS_IOCTL_H_HAVE_WINSOCK2_H@ +SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_TIME_UTC = @TIME_H_DEFINES_TIME_UTC@ +UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ +UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +UNISTD_H_HAVE_SYS_RANDOM_H = @UNISTD_H_HAVE_SYS_RANDOM_H@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WERROR_CFLAGS = @WERROR_CFLAGS@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINDOWS_STAT_INODES = @WINDOWS_STAT_INODES@ +WINDOWS_STAT_TIMESPEC = @WINDOWS_STAT_TIMESPEC@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_aux_dir = @abs_aux_dir@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +lispdir = @lispdir@ +localedir = $(datadir)/locale +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +LN = ln +AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) $(PCRE_CFLAGS) + +# Tell the linker to omit references to unused shared libraries. +AM_LDFLAGS = $(IGNORE_UNUSED_LIBRARIES_CFLAGS) +bin_SCRIPTS = egrep fgrep +grep_SOURCES = dfasearch.c die.h grep.c kwsearch.c kwset.c \ + searchutils.c $(am__append_1) +noinst_HEADERS = grep.h kwset.h search.h system.h + +# Sometimes, the expansion of $(LIBINTL) includes -lc which may +# include modules defining variables like 'optind', so libgreputils.a +# must precede $(LIBINTL) in order to ensure we use GNU getopt. +# But libgreputils.a must also follow $(LIBINTL), since libintl uses +# replacement functions defined in libgreputils.a. +LDADD = \ + ../lib/libgreputils.a $(LIBINTL) ../lib/libgreputils.a $(LIBICONV) \ + $(LIBTHREAD) + +grep_LDADD = $(LDADD) $(PCRE_LIBS) $(LIBCSTACK) +AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib +EXTRA_DIST = egrep.sh +CLEANFILES = egrep fgrep *-t +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +grep$(EXEEXT): $(grep_OBJECTS) $(grep_DEPENDENCIES) $(EXTRA_grep_DEPENDENCIES) + @rm -f grep$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(grep_OBJECTS) $(grep_LDADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dfasearch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grep.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kwsearch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kwset.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcresearch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/searchutils.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/dfasearch.Po + -rm -f ./$(DEPDIR)/grep.Po + -rm -f ./$(DEPDIR)/kwsearch.Po + -rm -f ./$(DEPDIR)/kwset.Po + -rm -f ./$(DEPDIR)/pcresearch.Po + -rm -f ./$(DEPDIR)/searchutils.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-binSCRIPTS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/dfasearch.Po + -rm -f ./$(DEPDIR)/grep.Po + -rm -f ./$(DEPDIR)/kwsearch.Po + -rm -f ./$(DEPDIR)/kwset.Po + -rm -f ./$(DEPDIR)/pcresearch.Po + -rm -f ./$(DEPDIR)/searchutils.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-binPROGRAMS install-binSCRIPTS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-binSCRIPTS + +.PRECIOUS: Makefile + + +egrep fgrep: egrep.sh Makefile + $(AM_V_GEN)grep=`echo grep | sed -e '$(transform)'` && \ + case $@ in egrep) option=-E;; fgrep) option=-F;; esac && \ + shell_does_substrings='set x/y && d=$${1%/*} && test "$$d" = x' && \ + if $(SHELL) -c "$$shell_does_substrings" 2>/dev/null; then \ + edit_substring='s,X,X,'; \ + else \ + edit_substring='s,\$${0%/\*},`expr "X$$0" : '\''X\\(.*\\)/'\''`,g'; \ + fi && \ + sed -e 's|[@]SHELL@|$(SHELL)|g' \ + -e "$$edit_substring" \ + -e "s|[@]grep@|$$grep|g" \ + -e "s|[@]option@|$$option|g" <$(srcdir)/egrep.sh >$@-t + $(AM_V_at)chmod +x $@-t + $(AM_V_at)mv $@-t $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/grep/src/dfasearch.c b/src/grep/src/dfasearch.c new file mode 100644 index 0000000..d6afa8d --- /dev/null +++ b/src/grep/src/dfasearch.c @@ -0,0 +1,590 @@ +/* dfasearch.c - searching subroutines using dfa and regex for grep. + Copyright 1992, 1998, 2000, 2007, 2009-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written August 1992 by Mike Haertel. */ + +#include <config.h> +#include "intprops.h" +#include "search.h" +#include "die.h" +#include <error.h> + +struct dfa_comp +{ + /* KWset compiled pattern. For GEAcompile, we compile + a list of strings, at least one of which is known to occur in + any string matching the regexp. */ + kwset_t kwset; + + /* DFA compiled regexp. */ + struct dfa *dfa; + + /* Regex compiled regexps. */ + struct re_pattern_buffer *patterns; + size_t pcount; + struct re_registers regs; + + /* Number of compiled fixed strings known to exactly match the regexp. + If kwsexec returns < kwset_exact_matches, then we don't need to + call the regexp matcher at all. */ + ptrdiff_t kwset_exact_matches; + + bool begline; +}; + +void +dfaerror (char const *mesg) +{ + die (EXIT_TROUBLE, 0, "%s", mesg); +} + +/* For now, the sole dfawarn-eliciting condition (use of a regexp + like '[:lower:]') is unequivocally an error, so treat it as such, + when possible. */ +void +dfawarn (char const *mesg) +{ + if (!getenv ("POSIXLY_CORRECT")) + dfaerror (mesg); +} + +/* If the DFA turns out to have some set of fixed strings one of + which must occur in the match, then we build a kwset matcher + to find those strings, and thus quickly filter out impossible + matches. */ +static void +kwsmusts (struct dfa_comp *dc) +{ + struct dfamust *dm = dfamust (dc->dfa); + if (!dm) + return; + dc->kwset = kwsinit (false); + if (dm->exact) + { + /* Prepare a substring whose presence implies a match. + The kwset matcher will return the index of the matching + string that it chooses. */ + ++dc->kwset_exact_matches; + ptrdiff_t old_len = strlen (dm->must); + ptrdiff_t new_len = old_len + dm->begline + dm->endline; + char *must = xmalloc (new_len); + char *mp = must; + *mp = eolbyte; + mp += dm->begline; + dc->begline |= dm->begline; + memcpy (mp, dm->must, old_len); + if (dm->endline) + mp[old_len] = eolbyte; + kwsincr (dc->kwset, must, new_len); + free (must); + } + else + { + /* Otherwise, filtering with this substring should help reduce the + search space, but we'll still have to use the regexp matcher. */ + kwsincr (dc->kwset, dm->must, strlen (dm->must)); + } + kwsprep (dc->kwset); + dfamustfree (dm); +} + +/* Return true if KEYS, of length LEN, might contain a back-reference. + Return false if KEYS cannot contain a back-reference. + BS_SAFE is true of encodings where a backslash cannot appear as the + last byte of a multibyte character. */ +static bool _GL_ATTRIBUTE_PURE +possible_backrefs_in_pattern (char const *keys, ptrdiff_t len, bool bs_safe) +{ + /* Normally a backslash, but in an unsafe encoding this is a non-char + value so that the comparison below always fails, because if there + are two adjacent '\' bytes, the first might be the last byte of a + multibyte character. */ + int second_backslash = bs_safe ? '\\' : CHAR_MAX + 1; + + /* This code can return true even if KEYS lacks a back-reference, for + patterns like [\2], or for encodings where '\' appears as the last + byte of a multibyte character. However, false alarms should be + rare and do not affect correctness. */ + + /* Do not look for a backslash in the pattern's last byte, since it + can't be part of a back-reference and this streamlines the code. */ + len--; + + if (0 <= len) + { + char const *lim = keys + len; + for (char const *p = keys; (p = memchr (p, '\\', lim - p)); p++) + { + if ('1' <= p[1] && p[1] <= '9') + return true; + if (p[1] == second_backslash) + { + p++; + if (p == lim) + break; + } + } + } + return false; +} + +static bool +regex_compile (struct dfa_comp *dc, char const *p, ptrdiff_t len, + ptrdiff_t pcount, ptrdiff_t lineno, reg_syntax_t syntax_bits, + bool syntax_only) +{ + struct re_pattern_buffer pat0; + struct re_pattern_buffer *pat = syntax_only ? &pat0 : &dc->patterns[pcount]; + pat->buffer = NULL; + pat->allocated = 0; + + /* Do not use a fastmap with -i, to work around glibc Bug#20381. */ + pat->fastmap = (syntax_only | match_icase) ? NULL : xmalloc (UCHAR_MAX + 1); + + pat->translate = NULL; + + if (syntax_only) + re_set_syntax (syntax_bits | RE_NO_SUB); + else + re_set_syntax (syntax_bits); + + char const *err = re_compile_pattern (p, len, pat); + if (!err) + return true; + + /* Emit a filename:lineno: prefix for patterns taken from files. */ + size_t pat_lineno; + char const *pat_filename + = lineno < 0 ? "" : pattern_file_name (lineno, &pat_lineno); + + if (*pat_filename == '\0') + error (0, 0, "%s", err); + else + error (0, 0, "%s:%zu: %s", pat_filename, pat_lineno, err); + + return false; +} + +/* Compile PATTERN, containing SIZE bytes that are followed by '\n'. + SYNTAX_BITS specifies whether PATTERN uses style -G, -E, or -A. + Return a description of the compiled pattern. */ + +void * +GEAcompile (char *pattern, size_t size, reg_syntax_t syntax_bits, + bool exact) +{ + char *motif; + struct dfa_comp *dc = xcalloc (1, sizeof (*dc)); + + dc->dfa = dfaalloc (); + + if (match_icase) + syntax_bits |= RE_ICASE; + int dfaopts = eolbyte ? 0 : DFA_EOL_NUL; + dfasyntax (dc->dfa, &localeinfo, syntax_bits, dfaopts); + bool bs_safe = !localeinfo.multibyte | localeinfo.using_utf8; + + /* For GNU regex, pass the patterns separately to detect errors like + "[\nallo\n]\n", where the patterns are "[", "allo" and "]", and + this should be a syntax error. The same for backref, where the + backref should be local to each pattern. */ + char const *p = pattern; + char const *patlim = pattern + size; + bool compilation_failed = false; + + dc->patterns = xmalloc (sizeof *dc->patterns); + dc->patterns++; + dc->pcount = 0; + size_t palloc = 1; + + char const *prev = pattern; + + /* Buffer containing back-reference-free patterns. */ + char *buf = NULL; + ptrdiff_t buflen = 0; + size_t bufalloc = 0; + + ptrdiff_t lineno = 0; + + do + { + char const *sep = rawmemchr (p, '\n'); + ptrdiff_t len = sep - p; + + bool backref = possible_backrefs_in_pattern (p, len, bs_safe); + + if (backref && prev < p) + { + ptrdiff_t prevlen = p - prev; + while (bufalloc < buflen + prevlen) + buf = x2realloc (buf, &bufalloc); + memcpy (buf + buflen, prev, prevlen); + buflen += prevlen; + } + + /* Ensure room for at least two more patterns. The extra one is + for the regex_compile that may be executed after this loop + exits, and its (unused) slot is patterns[-1] until then. */ + while (palloc <= dc->pcount + 1) + { + dc->patterns = x2nrealloc (dc->patterns - 1, &palloc, + sizeof *dc->patterns); + dc->patterns++; + } + + re_set_syntax (syntax_bits); + + if (!regex_compile (dc, p, len, dc->pcount, lineno, syntax_bits, + !backref)) + compilation_failed = true; + + p = sep + 1; + lineno++; + + if (backref) + { + dc->pcount++; + prev = p; + } + } + while (p <= patlim); + + if (compilation_failed) + exit (EXIT_TROUBLE); + + if (prev <= patlim) + { + if (pattern < prev) + { + ptrdiff_t prevlen = patlim - prev; + buf = xrealloc (buf, buflen + prevlen); + memcpy (buf + buflen, prev, prevlen); + buflen += prevlen; + } + else + { + buf = pattern; + buflen = size; + } + } + + /* In the match_words and match_lines cases, we use a different pattern + for the DFA matcher that will quickly throw out cases that won't work. + Then if DFA succeeds we do some hairy stuff using the regex matcher + to decide whether the match should really count. */ + if (match_words || match_lines) + { + static char const line_beg_no_bk[] = "^("; + static char const line_end_no_bk[] = ")$"; + static char const word_beg_no_bk[] = "(^|[^[:alnum:]_])("; + static char const word_end_no_bk[] = ")([^[:alnum:]_]|$)"; + static char const line_beg_bk[] = "^\\("; + static char const line_end_bk[] = "\\)$"; + static char const word_beg_bk[] = "\\(^\\|[^[:alnum:]_]\\)\\("; + static char const word_end_bk[] = "\\)\\([^[:alnum:]_]\\|$\\)"; + int bk = !(syntax_bits & RE_NO_BK_PARENS); + char *n = xmalloc (sizeof word_beg_bk - 1 + size + sizeof word_end_bk); + + strcpy (n, match_lines ? (bk ? line_beg_bk : line_beg_no_bk) + : (bk ? word_beg_bk : word_beg_no_bk)); + size_t total = strlen (n); + memcpy (n + total, pattern, size); + total += size; + strcpy (n + total, match_lines ? (bk ? line_end_bk : line_end_no_bk) + : (bk ? word_end_bk : word_end_no_bk)); + total += strlen (n + total); + pattern = motif = n; + size = total; + } + else + motif = NULL; + + dfaparse (pattern, size, dc->dfa); + kwsmusts (dc); + dfacomp (NULL, 0, dc->dfa, 1); + + if (buf != NULL) + { + if (exact || !dfasupported (dc->dfa)) + { + dc->patterns--; + dc->pcount++; + + if (!regex_compile (dc, buf, buflen, 0, -1, syntax_bits, false)) + abort (); + } + + if (buf != pattern) + free (buf); + } + + free (motif); + + return dc; +} + +size_t +EGexecute (void *vdc, char const *buf, size_t size, size_t *match_size, + char const *start_ptr) +{ + char const *buflim, *beg, *end, *ptr, *match, *best_match, *mb_start; + char eol = eolbyte; + regoff_t start; + size_t len, best_len; + struct kwsmatch kwsm; + size_t i; + struct dfa_comp *dc = vdc; + struct dfa *superset = dfasuperset (dc->dfa); + bool dfafast = dfaisfast (dc->dfa); + + mb_start = buf; + buflim = buf + size; + + for (beg = end = buf; end < buflim; beg = end) + { + end = buflim; + + if (!start_ptr) + { + char const *next_beg, *dfa_beg = beg; + ptrdiff_t count = 0; + bool exact_kwset_match = false; + bool backref = false; + + /* Try matching with KWset, if it's defined. */ + if (dc->kwset) + { + char const *prev_beg; + + /* Find a possible match using the KWset matcher. */ + ptrdiff_t offset = kwsexec (dc->kwset, beg - dc->begline, + buflim - beg + dc->begline, + &kwsm, true); + if (offset < 0) + return offset; + match = beg + offset; + prev_beg = beg; + + /* Narrow down to the line containing the possible match. */ + beg = memrchr (buf, eol, match - buf); + beg = beg ? beg + 1 : buf; + dfa_beg = beg; + + /* Determine the end pointer to give the DFA next. Typically + this is after the first newline after MATCH; but if the KWset + match is not exact, the DFA is fast, and the offset from + PREV_BEG is less than 64 or (MATCH - PREV_BEG), this is the + greater of the latter two values; this temporarily prefers + the DFA to KWset. */ + exact_kwset_match = kwsm.index < dc->kwset_exact_matches; + if (exact_kwset_match || !dfafast + || MAX (16, match - beg) < (match - prev_beg) >> 2) + { + end = rawmemchr (match, eol); + end++; + } + else if (MAX (16, match - beg) < (buflim - prev_beg) >> 2) + { + end = rawmemchr (prev_beg + 4 * MAX (16, match - beg), eol); + end++; + } + else + end = buflim; + + if (exact_kwset_match) + { + if (!localeinfo.multibyte | localeinfo.using_utf8) + goto success; + if (mb_start < beg) + mb_start = beg; + if (mb_goback (&mb_start, NULL, match, buflim) == 0) + goto success; + /* The matched line starts in the middle of a multibyte + character. Perform the DFA search starting from the + beginning of the next character. */ + dfa_beg = mb_start; + } + } + + /* Try matching with the superset of DFA, if it's defined. */ + if (superset && !exact_kwset_match) + { + /* Keep using the superset while it reports multiline + potential matches; this is more likely to be fast + than falling back to KWset would be. */ + next_beg = dfaexec (superset, dfa_beg, (char *) end, 0, + &count, NULL); + if (next_beg == NULL || next_beg == end) + continue; + + /* Narrow down to the line we've found. */ + if (count != 0) + { + beg = memrchr (buf, eol, next_beg - buf); + beg++; + dfa_beg = beg; + } + end = rawmemchr (next_beg, eol); + end++; + + count = 0; + } + + /* Try matching with DFA. */ + next_beg = dfaexec (dc->dfa, dfa_beg, (char *) end, 0, &count, + &backref); + + /* If there's no match, or if we've matched the sentinel, + we're done. */ + if (next_beg == NULL || next_beg == end) + continue; + + /* Narrow down to the line we've found. */ + if (count != 0) + { + beg = memrchr (buf, eol, next_beg - buf); + beg++; + } + end = rawmemchr (next_beg, eol); + end++; + + /* Successful, no back-references encountered! */ + if (!backref) + goto success; + ptr = beg; + } + else + { + /* We are looking for the leftmost (then longest) exact match. + We will go through the outer loop only once. */ + ptr = start_ptr; + } + + /* If the "line" is longer than the maximum regexp offset, + die as if we've run out of memory. */ + if (TYPE_MAXIMUM (regoff_t) < end - beg - 1) + xalloc_die (); + + /* Run the possible match through Regex. */ + best_match = end; + best_len = 0; + for (i = 0; i < dc->pcount; i++) + { + dc->patterns[i].not_eol = 0; + dc->patterns[i].newline_anchor = eolbyte == '\n'; + start = re_search (&dc->patterns[i], beg, end - beg - 1, + ptr - beg, end - ptr - 1, &dc->regs); + if (start < -1) + xalloc_die (); + else if (0 <= start) + { + len = dc->regs.end[0] - start; + match = beg + start; + if (match > best_match) + continue; + if (start_ptr && !match_words) + goto assess_pattern_match; + if ((!match_lines && !match_words) + || (match_lines && len == end - ptr - 1)) + { + match = ptr; + len = end - ptr; + goto assess_pattern_match; + } + /* If -w and not -x, check whether the match aligns with + word boundaries. Do this iteratively because: + (a) the line may contain more than one occurrence of the + pattern, and + (b) Several alternatives in the pattern might be valid at a + given point, and we may need to consider a shorter one to + find a word boundary. */ + if (!match_lines && match_words) + while (match <= best_match) + { + regoff_t shorter_len = 0; + if (! wordchar_next (match + len, end - 1) + && ! wordchar_prev (beg, match, end - 1)) + goto assess_pattern_match; + if (len > 0) + { + /* Try a shorter length anchored at the same place. */ + --len; + dc->patterns[i].not_eol = 1; + shorter_len = re_match (&dc->patterns[i], beg, + match + len - ptr, match - beg, + &dc->regs); + if (shorter_len < -1) + xalloc_die (); + } + if (0 < shorter_len) + len = shorter_len; + else + { + /* Try looking further on. */ + if (match == end - 1) + break; + match++; + dc->patterns[i].not_eol = 0; + start = re_search (&dc->patterns[i], beg, end - beg - 1, + match - beg, end - match - 1, + &dc->regs); + if (start < 0) + { + if (start < -1) + xalloc_die (); + break; + } + len = dc->regs.end[0] - start; + match = beg + start; + } + } /* while (match <= best_match) */ + continue; + assess_pattern_match: + if (!start_ptr) + { + /* Good enough for a non-exact match. + No need to look at further patterns, if any. */ + goto success; + } + if (match < best_match || (match == best_match && len > best_len)) + { + /* Best exact match: leftmost, then longest. */ + best_match = match; + best_len = len; + } + } /* if re_search >= 0 */ + } /* for Regex patterns. */ + if (best_match < end) + { + /* We have found an exact match. We were just + waiting for the best one (leftmost then longest). */ + beg = best_match; + len = best_len; + goto success_in_len; + } + } /* for (beg = end ..) */ + + return -1; + + success: + len = end - beg; + success_in_len:; + size_t off = beg - buf; + *match_size = len; + return off; +} diff --git a/src/grep/src/die.h b/src/grep/src/die.h new file mode 100644 index 0000000..cc47c5a --- /dev/null +++ b/src/grep/src/die.h @@ -0,0 +1,31 @@ +/* Report an error and exit. + Copyright 2016-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef DIE_H +#define DIE_H + +#include <error.h> +#include <stdbool.h> +#include <verify.h> + +/* Like 'error (STATUS, ...)', except STATUS must be a nonzero constant. + This may pacify the compiler or help it generate better code. */ +#define die(status, ...) \ + verify_expr (status, (error (status, __VA_ARGS__), assume (false))) + +#endif /* DIE_H */ diff --git a/src/grep/src/egrep.sh b/src/grep/src/egrep.sh new file mode 100644 index 0000000..6d6c15a --- /dev/null +++ b/src/grep/src/egrep.sh @@ -0,0 +1,2 @@ +#!@SHELL@ +exec @grep@ @option@ "$@" diff --git a/src/grep/src/grep.c b/src/grep/src/grep.c new file mode 100644 index 0000000..aabae2d --- /dev/null +++ b/src/grep/src/grep.c @@ -0,0 +1,3173 @@ +/* grep.c - main driver file for grep. + Copyright (C) 1992, 1997-2002, 2004-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written July 1992 by Mike Haertel. */ + +#include <config.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <wchar.h> +#include <inttypes.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include "system.h" + +#include "argmatch.h" +#include "c-ctype.h" +#include "c-stack.h" +#include "closeout.h" +#include "colorize.h" +#include "die.h" +#include "error.h" +#include "exclude.h" +#include "exitfail.h" +#include "fcntl-safer.h" +#if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS) +# include "nt/fts-nt.h" /* Use NT optimized FTS implementation. */ +#else +#include "fts_.h" +#endif +#include "getopt.h" +#include "getprogname.h" +#include "grep.h" +#include "hash.h" +#include "intprops.h" +#include "propername.h" +#include "safe-read.h" +#include "search.h" +#include "c-strcase.h" +#include "version-etc.h" +#include "xalloc.h" +#include "xbinary-io.h" +#include "xstrtol.h" + +#if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS) +# include "console.h" +#endif + +enum { SEP_CHAR_SELECTED = ':' }; +enum { SEP_CHAR_REJECTED = '-' }; +static char const SEP_STR_GROUP[] = "--"; + +/* When stdout is connected to a regular file, save its stat + information here, so that we can automatically skip it, thus + avoiding a potential (racy) infinite loop. */ +static struct stat out_stat; + +/* if non-zero, display usage information and exit */ +static int show_help; + +/* Print the version on standard output and exit. */ +static bool show_version; + +/* Suppress diagnostics for nonexistent or unreadable files. */ +static bool suppress_errors; + +/* If nonzero, use color markers. */ +static int color_option; + +/* Show only the part of a line matching the expression. */ +static bool only_matching; + +/* If nonzero, make sure first content char in a line is on a tab stop. */ +static bool align_tabs; + +/* Print width of line numbers and byte offsets. Nonzero if ALIGN_TABS. */ +static int offset_width; + +/* An entry in the PATLOC array saying where patterns came from. */ +struct patloc + { + /* Line number of the pattern in PATTERN_ARRAY. Line numbers + start at 0, and each pattern is terminated by '\n'. */ + ptrdiff_t lineno; + + /* Input location of the pattern. The FILENAME "-" represents + standard input, and "" represents the command line. FILELINE is + origin-1 for files and is irrelevant for the command line. */ + char const *filename; + ptrdiff_t fileline; + }; + +/* The array of pattern locations. The concatenation of all patterns + is stored in a single array, KEYS. Given the invocation + 'grep -f <(seq 5) -f <(seq 6) -f <(seq 3)', there will initially be + 28 bytes in KEYS. After duplicate patterns are removed, KEYS + will have 12 bytes and PATLOC will be {0,x,1}, {10,y,1} + where x, y and z are just place-holders for shell-generated names + since and z is omitted as it contains only duplicates. Sometimes + removing duplicates will grow PATLOC, since each run of + removed patterns not at a file start or end requires another + PATLOC entry for the first non-removed pattern. */ +static struct patloc *patloc; +static size_t patlocs_allocated, patlocs_used; + +/* Pointer to the array of patterns, each terminated by newline. */ +static char *pattern_array; + +/* The number of unique patterns seen so far. */ +static size_t n_patterns; + +/* Hash table of patterns seen so far. */ +static Hash_table *pattern_table; + +/* Hash and compare newline-terminated patterns for textual equality. + Patterns are represented by origin-1 offsets into PATTERN_ARRAY, + cast to void *. The origin-1 is so that the first pattern offset + does not appear to be a null pointer when cast to void *. */ +static size_t _GL_ATTRIBUTE_PURE +hash_pattern (void const *pat, size_t n_buckets) +{ + size_t h = 0; + intptr_t pat_offset = (intptr_t) pat - 1; + unsigned char const *s = (unsigned char const *) pattern_array + pat_offset; + for ( ; *s != '\n'; s++) + h = h * 33 ^ *s; + return h % n_buckets; +} +static bool _GL_ATTRIBUTE_PURE +compare_patterns (void const *a, void const *b) +{ + intptr_t a_offset = (intptr_t) a - 1; + intptr_t b_offset = (intptr_t) b - 1; + char const *p = pattern_array + a_offset; + char const *q = pattern_array + b_offset; + for (; *p == *q; p++, q++) + if (*p == '\n') + return true; + return false; +} + +/* Update KEYS to remove duplicate patterns, and return the number of + bytes in the resulting KEYS. KEYS contains a sequence of patterns + each terminated by '\n'. The first DUPFREE_SIZE bytes are a + sequence of patterns with no duplicates; SIZE is the total number + of bytes in KEYS. If some patterns past the first DUPFREE_SIZE + bytes are not duplicates, update PATLOCS accordingly. */ +static ptrdiff_t +update_patterns (char *keys, ptrdiff_t dupfree_size, ptrdiff_t size, + char const *filename) +{ + char *dst = keys + dupfree_size; + ptrdiff_t fileline = 1; + int prev_inserted = 0; + + char const *srclim = keys + size; + ptrdiff_t patsize; + for (char const *src = keys + dupfree_size; src < srclim; src += patsize) + { + char const *patend = rawmemchr (src, '\n'); + patsize = patend + 1 - src; + memmove (dst, src, patsize); + + intptr_t dst_offset_1 = dst - keys + 1; + int inserted = hash_insert_if_absent (pattern_table, + (void *) dst_offset_1, NULL); + if (inserted) + { + if (inserted < 0) + xalloc_die (); + dst += patsize; + + /* Add a PATLOCS entry unless this input line is simply the + next one in the same file. */ + if (!prev_inserted) + { + if (patlocs_used == patlocs_allocated) + patloc = x2nrealloc (patloc, &patlocs_allocated, + sizeof *patloc); + patloc[patlocs_used++] + = (struct patloc) { .lineno = n_patterns, + .filename = filename, + .fileline = fileline }; + } + n_patterns++; + } + + prev_inserted = inserted; + fileline++; + } + + return dst - keys; +} + +/* Map LINENO, the origin-0 line number of one of the input patterns, + to the name of the file from which it came. Return "-" if it was + read from stdin, "" if it was specified on the command line. + Set *NEW_LINENO to the origin-1 line number of PATTERN in the file, + or to an unspecified value if PATTERN came from the command line. */ +char const * _GL_ATTRIBUTE_PURE +pattern_file_name (size_t lineno, size_t *new_lineno) +{ + ptrdiff_t i; + for (i = 1; i < patlocs_used; i++) + if (lineno < patloc[i].lineno) + break; + *new_lineno = lineno - patloc[i - 1].lineno + patloc[i - 1].fileline; + return patloc[i - 1].filename; +} + +#if HAVE_ASAN +/* Record the starting address and length of the sole poisoned region, + so that we can unpoison it later, just before each following read. */ +static void const *poison_buf; +static size_t poison_len; + +static void +clear_asan_poison (void) +{ + if (poison_buf) + __asan_unpoison_memory_region (poison_buf, poison_len); +} + +static void +asan_poison (void const *addr, size_t size) +{ + poison_buf = addr; + poison_len = size; + + __asan_poison_memory_region (poison_buf, poison_len); +} +#else +static void clear_asan_poison (void) { } +static void asan_poison (void const volatile *addr, size_t size) { } +#endif + +/* The group separator used when context is requested. */ +static const char *group_separator = SEP_STR_GROUP; + +/* The context and logic for choosing default --color screen attributes + (foreground and background colors, etc.) are the following. + -- There are eight basic colors available, each with its own + nominal luminosity to the human eye and foreground/background + codes (black [0 %, 30/40], blue [11 %, 34/44], red [30 %, 31/41], + magenta [41 %, 35/45], green [59 %, 32/42], cyan [70 %, 36/46], + yellow [89 %, 33/43], and white [100 %, 37/47]). + -- Sometimes, white as a background is actually implemented using + a shade of light gray, so that a foreground white can be visible + on top of it (but most often not). + -- Sometimes, black as a foreground is actually implemented using + a shade of dark gray, so that it can be visible on top of a + background black (but most often not). + -- Sometimes, more colors are available, as extensions. + -- Other attributes can be selected/deselected (bold [1/22], + underline [4/24], standout/inverse [7/27], blink [5/25], and + invisible/hidden [8/28]). They are sometimes implemented by + using colors instead of what their names imply; e.g., bold is + often achieved by using brighter colors. In practice, only bold + is really available to us, underline sometimes being mapped by + the terminal to some strange color choice, and standout best + being left for use by downstream programs such as less(1). + -- We cannot assume that any of the extensions or special features + are available for the purpose of choosing defaults for everyone. + -- The most prevalent default terminal backgrounds are pure black + and pure white, and are not necessarily the same shades of + those as if they were selected explicitly with SGR sequences. + Some terminals use dark or light pictures as default background, + but those are covered over by an explicit selection of background + color with an SGR sequence; their users will appreciate their + background pictures not be covered like this, if possible. + -- Some uses of colors attributes is to make some output items + more understated (e.g., context lines); this cannot be achieved + by changing the background color. + -- For these reasons, the grep color defaults should strive not + to change the background color from its default, unless it's + for a short item that should be highlighted, not understated. + -- The grep foreground color defaults (without an explicitly set + background) should provide enough contrast to be readable on any + terminal with either a black (dark) or white (light) background. + This only leaves red, magenta, green, and cyan (and their bold + counterparts) and possibly bold blue. */ +/* The color strings used for matched text. + The user can overwrite them using the deprecated + environment variable GREP_COLOR or the new GREP_COLORS. */ +static const char *selected_match_color = "01;31"; /* bold red */ +static const char *context_match_color = "01;31"; /* bold red */ + +/* Other colors. Defaults look damn good. */ +static const char *filename_color = "35"; /* magenta */ +static const char *line_num_color = "32"; /* green */ +static const char *byte_num_color = "32"; /* green */ +static const char *sep_color = "36"; /* cyan */ +static const char *selected_line_color = ""; /* default color pair */ +static const char *context_line_color = ""; /* default color pair */ + +/* Select Graphic Rendition (SGR, "\33[...m") strings. */ +/* Also Erase in Line (EL) to Right ("\33[K") by default. */ +/* Why have EL to Right after SGR? + -- The behavior of line-wrapping when at the bottom of the + terminal screen and at the end of the current line is often + such that a new line is introduced, entirely cleared with + the current background color which may be different from the + default one (see the boolean back_color_erase terminfo(5) + capability), thus scrolling the display by one line. + The end of this new line will stay in this background color + even after reverting to the default background color with + "\33[m', unless it is explicitly cleared again with "\33[K" + (which is the behavior the user would instinctively expect + from the whole thing). There may be some unavoidable + background-color flicker at the end of this new line because + of this (when timing with the monitor's redraw is just right). + -- The behavior of HT (tab, "\t") is usually the same as that of + Cursor Forward Tabulation (CHT) with a default parameter + of 1 ("\33[I"), i.e., it performs pure movement to the next + tab stop, without any clearing of either content or screen + attributes (including background color); try + printf 'asdfqwerzxcv\rASDF\tZXCV\n' + in a bash(1) shell to demonstrate this. This is not what the + user would instinctively expect of HT (but is ok for CHT). + The instinctive behavior would include clearing the terminal + cells that are skipped over by HT with blank cells in the + current screen attributes, including background color; + the boolean dest_tabs_magic_smso terminfo(5) capability + indicates this saner behavior for HT, but only some rare + terminals have it (although it also indicates a special + glitch with standout mode in the Teleray terminal for which + it was initially introduced). The remedy is to add "\33K" + after each SGR sequence, be it START (to fix the behavior + of any HT after that before another SGR) or END (to fix the + behavior of an HT in default background color that would + follow a line-wrapping at the bottom of the screen in another + background color, and to complement doing it after START). + Piping grep's output through a pager such as less(1) avoids + any HT problems since the pager performs tab expansion. + + Generic disadvantages of this remedy are: + -- Some very rare terminals might support SGR but not EL (nobody + will use "grep --color" on a terminal that does not support + SGR in the first place). + -- Having these extra control sequences might somewhat complicate + the task of any program trying to parse "grep --color" + output in order to extract structuring information from it. + A specific disadvantage to doing it after SGR START is: + -- Even more possible background color flicker (when timing + with the monitor's redraw is just right), even when not at the + bottom of the screen. + There are no additional disadvantages specific to doing it after + SGR END. + + It would be impractical for GNU grep to become a full-fledged + terminal program linked against ncurses or the like, so it will + not detect terminfo(5) capabilities. */ +static const char *sgr_start = "\33[%sm\33[K"; +static const char *sgr_end = "\33[m\33[K"; + +/* SGR utility functions. */ +static void +pr_sgr_start (char const *s) +{ + if (*s) + print_start_colorize (sgr_start, s); +} +static void +pr_sgr_end (char const *s) +{ + if (*s) + print_end_colorize (sgr_end); +} +static void +pr_sgr_start_if (char const *s) +{ + if (color_option) + pr_sgr_start (s); +} +static void +pr_sgr_end_if (char const *s) +{ + if (color_option) + pr_sgr_end (s); +} + +struct color_cap + { + const char *name; + const char **var; + void (*fct) (void); + }; + +static void +color_cap_mt_fct (void) +{ + /* Our caller just set selected_match_color. */ + context_match_color = selected_match_color; +} + +static void +color_cap_rv_fct (void) +{ + /* By this point, it was 1 (or already -1). */ + color_option = -1; /* That's still != 0. */ +} + +static void +color_cap_ne_fct (void) +{ + sgr_start = "\33[%sm"; + sgr_end = "\33[m"; +} + +/* For GREP_COLORS. */ +static const struct color_cap color_dict[] = + { + { "mt", &selected_match_color, color_cap_mt_fct }, /* both ms/mc */ + { "ms", &selected_match_color, NULL }, /* selected matched text */ + { "mc", &context_match_color, NULL }, /* context matched text */ + { "fn", &filename_color, NULL }, /* filename */ + { "ln", &line_num_color, NULL }, /* line number */ + { "bn", &byte_num_color, NULL }, /* byte (sic) offset */ + { "se", &sep_color, NULL }, /* separator */ + { "sl", &selected_line_color, NULL }, /* selected lines */ + { "cx", &context_line_color, NULL }, /* context lines */ + { "rv", NULL, color_cap_rv_fct }, /* -v reverses sl/cx */ + { "ne", NULL, color_cap_ne_fct }, /* no EL on SGR_* */ + { NULL, NULL, NULL } + }; + +/* Saved errno value from failed output functions on stdout. */ +static int stdout_errno; + +#ifdef KMK_GREP +# ifdef KBUILD_OS_WINDOWS +# include <assert.h> +static void fwrite_errno (void const *, size_t, size_t); +static int g_fStdOutIsConsole = -1; /* TRUE or FALSE; -1 if not initialize. */ +#endif + +/* Attempts to set the code page, leave the rest of the locale as default. */ +static void kmk_grep_set_codepage (const char *pszCodepage) +{ +# ifdef KBUILD_OS_WINDOWS + /* Make sure it starts with a dot: */ + char szDot[256]; + if (pszCodepage[0] != '.') + { + snprintf (szDot, sizeof(szDot), ".%s", pszCodepage); + pszCodepage = szDot; + } + + if (setlocale (LC_ALL, pszCodepage) == NULL) + error (0, errno, _("warning: setlocale (LC_ALL, \"%s\") failed"), + pszCodepage); + + g_fStdOutIsConsole = -1; /* ensure this is reinitialized. */ +# endif +} +#endif /* KMK_GREP */ + +static void +putchar_errno (int c) +{ +#if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS) + char ch = (char)c; + fwrite_errno (&ch, 1, 1); +#else + if (putchar (c) < 0) + stdout_errno = errno; +#endif +} + +static void +fputs_errno (char const *s) +{ +#if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS) + fwrite_errno (s, 1, strlen (s)); +#else + if (fputs (s, stdout) < 0) + stdout_errno = errno; +#endif +} + +static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2) +printf_errno (char const *format, ...) +{ + va_list ap; + va_start (ap, format); +#if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS) + char szBuf[1024]; /* Only really used for a PRIuMAX number and maybe a newline. */ + int cch = vsnprintf (szBuf, sizeof (szBuf), format, ap); + assert (cch < sizeof(szBuf)); + fwrite_errno (szBuf, 1, cch); +#else + if (vfprintf (stdout, format, ap) < 0) + stdout_errno = errno; +#endif + va_end (ap); +} + +static void +fwrite_errno (void const *ptr, size_t size, size_t nmemb) +{ +#if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS) + /* + * This trick reduces the runtime of 'grep -r GNU .' in the grep source dir + * from just above 11 seconds to around 0.8 seconds. + * + * The trouble with the microsoft CRTs (both the old and the new UCRT), is + * that we end up writing one char at the time when writing to the console, + * which is a total performance killer. write_double_translated_ansi_nolock() + * and write_requires_double_translation_nolock() in lowio/write.cpp in the + * UCRT sources have further details. + */ + static HANDLE s_hStdOut = INVALID_HANDLE_VALUE; + if (g_fStdOutIsConsole != -1) + { /* likely*/ } + else + { + DWORD fModeIgnored; + s_hStdOut = (HANDLE)_get_osfhandle (fileno (stdout)); + g_fStdOutIsConsole = GetConsoleMode (s_hStdOut, &fModeIgnored) + ? TRUE : FALSE; + if (getenv ("KMK_GREP_CONSOLE_DEBUG")) + fprintf (stderr, "kmk_grep: hStdOut=%p %sconsole codepage=%u ansi=%u\n", + s_hStdOut, g_fStdOutIsConsole ? "" : "!", + get_crt_codepage (), get_ansi_codepage ()); + } + if (g_fStdOutIsConsole == TRUE && size && nmemb) + { + size_t const cbToWrite = size * nmemb; + if ( cbToWrite < (size_t)INT_MAX / 4 + && cbToWrite >= size + && cbToWrite >= nmemb) + { + /* ASSUME that one input byte won't be translated to more than one + surrogate pair, or two compound UTF-16 codepoints. */ + wchar_t awcBuf[1024]; + wchar_t *pawcFree = NULL; + wchar_t *pawcBuf; + size_t cwcBuf = cbToWrite * 2 + 16; + if (cwcBuf < sizeof(awcBuf) / sizeof(wchar_t)) + { + cwcBuf = sizeof(awcBuf) / sizeof(wchar_t); + pawcBuf = awcBuf; + } + else + pawcFree = pawcBuf = (wchar_t *)malloc(cwcBuf * sizeof(wchar_t)); + if (pawcBuf) + { + int cwcToWrite = MultiByteToWideChar(get_crt_codepage(), + 0 /*dwFlags*/, + ptr, (int)cbToWrite, + pawcBuf, (int)(cwcBuf - 1)); + if (cwcToWrite > 0) + { + pawcBuf[cwcToWrite] = '\0'; + + /* Let the CRT do the rest. At least the Visual C++ 2010 CRT + sources indicates _cputws will do the right thing. */ + fflush(stdout); + int rc = _cputws(pawcBuf); + if (pawcFree) + free(pawcFree); + if (rc != 0) + stdout_errno = errno; + return; + } + free(pawcFree); + } + } + } +#endif + if (fwrite (ptr, size, nmemb, stdout) != nmemb) + stdout_errno = errno; +} + +static void +fflush_errno (void) +{ + if (fflush (stdout) != 0) + stdout_errno = errno; +} + +static struct exclude *excluded_patterns[2]; +static struct exclude *excluded_directory_patterns[2]; +/* Short options. */ +static char const short_options[] = +"0123456789A:B:C:D:EFGHIPTUVX:abcd:e:f:hiLlm:noqRrsuvwxyZz"; + +/* Non-boolean long options that have no corresponding short equivalents. */ +enum +{ + BINARY_FILES_OPTION = CHAR_MAX + 1, + COLOR_OPTION, + EXCLUDE_DIRECTORY_OPTION, + EXCLUDE_OPTION, + EXCLUDE_FROM_OPTION, + GROUP_SEPARATOR_OPTION, + INCLUDE_OPTION, + LINE_BUFFERED_OPTION, + LABEL_OPTION, +#ifdef KMK_GREP + UTF8_OPTION, + CODEPAGE_OPTION, +#endif + NO_IGNORE_CASE_OPTION +}; + +/* Long options equivalences. */ +static struct option const long_options[] = +{ + {"basic-regexp", no_argument, NULL, 'G'}, + {"extended-regexp", no_argument, NULL, 'E'}, + {"fixed-regexp", no_argument, NULL, 'F'}, + {"fixed-strings", no_argument, NULL, 'F'}, + {"perl-regexp", no_argument, NULL, 'P'}, + {"after-context", required_argument, NULL, 'A'}, + {"before-context", required_argument, NULL, 'B'}, + {"binary-files", required_argument, NULL, BINARY_FILES_OPTION}, + {"byte-offset", no_argument, NULL, 'b'}, + {"context", required_argument, NULL, 'C'}, + {"color", optional_argument, NULL, COLOR_OPTION}, + {"colour", optional_argument, NULL, COLOR_OPTION}, + {"count", no_argument, NULL, 'c'}, + {"devices", required_argument, NULL, 'D'}, + {"directories", required_argument, NULL, 'd'}, + {"exclude", required_argument, NULL, EXCLUDE_OPTION}, + {"exclude-from", required_argument, NULL, EXCLUDE_FROM_OPTION}, + {"exclude-dir", required_argument, NULL, EXCLUDE_DIRECTORY_OPTION}, + {"file", required_argument, NULL, 'f'}, + {"files-with-matches", no_argument, NULL, 'l'}, + {"files-without-match", no_argument, NULL, 'L'}, + {"group-separator", required_argument, NULL, GROUP_SEPARATOR_OPTION}, + {"help", no_argument, &show_help, 1}, + {"include", required_argument, NULL, INCLUDE_OPTION}, + {"ignore-case", no_argument, NULL, 'i'}, + {"no-ignore-case", no_argument, NULL, NO_IGNORE_CASE_OPTION}, + {"initial-tab", no_argument, NULL, 'T'}, + {"label", required_argument, NULL, LABEL_OPTION}, + {"line-buffered", no_argument, NULL, LINE_BUFFERED_OPTION}, + {"line-number", no_argument, NULL, 'n'}, + {"line-regexp", no_argument, NULL, 'x'}, + {"max-count", required_argument, NULL, 'm'}, + + {"no-filename", no_argument, NULL, 'h'}, + {"no-group-separator", no_argument, NULL, GROUP_SEPARATOR_OPTION}, + {"no-messages", no_argument, NULL, 's'}, + {"null", no_argument, NULL, 'Z'}, + {"null-data", no_argument, NULL, 'z'}, + {"only-matching", no_argument, NULL, 'o'}, + {"quiet", no_argument, NULL, 'q'}, + {"recursive", no_argument, NULL, 'r'}, + {"dereference-recursive", no_argument, NULL, 'R'}, + {"regexp", required_argument, NULL, 'e'}, + {"invert-match", no_argument, NULL, 'v'}, + {"silent", no_argument, NULL, 'q'}, + {"text", no_argument, NULL, 'a'}, + {"binary", no_argument, NULL, 'U'}, + {"unix-byte-offsets", no_argument, NULL, 'u'}, + {"version", no_argument, NULL, 'V'}, + {"with-filename", no_argument, NULL, 'H'}, + {"word-regexp", no_argument, NULL, 'w'}, +#ifdef KMK_GREP + {"utf8", no_argument, NULL, UTF8_OPTION}, + {"cp", required_argument, NULL, CODEPAGE_OPTION}, + {"codepage", required_argument, NULL, CODEPAGE_OPTION}, +#endif + {0, 0, 0, 0} +}; + +/* Define flags declared in grep.h. */ +bool match_icase; +bool match_words; +bool match_lines; +char eolbyte; + +/* For error messages. */ +/* The input file name, or (if standard input) null or a --label argument. */ +static char const *filename; +/* Omit leading "./" from file names in diagnostics. */ +static bool omit_dot_slash; +static bool errseen; + +/* True if output from the current input file has been suppressed + because an output line had an encoding error. */ +static bool encoding_error_output; + +enum directories_type + { + READ_DIRECTORIES = 2, + RECURSE_DIRECTORIES, + SKIP_DIRECTORIES + }; + +/* How to handle directories. */ +static char const *const directories_args[] = +{ + "read", "recurse", "skip", NULL +}; +static enum directories_type const directories_types[] = +{ + READ_DIRECTORIES, RECURSE_DIRECTORIES, SKIP_DIRECTORIES +}; +ARGMATCH_VERIFY (directories_args, directories_types); + +static enum directories_type directories = READ_DIRECTORIES; + +enum { basic_fts_options = FTS_CWDFD | FTS_NOSTAT | FTS_TIGHT_CYCLE_CHECK }; +static int fts_options = basic_fts_options | FTS_COMFOLLOW | FTS_PHYSICAL; + +/* How to handle devices. */ +static enum + { + READ_COMMAND_LINE_DEVICES, + READ_DEVICES, + SKIP_DEVICES + } devices = READ_COMMAND_LINE_DEVICES; + +static bool grepfile (int, char const *, bool, bool); +static bool grepdesc (int, bool); + +static bool +is_device_mode (mode_t m) +{ + return S_ISCHR (m) || S_ISBLK (m) || S_ISSOCK (m) || S_ISFIFO (m); +} + +static bool +skip_devices (bool command_line) +{ + return (devices == SKIP_DEVICES + || ((devices == READ_COMMAND_LINE_DEVICES) & !command_line)); +} + +/* Return if ST->st_size is defined. Assume the file is not a + symbolic link. */ +static bool +usable_st_size (struct stat const *st) +{ + return S_ISREG (st->st_mode) || S_TYPEISSHM (st) || S_TYPEISTMO (st); +} + +/* Lame substitutes for SEEK_DATA and SEEK_HOLE on platforms lacking them. + Do not rely on these finding data or holes if they equal SEEK_SET. */ +#ifndef SEEK_DATA +enum { SEEK_DATA = SEEK_SET }; +#endif +#ifndef SEEK_HOLE +enum { SEEK_HOLE = SEEK_SET }; +#endif + +/* True if lseek with SEEK_CUR or SEEK_DATA failed on the current input. */ +static bool seek_failed; +static bool seek_data_failed; + +/* Functions we'll use to search. */ +typedef void *(*compile_fp_t) (char *, size_t, reg_syntax_t, bool); +typedef size_t (*execute_fp_t) (void *, char const *, size_t, size_t *, + char const *); +static execute_fp_t execute; +static void *compiled_pattern; + +char const * +input_filename (void) +{ + if (!filename) + filename = _("(standard input)"); + return filename; +} + +/* Unless requested, diagnose an error about the input file. */ +static void +suppressible_error (int errnum) +{ + if (! suppress_errors) + error (0, errnum, "%s", input_filename ()); + errseen = true; +} + +/* If there has already been a write error, don't bother closing + standard output, as that might elicit a duplicate diagnostic. */ +static void +clean_up_stdout (void) +{ + if (! stdout_errno) + close_stdout (); +} + +/* A cast to TYPE of VAL. Use this when TYPE is a pointer type, VAL + is properly aligned for TYPE, and 'gcc -Wcast-align' cannot infer + the alignment and would otherwise complain about the cast. */ +#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# define CAST_ALIGNED(type, val) \ + ({ __typeof__ (val) val_ = val; \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wcast-align\"") \ + (type) val_; \ + _Pragma ("GCC diagnostic pop") \ + }) +#else +# define CAST_ALIGNED(type, val) ((type) (val)) +#endif + +/* An unsigned type suitable for fast matching. */ +typedef uintmax_t uword; +static uword const uword_max = UINTMAX_MAX; + +struct localeinfo localeinfo; + +/* A mask to test for unibyte characters, with the pattern repeated to + fill a uword. For a multibyte character encoding where + all bytes are unibyte characters, this is 0. For UTF-8, this is + 0x808080.... For encodings where unibyte characters have no discerned + pattern, this is all 1s. The unsigned char C is a unibyte + character if C & UNIBYTE_MASK is zero. If the uword W is the + concatenation of bytes, the bytes are all unibyte characters + if W & UNIBYTE_MASK is zero. */ +static uword unibyte_mask; + +static void +initialize_unibyte_mask (void) +{ + /* For each encoding error I that MASK does not already match, + accumulate I's most significant 1 bit by ORing it into MASK. + Although any 1 bit of I could be used, in practice high-order + bits work better. */ + unsigned char mask = 0; + int ms1b = 1; + for (int i = 1; i <= UCHAR_MAX; i++) + if ((localeinfo.sbclen[i] != 1) & ! (mask & i)) + { + while (ms1b * 2 <= i) + ms1b *= 2; + mask |= ms1b; + } + + /* Now MASK will detect any encoding-error byte, although it may + cry wolf and it may not be optimal. Build a uword-length mask by + repeating MASK. */ + unibyte_mask = uword_max / UCHAR_MAX * mask; +} + +/* Skip the easy bytes in a buffer that is guaranteed to have a sentinel + that is not easy, and return a pointer to the first non-easy byte. + The easy bytes all have UNIBYTE_MASK off. */ +static char const * _GL_ATTRIBUTE_PURE +skip_easy_bytes (char const *buf) +{ + /* Search a byte at a time until the pointer is aligned, then a + uword at a time until a match is found, then a byte at a time to + identify the exact byte. The uword search may go slightly past + the buffer end, but that's benign. */ + char const *p; + uword const *s; + for (p = buf; (uintptr_t) p % sizeof (uword) != 0; p++) + if (to_uchar (*p) & unibyte_mask) + return p; + for (s = CAST_ALIGNED (uword const *, p); ! (*s & unibyte_mask); s++) + continue; + for (p = (char const *) s; ! (to_uchar (*p) & unibyte_mask); p++) + continue; + return p; +} + +/* Return true if BUF, of size SIZE, has an encoding error. + BUF must be followed by at least sizeof (uword) bytes, + the first of which may be modified. */ +static bool +buf_has_encoding_errors (char *buf, size_t size) +{ + if (! unibyte_mask) + return false; + + mbstate_t mbs = { 0 }; + size_t clen; + + buf[size] = -1; + for (char const *p = buf; (p = skip_easy_bytes (p)) < buf + size; p += clen) + { + clen = mbrlen (p, buf + size - p, &mbs); + if ((size_t) -2 <= clen) + return true; + } + + return false; +} + + +/* Return true if BUF, of size SIZE, has a null byte. + BUF must be followed by at least one byte, + which may be arbitrarily written to or read from. */ +static bool +buf_has_nulls (char *buf, size_t size) +{ + buf[size] = 0; + return strlen (buf) != size; +} + +/* Return true if a file is known to contain null bytes. + SIZE bytes have already been read from the file + with descriptor FD and status ST. */ +static bool +file_must_have_nulls (size_t size, int fd, struct stat const *st) +{ + /* If the file has holes, it must contain a null byte somewhere. */ + if (SEEK_HOLE != SEEK_SET && !seek_failed + && usable_st_size (st) && size < st->st_size) + { + off_t cur = size; + if (O_BINARY || fd == STDIN_FILENO) + { + cur = lseek (fd, 0, SEEK_CUR); + if (cur < 0) + return false; + } + + /* Look for a hole after the current location. */ + off_t hole_start = lseek (fd, cur, SEEK_HOLE); + if (0 <= hole_start) + { + if (lseek (fd, cur, SEEK_SET) < 0) + suppressible_error (errno); + if (hole_start < st->st_size) + return true; + } + } + + return false; +} + +/* Convert STR to a nonnegative integer, storing the result in *OUT. + STR must be a valid context length argument; report an error if it + isn't. Silently ceiling *OUT at the maximum value, as that is + practically equivalent to infinity for grep's purposes. */ +static void +context_length_arg (char const *str, intmax_t *out) +{ + switch (xstrtoimax (str, 0, 10, out, "")) + { + case LONGINT_OK: + case LONGINT_OVERFLOW: + if (0 <= *out) + break; + FALLTHROUGH; + default: + die (EXIT_TROUBLE, 0, "%s: %s", str, + _("invalid context length argument")); + } +} + +/* Return the add_exclude options suitable for excluding a file name. + If COMMAND_LINE, it is a command-line file name. */ +static int +exclude_options (bool command_line) +{ + return EXCLUDE_WILDCARDS | (command_line ? 0 : EXCLUDE_ANCHORED); +} + +/* Return true if the file with NAME should be skipped. + If COMMAND_LINE, it is a command-line argument. + If IS_DIR, it is a directory. */ +static bool +skipped_file (char const *name, bool command_line, bool is_dir) +{ + struct exclude **pats; + if (! is_dir) + pats = excluded_patterns; + else if (directories == SKIP_DIRECTORIES) + return true; + else if (command_line && omit_dot_slash) + return false; + else + pats = excluded_directory_patterns; + return pats[command_line] && excluded_file_name (pats[command_line], name); +} + +/* Hairy buffering mechanism for grep. The intent is to keep + all reads aligned on a page boundary and multiples of the + page size, unless a read yields a partial page. */ + +static char *buffer; /* Base of buffer. */ +static size_t bufalloc; /* Allocated buffer size, counting slop. */ +static int bufdesc; /* File descriptor. */ +static char *bufbeg; /* Beginning of user-visible stuff. */ +static char *buflim; /* Limit of user-visible stuff. */ +static size_t pagesize; /* alignment of memory pages */ +static off_t bufoffset; /* Read offset. */ +static off_t after_last_match; /* Pointer after last matching line that + would have been output if we were + outputting characters. */ +static bool skip_nuls; /* Skip '\0' in data. */ +static bool skip_empty_lines; /* Skip empty lines in data. */ +static uintmax_t totalnl; /* Total newline count before lastnl. */ + +/* Initial buffer size, not counting slop. */ +enum { INITIAL_BUFSIZE = 96 * 1024 }; + +/* Return VAL aligned to the next multiple of ALIGNMENT. VAL can be + an integer or a pointer. Both args must be free of side effects. */ +#define ALIGN_TO(val, alignment) \ + ((uintptr_t) (val) % (alignment) == 0 \ + ? (val) \ + : (val) + ((alignment) - (uintptr_t) (val) % (alignment))) + +/* Add two numbers that count input bytes or lines, and report an + error if the addition overflows. */ +static uintmax_t +add_count (uintmax_t a, uintmax_t b) +{ + uintmax_t sum = a + b; + if (sum < a) + die (EXIT_TROUBLE, 0, _("input is too large to count")); + return sum; +} + +/* Return true if BUF (of size SIZE) is all zeros. */ +static bool +all_zeros (char const *buf, size_t size) +{ + for (char const *p = buf; p < buf + size; p++) + if (*p) + return false; + return true; +} + +/* Reset the buffer for a new file, returning false if we should skip it. + Initialize on the first time through. */ +static bool +reset (int fd, struct stat const *st) +{ + bufbeg = buflim = ALIGN_TO (buffer + 1, pagesize); + bufbeg[-1] = eolbyte; + bufdesc = fd; + bufoffset = fd == STDIN_FILENO ? lseek (fd, 0, SEEK_CUR) : 0; + seek_failed = bufoffset < 0; + + /* Assume SEEK_DATA fails if SEEK_CUR does. */ + seek_data_failed = seek_failed; + + if (seek_failed) + { + if (errno != ESPIPE) + { + suppressible_error (errno); + return false; + } + bufoffset = 0; + } + return true; +} + +/* Read new stuff into the buffer, saving the specified + amount of old stuff. When we're done, 'bufbeg' points + to the beginning of the buffer contents, and 'buflim' + points just after the end. Return false if there's an error. */ +static bool +fillbuf (size_t save, struct stat const *st) +{ + size_t fillsize; + bool cc = true; + char *readbuf; + size_t readsize; + + if (pagesize <= buffer + bufalloc - sizeof (uword) - buflim) + readbuf = buflim; + else + { + size_t minsize = save + pagesize; + size_t newsize; + size_t newalloc; + char *newbuf; + + /* Grow newsize until it is at least as great as minsize. */ + for (newsize = bufalloc - pagesize - sizeof (uword); + newsize < minsize; + newsize *= 2) + if ((SIZE_MAX - pagesize - sizeof (uword)) / 2 < newsize) + xalloc_die (); + + /* Try not to allocate more memory than the file size indicates, + as that might cause unnecessary memory exhaustion if the file + is large. However, do not use the original file size as a + heuristic if we've already read past the file end, as most + likely the file is growing. */ + if (usable_st_size (st)) + { + off_t to_be_read = st->st_size - bufoffset; + off_t maxsize_off = save + to_be_read; + if (0 <= to_be_read && to_be_read <= maxsize_off + && maxsize_off == (size_t) maxsize_off + && minsize <= (size_t) maxsize_off + && (size_t) maxsize_off < newsize) + newsize = maxsize_off; + } + + /* Add enough room so that the buffer is aligned and has room + for byte sentinels fore and aft, and so that a uword can + be read aft. */ + newalloc = newsize + pagesize + sizeof (uword); + + newbuf = bufalloc < newalloc ? xmalloc (bufalloc = newalloc) : buffer; + readbuf = ALIGN_TO (newbuf + 1 + save, pagesize); + size_t moved = save + 1; /* Move the preceding byte sentinel too. */ + memmove (readbuf - moved, buflim - moved, moved); + if (newbuf != buffer) + { + free (buffer); + buffer = newbuf; + } + } + + bufbeg = readbuf - save; + + clear_asan_poison (); + + readsize = buffer + bufalloc - sizeof (uword) - readbuf; + readsize -= readsize % pagesize; + + while (true) + { + fillsize = safe_read (bufdesc, readbuf, readsize); + if (fillsize == SAFE_READ_ERROR) + { + fillsize = 0; + cc = false; + } + bufoffset += fillsize; + + if (((fillsize == 0) | !skip_nuls) || !all_zeros (readbuf, fillsize)) + break; + totalnl = add_count (totalnl, fillsize); + + if (SEEK_DATA != SEEK_SET && !seek_data_failed) + { + /* Solaris SEEK_DATA fails with errno == ENXIO in a hole at EOF. */ + off_t data_start = lseek (bufdesc, bufoffset, SEEK_DATA); + if (data_start < 0 && errno == ENXIO + && usable_st_size (st) && bufoffset < st->st_size) + data_start = lseek (bufdesc, 0, SEEK_END); + + if (data_start < 0) + seek_data_failed = true; + else + { + totalnl = add_count (totalnl, data_start - bufoffset); + bufoffset = data_start; + } + } + } + + buflim = readbuf + fillsize; + + /* Initialize the following word, because skip_easy_bytes and some + matchers read (but do not use) those bytes. This avoids false + positive reports of these bytes being used uninitialized. */ + memset (buflim, 0, sizeof (uword)); + + /* Mark the part of the buffer not filled by the read or set by + the above memset call as ASAN-poisoned. */ + asan_poison (buflim + sizeof (uword), + bufalloc - (buflim - buffer) - sizeof (uword)); + + return cc; +} + +/* Flags controlling the style of output. */ +static enum +{ + BINARY_BINARY_FILES, + TEXT_BINARY_FILES, + WITHOUT_MATCH_BINARY_FILES +} binary_files; /* How to handle binary files. */ + +/* Options for output as a list of matching/non-matching files */ +static enum +{ + LISTFILES_NONE, + LISTFILES_MATCHING, + LISTFILES_NONMATCHING, +} list_files; + +/* Whether to output filenames. 1 means yes, 0 means no, and -1 means + 'grep -r PATTERN FILE' was used and it is not known yet whether + FILE is a directory (which means yes) or not (which means no). */ +static int out_file; + +static int filename_mask; /* If zero, output nulls after filenames. */ +static bool out_quiet; /* Suppress all normal output. */ +static bool out_invert; /* Print nonmatching stuff. */ +static bool out_line; /* Print line numbers. */ +static bool out_byte; /* Print byte offsets. */ +static intmax_t out_before; /* Lines of leading context. */ +static intmax_t out_after; /* Lines of trailing context. */ +static bool count_matches; /* Count matching lines. */ +static intmax_t max_count; /* Max number of selected + lines from an input file. */ +static bool line_buffered; /* Use line buffering. */ +static char *label = NULL; /* Fake filename for stdin */ + + +/* Internal variables to keep track of byte count, context, etc. */ +static uintmax_t totalcc; /* Total character count before bufbeg. */ +static char const *lastnl; /* Pointer after last newline counted. */ +static char *lastout; /* Pointer after last character output; + NULL if no character has been output + or if it's conceptually before bufbeg. */ +static intmax_t outleft; /* Maximum number of selected lines. */ +static intmax_t pending; /* Pending lines of output. + Always kept 0 if out_quiet is true. */ +static bool done_on_match; /* Stop scanning file on first match. */ +static bool exit_on_match; /* Exit on first match. */ +static bool dev_null_output; /* Stdout is known to be /dev/null. */ +static bool binary; /* Use binary rather than text I/O. */ + +static void +nlscan (char const *lim) +{ + size_t newlines = 0; + for (char const *beg = lastnl; beg < lim; beg++) + { + beg = memchr (beg, eolbyte, lim - beg); + if (!beg) + break; + newlines++; + } + totalnl = add_count (totalnl, newlines); + lastnl = lim; +} + +/* Print the current filename. */ +static void +print_filename (void) +{ + pr_sgr_start_if (filename_color); + fputs_errno (input_filename ()); + pr_sgr_end_if (filename_color); +} + +/* Print a character separator. */ +static void +print_sep (char sep) +{ + pr_sgr_start_if (sep_color); + putchar_errno (sep); + pr_sgr_end_if (sep_color); +} + +/* Print a line number or a byte offset. */ +static void +print_offset (uintmax_t pos, const char *color) +{ + pr_sgr_start_if (color); + printf_errno ("%*"PRIuMAX, offset_width, pos); + pr_sgr_end_if (color); +} + +/* Print a whole line head (filename, line, byte). The output data + starts at BEG and contains LEN bytes; it is followed by at least + sizeof (uword) bytes, the first of which may be temporarily modified. + The output data comes from what is perhaps a larger input line that + goes until LIM, where LIM[-1] is an end-of-line byte. Use SEP as + the separator on output. + + Return true unless the line was suppressed due to an encoding error. */ + +static bool +print_line_head (char *beg, size_t len, char const *lim, char sep) +{ + if (binary_files != TEXT_BINARY_FILES) + { + char ch = beg[len]; + bool encoding_errors = buf_has_encoding_errors (beg, len); + beg[len] = ch; + if (encoding_errors) + { + encoding_error_output = true; + return false; + } + } + + if (out_file) + { + print_filename (); + if (filename_mask) + print_sep (sep); + else + putchar_errno (0); + } + + if (out_line) + { + if (lastnl < lim) + { + nlscan (beg); + totalnl = add_count (totalnl, 1); + lastnl = lim; + } + print_offset (totalnl, line_num_color); + print_sep (sep); + } + + if (out_byte) + { + uintmax_t pos = add_count (totalcc, beg - bufbeg); + print_offset (pos, byte_num_color); + print_sep (sep); + } + + if (align_tabs && (out_file | out_line | out_byte) && len != 0) + putchar_errno ('\t'); + + return true; +} + +static char * +print_line_middle (char *beg, char *lim, + const char *line_color, const char *match_color) +{ + size_t match_size; + size_t match_offset; + char *cur; + char *mid = NULL; + char *b; + + for (cur = beg; + (cur < lim + && ((match_offset = execute (compiled_pattern, beg, lim - beg, + &match_size, cur)) != (size_t) -1)); + cur = b + match_size) + { + b = beg + match_offset; + + /* Avoid matching the empty line at the end of the buffer. */ + if (b == lim) + break; + + /* Avoid hanging on grep --color "" foo */ + if (match_size == 0) + { + /* Make minimal progress; there may be further non-empty matches. */ + /* XXX - Could really advance by one whole multi-octet character. */ + match_size = 1; + if (!mid) + mid = cur; + } + else + { + /* This function is called on a matching line only, + but is it selected or rejected/context? */ + if (only_matching) + { + char sep = out_invert ? SEP_CHAR_REJECTED : SEP_CHAR_SELECTED; + if (! print_line_head (b, match_size, lim, sep)) + return NULL; + } + else + { + pr_sgr_start (line_color); + if (mid) + { + cur = mid; + mid = NULL; + } + fwrite_errno (cur, 1, b - cur); + } + + pr_sgr_start_if (match_color); + fwrite_errno (b, 1, match_size); + pr_sgr_end_if (match_color); + if (only_matching) + putchar_errno (eolbyte); + } + } + + if (only_matching) + cur = lim; + else if (mid) + cur = mid; + + return cur; +} + +static char * +print_line_tail (char *beg, const char *lim, const char *line_color) +{ + size_t eol_size; + size_t tail_size; + + eol_size = (lim > beg && lim[-1] == eolbyte); + eol_size += (lim - eol_size > beg && lim[-(1 + eol_size)] == '\r'); + tail_size = lim - eol_size - beg; + + if (tail_size > 0) + { + pr_sgr_start (line_color); + fwrite_errno (beg, 1, tail_size); + beg += tail_size; + pr_sgr_end (line_color); + } + + return beg; +} + +static void +prline (char *beg, char *lim, char sep) +{ + bool matching; + const char *line_color; + const char *match_color; + + if (!only_matching) + if (! print_line_head (beg, lim - beg - 1, lim, sep)) + return; + + matching = (sep == SEP_CHAR_SELECTED) ^ out_invert; + + if (color_option) + { + line_color = (((sep == SEP_CHAR_SELECTED) + ^ (out_invert && (color_option < 0))) + ? selected_line_color : context_line_color); + match_color = (sep == SEP_CHAR_SELECTED + ? selected_match_color : context_match_color); + } + else + line_color = match_color = NULL; /* Shouldn't be used. */ + + if ((only_matching && matching) + || (color_option && (*line_color || *match_color))) + { + /* We already know that non-matching lines have no match (to colorize). */ + if (matching && (only_matching || *match_color)) + { + beg = print_line_middle (beg, lim, line_color, match_color); + if (! beg) + return; + } + + if (!only_matching && *line_color) + { + /* This code is exercised at least when grep is invoked like this: + echo k| GREP_COLORS='sl=01;32' src/grep k --color=always */ + beg = print_line_tail (beg, lim, line_color); + } + } + + if (!only_matching && lim > beg) + fwrite_errno (beg, 1, lim - beg); + + if (line_buffered) + fflush_errno (); + + if (stdout_errno) + die (EXIT_TROUBLE, stdout_errno, _("write error")); + + lastout = lim; +} + +/* Print pending lines of trailing context prior to LIM. */ +static void +prpending (char const *lim) +{ + if (!lastout) + lastout = bufbeg; + for (; 0 < pending && lastout < lim; pending--) + { + char *nl = rawmemchr (lastout, eolbyte); + prline (lastout, nl + 1, SEP_CHAR_REJECTED); + } +} + +/* Output the lines between BEG and LIM. Deal with context. */ +static void +prtext (char *beg, char *lim) +{ + static bool used; /* Avoid printing SEP_STR_GROUP before any output. */ + char eol = eolbyte; + + if (!out_quiet && pending > 0) + prpending (beg); + + char *p = beg; + + if (!out_quiet) + { + /* Deal with leading context. */ + char const *bp = lastout ? lastout : bufbeg; + intmax_t i; + for (i = 0; i < out_before; ++i) + if (p > bp) + do + --p; + while (p[-1] != eol); + + /* Print the group separator unless the output is adjacent to + the previous output in the file. */ + if ((0 <= out_before || 0 <= out_after) && used + && p != lastout && group_separator) + { + pr_sgr_start_if (sep_color); + fputs_errno (group_separator); + pr_sgr_end_if (sep_color); + putchar_errno ('\n'); + } + + while (p < beg) + { + char *nl = rawmemchr (p, eol); + nl++; + prline (p, nl, SEP_CHAR_REJECTED); + p = nl; + } + } + + intmax_t n; + if (out_invert) + { + /* One or more lines are output. */ + for (n = 0; p < lim && n < outleft; n++) + { + char *nl = rawmemchr (p, eol); + nl++; + if (!out_quiet) + prline (p, nl, SEP_CHAR_SELECTED); + p = nl; + } + } + else + { + /* Just one line is output. */ + if (!out_quiet) + prline (beg, lim, SEP_CHAR_SELECTED); + n = 1; + p = lim; + } + + after_last_match = bufoffset - (buflim - p); + pending = out_quiet ? 0 : MAX (0, out_after); + used = true; + outleft -= n; +} + +/* Replace all NUL bytes in buffer P (which ends at LIM) with EOL. + This avoids running out of memory when binary input contains a long + sequence of zeros, which would otherwise be considered to be part + of a long line. P[LIM] should be EOL. */ +static void +zap_nuls (char *p, char *lim, char eol) +{ + if (eol) + while (true) + { + *lim = '\0'; + p += strlen (p); + *lim = eol; + if (p == lim) + break; + do + *p++ = eol; + while (!*p); + } +} + +/* Scan the specified portion of the buffer, matching lines (or + between matching lines if OUT_INVERT is true). Return a count of + lines printed. Replace all NUL bytes with NUL_ZAPPER as we go. */ +static intmax_t +grepbuf (char *beg, char const *lim) +{ + intmax_t outleft0 = outleft; + char *endp; + + for (char *p = beg; p < lim; p = endp) + { + size_t match_size; + size_t match_offset = execute (compiled_pattern, p, lim - p, + &match_size, NULL); + if (match_offset == (size_t) -1) + { + if (!out_invert) + break; + match_offset = lim - p; + match_size = 0; + } + char *b = p + match_offset; + endp = b + match_size; + /* Avoid matching the empty line at the end of the buffer. */ + if (!out_invert && b == lim) + break; + if (!out_invert || p < b) + { + char *prbeg = out_invert ? p : b; + char *prend = out_invert ? b : endp; + prtext (prbeg, prend); + if (!outleft || done_on_match) + { + if (exit_on_match) + exit (errseen ? exit_failure : EXIT_SUCCESS); + break; + } + } + } + + return outleft0 - outleft; +} + +/* Search a given (non-directory) file. Return a count of lines printed. + Set *INEOF to true if end-of-file reached. */ +static intmax_t +grep (int fd, struct stat const *st, bool *ineof) +{ + intmax_t nlines, i; + size_t residue, save; + char oldc; + char *beg; + char *lim; + char eol = eolbyte; + char nul_zapper = '\0'; + bool done_on_match_0 = done_on_match; + bool out_quiet_0 = out_quiet; + + /* The value of NLINES when nulls were first deduced in the input; + this is not necessarily the same as the number of matching lines + before the first null. -1 if no input nulls have been deduced. */ + intmax_t nlines_first_null = -1; + + if (! reset (fd, st)) + return 0; + + totalcc = 0; + lastout = 0; + totalnl = 0; + outleft = max_count; + after_last_match = 0; + pending = 0; + skip_nuls = skip_empty_lines && !eol; + encoding_error_output = false; + + nlines = 0; + residue = 0; + save = 0; + + if (! fillbuf (save, st)) + { + suppressible_error (errno); + return 0; + } + + offset_width = 0; + if (align_tabs) + { + /* Width is log of maximum number. Line numbers are origin-1. */ + uintmax_t num = usable_st_size (st) ? st->st_size : UINTMAX_MAX; + num += out_line && num < UINTMAX_MAX; + do + offset_width++; + while ((num /= 10) != 0); + } + + for (bool firsttime = true; ; firsttime = false) + { + if (nlines_first_null < 0 && eol && binary_files != TEXT_BINARY_FILES + && (buf_has_nulls (bufbeg, buflim - bufbeg) + || (firsttime && file_must_have_nulls (buflim - bufbeg, fd, st)))) + { + if (binary_files == WITHOUT_MATCH_BINARY_FILES) + return 0; + if (!count_matches) + done_on_match = out_quiet = true; + nlines_first_null = nlines; + nul_zapper = eol; + skip_nuls = skip_empty_lines; + } + + lastnl = bufbeg; + if (lastout) + lastout = bufbeg; + + beg = bufbeg + save; + + /* no more data to scan (eof) except for maybe a residue -> break */ + if (beg == buflim) + { + *ineof = true; + break; + } + + zap_nuls (beg, buflim, nul_zapper); + + /* Determine new residue (the length of an incomplete line at the end of + the buffer, 0 means there is no incomplete last line). */ + oldc = beg[-1]; + beg[-1] = eol; + /* FIXME: use rawmemrchr if/when it exists, since we have ensured + that this use of memrchr is guaranteed never to return NULL. */ + lim = memrchr (beg - 1, eol, buflim - beg + 1); + ++lim; + beg[-1] = oldc; + if (lim == beg) + lim = beg - residue; + beg -= residue; + residue = buflim - lim; + + if (beg < lim) + { + if (outleft) + nlines += grepbuf (beg, lim); + if (pending) + prpending (lim); + if ((!outleft && !pending) + || (done_on_match && MAX (0, nlines_first_null) < nlines)) + goto finish_grep; + } + + /* The last OUT_BEFORE lines at the end of the buffer will be needed as + leading context if there is a matching line at the begin of the + next data. Make beg point to their begin. */ + i = 0; + beg = lim; + while (i < out_before && beg > bufbeg && beg != lastout) + { + ++i; + do + --beg; + while (beg[-1] != eol); + } + + /* Detect whether leading context is adjacent to previous output. */ + if (beg != lastout) + lastout = 0; + + /* Handle some details and read more data to scan. */ + save = residue + lim - beg; + if (out_byte) + totalcc = add_count (totalcc, buflim - bufbeg - save); + if (out_line) + nlscan (beg); + if (! fillbuf (save, st)) + { + suppressible_error (errno); + goto finish_grep; + } + } + if (residue) + { + *buflim++ = eol; + if (outleft) + nlines += grepbuf (bufbeg + save - residue, buflim); + if (pending) + prpending (buflim); + } + + finish_grep: + done_on_match = done_on_match_0; + out_quiet = out_quiet_0; + if (binary_files == BINARY_BINARY_FILES && ! (out_quiet | suppress_errors) + && (encoding_error_output + || (0 <= nlines_first_null && nlines_first_null < nlines))) + error (0, 0, _("%s: binary file matches"), input_filename ()); + return nlines; +} + +static bool +grepdirent (FTS *fts, FTSENT *ent, bool command_line) +{ + bool follow; + command_line &= ent->fts_level == FTS_ROOTLEVEL; + + if (ent->fts_info == FTS_DP) + return true; + + if (!command_line + && skipped_file (ent->fts_name, false, + (ent->fts_info == FTS_D || ent->fts_info == FTS_DC + || ent->fts_info == FTS_DNR))) + { + fts_set (fts, ent, FTS_SKIP); + return true; + } + + filename = ent->fts_path; + if (omit_dot_slash && filename[1]) + filename += 2; + follow = (fts->fts_options & FTS_LOGICAL + || (fts->fts_options & FTS_COMFOLLOW && command_line)); + + switch (ent->fts_info) + { + case FTS_D: + if (directories == RECURSE_DIRECTORIES) + return true; + fts_set (fts, ent, FTS_SKIP); + break; + + case FTS_DC: + if (!suppress_errors) + error (0, 0, _("%s: warning: recursive directory loop"), filename); + return true; + + case FTS_DNR: + case FTS_ERR: + case FTS_NS: + suppressible_error (ent->fts_errno); + return true; + + case FTS_DEFAULT: + case FTS_NSOK: + if (skip_devices (command_line)) + { + struct stat *st = ent->fts_statp; +#if !defined(KMK_GREP) || !defined(_MSC_VER) /** @todo revisit this */ + struct stat st1; + if (! st->st_mode) + { + /* The file type is not already known. Get the file status + before opening, since opening might have side effects + on a device. */ + int flag = follow ? 0 : AT_SYMLINK_NOFOLLOW; + if (fstatat (fts->fts_cwd_fd, ent->fts_accpath, &st1, flag) != 0) + { + suppressible_error (errno); + return true; + } + st = &st1; + } +#endif + if (is_device_mode (st->st_mode)) + return true; + } + break; + + case FTS_F: + case FTS_SLNONE: + break; + + case FTS_SL: + case FTS_W: + return true; + + default: + abort (); + } + + return grepfile (fts->fts_cwd_fd, ent->fts_accpath, follow, command_line); +} + +/* True if errno is ERR after 'open ("symlink", ... O_NOFOLLOW ...)'. + POSIX specifies ELOOP, but it's EMLINK on FreeBSD and EFTYPE on NetBSD. */ +static bool +open_symlink_nofollow_error (int err) +{ + if (err == ELOOP || err == EMLINK) + return true; +#ifdef EFTYPE + if (err == EFTYPE) + return true; +#endif + return false; +} + +static bool +grepfile (int dirdesc, char const *name, bool follow, bool command_line) +{ + int oflag = (O_RDONLY | O_NOCTTY + | (IGNORE_DUPLICATE_BRANCH_WARNING + (binary ? O_BINARY : 0)) + | (follow ? 0 : O_NOFOLLOW) + | (skip_devices (command_line) ? O_NONBLOCK : 0)); + int desc = openat_safer (dirdesc, name, oflag); + if (desc < 0) + { + if (follow || ! open_symlink_nofollow_error (errno)) + suppressible_error (errno); + return true; + } + return grepdesc (desc, command_line); +} + +/* Read all data from FD, with status ST. Return true if successful, + false (setting errno) otherwise. */ +static bool +drain_input (int fd, struct stat const *st) +{ + ssize_t nbytes; + if (S_ISFIFO (st->st_mode) && dev_null_output) + { +#ifdef SPLICE_F_MOVE + /* Should be faster, since it need not copy data to user space. */ + nbytes = splice (fd, NULL, STDOUT_FILENO, NULL, + INITIAL_BUFSIZE, SPLICE_F_MOVE); + if (0 <= nbytes || errno != EINVAL) + { + while (0 < nbytes) + nbytes = splice (fd, NULL, STDOUT_FILENO, NULL, + INITIAL_BUFSIZE, SPLICE_F_MOVE); + return nbytes == 0; + } +#endif + } + while ((nbytes = safe_read (fd, buffer, bufalloc))) + if (nbytes == SAFE_READ_ERROR) + return false; + return true; +} + +/* Finish reading from FD, with status ST and where end-of-file has + been seen if INEOF. Typically this is a no-op, but when reading + from standard input this may adjust the file offset or drain a + pipe. */ + +static void +finalize_input (int fd, struct stat const *st, bool ineof) +{ + if (fd == STDIN_FILENO + && (outleft + ? (!ineof + && (seek_failed + || (lseek (fd, 0, SEEK_END) < 0 + /* Linux proc file system has EINVAL (Bug#25180). */ + && errno != EINVAL)) + && ! drain_input (fd, st)) + : (bufoffset != after_last_match && !seek_failed + && lseek (fd, after_last_match, SEEK_SET) < 0))) + suppressible_error (errno); +} + +static bool +grepdesc (int desc, bool command_line) +{ + intmax_t count; + bool status = true; + bool ineof = false; + struct stat st; + + /* Get the file status, possibly for the second time. This catches + a race condition if the directory entry changes after the + directory entry is read and before the file is opened. For + example, normally DESC is a directory only at the top level, but + there is an exception if some other process substitutes a + directory for a non-directory while 'grep' is running. */ + if (fstat (desc, &st) != 0) + { + suppressible_error (errno); + goto closeout; + } + + if (desc != STDIN_FILENO && skip_devices (command_line) + && is_device_mode (st.st_mode)) + goto closeout; + + if (desc != STDIN_FILENO && command_line + && skipped_file (filename, true, S_ISDIR (st.st_mode) != 0)) + goto closeout; + + /* Don't output file names if invoked as 'grep -r PATTERN NONDIRECTORY'. */ + if (out_file < 0) + out_file = !!S_ISDIR (st.st_mode); + + if (desc != STDIN_FILENO + && directories == RECURSE_DIRECTORIES && S_ISDIR (st.st_mode)) + { + /* Traverse the directory starting with its full name, because + unfortunately fts provides no way to traverse the directory + starting from its file descriptor. */ + + FTS *fts; + FTSENT *ent; + int opts = fts_options & ~(command_line ? 0 : FTS_COMFOLLOW); + char *fts_arg[2]; + + /* Close DESC now, to conserve file descriptors if the race + condition occurs many times in a deep recursion. */ + if (close (desc) != 0) + suppressible_error (errno); + + fts_arg[0] = (char *) filename; + fts_arg[1] = NULL; + fts = fts_open (fts_arg, opts, NULL); + + if (!fts) + xalloc_die (); + while ((ent = fts_read (fts))) + status &= grepdirent (fts, ent, command_line); + if (errno) + suppressible_error (errno); + if (fts_close (fts) != 0) + suppressible_error (errno); + return status; + } + if (desc != STDIN_FILENO + && ((directories == SKIP_DIRECTORIES && S_ISDIR (st.st_mode)) + || ((devices == SKIP_DEVICES + || (devices == READ_COMMAND_LINE_DEVICES && !command_line)) + && is_device_mode (st.st_mode)))) + goto closeout; + + /* If there is a regular file on stdout and the current file refers + to the same i-node, we have to report the problem and skip it. + Otherwise when matching lines from some other input reach the + disk before we open this file, we can end up reading and matching + those lines and appending them to the file from which we're reading. + Then we'd have what appears to be an infinite loop that'd terminate + only upon filling the output file system or reaching a quota. + However, there is no risk of an infinite loop if grep is generating + no output, i.e., with --silent, --quiet, -q. + Similarly, with any of these: + --max-count=N (-m) (for N >= 2) + --files-with-matches (-l) + --files-without-match (-L) + there is no risk of trouble. + For --max-count=1, grep stops after printing the first match, + so there is no risk of malfunction. But even --max-count=2, with + input==output, while there is no risk of infloop, there is a race + condition that could result in "alternate" output. */ + if (!out_quiet && list_files == LISTFILES_NONE && 1 < max_count + && S_ISREG (st.st_mode) && SAME_INODE (st, out_stat)) + { + if (! suppress_errors) + error (0, 0, _("%s: input file is also the output"), input_filename ()); + errseen = true; + goto closeout; + } + + count = grep (desc, &st, &ineof); + if (count_matches) + { + if (out_file) + { + print_filename (); + if (filename_mask) + print_sep (SEP_CHAR_SELECTED); + else + putchar_errno (0); + } + printf_errno ("%" PRIdMAX "\n", count); + if (line_buffered) + fflush_errno (); + } + + status = !count; + + if (list_files == LISTFILES_NONE) + finalize_input (desc, &st, ineof); + else if (list_files == (status ? LISTFILES_NONMATCHING : LISTFILES_MATCHING)) + { + print_filename (); + putchar_errno ('\n' & filename_mask); + if (line_buffered) + fflush_errno (); + } + + closeout: + if (desc != STDIN_FILENO && close (desc) != 0) + suppressible_error (errno); + return status; +} + +static bool +grep_command_line_arg (char const *arg) +{ + if (STREQ (arg, "-")) + { + filename = label; + if (binary) + xset_binary_mode (STDIN_FILENO, O_BINARY); + return grepdesc (STDIN_FILENO, true); + } + else + { + filename = arg; + return grepfile (AT_FDCWD, arg, true, true); + } +} + +_Noreturn void usage (int); +void +usage (int status) +{ + if (status != 0) + { + fprintf (stderr, _("Usage: %s [OPTION]... PATTERNS [FILE]...\n"), + getprogname ()); + fprintf (stderr, _("Try '%s --help' for more information.\n"), + getprogname ()); + } + else + { + printf (_("Usage: %s [OPTION]... PATTERNS [FILE]...\n"), getprogname ()); + printf (_("Search for PATTERNS in each FILE.\n")); + printf (_("\ +Example: %s -i 'hello world' menu.h main.c\n\ +PATTERNS can contain multiple patterns separated by newlines.\n\ +\n\ +Pattern selection and interpretation:\n"), getprogname ()); + printf (_("\ + -E, --extended-regexp PATTERNS are extended regular expressions\n\ + -F, --fixed-strings PATTERNS are strings\n\ + -G, --basic-regexp PATTERNS are basic regular expressions\n\ + -P, --perl-regexp PATTERNS are Perl regular expressions\n")); + /* -X is deliberately undocumented. */ + printf (_("\ + -e, --regexp=PATTERNS use PATTERNS for matching\n\ + -f, --file=FILE take PATTERNS from FILE\n\ + -i, --ignore-case ignore case distinctions in patterns and data\n\ + --no-ignore-case do not ignore case distinctions (default)\n\ + -w, --word-regexp match only whole words\n\ + -x, --line-regexp match only whole lines\n\ + -z, --null-data a data line ends in 0 byte, not newline\n")); + printf (_("\ +\n\ +Miscellaneous:\n\ + -s, --no-messages suppress error messages\n\ + -v, --invert-match select non-matching lines\n\ + -V, --version display version information and exit\n\ + --help display this help text and exit\n")); + printf (_("\ +\n\ +Output control:\n\ + -m, --max-count=NUM stop after NUM selected lines\n\ + -b, --byte-offset print the byte offset with output lines\n\ + -n, --line-number print line number with output lines\n\ + --line-buffered flush output on every line\n\ + -H, --with-filename print file name with output lines\n\ + -h, --no-filename suppress the file name prefix on output\n\ + --label=LABEL use LABEL as the standard input file name prefix\n\ +")); + printf (_("\ + -o, --only-matching show only nonempty parts of lines that match\n\ + -q, --quiet, --silent suppress all normal output\n\ + --binary-files=TYPE assume that binary files are TYPE;\n\ + TYPE is 'binary', 'text', or 'without-match'\n\ + -a, --text equivalent to --binary-files=text\n\ +")); + printf (_("\ + -I equivalent to --binary-files=without-match\n\ + -d, --directories=ACTION how to handle directories;\n\ + ACTION is 'read', 'recurse', or 'skip'\n\ + -D, --devices=ACTION how to handle devices, FIFOs and sockets;\n\ + ACTION is 'read' or 'skip'\n\ + -r, --recursive like --directories=recurse\n\ + -R, --dereference-recursive likewise, but follow all symlinks\n\ +")); + printf (_("\ + --include=GLOB search only files that match GLOB (a file pattern)" + "\n\ + --exclude=GLOB skip files that match GLOB\n\ + --exclude-from=FILE skip files that match any file pattern from FILE\n\ + --exclude-dir=GLOB skip directories that match GLOB\n\ +")); + printf (_("\ + -L, --files-without-match print only names of FILEs with no selected lines\n\ + -l, --files-with-matches print only names of FILEs with selected lines\n\ + -c, --count print only a count of selected lines per FILE\n\ + -T, --initial-tab make tabs line up (if needed)\n\ + -Z, --null print 0 byte after FILE name\n")); + printf (_("\ +\n\ +Context control:\n\ + -B, --before-context=NUM print NUM lines of leading context\n\ + -A, --after-context=NUM print NUM lines of trailing context\n\ + -C, --context=NUM print NUM lines of output context\n\ +")); + printf (_("\ + -NUM same as --context=NUM\n\ + --group-separator=SEP print SEP on line between matches with context\n\ + --no-group-separator do not print separator for matches with context\n\ + --color[=WHEN],\n\ + --colour[=WHEN] use markers to highlight the matching strings;\n\ + WHEN is 'always', 'never', or 'auto'\n\ + -U, --binary do not strip CR characters at EOL (MSDOS/Windows)\n\ +\n")); +#ifdef KMK_GREP + printf (_("\ +kmk_grep extensions:\n\ + --codepage=NUM switches the locale to the given codepage, \n\ + affecting how input files are treated and outputted\n\ + windows only, ignored elsewhere\n\ + --utf8 shorthand for --codepage=UTF8\n\ +\n")); +#endif + printf (_("\ +When FILE is '-', read standard input. With no FILE, read '.' if\n\ +recursive, '-' otherwise. With fewer than two FILEs, assume -h.\n\ +Exit status is 0 if any line is selected, 1 otherwise;\n\ +if any error occurs and -q is not given, the exit status is 2.\n")); + emit_bug_reporting_address (); + } + exit (status); +} + +/* Pattern compilers and matchers. */ + +static struct +{ + char name[12]; + int syntax; /* used if compile == GEAcompile */ + compile_fp_t compile; + execute_fp_t execute; +} const matchers[] = { + { "grep", RE_SYNTAX_GREP, (compile_fp_t)GEAcompile, (execute_fp_t)EGexecute }, + { "egrep", RE_SYNTAX_EGREP, (compile_fp_t)GEAcompile, (execute_fp_t)EGexecute }, + { "fgrep", 0, (compile_fp_t)Fcompile, (execute_fp_t)Fexecute }, + { "awk", RE_SYNTAX_AWK, (compile_fp_t)GEAcompile, (execute_fp_t)EGexecute }, + { "gawk", RE_SYNTAX_GNU_AWK, (compile_fp_t)GEAcompile, (execute_fp_t)EGexecute }, + { "posixawk", RE_SYNTAX_POSIX_AWK, (compile_fp_t)GEAcompile, (execute_fp_t)EGexecute }, +#if HAVE_LIBPCRE + { "perl", 0, (compile_fp_t)Pcompile, (execute_fp_t)Pexecute }, +#endif +}; +/* Keep these in sync with the 'matchers' table. */ +enum { E_MATCHER_INDEX = 1, F_MATCHER_INDEX = 2, G_MATCHER_INDEX = 0 }; + +/* Return the index of the matcher corresponding to M if available. + MATCHER is the index of the previous matcher, or -1 if none. + Exit in case of conflicts or if M is not available. */ +static int +setmatcher (char const *m, int matcher) +{ + for (int i = 0; i < sizeof matchers / sizeof *matchers; i++) + if (STREQ (m, matchers[i].name)) + { + if (0 <= matcher && matcher != i) + die (EXIT_TROUBLE, 0, _("conflicting matchers specified")); + return i; + } + +#if !HAVE_LIBPCRE + if (STREQ (m, "perl")) + die (EXIT_TROUBLE, 0, + _("Perl matching not supported in a --disable-perl-regexp build")); +#endif + die (EXIT_TROUBLE, 0, _("invalid matcher %s"), m); +} + +/* Get the next non-digit option from ARGC and ARGV. + Return -1 if there are no more options. + Process any digit options that were encountered on the way, + and store the resulting integer into *DEFAULT_CONTEXT. */ +static int +get_nondigit_option (int argc, char *const *argv, intmax_t *default_context) +{ + static int prev_digit_optind = -1; + int this_digit_optind; + bool was_digit; + char buf[INT_BUFSIZE_BOUND (intmax_t) + 4]; + char *p = buf; + int opt; + + was_digit = false; + this_digit_optind = optind; + while (true) + { + opt = getopt_long (argc, (char **) argv, short_options, + long_options, NULL); + if (! c_isdigit (opt)) + break; + + if (prev_digit_optind != this_digit_optind || !was_digit) + { + /* Reset to start another context length argument. */ + p = buf; + } + else + { + /* Suppress trivial leading zeros, to avoid incorrect + diagnostic on strings like 00000000000. */ + p -= buf[0] == '0'; + } + + if (p == buf + sizeof buf - 4) + { + /* Too many digits. Append "..." to make context_length_arg + complain about "X...", where X contains the digits seen + so far. */ + strcpy (p, "..."); + p += 3; + break; + } + *p++ = opt; + + was_digit = true; + prev_digit_optind = this_digit_optind; + this_digit_optind = optind; + } + if (p != buf) + { + *p = '\0'; + context_length_arg (buf, default_context); + } + + return opt; +} + +/* Parse GREP_COLORS. The default would look like: + GREP_COLORS='ms=01;31:mc=01;31:sl=:cx=:fn=35:ln=32:bn=32:se=36' + with boolean capabilities (ne and rv) unset (i.e., omitted). + No character escaping is needed or supported. */ +static void +parse_grep_colors (void) +{ + const char *p; + char *q; + char *name; + char *val; + + p = getenv ("GREP_COLORS"); /* Plural! */ + if (p == NULL || *p == '\0') + return; + + /* Work off a writable copy. */ + q = xstrdup (p); + + name = q; + val = NULL; + /* From now on, be well-formed or you're gone. */ + for (;;) + if (*q == ':' || *q == '\0') + { + char c = *q; + struct color_cap const *cap; + + *q++ = '\0'; /* Terminate name or val. */ + /* Empty name without val (empty cap) + * won't match and will be ignored. */ + for (cap = color_dict; cap->name; cap++) + if (STREQ (cap->name, name)) + break; + /* If name unknown, go on for forward compatibility. */ + if (cap->var && val) + *(cap->var) = val; + if (cap->fct) + cap->fct (); + if (c == '\0') + return; + name = q; + val = NULL; + } + else if (*q == '=') + { + if (q == name || val) + return; + *q++ = '\0'; /* Terminate name. */ + val = q; /* Can be the empty string. */ + } + else if (val == NULL) + q++; /* Accumulate name. */ + else if (*q == ';' || c_isdigit (*q)) + q++; /* Accumulate val. Protect the terminal from being sent crap. */ + else + return; +} + +/* Return true if PAT (of length PATLEN) contains an encoding error. */ +static bool +contains_encoding_error (char const *pat, size_t patlen) +{ + mbstate_t mbs = { 0 }; + size_t i, charlen; + + for (i = 0; i < patlen; i += charlen) + { + charlen = mb_clen (pat + i, patlen - i, &mbs); + if ((size_t) -2 <= charlen) + return true; + } + return false; +} + +/* When ignoring case and (-E or -F or -G), then for each single-byte + character I, ok_fold[I] is 1 if every case folded counterpart of I + is also single-byte, and is -1 otherwise. */ +static signed char ok_fold[NCHAR]; +static void +setup_ok_fold (void) +{ + for (int i = 0; i < NCHAR; i++) + { + wint_t wi = localeinfo.sbctowc[i]; + if (wi == WEOF) + continue; + + int ok = 1; + wchar_t folded[CASE_FOLDED_BUFSIZE]; + for (int n = case_folded_counterparts (wi, folded); 0 <= --n; ) + { + char buf[MB_LEN_MAX]; + mbstate_t s = { 0 }; + if (wcrtomb (buf, folded[n], &s) != 1) + { + ok = -1; + break; + } + } + ok_fold[i] = ok; + } +} + +/* Return the number of bytes in the initial character of PAT, of size + PATLEN, if Fcompile can handle that character. Return -1 if + Fcompile cannot handle it. MBS is the multibyte conversion state. + PATLEN must be nonzero. */ + +static int +fgrep_icase_charlen (char const *pat, size_t patlen, mbstate_t *mbs) +{ + unsigned char pat0 = pat[0]; + + /* If PAT starts with a single-byte character, Fcompile works if + every case folded counterpart is also single-byte. */ + if (localeinfo.sbctowc[pat0] != WEOF) + return ok_fold[pat0]; + + wchar_t wc; + size_t wn = mbrtowc (&wc, pat, patlen, mbs); + + /* If PAT starts with an encoding error, Fcompile does not work. */ + if (MB_LEN_MAX < wn) + return -1; + + /* PAT starts with a multibyte character. Fcompile works if the + character has no case folded counterparts and toupper translates + none of its encoding's bytes. */ + wchar_t folded[CASE_FOLDED_BUFSIZE]; + if (case_folded_counterparts (wc, folded)) + return -1; + for (int i = wn; 0 < --i; ) + { + unsigned char c = pat[i]; + if (toupper (c) != c) + return -1; + } + return wn; +} + +/* Return true if the -F patterns PAT, of size PATLEN, contain only + single-byte characters that case-fold only to single-byte + characters, or multibyte characters not subject to case folding, + and so can be processed by Fcompile. */ + +static bool +fgrep_icase_available (char const *pat, size_t patlen) +{ + mbstate_t mbs = {0,}; + + for (size_t i = 0; i < patlen; ) + { + int n = fgrep_icase_charlen (pat + i, patlen - i, &mbs); + if (n < 0) + return false; + i += n; + } + + return true; +} + +/* Change the pattern *KEYS_P, of size *LEN_P, from fgrep to grep style. */ + +void +fgrep_to_grep_pattern (char **keys_p, size_t *len_p) +{ + size_t len = *len_p; + char *keys = *keys_p; + mbstate_t mb_state = { 0 }; + char *new_keys = xnmalloc (len + 1, 2); + char *p = new_keys; + size_t n; + + for (; len; keys += n, len -= n) + { + n = mb_clen (keys, len, &mb_state); + switch (n) + { + case (size_t) -2: + n = len; + FALLTHROUGH; + default: + p = mempcpy (p, keys, n); + break; + + case (size_t) -1: + memset (&mb_state, 0, sizeof mb_state); + n = 1; + FALLTHROUGH; + case 1: + switch (*keys) + { + case '$': case '*': case '.': case '[': case '\\': case '^': + *p++ = '\\'; break; + } + *p++ = *keys; + break; + } + } + + *p = '\n'; + free (*keys_p); + *keys_p = new_keys; + *len_p = p - new_keys; +} + +/* If it is easy, convert the MATCHER-style patterns KEYS (of size + *LEN_P) to -F style, update *LEN_P to a possibly-smaller value, and + return F_MATCHER_INDEX. If not, leave KEYS and *LEN_P alone and + return MATCHER. This function is conservative and sometimes misses + conversions, e.g., it does not convert the -E pattern "(a|a|[aa])" + to the -F pattern "a". */ + +static int +try_fgrep_pattern (int matcher, char *keys, size_t *len_p) +{ + int result = matcher; + size_t len = *len_p; + char *new_keys = xmalloc (len + 1); + char *p = new_keys; + char const *q = keys; + mbstate_t mb_state = { 0 }; + + while (len != 0) + { + switch (*q) + { + case '$': case '*': case '.': case '[': case '^': + goto fail; + + case '(': case '+': case '?': case '{': case '|': + /* There is no "case ')'" here, as "grep -E ')'" acts like + "grep -E '\)'". */ + if (matcher != G_MATCHER_INDEX) + goto fail; + break; + + case '\\': + if (1 < len) + switch (q[1]) + { + case '\n': + case 'B': case 'S': case 'W': case'\'': case '<': + case 'b': case 's': case 'w': case '`': case '>': + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + goto fail; + + case '(': case '+': case '?': case '{': case '|': + /* Pass '\)' to GEAcompile so it can complain. Otherwise, + "grep '\)'" would act like "grep ')'" while "grep '.*\)' + would be an error. */ + case ')': + if (matcher == G_MATCHER_INDEX) + goto fail; + FALLTHROUGH; + default: + q++, len--; + break; + } + break; + } + + { + size_t n; + if (match_icase) + { + int ni = fgrep_icase_charlen (q, len, &mb_state); + if (ni < 0) + goto fail; + n = ni; + } + else + { + n = mb_clen (q, len, &mb_state); + if (MB_LEN_MAX < n) + goto fail; + } + + p = mempcpy (p, q, n); + q += n; + len -= n; + } + } + + if (*len_p != p - new_keys) + { + *len_p = p - new_keys; + char *keys_end = mempcpy (keys, new_keys, p - new_keys); + *keys_end = '\n'; + } + result = F_MATCHER_INDEX; + + fail: + free (new_keys); + return result; +} + +int +main (int argc, char **argv) +{ + char *keys = NULL; + size_t keycc = 0, keyalloc = 0; + int matcher = -1; + int opt; + int prev_optind, last_recursive; + int fread_errno; + intmax_t default_context; + FILE *fp; + exit_failure = EXIT_TROUBLE; + initialize_main (&argc, &argv); + + /* Which command-line options have been specified for filename output. + -1 for -h, 1 for -H, 0 for neither. */ + int filename_option = 0; + + eolbyte = '\n'; + filename_mask = ~0; + + max_count = INTMAX_MAX; + + /* The value -1 means to use DEFAULT_CONTEXT. */ + out_after = out_before = -1; + /* Default before/after context: changed by -C/-NUM options */ + default_context = -1; + /* Changed by -o option */ + only_matching = false; + + /* Internationalization. */ +#if defined HAVE_SETLOCALE +# if defined(KMK_GREP) && defined(KBUILD_OS_WINDOWS) + if (getenv ("KMK_GREP_CODEPAGE")) + kmk_grep_set_codepage (getenv ("KMK_GREP_CODEPAGE")); + else +# endif + setlocale (LC_ALL, ""); +#endif +#if defined ENABLE_NLS + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif + + init_localeinfo (&localeinfo); + + atexit (clean_up_stdout); + c_stack_action (NULL); + + last_recursive = 0; + + pattern_table = hash_initialize (0, 0, hash_pattern, compare_patterns, 0); + if (!pattern_table) + xalloc_die (); + + while (prev_optind = optind, + (opt = get_nondigit_option (argc, argv, &default_context)) != -1) + switch (opt) + { + case 'A': + context_length_arg (optarg, &out_after); + break; + + case 'B': + context_length_arg (optarg, &out_before); + break; + + case 'C': + /* Set output match context, but let any explicit leading or + trailing amount specified with -A or -B stand. */ + context_length_arg (optarg, &default_context); + break; + + case 'D': + if (STREQ (optarg, "read")) + devices = READ_DEVICES; + else if (STREQ (optarg, "skip")) + devices = SKIP_DEVICES; + else + die (EXIT_TROUBLE, 0, _("unknown devices method")); + break; + + case 'E': + matcher = setmatcher ("egrep", matcher); + break; + + case 'F': + matcher = setmatcher ("fgrep", matcher); + break; + + case 'P': + matcher = setmatcher ("perl", matcher); + break; + + case 'G': + matcher = setmatcher ("grep", matcher); + break; + + case 'X': /* undocumented on purpose */ + matcher = setmatcher (optarg, matcher); + break; + + case 'H': + filename_option = 1; + break; + + case 'I': + binary_files = WITHOUT_MATCH_BINARY_FILES; + break; + + case 'T': + align_tabs = true; + break; + + case 'U': + if (O_BINARY) + binary = true; + break; + + case 'u': + /* Obsolete option; it had no effect; FIXME: remove in 2023 */ + error (0, 0, _("warning: --unix-byte-offsets (-u) is obsolete")); + break; + + case 'V': + show_version = true; + break; + + case 'a': + binary_files = TEXT_BINARY_FILES; + break; + + case 'b': + out_byte = true; + break; + + case 'c': + count_matches = true; + break; + + case 'd': + directories = XARGMATCH ("--directories", optarg, + directories_args, directories_types); + if (directories == RECURSE_DIRECTORIES) + last_recursive = prev_optind; + break; + + case 'e': + { + ptrdiff_t cc = strlen (optarg); + if (keyalloc < keycc + cc + 1) + { + keyalloc = keycc + cc + 1; + pattern_array = keys = x2realloc (keys, &keyalloc); + } + char *keyend = mempcpy (keys + keycc, optarg, cc); + *keyend = '\n'; + keycc = update_patterns (keys, keycc, keycc + cc + 1, ""); + } + break; + + case 'f': + { + if (STREQ (optarg, "-")) + { + if (binary) + xset_binary_mode (STDIN_FILENO, O_BINARY); + fp = stdin; + } + else + { + fp = fopen (optarg, binary ? "rb" : "r"); + if (!fp) + die (EXIT_TROUBLE, errno, "%s", optarg); + } + ptrdiff_t newkeycc = keycc, cc; + for (;; newkeycc += cc) + { + if (keyalloc <= newkeycc + 1) + pattern_array = keys = x2realloc (keys, &keyalloc); + cc = fread (keys + newkeycc, 1, keyalloc - (newkeycc + 1), fp); + if (cc == 0) + break; + } + fread_errno = errno; + if (ferror (fp)) + die (EXIT_TROUBLE, fread_errno, "%s", optarg); + if (fp != stdin) + fclose (fp); + /* Append final newline if file ended in non-newline. */ + if (newkeycc != keycc && keys[newkeycc - 1] != '\n') + keys[newkeycc++] = '\n'; + keycc = update_patterns (keys, keycc, newkeycc, optarg); + } + break; + + case 'h': + filename_option = -1; + break; + + case 'i': + case 'y': /* For old-timers . . . */ + match_icase = true; + break; + + case NO_IGNORE_CASE_OPTION: + match_icase = false; + break; + + case 'L': + /* Like -l, except list files that don't contain matches. + Inspired by the same option in Hume's gre. */ + list_files = LISTFILES_NONMATCHING; + break; + + case 'l': + list_files = LISTFILES_MATCHING; + break; + + case 'm': + switch (xstrtoimax (optarg, 0, 10, &max_count, "")) + { + case LONGINT_OK: + case LONGINT_OVERFLOW: + break; + + default: + die (EXIT_TROUBLE, 0, _("invalid max count")); + } + break; + + case 'n': + out_line = true; + break; + + case 'o': + only_matching = true; + break; + + case 'q': + exit_on_match = true; + exit_failure = 0; + break; + + case 'R': + fts_options = basic_fts_options | FTS_LOGICAL; + FALLTHROUGH; + case 'r': + directories = RECURSE_DIRECTORIES; + last_recursive = prev_optind; + break; + + case 's': + suppress_errors = true; + break; + + case 'v': + out_invert = true; + break; + + case 'w': + wordinit (); + match_words = true; + break; + + case 'x': + match_lines = true; + break; + + case 'Z': + filename_mask = 0; + break; + + case 'z': + eolbyte = '\0'; + break; + + case BINARY_FILES_OPTION: + if (STREQ (optarg, "binary")) + binary_files = BINARY_BINARY_FILES; + else if (STREQ (optarg, "text")) + binary_files = TEXT_BINARY_FILES; + else if (STREQ (optarg, "without-match")) + binary_files = WITHOUT_MATCH_BINARY_FILES; + else + die (EXIT_TROUBLE, 0, _("unknown binary-files type")); + break; + + case COLOR_OPTION: + if (optarg) + { + if (!c_strcasecmp (optarg, "always") + || !c_strcasecmp (optarg, "yes") + || !c_strcasecmp (optarg, "force")) + color_option = 1; + else if (!c_strcasecmp (optarg, "never") + || !c_strcasecmp (optarg, "no") + || !c_strcasecmp (optarg, "none")) + color_option = 0; + else if (!c_strcasecmp (optarg, "auto") + || !c_strcasecmp (optarg, "tty") + || !c_strcasecmp (optarg, "if-tty")) + color_option = 2; + else + show_help = 1; + } + else + color_option = 2; + break; + + case EXCLUDE_OPTION: + case INCLUDE_OPTION: + for (int cmd = 0; cmd < 2; cmd++) + { + if (!excluded_patterns[cmd]) + excluded_patterns[cmd] = new_exclude (); + add_exclude (excluded_patterns[cmd], optarg, + ((opt == INCLUDE_OPTION ? EXCLUDE_INCLUDE : 0) + | exclude_options (cmd))); + } + break; + case EXCLUDE_FROM_OPTION: + for (int cmd = 0; cmd < 2; cmd++) + { + if (!excluded_patterns[cmd]) + excluded_patterns[cmd] = new_exclude (); + if (add_exclude_file (add_exclude, excluded_patterns[cmd], + optarg, exclude_options (cmd), '\n') + != 0) + die (EXIT_TROUBLE, errno, "%s", optarg); + } + break; + + case EXCLUDE_DIRECTORY_OPTION: + strip_trailing_slashes (optarg); + for (int cmd = 0; cmd < 2; cmd++) + { + if (!excluded_directory_patterns[cmd]) + excluded_directory_patterns[cmd] = new_exclude (); + add_exclude (excluded_directory_patterns[cmd], optarg, + exclude_options (cmd)); + } + break; + + case GROUP_SEPARATOR_OPTION: + group_separator = optarg; + break; + + case LINE_BUFFERED_OPTION: + line_buffered = true; + break; + + case LABEL_OPTION: + label = optarg; + break; + +#ifdef KMK_GREP + /* The --utf8 and --codepage <cp> options are mainly for windows where + UCRT doesn't check any of the standard locale selecting environment + variables and we have to give it directly to setlocale if we want + any control beyond the Windows defaults. + + The UCRT setlocale has a nice feature of allowing us to set just + the codepage, omitting the rest of the locale spec. */ + case UTF8_OPTION: + kmk_grep_set_codepage (".UTF-8"); + break; + case CODEPAGE_OPTION: + kmk_grep_set_codepage (optarg); + break; +#endif + + case 0: + /* long options */ + break; + + default: + usage (EXIT_TROUBLE); + break; + + } + + if (show_version) + { + version_etc (stdout, getprogname (), PACKAGE_NAME, VERSION, + (char *) NULL); + puts (_("Written by Mike Haertel and others; see\n" + "<https://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.")); + return EXIT_SUCCESS; + } + + if (show_help) + usage (EXIT_SUCCESS); + + if (keys) + { + if (keycc == 0) + { + /* No keys were specified (e.g. -f /dev/null). Match nothing. */ + out_invert ^= true; + match_lines = match_words = false; + keys[keycc++] = '\n'; + } + } + else if (optind < argc) + { + /* Make a copy so that it can be reallocated or freed later. */ + pattern_array = keys = xstrdup (argv[optind++]); + ptrdiff_t patlen = strlen (keys); + keys[patlen] = '\n'; + keycc = update_patterns (keys, 0, patlen + 1, ""); + } + else + usage (EXIT_TROUBLE); + + /* Strip trailing newline from keys. */ + keycc--; + + hash_free (pattern_table); + + bool possibly_tty = false; + struct stat tmp_stat; + if (! exit_on_match && fstat (STDOUT_FILENO, &tmp_stat) == 0) + { + if (S_ISREG (tmp_stat.st_mode)) + out_stat = tmp_stat; + else if (S_ISCHR (tmp_stat.st_mode)) + { + struct stat null_stat; + if (stat ("/dev/null", &null_stat) == 0 + && SAME_INODE (tmp_stat, null_stat)) + dev_null_output = true; + else + possibly_tty = true; + } + } + + /* POSIX says -c, -l and -q are mutually exclusive. In this + implementation, -q overrides -l and -L, which in turn override -c. */ + if (exit_on_match | dev_null_output) + list_files = LISTFILES_NONE; + if ((exit_on_match | dev_null_output) || list_files != LISTFILES_NONE) + { + count_matches = false; + done_on_match = true; + } + out_quiet = count_matches | done_on_match; + + if (out_after < 0) + out_after = default_context; + if (out_before < 0) + out_before = default_context; + + /* If it is easy to see that matching cannot succeed (e.g., 'grep -f + /dev/null'), fail without reading the input. */ + if ((max_count == 0 + || (keycc == 0 && out_invert && !match_lines && !match_words)) + && list_files != LISTFILES_NONMATCHING) + return EXIT_FAILURE; + + if (color_option == 2) + color_option = possibly_tty && should_colorize () && isatty (STDOUT_FILENO); + init_colorize (); + + if (color_option) + { + /* Legacy. */ + char *userval = getenv ("GREP_COLOR"); + if (userval != NULL && *userval != '\0') + selected_match_color = context_match_color = userval; + + /* New GREP_COLORS has priority. */ + parse_grep_colors (); + } + + initialize_unibyte_mask (); + + if (matcher < 0) + matcher = G_MATCHER_INDEX; + + if (matcher == F_MATCHER_INDEX + || matcher == E_MATCHER_INDEX || matcher == G_MATCHER_INDEX) + { + if (match_icase) + setup_ok_fold (); + + /* In a single-byte locale, switch from -F to -G if it is a single + pattern that matches words, where -G is typically faster. In a + multibyte locale, switch if the patterns have an encoding error + (where -F does not work) or if -i and the patterns will not work + for -iF. */ + if (matcher == F_MATCHER_INDEX) + { + if (! localeinfo.multibyte + ? n_patterns == 1 && match_words + : (contains_encoding_error (keys, keycc) + || (match_icase && !fgrep_icase_available (keys, keycc)))) + { + fgrep_to_grep_pattern (&pattern_array, &keycc); + keys = pattern_array; + matcher = G_MATCHER_INDEX; + } + } + /* With two or more patterns, if -F works then switch from either -E + or -G, as -F is probably faster then. */ + else if (1 < n_patterns) + matcher = try_fgrep_pattern (matcher, keys, &keycc); + } + + execute = matchers[matcher].execute; + compiled_pattern = + matchers[matcher].compile (keys, keycc, matchers[matcher].syntax, + only_matching | color_option); + /* We need one byte prior and one after. */ + char eolbytes[3] = { 0, eolbyte, 0 }; + size_t match_size; + skip_empty_lines = ((execute (compiled_pattern, eolbytes + 1, 1, + &match_size, NULL) == 0) + == out_invert); + + int num_operands = argc - optind; + out_file = (filename_option == 0 && num_operands <= 1 + ? - (directories == RECURSE_DIRECTORIES) + : 0 <= filename_option); + + if (binary) + xset_binary_mode (STDOUT_FILENO, O_BINARY); + + /* Prefer sysconf for page size, as getpagesize typically returns int. */ +#ifdef _SC_PAGESIZE + long psize = sysconf (_SC_PAGESIZE); +#else + long psize = getpagesize (); +#endif + if (! (0 < psize && psize <= (SIZE_MAX - sizeof (uword)) / 2)) + abort (); + pagesize = psize; + bufalloc = ALIGN_TO (INITIAL_BUFSIZE, pagesize) + pagesize + sizeof (uword); + buffer = xmalloc (bufalloc); + + if (fts_options & FTS_LOGICAL && devices == READ_COMMAND_LINE_DEVICES) + devices = READ_DEVICES; + + char *const *files; + if (0 < num_operands) + { + files = argv + optind; + } + else if (directories == RECURSE_DIRECTORIES && 0 < last_recursive) + { + static char *const cwd_only[] = { (char *) ".", NULL }; + files = cwd_only; + omit_dot_slash = true; + } + else + { + static char *const stdin_only[] = { (char *) "-", NULL }; + files = stdin_only; + } + + bool status = true; + do + status &= grep_command_line_arg (*files++); + while (*files != NULL); + + /* We register via atexit to test stdout. */ + return errseen ? EXIT_TROUBLE : status; +} diff --git a/src/grep/src/grep.h b/src/grep/src/grep.h new file mode 100644 index 0000000..a3cd73e --- /dev/null +++ b/src/grep/src/grep.h @@ -0,0 +1,34 @@ +/* grep.h - interface to grep driver for searching subroutines. + Copyright (C) 1992, 1998, 2001, 2007, 2009-2021 Free Software Foundation, + Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef GREP_GREP_H +#define GREP_GREP_H 1 + +#include <stdbool.h> + +/* The following flags are exported from grep for the matchers + to look at. */ +extern bool match_icase; /* -i */ +extern bool match_words; /* -w */ +extern bool match_lines; /* -x */ +extern char eolbyte; /* -z */ + +extern char const *pattern_file_name (size_t, size_t *); + +#endif diff --git a/src/grep/src/kwsearch.c b/src/grep/src/kwsearch.c new file mode 100644 index 0000000..ea18ce1 --- /dev/null +++ b/src/grep/src/kwsearch.c @@ -0,0 +1,240 @@ +/* kwsearch.c - searching subroutines using kwset for grep. + Copyright 1992, 1998, 2000, 2007, 2009-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written August 1992 by Mike Haertel. */ + +#include <config.h> +#include "search.h" + +/* A compiled -F pattern list. */ + +struct kwsearch +{ + /* The kwset for this pattern list. */ + kwset_t kwset; + + /* The number of user-specified patterns. This is less than + 'kwswords (kwset)' when some extra one-character words have been + appended, one for each troublesome character that will require a + DFA search. */ + ptrdiff_t words; + + /* The user's pattern and its size in bytes. */ + char *pattern; + size_t size; + + /* The user's pattern compiled as a regular expression, + or null if it has not been compiled. */ + void *re; +}; + +/* Compile the -F style PATTERN, containing SIZE bytes that are + followed by '\n'. Return a description of the compiled pattern. */ + +void * +Fcompile (char *pattern, size_t size, reg_syntax_t ignored, bool exact) +{ + kwset_t kwset; + char *buf = NULL; + size_t bufalloc = 0; + + kwset = kwsinit (true); + + char const *p = pattern; + do + { + char const *sep = rawmemchr (p, '\n'); + ptrdiff_t len = sep - p; + + if (match_lines) + { + if (eolbyte == '\n' && pattern < p) + p--; + else + { + if (bufalloc < len + 2) + { + free (buf); + bufalloc = len + 2; + buf = x2realloc (NULL, &bufalloc); + buf[0] = eolbyte; + } + memcpy (buf + 1, p, len); + buf[len + 1] = eolbyte; + p = buf; + } + len += 2; + } + kwsincr (kwset, p, len); + + p = sep + 1; + } + while (p <= pattern + size); + + free (buf); + + ptrdiff_t words = kwswords (kwset); + kwsprep (kwset); + + struct kwsearch *kwsearch = xmalloc (sizeof *kwsearch); + kwsearch->kwset = kwset; + kwsearch->words = words; + kwsearch->pattern = pattern; + kwsearch->size = size; + kwsearch->re = NULL; + return kwsearch; +} + +/* Use the compiled pattern VCP to search the buffer BUF of size SIZE. + If found, return the offset of the first match and store its + size into *MATCH_SIZE. If not found, return SIZE_MAX. + If START_PTR is nonnull, start searching there. */ +size_t +Fexecute (void *vcp, char const *buf, size_t size, size_t *match_size, + char const *start_ptr) +{ + char const *beg, *end, *mb_start; + ptrdiff_t len; + char eol = eolbyte; + struct kwsearch *kwsearch = vcp; + kwset_t kwset = kwsearch->kwset; + bool mb_check = localeinfo.multibyte & !localeinfo.using_utf8 & !match_lines; + bool longest = (mb_check | !!start_ptr | match_words) & !match_lines; + + for (mb_start = beg = start_ptr ? start_ptr : buf; beg <= buf + size; beg++) + { + struct kwsmatch kwsmatch; + ptrdiff_t offset = kwsexec (kwset, beg - match_lines, + buf + size - beg + match_lines, &kwsmatch, + longest); + if (offset < 0) + break; + len = kwsmatch.size - 2 * match_lines; + + size_t mbclen = 0; + if (mb_check + && mb_goback (&mb_start, &mbclen, beg + offset, buf + size) != 0) + { + /* We have matched a single byte that is not at the beginning of a + multibyte character. mb_goback has advanced MB_START past that + multibyte character. Now, we want to position BEG so that the + next kwsexec search starts there. Thus, to compensate for the + for-loop's BEG++, above, subtract one here. This code is + unusually hard to reach, and exceptionally, let's show how to + trigger it here: + + printf '\203AA\n'|LC_ALL=ja_JP.SHIFT_JIS src/grep -F A + + That assumes the named locale is installed. + Note that your system's shift-JIS locale may have a different + name, possibly including "sjis". */ + beg = mb_start - 1; + continue; + } + beg += offset; + if (!!start_ptr & !match_words) + goto success_in_beg_and_len; + if (match_lines) + { + len += start_ptr == NULL; + goto success_in_beg_and_len; + } + if (! match_words) + goto success; + + /* We need a preceding mb_start pointer. Use the beginning of line + if there is a preceding newline. */ + if (mbclen == 0) + { + char const *nl = memrchr (mb_start, eol, beg - mb_start); + if (nl) + mb_start = nl + 1; + } + + /* Succeed if neither the preceding nor the following character is a + word constituent. If the preceding is not, yet the following + character IS a word constituent, keep trying with shorter matches. */ + if (mbclen > 0 + ? ! wordchar_next (beg - mbclen, buf + size) + : ! wordchar_prev (mb_start, beg, buf + size)) + for (;;) + { + if (! wordchar_next (beg + len, buf + size)) + { + if (start_ptr) + goto success_in_beg_and_len; + else + goto success; + } + if (!start_ptr && !localeinfo.multibyte) + { + if (! kwsearch->re) + { + fgrep_to_grep_pattern (&kwsearch->pattern, &kwsearch->size); + kwsearch->re = GEAcompile (kwsearch->pattern, + kwsearch->size, + RE_SYNTAX_GREP, !!start_ptr); + } + if (beg + len < buf + size) + { + end = rawmemchr (beg + len, eol); + end++; + } + else + end = buf + size; + + if (EGexecute (kwsearch->re, beg, end - beg, match_size, NULL) + != (size_t) -1) + goto success_match_words; + beg = end - 1; + break; + } + if (!len) + break; + + struct kwsmatch shorter_match; + if (kwsexec (kwset, beg, --len, &shorter_match, true) != 0) + break; + len = shorter_match.size; + } + + /* No word match was found at BEG. Skip past word constituents, + since they cannot precede the next match and not skipping + them could make things much slower. */ + beg += wordchars_size (beg, buf + size); + mb_start = beg; + } + + return -1; + + success: + if (beg + len < buf + size) + { + end = rawmemchr (beg + len, eol); + end++; + } + else + end = buf + size; + success_match_words: + beg = memrchr (buf, eol, beg - buf); + beg = beg ? beg + 1 : buf; + len = end - beg; + success_in_beg_and_len:; + *match_size = len; + return beg - buf; +} diff --git a/src/grep/src/kwset.c b/src/grep/src/kwset.c new file mode 100644 index 0000000..792cc01 --- /dev/null +++ b/src/grep/src/kwset.c @@ -0,0 +1,929 @@ +/* kwset.c - search for any of a set of keywords. + Copyright (C) 1989, 1998, 2000, 2005, 2007, 2009-2021 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written August 1989 by Mike Haertel. */ + +/* For the Aho-Corasick algorithm, see: + Aho AV, Corasick MJ. Efficient string matching: an aid to + bibliographic search. CACM 18, 6 (1975), 333-40 + <https://dx.doi.org/10.1145/360825.360855>, which describes the + failure function used below. + + For the Boyer-Moore algorithm, see: Boyer RS, Moore JS. + A fast string searching algorithm. CACM 20, 10 (1977), 762-72 + <https://dx.doi.org/10.1145/359842.359859>. + + For a survey of more-recent string matching algorithms that might + help improve performance, see: Faro S, Lecroq T. The exact online + string matching problem: a review of the most recent results. + ACM Computing Surveys 45, 2 (2013), 13 + <https://dx.doi.org/10.1145/2431211.2431212>. */ + +#include <config.h> + +#include "kwset.h" + +#include <stdint.h> +#include <sys/types.h> +#include "system.h" +#include "intprops.h" +#include "memchr2.h" +#include "obstack.h" +#include "xalloc.h" +#include "verify.h" + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +static unsigned char +U (char ch) +{ + return to_uchar (ch); +} + +/* Balanced tree of edges and labels leaving a given trie node. */ +struct tree +{ + struct tree *llink; /* Left link; MUST be first field. */ + struct tree *rlink; /* Right link (to larger labels). */ + struct trie *trie; /* Trie node pointed to by this edge. */ + unsigned char label; /* Label on this edge. */ + char balance; /* Difference in depths of subtrees. */ +}; + +/* Node of a trie representing a set of keywords. */ +struct trie +{ + /* If an accepting node, this is either 2*W + 1 where W is the word + index, or is SIZE_MAX if Aho-Corasick is in use and FAIL + specifies where to look for more info. If not an accepting node, + this is zero. */ + size_t accepting; + + struct tree *links; /* Tree of edges leaving this node. */ + struct trie *parent; /* Parent of this node. */ + struct trie *next; /* List of all trie nodes in level order. */ + struct trie *fail; /* Aho-Corasick failure function. */ + ptrdiff_t depth; /* Depth of this node from the root. */ + ptrdiff_t shift; /* Shift function for search failures. */ + ptrdiff_t maxshift; /* Max shift of self and descendants. */ +}; + +/* Structure returned opaquely to the caller, containing everything. */ +struct kwset +{ + struct obstack obstack; /* Obstack for node allocation. */ + ptrdiff_t words; /* Number of words in the trie. */ + struct trie *trie; /* The trie itself. */ + ptrdiff_t mind; /* Minimum depth of an accepting node. */ + ptrdiff_t maxd; /* Maximum depth of any node. */ + unsigned char delta[NCHAR]; /* Delta table for rapid search. */ + struct trie *next[NCHAR]; /* Table of children of the root. */ + char *target; /* Target string if there's only one. */ + ptrdiff_t *shift; /* Used in Boyer-Moore search for one + string. */ + char const *trans; /* Character translation table. */ + + /* This helps to match a terminal byte, which is the first byte + for Aho-Corasick, and the last byte for Boyer-More. If all the + patterns have the same terminal byte (after translation via TRANS + if TRANS is nonnull), then this is that byte as an unsigned char. + Otherwise this is -1 if there is disagreement among the strings + about terminal bytes, and -2 if there are no terminal bytes and + no disagreement because all the patterns are empty. */ + int gc1; + + /* This helps to match a terminal byte. If 0 <= GC1HELP, B is + terminal when B == GC1 || B == GC1HELP (note that GC1 == GCHELP + is common here). This is typically faster than evaluating + to_uchar (TRANS[B]) == GC1. */ + int gc1help; + + /* If the string has two or more bytes, this is the penultimate byte, + after translation via TRANS if TRANS is nonnull. This variable + is used only by Boyer-Moore. */ + char gc2; + + /* kwsexec implementation. */ + ptrdiff_t (*kwsexec) (kwset_t, char const *, ptrdiff_t, + struct kwsmatch *, bool); +}; + +/* Use TRANS to transliterate C. A null TRANS does no transliteration. */ +static inline char +tr (char const *trans, char c) +{ + return trans ? trans[U(c)] : c; +} + +static ptrdiff_t acexec (kwset_t, char const *, ptrdiff_t, + struct kwsmatch *, bool); +static ptrdiff_t bmexec (kwset_t, char const *, ptrdiff_t, + struct kwsmatch *, bool); + +/* Return a newly allocated keyword set. A nonnull TRANS specifies a + table of character translations to be applied to all pattern and + search text. */ +kwset_t +kwsalloc (char const *trans) +{ + struct kwset *kwset = xmalloc (sizeof *kwset); + + obstack_init (&kwset->obstack); + kwset->words = 0; + kwset->trie = obstack_alloc (&kwset->obstack, sizeof *kwset->trie); + kwset->trie->accepting = 0; + kwset->trie->links = NULL; + kwset->trie->parent = NULL; + kwset->trie->next = NULL; + kwset->trie->fail = NULL; + kwset->trie->depth = 0; + kwset->trie->shift = 0; + kwset->mind = PTRDIFF_MAX; + kwset->maxd = -1; + kwset->target = NULL; + kwset->trans = trans; + kwset->kwsexec = acexec; + + return kwset; +} + +/* This upper bound is valid for CHAR_BIT >= 4 and + exact for CHAR_BIT in { 4..11, 13, 15, 17, 19 }. */ +enum { DEPTH_SIZE = CHAR_BIT + CHAR_BIT / 2 }; + +/* Add the given string to the contents of the keyword set. */ +void +kwsincr (kwset_t kwset, char const *text, ptrdiff_t len) +{ + assume (0 <= len); + struct trie *trie = kwset->trie; + char const *trans = kwset->trans; + bool reverse = kwset->kwsexec == bmexec; + + if (reverse) + text += len; + + /* Descend the trie (built of keywords) character-by-character, + installing new nodes when necessary. */ + while (len--) + { + unsigned char uc = reverse ? *--text : *text++; + unsigned char label = trans ? trans[uc] : uc; + + /* Descend the tree of outgoing links for this trie node, + looking for the current character and keeping track + of the path followed. */ + struct tree *cur = trie->links; + struct tree *links[DEPTH_SIZE]; + enum { L, R } dirs[DEPTH_SIZE]; + links[0] = (struct tree *) &trie->links; + dirs[0] = L; + ptrdiff_t depth = 1; + + while (cur && label != cur->label) + { + links[depth] = cur; + if (label < cur->label) + dirs[depth++] = L, cur = cur->llink; + else + dirs[depth++] = R, cur = cur->rlink; + } + + /* The current character doesn't have an outgoing link at + this trie node, so build a new trie node and install + a link in the current trie node's tree. */ + if (!cur) + { + cur = obstack_alloc (&kwset->obstack, sizeof *cur); + cur->llink = NULL; + cur->rlink = NULL; + cur->trie = obstack_alloc (&kwset->obstack, sizeof *cur->trie); + cur->trie->accepting = 0; + cur->trie->links = NULL; + cur->trie->parent = trie; + cur->trie->next = NULL; + cur->trie->fail = NULL; + cur->trie->depth = trie->depth + 1; + cur->trie->shift = 0; + cur->label = label; + cur->balance = 0; + + /* Install the new tree node in its parent. */ + if (dirs[--depth] == L) + links[depth]->llink = cur; + else + links[depth]->rlink = cur; + + /* Back up the tree fixing the balance flags. */ + while (depth && !links[depth]->balance) + { + if (dirs[depth] == L) + --links[depth]->balance; + else + ++links[depth]->balance; + --depth; + } + + /* Rebalance the tree by pointer rotations if necessary. */ + if (depth && ((dirs[depth] == L && --links[depth]->balance) + || (dirs[depth] == R && ++links[depth]->balance))) + { + struct tree *t, *r, *l, *rl, *lr; + + switch (links[depth]->balance) + { + case (char) -2: + switch (dirs[depth + 1]) + { + case L: + r = links[depth], t = r->llink, rl = t->rlink; + t->rlink = r, r->llink = rl; + t->balance = r->balance = 0; + break; + case R: + r = links[depth], l = r->llink, t = l->rlink; + rl = t->rlink, lr = t->llink; + t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl; + l->balance = t->balance != 1 ? 0 : -1; + r->balance = t->balance != (char) -1 ? 0 : 1; + t->balance = 0; + break; + default: + abort (); + } + break; + case 2: + switch (dirs[depth + 1]) + { + case R: + l = links[depth], t = l->rlink, lr = t->llink; + t->llink = l, l->rlink = lr; + t->balance = l->balance = 0; + break; + case L: + l = links[depth], r = l->rlink, t = r->llink; + lr = t->llink, rl = t->rlink; + t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl; + l->balance = t->balance != 1 ? 0 : -1; + r->balance = t->balance != (char) -1 ? 0 : 1; + t->balance = 0; + break; + default: + abort (); + } + break; + default: + abort (); + } + + if (dirs[depth - 1] == L) + links[depth - 1]->llink = t; + else + links[depth - 1]->rlink = t; + } + } + + trie = cur->trie; + } + + /* Mark the node finally reached as accepting, encoding the + index number of this word in the keyword set so far. */ + if (!trie->accepting) + { + size_t words = kwset->words; + trie->accepting = 2 * words + 1; + } + ++kwset->words; + + /* Keep track of the longest and shortest string of the keyword set. */ + if (trie->depth < kwset->mind) + kwset->mind = trie->depth; + if (trie->depth > kwset->maxd) + kwset->maxd = trie->depth; +} + +ptrdiff_t +kwswords (kwset_t kwset) +{ + return kwset->words; +} + +/* Enqueue the trie nodes referenced from the given tree in the + given queue. */ +static void +enqueue (struct tree *tree, struct trie **last) +{ + if (!tree) + return; + enqueue (tree->llink, last); + enqueue (tree->rlink, last); + (*last) = (*last)->next = tree->trie; +} + +/* Compute the Aho-Corasick failure function for the trie nodes referenced + from the given tree, given the failure function for their parent as + well as a last resort failure node. */ +static void +treefails (struct tree const *tree, struct trie const *fail, + struct trie *recourse, bool reverse) +{ + struct tree *cur; + + if (!tree) + return; + + treefails (tree->llink, fail, recourse, reverse); + treefails (tree->rlink, fail, recourse, reverse); + + /* Find, in the chain of fails going back to the root, the first + node that has a descendant on the current label. */ + while (fail) + { + cur = fail->links; + while (cur && tree->label != cur->label) + if (tree->label < cur->label) + cur = cur->llink; + else + cur = cur->rlink; + if (cur) + { + tree->trie->fail = cur->trie; + if (!reverse && cur->trie->accepting && !tree->trie->accepting) + tree->trie->accepting = SIZE_MAX; + return; + } + fail = fail->fail; + } + + tree->trie->fail = recourse; +} + +/* Set delta entries for the links of the given tree such that + the preexisting delta value is larger than the current depth. */ +static void +treedelta (struct tree const *tree, ptrdiff_t depth, unsigned char delta[]) +{ + if (!tree) + return; + treedelta (tree->llink, depth, delta); + treedelta (tree->rlink, depth, delta); + if (depth < delta[tree->label]) + delta[tree->label] = depth; +} + +/* Return true if A has every label in B. */ +static bool _GL_ATTRIBUTE_PURE +hasevery (struct tree const *a, struct tree const *b) +{ + if (!b) + return true; + if (!hasevery (a, b->llink)) + return false; + if (!hasevery (a, b->rlink)) + return false; + while (a && b->label != a->label) + if (b->label < a->label) + a = a->llink; + else + a = a->rlink; + return !!a; +} + +/* Compute a vector, indexed by character code, of the trie nodes + referenced from the given tree. */ +static void +treenext (struct tree const *tree, struct trie *next[]) +{ + if (!tree) + return; + treenext (tree->llink, next); + treenext (tree->rlink, next); + next[tree->label] = tree->trie; +} + +/* Prepare a built keyword set for use. */ +void +kwsprep (kwset_t kwset) +{ + char const *trans = kwset->trans; + ptrdiff_t i; + unsigned char deltabuf[NCHAR]; + unsigned char *delta = trans ? deltabuf : kwset->delta; + struct trie *curr, *last; + + /* Use Boyer-Moore if just one pattern, Aho-Corasick otherwise. */ + bool reverse = kwset->words == 1; + + if (reverse) + { + kwset_t new_kwset; + + /* Enqueue the immediate descendants in the level order queue. */ + for (curr = last = kwset->trie; curr; curr = curr->next) + enqueue (curr->links, &last); + + /* Looking for just one string. Extract it from the trie. */ + kwset->target = obstack_alloc (&kwset->obstack, kwset->mind); + for (i = 0, curr = kwset->trie; i < kwset->mind; ++i) + { + kwset->target[i] = curr->links->label; + curr = curr->next; + } + + new_kwset = kwsalloc (kwset->trans); + new_kwset->kwsexec = bmexec; + kwsincr (new_kwset, kwset->target, kwset->mind); + obstack_free (&kwset->obstack, NULL); + *kwset = *new_kwset; + free (new_kwset); + } + + /* Initial values for the delta table; will be changed later. The + delta entry for a given character is the smallest depth of any + node at which an outgoing edge is labeled by that character. */ + memset (delta, MIN (kwset->mind, UCHAR_MAX), sizeof deltabuf); + + /* Traverse the nodes of the trie in level order, simultaneously + computing the delta table, failure function, and shift function. */ + for (curr = last = kwset->trie; curr; curr = curr->next) + { + /* Enqueue the immediate descendants in the level order queue. */ + enqueue (curr->links, &last); + + /* Update the delta table for the descendants of this node. */ + treedelta (curr->links, curr->depth, delta); + + /* Compute the failure function for the descendants of this node. */ + treefails (curr->links, curr->fail, kwset->trie, reverse); + + if (reverse) + { + curr->shift = kwset->mind; + curr->maxshift = kwset->mind; + + /* Update the shifts at each node in the current node's chain + of fails back to the root. */ + struct trie *fail; + for (fail = curr->fail; fail; fail = fail->fail) + { + /* If the current node has some outgoing edge that the fail + doesn't, then the shift at the fail should be no larger + than the difference of their depths. */ + if (!hasevery (fail->links, curr->links)) + if (curr->depth - fail->depth < fail->shift) + fail->shift = curr->depth - fail->depth; + + /* If the current node is accepting then the shift at the + fail and its descendants should be no larger than the + difference of their depths. */ + if (curr->accepting && fail->maxshift > curr->depth - fail->depth) + fail->maxshift = curr->depth - fail->depth; + } + } + } + + if (reverse) + { + /* Traverse the trie in level order again, fixing up all nodes whose + shift exceeds their inherited maxshift. */ + for (curr = kwset->trie->next; curr; curr = curr->next) + { + if (curr->maxshift > curr->parent->maxshift) + curr->maxshift = curr->parent->maxshift; + if (curr->shift > curr->maxshift) + curr->shift = curr->maxshift; + } + } + + /* Create a vector, indexed by character code, of the outgoing links + from the root node. Accumulate GC1 and GC1HELP. */ + struct trie *nextbuf[NCHAR]; + struct trie **next = trans ? nextbuf : kwset->next; + memset (next, 0, sizeof nextbuf); + treenext (kwset->trie->links, next); + int gc1 = -2; + int gc1help = -1; + for (i = 0; i < NCHAR; i++) + { + int ti = i; + if (trans) + { + ti = U(trans[i]); + kwset->next[i] = next[ti]; + } + if (kwset->next[i]) + { + if (gc1 < -1) + { + gc1 = ti; + gc1help = i; + } + else if (gc1 == ti) + gc1help = gc1help == ti ? i : -1; + else if (i == ti && gc1 == gc1help) + gc1help = i; + else + gc1 = -1; + } + } + kwset->gc1 = gc1; + kwset->gc1help = gc1help; + + if (reverse) + { + /* Looking for just one string. Extract it from the trie. */ + kwset->target = obstack_alloc (&kwset->obstack, kwset->mind); + for (i = kwset->mind - 1, curr = kwset->trie; i >= 0; --i) + { + kwset->target[i] = curr->links->label; + curr = curr->next; + } + + if (kwset->mind > 1) + { + /* Looking for the delta2 shift that might be made after a + backwards match has failed. Extract it from the trie. */ + kwset->shift + = obstack_alloc (&kwset->obstack, + sizeof *kwset->shift * (kwset->mind - 1)); + for (i = 0, curr = kwset->trie->next; i < kwset->mind - 1; ++i) + { + kwset->shift[i] = curr->shift; + curr = curr->next; + } + + /* The penultimate byte. */ + kwset->gc2 = tr (trans, kwset->target[kwset->mind - 2]); + } + } + + /* Fix things up for any translation table. */ + if (trans) + for (i = 0; i < NCHAR; ++i) + kwset->delta[i] = delta[U(trans[i])]; +} + +/* Delta2 portion of a Boyer-Moore search. *TP is the string text + pointer; it is updated in place. EP is the end of the string text, + and SP the end of the pattern. LEN is the pattern length; it must + be at least 2. TRANS, if nonnull, is the input translation table. + GC1 and GC2 are the last and second-from last bytes of the pattern, + transliterated by TRANS; the caller precomputes them for + efficiency. If D1 is nonnull, it is a delta1 table for shifting *TP + when failing. KWSET->shift says how much to shift. */ +static inline bool +bm_delta2_search (char const **tpp, char const *ep, char const *sp, + ptrdiff_t len, + char const *trans, char gc1, char gc2, + unsigned char const *d1, kwset_t kwset) +{ + char const *tp = *tpp; + ptrdiff_t d = len, skip = 0; + + while (true) + { + ptrdiff_t i = 2; + if (tr (trans, tp[-2]) == gc2) + { + while (++i <= d) + if (tr (trans, tp[-i]) != tr (trans, sp[-i])) + break; + if (i > d) + { + for (i = d + skip + 1; i <= len; ++i) + if (tr (trans, tp[-i]) != tr (trans, sp[-i])) + break; + if (i > len) + { + *tpp = tp - len; + return true; + } + } + } + + tp += d = kwset->shift[i - 2]; + if (tp > ep) + break; + if (tr (trans, tp[-1]) != gc1) + { + if (d1) + tp += d1[U(tp[-1])]; + break; + } + skip = i - 1; + } + + *tpp = tp; + return false; +} + +/* Return the address of the first byte in the buffer S (of size N) + that matches the terminal byte specified by KWSET, or NULL if there + is no match. KWSET->gc1 should be nonnegative. */ +static char const * +memchr_kwset (char const *s, ptrdiff_t n, kwset_t kwset) +{ + char const *slim = s + n; + if (kwset->gc1help < 0) + { + for (; s < slim; s++) + if (kwset->next[U(*s)]) + return s; + } + else + { + int small_heuristic = 2; + size_t small_bytes = small_heuristic * sizeof (unsigned long int); + while (s < slim) + { + if (kwset->next[U(*s)]) + return s; + s++; + if ((uintptr_t) s % small_bytes == 0) + return memchr2 (s, kwset->gc1, kwset->gc1help, slim - s); + } + } + return NULL; +} + +/* Fast Boyer-Moore search (inlinable version). */ +static inline ptrdiff_t _GL_ATTRIBUTE_PURE +bmexec_trans (kwset_t kwset, char const *text, ptrdiff_t size) +{ + assume (0 <= size); + unsigned char const *d1; + char const *ep, *sp, *tp; + int d; + ptrdiff_t len = kwset->mind; + char const *trans = kwset->trans; + + if (len == 0) + return 0; + if (len > size) + return -1; + if (len == 1) + { + tp = memchr_kwset (text, size, kwset); + return tp ? tp - text : -1; + } + + d1 = kwset->delta; + sp = kwset->target + len; + tp = text + len; + char gc1 = kwset->gc1; + char gc2 = kwset->gc2; + + /* Significance of 12: 1 (initial offset) + 10 (skip loop) + 1 (md2). */ + ptrdiff_t len12; + if (!INT_MULTIPLY_WRAPV (len, 12, &len12) && len12 < size) + /* 11 is not a bug, the initial offset happens only once. */ + for (ep = text + size - 11 * len; tp <= ep; ) + { + char const *tp0 = tp; + d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])], tp += d; + if (d != 0) + { + d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])], tp += d; + if (d != 0) + { + d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])], tp += d; + if (d != 0) + { + d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])], tp += d; + + /* As a heuristic, prefer memchr to seeking by + delta1 when the latter doesn't advance much. */ + int advance_heuristic = 16 * sizeof (long); + if (advance_heuristic <= tp - tp0) + continue; + tp--; + tp = memchr_kwset (tp, text + size - tp, kwset); + if (! tp) + return -1; + tp++; + if (ep <= tp) + break; + } + } + } + if (bm_delta2_search (&tp, ep, sp, len, trans, gc1, gc2, d1, kwset)) + return tp - text; + } + + /* Now only a few characters are left to search. Carefully avoid + ever producing an out-of-bounds pointer. */ + ep = text + size; + d = d1[U(tp[-1])]; + while (d <= ep - tp) + { + d = d1[U((tp += d)[-1])]; + if (d != 0) + continue; + if (bm_delta2_search (&tp, ep, sp, len, trans, gc1, gc2, NULL, kwset)) + return tp - text; + } + + return -1; +} + +/* Fast Boyer-Moore search. */ +static ptrdiff_t +bmexec (kwset_t kwset, char const *text, ptrdiff_t size, + struct kwsmatch *kwsmatch, bool longest) +{ + /* Help the compiler inline in two ways, depending on whether + kwset->trans is null. */ + ptrdiff_t ret = (IGNORE_DUPLICATE_BRANCH_WARNING + (kwset->trans + ? bmexec_trans (kwset, text, size) + : bmexec_trans (kwset, text, size))); + kwsmatch->index = 0; + kwsmatch->offset = ret; + kwsmatch->size = kwset->mind; + return ret; +} + +/* Hairy multiple string search with the Aho-Corasick algorithm. + (inlinable version) */ +static inline ptrdiff_t +acexec_trans (kwset_t kwset, char const *text, ptrdiff_t len, + struct kwsmatch *kwsmatch, bool longest) +{ + struct trie const *trie, *accept; + char const *tp, *left, *lim; + struct tree const *tree; + char const *trans; + + /* Initialize register copies and look for easy ways out. */ + if (len < kwset->mind) + return -1; + trans = kwset->trans; + trie = kwset->trie; + lim = text + len; + tp = text; + + if (!trie->accepting) + { + unsigned char c; + int gc1 = kwset->gc1; + + while (true) + { + if (gc1 < 0) + { + while (! (trie = kwset->next[c = tr (trans, *tp++)])) + if (tp >= lim) + return -1; + } + else + { + tp = memchr_kwset (tp, lim - tp, kwset); + if (!tp) + return -1; + c = tr (trans, *tp++); + trie = kwset->next[c]; + } + + while (true) + { + if (trie->accepting) + goto match; + if (tp >= lim) + return -1; + c = tr (trans, *tp++); + + for (tree = trie->links; c != tree->label; ) + { + tree = c < tree->label ? tree->llink : tree->rlink; + if (! tree) + { + trie = trie->fail; + if (!trie) + { + trie = kwset->next[c]; + if (trie) + goto have_trie; + if (tp >= lim) + return -1; + goto next_c; + } + if (trie->accepting) + { + --tp; + goto match; + } + tree = trie->links; + } + } + trie = tree->trie; + have_trie:; + } + next_c:; + } + } + + match: + accept = trie; + while (accept->accepting == SIZE_MAX) + accept = accept->fail; + left = tp - accept->depth; + + /* Try left-most longest match. */ + if (longest) + { + while (tp < lim) + { + struct trie const *accept1; + char const *left1; + unsigned char c = tr (trans, *tp++); + + do + { + tree = trie->links; + while (tree && c != tree->label) + tree = c < tree->label ? tree->llink : tree->rlink; + } + while (!tree && (trie = trie->fail) && accept->depth <= trie->depth); + + if (!tree) + break; + trie = tree->trie; + if (trie->accepting) + { + accept1 = trie; + while (accept1->accepting == SIZE_MAX) + accept1 = accept1->fail; + left1 = tp - accept1->depth; + if (left1 <= left) + { + left = left1; + accept = accept1; + } + } + } + } + + kwsmatch->index = accept->accepting / 2; + kwsmatch->offset = left - text; + kwsmatch->size = accept->depth; + + return left - text; +} + +/* Hairy multiple string search with Aho-Corasick algorithm. */ +static ptrdiff_t +acexec (kwset_t kwset, char const *text, ptrdiff_t size, + struct kwsmatch *kwsmatch, bool longest) +{ + assume (0 <= size); + /* Help the compiler inline in two ways, depending on whether + kwset->trans is null. */ + return (IGNORE_DUPLICATE_BRANCH_WARNING + (kwset->trans + ? acexec_trans (kwset, text, size, kwsmatch, longest) + : acexec_trans (kwset, text, size, kwsmatch, longest))); +} + +/* Find the first instance of a KWSET member in TEXT, which has SIZE bytes. + Return the offset (into TEXT) of the first byte of the matching substring, + or -1 if no match is found. Upon a match, store details in + *KWSMATCH: index of matched keyword, start offset (same as the return + value), and length. If LONGEST, find the longest match; otherwise + any match will do. */ +ptrdiff_t +kwsexec (kwset_t kwset, char const *text, ptrdiff_t size, + struct kwsmatch *kwsmatch, bool longest) +{ + return kwset->kwsexec (kwset, text, size, kwsmatch, longest); +} + +/* Free the components of the given keyword set. */ +void +kwsfree (kwset_t kwset) +{ + obstack_free (&kwset->obstack, NULL); + free (kwset); +} diff --git a/src/grep/src/kwset.h b/src/grep/src/kwset.h new file mode 100644 index 0000000..24e13e2 --- /dev/null +++ b/src/grep/src/kwset.h @@ -0,0 +1,44 @@ +/* kwset.h - header declaring the keyword set library. + Copyright (C) 1989, 1998, 2005, 2007, 2009-2021 Free Software Foundation, + Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written August 1989 by Mike Haertel. */ + +#include <stddef.h> +#include <stdbool.h> + +struct kwsmatch +{ + ptrdiff_t index; /* Index number of matching keyword. */ + ptrdiff_t offset; /* Offset of match. */ + ptrdiff_t size; /* Length of match. */ +}; + +#include "arg-nonnull.h" + +struct kwset; +typedef struct kwset *kwset_t; + +extern kwset_t kwsalloc (char const *); +extern void kwsincr (kwset_t, char const *, ptrdiff_t); +extern ptrdiff_t kwswords (kwset_t) _GL_ATTRIBUTE_PURE; +extern void kwsprep (kwset_t); +extern ptrdiff_t kwsexec (kwset_t, char const *, ptrdiff_t, + struct kwsmatch *, bool) + _GL_ARG_NONNULL ((4)); +extern void kwsfree (kwset_t); diff --git a/src/grep/src/pcresearch.c b/src/grep/src/pcresearch.c new file mode 100644 index 0000000..37f7e40 --- /dev/null +++ b/src/grep/src/pcresearch.c @@ -0,0 +1,352 @@ +/* pcresearch.c - searching subroutines using PCRE for grep. + Copyright 2000, 2007, 2009-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written August 1992 by Mike Haertel. */ + +#include <config.h> +#include "search.h" +#include "die.h" + +#include <pcre.h> + +/* This must be at least 2; everything after that is for performance + in pcre_exec. */ +enum { NSUB = 300 }; + +#ifndef PCRE_EXTRA_MATCH_LIMIT_RECURSION +# define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0 +#endif +#ifndef PCRE_STUDY_JIT_COMPILE +# define PCRE_STUDY_JIT_COMPILE 0 +#endif +#ifndef PCRE_STUDY_EXTRA_NEEDED +# define PCRE_STUDY_EXTRA_NEEDED 0 +#endif + +struct pcre_comp +{ + /* Compiled internal form of a Perl regular expression. */ + pcre *cre; + + /* Additional information about the pattern. */ + pcre_extra *extra; + +#if PCRE_STUDY_JIT_COMPILE + /* The JIT stack and its maximum size. */ + pcre_jit_stack *jit_stack; + int jit_stack_size; +#endif + + /* Table, indexed by ! (flag & PCRE_NOTBOL), of whether the empty + string matches when that flag is used. */ + int empty_match[2]; +}; + + +/* Match the already-compiled PCRE pattern against the data in SUBJECT, + of size SEARCH_BYTES and starting with offset SEARCH_OFFSET, with + options OPTIONS, and storing resulting matches into SUB. Return + the (nonnegative) match location or a (negative) error number. */ +static int +jit_exec (struct pcre_comp *pc, char const *subject, int search_bytes, + int search_offset, int options, int *sub) +{ + while (true) + { + int e = pcre_exec (pc->cre, pc->extra, subject, search_bytes, + search_offset, options, sub, NSUB); + +#if PCRE_STUDY_JIT_COMPILE + if (e == PCRE_ERROR_JIT_STACKLIMIT + && 0 < pc->jit_stack_size && pc->jit_stack_size <= INT_MAX / 2) + { + int old_size = pc->jit_stack_size; + int new_size = pc->jit_stack_size = old_size * 2; + if (pc->jit_stack) + pcre_jit_stack_free (pc->jit_stack); + pc->jit_stack = pcre_jit_stack_alloc (old_size, new_size); + if (!pc->jit_stack) + die (EXIT_TROUBLE, 0, + _("failed to allocate memory for the PCRE JIT stack")); + pcre_assign_jit_stack (pc->extra, NULL, pc->jit_stack); + continue; + } +#endif + +#if PCRE_EXTRA_MATCH_LIMIT_RECURSION + if (e == PCRE_ERROR_RECURSIONLIMIT + && (PCRE_STUDY_EXTRA_NEEDED || pc->extra)) + { + unsigned long lim + = (pc->extra->flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION + ? pc->extra->match_limit_recursion + : 0); + if (lim <= ULONG_MAX / 2) + { + pc->extra->match_limit_recursion = lim ? 2 * lim : (1 << 24) - 1; + pc->extra->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; + continue; + } + } +#endif + + return e; + } +} + +/* Compile the -P style PATTERN, containing SIZE bytes that are + followed by '\n'. Return a description of the compiled pattern. */ + +void * +Pcompile (char *pattern, size_t size, reg_syntax_t ignored, bool exact) +{ + int e; + char const *ep; + static char const wprefix[] = "(?<!\\w)(?:"; + static char const wsuffix[] = ")(?!\\w)"; + static char const xprefix[] = "^(?:"; + static char const xsuffix[] = ")$"; + int fix_len_max = MAX (sizeof wprefix - 1 + sizeof wsuffix - 1, + sizeof xprefix - 1 + sizeof xsuffix - 1); + char *re = xnmalloc (4, size + (fix_len_max + 4 - 1) / 4); + int flags = PCRE_DOLLAR_ENDONLY | (match_icase ? PCRE_CASELESS : 0); + char *patlim = pattern + size; + char *n = re; + char const *p; + char const *pnul; + struct pcre_comp *pc = xcalloc (1, sizeof (*pc)); + + if (localeinfo.multibyte) + { + if (! localeinfo.using_utf8) + die (EXIT_TROUBLE, 0, _("-P supports only unibyte and UTF-8 locales")); + flags |= PCRE_UTF8; + } + + /* FIXME: Remove this restriction. */ + if (rawmemchr (pattern, '\n') != patlim) + die (EXIT_TROUBLE, 0, _("the -P option only supports a single pattern")); + + *n = '\0'; + if (match_words) + strcpy (n, wprefix); + if (match_lines) + strcpy (n, xprefix); + n += strlen (n); + + /* The PCRE interface doesn't allow NUL bytes in the pattern, so + replace each NUL byte in the pattern with the four characters + "\000", removing a preceding backslash if there are an odd + number of backslashes before the NUL. */ + *patlim = '\0'; + for (p = pattern; (pnul = p + strlen (p)) < patlim; p = pnul + 1) + { + memcpy (n, p, pnul - p); + n += pnul - p; + for (p = pnul; pattern < p && p[-1] == '\\'; p--) + continue; + n -= (pnul - p) & 1; + strcpy (n, "\\000"); + n += 4; + } + memcpy (n, p, patlim - p + 1); + n += patlim - p; + *patlim = '\n'; + + if (match_words) + strcpy (n, wsuffix); + if (match_lines) + strcpy (n, xsuffix); + + pc->cre = pcre_compile (re, flags, &ep, &e, pcre_maketables ()); + if (!pc->cre) + die (EXIT_TROUBLE, 0, "%s", ep); + + int pcre_study_flags = PCRE_STUDY_EXTRA_NEEDED | PCRE_STUDY_JIT_COMPILE; + pc->extra = pcre_study (pc->cre, pcre_study_flags, &ep); + if (ep) + die (EXIT_TROUBLE, 0, "%s", ep); + +#if PCRE_STUDY_JIT_COMPILE + if (pcre_fullinfo (pc->cre, pc->extra, PCRE_INFO_JIT, &e)) + die (EXIT_TROUBLE, 0, _("internal error (should never happen)")); + + /* The PCRE documentation says that a 32 KiB stack is the default. */ + if (e) + pc->jit_stack_size = 32 << 10; +#endif + + free (re); + + int sub[NSUB]; + pc->empty_match[false] = pcre_exec (pc->cre, pc->extra, "", 0, 0, + PCRE_NOTBOL, sub, NSUB); + pc->empty_match[true] = pcre_exec (pc->cre, pc->extra, "", 0, 0, 0, sub, + NSUB); + + return pc; +} + +size_t +Pexecute (void *vcp, char const *buf, size_t size, size_t *match_size, + char const *start_ptr) +{ + int sub[NSUB]; + char const *p = start_ptr ? start_ptr : buf; + bool bol = p[-1] == eolbyte; + char const *line_start = buf; + int e = PCRE_ERROR_NOMATCH; + char const *line_end; + struct pcre_comp *pc = vcp; + + /* The search address to pass to pcre_exec. This is the start of + the buffer, or just past the most-recently discovered encoding + error or line end. */ + char const *subject = buf; + + do + { + /* Search line by line. Although this code formerly used + PCRE_MULTILINE for performance, the performance wasn't always + better and the correctness issues were too puzzling. See + Bug#22655. */ + line_end = rawmemchr (p, eolbyte); + if (INT_MAX < line_end - p) + die (EXIT_TROUBLE, 0, _("exceeded PCRE's line length limit")); + + for (;;) + { + /* Skip past bytes that are easily determined to be encoding + errors, treating them as data that cannot match. This is + faster than having pcre_exec check them. */ + while (localeinfo.sbclen[to_uchar (*p)] == -1) + { + p++; + subject = p; + bol = false; + } + + int search_offset = p - subject; + + /* Check for an empty match; this is faster than letting + pcre_exec do it. */ + if (p == line_end) + { + sub[0] = sub[1] = search_offset; + e = pc->empty_match[bol]; + break; + } + + int options = 0; + if (!bol) + options |= PCRE_NOTBOL; + + e = jit_exec (pc, subject, line_end - subject, search_offset, + options, sub); + if (e != PCRE_ERROR_BADUTF8) + break; + int valid_bytes = sub[0]; + + if (search_offset <= valid_bytes) + { + /* Try to match the string before the encoding error. */ + if (valid_bytes == 0) + { + /* Handle the empty-match case specially, for speed. + This optimization is valid if VALID_BYTES is zero, + which means SEARCH_OFFSET is also zero. */ + sub[1] = 0; + e = pc->empty_match[bol]; + } + else + e = jit_exec (pc, subject, valid_bytes, search_offset, + options | PCRE_NO_UTF8_CHECK | PCRE_NOTEOL, sub); + + if (e != PCRE_ERROR_NOMATCH) + break; + + /* Treat the encoding error as data that cannot match. */ + p = subject + valid_bytes + 1; + bol = false; + } + + subject += valid_bytes + 1; + } + + if (e != PCRE_ERROR_NOMATCH) + break; + bol = true; + p = subject = line_start = line_end + 1; + } + while (p < buf + size); + + if (e <= 0) + { + switch (e) + { + case PCRE_ERROR_NOMATCH: + break; + + case PCRE_ERROR_NOMEMORY: + die (EXIT_TROUBLE, 0, _("%s: memory exhausted"), input_filename ()); + +#if PCRE_STUDY_JIT_COMPILE + case PCRE_ERROR_JIT_STACKLIMIT: + die (EXIT_TROUBLE, 0, _("%s: exhausted PCRE JIT stack"), + input_filename ()); +#endif + + case PCRE_ERROR_MATCHLIMIT: + die (EXIT_TROUBLE, 0, _("%s: exceeded PCRE's backtracking limit"), + input_filename ()); + + case PCRE_ERROR_RECURSIONLIMIT: + die (EXIT_TROUBLE, 0, _("%s: exceeded PCRE's recursion limit"), + input_filename ()); + + default: + /* For now, we lump all remaining PCRE failures into this basket. + If anyone cares to provide sample grep usage that can trigger + particular PCRE errors, we can add to the list (above) of more + detailed diagnostics. */ + die (EXIT_TROUBLE, 0, _("%s: internal PCRE error: %d"), + input_filename (), e); + } + + return -1; + } + else + { + char const *matchbeg = subject + sub[0]; + char const *matchend = subject + sub[1]; + char const *beg; + char const *end; + if (start_ptr) + { + beg = matchbeg; + end = matchend; + } + else + { + beg = line_start; + end = line_end + 1; + } + *match_size = end - beg; + return beg - buf; + } +} diff --git a/src/grep/src/search.h b/src/grep/src/search.h new file mode 100644 index 0000000..4853583 --- /dev/null +++ b/src/grep/src/search.h @@ -0,0 +1,89 @@ +/* search.c - searching subroutines using dfa, kwset and regex for grep. + Copyright 1992, 1998, 2000, 2007, 2009-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef GREP_SEARCH_H +#define GREP_SEARCH_H 1 + +#include <config.h> + +#include <sys/types.h> +#include <stdint.h> +#include <wchar.h> +#include <wctype.h> +#include <regex.h> + +#include "system.h" +#include "grep.h" +#include "dfa.h" +#include "kwset.h" +#include "xalloc.h" +#include "localeinfo.h" + +_GL_INLINE_HEADER_BEGIN +#ifndef SEARCH_INLINE +# define SEARCH_INLINE _GL_INLINE +#endif + +/* This must be a signed type. Each value is the difference in the size + of a character (in bytes) induced by converting to lower case. + The vast majority of values are 0, but a few are 1 or -1, so + technically, two bits may be sufficient. */ +typedef signed char mb_len_map_t; + +/* searchutils.c */ +extern void wordinit (void); +extern kwset_t kwsinit (bool); +extern size_t wordchars_size (char const *, char const *) _GL_ATTRIBUTE_PURE; +extern size_t wordchar_next (char const *, char const *) _GL_ATTRIBUTE_PURE; +extern size_t wordchar_prev (char const *, char const *, char const *) + _GL_ATTRIBUTE_PURE; +extern ptrdiff_t mb_goback (char const **, size_t *, char const *, + char const *); + +/* dfasearch.c */ +extern void *GEAcompile (char *, size_t, reg_syntax_t, bool); +extern size_t EGexecute (void *, char const *, size_t, size_t *, char const *); + +/* kwsearch.c */ +extern void *Fcompile (char *, size_t, reg_syntax_t, bool); +extern size_t Fexecute (void *, char const *, size_t, size_t *, char const *); + +/* pcresearch.c */ +extern void *Pcompile (char *, size_t, reg_syntax_t, bool); +extern size_t Pexecute (void *, char const *, size_t, size_t *, char const *); + +/* grep.c */ +extern struct localeinfo localeinfo; +extern void fgrep_to_grep_pattern (char **, size_t *); + +/* Return the number of bytes in the character at the start of S, which + is of size N. N must be positive. MBS is the conversion state. + This acts like mbrlen, except it returns 1 when mbrlen would return 0, + and it is typically faster because of the cache. */ +SEARCH_INLINE size_t +mb_clen (char const *s, size_t n, mbstate_t *mbs) +{ + size_t len = localeinfo.sbclen[to_uchar (*s)]; + return len == (size_t) -2 ? mbrlen (s, n, mbs) : len; +} + +extern char const *input_filename (void); + +_GL_INLINE_HEADER_END + +#endif /* GREP_SEARCH_H */ diff --git a/src/grep/src/searchutils.c b/src/grep/src/searchutils.c new file mode 100644 index 0000000..8058511 --- /dev/null +++ b/src/grep/src/searchutils.c @@ -0,0 +1,190 @@ +/* searchutils.c - helper subroutines for grep's matchers. + Copyright 1992, 1998, 2000, 2007, 2009-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include <config.h> + +#define SEARCH_INLINE _GL_EXTERN_INLINE +#define SYSTEM_INLINE _GL_EXTERN_INLINE +#include "search.h" + +/* For each byte B, sbwordchar[B] is true if B is a single-byte + character that is a word constituent, and is false otherwise. */ +static bool sbwordchar[NCHAR]; + +/* Whether -w considers WC to be a word constituent. */ +static bool +wordchar (wint_t wc) +{ + return wc == L'_' || iswalnum (wc); +} + +void +wordinit (void) +{ + for (int i = 0; i < NCHAR; i++) + sbwordchar[i] = wordchar (localeinfo.sbctowc[i]); +} + +kwset_t +kwsinit (bool mb_trans) +{ + char *trans = NULL; + + if (match_icase && (MB_CUR_MAX == 1 || mb_trans)) + { + trans = xmalloc (NCHAR); + /* If I is a single-byte character that becomes a different + single-byte character when uppercased, set trans[I] + to that character. Otherwise, set trans[I] to I. */ + for (int i = 0; i < NCHAR; i++) + trans[i] = toupper (i); + } + + return kwsalloc (trans); +} + +/* In the buffer *MB_START, return the number of bytes needed to go + back from CUR to the previous boundary, where a "boundary" is the + start of a multibyte character or is an error-encoding byte. The + buffer ends at END (i.e., one past the address of the buffer's last + byte). If CUR is already at a boundary, return 0. If CUR is no + larger than *MB_START, return CUR - *MB_START without modifying + *MB_START or *MBCLEN. + + When returning zero, set *MB_START to CUR. When returning a + positive value, set *MB_START to the next boundary after CUR, + or to END if there is no such boundary, and set *MBCLEN to the + length of the preceding character. */ +ptrdiff_t +mb_goback (char const **mb_start, size_t *mbclen, char const *cur, + char const *end) +{ + const char *p = *mb_start; + const char *p0 = p; + size_t clen; + + if (cur <= p) + return cur - p; + + if (localeinfo.using_utf8) + { + p = cur; + clen = 1; + + if (cur < end && (*cur & 0xc0) == 0x80) + for (int i = 1; i <= 3; i++) + if ((cur[-i] & 0xc0) != 0x80) + { + mbstate_t mbs = { 0 }; + clen = mb_clen (cur - i, end - (cur - i), &mbs); + if (i < clen && clen < (size_t) -2) + { + p0 = cur - i; + p = p0 + clen; + } + break; + } + } + else + { + mbstate_t mbs = { 0 }; + do + { + clen = mb_clen (p, end - p, &mbs); + + if ((size_t) -2 <= clen) + { + /* An invalid sequence, or a truncated multibyte character. + Treat it as a single byte character. */ + clen = 1; + memset (&mbs, 0, sizeof mbs); + } + p0 = p; + p += clen; + } + while (p < cur); + } + + *mb_start = p; + if (mbclen) + *mbclen = clen; + return p == cur ? 0 : cur - p0; +} + +/* Examine the start of BUF (which goes to END) for word constituents. + If COUNTALL, examine as many as possible; otherwise, examine at most one. + Return the total number of bytes in the examined characters. */ +static size_t +wordchars_count (char const *buf, char const *end, bool countall) +{ + size_t n = 0; + mbstate_t mbs = { 0 }; + while (n < end - buf) + { + unsigned char b = buf[n]; + if (sbwordchar[b]) + n++; + else if (localeinfo.sbclen[b] != -2) + break; + else + { + wchar_t wc = 0; + size_t wcbytes = mbrtowc (&wc, buf + n, end - buf - n, &mbs); + if (!wordchar (wc)) + break; + n += wcbytes + !wcbytes; + } + if (!countall) + break; + } + return n; +} + +/* Examine the start of BUF for the longest prefix containing just + word constituents. Return the total number of bytes in the prefix. + The buffer ends at END. */ +size_t +wordchars_size (char const *buf, char const *end) +{ + return wordchars_count (buf, end, true); +} + +/* If BUF starts with a word constituent, return the number of bytes + used to represent it; otherwise, return zero. The buffer ends at END. */ +size_t +wordchar_next (char const *buf, char const *end) +{ + return wordchars_count (buf, end, false); +} + +/* In the buffer BUF, return nonzero if the character whose encoding + contains the byte before CUR is a word constituent. The buffer + ends at END. */ +size_t +wordchar_prev (char const *buf, char const *cur, char const *end) +{ + if (buf == cur) + return 0; + unsigned char b = *--cur; + if (! localeinfo.multibyte + || (localeinfo.using_utf8 && localeinfo.sbclen[b] == 1)) + return sbwordchar[b]; + char const *p = buf; + cur -= mb_goback (&p, NULL, cur, end); + return wordchar_next (cur, end); +} diff --git a/src/grep/src/system.h b/src/grep/src/system.h new file mode 100644 index 0000000..2607f96 --- /dev/null +++ b/src/grep/src/system.h @@ -0,0 +1,132 @@ +/* Portability cruft. Include after config.h and sys/types.h. + Copyright 1996, 1998-2000, 2007, 2009-2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef GREP_SYSTEM_H +#define GREP_SYSTEM_H 1 + +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "configmake.h" +#include "dirname.h" +#include "ignore-value.h" +#include "minmax.h" +#include "same-inode.h" + +#include <stdlib.h> +#include <stddef.h> +#include <limits.h> +#include <string.h> +#include <ctype.h> + +enum { EXIT_TROUBLE = 2 }; +enum { NCHAR = UCHAR_MAX + 1 }; + +#include <gettext.h> +#define N_(String) gettext_noop(String) +#define _(String) gettext(String) + +#include <locale.h> + +#ifndef initialize_main +# define initialize_main(argcp, argvp) +#endif + +#include "unlocked-io.h" + +_GL_INLINE_HEADER_BEGIN +#ifndef SYSTEM_INLINE +# define SYSTEM_INLINE _GL_INLINE +#endif + +#define STREQ(a, b) (strcmp (a, b) == 0) + +/* Convert a possibly-signed character to an unsigned character. This is + a bit safer than casting to unsigned char, since it catches some type + errors that the cast doesn't. */ +SYSTEM_INLINE unsigned char +to_uchar (char ch) +{ + return ch; +} + +_GL_INLINE_HEADER_END + +#ifndef __has_feature +# define __has_feature(F) false +#endif + +#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer) +# define HAVE_ASAN 1 +#else +# define HAVE_ASAN 0 +#endif + +#if HAVE_ASAN + +/* Mark memory region [addr, addr+size) as unaddressable. + This memory must be previously allocated by the user program. Accessing + addresses in this region from instrumented code is forbidden until + this region is unpoisoned. This function is not guaranteed to poison + the whole region - it may poison only a subregion of [addr, addr+size) + due to ASan alignment restrictions. + Method is NOT thread-safe in the sense that no two threads can + (un)poison memory in the same memory region simultaneously. */ +void __asan_poison_memory_region (void const volatile *addr, size_t size); + +/* Mark memory region [addr, addr+size) as addressable. + This memory must be previously allocated by the user program. Accessing + addresses in this region is allowed until this region is poisoned again. + This function may unpoison a superregion of [addr, addr+size) due to + ASan alignment restrictions. + Method is NOT thread-safe in the sense that no two threads can + (un)poison memory in the same memory region simultaneously. */ +void __asan_unpoison_memory_region (void const volatile *addr, size_t size); + +#else + +static _GL_UNUSED void +__asan_poison_memory_region (void const volatile *addr, size_t size) { } +static _GL_UNUSED void +__asan_unpoison_memory_region (void const volatile *addr, size_t size) { } +#endif + +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + +/* When we deliberately use duplicate branches, use this macro to + disable gcc's -Wduplicated-branches in the containing expression. */ +#if 7 <= __GNUC__ +# define IGNORE_DUPLICATE_BRANCH_WARNING(exp) \ + ({ \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wduplicated-branches\"") \ + exp; \ + _Pragma ("GCC diagnostic pop") \ + }) +#else +# define IGNORE_DUPLICATE_BRANCH_WARNING(exp) exp +#endif + +#endif |