From cf28ed851948818eef148d616edca961f756ade8 Mon Sep 17 00:00:00 2001 From: John Marino Date: Tue, 8 May 2012 12:48:47 +0200 Subject: [PATCH] Upgrade grep version 2.9 to 2.12 on the vendor branch --- contrib/grep/README | 2 +- contrib/grep/doc/fdl.texi | 2 +- contrib/grep/doc/grep.texi | 431 +-- contrib/grep/doc/version.texi | 8 +- contrib/grep/lib/alloca.c | 4 +- contrib/grep/lib/argmatch.c | 12 +- contrib/grep/lib/argmatch.h | 9 +- contrib/grep/lib/at-func.c | 131 + contrib/grep/lib/basename-lgpl.c | 2 +- contrib/grep/lib/basename.c | 58 - contrib/grep/lib/binary-io.h | 2 +- contrib/grep/lib/bitrotate.h | 2 +- contrib/grep/lib/btowc.c | 2 +- contrib/grep/lib/c-ctype.c | 7 +- contrib/grep/lib/c-ctype.h | 41 +- contrib/grep/lib/c-strcase.h | 12 +- contrib/grep/lib/c-strcasecmp.c | 7 +- contrib/grep/lib/c-strcaseeq.h | 184 ++ contrib/grep/lib/c-strncasecmp.c | 7 +- contrib/grep/lib/chdir-long.c | 266 ++ .../grep/lib/{mbsrtowcs.c => chdir-long.h} | 26 +- contrib/grep/lib/cloexec.c | 83 + contrib/grep/lib/cloexec.h | 38 + contrib/grep/lib/close-stream.c | 4 +- contrib/grep/lib/{wcrtomb.c => close.c} | 68 +- contrib/grep/lib/closedir.c | 67 + contrib/grep/lib/closeout.c | 4 +- contrib/grep/lib/closeout.h | 2 +- contrib/grep/lib/colorize-posix.c | 58 + contrib/grep/lib/colorize-w32.c | 208 ++ contrib/grep/lib/colorize.c | 58 + .../grep/{src/mbsupport.h => lib/colorize.h} | 25 +- contrib/grep/lib/config.charset | 7 +- .../grep/lib/{exitfail.c => creat-safer.c} | 17 +- contrib/grep/lib/cycle-check.c | 85 + contrib/grep/lib/cycle-check.h | 52 + contrib/grep/lib/dev-ino.h | 13 + contrib/grep/lib/{exitfail.c => dirent--.h} | 13 +- contrib/grep/lib/dirent-private.h | 40 + contrib/grep/lib/{quote.h => dirent-safer.h} | 10 +- contrib/grep/lib/{mbsrtowcs.c => dirfd.c} | 28 +- contrib/grep/lib/dirname-lgpl.c | 8 +- contrib/grep/lib/dirname.c | 38 - contrib/grep/lib/dirname.h | 8 +- contrib/grep/lib/dosname.h | 2 +- contrib/grep/lib/{mbrlen.c => dup-safer.c} | 24 +- contrib/grep/lib/{mbsrtowcs.c => dup.c} | 53 +- contrib/grep/lib/dup2.c | 157 + contrib/grep/lib/error.c | 17 +- contrib/grep/lib/error.h | 8 +- contrib/grep/lib/exclude.c | 2 +- contrib/grep/lib/exclude.h | 4 +- contrib/grep/lib/exitfail.c | 2 +- contrib/grep/lib/exitfail.h | 2 +- contrib/grep/lib/fchdir.c | 208 ++ contrib/grep/lib/{exitfail.c => fcntl--.h} | 20 +- .../grep/lib/{exitfail.c => fcntl-safer.h} | 15 +- contrib/grep/lib/fcntl.c | 311 ++ contrib/grep/lib/fd-hook.c | 116 + contrib/grep/lib/fd-hook.h | 119 + contrib/grep/lib/fd-safer.c | 49 + contrib/grep/lib/fdopendir.c | 204 ++ contrib/grep/lib/filename.h | 54 + contrib/grep/lib/filenamecat-lgpl.c | 88 + .../grep/lib/{closeout.h => filenamecat.h} | 27 +- contrib/grep/lib/fnmatch.c | 17 +- contrib/grep/lib/fnmatch_loop.c | 18 +- contrib/grep/lib/fpending.c | 2 +- contrib/grep/lib/fpending.h | 2 +- contrib/grep/lib/fstat.c | 86 + contrib/grep/lib/fstatat.c | 135 + contrib/grep/lib/fts-cycle.c | 160 ++ contrib/grep/lib/fts.c | 2095 ++++++++++++++ contrib/grep/lib/fts_.h | 272 ++ contrib/grep/lib/getcwd-lgpl.c | 125 + contrib/grep/lib/getdtablesize.c | 86 + contrib/grep/lib/getopt.c | 75 +- contrib/grep/lib/getopt1.c | 6 +- contrib/grep/lib/getopt_int.h | 16 +- contrib/grep/lib/getpagesize.c | 4 +- contrib/grep/lib/gettext.h | 9 +- contrib/grep/lib/gnulib.mk | 776 ++++- contrib/grep/lib/hard-locale.c | 2 +- contrib/grep/lib/hard-locale.h | 2 +- contrib/grep/lib/hash.c | 59 +- contrib/grep/lib/hash.h | 41 +- contrib/grep/lib/i-ring.c | 68 + contrib/grep/lib/i-ring.h | 44 + contrib/grep/lib/iconv_open.c | 9 +- contrib/grep/lib/ignore-value.h | 7 +- contrib/grep/lib/intprops.h | 2 +- contrib/grep/lib/isatty.c | 81 + contrib/grep/lib/isblank.c | 2 +- contrib/grep/lib/isdir.c | 33 - contrib/grep/lib/isdir.h | 1 - .../grep/lib/{wctomb.c => iswctype-impl.h} | 17 +- contrib/grep/lib/{wctomb.c => iswctype.c} | 12 +- contrib/grep/lib/localcharset.c | 35 +- contrib/grep/lib/localcharset.h | 7 +- contrib/grep/lib/localeconv.c | 103 + contrib/grep/lib/lseek.c | 13 +- contrib/grep/lib/lstat.c | 97 + contrib/grep/lib/malloc.c | 7 +- contrib/grep/lib/malloca.c | 13 +- contrib/grep/lib/malloca.h | 7 +- contrib/grep/lib/mbchar.c | 2 +- contrib/grep/lib/mbchar.h | 2 +- contrib/grep/lib/mbiter.h | 6 +- contrib/grep/lib/mbrlen.c | 2 +- contrib/grep/lib/mbrtowc.c | 24 +- contrib/grep/lib/mbscasecmp.c | 2 +- contrib/grep/lib/mbsinit.c | 2 +- contrib/grep/lib/mbslen.c | 2 +- contrib/grep/lib/mbsrtowcs-state.c | 2 +- contrib/grep/lib/mbsrtowcs.c | 2 +- contrib/grep/lib/mbsstr.c | 2 +- contrib/grep/lib/mbuiter.h | 6 +- contrib/grep/lib/memchr.c | 2 +- contrib/grep/lib/mempcpy.c | 7 +- contrib/grep/lib/{memchr.c => memrchr.c} | 75 +- contrib/grep/lib/minmax.h | 7 +- contrib/grep/lib/msvc-inval.c | 129 + contrib/grep/lib/msvc-inval.h | 222 ++ contrib/grep/lib/msvc-nothrow.c | 49 + contrib/grep/lib/msvc-nothrow.h | 43 + contrib/grep/lib/nl_langinfo.c | 5 +- contrib/grep/lib/obstack.c | 28 +- contrib/grep/lib/obstack.h | 26 +- contrib/grep/lib/{mbslen.c => open-safer.c} | 42 +- contrib/grep/lib/open.c | 13 +- contrib/grep/lib/openat-die.c | 62 + contrib/grep/lib/openat-priv.h | 64 + contrib/grep/lib/openat-proc.c | 110 + contrib/grep/lib/{mbslen.c => openat-safer.c} | 42 +- contrib/grep/lib/openat.c | 286 ++ contrib/grep/lib/openat.h | 104 + contrib/grep/lib/opendir-safer.c | 76 + contrib/grep/lib/opendir.c | 148 + contrib/grep/lib/pathmax.h | 83 + contrib/grep/lib/pipe-safer.c | 56 + contrib/grep/lib/progname.c | 2 +- contrib/grep/lib/progname.h | 2 +- contrib/grep/lib/propername.c | 8 +- contrib/grep/lib/propername.h | 4 +- contrib/grep/lib/quote.c | 40 - contrib/grep/lib/quote.h | 15 +- contrib/grep/lib/quotearg.c | 103 +- contrib/grep/lib/quotearg.h | 8 +- contrib/grep/lib/readdir.c | 98 + contrib/grep/lib/realloc.c | 2 +- contrib/grep/lib/ref-add.sin | 5 +- contrib/grep/lib/ref-del.sin | 5 +- contrib/grep/lib/regcomp.c | 196 +- contrib/grep/lib/regex.c | 20 +- contrib/grep/lib/regex.h | 231 +- contrib/grep/lib/regex_internal.c | 67 +- contrib/grep/lib/regex_internal.h | 65 +- contrib/grep/lib/regexec.c | 156 +- contrib/grep/lib/{closeout.h => same-inode.h} | 33 +- contrib/grep/lib/save-cwd.c | 99 + contrib/grep/lib/{fpending.c => save-cwd.h} | 28 +- contrib/grep/lib/savedir.c | 163 -- contrib/grep/lib/savedir.h | 11 - contrib/grep/lib/stat.c | 38 +- contrib/grep/lib/stpcpy.c | 2 +- contrib/grep/lib/str-kmp.h | 7 +- .../grep/lib/{c-strcasecmp.c => strcasecmp.c} | 29 +- contrib/grep/lib/strdup.c | 54 + contrib/grep/lib/streq.h | 12 +- contrib/grep/lib/strerror-override.c | 366 +-- contrib/grep/lib/strerror-override.h | 31 +- contrib/grep/lib/strerror.c | 17 +- contrib/grep/lib/striconv.c | 7 +- contrib/grep/lib/striconv.h | 7 +- contrib/grep/lib/stripslash.c | 4 +- .../lib/{c-strncasecmp.c => strncasecmp.c} | 25 +- contrib/grep/lib/strndup.c | 39 - contrib/grep/lib/strnlen.c | 7 +- contrib/grep/lib/strnlen1.c | 2 +- contrib/grep/lib/strnlen1.h | 5 +- contrib/grep/lib/strtoimax.c | 2 +- contrib/grep/lib/strtol.c | 14 +- contrib/grep/lib/{strtoul.c => strtoll.c} | 20 +- contrib/grep/lib/strtoul.c | 2 +- contrib/grep/lib/strtoull.c | 4 +- contrib/grep/lib/trim.c | 4 +- contrib/grep/lib/trim.h | 2 +- contrib/grep/lib/{exitfail.c => unistd--.h} | 20 +- .../grep/lib/{closeout.h => unistd-safer.h} | 29 +- contrib/grep/lib/unistr/u8-mbtoucr.c | 4 +- contrib/grep/lib/unistr/u8-uctomb-aux.c | 4 +- contrib/grep/lib/unistr/u8-uctomb.c | 4 +- contrib/grep/lib/uniwidth/cjk.h | 20 +- contrib/grep/lib/uniwidth/width.c | 4 +- contrib/grep/lib/unlocked-io.h | 2 +- contrib/grep/lib/verify.h | 16 +- contrib/grep/lib/version-etc-fsf.c | 2 +- contrib/grep/lib/version-etc.c | 4 +- contrib/grep/lib/version-etc.h | 8 +- contrib/grep/lib/wcrtomb.c | 2 +- contrib/grep/lib/wcscoll-impl.h | 111 + contrib/grep/lib/{wctomb.c => wcscoll.c} | 12 +- contrib/grep/lib/wctob.c | 2 +- contrib/grep/lib/wctomb-impl.h | 2 +- contrib/grep/lib/wctomb.c | 2 +- contrib/grep/lib/wcwidth.c | 4 +- contrib/grep/lib/xalloc-die.c | 4 +- contrib/grep/lib/xalloc-oversized.h | 2 +- contrib/grep/lib/xalloc.h | 16 +- contrib/grep/lib/xmalloc.c | 2 +- contrib/grep/lib/xstriconv.c | 2 +- contrib/grep/lib/xstriconv.h | 2 +- contrib/grep/lib/xstrndup.c | 36 - contrib/grep/lib/xstrndup.h | 23 - contrib/grep/lib/xstrtoimax.c | 6 + contrib/grep/lib/xstrtol-error.c | 8 +- contrib/grep/lib/xstrtol.c | 21 +- contrib/grep/lib/xstrtol.h | 14 +- contrib/grep/lib/xstrtoumax.c | 6 - contrib/grep/src/dfa.c | 2534 +++++++++-------- contrib/grep/src/dfa.h | 12 +- contrib/grep/src/dfasearch.c | 56 +- contrib/grep/src/egrep.c | 2 +- contrib/grep/src/fgrep.c | 2 +- contrib/grep/src/grep.c | 4 +- contrib/grep/src/grep.h | 6 +- contrib/grep/src/kwsearch.c | 28 +- contrib/grep/src/kwset.c | 24 +- contrib/grep/src/kwset.h | 4 +- contrib/grep/src/main.c | 888 +++--- contrib/grep/src/mbsupport.h | 20 +- contrib/grep/src/pcresearch.c | 18 +- contrib/grep/src/search.h | 4 +- contrib/grep/src/searchutils.c | 8 +- contrib/grep/src/system.h | 11 +- 235 files changed, 11990 insertions(+), 3996 deletions(-) create mode 100644 contrib/grep/lib/at-func.c delete mode 100644 contrib/grep/lib/basename.c create mode 100644 contrib/grep/lib/c-strcaseeq.h create mode 100644 contrib/grep/lib/chdir-long.c copy contrib/grep/lib/{mbsrtowcs.c => chdir-long.h} (62%) create mode 100644 contrib/grep/lib/cloexec.c create mode 100644 contrib/grep/lib/cloexec.h copy contrib/grep/lib/{wcrtomb.c => close.c} (50%) create mode 100644 contrib/grep/lib/closedir.c create mode 100644 contrib/grep/lib/colorize-posix.c create mode 100644 contrib/grep/lib/colorize-w32.c create mode 100644 contrib/grep/lib/colorize.c copy contrib/grep/{src/mbsupport.h => lib/colorize.h} (53%) copy contrib/grep/lib/{exitfail.c => creat-safer.c} (68%) create mode 100644 contrib/grep/lib/cycle-check.c create mode 100644 contrib/grep/lib/cycle-check.h create mode 100644 contrib/grep/lib/dev-ino.h copy contrib/grep/lib/{exitfail.c => dirent--.h} (74%) create mode 100644 contrib/grep/lib/dirent-private.h copy contrib/grep/lib/{quote.h => dirent-safer.h} (75%) copy contrib/grep/lib/{mbsrtowcs.c => dirfd.c} (68%) delete mode 100644 contrib/grep/lib/dirname.c copy contrib/grep/lib/{mbrlen.c => dup-safer.c} (64%) copy contrib/grep/lib/{mbsrtowcs.c => dup.c} (53%) create mode 100644 contrib/grep/lib/dup2.c create mode 100644 contrib/grep/lib/fchdir.c copy contrib/grep/lib/{exitfail.c => fcntl--.h} (65%) copy contrib/grep/lib/{exitfail.c => fcntl-safer.h} (66%) create mode 100644 contrib/grep/lib/fcntl.c create mode 100644 contrib/grep/lib/fd-hook.c create mode 100644 contrib/grep/lib/fd-hook.h create mode 100644 contrib/grep/lib/fd-safer.c create mode 100644 contrib/grep/lib/fdopendir.c create mode 100644 contrib/grep/lib/filename.h create mode 100644 contrib/grep/lib/filenamecat-lgpl.c copy contrib/grep/lib/{closeout.h => filenamecat.h} (64%) create mode 100644 contrib/grep/lib/fstat.c create mode 100644 contrib/grep/lib/fstatat.c create mode 100644 contrib/grep/lib/fts-cycle.c create mode 100644 contrib/grep/lib/fts.c create mode 100644 contrib/grep/lib/fts_.h create mode 100644 contrib/grep/lib/getcwd-lgpl.c create mode 100644 contrib/grep/lib/getdtablesize.c create mode 100644 contrib/grep/lib/i-ring.c create mode 100644 contrib/grep/lib/i-ring.h create mode 100644 contrib/grep/lib/isatty.c delete mode 100644 contrib/grep/lib/isdir.c delete mode 100644 contrib/grep/lib/isdir.h copy contrib/grep/lib/{wctomb.c => iswctype-impl.h} (76%) copy contrib/grep/lib/{wctomb.c => iswctype.c} (79%) create mode 100644 contrib/grep/lib/localeconv.c create mode 100644 contrib/grep/lib/lstat.c copy contrib/grep/lib/{memchr.c => memrchr.c} (75%) create mode 100644 contrib/grep/lib/msvc-inval.c create mode 100644 contrib/grep/lib/msvc-inval.h create mode 100644 contrib/grep/lib/msvc-nothrow.c create mode 100644 contrib/grep/lib/msvc-nothrow.h copy contrib/grep/lib/{mbslen.c => open-safer.c} (52%) create mode 100644 contrib/grep/lib/openat-die.c create mode 100644 contrib/grep/lib/openat-priv.h create mode 100644 contrib/grep/lib/openat-proc.c copy contrib/grep/lib/{mbslen.c => openat-safer.c} (50%) create mode 100644 contrib/grep/lib/openat.c create mode 100644 contrib/grep/lib/openat.h create mode 100644 contrib/grep/lib/opendir-safer.c create mode 100644 contrib/grep/lib/opendir.c create mode 100644 contrib/grep/lib/pathmax.h create mode 100644 contrib/grep/lib/pipe-safer.c delete mode 100644 contrib/grep/lib/quote.c create mode 100644 contrib/grep/lib/readdir.c copy contrib/grep/lib/{closeout.h => same-inode.h} (57%) create mode 100644 contrib/grep/lib/save-cwd.c copy contrib/grep/lib/{fpending.c => save-cwd.h} (63%) delete mode 100644 contrib/grep/lib/savedir.c delete mode 100644 contrib/grep/lib/savedir.h copy contrib/grep/lib/{c-strcasecmp.c => strcasecmp.c} (60%) create mode 100644 contrib/grep/lib/strdup.c copy contrib/grep/lib/{c-strncasecmp.c => strncasecmp.c} (65%) delete mode 100644 contrib/grep/lib/strndup.c copy contrib/grep/lib/{strtoul.c => strtoll.c} (63%) copy contrib/grep/lib/{exitfail.c => unistd--.h} (65%) copy contrib/grep/lib/{closeout.h => unistd-safer.h} (62%) create mode 100644 contrib/grep/lib/wcscoll-impl.h copy contrib/grep/lib/{wctomb.c => wcscoll.c} (81%) delete mode 100644 contrib/grep/lib/xstrndup.c delete mode 100644 contrib/grep/lib/xstrndup.h create mode 100644 contrib/grep/lib/xstrtoimax.c delete mode 100644 contrib/grep/lib/xstrtoumax.c diff --git a/contrib/grep/README b/contrib/grep/README index 9c550ee362..36b377b200 100644 --- a/contrib/grep/README +++ b/contrib/grep/README @@ -1,4 +1,4 @@ - Copyright (C) 1992, 1997-2002, 2004-2011 Free Software Foundation, Inc. + Copyright (C) 1992, 1997-2002, 2004-2012 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright diff --git a/contrib/grep/doc/fdl.texi b/contrib/grep/doc/fdl.texi index 2caf58dc25..2d26c9ec76 100644 --- a/contrib/grep/doc/fdl.texi +++ b/contrib/grep/doc/fdl.texi @@ -5,7 +5,7 @@ @c hence no sectioning command or @node. @display -Copyright @copyright{} 2000-2002, 2007-2008, 2010-2011 Free Software +Copyright @copyright{} 2000-2002, 2007-2008, 2010-2012 Free Software Foundation, Inc. @uref{http://fsf.org/} diff --git a/contrib/grep/doc/grep.texi b/contrib/grep/doc/grep.texi index 7c80f8c21e..000a8446b5 100644 --- a/contrib/grep/doc/grep.texi +++ b/contrib/grep/doc/grep.texi @@ -16,7 +16,8 @@ @copying This manual is for @command{grep}, a pattern matching engine. -Copyright @copyright{} 1999-2002, 2005, 2008-2011 Free Software Foundation, Inc. +Copyright @copyright{} 1999-2002, 2005, 2008-2012 Free Software Foundation, +Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -49,7 +50,7 @@ Texts. A copy of the license is included in the section entitled @node Top @top grep -@command{grep} prints lines that match a pattern. +@command{grep} prints lines that contain a match for a pattern. This manual is for version @value{VERSION} of GNU Grep. @@ -72,7 +73,7 @@ This manual is for version @value{VERSION} of GNU Grep. @cindex searching for a pattern -@command{grep} searches the input files +@command{grep} searches input files for lines containing a match to a given pattern list. When it finds a match in a line, it copies the line to standard output (by default), @@ -116,13 +117,13 @@ There can be zero or more @var{input_file_names}. @section Command-line Options @command{grep} comes with a rich set of options: -some from @sc{posix.2} and some being @sc{gnu} extensions. -Long option names are always a @sc{gnu} extension, -even for options that are from @sc{posix} specifications. -Options that are specified by @sc{posix}, +some from POSIX and some being GNU extensions. +Long option names are always a GNU extension, +even for options that are from POSIX specifications. +Options that are specified by POSIX, under their short names, are explicitly marked as such -to facilitate @sc{posix}-portable programming. +to facilitate POSIX-portable programming. A few option names are provided for compatibility with older or more exotic implementations. @@ -143,7 +144,7 @@ which variant of the @command{grep} matching engine is used. @node Generic Program Information @subsection Generic Program Information -@table @samp +@table @option @item --help @opindex --help @@ -164,7 +165,7 @@ This version number should be included in all bug reports. @node Matching Control @subsection Matching Control -@table @samp +@table @option @item -e @var{pattern} @itemx --regexp=@var{pattern} @@ -174,7 +175,7 @@ This version number should be included in all bug reports. Use @var{pattern} as the pattern. This can be used to specify multiple search patterns, or to protect a pattern beginning with a @samp{-}. -(@samp{-e} is specified by @sc{posix}.) +(@option{-e} is specified by POSIX.) @item -f @var{file} @itemx --file=@var{file} @@ -183,7 +184,7 @@ or to protect a pattern beginning with a @samp{-}. @cindex pattern from file Obtain patterns from @var{file}, one per line. The empty file contains zero patterns, and therefore matches nothing. -(@samp{-f} is specified by @sc{posix}.) +(@option{-f} is specified by POSIX.) @item -i @itemx -y @@ -193,8 +194,8 @@ The empty file contains zero patterns, and therefore matches nothing. @opindex --ignore-case @cindex case insensitive search Ignore case distinctions in both the pattern and the input files. -@samp{-y} is an obsolete synonym that is provided for compatibility. -(@samp{-i} is specified by @sc{posix}.) +@option{-y} is an obsolete synonym that is provided for compatibility. +(@option{-i} is specified by POSIX.) @item -v @itemx --invert-match @@ -203,7 +204,7 @@ Ignore case distinctions in both the pattern and the input files. @cindex invert matching @cindex print non-matching lines Invert the sense of matching, to select non-matching lines. -(@samp{-v} is specified by @sc{posix}.) +(@option{-v} is specified by POSIX.) @item -w @itemx --word-regexp @@ -225,14 +226,14 @@ Word-constituent characters are letters, digits, and the underscore. @opindex --line-regexp @cindex match the whole line Select only those matches that exactly match the whole line. -(@samp{-x} is specified by @sc{posix}.) +(@option{-x} is specified by POSIX.) @end table @node General Output Control @subsection General Output Control -@table @samp +@table @option @item -c @itemx --count @@ -241,9 +242,9 @@ Select only those matches that exactly match the whole line. @cindex counting lines Suppress normal output; instead print a count of matching lines for each input file. -With the @samp{-v}, @samp{--invert-match} option, +With the @option{-v} (@option{--invert-match}) option, count non-matching lines. -(@samp{-c} is specified by @sc{posix}.) +(@option{-c} is specified by POSIX.) @item --color[=@var{WHEN}] @itemx --colour[=@var{WHEN}] @@ -254,11 +255,11 @@ Surround the matched (non-empty) strings, matching lines, context lines, file names, line numbers, byte offsets, and separators (for fields and groups of context lines) with escape sequences to display them in color on the terminal. -The colors are defined by the environment variable @var{GREP_COLORS} +The colors are defined by the environment variable @env{GREP_COLORS} and default to @samp{ms=01;31:mc=01;31:sl=:cx=:fn=35:ln=32:bn=32:se=36} for bold red matched text, magenta file names, green line numbers, green byte offsets, cyan separators, and default terminal colors otherwise. -The deprecated environment variable @var{GREP_COLOR} is still supported, +The deprecated environment variable @env{GREP_COLOR} is still supported, but its setting does not have priority; it defaults to `01;31' (bold red) which only covers the color for matched text. @@ -272,7 +273,7 @@ which only covers the color for matched text. Suppress normal output; instead print the name of each input file from which no output would normally have been printed. -The scanning of every file will stop on the first match. +The scanning of each file stops on the first match. @item -l @itemx --files-with-matches @@ -282,8 +283,8 @@ The scanning of every file will stop on the first match. Suppress normal output; instead print the name of each input file from which output would normally have been printed. -The scanning of every file will stop on the first match. -(@samp{-l} is specified by @sc{posix}.) +The scanning of each file stops on the first match. +(@option{-l} is specified by POSIX.) @item -m @var{num} @itemx --max-count=@var{num} @@ -322,9 +323,9 @@ When @command{grep} stops after @var{num} matching lines, it outputs any trailing context lines. Since context does not include matching lines, @command{grep} will stop when it encounters another matching line. -When the @samp{-c} or @samp{--count} option is also used, +When the @option{-c} or @option{--count} option is also used, @command{grep} does not output a count greater than @var{num}. -When the @samp{-v} or @samp{--invert-match} option is also used, +When the @option{-v} or @option{--invert-match} option is also used, @command{grep} stops after outputting @var{num} non-matching lines. @item -o @@ -345,8 +346,8 @@ with each such part on a separate output line. Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected. -Also see the @samp{-s} or @samp{--no-messages} option. -(@samp{-q} is specified by @sc{posix}.) +Also see the @option{-s} or @option{--no-messages} option. +(@option{-q} is specified by POSIX.) @item -s @itemx --no-messages @@ -355,17 +356,18 @@ Also see the @samp{-s} or @samp{--no-messages} option. @cindex suppress error messages Suppress error messages about nonexistent or unreadable files. Portability note: -unlike @sc{gnu} @command{grep}, -7th Edition Unix @command{grep} did not conform to @sc{posix}, -because it lacked @samp{-q} -and its @samp{-s} option behaved like -@sc{gnu} @command{grep}'s @samp{-q} option. -@sc{usg}-style @command{grep} also lacked @samp{-q} -but its @samp{-s} option behaved like @sc{gnu} @command{grep}'s. +unlike GNU @command{grep}, +7th Edition Unix @command{grep} did not conform to POSIX, +because it lacked @option{-q} +and its @option{-s} option behaved like +GNU @command{grep}'s @option{-q} option.@footnote{Of course, 7th Edition +Unix predated POSIX by several years!} +USG-style @command{grep} also lacked @option{-q} +but its @option{-s} option behaved like GNU @command{grep}'s. Portable shell scripts should avoid both -@samp{-q} and @samp{-s} and should redirect +@option{-q} and @option{-s} and should redirect standard and error output to @file{/dev/null} instead. -(@samp{-s} is specified by @sc{posix}.) +(@option{-s} is specified by POSIX.) @end table @@ -376,7 +378,7 @@ When several prefix fields are to be output, the order is always file name, line number, and byte offset, regardless of the order in which these options were specified. -@table @samp +@table @option @item -b @itemx --byte-offset @@ -385,11 +387,11 @@ regardless of the order in which these options were specified. @cindex byte offset Print the 0-based byte offset within the input file before each line of output. -If @samp{-o} (@samp{--only-matching}) is specified, +If @option{-o} (@option{--only-matching}) is specified, print the offset of the matching part itself. -When @command{grep} runs on @sc{ms-dos} or @sc{ms}-Windows, +When @command{grep} runs on MS-DOS or MS-Windows, the printed byte offsets depend on whether -the @samp{-u} (@samp{--unix-byte-offsets}) option is used; +the @option{-u} (@option{--unix-byte-offsets}) option is used; see below. @item -H @@ -427,7 +429,7 @@ gzip -cd foo.gz | grep --label=foo -H something @opindex --line-number @cindex line numbering Prefix each line of output with the 1-based line number within its input file. -(@samp{-n} is specified by @sc{posix}.) +(@option{-n} is specified by POSIX.) @item -T @itemx --initial-tab @@ -437,7 +439,7 @@ Prefix each line of output with the 1-based line number within its input file. Make sure that the first character of actual line content lies on a tab stop, so that the alignment of tabs looks normal. This is useful with options that prefix their output to the actual content: -@samp{-H}, @samp{-n}, and @samp{-b}. +@option{-H}, @option{-n}, and @option{-b}. In order to improve the probability that lines from a single file will all start at the same column, this also causes the line number and byte offset (if present) @@ -447,23 +449,23 @@ to be printed in a minimum-size field width. @itemx --unix-byte-offsets @opindex -u @opindex --unix-byte-offsets -@cindex @sc{ms-dos}/@sc{ms}-Windows byte offsets -@cindex byte offsets, on @sc{ms-dos}/@sc{ms}-Windows +@cindex MS-DOS/MS-Windows byte offsets +@cindex byte offsets, on MS-DOS/MS-Windows Report Unix-style byte offsets. This option causes @command{grep} to report byte offsets as if the file were a Unix-style text file, i.e., the byte offsets ignore the @code{CR} characters that were stripped. This will produce results identical to running @command{grep} on a Unix machine. -This option has no effect unless the @samp{-b} option is also used; -it has no effect on platforms other than @sc{ms-dos} and @sc{ms}-Windows. +This option has no effect unless the @option{-b} option is also used; +it has no effect on platforms other than MS-DOS and MS-Windows. @item -Z @itemx --null @opindex -Z @opindex --null @cindex zero-terminated file names -Output a zero byte (the @sc{ascii} @code{NUL} character) +Output a zero byte (the ASCII @code{NUL} character) instead of the character that normally follows a file name. For example, @samp{grep -lZ} outputs a zero byte after each file name @@ -482,10 +484,10 @@ even those that contain newline characters. Regardless of how these options are set, @command{grep} will never print any given line more than once. -If the @samp{-o} or @samp{--only-matching} option is specified, +If the @option{-o} (@option{--only-matching}) option is specified, these options have no effect and a warning is given upon their use. -@table @samp +@table @option @item -A @var{num} @itemx --after-context=@var{num} @@ -516,7 +518,7 @@ Print @var{num} lines of leading and trailing output context. @opindex --group-separator @cindex group separator When @option{-A}, @option{-B} or @option{-C} are in use, -print @var{string} instead of @samp{--} around disjoint groups +print @var{string} instead of @option{--} around disjoint groups of lines. @item --no-group-separator @@ -527,26 +529,44 @@ print disjoint groups of lines adjacent to each other. @end table +Here are some points about how @command{grep} chooses +the separator to print between prefix fields and line content: + +@itemize @bullet +@item Matching lines normally use @samp{:} as a separator between prefix fields and actual line content. + +@item Context (i.e., non-matching) lines use @samp{-} instead. + +@item When no context is specified, matching lines are simply output one right after another. + +@item When nonzero context is specified, lines that are adjacent in the input form a group and are output one right after another, while a separator appears by default between disjoint groups on a line -of its own and without any prefix. The default separator +of its own and without any prefix. + +@item +The default separator is @samp{--}, however whether to include it and its appearance -can be changed with the options above. Each group may contain +can be changed with the options above. + +@item +Each group may contain several matching lines when they are close enough to each other that two otherwise adjacent but divided groups connect and can just merge into a single contiguous one. +@end itemize @node File and Directory Selection @subsection File and Directory Selection -@table @samp +@table @option @item -a @itemx --text @@ -557,7 +577,7 @@ and can just merge into a single contiguous one. Process a binary file as if it were text; this is equivalent to the @samp{--binary-files=text} option. -@itemx --binary-files=@var{type} +@item --binary-files=@var{type} @opindex --binary-files @cindex binary files If the first few bytes of a file indicate that the file contains binary data, @@ -566,12 +586,15 @@ By default, @var{type} is @samp{binary}, and @command{grep} normally outputs either a one-line message saying that a binary file matches, or no message if there is no match. + If @var{type} is @samp{without-match}, @command{grep} assumes that a binary file does not match; -this is equivalent to the @samp{-I} option. +this is equivalent to the @option{-I} option. + If @var{type} is @samp{text}, @command{grep} processes a binary file as if it were text; -this is equivalent to the @samp{-a} option. +this is equivalent to the @option{-a} option. + @emph{Warning:} @samp{--binary-files=text} might output binary garbage, which can have nasty side effects if the output is a terminal and @@ -583,16 +606,22 @@ if the terminal driver interprets some of it as commands. @opindex --devices @cindex device search If an input file is a device, FIFO, or socket, use @var{action} to process it. -By default, @var{action} is @samp{read}, -which means that devices are read just as if they were ordinary files. +If @var{action} is @samp{read}, +all devices are read just as if they were ordinary files. If @var{action} is @samp{skip}, devices, FIFOs, and sockets are silently skipped. +By default, devices are read if they are on the command line or if the +@option{-R} (@option{--dereference-recursive}) option is used, and are +skipped if they are encountered recursively and the @option{-r} +(@option{--recursive}) option is used. +This option has no effect on a file that is read via standard input. @item -d @var{action} @itemx --directories=@var{action} @opindex -d @opindex --directories @cindex directory search +@cindex symbolic links If an input file is a directory, use @var{action} to process it. By default, @var{action} is @samp{read}, which means that directories are read just as if they were ordinary files @@ -601,8 +630,9 @@ and will cause @command{grep} to print error messages for every directory or silently skip them). If @var{action} is @samp{skip}, directories are silently skipped. If @var{action} is @samp{recurse}, -@command{grep} reads all files under each directory, recursively; -this is equivalent to the @samp{-r} option. +@command{grep} reads all files under each directory, recursively, +following command-line symbolic links and skipping other symlinks; +this is equivalent to the @option{-r} option. @item --exclude=@var{glob} @opindex --exclude @@ -620,7 +650,7 @@ and @code{\} to quote a wildcard or backslash character literally. @cindex searching directory trees Skip files whose base name matches any of the file-name globs read from @var{file} (using wildcard matching as described -under @samp{--exclude}). +under @option{--exclude}). @item --exclude-dir=@var{dir} @opindex --exclude-dir @@ -637,25 +667,37 @@ this is equivalent to the @samp{--binary-files=without-match} option. @cindex include files @cindex searching directory trees Search only files whose base name matches @var{glob} -(using wildcard matching as described under @samp{--exclude}). +(using wildcard matching as described under @option{--exclude}). @item -r -@itemx -R @itemx --recursive @opindex -r @opindex --recursive @cindex recursive search @cindex searching directory trees -For each directory mentioned on the command line, +@cindex symbolic links +For each directory operand, read and process all files in that directory, recursively. +Follow symbolic links on the command line, but skip symlinks +that are encountered recursively. This is the same as the @samp{--directories=recurse} option. +@item -R +@itemx --dereference-recursive +@opindex -R +@opindex --dereference-recursive +@cindex recursive search +@cindex searching directory trees +@cindex symbolic links +For each directory operand, read and process all files in that +directory, recursively, following all symbolic links. + @end table @node Other Options @subsection Other Options -@table @samp +@table @option @item --line-buffered @opindex --line-buffered @@ -666,7 +708,8 @@ This can cause a performance penalty. @item --mmap @opindex --mmap @cindex memory mapped input -This option is ignored for backwards compatibility. It used to read +This option is deprecated and now elicits a warning, but is otherwise a no-op. +It used to make @command{grep} read input with the @code{mmap} system call, instead of the default @code{read} system call. On modern systems, @code{mmap} would rarely if ever yield better performance. @@ -675,21 +718,21 @@ better performance. @itemx --binary @opindex -U @opindex --binary -@cindex @sc{ms-dos}/@sc{ms}-Windows binary files -@cindex binary files, @sc{ms-dos}/@sc{ms}-Windows +@cindex MS-DOS/MS-Windows binary files +@cindex binary files, MS-DOS/MS-Windows Treat the file(s) as binary. -By default, under @sc{ms-dos} and @sc{ms}-Windows, +By default, under MS-DOS and MS-Windows, @command{grep} guesses the file type by looking at the contents of the first 32kB read from the file. If @command{grep} decides the file is a text file, it strips the @code{CR} characters from the original file contents (to make regular expressions with @code{^} and @code{$} work correctly). -Specifying @samp{-U} overrules this guesswork, +Specifying @option{-U} overrules this guesswork, causing all files to be read and passed to the matching mechanism verbatim; if the file is a text file with @code{CR/LF} pairs at the end of each line, this will cause some regular expressions to fail. This option has no effect -on platforms other than @sc{ms-dos} and @sc{ms}-Windows. +on platforms other than MS-DOS and MS-Windows. @item -z @itemx --null-data @@ -697,8 +740,8 @@ on platforms other than @sc{ms-dos} and @sc{ms}-Windows. @opindex --null-data @cindex zero-terminated lines Treat the input as a set of lines, each terminated by a zero byte (the -@sc{ascii} @code{NUL} character) instead of a newline. -Like the @samp{-Z} or @samp{--null} option, +ASCII @code{NUL} character) instead of a newline. +Like the @option{-Z} or @option{--null} option, this option can be used with commands like @samp{sort -z} to process arbitrary file names. @@ -722,7 +765,41 @@ for the @code{LC_MESSAGES} category. The @samp{C} locale is used if none of these environment variables are set, if the locale catalog is not installed, or if @command{grep} was not compiled -with national language support (@sc{nls}). +with national language support (NLS). + +Many of the environment variables in the following list let you +control highlighting using +Select Graphic Rendition (SGR) +commands interpreted by the terminal or terminal emulator. +(See the +section +in the documentation of your text terminal +for permitted values and their meanings as character attributes.) +These substring values are integers in decimal representation +and can be concatenated with semicolons. +@command{grep} takes care of assembling the result +into a complete SGR sequence (@samp{\33[}...@samp{m}). +Common values to concatenate include +@samp{1} for bold, +@samp{4} for underline, +@samp{5} for blink, +@samp{7} for inverse, +@samp{39} for default foreground color, +@samp{30} to @samp{37} for foreground colors, +@samp{90} to @samp{97} for 16-color mode foreground colors, +@samp{38;5;0} to @samp{38;5;255} +for 88-color and 256-color modes foreground colors, +@samp{49} for default background color, +@samp{40} to @samp{47} for background colors, +@samp{100} to @samp{107} for 16-color mode background colors, +and @samp{48;5;0} to @samp{48;5;255} +for 88-color and 256-color modes background colors. + +The two-letter names used in the @env{GREP_COLORS} environment variable +(and some of the others) refer to terminal ``capabilities,'' the ability +of a terminal to highlight text, or change its color, and so on. +These capabilities are stored in an online database and accessed by +the @code{terminfo} library. @cindex environment variables @@ -743,17 +820,24 @@ whitespace. A backslash escapes the next character, so it can be used to specify an option containing whitespace or a backslash. +The @code{GREP_OPTIONS} value does not affect whether @command{grep} +without file operands searches standard input or the working +directory; that is affected only by command-line options. For +example, the command @samp{grep PAT} searches standard input and the +command @samp{grep -r PAT} searches the working directory, regardless +of whether @code{GREP_OPTIONS} contains @option{-r}. + @item GREP_COLOR @vindex GREP_COLOR @r{environment variable} @cindex highlight markers This variable specifies the color used to highlight matched (non-empty) text. -It is deprecated in favor of @code{GREP_COLORS}, but still supported. -The @samp{mt}, @samp{ms}, and @samp{mc} capabilities of @code{GREP_COLORS} +It is deprecated in favor of @env{GREP_COLORS}, but still supported. +The @samp{mt}, @samp{ms}, and @samp{mc} capabilities of @env{GREP_COLORS} have priority over it. It can only specify the color used to highlight the matching non-empty text in any matching line -(a selected line when the @samp{-v} command-line option is omitted, -or a context line when @samp{-v} is specified). +(a selected line when the @option{-v} command-line option is omitted, +or a context line when @option{-v} is specified). The default is @samp{01;31}, which means a bold red foreground text on the terminal's default background. @@ -762,7 +846,7 @@ which means a bold red foreground text on the terminal's default background. @cindex highlight markers This variable specifies the colors and other attributes used to highlight various parts of the output. -Its value is a colon-separated list of capabilities +Its value is a colon-separated list of @code{terminfo} capabilities that defaults to @samp{ms=01;31:mc=01;31:sl=:cx=:fn=35:ln=32:bn=32:se=36} with the @samp{rv} and @samp{ne} boolean capabilities omitted (i.e., false). Supported capabilities are as follows. @@ -772,10 +856,10 @@ Supported capabilities are as follows. @vindex sl GREP_COLORS @r{capability} SGR substring for whole selected lines (i.e., -matching lines when the @samp{-v} command-line option is omitted, -or non-matching lines when @samp{-v} is specified). +matching lines when the @option{-v} command-line option is omitted, +or non-matching lines when @option{-v} is specified). If however the boolean @samp{rv} capability -and the @samp{-v} command-line option are both specified, +and the @option{-v} command-line option are both specified, it applies to context matching lines instead. The default is empty (i.e., the terminal's default color pair). @@ -783,10 +867,10 @@ The default is empty (i.e., the terminal's default color pair). @vindex cx GREP_COLORS @r{capability} SGR substring for whole context lines (i.e., -non-matching lines when the @samp{-v} command-line option is omitted, -or matching lines when @samp{-v} is specified). +non-matching lines when the @option{-v} command-line option is omitted, +or matching lines when @option{-v} is specified). If however the boolean @samp{rv} capability -and the @samp{-v} command-line option are both specified, +and the @option{-v} command-line option are both specified, it applies to selected non-matching lines instead. The default is empty (i.e., the terminal's default color pair). @@ -794,15 +878,15 @@ The default is empty (i.e., the terminal's default color pair). @vindex rv GREP_COLORS @r{capability} Boolean value that reverses (swaps) the meanings of the @samp{sl=} and @samp{cx=} capabilities -when the @samp{-v} command-line option is specified. +when the @option{-v} command-line option is specified. The default is false (i.e., the capability is omitted). @item mt=01;31 @vindex mt GREP_COLORS @r{capability} SGR substring for matching non-empty text in any matching line (i.e., -a selected line when the @samp{-v} command-line option is omitted, -or a context line when @samp{-v} is specified). +a selected line when the @option{-v} command-line option is omitted, +or a context line when @option{-v} is specified). Setting this is equivalent to setting both @samp{ms=} and @samp{mc=} at once to the same value. The default is a bold red text foreground over the current line background. @@ -810,17 +894,17 @@ The default is a bold red text foreground over the current line background. @item ms=01;31 @vindex ms GREP_COLORS @r{capability} SGR substring for matching non-empty text in a selected line. -(This is only used when the @samp{-v} command-line option is omitted.) +(This is used only when the @option{-v} command-line option is omitted.) The effect of the @samp{sl=} (or @samp{cx=} if @samp{rv}) capability -remains active when this kicks in. +remains active when this takes effect. The default is a bold red text foreground over the current line background. @item mc=01;31 @vindex mc GREP_COLORS @r{capability} SGR substring for matching non-empty text in a context line. -(This is only used when the @samp{-v} command-line option is specified.) +(This is used only when the @option{-v} command-line option is specified.) The effect of the @samp{cx=} (or @samp{sl=} if @samp{rv}) capability -remains active when this kicks in. +remains active when this takes effect. The default is a bold red text foreground over the current line background. @item fn=35 @@ -855,7 +939,7 @@ each time a colorized item ends. This is needed on terminals on which EL is not supported. It is otherwise useful on terminals for which the @code{back_color_erase} -(@code{bce}) boolean terminfo capability does not apply, +(@code{bce}) boolean @code{terminfo} capability does not apply, when the chosen highlight colors do not affect the background, or when EL is too slow or causes too much flicker. The default is false (i.e., the capability is omitted). @@ -864,28 +948,6 @@ The default is false (i.e., the capability is omitted). Note that boolean capabilities have no @samp{=}... part. They are omitted (i.e., false) by default and become true when specified. -See the Select Graphic Rendition (SGR) section -in the documentation of your text terminal -for permitted values and their meaning as character attributes. -These substring values are integers in decimal representation -and can be concatenated with semicolons. -@command{grep} takes care of assembling the result -into a complete SGR sequence (@samp{\33[}...@samp{m}). -Common values to concatenate include -@samp{1} for bold, -@samp{4} for underline, -@samp{5} for blink, -@samp{7} for inverse, -@samp{39} for default foreground color, -@samp{30} to @samp{37} for foreground colors, -@samp{90} to @samp{97} for 16-color mode foreground colors, -@samp{38;5;0} to @samp{38;5;255} -for 88-color and 256-color modes foreground colors, -@samp{49} for default background color, -@samp{40} to @samp{47} for background colors, -@samp{100} to @samp{107} for 16-color mode background colors, -and @samp{48;5;0} to @samp{48;5;255} -for 88-color and 256-color modes background colors. @item LC_ALL @itemx LC_COLLATE @@ -926,9 +988,9 @@ The default @samp{C} locale uses American English messages. @item POSIXLY_CORRECT @vindex POSIXLY_CORRECT @r{environment variable} -If set, @command{grep} behaves as @sc{posix.2} requires; otherwise, -@command{grep} behaves more like other @sc{gnu} programs. -@sc{posix.2} +If set, @command{grep} behaves as POSIX requires; otherwise, +@command{grep} behaves more like other GNU programs. +POSIX requires that options that follow file names must be treated as file names; by default, @@ -946,7 +1008,7 @@ even if it appears to be one. A shell can put this variable in the environment for each command it runs, specifying which operands are the results of file name wildcard expansion and therefore should not be treated as options. -This behavior is available only with the @sc{gnu} C library, +This behavior is available only with the GNU C library, and only when @code{POSIXLY_CORRECT} is not set. @end table @@ -961,7 +1023,7 @@ Normally, the exit status is 0 if selected lines are found and 1 otherwise. But the exit status is 2 if an error occurred, unless the @option{-q} or @option{--quiet} or @option{--silent} option is used and a selected line is found. -Note, however, that @sc{posix} only mandates, +Note, however, that POSIX only mandates, for programs such as @command{grep}, @command{cmp}, and @command{diff}, that the exit status in case of error be greater than 1; it is therefore advisable, for the sake of portability, @@ -972,17 +1034,19 @@ instead of strict equality with@ 2. @node grep Programs @section @command{grep} Programs @cindex @command{grep} programs -@cindex variants of @command{gerp} +@cindex variants of @command{grep} @command{grep} searches the named input files -(or standard input if no files are named, -or the file name @file{-} is given) for lines containing a match to the given pattern. By default, @command{grep} prints the matching lines. +A file named @file{-} stands for standard input. +If no input is specified, @command{grep} searches the working +directory @file{.} if given a command-line option specifying +recursion; otherwise, @command{grep} searches standard input. There are four major variants of @command{grep}, controlled by the following options. -@table @samp +@table @option @item -G @itemx --basic-regexp @@ -998,7 +1062,7 @@ This is the default. @opindex --extended-regexp @cindex matching extended regular expressions Interpret the pattern as an extended regular expression (ERE). -(@samp{-E} is specified by @sc{posix}.) +(@option{-E} is specified by POSIX.) @item -F @itemx --fixed-strings @@ -1007,7 +1071,7 @@ Interpret the pattern as an extended regular expression (ERE). @cindex matching fixed strings Interpret the pattern as a list of fixed strings, separated by newlines, any of which is to be matched. -(@samp{-F} is specified by @sc{posix}.) +(@option{-F} is specified by POSIX.) @item -P @itemx --perl-regexp @@ -1040,15 +1104,15 @@ by using various operators to combine smaller expressions. @command{grep} understands three different versions of regular expression syntax: ``basic,'' (BRE) ``extended'' (ERE) and ``perl''. -In @sc{gnu} @command{grep}, -there is no difference in available functionality between basic and +In GNU @command{grep}, +there is no difference in available functionality between the basic and extended syntaxes. In other implementations, basic regular expressions are less powerful. The following description applies to extended regular expressions; differences for basic regular expressions are summarized afterwards. Perl regular expressions give additional functionality, and are -documented in pcresyntax(3) and pcrepattern(3), but may not be -available on every system. +documented in the @i{pcresyntax}(3) and @i{pcrepattern}(3) manual pages, +but may not be available on every system. @menu * Fundamental Structure:: @@ -1125,6 +1189,7 @@ The preceding item is matched at least @var{n} times, but not more than @end table +The empty regular expression matches the empty string. Two regular expressions may be concatenated; the resulting regular expression matches any string formed by concatenating two substrings @@ -1132,7 +1197,7 @@ that respectively match the concatenated expressions. Two regular expressions may be joined by the infix operator @samp{|}; the resulting regular expression -matches any string matching either alternalte expression. +matches any string matching either alternate expression. Repetition takes precedence over concatenation, which in turn takes precedence over alternation. @@ -1171,8 +1236,8 @@ of bracket expressions, you can use the @samp{C} locale by setting the Finally, certain named classes of characters are predefined within bracket expressions, as follows. Their interpretation depends on the @code{LC_CTYPE} locale; -the interpretation below is that of the @samp{C} locale, -which is the default if no @code{LC_CTYPE} locale is specified. +for example, @samp{[[:alnum:]]} means the character class of numbers and letters +in the current locale. @cindex classes of characters @cindex character classes @@ -1182,13 +1247,13 @@ which is the default if no @code{LC_CTYPE} locale is specified. @opindex alnum @r{character class} @cindex alphanumeric characters Alphanumeric characters: -@samp{[:alpha:]} and @samp{[:digit:]}. +@samp{[:alpha:]} and @samp{[:digit:]}; in the @samp{C} locale and ASCII character encoding, this is the same as @samp{[0-9A-Za-z]}. @item [:alpha:] @opindex alpha @r{character class} @cindex alphabetic characters Alphabetic characters: -@samp{[:lower:]} and @samp{[:upper:]}. +@samp{[:lower:]} and @samp{[:upper:]}; in the @samp{C} locale and ASCII character encoding, this is the same as @samp{[A-Za-z]}. @item [:blank:] @opindex blank @r{character class} @@ -1200,7 +1265,7 @@ space and tab. @opindex cntrl @r{character class} @cindex control characters Control characters. -In @sc{ascii}, these characters have octal codes 000 +In ASCII, these characters have octal codes 000 through 037, and 177 (@code{DEL}). In other character sets, these are the equivalent characters, if any. @@ -1220,7 +1285,8 @@ Graphical characters: @item [:lower:] @opindex lower @r{character class} @cindex lower-case letters -Lower-case letters: +Lower-case letters; in the @samp{C} locale and ASCII character +encoding, this is @code{a b c d e f g h i j k l m n o p q r s t u v w x y z}. @item [:print:] @@ -1232,21 +1298,23 @@ Printable characters: @item [:punct:] @opindex punct @r{character class} @cindex punctuation characters -Punctuation characters: +Punctuation characters; in the @samp{C} locale and ASCII character +encoding, this is @code{!@: " # $ % & ' ( ) * + , - .@: / : ; < = > ?@: @@ [ \ ] ^ _ ` @{ | @} ~}. @item [:space:] @opindex space @r{character class} @cindex space characters @cindex whitespace characters -Space characters: +Space characters: in the @samp{C} locale, this is tab, newline, vertical tab, form feed, carriage return, and space. @xref{Usage}, for more discussion of matching newlines. @item [:upper:] @opindex upper @r{character class} @cindex upper-case letters -Upper-case letters: +Upper-case letters: in the @samp{C} locale and ASCII character +encoding, this is @code{A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}. @item [:xdigit:] @@ -1257,12 +1325,9 @@ Hexadecimal digits: @code{0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f}. @end table -For example, @samp{[[:alnum:]]} means @samp{[0-9A-Za-z]}, except the latter -depends upon the @samp{C} locale and the @sc{ascii} character -encoding, whereas the former is independent of locale and character set. -(Note that the brackets in these class names are +Note that the brackets in these class names are part of the symbolic names, and must be included in addition to -the brackets delimiting the bracket expression.) +the brackets delimiting the bracket expression. @anchor{invalid-bracket-expr} If you mistakenly omit the outer brackets, and search for say, @samp{[:upper:]}, @@ -1318,28 +1383,28 @@ takes a special meaning: @table @samp -@item @samp{\b} +@item \b Match the empty string at the edge of a word. -@item @samp{\B} +@item \B Match the empty string provided it's not at the edge of a word. -@item @samp{\<} +@item \< Match the empty string at the beginning of word. -@item @samp{\>} +@item \> Match the empty string at the end of word. -@item @samp{\w} -Match word constituent, it is a synonym for @samp{[[:alnum:]]}. +@item \w +Match word constituent, it is a synonym for @samp{[_[:alnum:]]}. -@item @samp{\W} -Match non-word constituent, it is a synonym for @samp{[^[:alnum:]]}. +@item \W +Match non-word constituent, it is a synonym for @samp{[^_[:alnum:]]}. -@item @samp{\s} +@item \s Match whitespace, it is a synonym for @samp{[[:space:]]}. -@item @samp{\S} +@item \S Match non-whitespace, it is a synonym for @samp{[^[:space:]]}. @end table @@ -1353,6 +1418,8 @@ For example, @samp{\brat\b} matches the separate word @samp{rat}, The caret @samp{^} and the dollar sign @samp{$} are meta-characters that respectively match the empty string at the beginning and end of a line. +They are termed @dfn{anchors}, since they force the match to be ``anchored'' +to beginning or end of a line, respectively. @node Back-references and Subexpressions @section Back-references and Subexpressions @@ -1368,7 +1435,7 @@ the back-reference makes the whole match fail. For example, @samp{a(.)|b\1} will not match @samp{ba}. When multiple regular expressions are given with -@samp{-e} or from a file (@samp{-f file}), +@option{-e} or from a file (@samp{-f @var{file}}), back-references are local to each expression. @node Basic vs Extended @@ -1386,13 +1453,13 @@ and some @command{egrep} implementations support @samp{\@{} instead, so portable scripts should avoid @samp{@{} in @samp{grep@ -E} patterns and should use @samp{[@{]} to match a literal @samp{@{}. -@sc{gnu} @command{grep@ -E} attempts to support traditional usage by +GNU @command{grep@ -E} attempts to support traditional usage by assuming that @samp{@{} is not special if it would be the start of an invalid interval specification. For example, the command @samp{grep@ -E@ '@{1'} searches for the two-character string @samp{@{1} instead of reporting a syntax error in the regular expression. -@sc{posix.2} allows this behavior as an extension, but portable scripts +POSIX allows this behavior as an extension, but portable scripts should avoid it. @@ -1400,7 +1467,7 @@ should avoid it. @chapter Usage @cindex usage, examples -Here is an example command that invokes @sc{gnu} @command{grep}: +Here is an example command that invokes GNU @command{grep}: @example grep -i 'hello.*world' menu.h main.c @@ -1411,7 +1478,7 @@ This lists all lines in the files @file{menu.h} and @file{main.c} that contain the string @samp{hello} followed by the string @samp{world}; this is because @samp{.*} matches zero or more characters within a line. @xref{Regular Expressions}. -The @samp{-i} option causes @command{grep} +The @option{-i} option causes @command{grep} to ignore case, causing it to match the line @samp{Hello, world!}, which it would not otherwise match. @xref{Invoking}, for more details about @@ -1455,14 +1522,11 @@ find /home/gigi -name '*.c' -print0 | xargs -0r grep -H 'hello' This differs from the command: @example -grep -rH 'hello' *.c +grep -H 'hello' *.c @end example which merely looks for @samp{hello} in all files in the current directory whose names end in @samp{.c}. -Here the @option{-r} is -probably unnecessary, as recursion occurs only in the unlikely event -that one of @samp{.c} files is a directory. The @samp{find ...} command line above is more similar to the command: @example @@ -1478,7 +1542,7 @@ grep -e '--cut here--' * @noindent searches for all lines matching @samp{--cut here--}. -Without @samp{-e}, +Without @option{-e}, @command{grep} would attempt to parse @samp{--cut here--} as a list of options. @@ -1529,7 +1593,7 @@ gets you: /etc/passwd:eli:x:2098:1000:Eli Smith:/home/eli:/bin/bash @end example -Alternatively, use @samp{-H}, which is a @sc{gnu} extension: +Alternatively, use @option{-H}, which is a GNU extension: @example grep -H 'eli' /etc/passwd @@ -1556,13 +1620,13 @@ Why does @command{grep} report ``Binary file matches''? If @command{grep} listed all matching ``lines'' from a binary file, it would probably generate output that is not useful, and it might even muck up your display. -So @sc{gnu} @command{grep} suppresses output from +So GNU @command{grep} suppresses output from files that appear to be binary files. -To force @sc{gnu} @command{grep} +To force GNU @command{grep} to output lines even from files that appear to be binary, use the -@samp{-a} or @samp{--binary-files=text} option. +@option{-a} or @samp{--binary-files=text} option. To eliminate the -``Binary file matches'' messages, use the @samp{-I} or +``Binary file matches'' messages, use the @option{-I} or @samp{--binary-files=without-match} option. @item @@ -1571,11 +1635,11 @@ Why doesn't @samp{grep -lv} print non-matching file names? @samp{grep -lv} lists the names of all files containing one or more lines that do not match. To list the names of all files that contain no -matching lines, use the @samp{-L} or @samp{--files-without-match} +matching lines, use the @option{-L} or @option{--files-without-match} option. @item -I can do @sc{or} with @samp{|}, but what about @sc{and}? +I can do ``OR'' with @samp{|}, but what about ``AND''? @example grep 'paul' /etc/motd | grep 'franc,ois' @@ -1584,6 +1648,19 @@ grep 'paul' /etc/motd | grep 'franc,ois' @noindent finds all lines that contain both @samp{paul} and @samp{franc,ois}. +@item +Why does the empty pattern match every input line? + +The @command{grep} command searches for lines that contain strings +that match a pattern. Every line contains the empty string, so an +empty pattern causes @command{grep} to find a match on each line. It +is not the only such pattern: @samp{^}, @samp{$}, @samp{.*}, and many +other patterns cause @command{grep} to match every line. + +To match empty lines, use the pattern @samp{^$}. To match blank +lines, use the pattern @samp{^[[:blank:]]*$}. To match no lines at +all, use the command @samp{grep -f /dev/null}. + @item How can I search in both standard input and in files? @@ -1605,7 +1682,7 @@ a palindrome of 4 characters can be written with a BRE: grep -w -e '\(.\)\(.\).\2\1' file @end example -It matches the word "radar" or "civic". +It matches the word ``radar'' or ``civic.'' Guglielmo Bondioni proposed a single RE that finds all palindromes up to 19 characters long @@ -1615,7 +1692,7 @@ using @w{9 subexpressions} and @w{9 back-references}: grep -E -e '^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\9\8\7\6\5\4\3\2\1$' file @end smallexample -Note this is done by using @sc{gnu} ERE extensions; +Note this is done by using GNU ERE extensions; it might not be portable to other implementations of @command{grep}. @item @@ -1704,13 +1781,13 @@ Back-references are very slow, and may require exponential time. @chapter Copying @cindex copying -GNU grep is licensed under the GNU GPL, which makes it @dfn{free +GNU @command{grep} is licensed under the GNU GPL, which makes it @dfn{free software}. The ``free'' in ``free software'' refers to liberty, not price. As some GNU project advocates like to point out, think of ``free speech'' rather than ``free beer''. In short, you have the right (freedom) to -run and change grep and distribute it to other people, and---if you +run and change @command{grep} and distribute it to other people, and---if you want---charge money for doing either. The important restriction is that you have to grant your recipients the same rights and impose the same restrictions. diff --git a/contrib/grep/doc/version.texi b/contrib/grep/doc/version.texi index 9d76d0585c..6e38f06e36 100644 --- a/contrib/grep/doc/version.texi +++ b/contrib/grep/doc/version.texi @@ -1,4 +1,4 @@ -@set UPDATED 7 May 2011 -@set UPDATED-MONTH May 2011 -@set EDITION 2.9 -@set VERSION 2.9 +@set UPDATED 17 April 2012 +@set UPDATED-MONTH April 2012 +@set EDITION 2.12 +@set VERSION 2.12 diff --git a/contrib/grep/lib/alloca.c b/contrib/grep/lib/alloca.c index 9c87b925fb..ee0f018868 100644 --- a/contrib/grep/lib/alloca.c +++ b/contrib/grep/lib/alloca.c @@ -1,5 +1,3 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* alloca.c -- allocate automatically reclaimed memory (Mostly) portable public-domain implementation -- D A Gwyn @@ -477,4 +475,4 @@ i00afunc (long address) # endif /* CRAY */ # endif /* no alloca */ -#endif /* not GCC version 3 */ +#endif /* not GCC 2 */ diff --git a/contrib/grep/lib/argmatch.c b/contrib/grep/lib/argmatch.c index 9a3eca4d4c..a713364221 100644 --- a/contrib/grep/lib/argmatch.c +++ b/contrib/grep/lib/argmatch.c @@ -1,6 +1,6 @@ /* argmatch.c -- find a match for a string in an array - Copyright (C) 1990, 1998-1999, 2001-2007, 2009-2011 Free Software + Copyright (C) 1990, 1998-1999, 2001-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -77,7 +77,7 @@ argmatch_exit_fn argmatch_die = __argmatch_die; synonyms, i.e., for "yes", "yop" -> 0 "no", "nope" -> 1 - "y" is a valid argument, for `0', and "n" for `1'. */ + "y" is a valid argument, for 0, and "n" for 1. */ ptrdiff_t argmatch (const char *arg, const char *const *arglist, @@ -150,17 +150,17 @@ argmatch_valid (const char *const *arglist, /* We try to put synonyms on the same line. The assumption is that synonyms follow each other */ - fprintf (stderr, _("Valid arguments are:")); + fputs (_("Valid arguments are:"), stderr); for (i = 0; arglist[i]; i++) if ((i == 0) || memcmp (last_val, vallist + valsize * i, valsize)) { - fprintf (stderr, "\n - `%s'", arglist[i]); + fprintf (stderr, "\n - %s", quote (arglist[i])); last_val = vallist + valsize * i; } else { - fprintf (stderr, ", `%s'", arglist[i]); + fprintf (stderr, ", %s", quote (arglist[i])); } putc ('\n', stderr); } @@ -269,7 +269,7 @@ main (int argc, const char *const *argv) backup_type = XARGMATCH (program_name, argv[1], backup_args, backup_vals); - printf ("The version control is `%s'\n", + printf ("The version control is '%s'\n", ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals)); return 0; diff --git a/contrib/grep/lib/argmatch.h b/contrib/grep/lib/argmatch.h index f87729dd64..7e88696a4a 100644 --- a/contrib/grep/lib/argmatch.h +++ b/contrib/grep/lib/argmatch.h @@ -1,6 +1,6 @@ /* argmatch.h -- definitions and prototypes for argmatch.c - Copyright (C) 1990, 1998-1999, 2001-2002, 2004-2005, 2009-2011 Free Software + Copyright (C) 1990, 1998-1999, 2001-2002, 2004-2005, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -40,14 +40,14 @@ to the same values in VALLIST). */ ptrdiff_t argmatch (char const *arg, char const *const *arglist, - char const *vallist, size_t valsize); + char const *vallist, size_t valsize) _GL_ATTRIBUTE_PURE; # define ARGMATCH(Arg, Arglist, Vallist) \ argmatch (Arg, Arglist, (char const *) (Vallist), sizeof *(Vallist)) /* xargmatch calls this function when it fails. This function should not return. By default, this is a function that calls ARGMATCH_DIE which - in turn defaults to `exit (exit_failure)'. */ + in turn defaults to 'exit (exit_failure)'. */ typedef void (*argmatch_exit_fn) (void); extern argmatch_exit_fn argmatch_die; @@ -93,7 +93,8 @@ ptrdiff_t __xargmatch_internal (char const *context, char const *argmatch_to_argument (char const *value, char const *const *arglist, - char const *vallist, size_t valsize); + char const *vallist, size_t valsize) + _GL_ATTRIBUTE_PURE; # define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist) \ argmatch_to_argument (Value, Arglist, \ diff --git a/contrib/grep/lib/at-func.c b/contrib/grep/lib/at-func.c new file mode 100644 index 0000000000..b25bc4d819 --- /dev/null +++ b/contrib/grep/lib/at-func.c @@ -0,0 +1,131 @@ +/* Define at-style functions like fstatat, unlinkat, fchownat, etc. + Copyright (C) 2006, 2009-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +#include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ +#include "openat.h" +#include "openat-priv.h" +#include "save-cwd.h" + +#ifdef AT_FUNC_USE_F1_COND +# define CALL_FUNC(F) \ + (flag == AT_FUNC_USE_F1_COND \ + ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \ + : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS)) +# define VALIDATE_FLAG(F) \ + if (flag & ~AT_FUNC_USE_F1_COND) \ + { \ + errno = EINVAL; \ + return FUNC_FAIL; \ + } +#else +# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)) +# define VALIDATE_FLAG(F) /* empty */ +#endif + +#ifdef AT_FUNC_RESULT +# define FUNC_RESULT AT_FUNC_RESULT +#else +# define FUNC_RESULT int +#endif + +#ifdef AT_FUNC_FAIL +# define FUNC_FAIL AT_FUNC_FAIL +#else +# define FUNC_FAIL -1 +#endif + +/* Call AT_FUNC_F1 to operate on FILE, which is in the directory + open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value, + AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag; + call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than + AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT + or AT_FUNC_FAIL are defined. If possible, do it without changing the + working directory. Otherwise, resort to using save_cwd/fchdir, + then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd + fails, then give a diagnostic and exit nonzero. */ +FUNC_RESULT +AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) +{ + /* Be careful to choose names unlikely to conflict with + AT_FUNC_POST_FILE_PARAM_DECLS. */ + struct saved_cwd saved_cwd; + int saved_errno; + FUNC_RESULT err; + + VALIDATE_FLAG (flag); + + if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) + return CALL_FUNC (file); + + { + char proc_buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (proc_buf, fd, file); + if (proc_file) + { + FUNC_RESULT proc_result = CALL_FUNC (proc_file); + int proc_errno = errno; + if (proc_file != proc_buf) + free (proc_file); + /* If the syscall succeeds, or if it fails with an unexpected + errno value, then return right away. Otherwise, fall through + and resort to using save_cwd/restore_cwd. */ + if (FUNC_FAIL != proc_result) + return proc_result; + if (! EXPECTED_ERRNO (proc_errno)) + { + errno = proc_errno; + return proc_result; + } + } + } + + if (save_cwd (&saved_cwd) != 0) + openat_save_fail (errno); + if (0 <= fd && fd == saved_cwd.desc) + { + /* If saving the working directory collides with the user's + requested fd, then the user's fd must have been closed to + begin with. */ + free_cwd (&saved_cwd); + errno = EBADF; + return FUNC_FAIL; + } + + if (fchdir (fd) != 0) + { + saved_errno = errno; + free_cwd (&saved_cwd); + errno = saved_errno; + return FUNC_FAIL; + } + + err = CALL_FUNC (file); + saved_errno = (err == FUNC_FAIL ? errno : 0); + + if (restore_cwd (&saved_cwd) != 0) + openat_restore_fail (errno); + + free_cwd (&saved_cwd); + + if (saved_errno) + errno = saved_errno; + return err; +} +#undef CALL_FUNC +#undef FUNC_RESULT +#undef FUNC_FAIL diff --git a/contrib/grep/lib/basename-lgpl.c b/contrib/grep/lib/basename-lgpl.c index 529bc35d72..43ef8c211b 100644 --- a/contrib/grep/lib/basename-lgpl.c +++ b/contrib/grep/lib/basename-lgpl.c @@ -1,6 +1,6 @@ /* basename.c -- return the last element in a file name - Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2011 Free Software + Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/basename.c b/contrib/grep/lib/basename.c deleted file mode 100644 index 90ac5012a4..0000000000 --- a/contrib/grep/lib/basename.c +++ /dev/null @@ -1,58 +0,0 @@ -/* basename.c -- return the last element in a file name - - Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2011 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 of the License, 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 . */ - -#include - -#include "dirname.h" - -#include -#include "xalloc.h" -#include "xstrndup.h" - -char * -base_name (char const *name) -{ - char const *base = last_component (name); - size_t length; - - /* If there is no last component, then name is a file system root or the - empty string. */ - if (! *base) - return xstrndup (name, base_len (name)); - - /* Collapse a sequence of trailing slashes into one. */ - length = base_len (base); - if (ISSLASH (base[length])) - length++; - - /* On systems with drive letters, `a/b:c' must return `./b:c' rather - than `b:c' to avoid confusion with a drive letter. On systems - with pure POSIX semantics, this is not an issue. */ - if (FILE_SYSTEM_PREFIX_LEN (base)) - { - char *p = xmalloc (length + 3); - p[0] = '.'; - p[1] = '/'; - memcpy (p + 2, base, length); - p[length + 2] = '\0'; - return p; - } - - /* Finally, copy the basename. */ - return xstrndup (base, length); -} diff --git a/contrib/grep/lib/binary-io.h b/contrib/grep/lib/binary-io.h index c09dbf5799..824ad5b78a 100644 --- a/contrib/grep/lib/binary-io.h +++ b/contrib/grep/lib/binary-io.h @@ -1,5 +1,5 @@ /* Binary mode I/O. - Copyright (C) 2001, 2003, 2005, 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2001, 2003, 2005, 2008-2012 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 diff --git a/contrib/grep/lib/bitrotate.h b/contrib/grep/lib/bitrotate.h index c3a5e1a5d2..5fb8f9be47 100644 --- a/contrib/grep/lib/bitrotate.h +++ b/contrib/grep/lib/bitrotate.h @@ -1,5 +1,5 @@ /* bitrotate.h - Rotate bits in integers - Copyright (C) 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 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 diff --git a/contrib/grep/lib/btowc.c b/contrib/grep/lib/btowc.c index 9b3908d2b2..cec9eca564 100644 --- a/contrib/grep/lib/btowc.c +++ b/contrib/grep/lib/btowc.c @@ -1,5 +1,5 @@ /* Convert unibyte character to wide character. - Copyright (C) 2008, 2010-2011 Free Software Foundation, Inc. + Copyright (C) 2008, 2010-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/c-ctype.c b/contrib/grep/lib/c-ctype.c index 835f4e1adc..952d7a851f 100644 --- a/contrib/grep/lib/c-ctype.c +++ b/contrib/grep/lib/c-ctype.c @@ -1,8 +1,6 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Character handling in C locale. - Copyright 2000-2003, 2006, 2009-2011 Free Software Foundation, Inc. + Copyright 2000-2003, 2006, 2009-2012 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 @@ -15,8 +13,7 @@ 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. */ +along with this program; if not, see . */ #include diff --git a/contrib/grep/lib/c-ctype.h b/contrib/grep/lib/c-ctype.h index a58913eabc..0b31309e96 100644 --- a/contrib/grep/lib/c-ctype.h +++ b/contrib/grep/lib/c-ctype.h @@ -1,5 +1,3 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Character handling in C locale. These functions work like the corresponding functions in , @@ -7,7 +5,7 @@ functions' behaviour depends on the current locale set via setlocale. - Copyright (C) 2000-2003, 2006, 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2000-2003, 2006, 2008-2012 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 @@ -20,8 +18,7 @@ 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. */ +along with this program; if not, see . */ #ifndef C_CTYPE_H #define C_CTYPE_H @@ -120,23 +117,23 @@ extern "C" { if (c_isalpha (*s)) ... */ -extern bool c_isascii (int c); /* not locale dependent */ - -extern bool c_isalnum (int c); -extern bool c_isalpha (int c); -extern bool c_isblank (int c); -extern bool c_iscntrl (int c); -extern bool c_isdigit (int c); -extern bool c_islower (int c); -extern bool c_isgraph (int c); -extern bool c_isprint (int c); -extern bool c_ispunct (int c); -extern bool c_isspace (int c); -extern bool c_isupper (int c); -extern bool c_isxdigit (int c); - -extern int c_tolower (int c); -extern int c_toupper (int c); +extern bool c_isascii (int c) _GL_ATTRIBUTE_CONST; /* not locale dependent */ + +extern bool c_isalnum (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isalpha (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isblank (int c) _GL_ATTRIBUTE_CONST; +extern bool c_iscntrl (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isdigit (int c) _GL_ATTRIBUTE_CONST; +extern bool c_islower (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isgraph (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isprint (int c) _GL_ATTRIBUTE_CONST; +extern bool c_ispunct (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isspace (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isupper (int c) _GL_ATTRIBUTE_CONST; +extern bool c_isxdigit (int c) _GL_ATTRIBUTE_CONST; + +extern int c_tolower (int c) _GL_ATTRIBUTE_CONST; +extern int c_toupper (int c) _GL_ATTRIBUTE_CONST; #if defined __GNUC__ && defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__ && !defined NO_C_CTYPE_MACROS diff --git a/contrib/grep/lib/c-strcase.h b/contrib/grep/lib/c-strcase.h index 09e9e9cb1a..fdef2385ea 100644 --- a/contrib/grep/lib/c-strcase.h +++ b/contrib/grep/lib/c-strcase.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Case-insensitive string comparison functions in C locale. - Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2011 Free Software + Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ #ifndef C_STRCASE_H #define C_STRCASE_H @@ -42,12 +39,13 @@ extern "C" { /* Compare strings S1 and S2, ignoring case, returning less than, equal to or greater than zero if S1 is lexicographically less than, equal to or greater than S2. */ -extern int c_strcasecmp (const char *s1, const char *s2); +extern int c_strcasecmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE; /* Compare no more than N characters of strings S1 and S2, ignoring case, returning less than, equal to or greater than zero if S1 is lexicographically less than, equal to or greater than S2. */ -extern int c_strncasecmp (const char *s1, const char *s2, size_t n); +extern int c_strncasecmp (const char *s1, const char *s2, size_t n) + _GL_ATTRIBUTE_PURE; #ifdef __cplusplus diff --git a/contrib/grep/lib/c-strcasecmp.c b/contrib/grep/lib/c-strcasecmp.c index 928c5e6b80..d8332caf83 100644 --- a/contrib/grep/lib/c-strcasecmp.c +++ b/contrib/grep/lib/c-strcasecmp.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* c-strcasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1998-1999, 2005-2006, 2009-2012 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 @@ -14,8 +12,7 @@ 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. */ + along with this program; if not, see . */ #include diff --git a/contrib/grep/lib/c-strcaseeq.h b/contrib/grep/lib/c-strcaseeq.h new file mode 100644 index 0000000000..5c4bdffecb --- /dev/null +++ b/contrib/grep/lib/c-strcaseeq.h @@ -0,0 +1,184 @@ +/* Optimized case-insensitive string comparison in C locale. + Copyright (C) 2001-2002, 2007, 2009-2012 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 of the License, 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 . */ + +/* Written by Bruno Haible . */ + +#include "c-strcase.h" +#include "c-ctype.h" + +/* STRCASEEQ allows to optimize string comparison with a small literal string. + STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0) + is semantically equivalent to + c_strcasecmp (s, "UTF-8") == 0 + just faster. */ + +/* Help GCC to generate good code for string comparisons with + immediate strings. */ +#if defined (__GNUC__) && defined (__OPTIMIZE__) + +/* Case insensitive comparison of ASCII characters. */ +# if C_CTYPE_ASCII +# define CASEEQ(other,upper) \ + (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper)) +# elif C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE +# define CASEEQ(other,upper) \ + (c_isupper (upper) ? (other) == (upper) || (other) == (upper) - 'A' + 'a' : (other) == (upper)) +# else +# define CASEEQ(other,upper) \ + (c_toupper (other) == (upper)) +# endif + +static inline int +strcaseeq9 (const char *s1, const char *s2) +{ + return c_strcasecmp (s1 + 9, s2 + 9) == 0; +} + +static inline int +strcaseeq8 (const char *s1, const char *s2, char s28) +{ + if (CASEEQ (s1[8], s28)) + { + if (s28 == 0) + return 1; + else + return strcaseeq9 (s1, s2); + } + else + return 0; +} + +static inline int +strcaseeq7 (const char *s1, const char *s2, char s27, char s28) +{ + if (CASEEQ (s1[7], s27)) + { + if (s27 == 0) + return 1; + else + return strcaseeq8 (s1, s2, s28); + } + else + return 0; +} + +static inline int +strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28) +{ + if (CASEEQ (s1[6], s26)) + { + if (s26 == 0) + return 1; + else + return strcaseeq7 (s1, s2, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[5], s25)) + { + if (s25 == 0) + return 1; + else + return strcaseeq6 (s1, s2, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[4], s24)) + { + if (s24 == 0) + return 1; + else + return strcaseeq5 (s1, s2, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[3], s23)) + { + if (s23 == 0) + return 1; + else + return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[2], s22)) + { + if (s22 == 0) + return 1; + else + return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[1], s21)) + { + if (s21 == 0) + return 1; + else + return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +strcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (CASEEQ (s1[0], s20)) + { + if (s20 == 0) + return 1; + else + return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28) + +#else + +#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + (c_strcasecmp (s1, s2) == 0) + +#endif diff --git a/contrib/grep/lib/c-strncasecmp.c b/contrib/grep/lib/c-strncasecmp.c index 810bf56a94..47fb5fdb67 100644 --- a/contrib/grep/lib/c-strncasecmp.c +++ b/contrib/grep/lib/c-strncasecmp.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* c-strncasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1998-1999, 2005-2006, 2009-2012 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 @@ -14,8 +12,7 @@ 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. */ + along with this program; if not, see . */ #include diff --git a/contrib/grep/lib/chdir-long.c b/contrib/grep/lib/chdir-long.c new file mode 100644 index 0000000000..599d14157a --- /dev/null +++ b/contrib/grep/lib/chdir-long.c @@ -0,0 +1,266 @@ +/* provide a chdir function that tries not to fail due to ENAMETOOLONG + Copyright (C) 2004-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +#include + +#include "chdir-long.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifndef PATH_MAX +# error "compile this file only if your system defines PATH_MAX" +#endif + +/* The results of openat() in this file are not leaked to any + single-threaded code that could use stdio. + FIXME - if the kernel ever adds support for multi-thread safety for + avoiding standard fds, then we should use openat_safer. */ + +struct cd_buf +{ + int fd; +}; + +static inline void +cdb_init (struct cd_buf *cdb) +{ + cdb->fd = AT_FDCWD; +} + +static inline int +cdb_fchdir (struct cd_buf const *cdb) +{ + return fchdir (cdb->fd); +} + +static inline void +cdb_free (struct cd_buf const *cdb) +{ + if (0 <= cdb->fd) + { + bool close_fail = close (cdb->fd); + assert (! close_fail); + } +} + +/* Given a file descriptor of an open directory (or AT_FDCWD), CDB->fd, + try to open the CDB->fd-relative directory, DIR. If the open succeeds, + update CDB->fd with the resulting descriptor, close the incoming file + descriptor, and return zero. Upon failure, return -1 and set errno. */ +static int +cdb_advance_fd (struct cd_buf *cdb, char const *dir) +{ + int new_fd = openat (cdb->fd, dir, + O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); + if (new_fd < 0) + return -1; + + cdb_free (cdb); + cdb->fd = new_fd; + + return 0; +} + +/* Return a pointer to the first non-slash in S. */ +static inline char * _GL_ATTRIBUTE_PURE +find_non_slash (char const *s) +{ + size_t n_slash = strspn (s, "/"); + return (char *) s + n_slash; +} + +/* This is a function much like chdir, but without the PATH_MAX limitation + on the length of the directory name. A significant difference is that + it must be able to modify (albeit only temporarily) the directory + name. It handles an arbitrarily long directory name by operating + on manageable portions of the name. On systems without the openat + syscall, this means changing the working directory to more and more + "distant" points along the long directory name and then restoring + the working directory. If any of those attempts to save or restore + the working directory fails, this function exits nonzero. + + Note that this function may still fail with errno == ENAMETOOLONG, but + only if the specified directory name contains a component that is long + enough to provoke such a failure all by itself (e.g. if the component + has length PATH_MAX or greater on systems that define PATH_MAX). */ + +int +chdir_long (char *dir) +{ + int e = chdir (dir); + if (e == 0 || errno != ENAMETOOLONG) + return e; + + { + size_t len = strlen (dir); + char *dir_end = dir + len; + struct cd_buf cdb; + size_t n_leading_slash; + + cdb_init (&cdb); + + /* If DIR is the empty string, then the chdir above + must have failed and set errno to ENOENT. */ + assert (0 < len); + assert (PATH_MAX <= len); + + /* Count leading slashes. */ + n_leading_slash = strspn (dir, "/"); + + /* Handle any leading slashes as well as any name that matches + the regular expression, m!^//hostname[/]*! . Handling this + prefix separately usually results in a single additional + cdb_advance_fd call, but it's worthwhile, since it makes the + code in the following loop cleaner. */ + if (n_leading_slash == 2) + { + int err; + /* Find next slash. + We already know that dir[2] is neither a slash nor '\0'. */ + char *slash = memchr (dir + 3, '/', dir_end - (dir + 3)); + if (slash == NULL) + { + errno = ENAMETOOLONG; + return -1; + } + *slash = '\0'; + err = cdb_advance_fd (&cdb, dir); + *slash = '/'; + if (err != 0) + goto Fail; + dir = find_non_slash (slash + 1); + } + else if (n_leading_slash) + { + if (cdb_advance_fd (&cdb, "/") != 0) + goto Fail; + dir += n_leading_slash; + } + + assert (*dir != '/'); + assert (dir <= dir_end); + + while (PATH_MAX <= dir_end - dir) + { + int err; + /* Find a slash that is PATH_MAX or fewer bytes away from dir. + I.e. see if there is a slash that will give us a name of + length PATH_MAX-1 or less. */ + char *slash = memrchr (dir, '/', PATH_MAX); + if (slash == NULL) + { + errno = ENAMETOOLONG; + return -1; + } + + *slash = '\0'; + assert (slash - dir < PATH_MAX); + err = cdb_advance_fd (&cdb, dir); + *slash = '/'; + if (err != 0) + goto Fail; + + dir = find_non_slash (slash + 1); + } + + if (dir < dir_end) + { + if (cdb_advance_fd (&cdb, dir) != 0) + goto Fail; + } + + if (cdb_fchdir (&cdb) != 0) + goto Fail; + + cdb_free (&cdb); + return 0; + + Fail: + { + int saved_errno = errno; + cdb_free (&cdb); + errno = saved_errno; + return -1; + } + } +} + +#if TEST_CHDIR + +# include "closeout.h" +# include "error.h" + +char *program_name; + +int +main (int argc, char *argv[]) +{ + char *line = NULL; + size_t n = 0; + int len; + + program_name = argv[0]; + atexit (close_stdout); + + len = getline (&line, &n, stdin); + if (len < 0) + { + int saved_errno = errno; + if (feof (stdin)) + exit (0); + + error (EXIT_FAILURE, saved_errno, + "reading standard input"); + } + else if (len == 0) + exit (0); + + if (line[len-1] == '\n') + line[len-1] = '\0'; + + if (chdir_long (line) != 0) + error (EXIT_FAILURE, errno, + "chdir_long failed: %s", line); + + if (argc <= 1) + { + /* Using 'pwd' here makes sense only if it is a robust implementation, + like the one in coreutils after the 2004-04-19 changes. */ + char const *cmd = "pwd"; + execlp (cmd, (char *) NULL); + error (EXIT_FAILURE, errno, "%s", cmd); + } + + fclose (stdin); + fclose (stderr); + + exit (EXIT_SUCCESS); +} +#endif + +/* +Local Variables: +compile-command: "gcc -DTEST_CHDIR=1 -g -O -W -Wall chdir-long.c libcoreutils.a" +End: +*/ diff --git a/contrib/grep/lib/mbsrtowcs.c b/contrib/grep/lib/chdir-long.h similarity index 62% copy from contrib/grep/lib/mbsrtowcs.c copy to contrib/grep/lib/chdir-long.h index 69e6dfffb8..51db5a8041 100644 --- a/contrib/grep/lib/mbsrtowcs.c +++ b/contrib/grep/lib/chdir-long.h @@ -1,6 +1,5 @@ -/* Convert string to wide string. - Copyright (C) 2008-2011 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. +/* provide a chdir function that tries not to fail due to ENAMETOOLONG + Copyright (C) 2004-2005, 2009-2012 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 @@ -15,18 +14,17 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Jim Meyering. */ -/* Specification. */ -#include - -#include +#include #include -#include - -#include "strnlen1.h" - -extern mbstate_t _gl_mbsrtowcs_state; +#include "pathmax.h" -#include "mbsrtowcs-impl.h" +/* On systems without PATH_MAX, presume that chdir accepts + arbitrarily long directory names. */ +#ifndef PATH_MAX +# define chdir_long(Dir) chdir (Dir) +#else +int chdir_long (char *dir); +#endif diff --git a/contrib/grep/lib/cloexec.c b/contrib/grep/lib/cloexec.c new file mode 100644 index 0000000000..7919e8677c --- /dev/null +++ b/contrib/grep/lib/cloexec.c @@ -0,0 +1,83 @@ +/* closexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 1991, 2004-2006, 2009-2012 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 of the License, 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 . + + The code is taken from glibc/manual/llio.texi */ + +#include + +#include "cloexec.h" + +#include +#include +#include + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int +set_cloexec_flag (int desc, bool value) +{ +#ifdef F_SETFD + + int flags = fcntl (desc, F_GETFD, 0); + + if (0 <= flags) + { + int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); + + if (flags == newflags + || fcntl (desc, F_SETFD, newflags) != -1) + return 0; + } + + return -1; + +#else /* !F_SETFD */ + + /* Use dup2 to reject invalid file descriptors; the cloexec flag + will be unaffected. */ + if (desc < 0) + { + errno = EBADF; + return -1; + } + if (dup2 (desc, desc) < 0) + /* errno is EBADF here. */ + return -1; + + /* There is nothing we can do on this kind of platform. Punt. */ + return 0; +#endif /* !F_SETFD */ +} + + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int +dup_cloexec (int fd) +{ + return fcntl (fd, F_DUPFD_CLOEXEC, 0); +} diff --git a/contrib/grep/lib/cloexec.h b/contrib/grep/lib/cloexec.h new file mode 100644 index 0000000000..92e9f81e5e --- /dev/null +++ b/contrib/grep/lib/cloexec.h @@ -0,0 +1,38 @@ +/* closexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 2004, 2009-2012 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 of the License, 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 . + +*/ + +#include + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int set_cloexec_flag (int desc, bool value); + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int dup_cloexec (int fd); diff --git a/contrib/grep/lib/close-stream.c b/contrib/grep/lib/close-stream.c index 8819b58095..04fa5ece09 100644 --- a/contrib/grep/lib/close-stream.c +++ b/contrib/grep/lib/close-stream.c @@ -1,6 +1,6 @@ /* Close a stream, with nicer error checking than fclose's. - Copyright (C) 1998-2002, 2004, 2006-2011 Free Software Foundation, Inc. + Copyright (C) 1998-2002, 2004, 2006-2012 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 @@ -63,7 +63,7 @@ close_stream (FILE *stream) fclose failed, with one exception: ignore an fclose failure if there was no previous error, no data remains to be flushed, and fclose failed with EBADF. That can happen when a program like cp - is invoked like this `cp a b >&-' (i.e., with standard output + is invoked like this 'cp a b >&-' (i.e., with standard output closed) and doesn't generate any output (hence no previous error and nothing to be flushed). */ diff --git a/contrib/grep/lib/wcrtomb.c b/contrib/grep/lib/close.c similarity index 50% copy from contrib/grep/lib/wcrtomb.c copy to contrib/grep/lib/close.c index 6632589365..4b7accbc96 100644 --- a/contrib/grep/lib/wcrtomb.c +++ b/contrib/grep/lib/close.c @@ -1,6 +1,5 @@ -/* Convert wide character to multibyte character. - Copyright (C) 2008-2011 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. +/* close replacement. + Copyright (C) 2008-2012 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 @@ -18,36 +17,53 @@ #include /* Specification. */ -#include +#include #include -#include +#include "fd-hook.h" +#include "msvc-inval.h" -size_t -wcrtomb (char *s, wchar_t wc, mbstate_t *ps) +#undef close + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +close_nothrow (int fd) { - /* This implementation of wcrtomb on top of wctomb() supports only - stateless encodings. ps must be in the initial state. */ - if (ps != NULL && !mbsinit (ps)) + int result; + + TRY_MSVC_INVAL { - errno = EINVAL; - return (size_t)(-1); + result = close (fd); } - - if (s == NULL) - /* We know the NUL wide character corresponds to the NUL character. */ - return 1; - else + CATCH_MSVC_INVAL { - int ret = wctomb (s, wc); - - if (ret >= 0) - return ret; - else - { - errno = EILSEQ; - return (size_t)(-1); - } + result = -1; + errno = EBADF; } + DONE_MSVC_INVAL; + + return result; +} +#else +# define close_nothrow close +#endif + +/* Override close() to call into other gnulib modules. */ + +int +rpl_close (int fd) +{ +#if WINDOWS_SOCKETS + int retval = execute_all_close_hooks (close_nothrow, fd); +#else + int retval = close_nothrow (fd); +#endif + +#if REPLACE_FCHDIR + if (retval >= 0) + _gl_unregister_fd (fd); +#endif + + return retval; } diff --git a/contrib/grep/lib/closedir.c b/contrib/grep/lib/closedir.c new file mode 100644 index 0000000000..df31e86b4e --- /dev/null +++ b/contrib/grep/lib/closedir.c @@ -0,0 +1,67 @@ +/* Stop reading the entries of a directory. + Copyright (C) 2006-2012 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include + +#if REPLACE_FCHDIR +# include +#endif + +#if HAVE_CLOSEDIR + +/* Override closedir(), to keep track of the open file descriptors. + Needed because there is a function dirfd(). */ + +#else + +# include + +# include "dirent-private.h" + +#endif + +int +closedir (DIR *dirp) +{ +# if REPLACE_FCHDIR + int fd = dirfd (dirp); +# endif + int retval; + +#if HAVE_CLOSEDIR +# undef closedir + + retval = closedir (dirp); + +#else + + if (dirp->current != INVALID_HANDLE_VALUE) + FindClose (dirp->current); + free (dirp); + + retval = 0; + +#endif + +#if REPLACE_FCHDIR + if (retval >= 0) + _gl_unregister_fd (fd); +#endif + return retval; +} diff --git a/contrib/grep/lib/closeout.c b/contrib/grep/lib/closeout.c index f6cdd3f699..eea402473c 100644 --- a/contrib/grep/lib/closeout.c +++ b/contrib/grep/lib/closeout.c @@ -1,6 +1,6 @@ /* Close standard output and standard error, exiting with a diagnostic on error. - Copyright (C) 1998-2002, 2004, 2006, 2008-2011 Free Software Foundation, + Copyright (C) 1998-2002, 2004, 2006, 2008-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -100,7 +100,7 @@ close_stdout_set_ignore_EPIPE (bool ignore) can bypass the removal of these files. It's important to detect such failures and exit nonzero because many - tools (most notably `make' and other build-management systems) depend + tools (most notably 'make' and other build-management systems) depend on being able to detect failure in other tools via their exit status. */ void diff --git a/contrib/grep/lib/closeout.h b/contrib/grep/lib/closeout.h index ec8d7a6d2c..5310b28627 100644 --- a/contrib/grep/lib/closeout.h +++ b/contrib/grep/lib/closeout.h @@ -1,6 +1,6 @@ /* Close standard output and standard error. - Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2011 Free Software + Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/colorize-posix.c b/contrib/grep/lib/colorize-posix.c new file mode 100644 index 0000000000..116bbb2c40 --- /dev/null +++ b/contrib/grep/lib/colorize-posix.c @@ -0,0 +1,58 @@ +/* Output colorization. + Copyright 2011-2012 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. */ + +/* Without this pragma, gcc 4.7.0 20120102 suggests that the + init_colorize function might be candidate for attribute 'const' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif + +#include + +#include "colorize.h" + +#include +#include +#include +#include + +/* Return non-zero if we should highlight matches in output to file + descriptor FD. */ +int +should_colorize (void) +{ + char const *t = getenv ("TERM"); + return t && strcmp (t, "dumb") != 0; +} + +void init_colorize (void) { } + +/* Start a colorized text attribute on stdout using the SGR_START + format; the attribute is specified by SGR_SEQ. */ +void +print_start_colorize (char const *sgr_start, char const *sgr_seq) +{ + printf (sgr_start, sgr_seq); +} + +/* Restore the normal text attribute using the SGR_END string. */ +void +print_end_colorize (char const *sgr_end) +{ + fputs (sgr_end, stdout); +} diff --git a/contrib/grep/lib/colorize-w32.c b/contrib/grep/lib/colorize-w32.c new file mode 100644 index 0000000000..7341fe2083 --- /dev/null +++ b/contrib/grep/lib/colorize-w32.c @@ -0,0 +1,208 @@ +/* Output colorization on MS-Windows. + Copyright 2011-2012 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 by Eli Zaretskii. */ + +#include + +#include "colorize.h" + +#include +#include +#include +#include + +#undef DATADIR /* conflicts with objidl.h, which is included by windows.h */ +#include + +static HANDLE hstdout = INVALID_HANDLE_VALUE; +static SHORT norm_attr; + +/* Initialize the normal text attribute used by the console. */ +void +init_colorize (void) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + hstdout = GetStdHandle (STD_OUTPUT_HANDLE); + if (hstdout != INVALID_HANDLE_VALUE + && GetConsoleScreenBufferInfo (hstdout, &csbi)) + norm_attr = csbi.wAttributes; + else + hstdout = INVALID_HANDLE_VALUE; +} + +/* Return non-zero if we should highlight matches in output. */ +int +should_colorize (void) +{ + /* $TERM is not normally defined on DOS/Windows, so don't require + it for highlighting. But some programs, like Emacs, do define + it when running Grep as a subprocess, so make sure they don't + set TERM=dumb. */ + char const *t = getenv ("TERM"); + return ! (t && strcmp (t, "dumb") == 0); +} + +/* Convert a color spec, a semi-colon separated list of the form + "NN;MM;KK;...", where each number is a value of the SGR parameter, + into the corresponding Windows console text attribute. + + This function supports a subset of the SGR rendition aspects that + the Windows console can display. */ +static int +w32_sgr2attr (const char *sgr_seq) +{ + const char *s, *p; + int code, fg = norm_attr & 15, bg = norm_attr & (15 << 4); + int bright = 0, inverse = 0; + static const int fg_color[] = { + 0, /* black */ + FOREGROUND_RED, /* red */ + FOREGROUND_GREEN, /* green */ + FOREGROUND_GREEN | FOREGROUND_RED, /* yellow */ + FOREGROUND_BLUE, /* blue */ + FOREGROUND_BLUE | FOREGROUND_RED, /* magenta */ + FOREGROUND_BLUE | FOREGROUND_GREEN, /* cyan */ + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* gray */ + }; + static const int bg_color[] = { + 0, /* black */ + BACKGROUND_RED, /* red */ + BACKGROUND_GREEN, /* green */ + BACKGROUND_GREEN | BACKGROUND_RED, /* yellow */ + BACKGROUND_BLUE, /* blue */ + BACKGROUND_BLUE | BACKGROUND_RED, /* magenta */ + BACKGROUND_BLUE | BACKGROUND_GREEN, /* cyan */ + BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE /* gray */ + }; + + for (s = p = sgr_seq; *s; p++) + { + if (*p == ';' || *p == '\0') + { + code = strtol (s, NULL, 10); + s = p + (*p != '\0'); + + switch (code) + { + case 0: /* all attributes off */ + fg = norm_attr & 15; + bg = norm_attr & (15 << 4); + bright = 0; + inverse = 0; + break; + case 1: /* intensity on */ + bright = 1; + break; + case 7: /* inverse video */ + inverse = 1; + break; + case 22: /* intensity off */ + bright = 0; + break; + case 27: /* inverse off */ + inverse = 0; + break; + case 30: case 31: case 32: case 33: /* foreground color */ + case 34: case 35: case 36: case 37: + fg = fg_color[code - 30]; + break; + case 39: /* default foreground */ + fg = norm_attr & 15; + break; + case 40: case 41: case 42: case 43: /* background color */ + case 44: case 45: case 46: case 47: + bg = bg_color[code - 40]; + break; + case 49: /* default background */ + bg = norm_attr & (15 << 4); + break; + default: + break; + } + } + } + if (inverse) + { + int t = fg; + fg = (bg >> 4); + bg = (t << 4); + } + if (bright) + fg |= FOREGROUND_INTENSITY; + + return (bg & (15 << 4)) | (fg & 15); +} + +/* Start a colorized text attribute on stdout using the SGR_START + format; the attribute is specified by SGR_SEQ. */ +void +print_start_colorize (char const *sgr_start, char const *sgr_seq) +{ + /* If stdout is connected to a console, set the console text + attribute directly instead of using SGR_START. Otherwise, use + SGR_START to emit the SGR escape sequence as on Posix platforms; + this is needed when Grep is invoked as a subprocess of another + program, such as Emacs, which will handle the display of the + matches. */ + if (hstdout != INVALID_HANDLE_VALUE) + { + SHORT attr = w32_sgr2attr (sgr_seq); + SetConsoleTextAttribute (hstdout, attr); + } + else + printf (sgr_start, sgr_seq); +} + +/* Clear to the end of the current line with the default attribute. + This is needed for reasons similar to those that require the "EL to + Right after SGR" operation on Posix platforms: if we don't do this, + setting the `mt', `ms', or `mc' capabilities to use a non-default + background color spills that color to the empty space at the end of + the last screen line in a match whose line spans multiple screen + lines. */ +static void +w32_clreol (void) +{ + DWORD nchars; + COORD start_pos; + DWORD written; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo (hstdout, &csbi); + start_pos = csbi.dwCursorPosition; + nchars = csbi.dwSize.X - start_pos.X; + + FillConsoleOutputAttribute (hstdout, norm_attr, nchars, start_pos, + &written); + FillConsoleOutputCharacter (hstdout, ' ', nchars, start_pos, &written); +} + +/* Restore the normal text attribute using the SGR_END string. */ +void +print_end_colorize (char const *sgr_end) +{ + if (hstdout != INVALID_HANDLE_VALUE) + { + SetConsoleTextAttribute (hstdout, norm_attr); + w32_clreol (); + } + else + fputs (sgr_end, stdout); +} diff --git a/contrib/grep/lib/colorize.c b/contrib/grep/lib/colorize.c new file mode 100644 index 0000000000..116bbb2c40 --- /dev/null +++ b/contrib/grep/lib/colorize.c @@ -0,0 +1,58 @@ +/* Output colorization. + Copyright 2011-2012 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. */ + +/* Without this pragma, gcc 4.7.0 20120102 suggests that the + init_colorize function might be candidate for attribute 'const' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif + +#include + +#include "colorize.h" + +#include +#include +#include +#include + +/* Return non-zero if we should highlight matches in output to file + descriptor FD. */ +int +should_colorize (void) +{ + char const *t = getenv ("TERM"); + return t && strcmp (t, "dumb") != 0; +} + +void init_colorize (void) { } + +/* Start a colorized text attribute on stdout using the SGR_START + format; the attribute is specified by SGR_SEQ. */ +void +print_start_colorize (char const *sgr_start, char const *sgr_seq) +{ + printf (sgr_start, sgr_seq); +} + +/* Restore the normal text attribute using the SGR_END string. */ +void +print_end_colorize (char const *sgr_end) +{ + fputs (sgr_end, stdout); +} diff --git a/contrib/grep/src/mbsupport.h b/contrib/grep/lib/colorize.h similarity index 53% copy from contrib/grep/src/mbsupport.h copy to contrib/grep/lib/colorize.h index 007f412a46..23687d080b 100644 --- a/contrib/grep/src/mbsupport.h +++ b/contrib/grep/lib/colorize.h @@ -1,7 +1,6 @@ -/* mbsupport.h --- Localize determination of whether we have multibyte stuff. - - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. +/* Output colorization. + Copyright 2011-2012 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) @@ -17,19 +16,7 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* This file is needed so that we test for i18n support in just one place. - This gives us a consistent definition for all uses of MBS_SUPPORT. This - follows the ``Don't Repeat Yourself'' principle from "The Pragmatic - Programmer". - - The tests should be *all* the ones that are needed for an individual - application. */ - -#include - -#if defined HAVE_WCSCOLL && defined HAVE_ISWCTYPE -# define MBS_SUPPORT 1 -#else -# define MBS_SUPPORT 0 -#endif +extern int should_colorize (void); +extern void init_colorize (void); +extern void print_start_colorize (char const *sgr_start, char const *sgr_seq); +extern void print_end_colorize (char const *sgr_end); diff --git a/contrib/grep/lib/config.charset b/contrib/grep/lib/config.charset index 93b5a5d6da..89b3017b4e 100644 --- a/contrib/grep/lib/config.charset +++ b/contrib/grep/lib/config.charset @@ -1,7 +1,7 @@ #! /bin/sh # Output a system dependent table of character encoding aliases. # -# Copyright (C) 2000-2004, 2006-2011 Free Software Foundation, Inc. +# Copyright (C) 2000-2004, 2006-2012 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 @@ -14,8 +14,7 @@ # 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. +# with this program; if not, see . # # The table consists of lines of the form # ALIAS CANONICAL @@ -30,6 +29,8 @@ # The current list of GNU canonical charset names is as follows. # # name MIME? used by which systems +# (darwin = MacOS X, woe32 = native Windows) +# # ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin # ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin # ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin diff --git a/contrib/grep/lib/exitfail.c b/contrib/grep/lib/creat-safer.c similarity index 68% copy from contrib/grep/lib/exitfail.c copy to contrib/grep/lib/creat-safer.c index 953aa02fe8..f0f9a22c27 100644 --- a/contrib/grep/lib/exitfail.c +++ b/contrib/grep/lib/creat-safer.c @@ -1,6 +1,6 @@ -/* Failure exit status +/* Invoke creat, but avoid some glitches. - Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2009-2012 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 @@ -15,10 +15,17 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* Written by Jim Meyering. */ + #include -#include "exitfail.h" +#include "fcntl-safer.h" -#include +#include +#include "unistd-safer.h" -int volatile exit_failure = EXIT_FAILURE; +int +creat_safer (char const *file, mode_t mode) +{ + return fd_safer (creat (file, mode)); +} diff --git a/contrib/grep/lib/cycle-check.c b/contrib/grep/lib/cycle-check.c new file mode 100644 index 0000000000..011cae95dc --- /dev/null +++ b/contrib/grep/lib/cycle-check.c @@ -0,0 +1,85 @@ +/* help detect directory cycles efficiently + + Copyright (C) 2003-2006, 2009-2012 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 of the License, 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 . */ + +/* Written by Jim Meyering */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "cycle-check.h" + +#define CC_MAGIC 9827862 + +/* Return true if I is a power of 2, or is zero. */ + +static inline bool +is_zero_or_power_of_two (uintmax_t i) +{ + return (i & (i - 1)) == 0; +} + +void +cycle_check_init (struct cycle_check_state *state) +{ + state->chdir_counter = 0; + state->magic = CC_MAGIC; +} + +/* In traversing a directory hierarchy, call this function once for each + descending chdir call, with SB corresponding to the chdir operand. + If SB corresponds to a directory that has already been seen, + return true to indicate that there is a directory cycle. + Note that this is done "lazily", which means that some of + the directories in the cycle may be processed twice before + the cycle is detected. */ + +bool +cycle_check (struct cycle_check_state *state, struct stat const *sb) +{ + assert (state->magic == CC_MAGIC); + + /* If the current directory ever happens to be the same + as the one we last recorded for the cycle detection, + then it's obviously part of a cycle. */ + if (state->chdir_counter && SAME_INODE (*sb, state->dev_ino)) + return true; + + /* If the number of "descending" chdir calls is a power of two, + record the dev/ino of the current directory. */ + if (is_zero_or_power_of_two (++(state->chdir_counter))) + { + /* On all architectures that we know about, if the counter + overflows then there is a directory cycle here somewhere, + even if we haven't detected it yet. Typically this happens + only after the counter is incremented 2**64 times, so it's a + fairly theoretical point. */ + if (state->chdir_counter == 0) + return true; + + state->dev_ino.st_dev = sb->st_dev; + state->dev_ino.st_ino = sb->st_ino; + } + + return false; +} diff --git a/contrib/grep/lib/cycle-check.h b/contrib/grep/lib/cycle-check.h new file mode 100644 index 0000000000..88864768a5 --- /dev/null +++ b/contrib/grep/lib/cycle-check.h @@ -0,0 +1,52 @@ +/* help detect directory cycles efficiently + + Copyright (C) 2003-2004, 2006, 2009-2012 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 of the License, 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 . */ + +/* Written by Jim Meyering */ + +#ifndef CYCLE_CHECK_H +# define CYCLE_CHECK_H 1 + +# include +# include +# include "dev-ino.h" +# include "same-inode.h" + +struct cycle_check_state +{ + struct dev_ino dev_ino; + uintmax_t chdir_counter; + int magic; +}; + +void cycle_check_init (struct cycle_check_state *state); +bool cycle_check (struct cycle_check_state *state, struct stat const *sb); + +# define CYCLE_CHECK_REFLECT_CHDIR_UP(State, SB_dir, SB_subdir) \ + do \ + { \ + /* You must call cycle_check at least once before using this macro. */ \ + if ((State)->chdir_counter == 0) \ + abort (); \ + if (SAME_INODE ((State)->dev_ino, SB_subdir)) \ + { \ + (State)->dev_ino.st_dev = (SB_dir).st_dev; \ + (State)->dev_ino.st_ino = (SB_dir).st_ino; \ + } \ + } \ + while (0) + +#endif diff --git a/contrib/grep/lib/dev-ino.h b/contrib/grep/lib/dev-ino.h new file mode 100644 index 0000000000..695d38c7bb --- /dev/null +++ b/contrib/grep/lib/dev-ino.h @@ -0,0 +1,13 @@ +#ifndef DEV_INO_H +# define DEV_INO_H 1 + +# include +# include + +struct dev_ino +{ + ino_t st_ino; + dev_t st_dev; +}; + +#endif diff --git a/contrib/grep/lib/exitfail.c b/contrib/grep/lib/dirent--.h similarity index 74% copy from contrib/grep/lib/exitfail.c copy to contrib/grep/lib/dirent--.h index 953aa02fe8..1b75793867 100644 --- a/contrib/grep/lib/exitfail.c +++ b/contrib/grep/lib/dirent--.h @@ -1,6 +1,6 @@ -/* Failure exit status +/* Like dirent.h, but redefine some names to avoid glitches. - Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 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 @@ -15,10 +15,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Eric Blake. */ -#include "exitfail.h" +#include "dirent-safer.h" -#include - -int volatile exit_failure = EXIT_FAILURE; +#undef opendir +#define opendir opendir_safer diff --git a/contrib/grep/lib/dirent-private.h b/contrib/grep/lib/dirent-private.h new file mode 100644 index 0000000000..b60203c4b9 --- /dev/null +++ b/contrib/grep/lib/dirent-private.h @@ -0,0 +1,40 @@ +/* Private details of the DIR type. + Copyright (C) 2011-2012 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 of the License, 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 . */ + +#ifndef _DIRENT_PRIVATE_H +#define _DIRENT_PRIVATE_H 1 + +#define WIN32_LEAN_AND_MEAN +#include + +struct gl_directory +{ + /* Status, or error code to produce in next readdir() call. + -2 means the end of the directory is already reached, + -1 means the entry was already filled by FindFirstFile, + 0 means the entry needs to be filled using FindNextFile. + A positive value is an error code. */ + int status; + /* Handle, reading the directory, at current position. */ + HANDLE current; + /* Found directory entry. */ + WIN32_FIND_DATA entry; + /* Argument to pass to FindFirstFile. It consists of the absolutized + directory name, followed by a directory separator and the wildcards. */ + char dir_name_mask[1]; +}; + +#endif /* _DIRENT_PRIVATE_H */ diff --git a/contrib/grep/lib/quote.h b/contrib/grep/lib/dirent-safer.h similarity index 75% copy from contrib/grep/lib/quote.h copy to contrib/grep/lib/dirent-safer.h index d0acb51f02..861ea93a44 100644 --- a/contrib/grep/lib/quote.h +++ b/contrib/grep/lib/dirent-safer.h @@ -1,6 +1,6 @@ -/* quote.h - prototypes for quote.c +/* Invoke dirent-like functions, but avoid some glitches. - Copyright (C) 1998-2001, 2003, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 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 @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* Written by Eric Blake. */ -char const *quote_n (int n, char const *name); -char const *quote (char const *name); +#include + +DIR *opendir_safer (const char *name); diff --git a/contrib/grep/lib/mbsrtowcs.c b/contrib/grep/lib/dirfd.c similarity index 68% copy from contrib/grep/lib/mbsrtowcs.c copy to contrib/grep/lib/dirfd.c index 69e6dfffb8..2f4d424f48 100644 --- a/contrib/grep/lib/mbsrtowcs.c +++ b/contrib/grep/lib/dirfd.c @@ -1,6 +1,6 @@ -/* Convert string to wide string. - Copyright (C) 2008-2011 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. +/* dirfd.c -- return the file descriptor associated with an open DIR* + + Copyright (C) 2001, 2006, 2008-2012 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 @@ -15,18 +15,18 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Jim Meyering. */ -/* Specification. */ -#include +#include +#include #include -#include -#include - -#include "strnlen1.h" - - -extern mbstate_t _gl_mbsrtowcs_state; -#include "mbsrtowcs-impl.h" +int +dirfd (DIR *dir_p) +{ + int fd = DIR_TO_FD (dir_p); + if (fd == -1) + errno = ENOTSUP; + return fd; +} diff --git a/contrib/grep/lib/dirname-lgpl.c b/contrib/grep/lib/dirname-lgpl.c index f5b0c0ff01..2895cbcb28 100644 --- a/contrib/grep/lib/dirname-lgpl.c +++ b/contrib/grep/lib/dirname-lgpl.c @@ -1,6 +1,6 @@ /* dirname.c -- return all but the last element in a file name - Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2011 Free Software + Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ /* Return the length of the prefix of FILE that will be used by dir_name. If FILE is in the working directory, this returns zero - even though `dir_name (FILE)' will return ".". Works properly even + even though 'dir_name (FILE)' will return ".". Works properly even if there are trailing slashes (by effectively ignoring them). */ size_t @@ -53,9 +53,9 @@ dir_len (char const *file) } -/* In general, we can't use the builtin `dirname' function if available, +/* In general, we can't use the builtin 'dirname' function if available, since it has different meanings in different environments. - In some environments the builtin `dirname' modifies its argument. + In some environments the builtin 'dirname' modifies its argument. Return the leading directories part of FILE, allocated with malloc. Works properly even if there are trailing slashes (by effectively diff --git a/contrib/grep/lib/dirname.c b/contrib/grep/lib/dirname.c deleted file mode 100644 index 411ded31b8..0000000000 --- a/contrib/grep/lib/dirname.c +++ /dev/null @@ -1,38 +0,0 @@ -/* dirname.c -- return all but the last element in a file name - - Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2011 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 of the License, 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 . */ - -#include - -#include "dirname.h" - -#include -#include -#include "xalloc.h" - -/* Just like mdir_name (dirname-lgpl.c), except, rather than - returning NULL upon malloc failure, here, we report the - "memory exhausted" condition and exit. */ - -char * -dir_name (char const *file) -{ - char *result = mdir_name (file); - if (!result) - xalloc_die (); - return result; -} diff --git a/contrib/grep/lib/dirname.h b/contrib/grep/lib/dirname.h index 2ef9882445..51a685c3a4 100644 --- a/contrib/grep/lib/dirname.h +++ b/contrib/grep/lib/dirname.h @@ -1,6 +1,6 @@ /* Take file names apart into directory and base names. - Copyright (C) 1998, 2001, 2003-2006, 2009-2011 Free Software Foundation, + Copyright (C) 1998, 2001, 2003-2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -37,9 +37,9 @@ char *dir_name (char const *file); # endif char *mdir_name (char const *file); -size_t base_len (char const *file); -size_t dir_len (char const *file); -char *last_component (char const *file); +size_t base_len (char const *file) _GL_ATTRIBUTE_PURE; +size_t dir_len (char const *file) _GL_ATTRIBUTE_PURE; +char *last_component (char const *file) _GL_ATTRIBUTE_PURE; bool strip_trailing_slashes (char *file); diff --git a/contrib/grep/lib/dosname.h b/contrib/grep/lib/dosname.h index acdd03b156..0468ce4dc8 100644 --- a/contrib/grep/lib/dosname.h +++ b/contrib/grep/lib/dosname.h @@ -1,6 +1,6 @@ /* File names on MS-DOS/Windows systems. - Copyright (C) 2000-2001, 2004-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2004-2006, 2009-2012 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 diff --git a/contrib/grep/lib/mbrlen.c b/contrib/grep/lib/dup-safer.c similarity index 64% copy from contrib/grep/lib/mbrlen.c copy to contrib/grep/lib/dup-safer.c index 54d2c88f7b..0f5d3be3f7 100644 --- a/contrib/grep/lib/mbrlen.c +++ b/contrib/grep/lib/dup-safer.c @@ -1,6 +1,6 @@ -/* Recognize multibyte character. - Copyright (C) 1999-2000, 2008-2011 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. +/* Invoke dup, but avoid some glitches. + + Copyright (C) 2001, 2004-2006, 2009-2012 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 @@ -15,18 +15,20 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* Written by Paul Eggert. */ + #include -/* Specification. */ -#include +#include "unistd-safer.h" +#include +#include -static mbstate_t internal_state; +/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or + STDERR_FILENO. */ -size_t -mbrlen (const char *s, size_t n, mbstate_t *ps) +int +dup_safer (int fd) { - if (ps == NULL) - ps = &internal_state; - return mbrtowc (NULL, s, n, ps); + return fcntl (fd, F_DUPFD, STDERR_FILENO + 1); } diff --git a/contrib/grep/lib/mbsrtowcs.c b/contrib/grep/lib/dup.c similarity index 53% copy from contrib/grep/lib/mbsrtowcs.c copy to contrib/grep/lib/dup.c index 69e6dfffb8..0a0b69ed4e 100644 --- a/contrib/grep/lib/mbsrtowcs.c +++ b/contrib/grep/lib/dup.c @@ -1,6 +1,6 @@ -/* Convert string to wide string. - Copyright (C) 2008-2011 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. +/* Duplicate an open file descriptor. + + Copyright (C) 2011-2012 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 @@ -18,15 +18,44 @@ #include /* Specification. */ -#include +#include #include -#include -#include - -#include "strnlen1.h" - - -extern mbstate_t _gl_mbsrtowcs_state; -#include "mbsrtowcs-impl.h" +#include "msvc-inval.h" + +#undef dup + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static inline int +dup_nothrow (int fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = dup (fd); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +#else +# define dup_nothrow dup +#endif + +int +rpl_dup (int fd) +{ + int result = dup_nothrow (fd); +#if REPLACE_FCHDIR + if (result >= 0) + result = _gl_register_dup (fd, result); +#endif + return result; +} diff --git a/contrib/grep/lib/dup2.c b/contrib/grep/lib/dup2.c new file mode 100644 index 0000000000..f6d0f1c73c --- /dev/null +++ b/contrib/grep/lib/dup2.c @@ -0,0 +1,157 @@ +/* Duplicate an open file descriptor to a specified file descriptor. + + Copyright (C) 1999, 2004-2007, 2009-2012 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 of the License, 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 . */ + +/* written by Paul Eggert */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if HAVE_DUP2 + +# undef dup2 + +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +# include "msvc-inval.h" + +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" + +static int +ms_windows_dup2 (int fd, int desired_fd) +{ + int result; + + /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, + dup2 (fd, fd) returns 0, but all further attempts to use fd in + future dup2 calls will hang. */ + if (fd == desired_fd) + { + if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + return fd; + } + + /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: + http://bugs.winehq.org/show_bug.cgi?id=21289 */ + if (desired_fd < 0) + { + errno = EBADF; + return -1; + } + + TRY_MSVC_INVAL + { + result = dup2 (fd, desired_fd); + } + CATCH_MSVC_INVAL + { + errno = EBADF; + result = -1; + } + DONE_MSVC_INVAL; + + if (result == 0) + result = desired_fd; + + return result; +} + +# define dup2 ms_windows_dup2 + +# endif + +int +rpl_dup2 (int fd, int desired_fd) +{ + int result; + +# ifdef F_GETFL + /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. + On Cygwin 1.5.x, dup2 (1, 1) returns 0. + On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ + if (fd == desired_fd) + return fcntl (fd, F_GETFL) == -1 ? -1 : fd; +# endif + + result = dup2 (fd, desired_fd); + + /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ + if (result == -1 && errno == EMFILE) + errno = EBADF; +# if REPLACE_FCHDIR + if (fd != desired_fd && result != -1) + result = _gl_register_dup (fd, result); +# endif + return result; +} + +#else /* !HAVE_DUP2 */ + +/* On older platforms, dup2 did not exist. */ + +# ifndef F_DUPFD +static int +dupfd (int fd, int desired_fd) +{ + int duplicated_fd = dup (fd); + if (duplicated_fd < 0 || duplicated_fd == desired_fd) + return duplicated_fd; + else + { + int r = dupfd (fd, desired_fd); + int e = errno; + close (duplicated_fd); + errno = e; + return r; + } +} +# endif + +int +dup2 (int fd, int desired_fd) +{ + int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; + if (result == -1 || fd == desired_fd) + return result; + close (desired_fd); +# ifdef F_DUPFD + result = fcntl (fd, F_DUPFD, desired_fd); +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif +# else + result = dupfd (fd, desired_fd); +# endif + if (result == -1 && (errno == EMFILE || errno == EINVAL)) + errno = EBADF; + return result; +} +#endif /* !HAVE_DUP2 */ diff --git a/contrib/grep/lib/error.c b/contrib/grep/lib/error.c index 7482baacfb..dc8c65fa7f 100644 --- a/contrib/grep/lib/error.c +++ b/contrib/grep/lib/error.c @@ -1,5 +1,5 @@ /* Error handler for noninteractive utilities - Copyright (C) 1990-1998, 2000-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1990-1998, 2000-2007, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software: you can redistribute it and/or modify @@ -54,7 +54,7 @@ function without parameters instead. */ void (*error_print_progname) (void); -/* This variable is incremented each time `error' is called. */ +/* This variable is incremented each time 'error' is called. */ unsigned int error_message_count; #ifdef _LIBC @@ -65,7 +65,7 @@ unsigned int error_message_count; # include # include -/* In GNU libc we want do not want to use the common name `error' directly. +/* In GNU libc we want do not want to use the common name 'error' directly. Instead make it a weak alias. */ extern void __error (int status, int errnum, const char *message, ...) __attribute__ ((__format__ (__printf__, 3, 4))); @@ -89,9 +89,11 @@ extern void __error_at_line (int status, int errnum, const char *file_name, # include # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Get declarations of the Win32 API functions. */ +/* Get declarations of the native Windows API functions. */ # define WIN32_LEAN_AND_MEAN # include +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" # endif /* The gnulib override of fcntl is not needed in this file. */ @@ -123,9 +125,10 @@ static inline int is_open (int fd) { # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - /* On Win32: The initial state of unassigned standard file descriptors is - that they are open but point to an INVALID_HANDLE_VALUE. There is no - fcntl, and the gnulib replacement fcntl does not support F_GETFL. */ + /* On native Windows: The initial state of unassigned standard file + descriptors is that they are open but point to an INVALID_HANDLE_VALUE. + There is no fcntl, and the gnulib replacement fcntl does not support + F_GETFL. */ return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; # else # ifndef F_GETFL diff --git a/contrib/grep/lib/error.h b/contrib/grep/lib/error.h index 80f81bcef2..9c2cb8bc6a 100644 --- a/contrib/grep/lib/error.h +++ b/contrib/grep/lib/error.h @@ -1,5 +1,5 @@ /* Declaration for error-reporting function - Copyright (C) 1995-1997, 2003, 2006, 2008-2011 Free Software Foundation, + Copyright (C) 1995-1997, 2003, 2006, 2008-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -35,9 +35,9 @@ extern "C" { #endif -/* Print a message with `fprintf (stderr, FORMAT, ...)'; +/* Print a message with 'fprintf (stderr, FORMAT, ...)'; if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ + If STATUS is nonzero, terminate the program with 'exit (STATUS)'. */ extern void error (int __status, int __errnum, const char *__format, ...) _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4)); @@ -51,7 +51,7 @@ extern void error_at_line (int __status, int __errnum, const char *__fname, function without parameters instead. */ extern void (*error_print_progname) (void); -/* This variable is incremented each time `error' is called. */ +/* This variable is incremented each time 'error' is called. */ extern unsigned int error_message_count; /* Sometimes we want to have at most one error per line. This diff --git a/contrib/grep/lib/exclude.c b/contrib/grep/lib/exclude.c index df49714a6b..bc3e6e62ff 100644 --- a/contrib/grep/lib/exclude.c +++ b/contrib/grep/lib/exclude.c @@ -1,6 +1,6 @@ /* exclude.c -- exclude file names - Copyright (C) 1992-1994, 1997, 1999-2007, 2009-2011 Free Software + Copyright (C) 1992-1994, 1997, 1999-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/exclude.h b/contrib/grep/lib/exclude.h index 0a314a99fc..50e8a63155 100644 --- a/contrib/grep/lib/exclude.h +++ b/contrib/grep/lib/exclude.h @@ -1,6 +1,6 @@ /* exclude.h -- declarations for excluding file names - Copyright (C) 1992-1994, 1997, 1999, 2001-2003, 2005-2006, 2009-2011 Free + Copyright (C) 1992-1994, 1997, 1999, 2001-2003, 2005-2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -39,7 +39,7 @@ struct exclude; -bool fnmatch_pattern_has_wildcards (const char *, int); +bool fnmatch_pattern_has_wildcards (const char *, int) _GL_ATTRIBUTE_PURE; struct exclude *new_exclude (void); void free_exclude (struct exclude *); diff --git a/contrib/grep/lib/exitfail.c b/contrib/grep/lib/exitfail.c index 953aa02fe8..fdd674c11b 100644 --- a/contrib/grep/lib/exitfail.c +++ b/contrib/grep/lib/exitfail.c @@ -1,6 +1,6 @@ /* Failure exit status - Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2005-2007, 2009-2012 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 diff --git a/contrib/grep/lib/exitfail.h b/contrib/grep/lib/exitfail.h index 6d01d4f91e..074f212192 100644 --- a/contrib/grep/lib/exitfail.h +++ b/contrib/grep/lib/exitfail.h @@ -1,6 +1,6 @@ /* Failure exit status - Copyright (C) 2002, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2002, 2009-2012 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 diff --git a/contrib/grep/lib/fchdir.c b/contrib/grep/lib/fchdir.c new file mode 100644 index 0000000000..2e07553e6b --- /dev/null +++ b/contrib/grep/lib/fchdir.c @@ -0,0 +1,208 @@ +/* fchdir replacement. + Copyright (C) 2006-2012 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dosname.h" +#include "filenamecat.h" + +#ifndef REPLACE_OPEN_DIRECTORY +# define REPLACE_OPEN_DIRECTORY 0 +#endif + +/* This replacement assumes that a directory is not renamed while opened + through a file descriptor. + + FIXME: On mingw, this would be possible to enforce if we were to + also open a HANDLE to each directory currently visited by a file + descriptor, since mingw refuses to rename any in-use file system + object. */ + +/* Array of file descriptors opened. If REPLACE_OPEN_DIRECTORY or if it points + to a directory, it stores info about this directory. */ +typedef struct +{ + char *name; /* Absolute name of the directory, or NULL. */ + /* FIXME - add a DIR* member to make dirfd possible on mingw? */ +} dir_info_t; +static dir_info_t *dirs; +static size_t dirs_allocated; + +/* Try to ensure dirs has enough room for a slot at index fd; free any + contents already in that slot. Return false and set errno to + ENOMEM on allocation failure. */ +static bool +ensure_dirs_slot (size_t fd) +{ + if (fd < dirs_allocated) + free (dirs[fd].name); + else + { + size_t new_allocated; + dir_info_t *new_dirs; + + new_allocated = 2 * dirs_allocated + 1; + if (new_allocated <= fd) + new_allocated = fd + 1; + new_dirs = + (dirs != NULL + ? (dir_info_t *) realloc (dirs, new_allocated * sizeof *dirs) + : (dir_info_t *) malloc (new_allocated * sizeof *dirs)); + if (new_dirs == NULL) + return false; + memset (new_dirs + dirs_allocated, 0, + (new_allocated - dirs_allocated) * sizeof *dirs); + dirs = new_dirs; + dirs_allocated = new_allocated; + } + return true; +} + +/* Return an absolute name of DIR in malloc'd storage. */ +static char * +get_name (char const *dir) +{ + char *cwd; + char *result; + int saved_errno; + + if (IS_ABSOLUTE_FILE_NAME (dir)) + return strdup (dir); + + /* We often encounter "."; treat it as a special case. */ + cwd = getcwd (NULL, 0); + if (!cwd || (dir[0] == '.' && dir[1] == '\0')) + return cwd; + + result = mfile_name_concat (cwd, dir, NULL); + saved_errno = errno; + free (cwd); + errno = saved_errno; + return result; +} + +/* Hook into the gnulib replacements for open() and close() to keep track + of the open file descriptors. */ + +/* Close FD, cleaning up any fd to name mapping if fd was visiting a + directory. */ +void +_gl_unregister_fd (int fd) +{ + if (fd >= 0 && fd < dirs_allocated) + { + free (dirs[fd].name); + dirs[fd].name = NULL; + } +} + +/* Mark FD as visiting FILENAME. FD must be non-negative, and refer + to an open file descriptor. If REPLACE_OPEN_DIRECTORY is non-zero, + this should only be called if FD is visiting a directory. Close FD + and return -1 if there is insufficient memory to track the + directory name; otherwise return FD. */ +int +_gl_register_fd (int fd, const char *filename) +{ + struct stat statbuf; + + assert (0 <= fd); + if (REPLACE_OPEN_DIRECTORY + || (fstat (fd, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))) + { + if (!ensure_dirs_slot (fd) + || (dirs[fd].name = get_name (filename)) == NULL) + { + int saved_errno = errno; + close (fd); + errno = saved_errno; + return -1; + } + } + return fd; +} + +/* Mark NEWFD as a duplicate of OLDFD; useful from dup, dup2, dup3, + and fcntl. Both arguments must be valid and distinct file + descriptors. Close NEWFD and return -1 if OLDFD is tracking a + directory, but there is insufficient memory to track the same + directory in NEWFD; otherwise return NEWFD. */ +int +_gl_register_dup (int oldfd, int newfd) +{ + assert (0 <= oldfd && 0 <= newfd && oldfd != newfd); + if (oldfd < dirs_allocated && dirs[oldfd].name) + { + /* Duplicated a directory; must ensure newfd is allocated. */ + if (!ensure_dirs_slot (newfd) + || (dirs[newfd].name = strdup (dirs[oldfd].name)) == NULL) + { + int saved_errno = errno; + close (newfd); + errno = saved_errno; + newfd = -1; + } + } + else if (newfd < dirs_allocated) + { + /* Duplicated a non-directory; ensure newfd is cleared. */ + free (dirs[newfd].name); + dirs[newfd].name = NULL; + } + return newfd; +} + +/* If FD is currently visiting a directory, then return the name of + that directory. Otherwise, return NULL and set errno. */ +const char * +_gl_directory_name (int fd) +{ + if (0 <= fd && fd < dirs_allocated && dirs[fd].name != NULL) + return dirs[fd].name; + /* At this point, fd is either invalid, or open but not a directory. + If dup2 fails, errno is correctly EBADF. */ + if (0 <= fd) + { + if (dup2 (fd, fd) == fd) + errno = ENOTDIR; + } + else + errno = EBADF; + return NULL; +} + + +/* Implement fchdir() in terms of chdir(). */ + +int +fchdir (int fd) +{ + const char *name = _gl_directory_name (fd); + return name ? chdir (name) : -1; +} diff --git a/contrib/grep/lib/exitfail.c b/contrib/grep/lib/fcntl--.h similarity index 65% copy from contrib/grep/lib/exitfail.c copy to contrib/grep/lib/fcntl--.h index 953aa02fe8..8fde6c1120 100644 --- a/contrib/grep/lib/exitfail.c +++ b/contrib/grep/lib/fcntl--.h @@ -1,6 +1,6 @@ -/* Failure exit status +/* Like fcntl.h, but redefine some names to avoid glitches. - Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005, 2009-2012 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 @@ -15,10 +15,18 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Paul Eggert. */ -#include "exitfail.h" +#include +#include "fcntl-safer.h" -#include +#undef open +#define open open_safer -int volatile exit_failure = EXIT_FAILURE; +#undef creat +#define creat creat_safer + +#if GNULIB_OPENAT_SAFER +# undef openat +# define openat openat_safer +#endif diff --git a/contrib/grep/lib/exitfail.c b/contrib/grep/lib/fcntl-safer.h similarity index 66% copy from contrib/grep/lib/exitfail.c copy to contrib/grep/lib/fcntl-safer.h index 953aa02fe8..440a2ffde8 100644 --- a/contrib/grep/lib/exitfail.c +++ b/contrib/grep/lib/fcntl-safer.h @@ -1,6 +1,6 @@ -/* Failure exit status +/* Invoke fcntl-like functions, but avoid some glitches. - Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005, 2009-2012 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 @@ -15,10 +15,13 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Paul Eggert. */ -#include "exitfail.h" +#include -#include +int open_safer (char const *, int, ...); +int creat_safer (char const *, mode_t); -int volatile exit_failure = EXIT_FAILURE; +#if GNULIB_OPENAT_SAFER +int openat_safer (int, char const *, int, ...); +#endif diff --git a/contrib/grep/lib/fcntl.c b/contrib/grep/lib/fcntl.c new file mode 100644 index 0000000000..3dfb6b73a8 --- /dev/null +++ b/contrib/grep/lib/fcntl.c @@ -0,0 +1,311 @@ +/* Provide file descriptor control. + + Copyright (C) 2009-2012 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 of the License, 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 . */ + +/* Written by Eric Blake . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include + +#if !HAVE_FCNTL +# define rpl_fcntl fcntl +#endif +#undef fcntl + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" + +/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */ +# define OPEN_MAX_MAX 0x10000 + +/* Duplicate OLDFD into the first available slot of at least NEWFD, + which must be positive, with FLAGS determining whether the duplicate + will be inheritable. */ +static int +dupfd (int oldfd, int newfd, int flags) +{ + /* Mingw has no way to create an arbitrary fd. Iterate until all + file descriptors less than newfd are filled up. */ + HANDLE curr_process = GetCurrentProcess (); + HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd); + unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT]; + unsigned int fds_to_close_bound = 0; + int result; + BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE; + int mode; + + if (newfd < 0 || getdtablesize () <= newfd) + { + errno = EINVAL; + return -1; + } + if (old_handle == INVALID_HANDLE_VALUE + || (mode = setmode (oldfd, O_BINARY)) == -1) + { + /* oldfd is not open, or is an unassigned standard file + descriptor. */ + errno = EBADF; + return -1; + } + setmode (oldfd, mode); + flags |= mode; + + for (;;) + { + HANDLE new_handle; + int duplicated_fd; + unsigned int index; + + if (!DuplicateHandle (curr_process, /* SourceProcessHandle */ + old_handle, /* SourceHandle */ + curr_process, /* TargetProcessHandle */ + (PHANDLE) &new_handle, /* TargetHandle */ + (DWORD) 0, /* DesiredAccess */ + inherit, /* InheritHandle */ + DUPLICATE_SAME_ACCESS)) /* Options */ + { + /* TODO: Translate GetLastError () into errno. */ + errno = EMFILE; + result = -1; + break; + } + duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags); + if (duplicated_fd < 0) + { + CloseHandle (new_handle); + errno = EMFILE; + result = -1; + break; + } + if (newfd <= duplicated_fd) + { + result = duplicated_fd; + break; + } + + /* Set the bit duplicated_fd in fds_to_close[]. */ + index = (unsigned int) duplicated_fd / CHAR_BIT; + if (fds_to_close_bound <= index) + { + if (sizeof fds_to_close <= index) + /* Need to increase OPEN_MAX_MAX. */ + abort (); + memset (fds_to_close + fds_to_close_bound, '\0', + index + 1 - fds_to_close_bound); + fds_to_close_bound = index + 1; + } + fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT); + } + + /* Close the previous fds that turned out to be too small. */ + { + int saved_errno = errno; + unsigned int duplicated_fd; + + for (duplicated_fd = 0; + duplicated_fd < fds_to_close_bound * CHAR_BIT; + duplicated_fd++) + if ((fds_to_close[duplicated_fd / CHAR_BIT] + >> (duplicated_fd % CHAR_BIT)) + & 1) + close (duplicated_fd); + + errno = saved_errno; + } + +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (oldfd, result); +# endif + return result; +} +#endif /* W32 */ + +/* Perform the specified ACTION on the file descriptor FD, possibly + using the argument ARG further described below. This replacement + handles the following actions, and forwards all others on to the + native fcntl. An unrecognized ACTION returns -1 with errno set to + EINVAL. + + F_DUPFD - duplicate FD, with int ARG being the minimum target fd. + If successful, return the duplicate, which will be inheritable; + otherwise return -1 and set errno. + + F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum + target fd. If successful, return the duplicate, which will not be + inheritable; otherwise return -1 and set errno. + + F_GETFD - ARG need not be present. If successful, return a + non-negative value containing the descriptor flags of FD (only + FD_CLOEXEC is portable, but other flags may be present); otherwise + return -1 and set errno. */ + +int +rpl_fcntl (int fd, int action, /* arg */...) +{ + va_list arg; + int result = -1; + va_start (arg, action); + switch (action) + { + +#if !HAVE_FCNTL + case F_DUPFD: + { + int target = va_arg (arg, int); + result = dupfd (fd, target, 0); + break; + } +#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR + case F_DUPFD: + { + int target = va_arg (arg, int); + /* Detect invalid target; needed for cygwin 1.5.x. */ + if (target < 0 || getdtablesize () <= target) + errno = EINVAL; + else + { + /* Haiku alpha 2 loses fd flags on original. */ + int flags = fcntl (fd, F_GETFD); + if (flags < 0) + { + result = -1; + break; + } + result = fcntl (fd, action, target); + if (0 <= result && fcntl (fd, F_SETFD, flags) == -1) + { + int saved_errno = errno; + close (result); + result = -1; + errno = saved_errno; + } +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + break; + } /* F_DUPFD */ +#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */ + + case F_DUPFD_CLOEXEC: + { + int target = va_arg (arg, int); + +#if !HAVE_FCNTL + result = dupfd (fd, target, O_CLOEXEC); + break; +#else /* HAVE_FCNTL */ + /* Try the system call first, if the headers claim it exists + (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we + may be running with a glibc that has the macro but with an + older kernel that does not support it. Cache the + information on whether the system call really works, but + avoid caching failure if the corresponding F_DUPFD fails + for any reason. 0 = unknown, 1 = yes, -1 = no. */ + static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0; + if (0 <= have_dupfd_cloexec) + { + result = fcntl (fd, action, target); + if (0 <= result || errno != EINVAL) + { + have_dupfd_cloexec = 1; +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + else + { + result = rpl_fcntl (fd, F_DUPFD, target); + if (result < 0) + break; + have_dupfd_cloexec = -1; + } + } + else + result = rpl_fcntl (fd, F_DUPFD, target); + if (0 <= result && have_dupfd_cloexec == -1) + { + int flags = fcntl (result, F_GETFD); + if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1) + { + int saved_errno = errno; + close (result); + errno = saved_errno; + result = -1; + } + } + break; +#endif /* HAVE_FCNTL */ + } /* F_DUPFD_CLOEXEC */ + +#if !HAVE_FCNTL + case F_GETFD: + { +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + HANDLE handle = (HANDLE) _get_osfhandle (fd); + DWORD flags; + if (handle == INVALID_HANDLE_VALUE + || GetHandleInformation (handle, &flags) == 0) + errno = EBADF; + else + result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC; +# else /* !W32 */ + /* Use dup2 to reject invalid file descriptors. No way to + access this information, so punt. */ + if (0 <= dup2 (fd, fd)) + result = 0; +# endif /* !W32 */ + break; + } /* F_GETFD */ +#endif /* !HAVE_FCNTL */ + + /* Implementing F_SETFD on mingw is not trivial - there is no + API for changing the O_NOINHERIT bit on an fd, and merely + changing the HANDLE_FLAG_INHERIT bit on the underlying handle + can lead to odd state. It may be possible by duplicating the + handle, using _open_osfhandle with the right flags, then + using dup2 to move the duplicate onto the original, but that + is not supported for now. */ + + default: + { +#if HAVE_FCNTL + void *p = va_arg (arg, void *); + result = fcntl (fd, action, p); +#else + errno = EINVAL; +#endif + break; + } + } + va_end (arg); + return result; +} diff --git a/contrib/grep/lib/fd-hook.c b/contrib/grep/lib/fd-hook.c new file mode 100644 index 0000000000..8f4ffe2a8d --- /dev/null +++ b/contrib/grep/lib/fd-hook.c @@ -0,0 +1,116 @@ +/* Hook for making making file descriptor functions close(), ioctl() extensible. + Copyright (C) 2009-2012 Free Software Foundation, Inc. + Written by Bruno Haible , 2009. + + 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include "fd-hook.h" + +#include + +/* Currently, this entire code is only needed for the handling of sockets + on native Windows platforms. */ +#if WINDOWS_SOCKETS + +/* The first and last link in the doubly linked list. + Initially the list is empty. */ +static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL }; + +int +execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary, + int fd) +{ + if (remaining_list == &anchor) + /* End of list reached. */ + return primary (fd); + else + return remaining_list->private_close_fn (remaining_list->private_next, + primary, fd); +} + +int +execute_all_close_hooks (gl_close_fn primary, int fd) +{ + return execute_close_hooks (anchor.private_next, primary, fd); +} + +int +execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary, + int fd, int request, void *arg) +{ + if (remaining_list == &anchor) + /* End of list reached. */ + return primary (fd, request, arg); + else + return remaining_list->private_ioctl_fn (remaining_list->private_next, + primary, fd, request, arg); +} + +int +execute_all_ioctl_hooks (gl_ioctl_fn primary, + int fd, int request, void *arg) +{ + return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg); +} + +void +register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link) +{ + if (close_hook == NULL) + close_hook = execute_close_hooks; + if (ioctl_hook == NULL) + ioctl_hook = execute_ioctl_hooks; + + if (link->private_next == NULL && link->private_prev == NULL) + { + /* Add the link to the doubly linked list. */ + link->private_next = anchor.private_next; + link->private_prev = &anchor; + link->private_close_fn = close_hook; + link->private_ioctl_fn = ioctl_hook; + anchor.private_next->private_prev = link; + anchor.private_next = link; + } + else + { + /* The link is already in use. */ + if (link->private_close_fn != close_hook + || link->private_ioctl_fn != ioctl_hook) + abort (); + } +} + +void +unregister_fd_hook (struct fd_hook *link) +{ + struct fd_hook *next = link->private_next; + struct fd_hook *prev = link->private_prev; + + if (next != NULL && prev != NULL) + { + /* The link is in use. Remove it from the doubly linked list. */ + prev->private_next = next; + next->private_prev = prev; + /* Clear the link, to mark it unused. */ + link->private_next = NULL; + link->private_prev = NULL; + link->private_close_fn = NULL; + link->private_ioctl_fn = NULL; + } +} + +#endif diff --git a/contrib/grep/lib/fd-hook.h b/contrib/grep/lib/fd-hook.h new file mode 100644 index 0000000000..721e9ad931 --- /dev/null +++ b/contrib/grep/lib/fd-hook.h @@ -0,0 +1,119 @@ +/* Hook for making making file descriptor functions close(), ioctl() extensible. + Copyright (C) 2009-2012 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 of the License, 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 . */ + + +#ifndef FD_HOOK_H +#define FD_HOOK_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Currently, this entire code is only needed for the handling of sockets + on native Windows platforms. */ +#if WINDOWS_SOCKETS + + +/* Type of function that closes FD. */ +typedef int (*gl_close_fn) (int fd); + +/* Type of function that applies a control request to FD. */ +typedef int (*gl_ioctl_fn) (int fd, int request, void *arg); + +/* An element of the list of file descriptor hooks. + In CLOS (Common Lisp Object System) speak, it consists of an "around" + method for the close() function and an "around" method for the ioctl() + function. + The fields of this structure are considered private. */ +struct fd_hook +{ + /* Doubly linked list. */ + struct fd_hook *private_next; + struct fd_hook *private_prev; + /* Function that treats the types of FD that it knows about and calls + execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback. */ + int (*private_close_fn) (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + /* Function that treats the types of FD that it knows about and calls + execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a + fallback. */ + int (*private_ioctl_fn) (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); +}; + +/* This type of function closes FD, applying special knowledge for the FD + types it knows about, and calls + execute_close_hooks (REMAINING_LIST, PRIMARY, FD) + for the other FD types. + In CLOS speak, REMAINING_LIST is the remaining list of "around" methods, + and PRIMARY is the "primary" method for close(). */ +typedef int (*close_hook_fn) (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + +/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method. + Return 0 or -1, like close() would do. */ +extern int execute_close_hooks (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + +/* Execute all close hooks, with PRIMARY as "primary" method. + Return 0 or -1, like close() would do. */ +extern int execute_all_close_hooks (gl_close_fn primary, int fd); + +/* This type of function applies a control request to FD, applying special + knowledge for the FD types it knows about, and calls + execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) + for the other FD types. + In CLOS speak, REMAINING_LIST is the remaining list of "around" methods, + and PRIMARY is the "primary" method for ioctl(). */ +typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method. + Return 0 or -1, like ioctl() would do. */ +extern int execute_ioctl_hooks (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Execute all ioctl hooks, with PRIMARY as "primary" method. + Return 0 or -1, like ioctl() would do. */ +extern int execute_all_ioctl_hooks (gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Add a function pair to the list of file descriptor hooks. + CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change. + The LINK variable points to a piece of memory which is guaranteed to be + accessible until the corresponding call to unregister_fd_hook. */ +extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, + struct fd_hook *link); + +/* Removes a hook from the list of file descriptor hooks. */ +extern void unregister_fd_hook (struct fd_hook *link); + + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* FD_HOOK_H */ diff --git a/contrib/grep/lib/fd-safer.c b/contrib/grep/lib/fd-safer.c new file mode 100644 index 0000000000..052837bdd1 --- /dev/null +++ b/contrib/grep/lib/fd-safer.c @@ -0,0 +1,49 @@ +/* Return a safer copy of a file descriptor. + + Copyright (C) 2005-2006, 2009-2012 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 of the License, 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 . */ + +/* Written by Paul Eggert. */ + +#include + +#include "unistd-safer.h" + +#include +#include + +/* Return FD, unless FD would be a copy of standard input, output, or + error; in that case, return a duplicate of FD, closing FD. On + failure to duplicate, close FD, set errno, and return -1. Preserve + errno if FD is negative, so that the caller can always inspect + errno when the returned value is negative. + + This function is usefully wrapped around functions that return file + descriptors, e.g., fd_safer (open ("file", O_RDONLY)). */ + +int +fd_safer (int fd) +{ + if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) + { + int f = dup_safer (fd); + int e = errno; + close (fd); + errno = e; + fd = f; + } + + return fd; +} diff --git a/contrib/grep/lib/fdopendir.c b/contrib/grep/lib/fdopendir.c new file mode 100644 index 0000000000..4ae7d05395 --- /dev/null +++ b/contrib/grep/lib/fdopendir.c @@ -0,0 +1,204 @@ +/* provide a replacement fdopendir function + Copyright (C) 2004-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +#include + +#include + +#include +#include + +#if !HAVE_FDOPENDIR + +# include "openat.h" +# include "openat-priv.h" +# include "save-cwd.h" + +# if GNULIB_DIRENT_SAFER +# include "dirent--.h" +# endif + +# ifndef REPLACE_FCHDIR +# define REPLACE_FCHDIR 0 +# endif + +static DIR *fdopendir_with_dup (int, int, struct saved_cwd const *); +static DIR *fd_clone_opendir (int, struct saved_cwd const *); + +/* Replacement for POSIX fdopendir. + + First, try to simulate it via opendir ("/proc/self/fd/..."). Failing + that, simulate it by using fchdir metadata, or by doing + save_cwd/fchdir/opendir(".")/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. + + If successful, the resulting stream is based on FD in + implementations where streams are based on file descriptors and in + applications where no other thread or signal handler allocates or + frees file descriptors. In other cases, consult dirfd on the result + to find out whether FD is still being used. + + Otherwise, this function works just like POSIX fdopendir. + + W A R N I N G: + + Unlike other fd-related functions, this one places constraints on FD. + If this function returns successfully, FD is under control of the + dirent.h system, and the caller should not close or modify the state of + FD other than by the dirent.h functions. */ +DIR * +fdopendir (int fd) +{ + DIR *dir = fdopendir_with_dup (fd, -1, NULL); + + if (! REPLACE_FCHDIR && ! dir) + { + int saved_errno = errno; + if (EXPECTED_ERRNO (saved_errno)) + { + struct saved_cwd cwd; + if (save_cwd (&cwd) != 0) + openat_save_fail (errno); + dir = fdopendir_with_dup (fd, -1, &cwd); + saved_errno = errno; + free_cwd (&cwd); + errno = saved_errno; + } + } + + return dir; +} + +/* Like fdopendir, except that if OLDER_DUPFD is not -1, it is known + to be a dup of FD which is less than FD - 1 and which will be + closed by the caller and not otherwise used by the caller. This + function makes sure that FD is closed and all file descriptors less + than FD are open, and then calls fd_clone_opendir on a dup of FD. + That way, barring race conditions, fd_clone_opendir returns a + stream whose file descriptor is FD. + + If REPLACE_CHDIR or CWD is null, use opendir ("/proc/self/fd/...", + falling back on fchdir metadata. Otherwise, CWD is a saved version + of the working directory; use fchdir/opendir(".")/restore_cwd(CWD). */ +static DIR * +fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd) +{ + int dupfd = dup (fd); + if (dupfd < 0 && errno == EMFILE) + dupfd = older_dupfd; + if (dupfd < 0) + return NULL; + else + { + DIR *dir; + int saved_errno; + if (dupfd < fd - 1 && dupfd != older_dupfd) + { + dir = fdopendir_with_dup (fd, dupfd, cwd); + saved_errno = errno; + } + else + { + close (fd); + dir = fd_clone_opendir (dupfd, cwd); + saved_errno = errno; + if (! dir) + { + int fd1 = dup (dupfd); + if (fd1 != fd) + openat_save_fail (fd1 < 0 ? errno : EBADF); + } + } + + if (dupfd != older_dupfd) + close (dupfd); + errno = saved_errno; + return dir; + } +} + +/* Like fdopendir, except the result controls a clone of FD. It is + the caller's responsibility both to close FD and (if the result is + not null) to closedir the result. */ +static DIR * +fd_clone_opendir (int fd, struct saved_cwd const *cwd) +{ + if (REPLACE_FCHDIR || ! cwd) + { + DIR *dir = NULL; + int saved_errno = EOPNOTSUPP; + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, "."); + if (proc_file) + { + dir = opendir (proc_file); + saved_errno = errno; + if (proc_file != buf) + free (proc_file); + } +# if REPLACE_FCHDIR + if (! dir && EXPECTED_ERRNO (saved_errno)) + { + char const *name = _gl_directory_name (fd); + return (name ? opendir (name) : NULL); + } +# endif + errno = saved_errno; + return dir; + } + else + { + if (fchdir (fd) != 0) + return NULL; + else + { + DIR *dir = opendir ("."); + int saved_errno = errno; + if (restore_cwd (cwd) != 0) + openat_restore_fail (errno); + errno = saved_errno; + return dir; + } + } +} + +#else /* HAVE_FDOPENDIR */ + +# include +# include + +# undef fdopendir + +/* Like fdopendir, but work around GNU/Hurd bug by validating FD. */ + +DIR * +rpl_fdopendir (int fd) +{ + struct stat st; + if (fstat (fd, &st)) + return NULL; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return NULL; + } + return fdopendir (fd); +} + +#endif /* HAVE_FDOPENDIR */ diff --git a/contrib/grep/lib/filename.h b/contrib/grep/lib/filename.h new file mode 100644 index 0000000000..7b89d0d06b --- /dev/null +++ b/contrib/grep/lib/filename.h @@ -0,0 +1,54 @@ +/* Basic filename support macros. + Copyright (C) 2001-2004, 2007-2012 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 of the License, 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 . */ + +#ifndef _FILENAME_H +#define _FILENAME_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, + it may be concatenated to a directory pathname. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +# define FILE_SYSTEM_PREFIX_LEN(P) 0 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _FILENAME_H */ diff --git a/contrib/grep/lib/filenamecat-lgpl.c b/contrib/grep/lib/filenamecat-lgpl.c new file mode 100644 index 0000000000..c7c46172a3 --- /dev/null +++ b/contrib/grep/lib/filenamecat-lgpl.c @@ -0,0 +1,88 @@ +/* Concatenate two arbitrary file names. + + Copyright (C) 1996-2007, 2009-2012 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 of the License, 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 . */ + +/* Written by Jim Meyering. */ + +#include + +/* Specification. */ +#include "filenamecat.h" + +#include +#include + +#include "dirname.h" + +#if ! HAVE_MEMPCPY && ! defined mempcpy +# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +#endif + +/* Return the longest suffix of F that is a relative file name. + If it has no such suffix, return the empty string. */ + +static char const * _GL_ATTRIBUTE_PURE +longest_relative_suffix (char const *f) +{ + for (f += FILE_SYSTEM_PREFIX_LEN (f); ISSLASH (*f); f++) + continue; + return f; +} + +/* Concatenate two file name components, DIR and ABASE, in + newly-allocated storage and return the result. + The resulting file name F is such that the commands "ls F" and "(cd + DIR; ls BASE)" refer to the same file, where BASE is ABASE with any + file system prefixes and leading separators removed. + Arrange for a directory separator if necessary between DIR and BASE + in the result, removing any redundant separators. + In any case, if BASE_IN_RESULT is non-NULL, set + *BASE_IN_RESULT to point to the copy of ABASE in the returned + concatenation. However, if ABASE begins with more than one slash, + set *BASE_IN_RESULT to point to the sole corresponding slash that + is copied into the result buffer. + + Return NULL if malloc fails. */ + +char * +mfile_name_concat (char const *dir, char const *abase, char **base_in_result) +{ + char const *dirbase = last_component (dir); + size_t dirbaselen = base_len (dirbase); + size_t dirlen = dirbase - dir + dirbaselen; + size_t needs_separator = (dirbaselen && ! ISSLASH (dirbase[dirbaselen - 1])); + + char const *base = longest_relative_suffix (abase); + size_t baselen = strlen (base); + + char *p_concat = malloc (dirlen + needs_separator + baselen + 1); + char *p; + + if (p_concat == NULL) + return NULL; + + p = mempcpy (p_concat, dir, dirlen); + *p = DIRECTORY_SEPARATOR; + p += needs_separator; + + if (base_in_result) + *base_in_result = p - IS_ABSOLUTE_FILE_NAME (abase); + + p = mempcpy (p, base, baselen); + *p = '\0'; + + return p_concat; +} diff --git a/contrib/grep/lib/closeout.h b/contrib/grep/lib/filenamecat.h similarity index 64% copy from contrib/grep/lib/closeout.h copy to contrib/grep/lib/filenamecat.h index ec8d7a6d2c..e7b2e3063a 100644 --- a/contrib/grep/lib/closeout.h +++ b/contrib/grep/lib/filenamecat.h @@ -1,6 +1,6 @@ -/* Close standard output and standard error. +/* Concatenate two arbitrary file names. - Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2011 Free Software + Copyright (C) 1996-1997, 2003, 2005, 2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -16,21 +16,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef CLOSEOUT_H -# define CLOSEOUT_H 1 - -# include - -# ifdef __cplusplus -extern "C" { -# endif - -void close_stdout_set_file_name (const char *file); -void close_stdout_set_ignore_EPIPE (bool ignore); -void close_stdout (void); - -# ifdef __cplusplus -} -# endif +/* Written by Jim Meyering. */ +#if GNULIB_FILENAMECAT +char *file_name_concat (char const *dir, char const *base, + char **base_in_result); #endif + +char *mfile_name_concat (char const *dir, char const *base, + char **base_in_result); diff --git a/contrib/grep/lib/fnmatch.c b/contrib/grep/lib/fnmatch.c index ecfc8fb0cb..842182bf6a 100644 --- a/contrib/grep/lib/fnmatch.c +++ b/contrib/grep/lib/fnmatch.c @@ -1,6 +1,4 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -/* Copyright (C) 1991-1993, 1996-2007, 2009-2011 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993, 1996-2007, 2009-2012 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 @@ -13,8 +11,7 @@ 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. */ + along with this program; if not, see . */ #ifndef _LIBC # include @@ -44,7 +41,7 @@ (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \ && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY)) -/* For platform which support the ISO C amendement 1 functionality we +/* For platform which support the ISO C amendment 1 functionality we support user defined character classes. */ #if defined _LIBC || WIDE_CHAR_SUPPORT # include @@ -80,7 +77,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, + program understand 'configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU @@ -94,7 +91,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); # if defined _LIBC || WIDE_CHAR_SUPPORT /* The GNU C library provides support for user-defined character classes - and the functions from ISO C amendement 1. */ + and the functions from ISO C amendment 1. */ # ifdef CHARCLASS_NAME_MAX # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX # else @@ -121,7 +118,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); # endif # else -# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, 'xdigit'. */ # define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ @@ -170,7 +167,6 @@ static int posixly_correct; # endif # endif # define MEMCHR(S, C, N) memchr (S, C, N) -# define STRCOLL(S1, S2) strcoll (S1, S2) # include "fnmatch_loop.c" @@ -198,7 +194,6 @@ static int posixly_correct; # endif # endif # define MEMCHR(S, C, N) wmemchr (S, C, N) -# define STRCOLL(S1, S2) wcscoll (S1, S2) # define WIDE_CHAR_VERSION 1 # undef IS_CHAR_CLASS diff --git a/contrib/grep/lib/fnmatch_loop.c b/contrib/grep/lib/fnmatch_loop.c index 06e7d8b6ea..048079e11f 100644 --- a/contrib/grep/lib/fnmatch_loop.c +++ b/contrib/grep/lib/fnmatch_loop.c @@ -1,6 +1,4 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -/* Copyright (C) 1991-1993, 1996-2006, 2009-2011 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993, 1996-2006, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify @@ -14,8 +12,7 @@ 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. */ + along with this program; if not, see . */ /* Match STRING against the file name pattern PATTERN, returning zero if it matches, nonzero if not. */ @@ -218,7 +215,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, return FNM_NOMATCH; if (*n == L_('/') && (flags & FNM_FILE_NAME)) - /* `/' cannot be matched. */ + /* '/' cannot be matched. */ return FNM_NOMATCH; not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^'))); @@ -384,7 +381,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, { /* We found a table entry. Now see whether the character we are currently at has the same - equivalance class value. */ + equivalence class value. */ int len = weights[idx & 0xffffff]; int32_t idx2; const UCHAR *np = (const UCHAR *) n; @@ -638,7 +635,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, UCHAR cend = *p++; # ifdef WIDE_CHAR_VERSION - /* Search in the `names' array for the characters. */ + /* Search in the 'names' array for the characters. */ fcollseq = __collseq_table_lookup (collseq, fn); if (fcollseq == ~((uint32_t) 0)) /* XXX We don't know anything about the character @@ -841,7 +838,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, #else /* We use a boring value comparison of the character values. This is better than comparing using - `strcoll' since the latter would have surprising + 'strcoll' since the latter would have surprising and sometimes fatal consequences. */ UCHAR cend = *p++; @@ -1158,7 +1155,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, case L_('@'): do - /* I cannot believe it but `strcat' is actually acceptable + /* I cannot believe it but 'strcat' is actually acceptable here. Match the entire string with the prefix from the pattern list and the rest of the pattern following the pattern list. */ @@ -1216,7 +1213,6 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, #undef END #undef MEMPCPY #undef MEMCHR -#undef STRCOLL #undef STRLEN #undef STRCAT #undef L_ diff --git a/contrib/grep/lib/fpending.c b/contrib/grep/lib/fpending.c index 5ec38cb27e..2591d53437 100644 --- a/contrib/grep/lib/fpending.c +++ b/contrib/grep/lib/fpending.c @@ -1,5 +1,5 @@ /* fpending.c -- return the number of pending output bytes on a stream - Copyright (C) 2000, 2004, 2006-2007, 2009-2011 Free Software Foundation, + Copyright (C) 2000, 2004, 2006-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/fpending.h b/contrib/grep/lib/fpending.h index d7994f7f4e..5b5d71c024 100644 --- a/contrib/grep/lib/fpending.h +++ b/contrib/grep/lib/fpending.h @@ -1,6 +1,6 @@ /* Declare __fpending. - Copyright (C) 2000, 2003, 2005-2006, 2009-2011 Free Software Foundation, + Copyright (C) 2000, 2003, 2005-2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/fstat.c b/contrib/grep/lib/fstat.c new file mode 100644 index 0000000000..ac2b1effe3 --- /dev/null +++ b/contrib/grep/lib/fstat.c @@ -0,0 +1,86 @@ +/* fstat() replacement. + Copyright (C) 2011-2012 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 of the License, 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 . */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_fstat doesn't recurse to + rpl_fstat. */ +#define __need_system_sys_stat_h +#include + +/* Get the original definition of fstat. It might be defined as a macro. */ +#include +#include +#if _GL_WINDOWS_64_BIT_ST_SIZE +# define stat _stati64 +# define fstat _fstati64 +#endif +#undef __need_system_sys_stat_h + +static inline int +orig_fstat (int fd, struct stat *buf) +{ + return fstat (fd, buf); +} + +/* Specification. */ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +#include "sys/stat.h" + +#include +#include + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +#endif + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static inline int +fstat_nothrow (int fd, struct stat *buf) +{ + int result; + + TRY_MSVC_INVAL + { + result = orig_fstat (fd, buf); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +#else +# define fstat_nothrow orig_fstat +#endif + +int +rpl_fstat (int fd, struct stat *buf) +{ +#if REPLACE_FCHDIR && REPLACE_OPEN_DIRECTORY + /* Handle the case when rpl_open() used a dummy file descriptor to work + around an open() that can't normally visit directories. */ + const char *name = _gl_directory_name (fd); + if (name != NULL) + return stat (name, buf); +#endif + + return fstat_nothrow (fd, buf); +} diff --git a/contrib/grep/lib/fstatat.c b/contrib/grep/lib/fstatat.c new file mode 100644 index 0000000000..9b701c4d61 --- /dev/null +++ b/contrib/grep/lib/fstatat.c @@ -0,0 +1,135 @@ +/* Work around an fstatat bug on Solaris 9. + + Copyright (C) 2006, 2009-2012 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 of the License, 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 . */ + +/* Written by Paul Eggert and Jim Meyering. */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_fstatat doesn't recurse to + rpl_fstatat. */ +#define __need_system_sys_stat_h +#include + +/* Get the original definition of fstatat. It might be defined as a macro. */ +#include +#include +#undef __need_system_sys_stat_h + +#if HAVE_FSTATAT +static inline int +orig_fstatat (int fd, char const *filename, struct stat *buf, int flags) +{ + return fstatat (fd, filename, buf, flags); +} +#endif + +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +#include "sys/stat.h" + +#include +#include +#include + +#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG + +# ifndef LSTAT_FOLLOWS_SLASHED_SYMLINK +# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0 +# endif + +/* fstatat should always follow symbolic links that end in /, but on + Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. + Likewise, trailing slash on a non-directory should be an error. + These are the same problems that lstat.c and stat.c address, so + solve it in a similar way. + + AIX 7.1 fstatat (AT_FDCWD, ..., 0) always fails, which is a bug. + Work around this bug if FSTATAT_AT_FDCWD_0_BROKEN is nonzero. */ + +int +rpl_fstatat (int fd, char const *file, struct stat *st, int flag) +{ + int result = orig_fstatat (fd, file, st, flag); + size_t len; + + if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0) + return result; + len = strlen (file); + if (flag & AT_SYMLINK_NOFOLLOW) + { + /* Fix lstat behavior. */ + if (file[len - 1] != '/' || S_ISDIR (st->st_mode)) + return 0; + if (!S_ISLNK (st->st_mode)) + { + errno = ENOTDIR; + return -1; + } + result = orig_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW); + } + /* Fix stat behavior. */ + if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/') + { + errno = ENOTDIR; + return -1; + } + return result; +} + +#else /* ! (HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG) */ + +/* On mingw, the gnulib defines 'stat' as a function-like + macro; but using it in AT_FUNC_F2 causes compilation failure + because the preprocessor sees a use of a macro that requires two + arguments but is only given one. Hence, we need an inline + forwarder to get past the preprocessor. */ +static inline int +stat_func (char const *name, struct stat *st) +{ + return stat (name, st); +} + +/* Likewise, if there is no native 'lstat', then the gnulib + defined it as stat, which also needs adjustment. */ +# if !HAVE_LSTAT +# undef lstat +# define lstat stat_func +# endif + +/* Replacement for Solaris' function by the same name. + + First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE"). + Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. + Otherwise, this function works just like Solaris' fstatat. */ + +# define AT_FUNC_NAME fstatat +# define AT_FUNC_F1 lstat +# define AT_FUNC_F2 stat_func +# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW +# define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag +# define AT_FUNC_POST_FILE_ARGS , st +# include "at-func.c" +# undef AT_FUNC_NAME +# undef AT_FUNC_F1 +# undef AT_FUNC_F2 +# undef AT_FUNC_USE_F1_COND +# undef AT_FUNC_POST_FILE_PARAM_DECLS +# undef AT_FUNC_POST_FILE_ARGS + +#endif /* !HAVE_FSTATAT */ diff --git a/contrib/grep/lib/fts-cycle.c b/contrib/grep/lib/fts-cycle.c new file mode 100644 index 0000000000..bdb090faca --- /dev/null +++ b/contrib/grep/lib/fts-cycle.c @@ -0,0 +1,160 @@ +/* Detect cycles in file tree walks. + + Copyright (C) 2003-2006, 2009-2012 Free Software Foundation, Inc. + + Written by Jim Meyering. + + 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 of the License, 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 . */ + +#include "cycle-check.h" +#include "hash.h" + +/* Use each of these to map a device/inode pair to an FTSENT. */ +struct Active_dir +{ + dev_t dev; + ino_t ino; + FTSENT *fts_ent; +}; + +static bool +AD_compare (void const *x, void const *y) +{ + struct Active_dir const *ax = x; + struct Active_dir const *ay = y; + return ax->ino == ay->ino + && ax->dev == ay->dev; +} + +static size_t +AD_hash (void const *x, size_t table_size) +{ + struct Active_dir const *ax = x; + return (uintmax_t) ax->ino % table_size; +} + +/* Set up the cycle-detection machinery. */ + +static bool +setup_dir (FTS *fts) +{ + if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL)) + { + enum { HT_INITIAL_SIZE = 31 }; + fts->fts_cycle.ht = hash_initialize (HT_INITIAL_SIZE, NULL, AD_hash, + AD_compare, free); + if (! fts->fts_cycle.ht) + return false; + } + else + { + fts->fts_cycle.state = malloc (sizeof *fts->fts_cycle.state); + if (! fts->fts_cycle.state) + return false; + cycle_check_init (fts->fts_cycle.state); + } + + return true; +} + +/* Enter a directory during a file tree walk. */ + +static bool +enter_dir (FTS *fts, FTSENT *ent) +{ + if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL)) + { + struct stat const *st = ent->fts_statp; + struct Active_dir *ad = malloc (sizeof *ad); + struct Active_dir *ad_from_table; + + if (!ad) + return false; + + ad->dev = st->st_dev; + ad->ino = st->st_ino; + ad->fts_ent = ent; + + /* See if we've already encountered this directory. + This can happen when following symlinks as well as + with a corrupted directory hierarchy. */ + ad_from_table = hash_insert (fts->fts_cycle.ht, ad); + + if (ad_from_table != ad) + { + free (ad); + if (!ad_from_table) + return false; + + /* There was an entry with matching dev/inode already in the table. + Record the fact that we've found a cycle. */ + ent->fts_cycle = ad_from_table->fts_ent; + ent->fts_info = FTS_DC; + } + } + else + { + if (cycle_check (fts->fts_cycle.state, ent->fts_statp)) + { + /* FIXME: setting fts_cycle like this isn't proper. + To do what the documentation requires, we'd have to + go around the cycle again and find the right entry. + But no callers in coreutils use the fts_cycle member. */ + ent->fts_cycle = ent; + ent->fts_info = FTS_DC; + } + } + + return true; +} + +/* Leave a directory during a file tree walk. */ + +static void +leave_dir (FTS *fts, FTSENT *ent) +{ + struct stat const *st = ent->fts_statp; + if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL)) + { + struct Active_dir obj; + void *found; + obj.dev = st->st_dev; + obj.ino = st->st_ino; + found = hash_delete (fts->fts_cycle.ht, &obj); + if (!found) + abort (); + free (found); + } + else + { + FTSENT *parent = ent->fts_parent; + if (parent != NULL && 0 <= parent->fts_level) + CYCLE_CHECK_REFLECT_CHDIR_UP (fts->fts_cycle.state, + *(parent->fts_statp), *st); + } +} + +/* Free any memory used for cycle detection. */ + +static void +free_dir (FTS *sp) +{ + if (sp->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL)) + { + if (sp->fts_cycle.ht) + hash_free (sp->fts_cycle.ht); + } + else + free (sp->fts_cycle.state); +} diff --git a/contrib/grep/lib/fts.c b/contrib/grep/lib/fts.c new file mode 100644 index 0000000000..42c8067708 --- /dev/null +++ b/contrib/grep/lib/fts.c @@ -0,0 +1,2095 @@ +/* Traverse a file hierarchy. + + Copyright (C) 2004-2012 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 of the License, 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 . */ + +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; +#endif /* LIBC_SCCS and not lint */ + +#include "fts_.h" + +#if HAVE_SYS_PARAM_H || defined _LIBC +# include +#endif +#ifdef _LIBC +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include + +#if ! _LIBC +# include "fcntl--.h" +# include "dirent--.h" +# include "unistd--.h" +/* FIXME - use fcntl(F_DUPFD_CLOEXEC)/openat(O_CLOEXEC) once they are + supported. */ +# include "cloexec.h" +# include "openat.h" +# include "same-inode.h" +#endif + +#include +#ifndef _D_EXACT_NAMLEN +# define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name) +#endif + +#if HAVE_STRUCT_DIRENT_D_TYPE +/* True if the type of the directory entry D is known. */ +# define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN) +/* True if the type of the directory entry D must be T. */ +# define DT_MUST_BE(d, t) ((d)->d_type == (t)) +# define D_TYPE(d) ((d)->d_type) +#else +# define DT_IS_KNOWN(d) false +# define DT_MUST_BE(d, t) false +# define D_TYPE(d) DT_UNKNOWN + +# undef DT_UNKNOWN +# define DT_UNKNOWN 0 + +/* Any nonzero values will do here, so long as they're distinct. + Undef any existing macros out of the way. */ +# undef DT_BLK +# undef DT_CHR +# undef DT_DIR +# undef DT_FIFO +# undef DT_LNK +# undef DT_REG +# undef DT_SOCK +# define DT_BLK 1 +# define DT_CHR 2 +# define DT_DIR 3 +# define DT_FIFO 4 +# define DT_LNK 5 +# define DT_REG 6 +# define DT_SOCK 7 +#endif + +#ifndef S_IFLNK +# define S_IFLNK 0 +#endif +#ifndef S_IFSOCK +# define S_IFSOCK 0 +#endif + +enum +{ + NOT_AN_INODE_NUMBER = 0 +}; + +#ifdef D_INO_IN_DIRENT +# define D_INO(dp) (dp)->d_ino +#else +/* Some systems don't have inodes, so fake them to avoid lots of ifdefs. */ +# define D_INO(dp) NOT_AN_INODE_NUMBER +#endif + +/* If possible (see max_entries, below), read no more than this many directory + entries at a time. Without this limit (i.e., when using non-NULL + fts_compar), processing a directory with 4,000,000 entries requires ~1GiB + of memory, and handling 64M entries would require 16GiB of memory. */ +#ifndef FTS_MAX_READDIR_ENTRIES +# define FTS_MAX_READDIR_ENTRIES 100000 +#endif + +/* If there are more than this many entries in a directory, + and the conditions mentioned below are satisfied, then sort + the entries on inode number before any further processing. */ +#ifndef FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD +# define FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD 10000 +#endif + +enum +{ + _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD = FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD +}; + +enum Fts_stat +{ + FTS_NO_STAT_REQUIRED = 1, + FTS_STAT_REQUIRED = 2 +}; + +#ifdef _LIBC +# undef close +# define close __close +# undef closedir +# define closedir __closedir +# undef fchdir +# define fchdir __fchdir +# undef open +# define open __open +# undef readdir +# define readdir __readdir +#else +# undef internal_function +# define internal_function /* empty */ +#endif + +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +/* If this host provides the openat function, then we can avoid + attempting to open "." in some initialization code below. */ +#ifdef HAVE_OPENAT +# define HAVE_OPENAT_SUPPORT 1 +#else +# define HAVE_OPENAT_SUPPORT 0 +#endif + +#ifdef NDEBUG +# define fts_assert(expr) ((void) 0) +#else +# define fts_assert(expr) \ + do \ + { \ + if (!(expr)) \ + abort (); \ + } \ + while (false) +#endif + +static FTSENT *fts_alloc (FTS *, const char *, size_t) internal_function; +static FTSENT *fts_build (FTS *, int) internal_function; +static void fts_lfree (FTSENT *) internal_function; +static void fts_load (FTS *, FTSENT *) internal_function; +static size_t fts_maxarglen (char * const *) internal_function; +static void fts_padjust (FTS *, FTSENT *) internal_function; +static bool fts_palloc (FTS *, size_t) internal_function; +static FTSENT *fts_sort (FTS *, FTSENT *, size_t) internal_function; +static unsigned short int fts_stat (FTS *, FTSENT *, bool) internal_function; +static int fts_safe_changedir (FTS *, FTSENT *, int, const char *) + internal_function; + +#include "fts-cycle.c" + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) +#define STREQ(a, b) (strcmp (a, b) == 0) + +#define CLR(opt) (sp->fts_options &= ~(opt)) +#define ISSET(opt) (sp->fts_options & (opt)) +#define SET(opt) (sp->fts_options |= (opt)) + +/* FIXME: FTS_NOCHDIR is now misnamed. + Call it FTS_USE_FULL_RELATIVE_FILE_NAMES instead. */ +#define FCHDIR(sp, fd) \ + (!ISSET(FTS_NOCHDIR) && (ISSET(FTS_CWDFD) \ + ? (cwd_advance_fd ((sp), (fd), true), 0) \ + : fchdir (fd))) + + +/* fts_build flags */ +/* FIXME: make this an enum */ +#define BCHILD 1 /* fts_children */ +#define BNAMES 2 /* fts_children, names only */ +#define BREAD 3 /* fts_read */ + +#if FTS_DEBUG +# include +# include +# include +# include "getcwdat.h" +bool fts_debug = false; +# define Dprintf(x) do { if (fts_debug) printf x; } while (false) +#else +# define Dprintf(x) +# define fd_ring_check(x) +# define fd_ring_print(a, b, c) +#endif + +#define LEAVE_DIR(Fts, Ent, Tag) \ + do \ + { \ + Dprintf ((" %s-leaving: %s\n", Tag, (Ent)->fts_path)); \ + leave_dir (Fts, Ent); \ + fd_ring_check (Fts); \ + } \ + while (false) + +static void +fd_ring_clear (I_ring *fd_ring) +{ + while ( ! i_ring_empty (fd_ring)) + { + int fd = i_ring_pop (fd_ring); + if (0 <= fd) + close (fd); + } +} + +/* Overload the fts_statp->st_size member (otherwise unused, when + fts_info is FTS_NSOK) to indicate whether fts_read should stat + this entry or not. */ +static void +fts_set_stat_required (FTSENT *p, bool required) +{ + fts_assert (p->fts_info == FTS_NSOK); + p->fts_statp->st_size = (required + ? FTS_STAT_REQUIRED + : FTS_NO_STAT_REQUIRED); +} + +/* file-descriptor-relative opendir. */ +/* FIXME: if others need this function, move it into lib/openat.c */ +static inline DIR * +internal_function +opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd) +{ + int new_fd = openat (fd, dir, + (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK + | extra_flags)); + DIR *dirp; + + if (new_fd < 0) + return NULL; + set_cloexec_flag (new_fd, true); + dirp = fdopendir (new_fd); + if (dirp) + *pdir_fd = new_fd; + else + { + int saved_errno = errno; + close (new_fd); + errno = saved_errno; + } + return dirp; +} + +/* Virtual fchdir. Advance SP's working directory file descriptor, + SP->fts_cwd_fd, to FD, and push the previous value onto the fd_ring. + CHDIR_DOWN_ONE is true if FD corresponds to an entry in the directory + open on sp->fts_cwd_fd; i.e., to move the working directory one level + down. */ +static void +internal_function +cwd_advance_fd (FTS *sp, int fd, bool chdir_down_one) +{ + int old = sp->fts_cwd_fd; + fts_assert (old != fd || old == AT_FDCWD); + + if (chdir_down_one) + { + /* Push "old" onto the ring. + If the displaced file descriptor is non-negative, close it. */ + int prev_fd_in_slot = i_ring_push (&sp->fts_fd_ring, old); + fd_ring_print (sp, stderr, "post-push"); + if (0 <= prev_fd_in_slot) + close (prev_fd_in_slot); /* ignore any close failure */ + } + else if ( ! ISSET (FTS_NOCHDIR)) + { + if (0 <= old) + close (old); /* ignore any close failure */ + } + + sp->fts_cwd_fd = fd; +} + +/* Restore the initial, pre-traversal, "working directory". + In FTS_CWDFD mode, we merely call cwd_advance_fd, otherwise, + we may actually change the working directory. + Return 0 upon success. Upon failure, set errno and return nonzero. */ +static int +restore_initial_cwd (FTS *sp) +{ + int fail = FCHDIR (sp, ISSET (FTS_CWDFD) ? AT_FDCWD : sp->fts_rfd); + fd_ring_clear (&(sp->fts_fd_ring)); + return fail; +} + +/* Open the directory DIR if possible, and return a file + descriptor. Return -1 and set errno on failure. It doesn't matter + whether the file descriptor has read or write access. */ + +static inline int +internal_function +diropen (FTS const *sp, char const *dir) +{ + int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK + | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0) + | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)); + + int fd = (ISSET (FTS_CWDFD) + ? openat (sp->fts_cwd_fd, dir, open_flags) + : open (dir, open_flags)); + if (0 <= fd) + set_cloexec_flag (fd, true); + return fd; +} + +FTS * +fts_open (char * const *argv, + register int options, + int (*compar) (FTSENT const **, FTSENT const **)) +{ + register FTS *sp; + register FTSENT *p, *root; + register size_t nitems; + FTSENT *parent = NULL; + FTSENT *tmp = NULL; /* pacify gcc */ + bool defer_stat; + + /* Options check. */ + if (options & ~FTS_OPTIONMASK) { + __set_errno (EINVAL); + return (NULL); + } + if ((options & FTS_NOCHDIR) && (options & FTS_CWDFD)) { + __set_errno (EINVAL); + return (NULL); + } + if ( ! (options & (FTS_LOGICAL | FTS_PHYSICAL))) { + __set_errno (EINVAL); + return (NULL); + } + + /* Allocate/initialize the stream */ + if ((sp = malloc(sizeof(FTS))) == NULL) + return (NULL); + memset(sp, 0, sizeof(FTS)); + sp->fts_compar = compar; + sp->fts_options = options; + + /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ + if (ISSET(FTS_LOGICAL)) { + SET(FTS_NOCHDIR); + CLR(FTS_CWDFD); + } + + /* Initialize fts_cwd_fd. */ + sp->fts_cwd_fd = AT_FDCWD; + if ( ISSET(FTS_CWDFD) && ! HAVE_OPENAT_SUPPORT) + { + /* While it isn't technically necessary to open "." this + early, doing it here saves us the trouble of ensuring + later (where it'd be messier) that "." can in fact + be opened. If not, revert to FTS_NOCHDIR mode. */ + int fd = open (".", + O_SEARCH | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)); + if (fd < 0) + { + /* Even if "." is unreadable, don't revert to FTS_NOCHDIR mode + on systems like Linux+PROC_FS, where our openat emulation + is good enough. Note: on a system that emulates + openat via /proc, this technique can still fail, but + only in extreme conditions, e.g., when the working + directory cannot be saved (i.e. save_cwd fails) -- + and that happens on Linux only when "." is unreadable + and the CWD would be longer than PATH_MAX. + FIXME: once Linux kernel openat support is well established, + replace the above open call and this entire if/else block + with the body of the if-block below. */ + if ( openat_needs_fchdir ()) + { + SET(FTS_NOCHDIR); + CLR(FTS_CWDFD); + } + } + else + { + close (fd); + } + } + + /* + * Start out with 1K of file name space, and enough, in any case, + * to hold the user's file names. + */ +#ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +#endif + { + size_t maxarglen = fts_maxarglen(argv); + if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) + goto mem1; + } + + /* Allocate/initialize root's parent. */ + if (*argv != NULL) { + if ((parent = fts_alloc(sp, "", 0)) == NULL) + goto mem2; + parent->fts_level = FTS_ROOTPARENTLEVEL; + } + + /* The classic fts implementation would call fts_stat with + a new entry for each iteration of the loop below. + If the comparison function is not specified or if the + FTS_DEFER_STAT option is in effect, don't stat any entry + in this loop. This is an attempt to minimize the interval + between the initial stat/lstat/fstatat and the point at which + a directory argument is first opened. This matters for any + directory command line argument that resides on a file system + without genuine i-nodes. If you specify FTS_DEFER_STAT along + with a comparison function, that function must not access any + data via the fts_statp pointer. */ + defer_stat = (compar == NULL || ISSET(FTS_DEFER_STAT)); + + /* Allocate/initialize root(s). */ + for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { + /* *Do* allow zero-length file names. */ + size_t len = strlen(*argv); + if ((p = fts_alloc(sp, *argv, len)) == NULL) + goto mem3; + p->fts_level = FTS_ROOTLEVEL; + p->fts_parent = parent; + p->fts_accpath = p->fts_name; + /* Even when defer_stat is true, be sure to stat the first + command line argument, since fts_read (at least with + FTS_XDEV) requires that. */ + if (defer_stat && root != NULL) { + p->fts_info = FTS_NSOK; + fts_set_stat_required(p, true); + } else { + p->fts_info = fts_stat(sp, p, false); + } + + /* + * If comparison routine supplied, traverse in sorted + * order; otherwise traverse in the order specified. + */ + if (compar) { + p->fts_link = root; + root = p; + } else { + p->fts_link = NULL; + if (root == NULL) + tmp = root = p; + else { + tmp->fts_link = p; + tmp = p; + } + } + } + if (compar && nitems > 1) + root = fts_sort(sp, root, nitems); + + /* + * Allocate a dummy pointer and make fts_read think that we've just + * finished the node before the root(s); set p->fts_info to FTS_INIT + * so that everything about the "current" node is ignored. + */ + if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) + goto mem3; + sp->fts_cur->fts_link = root; + sp->fts_cur->fts_info = FTS_INIT; + if (! setup_dir (sp)) + goto mem3; + + /* + * If using chdir(2), grab a file descriptor pointing to dot to ensure + * that we can get back here; this could be avoided for some file names, + * but almost certainly not worth the effort. Slashes, symbolic links, + * and ".." are all fairly nasty problems. Note, if we can't get the + * descriptor we run anyway, just more slowly. + */ + if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD) + && (sp->fts_rfd = diropen (sp, ".")) < 0) + SET(FTS_NOCHDIR); + + i_ring_init (&sp->fts_fd_ring, -1); + return (sp); + +mem3: fts_lfree(root); + free(parent); +mem2: free(sp->fts_path); +mem1: free(sp); + return (NULL); +} + +static void +internal_function +fts_load (FTS *sp, register FTSENT *p) +{ + register size_t len; + register char *cp; + + /* + * Load the stream structure for the next traversal. Since we don't + * actually enter the directory until after the preorder visit, set + * the fts_accpath field specially so the chdir gets done to the right + * place and the user can access the first node. From fts_open it's + * known that the file name will fit. + */ + len = p->fts_pathlen = p->fts_namelen; + memmove(sp->fts_path, p->fts_name, len + 1); + if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { + len = strlen(++cp); + memmove(p->fts_name, cp, len + 1); + p->fts_namelen = len; + } + p->fts_accpath = p->fts_path = sp->fts_path; +} + +int +fts_close (FTS *sp) +{ + register FTSENT *freep, *p; + int saved_errno = 0; + + /* + * This still works if we haven't read anything -- the dummy structure + * points to the root list, so we step through to the end of the root + * list which has a valid parent pointer. + */ + if (sp->fts_cur) { + for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { + freep = p; + p = p->fts_link != NULL ? p->fts_link : p->fts_parent; + free(freep); + } + free(p); + } + + /* Free up child linked list, sort array, file name buffer. */ + if (sp->fts_child) + fts_lfree(sp->fts_child); + free(sp->fts_array); + free(sp->fts_path); + + if (ISSET(FTS_CWDFD)) + { + if (0 <= sp->fts_cwd_fd) + if (close (sp->fts_cwd_fd)) + saved_errno = errno; + } + else if (!ISSET(FTS_NOCHDIR)) + { + /* Return to original directory, save errno if necessary. */ + if (fchdir(sp->fts_rfd)) + saved_errno = errno; + + /* If close fails, record errno only if saved_errno is zero, + so that we report the probably-more-meaningful fchdir errno. */ + if (close (sp->fts_rfd)) + if (saved_errno == 0) + saved_errno = errno; + } + + fd_ring_clear (&sp->fts_fd_ring); + + if (sp->fts_leaf_optimization_works_ht) + hash_free (sp->fts_leaf_optimization_works_ht); + + free_dir (sp); + + /* Free up the stream pointer. */ + free(sp); + + /* Set errno and return. */ + if (saved_errno) { + __set_errno (saved_errno); + return (-1); + } + + return (0); +} + +#if defined __linux__ \ + && HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE + +# include + +/* Linux-specific constants from coreutils' src/fs.h */ +# define S_MAGIC_TMPFS 0x1021994 +# define S_MAGIC_NFS 0x6969 +# define S_MAGIC_REISERFS 0x52654973 +# define S_MAGIC_PROC 0x9FA0 + +/* Return false if it is easy to determine the file system type of + the directory on which DIR_FD is open, and sorting dirents on + inode numbers is known not to improve traversal performance with + that type of file system. Otherwise, return true. */ +static bool +dirent_inode_sort_may_be_useful (int dir_fd) +{ + /* Skip the sort only if we can determine efficiently + that skipping it is the right thing to do. + The cost of performing an unnecessary sort is negligible, + while the cost of *not* performing it can be O(N^2) with + a very large constant. */ + struct statfs fs_buf; + + /* If fstatfs fails, assume sorting would be useful. */ + if (fstatfs (dir_fd, &fs_buf) != 0) + return true; + + /* FIXME: what about when f_type is not an integral type? + deal with that if/when it's encountered. */ + switch (fs_buf.f_type) + { + case S_MAGIC_TMPFS: + case S_MAGIC_NFS: + /* On a file system of any of these types, sorting + is unnecessary, and hence wasteful. */ + return false; + + default: + return true; + } +} + +/* Given a file descriptor DIR_FD open on a directory D, + return true if it is valid to apply the leaf-optimization + technique of counting directories in D via stat.st_nlink. */ +static bool +leaf_optimization_applies (int dir_fd) +{ + struct statfs fs_buf; + + /* If fstatfs fails, assume we can't use the optimization. */ + if (fstatfs (dir_fd, &fs_buf) != 0) + return false; + + /* FIXME: do we need to detect AFS mount points? I doubt it, + unless fstatfs can report S_MAGIC_REISERFS for such a directory. */ + + switch (fs_buf.f_type) + { + /* List here the file system types that lack usable dirent.d_type + info, yet for which the optimization does apply. */ + case S_MAGIC_REISERFS: + return true; + + case S_MAGIC_PROC: + /* Explicitly listing this or any other file system type for which + the optimization is not applicable is not necessary, but we leave + it here to document the risk. Per http://bugs.debian.org/143111, + /proc may have bogus stat.st_nlink values. */ + /* fall through */ + default: + return false; + } +} + +#else +static bool +dirent_inode_sort_may_be_useful (int dir_fd _GL_UNUSED) { return true; } +static bool +leaf_optimization_applies (int dir_fd _GL_UNUSED) { return false; } +#endif + +/* link-count-optimization entry: + map a stat.st_dev number to a boolean: leaf_optimization_works */ +struct LCO_ent +{ + dev_t st_dev; + bool opt_ok; +}; + +/* Use a tiny initial size. If a traversal encounters more than + a few devices, the cost of growing/rehashing this table will be + rendered negligible by the number of inodes processed. */ +enum { LCO_HT_INITIAL_SIZE = 13 }; + +static size_t +LCO_hash (void const *x, size_t table_size) +{ + struct LCO_ent const *ax = x; + return (uintmax_t) ax->st_dev % table_size; +} + +static bool +LCO_compare (void const *x, void const *y) +{ + struct LCO_ent const *ax = x; + struct LCO_ent const *ay = y; + return ax->st_dev == ay->st_dev; +} + +/* Ask the same question as leaf_optimization_applies, but query + the cache first (FTS.fts_leaf_optimization_works_ht), and if necessary, + update that cache. */ +static bool +link_count_optimize_ok (FTSENT const *p) +{ + FTS *sp = p->fts_fts; + Hash_table *h = sp->fts_leaf_optimization_works_ht; + struct LCO_ent tmp; + struct LCO_ent *ent; + bool opt_ok; + struct LCO_ent *t2; + + /* If we're not in CWDFD mode, don't bother with this optimization, + since the caller is not serious about performance. */ + if (!ISSET(FTS_CWDFD)) + return false; + + /* map st_dev to the boolean, leaf_optimization_works */ + if (h == NULL) + { + h = sp->fts_leaf_optimization_works_ht + = hash_initialize (LCO_HT_INITIAL_SIZE, NULL, LCO_hash, + LCO_compare, free); + if (h == NULL) + return false; + } + tmp.st_dev = p->fts_statp->st_dev; + ent = hash_lookup (h, &tmp); + if (ent) + return ent->opt_ok; + + /* Look-up failed. Query directly and cache the result. */ + t2 = malloc (sizeof *t2); + if (t2 == NULL) + return false; + + /* Is it ok to perform the optimization in the dir, FTS_CWD_FD? */ + opt_ok = leaf_optimization_applies (sp->fts_cwd_fd); + t2->opt_ok = opt_ok; + t2->st_dev = p->fts_statp->st_dev; + + ent = hash_insert (h, t2); + if (ent == NULL) + { + /* insertion failed */ + free (t2); + return false; + } + fts_assert (ent == t2); + + return opt_ok; +} + +/* + * Special case of "/" at the end of the file name so that slashes aren't + * appended which would cause file names to be written as "....//foo". + */ +#define NAPPEND(p) \ + (p->fts_path[p->fts_pathlen - 1] == '/' \ + ? p->fts_pathlen - 1 : p->fts_pathlen) + +FTSENT * +fts_read (register FTS *sp) +{ + register FTSENT *p, *tmp; + register unsigned short int instr; + register char *t; + + /* If finished or unrecoverable error, return NULL. */ + if (sp->fts_cur == NULL || ISSET(FTS_STOP)) + return (NULL); + + /* Set current node pointer. */ + p = sp->fts_cur; + + /* Save and zero out user instructions. */ + instr = p->fts_instr; + p->fts_instr = FTS_NOINSTR; + + /* Any type of file may be re-visited; re-stat and re-turn. */ + if (instr == FTS_AGAIN) { + p->fts_info = fts_stat(sp, p, false); + return (p); + } + Dprintf (("fts_read: p=%s\n", + p->fts_info == FTS_INIT ? "" : p->fts_path)); + + /* + * Following a symlink -- SLNONE test allows application to see + * SLNONE and recover. If indirecting through a symlink, have + * keep a pointer to current location. If unable to get that + * pointer, follow fails. + */ + if (instr == FTS_FOLLOW && + (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { + p->fts_info = fts_stat(sp, p, true); + if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { + if ((p->fts_symfd = diropen (sp, ".")) < 0) { + p->fts_errno = errno; + p->fts_info = FTS_ERR; + } else + p->fts_flags |= FTS_SYMFOLLOW; + } + goto check_for_dir; + } + + /* Directory in pre-order. */ + if (p->fts_info == FTS_D) { + /* If skipped or crossed mount point, do post-order visit. */ + if (instr == FTS_SKIP || + (ISSET(FTS_XDEV) && p->fts_statp->st_dev != sp->fts_dev)) { + if (p->fts_flags & FTS_SYMFOLLOW) + (void)close(p->fts_symfd); + if (sp->fts_child) { + fts_lfree(sp->fts_child); + sp->fts_child = NULL; + } + p->fts_info = FTS_DP; + LEAVE_DIR (sp, p, "1"); + return (p); + } + + /* Rebuild if only read the names and now traversing. */ + if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { + CLR(FTS_NAMEONLY); + fts_lfree(sp->fts_child); + sp->fts_child = NULL; + } + + /* + * Cd to the subdirectory. + * + * If have already read and now fail to chdir, whack the list + * to make the names come out right, and set the parent errno + * so the application will eventually get an error condition. + * Set the FTS_DONTCHDIR flag so that when we logically change + * directories back to the parent we don't do a chdir. + * + * If haven't read do so. If the read fails, fts_build sets + * FTS_STOP or the fts_info field of the node. + */ + if (sp->fts_child != NULL) { + if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { + p->fts_errno = errno; + p->fts_flags |= FTS_DONTCHDIR; + for (p = sp->fts_child; p != NULL; + p = p->fts_link) + p->fts_accpath = + p->fts_parent->fts_accpath; + } + } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { + if (ISSET(FTS_STOP)) + return (NULL); + /* If fts_build's call to fts_safe_changedir failed + because it was not able to fchdir into a + subdirectory, tell the caller. */ + if (p->fts_errno && p->fts_info != FTS_DNR) + p->fts_info = FTS_ERR; + LEAVE_DIR (sp, p, "2"); + return (p); + } + p = sp->fts_child; + sp->fts_child = NULL; + goto name; + } + + /* Move to the next node on this level. */ +next: tmp = p; + + /* If we have so many directory entries that we're reading them + in batches, and we've reached the end of the current batch, + read in a new batch. */ + if (p->fts_link == NULL && p->fts_parent->fts_dirp) + { + p = tmp->fts_parent; + sp->fts_cur = p; + sp->fts_path[p->fts_pathlen] = '\0'; + + if ((p = fts_build (sp, BREAD)) == NULL) + { + if (ISSET(FTS_STOP)) + return NULL; + goto cd_dot_dot; + } + + free(tmp); + goto name; + } + + if ((p = p->fts_link) != NULL) { + sp->fts_cur = p; + free(tmp); + + /* + * If reached the top, return to the original directory (or + * the root of the tree), and load the file names for the next + * root. + */ + if (p->fts_level == FTS_ROOTLEVEL) { + if (restore_initial_cwd(sp)) { + SET(FTS_STOP); + return (NULL); + } + free_dir(sp); + fts_load(sp, p); + setup_dir(sp); + goto check_for_dir; + } + + /* + * User may have called fts_set on the node. If skipped, + * ignore. If followed, get a file descriptor so we can + * get back if necessary. + */ + if (p->fts_instr == FTS_SKIP) + goto next; + if (p->fts_instr == FTS_FOLLOW) { + p->fts_info = fts_stat(sp, p, true); + if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { + if ((p->fts_symfd = diropen (sp, ".")) < 0) { + p->fts_errno = errno; + p->fts_info = FTS_ERR; + } else + p->fts_flags |= FTS_SYMFOLLOW; + } + p->fts_instr = FTS_NOINSTR; + } + +name: t = sp->fts_path + NAPPEND(p->fts_parent); + *t++ = '/'; + memmove(t, p->fts_name, p->fts_namelen + 1); +check_for_dir: + sp->fts_cur = p; + if (p->fts_info == FTS_NSOK) + { + if (p->fts_statp->st_size == FTS_STAT_REQUIRED) + { + FTSENT *parent = p->fts_parent; + if (FTS_ROOTLEVEL < p->fts_level + /* ->fts_n_dirs_remaining is not valid + for command-line-specified names. */ + && parent->fts_n_dirs_remaining == 0 + && ISSET(FTS_NOSTAT) + && ISSET(FTS_PHYSICAL) + && link_count_optimize_ok (parent)) + { + /* nothing more needed */ + } + else + { + p->fts_info = fts_stat(sp, p, false); + if (S_ISDIR(p->fts_statp->st_mode) + && p->fts_level != FTS_ROOTLEVEL + && parent->fts_n_dirs_remaining) + parent->fts_n_dirs_remaining--; + } + } + else + fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED); + } + + if (p->fts_info == FTS_D) + { + /* Now that P->fts_statp is guaranteed to be valid, + if this is a command-line directory, record its + device number, to be used for FTS_XDEV. */ + if (p->fts_level == FTS_ROOTLEVEL) + sp->fts_dev = p->fts_statp->st_dev; + Dprintf ((" entering: %s\n", p->fts_path)); + if (! enter_dir (sp, p)) + { + __set_errno (ENOMEM); + return NULL; + } + } + return p; + } +cd_dot_dot: + + /* Move up to the parent node. */ + p = tmp->fts_parent; + sp->fts_cur = p; + free(tmp); + + if (p->fts_level == FTS_ROOTPARENTLEVEL) { + /* + * Done; free everything up and set errno to 0 so the user + * can distinguish between error and EOF. + */ + free(p); + __set_errno (0); + return (sp->fts_cur = NULL); + } + + fts_assert (p->fts_info != FTS_NSOK); + + /* NUL terminate the file name. */ + sp->fts_path[p->fts_pathlen] = '\0'; + + /* + * Return to the parent directory. If at a root node, restore + * the initial working directory. If we came through a symlink, + * go back through the file descriptor. Otherwise, move up + * one level, via "..". + */ + if (p->fts_level == FTS_ROOTLEVEL) { + if (restore_initial_cwd(sp)) { + p->fts_errno = errno; + SET(FTS_STOP); + } + } else if (p->fts_flags & FTS_SYMFOLLOW) { + if (FCHDIR(sp, p->fts_symfd)) { + int saved_errno = errno; + (void)close(p->fts_symfd); + __set_errno (saved_errno); + p->fts_errno = errno; + SET(FTS_STOP); + } + (void)close(p->fts_symfd); + } else if (!(p->fts_flags & FTS_DONTCHDIR) && + fts_safe_changedir(sp, p->fts_parent, -1, "..")) { + p->fts_errno = errno; + SET(FTS_STOP); + } + p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; + if (p->fts_errno == 0) + LEAVE_DIR (sp, p, "3"); + return ISSET(FTS_STOP) ? NULL : p; +} + +/* + * Fts_set takes the stream as an argument although it's not used in this + * implementation; it would be necessary if anyone wanted to add global + * semantics to fts using fts_set. An error return is allowed for similar + * reasons. + */ +/* ARGSUSED */ +int +fts_set(FTS *sp _GL_UNUSED, FTSENT *p, int instr) +{ + if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && + instr != FTS_NOINSTR && instr != FTS_SKIP) { + __set_errno (EINVAL); + return (1); + } + p->fts_instr = instr; + return (0); +} + +FTSENT * +fts_children (register FTS *sp, int instr) +{ + register FTSENT *p; + int fd; + + if (instr != 0 && instr != FTS_NAMEONLY) { + __set_errno (EINVAL); + return (NULL); + } + + /* Set current node pointer. */ + p = sp->fts_cur; + + /* + * Errno set to 0 so user can distinguish empty directory from + * an error. + */ + __set_errno (0); + + /* Fatal errors stop here. */ + if (ISSET(FTS_STOP)) + return (NULL); + + /* Return logical hierarchy of user's arguments. */ + if (p->fts_info == FTS_INIT) + return (p->fts_link); + + /* + * If not a directory being visited in pre-order, stop here. Could + * allow FTS_DNR, assuming the user has fixed the problem, but the + * same effect is available with FTS_AGAIN. + */ + if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) + return (NULL); + + /* Free up any previous child list. */ + if (sp->fts_child != NULL) + fts_lfree(sp->fts_child); + + if (instr == FTS_NAMEONLY) { + SET(FTS_NAMEONLY); + instr = BNAMES; + } else + instr = BCHILD; + + /* + * If using chdir on a relative file name and called BEFORE fts_read + * does its chdir to the root of a traversal, we can lose -- we need to + * chdir into the subdirectory, and we don't know where the current + * directory is, so we can't get back so that the upcoming chdir by + * fts_read will work. + */ + if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || + ISSET(FTS_NOCHDIR)) + return (sp->fts_child = fts_build(sp, instr)); + + if ((fd = diropen (sp, ".")) < 0) + return (sp->fts_child = NULL); + sp->fts_child = fts_build(sp, instr); + if (ISSET(FTS_CWDFD)) + { + cwd_advance_fd (sp, fd, true); + } + else + { + if (fchdir(fd)) + { + int saved_errno = errno; + close (fd); + __set_errno (saved_errno); + return NULL; + } + close (fd); + } + return (sp->fts_child); +} + +/* A comparison function to sort on increasing inode number. + For some file system types, sorting either way makes a huge + performance difference for a directory with very many entries, + but sorting on increasing values is slightly better than sorting + on decreasing values. The difference is in the 5% range. */ +static int +fts_compare_ino (struct _ftsent const **a, struct _ftsent const **b) +{ + return (a[0]->fts_statp->st_ino < b[0]->fts_statp->st_ino ? -1 + : b[0]->fts_statp->st_ino < a[0]->fts_statp->st_ino ? 1 : 0); +} + +/* Map the dirent.d_type value, DTYPE, to the corresponding stat.st_mode + S_IF* bit and set ST.st_mode, thus clearing all other bits in that field. */ +static void +set_stat_type (struct stat *st, unsigned int dtype) +{ + mode_t type; + switch (dtype) + { + case DT_BLK: + type = S_IFBLK; + break; + case DT_CHR: + type = S_IFCHR; + break; + case DT_DIR: + type = S_IFDIR; + break; + case DT_FIFO: + type = S_IFIFO; + break; + case DT_LNK: + type = S_IFLNK; + break; + case DT_REG: + type = S_IFREG; + break; + case DT_SOCK: + type = S_IFSOCK; + break; + default: + type = 0; + } + st->st_mode = type; +} + +#define closedir_and_clear(dirp) \ + do \ + { \ + closedir (dirp); \ + dirp = NULL; \ + } \ + while (0) + +#define fts_opendir(file, Pdir_fd) \ + opendirat((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \ + ? sp->fts_cwd_fd : AT_FDCWD), \ + file, \ + (((ISSET(FTS_PHYSICAL) \ + && ! (ISSET(FTS_COMFOLLOW) \ + && cur->fts_level == FTS_ROOTLEVEL)) \ + ? O_NOFOLLOW : 0) \ + | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)), \ + Pdir_fd) + +/* + * This is the tricky part -- do not casually change *anything* in here. The + * idea is to build the linked list of entries that are used by fts_children + * and fts_read. There are lots of special cases. + * + * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is + * set and it's a physical walk (so that symbolic links can't be directories), + * we can do things quickly. First, if it's a 4.4BSD file system, the type + * of the file is in the directory entry. Otherwise, we assume that the number + * of subdirectories in a node is equal to the number of links to the parent. + * The former skips all stat calls. The latter skips stat calls in any leaf + * directories and for any files after the subdirectories in the directory have + * been found, cutting the stat calls by about 2/3. + */ +static FTSENT * +internal_function +fts_build (register FTS *sp, int type) +{ + register FTSENT *p, *head; + register size_t nitems; + FTSENT *tail; + void *oldaddr; + int saved_errno; + bool descend; + bool doadjust; + ptrdiff_t level; + nlink_t nlinks; + bool nostat; + size_t len, maxlen, new_len; + char *cp; + int dir_fd; + FTSENT *cur = sp->fts_cur; + bool continue_readdir = !!cur->fts_dirp; + + /* When cur->fts_dirp is non-NULL, that means we should + continue calling readdir on that existing DIR* pointer + rather than opening a new one. */ + if (continue_readdir) + { + DIR *dp = cur->fts_dirp; + dir_fd = dirfd (dp); + if (dir_fd < 0) + { + closedir_and_clear (cur->fts_dirp); + if (type == BREAD) + { + cur->fts_info = FTS_DNR; + cur->fts_errno = errno; + } + return NULL; + } + } + else + { + /* Open the directory for reading. If this fails, we're done. + If being called from fts_read, set the fts_info field. */ + if ((cur->fts_dirp = fts_opendir(cur->fts_accpath, &dir_fd)) == NULL) + { + if (type == BREAD) + { + cur->fts_info = FTS_DNR; + cur->fts_errno = errno; + } + return NULL; + } + /* Rather than calling fts_stat for each and every entry encountered + in the readdir loop (below), stat each directory only right after + opening it. */ + if (cur->fts_info == FTS_NSOK) + cur->fts_info = fts_stat(sp, cur, false); + else if (sp->fts_options & FTS_TIGHT_CYCLE_CHECK) + { + /* Now read the stat info again after opening a directory to + reveal eventual changes caused by a submount triggered by + the traversal. But do it only for utilities which use + FTS_TIGHT_CYCLE_CHECK. Therefore, only find and du + benefit/suffer from this feature for now. */ + LEAVE_DIR (sp, cur, "4"); + fts_stat (sp, cur, false); + if (! enter_dir (sp, cur)) + { + __set_errno (ENOMEM); + return NULL; + } + } + } + + /* Maximum number of readdir entries to read at one time. This + limitation is to avoid reading millions of entries into memory + at once. When an fts_compar function is specified, we have no + choice: we must read all entries into memory before calling that + function. But when no such function is specified, we can read + entries in batches that are large enough to help us with inode- + sorting, yet not so large that we risk exhausting memory. */ + size_t max_entries = (sp->fts_compar == NULL + ? FTS_MAX_READDIR_ENTRIES : SIZE_MAX); + + /* + * Nlinks is the number of possible entries of type directory in the + * directory if we're cheating on stat calls, 0 if we're not doing + * any stat calls at all, (nlink_t) -1 if we're statting everything. + */ + if (type == BNAMES) { + nlinks = 0; + /* Be quiet about nostat, GCC. */ + nostat = false; + } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { + nlinks = (cur->fts_statp->st_nlink + - (ISSET(FTS_SEEDOT) ? 0 : 2)); + nostat = true; + } else { + nlinks = -1; + nostat = false; + } + + /* + * If we're going to need to stat anything or we want to descend + * and stay in the directory, chdir. If this fails we keep going, + * but set a flag so we don't chdir after the post-order visit. + * We won't be able to stat anything, but we can still return the + * names themselves. Note, that since fts_read won't be able to + * chdir into the directory, it will have to return different file + * names than before, i.e. "a/b" instead of "b". Since the node + * has already been visited in pre-order, have to wait until the + * post-order visit to return the error. There is a special case + * here, if there was nothing to stat then it's not an error to + * not be able to stat. This is all fairly nasty. If a program + * needed sorted entries or stat information, they had better be + * checking FTS_NS on the returned nodes. + */ + if (continue_readdir) + { + /* When resuming a short readdir run, we already have + the required dirp and dir_fd. */ + descend = true; + } + else if (nlinks || type == BREAD) { + if (ISSET(FTS_CWDFD)) + { + dir_fd = dup (dir_fd); + if (0 <= dir_fd) + set_cloexec_flag (dir_fd, true); + } + if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) { + if (nlinks && type == BREAD) + cur->fts_errno = errno; + cur->fts_flags |= FTS_DONTCHDIR; + descend = false; + closedir_and_clear(cur->fts_dirp); + if (ISSET(FTS_CWDFD) && 0 <= dir_fd) + close (dir_fd); + cur->fts_dirp = NULL; + } else + descend = true; + } else + descend = false; + + /* + * Figure out the max file name length that can be stored in the + * current buffer -- the inner loop allocates more space as necessary. + * We really wouldn't have to do the maxlen calculations here, we + * could do them in fts_read before returning the name, but it's a + * lot easier here since the length is part of the dirent structure. + * + * If not changing directories set a pointer so that can just append + * each new component into the file name. + */ + len = NAPPEND(cur); + if (ISSET(FTS_NOCHDIR)) { + cp = sp->fts_path + len; + *cp++ = '/'; + } else { + /* GCC, you're too verbose. */ + cp = NULL; + } + len++; + maxlen = sp->fts_pathlen - len; + + level = cur->fts_level + 1; + + /* Read the directory, attaching each entry to the "link" pointer. */ + doadjust = false; + head = NULL; + tail = NULL; + nitems = 0; + while (cur->fts_dirp) { + bool is_dir; + struct dirent *dp = readdir(cur->fts_dirp); + if (dp == NULL) + break; + if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) + continue; + + if ((p = fts_alloc (sp, dp->d_name, + _D_EXACT_NAMLEN (dp))) == NULL) + goto mem1; + if (_D_EXACT_NAMLEN (dp) >= maxlen) { + /* include space for NUL */ + oldaddr = sp->fts_path; + if (! fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) { + /* + * No more memory. Save + * errno, free up the current structure and the + * structures already allocated. + */ +mem1: saved_errno = errno; + free(p); + fts_lfree(head); + closedir_and_clear(cur->fts_dirp); + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + __set_errno (saved_errno); + return (NULL); + } + /* Did realloc() change the pointer? */ + if (oldaddr != sp->fts_path) { + doadjust = true; + if (ISSET(FTS_NOCHDIR)) + cp = sp->fts_path + len; + } + maxlen = sp->fts_pathlen - len; + } + + new_len = len + _D_EXACT_NAMLEN (dp); + if (new_len < len) { + /* + * In the unlikely event that we would end up + * with a file name longer than SIZE_MAX, free up + * the current structure and the structures already + * allocated, then error out with ENAMETOOLONG. + */ + free(p); + fts_lfree(head); + closedir_and_clear(cur->fts_dirp); + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + __set_errno (ENAMETOOLONG); + return (NULL); + } + p->fts_level = level; + p->fts_parent = sp->fts_cur; + p->fts_pathlen = new_len; + + /* Store dirent.d_ino, in case we need to sort + entries before processing them. */ + p->fts_statp->st_ino = D_INO (dp); + + /* Build a file name for fts_stat to stat. */ + if (ISSET(FTS_NOCHDIR)) { + p->fts_accpath = p->fts_path; + memmove(cp, p->fts_name, p->fts_namelen + 1); + } else + p->fts_accpath = p->fts_name; + + if (sp->fts_compar == NULL || ISSET(FTS_DEFER_STAT)) { + /* Record what fts_read will have to do with this + entry. In many cases, it will simply fts_stat it, + but we can take advantage of any d_type information + to optimize away the unnecessary stat calls. I.e., + if FTS_NOSTAT is in effect and we're not following + symlinks (FTS_PHYSICAL) and d_type indicates this + is *not* a directory, then we won't have to stat it + at all. If it *is* a directory, then (currently) + we stat it regardless, in order to get device and + inode numbers. Some day we might optimize that + away, too, for directories where d_ino is known to + be valid. */ + bool skip_stat = (ISSET(FTS_PHYSICAL) + && ISSET(FTS_NOSTAT) + && DT_IS_KNOWN(dp) + && ! DT_MUST_BE(dp, DT_DIR)); + p->fts_info = FTS_NSOK; + /* Propagate dirent.d_type information back + to caller, when possible. */ + set_stat_type (p->fts_statp, D_TYPE (dp)); + fts_set_stat_required(p, !skip_stat); + is_dir = (ISSET(FTS_PHYSICAL) + && DT_MUST_BE(dp, DT_DIR)); + } else { + p->fts_info = fts_stat(sp, p, false); + is_dir = (p->fts_info == FTS_D + || p->fts_info == FTS_DC + || p->fts_info == FTS_DOT); + } + + /* Decrement link count if applicable. */ + if (nlinks > 0 && is_dir) + nlinks -= nostat; + + /* We walk in directory order so "ls -f" doesn't get upset. */ + p->fts_link = NULL; + if (head == NULL) + head = tail = p; + else { + tail->fts_link = p; + tail = p; + } + ++nitems; + if (max_entries <= nitems) { + /* When there are too many dir entries, leave + fts_dirp open, so that a subsequent fts_read + can take up where we leave off. */ + goto break_without_closedir; + } + } + + if (cur->fts_dirp) + closedir_and_clear(cur->fts_dirp); + + break_without_closedir: + + /* + * If realloc() changed the address of the file name, adjust the + * addresses for the rest of the tree and the dir list. + */ + if (doadjust) + fts_padjust(sp, head); + + /* + * If not changing directories, reset the file name back to original + * state. + */ + if (ISSET(FTS_NOCHDIR)) { + if (len == sp->fts_pathlen || nitems == 0) + --cp; + *cp = '\0'; + } + + /* + * If descended after called from fts_children or after called from + * fts_read and nothing found, get back. At the root level we use + * the saved fd; if one of fts_open()'s arguments is a relative name + * to an empty directory, we wind up here with no other way back. If + * can't get back, we're done. + */ + if (!continue_readdir && descend && (type == BCHILD || !nitems) && + (cur->fts_level == FTS_ROOTLEVEL + ? restore_initial_cwd(sp) + : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + fts_lfree(head); + return (NULL); + } + + /* If didn't find anything, return NULL. */ + if (!nitems) { + if (type == BREAD) + cur->fts_info = FTS_DP; + fts_lfree(head); + return (NULL); + } + + /* If there are many entries, no sorting function has been specified, + and this file system is of a type that may be slow with a large + number of entries, then sort the directory entries on increasing + inode numbers. */ + if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD + && !sp->fts_compar + && ISSET (FTS_CWDFD) + && dirent_inode_sort_may_be_useful (sp->fts_cwd_fd)) { + sp->fts_compar = fts_compare_ino; + head = fts_sort (sp, head, nitems); + sp->fts_compar = NULL; + } + + /* Sort the entries. */ + if (sp->fts_compar && nitems > 1) + head = fts_sort(sp, head, nitems); + return (head); +} + +#if FTS_DEBUG + +/* Walk ->fts_parent links starting at E_CURR, until the root of the + current hierarchy. There should be a directory with dev/inode + matching those of AD. If not, print a lot of diagnostics. */ +static void +find_matching_ancestor (FTSENT const *e_curr, struct Active_dir const *ad) +{ + FTSENT const *ent; + for (ent = e_curr; ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent) + { + if (ad->ino == ent->fts_statp->st_ino + && ad->dev == ent->fts_statp->st_dev) + return; + } + printf ("ERROR: tree dir, %s, not active\n", ad->fts_ent->fts_accpath); + printf ("active dirs:\n"); + for (ent = e_curr; + ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent) + printf (" %s(%"PRIuMAX"/%"PRIuMAX") to %s(%"PRIuMAX"/%"PRIuMAX")...\n", + ad->fts_ent->fts_accpath, + (uintmax_t) ad->dev, + (uintmax_t) ad->ino, + ent->fts_accpath, + (uintmax_t) ent->fts_statp->st_dev, + (uintmax_t) ent->fts_statp->st_ino); +} + +void +fts_cross_check (FTS const *sp) +{ + FTSENT const *ent = sp->fts_cur; + FTSENT const *t; + if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK)) + return; + + Dprintf (("fts-cross-check cur=%s\n", ent->fts_path)); + /* Make sure every parent dir is in the tree. */ + for (t = ent->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) + { + struct Active_dir ad; + ad.ino = t->fts_statp->st_ino; + ad.dev = t->fts_statp->st_dev; + if ( ! hash_lookup (sp->fts_cycle.ht, &ad)) + printf ("ERROR: active dir, %s, not in tree\n", t->fts_path); + } + + /* Make sure every dir in the tree is an active dir. + But ENT is not necessarily a directory. If so, just skip this part. */ + if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL + && (ent->fts_info == FTS_DP + || ent->fts_info == FTS_D)) + { + struct Active_dir *ad; + for (ad = hash_get_first (sp->fts_cycle.ht); ad != NULL; + ad = hash_get_next (sp->fts_cycle.ht, ad)) + { + find_matching_ancestor (ent, ad); + } + } +} + +static bool +same_fd (int fd1, int fd2) +{ + struct stat sb1, sb2; + return (fstat (fd1, &sb1) == 0 + && fstat (fd2, &sb2) == 0 + && SAME_INODE (sb1, sb2)); +} + +static void +fd_ring_print (FTS const *sp, FILE *stream, char const *msg) +{ + I_ring const *fd_ring = &sp->fts_fd_ring; + unsigned int i = fd_ring->fts_front; + char *cwd = getcwdat (sp->fts_cwd_fd, NULL, 0); + fprintf (stream, "=== %s ========== %s\n", msg, cwd); + free (cwd); + if (i_ring_empty (fd_ring)) + return; + + while (true) + { + int fd = fd_ring->fts_fd_ring[i]; + if (fd < 0) + fprintf (stream, "%d: %d:\n", i, fd); + else + { + char *wd = getcwdat (fd, NULL, 0); + fprintf (stream, "%d: %d: %s\n", i, fd, wd); + free (wd); + } + if (i == fd_ring->fts_back) + break; + i = (i + I_RING_SIZE - 1) % I_RING_SIZE; + } +} + +/* Ensure that each file descriptor on the fd_ring matches a + parent, grandparent, etc. of the current working directory. */ +static void +fd_ring_check (FTS const *sp) +{ + if (!fts_debug) + return; + + /* Make a writable copy. */ + I_ring fd_w = sp->fts_fd_ring; + + int cwd_fd = sp->fts_cwd_fd; + cwd_fd = dup (cwd_fd); + char *dot = getcwdat (cwd_fd, NULL, 0); + error (0, 0, "===== check ===== cwd: %s", dot); + free (dot); + while ( ! i_ring_empty (&fd_w)) + { + int fd = i_ring_pop (&fd_w); + if (0 <= fd) + { + int parent_fd = openat (cwd_fd, "..", O_SEARCH | O_NOATIME); + if (parent_fd < 0) + { + // Warn? + break; + } + if (!same_fd (fd, parent_fd)) + { + char *cwd = getcwdat (fd, NULL, 0); + error (0, errno, "ring : %s", cwd); + char *c2 = getcwdat (parent_fd, NULL, 0); + error (0, errno, "parent: %s", c2); + free (cwd); + free (c2); + fts_assert (0); + } + close (cwd_fd); + cwd_fd = parent_fd; + } + } + close (cwd_fd); +} +#endif + +static unsigned short int +internal_function +fts_stat(FTS *sp, register FTSENT *p, bool follow) +{ + struct stat *sbp = p->fts_statp; + int saved_errno; + + if (p->fts_level == FTS_ROOTLEVEL && ISSET(FTS_COMFOLLOW)) + follow = true; + + /* + * If doing a logical walk, or application requested FTS_FOLLOW, do + * a stat(2). If that fails, check for a non-existent symlink. If + * fail, set the errno from the stat call. + */ + if (ISSET(FTS_LOGICAL) || follow) { + if (stat(p->fts_accpath, sbp)) { + saved_errno = errno; + if (errno == ENOENT + && lstat(p->fts_accpath, sbp) == 0) { + __set_errno (0); + return (FTS_SLNONE); + } + p->fts_errno = saved_errno; + goto err; + } + } else if (fstatat(sp->fts_cwd_fd, p->fts_accpath, sbp, + AT_SYMLINK_NOFOLLOW)) { + p->fts_errno = errno; +err: memset(sbp, 0, sizeof(struct stat)); + return (FTS_NS); + } + + if (S_ISDIR(sbp->st_mode)) { + p->fts_n_dirs_remaining = (sbp->st_nlink + - (ISSET(FTS_SEEDOT) ? 0 : 2)); + if (ISDOT(p->fts_name)) { + /* Command-line "." and ".." are real directories. */ + return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT); + } + + return (FTS_D); + } + if (S_ISLNK(sbp->st_mode)) + return (FTS_SL); + if (S_ISREG(sbp->st_mode)) + return (FTS_F); + return (FTS_DEFAULT); +} + +static int +fts_compar (void const *a, void const *b) +{ + /* Convert A and B to the correct types, to pacify the compiler, and + for portability to bizarre hosts where "void const *" and "FTSENT + const **" differ in runtime representation. The comparison + function cannot modify *a and *b, but there is no compile-time + check for this. */ + FTSENT const **pa = (FTSENT const **) a; + FTSENT const **pb = (FTSENT const **) b; + return pa[0]->fts_fts->fts_compar (pa, pb); +} + +static FTSENT * +internal_function +fts_sort (FTS *sp, FTSENT *head, register size_t nitems) +{ + register FTSENT **ap, *p; + + /* On most modern hosts, void * and FTSENT ** have the same + run-time representation, and one can convert sp->fts_compar to + the type qsort expects without problem. Use the heuristic that + this is OK if the two pointer types are the same size, and if + converting FTSENT ** to long int is the same as converting + FTSENT ** to void * and then to long int. This heuristic isn't + valid in general but we don't know of any counterexamples. */ + FTSENT *dummy; + int (*compare) (void const *, void const *) = + ((sizeof &dummy == sizeof (void *) + && (long int) &dummy == (long int) (void *) &dummy) + ? (int (*) (void const *, void const *)) sp->fts_compar + : fts_compar); + + /* + * Construct an array of pointers to the structures and call qsort(3). + * Reassemble the array in the order returned by qsort. If unable to + * sort for memory reasons, return the directory entries in their + * current order. Allocate enough space for the current needs plus + * 40 so don't realloc one entry at a time. + */ + if (nitems > sp->fts_nitems) { + FTSENT **a; + + sp->fts_nitems = nitems + 40; + if (SIZE_MAX / sizeof *a < sp->fts_nitems + || ! (a = realloc (sp->fts_array, + sp->fts_nitems * sizeof *a))) { + free(sp->fts_array); + sp->fts_array = NULL; + sp->fts_nitems = 0; + return (head); + } + sp->fts_array = a; + } + for (ap = sp->fts_array, p = head; p; p = p->fts_link) + *ap++ = p; + qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), compare); + for (head = *(ap = sp->fts_array); --nitems; ++ap) + ap[0]->fts_link = ap[1]; + ap[0]->fts_link = NULL; + return (head); +} + +static FTSENT * +internal_function +fts_alloc (FTS *sp, const char *name, register size_t namelen) +{ + register FTSENT *p; + size_t len; + + /* + * The file name is a variable length array. Allocate the FTSENT + * structure and the file name in one chunk. + */ + len = sizeof(FTSENT) + namelen; + if ((p = malloc(len)) == NULL) + return (NULL); + + /* Copy the name and guarantee NUL termination. */ + memmove(p->fts_name, name, namelen); + p->fts_name[namelen] = '\0'; + + p->fts_namelen = namelen; + p->fts_fts = sp; + p->fts_path = sp->fts_path; + p->fts_errno = 0; + p->fts_dirp = NULL; + p->fts_flags = 0; + p->fts_instr = FTS_NOINSTR; + p->fts_number = 0; + p->fts_pointer = NULL; + return (p); +} + +static void +internal_function +fts_lfree (register FTSENT *head) +{ + register FTSENT *p; + + /* Free a linked list of structures. */ + while ((p = head)) { + head = head->fts_link; + if (p->fts_dirp) + closedir (p->fts_dirp); + free(p); + } +} + +/* + * Allow essentially unlimited file name lengths; find, rm, ls should + * all work on any tree. Most systems will allow creation of file + * names much longer than MAXPATHLEN, even though the kernel won't + * resolve them. Add the size (not just what's needed) plus 256 bytes + * so don't realloc the file name 2 bytes at a time. + */ +static bool +internal_function +fts_palloc (FTS *sp, size_t more) +{ + char *p; + size_t new_len = sp->fts_pathlen + more + 256; + + /* + * See if fts_pathlen would overflow. + */ + if (new_len < sp->fts_pathlen) { + free(sp->fts_path); + sp->fts_path = NULL; + __set_errno (ENAMETOOLONG); + return false; + } + sp->fts_pathlen = new_len; + p = realloc(sp->fts_path, sp->fts_pathlen); + if (p == NULL) { + free(sp->fts_path); + sp->fts_path = NULL; + return false; + } + sp->fts_path = p; + return true; +} + +/* + * When the file name is realloc'd, have to fix all of the pointers in + * structures already returned. + */ +static void +internal_function +fts_padjust (FTS *sp, FTSENT *head) +{ + FTSENT *p; + char *addr = sp->fts_path; + +#define ADJUST(p) do { \ + if ((p)->fts_accpath != (p)->fts_name) { \ + (p)->fts_accpath = \ + (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ + } \ + (p)->fts_path = addr; \ +} while (0) + /* Adjust the current set of children. */ + for (p = sp->fts_child; p; p = p->fts_link) + ADJUST(p); + + /* Adjust the rest of the tree, including the current level. */ + for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { + ADJUST(p); + p = p->fts_link ? p->fts_link : p->fts_parent; + } +} + +static size_t +internal_function _GL_ATTRIBUTE_PURE +fts_maxarglen (char * const *argv) +{ + size_t len, max; + + for (max = 0; *argv; ++argv) + if ((len = strlen(*argv)) > max) + max = len; + return (max + 1); +} + +/* + * Change to dir specified by fd or file name without getting + * tricked by someone changing the world out from underneath us. + * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in. + * If FD is non-negative, expect it to be used after this function returns, + * and to be closed eventually. So don't pass e.g., 'dirfd(dirp)' and then + * do closedir(dirp), because that would invalidate the saved FD. + * Upon failure, close FD immediately and return nonzero. + */ +static int +internal_function +fts_safe_changedir (FTS *sp, FTSENT *p, int fd, char const *dir) +{ + int ret; + bool is_dotdot = dir && STREQ (dir, ".."); + int newfd; + + /* This clause handles the unusual case in which FTS_NOCHDIR + is specified, along with FTS_CWDFD. In that case, there is + no need to change even the virtual cwd file descriptor. + However, if FD is non-negative, we do close it here. */ + if (ISSET (FTS_NOCHDIR)) + { + if (ISSET (FTS_CWDFD) && 0 <= fd) + close (fd); + return 0; + } + + if (fd < 0 && is_dotdot && ISSET (FTS_CWDFD)) + { + /* When possible, skip the diropen and subsequent fstat+dev/ino + comparison. I.e., when changing to parent directory + (chdir ("..")), use a file descriptor from the ring and + save the overhead of diropen+fstat, as well as avoiding + failure when we lack "x" access to the virtual cwd. */ + if ( ! i_ring_empty (&sp->fts_fd_ring)) + { + int parent_fd; + fd_ring_print (sp, stderr, "pre-pop"); + parent_fd = i_ring_pop (&sp->fts_fd_ring); + is_dotdot = true; + if (0 <= parent_fd) + { + fd = parent_fd; + dir = NULL; + } + } + } + + newfd = fd; + if (fd < 0 && (newfd = diropen (sp, dir)) < 0) + return -1; + + /* The following dev/inode check is necessary if we're doing a + "logical" traversal (through symlinks, a la chown -L), if the + system lacks O_NOFOLLOW support, or if we're changing to ".." + (but not via a popped file descriptor). When changing to the + name "..", O_NOFOLLOW can't help. In general, when the target is + not "..", diropen's use of O_NOFOLLOW ensures we don't mistakenly + follow a symlink, so we can avoid the expense of this fstat. */ + if (ISSET(FTS_LOGICAL) || ! HAVE_WORKING_O_NOFOLLOW + || (dir && STREQ (dir, ".."))) + { + struct stat sb; + if (fstat(newfd, &sb)) + { + ret = -1; + goto bail; + } + if (p->fts_statp->st_dev != sb.st_dev + || p->fts_statp->st_ino != sb.st_ino) + { + __set_errno (ENOENT); /* disinformation */ + ret = -1; + goto bail; + } + } + + if (ISSET(FTS_CWDFD)) + { + cwd_advance_fd (sp, newfd, ! is_dotdot); + return 0; + } + + ret = fchdir(newfd); +bail: + if (fd < 0) + { + int oerrno = errno; + (void)close(newfd); + __set_errno (oerrno); + } + return ret; +} diff --git a/contrib/grep/lib/fts_.h b/contrib/grep/lib/fts_.h new file mode 100644 index 0000000000..529403979f --- /dev/null +++ b/contrib/grep/lib/fts_.h @@ -0,0 +1,272 @@ +/* Traverse a file hierarchy. + + Copyright (C) 2004-2012 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 of the License, 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 . */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fts.h 8.3 (Berkeley) 8/14/94 + */ + +#ifndef _FTS_H +# define _FTS_H 1 + +# ifdef _LIBC +# include +# else +# undef __THROW +# define __THROW +# undef __BEGIN_DECLS +# undef __END_DECLS +# ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +# else +# define __BEGIN_DECLS +# define __END_DECLS +# endif +# endif + +# include +# include +# include +# include +# include "i-ring.h" + +typedef struct { + struct _ftsent *fts_cur; /* current node */ + struct _ftsent *fts_child; /* linked list of children */ + struct _ftsent **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* file name for this descent */ + int fts_rfd; /* fd for root */ + int fts_cwd_fd; /* the file descriptor on which the + virtual cwd is open, or AT_FDCWD */ + size_t fts_pathlen; /* sizeof(path) */ + size_t fts_nitems; /* elements in the sort array */ + int (*fts_compar) (struct _ftsent const **, struct _ftsent const **); + /* compare fn */ + +# define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ +# define FTS_LOGICAL 0x0002 /* logical walk */ +# define FTS_NOCHDIR 0x0004 /* don't change directories */ +# define FTS_NOSTAT 0x0008 /* don't get stat info */ +# define FTS_PHYSICAL 0x0010 /* physical walk */ +# define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ +# define FTS_XDEV 0x0040 /* don't cross devices */ +# define FTS_WHITEOUT 0x0080 /* return whiteout information */ + + /* There are two ways to detect cycles. + The lazy way (which works only with FTS_PHYSICAL), + with which one may process a directory that is a + part of the cycle several times before detecting the cycle. + The "tight" way, whereby fts uses more memory (proportional + to number of "active" directories, aka distance from root + of current tree to current directory -- see active_dir_ht) + to detect any cycle right away. For example, du must use + this option to avoid counting disk space in a cycle multiple + times, but chown -R need not. + The default is to use the constant-memory lazy way, when possible + (see below). + + However, with FTS_LOGICAL (when following symlinks, e.g., chown -L) + using lazy cycle detection is inadequate. For example, traversing + a directory containing a symbolic link to a peer directory, it is + possible to encounter the same directory twice even though there + is no cycle: + dir + ... + slink -> dir + So, when FTS_LOGICAL is selected, we have to use a different + mode of cycle detection: FTS_TIGHT_CYCLE_CHECK. */ +# define FTS_TIGHT_CYCLE_CHECK 0x0100 + + /* Use this flag to enable semantics with which the parent + application may be made both more efficient and more robust. + Whereas the default is to visit each directory in a recursive + traversal (via chdir), using this flag makes it so the initial + working directory is never changed. Instead, these functions + perform the traversal via a virtual working directory, maintained + through the file descriptor member, fts_cwd_fd. */ +# define FTS_CWDFD 0x0200 + + /* Historically, for each directory that fts initially encounters, it would + open it, read all entries, and stat each entry, storing the results, and + then it would process the first entry. But that behavior is bad for + locality of reference, and also causes trouble with inode-simulating + file systems like FAT, CIFS, FUSE-based ones, etc., when entries from + their name/inode cache are flushed too early. + Use this flag to make fts_open and fts_read defer the stat/lstat/fststat + of each entry until it is actually processed. However, note that if you + use this option and also specify a comparison function, that function may + not examine any data via fts_statp. However, when fts_statp->st_mode is + nonzero, the S_IFMT type bits are valid, with mapped dirent.d_type data. + Of course, that happens only on file systems that provide useful + dirent.d_type data. */ +# define FTS_DEFER_STAT 0x0400 + +# define FTS_NOATIME 0x0800 /* use O_NOATIME during traversal */ + +# define FTS_OPTIONMASK 0x0fff /* valid user option mask */ + +# define FTS_NAMEONLY 0x1000 /* (private) child names only */ +# define FTS_STOP 0x2000 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ + + /* Map a directory's device number to a boolean. The boolean is + true if for that file system (type determined by a single fstatfs + call per FS) st_nlink can be used to calculate the number of + sub-directory entries in a directory. + Using this table is an optimization that permits us to look up + file system type on a per-inode basis at the minimal cost of + calling fstatfs only once per traversed device. */ + struct hash_table *fts_leaf_optimization_works_ht; + + union { + /* This data structure is used if FTS_TIGHT_CYCLE_CHECK is + specified. It records the directories between a starting + point and the current directory. I.e., a directory is + recorded here IFF we have visited it once, but we have not + yet completed processing of all its entries. Every time we + visit a new directory, we add that directory to this set. + When we finish with a directory (usually by visiting it a + second time), we remove it from this set. Each entry in + this data structure is a device/inode pair. This data + structure is used to detect directory cycles efficiently and + promptly even when the depth of a hierarchy is in the tens + of thousands. */ + struct hash_table *ht; + + /* FIXME: rename these two members to have the fts_ prefix */ + /* This data structure uses a lazy cycle-detection algorithm, + as done by rm via cycle-check.c. It's the default, + but it's not appropriate for programs like du. */ + struct cycle_check_state *state; + } fts_cycle; + + /* A stack of the file descriptors corresponding to the + most-recently traversed parent directories. + Currently used only in FTS_CWDFD mode. */ + I_ring fts_fd_ring; +} FTS; + +typedef struct _ftsent { + struct _ftsent *fts_cycle; /* cycle node */ + struct _ftsent *fts_parent; /* parent directory */ + struct _ftsent *fts_link; /* next file in directory */ + DIR *fts_dirp; /* Dir pointer for any directory + containing more entries than we + read at one time. */ + long fts_number; /* local numeric value */ + void *fts_pointer; /* local address value */ + char *fts_accpath; /* access file name */ + char *fts_path; /* root name; == fts_fts->fts_path */ + int fts_errno; /* errno for this node */ + int fts_symfd; /* fd for symlink */ + size_t fts_pathlen; /* strlen(fts_path) */ + + FTS *fts_fts; /* the file hierarchy itself */ + +# define FTS_ROOTPARENTLEVEL (-1) +# define FTS_ROOTLEVEL 0 + ptrdiff_t fts_level; /* depth (-1 to N) */ + + size_t fts_namelen; /* strlen(fts_name) */ + nlink_t fts_n_dirs_remaining; /* count down from st_nlink */ + +# define FTS_D 1 /* preorder directory */ +# define FTS_DC 2 /* directory that causes cycles */ +# define FTS_DEFAULT 3 /* none of the above */ +# define FTS_DNR 4 /* unreadable directory */ +# define FTS_DOT 5 /* dot or dot-dot */ +# define FTS_DP 6 /* postorder directory */ +# define FTS_ERR 7 /* error; errno is set */ +# define FTS_F 8 /* regular file */ +# define FTS_INIT 9 /* initialized only */ +# define FTS_NS 10 /* stat(2) failed */ +# define FTS_NSOK 11 /* no stat(2) requested */ +# define FTS_SL 12 /* symbolic link */ +# define FTS_SLNONE 13 /* symbolic link without target */ +# define FTS_W 14 /* whiteout object */ + unsigned short int fts_info; /* user flags for FTSENT structure */ + +# define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ +# define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ + unsigned short int fts_flags; /* private flags for FTSENT structure */ + +# define FTS_AGAIN 1 /* read node again */ +# define FTS_FOLLOW 2 /* follow symbolic link */ +# define FTS_NOINSTR 3 /* no instructions */ +# define FTS_SKIP 4 /* discard node */ + unsigned short int fts_instr; /* fts_set() instructions */ + + struct stat fts_statp[1]; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT; + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#if __GNUC_PREREQ (3,4) +# undef __attribute_warn_unused_result__ +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +#else +# define __attribute_warn_unused_result__ /* empty */ +#endif + +__BEGIN_DECLS +FTSENT *fts_children (FTS *, int) __THROW __attribute_warn_unused_result__; +int fts_close (FTS *) __THROW __attribute_warn_unused_result__; +FTS *fts_open (char * const *, int, + int (*)(const FTSENT **, const FTSENT **)) + __THROW __attribute_warn_unused_result__; +FTSENT *fts_read (FTS *) __THROW __attribute_warn_unused_result__; +int fts_set (FTS *, FTSENT *, int) __THROW; +__END_DECLS + +#endif /* fts.h */ diff --git a/contrib/grep/lib/getcwd-lgpl.c b/contrib/grep/lib/getcwd-lgpl.c new file mode 100644 index 0000000000..f1e821b630 --- /dev/null +++ b/contrib/grep/lib/getcwd-lgpl.c @@ -0,0 +1,125 @@ +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. + This file is part of gnulib. + + 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 of the License, 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 . */ + +#include + +/* Specification */ +#include + +#include +#include + +#if GNULIB_GETCWD +/* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use. */ +typedef int dummy; +#else + +/* Get the name of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined + (perhaps because the absolute name was longer than PATH_MAX, or + because of missing read/search permissions on parent directories) + or SIZE was too small. If successful, returns BUF. If BUF is + NULL, an array is allocated with 'malloc'; the array is SIZE bytes + long, unless SIZE == 0, in which case it is as big as + necessary. */ + +# undef getcwd +char * +rpl_getcwd (char *buf, size_t size) +{ + char *ptr; + char *result; + + /* Handle single size operations. */ + if (buf) + { + if (!size) + { + errno = EINVAL; + return NULL; + } + return getcwd (buf, size); + } + + if (size) + { + buf = malloc (size); + if (!buf) + { + errno = ENOMEM; + return NULL; + } + result = getcwd (buf, size); + if (!result) + { + int saved_errno = errno; + free (buf); + errno = saved_errno; + } + return result; + } + + /* Flexible sizing requested. Avoid over-allocation for the common + case of a name that fits within a 4k page, minus some space for + local variables, to be sure we don't skip over a guard page. */ + { + char tmp[4032]; + size = sizeof tmp; + ptr = getcwd (tmp, size); + if (ptr) + { + result = strdup (ptr); + if (!result) + errno = ENOMEM; + return result; + } + if (errno != ERANGE) + return NULL; + } + + /* My what a large directory name we have. */ + do + { + size <<= 1; + ptr = realloc (buf, size); + if (ptr == NULL) + { + free (buf); + errno = ENOMEM; + return NULL; + } + buf = ptr; + result = getcwd (buf, size); + } + while (!result && errno == ERANGE); + + if (!result) + { + int saved_errno = errno; + free (buf); + errno = saved_errno; + } + else + { + /* Trim to fit, if possible. */ + result = realloc (buf, strlen (buf) + 1); + if (!result) + result = buf; + } + return result; +} + +#endif diff --git a/contrib/grep/lib/getdtablesize.c b/contrib/grep/lib/getdtablesize.c new file mode 100644 index 0000000000..70ba0751b5 --- /dev/null +++ b/contrib/grep/lib/getdtablesize.c @@ -0,0 +1,86 @@ +/* getdtablesize() function for platforms that don't have it. + Copyright (C) 2008-2012 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +#include + +#include "msvc-inval.h" + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static inline int +_setmaxstdio_nothrow (int newmax) +{ + int result; + + TRY_MSVC_INVAL + { + result = _setmaxstdio (newmax); + } + CATCH_MSVC_INVAL + { + result = -1; + } + DONE_MSVC_INVAL; + + return result; +} +# define _setmaxstdio _setmaxstdio_nothrow +#endif + +/* Cache for the previous getdtablesize () result. */ +static int dtablesize; + +int +getdtablesize (void) +{ + if (dtablesize == 0) + { + /* We are looking for the number N such that the valid file descriptors + are 0..N-1. It can be obtained through a loop as follows: + { + int fd; + for (fd = 3; fd < 65536; fd++) + if (dup2 (0, fd) == -1) + break; + return fd; + } + On Windows XP, the result is 2048. + The drawback of this loop is that it allocates memory for a libc + internal array that is never freed. + + The number N can also be obtained as the upper bound for + _getmaxstdio (). _getmaxstdio () returns the maximum number of open + FILE objects. The sanity check in _setmaxstdio reveals the maximum + number of file descriptors. This too allocates memory, but it is + freed when we call _setmaxstdio with the original value. */ + int orig_max_stdio = _getmaxstdio (); + unsigned int bound; + for (bound = 0x10000; _setmaxstdio (bound) < 0; bound = bound / 2) + ; + _setmaxstdio (orig_max_stdio); + dtablesize = bound; + } + return dtablesize; +} + +#endif diff --git a/contrib/grep/lib/getopt.c b/contrib/grep/lib/getopt.c index 23510d8afe..4342a34104 100644 --- a/contrib/grep/lib/getopt.c +++ b/contrib/grep/lib/getopt.c @@ -2,7 +2,7 @@ NOTE: getopt is part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! - Copyright (C) 1987-1996, 1998-2004, 2006, 2008-2011 Free Software + Copyright (C) 1987-1996, 1998-2004, 2006, 2008-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -41,15 +41,15 @@ # include #endif -/* This version of `getopt' appears to the caller like standard Unix `getopt' +/* This version of 'getopt' appears to the caller like standard Unix 'getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. - As `getopt_long' works, it permutes the elements of ARGV so that, + As 'getopt_long' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. - Using `getopt' or setting the environment variable POSIXLY_CORRECT + Using 'getopt' or setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. @@ -58,24 +58,24 @@ #include "getopt_int.h" -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, + Also, when 'ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller - and for communication between successive calls to `getopt'. + and for communication between successive calls to 'getopt'. - On entry to `getopt', zero means this is the first call; initialize. + On entry to 'getopt', zero means this is the first call; initialize. - When `getopt' returns -1, this is the index of the first of the + When 'getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. - Otherwise, `optind' communicates from one call to the next + Otherwise, 'optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ @@ -137,7 +137,7 @@ extern char *__getopt_nonoption_flags; The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. - `first_nonopt' and `last_nonopt' are relocated so that they describe + 'first_nonopt' and 'last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void @@ -154,7 +154,7 @@ exchange (char **argv, struct _getopt_data *d) but it consists of two parts that need to be swapped next. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the `__getopt_nonoption_flags' + /* First make sure the handling of the '__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) @@ -291,48 +291,48 @@ _getopt_initialize (int argc _GL_UNUSED, If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' + (aside from the initial '-') are option characters. If 'getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can + If 'getopt' finds another option character, it returns that character, + updating 'optind' and 'nextchar' so that the next call to 'getopt' can resume the scan with the following option character or ARGV-element. - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element + If there are no more option characters, 'getopt' returns -1. + Then 'optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to + return '?' after printing an error message. If you set 'opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that + ARGV-element, is returned in 'optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. + it is returned in 'optarg', otherwise 'optarg' is set to zero. - If OPTSTRING starts with `-' or `+', it requests different methods of + If OPTSTRING starts with '-' or '+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - Long-named options begin with `--' instead of `-'. + Long-named options begin with '--' instead of '-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. + from the option name by a '=', or else the in next ARGV-element. + When 'getopt' finds a long-named option, it returns 0 if that option's + 'flag' field is nonzero, the value of the option's 'val' field + if the 'flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. - LONGOPTS is a vector of `struct option' terminated by an + LONGOPTS is a vector of 'struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. @@ -409,7 +409,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, d->__last_nonopt = d->optind; } - /* The special ARGV-element `--' means premature end of options. + /* The special ARGV-element '--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ @@ -788,7 +788,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char c = *d->__nextchar++; const char *temp = strchr (optstring, c); - /* Increment `optind' when we start to process its last character. */ + /* Increment 'optind' when we start to process its last character. */ if (*d->__nextchar == '\0') ++d->optind; @@ -839,6 +839,9 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, int indfound = 0; int option_index; + if (longopts == NULL) + goto no_longs; + /* This is an option that requires an argument. */ if (*d->__nextchar != '\0') { @@ -884,7 +887,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, return c; } else - /* We already incremented `d->optind' once; + /* We already incremented 'd->optind' once; increment it again when taking next ARGV-elt as argument. */ d->optarg = argv[d->optind++]; @@ -1046,8 +1049,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } return pfound->val; } - d->__nextchar = NULL; - return 'W'; /* Let the application handle it. */ + + no_longs: + d->__nextchar = NULL; + return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { @@ -1109,7 +1114,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, c = '?'; } else - /* We already incremented `optind' once; + /* We already incremented 'optind' once; increment it again when taking next ARGV-elt as argument. */ d->optarg = argv[d->optind++]; d->__nextchar = NULL; @@ -1172,7 +1177,7 @@ __posix_getopt (int argc, char *const *argv, const char *optstring) #ifdef TEST /* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ + the above definition of 'getopt'. */ int main (int argc, char **argv) diff --git a/contrib/grep/lib/getopt1.c b/contrib/grep/lib/getopt1.c index 36568024cc..fb2a8f5a7b 100644 --- a/contrib/grep/lib/getopt1.c +++ b/contrib/grep/lib/getopt1.c @@ -1,5 +1,5 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987-1994, 1996-1998, 2004, 2006, 2009-2011 Free Software + Copyright (C) 1987-1994, 1996-1998, 2004, 2006, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -141,11 +141,11 @@ main (int argc, char **argv) break; case 'c': - printf ("option c with value `%s'\n", optarg); + printf ("option c with value '%s'\n", optarg); break; case 'd': - printf ("option d with value `%s'\n", optarg); + printf ("option d with value '%s'\n", optarg); break; case '?': diff --git a/contrib/grep/lib/getopt_int.h b/contrib/grep/lib/getopt_int.h index 9f0c7131a1..2da020c995 100644 --- a/contrib/grep/lib/getopt_int.h +++ b/contrib/grep/lib/getopt_int.h @@ -1,5 +1,5 @@ /* Internal declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2011 Free Software + Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -40,7 +40,7 @@ extern int _getopt_internal (int ___argc, char **___argv, stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character + variable POSIXLY_CORRECT, or using '+' as the first character of the list of option characters, or by calling getopt. PERMUTE is the default. We permute the contents of ARGV as we @@ -52,12 +52,12 @@ extern int _getopt_internal (int ___argc, char **___argv, written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the + with character code 1. Using '-' as the first character of the list of option characters selects this mode of operation. - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + The special argument '--' forces an end of option-scanning regardless + of the value of 'ordering'. In the case of RETURN_IN_ORDER, only + '--' can cause 'getopt' to return -1 with 'optind' != ARGC. */ enum __ord { @@ -99,8 +99,8 @@ struct _getopt_data /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first - of them; `last_nonopt' is the index after the last of them. */ + been skipped. 'first_nonopt' is the index in ARGV of the first + of them; 'last_nonopt' is the index after the last of them. */ int __first_nonopt; int __last_nonopt; diff --git a/contrib/grep/lib/getpagesize.c b/contrib/grep/lib/getpagesize.c index d7c1ba807a..02c00fbea4 100644 --- a/contrib/grep/lib/getpagesize.c +++ b/contrib/grep/lib/getpagesize.c @@ -1,6 +1,6 @@ /* getpagesize emulation for systems where it cannot be done in a C macro. - Copyright (C) 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2007, 2009-2012 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 @@ -22,7 +22,7 @@ /* Specification. */ #include -/* This implementation is only for native Win32 systems. */ +/* This implementation is only for native Windows systems. */ #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ # define WIN32_LEAN_AND_MEAN diff --git a/contrib/grep/lib/gettext.h b/contrib/grep/lib/gettext.h index ef0444317d..75875cdb0f 100644 --- a/contrib/grep/lib/gettext.h +++ b/contrib/grep/lib/gettext.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2011 Free Software + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + with this program; if not, see . */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 @@ -187,7 +184,7 @@ npgettext_aux (const char *domain, #include #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ - (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ + (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ /* || __STDC_VERSION__ >= 199901L */ ) #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS diff --git a/contrib/grep/lib/gnulib.mk b/contrib/grep/lib/gnulib.mk index a61eaaa89e..c23a359bb4 100644 --- a/contrib/grep/lib/gnulib.mk +++ b/contrib/grep/lib/gnulib.mk @@ -1,33 +1,30 @@ ## DO NOT EDIT! GENERATED AUTOMATICALLY! ## Process this file with automake to produce Makefile.in. -# Copyright (C) 2002-2011 Free Software Foundation, Inc. +# Copyright (C) 2002-2012 Free Software Foundation, Inc. # -# This file is free software, distributed under the terms of the GNU -# General Public License. As a special exception to the GNU General -# Public License, this file may be distributed as part of a program -# that contains a configuration script generated by Autoconf, under +# This file 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 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libgreputils --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=gnulib-tests --aux-dir=build-aux --with-tests --no-conditional-dependencies --no-libtool --macro-prefix=gl alloca announce-gen argmatch binary-io btowc c-ctype closeout dirent dirname do-release-commit-and-tag error exclude fcntl-h fnmatch getopt-gnu getpagesize gettext-h git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload hard-locale ignore-value intprops isblank isdir locale lseek maintainer-makefile malloc-gnu manywarnings mbrlen mbrtowc memchr mempcpy minmax obstack open progname propername quotearg readme-release realloc-gnu regex ssize_t stddef stdlib stpcpy strerror string strtoull strtoumax sys_stat unistd unlocked-io update-copyright useless-if-before-free version-etc-fsf wchar wcrtomb wctob wctype-h xalloc xstrtoumax - -AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects - -SUBDIRS = -noinst_HEADERS = -noinst_LIBRARIES = -noinst_LTLIBRARIES = -EXTRA_DIST = -BUILT_SOURCES = -SUFFIXES = -MOSTLYCLEANFILES = core *.stackdump -MOSTLYCLEANDIRS = -CLEANFILES = -DISTCLEANFILES = -MAINTAINERCLEANFILES = - -AM_CPPFLAGS = -AM_CFLAGS = +# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libgreputils --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=gnulib-tests --aux-dir=build-aux --with-tests --avoid=lock-tests --makefile-name=gnulib.mk --no-conditional-dependencies --no-libtool --macro-prefix=gl alloca announce-gen argmatch binary-io btowc c-ctype closeout do-release-commit-and-tag error exclude fcntl-h fnmatch fstatat fts getopt-gnu getpagesize gettext-h git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload hard-locale ignore-value intprops inttypes isatty isblank iswctype largefile locale lseek maintainer-makefile malloc-gnu manywarnings mbrlen mbrtowc memchr mempcpy minmax obstack openat-safer progname propername quote readme-release realloc-gnu regex same-inode ssize_t stddef stdlib stpcpy strerror string strtoull strtoumax sys_stat unistd unlocked-io update-copyright useless-if-before-free version-etc-fsf wchar wcrtomb wcscoll wctob wctype-h xalloc xstrtoimax + + +MOSTLYCLEANFILES += core *.stackdump noinst_LIBRARIES += libgreputils.a @@ -77,37 +74,22 @@ EXTRA_DIST += $(top_srcdir)/build-aux/announce-gen ## end gnulib module announce-gen -## begin gnulib module arg-nonnull - -# The BUILT_SOURCES created by this Makefile snippet are not used via #include -# statements but through direct file reference. Therefore this snippet must be -# present in all Makefile.am that need it. This is ensured by the applicability -# 'all' defined above. +## begin gnulib module argmatch -BUILT_SOURCES += arg-nonnull.h -# The arg-nonnull.h that gets inserted into generated .h files is the same as -# build-aux/arg-nonnull.h, except that it has the copyright header cut off. -arg-nonnull.h: $(top_srcdir)/build-aux/arg-nonnull.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/GL_ARG_NONNULL/,$$p' \ - < $(top_srcdir)/build-aux/arg-nonnull.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += arg-nonnull.h arg-nonnull.h-t +libgreputils_a_SOURCES += argmatch.c -ARG_NONNULL_H=arg-nonnull.h +EXTRA_DIST += argmatch.h -EXTRA_DIST += $(top_srcdir)/build-aux/arg-nonnull.h +## end gnulib module argmatch -## end gnulib module arg-nonnull +## begin gnulib module at-internal -## begin gnulib module argmatch -libgreputils_a_SOURCES += argmatch.c +EXTRA_DIST += openat-priv.h openat-proc.c -EXTRA_DIST += argmatch.h +EXTRA_libgreputils_a_SOURCES += openat-proc.c -## end gnulib module argmatch +## end gnulib module at-internal ## begin gnulib module binary-io @@ -130,30 +112,6 @@ EXTRA_libgreputils_a_SOURCES += btowc.c ## end gnulib module btowc -## begin gnulib module c++defs - -# The BUILT_SOURCES created by this Makefile snippet are not used via #include -# statements but through direct file reference. Therefore this snippet must be -# present in all Makefile.am that need it. This is ensured by the applicability -# 'all' defined above. - -BUILT_SOURCES += c++defs.h -# The c++defs.h that gets inserted into generated .h files is the same as -# build-aux/c++defs.h, except that it has the copyright header cut off. -c++defs.h: $(top_srcdir)/build-aux/c++defs.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/_GL_CXXDEFS/,$$p' \ - < $(top_srcdir)/build-aux/c++defs.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += c++defs.h c++defs.h-t - -CXXDEFS_H=c++defs.h - -EXTRA_DIST += $(top_srcdir)/build-aux/c++defs.h - -## end gnulib module c++defs - ## begin gnulib module c-ctype libgreputils_a_SOURCES += c-ctype.h c-ctype.c @@ -166,6 +124,39 @@ libgreputils_a_SOURCES += c-strcase.h c-strcasecmp.c c-strncasecmp.c ## end gnulib module c-strcase +## begin gnulib module c-strcaseeq + + +EXTRA_DIST += c-strcaseeq.h + +## end gnulib module c-strcaseeq + +## begin gnulib module chdir-long + + +EXTRA_DIST += chdir-long.c chdir-long.h + +EXTRA_libgreputils_a_SOURCES += chdir-long.c + +## end gnulib module chdir-long + +## begin gnulib module cloexec + +libgreputils_a_SOURCES += cloexec.c + +EXTRA_DIST += cloexec.h + +## end gnulib module cloexec + +## begin gnulib module close + + +EXTRA_DIST += close.c + +EXTRA_libgreputils_a_SOURCES += close.c + +## end gnulib module close + ## begin gnulib module close-stream libgreputils_a_SOURCES += close-stream.c @@ -174,6 +165,15 @@ EXTRA_DIST += close-stream.h ## end gnulib module close-stream +## begin gnulib module closedir + + +EXTRA_DIST += closedir.c dirent-private.h + +EXTRA_libgreputils_a_SOURCES += closedir.c + +## end gnulib module closedir + ## begin gnulib module closeout libgreputils_a_SOURCES += closeout.c @@ -219,11 +219,7 @@ configmake.h: Makefile echo '#define PKGLIBDIR "$(pkglibdir)"'; \ echo '#define PKGLIBEXECDIR "$(pkglibexecdir)"'; \ } | sed '/""/d' > $@-t && \ - if test -f $@ && cmp $@-t $@ > /dev/null; then \ - rm -f $@-t; \ - else \ - rm -f $@; mv $@-t $@; \ - fi + mv -f $@-t $@ BUILT_SOURCES += configmake.h CLEANFILES += configmake.h configmake.h-t @@ -257,6 +253,21 @@ EXTRA_DIST += ctype.in.h ## end gnulib module ctype +## begin gnulib module cycle-check + +libgreputils_a_SOURCES += cycle-check.c + +EXTRA_DIST += cycle-check.h + +## end gnulib module cycle-check + +## begin gnulib module dev-ino + + +EXTRA_DIST += dev-ino.h + +## end gnulib module dev-ino + ## begin gnulib module dirent BUILT_SOURCES += dirent.h @@ -267,23 +278,32 @@ dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_H)|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \ + -e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \ + -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \ + -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \ + -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \ -e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \ -e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \ -e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \ -e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \ + -e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \ + -e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \ + -e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \ + -e 's/@''HAVE_CLOSEDIR''@/$(HAVE_CLOSEDIR)/g' \ -e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \ -e 's|@''HAVE_DECL_FDOPENDIR''@|$(HAVE_DECL_FDOPENDIR)|g' \ -e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \ -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \ -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \ + -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \ -e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \ -e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \ -e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \ - -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ @@ -296,15 +316,22 @@ EXTRA_DIST += dirent.in.h ## end gnulib module dirent -## begin gnulib module dirname +## begin gnulib module dirent-safer + +libgreputils_a_SOURCES += opendir-safer.c + +EXTRA_DIST += dirent--.h dirent-safer.h -libgreputils_a_SOURCES += dirname.c basename.c +## end gnulib module dirent-safer -EXTRA_DIST += stripslash.c +## begin gnulib module dirfd -EXTRA_libgreputils_a_SOURCES += stripslash.c -## end gnulib module dirname +EXTRA_DIST += dirfd.c + +EXTRA_libgreputils_a_SOURCES += dirfd.c + +## end gnulib module dirfd ## begin gnulib module dirname-lgpl @@ -328,6 +355,24 @@ EXTRA_DIST += dosname.h ## end gnulib module dosname +## begin gnulib module dup + + +EXTRA_DIST += dup.c + +EXTRA_libgreputils_a_SOURCES += dup.c + +## end gnulib module dup + +## begin gnulib module dup2 + + +EXTRA_DIST += dup2.c + +EXTRA_libgreputils_a_SOURCES += dup2.c + +## end gnulib module dup2 + ## begin gnulib module errno BUILT_SOURCES += $(ERRNO_H) @@ -387,6 +432,24 @@ EXTRA_DIST += exitfail.h ## end gnulib module exitfail +## begin gnulib module fchdir + + +EXTRA_DIST += fchdir.c + +EXTRA_libgreputils_a_SOURCES += fchdir.c + +## end gnulib module fchdir + +## begin gnulib module fcntl + + +EXTRA_DIST += fcntl.c + +EXTRA_libgreputils_a_SOURCES += fcntl.c + +## end gnulib module fcntl + ## begin gnulib module fcntl-h BUILT_SOURCES += fcntl.h @@ -422,6 +485,46 @@ EXTRA_DIST += fcntl.in.h ## end gnulib module fcntl-h +## begin gnulib module fcntl-safer + +libgreputils_a_SOURCES += creat-safer.c open-safer.c + +EXTRA_DIST += fcntl--.h fcntl-safer.h + +## end gnulib module fcntl-safer + +## begin gnulib module fd-hook + +libgreputils_a_SOURCES += fd-hook.c + +EXTRA_DIST += fd-hook.h + +## end gnulib module fd-hook + +## begin gnulib module fdopendir + + +EXTRA_DIST += fdopendir.c + +EXTRA_libgreputils_a_SOURCES += fdopendir.c + +## end gnulib module fdopendir + +## begin gnulib module filename + + +EXTRA_DIST += filename.h + +## end gnulib module filename + +## begin gnulib module filenamecat-lgpl + +libgreputils_a_SOURCES += filenamecat-lgpl.c + +EXTRA_DIST += filenamecat.h + +## end gnulib module filenamecat-lgpl + ## begin gnulib module fnmatch BUILT_SOURCES += $(FNMATCH_H) @@ -457,6 +560,33 @@ EXTRA_libgreputils_a_SOURCES += fpending.c ## end gnulib module fpending +## begin gnulib module fstat + + +EXTRA_DIST += fstat.c + +EXTRA_libgreputils_a_SOURCES += fstat.c + +## end gnulib module fstat + +## begin gnulib module fstatat + + +EXTRA_DIST += at-func.c fstatat.c openat-priv.h + +EXTRA_libgreputils_a_SOURCES += at-func.c fstatat.c + +## end gnulib module fstatat + +## begin gnulib module fts + + +EXTRA_DIST += fts-cycle.c fts.c fts_.h + +EXTRA_libgreputils_a_SOURCES += fts-cycle.c fts.c + +## end gnulib module fts + ## begin gnulib module gendocs @@ -464,6 +594,24 @@ EXTRA_DIST += $(top_srcdir)/build-aux/gendocs.sh ## end gnulib module gendocs +## begin gnulib module getcwd-lgpl + + +EXTRA_DIST += getcwd-lgpl.c + +EXTRA_libgreputils_a_SOURCES += getcwd-lgpl.c + +## end gnulib module getcwd-lgpl + +## begin gnulib module getdtablesize + + +EXTRA_DIST += getdtablesize.c + +EXTRA_libgreputils_a_SOURCES += getdtablesize.c + +## end gnulib module getdtablesize + ## begin gnulib module getopt-posix BUILT_SOURCES += $(GETOPT_H) @@ -573,6 +721,14 @@ EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath ## end gnulib module havelib +## begin gnulib module i-ring + +libgreputils_a_SOURCES += i-ring.c + +EXTRA_DIST += i-ring.h + +## end gnulib module i-ring + ## begin gnulib module iconv-h BUILT_SOURCES += $(ICONV_H) @@ -657,7 +813,7 @@ BUILT_SOURCES += inttypes.h # We need the following in order to create when the system # doesn't have one that works with the given compiler. -inttypes.h: inttypes.in.h $(top_builddir)/config.status $(WARN_ON_USE_H) $(ARG_NONNULL_H) +inttypes.h: inttypes.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H) $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ @@ -678,10 +834,12 @@ inttypes.h: inttypes.in.h $(top_builddir)/config.status $(WARN_ON_USE_H) $(ARG_N -e 's/@''HAVE_DECL_IMAXDIV''@/$(HAVE_DECL_IMAXDIV)/g' \ -e 's/@''HAVE_DECL_STRTOIMAX''@/$(HAVE_DECL_STRTOIMAX)/g' \ -e 's/@''HAVE_DECL_STRTOUMAX''@/$(HAVE_DECL_STRTOUMAX)/g' \ + -e 's/@''REPLACE_STRTOIMAX''@/$(REPLACE_STRTOIMAX)/g' \ -e 's/@''INT32_MAX_LT_INTMAX_MAX''@/$(INT32_MAX_LT_INTMAX_MAX)/g' \ -e 's/@''INT64_MAX_EQ_LONG_MAX''@/$(INT64_MAX_EQ_LONG_MAX)/g' \ -e 's/@''UINT32_MAX_LT_UINTMAX_MAX''@/$(UINT32_MAX_LT_UINTMAX_MAX)/g' \ -e 's/@''UINT64_MAX_EQ_ULONG_MAX''@/$(UINT64_MAX_EQ_ULONG_MAX)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ < $(srcdir)/inttypes.in.h; \ @@ -693,22 +851,23 @@ EXTRA_DIST += inttypes.in.h ## end gnulib module inttypes-incomplete -## begin gnulib module isblank +## begin gnulib module isatty -EXTRA_DIST += isblank.c +EXTRA_DIST += isatty.c -EXTRA_libgreputils_a_SOURCES += isblank.c +EXTRA_libgreputils_a_SOURCES += isatty.c -## end gnulib module isblank +## end gnulib module isatty -## begin gnulib module isdir +## begin gnulib module isblank -libgreputils_a_SOURCES += isdir.c -EXTRA_DIST += isdir.h +EXTRA_DIST += isblank.c -## end gnulib module isdir +EXTRA_libgreputils_a_SOURCES += isblank.c + +## end gnulib module isblank ## begin gnulib module iswblank @@ -719,6 +878,15 @@ EXTRA_libgreputils_a_SOURCES += iswblank.c ## end gnulib module iswblank +## begin gnulib module iswctype + + +EXTRA_DIST += iswctype-impl.h iswctype.c + +EXTRA_libgreputils_a_SOURCES += iswctype.c + +## end gnulib module iswctype + ## begin gnulib module langinfo BUILT_SOURCES += langinfo.h @@ -840,12 +1008,15 @@ locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \ + -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ -e 's|@''HAVE_DUPLOCALE''@|$(HAVE_DUPLOCALE)|g' \ -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \ + -e 's|@''REPLACE_LOCALECONV''@|$(REPLACE_LOCALECONV)|g' \ -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \ -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ + -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ @@ -858,6 +1029,15 @@ EXTRA_DIST += locale.in.h ## end gnulib module locale +## begin gnulib module localeconv + + +EXTRA_DIST += localeconv.c + +EXTRA_libgreputils_a_SOURCES += localeconv.c + +## end gnulib module localeconv + ## begin gnulib module lseek @@ -867,6 +1047,15 @@ EXTRA_libgreputils_a_SOURCES += lseek.c ## end gnulib module lseek +## begin gnulib module lstat + + +EXTRA_DIST += lstat.c + +EXTRA_libgreputils_a_SOURCES += lstat.c + +## end gnulib module lstat + ## begin gnulib module maintainer-makefile EXTRA_DIST += $(top_srcdir)/maint.mk @@ -1002,12 +1191,39 @@ EXTRA_libgreputils_a_SOURCES += mempcpy.c ## end gnulib module mempcpy +## begin gnulib module memrchr + + +EXTRA_DIST += memrchr.c + +EXTRA_libgreputils_a_SOURCES += memrchr.c + +## end gnulib module memrchr + ## begin gnulib module minmax libgreputils_a_SOURCES += minmax.h ## end gnulib module minmax +## begin gnulib module msvc-inval + + +EXTRA_DIST += msvc-inval.c msvc-inval.h + +EXTRA_libgreputils_a_SOURCES += msvc-inval.c + +## end gnulib module msvc-inval + +## begin gnulib module msvc-nothrow + + +EXTRA_DIST += msvc-nothrow.c msvc-nothrow.h + +EXTRA_libgreputils_a_SOURCES += msvc-nothrow.c + +## end gnulib module msvc-nothrow + ## begin gnulib module nl_langinfo @@ -1035,6 +1251,52 @@ EXTRA_libgreputils_a_SOURCES += open.c ## end gnulib module open +## begin gnulib module openat + + +EXTRA_DIST += openat-priv.h openat.c + +EXTRA_libgreputils_a_SOURCES += openat.c + +## end gnulib module openat + +## begin gnulib module openat-die + +libgreputils_a_SOURCES += openat-die.c + +## end gnulib module openat-die + +## begin gnulib module openat-h + + +EXTRA_DIST += openat.h + +## end gnulib module openat-h + +## begin gnulib module openat-safer + +libgreputils_a_SOURCES += openat-safer.c + +EXTRA_DIST += fcntl--.h fcntl-safer.h + +## end gnulib module openat-safer + +## begin gnulib module opendir + + +EXTRA_DIST += dirent-private.h opendir.c + +EXTRA_libgreputils_a_SOURCES += opendir.c + +## end gnulib module opendir + +## begin gnulib module pathmax + + +EXTRA_DIST += pathmax.h + +## end gnulib module pathmax + ## begin gnulib module progname libgreputils_a_SOURCES += progname.h progname.c @@ -1049,7 +1311,6 @@ libgreputils_a_SOURCES += propername.h propername.c ## begin gnulib module quote -libgreputils_a_SOURCES += quote.c EXTRA_DIST += quote.h @@ -1059,10 +1320,19 @@ EXTRA_DIST += quote.h libgreputils_a_SOURCES += quotearg.c -EXTRA_DIST += quotearg.h +EXTRA_DIST += quote.h quotearg.h ## end gnulib module quotearg +## begin gnulib module readdir + + +EXTRA_DIST += dirent-private.h readdir.c + +EXTRA_libgreputils_a_SOURCES += readdir.c + +## end gnulib module readdir + ## begin gnulib module readme-release @@ -1097,6 +1367,127 @@ EXTRA_libgreputils_a_SOURCES += regcomp.c regex.c regex_internal.c regexec.c ## end gnulib module regex +## begin gnulib module same-inode + + +EXTRA_DIST += same-inode.h + +## end gnulib module same-inode + +## begin gnulib module save-cwd + +libgreputils_a_SOURCES += save-cwd.c + +EXTRA_DIST += save-cwd.h + +## end gnulib module save-cwd + +## begin gnulib module snippet/_Noreturn + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all Makefile.am that +# need it. This is ensured by the applicability 'all' defined above. + +_NORETURN_H=$(top_srcdir)/build-aux/snippet/_Noreturn.h + +EXTRA_DIST += $(top_srcdir)/build-aux/snippet/_Noreturn.h + +## end gnulib module snippet/_Noreturn + +## begin gnulib module snippet/arg-nonnull + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +BUILT_SOURCES += arg-nonnull.h +# The arg-nonnull.h that gets inserted into generated .h files is the same as +# build-aux/snippet/arg-nonnull.h, except that it has the copyright header cut +# off. +arg-nonnull.h: $(top_srcdir)/build-aux/snippet/arg-nonnull.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/GL_ARG_NONNULL/,$$p' \ + < $(top_srcdir)/build-aux/snippet/arg-nonnull.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += arg-nonnull.h arg-nonnull.h-t + +ARG_NONNULL_H=arg-nonnull.h + +EXTRA_DIST += $(top_srcdir)/build-aux/snippet/arg-nonnull.h + +## end gnulib module snippet/arg-nonnull + +## begin gnulib module snippet/c++defs + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +BUILT_SOURCES += c++defs.h +# The c++defs.h that gets inserted into generated .h files is the same as +# build-aux/snippet/c++defs.h, except that it has the copyright header cut off. +c++defs.h: $(top_srcdir)/build-aux/snippet/c++defs.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/_GL_CXXDEFS/,$$p' \ + < $(top_srcdir)/build-aux/snippet/c++defs.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += c++defs.h c++defs.h-t + +CXXDEFS_H=c++defs.h + +EXTRA_DIST += $(top_srcdir)/build-aux/snippet/c++defs.h + +## end gnulib module snippet/c++defs + +## begin gnulib module snippet/unused-parameter + +# The BUILT_SOURCES created by this Makefile snippet are not used via #include +# statements but through direct file reference. Therefore this snippet must be +# present in all Makefile.am that need it. This is ensured by the applicability +# 'all' defined above. + +BUILT_SOURCES += unused-parameter.h +# The unused-parameter.h that gets inserted into generated .h files is the same +# as build-aux/snippet/unused-parameter.h, except that it has the copyright +# header cut off. +unused-parameter.h: $(top_srcdir)/build-aux/snippet/unused-parameter.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/GL_UNUSED_PARAMETER/,$$p' \ + < $(top_srcdir)/build-aux/snippet/unused-parameter.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += unused-parameter.h unused-parameter.h-t + +UNUSED_PARAMETER_H=unused-parameter.h + +EXTRA_DIST += $(top_srcdir)/build-aux/snippet/unused-parameter.h + +## end gnulib module snippet/unused-parameter + +## begin gnulib module snippet/warn-on-use + +BUILT_SOURCES += warn-on-use.h +# The warn-on-use.h that gets inserted into generated .h files is the same as +# build-aux/snippet/warn-on-use.h, except that it has the copyright header cut +# off. +warn-on-use.h: $(top_srcdir)/build-aux/snippet/warn-on-use.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/^.ifndef/,$$p' \ + < $(top_srcdir)/build-aux/snippet/warn-on-use.h \ + > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += warn-on-use.h warn-on-use.h-t + +WARN_ON_USE_H=warn-on-use.h + +EXTRA_DIST += $(top_srcdir)/build-aux/snippet/warn-on-use.h + +## end gnulib module snippet/warn-on-use + ## begin gnulib module stat @@ -1243,7 +1634,8 @@ BUILT_SOURCES += stdlib.h # We need the following in order to create when the system # doesn't have one that works with the given compiler. -stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) +stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ + $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ @@ -1265,8 +1657,11 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \ -e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \ -e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \ + -e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \ -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \ + -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \ -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \ + -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ @@ -1291,7 +1686,10 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \ -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \ -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \ + -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \ -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ + -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \ + -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ @@ -1309,7 +1707,9 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \ -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \ -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ + -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \ -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ + -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \ -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \ -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \ -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \ @@ -1317,6 +1717,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \ -e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _Noreturn/r $(_NORETURN_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ } > $@-t && \ @@ -1336,6 +1737,24 @@ EXTRA_libgreputils_a_SOURCES += stpcpy.c ## end gnulib module stpcpy +## begin gnulib module strcase + + +EXTRA_DIST += strcasecmp.c strncasecmp.c + +EXTRA_libgreputils_a_SOURCES += strcasecmp.c strncasecmp.c + +## end gnulib module strcase + +## begin gnulib module strdup-posix + + +EXTRA_DIST += strdup.c + +EXTRA_libgreputils_a_SOURCES += strdup.c + +## end gnulib module strdup-posix + ## begin gnulib module streq @@ -1383,6 +1802,8 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_STRING_H''@|$(NEXT_STRING_H)|g' \ + -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \ + -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/g' \ -e 's/@''GNULIB_MBSLEN''@/$(GNULIB_MBSLEN)/g' \ -e 's/@''GNULIB_MBSNLEN''@/$(GNULIB_MBSNLEN)/g' \ -e 's/@''GNULIB_MBSCHR''@/$(GNULIB_MBSCHR)/g' \ @@ -1419,7 +1840,9 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_STRSIGNAL''@/$(GNULIB_STRSIGNAL)/g' \ -e 's/@''GNULIB_STRVERSCMP''@/$(GNULIB_STRVERSCMP)/g' \ < $(srcdir)/string.in.h | \ - sed -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \ + sed -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \ + -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \ + -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \ -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \ -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ @@ -1465,14 +1888,36 @@ EXTRA_DIST += string.in.h ## end gnulib module string -## begin gnulib module strndup +## begin gnulib module strings +BUILT_SOURCES += strings.h -EXTRA_DIST += strndup.c +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +strings.h: strings.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_STRINGS_H''@|$(HAVE_STRINGS_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STRINGS_H''@|$(NEXT_STRINGS_H)|g' \ + -e 's|@''GNULIB_FFS''@|$(GNULIB_FFS)|g' \ + -e 's|@''HAVE_FFS''@|$(HAVE_FFS)|g' \ + -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \ + -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/strings.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += strings.h strings.h-t -EXTRA_libgreputils_a_SOURCES += strndup.c +EXTRA_DIST += strings.in.h -## end gnulib module strndup +## end gnulib module strings ## begin gnulib module strnlen @@ -1489,6 +1934,24 @@ libgreputils_a_SOURCES += strnlen1.h strnlen1.c ## end gnulib module strnlen1 +## begin gnulib module strtoimax + + +EXTRA_DIST += strtoimax.c + +EXTRA_libgreputils_a_SOURCES += strtoimax.c + +## end gnulib module strtoimax + +## begin gnulib module strtoll + + +EXTRA_DIST += strtol.c strtoll.c + +EXTRA_libgreputils_a_SOURCES += strtol.c strtoll.c + +## end gnulib module strtoll + ## begin gnulib module strtoull @@ -1522,7 +1985,9 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ + -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ + -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ @@ -1567,6 +2032,31 @@ EXTRA_DIST += sys_stat.in.h ## end gnulib module sys_stat +## begin gnulib module sys_types + +BUILT_SOURCES += sys/types.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/types.h: sys_types.in.h $(top_builddir)/config.status + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + < $(srcdir)/sys_types.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/types.h sys/types.h-t + +EXTRA_DIST += sys_types.in.h + +## end gnulib module sys_types + ## begin gnulib module time BUILT_SOURCES += time.h @@ -1632,8 +2122,11 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \ -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \ -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \ -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \ @@ -1641,6 +2134,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \ -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \ -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \ + -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \ -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \ -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \ -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \ @@ -1653,6 +2147,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \ -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \ -e 's/@''GNULIB_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \ + -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/g' \ -e 's/@''GNULIB_LCHOWN''@/$(GNULIB_LCHOWN)/g' \ -e 's/@''GNULIB_LINK''@/$(GNULIB_LINK)/g' \ -e 's/@''GNULIB_LINKAT''@/$(GNULIB_LINKAT)/g' \ @@ -1665,11 +2160,12 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's/@''GNULIB_READLINK''@/$(GNULIB_READLINK)/g' \ -e 's/@''GNULIB_READLINKAT''@/$(GNULIB_READLINKAT)/g' \ -e 's/@''GNULIB_RMDIR''@/$(GNULIB_RMDIR)/g' \ + -e 's/@''GNULIB_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/g' \ -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \ -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \ -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \ -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \ - -e 's/@''GNULIB_UNISTD_H_GETOPT''@/$(GNULIB_UNISTD_H_GETOPT)/g' \ + -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \ -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \ -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GNULIB_UNISTD_H_SIGPIPE)/g' \ -e 's/@''GNULIB_UNLINK''@/$(GNULIB_UNLINK)/g' \ @@ -1684,6 +2180,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ + -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \ -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \ -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \ @@ -1701,6 +2198,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \ -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \ + -e 's|@''HAVE_SETHOSTNAME''@|$(HAVE_SETHOSTNAME)|g' \ -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \ -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \ @@ -1708,10 +2206,12 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \ -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ -e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \ + -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \ -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \ -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \ -e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \ + -e 's|@''HAVE_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \ -e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|g' \ -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \ @@ -1721,11 +2221,13 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \ -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \ -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \ + -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \ -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \ -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \ -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \ -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \ + -e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|g' \ -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \ -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \ -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \ @@ -1755,6 +2257,14 @@ EXTRA_DIST += unistd.in.h ## end gnulib module unistd +## begin gnulib module unistd-safer + +libgreputils_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c + +EXTRA_DIST += unistd--.h unistd-safer.h + +## end gnulib module unistd-safer + ## begin gnulib module unistr/base BUILT_SOURCES += $(LIBUNISTRING_UNISTR_H) @@ -1836,31 +2346,6 @@ EXTRA_DIST += unlocked-io.h ## end gnulib module unlocked-io -## begin gnulib module unused-parameter - -# The BUILT_SOURCES created by this Makefile snippet are not used via #include -# statements but through direct file reference. Therefore this snippet must be -# present in all Makefile.am that need it. This is ensured by the applicability -# 'all' defined above. - -BUILT_SOURCES += unused-parameter.h -# The unused-parameter.h that gets inserted into generated .h files is the same -# as build-aux/unused-parameter.h, except that it has the copyright header cut -# off. -unused-parameter.h: $(top_srcdir)/build-aux/unused-parameter.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/GL_UNUSED_PARAMETER/,$$p' \ - < $(top_srcdir)/build-aux/unused-parameter.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += unused-parameter.h unused-parameter.h-t - -UNUSED_PARAMETER_H=unused-parameter.h - -EXTRA_DIST += $(top_srcdir)/build-aux/unused-parameter.h - -## end gnulib module unused-parameter - ## begin gnulib module update-copyright @@ -1901,25 +2386,6 @@ libgreputils_a_SOURCES += version-etc-fsf.c ## end gnulib module version-etc-fsf -## begin gnulib module warn-on-use - -BUILT_SOURCES += warn-on-use.h -# The warn-on-use.h that gets inserted into generated .h files is the same as -# build-aux/warn-on-use.h, except that it has the copyright header cut off. -warn-on-use.h: $(top_srcdir)/build-aux/warn-on-use.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/^.ifndef/,$$p' \ - < $(top_srcdir)/build-aux/warn-on-use.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += warn-on-use.h warn-on-use.h-t - -WARN_ON_USE_H=warn-on-use.h - -EXTRA_DIST += $(top_srcdir)/build-aux/warn-on-use.h - -## end gnulib module warn-on-use - ## begin gnulib module wchar BUILT_SOURCES += wchar.h @@ -2050,6 +2516,15 @@ EXTRA_libgreputils_a_SOURCES += wcrtomb.c ## end gnulib module wcrtomb +## begin gnulib module wcscoll + + +EXTRA_DIST += wcscoll-impl.h wcscoll.c + +EXTRA_libgreputils_a_SOURCES += wcscoll.c + +## end gnulib module wcscoll + ## begin gnulib module wctob @@ -2095,6 +2570,7 @@ wctype.h: wctype.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \ -e 's/@''REPLACE_ISWBLANK''@/$(REPLACE_ISWBLANK)/g' \ -e 's/@''REPLACE_ISWCNTRL''@/$(REPLACE_ISWCNTRL)/g' \ + -e 's/@''REPLACE_TOWLOWER''@/$(REPLACE_TOWLOWER)/g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ < $(srcdir)/wctype.in.h; \ @@ -2142,11 +2618,11 @@ libgreputils_a_SOURCES += xstriconv.h xstriconv.c ## end gnulib module xstriconv -## begin gnulib module xstrndup +## begin gnulib module xstrtoimax -libgreputils_a_SOURCES += xstrndup.h xstrndup.c +libgreputils_a_SOURCES += xstrtoimax.c -## end gnulib module xstrndup +## end gnulib module xstrtoimax ## begin gnulib module xstrtol @@ -2156,12 +2632,6 @@ EXTRA_DIST += xstrtol.h ## end gnulib module xstrtol -## begin gnulib module xstrtoumax - -libgreputils_a_SOURCES += xstrtoumax.c - -## end gnulib module xstrtoumax - mostlyclean-local: mostlyclean-generic @for dir in '' $(MOSTLYCLEANDIRS); do \ diff --git a/contrib/grep/lib/hard-locale.c b/contrib/grep/lib/hard-locale.c index 26e614b74b..14e41b49b9 100644 --- a/contrib/grep/lib/hard-locale.c +++ b/contrib/grep/lib/hard-locale.c @@ -1,6 +1,6 @@ /* hard-locale.c -- Determine whether a locale is hard. - Copyright (C) 1997-1999, 2002-2004, 2006-2007, 2009-2011 Free Software + Copyright (C) 1997-1999, 2002-2004, 2006-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/hard-locale.h b/contrib/grep/lib/hard-locale.h index 7540628ea3..b081e1cd47 100644 --- a/contrib/grep/lib/hard-locale.h +++ b/contrib/grep/lib/hard-locale.h @@ -1,6 +1,6 @@ /* Determine whether a locale is hard. - Copyright (C) 1999, 2003-2004, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1999, 2003-2004, 2009-2012 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 diff --git a/contrib/grep/lib/hash.c b/contrib/grep/lib/hash.c index 4d76f765e9..19330576fc 100644 --- a/contrib/grep/lib/hash.c +++ b/contrib/grep/lib/hash.c @@ -1,6 +1,6 @@ /* hash - hashing table processing. - Copyright (C) 1998-2004, 2006-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1998-2004, 2006-2007, 2009-2012 Free Software Foundation, Inc. Written by Jim Meyering, 1992. @@ -63,7 +63,7 @@ struct hash_table /* Tuning arguments, kept in a physically separate structure. */ const Hash_tuning *tuning; - /* Three functions are given to `hash_initialize', see the documentation + /* Three functions are given to 'hash_initialize', see the documentation block for this function. In a word, HASHER randomizes a user entry into a number up from 0 up to some maximum minus 1; COMPARATOR returns true if two user entries compare equally; and DATA_FREER is the cleanup @@ -87,23 +87,23 @@ struct hash_table some user-provided data (also called a user entry). An entry indistinctly refers to both the internal entry and its associated user entry. A user entry contents may be hashed by a randomization function (the hashing - function, or just `hasher' for short) into a number (or `slot') between 0 + function, or just "hasher" for short) into a number (or "slot") between 0 and the current table size. At each slot position in the hash table, starts a linked chain of entries for which the user data all hash to this slot. A bucket is the collection of all entries hashing to the same slot. - A good `hasher' function will distribute entries rather evenly in buckets. + A good "hasher" function will distribute entries rather evenly in buckets. In the ideal case, the length of each bucket is roughly the number of entries divided by the table size. Finding the slot for a data is usually - done in constant time by the `hasher', and the later finding of a precise + done in constant time by the "hasher", and the later finding of a precise entry is linear in time with the size of the bucket. Consequently, a larger hash table size (that is, a larger number of buckets) is prone to - yielding shorter chains, *given* the `hasher' function behaves properly. + yielding shorter chains, *given* the "hasher" function behaves properly. Long buckets slow down the lookup algorithm. One might use big hash table sizes in hope to reduce the average length of buckets, but this might become inordinate, as unused slots in the hash table take some space. The - best bet is to make sure you are using a good `hasher' function (beware + best bet is to make sure you are using a good "hasher" function (beware that those are not that easy to write! :-), and to use a table size larger than the actual number of entries. */ @@ -113,8 +113,8 @@ struct hash_table 1.0). The growth threshold defaults to 0.8, and the growth factor defaults to 1.414, meaning that the table will have doubled its size every second time 80% of the buckets get used. */ -#define DEFAULT_GROWTH_THRESHOLD 0.8 -#define DEFAULT_GROWTH_FACTOR 1.414 +#define DEFAULT_GROWTH_THRESHOLD 0.8f +#define DEFAULT_GROWTH_FACTOR 1.414f /* If a deletion empties a bucket and causes the ratio of used buckets to table size to become smaller than the shrink threshold (a number between @@ -122,8 +122,8 @@ struct hash_table number greater than the shrink threshold but smaller than 1.0). The shrink threshold and factor default to 0.0 and 1.0, meaning that the table never shrinks. */ -#define DEFAULT_SHRINK_THRESHOLD 0.0 -#define DEFAULT_SHRINK_FACTOR 1.0 +#define DEFAULT_SHRINK_THRESHOLD 0.0f +#define DEFAULT_SHRINK_FACTOR 1.0f /* Use this to initialize or reset a TUNING structure to some sensible values. */ @@ -300,7 +300,7 @@ hash_get_first (const Hash_table *table) } /* Return the user data for the entry following ENTRY, where ENTRY has been - returned by a previous call to either `hash_get_first' or `hash_get_next'. + returned by a previous call to either 'hash_get_first' or 'hash_get_next'. Return NULL if there are no more entries. */ void * @@ -419,9 +419,9 @@ hash_string (const char *string, size_t n_buckets) #else /* not USE_DIFF_HASH */ -/* This one comes from `recode', and performs a bit better than the above as +/* This one comes from 'recode', and performs a bit better than the above as per a few experiments. It is inspired from a hashing routine found in the - very old Cyber `snoop', itself written in typical Greg Mansfield style. + very old Cyber 'snoop', itself written in typical Greg Mansfield style. (By the way, what happened to this excellent man? Is he still alive?) */ size_t @@ -440,7 +440,7 @@ hash_string (const char *string, size_t n_buckets) /* Return true if CANDIDATE is a prime number. CANDIDATE should be an odd number at least equal to 11. */ -static bool +static bool _GL_ATTRIBUTE_CONST is_prime (size_t candidate) { size_t divisor = 3; @@ -459,7 +459,7 @@ is_prime (size_t candidate) /* Round a given CANDIDATE number up to the nearest prime, and return that prime. Primes lower than 10 are merely skipped. */ -static size_t +static size_t _GL_ATTRIBUTE_CONST next_prime (size_t candidate) { /* Skip small primes. */ @@ -540,7 +540,7 @@ check_tuning (Hash_table *table) TUNING, or return 0 if there is no possible way to allocate that many entries. */ -static size_t +static size_t _GL_ATTRIBUTE_PURE compute_bucket_size (size_t candidate, const Hash_tuning *tuning) { if (!tuning->is_n_buckets) @@ -584,9 +584,9 @@ compute_bucket_size (size_t candidate, const Hash_tuning *tuning) The user-supplied DATA_FREER function, when not NULL, may be later called with the user data as an argument, just before the entry containing the - data gets freed. This happens from within `hash_free' or `hash_clear'. + data gets freed. This happens from within 'hash_free' or 'hash_clear'. You should specify this function only if you want these functions to free - all of your `data' data. This is typically the case when your data is + all of your 'data' data. This is typically the case when your data is simply an auxiliary struct that you have malloc'd to aggregate several values. */ @@ -1018,7 +1018,9 @@ hash_rehash (Hash_table *table, size_t candidate) return false; } -/* Return -1 upon memory allocation failure. +/* Insert ENTRY into hash TABLE if there is not already a matching entry. + + Return -1 upon memory allocation failure. Return 1 if insertion succeeded. Return 0 if there is already a matching entry in the table, and in that case, if MATCHED_ENT is non-NULL, set *MATCHED_ENT @@ -1030,10 +1032,11 @@ hash_rehash (Hash_table *table, size_t candidate) hash_insert, the only way to distinguish those cases is to compare the return value and ENTRY. That works only when you can have two different ENTRY values that point to data that compares "equal". Thus, - when the ENTRY value is a simple scalar, you must use hash_insert0. - ENTRY must not be NULL. */ + when the ENTRY value is a simple scalar, you must use + hash_insert_if_absent. ENTRY must not be NULL. */ int -hash_insert0 (Hash_table *table, void const *entry, void const **matched_ent) +hash_insert_if_absent (Hash_table *table, void const *entry, + void const **matched_ent) { void *data; struct hash_entry *bucket; @@ -1113,6 +1116,14 @@ hash_insert0 (Hash_table *table, void const *entry, void const **matched_ent) return 1; } +/* hash_insert0 is the deprecated name for hash_insert_if_absent. + . */ +int +hash_insert0 (Hash_table *table, void const *entry, void const **matched_ent) +{ + return hash_insert_if_absent (table, entry, matched_ent); +} + /* If ENTRY matches an entry already in the hash table, return the pointer to the entry from the table. Otherwise, insert ENTRY and return ENTRY. Return NULL if the storage required for insertion cannot be allocated. @@ -1123,7 +1134,7 @@ void * hash_insert (Hash_table *table, void const *entry) { void const *matched_ent; - int err = hash_insert0 (table, entry, &matched_ent); + int err = hash_insert_if_absent (table, entry, &matched_ent); return (err == -1 ? NULL : (void *) (err == 0 ? matched_ent : entry)); diff --git a/contrib/grep/lib/hash.h b/contrib/grep/lib/hash.h index 9f694be555..06e303bfbf 100644 --- a/contrib/grep/lib/hash.h +++ b/contrib/grep/lib/hash.h @@ -1,5 +1,5 @@ /* hash - hashing table processing. - Copyright (C) 1998-1999, 2001, 2003, 2009-2011 Free Software Foundation, + Copyright (C) 1998-1999, 2001, 2003, 2009-2012 Free Software Foundation, Inc. Written by Jim Meyering , 1998. @@ -19,7 +19,7 @@ /* A generic hash table package. */ /* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use - obstacks instead of malloc, and recompile `hash.c' with same setting. */ + obstacks instead of malloc, and recompile 'hash.c' with same setting. */ #ifndef HASH_H_ # define HASH_H_ @@ -35,6 +35,16 @@ # define _GL_ATTRIBUTE_WUR /* empty */ # endif +# ifndef _GL_ATTRIBUTE_DEPRECATED +/* The __attribute__((__deprecated__)) feature + is available in gcc versions 3.1 and newer. */ +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1) +# define _GL_ATTRIBUTE_DEPRECATED /* empty */ +# else +# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) +# endif +# endif + typedef size_t (*Hash_hasher) (const void *, size_t); typedef bool (*Hash_comparator) (const void *, const void *); typedef void (*Hash_data_freer) (void *); @@ -42,8 +52,8 @@ typedef bool (*Hash_processor) (void *, void *); struct hash_tuning { - /* This structure is mainly used for `hash_initialize', see the block - documentation of `hash_reset_tuning' for more complete comments. */ + /* This structure is mainly used for 'hash_initialize', see the block + documentation of 'hash_reset_tuning' for more complete comments. */ float shrink_threshold; /* ratio of used buckets to trigger a shrink */ float shrink_factor; /* ratio of new smaller size to original size */ @@ -59,22 +69,22 @@ struct hash_table; typedef struct hash_table Hash_table; /* Information and lookup. */ -size_t hash_get_n_buckets (const Hash_table *); -size_t hash_get_n_buckets_used (const Hash_table *); -size_t hash_get_n_entries (const Hash_table *); -size_t hash_get_max_bucket_length (const Hash_table *); -bool hash_table_ok (const Hash_table *); +size_t hash_get_n_buckets (const Hash_table *) _GL_ATTRIBUTE_PURE; +size_t hash_get_n_buckets_used (const Hash_table *) _GL_ATTRIBUTE_PURE; +size_t hash_get_n_entries (const Hash_table *) _GL_ATTRIBUTE_PURE; +size_t hash_get_max_bucket_length (const Hash_table *) _GL_ATTRIBUTE_PURE; +bool hash_table_ok (const Hash_table *) _GL_ATTRIBUTE_PURE; void hash_print_statistics (const Hash_table *, FILE *); void *hash_lookup (const Hash_table *, const void *); /* Walking. */ -void *hash_get_first (const Hash_table *); +void *hash_get_first (const Hash_table *) _GL_ATTRIBUTE_PURE; void *hash_get_next (const Hash_table *, const void *); size_t hash_get_entries (const Hash_table *, void **, size_t); size_t hash_do_for_each (const Hash_table *, Hash_processor, void *); /* Allocation and clean-up. */ -size_t hash_string (const char *, size_t); +size_t hash_string (const char *, size_t) _GL_ATTRIBUTE_PURE; void hash_reset_tuning (Hash_tuning *); Hash_table *hash_initialize (size_t, const Hash_tuning *, Hash_hasher, Hash_comparator, @@ -85,8 +95,13 @@ void hash_free (Hash_table *); /* Insertion and deletion. */ bool hash_rehash (Hash_table *, size_t) _GL_ATTRIBUTE_WUR; void *hash_insert (Hash_table *, const void *) _GL_ATTRIBUTE_WUR; -int hash_insert0 (Hash_table *table, const void *entry, - const void **matched_ent); + +/* Deprecate this interface. It has been renamed to hash_insert_if_absent. */ +int hash_insert0 (Hash_table *table, /* FIXME: remove in 2013 */ + const void *entry, + const void **matched_ent) _GL_ATTRIBUTE_DEPRECATED; +int hash_insert_if_absent (Hash_table *table, const void *entry, + const void **matched_ent); void *hash_delete (Hash_table *, const void *); #endif diff --git a/contrib/grep/lib/i-ring.c b/contrib/grep/lib/i-ring.c new file mode 100644 index 0000000000..8bd2c541d3 --- /dev/null +++ b/contrib/grep/lib/i-ring.c @@ -0,0 +1,68 @@ +/* a simple ring buffer + Copyright (C) 2006, 2009-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +#include +#include "i-ring.h" + +#include + +void +i_ring_init (I_ring *ir, int default_val) +{ + int i; + ir->ir_empty = true; + ir->ir_front = 0; + ir->ir_back = 0; + for (i = 0; i < I_RING_SIZE; i++) + ir->ir_data[i] = default_val; + ir->ir_default_val = default_val; +} + +bool +i_ring_empty (I_ring const *ir) +{ + return ir->ir_empty; +} + +int +i_ring_push (I_ring *ir, int val) +{ + unsigned int dest_idx = (ir->ir_front + !ir->ir_empty) % I_RING_SIZE; + int old_val = ir->ir_data[dest_idx]; + ir->ir_data[dest_idx] = val; + ir->ir_front = dest_idx; + if (dest_idx == ir->ir_back) + ir->ir_back = (ir->ir_back + !ir->ir_empty) % I_RING_SIZE; + ir->ir_empty = false; + return old_val; +} + +int +i_ring_pop (I_ring *ir) +{ + int top_val; + if (i_ring_empty (ir)) + abort (); + top_val = ir->ir_data[ir->ir_front]; + ir->ir_data[ir->ir_front] = ir->ir_default_val; + if (ir->ir_front == ir->ir_back) + ir->ir_empty = true; + else + ir->ir_front = ((ir->ir_front + I_RING_SIZE - 1) % I_RING_SIZE); + return top_val; +} diff --git a/contrib/grep/lib/i-ring.h b/contrib/grep/lib/i-ring.h new file mode 100644 index 0000000000..9757c84d1e --- /dev/null +++ b/contrib/grep/lib/i-ring.h @@ -0,0 +1,44 @@ +/* definitions for a simple ring buffer + Copyright (C) 2006, 2009-2012 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 of the License, 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 . */ + +#include +#include "verify.h" + +enum { I_RING_SIZE = 4 }; +verify (1 <= I_RING_SIZE); + +/* When ir_empty is true, the ring is empty. + Otherwise, ir_data[B..F] are defined, where B..F is the contiguous + range of indices, modulo I_RING_SIZE, from back to front, inclusive. + Undefined elements of ir_data are always set to ir_default_val. + Popping from an empty ring aborts. + Pushing onto a full ring returns the displaced value. + An empty ring has F==B and ir_empty == true. + A ring with one entry still has F==B, but now ir_empty == false. */ +struct I_ring +{ + int ir_data[I_RING_SIZE]; + int ir_default_val; + unsigned int ir_front; + unsigned int ir_back; + bool ir_empty; +}; +typedef struct I_ring I_ring; + +void i_ring_init (I_ring *ir, int ir_default_val); +int i_ring_push (I_ring *ir, int val); +int i_ring_pop (I_ring *ir); +bool i_ring_empty (I_ring const *ir) _GL_ATTRIBUTE_PURE; diff --git a/contrib/grep/lib/iconv_open.c b/contrib/grep/lib/iconv_open.c index eafcebc332..76536176b0 100644 --- a/contrib/grep/lib/iconv_open.c +++ b/contrib/grep/lib/iconv_open.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Character set conversion. - Copyright (C) 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2007, 2009-2012 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 @@ -14,8 +12,7 @@ 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. */ + with this program; if not, see . */ #include @@ -59,7 +56,7 @@ rpl_iconv_open (const char *tocode, const char *fromcode) iconv() to these encoding inserts a BOM, which is wrong. We do not need to handle conversion between arbitrary encodings and UTF-{16,32}{BE,LE}, because the 'striconveh' module implements two-step - conversion throough UTF-8. + conversion through UTF-8. The _ICONV_* constants are chosen to be disjoint from any iconv_t returned by the system's iconv_open() functions. Recall that iconv_t is a scalar type. */ diff --git a/contrib/grep/lib/ignore-value.h b/contrib/grep/lib/ignore-value.h index f021a1ac8e..52919de8f1 100644 --- a/contrib/grep/lib/ignore-value.h +++ b/contrib/grep/lib/ignore-value.h @@ -1,6 +1,6 @@ /* ignore a function return without a compiler warning - Copyright (C) 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 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 @@ -54,9 +54,4 @@ # define ignore_value(x) (({ __typeof__ (x) __x = (x); (void) __x; })) # endif -/* ignore_value works for scalars, pointers and aggregates; - deprecate ignore_ptr. */ -static inline void _GL_ATTRIBUTE_DEPRECATED -ignore_ptr (void *p) { (void) p; } /* deprecated: use ignore_value */ - #endif diff --git a/contrib/grep/lib/intprops.h b/contrib/grep/lib/intprops.h index 1f6a539c18..2485c78d4b 100644 --- a/contrib/grep/lib/intprops.h +++ b/contrib/grep/lib/intprops.h @@ -1,6 +1,6 @@ /* intprops.h -- properties of integer types - Copyright (C) 2001-2005, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2005, 2009-2012 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 diff --git a/contrib/grep/lib/isatty.c b/contrib/grep/lib/isatty.c new file mode 100644 index 0000000000..2ecdd5494a --- /dev/null +++ b/contrib/grep/lib/isatty.c @@ -0,0 +1,81 @@ +/* isatty() replacement. + Copyright (C) 2012 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include + +/* This replacement is enabled on native Windows. */ + +#include + +/* Get declarations of the Win32 API functions. */ +#define WIN32_LEAN_AND_MEAN +#include + +#include "msvc-inval.h" + +/* Get _get_osfhandle(). */ +#include "msvc-nothrow.h" + +/* Optimized test whether a HANDLE refers to a console. + See . */ +#define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3) + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static inline int +_isatty_nothrow (int fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = _isatty (fd); + } + CATCH_MSVC_INVAL + { + result = 0; + } + DONE_MSVC_INVAL; + + return result; +} +#else +# define _isatty_nothrow _isatty +#endif + +/* Determine whether FD refers to a console device. Return 1 if yes. + Return 0 and set errno if no. (ptsname_r relies on the errno value.) */ +int +isatty (int fd) +{ + HANDLE h = (HANDLE) _get_osfhandle (fd); + if (h == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return 0; + } + /* _isatty (fd) tests whether GetFileType of the handle is FILE_TYPE_CHAR. + But it does not set errno when it returns 0. */ + if (_isatty_nothrow (fd)) + { + if (IsConsoleHandle (h)) + return 1; + } + errno = ENOTTY; + return 0; +} diff --git a/contrib/grep/lib/isblank.c b/contrib/grep/lib/isblank.c index 65cc54f854..63ff34f0f0 100644 --- a/contrib/grep/lib/isblank.c +++ b/contrib/grep/lib/isblank.c @@ -1,6 +1,6 @@ /* Test whether a character is a blank. - Copyright (C) 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 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 diff --git a/contrib/grep/lib/isdir.c b/contrib/grep/lib/isdir.c deleted file mode 100644 index 77cd7a2699..0000000000 --- a/contrib/grep/lib/isdir.c +++ /dev/null @@ -1,33 +0,0 @@ -/* isdir.c -- determine whether a directory exists - - Copyright (C) 1990, 1998, 2006, 2009-2011 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 of the License, 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 . */ - -#include - -#include "isdir.h" - -#include -#include - -/* If PATH is an existing directory or symbolic link to a directory, - return nonzero, else 0. */ -int -isdir (const char *path) -{ - struct stat stats; - - return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode); -} diff --git a/contrib/grep/lib/isdir.h b/contrib/grep/lib/isdir.h deleted file mode 100644 index 80116bc6be..0000000000 --- a/contrib/grep/lib/isdir.h +++ /dev/null @@ -1 +0,0 @@ -int isdir (const char *path); diff --git a/contrib/grep/lib/wctomb.c b/contrib/grep/lib/iswctype-impl.h similarity index 76% copy from contrib/grep/lib/wctomb.c copy to contrib/grep/lib/iswctype-impl.h index 889a3c6fff..04bc46b8dc 100644 --- a/contrib/grep/lib/wctomb.c +++ b/contrib/grep/lib/iswctype-impl.h @@ -1,5 +1,5 @@ -/* Convert wide character to multibyte character. - Copyright (C) 2011 Free Software Foundation, Inc. +/* Test whether a wide character has a given property. + Copyright (C) 2011-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2011. This program is free software: you can redistribute it and/or modify @@ -15,11 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include - -#include - -#include -#include - -#include "wctomb-impl.h" +int +iswctype (wint_t wc, wctype_t desc) +{ + return ((int (*) (wint_t)) desc) (wc); +} diff --git a/contrib/grep/lib/wctomb.c b/contrib/grep/lib/iswctype.c similarity index 79% copy from contrib/grep/lib/wctomb.c copy to contrib/grep/lib/iswctype.c index 889a3c6fff..e7c6317f76 100644 --- a/contrib/grep/lib/wctomb.c +++ b/contrib/grep/lib/iswctype.c @@ -1,5 +1,5 @@ -/* Convert wide character to multibyte character. - Copyright (C) 2011 Free Software Foundation, Inc. +/* Test whether a wide character has a given property. + Copyright (C) 2011-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2011. This program is free software: you can redistribute it and/or modify @@ -17,9 +17,7 @@ #include -#include +/* Specification. */ +#include -#include -#include - -#include "wctomb-impl.h" +#include "iswctype-impl.h" diff --git a/contrib/grep/lib/localcharset.c b/contrib/grep/lib/localcharset.c index d8b5953c23..113205dea4 100644 --- a/contrib/grep/lib/localcharset.c +++ b/contrib/grep/lib/localcharset.c @@ -1,8 +1,6 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Determine a canonical name for the current locale's character encoding. - Copyright (C) 2000-2006, 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2000-2006, 2008-2012 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 @@ -15,8 +13,7 @@ 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. */ + with this program; if not, see . */ /* Written by Bruno Haible . */ @@ -36,7 +33,7 @@ #endif #if defined _WIN32 || defined __WIN32__ -# define WIN32_NATIVE +# define WINDOWS_NATIVE #endif #if defined __EMX__ @@ -46,7 +43,7 @@ # endif #endif -#if !defined WIN32_NATIVE +#if !defined WINDOWS_NATIVE # include # if HAVE_LANGINFO_CODESET # include @@ -59,7 +56,7 @@ # define WIN32_LEAN_AND_MEAN # include # endif -#elif defined WIN32_NATIVE +#elif defined WINDOWS_NATIVE # define WIN32_LEAN_AND_MEAN # include #endif @@ -85,7 +82,7 @@ #endif #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ - /* Win32, Cygwin, OS/2, DOS */ + /* Native Windows, Cygwin, OS/2, DOS */ # define ISSLASH(C) ((C) == '/' || (C) == '\\') #endif @@ -125,7 +122,7 @@ get_charset_aliases (void) cp = charset_aliases; if (cp == NULL) { -#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__) +#if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__) const char *dir; const char *base = "charset.alias"; char *file_name; @@ -310,7 +307,7 @@ get_charset_aliases (void) "DECKOREAN" "\0" "EUC-KR" "\0"; # endif -# if defined WIN32_NATIVE || defined __CYGWIN__ +# if defined WINDOWS_NATIVE || defined __CYGWIN__ /* To avoid the troubles of installing a separate file in the same directory as the DLL and of retrieving the DLL's directory at runtime, simply inline the aliases here. */ @@ -362,7 +359,7 @@ locale_charset (void) const char *codeset; const char *aliases; -#if !(defined WIN32_NATIVE || defined OS2) +#if !(defined WINDOWS_NATIVE || defined OS2) # if HAVE_LANGINFO_CODESET @@ -409,10 +406,10 @@ locale_charset (void) } } - /* Woe32 has a function returning the locale's codepage as a number: - GetACP(). This encoding is used by Cygwin, unless the user has set - the environment variable CYGWIN=codepage:oem (which very few people - do). + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). This encoding is used by Cygwin, unless the user + has set the environment variable CYGWIN=codepage:oem (which very few + people do). Output directed to console windows needs to be converted (to GetOEMCP() if the console is using a raster font, or to GetConsoleOutputCP() if it is using a TrueType font). Cygwin does @@ -455,12 +452,12 @@ locale_charset (void) # endif -#elif defined WIN32_NATIVE +#elif defined WINDOWS_NATIVE static char buf[2 + 10 + 1]; - /* Woe32 has a function returning the locale's codepage as a number: - GetACP(). + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). When the output goes to a console window, it needs to be provided in GetOEMCP() encoding if the console is using a raster font, or in GetConsoleOutputCP() encoding if it is using a TrueType font. diff --git a/contrib/grep/lib/localcharset.h b/contrib/grep/lib/localcharset.h index 53c8a948b9..39dc593995 100644 --- a/contrib/grep/lib/localcharset.h +++ b/contrib/grep/lib/localcharset.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Determine a canonical name for the current locale's character encoding. - Copyright (C) 2000-2003, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2000-2003, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU CHARSET Library. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + with this program; if not, see . */ #ifndef _LOCALCHARSET_H #define _LOCALCHARSET_H diff --git a/contrib/grep/lib/localeconv.c b/contrib/grep/lib/localeconv.c new file mode 100644 index 0000000000..2c91b374f0 --- /dev/null +++ b/contrib/grep/lib/localeconv.c @@ -0,0 +1,103 @@ +/* Query locale dependent information for formatting numbers. + Copyright (C) 2012 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include + +#if HAVE_STRUCT_LCONV_DECIMAL_POINT + +/* Override for platforms where 'struct lconv' lacks the int_p_*, int_n_* + members. */ + +struct lconv * +localeconv (void) +{ + static struct lconv result; +# undef lconv +# undef localeconv + struct lconv *sys_result = localeconv (); + + result.decimal_point = sys_result->decimal_point; + result.thousands_sep = sys_result->thousands_sep; + result.grouping = sys_result->grouping; + result.mon_decimal_point = sys_result->mon_decimal_point; + result.mon_thousands_sep = sys_result->mon_thousands_sep; + result.mon_grouping = sys_result->mon_grouping; + result.positive_sign = sys_result->positive_sign; + result.negative_sign = sys_result->negative_sign; + result.currency_symbol = sys_result->currency_symbol; + result.frac_digits = sys_result->frac_digits; + result.p_cs_precedes = sys_result->p_cs_precedes; + result.p_sign_posn = sys_result->p_sign_posn; + result.p_sep_by_space = sys_result->p_sep_by_space; + result.n_cs_precedes = sys_result->n_cs_precedes; + result.n_sign_posn = sys_result->n_sign_posn; + result.n_sep_by_space = sys_result->n_sep_by_space; + result.int_curr_symbol = sys_result->int_curr_symbol; + result.int_frac_digits = sys_result->int_frac_digits; + result.int_p_cs_precedes = sys_result->p_cs_precedes; + result.int_p_sign_posn = sys_result->p_sign_posn; + result.int_p_sep_by_space = sys_result->p_sep_by_space; + result.int_n_cs_precedes = sys_result->n_cs_precedes; + result.int_n_sign_posn = sys_result->n_sign_posn; + result.int_n_sep_by_space = sys_result->n_sep_by_space; + + return &result; +} + +#else + +/* Override for platforms where 'struct lconv' is a dummy. */ + +# include + +struct lconv * +localeconv (void) +{ + static /*const*/ struct lconv result = + { + /* decimal_point */ ".", + /* thousands_sep */ "", + /* grouping */ "", + /* mon_decimal_point */ "", + /* mon_thousands_sep */ "", + /* mon_grouping */ "", + /* positive_sign */ "", + /* negative_sign */ "", + /* currency_symbol */ "", + /* frac_digits */ CHAR_MAX, + /* p_cs_precedes */ CHAR_MAX, + /* p_sign_posn */ CHAR_MAX, + /* p_sep_by_space */ CHAR_MAX, + /* n_cs_precedes */ CHAR_MAX, + /* n_sign_posn */ CHAR_MAX, + /* n_sep_by_space */ CHAR_MAX, + /* int_curr_symbol */ "", + /* int_frac_digits */ CHAR_MAX, + /* int_p_cs_precedes */ CHAR_MAX, + /* int_p_sign_posn */ CHAR_MAX, + /* int_p_sep_by_space */ CHAR_MAX, + /* int_n_cs_precedes */ CHAR_MAX, + /* int_n_sign_posn */ CHAR_MAX, + /* int_n_sep_by_space */ CHAR_MAX + }; + + return &result; +} + +#endif diff --git a/contrib/grep/lib/lseek.c b/contrib/grep/lib/lseek.c index b33a75686b..794c230447 100644 --- a/contrib/grep/lib/lseek.c +++ b/contrib/grep/lib/lseek.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* An lseek() function that detects pipes. - Copyright (C) 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2007, 2009-2012 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 @@ -14,8 +12,7 @@ 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. */ + with this program; if not, see . */ #include @@ -26,6 +23,8 @@ /* Windows platforms. */ /* Get GetFileType. */ # include +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" #else # include #endif @@ -60,5 +59,9 @@ rpl_lseek (int fd, off_t offset, int whence) return -1; } #endif +#if _GL_WINDOWS_64_BIT_OFF_T + return _lseeki64 (fd, offset, whence); +#else return lseek (fd, offset, whence); +#endif } diff --git a/contrib/grep/lib/lstat.c b/contrib/grep/lib/lstat.c new file mode 100644 index 0000000000..db119a10d3 --- /dev/null +++ b/contrib/grep/lib/lstat.c @@ -0,0 +1,97 @@ +/* Work around a bug of lstat on some systems + + Copyright (C) 1997-2006, 2008-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_lstat doesn't recurse to + rpl_lstat. */ +#define __need_system_sys_stat_h +#include + +#if !HAVE_LSTAT +/* On systems that lack symlinks, our replacement already + defined lstat as stat, so there is nothing further to do other than + avoid an empty file. */ +typedef int dummy; +#else /* HAVE_LSTAT */ + +/* Get the original definition of lstat. It might be defined as a macro. */ +# include +# include +# undef __need_system_sys_stat_h + +static inline int +orig_lstat (const char *filename, struct stat *buf) +{ + return lstat (filename, buf); +} + +/* Specification. */ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +# include "sys/stat.h" + +# include +# include + +/* lstat works differently on Linux and Solaris systems. POSIX (see + "pathname resolution" in the glossary) requires that programs like + 'ls' take into consideration the fact that FILE has a trailing slash + when FILE is a symbolic link. On Linux and Solaris 10 systems, the + lstat function already has the desired semantics (in treating + 'lstat ("symlink/", sbuf)' just like 'lstat ("symlink/.", sbuf)', + but on Solaris 9 and earlier it does not. + + If FILE has a trailing slash and specifies a symbolic link, + then use stat() to get more info on the referent of FILE. + If the referent is a non-directory, then set errno to ENOTDIR + and return -1. Otherwise, return stat's result. */ + +int +rpl_lstat (const char *file, struct stat *sbuf) +{ + size_t len; + int lstat_result = orig_lstat (file, sbuf); + + if (lstat_result != 0) + return lstat_result; + + /* This replacement file can blindly check against '/' rather than + using the ISSLASH macro, because all platforms with '\\' either + lack symlinks (mingw) or have working lstat (cygwin) and thus do + not compile this file. 0 len should have already been filtered + out above, with a failure return of ENOENT. */ + len = strlen (file); + if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode)) + return 0; + + /* At this point, a trailing slash is only permitted on + symlink-to-dir; but it should have found information on the + directory, not the symlink. Call stat() to get info about the + link's referent. Our replacement stat guarantees valid results, + even if the symlink is not pointing to a directory. */ + if (!S_ISLNK (sbuf->st_mode)) + { + errno = ENOTDIR; + return -1; + } + return stat (file, sbuf); +} + +#endif /* HAVE_LSTAT */ diff --git a/contrib/grep/lib/malloc.c b/contrib/grep/lib/malloc.c index 7d2c09092a..e0d5c89d18 100644 --- a/contrib/grep/lib/malloc.c +++ b/contrib/grep/lib/malloc.c @@ -1,8 +1,6 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* malloc() function that is glibc compatible. - Copyright (C) 1997-1998, 2006-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1997-1998, 2006-2007, 2009-2012 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 @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ /* written by Jim Meyering and Bruno Haible */ diff --git a/contrib/grep/lib/malloca.c b/contrib/grep/lib/malloca.c index 11482c5078..1f7533a7d3 100644 --- a/contrib/grep/lib/malloca.c +++ b/contrib/grep/lib/malloca.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Safe automatic memory allocation. - Copyright (C) 2003, 2006-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2003, 2006-2007, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ #define _GL_USE_STDLIB_ALLOC 1 #include @@ -24,6 +21,8 @@ /* Specification. */ #include "malloca.h" +#include + #include "verify.h" /* The speed critical point in this file is freea() applied to an alloca() @@ -87,7 +86,7 @@ mmalloca (size_t n) ((int *) p)[-1] = MAGIC_NUMBER; /* Enter p into the hash table. */ - slot = (unsigned long) p % HASH_TABLE_SIZE; + slot = (uintptr_t) p % HASH_TABLE_SIZE; ((struct header *) (p - HEADER_SIZE))->next = mmalloca_results[slot]; mmalloca_results[slot] = p; @@ -120,7 +119,7 @@ freea (void *p) { /* Looks like a mmalloca() result. To see whether it really is one, perform a lookup in the hash table. */ - size_t slot = (unsigned long) p % HASH_TABLE_SIZE; + size_t slot = (uintptr_t) p % HASH_TABLE_SIZE; void **chain = &mmalloca_results[slot]; for (; *chain != NULL;) { diff --git a/contrib/grep/lib/malloca.h b/contrib/grep/lib/malloca.h index 933fa7ec70..0cedf5f633 100644 --- a/contrib/grep/lib/malloca.h +++ b/contrib/grep/lib/malloca.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Safe automatic memory allocation. - Copyright (C) 2003-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2003-2007, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ #ifndef _MALLOCA_H #define _MALLOCA_H diff --git a/contrib/grep/lib/mbchar.c b/contrib/grep/lib/mbchar.c index c9b0dcdce8..10709510a2 100644 --- a/contrib/grep/lib/mbchar.c +++ b/contrib/grep/lib/mbchar.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2006, 2009-2011 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006, 2009-2012 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 diff --git a/contrib/grep/lib/mbchar.h b/contrib/grep/lib/mbchar.h index 6dcb6cfa60..ccbcb827e5 100644 --- a/contrib/grep/lib/mbchar.h +++ b/contrib/grep/lib/mbchar.h @@ -1,5 +1,5 @@ /* Multibyte character data type. - Copyright (C) 2001, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001, 2005-2007, 2009-2012 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 diff --git a/contrib/grep/lib/mbiter.h b/contrib/grep/lib/mbiter.h index 38cf6b1afe..5419a67abc 100644 --- a/contrib/grep/lib/mbiter.h +++ b/contrib/grep/lib/mbiter.h @@ -1,5 +1,5 @@ /* Iterating through multibyte strings: macros for multi-byte encodings. - Copyright (C) 2001, 2005, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001, 2005, 2007, 2009-2012 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 @@ -47,9 +47,9 @@ initializes the iterator, starting at startptr and crossing length bytes. mbi_avail (iter) - returns true if there are more multibyte chracters available before + returns true if there are more multibyte characters available before the end of string is reached. In this case, mbi_cur (iter) is - initialized to the next multibyte chracter. + initialized to the next multibyte character. mbi_advance (iter) advances the iterator by one multibyte character. diff --git a/contrib/grep/lib/mbrlen.c b/contrib/grep/lib/mbrlen.c index 54d2c88f7b..f52e76042b 100644 --- a/contrib/grep/lib/mbrlen.c +++ b/contrib/grep/lib/mbrlen.c @@ -1,5 +1,5 @@ /* Recognize multibyte character. - Copyright (C) 1999-2000, 2008-2011 Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2008-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/mbrtowc.c b/contrib/grep/lib/mbrtowc.c index 7a8e5996d0..e3f354beed 100644 --- a/contrib/grep/lib/mbrtowc.c +++ b/contrib/grep/lib/mbrtowc.c @@ -1,5 +1,5 @@ /* Convert multibyte character to wide character. - Copyright (C) 1999-2002, 2005-2011 Free Software Foundation, Inc. + Copyright (C) 1999-2002, 2005-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify @@ -128,7 +128,7 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) { const char *encoding = locale_charset (); - if (STREQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) + if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) { /* Cf. unistr/u8-mblen.c. */ unsigned char c = (unsigned char) p[0]; @@ -185,7 +185,8 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) /* As a reference for this code, you can use the GNU libiconv implementation. Look for uses of the RET_TOOFEW macro. */ - if (STREQ (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0)) + if (STREQ_OPT (encoding, + "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0)) { if (m == 1) { @@ -208,9 +209,12 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } goto invalid; } - if (STREQ (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) - || STREQ (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) - || STREQ (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0)) + if (STREQ_OPT (encoding, + "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, + "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, + "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0)) { if (m == 1) { @@ -221,7 +225,8 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } goto invalid; } - if (STREQ (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)) + if (STREQ_OPT (encoding, + "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)) { if (m == 1) { @@ -239,7 +244,8 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } goto invalid; } - if (STREQ (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0)) + if (STREQ_OPT (encoding, + "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0)) { if (m == 1) { @@ -272,7 +278,7 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } goto invalid; } - if (STREQ (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0)) + if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0)) { if (m == 1) { diff --git a/contrib/grep/lib/mbscasecmp.c b/contrib/grep/lib/mbscasecmp.c index dfff49c379..863bf0ad29 100644 --- a/contrib/grep/lib/mbscasecmp.c +++ b/contrib/grep/lib/mbscasecmp.c @@ -1,5 +1,5 @@ /* Case-insensitive string comparison function. - Copyright (C) 1998-1999, 2005-2011 Free Software Foundation, Inc. + Copyright (C) 1998-1999, 2005-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2005, based on earlier glibc code. diff --git a/contrib/grep/lib/mbsinit.c b/contrib/grep/lib/mbsinit.c index 8ac213703a..638142e8ba 100644 --- a/contrib/grep/lib/mbsinit.c +++ b/contrib/grep/lib/mbsinit.c @@ -1,5 +1,5 @@ /* Test for initial conversion state. - Copyright (C) 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/mbslen.c b/contrib/grep/lib/mbslen.c index efddd52454..a829ff545c 100644 --- a/contrib/grep/lib/mbslen.c +++ b/contrib/grep/lib/mbslen.c @@ -1,5 +1,5 @@ /* Counting the multibyte characters in a string. - Copyright (C) 2007-2011 Free Software Foundation, Inc. + Copyright (C) 2007-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2007. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/mbsrtowcs-state.c b/contrib/grep/lib/mbsrtowcs-state.c index 91073b5eb0..bf246eb45f 100644 --- a/contrib/grep/lib/mbsrtowcs-state.c +++ b/contrib/grep/lib/mbsrtowcs-state.c @@ -1,5 +1,5 @@ /* Convert string to wide string. - Copyright (C) 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/mbsrtowcs.c b/contrib/grep/lib/mbsrtowcs.c index 69e6dfffb8..e3ec8767c3 100644 --- a/contrib/grep/lib/mbsrtowcs.c +++ b/contrib/grep/lib/mbsrtowcs.c @@ -1,5 +1,5 @@ /* Convert string to wide string. - Copyright (C) 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/mbsstr.c b/contrib/grep/lib/mbsstr.c index 611000e6dd..464fb7d6c9 100644 --- a/contrib/grep/lib/mbsstr.c +++ b/contrib/grep/lib/mbsstr.c @@ -1,5 +1,5 @@ /* Searching in a string. - Copyright (C) 2005-2011 Free Software Foundation, Inc. + Copyright (C) 2005-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2005. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/mbuiter.h b/contrib/grep/lib/mbuiter.h index 178f36eeaa..44b617371b 100644 --- a/contrib/grep/lib/mbuiter.h +++ b/contrib/grep/lib/mbuiter.h @@ -1,5 +1,5 @@ /* Iterating through multibyte strings: macros for multi-byte encodings. - Copyright (C) 2001, 2005, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001, 2005, 2007, 2009-2012 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 @@ -55,9 +55,9 @@ initializes the iterator, starting at startptr. mbui_avail (iter) - returns true if there are more multibyte chracters available before + returns true if there are more multibyte characters available before the end of string is reached. In this case, mbui_cur (iter) is - initialized to the next multibyte chracter. + initialized to the next multibyte character. mbui_advance (iter) advances the iterator by one multibyte character. diff --git a/contrib/grep/lib/memchr.c b/contrib/grep/lib/memchr.c index 6d903b1014..b8fb0efb95 100644 --- a/contrib/grep/lib/memchr.c +++ b/contrib/grep/lib/memchr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2011 +/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2012 Free Software Foundation, Inc. Based on strlen implementation by Torbjorn Granlund (tege@sics.se), diff --git a/contrib/grep/lib/mempcpy.c b/contrib/grep/lib/mempcpy.c index 02ed566276..a97fe42295 100644 --- a/contrib/grep/lib/mempcpy.c +++ b/contrib/grep/lib/mempcpy.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Copy memory area and return pointer after last written byte. - Copyright (C) 2003, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2009-2012 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 @@ -14,8 +12,7 @@ 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. */ + along with this program; if not, see . */ #include diff --git a/contrib/grep/lib/memchr.c b/contrib/grep/lib/memrchr.c similarity index 75% copy from contrib/grep/lib/memchr.c copy to contrib/grep/lib/memrchr.c index 6d903b1014..8f2edeb3e4 100644 --- a/contrib/grep/lib/memchr.c +++ b/contrib/grep/lib/memrchr.c @@ -1,5 +1,7 @@ -/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2011 - Free Software Foundation, Inc. +/* memrchr -- find the last occurrence of a byte in a memory block + + Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2012 Free Software + Foundation, Inc. Based on strlen implementation by Torbjorn Granlund (tege@sics.se), with help from Dan Sahlin (dan@sics.se) and @@ -7,56 +9,41 @@ adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), and implemented by Roland McGrath (roland@ai.mit.edu). -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@prep.ai.mit.edu. - -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 of the License, or 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 . */ + 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 of the License, or + (at your option) any later version. -#ifndef _LIBC -# include -#endif - -#include + 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. -#include + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #if defined _LIBC # include #else +# include # define reg_char char #endif +#include #include -#if HAVE_BP_SYM_H || defined _LIBC -# include -#else -# define BP_SYM(sym) sym -#endif - -#undef __memchr +#undef __memrchr #ifdef _LIBC -# undef memchr +# undef memrchr #endif #ifndef weak_alias -# define __memchr memchr +# define __memrchr memrchr #endif /* Search no more than N bytes of S for C. */ void * -__memchr (void const *s, int c_in, size_t n) +__memrchr (void const *s, int c_in, size_t n) { /* On 32-bit hardware, choosing longword to be a 32-bit unsigned long instead of a 64-bit uintmax_t tends to give better @@ -73,12 +60,12 @@ __memchr (void const *s, int c_in, size_t n) c = (unsigned char) c_in; - /* Handle the first few bytes by reading one byte at a time. + /* Handle the last few bytes by reading one byte at a time. Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s; + for (char_ptr = (const unsigned char *) s + n; n > 0 && (size_t) char_ptr % sizeof (longword) != 0; - --n, ++char_ptr) - if (*char_ptr == c) + --n) + if (*--char_ptr == c) return (void *) char_ptr; longword_ptr = (const longword *) char_ptr; @@ -141,12 +128,14 @@ __memchr (void const *s, int c_in, size_t n) while (n >= sizeof (longword)) { - longword longword1 = *longword_ptr ^ repeated_c; + longword longword1 = *--longword_ptr ^ repeated_c; if ((((longword1 - repeated_one) & ~longword1) & (repeated_one << 7)) != 0) - break; - longword_ptr++; + { + longword_ptr++; + break; + } n -= sizeof (longword); } @@ -159,14 +148,14 @@ __memchr (void const *s, int c_in, size_t n) iteration. But this does not work on big-endian machines. Choose code that works in both cases. */ - for (; n > 0; --n, ++char_ptr) + while (n-- > 0) { - if (*char_ptr == c) + if (*--char_ptr == c) return (void *) char_ptr; } return NULL; } #ifdef weak_alias -weak_alias (__memchr, BP_SYM (memchr)) +weak_alias (__memrchr, memrchr) #endif diff --git a/contrib/grep/lib/minmax.h b/contrib/grep/lib/minmax.h index cb2f327cc0..75a9b3cc7e 100644 --- a/contrib/grep/lib/minmax.h +++ b/contrib/grep/lib/minmax.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* MIN, MAX macros. - Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2011 Free Software + Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ #ifndef _MINMAX_H #define _MINMAX_H diff --git a/contrib/grep/lib/msvc-inval.c b/contrib/grep/lib/msvc-inval.c new file mode 100644 index 0000000000..ba76a7ea66 --- /dev/null +++ b/contrib/grep/lib/msvc-inval.c @@ -0,0 +1,129 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2012 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 . */ + +#include + +/* Specification. */ +#include "msvc-inval.h" + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) + +/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler + declaration. */ +# include + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING + +static void cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ +} + +# else + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +# if defined _MSC_VER + +static void cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# else + +/* An index to thread-local storage. */ +static DWORD tls_index; +static int tls_initialized /* = 0 */; + +/* Used as a fallback only. */ +static struct gl_msvc_inval_per_thread not_per_thread; + +struct gl_msvc_inval_per_thread * +gl_msvc_inval_current (void) +{ + if (!tls_initialized) + { + tls_index = TlsAlloc (); + tls_initialized = 1; + } + if (tls_index == TLS_OUT_OF_INDEXES) + /* TlsAlloc had failed. */ + return ¬_per_thread; + else + { + struct gl_msvc_inval_per_thread *pointer = + (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); + if (pointer == NULL) + { + /* First call. Allocate a new 'struct gl_msvc_inval_per_thread'. */ + pointer = + (struct gl_msvc_inval_per_thread *) + malloc (sizeof (struct gl_msvc_inval_per_thread)); + if (pointer == NULL) + /* Could not allocate memory. Use the global storage. */ + pointer = ¬_per_thread; + TlsSetValue (tls_index, pointer); + } + return pointer; + } +} + +static void cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); + if (current->restart_valid) + longjmp (current->restart, 1); + else + /* An invalid parameter notification from outside the gnulib code. + Give the caller a chance to intervene. */ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# endif + +# endif + +static int gl_msvc_inval_initialized /* = 0 */; + +void +gl_msvc_inval_ensure_handler (void) +{ + if (gl_msvc_inval_initialized == 0) + { + _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); + gl_msvc_inval_initialized = 1; + } +} + +#endif diff --git a/contrib/grep/lib/msvc-inval.h b/contrib/grep/lib/msvc-inval.h new file mode 100644 index 0000000000..eb6930b1c6 --- /dev/null +++ b/contrib/grep/lib/msvc-inval.h @@ -0,0 +1,222 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2012 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 . */ + +#ifndef _MSVC_INVAL_H +#define _MSVC_INVAL_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines macros that turn such an invalid parameter notification + into a non-local exit. An error code can then be produced at the target + of this exit. You can thus write code like + + TRY_MSVC_INVAL + { + + } + CATCH_MSVC_INVAL + { + + } + DONE_MSVC_INVAL; + + This entire block expands to a single statement. + + The handling of invalid parameters can be done in three ways: + + * The default way, which is reasonable for programs (not libraries): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [DEFAULT_HANDLING]) + + * The way for libraries that make "hairy" calls (like close(-1), or + fclose(fp) where fileno(fp) is closed, or simply getdtablesize()): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [HAIRY_LIBRARY_HANDLING]) + + * The way for libraries that make no "hairy" calls: + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [SANE_LIBRARY_HANDLING]) + */ + +#define DEFAULT_HANDLING 0 +#define HAIRY_LIBRARY_HANDLING 1 +#define SANE_LIBRARY_HANDLING 2 + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) +/* A native Windows platform with the "invalid parameter handler" concept, + and either DEFAULT_HANDLING or HAIRY_LIBRARY_HANDLING. */ + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING +/* Default handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that just returns. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Handling for hairy libraries. */ + +# include + +/* Gnulib can define its own status codes, as described in the page + "Raising Software Exceptions" on microsoft.com + . + Our status codes are composed of + - 0xE0000000, mandatory for all user-defined status codes, + - 0x474E550, a API identifier ("GNU"), + - 0, 1, 2, ..., used to distinguish different status codes from the + same API. */ +# define STATUS_GNULIB_INVALID_PARAMETER (0xE0000000 + 0x474E550 + 0) + +# if defined _MSC_VER +/* A compiler that supports __try/__except, as described in the page + "try-except statement" on microsoft.com + . + With __try/__except, we can use the multithread-safe exception handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + __try +# define CATCH_MSVC_INVAL \ + __except (GetExceptionCode () == STATUS_GNULIB_INVALID_PARAMETER \ + ? EXCEPTION_EXECUTE_HANDLER \ + : EXCEPTION_CONTINUE_SEARCH) +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Any compiler. + We can only use setjmp/longjmp. */ + +# include + +# ifdef __cplusplus +extern "C" { +# endif + +struct gl_msvc_inval_per_thread +{ + /* The restart that will resume execution at the code between + CATCH_MSVC_INVAL and DONE_MSVC_INVAL. It is enabled only between + TRY_MSVC_INVAL and CATCH_MSVC_INVAL. */ + jmp_buf restart; + + /* Tells whether the contents of restart is valid. */ + int restart_valid; +}; + +/* Ensure that the invalid parameter handler in installed that passes + control to the gl_msvc_inval_restart if it is valid, or raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER otherwise. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +/* Return a pointer to the per-thread data for the current thread. */ +extern struct gl_msvc_inval_per_thread *gl_msvc_inval_current (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + struct gl_msvc_inval_per_thread *msvc_inval_current; \ + gl_msvc_inval_ensure_handler (); \ + msvc_inval_current = gl_msvc_inval_current (); \ + /* First, initialize gl_msvc_inval_restart. */ \ + if (setjmp (msvc_inval_current->restart) == 0) \ + { \ + /* Then, mark it as valid. */ \ + msvc_inval_current->restart_valid = 1; +# define CATCH_MSVC_INVAL \ + /* Execution completed. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; \ + } \ + else \ + { \ + /* Execution triggered an invalid parameter notification. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; +# define DONE_MSVC_INVAL \ + } \ + } \ + while (0) + +# endif + +# endif + +#else +/* A platform that does not need to the invalid parameter handler, + or when SANE_LIBRARY_HANDLING is desired. */ + +/* The braces here avoid GCC warnings like + "warning: suggest explicit braces to avoid ambiguous 'else'". */ +# define TRY_MSVC_INVAL \ + do \ + { \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +#endif + +#endif /* _MSVC_INVAL_H */ diff --git a/contrib/grep/lib/msvc-nothrow.c b/contrib/grep/lib/msvc-nothrow.c new file mode 100644 index 0000000000..e5cf181a04 --- /dev/null +++ b/contrib/grep/lib/msvc-nothrow.c @@ -0,0 +1,49 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2012 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 . */ + +#include + +/* Specification. */ +#include "msvc-nothrow.h" + +/* Get declarations of the native Windows API functions. */ +#define WIN32_LEAN_AND_MEAN +#include + +#include "msvc-inval.h" + +#undef _get_osfhandle + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +intptr_t +_gl_nothrow_get_osfhandle (int fd) +{ + intptr_t result; + + TRY_MSVC_INVAL + { + result = _get_osfhandle (fd); + } + CATCH_MSVC_INVAL + { + result = (intptr_t) INVALID_HANDLE_VALUE; + } + DONE_MSVC_INVAL; + + return result; +} +#endif diff --git a/contrib/grep/lib/msvc-nothrow.h b/contrib/grep/lib/msvc-nothrow.h new file mode 100644 index 0000000000..2b71945b0b --- /dev/null +++ b/contrib/grep/lib/msvc-nothrow.h @@ -0,0 +1,43 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2012 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 . */ + +#ifndef _MSVC_NOTHROW_H +#define _MSVC_NOTHROW_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines wrappers that turn such an invalid parameter notification + into an error code. */ + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Get original declaration of _get_osfhandle. */ +# include + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER + +/* Override _get_osfhandle. */ +extern intptr_t _gl_nothrow_get_osfhandle (int fd); +# define _get_osfhandle _gl_nothrow_get_osfhandle + +# endif + +#endif + +#endif /* _MSVC_NOTHROW_H */ diff --git a/contrib/grep/lib/nl_langinfo.c b/contrib/grep/lib/nl_langinfo.c index 8406ff1912..c73c76982c 100644 --- a/contrib/grep/lib/nl_langinfo.c +++ b/contrib/grep/lib/nl_langinfo.c @@ -1,6 +1,6 @@ /* nl_langinfo() replacement: query locale dependent information. - Copyright (C) 2007-2011 Free Software Foundation, Inc. + Copyright (C) 2007-2012 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 @@ -141,7 +141,8 @@ nl_langinfo (nl_item item) { static char buf[2 + 10 + 1]; - /* Woe32 has a function returning the locale's codepage as a number. */ + /* The Windows API has a function returning the locale's codepage as + a number. */ sprintf (buf, "CP%u", GetACP ()); return buf; } diff --git a/contrib/grep/lib/obstack.c b/contrib/grep/lib/obstack.c index f31a2e999c..fc50f1e4a8 100644 --- a/contrib/grep/lib/obstack.c +++ b/contrib/grep/lib/obstack.c @@ -1,6 +1,6 @@ /* obstack.c - subroutines used implicitly by object stack macros - Copyright (C) 1988-1994, 1996-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1988-1994, 1996-2006, 2009-2012 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 @@ -34,7 +34,7 @@ C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object + program understand 'configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #include /* Random thing to get __GNU_LIBRARY__. */ @@ -74,23 +74,23 @@ enum /* When we copy a long block of data, this is the unit to do it with. On some machines, copying successive ints does not work; - in such a case, redefine COPYING_UNIT to `long' (if that works) - or `char' as a last resort. */ + in such a case, redefine COPYING_UNIT to 'long' (if that works) + or 'char' as a last resort. */ # ifndef COPYING_UNIT # define COPYING_UNIT int # endif -/* The functions allocating more room by calling `obstack_chunk_alloc' - jump to the handler pointed to by `obstack_alloc_failed_handler'. +/* The functions allocating more room by calling 'obstack_chunk_alloc' + jump to the handler pointed to by 'obstack_alloc_failed_handler'. This can be set to a user defined function which should either abort gracefully or use longjump - but shouldn't return. This variable by default points to the internal function - `print_and_abort'. */ -static void print_and_abort (void); + 'print_and_abort'. */ +static _Noreturn void print_and_abort (void); void (*obstack_alloc_failed_handler) (void) = print_and_abort; -/* Exit value used when `print_and_abort' is used. */ +/* Exit value used when 'print_and_abort' is used. */ # include # ifdef _LIBC int obstack_exit_failure = EXIT_FAILURE; @@ -401,15 +401,7 @@ _obstack_memory_used (struct obstack *h) # include # endif -# ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) -# define __attribute__(Spec) /* empty */ -# endif -# endif - -static void -__attribute__ ((noreturn)) +static _Noreturn void print_and_abort (void) { /* Don't change any of these strings. Yes, it would be possible to add diff --git a/contrib/grep/lib/obstack.h b/contrib/grep/lib/obstack.h index 8a8d44bc8e..6a44b44b97 100644 --- a/contrib/grep/lib/obstack.h +++ b/contrib/grep/lib/obstack.h @@ -1,5 +1,5 @@ /* obstack.h - object stack macros - Copyright (C) 1988-1994, 1996-1999, 2003-2006, 2009-2011 Free Software + Copyright (C) 1988-1994, 1996-1999, 2003-2006, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -32,11 +32,11 @@ stack" is typically an immature growing object, while the rest of the stack is of mature, fixed size and fixed address objects. These routines grab large chunks of memory, using a function you -supply, called `obstack_chunk_alloc'. On occasion, they free chunks, -by calling `obstack_chunk_free'. You must define them and declare +supply, called 'obstack_chunk_alloc'. On occasion, they free chunks, +by calling 'obstack_chunk_free'. You must define them and declare them before using any obstack macros. -Each independent stack is represented by a `struct obstack'. +Each independent stack is represented by a 'struct obstack'. Each of the obstack macros expects a pointer to such a structure as the first argument. @@ -93,7 +93,7 @@ Summary: Exactly one object is growing in an obstack at any one time. You can run one obstack per control block. You may have as many control blocks as you dare. - Because of the way we do it, you can `unwind' an obstack + Because of the way we do it, you can "unwind" an obstack back to a previous state. (You may remove objects much as you would with a stack.) */ @@ -122,7 +122,7 @@ Summary: #define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) -/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case +/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case where pointers can be converted to integers, aligned as integers, and converted back again. If PTR_INT_TYPE is narrower than a pointer (e.g., the AS/400), play it safe and compute the alignment @@ -159,7 +159,7 @@ struct obstack /* control current object in current chunk */ void *tempptr; } temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ - /* These prototypes vary based on `use_extra_arg', and we use + /* These prototypes vary based on 'use_extra_arg', and we use casts to the prototypeless function type in all assignments, but having prototypes here quiets -Wstrict-prototypes. */ struct _obstack_chunk *(*chunkfun) (void *, long); @@ -193,13 +193,13 @@ extern int _obstack_memory_used (struct obstack *); extern void __obstack_free (struct obstack *obstack, void *block); -/* Error handler called when `obstack_chunk_alloc' failed to allocate +/* Error handler called when 'obstack_chunk_alloc' failed to allocate more memory. This can be set to a user defined function which should either abort gracefully or use longjump - but shouldn't return. The default action is to print a message and abort. */ extern void (*obstack_alloc_failed_handler) (void); -/* Exit value used when `print_and_abort' is used. */ +/* Exit value used when 'print_and_abort' is used. */ extern int obstack_exit_failure; /* Pointer to beginning of object being allocated or to be allocated next. @@ -253,7 +253,7 @@ extern int obstack_exit_failure; #define obstack_memory_used(h) _obstack_memory_used (h) -#if defined __GNUC__ && defined __STDC__ && __STDC__ +#if defined __GNUC__ /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and does not implement __extension__. But that compiler doesn't define __GNUC_MINOR__. */ @@ -264,7 +264,7 @@ extern int obstack_exit_failure; /* For GNU C, if not -traditional, we can define these macros to compute all args only once without using a global variable. - Also, we can avoid using the `temp' slot, to make faster code. */ + Also, we can avoid using the 'temp' slot, to make faster code. */ # define obstack_object_size(OBSTACK) \ __extension__ \ @@ -405,7 +405,7 @@ __extension__ \ __o->next_free = __o->object_base = (char *)__obj; \ else (__obstack_free) (__o, __obj); }) -#else /* not __GNUC__ or not __STDC__ */ +#else /* not __GNUC__ */ # define obstack_object_size(h) \ (unsigned) ((h)->next_free - (h)->object_base) @@ -503,7 +503,7 @@ __extension__ \ = (h)->temp.tempint + (char *) (h)->chunk) \ : (((__obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0))) -#endif /* not __GNUC__ or not __STDC__ */ +#endif /* not __GNUC__ */ #ifdef __cplusplus } /* C++ */ diff --git a/contrib/grep/lib/mbslen.c b/contrib/grep/lib/open-safer.c similarity index 52% copy from contrib/grep/lib/mbslen.c copy to contrib/grep/lib/open-safer.c index efddd52454..17f7600fff 100644 --- a/contrib/grep/lib/mbslen.c +++ b/contrib/grep/lib/open-safer.c @@ -1,6 +1,6 @@ -/* Counting the multibyte characters in a string. - Copyright (C) 2007-2011 Free Software Foundation, Inc. - Written by Bruno Haible , 2007. +/* Invoke open, but avoid some glitches. + + Copyright (C) 2005-2006, 2008-2012 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 @@ -15,30 +15,32 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Paul Eggert. */ -/* Specification. */ -#include +#include -#include +#include "fcntl-safer.h" -#include "mbuiter.h" +#include +#include +#include "unistd-safer.h" -/* Return the number of multibyte characters in the character string STRING. */ -size_t -mbslen (const char *string) +int +open_safer (char const *file, int flags, ...) { - if (MB_CUR_MAX > 1) + mode_t mode = 0; + + if (flags & O_CREAT) { - size_t count; - mbui_iterator_t iter; + va_list ap; + va_start (ap, flags); - count = 0; - for (mbui_init (iter, string); mbui_avail (iter); mbui_advance (iter)) - count++; + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (ap, PROMOTED_MODE_T); - return count; + va_end (ap); } - else - return strlen (string); + + return fd_safer (open (file, flags, mode)); } diff --git a/contrib/grep/lib/open.c b/contrib/grep/lib/open.c index e60b619949..27801b916c 100644 --- a/contrib/grep/lib/open.c +++ b/contrib/grep/lib/open.c @@ -1,5 +1,5 @@ /* Open a descriptor to a file. - Copyright (C) 2007-2011 Free Software Foundation, Inc. + Copyright (C) 2007-2012 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 @@ -16,13 +16,16 @@ /* Written by Bruno Haible , 2007. */ +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_open doesn't recurse to + rpl_open. */ +#define __need_system_fcntl_h #include /* Get the original definition of open. It might be defined as a macro. */ -#define __need_system_fcntl_h #include -#undef __need_system_fcntl_h #include +#undef __need_system_fcntl_h static inline int orig_open (const char *filename, int flags, mode_t mode) @@ -31,7 +34,9 @@ orig_open (const char *filename, int flags, mode_t mode) } /* Specification. */ -#include +/* Write "fcntl.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates + this include because of the preliminary #include above. */ +#include "fcntl.h" #include #include diff --git a/contrib/grep/lib/openat-die.c b/contrib/grep/lib/openat-die.c new file mode 100644 index 0000000000..a5f17d8a55 --- /dev/null +++ b/contrib/grep/lib/openat-die.c @@ -0,0 +1,62 @@ +/* Report a save- or restore-cwd failure in our openat replacement and then exit. + + Copyright (C) 2005-2006, 2008-2012 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 of the License, 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 . */ + +#include + +#include "openat.h" + +#include + +#ifndef GNULIB_LIBPOSIX +# include "error.h" +#endif + +#include "exitfail.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +void +openat_save_fail (int errnum) +{ +#ifndef GNULIB_LIBPOSIX + error (exit_failure, errnum, + _("unable to record current working directory")); +#endif + /* _Noreturn cannot be applied to error, since it returns + when its first argument is 0. To help compilers understand that this + function does not return, call abort. Also, the abort is a + safety feature if exit_failure is 0 (which shouldn't happen). */ + abort (); +} + + +/* Exit with an error about failure to restore the working directory + during an openat emulation. The caller must ensure that fd 2 is + not a just-opened fd, even when openat_safer is not in use. */ + +void +openat_restore_fail (int errnum) +{ +#ifndef GNULIB_LIBPOSIX + error (exit_failure, errnum, + _("failed to return to initial working directory")); +#endif + + /* As above. */ + abort (); +} diff --git a/contrib/grep/lib/openat-priv.h b/contrib/grep/lib/openat-priv.h new file mode 100644 index 0000000000..fd0adc1855 --- /dev/null +++ b/contrib/grep/lib/openat-priv.h @@ -0,0 +1,64 @@ +/* Internals for openat-like functions. + + Copyright (C) 2005-2006, 2009-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +#ifndef _GL_HEADER_OPENAT_PRIV +#define _GL_HEADER_OPENAT_PRIV + +#include +#include +#include + +/* Maximum number of bytes that it is safe to allocate as a single + array on the stack, and that is known as a compile-time constant. + The assumption is that we'll touch the array very quickly, or a + temporary very near the array, provoking an out-of-memory trap. On + some operating systems, there is only one guard page for the stack, + and a page size can be as small as 4096 bytes. Subtract 64 in the + hope that this will let the compiler touch a nearby temporary and + provoke a trap. */ +#define SAFER_ALLOCA_MAX (4096 - 64) + +#define SAFER_ALLOCA(m) ((m) < SAFER_ALLOCA_MAX ? (m) : SAFER_ALLOCA_MAX) + +#if defined PATH_MAX +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (PATH_MAX) +#elif defined _XOPEN_PATH_MAX +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (_XOPEN_PATH_MAX) +#else +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (1024) +#endif + +char *openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file); + +/* Trying to access a BUILD_PROC_NAME file will fail on systems without + /proc support, and even on systems *with* ProcFS support. Return + nonzero if the failure may be legitimate, e.g., because /proc is not + readable, or the particular .../fd/N directory is not present. */ +#define EXPECTED_ERRNO(Errno) \ + ((Errno) == ENOTDIR || (Errno) == ENOENT \ + || (Errno) == EPERM || (Errno) == EACCES \ + || (Errno) == ENOSYS /* Solaris 8 */ \ + || (Errno) == EOPNOTSUPP /* FreeBSD */) + +/* Wrapper function shared among linkat and renameat. */ +int at_func2 (int fd1, char const *file1, + int fd2, char const *file2, + int (*func) (char const *file1, char const *file2)); + +#endif /* _GL_HEADER_OPENAT_PRIV */ diff --git a/contrib/grep/lib/openat-proc.c b/contrib/grep/lib/openat-proc.c new file mode 100644 index 0000000000..186cda0833 --- /dev/null +++ b/contrib/grep/lib/openat-proc.c @@ -0,0 +1,110 @@ +/* Create /proc/self/fd-related names for subfiles of open directories. + + Copyright (C) 2006, 2009-2012 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 of the License, 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 . */ + +/* Written by Paul Eggert. */ + +#include + +#include "openat-priv.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "intprops.h" + +/* The results of open() in this file are not used with fchdir, + and we do not leak fds to any single-threaded code that could use stdio, + therefore save some unnecessary work in fchdir.c. + FIXME - if the kernel ever adds support for multi-thread safety for + avoiding standard fds, then we should use open_safer. */ +#undef open +#undef close + +#define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/%s" + +#define PROC_SELF_FD_NAME_SIZE_BOUND(len) \ + (sizeof PROC_SELF_FD_FORMAT - sizeof "%d%s" \ + + INT_STRLEN_BOUND (int) + (len) + 1) + + +/* Set BUF to the expansion of PROC_SELF_FD_FORMAT, using FD and FILE + respectively for %d and %s. If successful, return BUF if the + result fits in BUF, dynamically allocated memory otherwise. But + return NULL if /proc is not reliable, either because the operating + system support is lacking or because memory is low. */ +char * +openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file) +{ + static int proc_status = 0; + + /* Make sure the caller gets ENOENT when appropriate. */ + if (!*file) + { + buf[0] = '\0'; + return buf; + } + + if (! proc_status) + { + /* Set PROC_STATUS to a positive value if /proc/self/fd is + reliable, and a negative value otherwise. Solaris 10 + /proc/self/fd mishandles "..", and any file name might expand + to ".." after symbolic link expansion, so avoid /proc/self/fd + if it mishandles "..". Solaris 10 has openat, but this + problem is exhibited on code that built on Solaris 8 and + running on Solaris 10. */ + + int proc_self_fd = open ("/proc/self/fd", + O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); + if (proc_self_fd < 0) + proc_status = -1; + else + { + /* Detect whether /proc/self/fd/%i/../fd exists, where %i is the + number of a file descriptor open on /proc/self/fd. On Linux, + that name resolves to /proc/self/fd, which was opened above. + However, on Solaris, it may resolve to /proc/self/fd/fd, which + cannot exist, since all names in /proc/self/fd are numeric. */ + char dotdot_buf[PROC_SELF_FD_NAME_SIZE_BOUND (sizeof "../fd" - 1)]; + sprintf (dotdot_buf, PROC_SELF_FD_FORMAT, proc_self_fd, "../fd"); + proc_status = access (dotdot_buf, F_OK) ? -1 : 1; + close (proc_self_fd); + } + } + + if (proc_status < 0) + return NULL; + else + { + size_t bufsize = PROC_SELF_FD_NAME_SIZE_BOUND (strlen (file)); + char *result = buf; + if (OPENAT_BUFFER_SIZE < bufsize) + { + result = malloc (bufsize); + if (! result) + return NULL; + } + sprintf (result, PROC_SELF_FD_FORMAT, fd, file); + return result; + } +} diff --git a/contrib/grep/lib/mbslen.c b/contrib/grep/lib/openat-safer.c similarity index 50% copy from contrib/grep/lib/mbslen.c copy to contrib/grep/lib/openat-safer.c index efddd52454..f6ed93f638 100644 --- a/contrib/grep/lib/mbslen.c +++ b/contrib/grep/lib/openat-safer.c @@ -1,6 +1,6 @@ -/* Counting the multibyte characters in a string. - Copyright (C) 2007-2011 Free Software Foundation, Inc. - Written by Bruno Haible , 2007. +/* Invoke openat, but avoid some glitches. + + Copyright (C) 2005-2006, 2008-2012 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 @@ -15,30 +15,32 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Paul Eggert for open, ported by Eric Blake for openat. */ -/* Specification. */ -#include +#include -#include +#include "fcntl-safer.h" -#include "mbuiter.h" +#include +#include +#include "unistd-safer.h" -/* Return the number of multibyte characters in the character string STRING. */ -size_t -mbslen (const char *string) +int +openat_safer (int fd, char const *file, int flags, ...) { - if (MB_CUR_MAX > 1) + mode_t mode = 0; + + if (flags & O_CREAT) { - size_t count; - mbui_iterator_t iter; + va_list ap; + va_start (ap, flags); - count = 0; - for (mbui_init (iter, string); mbui_avail (iter); mbui_advance (iter)) - count++; + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (ap, PROMOTED_MODE_T); - return count; + va_end (ap); } - else - return strlen (string); + + return fd_safer (openat (fd, file, flags, mode)); } diff --git a/contrib/grep/lib/openat.c b/contrib/grep/lib/openat.c new file mode 100644 index 0000000000..ac2496e907 --- /dev/null +++ b/contrib/grep/lib/openat.c @@ -0,0 +1,286 @@ +/* provide a replacement openat function + Copyright (C) 2004-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_openat doesn't recurse to + rpl_openat. */ +#define __need_system_fcntl_h +#include + +/* Get the original definition of open. It might be defined as a macro. */ +#include +#include +#undef __need_system_fcntl_h + +#if HAVE_OPENAT +static inline int +orig_openat (int fd, char const *filename, int flags, mode_t mode) +{ + return openat (fd, filename, flags, mode); +} +#endif + +/* Write "fcntl.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates + this include because of the preliminary #include above. */ +#include "fcntl.h" + +#include "openat.h" + +#include +#include +#include +#include +#include +#include + +#if HAVE_OPENAT + +/* Like openat, but work around Solaris 9 bugs with trailing slash. */ +int +rpl_openat (int dfd, char const *filename, int flags, ...) +{ + mode_t mode; + int fd; + + mode = 0; + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + +# if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR + is specified, then fail. + Rationale: POSIX + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file already exists as a directory, then + - if O_CREAT is specified, open() must fail because of the semantics + of O_CREAT, + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX + says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + - if O_CREAT is specified, open() must fail since open() cannot create + directories, + - if O_WRONLY or O_RDWR is specified, open() must fail because the + file does not contain a '.' directory. */ + if (flags & (O_CREAT | O_WRONLY | O_RDWR)) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return -1; + } + } +# endif + + fd = orig_openat (dfd, filename, flags, mode); + +# if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and fd does not refer to a directory, + then fail. + Rationale: POSIX + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file without the slash is not a directory, open() must fail + with ENOTDIR. */ + if (fd >= 0) + { + /* We know len is positive, since open did not fail with ENOENT. */ + size_t len = strlen (filename); + if (filename[len - 1] == '/') + { + struct stat statbuf; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return -1; + } + } + } +# endif + + return fd; +} + +#else /* !HAVE_OPENAT */ + +# include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ +# include "openat-priv.h" +# include "save-cwd.h" + +/* Replacement for Solaris' openat function. + + First, try to simulate it via open ("/proc/self/fd/FD/FILE"). + Failing that, simulate it by doing save_cwd/fchdir/open/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. + Otherwise, upon failure, set errno and return -1, as openat does. + Upon successful completion, return a file descriptor. */ +int +openat (int fd, char const *file, int flags, ...) +{ + mode_t mode = 0; + + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + + return openat_permissive (fd, file, flags, mode, NULL); +} + +/* Like openat (FD, FILE, FLAGS, MODE), but if CWD_ERRNO is + nonnull, set *CWD_ERRNO to an errno value if unable to save + or restore the initial working directory. This is needed only + the first time remove.c's remove_dir opens a command-line + directory argument. + + If a previous attempt to restore the current working directory + failed, then we must not even try to access a '.'-relative name. + It is the caller's responsibility not to call this function + in that case. */ + +int +openat_permissive (int fd, char const *file, int flags, mode_t mode, + int *cwd_errno) +{ + struct saved_cwd saved_cwd; + int saved_errno; + int err; + bool save_ok; + + if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) + return open (file, flags, mode); + + { + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, file); + if (proc_file) + { + int open_result = open (proc_file, flags, mode); + int open_errno = errno; + if (proc_file != buf) + free (proc_file); + /* If the syscall succeeds, or if it fails with an unexpected + errno value, then return right away. Otherwise, fall through + and resort to using save_cwd/restore_cwd. */ + if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) + { + errno = open_errno; + return open_result; + } + } + } + + save_ok = (save_cwd (&saved_cwd) == 0); + if (! save_ok) + { + if (! cwd_errno) + openat_save_fail (errno); + *cwd_errno = errno; + } + if (0 <= fd && fd == saved_cwd.desc) + { + /* If saving the working directory collides with the user's + requested fd, then the user's fd must have been closed to + begin with. */ + free_cwd (&saved_cwd); + errno = EBADF; + return -1; + } + + err = fchdir (fd); + saved_errno = errno; + + if (! err) + { + err = open (file, flags, mode); + saved_errno = errno; + if (save_ok && restore_cwd (&saved_cwd) != 0) + { + if (! cwd_errno) + { + /* Don't write a message to just-created fd 2. */ + saved_errno = errno; + if (err == STDERR_FILENO) + close (err); + openat_restore_fail (saved_errno); + } + *cwd_errno = errno; + } + } + + free_cwd (&saved_cwd); + errno = saved_errno; + return err; +} + +/* Return true if our openat implementation must resort to + using save_cwd and restore_cwd. */ +bool +openat_needs_fchdir (void) +{ + bool needs_fchdir = true; + int fd = open ("/", O_SEARCH); + + if (0 <= fd) + { + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, "."); + if (proc_file) + { + needs_fchdir = false; + if (proc_file != buf) + free (proc_file); + } + close (fd); + } + + return needs_fchdir; +} + +#endif /* !HAVE_OPENAT */ diff --git a/contrib/grep/lib/openat.h b/contrib/grep/lib/openat.h new file mode 100644 index 0000000000..d646250bb3 --- /dev/null +++ b/contrib/grep/lib/openat.h @@ -0,0 +1,104 @@ +/* provide a replacement openat function + Copyright (C) 2004-2006, 2008-2012 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 of the License, 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 . */ + +/* written by Jim Meyering */ + +#ifndef _GL_HEADER_OPENAT +#define _GL_HEADER_OPENAT + +#include + +#include +#include +#include +#include + +#if !HAVE_OPENAT + +int openat_permissive (int fd, char const *file, int flags, mode_t mode, + int *cwd_errno); +bool openat_needs_fchdir (void); + +#else + +# define openat_permissive(Fd, File, Flags, Mode, Cwd_errno) \ + openat (Fd, File, Flags, Mode) +# define openat_needs_fchdir() false + +#endif + +_Noreturn void openat_restore_fail (int); +_Noreturn void openat_save_fail (int); + +/* Using these function names makes application code + slightly more readable than it would be with + fchownat (..., 0) or fchownat (..., AT_SYMLINK_NOFOLLOW). */ + +#if GNULIB_FCHOWNAT + +static inline int +chownat (int fd, char const *file, uid_t owner, gid_t group) +{ + return fchownat (fd, file, owner, group, 0); +} + +static inline int +lchownat (int fd, char const *file, uid_t owner, gid_t group) +{ + return fchownat (fd, file, owner, group, AT_SYMLINK_NOFOLLOW); +} + +#endif + +#if GNULIB_FCHMODAT + +static inline int +chmodat (int fd, char const *file, mode_t mode) +{ + return fchmodat (fd, file, mode, 0); +} + +static inline int +lchmodat (int fd, char const *file, mode_t mode) +{ + return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW); +} + +#endif + +#if GNULIB_FSTATAT + +static inline int +statat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, 0); +} + +static inline int +lstatat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW); +} + +#endif + +/* For now, there are no wrappers named laccessat or leuidaccessat, + since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and + since access rights on symlinks are of limited utility. Likewise, + wrappers are not provided for accessat or euidaccessat, so as to + avoid dragging in -lgen on some platforms. */ + +#endif /* _GL_HEADER_OPENAT */ diff --git a/contrib/grep/lib/opendir-safer.c b/contrib/grep/lib/opendir-safer.c new file mode 100644 index 0000000000..4320716589 --- /dev/null +++ b/contrib/grep/lib/opendir-safer.c @@ -0,0 +1,76 @@ +/* Invoke opendir, but avoid some glitches. + + Copyright (C) 2009-2012 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 of the License, 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 . */ + +/* Written by Eric Blake. */ + +#include + +#include "dirent-safer.h" + +#include +#include +#include "unistd-safer.h" + +/* Like opendir, but do not clobber stdin, stdout, or stderr. */ + +DIR * +opendir_safer (char const *name) +{ + DIR *dp = opendir (name); + + if (dp) + { + int fd = dirfd (dp); + + if (0 <= fd && fd <= STDERR_FILENO) + { + /* If fdopendir is native (as on Linux), then it is safe to + assume dirfd(fdopendir(n))==n. If we are using the + gnulib module fdopendir, then this guarantee is not met, + but fdopendir recursively calls opendir_safer up to 3 + times to at least get a safe fd. If fdopendir is not + present but dirfd is accurate (as on cygwin 1.5.x), then + we recurse up to 3 times ourselves. Finally, if dirfd + always fails (as on mingw), then we are already safe. */ + DIR *newdp; + int e; +#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR + int f = dup_safer (fd); + if (f < 0) + { + e = errno; + newdp = NULL; + } + else + { + newdp = fdopendir (f); + e = errno; + if (! newdp) + close (f); + } +#else /* !FDOPENDIR */ + newdp = opendir_safer (name); + e = errno; +#endif + closedir (dp); + errno = e; + dp = newdp; + } + } + + return dp; +} diff --git a/contrib/grep/lib/opendir.c b/contrib/grep/lib/opendir.c new file mode 100644 index 0000000000..50e25e305a --- /dev/null +++ b/contrib/grep/lib/opendir.c @@ -0,0 +1,148 @@ +/* Start reading the entries of a directory. + Copyright (C) 2006-2012 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if HAVE_OPENDIR + +/* Override opendir(), to keep track of the open file descriptors. + Needed because there is a function dirfd(). */ + +#else + +# include + +# include "dirent-private.h" +# include "filename.h" + +#endif + +#if REPLACE_FCHDIR +# include +#endif + +DIR * +opendir (const char *dir_name) +{ +#if HAVE_OPENDIR +# undef opendir + DIR *dirp; + + dirp = opendir (dir_name); + if (dirp == NULL) + return NULL; + +#else + + char dir_name_mask[MAX_PATH + 1 + 1 + 1]; + int status; + HANDLE current; + WIN32_FIND_DATA entry; + struct gl_directory *dirp; + + if (dir_name[0] == '\0') + { + errno = ENOENT; + return NULL; + } + + /* Make the dir_name absolute, so that we continue reading the same + directory if the current directory changed between this opendir() + call and a subsequent rewinddir() call. */ + if (!GetFullPathName (dir_name, MAX_PATH, dir_name_mask, NULL)) + { + errno = EINVAL; + return NULL; + } + + /* Append the mask. + "*" and "*.*" appear to be equivalent. */ + { + char *p; + + p = dir_name_mask + strlen (dir_name_mask); + if (p > dir_name_mask && !ISSLASH (p[-1])) + *p++ = '\\'; + *p++ = '*'; + *p = '\0'; + } + + /* Start searching the directory. */ + status = -1; + current = FindFirstFile (dir_name_mask, &entry); + if (current == INVALID_HANDLE_VALUE) + { + switch (GetLastError ()) + { + case ERROR_FILE_NOT_FOUND: + status = -2; + break; + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + return NULL; + case ERROR_DIRECTORY: + errno = ENOTDIR; + return NULL; + case ERROR_ACCESS_DENIED: + errno = EACCES; + return NULL; + default: + errno = EIO; + return NULL; + } + } + + /* Allocate the result. */ + dirp = + (struct gl_directory *) + malloc (offsetof (struct gl_directory, dir_name_mask[0]) + + strlen (dir_name_mask) + 1); + if (dirp == NULL) + { + if (current != INVALID_HANDLE_VALUE) + FindClose (current); + errno = ENOMEM; + return NULL; + } + dirp->status = status; + dirp->current = current; + if (status == -1) + memcpy (&dirp->entry, &entry, sizeof (WIN32_FIND_DATA)); + strcpy (dirp->dir_name_mask, dir_name_mask); + +#endif + +#if REPLACE_FCHDIR + { + int fd = dirfd (dirp); + if (0 <= fd && _gl_register_fd (fd, dir_name) != fd) + { + int saved_errno = errno; + closedir (dirp); + errno = saved_errno; + return NULL; + } + } +#endif + + return dirp; +} diff --git a/contrib/grep/lib/pathmax.h b/contrib/grep/lib/pathmax.h new file mode 100644 index 0000000000..03db7cb519 --- /dev/null +++ b/contrib/grep/lib/pathmax.h @@ -0,0 +1,83 @@ +/* Define PATH_MAX somehow. Requires sys/types.h. + Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2012 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 . */ + +#ifndef _PATHMAX_H +# define _PATHMAX_H + +/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, + including the terminating NUL byte. + + PATH_MAX is not defined on systems which have no limit on filename length, + such as GNU/Hurd. + + This file does *not* define PATH_MAX always. Programs that use this file + can handle the GNU/Hurd case in several ways: + - Either with a package-wide handling, or with a per-file handling, + - Either through a + #ifdef PATH_MAX + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX 8192 + #endif + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX pathconf ("/", _PC_PATH_MAX) + #endif + */ + +# include + +# include + +# ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 256 +# endif + +/* Don't include sys/param.h if it already has been. */ +# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN +# include +# endif + +# if !defined PATH_MAX && defined MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# endif + +# ifdef __hpux +/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, + *not* including the terminating NUL byte, and is set to 1023. + Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is + not defined at all any more. */ +# undef PATH_MAX +# define PATH_MAX 1024 +# endif + +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, + section "Maximum Path Length Limitation", + + explains that the maximum size of a filename, including the terminating + NUL byte, is 260 = 3 + 256 + 1. + This is the same value as + - FILENAME_MAX in , + - _MAX_PATH in , + - MAX_PATH in . + Undefine the original value, because mingw's gets it wrong. */ +# undef PATH_MAX +# define PATH_MAX 260 +# endif + +#endif /* _PATHMAX_H */ diff --git a/contrib/grep/lib/pipe-safer.c b/contrib/grep/lib/pipe-safer.c new file mode 100644 index 0000000000..d6dce5ffc1 --- /dev/null +++ b/contrib/grep/lib/pipe-safer.c @@ -0,0 +1,56 @@ +/* Invoke pipe, but avoid some glitches. + Copyright (C) 2005-2006, 2009-2012 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 of the License, 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 . */ + +/* Written by Jim Meyering. */ + +#include + +#include "unistd-safer.h" + +#include +#include + +/* Like pipe, but ensure that neither of the file descriptors is + STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO. Fail with ENOSYS on + platforms that lack pipe. */ + +int +pipe_safer (int fd[2]) +{ +#if HAVE_PIPE + if (pipe (fd) == 0) + { + int i; + for (i = 0; i < 2; i++) + { + fd[i] = fd_safer (fd[i]); + if (fd[i] < 0) + { + int e = errno; + close (fd[1 - i]); + errno = e; + return -1; + } + } + + return 0; + } +#else + errno = ENOSYS; +#endif + + return -1; +} diff --git a/contrib/grep/lib/progname.c b/contrib/grep/lib/progname.c index 2465748175..bdd4dd74d4 100644 --- a/contrib/grep/lib/progname.c +++ b/contrib/grep/lib/progname.c @@ -1,5 +1,5 @@ /* Program name management. - Copyright (C) 2001-2003, 2005-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2001. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/progname.h b/contrib/grep/lib/progname.h index 084406607d..a75a02e6da 100644 --- a/contrib/grep/lib/progname.h +++ b/contrib/grep/lib/progname.h @@ -1,5 +1,5 @@ /* Program name management. - Copyright (C) 2001-2004, 2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2006, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2001. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/propername.c b/contrib/grep/lib/propername.c index b74923de95..79c6b08e45 100644 --- a/contrib/grep/lib/propername.c +++ b/contrib/grep/lib/propername.c @@ -1,5 +1,5 @@ /* Localization of proper names. - Copyright (C) 2006-2011 Free Software Foundation, Inc. + Copyright (C) 2006-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2006. This program is free software: you can redistribute it and/or modify @@ -15,6 +15,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that + the proper_name function might be candidate for attribute 'const' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif + #include /* Specification. */ diff --git a/contrib/grep/lib/propername.h b/contrib/grep/lib/propername.h index d2a1e3bf0d..0ce1923f68 100644 --- a/contrib/grep/lib/propername.h +++ b/contrib/grep/lib/propername.h @@ -1,5 +1,5 @@ /* Localization of proper names. - Copyright (C) 2006, 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2006, 2008-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2006. This program is free software: you can redistribute it and/or modify @@ -89,7 +89,7 @@ extern "C" { #endif /* Return the localization of NAME. NAME is written in ASCII. */ -extern const char * proper_name (const char *name); +extern const char * proper_name (const char *name) /* NOT attribute const */; /* Return the localization of a name whose original writing is not ASCII. NAME_UTF8 is the real name, written in UTF-8 with octal or hexadecimal diff --git a/contrib/grep/lib/quote.c b/contrib/grep/lib/quote.c deleted file mode 100644 index 1989c8c350..0000000000 --- a/contrib/grep/lib/quote.c +++ /dev/null @@ -1,40 +0,0 @@ -/* quote.c - quote arguments for output - - Copyright (C) 1998-2001, 2003, 2005-2006, 2009-2011 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 of the License, 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 . */ - -/* Written by Paul Eggert */ - -#include - -#include "quotearg.h" -#include "quote.h" - -/* Return an unambiguous printable representation of NAME, - allocated in slot N, suitable for diagnostics. */ -char const * -quote_n (int n, char const *name) -{ - return quotearg_n_style (n, locale_quoting_style, name); -} - -/* Return an unambiguous printable representation of NAME, - suitable for diagnostics. */ -char const * -quote (char const *name) -{ - return quote_n (0, name); -} diff --git a/contrib/grep/lib/quote.h b/contrib/grep/lib/quote.h index d0acb51f02..b30b166ddb 100644 --- a/contrib/grep/lib/quote.h +++ b/contrib/grep/lib/quote.h @@ -1,6 +1,6 @@ /* quote.h - prototypes for quote.c - Copyright (C) 1998-2001, 2003, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1998-2001, 2003, 2009-2012 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 @@ -15,6 +15,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#ifndef QUOTE_H_ +# define QUOTE_H_ 1 +/* The quoting options used by quote_n and quote. Its type is incomplete, + so it's useful only in expressions like '"e_quoting_options'. */ +extern struct quoting_options quote_quoting_options; + +/* Return an unambiguous printable representation of NAME, + allocated in slot N, suitable for diagnostics. */ char const *quote_n (int n, char const *name); + +/* Return an unambiguous printable representation of NAME, + suitable for diagnostics. */ char const *quote (char const *name); + +#endif /* !QUOTE_H_ */ diff --git a/contrib/grep/lib/quotearg.c b/contrib/grep/lib/quotearg.c index da8ba1eac6..1ea583d9c2 100644 --- a/contrib/grep/lib/quotearg.c +++ b/contrib/grep/lib/quotearg.c @@ -1,6 +1,6 @@ /* quotearg.c - quote arguments for output - Copyright (C) 1998-2002, 2004-2011 Free Software Foundation, Inc. + Copyright (C) 1998-2002, 2004-2012 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 @@ -17,11 +17,21 @@ /* Written by Paul Eggert */ +/* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that + the quoting_options_from_style function might be candidate for + attribute 'pure' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +#endif + #include #include "quotearg.h" +#include "quote.h" #include "xalloc.h" +#include "c-strcaseeq.h" +#include "localcharset.h" #include #include @@ -165,10 +175,10 @@ set_custom_quoting (struct quoting_options *o, } /* Return quoting options for STYLE, with no extra quoting. */ -static struct quoting_options +static struct quoting_options /* NOT PURE!! */ quoting_options_from_style (enum quoting_style style) { - struct quoting_options o = { 0 }; + struct quoting_options o = { 0, 0, { 0 }, NULL, NULL }; if (style == custom_quoting_style) abort (); o.style = style; @@ -176,14 +186,43 @@ quoting_options_from_style (enum quoting_style style) } /* MSGID approximates a quotation mark. Return its translation if it - has one; otherwise, return either it or "\"", depending on S. */ + has one; otherwise, return either it or "\"", depending on S. + + S is either clocale_quoting_style or locale_quoting_style. */ static char const * gettext_quote (char const *msgid, enum quoting_style s) { char const *translation = _(msgid); - if (translation == msgid && s == clocale_quoting_style) - translation = "\""; - return translation; + char const *locale_code; + + if (translation != msgid) + return translation; + + /* For UTF-8 and GB-18030, use single quotes U+2018 and U+2019. + Here is a list of other locales that include U+2018 and U+2019: + + ISO-8859-7 0xA1 KOI8-T 0x91 + CP869 0x8B CP874 0x91 + CP932 0x81 0x65 CP936 0xA1 0xAE + CP949 0xA1 0xAE CP950 0xA1 0xA5 + CP1250 0x91 CP1251 0x91 + CP1252 0x91 CP1253 0x91 + CP1254 0x91 CP1255 0x91 + CP1256 0x91 CP1257 0x91 + EUC-JP 0xA1 0xC6 EUC-KR 0xA1 0xAE + EUC-TW 0xA1 0xE4 BIG5 0xA1 0xA5 + BIG5-HKSCS 0xA1 0xA5 EUC-CN 0xA1 0xAE + GBK 0xA1 0xAE Georgian-PS 0x91 + PT154 0x91 + + None of these is still in wide use; using iconv is overkill. */ + locale_code = locale_charset (); + if (STRCASEEQ (locale_code, "UTF-8", 'U','T','F','-','8',0,0,0,0)) + return msgid[0] == '`' ? "\xe2\x80\x98": "\xe2\x80\x99"; + if (STRCASEEQ (locale_code, "GB18030", 'G','B','1','8','0','3','0',0,0)) + return msgid[0] == '`' ? "\xa1\ae": "\xa1\xaf"; + + return (s == clocale_quoting_style ? "\"" : "'"); } /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of @@ -251,22 +290,24 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize, { /* TRANSLATORS: Get translations for open and closing quotation marks. - The message catalog should translate "`" to a left quotation mark suitable for the locale, and similarly for - "'". If the catalog has no translation, - locale_quoting_style quotes `like this', and - clocale_quoting_style quotes "like this". - - For example, an American English Unicode locale should - translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and - should translate "'" to U+201D (RIGHT DOUBLE QUOTATION - MARK). A British English Unicode locale should instead - translate these to U+2018 (LEFT SINGLE QUOTATION MARK) - and U+2019 (RIGHT SINGLE QUOTATION MARK), respectively. + "'". For example, a French Unicode local should translate + these to U+00AB (LEFT-POINTING DOUBLE ANGLE + QUOTATION MARK), and U+00BB (RIGHT-POINTING DOUBLE ANGLE + QUOTATION MARK), respectively. + + If the catalog has no translation, we will try to + use Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and + Unicode U+2019 (RIGHT SINGLE QUOTATION MARK). If the + current locale is not Unicode, locale_quoting_style + will quote 'like this', and clocale_quoting_style will + quote "like this". You should always include translations + for "`" and "'" even if U+2018 and U+2019 are appropriate + for your locale. If you don't know what to put here, please see - + and use glyphs suitable for your language. */ left_quote = gettext_quote (N_("`"), quoting_style); right_quote = gettext_quote (N_("'"), quoting_style); @@ -730,7 +771,7 @@ quotearg_n_options (int n, char const *arg, size_t argsize, if (nslots <= n0) { - /* FIXME: technically, the type of n1 should be `unsigned int', + /* FIXME: technically, the type of n1 should be 'unsigned int', but that evokes an unsuppressible warning from gcc-4.0.1 and older. If gcc ever provides an option to suppress that warning, revert to the original type, so that the test in xalloc_oversized @@ -886,3 +927,25 @@ quotearg_custom_mem (char const *left_quote, char const *right_quote, return quotearg_n_custom_mem (0, left_quote, right_quote, arg, argsize); } + + +/* The quoting option used by quote_n and quote. */ +struct quoting_options quote_quoting_options = + { + locale_quoting_style, + 0, + { 0 }, + NULL, NULL + }; + +char const * +quote_n (int n, char const *name) +{ + return quotearg_n_options (n, name, SIZE_MAX, "e_quoting_options); +} + +char const * +quote (char const *name) +{ + return quote_n (0, name); +} diff --git a/contrib/grep/lib/quotearg.h b/contrib/grep/lib/quotearg.h index 2756d760aa..e6b08ab230 100644 --- a/contrib/grep/lib/quotearg.h +++ b/contrib/grep/lib/quotearg.h @@ -1,6 +1,6 @@ /* quotearg.h - quote arguments for output - Copyright (C) 1998-2002, 2004, 2006, 2008-2011 Free Software Foundation, + Copyright (C) 1998-2002, 2004, 2006, 2008-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -112,8 +112,10 @@ enum quoting_style */ escape_quoting_style, - /* Like clocale_quoting_style, but quote `like this' instead of - "like this" in the default C locale (ls --quoting-style=locale). + /* Like clocale_quoting_style, but use single quotes in the + default C locale or if the program does not use gettext + (ls --quoting-style=locale). For UTF-8 locales, quote + characters will use Unicode. LC_MESSAGES=C quotearg_buffer: diff --git a/contrib/grep/lib/readdir.c b/contrib/grep/lib/readdir.c new file mode 100644 index 0000000000..28aff9ccb4 --- /dev/null +++ b/contrib/grep/lib/readdir.c @@ -0,0 +1,98 @@ +/* Read the next entry of a directory. + Copyright (C) 2011-2012 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 of the License, 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 . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#include "dirent-private.h" + +struct dirent * +readdir (DIR *dirp) +{ + char type; + struct dirent *result; + + /* There is no need to add code to produce entries for "." and "..". + According to the POSIX:2008 section "4.12 Pathname Resolution" + + "." and ".." are syntactic entities. + POSIX also says: + "If entries for dot or dot-dot exist, one entry shall be returned + for dot and one entry shall be returned for dot-dot; otherwise, + they shall not be returned." */ + + switch (dirp->status) + { + case -2: + /* End of directory already reached. */ + return NULL; + case -1: + break; + case 0: + if (!FindNextFile (dirp->current, &dirp->entry)) + { + switch (GetLastError ()) + { + case ERROR_NO_MORE_FILES: + dirp->status = -2; + return NULL; + default: + errno = EIO; + return NULL; + } + } + break; + default: + errno = dirp->status; + return NULL; + } + + dirp->status = 0; + + if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + type = DT_DIR; + else if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + type = DT_LNK; + else if ((dirp->entry.dwFileAttributes + & ~(FILE_ATTRIBUTE_READONLY + | FILE_ATTRIBUTE_HIDDEN + | FILE_ATTRIBUTE_SYSTEM + | FILE_ATTRIBUTE_ARCHIVE + | FILE_ATTRIBUTE_NORMAL + | FILE_ATTRIBUTE_TEMPORARY + | FILE_ATTRIBUTE_SPARSE_FILE + | FILE_ATTRIBUTE_COMPRESSED + | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED + | FILE_ATTRIBUTE_ENCRYPTED)) == 0) + /* Devices like COM1, LPT1, NUL would also have the attributes 0x20 but + they cannot occur here. */ + type = DT_REG; + else + type = DT_UNKNOWN; + + /* Reuse the memory of dirp->entry for the result. */ + result = + (struct dirent *) + ((char *) dirp->entry.cFileName - offsetof (struct dirent, d_name[0])); + result->d_type = type; + + return result; +} diff --git a/contrib/grep/lib/realloc.c b/contrib/grep/lib/realloc.c index 0c96ffacba..99556ccf9c 100644 --- a/contrib/grep/lib/realloc.c +++ b/contrib/grep/lib/realloc.c @@ -1,6 +1,6 @@ /* realloc() function that is glibc compatible. - Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2011 Free Software + Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/ref-add.sin b/contrib/grep/lib/ref-add.sin index a57eaef607..4ec043f87d 100644 --- a/contrib/grep/lib/ref-add.sin +++ b/contrib/grep/lib/ref-add.sin @@ -1,6 +1,6 @@ # Add this package to a list of references stored in a text file. # -# Copyright (C) 2000, 2009-2011 Free Software Foundation, Inc. +# Copyright (C) 2000, 2009-2012 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 @@ -13,8 +13,7 @@ # 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. +# with this program; if not, see . # # Written by Bruno Haible . # diff --git a/contrib/grep/lib/ref-del.sin b/contrib/grep/lib/ref-del.sin index e23097db33..eb0388117b 100644 --- a/contrib/grep/lib/ref-del.sin +++ b/contrib/grep/lib/ref-del.sin @@ -1,6 +1,6 @@ # Remove this package from a list of references stored in a text file. # -# Copyright (C) 2000, 2009-2011 Free Software Foundation, Inc. +# Copyright (C) 2000, 2009-2012 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 @@ -13,8 +13,7 @@ # 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. +# with this program; if not, see . # # Written by Bruno Haible . # diff --git a/contrib/grep/lib/regcomp.c b/contrib/grep/lib/regcomp.c index e734f47f6a..1334f47234 100644 --- a/contrib/grep/lib/regcomp.c +++ b/contrib/grep/lib/regcomp.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Extended regular expression matching and search library. - Copyright (C) 2002-2011 Free Software Foundation, Inc. + Copyright (C) 2002-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . @@ -16,8 +14,7 @@ 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. */ + with this program; if not, see . */ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax); @@ -208,7 +205,7 @@ static const size_t __re_error_msgid_idx[] = compiles PATTERN (of length LENGTH) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. - Assumes the `allocated' (and perhaps `buffer') and `translate' fields + Assumes the 'allocated' (and perhaps 'buffer') and 'translate' fields are set in BUFP on entry. */ #ifdef _LIBC @@ -243,7 +240,7 @@ re_compile_pattern (const char *pattern, size_t length, weak_alias (__re_compile_pattern, re_compile_pattern) #endif -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can +/* Set by 're_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ /* This has no initializer because initialized variables in Emacs @@ -275,7 +272,7 @@ int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + re_dfa_t *dfa = bufp->buffer; char *fastmap = bufp->fastmap; memset (fastmap, '\0', sizeof (char) * SBC_MAX); @@ -309,7 +306,7 @@ static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap) { - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + re_dfa_t *dfa = bufp->buffer; Idx node_cnt; bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) @@ -441,15 +438,15 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + 'buffer' to the compiled pattern; + 'used' to the length of the compiled pattern; + 'syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' to an allocated space for the fastmap; - `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. + 'newline_anchor' to REG_NEWLINE being set in CFLAGS; + 'fastmap' to an allocated space for the fastmap; + 'fastmap_accurate' to zero; + 're_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. @@ -588,19 +585,23 @@ weak_alias (__regerror, regerror) static const bitset_t utf8_sb_map = { /* Set the first 128 bits. */ -# if 4 * BITSET_WORD_BITS < ASCII_CHARS -# error "bitset_word_t is narrower than 32 bits" -# elif 3 * BITSET_WORD_BITS < ASCII_CHARS +# ifdef __GNUC__ + [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX +# else +# if 4 * BITSET_WORD_BITS < ASCII_CHARS +# error "bitset_word_t is narrower than 32 bits" +# elif 3 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 2 * BITSET_WORD_BITS < ASCII_CHARS +# elif 2 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 1 * BITSET_WORD_BITS < ASCII_CHARS +# elif 1 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, -# endif +# endif (BITSET_WORD_MAX >> (SBC_MAX % BITSET_WORD_BITS == 0 ? 0 : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) +# endif }; #endif @@ -659,7 +660,7 @@ void regfree (preg) regex_t *preg; { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; if (BE (dfa != NULL, 1)) free_dfa_content (dfa); preg->buffer = NULL; @@ -720,7 +721,7 @@ re_comp (s) + __re_error_msgid_idx[(int) REG_ESPACE]); } - /* Since `re_exec' always passes NULL for the `regs' argument, we + /* Since 're_exec' always passes NULL for the 'regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ @@ -731,7 +732,7 @@ re_comp (s) if (!ret) return NULL; - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ + /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */ return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } @@ -766,7 +767,7 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length, preg->regs_allocated = REGS_UNALLOCATED; /* Initialize the dfa. */ - dfa = (re_dfa_t *) preg->buffer; + dfa = preg->buffer; if (BE (preg->allocated < sizeof (re_dfa_t), 0)) { /* If zero allocated, but buffer is non-null, try to realloc @@ -777,7 +778,7 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length, if (dfa == NULL) return REG_ESPACE; preg->allocated = sizeof (re_dfa_t); - preg->buffer = (unsigned char *) dfa; + preg->buffer = dfa; } preg->used = sizeof (re_dfa_t); @@ -852,7 +853,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) { __re_size_t table_size; #ifndef _LIBC - char *codeset_name; + const char *codeset_name; #endif #ifdef RE_ENABLE_I18N size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); @@ -875,7 +876,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) calculation below, and for similar doubling calculations elsewhere. And it's <= rather than <, because some of the doubling calculations add 1 afterwards. */ - if (BE (SIZE_MAX / max_object_size / 2 <= pat_len, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2 <= pat_len, 0)) return REG_ESPACE; dfa->nodes_alloc = pat_len + 1; @@ -949,9 +950,39 @@ static void internal_function init_word_char (re_dfa_t *dfa) { - int i, j, ch; dfa->word_ops_used = 1; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + int i = 0; + int j; + int ch = 0; + if (BE (dfa->map_notascii == 0, 1)) + { + if (BITSET_WORD_BITS == 64) + { + dfa->word_char[0] = UINT64_C (0x03ff000000000000); + dfa->word_char[1] = UINT64_C (0x07fffffe87fffffe); + i = 2; + } + else if (BITSET_WORD_BITS == 32) + { + dfa->word_char[0] = UINT32_C (0x00000000); + dfa->word_char[1] = UINT32_C (0x03ff0000); + dfa->word_char[2] = UINT32_C (0x87fffffe); + dfa->word_char[3] = UINT32_C (0x07fffffe); + i = 4; + } + else + goto general_case; + ch = 128; + + if (BE (dfa->is_utf8, 1)) + { + memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8); + return; + } + } + + general_case: + for (; i < BITSET_WORDS; ++i) for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) if (isalnum (ch) || ch == '_') dfa->word_char[i] |= (bitset_word_t) 1 << j; @@ -962,7 +993,7 @@ init_word_char (re_dfa_t *dfa) static void free_workarea_compile (regex_t *preg) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_storage_t *storage, *next; for (storage = dfa->str_tree_storage; storage; storage = next) { @@ -1146,7 +1177,7 @@ optimize_utf8 (re_dfa_t *dfa) static reg_errcode_t analyze (regex_t *preg) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; reg_errcode_t ret; /* Allocate arrays. */ @@ -1327,7 +1358,7 @@ lower_subexps (void *extra, bin_tree_t *node) static bin_tree_t * lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *body = node->left; bin_tree_t *op, *cls, *tree1, *tree; @@ -1661,7 +1692,7 @@ calc_eclosure (re_dfa_t *dfa) /* If we have already calculated, skip it. */ if (dfa->eclosures[node_idx].nelem != 0) continue; - /* Calculate epsilon closure of `node_idx'. */ + /* Calculate epsilon closure of 'node_idx'. */ err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); if (BE (err != REG_NOERROR, 0)) return err; @@ -1711,14 +1742,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) { re_node_set eclosure_elem; Idx edest = dfa->edests[node].elems[i]; - /* If calculating the epsilon closure of `edest' is in progress, + /* If calculating the epsilon closure of 'edest' is in progress, return intermediate result. */ if (dfa->eclosures[edest].nelem == REG_MISSING) { incomplete = true; continue; } - /* If we haven't calculated the epsilon closure of `edest' yet, + /* If we haven't calculated the epsilon closure of 'edest' yet, calculate now. Otherwise use calculated epsilon closure. */ if (dfa->eclosures[edest].nelem == 0) { @@ -1728,11 +1759,11 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) } else eclosure_elem = dfa->eclosures[edest]; - /* Merge the epsilon closure of `edest'. */ + /* Merge the epsilon closure of 'edest'. */ err = re_node_set_merge (&eclosure, &eclosure_elem); if (BE (err != REG_NOERROR, 0)) return err; - /* If the epsilon closure of `edest' is incomplete, + /* If the epsilon closure of 'edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) { @@ -2094,7 +2125,7 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) /* Entry point of the parser. Parse the regular expression REGEXP and return the structure tree. - If an error is occured, ERR is set by error code, and return NULL. + If an error occurs, ERR is set by error code, and return NULL. This function build the following tree, from regular expression : CAT / \ @@ -2108,7 +2139,7 @@ static bin_tree_t * parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree, *eor, *root; re_token_t current_token; dfa->syntax = syntax; @@ -2136,13 +2167,13 @@ parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, / \ - ALT means alternative, which represents the operator `|'. */ + ALT means alternative, which represents the operator '|'. */ static bin_tree_t * parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree, *branch = NULL; tree = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) @@ -2184,7 +2215,7 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { bin_tree_t *tree, *expr; - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; tree = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; @@ -2195,16 +2226,21 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, expr = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && expr == NULL, 0)) { + if (tree != NULL) + postorder (tree, free_tree, NULL); return NULL; } if (tree != NULL && expr != NULL) { - tree = create_tree (dfa, tree, expr, CONCAT); - if (tree == NULL) + bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT); + if (newtree == NULL) { + postorder (expr, free_tree, NULL); + postorder (tree, free_tree, NULL); *err = REG_ESPACE; return NULL; } + tree = newtree; } else if (tree == NULL) tree = expr; @@ -2223,7 +2259,7 @@ static bin_tree_t * parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree; switch (token->type) { @@ -2439,7 +2475,7 @@ static bin_tree_t * parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree; size_t cur_nsub; cur_nsub = preg->re_nsub++; @@ -2453,7 +2489,11 @@ parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, { tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) - *err = REG_EPAREN; + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + *err = REG_EPAREN; + } if (BE (*err != REG_NOERROR, 0)) return NULL; } @@ -2531,6 +2571,12 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, *err = REG_BADBR; return NULL; } + + if (BE (RE_DUP_MAX < (end == REG_MISSING ? start : end), 0)) + { + *err = REG_ESIZE; + return NULL; + } } else { @@ -2617,7 +2663,7 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may + mbcset->range_ends, is a pointer argument since we may update it. */ static reg_errcode_t @@ -2751,12 +2797,14 @@ build_range_exp (const reg_syntax_t syntax, static reg_errcode_t internal_function -build_collating_symbol (bitset_t sbcset, # ifdef RE_ENABLE_I18N - re_charset_t *mbcset _UNUSED_PARAMETER_, +build_collating_symbol (bitset_t sbcset, + re_charset_t *mbcset _UNUSED_PARAMETER_, Idx *coll_sym_alloc _UNUSED_PARAMETER_, -# endif - const unsigned char *name) + const unsigned char *name) +# else /* not RE_ENABLE_I18N */ +build_collating_symbol (bitset_t sbcset, const unsigned char *name) +# endif /* not RE_ENABLE_I18N */ { size_t name_len = strlen ((const char *) name); if (BE (name_len != 1, 0)) @@ -2784,8 +2832,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, const int32_t *symb_table; const unsigned char *extra; - /* Local function for parse_bracket_exp used in _LIBC environement. - Seek the collating symbol entry correspondings to NAME. + /* Local function for parse_bracket_exp used in _LIBC environment. + Seek the collating symbol entry corresponding to NAME. Return the index of the symbol in the SYMB_TABLE. */ auto inline int32_t @@ -2888,11 +2936,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, return UINT_MAX; } - /* Local function for parse_bracket_exp used in _LIBC environement. + /* Local function for parse_bracket_exp used in _LIBC environment. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may + mbcset->range_ends, is a pointer argument since we may update it. */ auto inline reg_errcode_t @@ -2972,11 +3020,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, return REG_NOERROR; } - /* Local function for parse_bracket_exp used in _LIBC environement. + /* Local function for parse_bracket_exp used in _LIBC environment. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument sinse we may update it. */ + pointer argument since we may update it. */ auto inline reg_errcode_t __attribute ((always_inline)) @@ -3078,6 +3126,10 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, if (BE (sbcset == NULL, 0)) #endif /* RE_ENABLE_I18N */ { + re_free (sbcset); +#ifdef RE_ENABLE_I18N + re_free (mbcset); +#endif *err = REG_ESPACE; return NULL; } @@ -3417,11 +3469,12 @@ parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, Build the equivalence class which is represented by NAME. The result are written to MBCSET and SBCSET. EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, - is a pointer argument sinse we may update it. */ + is a pointer argument since we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N -build_equiv_class (bitset_t sbcset, re_charset_t *mbcset _UNUSED_PARAMETER_, +build_equiv_class (bitset_t sbcset, + re_charset_t *mbcset _UNUSED_PARAMETER_, Idx *equiv_class_alloc _UNUSED_PARAMETER_, const unsigned char *name) #else /* not RE_ENABLE_I18N */ @@ -3449,19 +3502,18 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - idx1 = findidx (&cp); - if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) + idx1 = findidx (&cp, -1); + if (BE (idx1 == 0 || *cp != '\0', 0)) /* This isn't a valid character. */ return REG_ECOLLATE; - /* Build single byte matcing table for this equivalence class. */ - char_buf[1] = (unsigned char) '\0'; + /* Build single byte matching table for this equivalence class. */ len = weights[idx1 & 0xffffff]; for (ch = 0; ch < SBC_MAX; ++ch) { char_buf[0] = ch; cp = char_buf; - idx2 = findidx (&cp); + idx2 = findidx (&cp, 1); /* idx2 = table[ch]; */ @@ -3514,7 +3566,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) Build the character class which is represented by NAME. The result are written to MBCSET and SBCSET. CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, - is a pointer argument sinse we may update it. */ + is a pointer argument since we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N @@ -3708,8 +3760,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, } /* This is intended for the expressions like "a{1,3}". - Fetch a number from `input', and return the number. + Fetch a number from 'input', and return the number. Return REG_MISSING if the number field is empty like "{,1}". + Return RE_DUP_MAX + 1 if the number field is too large. Return REG_ERROR if an error occurred. */ static Idx @@ -3728,8 +3781,9 @@ fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) num = ((token->type != CHARACTER || c < '0' || '9' < c || num == REG_ERROR) ? REG_ERROR - : ((num == REG_MISSING) ? c - '0' : num * 10 + c - '0')); - num = (num > RE_DUP_MAX) ? REG_ERROR : num; + : num == REG_MISSING + ? c - '0' + : MIN (RE_DUP_MAX + 1, num * 10 + c - '0')); } return num; } diff --git a/contrib/grep/lib/regex.c b/contrib/grep/lib/regex.c index fc46c0ba2d..7b440493f6 100644 --- a/contrib/grep/lib/regex.c +++ b/contrib/grep/lib/regex.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Extended regular expression matching and search library. - Copyright (C) 2002-2003, 2005-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2005-2006, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . @@ -16,12 +14,20 @@ 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. */ + with this program; if not, see . */ -#include +#ifndef _LIBC +# include -/* Make sure noone compiles this code with a C++ compiler. */ +# if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +# endif +# if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wtype-limits" +# endif +#endif + +/* Make sure no one compiles this code with a C++ compiler. */ #if defined __cplusplus && defined _LIBC # error "This is C code, use a C compiler" #endif diff --git a/contrib/grep/lib/regex.h b/contrib/grep/lib/regex.h index 52b8598c5c..211b5fcb27 100644 --- a/contrib/grep/lib/regex.h +++ b/contrib/grep/lib/regex.h @@ -1,8 +1,6 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Definitions for data structures and routines for the regular expression library. - Copyright (C) 1985, 1989-1993, 1995-1998, 2000-2003, 2005-2006, 2009-2011 + Copyright (C) 1985, 1989-1993, 1995-1998, 2000-2003, 2005-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,8 +15,7 @@ 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. */ + with this program; if not, see . */ #ifndef _REGEX_H #define _REGEX_H 1 @@ -30,13 +27,10 @@ extern "C" { #endif -/* Define __USE_GNU_REGEX to declare GNU extensions that violate the +/* Define __USE_GNU to declare GNU extensions that violate the POSIX name space rules. */ -#undef __USE_GNU_REGEX -#if (defined _GNU_SOURCE \ - || (!defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE \ - && !defined _XOPEN_SOURCE)) -# define __USE_GNU_REGEX 1 +#ifdef _GNU_SOURCE +# define __USE_GNU 1 #endif #ifdef _REGEX_LARGE_OFFSETS @@ -47,16 +41,6 @@ extern "C" { supported within glibc itself, and glibc users should not define _REGEX_LARGE_OFFSETS. */ -/* The type of the offset of a byte within a string. - For historical reasons POSIX 1003.1-2004 requires that regoff_t be - at least as wide as off_t. However, many common POSIX platforms set - regoff_t to the more-sensible ssize_t and the Open Group has - signalled its intention to change the requirement to be that - regoff_t be at least as wide as ptrdiff_t and ssize_t; see XBD ERN - 60 (2005-08-25). We don't know of any hosts where ssize_t or - ptrdiff_t is wider than ssize_t, so ssize_t is safe. */ -typedef ssize_t regoff_t; - /* The type of nonnegative object indexes. Traditionally, GNU regex uses 'int' for these. Code that uses __re_idx_t should work regardless of whether the type is signed. */ @@ -71,10 +55,8 @@ typedef size_t __re_long_size_t; #else -/* Use types that are binary-compatible with the traditional GNU regex - implementation, which mishandles strings longer than INT_MAX. */ - -typedef int regoff_t; +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ typedef int __re_idx_t; typedef unsigned int __re_size_t; typedef unsigned long int __re_long_size_t; @@ -95,8 +77,7 @@ typedef unsigned long int active_reg_t; add or remove a bit, only one other definition need change. */ typedef unsigned long int reg_syntax_t; -#ifdef __USE_GNU_REGEX - +#ifdef __USE_GNU /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ # define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) @@ -163,9 +144,9 @@ typedef unsigned long int reg_syntax_t; If not set, newline is literal. */ # define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) -/* If this bit is set, then `{...}' defines an interval, and \{ and \} +/* If this bit is set, then '{...}' defines an interval, and \{ and \} are literals. - If not set, then `\{...\}' defines an interval. */ + If not set, then '\{...\}' defines an interval. */ # define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. @@ -227,8 +208,7 @@ typedef unsigned long int reg_syntax_t; /* If this bit is set, then no_sub will be set to 1 during re_compile_pattern. */ # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) - -#endif /* defined __USE_GNU_REGEX */ +#endif /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is @@ -236,7 +216,7 @@ typedef unsigned long int reg_syntax_t; already-compiled regexps. */ extern reg_syntax_t re_syntax_options; -#ifdef __USE_GNU_REGEX +#ifdef __USE_GNU /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ @@ -248,16 +228,19 @@ extern reg_syntax_t re_syntax_options; | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CHAR_CLASSES \ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) # define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ - & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ - | RE_CONTEXT_INVALID_OPS )) + ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INVALID_INTERVAL_ORD) \ + & ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \ + | RE_CONTEXT_INVALID_OPS )) # define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS) + | RE_INTERVALS | RE_NO_GNU_OPS \ + | RE_INVALID_INTERVAL_ORD) # define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ @@ -308,13 +291,12 @@ extern reg_syntax_t re_syntax_options; | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ -#endif /* defined __USE_GNU_REGEX */ - -#ifdef __USE_GNU_REGEX - /* Maximum number of duplicates an interval can allow. POSIX-conforming systems might define this in , but we want our value, so remove any previous define. */ +# ifdef _REGEX_INCLUDE_LIMITS_H +# include +# endif # ifdef RE_DUP_MAX # undef RE_DUP_MAX # endif @@ -322,16 +304,15 @@ extern reg_syntax_t re_syntax_options; /* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored the counter as a 2-byte signed integer. This is no longer true, so RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to - ((SIZE_MAX - 2) / 10 - 1) if _REGEX_LARGE_OFFSETS is defined. + ((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined. However, there would be a huge performance problem if someone actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains its historical value. */ # define RE_DUP_MAX (0x7fff) - -#endif /* defined __USE_GNU_REGEX */ +#endif -/* POSIX `cflags' bits (i.e., information for `regcomp'). */ +/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ @@ -351,7 +332,7 @@ extern reg_syntax_t re_syntax_options; #define REG_NOSUB (1 << 3) -/* POSIX `eflags' bits (i.e., information for regexec). */ +/* POSIX 'eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the @@ -369,7 +350,7 @@ extern reg_syntax_t re_syntax_options; /* If any error codes are removed, changed, or added, update the - `__re_error_msgid' table in regcomp.c. */ + '__re_error_msgid' table in regcomp.c. */ typedef enum { @@ -394,11 +375,11 @@ typedef enum /* Error codes we've added. */ _REG_EEND, /* Premature end. */ - _REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + _REG_ESIZE, /* Too large (e.g., repeat count too large). */ _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; -#ifdef _XOPEN_SOURCE +#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K # define REG_ENOSYS _REG_ENOSYS #endif #define REG_NOERROR _REG_NOERROR @@ -419,126 +400,127 @@ typedef enum #define REG_ESIZE _REG_ESIZE #define REG_ERPAREN _REG_ERPAREN -/* struct re_pattern_buffer normally uses member names like `buffer' - that POSIX does not allow. In POSIX mode these members have names - with leading `re_' (e.g., `re_buffer'). */ -#ifdef __USE_GNU_REGEX -# define _REG_RE_NAME(id) id -# define _REG_RM_NAME(id) id -#else -# define _REG_RE_NAME(id) re_##id -# define _REG_RM_NAME(id) rm_##id +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields 'buffer', 'allocated', 'fastmap', + and 'translate' can be set. After the pattern has been compiled, + the fields 're_nsub', 'not_bol' and 'not_eol' are available. All + other fields are private to the regex routines. */ + +#ifndef RE_TRANSLATE_TYPE +# define __RE_TRANSLATE_TYPE unsigned char * +# ifdef __USE_GNU +# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE +# endif #endif -/* The user can specify the type of the re_translate member by - defining the macro RE_TRANSLATE_TYPE, which defaults to unsigned - char *. This pollutes the POSIX name space, so in POSIX mode just - use unsigned char *. */ -#ifdef __USE_GNU_REGEX -# ifndef RE_TRANSLATE_TYPE -# define RE_TRANSLATE_TYPE unsigned char * -# endif -# define REG_TRANSLATE_TYPE RE_TRANSLATE_TYPE +#ifdef __USE_GNU +# define __REPB_PREFIX(name) name #else -# define REG_TRANSLATE_TYPE unsigned char * +# define __REPB_PREFIX(name) __##name #endif -/* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields `buffer', `allocated', `fastmap', - `translate', and `no_sub' can be set. After the pattern has been - compiled, the `re_nsub' field is available. All other fields are - private to the regex routines. */ - struct re_pattern_buffer { - /* Space that holds the compiled pattern. It is declared as - `unsigned char *' because its elements are sometimes used as - array indexes. */ - unsigned char *_REG_RE_NAME (buffer); + /* Space that holds the compiled pattern. The type + 'struct re_dfa_t' is private and is not declared here. */ + struct re_dfa_t *__REPB_PREFIX(buffer); - /* Number of bytes to which `buffer' points. */ - __re_long_size_t _REG_RE_NAME (allocated); + /* Number of bytes to which 'buffer' points. */ + __re_long_size_t __REPB_PREFIX(allocated); - /* Number of bytes actually used in `buffer'. */ - __re_long_size_t _REG_RE_NAME (used); + /* Number of bytes actually used in 'buffer'. */ + __re_long_size_t __REPB_PREFIX(used); /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t _REG_RE_NAME (syntax); + reg_syntax_t __REPB_PREFIX(syntax); /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ - char *_REG_RE_NAME (fastmap); + char *__REPB_PREFIX(fastmap); /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ - REG_TRANSLATE_TYPE _REG_RE_NAME (translate); + __RE_TRANSLATE_TYPE __REPB_PREFIX(translate); /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in `re_search_2', to see whether or + Well, in truth it's used only in 're_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely - perfectly; see `re_compile_fastmap' (the `duplicate' case). */ - unsigned int _REG_RE_NAME (can_be_null) : 1; + perfectly; see 're_compile_fastmap' (the "duplicate" case). */ + unsigned __REPB_PREFIX(can_be_null) : 1; - /* If REGS_UNALLOCATED, allocate space in the `regs' structure - for `max (RE_NREGS, re_nsub + 1)' groups. + /* If REGS_UNALLOCATED, allocate space in the 'regs' structure + for 'max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ -#ifdef __USE_GNU_REGEX +#ifdef __USE_GNU # define REGS_UNALLOCATED 0 # define REGS_REALLOCATE 1 # define REGS_FIXED 2 #endif - unsigned int _REG_RE_NAME (regs_allocated) : 2; + unsigned __REPB_PREFIX(regs_allocated) : 2; - /* Set to zero when `re_compile_pattern' compiles a pattern; set to - one by `re_compile_fastmap' if it updates the fastmap. */ - unsigned int _REG_RE_NAME (fastmap_accurate) : 1; + /* Set to zero when 're_compile_pattern' compiles a pattern; set to + one by 're_compile_fastmap' if it updates the fastmap. */ + unsigned __REPB_PREFIX(fastmap_accurate) : 1; - /* If set, `re_match_2' does not return information about + /* If set, 're_match_2' does not return information about subexpressions. */ - unsigned int _REG_RE_NAME (no_sub) : 1; + unsigned __REPB_PREFIX(no_sub) : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ - unsigned int _REG_RE_NAME (not_bol) : 1; + unsigned __REPB_PREFIX(not_bol) : 1; /* Similarly for an end-of-line anchor. */ - unsigned int _REG_RE_NAME (not_eol) : 1; + unsigned __REPB_PREFIX(not_eol) : 1; /* If true, an anchor at a newline matches. */ - unsigned int _REG_RE_NAME (newline_anchor) : 1; - -/* [[[end pattern_buffer]]] */ + unsigned __REPB_PREFIX(newline_anchor) : 1; }; typedef struct re_pattern_buffer regex_t; +/* Type for byte offsets within the string. POSIX mandates this. */ +#ifdef _REGEX_LARGE_OFFSETS +/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as + ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t + is wider than ssize_t, so ssize_t is safe. */ +typedef ssize_t regoff_t; +#else +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ +typedef int regoff_t; +#endif + + +#ifdef __USE_GNU /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { - __re_size_t _REG_RM_NAME (num_regs); - regoff_t *_REG_RM_NAME (start); - regoff_t *_REG_RM_NAME (end); + __re_size_t num_regs; + regoff_t *start; + regoff_t *end; }; -/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - `re_match_2' returns information about at least this many registers - the first time a `regs' structure is passed. */ -#if !defined RE_NREGS && defined __USE_GNU_REGEX -# define RE_NREGS 30 +/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + 're_match_2' returns information about at least this many registers + the first time a 'regs' structure is passed. */ +# ifndef RE_NREGS +# define RE_NREGS 30 +# endif #endif /* POSIX specification for registers. Aside from the different names than - `re_registers', POSIX uses an array of structures, instead of a + 're_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { @@ -548,13 +530,19 @@ typedef struct /* Declarations for routines. */ +#ifdef __USE_GNU /* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the `re_syntax_options' variable. */ + You can also simply assign to the 're_syntax_options' variable. */ extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); /* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global `re_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. */ + and syntax given by the global 're_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. + + To free the allocated storage, you must call 'regfree' on BUFFER. + Note that the translate table must either have been initialised by + 'regcomp', with a malloc'ed value, or set to NULL before calling + 'regfree'. */ extern const char *re_compile_pattern (const char *__pattern, size_t __length, struct re_pattern_buffer *__buffer); @@ -576,7 +564,7 @@ extern regoff_t re_search (struct re_pattern_buffer *__buffer, struct re_registers *__regs); -/* Like `re_search', but search in the concatenation of STRING1 and +/* Like 're_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, const char *__string1, __re_idx_t __length1, @@ -586,14 +574,14 @@ extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, __re_idx_t __stop); -/* Like `re_search', but return how many characters in STRING the regexp +/* Like 're_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern regoff_t re_match (struct re_pattern_buffer *__buffer, const char *__string, __re_idx_t __length, __re_idx_t __start, struct re_registers *__regs); -/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +/* Relates to 're_match' as 're_search_2' relates to 're_search'. */ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, const char *__string1, __re_idx_t __length1, const char *__string2, __re_idx_t __length2, @@ -604,21 +592,22 @@ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be - allocated with malloc, and must each be at least `NUM_REGS * sizeof + allocated with malloc, and must each be at least 'NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using - BUFFER will allocate its own register data, without freeing the old - data. */ + BUFFER will allocate its own register data, without + freeing the old data. */ extern void re_set_registers (struct re_pattern_buffer *__buffer, struct re_registers *__regs, __re_size_t __num_regs, regoff_t *__starts, regoff_t *__ends); +#endif /* Use GNU */ -#if defined _REGEX_RE_COMP || defined _LIBC +#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_BSD) # ifndef _CRAY /* 4.2 bsd compatibility. */ extern char *re_comp (const char *); @@ -646,7 +635,7 @@ extern int re_exec (const char *); #ifndef _Restrict_arr_ # if ((199901L <= __STDC_VERSION__ \ || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \ - && !__STRICT_ANSI__)) \ + && !defined __STRICT_ANSI__)) \ && !defined __GNUG__) # define _Restrict_arr_ _Restrict_ # else diff --git a/contrib/grep/lib/regex_internal.c b/contrib/grep/lib/regex_internal.c index dcfb0df67d..9537297370 100644 --- a/contrib/grep/lib/regex_internal.c +++ b/contrib/grep/lib/regex_internal.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Extended regular expression matching and search library. - Copyright (C) 2002-2011 Free Software Foundation, Inc. + Copyright (C) 2002-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . @@ -16,8 +14,7 @@ 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. */ + with this program; if not, see . */ #include "verify.h" #include "intprops.h" @@ -138,9 +135,9 @@ re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) { wint_t *new_wcs; - /* Avoid overflow. */ - size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); - if (BE (SIZE_MAX / max_object_size < new_buf_len, 0)) + /* Avoid overflow in realloc. */ + const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_buf_len, 0)) return REG_ESPACE; new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); @@ -240,13 +237,8 @@ build_wcs_buffer (re_string_t *pstr) else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2, 0)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) + if (BE (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len), 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; @@ -255,6 +247,12 @@ build_wcs_buffer (re_string_t *pstr) wc = pstr->trans[wc]; pstr->cur_state = prev_st; } + else if (BE (mbclen == (size_t) -2, 0)) + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } /* Write wide character and padding. */ pstr->wcs[byte_idx++] = wc; @@ -337,9 +335,11 @@ build_wcs_upper_buffer (re_string_t *pstr) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } - else if (mbclen == (size_t) -1 || mbclen == 0) + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) { - /* It is an invalid character or '\0'. Just use the byte. */ + /* It is an invalid character, an incomplete character + at the end of the string, or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; pstr->mbs[byte_idx] = ch; /* And also cast it to wide char. */ @@ -452,7 +452,8 @@ build_wcs_upper_buffer (re_string_t *pstr) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } - else if (mbclen == (size_t) -1 || mbclen == 0) + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; @@ -499,8 +500,7 @@ re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) rawbuf_idx < new_raw_idx;) { wchar_t wc2; - Idx remain_len; - remain_len = pstr->len - rawbuf_idx; + Idx remain_len = pstr->raw_len - rawbuf_idx; prev_st = pstr->cur_state; mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, remain_len, &pstr->cur_state); @@ -736,21 +736,21 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) mbstate_t cur_state; wchar_t wc2; Idx mlen = raw + pstr->len - p; + unsigned char buf[6]; size_t mbclen; -#if 0 /* dead code: buf is set but never used */ - unsigned char buf[6]; + const unsigned char *pp = p; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; + pp = buf; } -#endif /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); - mbclen = __mbrtowc (&wc2, (const char *) p, mlen, + mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, &cur_state); if (raw + offset - p <= mbclen && mbclen < (size_t) -2) @@ -872,7 +872,7 @@ re_string_peek_byte_case (const re_string_t *pstr, Idx idx) } static unsigned char -internal_function __attribute ((pure)) +internal_function re_string_fetch_byte_case (re_string_t *pstr) { if (BE (!pstr->mbs_allocated, 1)) @@ -1419,13 +1419,12 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) Idx *new_nexts, *new_indices; re_node_set *new_edests, *new_eclosures; re_token_t *new_nodes; - size_t max_object_size = - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - sizeof (Idx))); - /* Avoid overflows. */ - if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0)) + /* Avoid overflows in realloc. */ + const size_t max_object_size = MAX (sizeof (re_token_t), + MAX (sizeof (re_node_set), + sizeof (Idx))); + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_nodes_alloc, 0)) return REG_MISSING; new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); @@ -1557,7 +1556,7 @@ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, && re_node_set_compare (state->entrance_nodes, nodes)) return state; } - /* There are no appropriate state in `dfa', create the new one. */ + /* There are no appropriate state in 'dfa', create the new one. */ new_state = create_cd_newstate (dfa, nodes, context, hash); if (BE (new_state == NULL, 0)) *err = REG_ESPACE; @@ -1586,7 +1585,7 @@ register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, { Idx elem = newstate->nodes.elems[i]; if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0)) + if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem)) return REG_ESPACE; } @@ -1621,7 +1620,7 @@ free_state (re_dfastate_t *state) re_free (state); } -/* Create the new state which is independ of contexts. +/* Create the new state which is independent of contexts. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * diff --git a/contrib/grep/lib/regex_internal.h b/contrib/grep/lib/regex_internal.h index 7ad6ee5da2..aa35ed90e3 100644 --- a/contrib/grep/lib/regex_internal.h +++ b/contrib/grep/lib/regex_internal.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Extended regular expression matching and search library. - Copyright (C) 2002-2011 Free Software Foundation, Inc. + Copyright (C) 2002-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . @@ -16,15 +14,13 @@ 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. */ + with this program; if not, see . */ #ifndef _REGEX_INTERNAL_H #define _REGEX_INTERNAL_H 1 #include #include -#include #include #include #include @@ -34,13 +30,14 @@ # include "localcharset.h" #endif #include - #include #include +#include #include #if defined _LIBC # include #else +# define __libc_lock_define(CLASS,NAME) # define __libc_lock_init(NAME) do { } while (0) # define __libc_lock_lock(NAME) do { } while (0) # define __libc_lock_unlock(NAME) do { } while (0) @@ -78,11 +75,6 @@ # define gettext_noop(String) String #endif -/* For loser systems without the definition. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - #if (defined MB_CUR_MAX && HAVE_WCTYPE_H && HAVE_ISWCTYPE && HAVE_WCSCOLL) || _LIBC # define RE_ENABLE_I18N #endif @@ -113,8 +105,8 @@ # define __wctype wctype # define __iswctype iswctype # define __btowc btowc -# define __wcrtomb wcrtomb # define __mbrtowc mbrtowc +# define __wcrtomb wcrtomb # define __regfree regfree # define attribute_hidden #endif /* not _LIBC */ @@ -126,6 +118,11 @@ #endif typedef __re_idx_t Idx; +#ifdef _REGEX_LARGE_OFFSETS +# define IDX_MAX (SIZE_MAX - 2) +#else +# define IDX_MAX INT_MAX +#endif /* Special return value for failure to match. */ #define REG_MISSING ((Idx) -1) @@ -336,7 +333,7 @@ typedef struct Idx idx; /* for BACK_REF */ re_context_type ctx_type; /* for ANCHOR */ } opr; -#if __GNUC__ >= 2 && !__STRICT_ANSI__ +#if __GNUC__ >= 2 && !defined __STRICT_ANSI__ re_token_type_t type : 8; #else re_token_type_t type; @@ -417,26 +414,24 @@ struct re_dfa_t; typedef struct re_dfa_t re_dfa_t; #ifndef _LIBC -# if defined __i386__ && !defined __EMX__ -# define internal_function __attribute ((regparm (3), stdcall)) -# else -# define internal_function -# endif +# define internal_function #endif +#ifndef NOT_IN_libc static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) internal_function; -#ifdef RE_ENABLE_I18N +# ifdef RE_ENABLE_I18N static void build_wcs_buffer (re_string_t *pstr) internal_function; static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) - internal_function; -#endif /* RE_ENABLE_I18N */ + internal_function; +# endif /* RE_ENABLE_I18N */ static void build_upper_buffer (re_string_t *pstr) internal_function; static void re_string_translate_buffer (re_string_t *pstr) internal_function; static unsigned int re_string_context_at (const re_string_t *input, Idx idx, int eflags) internal_function __attribute ((pure)); +#endif #define re_string_peek_byte(pstr, offset) \ ((pstr)->mbs[(pstr)->cur_idx + offset]) #define re_string_fetch_byte(pstr) \ @@ -474,6 +469,9 @@ static unsigned int re_string_context_at (const re_string_t *input, Idx idx, #ifndef MAX # define MAX(a,b) ((a) < (b) ? (b) : (a)) #endif +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) @@ -489,8 +487,8 @@ struct bin_tree_t re_token_t token; - /* `node_idx' is the index in dfa->nodes, if `type' == 0. - Otherwise `type' indicate the type of this node. */ + /* 'node_idx' is the index in dfa->nodes, if 'type' == 0. + Otherwise 'type' indicate the type of this node. */ Idx node_idx; }; typedef struct bin_tree_t bin_tree_t; @@ -543,9 +541,9 @@ struct re_dfastate_t struct re_dfastate_t **trtable, **word_trtable; unsigned int context : 4; unsigned int halt : 1; - /* If this state can accept `multi byte'. + /* If this state can accept "multi byte". Note that we refer to multibyte characters, and multi character - collating elements as `multi byte'. */ + collating elements as "multi byte". */ unsigned int accept_mb : 1; /* If this state has backreference node(s). */ unsigned int has_backref : 1; @@ -674,7 +672,7 @@ struct re_dfa_t re_bitset_ptr_t sb_char; int str_tree_storage_idx; - /* number of subexpressions `re_nsub' is in regex_t. */ + /* number of subexpressions 're_nsub' is in regex_t. */ re_hashval_t state_hash_mask; Idx init_node; Idx nbackref; /* The number of backreference in this dfa. */ @@ -698,9 +696,7 @@ struct re_dfa_t #ifdef DEBUG char* re_str; #endif -#ifdef _LIBC __libc_lock_define (, lock) -#endif }; #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) @@ -824,16 +820,16 @@ re_string_wchar_at (const re_string_t *pstr, Idx idx) return (wint_t) pstr->wcs[idx]; } +# ifndef NOT_IN_libc static int internal_function __attribute ((pure)) re_string_elem_size_at (const re_string_t *pstr _UNUSED_PARAMETER_, Idx idx _UNUSED_PARAMETER_) { -# ifdef _LIBC +# ifdef _LIBC const unsigned char *p, *extra; const int32_t *table, *indirect; - int32_t tmp; -# include +# include uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) @@ -844,13 +840,14 @@ re_string_elem_size_at (const re_string_t *pstr _UNUSED_PARAMETER_, indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); p = pstr->mbs + idx; - tmp = findidx (&p); + findidx (&p, pstr->len - idx); return p - pstr->mbs - idx; } else -# endif /* _LIBC */ +# endif /* _LIBC */ return 1; } +# endif #endif /* RE_ENABLE_I18N */ #ifndef __GNUC_PREREQ diff --git a/contrib/grep/lib/regexec.c b/contrib/grep/lib/regexec.c index ac67aebe98..5461bf6d3c 100644 --- a/contrib/grep/lib/regexec.c +++ b/contrib/grep/lib/regexec.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Extended regular expression matching and search library. - Copyright (C) 2002-2011 Free Software Foundation, Inc. + Copyright (C) 2002-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . @@ -16,8 +14,7 @@ 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. */ + with this program; if not, see . */ #include "verify.h" #include "intprops.h" @@ -55,9 +52,8 @@ static regoff_t re_search_stub (struct re_pattern_buffer *bufp, regoff_t range, Idx stop, struct re_registers *regs, bool ret_len) internal_function; -static unsigned int re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, - Idx nregs, int regs_allocated) - internal_function; +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, + Idx nregs, int regs_allocated) internal_function; static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) internal_function; static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, @@ -213,11 +209,11 @@ static reg_errcode_t extend_buffers (re_match_context_t *mctx) string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + 'regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. - EFLAGS specifies `execution flags' which affect matching: if + EFLAGS specifies "execution flags" which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. @@ -234,7 +230,7 @@ regexec (preg, string, nmatch, pmatch, eflags) reg_errcode_t err; Idx start, length; #ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; #endif if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) @@ -369,7 +365,6 @@ weak_alias (__re_search_2, re_search_2) #endif static regoff_t -internal_function re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, Idx length1, const char *string2, Idx length2, @@ -420,7 +415,6 @@ re_search_2_stub (struct re_pattern_buffer *bufp, otherwise the position of the match is returned. */ static regoff_t -internal_function re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length, Idx start, regoff_t range, Idx stop, struct re_registers *regs, @@ -432,7 +426,7 @@ re_search_stub (struct re_pattern_buffer *bufp, regoff_t rval; int eflags = 0; #ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + re_dfa_t *dfa = bufp->buffer; #endif Idx last_start = start + range; @@ -489,7 +483,7 @@ re_search_stub (struct re_pattern_buffer *bufp, /* I hope we needn't fill ther regs with -1's when no match was found. */ if (result != REG_NOERROR) - rval = -1; + rval = result == REG_NOMATCH ? -1 : -2; else if (regs != NULL) { /* If caller wants register contents data back, copy them. */ @@ -515,15 +509,14 @@ re_search_stub (struct re_pattern_buffer *bufp, return rval; } -static unsigned int -internal_function +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, int regs_allocated) { int rval = REGS_REALLOCATE; Idx i; Idx need_regs = nregs + 1; - /* We need one extra element beyond `num_regs' for the `-1' marker GNU code + /* We need one extra element beyond 'num_regs' for the '-1' marker GNU code uses. */ /* Have the register data arrays been allocated? */ @@ -646,7 +639,7 @@ re_exec (s) (0 <= LAST_START && LAST_START <= LENGTH) */ static reg_errcode_t -internal_function __attribute_warn_unused_result__ +__attribute_warn_unused_result__ re_search_internal (const regex_t *preg, const char *string, Idx length, Idx start, Idx last_start, Idx stop, @@ -654,7 +647,7 @@ re_search_internal (const regex_t *preg, int eflags) { reg_errcode_t err; - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + const re_dfa_t *dfa = preg->buffer; Idx left_lim, right_lim; int incr; bool fl_longest_match; @@ -729,7 +722,8 @@ re_search_internal (const regex_t *preg, if (nmatch > 1 || dfa->has_mb_node) { /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0)) + if (BE ((MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) + <= mctx.input.bufs_len), 0)) { err = REG_ESPACE; goto free_return; @@ -931,7 +925,7 @@ re_search_internal (const regex_t *preg, goto free_return; } - /* At last, add the offset to the each registers, since we slided + /* At last, add the offset to each register, since we slid the buffers so that we could assume that the matching starts from 0. */ for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) @@ -981,7 +975,7 @@ re_search_internal (const regex_t *preg, } static reg_errcode_t -internal_function __attribute_warn_unused_result__ +__attribute_warn_unused_result__ prune_impossible_nodes (re_match_context_t *mctx) { const re_dfa_t *const dfa = mctx->dfa; @@ -997,7 +991,7 @@ prune_impossible_nodes (re_match_context_t *mctx) halt_node = mctx->last_node; /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) <= match_last, 0)) return REG_ESPACE; sifted_states = re_malloc (re_dfastate_t *, match_last + 1); @@ -1115,7 +1109,7 @@ acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, FL_LONGEST_MATCH means we want the POSIX longest matching. If P_MATCH_FIRST is not NULL, and the match fails, it is set to the next place where we may want to try matching. - Note that the matcher assume that the maching starts from the current + Note that the matcher assumes that the matching starts from the current index of the buffer. */ static Idx @@ -1184,7 +1178,8 @@ check_matching (re_match_context_t *mctx, bool fl_longest_match, re_dfastate_t *old_state = cur_state; Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; - if (BE (next_char_idx >= mctx->input.bufs_len, 0) + if ((BE (next_char_idx >= mctx->input.bufs_len, 0) + && mctx->input.bufs_len < mctx->input.len) || (BE (next_char_idx >= mctx->input.valid_len, 0) && mctx->input.valid_len < mctx->input.len)) { @@ -1445,7 +1440,7 @@ internal_function __attribute_warn_unused_result__ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, bool fl_backtrack) { - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + const re_dfa_t *dfa = preg->buffer; Idx idx, cur_node; re_node_set eps_via_nodes; struct re_fail_stack_t *fs; @@ -1617,21 +1612,21 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, and sift the nodes in each states according to the following rules. Updated state_log will be wrote to STATE_LOG. - Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... + Rules: We throw away the Node 'a' in the STATE_LOG[STR_IDX] if... 1. When STR_IDX == MATCH_LAST(the last index in the state_log): - If `a' isn't the LAST_NODE and `a' can't epsilon transit to - the LAST_NODE, we throw away the node `a'. - 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts - string `s' and transit to `b': + If 'a' isn't the LAST_NODE and 'a' can't epsilon transit to + the LAST_NODE, we throw away the node 'a'. + 2. When 0 <= STR_IDX < MATCH_LAST and 'a' accepts + string 's' and transit to 'b': i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw - away the node `a'. + away the node 'a'. ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is - thrown away, we throw away the node `a'. + thrown away, we throw away the node 'a'. 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the - node `a'. + node 'a'. ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, - we throw away the node `a'. */ + we throw away the node 'a'. */ #define STATE_NODE_CONTAINS(state,node) \ ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) @@ -1704,11 +1699,11 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, Idx i; /* Then build the next sifted state. - We build the next sifted state on `cur_dest', and update - `sifted_states[str_idx]' with `cur_dest'. + We build the next sifted state on 'cur_dest', and update + 'sifted_states[str_idx]' with 'cur_dest'. Note: - `cur_dest' is the sifted state from `state_log[str_idx + 1]'. - `cur_src' points the node_set of the old `state_log[str_idx]' + 'cur_dest' is the sifted state from 'state_log[str_idx + 1]'. + 'cur_src' points the node_set of the old 'state_log[str_idx]' (with the epsilon nodes pre-filtered out). */ for (i = 0; i < cur_src->nelem; i++) { @@ -1721,7 +1716,7 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ + /* If the node may accept "multi byte". */ if (dfa->nodes[prev_node].accept_mb) naccepted = sift_states_iter_mb (mctx, sctx, prev_node, str_idx, sctx->last_str_idx); @@ -1762,7 +1757,8 @@ clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) { Idx top = mctx->state_log_top; - if (next_state_log_idx >= mctx->input.bufs_len + if ((next_state_log_idx >= mctx->input.bufs_len + && mctx->input.bufs_len < mctx->input.len) || (next_state_log_idx >= mctx->input.valid_len && mctx->input.valid_len < mctx->input.len)) { @@ -2277,17 +2273,17 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, { const re_dfa_t *const dfa = mctx->dfa; int naccepted; - /* Check the node can accept `multi byte'. */ + /* Check the node can accept "multi byte". */ naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); if (naccepted > 0 && str_idx + naccepted <= max_str_idx && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], dfa->nexts[node_idx])) - /* The node can't accept the `multi byte', or the + /* The node can't accept the "multi byte", or the destination was already thrown away, then the node - could't accept the current input `multi byte'. */ + could't accept the current input "multi byte". */ naccepted = 0; /* Otherwise, it is sure that the node could accept - `naccepted' bytes input. */ + 'naccepted' bytes input. */ return naccepted; } #endif /* RE_ENABLE_I18N */ @@ -2466,7 +2462,7 @@ find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) /* From the node set CUR_NODES, pick up the nodes whose types are OP_OPEN_SUBEXP and which have corresponding back references in the regular expression. And register them to use them later for evaluating the - correspoding back references. */ + corresponding back references. */ static reg_errcode_t internal_function @@ -2577,7 +2573,7 @@ transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) if (naccepted == 0) continue; - /* The node can accepts `naccepted' bytes. */ + /* The node can accepts 'naccepted' bytes. */ dest_idx = re_string_cur_idx (&mctx->input) + naccepted; mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted : mctx->max_mb_elem_len); @@ -2629,7 +2625,7 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) const re_token_t *node = dfa->nodes + node_idx; re_node_set *new_dest_nodes; - /* Check whether `node' is a backreference or not. */ + /* Check whether 'node' is a backreference or not. */ if (node->type != OP_BACK_REF) continue; @@ -2641,14 +2637,14 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) continue; } - /* `node' is a backreference. + /* 'node' is a backreference. Check the substring which the substring matched. */ bkc_idx = mctx->nbkref_ents; err = get_subexp (mctx, node_idx, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; - /* And add the epsilon closures (which is `new_dest_nodes') of + /* And add the epsilon closures (which is 'new_dest_nodes') of the backreference to appropriate state_log. */ #ifdef DEBUG assert (dfa->nexts[node_idx] != REG_MISSING); @@ -2672,7 +2668,7 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) dest_state = mctx->state_log[dest_str_idx]; prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 : mctx->state_log[cur_str_idx]->nodes.nelem); - /* Add `new_dest_node' to state_log. */ + /* Add 'new_dest_node' to state_log. */ if (dest_state == NULL) { mctx->state_log[dest_str_idx] @@ -2946,9 +2942,12 @@ check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, { re_dfastate_t **new_array; Idx old_alloc = path->alloc; - Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1; - if (BE (new_alloc < old_alloc, 0) - || BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0)) + Idx incr_alloc = last_str + mctx->max_mb_elem_len + 1; + Idx new_alloc; + if (BE (IDX_MAX - old_alloc < incr_alloc, 0)) + return REG_ESPACE; + new_alloc = old_alloc + incr_alloc; + if (BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0)) return REG_ESPACE; new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); if (BE (new_array == NULL, 0)) @@ -3111,7 +3110,7 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ + /* If the node may accept "multi byte". */ if (dfa->nodes[cur_node].accept_mb) { naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, @@ -3368,7 +3367,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) bitset_word_t elem, mask; bool dests_node_malloced = false; bool dest_states_malloced = false; - Idx ndests; /* Number of the destination states from `state'. */ + Idx ndests; /* Number of the destination states from 'state'. */ re_dfastate_t **trtable; re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; re_node_set follows, *dests_node; @@ -3382,8 +3381,8 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) } *dests_alloc; /* We build DFA states which corresponds to the destination nodes - from `state'. `dests_node[i]' represents the nodes which i-th - destination state contains, and `dests_ch[i]' represents the + from 'state'. 'dests_node[i]' represents the nodes which i-th + destination state contains, and 'dests_ch[i]' represents the characters which i-th destination state accepts. */ if (__libc_use_alloca (sizeof (struct dests_alloc))) dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); @@ -3397,16 +3396,17 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) dests_node = dests_alloc->dests_node; dests_ch = dests_alloc->dests_ch; - /* Initialize transiton table. */ + /* Initialize transition table. */ state->word_trtable = state->trtable = NULL; - /* At first, group all nodes belonging to `state' into several + /* At first, group all nodes belonging to 'state' into several destinations. */ ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); if (BE (! REG_VALID_NONZERO_INDEX (ndests), 0)) { if (dests_node_malloced) free (dests_alloc); + /* Return false in case of an error, true otherwise. */ if (ndests == 0) { state->trtable = (re_dfastate_t **) @@ -3602,13 +3602,13 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, reg_errcode_t err; bool ok; Idx i, j, k; - Idx ndests; /* Number of the destinations from `state'. */ + Idx ndests; /* Number of the destinations from 'state'. */ bitset_t accepts; /* Characters a node can accept. */ const re_node_set *cur_nodes = &state->nodes; bitset_empty (accepts); ndests = 0; - /* For all the nodes belonging to `state', */ + /* For all the nodes belonging to 'state', */ for (i = 0; i < cur_nodes->nelem; ++i) { re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; @@ -3651,7 +3651,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, else continue; - /* Check the `accepts' and sift the characters which are not + /* Check the 'accepts' and sift the characters which are not match it the context. */ if (constraint) { @@ -3710,7 +3710,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, } } - /* Then divide `accepts' into DFA states, or create a new + /* Then divide 'accepts' into DFA states, or create a new state. Above, we make sure that accepts is not empty. */ for (j = 0; j < ndests; ++j) { @@ -3723,7 +3723,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) continue; - /* Enumerate the intersection set of this state and `accepts'. */ + /* Enumerate the intersection set of this state and 'accepts'. */ has_intersec = 0; for (k = 0; k < BITSET_WORDS; ++k) has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; @@ -3731,7 +3731,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, if (!has_intersec) continue; - /* Then check if this state is a subset of `accepts'. */ + /* Then check if this state is a subset of 'accepts'. */ not_subset = not_consumed = 0; for (k = 0; k < BITSET_WORDS; ++k) { @@ -3739,8 +3739,8 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; } - /* If this state isn't a subset of `accepts', create a - new group state, which has the `remains'. */ + /* If this state isn't a subset of 'accepts', create a + new group state, which has the 'remains'. */ if (not_subset) { bitset_copy (dests_ch[ndests], remains); @@ -3779,7 +3779,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, } #ifdef RE_ENABLE_I18N -/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. +/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts. Return the number of the bytes the node accepts. STR_IDX is the current index of the input string. @@ -3906,7 +3906,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, const int32_t *table, *indirect; const unsigned char *weights, *extra; const char *collseqwc; - int32_t idx; /* This #include defines a local function! */ # include @@ -3964,7 +3963,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - int32_t idx = findidx (&cp); + int32_t idx = findidx (&cp, elem_len); if (idx > 0) for (i = 0; i < cset->nequiv_classes; ++i) { @@ -3995,7 +3994,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, # endif /* _LIBC */ { /* match with range expression? */ -#if __GNUC__ >= 2 && ! (__STDC_VERSION__ < 199901L && __STRICT_ANSI__) +#if __GNUC__ >= 2 && ! (__STDC_VERSION__ < 199901L && defined __STRICT_ANSI__) wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; #else wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; @@ -4076,7 +4075,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) /* Skip the collation sequence value. */ idx += sizeof (uint32_t); /* Skip the wide char sequence of the collating element. */ - idx = idx + sizeof (uint32_t) * (extra[idx] + 1); + idx = idx + sizeof (uint32_t) * (*(int32_t *) (extra + idx) + 1); /* If we found the entry, return the sequence value. */ if (found) return *(uint32_t *) (extra + idx); @@ -4150,11 +4149,12 @@ extend_buffers (re_match_context_t *mctx) re_string_t *pstr = &mctx->input; /* Avoid overflow. */ - if (BE (SIZE_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) / 2 + <= pstr->bufs_len, 0)) return REG_ESPACE; - /* Double the lengthes of the buffers. */ - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + /* Double the lengths of the buffers. */ + ret = re_string_realloc_buffers (pstr, MIN (pstr->len, pstr->bufs_len * 2)); if (BE (ret != REG_NOERROR, 0)) return ret; @@ -4217,7 +4217,7 @@ match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) size_t max_object_size = MAX (sizeof (struct re_backref_cache_entry), sizeof (re_sub_match_top_t *)); - if (BE (SIZE_MAX / max_object_size < n, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < n, 0)) return REG_ESPACE; mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); diff --git a/contrib/grep/lib/closeout.h b/contrib/grep/lib/same-inode.h similarity index 57% copy from contrib/grep/lib/closeout.h copy to contrib/grep/lib/same-inode.h index ec8d7a6d2c..8c3900d041 100644 --- a/contrib/grep/lib/closeout.h +++ b/contrib/grep/lib/same-inode.h @@ -1,7 +1,6 @@ -/* Close standard output and standard error. +/* Determine whether two stat buffers refer to the same file. - Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2011 Free Software - Foundation, Inc. + Copyright (C) 2006, 2009-2012 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 @@ -16,21 +15,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef CLOSEOUT_H -# define CLOSEOUT_H 1 - -# include - -# ifdef __cplusplus -extern "C" { -# endif - -void close_stdout_set_file_name (const char *file); -void close_stdout_set_ignore_EPIPE (bool ignore); -void close_stdout (void); - -# ifdef __cplusplus -} +#ifndef SAME_INODE_H +# define SAME_INODE_H 1 + +# ifdef __VMS +# define SAME_INODE(a, b) \ + ((a).st_ino[0] == (b).st_ino[0] \ + && (a).st_ino[1] == (b).st_ino[1] \ + && (a).st_ino[2] == (b).st_ino[2] \ + && (a).st_dev == (b).st_dev) +# else +# define SAME_INODE(a, b) \ + ((a).st_ino == (b).st_ino \ + && (a).st_dev == (b).st_dev) # endif #endif diff --git a/contrib/grep/lib/save-cwd.c b/contrib/grep/lib/save-cwd.c new file mode 100644 index 0000000000..592d274eec --- /dev/null +++ b/contrib/grep/lib/save-cwd.c @@ -0,0 +1,99 @@ +/* save-cwd.c -- Save and restore current working directory. + + Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2012 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 of the License, 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 . */ + +/* Written by Jim Meyering. */ + +#include + +#include "save-cwd.h" + +#include +#include +#include +#include +#include + +#include "chdir-long.h" +#include "unistd--.h" +#include "cloexec.h" + +#if GNULIB_FCNTL_SAFER +# include "fcntl--.h" +#else +# define GNULIB_FCNTL_SAFER 0 +#endif + +/* Record the location of the current working directory in CWD so that + the program may change to other directories and later use restore_cwd + to return to the recorded location. This function may allocate + space using malloc (via getcwd) or leave a file descriptor open; + use free_cwd to perform the necessary free or close. Upon failure, + no memory is allocated, any locally opened file descriptors are + closed; return non-zero -- in that case, free_cwd need not be + called, but doing so is ok. Otherwise, return zero. + + The _raison d'etre_ for this interface is that the working directory + is sometimes inaccessible, and getcwd is not robust or as efficient. + So, we prefer to use the open/fchdir approach, but fall back on + getcwd if necessary. This module works for most cases with just + the getcwd-lgpl module, but to be truly robust, use the getcwd module. + + Some systems lack fchdir altogether: e.g., OS/2, pre-2001 Cygwin, + SCO Xenix. Also, SunOS 4 and Irix 5.3 provide the function, yet it + doesn't work for partitions on which auditing is enabled. If + you're still using an obsolete system with these problems, please + send email to the maintainer of this code. */ + +int +save_cwd (struct saved_cwd *cwd) +{ + cwd->name = NULL; + + cwd->desc = open (".", O_SEARCH); + if (!GNULIB_FCNTL_SAFER) + cwd->desc = fd_safer (cwd->desc); + if (cwd->desc < 0) + { + cwd->name = getcwd (NULL, 0); + return cwd->name ? 0 : -1; + } + + set_cloexec_flag (cwd->desc, true); + return 0; +} + +/* Change to recorded location, CWD, in directory hierarchy. + Upon failure, return -1 (errno is set by chdir or fchdir). + Upon success, return zero. */ + +int +restore_cwd (const struct saved_cwd *cwd) +{ + if (0 <= cwd->desc) + return fchdir (cwd->desc); + else + return chdir_long (cwd->name); +} + +void +free_cwd (struct saved_cwd *cwd) +{ + if (cwd->desc >= 0) + close (cwd->desc); + free (cwd->name); +} diff --git a/contrib/grep/lib/fpending.c b/contrib/grep/lib/save-cwd.h similarity index 63% copy from contrib/grep/lib/fpending.c copy to contrib/grep/lib/save-cwd.h index 5ec38cb27e..0c875da284 100644 --- a/contrib/grep/lib/fpending.c +++ b/contrib/grep/lib/save-cwd.h @@ -1,5 +1,6 @@ -/* fpending.c -- return the number of pending output bytes on a stream - Copyright (C) 2000, 2004, 2006-2007, 2009-2011 Free Software Foundation, +/* Save and restore current working directory. + + Copyright (C) 1995, 1997-1998, 2003, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -15,16 +16,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* Written by Jim Meyering. */ +/* Written by Jim Meyering. */ + +#ifndef SAVE_CWD_H +# define SAVE_CWD_H 1 -#include +struct saved_cwd + { + int desc; + char *name; + }; -#include "fpending.h" +int save_cwd (struct saved_cwd *cwd); +int restore_cwd (const struct saved_cwd *cwd); +void free_cwd (struct saved_cwd *cwd); -/* Return the number of pending (aka buffered, unflushed) - bytes on the stream, FP, that is open for writing. */ -size_t -__fpending (FILE *fp) -{ - return PENDING_OUTPUT_N_BYTES; -} +#endif /* SAVE_CWD_H */ diff --git a/contrib/grep/lib/savedir.c b/contrib/grep/lib/savedir.c deleted file mode 100644 index 0299a9164e..0000000000 --- a/contrib/grep/lib/savedir.c +++ /dev/null @@ -1,163 +0,0 @@ -/* savedir.c -- save the list of files in a directory in a string - Copyright (C) 1990, 1997-2001, 2009-2011 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 by David MacKenzie . */ - -#include - -#include -#include -#include - -#ifdef CLOSEDIR_VOID -/* Fake a return value. */ -# define CLOSEDIR(d) (closedir (d), 0) -#else -# define CLOSEDIR(d) closedir (d) -#endif - -#include -#include -#include -#include "savedir.h" -#include "xalloc.h" - -static char *path; -static size_t pathlen; - -extern int isdir (const char *name); - -static int -isdir1 (const char *dir, const char *file) -{ - size_t dirlen = strlen (dir); - size_t filelen = strlen (file); - - while (dirlen && dir[dirlen - 1] == '/') - dirlen--; - - if ((dirlen + filelen + 2) > pathlen) - { - pathlen *= 2; - if ((dirlen + filelen + 2) > pathlen) - pathlen = dirlen + filelen + 2; - - path = xrealloc (path, pathlen); - } - - memcpy (path, dir, dirlen); - path[dirlen] = '/'; - strcpy (path + dirlen + 1, file); - return isdir (path); -} - -/* Return a freshly allocated string containing the filenames - in directory DIR, separated by '\0' characters; - the end is marked by two '\0' characters in a row. - NAME_SIZE is the number of bytes to initially allocate - for the string; it will be enlarged as needed. - Return NULL if DIR cannot be opened or if out of memory. */ -char * -savedir (const char *dir, off_t name_size, struct exclude *included_patterns, - struct exclude *excluded_patterns, struct exclude *excluded_directory_patterns ) -{ - DIR *dirp; - struct dirent *dp; - char *name_space; - char *namep; - - dirp = opendir (dir); - if (dirp == NULL) - return NULL; - - /* Be sure name_size is at least `1' so there's room for - the final NUL byte. */ - if (name_size <= 0) - name_size = 1; - - name_space = (char *) malloc (name_size); - if (name_space == NULL) - { - closedir (dirp); - return NULL; - } - namep = name_space; - - while ((dp = readdir (dirp)) != NULL) - { - /* Skip "." and ".." (some NFS file systems' directories lack them). */ - if (dp->d_name[0] != '.' - || (dp->d_name[1] != '\0' - && (dp->d_name[1] != '.' || dp->d_name[2] != '\0'))) - { - size_t namlen = strlen (dp->d_name); - size_t size_needed = (namep - name_space) + namlen + 2; - - if ((included_patterns || excluded_patterns) - && !isdir1 (dir, dp->d_name)) - { - if (included_patterns - && excluded_file_name (included_patterns, dp->d_name)) - continue; - if (excluded_patterns - && excluded_file_name (excluded_patterns, dp->d_name)) - continue; - } - - if ( excluded_directory_patterns - && isdir1 (dir, dp->d_name) ) - { - if (excluded_directory_patterns - && excluded_file_name (excluded_directory_patterns, dp->d_name)) - continue; - } - - if (size_needed > name_size) - { - char *new_name_space; - - while (size_needed > name_size) - name_size += 1024; - - new_name_space = realloc (name_space, name_size); - if (new_name_space == NULL) - { - closedir (dirp); - goto fail; - } - namep = new_name_space + (namep - name_space); - name_space = new_name_space; - } - strcpy (namep, dp->d_name); - namep += namlen + 1; - } - } - *namep = '\0'; - if (CLOSEDIR (dirp)) - { - fail: - free (name_space); - name_space = NULL; - } - if (path) - { - free (path); - path = NULL; - pathlen = 0; - } - return name_space; -} diff --git a/contrib/grep/lib/savedir.h b/contrib/grep/lib/savedir.h deleted file mode 100644 index 00cb1a98ea..0000000000 --- a/contrib/grep/lib/savedir.h +++ /dev/null @@ -1,11 +0,0 @@ -#if !defined SAVEDIR_H_ -# define SAVEDIR_H_ - -#include "exclude.h" - -extern char * -savedir (const char *dir, off_t name_size, - struct exclude *, struct exclude *, - struct exclude *); - -#endif diff --git a/contrib/grep/lib/stat.c b/contrib/grep/lib/stat.c index cbc9100fd4..1fc633eeef 100644 --- a/contrib/grep/lib/stat.c +++ b/contrib/grep/lib/stat.c @@ -1,5 +1,5 @@ /* Work around platform bugs in stat. - Copyright (C) 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 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 @@ -16,14 +16,31 @@ /* written by Eric Blake */ +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_stat doesn't recurse to + rpl_stat. */ +#define __need_system_sys_stat_h #include /* Get the original definition of stat. It might be defined as a macro. */ -#define __need_system_sys_stat_h #include #include #undef __need_system_sys_stat_h +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# if _GL_WINDOWS_64_BIT_ST_SIZE +# define stat _stati64 +# define REPLACE_FUNC_STAT_DIR 1 +# undef REPLACE_FUNC_STAT_FILE +# elif REPLACE_FUNC_STAT_FILE +/* mingw64 has a broken stat() function, based on _stat(), in libmingwex.a. + Bypass it. */ +# define stat _stat +# define REPLACE_FUNC_STAT_DIR 1 +# undef REPLACE_FUNC_STAT_FILE +# endif +#endif + static inline int orig_stat (const char *filename, struct stat *buf) { @@ -31,13 +48,26 @@ orig_stat (const char *filename, struct stat *buf) } /* Specification. */ -#include +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +#include "sys/stat.h" #include #include #include #include #include "dosname.h" +#include "verify.h" + +#if REPLACE_FUNC_STAT_DIR +# include "pathmax.h" + /* The only known systems where REPLACE_FUNC_STAT_DIR is needed also + have a constant PATH_MAX. */ +# ifndef PATH_MAX +# error "Please port this replacement to your platform" +# endif +#endif /* Store information about NAME into ST. Work around bugs with trailing slashes. Mingw has other bugs (such as st_ino always @@ -63,6 +93,7 @@ rpl_stat (char const *name, struct stat *st) } #endif /* REPLACE_FUNC_STAT_FILE */ #if REPLACE_FUNC_STAT_DIR + if (result == -1 && errno == ENOENT) { /* Due to mingw's oddities, there are some directories (like @@ -77,6 +108,7 @@ rpl_stat (char const *name, struct stat *st) char fixed_name[PATH_MAX + 1] = {0}; size_t len = strlen (name); bool check_dir = false; + verify (PATH_MAX <= 4096); if (PATH_MAX <= len) errno = ENAMETOOLONG; else if (len) diff --git a/contrib/grep/lib/stpcpy.c b/contrib/grep/lib/stpcpy.c index fa42af4a4d..e857abef0b 100644 --- a/contrib/grep/lib/stpcpy.c +++ b/contrib/grep/lib/stpcpy.c @@ -1,5 +1,5 @@ /* stpcpy.c -- copy a string and return pointer to end of new string - Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2011 Free Software + Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2012 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. diff --git a/contrib/grep/lib/str-kmp.h b/contrib/grep/lib/str-kmp.h index df48a2ccc0..3395173a08 100644 --- a/contrib/grep/lib/str-kmp.h +++ b/contrib/grep/lib/str-kmp.h @@ -1,8 +1,6 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Substring search in a NUL terminated string of UNIT elements, using the Knuth-Morris-Pratt algorithm. - Copyright (C) 2005-2011 Free Software Foundation, Inc. + Copyright (C) 2005-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2005. This program is free software; you can redistribute it and/or modify @@ -16,8 +14,7 @@ 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. */ + along with this program; if not, see . */ /* Before including this file, you need to define: UNIT The element type of the needle and haystack. diff --git a/contrib/grep/lib/c-strcasecmp.c b/contrib/grep/lib/strcasecmp.c similarity index 60% copy from contrib/grep/lib/c-strcasecmp.c copy to contrib/grep/lib/strcasecmp.c index 928c5e6b80..77ca288722 100644 --- a/contrib/grep/lib/c-strcasecmp.c +++ b/contrib/grep/lib/strcasecmp.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -/* c-strcasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2011 Free Software Foundation, Inc. +/* Case-insensitive string comparison function. + Copyright (C) 1998-1999, 2005-2007, 2009-2012 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 @@ -14,23 +12,28 @@ 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. */ + along with this program; if not, see . */ #include /* Specification. */ -#include "c-strcase.h" +#include +#include #include -#include "c-ctype.h" +#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) + +/* Compare strings S1 and S2, ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less than, equal to or greater + than S2. + Note: This function does not work with multibyte strings! */ int -c_strcasecmp (const char *s1, const char *s2) +strcasecmp (const char *s1, const char *s2) { - register const unsigned char *p1 = (const unsigned char *) s1; - register const unsigned char *p2 = (const unsigned char *) s2; + const unsigned char *p1 = (const unsigned char *) s1; + const unsigned char *p2 = (const unsigned char *) s2; unsigned char c1, c2; if (p1 == p2) @@ -38,8 +41,8 @@ c_strcasecmp (const char *s1, const char *s2) do { - c1 = c_tolower (*p1); - c2 = c_tolower (*p2); + c1 = TOLOWER (*p1); + c2 = TOLOWER (*p2); if (c1 == '\0') break; diff --git a/contrib/grep/lib/strdup.c b/contrib/grep/lib/strdup.c new file mode 100644 index 0000000000..a3f8c863f3 --- /dev/null +++ b/contrib/grep/lib/strdup.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 1996-1998, 2002-2004, 2006-2007, 2009-2012 Free Software + Foundation, Inc. + + This file is part of the GNU C Library. + + 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 . */ + +#ifndef _LIBC +# include +#endif + +/* Get specification. */ +#include + +#include + +#undef __strdup +#ifdef _LIBC +# undef strdup +#endif + +#ifndef weak_alias +# define __strdup strdup +#endif + +/* Duplicate S, returning an identical malloc'd string. */ +char * +__strdup (const char *s) +{ + size_t len = strlen (s) + 1; + void *new = malloc (len); + + if (new == NULL) + return NULL; + + return (char *) memcpy (new, s, len); +} +#ifdef libc_hidden_def +libc_hidden_def (__strdup) +#endif +#ifdef weak_alias +weak_alias (__strdup, strdup) +#endif diff --git a/contrib/grep/lib/streq.h b/contrib/grep/lib/streq.h index 067732dd69..b312f7f917 100644 --- a/contrib/grep/lib/streq.h +++ b/contrib/grep/lib/streq.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Optimized string comparison. - Copyright (C) 2001-2002, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2002, 2007, 2009-2012 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 @@ -23,8 +21,8 @@ #include -/* STREQ allows to optimize string comparison with a small literal string. - STREQ (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) +/* STREQ_OPT allows to optimize string comparison with a small literal string. + STREQ_OPT (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) is semantically equivalent to strcmp (s, "EUC-KR") == 0 just faster. */ @@ -165,12 +163,12 @@ streq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, return 0; } -#define STREQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ +#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ streq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28) #else -#define STREQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ +#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ (strcmp (s1, s2) == 0) #endif diff --git a/contrib/grep/lib/strerror-override.c b/contrib/grep/lib/strerror-override.c index c2ca764eb4..9ca6523490 100644 --- a/contrib/grep/lib/strerror-override.c +++ b/contrib/grep/lib/strerror-override.c @@ -1,6 +1,6 @@ /* strerror-override.c --- POSIX compatible system error routine - Copyright (C) 2010-2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 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 @@ -23,7 +23,7 @@ #include -#if GNULIB_defined_ESOCK /* native Windows platforms */ +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ # if HAVE_WINSOCK2_H # include # endif @@ -34,147 +34,109 @@ const char * strerror_override (int errnum) { - const char *msg = NULL; - -#if GNULIB_defined_ETXTBSY \ - || GNULIB_defined_ESOCK \ - || GNULIB_defined_ENOMSG \ - || GNULIB_defined_EIDRM \ - || GNULIB_defined_ENOLINK \ - || GNULIB_defined_EPROTO \ - || GNULIB_defined_EMULTIHOP \ - || GNULIB_defined_EBADMSG \ - || GNULIB_defined_EOVERFLOW \ - || GNULIB_defined_ENOTSUP \ - || GNULIB_defined_ESTALE \ - || GNULIB_defined_EDQUOT \ - || GNULIB_defined_ECANCELED /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ switch (errnum) { -# if GNULIB_defined_ETXTBSY - case ETXTBSY: - msg = "Text file busy"; - break; -# endif +#if REPLACE_STRERROR_0 + case 0: + return "Success"; +#endif -# if GNULIB_defined_ESOCK /* native Windows platforms */ - /* EWOULDBLOCK is the same as EAGAIN. */ +#if GNULIB_defined_ESOCK /* native Windows platforms with older */ case EINPROGRESS: - msg = "Operation now in progress"; - break; + return "Operation now in progress"; case EALREADY: - msg = "Operation already in progress"; - break; + return "Operation already in progress"; case ENOTSOCK: - msg = "Socket operation on non-socket"; - break; + return "Socket operation on non-socket"; case EDESTADDRREQ: - msg = "Destination address required"; - break; + return "Destination address required"; case EMSGSIZE: - msg = "Message too long"; - break; + return "Message too long"; case EPROTOTYPE: - msg = "Protocol wrong type for socket"; - break; + return "Protocol wrong type for socket"; case ENOPROTOOPT: - msg = "Protocol not available"; - break; + return "Protocol not available"; case EPROTONOSUPPORT: - msg = "Protocol not supported"; - break; - case ESOCKTNOSUPPORT: - msg = "Socket type not supported"; - break; + return "Protocol not supported"; case EOPNOTSUPP: - msg = "Operation not supported"; - break; - case EPFNOSUPPORT: - msg = "Protocol family not supported"; - break; + return "Operation not supported"; case EAFNOSUPPORT: - msg = "Address family not supported by protocol"; - break; + return "Address family not supported by protocol"; case EADDRINUSE: - msg = "Address already in use"; - break; + return "Address already in use"; case EADDRNOTAVAIL: - msg = "Cannot assign requested address"; - break; + return "Cannot assign requested address"; case ENETDOWN: - msg = "Network is down"; - break; + return "Network is down"; case ENETUNREACH: - msg = "Network is unreachable"; - break; - case ENETRESET: - msg = "Network dropped connection on reset"; - break; - case ECONNABORTED: - msg = "Software caused connection abort"; - break; + return "Network is unreachable"; case ECONNRESET: - msg = "Connection reset by peer"; - break; + return "Connection reset by peer"; case ENOBUFS: - msg = "No buffer space available"; - break; + return "No buffer space available"; case EISCONN: - msg = "Transport endpoint is already connected"; - break; + return "Transport endpoint is already connected"; case ENOTCONN: - msg = "Transport endpoint is not connected"; - break; - case ESHUTDOWN: - msg = "Cannot send after transport endpoint shutdown"; - break; - case ETOOMANYREFS: - msg = "Too many references: cannot splice"; - break; + return "Transport endpoint is not connected"; case ETIMEDOUT: - msg = "Connection timed out"; - break; + return "Connection timed out"; case ECONNREFUSED: - msg = "Connection refused"; - break; + return "Connection refused"; case ELOOP: - msg = "Too many levels of symbolic links"; - break; - case EHOSTDOWN: - msg = "Host is down"; - break; + return "Too many levels of symbolic links"; case EHOSTUNREACH: - msg = "No route to host"; - break; + return "No route to host"; + case EWOULDBLOCK: + return "Operation would block"; + case ETXTBSY: + return "Text file busy"; + case ENODATA: + return "No data available"; + case ENOSR: + return "Out of streams resources"; + case ENOSTR: + return "Device not a stream"; + case ENOTRECOVERABLE: + return "State not recoverable"; + case EOWNERDEAD: + return "Owner died"; + case ETIME: + return "Timer expired"; + case EOTHER: + return "Other error"; +#endif +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ + case ESOCKTNOSUPPORT: + return "Socket type not supported"; + case EPFNOSUPPORT: + return "Protocol family not supported"; + case ESHUTDOWN: + return "Cannot send after transport endpoint shutdown"; + case ETOOMANYREFS: + return "Too many references: cannot splice"; + case EHOSTDOWN: + return "Host is down"; case EPROCLIM: - msg = "Too many processes"; - break; + return "Too many processes"; case EUSERS: - msg = "Too many users"; - break; + return "Too many users"; case EDQUOT: - msg = "Disk quota exceeded"; - break; + return "Disk quota exceeded"; case ESTALE: - msg = "Stale NFS file handle"; - break; + return "Stale NFS file handle"; case EREMOTE: - msg = "Object is remote"; - break; -# if HAVE_WINSOCK2_H + return "Object is remote"; +# if HAVE_WINSOCK2_H /* WSA_INVALID_HANDLE maps to EBADF */ /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */ /* WSA_INVALID_PARAMETER maps to EINVAL */ case WSA_OPERATION_ABORTED: - msg = "Overlapped operation aborted"; - break; + return "Overlapped operation aborted"; case WSA_IO_INCOMPLETE: - msg = "Overlapped I/O event object not in signaled state"; - break; + return "Overlapped I/O event object not in signaled state"; case WSA_IO_PENDING: - msg = "Overlapped operations will complete later"; - break; + return "Overlapped operations will complete later"; /* WSAEINTR maps to EINTR */ /* WSAEBADF maps to EBADF */ /* WSAEACCES maps to EACCES */ @@ -182,36 +144,36 @@ strerror_override (int errnum) /* WSAEINVAL maps to EINVAL */ /* WSAEMFILE maps to EMFILE */ /* WSAEWOULDBLOCK maps to EWOULDBLOCK */ - /* WSAEINPROGRESS is EINPROGRESS */ - /* WSAEALREADY is EALREADY */ - /* WSAENOTSOCK is ENOTSOCK */ - /* WSAEDESTADDRREQ is EDESTADDRREQ */ - /* WSAEMSGSIZE is EMSGSIZE */ - /* WSAEPROTOTYPE is EPROTOTYPE */ - /* WSAENOPROTOOPT is ENOPROTOOPT */ - /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */ + /* WSAEINPROGRESS maps to EINPROGRESS */ + /* WSAEALREADY maps to EALREADY */ + /* WSAENOTSOCK maps to ENOTSOCK */ + /* WSAEDESTADDRREQ maps to EDESTADDRREQ */ + /* WSAEMSGSIZE maps to EMSGSIZE */ + /* WSAEPROTOTYPE maps to EPROTOTYPE */ + /* WSAENOPROTOOPT maps to ENOPROTOOPT */ + /* WSAEPROTONOSUPPORT maps to EPROTONOSUPPORT */ /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ - /* WSAEOPNOTSUPP is EOPNOTSUPP */ + /* WSAEOPNOTSUPP maps to EOPNOTSUPP */ /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ - /* WSAEAFNOSUPPORT is EAFNOSUPPORT */ - /* WSAEADDRINUSE is EADDRINUSE */ - /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */ - /* WSAENETDOWN is ENETDOWN */ - /* WSAENETUNREACH is ENETUNREACH */ - /* WSAENETRESET is ENETRESET */ - /* WSAECONNABORTED is ECONNABORTED */ - /* WSAECONNRESET is ECONNRESET */ - /* WSAENOBUFS is ENOBUFS */ - /* WSAEISCONN is EISCONN */ - /* WSAENOTCONN is ENOTCONN */ + /* WSAEAFNOSUPPORT maps to EAFNOSUPPORT */ + /* WSAEADDRINUSE maps to EADDRINUSE */ + /* WSAEADDRNOTAVAIL maps to EADDRNOTAVAIL */ + /* WSAENETDOWN maps to ENETDOWN */ + /* WSAENETUNREACH maps to ENETUNREACH */ + /* WSAENETRESET maps to ENETRESET */ + /* WSAECONNABORTED maps to ECONNABORTED */ + /* WSAECONNRESET maps to ECONNRESET */ + /* WSAENOBUFS maps to ENOBUFS */ + /* WSAEISCONN maps to EISCONN */ + /* WSAENOTCONN maps to ENOTCONN */ /* WSAESHUTDOWN is ESHUTDOWN */ /* WSAETOOMANYREFS is ETOOMANYREFS */ - /* WSAETIMEDOUT is ETIMEDOUT */ - /* WSAECONNREFUSED is ECONNREFUSED */ - /* WSAELOOP is ELOOP */ + /* WSAETIMEDOUT maps to ETIMEDOUT */ + /* WSAECONNREFUSED maps to ECONNREFUSED */ + /* WSAELOOP maps to ELOOP */ /* WSAENAMETOOLONG maps to ENAMETOOLONG */ /* WSAEHOSTDOWN is EHOSTDOWN */ - /* WSAEHOSTUNREACH is EHOSTUNREACH */ + /* WSAEHOSTUNREACH maps to EHOSTUNREACH */ /* WSAENOTEMPTY maps to ENOTEMPTY */ /* WSAEPROCLIM is EPROCLIM */ /* WSAEUSERS is EUSERS */ @@ -219,127 +181,109 @@ strerror_override (int errnum) /* WSAESTALE is ESTALE */ /* WSAEREMOTE is EREMOTE */ case WSASYSNOTREADY: - msg = "Network subsystem is unavailable"; - break; + return "Network subsystem is unavailable"; case WSAVERNOTSUPPORTED: - msg = "Winsock.dll version out of range"; - break; + return "Winsock.dll version out of range"; case WSANOTINITIALISED: - msg = "Successful WSAStartup not yet performed"; - break; + return "Successful WSAStartup not yet performed"; case WSAEDISCON: - msg = "Graceful shutdown in progress"; - break; + return "Graceful shutdown in progress"; case WSAENOMORE: case WSA_E_NO_MORE: - msg = "No more results"; - break; + return "No more results"; case WSAECANCELLED: case WSA_E_CANCELLED: - msg = "Call was canceled"; - break; + return "Call was canceled"; case WSAEINVALIDPROCTABLE: - msg = "Procedure call table is invalid"; - break; + return "Procedure call table is invalid"; case WSAEINVALIDPROVIDER: - msg = "Service provider is invalid"; - break; + return "Service provider is invalid"; case WSAEPROVIDERFAILEDINIT: - msg = "Service provider failed to initialize"; - break; + return "Service provider failed to initialize"; case WSASYSCALLFAILURE: - msg = "System call failure"; - break; + return "System call failure"; case WSASERVICE_NOT_FOUND: - msg = "Service not found"; - break; + return "Service not found"; case WSATYPE_NOT_FOUND: - msg = "Class type not found"; - break; + return "Class type not found"; case WSAEREFUSED: - msg = "Database query was refused"; - break; + return "Database query was refused"; case WSAHOST_NOT_FOUND: - msg = "Host not found"; - break; + return "Host not found"; case WSATRY_AGAIN: - msg = "Nonauthoritative host not found"; - break; + return "Nonauthoritative host not found"; case WSANO_RECOVERY: - msg = "Nonrecoverable error"; - break; + return "Nonrecoverable error"; case WSANO_DATA: - msg = "Valid name, no data record of requested type"; - break; + return "Valid name, no data record of requested type"; /* WSA_QOS_* omitted */ -# endif # endif +#endif -# if GNULIB_defined_ENOMSG +#if GNULIB_defined_ENOMSG case ENOMSG: - msg = "No message of desired type"; - break; -# endif + return "No message of desired type"; +#endif -# if GNULIB_defined_EIDRM +#if GNULIB_defined_EIDRM case EIDRM: - msg = "Identifier removed"; - break; -# endif + return "Identifier removed"; +#endif -# if GNULIB_defined_ENOLINK +#if GNULIB_defined_ENOLINK case ENOLINK: - msg = "Link has been severed"; - break; -# endif + return "Link has been severed"; +#endif -# if GNULIB_defined_EPROTO +#if GNULIB_defined_EPROTO case EPROTO: - msg = "Protocol error"; - break; -# endif + return "Protocol error"; +#endif -# if GNULIB_defined_EMULTIHOP +#if GNULIB_defined_EMULTIHOP case EMULTIHOP: - msg = "Multihop attempted"; - break; -# endif + return "Multihop attempted"; +#endif -# if GNULIB_defined_EBADMSG +#if GNULIB_defined_EBADMSG case EBADMSG: - msg = "Bad message"; - break; -# endif + return "Bad message"; +#endif -# if GNULIB_defined_EOVERFLOW +#if GNULIB_defined_EOVERFLOW case EOVERFLOW: - msg = "Value too large for defined data type"; - break; -# endif + return "Value too large for defined data type"; +#endif -# if GNULIB_defined_ENOTSUP +#if GNULIB_defined_ENOTSUP case ENOTSUP: - msg = "Not supported"; - break; -# endif + return "Not supported"; +#endif + +#if GNULIB_defined_ENETRESET + case ENETRESET: + return "Network dropped connection on reset"; +#endif + +#if GNULIB_defined_ECONNABORTED + case ECONNABORTED: + return "Software caused connection abort"; +#endif -# if GNULIB_defined_ESTALE +#if GNULIB_defined_ESTALE case ESTALE: - msg = "Stale NFS file handle"; - break; -# endif + return "Stale NFS file handle"; +#endif -# if GNULIB_defined_EDQUOT +#if GNULIB_defined_EDQUOT case EDQUOT: - msg = "Disk quota exceeded"; - break; -# endif + return "Disk quota exceeded"; +#endif -# if GNULIB_defined_ECANCELED +#if GNULIB_defined_ECANCELED case ECANCELED: - msg = "Operation canceled"; - break; -# endif - } + return "Operation canceled"; #endif - return msg; + default: + return NULL; + } } diff --git a/contrib/grep/lib/strerror-override.h b/contrib/grep/lib/strerror-override.h index b8ef854847..09526ea91a 100644 --- a/contrib/grep/lib/strerror-override.h +++ b/contrib/grep/lib/strerror-override.h @@ -1,6 +1,6 @@ /* strerror-override.h --- POSIX compatible system error routine - Copyright (C) 2010-2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 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 @@ -28,19 +28,22 @@ /* If ERRNUM maps to an errno value defined by gnulib, return a string describing the error. Otherwise return NULL. */ -# if GNULIB_defined_ETXTBSY \ - || GNULIB_defined_ESOCK \ - || GNULIB_defined_ENOMSG \ - || GNULIB_defined_EIDRM \ - || GNULIB_defined_ENOLINK \ - || GNULIB_defined_EPROTO \ - || GNULIB_defined_EMULTIHOP \ - || GNULIB_defined_EBADMSG \ - || GNULIB_defined_EOVERFLOW \ - || GNULIB_defined_ENOTSUP \ - || GNULIB_defined_ESTALE \ - || GNULIB_defined_EDQUOT \ - || GNULIB_defined_ECANCELED +# if REPLACE_STRERROR_0 \ + || GNULIB_defined_ESOCK \ + || GNULIB_defined_EWINSOCK \ + || GNULIB_defined_ENOMSG \ + || GNULIB_defined_EIDRM \ + || GNULIB_defined_ENOLINK \ + || GNULIB_defined_EPROTO \ + || GNULIB_defined_EMULTIHOP \ + || GNULIB_defined_EBADMSG \ + || GNULIB_defined_EOVERFLOW \ + || GNULIB_defined_ENOTSUP \ + || GNULIB_defined_ENETRESET \ + || GNULIB_defined_ECONNABORTED \ + || GNULIB_defined_ESTALE \ + || GNULIB_defined_EDQUOT \ + || GNULIB_defined_ECANCELED extern const char *strerror_override (int errnum); # else # define strerror_override(ignored) NULL diff --git a/contrib/grep/lib/strerror.c b/contrib/grep/lib/strerror.c index d0dd1af984..587bd21a6c 100644 --- a/contrib/grep/lib/strerror.c +++ b/contrib/grep/lib/strerror.c @@ -1,6 +1,6 @@ /* strerror.c --- POSIX compatible system error routine - Copyright (C) 2007-2011 Free Software Foundation, Inc. + Copyright (C) 2007-2012 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 @@ -45,20 +45,7 @@ strerror (int n) if (msg) return (char *) msg; - /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382. - MacOS X 10.5 does not distinguish 0 from -1. */ - if (n) - msg = strerror (n); - else - { - int saved_errno = errno; - errno = 0; - msg = strerror (n); - if (errno || (msg && - (strstr (msg, "nknown") || strstr (msg, "ndefined")))) - msg = "Success"; - errno = saved_errno; - } + msg = strerror (n); /* Our strerror_r implementation might use the system's strerror buffer, so all other clients of strerror have to see the error diff --git a/contrib/grep/lib/striconv.c b/contrib/grep/lib/striconv.c index 4fdeb74386..4458d0c3b5 100644 --- a/contrib/grep/lib/striconv.c +++ b/contrib/grep/lib/striconv.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Charset conversion. - Copyright (C) 2001-2007, 2010-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2007, 2010-2012 Free Software Foundation, Inc. Written by Bruno Haible and Simon Josefsson. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ #include diff --git a/contrib/grep/lib/striconv.h b/contrib/grep/lib/striconv.h index 30bc1f8f9c..fc3aa696a2 100644 --- a/contrib/grep/lib/striconv.h +++ b/contrib/grep/lib/striconv.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Charset conversion. - Copyright (C) 2001-2004, 2006-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2006-2007, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible and Simon Josefsson. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ #ifndef _STRICONV_H #define _STRICONV_H diff --git a/contrib/grep/lib/stripslash.c b/contrib/grep/lib/stripslash.c index 1212440b5a..ef458c63a9 100644 --- a/contrib/grep/lib/stripslash.c +++ b/contrib/grep/lib/stripslash.c @@ -1,6 +1,6 @@ /* stripslash.c -- remove redundant trailing slashes from a file name - Copyright (C) 1990, 2001, 2003-2006, 2009-2011 Free Software Foundation, + Copyright (C) 1990, 2001, 2003-2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ strip_trailing_slashes (char *file) bool had_slash; /* last_component returns "" for file system roots, but we need to turn - `///' into `/'. */ + "///" into "/". */ if (! *base) base = file; base_lim = base + base_len (base); diff --git a/contrib/grep/lib/c-strncasecmp.c b/contrib/grep/lib/strncasecmp.c similarity index 65% copy from contrib/grep/lib/c-strncasecmp.c copy to contrib/grep/lib/strncasecmp.c index 810bf56a94..bf413b41ba 100644 --- a/contrib/grep/lib/c-strncasecmp.c +++ b/contrib/grep/lib/strncasecmp.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -/* c-strncasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2011 Free Software Foundation, Inc. +/* strncasecmp.c -- case insensitive string comparator + Copyright (C) 1998-1999, 2005-2007, 2009-2012 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 @@ -14,20 +12,25 @@ 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. */ + along with this program; if not, see . */ #include /* Specification. */ -#include "c-strcase.h" +#include +#include #include -#include "c-ctype.h" +#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) + +/* Compare no more than N bytes of strings S1 and S2, ignoring case, + returning less than, equal to or greater than zero if S1 is + lexicographically less than, equal to or greater than S2. + Note: This function cannot work correctly in multibyte locales. */ int -c_strncasecmp (const char *s1, const char *s2, size_t n) +strncasecmp (const char *s1, const char *s2, size_t n) { register const unsigned char *p1 = (const unsigned char *) s1; register const unsigned char *p2 = (const unsigned char *) s2; @@ -38,8 +41,8 @@ c_strncasecmp (const char *s1, const char *s2, size_t n) do { - c1 = c_tolower (*p1); - c2 = c_tolower (*p2); + c1 = TOLOWER (*p1); + c2 = TOLOWER (*p2); if (--n == 0 || c1 == '\0') break; diff --git a/contrib/grep/lib/strndup.c b/contrib/grep/lib/strndup.c deleted file mode 100644 index c5aca3ea42..0000000000 --- a/contrib/grep/lib/strndup.c +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -/* A replacement function, for systems that lack strndup. - - Copyright (C) 1996-1998, 2001-2003, 2005-2007, 2009-2011 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 - -#include - -#include - -char * -strndup (char const *s, size_t n) -{ - size_t len = strnlen (s, n); - char *new = malloc (len + 1); - - if (new == NULL) - return NULL; - - new[len] = '\0'; - return memcpy (new, s, len); -} diff --git a/contrib/grep/lib/strnlen.c b/contrib/grep/lib/strnlen.c index 241bb592b4..d36180dc77 100644 --- a/contrib/grep/lib/strnlen.c +++ b/contrib/grep/lib/strnlen.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Find the length of STRING, but scan at most MAXLEN characters. - Copyright (C) 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005-2007, 2009-2012 Free Software Foundation, Inc. Written by Simon Josefsson. This program is free software; you can redistribute it and/or modify @@ -15,8 +13,7 @@ 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. */ + along with this program; if not, see . */ #include diff --git a/contrib/grep/lib/strnlen1.c b/contrib/grep/lib/strnlen1.c index f64ce104a3..52dc507895 100644 --- a/contrib/grep/lib/strnlen1.c +++ b/contrib/grep/lib/strnlen1.c @@ -1,5 +1,5 @@ /* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2009-2012 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 diff --git a/contrib/grep/lib/strnlen1.h b/contrib/grep/lib/strnlen1.h index 1bb13de60d..4c4f0c0813 100644 --- a/contrib/grep/lib/strnlen1.h +++ b/contrib/grep/lib/strnlen1.h @@ -1,5 +1,5 @@ /* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005, 2009-2012 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 @@ -28,7 +28,8 @@ extern "C" { /* Find the length of STRING + 1, but scan at most MAXLEN bytes. If no '\0' terminator is found in that many characters, return MAXLEN. */ /* This is the same as strnlen (string, maxlen - 1) + 1. */ -extern size_t strnlen1 (const char *string, size_t maxlen); +extern size_t strnlen1 (const char *string, size_t maxlen) + _GL_ATTRIBUTE_PURE; #ifdef __cplusplus diff --git a/contrib/grep/lib/strtoimax.c b/contrib/grep/lib/strtoimax.c index 497d15585c..4f5fdbb5f2 100644 --- a/contrib/grep/lib/strtoimax.c +++ b/contrib/grep/lib/strtoimax.c @@ -1,6 +1,6 @@ /* Convert string representation of a number into an intmax_t value. - Copyright (C) 1999, 2001-2004, 2006, 2009-2011 Free Software Foundation, + Copyright (C) 1999, 2001-2004, 2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/strtol.c b/contrib/grep/lib/strtol.c index 6c15d11e8f..bf992a8c27 100644 --- a/contrib/grep/lib/strtol.c +++ b/contrib/grep/lib/strtol.c @@ -1,6 +1,6 @@ /* Convert string representation of a number into an integer value. - Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2011 Free Software + Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2012 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C @@ -40,7 +40,7 @@ # include "../locale/localeinfo.h" #endif -/* Nonzero if we are defining `strtoul' or `strtoull', operating on +/* Nonzero if we are defining 'strtoul' or 'strtoull', operating on unsigned integers. */ #ifndef UNSIGNED # define UNSIGNED 0 @@ -110,8 +110,8 @@ # endif #endif -/* If QUAD is defined, we are defining `strtoll' or `strtoull', - operating on `long long int's. */ +/* If QUAD is defined, we are defining 'strtoll' or 'strtoull', + operating on 'long long int's. */ #ifdef QUAD # define LONG long long # define STRTOL_LONG_MIN LLONG_MIN @@ -227,7 +227,7 @@ -/* Convert NPTR to an `unsigned long int' or `long int' in base BASE. +/* Convert NPTR to an 'unsigned long int' or 'long int' in base BASE. If BASE is 0 the base is determined by the presence of a leading zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. If BASE is < 2 or > 36, it is reset to 10. @@ -380,7 +380,7 @@ INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, #if !UNSIGNED /* Check for a value that is within the range of - `unsigned LONG int', but outside the range of `LONG int'. */ + 'unsigned LONG int', but outside the range of 'LONG int'. */ if (overflow == 0 && i > (negative ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 @@ -405,7 +405,7 @@ noconv: /* We must handle a special case here: the base is 0 or 16 and the first two characters are '0' and 'x', but the rest are no hexadecimal digits. This is no error case. We return 0 and - ENDPTR points to the `x`. */ + ENDPTR points to the 'x'. */ if (endptr != NULL) { if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') diff --git a/contrib/grep/lib/strtoul.c b/contrib/grep/lib/strtoll.c similarity index 63% copy from contrib/grep/lib/strtoul.c copy to contrib/grep/lib/strtoll.c index 6fa6d0c2e0..fdfceb0137 100644 --- a/contrib/grep/lib/strtoul.c +++ b/contrib/grep/lib/strtoll.c @@ -1,4 +1,6 @@ -/* Copyright (C) 1991, 1997, 2009-2011 Free Software Foundation, Inc. +/* Function to parse a 'long long int' from text. + Copyright (C) 1995-1997, 1999, 2001, 2009-2012 Free Software Foundation, + Inc. This file is part of the GNU C Library. This program is free software: you can redistribute it and/or modify @@ -14,6 +16,18 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#define UNSIGNED 1 +#define QUAD 1 -#include "strtol.c" +#include + +#ifdef _LIBC +# ifdef SHARED +# include + +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2) +compat_symbol (libc, __strtoll_internal, __strtoq_internal, GLIBC_2_0); +# endif + +# endif +weak_alias (strtoll, strtoq) +#endif diff --git a/contrib/grep/lib/strtoul.c b/contrib/grep/lib/strtoul.c index 6fa6d0c2e0..e99da41edc 100644 --- a/contrib/grep/lib/strtoul.c +++ b/contrib/grep/lib/strtoul.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1997, 2009-2011 Free Software Foundation, Inc. +/* Copyright (C) 1991, 1997, 2009-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/strtoull.c b/contrib/grep/lib/strtoull.c index bf259958d6..33c2c5d9af 100644 --- a/contrib/grep/lib/strtoull.c +++ b/contrib/grep/lib/strtoull.c @@ -1,5 +1,5 @@ -/* Function to parse an `unsigned long long int' from text. - Copyright (C) 1995-1997, 1999, 2009-2011 Free Software Foundation, Inc. +/* Function to parse an 'unsigned long long int' from text. + Copyright (C) 1995-1997, 1999, 2009-2012 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. diff --git a/contrib/grep/lib/trim.c b/contrib/grep/lib/trim.c index 155063eed3..7f31380d18 100644 --- a/contrib/grep/lib/trim.c +++ b/contrib/grep/lib/trim.c @@ -1,5 +1,5 @@ /* Removes leading and/or trailing whitespaces - Copyright (C) 2006-2011 Free Software Foundation, Inc. + Copyright (C) 2006-2012 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 @@ -30,7 +30,7 @@ #include "mbiter.h" #include "xalloc.h" -/* Use this to suppress gcc's `...may be used before initialized' warnings. */ +/* Use this to suppress gcc's "...may be used before initialized" warnings. */ #ifdef lint # define IF_LINT(Code) Code #else diff --git a/contrib/grep/lib/trim.h b/contrib/grep/lib/trim.h index 0bbb2ffa66..bfe0c3f261 100644 --- a/contrib/grep/lib/trim.h +++ b/contrib/grep/lib/trim.h @@ -1,5 +1,5 @@ /* Removes leading and/or trailing whitespaces - Copyright (C) 2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2006, 2009-2012 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 diff --git a/contrib/grep/lib/exitfail.c b/contrib/grep/lib/unistd--.h similarity index 65% copy from contrib/grep/lib/exitfail.c copy to contrib/grep/lib/unistd--.h index 953aa02fe8..78b9e4ac76 100644 --- a/contrib/grep/lib/exitfail.c +++ b/contrib/grep/lib/unistd--.h @@ -1,6 +1,6 @@ -/* Failure exit status +/* Like unistd.h, but redefine some names to avoid glitches. - Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005, 2009-2012 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 @@ -15,10 +15,18 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include +/* Written by Paul Eggert. */ -#include "exitfail.h" +#include +#include "unistd-safer.h" -#include +#undef dup +#define dup dup_safer -int volatile exit_failure = EXIT_FAILURE; +#undef pipe +#define pipe pipe_safer + +#if GNULIB_PIPE2_SAFER +# undef pipe2 +# define pipe2 pipe2_safer +#endif diff --git a/contrib/grep/lib/closeout.h b/contrib/grep/lib/unistd-safer.h similarity index 62% copy from contrib/grep/lib/closeout.h copy to contrib/grep/lib/unistd-safer.h index ec8d7a6d2c..684bf79f5b 100644 --- a/contrib/grep/lib/closeout.h +++ b/contrib/grep/lib/unistd-safer.h @@ -1,7 +1,6 @@ -/* Close standard output and standard error. +/* Invoke unistd-like functions, but avoid some glitches. - Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2011 Free Software - Foundation, Inc. + Copyright (C) 2001, 2003, 2005, 2009-2012 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 @@ -16,21 +15,17 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef CLOSEOUT_H -# define CLOSEOUT_H 1 +/* Written by Paul Eggert and Eric Blake. */ -# include +int dup_safer (int); +int fd_safer (int); +int pipe_safer (int[2]); -# ifdef __cplusplus -extern "C" { -# endif - -void close_stdout_set_file_name (const char *file); -void close_stdout_set_ignore_EPIPE (bool ignore); -void close_stdout (void); - -# ifdef __cplusplus -} -# endif +#if GNULIB_FD_SAFER_FLAG +int dup_safer_flag (int, int); +int fd_safer_flag (int, int); +#endif +#if GNULIB_PIPE2_SAFER +int pipe2_safer (int[2], int); #endif diff --git a/contrib/grep/lib/unistr/u8-mbtoucr.c b/contrib/grep/lib/unistr/u8-mbtoucr.c index 794dfc3665..8bc59d7ce7 100644 --- a/contrib/grep/lib/unistr/u8-mbtoucr.c +++ b/contrib/grep/lib/unistr/u8-mbtoucr.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Look at first character in UTF-8 string, returning an error code. - Copyright (C) 1999-2002, 2006-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1999-2002, 2006-2007, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2001. This program is free software: you can redistribute it and/or modify it diff --git a/contrib/grep/lib/unistr/u8-uctomb-aux.c b/contrib/grep/lib/unistr/u8-uctomb-aux.c index 206487c022..5ee212b7ee 100644 --- a/contrib/grep/lib/unistr/u8-uctomb-aux.c +++ b/contrib/grep/lib/unistr/u8-uctomb-aux.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Conversion UCS-4 to UTF-8. - Copyright (C) 2002, 2006-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2002, 2006-2007, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2002. This program is free software: you can redistribute it and/or modify it diff --git a/contrib/grep/lib/unistr/u8-uctomb.c b/contrib/grep/lib/unistr/u8-uctomb.c index 8aa1849d25..e56e4a2386 100644 --- a/contrib/grep/lib/unistr/u8-uctomb.c +++ b/contrib/grep/lib/unistr/u8-uctomb.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Store a character in UTF-8 string. - Copyright (C) 2002, 2005-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2002, 2005-2006, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2002. This program is free software: you can redistribute it and/or modify it diff --git a/contrib/grep/lib/uniwidth/cjk.h b/contrib/grep/lib/uniwidth/cjk.h index 5f7b3b3125..d75c94f169 100644 --- a/contrib/grep/lib/uniwidth/cjk.h +++ b/contrib/grep/lib/uniwidth/cjk.h @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Test for CJK encoding. - Copyright (C) 2001-2002, 2005-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2002, 2005-2007, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2002. This program is free software: you can redistribute it and/or modify it @@ -24,16 +22,16 @@ is_cjk_encoding (const char *encoding) { if (0 /* Legacy Japanese encodings */ - || STREQ (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0) + || STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0) /* Legacy Chinese encodings */ - || STREQ (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) - || STREQ (encoding, "GBK", 'G', 'B', 'K', 0, 0, 0, 0, 0, 0) - || STREQ (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0) - || STREQ (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0) + || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, "GBK", 'G', 'B', 'K', 0, 0, 0, 0, 0, 0) + || STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0) + || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0) /* Legacy Korean encodings */ - || STREQ (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) - || STREQ (encoding, "CP949", 'C', 'P', '9', '4', '9', 0, 0, 0, 0) - || STREQ (encoding, "JOHAB", 'J', 'O', 'H', 'A', 'B', 0, 0, 0, 0)) + || STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, "CP949", 'C', 'P', '9', '4', '9', 0, 0, 0, 0) + || STREQ_OPT (encoding, "JOHAB", 'J', 'O', 'H', 'A', 'B', 0, 0, 0, 0)) return 1; return 0; } diff --git a/contrib/grep/lib/uniwidth/width.c b/contrib/grep/lib/uniwidth/width.c index 3fab5eaa1b..b6e2c334ba 100644 --- a/contrib/grep/lib/uniwidth/width.c +++ b/contrib/grep/lib/uniwidth/width.c @@ -1,7 +1,5 @@ -/* -*- buffer-read-only: t -*- vi: set ro: */ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Determine display width of Unicode character. - Copyright (C) 2001-2002, 2006-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2002, 2006-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2002. This program is free software: you can redistribute it and/or modify it diff --git a/contrib/grep/lib/unlocked-io.h b/contrib/grep/lib/unlocked-io.h index 901cbdd836..65bfbc4a5b 100644 --- a/contrib/grep/lib/unlocked-io.h +++ b/contrib/grep/lib/unlocked-io.h @@ -1,6 +1,6 @@ /* Prefer faster, non-thread-safe stdio functions if available. - Copyright (C) 2001-2004, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2009-2012 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 diff --git a/contrib/grep/lib/verify.h b/contrib/grep/lib/verify.h index 9a8caad001..cef14ad157 100644 --- a/contrib/grep/lib/verify.h +++ b/contrib/grep/lib/verify.h @@ -1,6 +1,6 @@ /* Compile-time assert-like macros. - Copyright (C) 2005-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2009-2012 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 @@ -21,13 +21,11 @@ # define _GL_VERIFY_H -/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per the - C1X draft N1548 section 6.7.10. This is supported by GCC 4.6.0 and - later, in C mode, and its use here generates easier-to-read diagnostics - when verify (R) fails. +/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11. + This is supported by GCC 4.6.0 and later, in C mode, and its use + here generates easier-to-read diagnostics when verify (R) fails. - Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per the - C++0X draft N3242 section 7.(4). + Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11. This will likely be supported by future GCC versions, in C++ mode. Use this only with GCC. If we were willing to slow 'configure' @@ -188,7 +186,7 @@ template trailing ';'. If R is false, fail at compile-time, preferably with a diagnostic that includes the string-literal DIAGNOSTIC. - Unfortunately, unlike C1X, this implementation must appear as an + Unfortunately, unlike C11, this implementation must appear as an ordinary declaration, and cannot appear inside struct { ... }. */ # ifdef _GL_HAVE__STATIC_ASSERT @@ -205,7 +203,7 @@ template # define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC) # endif # if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert -# define static_assert _Static_assert /* Draft C1X requires this #define. */ +# define static_assert _Static_assert /* C11 requires this #define. */ # endif # endif diff --git a/contrib/grep/lib/version-etc-fsf.c b/contrib/grep/lib/version-etc-fsf.c index c82158302c..c452f40dfb 100644 --- a/contrib/grep/lib/version-etc-fsf.c +++ b/contrib/grep/lib/version-etc-fsf.c @@ -1,5 +1,5 @@ /* Variable with FSF copyright information, for version-etc. - Copyright (C) 1999-2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1999-2006, 2009-2012 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 diff --git a/contrib/grep/lib/version-etc.c b/contrib/grep/lib/version-etc.c index b8d4724b56..ae1e44d61d 100644 --- a/contrib/grep/lib/version-etc.c +++ b/contrib/grep/lib/version-etc.c @@ -1,5 +1,5 @@ /* Print --version and bug-reporting information in a consistent format. - Copyright (C) 1999-2011 Free Software Foundation, Inc. + Copyright (C) 1999-2012 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 @@ -38,7 +38,7 @@ # define PACKAGE PACKAGE_TARNAME #endif -enum { COPYRIGHT_YEAR = 2011 }; +enum { COPYRIGHT_YEAR = 2012 }; /* The three functions below display the --version information the standard way. diff --git a/contrib/grep/lib/version-etc.h b/contrib/grep/lib/version-etc.h index a9b313d23a..5548c023c3 100644 --- a/contrib/grep/lib/version-etc.h +++ b/contrib/grep/lib/version-etc.h @@ -1,5 +1,5 @@ /* Print --version and bug-reporting information in a consistent format. - Copyright (C) 1999, 2003, 2005, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1999, 2003, 2005, 2009-2012 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 @@ -22,7 +22,7 @@ # include # include -/* The `sentinel' attribute was added in gcc 4.0. */ +/* The 'sentinel' attribute was added in gcc 4.0. */ #ifndef _GL_ATTRIBUTE_SENTINEL # if 4 <= __GNUC__ # define _GL_ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__)) @@ -37,7 +37,7 @@ extern const char version_etc_copyright[]; standard way: command and package names, package version, followed by a short GPLv3+ notice and a list of up to 10 author names. - If COMMAND_NAME is NULL, the PACKAGE is asumed to be the name of + If COMMAND_NAME is NULL, the PACKAGE is assumed to be the name of the program. The formats are therefore: PACKAGE VERSION @@ -72,7 +72,7 @@ extern void version_etc (FILE *stream, /* const char *author1, ..., NULL */ ...) _GL_ATTRIBUTE_SENTINEL; -/* Display the usual `Report bugs to' stanza */ +/* Display the usual "Report bugs to" stanza. */ extern void emit_bug_reporting_address (void); #endif /* VERSION_ETC_H */ diff --git a/contrib/grep/lib/wcrtomb.c b/contrib/grep/lib/wcrtomb.c index 6632589365..9e6494eef4 100644 --- a/contrib/grep/lib/wcrtomb.c +++ b/contrib/grep/lib/wcrtomb.c @@ -1,5 +1,5 @@ /* Convert wide character to multibyte character. - Copyright (C) 2008-2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/wcscoll-impl.h b/contrib/grep/lib/wcscoll-impl.h new file mode 100644 index 0000000000..8a93d5257c --- /dev/null +++ b/contrib/grep/lib/wcscoll-impl.h @@ -0,0 +1,111 @@ +/* Compare two wide strings using the current locale. + Copyright (C) 2011-2012 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + 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 of the License, 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 . */ + +int +wcscoll (const wchar_t *s1, const wchar_t *s2) +{ + char mbbuf1[1024]; + char mbbuf2[1024]; + char *mbs1; + char *mbs2; + + { + int saved_errno = errno; + + /* Convert s1 to a multibyte string, trying to avoid malloc(). */ + { + size_t ret; + + ret = wcstombs (mbbuf1, s1, sizeof (mbbuf1)); + if (ret == (size_t)-1) + goto failed1; + if (ret < sizeof (mbbuf1)) + mbs1 = mbbuf1; + else + { + size_t need = wcstombs (NULL, s1, 0); + if (need == (size_t)-1) + goto failed1; + mbs1 = (char *) malloc (need + 1); + if (mbs1 == NULL) + goto out_of_memory1; + ret = wcstombs (mbs1, s1, need + 1); + if (ret != need) + abort (); + } + } + + /* Convert s2 to a multibyte string, trying to avoid malloc(). */ + { + size_t ret; + + ret = wcstombs (mbbuf2, s2, sizeof (mbbuf2)); + if (ret == (size_t)-1) + goto failed2; + if (ret < sizeof (mbbuf2)) + mbs2 = mbbuf2; + else + { + size_t need = wcstombs (NULL, s2, 0); + if (need == (size_t)-1) + goto failed2; + mbs2 = (char *) malloc (need + 1); + if (mbs2 == NULL) + goto out_of_memory2; + ret = wcstombs (mbs2, s2, need + 1); + if (ret != need) + abort (); + } + } + + /* No error so far. */ + errno = saved_errno; + } + + /* Compare the two multibyte strings. */ + { + int result = strcoll (mbs1, mbs2); + + if (mbs1 != mbbuf1) + { + int saved_errno = errno; + free (mbs1); + errno = saved_errno; + } + if (mbs2 != mbbuf2) + { + int saved_errno = errno; + free (mbs2); + errno = saved_errno; + } + return result; + } + + out_of_memory2: + if (mbs1 != mbbuf1) + free (mbs1); + out_of_memory1: + errno = ENOMEM; + return 0; + + failed2: + if (mbs1 != mbbuf1) + free (mbs1); + failed1: + errno = EILSEQ; + return 0; +} diff --git a/contrib/grep/lib/wctomb.c b/contrib/grep/lib/wcscoll.c similarity index 81% copy from contrib/grep/lib/wctomb.c copy to contrib/grep/lib/wcscoll.c index 889a3c6fff..ce60aea9a7 100644 --- a/contrib/grep/lib/wctomb.c +++ b/contrib/grep/lib/wcscoll.c @@ -1,5 +1,5 @@ -/* Convert wide character to multibyte character. - Copyright (C) 2011 Free Software Foundation, Inc. +/* Compare two wide strings using the current locale. + Copyright (C) 2011-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2011. This program is free software: you can redistribute it and/or modify @@ -17,9 +17,11 @@ #include -#include +/* Specification. */ +#include +#include +#include #include -#include -#include "wctomb-impl.h" +#include "wcscoll-impl.h" diff --git a/contrib/grep/lib/wctob.c b/contrib/grep/lib/wctob.c index cc26afc512..0885c1b127 100644 --- a/contrib/grep/lib/wctob.c +++ b/contrib/grep/lib/wctob.c @@ -1,5 +1,5 @@ /* Convert wide character to unibyte character. - Copyright (C) 2008, 2010-2011 Free Software Foundation, Inc. + Copyright (C) 2008, 2010-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/wctomb-impl.h b/contrib/grep/lib/wctomb-impl.h index 4e95de6383..68264cfb97 100644 --- a/contrib/grep/lib/wctomb-impl.h +++ b/contrib/grep/lib/wctomb-impl.h @@ -1,5 +1,5 @@ /* Convert wide character to multibyte character. - Copyright (C) 2011 Free Software Foundation, Inc. + Copyright (C) 2011-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2011. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/wctomb.c b/contrib/grep/lib/wctomb.c index 889a3c6fff..736a7c7090 100644 --- a/contrib/grep/lib/wctomb.c +++ b/contrib/grep/lib/wctomb.c @@ -1,5 +1,5 @@ /* Convert wide character to multibyte character. - Copyright (C) 2011 Free Software Foundation, Inc. + Copyright (C) 2011-2012 Free Software Foundation, Inc. Written by Bruno Haible , 2011. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/wcwidth.c b/contrib/grep/lib/wcwidth.c index a006ca7a83..44503b04bb 100644 --- a/contrib/grep/lib/wcwidth.c +++ b/contrib/grep/lib/wcwidth.c @@ -1,5 +1,5 @@ /* Determine the number of screen columns needed for a character. - Copyright (C) 2006-2007, 2010-2011 Free Software Foundation, Inc. + Copyright (C) 2006-2007, 2010-2012 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 @@ -32,7 +32,7 @@ wcwidth (wchar_t wc) { /* In UTF-8 locales, use a Unicode aware width function. */ const char *encoding = locale_charset (); - if (STREQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0 ,0)) + if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0 ,0)) { /* We assume that in a UTF-8 locale, a wide character is the same as a Unicode character. */ diff --git a/contrib/grep/lib/xalloc-die.c b/contrib/grep/lib/xalloc-die.c index aba4a068d0..e85d6dfb69 100644 --- a/contrib/grep/lib/xalloc-die.c +++ b/contrib/grep/lib/xalloc-die.c @@ -1,6 +1,6 @@ /* Report a memory allocation failure and exit. - Copyright (C) 1997-2000, 2002-2004, 2006, 2009-2011 Free Software + Copyright (C) 1997-2000, 2002-2004, 2006, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -33,7 +33,7 @@ xalloc_die (void) { error (exit_failure, 0, "%s", _("memory exhausted")); - /* The `noreturn' cannot be given to error, since it may return if + /* _Noreturn cannot be given to error, since it may return if its first argument is 0. To help compilers understand the xalloc_die does not return, call abort. Also, the abort is a safety feature if exit_failure is 0 (which shouldn't happen). */ diff --git a/contrib/grep/lib/xalloc-oversized.h b/contrib/grep/lib/xalloc-oversized.h index ab19bcf2f9..6779755983 100644 --- a/contrib/grep/lib/xalloc-oversized.h +++ b/contrib/grep/lib/xalloc-oversized.h @@ -1,6 +1,6 @@ /* xalloc-oversized.h -- memory allocation size checking - Copyright (C) 1990-2000, 2003-2004, 2006-2011 Free Software Foundation, Inc. + Copyright (C) 1990-2000, 2003-2004, 2006-2012 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 diff --git a/contrib/grep/lib/xalloc.h b/contrib/grep/lib/xalloc.h index c1bbe7e5b6..6f5b87ee2d 100644 --- a/contrib/grep/lib/xalloc.h +++ b/contrib/grep/lib/xalloc.h @@ -1,6 +1,6 @@ /* xalloc.h -- malloc with out-of-memory checking - Copyright (C) 1990-2000, 2003-2004, 2006-2011 Free Software Foundation, Inc. + Copyright (C) 1990-2000, 2003-2004, 2006-2012 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 @@ -27,12 +27,6 @@ extern "C" { # endif -# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -# define _GL_ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) -# else -# define _GL_ATTRIBUTE_NORETURN /* empty */ -# endif - # if __GNUC__ >= 3 # define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) # else @@ -50,7 +44,7 @@ extern "C" { or by using gnulib's xalloc-die module. This is the function to call when one wants the program to die because of a memory allocation failure. */ -extern void xalloc_die (void) _GL_ATTRIBUTE_NORETURN; +extern _Noreturn void xalloc_die (void); void *xmalloc (size_t s) _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1)); @@ -198,9 +192,9 @@ x2nrealloc (void *p, size_t *pn, size_t s) { /* The approximate size to use for initial small allocation requests, when the invoking code specifies an old size of - zero. 64 bytes is the largest "small" request for the - GNU C library malloc. */ - enum { DEFAULT_MXFAST = 64 }; + zero. This is the largest "small" request for the GNU C + library malloc. */ + enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; n = DEFAULT_MXFAST / s; n += !n; diff --git a/contrib/grep/lib/xmalloc.c b/contrib/grep/lib/xmalloc.c index 08c30fb8a3..3b5f86cdca 100644 --- a/contrib/grep/lib/xmalloc.c +++ b/contrib/grep/lib/xmalloc.c @@ -1,6 +1,6 @@ /* xmalloc.c -- malloc with out of memory checking - Copyright (C) 1990-2000, 2002-2006, 2008-2011 Free Software Foundation, Inc. + Copyright (C) 1990-2000, 2002-2006, 2008-2012 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 diff --git a/contrib/grep/lib/xstriconv.c b/contrib/grep/lib/xstriconv.c index 9e4498fa5c..23d6fc61bf 100644 --- a/contrib/grep/lib/xstriconv.c +++ b/contrib/grep/lib/xstriconv.c @@ -1,5 +1,5 @@ /* Charset conversion with out-of-memory checking. - Copyright (C) 2001-2004, 2006, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2006, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/xstriconv.h b/contrib/grep/lib/xstriconv.h index eba6b167ab..f176f4ebb9 100644 --- a/contrib/grep/lib/xstriconv.h +++ b/contrib/grep/lib/xstriconv.h @@ -1,5 +1,5 @@ /* Charset conversion with out-of-memory checking. - Copyright (C) 2001-2004, 2006-2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2006-2007, 2009-2012 Free Software Foundation, Inc. Written by Bruno Haible and Simon Josefsson. This program is free software: you can redistribute it and/or modify diff --git a/contrib/grep/lib/xstrndup.c b/contrib/grep/lib/xstrndup.c deleted file mode 100644 index d58302a13d..0000000000 --- a/contrib/grep/lib/xstrndup.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Duplicate a bounded initial segment of a string, with out-of-memory - checking. - Copyright (C) 2003, 2006-2007, 2009-2011 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 of the License, 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 . */ - -#include - -/* Specification. */ -#include "xstrndup.h" - -#include -#include "xalloc.h" - -/* Return a newly allocated copy of at most N bytes of STRING. - In other words, return a copy of the initial segment of length N of - STRING. */ -char * -xstrndup (const char *string, size_t n) -{ - char *s = strndup (string, n); - if (! s) - xalloc_die (); - return s; -} diff --git a/contrib/grep/lib/xstrndup.h b/contrib/grep/lib/xstrndup.h deleted file mode 100644 index f96a538dfd..0000000000 --- a/contrib/grep/lib/xstrndup.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Duplicate a bounded initial segment of a string, with out-of-memory - checking. - Copyright (C) 2003, 2009-2011 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 of the License, 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 . */ - -#include - -/* Return a newly allocated copy of at most N bytes of STRING. - In other words, return a copy of the initial segment of length N of - STRING. */ -extern char *xstrndup (const char *string, size_t n); diff --git a/contrib/grep/lib/xstrtoimax.c b/contrib/grep/lib/xstrtoimax.c new file mode 100644 index 0000000000..b4baf5bc60 --- /dev/null +++ b/contrib/grep/lib/xstrtoimax.c @@ -0,0 +1,6 @@ +#define __strtol strtoimax +#define __strtol_t intmax_t +#define __xstrtol xstrtoimax +#define STRTOL_T_MINIMUM INTMAX_MIN +#define STRTOL_T_MAXIMUM INTMAX_MAX +#include "xstrtol.c" diff --git a/contrib/grep/lib/xstrtol-error.c b/contrib/grep/lib/xstrtol-error.c index 52e712c10b..ce96ef6c65 100644 --- a/contrib/grep/lib/xstrtol-error.c +++ b/contrib/grep/lib/xstrtol-error.c @@ -1,6 +1,6 @@ /* A more useful interface to strtol. - Copyright (C) 1995-1996, 1998-1999, 2001-2004, 2006-2011 Free Software + Copyright (C) 1995-1996, 1998-1999, 2001-2004, 2006-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -60,16 +60,16 @@ xstrtol_error (enum strtol_error err, abort (); case LONGINT_INVALID: - msgid = N_("invalid %s%s argument `%s'"); + msgid = N_("invalid %s%s argument '%s'"); break; case LONGINT_INVALID_SUFFIX_CHAR: case LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW: - msgid = N_("invalid suffix in %s%s argument `%s'"); + msgid = N_("invalid suffix in %s%s argument '%s'"); break; case LONGINT_OVERFLOW: - msgid = N_("%s%s argument `%s' too large"); + msgid = N_("%s%s argument '%s' too large"); break; } diff --git a/contrib/grep/lib/xstrtol.c b/contrib/grep/lib/xstrtol.c index 97ebd9078b..7c4fbd87b8 100644 --- a/contrib/grep/lib/xstrtol.c +++ b/contrib/grep/lib/xstrtol.c @@ -1,6 +1,6 @@ /* A more useful interface to strtol. - Copyright (C) 1995-1996, 1998-2001, 2003-2007, 2009-2011 Free Software + Copyright (C) 1995-1996, 1998-2001, 2003-2007, 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -43,6 +43,19 @@ #include "intprops.h" +/* xstrtoll.c and xstrtoull.c, which include this file, require that + ULLONG_MAX, LLONG_MAX, LLONG_MIN are defined, but does not + define them on all platforms. */ +#ifndef ULLONG_MAX +# define ULLONG_MAX TYPE_MAXIMUM (unsigned long long) +#endif +#ifndef LLONG_MAX +# define LLONG_MAX TYPE_MAXIMUM (long long int) +#endif +#ifndef LLONG_MIN +# define LLONG_MIN TYPE_MINIMUM (long long int) +#endif + static strtol_error bkm_scale (__strtol_t *x, int scale_factor) { @@ -113,9 +126,9 @@ __xstrtol (const char *s, char **ptr, int strtol_base, err = LONGINT_OVERFLOW; } - /* Let valid_suffixes == NULL mean `allow any suffix'. */ + /* Let valid_suffixes == NULL mean "allow any suffix". */ /* FIXME: update all callers except the ones that allow suffixes - after the number, changing last parameter NULL to `""'. */ + after the number, changing last parameter NULL to "". */ if (!valid_suffixes) { *val = tmp; @@ -136,7 +149,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base, if (strchr (valid_suffixes, '0')) { - /* The ``valid suffix'' '0' is a special flag meaning that + /* The "valid suffix" '0' is a special flag meaning that an optional second suffix is allowed, which can change the base. A suffix "B" (e.g. "100MB") stands for a power of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for diff --git a/contrib/grep/lib/xstrtol.h b/contrib/grep/lib/xstrtol.h index 716a94ff94..516ac5655f 100644 --- a/contrib/grep/lib/xstrtol.h +++ b/contrib/grep/lib/xstrtol.h @@ -1,6 +1,6 @@ /* A more useful interface to strtol. - Copyright (C) 1995-1996, 1998-1999, 2001-2004, 2006-2011 Free Software + Copyright (C) 1995-1996, 1998-1999, 2001-2004, 2006-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -51,12 +51,6 @@ _DECLARE_XSTRTOL (xstrtoll, long long int) _DECLARE_XSTRTOL (xstrtoull, unsigned long long int) #endif -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) -# define _GL_ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) -#else -# define _GL_ATTRIBUTE_NORETURN /* empty */ -#endif - /* Report an error for an invalid integer in an option argument. ERR is the error code returned by one of the xstrto* functions. @@ -72,8 +66,8 @@ _DECLARE_XSTRTOL (xstrtoull, unsigned long long int) After reporting an error, exit with a failure status. */ -void xstrtol_fatal (enum strtol_error, - int, char, struct option const *, - char const *) _GL_ATTRIBUTE_NORETURN; +void _Noreturn xstrtol_fatal (enum strtol_error, + int, char, struct option const *, + char const *); #endif /* not XSTRTOL_H_ */ diff --git a/contrib/grep/lib/xstrtoumax.c b/contrib/grep/lib/xstrtoumax.c deleted file mode 100644 index 9a2349f00d..0000000000 --- a/contrib/grep/lib/xstrtoumax.c +++ /dev/null @@ -1,6 +0,0 @@ -#define __strtol strtoumax -#define __strtol_t uintmax_t -#define __xstrtol xstrtoumax -#define STRTOL_T_MINIMUM 0 -#define STRTOL_T_MAXIMUM UINTMAX_MAX -#include "xstrtol.c" diff --git a/contrib/grep/src/dfa.c b/contrib/grep/src/dfa.c index f2cd198962..1cbe5379fc 100644 --- a/contrib/grep/src/dfa.c +++ b/contrib/grep/src/dfa.c @@ -1,5 +1,5 @@ /* dfa.c - deterministic extended regexp routines for GNU - Copyright (C) 1988, 1998, 2000, 2002, 2004-2005, 2007-2011 Free Software + Copyright (C) 1988, 1998, 2000, 2002, 2004-2005, 2007-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -46,7 +46,7 @@ #include "gettext.h" #define _(str) gettext (str) -#include "mbsupport.h" /* defines MBS_SUPPORT if appropriate */ +#include "mbsupport.h" /* defines MBS_SUPPORT if appropriate */ #include #include @@ -86,6 +86,32 @@ /* Sets of unsigned characters are stored as bit vectors in arrays of ints. */ typedef int charclass[CHARCLASS_INTS]; +/* 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. */ +static inline unsigned char +to_uchar (char ch) +{ + return ch; +} + +/* Contexts tell us whether a character is a newline or a word constituent. + Word-constituent characters are those that satisfy iswalnum(), plus '_'. + Each character has a single CTX_* value; bitmasks of CTX_* values denote + a particular character class. + + A state also stores a context value, which is a bitmask of CTX_* values. + A state's context represents a set of characters that the state's + predecessors must match. For example, a state whose context does not + include CTX_LETTER will never have transitions where the previous + character is a word constituent. A state whose context is CTX_ANY + might have transitions from any character. */ + +#define CTX_NONE 1 +#define CTX_LETTER 2 +#define CTX_NEWLINE 4 +#define CTX_ANY 7 + /* Sometimes characters can only be matched depending on the surrounding context. Such context decisions depend on what the previous character was, and the value of the current (lookahead) character. Context @@ -93,54 +119,55 @@ typedef int charclass[CHARCLASS_INTS]; is set indicates that the constraint succeeds in the corresponding context. - bit 7 - previous and current are newlines - bit 6 - previous was newline, current isn't - bit 5 - previous wasn't newline, current is - bit 4 - neither previous nor current is a newline - bit 3 - previous and current are word-constituents - bit 2 - previous was word-constituent, current isn't - bit 1 - previous wasn't word-constituent, current is - bit 0 - neither previous nor current is word-constituent - - Word-constituent characters are those that satisfy isalnum(). + bit 8-11 - valid contexts when next character is CTX_NEWLINE + bit 4-7 - valid contexts when next character is CTX_LETTER + bit 0-3 - valid contexts when next character is CTX_NONE The macro SUCCEEDS_IN_CONTEXT determines whether a given constraint - succeeds in a particular context. Prevn is true if the previous character - was a newline, currn is true if the lookahead character is a newline. - Prevl and currl similarly depend upon whether the previous and current - characters are word-constituent letters. */ -#define MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \ - ((constraint) & 1 << (((prevn) ? 2 : 0) + ((currn) ? 1 : 0) + 4)) -#define MATCHES_LETTER_CONTEXT(constraint, prevl, currl) \ - ((constraint) & 1 << (((prevl) ? 2 : 0) + ((currl) ? 1 : 0))) -#define SUCCEEDS_IN_CONTEXT(constraint, prevn, currn, prevl, currl) \ - (MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \ - && MATCHES_LETTER_CONTEXT(constraint, prevl, currl)) + succeeds in a particular context. Prev is a bitmask of possible + context values for the previous character, curr is the (single-bit) + context value for the lookahead character. */ +#define NEWLINE_CONSTRAINT(constraint) (((constraint) >> 8) & 0xf) +#define LETTER_CONSTRAINT(constraint) (((constraint) >> 4) & 0xf) +#define OTHER_CONSTRAINT(constraint) ((constraint) & 0xf) + +#define SUCCEEDS_IN_CONTEXT(constraint, prev, curr) \ + ((((curr) & CTX_NONE ? OTHER_CONSTRAINT(constraint) : 0) \ + | ((curr) & CTX_LETTER ? LETTER_CONSTRAINT(constraint) : 0) \ + | ((curr) & CTX_NEWLINE ? NEWLINE_CONSTRAINT(constraint) : 0)) & (prev)) /* The following macros give information about what a constraint depends on. */ +#define PREV_NEWLINE_CONSTRAINT(constraint) (((constraint) >> 2) & 0x111) +#define PREV_LETTER_CONSTRAINT(constraint) (((constraint) >> 1) & 0x111) +#define PREV_OTHER_CONSTRAINT(constraint) ((constraint) & 0x111) + #define PREV_NEWLINE_DEPENDENT(constraint) \ - (((constraint) & 0xc0) >> 2 != ((constraint) & 0x30)) + (PREV_NEWLINE_CONSTRAINT (constraint) != PREV_OTHER_CONSTRAINT (constraint)) #define PREV_LETTER_DEPENDENT(constraint) \ - (((constraint) & 0x0c) >> 2 != ((constraint) & 0x03)) + (PREV_LETTER_CONSTRAINT (constraint) != PREV_OTHER_CONSTRAINT (constraint)) /* Tokens that match the empty string subject to some constraint actually work by applying that constraint to determine what may follow them, taking into account what has gone before. The following values are the constraints corresponding to the special tokens previously defined. */ -#define NO_CONSTRAINT 0xff -#define BEGLINE_CONSTRAINT 0xcf -#define ENDLINE_CONSTRAINT 0xaf -#define BEGWORD_CONSTRAINT 0xf2 -#define ENDWORD_CONSTRAINT 0xf4 -#define LIMWORD_CONSTRAINT 0xf6 -#define NOTLIMWORD_CONSTRAINT 0xf9 +#define NO_CONSTRAINT 0x777 +#define BEGLINE_CONSTRAINT 0x444 +#define ENDLINE_CONSTRAINT 0x700 +#define BEGWORD_CONSTRAINT 0x050 +#define ENDWORD_CONSTRAINT 0x202 +#define LIMWORD_CONSTRAINT 0x252 +#define NOTLIMWORD_CONSTRAINT 0x525 /* The regexp is parsed into an array of tokens in postfix form. Some tokens are operators and others are terminal symbols. Most (but not all) of these codes are returned by the lexical analyzer. */ -typedef enum + +typedef ptrdiff_t token; + +/* Predefined token values. */ +enum { - END = -1, /* END is a terminal symbol that matches the + END = -1, /* END is a terminal symbol that matches the end of input; any value of END or less in the parse tree is such a symbol. Accepting states of the DFA are those that would have @@ -148,83 +175,83 @@ typedef enum /* Ordinary character values are terminal symbols that match themselves. */ - EMPTY = NOTCHAR, /* EMPTY is a terminal symbol that matches + EMPTY = NOTCHAR, /* EMPTY is a terminal symbol that matches the empty string. */ - BACKREF, /* BACKREF is generated by \; it + BACKREF, /* BACKREF is generated by \; it is not completely handled. If the scanner detects a transition on backref, it returns a kind of "semi-success" indicating that the match will have to be verified with a backtracking matcher. */ - BEGLINE, /* BEGLINE is a terminal symbol that matches + BEGLINE, /* BEGLINE is a terminal symbol that matches the empty string if it is at the beginning of a line. */ - ENDLINE, /* ENDLINE is a terminal symbol that matches + ENDLINE, /* ENDLINE is a terminal symbol that matches the empty string if it is at the end of a line. */ - BEGWORD, /* BEGWORD is a terminal symbol that matches + BEGWORD, /* BEGWORD is a terminal symbol that matches the empty string if it is at the beginning of a word. */ - ENDWORD, /* ENDWORD is a terminal symbol that matches + ENDWORD, /* ENDWORD is a terminal symbol that matches the empty string if it is at the end of a word. */ - LIMWORD, /* LIMWORD is a terminal symbol that matches + LIMWORD, /* LIMWORD is a terminal symbol that matches the empty string if it is at the beginning or the end of a word. */ - NOTLIMWORD, /* NOTLIMWORD is a terminal symbol that + NOTLIMWORD, /* NOTLIMWORD is a terminal symbol that matches the empty string if it is not at the beginning or end of a word. */ - QMARK, /* QMARK is an operator of one argument that - matches zero or one occurences of its + QMARK, /* QMARK is an operator of one argument that + matches zero or one occurrences of its argument. */ - STAR, /* STAR is an operator of one argument that + STAR, /* STAR is an operator of one argument that matches the Kleene closure (zero or more occurrences) of its argument. */ - PLUS, /* PLUS is an operator of one argument that + PLUS, /* PLUS is an operator of one argument that matches the positive closure (one or more occurrences) of its argument. */ - REPMN, /* REPMN is a lexical token corresponding + REPMN, /* REPMN is a lexical token corresponding to the {m,n} construct. REPMN never appears in the compiled token vector. */ - CAT, /* CAT is an operator of two arguments that + CAT, /* CAT is an operator of two arguments that matches the concatenation of its arguments. CAT is never returned by the lexical analyzer. */ - OR, /* OR is an operator of two arguments that + OR, /* OR is an operator of two arguments that matches either of its arguments. */ - LPAREN, /* LPAREN never appears in the parse tree, + LPAREN, /* LPAREN never appears in the parse tree, it is only a lexeme. */ - RPAREN, /* RPAREN never appears in the parse tree. */ + RPAREN, /* RPAREN never appears in the parse tree. */ - ANYCHAR, /* ANYCHAR is a terminal symbol that matches - any multibyte (or single byte) characters. - It is used only if MB_CUR_MAX > 1. */ + ANYCHAR, /* ANYCHAR is a terminal symbol that matches + any multibyte (or single byte) characters. + It is used only if MB_CUR_MAX > 1. */ - MBCSET, /* MBCSET is similar to CSET, but for + MBCSET, /* MBCSET is similar to CSET, but for multibyte characters. */ - WCHAR, /* Only returned by lex. wctok contains + WCHAR, /* Only returned by lex. wctok contains the wide character representation. */ - CSET /* CSET and (and any value greater) is a + CSET /* CSET and (and any value greater) is a terminal symbol that matches any of a class of characters. */ -} token; +}; /* States of the recognizer correspond to sets of positions in the parse @@ -233,120 +260,127 @@ typedef enum a constraint. */ typedef struct { - unsigned int index; /* Index into the parse array. */ - unsigned int constraint; /* Constraint for matching this position. */ + size_t index; /* Index into the parse array. */ + unsigned int constraint; /* Constraint for matching this position. */ } position; /* Sets of positions are stored as arrays. */ typedef struct { - position *elems; /* Elements of this position set. */ - int nelem; /* Number of elements in this set. */ + position *elems; /* Elements of this position set. */ + size_t nelem; /* Number of elements in this set. */ + size_t alloc; /* Number of elements allocated in ELEMS. */ } position_set; +/* Sets of leaves are also stored as arrays. */ +typedef struct +{ + size_t *elems; /* Elements of this position set. */ + size_t nelem; /* Number of elements in this set. */ +} leaf_set; + /* A state of the dfa consists of a set of positions, some flags, and the token value of the lowest-numbered position of the state that contains an END token. */ typedef struct { - int hash; /* Hash of the positions of this state. */ - position_set elems; /* Positions this state could match. */ - char newline; /* True if previous state matched newline. */ - char letter; /* True if previous state matched a letter. */ - char backref; /* True if this state matches a \. */ - unsigned char constraint; /* Constraint for this state to accept. */ - int first_end; /* Token value of the first END in elems. */ -#if MBS_SUPPORT - position_set mbps; /* Positions which can match multibyte - characters. e.g. period. - These staff are used only if - MB_CUR_MAX > 1. */ -#endif + size_t hash; /* Hash of the positions of this state. */ + position_set elems; /* Positions this state could match. */ + unsigned char context; /* Context from previous state. */ + char backref; /* True if this state matches a \. */ + unsigned short constraint; /* Constraint for this state to accept. */ + token first_end; /* Token value of the first END in elems. */ + position_set mbps; /* Positions which can match multibyte + characters. e.g. period. + These staff are used only if + MB_CUR_MAX > 1. */ } dfa_state; -#if MBS_SUPPORT +/* States are indexed by state_num values. These are normally + nonnegative but -1 is used as a special value. */ +typedef ptrdiff_t state_num; + /* A bracket operator. e.g. [a-c], [[:alpha:]], etc. */ struct mb_char_classes { - int cset; + ptrdiff_t cset; int invert; - wchar_t *chars; /* Normal characters. */ - int nchars; - wctype_t *ch_classes; /* Character classes. */ - int nch_classes; - wchar_t *range_sts; /* Range characters (start of the range). */ - wchar_t *range_ends; /* Range characters (end of the range). */ - int nranges; - char **equivs; /* Equivalent classes. */ - int nequivs; + wchar_t *chars; /* Normal characters. */ + size_t nchars; + wctype_t *ch_classes; /* Character classes. */ + size_t nch_classes; + wchar_t *range_sts; /* Range characters (start of the range). */ + wchar_t *range_ends; /* Range characters (end of the range). */ + size_t nranges; + char **equivs; /* Equivalence classes. */ + size_t nequivs; char **coll_elems; - int ncoll_elems; /* Collating elements. */ + size_t ncoll_elems; /* Collating elements. */ }; -#endif /* A compiled regular expression. */ struct dfa { /* Fields filled by the scanner. */ - charclass *charclasses; /* Array of character sets for CSET tokens. */ - int cindex; /* Index for adding new charclasses. */ - int calloc; /* Number of charclasses currently allocated. */ + charclass *charclasses; /* Array of character sets for CSET tokens. */ + size_t cindex; /* Index for adding new charclasses. */ + size_t calloc; /* Number of charclasses currently allocated. */ /* Fields filled by the parser. */ - token *tokens; /* Postfix parse array. */ - int tindex; /* Index for adding new tokens. */ - int talloc; /* Number of tokens currently allocated. */ - int depth; /* Depth required of an evaluation stack + token *tokens; /* Postfix parse array. */ + size_t tindex; /* Index for adding new tokens. */ + size_t talloc; /* Number of tokens currently allocated. */ + size_t depth; /* Depth required of an evaluation stack used for depth-first traversal of the parse tree. */ - int nleaves; /* Number of leaves on the parse tree. */ - int nregexps; /* Count of parallel regexps being built + size_t nleaves; /* Number of leaves on the parse tree. */ + size_t nregexps; /* Count of parallel regexps being built with dfaparse(). */ - unsigned int mb_cur_max; /* Cached value of MB_CUR_MAX. */ - int utf8_anychar_classes[5]; /* To lower ANYCHAR in UTF-8 locales. */ + unsigned int mb_cur_max; /* Cached value of MB_CUR_MAX. */ + token utf8_anychar_classes[5]; /* To lower ANYCHAR in UTF-8 locales. */ /* The following are used only if MB_CUR_MAX > 1. */ /* The value of multibyte_prop[i] is defined by following rule. - if tokens[i] < NOTCHAR - bit 0 : tokens[i] is the first byte of a character, including - single-byte characters. - bit 1 : tokens[i] is the last byte of a character, including - single-byte characters. + if tokens[i] < NOTCHAR + bit 0 : tokens[i] is the first byte of a character, including + single-byte characters. + bit 1 : tokens[i] is the last byte of a character, including + single-byte characters. - if tokens[i] = MBCSET - ("the index of mbcsets correspnd to this operator" << 2) + 3 + if tokens[i] = MBCSET + ("the index of mbcsets corresponding to this operator" << 2) + 3 e.g. tokens - = 'single_byte_a', 'multi_byte_A', single_byte_b' - = 'sb_a', 'mb_A(1st byte)', 'mb_A(2nd byte)', 'mb_A(3rd byte)', 'sb_b' + = 'single_byte_a', 'multi_byte_A', single_byte_b' + = 'sb_a', 'mb_A(1st byte)', 'mb_A(2nd byte)', 'mb_A(3rd byte)', 'sb_b' multibyte_prop - = 3 , 1 , 0 , 2 , 3 - */ - int nmultibyte_prop; + = 3 , 1 , 0 , 2 , 3 + */ + size_t nmultibyte_prop; int *multibyte_prop; /* Array of the bracket expression in the DFA. */ struct mb_char_classes *mbcsets; - int nmbcsets; - int mbcsets_alloc; + size_t nmbcsets; + size_t mbcsets_alloc; /* Fields filled by the state builder. */ - dfa_state *states; /* States of the dfa. */ - int sindex; /* Index for adding new states. */ - int salloc; /* Number of states currently allocated. */ + dfa_state *states; /* States of the dfa. */ + state_num sindex; /* Index for adding new states. */ + state_num salloc; /* Number of states currently allocated. */ /* Fields filled by the parse tree->NFA conversion. */ - position_set *follows; /* Array of follow sets, indexed by position + position_set *follows; /* Array of follow sets, indexed by position index. The follow of a position is the set of positions containing characters that could conceivably follow a character matching the given position in a string matching the regexp. Allocated to the maximum possible position index. */ - int searchflag; /* True if we are supposed to build a searching + int searchflag; /* True if we are supposed to build a searching as opposed to an exact matcher. A searching matcher finds the first and shortest string matching a regexp anywhere in the buffer, @@ -355,29 +389,29 @@ struct dfa beginning of the buffer. */ /* Fields filled by dfaexec. */ - int tralloc; /* Number of transition tables that have + state_num tralloc; /* Number of transition tables that have slots so far. */ - int trcount; /* Number of transition tables that have + int trcount; /* Number of transition tables that have actually been built. */ - int **trans; /* Transition tables for states that can + state_num **trans; /* Transition tables for states that can never accept. If the transitions for a state have not yet been computed, or the state could possibly accept, its entry in this table is NULL. */ - int **realtrans; /* Trans always points to realtrans + 1; this + state_num **realtrans; /* Trans always points to realtrans + 1; this is so trans[-1] can contain NULL. */ - int **fails; /* Transition tables after failing to accept + state_num **fails; /* Transition tables after failing to accept on a state that potentially could do so. */ - int *success; /* Table of acceptance conditions used in + int *success; /* Table of acceptance conditions used in dfaexec and computed in build_state. */ - int *newlines; /* Transitions on newlines. The entry for a + state_num *newlines; /* Transitions on newlines. The entry for a newline in any transition table is always -1 so we can count lines without wasting too many cycles. The transition for a newline is stored separately and handled as a special case. Newline is also used as a sentinel at the end of the buffer. */ - struct dfamust *musts; /* List of strings, at least one of which + struct dfamust *musts; /* List of strings, at least one of which is known to appear in any r.e. matching the dfa. */ }; @@ -389,26 +423,44 @@ struct dfa /* ACCEPTS_IN_CONTEXT returns true if the given state accepts in the specified context. */ -#define ACCEPTS_IN_CONTEXT(prevn, currn, prevl, currl, state, dfa) \ - SUCCEEDS_IN_CONTEXT((dfa).states[state].constraint, \ - prevn, currn, prevl, currl) +#define ACCEPTS_IN_CONTEXT(prev, curr, state, dfa) \ + SUCCEEDS_IN_CONTEXT ((dfa).states[state].constraint, prev, curr) static void dfamust (struct dfa *dfa); static void regexp (void); -#define CALLOC(p, t, n) ((p) = XCALLOC (n, t)) -#define MALLOC(p, t, n) ((p) = XNMALLOC (n, t)) -#define REALLOC(p, t, n) ((p) = xnrealloc (p, n, sizeof (t))) - -/* Reallocate an array of type t if nalloc is too small for index. */ -#define REALLOC_IF_NECESSARY(p, t, nalloc, index) \ - do \ - if ((nalloc) <= (index)) \ - { \ - size_t new_nalloc = (index) + ! (p); \ - (p) = x2nrealloc (p, &new_nalloc, sizeof (t)); \ - (nalloc) = new_nalloc; \ - } \ +/* These two macros are identical to the ones in gnulib's xalloc.h, + except that they not to case the result to "(t *)", and thus may + be used via type-free CALLOC and MALLOC macros. */ +#undef XNMALLOC +#undef XCALLOC + +/* Allocate memory for N elements of type T, with error checking. */ +/* extern t *XNMALLOC (size_t n, typename t); */ +# define XNMALLOC(n, t) \ + (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))) + +/* Allocate memory for N elements of type T, with error checking, + and zero it. */ +/* extern t *XCALLOC (size_t n, typename t); */ +# define XCALLOC(n, t) \ + (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))) + +#define CALLOC(p, n) do { (p) = XCALLOC (n, *(p)); } while (0) +#define MALLOC(p, n) do { (p) = XNMALLOC (n, *(p)); } while (0) +#define REALLOC(p, n) do {(p) = xnrealloc (p, n, sizeof (*(p))); } while (0) + +/* Reallocate an array of type *P if N_ALLOC is <= N_REQUIRED. */ +#define REALLOC_IF_NECESSARY(p, n_alloc, n_required) \ + do \ + { \ + if ((n_alloc) <= (n_required)) \ + { \ + size_t new_n_alloc = (n_required) + !(p); \ + (p) = x2nrealloc (p, &new_n_alloc, sizeof (*(p))); \ + (n_alloc) = new_n_alloc; \ + } \ + } \ while (false) @@ -420,35 +472,72 @@ prtok (token t) char const *s; if (t < 0) - fprintf(stderr, "END"); + fprintf (stderr, "END"); else if (t < NOTCHAR) - fprintf(stderr, "%c", t); + { + int ch = t; + fprintf (stderr, "%c", ch); + } else { switch (t) { - case EMPTY: s = "EMPTY"; break; - case BACKREF: s = "BACKREF"; break; - case BEGLINE: s = "BEGLINE"; break; - case ENDLINE: s = "ENDLINE"; break; - case BEGWORD: s = "BEGWORD"; break; - case ENDWORD: s = "ENDWORD"; break; - case LIMWORD: s = "LIMWORD"; break; - case NOTLIMWORD: s = "NOTLIMWORD"; break; - case QMARK: s = "QMARK"; break; - case STAR: s = "STAR"; break; - case PLUS: s = "PLUS"; break; - case CAT: s = "CAT"; break; - case OR: s = "OR"; break; - case LPAREN: s = "LPAREN"; break; - case RPAREN: s = "RPAREN"; break; -#if MBS_SUPPORT - case ANYCHAR: s = "ANYCHAR"; break; - case MBCSET: s = "MBCSET"; break; -#endif /* MBS_SUPPORT */ - default: s = "CSET"; break; + case EMPTY: + s = "EMPTY"; + break; + case BACKREF: + s = "BACKREF"; + break; + case BEGLINE: + s = "BEGLINE"; + break; + case ENDLINE: + s = "ENDLINE"; + break; + case BEGWORD: + s = "BEGWORD"; + break; + case ENDWORD: + s = "ENDWORD"; + break; + case LIMWORD: + s = "LIMWORD"; + break; + case NOTLIMWORD: + s = "NOTLIMWORD"; + break; + case QMARK: + s = "QMARK"; + break; + case STAR: + s = "STAR"; + break; + case PLUS: + s = "PLUS"; + break; + case CAT: + s = "CAT"; + break; + case OR: + s = "OR"; + break; + case LPAREN: + s = "LPAREN"; + break; + case RPAREN: + s = "RPAREN"; + break; + case ANYCHAR: + s = "ANYCHAR"; + break; + case MBCSET: + s = "MBCSET"; + break; + default: + s = "CSET"; + break; } - fprintf(stderr, "%s", s); + fprintf (stderr, "%s", s); } } #endif /* DEBUG */ @@ -504,17 +593,17 @@ equal (charclass const s1, charclass const s2) static struct dfa *dfa; /* Find the index of charclass s in dfa->charclasses, or allocate a new charclass. */ -static int +static size_t charclass_index (charclass const s) { - int i; + size_t i; for (i = 0; i < dfa->cindex; ++i) - if (equal(s, dfa->charclasses[i])) + if (equal (s, dfa->charclasses[i])) return i; - REALLOC_IF_NECESSARY(dfa->charclasses, charclass, dfa->calloc, dfa->cindex); + REALLOC_IF_NECESSARY (dfa->charclasses, dfa->calloc, dfa->cindex + 1); ++dfa->cindex; - copyset(s, dfa->charclasses[i]); + copyset (s, dfa->charclasses[i]); return i; } @@ -527,14 +616,72 @@ static int case_fold; /* End-of-line byte in data. */ static unsigned char eolbyte; +/* Cache of char-context values. */ +static int sbit[NOTCHAR]; + +/* Set of characters considered letters. */ +static charclass letters; + +/* Set of characters that are newline. */ +static charclass newline; + +/* Add this to the test for whether a byte is word-constituent, since on + BSD-based systems, many values in the 128..255 range are classified as + alphabetic, while on glibc-based systems, they are not. */ +#ifdef __GLIBC__ +# define is_valid_unibyte_character(c) 1 +#else +# define is_valid_unibyte_character(c) (! (MBS_SUPPORT && btowc (c) == WEOF)) +#endif + +/* Return non-zero if C is a 'word-constituent' byte; zero otherwise. */ +#define IS_WORD_CONSTITUENT(C) \ + (is_valid_unibyte_character (C) && (isalnum (C) || (C) == '_')) + +static int +char_context (unsigned char c) +{ + if (c == eolbyte || c == 0) + return CTX_NEWLINE; + if (IS_WORD_CONSTITUENT (c)) + return CTX_LETTER; + return CTX_NONE; +} + +static int +wchar_context (wint_t wc) +{ + if (wc == (wchar_t) eolbyte || wc == 0) + return CTX_NEWLINE; + if (wc == L'_' || iswalnum (wc)) + return CTX_LETTER; + return CTX_NONE; +} + /* Entry point to set syntax options. */ void dfasyntax (reg_syntax_t bits, int fold, unsigned char eol) { + unsigned int i; + syntax_bits_set = 1; syntax_bits = bits; case_fold = fold; eolbyte = eol; + + for (i = 0; i < NOTCHAR; ++i) + { + sbit[i] = char_context (i); + switch (sbit[i]) + { + case CTX_LETTER: + setbit (i, letters); + break; + case CTX_NEWLINE: + setbit (i, newline); + break; + } + } } /* Set a bit in the charclass for the given wchar_t. Do nothing if WC @@ -565,7 +712,13 @@ setbit_c (int b, charclass c) setbit (b, c); } #else -#define setbit_c setbit +# define setbit_c setbit +static inline bool +setbit_wc (wint_t wc, charclass c) +{ + abort (); + /*NOTREACHED*/ return false; +} #endif /* Like setbit_c, but if case is folded, set both cases of a letter. For @@ -575,7 +728,6 @@ setbit_c (int b, charclass c) static void setbit_case_fold_c (int b, charclass c) { -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { wint_t wc = btowc (b); @@ -586,7 +738,6 @@ setbit_case_fold_c (int b, charclass c) setbit_wc (iswupper (wc) ? towlower (wc) : towupper (wc), c); } else -#endif { setbit (b, c); if (case_fold && isalpha (b)) @@ -604,7 +755,7 @@ using_utf8 (void) static int utf8 = -1; if (utf8 == -1) { -#if defined HAVE_LANGINFO_CODESET && defined MBS_SUPPORT +#if defined HAVE_LANGINFO_CODESET && MBS_SUPPORT utf8 = (STREQ (nl_langinfo (CODESET), "UTF-8")); #else utf8 = 0; @@ -619,41 +770,39 @@ using_utf8 (void) reader is referred to the GNU Regex documentation for the meaning of the @#%!@#%^!@ syntax bits. */ -static char const *lexptr; /* Pointer to next input character. */ -static int lexleft; /* Number of characters remaining. */ -static token lasttok; /* Previous token returned; initially END. */ -static int laststart; /* True if we're separated from beginning or (, | +static char const *lexptr; /* Pointer to next input character. */ +static size_t lexleft; /* Number of characters remaining. */ +static token lasttok; /* Previous token returned; initially END. */ +static int laststart; /* True if we're separated from beginning or (, | only by zero-width characters. */ -static int parens; /* Count of outstanding left parens. */ -static int minrep, maxrep; /* Repeat counts for {m,n}. */ -static int hard_LC_COLLATE; /* Nonzero if LC_COLLATE is hard. */ +static size_t parens; /* Count of outstanding left parens. */ +static int minrep, maxrep; /* Repeat counts for {m,n}. */ +static int hard_LC_COLLATE; /* Nonzero if LC_COLLATE is hard. */ -static int cur_mb_len = 1; /* Length of the multibyte representation of +static int cur_mb_len = 1; /* Length of the multibyte representation of wctok. */ -#if MBS_SUPPORT /* These variables are used only if (MB_CUR_MAX > 1). */ -static mbstate_t mbs; /* Mbstate for mbrlen(). */ -static wchar_t wctok; /* Wide character representation of the current +static mbstate_t mbs; /* Mbstate for mbrlen(). */ +static wchar_t wctok; /* Wide character representation of the current multibyte character. */ -static unsigned char *mblen_buf;/* Correspond to the input buffer in dfaexec(). - Each element store the amount of remain - byte of corresponding multibyte character - in the input string. A element's value - is 0 if corresponding character is a - single byte chracter. - e.g. input : 'a', , , - mblen_buf : 0, 3, 2, 1 - */ -static wchar_t *inputwcs; /* Wide character representation of input +static unsigned char *mblen_buf; /* Correspond to the input buffer in dfaexec(). + Each element store the amount of remain + byte of corresponding multibyte character + in the input string. A element's value + is 0 if corresponding character is a + single byte character. + e.g. input : 'a', , , + mblen_buf : 0, 3, 2, 1 + */ +static wchar_t *inputwcs; /* Wide character representation of input string in dfaexec(). The length of this array is same as the length of input string(char array). inputstring[i] is a single-byte char, or 1st byte of a multibyte char. And inputwcs[i] is the codepoint. */ -static unsigned char const *buf_begin; /* reference to begin in dfaexec(). */ -static unsigned char const *buf_end; /* reference to end in dfaexec(). */ -#endif /* MBS_SUPPORT */ +static unsigned char const *buf_begin; /* reference to begin in dfaexec(). */ +static unsigned char const *buf_end; /* reference to end in dfaexec(). */ #if MBS_SUPPORT @@ -670,19 +819,19 @@ static unsigned char const *buf_end; /* reference to end in dfaexec(). */ else \ { \ wchar_t _wc; \ - cur_mb_len = mbrtowc(&_wc, lexptr, lexleft, &mbs); \ + cur_mb_len = mbrtowc (&_wc, lexptr, lexleft, &mbs); \ if (cur_mb_len <= 0) \ { \ cur_mb_len = 1; \ --lexleft; \ - (wc) = (c) = (unsigned char) *lexptr++; \ + (wc) = (c) = to_uchar (*lexptr++); \ } \ else \ { \ lexptr += cur_mb_len; \ lexleft -= cur_mb_len; \ (wc) = _wc; \ - (c) = wctob(wc); \ + (c) = wctob (wc); \ } \ } \ } while(0) @@ -690,8 +839,8 @@ static unsigned char const *buf_end; /* reference to end in dfaexec(). */ # define FETCH(c, eoferr) \ do { \ wint_t wc; \ - FETCH_WC(c, wc, eoferr); \ - } while(0) + FETCH_WC (c, wc, eoferr); \ + } while (0) #else /* Note that characters become unsigned here. */ @@ -704,7 +853,7 @@ static unsigned char const *buf_end; /* reference to end in dfaexec(). */ else \ return lasttok = END; \ } \ - (c) = (unsigned char) *lexptr++; \ + (c) = to_uchar (*lexptr++); \ --lexleft; \ } while(0) @@ -712,34 +861,39 @@ static unsigned char const *buf_end; /* reference to end in dfaexec(). */ #endif /* MBS_SUPPORT */ +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + typedef int predicate (int); /* The following list maps the names of the Posix named character classes to predicate functions that determine whether a given character is in the class. The leading [ has already been eaten by the lexical analyzer. */ -struct dfa_ctype { +struct dfa_ctype +{ const char *name; predicate *func; bool single_byte_only; }; static const struct dfa_ctype prednames[] = { - { "alpha", isalpha, false }, - { "upper", isupper, false }, - { "lower", islower, false }, - { "digit", isdigit, true }, - { "xdigit", isxdigit, true }, - { "space", isspace, false }, - { "punct", ispunct, false }, - { "alnum", isalnum, false }, - { "print", isprint, false }, - { "graph", isgraph, false }, - { "cntrl", iscntrl, false }, - { "blank", isblank, false }, - { NULL, NULL, false } + {"alpha", isalpha, false}, + {"upper", isupper, false}, + {"lower", islower, false}, + {"digit", isdigit, true}, + {"xdigit", isxdigit, true}, + {"space", isspace, false}, + {"punct", ispunct, false}, + {"alnum", isalnum, false}, + {"print", isprint, false}, + {"graph", isgraph, false}, + {"cntrl", iscntrl, false}, + {"blank", isblank, false}, + {NULL, NULL, false} }; -static const struct dfa_ctype * +static const struct dfa_ctype *_GL_ATTRIBUTE_PURE find_pred (const char *str) { unsigned int i; @@ -767,21 +921,22 @@ parse_bracket_exp (void) Bit 3 = includes ranges, char/equiv classes or collation elements. */ int colon_warning_state; -#if MBS_SUPPORT - wint_t wc, wc1, wc2; + wint_t wc; + wint_t wc2; + wint_t wc1 = 0; /* Work area to build a mb_char_classes. */ struct mb_char_classes *work_mbc; - int chars_al, range_sts_al, range_ends_al, ch_classes_al, + size_t chars_al, range_sts_al, range_ends_al, ch_classes_al, equivs_al, coll_elems_al; - chars_al = 1; + chars_al = 0; range_sts_al = range_ends_al = 0; ch_classes_al = equivs_al = coll_elems_al = 0; if (MB_CUR_MAX > 1) { - REALLOC_IF_NECESSARY(dfa->mbcsets, struct mb_char_classes, - dfa->mbcsets_alloc, dfa->nmbcsets + 1); + REALLOC_IF_NECESSARY (dfa->mbcsets, dfa->mbcsets_alloc, + dfa->nmbcsets + 1); /* dfa->multibyte_prop[] hold the index of dfa->mbcsets. We will update dfa->multibyte_prop[] in addtok(), because we can't @@ -793,7 +948,6 @@ parse_bracket_exp (void) } else work_mbc = NULL; -#endif memset (ccl, 0, sizeof ccl); FETCH_WC (c, wc, _("unbalanced [")); @@ -808,7 +962,7 @@ parse_bracket_exp (void) colon_warning_state = (c == ':'); do { - c1 = EOF; /* mark c1 is not initialized". */ + c1 = EOF; /* mark c1 is not initialized". */ colon_warning_state &= ~2; /* Note that if we're looking at some other [:...:] construct, @@ -823,11 +977,8 @@ parse_bracket_exp (void) /* If pattern contains `[[:', `[[.', or `[[='. */ if (c1 == ':' -#if MBS_SUPPORT /* TODO: handle `[[.' and `[[=' also for MB_CUR_MAX == 1. */ - || (MB_CUR_MAX > 1 && (c1 == '.' || c1 == '=')) -#endif - ) + || (MB_CUR_MAX > 1 && (c1 == '.' || c1 == '='))) { size_t len = 0; for (;;) @@ -849,64 +1000,49 @@ parse_bracket_exp (void) /* build character class. */ { char const *class - = (case_fold && (STREQ (str, "upper") - || STREQ (str, "lower")) - ? "alpha" - : str); + = (case_fold && (STREQ (str, "upper") + || STREQ (str, "lower")) ? "alpha" : str); const struct dfa_ctype *pred = find_pred (class); if (!pred) - dfaerror(_("invalid character class")); + dfaerror (_("invalid character class")); -#if MBS_SUPPORT if (MB_CUR_MAX > 1 && !pred->single_byte_only) { /* Store the character class as wctype_t. */ wctype_t wt = wctype (class); - if (ch_classes_al == 0) - MALLOC(work_mbc->ch_classes, wctype_t, ++ch_classes_al); - REALLOC_IF_NECESSARY(work_mbc->ch_classes, wctype_t, - ch_classes_al, - work_mbc->nch_classes + 1); + REALLOC_IF_NECESSARY (work_mbc->ch_classes, + ch_classes_al, + work_mbc->nch_classes + 1); work_mbc->ch_classes[work_mbc->nch_classes++] = wt; } -#endif for (c2 = 0; c2 < NOTCHAR; ++c2) - if (pred->func(c2)) + if (pred->func (c2)) setbit_case_fold_c (c2, ccl); } -#if MBS_SUPPORT - else if (c1 == '=' || c1 == '.') + else if (MBS_SUPPORT && (c1 == '=' || c1 == '.')) { - char *elem; - MALLOC(elem, char, len + 1); - strncpy(elem, str, len + 1); + char *elem = xmemdup (str, len + 1); if (c1 == '=') - /* build equivalent class. */ + /* build equivalence class. */ { - if (equivs_al == 0) - MALLOC(work_mbc->equivs, char*, ++equivs_al); - REALLOC_IF_NECESSARY(work_mbc->equivs, char*, - equivs_al, - work_mbc->nequivs + 1); + REALLOC_IF_NECESSARY (work_mbc->equivs, + equivs_al, work_mbc->nequivs + 1); work_mbc->equivs[work_mbc->nequivs++] = elem; } if (c1 == '.') /* build collating element. */ { - if (coll_elems_al == 0) - MALLOC(work_mbc->coll_elems, char*, ++coll_elems_al); - REALLOC_IF_NECESSARY(work_mbc->coll_elems, char*, - coll_elems_al, - work_mbc->ncoll_elems + 1); + REALLOC_IF_NECESSARY (work_mbc->coll_elems, + coll_elems_al, + work_mbc->ncoll_elems + 1); work_mbc->coll_elems[work_mbc->ncoll_elems++] = elem; } } -#endif colon_warning_state |= 8; /* Fetch new lookahead character. */ @@ -919,15 +1055,15 @@ parse_bracket_exp (void) } if (c == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) - FETCH_WC(c, wc, _("unbalanced [")); + FETCH_WC (c, wc, _("unbalanced [")); if (c1 == EOF) - FETCH_WC(c1, wc1, _("unbalanced [")); + FETCH_WC (c1, wc1, _("unbalanced [")); if (c1 == '-') /* build range characters. */ { - FETCH_WC(c2, wc2, _("unbalanced [")); + FETCH_WC (c2, wc2, _("unbalanced [")); if (c2 == ']') { /* In the case [x-], the - is an ordinary hyphen, @@ -939,43 +1075,35 @@ parse_bracket_exp (void) if (c1 == '-' && c2 != ']') { - if (c2 == '\\' - && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) - FETCH_WC(c2, wc2, _("unbalanced [")); + if (c2 == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) + FETCH_WC (c2, wc2, _("unbalanced [")); -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { /* When case folding map a range, say [m-z] (or even [M-z]) to the pair of ranges, [m-z] [M-Z]. */ - if (range_sts_al == 0) - { - MALLOC(work_mbc->range_sts, wchar_t, ++range_sts_al); - MALLOC(work_mbc->range_ends, wchar_t, ++range_ends_al); - } - REALLOC_IF_NECESSARY(work_mbc->range_sts, wchar_t, - range_sts_al, work_mbc->nranges + 1); - REALLOC_IF_NECESSARY(work_mbc->range_ends, wchar_t, - range_ends_al, work_mbc->nranges + 1); + REALLOC_IF_NECESSARY (work_mbc->range_sts, + range_sts_al, work_mbc->nranges + 1); + REALLOC_IF_NECESSARY (work_mbc->range_ends, + range_ends_al, work_mbc->nranges + 1); work_mbc->range_sts[work_mbc->nranges] = - case_fold ? towlower(wc) : (wchar_t)wc; + case_fold ? towlower (wc) : (wchar_t) wc; work_mbc->range_ends[work_mbc->nranges++] = - case_fold ? towlower(wc2) : (wchar_t)wc2; + case_fold ? towlower (wc2) : (wchar_t) wc2; #ifndef GREP - if (case_fold && (iswalpha(wc) || iswalpha(wc2))) + if (case_fold && (iswalpha (wc) || iswalpha (wc2))) { - REALLOC_IF_NECESSARY(work_mbc->range_sts, wchar_t, - range_sts_al, work_mbc->nranges + 1); - work_mbc->range_sts[work_mbc->nranges] = towupper(wc); - REALLOC_IF_NECESSARY(work_mbc->range_ends, wchar_t, - range_ends_al, work_mbc->nranges + 1); - work_mbc->range_ends[work_mbc->nranges++] = towupper(wc2); + REALLOC_IF_NECESSARY (work_mbc->range_sts, + range_sts_al, work_mbc->nranges + 1); + work_mbc->range_sts[work_mbc->nranges] = towupper (wc); + REALLOC_IF_NECESSARY (work_mbc->range_ends, + range_ends_al, work_mbc->nranges + 1); + work_mbc->range_ends[work_mbc->nranges++] = towupper (wc2); } #endif } else -#endif { c1 = c; if (case_fold) @@ -1006,76 +1134,64 @@ parse_bracket_exp (void) } colon_warning_state |= 8; - FETCH_WC(c1, wc1, _("unbalanced [")); + FETCH_WC (c1, wc1, _("unbalanced [")); continue; } colon_warning_state |= (c == ':') ? 2 : 4; -#if MBS_SUPPORT - if (MB_CUR_MAX > 1) + if (MB_CUR_MAX == 1) { - if (case_fold && iswalpha(wc)) - { - wc = towlower(wc); - if (!setbit_wc (wc, ccl)) - { - REALLOC_IF_NECESSARY(work_mbc->chars, wchar_t, chars_al, - work_mbc->nchars + 1); - work_mbc->chars[work_mbc->nchars++] = wc; - } -#ifdef GREP - continue; -#else - wc = towupper(wc); -#endif - } + setbit_case_fold_c (c, ccl); + continue; + } + + if (case_fold && iswalpha (wc)) + { + wc = towlower (wc); if (!setbit_wc (wc, ccl)) { - REALLOC_IF_NECESSARY(work_mbc->chars, wchar_t, chars_al, - work_mbc->nchars + 1); + REALLOC_IF_NECESSARY (work_mbc->chars, chars_al, + work_mbc->nchars + 1); work_mbc->chars[work_mbc->nchars++] = wc; } - } - else +#ifdef GREP + continue; +#else + wc = towupper (wc); #endif - setbit_case_fold_c (c, ccl); + } + if (!setbit_wc (wc, ccl)) + { + REALLOC_IF_NECESSARY (work_mbc->chars, chars_al, + work_mbc->nchars + 1); + work_mbc->chars[work_mbc->nchars++] = wc; + } } - while (( -#if MBS_SUPPORT - wc = wc1, -#endif - (c = c1) != ']')); + while ((wc = wc1, (c = c1) != ']')); if (colon_warning_state == 7) dfawarn (_("character class syntax is [[:space:]], not [:space:]")); -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { static charclass zeroclass; work_mbc->invert = invert; - work_mbc->cset = equal(ccl, zeroclass) ? -1 : charclass_index(ccl); + work_mbc->cset = equal (ccl, zeroclass) ? -1 : charclass_index (ccl); return MBCSET; } -#endif if (invert) { -#if MBS_SUPPORT - assert(MB_CUR_MAX == 1); -#endif - notset(ccl); + assert (MB_CUR_MAX == 1); + notset (ccl); if (syntax_bits & RE_HAT_LISTS_NOT_NEWLINE) - clrbit(eolbyte, ccl); + clrbit (eolbyte, ccl); } - return CSET + charclass_index(ccl); + return CSET + charclass_index (ccl); } -/* Return non-zero if C is a `word-constituent' byte; zero otherwise. */ -#define IS_WORD_CONSTITUENT(C) (isalnum(C) || (C) == '_') - static token lex (void) { @@ -1092,16 +1208,14 @@ lex (void) "if (backslash) ...". */ for (i = 0; i < 2; ++i) { -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { FETCH_WC (c, wctok, NULL); - if ((int)c == EOF) + if ((int) c == EOF) goto normal_char; } else -#endif /* MBS_SUPPORT */ - FETCH(c, NULL); + FETCH (c, NULL); switch (c) { @@ -1109,7 +1223,7 @@ lex (void) if (backslash) goto normal_char; if (lexleft == 0) - dfaerror(_("unfinished \\ escape")); + dfaerror (_("unfinished \\ escape")); backslash = 1; break; @@ -1117,9 +1231,7 @@ lex (void) if (backslash) goto normal_char; if (syntax_bits & RE_CONTEXT_INDEP_ANCHORS - || lasttok == END - || lasttok == LPAREN - || lasttok == OR) + || lasttok == END || lasttok == LPAREN || lasttok == OR) return lasttok = BEGLINE; goto normal_char; @@ -1157,12 +1269,12 @@ lex (void) case '`': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) - return lasttok = BEGLINE; /* FIXME: should be beginning of string */ + return lasttok = BEGLINE; /* FIXME: should be beginning of string */ goto normal_char; case '\'': if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) - return lasttok = ENDLINE; /* FIXME: should be end of string */ + return lasttok = ENDLINE; /* FIXME: should be end of string */ goto normal_char; case '<': @@ -1218,73 +1330,53 @@ lex (void) if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart) goto normal_char; - if (syntax_bits & RE_NO_BK_BRACES) - { - /* Scan ahead for a valid interval; if it's not valid, - treat it as a literal '{'. */ - int lo = -1, hi = -1; - char const *p = lexptr; - char const *lim = p + lexleft; - for (; p != lim && ISASCIIDIGIT (*p); p++) - lo = (lo < 0 ? 0 : lo * 10) + *p - '0'; - if (p != lim && *p == ',') - while (++p != lim && ISASCIIDIGIT (*p)) - hi = (hi < 0 ? 0 : hi * 10) + *p - '0'; - else - hi = lo; - if (p == lim || *p != '}' - || lo < 0 || RE_DUP_MAX < hi || (0 <= hi && hi < lo)) - goto normal_char; - } - - minrep = 0; /* Cases: {M} - exact count {M,} - minimum count, maximum is infinity + {,N} - 0 through N + {,} - 0 to infinity (same as '*') {M,N} - M through N */ - FETCH(c, _("unfinished repeat count")); - if (ISASCIIDIGIT (c)) - { - minrep = c - '0'; - for (;;) - { - FETCH(c, _("unfinished repeat count")); - if (! ISASCIIDIGIT (c)) - break; - minrep = 10 * minrep + c - '0'; - } - } - else - dfaerror(_("malformed repeat count")); - if (c == ',') - { - FETCH (c, _("unfinished repeat count")); - if (! ISASCIIDIGIT (c)) - maxrep = -1; - else - { - maxrep = c - '0'; - for (;;) - { - FETCH (c, _("unfinished repeat count")); - if (! ISASCIIDIGIT (c)) - break; - maxrep = 10 * maxrep + c - '0'; - } - if (0 <= maxrep && maxrep < minrep) - dfaerror (_("malformed repeat count")); - } - } - else - maxrep = minrep; - if (!(syntax_bits & RE_NO_BK_BRACES)) - { - if (c != '\\') - dfaerror(_("malformed repeat count")); - FETCH(c, _("unfinished repeat count")); - } - if (c != '}') - dfaerror(_("malformed repeat count")); + { + char const *p = lexptr; + char const *lim = p + lexleft; + minrep = maxrep = -1; + for (; p != lim && ISASCIIDIGIT (*p); p++) + { + if (minrep < 0) + minrep = *p - '0'; + else + minrep = MIN (RE_DUP_MAX + 1, minrep * 10 + *p - '0'); + } + if (p != lim) + { + if (*p != ',') + maxrep = minrep; + else + { + if (minrep < 0) + minrep = 0; + while (++p != lim && ISASCIIDIGIT (*p)) + { + if (maxrep < 0) + maxrep = *p - '0'; + else + maxrep = MIN (RE_DUP_MAX + 1, maxrep * 10 + *p - '0'); + } + } + } + if (! ((! backslash || (p != lim && *p++ == '\\')) + && p != lim && *p++ == '}' + && 0 <= minrep && (maxrep < 0 || minrep <= maxrep))) + { + if (syntax_bits & RE_INVALID_INTERVAL_ORD) + goto normal_char; + dfaerror (_("Invalid content of \\{\\}")); + } + if (RE_DUP_MAX < maxrep) + dfaerror (_("Regular expression too big")); + lexptr = p; + lexleft = lim - p; + } laststart = 0; return lasttok = REPMN; @@ -1298,8 +1390,7 @@ lex (void) case '\n': if (syntax_bits & RE_LIMITED_OPS - || backslash - || !(syntax_bits & RE_NEWLINE_ALT)) + || backslash || !(syntax_bits & RE_NEWLINE_ALT)) goto normal_char; laststart = 1; return lasttok = OR; @@ -1323,7 +1414,6 @@ lex (void) case '.': if (backslash) goto normal_char; -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { /* In multibyte environment period must match with a single @@ -1331,63 +1421,60 @@ lex (void) laststart = 0; return lasttok = ANYCHAR; } -#endif /* MBS_SUPPORT */ - zeroset(ccl); - notset(ccl); + zeroset (ccl); + notset (ccl); if (!(syntax_bits & RE_DOT_NEWLINE)) - clrbit(eolbyte, ccl); + clrbit (eolbyte, ccl); if (syntax_bits & RE_DOT_NOT_NULL) - clrbit('\0', ccl); + clrbit ('\0', ccl); laststart = 0; - return lasttok = CSET + charclass_index(ccl); + return lasttok = CSET + charclass_index (ccl); case 's': case 'S': if (!backslash || (syntax_bits & RE_NO_GNU_OPS)) goto normal_char; - zeroset(ccl); + zeroset (ccl); for (c2 = 0; c2 < NOTCHAR; ++c2) - if (isspace(c2)) - setbit(c2, ccl); + if (isspace (c2)) + setbit (c2, ccl); if (c == 'S') - notset(ccl); + notset (ccl); laststart = 0; - return lasttok = CSET + charclass_index(ccl); + return lasttok = CSET + charclass_index (ccl); case 'w': case 'W': if (!backslash || (syntax_bits & RE_NO_GNU_OPS)) goto normal_char; - zeroset(ccl); + zeroset (ccl); for (c2 = 0; c2 < NOTCHAR; ++c2) - if (IS_WORD_CONSTITUENT(c2)) - setbit(c2, ccl); + if (IS_WORD_CONSTITUENT (c2)) + setbit (c2, ccl); if (c == 'W') - notset(ccl); + notset (ccl); laststart = 0; - return lasttok = CSET + charclass_index(ccl); + return lasttok = CSET + charclass_index (ccl); case '[': if (backslash) goto normal_char; laststart = 0; - return lasttok = parse_bracket_exp(); + return lasttok = parse_bracket_exp (); default: normal_char: laststart = 0; -#if MBS_SUPPORT /* For multibyte character sets, folding is done in atom. Always return WCHAR. */ if (MB_CUR_MAX > 1) return lasttok = WCHAR; -#endif - if (case_fold && isalpha(c)) + if (case_fold && isalpha (c)) { - zeroset(ccl); + zeroset (ccl); setbit_case_fold_c (c, ccl); - return lasttok = CSET + charclass_index(ccl); + return lasttok = CSET + charclass_index (ccl); } return lasttok = c; @@ -1396,14 +1483,14 @@ lex (void) /* The above loop should consume at most a backslash and some other character. */ - abort(); - return END; /* keeps pedantic compilers happy. */ + abort (); + return END; /* keeps pedantic compilers happy. */ } /* Recursive descent parser for regular expressions. */ -static token tok; /* Lookahead token. */ -static int depth; /* Current depth of a hypothetical stack +static token tok; /* Lookahead token. */ +static size_t depth; /* Current depth of a hypothetical stack holding deferred productions. This is used to determine the depth that will be required of the real stack later on in @@ -1412,18 +1499,14 @@ static int depth; /* Current depth of a hypothetical stack static void addtok_mb (token t, int mbprop) { -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { - REALLOC_IF_NECESSARY(dfa->multibyte_prop, int, dfa->nmultibyte_prop, - dfa->tindex); + REALLOC_IF_NECESSARY (dfa->multibyte_prop, dfa->nmultibyte_prop, + dfa->tindex + 1); dfa->multibyte_prop[dfa->tindex] = mbprop; } -#else - (void) mbprop; -#endif - REALLOC_IF_NECESSARY(dfa->tokens, token, dfa->talloc, dfa->tindex); + REALLOC_IF_NECESSARY (dfa->tokens, dfa->talloc, dfa->tindex + 1); dfa->tokens[dfa->tindex++] = t; switch (t) @@ -1455,7 +1538,6 @@ static void addtok_wc (wint_t wc); static void addtok (token t) { -#if MBS_SUPPORT if (MB_CUR_MAX > 1 && t == MBCSET) { bool need_or = false; @@ -1465,7 +1547,7 @@ addtok (token t) This does not require UTF-8. */ if (!work_mbc->invert) { - int i; + size_t i; for (i = 0; i < work_mbc->nchars; i++) { addtok_wc (work_mbc->chars[i]); @@ -1478,12 +1560,11 @@ addtok (token t) /* UTF-8 allows treating a simple, non-inverted MBCSET like a CSET. */ if (work_mbc->invert - || (!using_utf8() && work_mbc->cset != -1) + || (!using_utf8 () && work_mbc->cset != -1) || work_mbc->nchars != 0 || work_mbc->nch_classes != 0 || work_mbc->nranges != 0 - || work_mbc->nequivs != 0 - || work_mbc->ncoll_elems != 0) + || work_mbc->nequivs != 0 || work_mbc->ncoll_elems != 0) { addtok_mb (MBCSET, ((dfa->nmbcsets - 1) << 2) + 3); if (need_or) @@ -1503,8 +1584,9 @@ addtok (token t) } } else -#endif - addtok_mb (t, 3); + { + addtok_mb (t, 3); + } } #if MBS_SUPPORT @@ -1529,23 +1611,30 @@ addtok_wc (wint_t wc) if (cur_mb_len <= 0) buf[0] = 0; - addtok_mb(buf[0], cur_mb_len == 1 ? 3 : 1); + addtok_mb (buf[0], cur_mb_len == 1 ? 3 : 1); for (i = 1; i < cur_mb_len; i++) { - addtok_mb(buf[i], i == cur_mb_len - 1 ? 2 : 0); - addtok(CAT); + addtok_mb (buf[i], i == cur_mb_len - 1 ? 2 : 0); + addtok (CAT); } } +#else +static void +addtok_wc (wint_t wc) +{ +} +#endif static void add_utf8_anychar (void) { +#if MBS_SUPPORT static const charclass utf8_classes[5] = { - { 0, 0, 0, 0, ~0, ~0, 0, 0 }, /* 80-bf: non-lead bytes */ - { ~0, ~0, ~0, ~0, 0, 0, 0, 0 }, /* 00-7f: 1-byte sequence */ - { 0, 0, 0, 0, 0, 0, 0xfffffffcU, 0 }, /* c2-df: 2-byte sequence */ - { 0, 0, 0, 0, 0, 0, 0, 0xffff }, /* e0-ef: 3-byte sequence */ - { 0, 0, 0, 0, 0, 0, 0, 0xff0000 } /* f0-f7: 4-byte sequence */ + {0, 0, 0, 0, ~0, ~0, 0, 0}, /* 80-bf: non-lead bytes */ + {~0, ~0, ~0, ~0, 0, 0, 0, 0}, /* 00-7f: 1-byte sequence */ + {0, 0, 0, 0, 0, 0, 0xfffffffcU, 0}, /* c2-df: 2-byte sequence */ + {0, 0, 0, 0, 0, 0, 0, 0xffff}, /* e0-ef: 3-byte sequence */ + {0, 0, 0, 0, 0, 0, 0, 0xff0000} /* f0-f7: 4-byte sequence */ }; const unsigned int n = sizeof (utf8_classes) / sizeof (utf8_classes[0]); unsigned int i; @@ -1555,7 +1644,7 @@ add_utf8_anychar (void) for (i = 0; i < n; i++) { charclass c; - memcpy (c, utf8_classes[i], sizeof c); + copyset (utf8_classes[i], c); if (i == 1) { if (!(syntax_bits & RE_DOT_NEWLINE)) @@ -1563,15 +1652,15 @@ add_utf8_anychar (void) if (syntax_bits & RE_DOT_NOT_NULL) clrbit ('\0', c); } - dfa->utf8_anychar_classes[i] = CSET + charclass_index(c); + dfa->utf8_anychar_classes[i] = CSET + charclass_index (c); } /* A valid UTF-8 character is - ([0x00-0x7f] - |[0xc2-0xdf][0x80-0xbf] - |[0xe0-0xef[0x80-0xbf][0x80-0xbf] - |[0xf0-f7][0x80-0xbf][0x80-0xbf][0x80-0xbf]) + ([0x00-0x7f] + |[0xc2-0xdf][0x80-0xbf] + |[0xe0-0xef[0x80-0xbf][0x80-0xbf] + |[0xf0-f7][0x80-0xbf][0x80-0xbf][0x80-0xbf]) which I'll write more concisely "B|CA|DAA|EAAA". Factor the [0x00-0x7f] and you get "B|(C|(D|EA)A)A". And since the token buffer is in reverse @@ -1584,8 +1673,8 @@ add_utf8_anychar (void) addtok (CAT); addtok (OR); } -} #endif +} /* The grammar understood by the parser is as follows. @@ -1629,35 +1718,31 @@ atom (void) { /* empty */ } -#if MBS_SUPPORT - else if (tok == WCHAR) + else if (MBS_SUPPORT && tok == WCHAR) { - addtok_wc (case_fold ? towlower(wctok) : wctok); + addtok_wc (case_fold ? towlower (wctok) : wctok); #ifndef GREP - if (case_fold && iswalpha(wctok)) + if (case_fold && iswalpha (wctok)) { - addtok_wc (towupper(wctok)); + addtok_wc (towupper (wctok)); addtok (OR); } #endif - tok = lex(); + tok = lex (); } - - else if (tok == ANYCHAR && using_utf8()) + else if (MBS_SUPPORT && tok == ANYCHAR && using_utf8 ()) { /* For UTF-8 expand the period to a series of CSETs that define a valid UTF-8 character. This avoids using the slow multibyte path. I'm pretty sure it would be both profitable and correct to do it for any encoding; however, the optimization must be done manually as - it is done above in add_utf8_anychar. So, let's start with + it is done above in add_utf8_anychar. So, let's start with UTF-8: it is the most used, and the structure of the encoding makes the correctness more obvious. */ - add_utf8_anychar(); - tok = lex(); + add_utf8_anychar (); + tok = lex (); } -#endif /* MBS_SUPPORT */ - else if ((tok >= 0 && tok < NOTCHAR) || tok >= CSET || tok == BACKREF || tok == BEGLINE || tok == ENDLINE || tok == BEGWORD #if MBS_SUPPORT @@ -1665,26 +1750,26 @@ atom (void) #endif /* MBS_SUPPORT */ || tok == ENDWORD || tok == LIMWORD || tok == NOTLIMWORD) { - addtok(tok); - tok = lex(); + addtok (tok); + tok = lex (); } else if (tok == LPAREN) { - tok = lex(); - regexp(); + tok = lex (); + regexp (); if (tok != RPAREN) - dfaerror(_("unbalanced (")); - tok = lex(); + dfaerror (_("unbalanced (")); + tok = lex (); } else - addtok(EMPTY); + addtok (EMPTY); } /* Return the number of tokens in the given subexpression. */ -static int -nsubtoks (int tindex) +static size_t _GL_ATTRIBUTE_PURE +nsubtoks (size_t tindex) { - int ntoks1; + size_t ntoks1; switch (dfa->tokens[tindex - 1]) { @@ -1693,92 +1778,91 @@ nsubtoks (int tindex) case QMARK: case STAR: case PLUS: - return 1 + nsubtoks(tindex - 1); + return 1 + nsubtoks (tindex - 1); case CAT: case OR: - ntoks1 = nsubtoks(tindex - 1); - return 1 + ntoks1 + nsubtoks(tindex - 1 - ntoks1); + ntoks1 = nsubtoks (tindex - 1); + return 1 + ntoks1 + nsubtoks (tindex - 1 - ntoks1); } } /* Copy the given subexpression to the top of the tree. */ static void -copytoks (int tindex, int ntokens) +copytoks (size_t tindex, size_t ntokens) { - int i; + size_t i; for (i = 0; i < ntokens; ++i) { - addtok(dfa->tokens[tindex + i]); -#if MBS_SUPPORT + addtok (dfa->tokens[tindex + i]); /* Update index into multibyte csets. */ if (MB_CUR_MAX > 1 && dfa->tokens[tindex + i] == MBCSET) dfa->multibyte_prop[dfa->tindex - 1] = dfa->multibyte_prop[tindex + i]; -#endif } } static void closure (void) { - int tindex, ntokens, i; + int i; + size_t tindex, ntokens; - atom(); + atom (); while (tok == QMARK || tok == STAR || tok == PLUS || tok == REPMN) if (tok == REPMN && (minrep || maxrep)) { - ntokens = nsubtoks(dfa->tindex); + ntokens = nsubtoks (dfa->tindex); tindex = dfa->tindex - ntokens; if (maxrep < 0) - addtok(PLUS); + addtok (PLUS); if (minrep == 0) - addtok(QMARK); + addtok (QMARK); for (i = 1; i < minrep; ++i) { - copytoks(tindex, ntokens); - addtok(CAT); + copytoks (tindex, ntokens); + addtok (CAT); } for (; i < maxrep; ++i) { - copytoks(tindex, ntokens); - addtok(QMARK); - addtok(CAT); + copytoks (tindex, ntokens); + addtok (QMARK); + addtok (CAT); } - tok = lex(); + tok = lex (); } else if (tok == REPMN) { - dfa->tindex -= nsubtoks(dfa->tindex); - tok = lex(); - closure(); + dfa->tindex -= nsubtoks (dfa->tindex); + tok = lex (); + closure (); } else { - addtok(tok); - tok = lex(); + addtok (tok); + tok = lex (); } } static void branch (void) { - closure(); + closure (); while (tok != RPAREN && tok != OR && tok >= 0) { - closure(); - addtok(CAT); + closure (); + addtok (CAT); } } static void regexp (void) { - branch(); + branch (); while (tok == OR) { - tok = lex(); - branch(); - addtok(OR); + tok = lex (); + branch (); + addtok (OR); } } @@ -1797,30 +1881,28 @@ dfaparse (char const *s, size_t len, struct dfa *d) #ifdef LC_COLLATE hard_LC_COLLATE = hard_locale (LC_COLLATE); #endif -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { cur_mb_len = 0; - memset(&mbs, 0, sizeof mbs); + memset (&mbs, 0, sizeof mbs); } -#endif /* MBS_SUPPORT */ - if (! syntax_bits_set) - dfaerror(_("no syntax specified")); + if (!syntax_bits_set) + dfaerror (_("no syntax specified")); - tok = lex(); + tok = lex (); depth = d->depth; - regexp(); + regexp (); if (tok != END) - dfaerror(_("unbalanced )")); + dfaerror (_("unbalanced )")); - addtok(END - d->nregexps); - addtok(CAT); + addtok (END - d->nregexps); + addtok (CAT); if (d->nregexps) - addtok(OR); + addtok (OR); ++d->nregexps; } @@ -1829,52 +1911,61 @@ dfaparse (char const *s, size_t len, struct dfa *d) /* Copy one set to another; the destination must be large enough. */ static void -copy (position_set const *src, position_set *dst) +copy (position_set const *src, position_set * dst) { - int i; - - for (i = 0; i < src->nelem; ++i) - dst->elems[i] = src->elems[i]; + REALLOC_IF_NECESSARY (dst->elems, dst->alloc, src->nelem); + memcpy (dst->elems, src->elems, sizeof (dst->elems[0]) * src->nelem); dst->nelem = src->nelem; } -/* Insert a position in a set. Position sets are maintained in sorted - order according to index. If position already exists in the set with - the same index then their constraints are logically or'd together. +static void +alloc_position_set (position_set * s, size_t size) +{ + MALLOC (s->elems, size); + s->alloc = size; + s->nelem = 0; +} + +/* Insert position P in set S. S is maintained in sorted order on + decreasing index. If there is already an entry in S with P.index + then merge (logically-OR) P's constraints into the one in S. S->elems must point to an array large enough to hold the resulting set. */ static void -insert (position p, position_set *s) +insert (position p, position_set * s) { - int count = s->nelem; - int lo = 0, hi = count; + size_t count = s->nelem; + size_t lo = 0, hi = count; + size_t i; while (lo < hi) { - int mid = ((unsigned) lo + (unsigned) hi) >> 1; - if (s->elems[mid].index < p.index) + size_t mid = (lo + hi) >> 1; + if (s->elems[mid].index > p.index) lo = mid + 1; else hi = mid; } if (lo < count && p.index == s->elems[lo].index) - s->elems[lo].constraint |= p.constraint; - else { - int i; - for (i = count; i > lo; i--) - s->elems[i] = s->elems[i - 1]; - s->elems[lo] = p; - ++s->nelem; + s->elems[lo].constraint |= p.constraint; + return; } + + REALLOC_IF_NECESSARY (s->elems, s->alloc, count + 1); + for (i = count; i > lo; i--) + s->elems[i] = s->elems[i - 1]; + s->elems[lo] = p; + ++s->nelem; } /* Merge two sets of positions into a third. The result is exactly as if the positions of both sets were inserted into an initially empty set. */ static void -merge (position_set const *s1, position_set const *s2, position_set *m) +merge (position_set const *s1, position_set const *s2, position_set * m) { - int i = 0, j = 0; + size_t i = 0, j = 0; + REALLOC_IF_NECESSARY (m->elems, m->alloc, s1->nelem + s2->nelem); m->nelem = 0; while (i < s1->nelem && j < s2->nelem) if (s1->elems[i].index > s2->elems[j].index) @@ -1894,9 +1985,9 @@ merge (position_set const *s1, position_set const *s2, position_set *m) /* Delete a position from a set. */ static void -delete (position p, position_set *s) +delete (position p, position_set * s) { - int i; + size_t i; for (i = 0; i < s->nelem; ++i) if (p.index == s->elems[i].index) @@ -1908,17 +1999,13 @@ delete (position p, position_set *s) /* Find the index of the state corresponding to the given position set with the given preceding context, or create a new state if there is no such - state. Newline and letter tell whether we got here on a newline or - letter, respectively. */ -static int -state_index (struct dfa *d, position_set const *s, int newline, int letter) + state. Context tells whether we got here on a newline or letter. */ +static state_num +state_index (struct dfa *d, position_set const *s, int context) { - int hash = 0; + size_t hash = 0; int constraint; - int i, j; - - newline = newline ? 1 : 0; - letter = letter ? 1 : 0; + state_num i, j; for (i = 0; i < s->nelem; ++i) hash ^= s->elems[i].index + s->elems[i].constraint; @@ -1927,7 +2014,7 @@ state_index (struct dfa *d, position_set const *s, int newline, int letter) for (i = 0; i < d->sindex; ++i) { if (hash != d->states[i].hash || s->nelem != d->states[i].elems.nelem - || newline != d->states[i].newline || letter != d->states[i].letter) + || context != d->states[i].context) continue; for (j = 0; j < s->nelem; ++j) if (s->elems[j].constraint @@ -1939,29 +2026,26 @@ state_index (struct dfa *d, position_set const *s, int newline, int letter) } /* We'll have to create a new state. */ - REALLOC_IF_NECESSARY(d->states, dfa_state, d->salloc, d->sindex); + REALLOC_IF_NECESSARY (d->states, d->salloc, d->sindex + 1); d->states[i].hash = hash; - MALLOC(d->states[i].elems.elems, position, s->nelem); - copy(s, &d->states[i].elems); - d->states[i].newline = newline; - d->states[i].letter = letter; + alloc_position_set (&d->states[i].elems, s->nelem); + copy (s, &d->states[i].elems); + d->states[i].context = context; d->states[i].backref = 0; d->states[i].constraint = 0; d->states[i].first_end = 0; -#if MBS_SUPPORT - d->states[i].mbps.nelem = 0; - d->states[i].mbps.elems = NULL; -#endif + if (MBS_SUPPORT) + { + d->states[i].mbps.nelem = 0; + d->states[i].mbps.elems = NULL; + } for (j = 0; j < s->nelem; ++j) if (d->tokens[s->elems[j].index] < 0) { constraint = s->elems[j].constraint; - if (SUCCEEDS_IN_CONTEXT(constraint, newline, 0, letter, 0) - || SUCCEEDS_IN_CONTEXT(constraint, newline, 0, letter, 1) - || SUCCEEDS_IN_CONTEXT(constraint, newline, 1, letter, 0) - || SUCCEEDS_IN_CONTEXT(constraint, newline, 1, letter, 1)) + if (SUCCEEDS_IN_CONTEXT (constraint, context, CTX_ANY)) d->states[i].constraint |= constraint; - if (! d->states[i].first_end) + if (!d->states[i].first_end) d->states[i].first_end = d->tokens[s->elems[j].index]; } else if (d->tokens[s->elems[j].index] == BACKREF) @@ -1981,13 +2065,13 @@ state_index (struct dfa *d, position_set const *s, int newline, int letter) constraint. Repeat exhaustively until no funny positions are left. S->elems must be large enough to hold the result. */ static void -epsclosure (position_set *s, struct dfa const *d) +epsclosure (position_set * s, struct dfa const *d) { - int i, j; - char *visited; /* array of booleans, enough to use char, not int */ + size_t i, j; + char *visited; /* array of booleans, enough to use char, not int */ position p, old; - CALLOC(visited, char, d->tindex); + CALLOC (visited, d->tindex); for (i = 0; i < s->nelem; ++i) if (d->tokens[s->elems[i].index] >= NOTCHAR @@ -2000,7 +2084,7 @@ epsclosure (position_set *s, struct dfa const *d) { old = s->elems[i]; p.constraint = old.constraint; - delete(s->elems[i], s); + delete (s->elems[i], s); if (visited[old.index]) { --i; @@ -2033,15 +2117,62 @@ epsclosure (position_set *s, struct dfa const *d) for (j = 0; j < d->follows[old.index].nelem; ++j) { p.index = d->follows[old.index].elems[j].index; - insert(p, s); + insert (p, s); } /* Force rescan to start at the beginning. */ i = -1; } - free(visited); + free (visited); } +/* Returns the set of contexts for which there is at least one + character included in C. */ + +static int +charclass_context (charclass c) +{ + int context = 0; + unsigned int j; + + if (tstbit (eolbyte, c)) + context |= CTX_NEWLINE; + + for (j = 0; j < CHARCLASS_INTS; ++j) + { + if (c[j] & letters[j]) + context |= CTX_LETTER; + if (c[j] & ~(letters[j] | newline[j])) + context |= CTX_NONE; + } + + return context; +} + +/* Returns the contexts on which the position set S depends. Each context + in the set of returned contexts (let's call it SC) may have a different + follow set than other contexts in SC, and also different from the + follow set of the complement set (sc ^ CTX_ANY). However, all contexts + in the complement set will have the same follow set. */ + +static int _GL_ATTRIBUTE_PURE +state_separate_contexts (position_set const *s) +{ + int separate_contexts = 0; + size_t j; + + for (j = 0; j < s->nelem; ++j) + { + if (PREV_NEWLINE_DEPENDENT (s->elems[j].constraint)) + separate_contexts |= CTX_NEWLINE; + if (PREV_LETTER_DEPENDENT (s->elems[j].constraint)) + separate_contexts |= CTX_LETTER; + } + + return separate_contexts; +} + + /* Perform bottom-up analysis on the parse tree, computing various functions. Note that at this point, we're pretending constructs like \< are real characters rather than constraints on what can follow them. @@ -2097,235 +2228,221 @@ epsclosure (position_set *s, struct dfa const *d) void dfaanalyze (struct dfa *d, int searchflag) { - int *nullable; /* Nullable stack. */ - int *nfirstpos; /* Element count stack for firstpos sets. */ - position *firstpos; /* Array where firstpos elements are stored. */ - int *nlastpos; /* Element count stack for lastpos sets. */ - position *lastpos; /* Array where lastpos elements are stored. */ - int *nalloc; /* Sizes of arrays allocated to follow sets. */ - position_set tmp; /* Temporary set for merging sets. */ - position_set merged; /* Result of merging sets. */ - int wants_newline; /* True if some position wants newline info. */ + int *nullable; /* Nullable stack. */ + size_t *nfirstpos; /* Element count stack for firstpos sets. */ + position *firstpos; /* Array where firstpos elements are stored. */ + size_t *nlastpos; /* Element count stack for lastpos sets. */ + position *lastpos; /* Array where lastpos elements are stored. */ + position_set tmp; /* Temporary set for merging sets. */ + position_set merged; /* Result of merging sets. */ + int separate_contexts; /* Context wanted by some position. */ int *o_nullable; - int *o_nfirst, *o_nlast; + size_t *o_nfirst, *o_nlast; position *o_firstpos, *o_lastpos; - int i, j; + size_t i, j; position *pos; #ifdef DEBUG - fprintf(stderr, "dfaanalyze:\n"); + fprintf (stderr, "dfaanalyze:\n"); for (i = 0; i < d->tindex; ++i) { - fprintf(stderr, " %d:", i); - prtok(d->tokens[i]); + fprintf (stderr, " %zd:", i); + prtok (d->tokens[i]); } - putc('\n', stderr); + putc ('\n', stderr); #endif d->searchflag = searchflag; - MALLOC(nullable, int, d->depth); + MALLOC (nullable, d->depth); o_nullable = nullable; - MALLOC(nfirstpos, int, d->depth); + MALLOC (nfirstpos, d->depth); o_nfirst = nfirstpos; - MALLOC(firstpos, position, d->nleaves); + MALLOC (firstpos, d->nleaves); o_firstpos = firstpos, firstpos += d->nleaves; - MALLOC(nlastpos, int, d->depth); + MALLOC (nlastpos, d->depth); o_nlast = nlastpos; - MALLOC(lastpos, position, d->nleaves); + MALLOC (lastpos, d->nleaves); o_lastpos = lastpos, lastpos += d->nleaves; - CALLOC(nalloc, int, d->tindex); - MALLOC(merged.elems, position, 2 * d->nleaves); + alloc_position_set (&merged, d->nleaves); - CALLOC(d->follows, position_set, d->tindex); + CALLOC (d->follows, d->tindex); for (i = 0; i < d->tindex; ++i) -#ifdef DEBUG - { /* Nonsyntactic #ifdef goo... */ -#endif - switch (d->tokens[i]) - { - case EMPTY: - /* The empty set is nullable. */ - *nullable++ = 1; + { + switch (d->tokens[i]) + { + case EMPTY: + /* The empty set is nullable. */ + *nullable++ = 1; - /* The firstpos and lastpos of the empty leaf are both empty. */ - *nfirstpos++ = *nlastpos++ = 0; - break; + /* The firstpos and lastpos of the empty leaf are both empty. */ + *nfirstpos++ = *nlastpos++ = 0; + break; - case STAR: - case PLUS: - /* Every element in the firstpos of the argument is in the follow - of every element in the lastpos. */ - tmp.nelem = nfirstpos[-1]; - tmp.elems = firstpos; - pos = lastpos; - for (j = 0; j < nlastpos[-1]; ++j) - { - merge(&tmp, &d->follows[pos[j].index], &merged); - REALLOC_IF_NECESSARY(d->follows[pos[j].index].elems, position, - nalloc[pos[j].index], merged.nelem - 1); - copy(&merged, &d->follows[pos[j].index]); - } + case STAR: + case PLUS: + /* Every element in the firstpos of the argument is in the follow + of every element in the lastpos. */ + tmp.nelem = nfirstpos[-1]; + tmp.elems = firstpos; + pos = lastpos; + for (j = 0; j < nlastpos[-1]; ++j) + { + merge (&tmp, &d->follows[pos[j].index], &merged); + copy (&merged, &d->follows[pos[j].index]); + } - case QMARK: - /* A QMARK or STAR node is automatically nullable. */ - if (d->tokens[i] != PLUS) - nullable[-1] = 1; - break; + case QMARK: + /* A QMARK or STAR node is automatically nullable. */ + if (d->tokens[i] != PLUS) + nullable[-1] = 1; + break; - case CAT: - /* Every element in the firstpos of the second argument is in the - follow of every element in the lastpos of the first argument. */ - tmp.nelem = nfirstpos[-1]; - tmp.elems = firstpos; - pos = lastpos + nlastpos[-1]; - for (j = 0; j < nlastpos[-2]; ++j) - { - merge(&tmp, &d->follows[pos[j].index], &merged); - REALLOC_IF_NECESSARY(d->follows[pos[j].index].elems, position, - nalloc[pos[j].index], merged.nelem - 1); - copy(&merged, &d->follows[pos[j].index]); - } + case CAT: + /* Every element in the firstpos of the second argument is in the + follow of every element in the lastpos of the first argument. */ + tmp.nelem = nfirstpos[-1]; + tmp.elems = firstpos; + pos = lastpos + nlastpos[-1]; + for (j = 0; j < nlastpos[-2]; ++j) + { + merge (&tmp, &d->follows[pos[j].index], &merged); + copy (&merged, &d->follows[pos[j].index]); + } - /* The firstpos of a CAT node is the firstpos of the first argument, - union that of the second argument if the first is nullable. */ - if (nullable[-2]) - nfirstpos[-2] += nfirstpos[-1]; - else - firstpos += nfirstpos[-1]; - --nfirstpos; + /* The firstpos of a CAT node is the firstpos of the first argument, + union that of the second argument if the first is nullable. */ + if (nullable[-2]) + nfirstpos[-2] += nfirstpos[-1]; + else + firstpos += nfirstpos[-1]; + --nfirstpos; - /* The lastpos of a CAT node is the lastpos of the second argument, - union that of the first argument if the second is nullable. */ - if (nullable[-1]) - nlastpos[-2] += nlastpos[-1]; - else - { - pos = lastpos + nlastpos[-2]; - for (j = nlastpos[-1] - 1; j >= 0; --j) - pos[j] = lastpos[j]; - lastpos += nlastpos[-2]; - nlastpos[-2] = nlastpos[-1]; - } - --nlastpos; + /* The lastpos of a CAT node is the lastpos of the second argument, + union that of the first argument if the second is nullable. */ + if (nullable[-1]) + nlastpos[-2] += nlastpos[-1]; + else + { + pos = lastpos + nlastpos[-2]; + for (j = nlastpos[-1]; j-- > 0;) + pos[j] = lastpos[j]; + lastpos += nlastpos[-2]; + nlastpos[-2] = nlastpos[-1]; + } + --nlastpos; - /* A CAT node is nullable if both arguments are nullable. */ - nullable[-2] = nullable[-1] && nullable[-2]; - --nullable; - break; + /* A CAT node is nullable if both arguments are nullable. */ + nullable[-2] = nullable[-1] && nullable[-2]; + --nullable; + break; - case OR: - /* The firstpos is the union of the firstpos of each argument. */ - nfirstpos[-2] += nfirstpos[-1]; - --nfirstpos; + case OR: + /* The firstpos is the union of the firstpos of each argument. */ + nfirstpos[-2] += nfirstpos[-1]; + --nfirstpos; - /* The lastpos is the union of the lastpos of each argument. */ - nlastpos[-2] += nlastpos[-1]; - --nlastpos; + /* The lastpos is the union of the lastpos of each argument. */ + nlastpos[-2] += nlastpos[-1]; + --nlastpos; - /* An OR node is nullable if either argument is nullable. */ - nullable[-2] = nullable[-1] || nullable[-2]; - --nullable; - break; + /* An OR node is nullable if either argument is nullable. */ + nullable[-2] = nullable[-1] || nullable[-2]; + --nullable; + break; - default: - /* Anything else is a nonempty position. (Note that special - constructs like \< are treated as nonempty strings here; - an "epsilon closure" effectively makes them nullable later. - Backreferences have to get a real position so we can detect - transitions on them later. But they are nullable. */ - *nullable++ = d->tokens[i] == BACKREF; - - /* This position is in its own firstpos and lastpos. */ - *nfirstpos++ = *nlastpos++ = 1; - --firstpos, --lastpos; - firstpos->index = lastpos->index = i; - firstpos->constraint = lastpos->constraint = NO_CONSTRAINT; - - /* Allocate the follow set for this position. */ - nalloc[i] = 1; - MALLOC(d->follows[i].elems, position, nalloc[i]); - break; - } + default: + /* Anything else is a nonempty position. (Note that special + constructs like \< are treated as nonempty strings here; + an "epsilon closure" effectively makes them nullable later. + Backreferences have to get a real position so we can detect + transitions on them later. But they are nullable. */ + *nullable++ = d->tokens[i] == BACKREF; + + /* This position is in its own firstpos and lastpos. */ + *nfirstpos++ = *nlastpos++ = 1; + --firstpos, --lastpos; + firstpos->index = lastpos->index = i; + firstpos->constraint = lastpos->constraint = NO_CONSTRAINT; + + /* Allocate the follow set for this position. */ + alloc_position_set (&d->follows[i], 1); + break; + } #ifdef DEBUG - /* ... balance the above nonsyntactic #ifdef goo... */ - fprintf(stderr, "node %d:", i); - prtok(d->tokens[i]); - putc('\n', stderr); - fprintf(stderr, nullable[-1] ? " nullable: yes\n" : " nullable: no\n"); - fprintf(stderr, " firstpos:"); - for (j = nfirstpos[-1] - 1; j >= 0; --j) + /* ... balance the above nonsyntactic #ifdef goo... */ + fprintf (stderr, "node %zd:", i); + prtok (d->tokens[i]); + putc ('\n', stderr); + fprintf (stderr, nullable[-1] ? " nullable: yes\n" : " nullable: no\n"); + fprintf (stderr, " firstpos:"); + for (j = nfirstpos[-1]; j-- > 0;) { - fprintf(stderr, " %d:", firstpos[j].index); - prtok(d->tokens[firstpos[j].index]); + fprintf (stderr, " %zd:", firstpos[j].index); + prtok (d->tokens[firstpos[j].index]); } - fprintf(stderr, "\n lastpos:"); - for (j = nlastpos[-1] - 1; j >= 0; --j) + fprintf (stderr, "\n lastpos:"); + for (j = nlastpos[-1]; j-- > 0;) { - fprintf(stderr, " %d:", lastpos[j].index); - prtok(d->tokens[lastpos[j].index]); + fprintf (stderr, " %zd:", lastpos[j].index); + prtok (d->tokens[lastpos[j].index]); } - putc('\n', stderr); - } + putc ('\n', stderr); #endif + } /* For each follow set that is the follow set of a real position, replace it with its epsilon closure. */ for (i = 0; i < d->tindex; ++i) if (d->tokens[i] < NOTCHAR || d->tokens[i] == BACKREF #if MBS_SUPPORT - || d->tokens[i] == ANYCHAR - || d->tokens[i] == MBCSET + || d->tokens[i] == ANYCHAR || d->tokens[i] == MBCSET #endif || d->tokens[i] >= CSET) { #ifdef DEBUG - fprintf(stderr, "follows(%d:", i); - prtok(d->tokens[i]); - fprintf(stderr, "):"); - for (j = d->follows[i].nelem - 1; j >= 0; --j) + fprintf (stderr, "follows(%zd:", i); + prtok (d->tokens[i]); + fprintf (stderr, "):"); + for (j = d->follows[i].nelem; j-- > 0;) { - fprintf(stderr, " %d:", d->follows[i].elems[j].index); - prtok(d->tokens[d->follows[i].elems[j].index]); + fprintf (stderr, " %zd:", d->follows[i].elems[j].index); + prtok (d->tokens[d->follows[i].elems[j].index]); } - putc('\n', stderr); + putc ('\n', stderr); #endif - copy(&d->follows[i], &merged); - epsclosure(&merged, d); - if (d->follows[i].nelem < merged.nelem) - REALLOC(d->follows[i].elems, position, merged.nelem); - copy(&merged, &d->follows[i]); + copy (&d->follows[i], &merged); + epsclosure (&merged, d); + copy (&merged, &d->follows[i]); } /* Get the epsilon closure of the firstpos of the regexp. The result will be the set of positions of state 0. */ merged.nelem = 0; for (i = 0; i < nfirstpos[-1]; ++i) - insert(firstpos[i], &merged); - epsclosure(&merged, d); - - /* Check if any of the positions of state 0 will want newline context. */ - wants_newline = 0; - for (i = 0; i < merged.nelem; ++i) - if (PREV_NEWLINE_DEPENDENT(merged.elems[i].constraint)) - wants_newline = 1; + insert (firstpos[i], &merged); + epsclosure (&merged, d); /* Build the initial state. */ d->salloc = 1; d->sindex = 0; - MALLOC(d->states, dfa_state, d->salloc); - state_index(d, &merged, wants_newline, 0); + MALLOC (d->states, d->salloc); - free(o_nullable); - free(o_nfirst); - free(o_firstpos); - free(o_nlast); - free(o_lastpos); - free(nalloc); - free(merged.elems); + separate_contexts = state_separate_contexts (&merged); + state_index (d, &merged, + (separate_contexts & CTX_NEWLINE + ? CTX_NEWLINE : separate_contexts ^ CTX_ANY)); + + free (o_nullable); + free (o_nfirst); + free (o_firstpos); + free (o_nlast); + free (o_lastpos); + free (merged.elems); } + /* Find, for each character, the transition out of state s of d, and store it in the appropriate slot of trans. @@ -2357,94 +2474,72 @@ dfaanalyze (struct dfa *d, int searchflag) create a new group labeled with the characters of C and insert this position in that group. */ void -dfastate (int s, struct dfa *d, int trans[]) -{ - position_set *grps; /* As many as will ever be needed. */ - charclass *labels; /* Labels corresponding to the groups. */ - int ngrps = 0; /* Number of groups actually used. */ - position pos; /* Current position being considered. */ - charclass matches; /* Set of matching characters. */ - int matchesf; /* True if matches is nonempty. */ - charclass intersect; /* Intersection with some label set. */ - int intersectf; /* True if intersect is nonempty. */ - charclass leftovers; /* Stuff in the label that didn't match. */ - int leftoversf; /* True if leftovers is nonempty. */ - static charclass letters; /* Set of characters considered letters. */ - static charclass newline; /* Set of characters that aren't newline. */ - position_set follows; /* Union of the follows of some group. */ - position_set tmp; /* Temporary space for merging sets. */ - int state; /* New state. */ - int wants_newline; /* New state wants to know newline context. */ - int state_newline; /* New state on a newline transition. */ - int wants_letter; /* New state wants to know letter context. */ - int state_letter; /* New state on a letter transition. */ - static int initialized; /* Flag for static initialization. */ -#if MBS_SUPPORT - int next_isnt_1st_byte = 0; /* Flag if we can't add state0. */ -#endif - int i, j, k; - - grps = xnmalloc (NOTCHAR, sizeof *grps); - labels = xnmalloc (NOTCHAR, sizeof *labels); - - /* Initialize the set of letters, if necessary. */ - if (! initialized) - { - initialized = 1; - for (i = 0; i < NOTCHAR; ++i) - if (IS_WORD_CONSTITUENT(i)) - setbit(i, letters); - setbit(eolbyte, newline); - } - - zeroset(matches); +dfastate (state_num s, struct dfa *d, state_num trans[]) +{ + leaf_set *grps; /* As many as will ever be needed. */ + charclass *labels; /* Labels corresponding to the groups. */ + size_t ngrps = 0; /* Number of groups actually used. */ + position pos; /* Current position being considered. */ + charclass matches; /* Set of matching characters. */ + int matchesf; /* True if matches is nonempty. */ + charclass intersect; /* Intersection with some label set. */ + int intersectf; /* True if intersect is nonempty. */ + charclass leftovers; /* Stuff in the label that didn't match. */ + int leftoversf; /* True if leftovers is nonempty. */ + position_set follows; /* Union of the follows of some group. */ + position_set tmp; /* Temporary space for merging sets. */ + int possible_contexts; /* Contexts that this group can match. */ + int separate_contexts; /* Context that new state wants to know. */ + state_num state; /* New state. */ + state_num state_newline; /* New state on a newline transition. */ + state_num state_letter; /* New state on a letter transition. */ + int next_isnt_1st_byte = 0; /* Flag if we can't add state0. */ + size_t i, j, k; + + MALLOC (grps, NOTCHAR); + MALLOC (labels, NOTCHAR); + + zeroset (matches); for (i = 0; i < d->states[s].elems.nelem; ++i) { pos = d->states[s].elems.elems[i]; if (d->tokens[pos.index] >= 0 && d->tokens[pos.index] < NOTCHAR) - setbit(d->tokens[pos.index], matches); + setbit (d->tokens[pos.index], matches); else if (d->tokens[pos.index] >= CSET) - copyset(d->charclasses[d->tokens[pos.index] - CSET], matches); -#if MBS_SUPPORT - else if (d->tokens[pos.index] == ANYCHAR - || d->tokens[pos.index] == MBCSET) - /* MB_CUR_MAX > 1 */ + copyset (d->charclasses[d->tokens[pos.index] - CSET], matches); + else if (MBS_SUPPORT + && (d->tokens[pos.index] == ANYCHAR + || d->tokens[pos.index] == MBCSET)) + /* MB_CUR_MAX > 1 */ { /* ANYCHAR and MBCSET must match with a single character, so we must put it to d->states[s].mbps, which contains the positions which can match with a single character not a byte. */ if (d->states[s].mbps.nelem == 0) - { - MALLOC(d->states[s].mbps.elems, position, - d->states[s].elems.nelem); - } - insert(pos, &(d->states[s].mbps)); + alloc_position_set (&d->states[s].mbps, 1); + insert (pos, &(d->states[s].mbps)); continue; } -#endif /* MBS_SUPPORT */ else continue; /* Some characters may need to be eliminated from matches because they fail in the current context. */ - if (pos.constraint != 0xFF) + if (pos.constraint != NO_CONSTRAINT) { - if (! MATCHES_NEWLINE_CONTEXT(pos.constraint, - d->states[s].newline, 1)) - clrbit(eolbyte, matches); - if (! MATCHES_NEWLINE_CONTEXT(pos.constraint, - d->states[s].newline, 0)) + if (!SUCCEEDS_IN_CONTEXT (pos.constraint, + d->states[s].context, CTX_NEWLINE)) for (j = 0; j < CHARCLASS_INTS; ++j) - matches[j] &= newline[j]; - if (! MATCHES_LETTER_CONTEXT(pos.constraint, - d->states[s].letter, 1)) + matches[j] &= ~newline[j]; + if (!SUCCEEDS_IN_CONTEXT (pos.constraint, + d->states[s].context, CTX_LETTER)) for (j = 0; j < CHARCLASS_INTS; ++j) matches[j] &= ~letters[j]; - if (! MATCHES_LETTER_CONTEXT(pos.constraint, - d->states[s].letter, 0)) + if (!SUCCEEDS_IN_CONTEXT (pos.constraint, + d->states[s].context, CTX_NONE)) for (j = 0; j < CHARCLASS_INTS; ++j) - matches[j] &= letters[j]; + matches[j] &= letters[j] | newline[j]; /* If there are no characters left, there's no point in going on. */ for (j = 0; j < CHARCLASS_INTS && !matches[j]; ++j) @@ -2459,7 +2554,7 @@ dfastate (int s, struct dfa *d, int trans[]) group's label doesn't contain that character, go on to the next group. */ if (d->tokens[pos.index] >= 0 && d->tokens[pos.index] < NOTCHAR - && !tstbit(d->tokens[pos.index], labels[j])) + && !tstbit (d->tokens[pos.index], labels[j])) continue; /* Check if this group's label has a nonempty intersection with @@ -2467,7 +2562,7 @@ dfastate (int s, struct dfa *d, int trans[]) intersectf = 0; for (k = 0; k < CHARCLASS_INTS; ++k) (intersect[k] = matches[k] & labels[j][k]) ? (intersectf = 1) : 0; - if (! intersectf) + if (!intersectf) continue; /* It does; now find the set differences both ways. */ @@ -2484,20 +2579,22 @@ dfastate (int s, struct dfa *d, int trans[]) /* If there were leftovers, create a new group labeled with them. */ if (leftoversf) { - copyset(leftovers, labels[ngrps]); - copyset(intersect, labels[j]); - MALLOC(grps[ngrps].elems, position, d->nleaves); - copy(&grps[j], &grps[ngrps]); + copyset (leftovers, labels[ngrps]); + copyset (intersect, labels[j]); + MALLOC (grps[ngrps].elems, d->nleaves); + memcpy (grps[ngrps].elems, grps[j].elems, + sizeof (grps[j].elems[0]) * grps[j].nelem); + grps[ngrps].nelem = grps[j].nelem; ++ngrps; } - /* Put the position in the current group. Note that there is no - reason to call insert() here. */ - grps[j].elems[grps[j].nelem++] = pos; + /* Put the position in the current group. The constraint is + irrelevant here. */ + grps[j].elems[grps[j].nelem++] = pos.index; /* If every character matching the current position has been accounted for, we're done. */ - if (! matchesf) + if (!matchesf) break; } @@ -2505,44 +2602,38 @@ dfastate (int s, struct dfa *d, int trans[]) unaccounted for, then we'll have to create a new group. */ if (j == ngrps) { - copyset(matches, labels[ngrps]); - zeroset(matches); - MALLOC(grps[ngrps].elems, position, d->nleaves); + copyset (matches, labels[ngrps]); + zeroset (matches); + MALLOC (grps[ngrps].elems, d->nleaves); grps[ngrps].nelem = 1; - grps[ngrps].elems[0] = pos; + grps[ngrps].elems[0] = pos.index; ++ngrps; } } - MALLOC(follows.elems, position, d->nleaves); - MALLOC(tmp.elems, position, d->nleaves); + alloc_position_set (&follows, d->nleaves); + alloc_position_set (&tmp, d->nleaves); /* If we are a searching matcher, the default transition is to a state containing the positions of state 0, otherwise the default transition is to fail miserably. */ if (d->searchflag) { - wants_newline = 0; - wants_letter = 0; - for (i = 0; i < d->states[0].elems.nelem; ++i) - { - if (PREV_NEWLINE_DEPENDENT(d->states[0].elems.elems[i].constraint)) - wants_newline = 1; - if (PREV_LETTER_DEPENDENT(d->states[0].elems.elems[i].constraint)) - wants_letter = 1; - } - copy(&d->states[0].elems, &follows); - state = state_index(d, &follows, 0, 0); - if (wants_newline) - state_newline = state_index(d, &follows, 1, 0); + /* Find the state(s) corresponding to the positions of state 0. */ + copy (&d->states[0].elems, &follows); + separate_contexts = state_separate_contexts (&follows); + state = state_index (d, &follows, separate_contexts ^ CTX_ANY); + if (separate_contexts & CTX_NEWLINE) + state_newline = state_index (d, &follows, CTX_NEWLINE); else state_newline = state; - if (wants_letter) - state_letter = state_index(d, &follows, 0, 1); + if (separate_contexts & CTX_LETTER) + state_letter = state_index (d, &follows, CTX_LETTER); else state_letter = state; + for (i = 0; i < NOTCHAR; ++i) - trans[i] = (IS_WORD_CONSTITUENT(i)) ? state_letter : state; + trans[i] = (IS_WORD_CONSTITUENT (i)) ? state_letter : state; trans[eolbyte] = state_newline; } else @@ -2556,10 +2647,9 @@ dfastate (int s, struct dfa *d, int trans[]) /* Find the union of the follows of the positions of the group. This is a hideously inefficient loop. Fix it someday. */ for (j = 0; j < grps[i].nelem; ++j) - for (k = 0; k < d->follows[grps[i].elems[j].index].nelem; ++k) - insert(d->follows[grps[i].elems[j].index].elems[k], &follows); + for (k = 0; k < d->follows[grps[i].elems[j]].nelem; ++k) + insert (d->follows[grps[i].elems[j]].elems[k], &follows); -#if MBS_SUPPORT if (d->mb_cur_max > 1) { /* If a token in follows.elems is not 1st byte of a multibyte @@ -2590,42 +2680,29 @@ dfastate (int s, struct dfa *d, int trans[]) } } } -#endif /* If we are building a searching matcher, throw in the positions of state 0 as well. */ -#if MBS_SUPPORT - if (d->searchflag && (d->mb_cur_max == 1 || !next_isnt_1st_byte)) -#else - if (d->searchflag) -#endif + if (d->searchflag + && (!MBS_SUPPORT || (d->mb_cur_max == 1 || !next_isnt_1st_byte))) for (j = 0; j < d->states[0].elems.nelem; ++j) - insert(d->states[0].elems.elems[j], &follows); + insert (d->states[0].elems.elems[j], &follows); /* Find out if the new state will want any context information. */ - wants_newline = 0; - if (tstbit(eolbyte, labels[i])) - for (j = 0; j < follows.nelem; ++j) - if (PREV_NEWLINE_DEPENDENT(follows.elems[j].constraint)) - wants_newline = 1; - - wants_letter = 0; - for (j = 0; j < CHARCLASS_INTS; ++j) - if (labels[i][j] & letters[j]) - break; - if (j < CHARCLASS_INTS) - for (j = 0; j < follows.nelem; ++j) - if (PREV_LETTER_DEPENDENT(follows.elems[j].constraint)) - wants_letter = 1; + possible_contexts = charclass_context (labels[i]); + separate_contexts = state_separate_contexts (&follows); /* Find the state(s) corresponding to the union of the follows. */ - state = state_index(d, &follows, 0, 0); - if (wants_newline) - state_newline = state_index(d, &follows, 1, 0); + if ((separate_contexts & possible_contexts) != possible_contexts) + state = state_index (d, &follows, separate_contexts ^ CTX_ANY); + else + state = -1; + if (separate_contexts & possible_contexts & CTX_NEWLINE) + state_newline = state_index (d, &follows, CTX_NEWLINE); else state_newline = state; - if (wants_letter) - state_letter = state_index(d, &follows, 0, 1); + if (separate_contexts & possible_contexts & CTX_LETTER) + state_letter = state_index (d, &follows, CTX_LETTER); else state_letter = state; @@ -2638,7 +2715,7 @@ dfastate (int s, struct dfa *d, int trans[]) if (c == eolbyte) trans[c] = state_newline; - else if (IS_WORD_CONSTITUENT(c)) + else if (IS_WORD_CONSTITUENT (c)) trans[c] = state_letter; else if (c < NOTCHAR) trans[c] = state; @@ -2646,11 +2723,11 @@ dfastate (int s, struct dfa *d, int trans[]) } for (i = 0; i < ngrps; ++i) - free(grps[i].elems); - free(follows.elems); - free(tmp.elems); - free(grps); - free(labels); + free (grps[i].elems); + free (follows.elems); + free (tmp.elems); + free (grps); + free (labels); } /* Some routines for manipulating a compiled dfa's transition tables. @@ -2661,10 +2738,10 @@ dfastate (int s, struct dfa *d, int trans[]) TODO: Improve this comment, get rid of the unnecessary redundancy. */ static void -build_state (int s, struct dfa *d) +build_state (state_num s, struct dfa *d) { - int *trans; /* The new transition table. */ - int i; + state_num *trans; /* The new transition table. */ + state_num i; /* Set an upper limit on the number of transition tables that will ever exist at once. 1024 is arbitrary. The idea is that the frequently @@ -2674,8 +2751,8 @@ build_state (int s, struct dfa *d) { for (i = 0; i < d->tralloc; ++i) { - free(d->trans[i]); - free(d->fails[i]); + free (d->trans[i]); + free (d->fails[i]); d->trans[i] = d->fails[i] = NULL; } d->trcount = 0; @@ -2685,18 +2762,15 @@ build_state (int s, struct dfa *d) /* Set up the success bits for this state. */ d->success[s] = 0; - if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 1, d->states[s].letter, 0, - s, *d)) - d->success[s] |= 4; - if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 0, d->states[s].letter, 1, - s, *d)) - d->success[s] |= 2; - if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 0, d->states[s].letter, 0, - s, *d)) - d->success[s] |= 1; - - MALLOC(trans, int, NOTCHAR); - dfastate(s, d, trans); + if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NEWLINE, s, *d)) + d->success[s] |= CTX_NEWLINE; + if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_LETTER, s, *d)) + d->success[s] |= CTX_LETTER; + if (ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NONE, s, *d)) + d->success[s] |= CTX_NONE; + + MALLOC (trans, NOTCHAR); + dfastate (s, d, trans); /* Now go through the new transition table, and make sure that the trans and fail arrays are allocated large enough to hold a pointer for the @@ -2704,15 +2778,15 @@ build_state (int s, struct dfa *d) for (i = 0; i < NOTCHAR; ++i) if (trans[i] >= d->tralloc) { - int oldalloc = d->tralloc; + state_num oldalloc = d->tralloc; while (trans[i] >= d->tralloc) d->tralloc *= 2; - REALLOC(d->realtrans, int *, d->tralloc + 1); + REALLOC (d->realtrans, d->tralloc + 1); d->trans = d->realtrans + 1; - REALLOC(d->fails, int *, d->tralloc); - REALLOC(d->success, int, d->tralloc); - REALLOC(d->newlines, int, d->tralloc); + REALLOC (d->fails, d->tralloc); + REALLOC (d->success, d->tralloc); + REALLOC (d->newlines, d->tralloc); while (oldalloc < d->tralloc) { d->trans[oldalloc] = NULL; @@ -2725,7 +2799,7 @@ build_state (int s, struct dfa *d) d->newlines[s] = trans[eolbyte]; trans[eolbyte] = -1; - if (ACCEPTING(s, *d)) + if (ACCEPTING (s, *d)) d->fails[s] = trans; else d->trans[s] = trans; @@ -2736,15 +2810,14 @@ build_state_zero (struct dfa *d) { d->tralloc = 1; d->trcount = 0; - CALLOC(d->realtrans, int *, d->tralloc + 1); + CALLOC (d->realtrans, d->tralloc + 1); d->trans = d->realtrans + 1; - CALLOC(d->fails, int *, d->tralloc); - MALLOC(d->success, int, d->tralloc); - MALLOC(d->newlines, int, d->tralloc); - build_state(0, d); + CALLOC (d->fails, d->tralloc); + MALLOC (d->success, d->tralloc); + MALLOC (d->newlines, d->tralloc); + build_state (0, d); } -#if MBS_SUPPORT /* Multibyte character handling sub-routines for dfaexec. */ /* Initial state may encounter the byte which is not a single byte character @@ -2763,29 +2836,29 @@ build_state_zero (struct dfa *d) ++p; \ if ((char *) p >= end) \ { \ - free(mblen_buf); \ - free(inputwcs); \ + free (mblen_buf); \ + free (inputwcs); \ *end = saved_end; \ return NULL; \ } \ } static void -realloc_trans_if_necessary(struct dfa *d, int new_state) +realloc_trans_if_necessary (struct dfa *d, state_num new_state) { /* Make sure that the trans and fail arrays are allocated large enough to hold a pointer for the new state. */ if (new_state >= d->tralloc) { - int oldalloc = d->tralloc; + state_num oldalloc = d->tralloc; while (new_state >= d->tralloc) d->tralloc *= 2; - REALLOC(d->realtrans, int *, d->tralloc + 1); + REALLOC (d->realtrans, d->tralloc + 1); d->trans = d->realtrans + 1; - REALLOC(d->fails, int *, d->tralloc); - REALLOC(d->success, int, d->tralloc); - REALLOC(d->newlines, int, d->tralloc); + REALLOC (d->fails, d->tralloc); + REALLOC (d->success, d->tralloc); + REALLOC (d->newlines, d->tralloc); while (oldalloc < d->tralloc) { d->trans[oldalloc] = NULL; @@ -2798,9 +2871,9 @@ realloc_trans_if_necessary(struct dfa *d, int new_state) transit_state_consume_1char. */ typedef enum { - TRANSIT_STATE_IN_PROGRESS, /* State transition has not finished. */ - TRANSIT_STATE_DONE, /* State transition has finished. */ - TRANSIT_STATE_END_BUFFER /* Reach the end of the buffer. */ + TRANSIT_STATE_IN_PROGRESS, /* State transition has not finished. */ + TRANSIT_STATE_DONE, /* State transition has finished. */ + TRANSIT_STATE_END_BUFFER /* Reach the end of the buffer. */ } status_transit_state; /* Consume a single byte and transit state from 's' to '*next_state'. @@ -2808,11 +2881,11 @@ typedef enum But state transition is done just once, otherwise matching succeed or reach the end of the buffer. */ static status_transit_state -transit_state_singlebyte (struct dfa *d, int s, unsigned char const *p, - int *next_state) +transit_state_singlebyte (struct dfa *d, state_num s, unsigned char const *p, + state_num * next_state) { - int *t; - int works = s; + state_num *t; + state_num works = s; status_transit_state rval = TRANSIT_STATE_IN_PROGRESS; @@ -2841,124 +2914,111 @@ transit_state_singlebyte (struct dfa *d, int s, unsigned char const *p, } else { - build_state(works, d); + build_state (works, d); } } *next_state = works; return rval; } -/* Check whether period can match or not in the current context. If it can, - return the amount of the bytes with which period can match, otherwise - return 0. - `pos' is the position of the period. `idx' is the index from the - buf_begin, and it is the current position in the buffer. */ +/* Match a "." against the current context. buf_begin[IDX] is the + current position. Return the length of the match, in bytes. + POS is the position of the ".". */ static int -match_anychar (struct dfa *d, int s, position pos, int idx) +match_anychar (struct dfa *d, state_num s, position pos, size_t idx) { - int newline = 0; - int letter = 0; + int context; wchar_t wc; int mbclen; wc = inputwcs[idx]; - mbclen = (mblen_buf[idx] == 0)? 1 : mblen_buf[idx]; + mbclen = (mblen_buf[idx] == 0) ? 1 : mblen_buf[idx]; - /* Check context. */ - if (wc == (wchar_t)eolbyte) + /* Check syntax bits. */ + if (wc == (wchar_t) eolbyte) { if (!(syntax_bits & RE_DOT_NEWLINE)) return 0; - newline = 1; } - else if (wc == (wchar_t)'\0') + else if (wc == (wchar_t) '\0') { if (syntax_bits & RE_DOT_NOT_NULL) return 0; - newline = 1; } - if (iswalnum(wc) || wc == L'_') - letter = 1; - - if (!SUCCEEDS_IN_CONTEXT(pos.constraint, d->states[s].newline, - newline, d->states[s].letter, letter)) + context = wchar_context (wc); + if (!SUCCEEDS_IN_CONTEXT (pos.constraint, d->states[s].context, context)) return 0; return mbclen; } -/* Check whether bracket expression can match or not in the current context. - If it can, return the amount of the bytes with which expression can match, - otherwise return 0. - `pos' is the position of the bracket expression. `idx' is the index - from the buf_begin, and it is the current position in the buffer. */ +/* Match a bracket expression against the current context. + buf_begin[IDX] is the current position. + Return the length of the match, in bytes. + POS is the position of the bracket expression. */ static int -match_mb_charset (struct dfa *d, int s, position pos, int idx) +match_mb_charset (struct dfa *d, state_num s, position pos, size_t idx) { - int i; - int match; /* Flag which represent that matching succeed. */ - int match_len; /* Length of the character (or collating element) - with which this operator match. */ - int op_len; /* Length of the operator. */ + size_t i; + int match; /* Flag which represent that matching succeed. */ + int match_len; /* Length of the character (or collating element) + with which this operator match. */ + int op_len; /* Length of the operator. */ char buffer[128]; wchar_t wcbuf[6]; - /* Pointer to the structure to which we are currently refering. */ + /* Pointer to the structure to which we are currently referring. */ struct mb_char_classes *work_mbc; - int newline = 0; - int letter = 0; - wchar_t wc; /* Current refering character. */ + int context; + wchar_t wc; /* Current referring character. */ wc = inputwcs[idx]; - /* Check context. */ - if (wc == (wchar_t)eolbyte) + /* Check syntax bits. */ + if (wc == (wchar_t) eolbyte) { if (!(syntax_bits & RE_DOT_NEWLINE)) return 0; - newline = 1; } - else if (wc == (wchar_t)'\0') + else if (wc == (wchar_t) '\0') { if (syntax_bits & RE_DOT_NOT_NULL) return 0; - newline = 1; } - if (iswalnum(wc) || wc == L'_') - letter = 1; - if (!SUCCEEDS_IN_CONTEXT(pos.constraint, d->states[s].newline, - newline, d->states[s].letter, letter)) + + context = wchar_context (wc); + if (!SUCCEEDS_IN_CONTEXT (pos.constraint, d->states[s].context, context)) return 0; - /* Assign the current refering operator to work_mbc. */ + /* Assign the current referring operator to work_mbc. */ work_mbc = &(d->mbcsets[(d->multibyte_prop[pos.index]) >> 2]); match = !work_mbc->invert; - match_len = (mblen_buf[idx] == 0)? 1 : mblen_buf[idx]; + match_len = (mblen_buf[idx] == 0) ? 1 : mblen_buf[idx]; /* Match in range 0-255? */ if (wc < NOTCHAR && work_mbc->cset != -1 - && tstbit((unsigned char)wc, d->charclasses[work_mbc->cset])) + && tstbit ((unsigned char) wc, d->charclasses[work_mbc->cset])) goto charset_matched; /* match with a character class? */ - for (i = 0; inch_classes; i++) + for (i = 0; i < work_mbc->nch_classes; i++) { - if (iswctype((wint_t)wc, work_mbc->ch_classes[i])) + if (iswctype ((wint_t) wc, work_mbc->ch_classes[i])) goto charset_matched; } - strncpy(buffer, (char const *) buf_begin + idx, match_len); + strncpy (buffer, (char const *) buf_begin + idx, match_len); buffer[match_len] = '\0'; - /* match with an equivalent class? */ - for (i = 0; inequivs; i++) + /* match with an equivalence class? */ + for (i = 0; i < work_mbc->nequivs; i++) { - op_len = strlen(work_mbc->equivs[i]); - strncpy(buffer, (char const *) buf_begin + idx, op_len); + op_len = strlen (work_mbc->equivs[i]); + strncpy (buffer, (char const *) buf_begin + idx, op_len); buffer[op_len] = '\0'; - if (strcoll(work_mbc->equivs[i], buffer) == 0) + if (strcoll (work_mbc->equivs[i], buffer) == 0) { match_len = op_len; goto charset_matched; @@ -2966,13 +3026,13 @@ match_mb_charset (struct dfa *d, int s, position pos, int idx) } /* match with a collating element? */ - for (i = 0; incoll_elems; i++) + for (i = 0; i < work_mbc->ncoll_elems; i++) { - op_len = strlen(work_mbc->coll_elems[i]); - strncpy(buffer, (char const *) buf_begin + idx, op_len); + op_len = strlen (work_mbc->coll_elems[i]); + strncpy (buffer, (char const *) buf_begin + idx, op_len); buffer[op_len] = '\0'; - if (strcoll(work_mbc->coll_elems[i], buffer) == 0) + if (strcoll (work_mbc->coll_elems[i], buffer) == 0) { match_len = op_len; goto charset_matched; @@ -2983,18 +3043,17 @@ match_mb_charset (struct dfa *d, int s, position pos, int idx) wcbuf[1] = wcbuf[3] = wcbuf[5] = '\0'; /* match with a range? */ - for (i = 0; inranges; i++) + for (i = 0; i < work_mbc->nranges; i++) { wcbuf[2] = work_mbc->range_sts[i]; wcbuf[4] = work_mbc->range_ends[i]; - if (wcscoll(wcbuf, wcbuf+2) >= 0 && - wcscoll(wcbuf+4, wcbuf) >= 0) + if (wcscoll (wcbuf, wcbuf + 2) >= 0 && wcscoll (wcbuf + 4, wcbuf) >= 0) goto charset_matched; } /* match with a character? */ - for (i = 0; inchars; i++) + for (i = 0; i < work_mbc->nchars; i++) { if (wc == work_mbc->chars[i]) goto charset_matched; @@ -3002,7 +3061,7 @@ match_mb_charset (struct dfa *d, int s, position pos, int idx) match = !match; - charset_matched: +charset_matched: return match ? match_len : 0; } @@ -3013,26 +3072,26 @@ match_mb_charset (struct dfa *d, int s, position pos, int idx) `idx' is the index from the buf_begin, and it is the current position in the buffer. Caller MUST free the array which this function return. */ -static int* -check_matching_with_multibyte_ops (struct dfa *d, int s, int idx) +static int * +check_matching_with_multibyte_ops (struct dfa *d, state_num s, size_t idx) { - int i; - int* rarray; + size_t i; + int *rarray; - MALLOC(rarray, int, d->states[s].mbps.nelem); + MALLOC (rarray, d->states[s].mbps.nelem); for (i = 0; i < d->states[s].mbps.nelem; ++i) { position pos = d->states[s].mbps.elems[i]; - switch(d->tokens[pos.index]) + switch (d->tokens[pos.index]) { case ANYCHAR: - rarray[i] = match_anychar(d, s, pos, idx); + rarray[i] = match_anychar (d, s, pos, idx); break; case MBCSET: - rarray[i] = match_mb_charset(d, s, pos, idx); + rarray[i] = match_mb_charset (d, s, pos, idx); break; default: - break; /* cannot happen. */ + break; /* cannot happen. */ } } return rarray; @@ -3045,64 +3104,66 @@ check_matching_with_multibyte_ops (struct dfa *d, int s, int idx) `mbclen' and `pps' are the output. `mbclen' is the length of the character consumed, and `pps' is the set this function enumerate. */ static status_transit_state -transit_state_consume_1char (struct dfa *d, int s, unsigned char const **pp, - int *match_lens, int *mbclen, position_set *pps) -{ - int i, j; - int s1, s2; - int* work_mbls; +transit_state_consume_1char (struct dfa *d, state_num s, + unsigned char const **pp, + int *match_lens, int *mbclen, position_set * pps) +{ + size_t i, j; + int k; + state_num s1, s2; + int *work_mbls; status_transit_state rs = TRANSIT_STATE_DONE; /* Calculate the length of the (single/multi byte) character to which p points. */ - *mbclen = (mblen_buf[*pp - buf_begin] == 0)? 1 - : mblen_buf[*pp - buf_begin]; + *mbclen = (mblen_buf[*pp - buf_begin] == 0) ? 1 : mblen_buf[*pp - buf_begin]; /* Calculate the state which can be reached from the state `s' by consuming `*mbclen' single bytes from the buffer. */ s1 = s; - for (i = 0; i < *mbclen; i++) + for (k = 0; k < *mbclen; k++) { s2 = s1; - rs = transit_state_singlebyte(d, s2, (*pp)++, &s1); + rs = transit_state_singlebyte (d, s2, (*pp)++, &s1); } /* Copy the positions contained by `s1' to the set `pps'. */ - copy(&(d->states[s1].elems), pps); + copy (&(d->states[s1].elems), pps); - /* Check (inputed)match_lens, and initialize if it is NULL. */ + /* Check (input) match_lens, and initialize if it is NULL. */ if (match_lens == NULL && d->states[s].mbps.nelem != 0) - work_mbls = check_matching_with_multibyte_ops(d, s, *pp - buf_begin); + work_mbls = check_matching_with_multibyte_ops (d, s, *pp - buf_begin); else work_mbls = match_lens; /* Add all of the positions which can be reached from `s' by consuming a single character. */ - for (i = 0; i < d->states[s].mbps.nelem ; i++) - { + for (i = 0; i < d->states[s].mbps.nelem; i++) + { if (work_mbls[i] == *mbclen) for (j = 0; j < d->follows[d->states[s].mbps.elems[i].index].nelem; j++) - insert(d->follows[d->states[s].mbps.elems[i].index].elems[j], - pps); + insert (d->follows[d->states[s].mbps.elems[i].index].elems[j], pps); } if (match_lens == NULL && work_mbls != NULL) - free(work_mbls); + free (work_mbls); + + /* FIXME: this return value is always ignored. */ return rs; } /* Transit state from s, then return new state and update the pointer of the buffer. This function is for some operator which can match with a multi- byte character or a collating element (which may be multi characters). */ -static int -transit_state (struct dfa *d, int s, unsigned char const **pp) +static state_num +transit_state (struct dfa *d, state_num s, unsigned char const **pp) { - int s1; - int mbclen; /* The length of current input multibyte character. */ + state_num s1; + int mbclen; /* The length of current input multibyte character. */ int maxlen = 0; - int i, j; + size_t i, j; int *match_lens = NULL; - int nelem = d->states[s].mbps.nelem; /* Just a alias. */ + size_t nelem = d->states[s].mbps.nelem; /* Just a alias. */ position_set follows; unsigned char const *p1 = *pp; wchar_t wc; @@ -3112,7 +3173,7 @@ transit_state (struct dfa *d, int s, unsigned char const **pp) We check whether each of them can match or not. */ { /* Note: caller must free the return value of this function. */ - match_lens = check_matching_with_multibyte_ops(d, s, *pp - buf_begin); + match_lens = check_matching_with_multibyte_ops (d, s, *pp - buf_begin); for (i = 0; i < nelem; i++) /* Search the operator which match the longest string, @@ -3128,58 +3189,58 @@ transit_state (struct dfa *d, int s, unsigned char const **pp) We need to check only one single byte character. */ { status_transit_state rs; - rs = transit_state_singlebyte(d, s, *pp, &s1); + rs = transit_state_singlebyte (d, s, *pp, &s1); /* We must update the pointer if state transition succeeded. */ if (rs == TRANSIT_STATE_DONE) ++*pp; - free(match_lens); + free (match_lens); return s1; } /* This state has some operators which can match a multibyte character. */ - follows.nelem = 0; - MALLOC(follows.elems, position, d->nleaves); + alloc_position_set (&follows, d->nleaves); /* `maxlen' may be longer than the length of a character, because it may not be a character but a (multi character) collating element. We enumerate all of the positions which `s' can reach by consuming `maxlen' bytes. */ - transit_state_consume_1char(d, s, pp, match_lens, &mbclen, &follows); + transit_state_consume_1char (d, s, pp, match_lens, &mbclen, &follows); wc = inputwcs[*pp - mbclen - buf_begin]; - s1 = state_index(d, &follows, wc == L'\n', iswalnum(wc)); - realloc_trans_if_necessary(d, s1); + s1 = state_index (d, &follows, wchar_context (wc)); + realloc_trans_if_necessary (d, s1); while (*pp - p1 < maxlen) { - follows.nelem = 0; - transit_state_consume_1char(d, s1, pp, NULL, &mbclen, &follows); + transit_state_consume_1char (d, s1, pp, NULL, &mbclen, &follows); - for (i = 0; i < nelem ; i++) + for (i = 0; i < nelem; i++) { if (match_lens[i] == *pp - p1) for (j = 0; j < d->follows[d->states[s1].mbps.elems[i].index].nelem; j++) - insert(d->follows[d->states[s1].mbps.elems[i].index].elems[j], - &follows); + insert (d->follows[d->states[s1].mbps.elems[i].index].elems[j], + &follows); } wc = inputwcs[*pp - mbclen - buf_begin]; - s1 = state_index(d, &follows, wc == L'\n', iswalnum(wc)); - realloc_trans_if_necessary(d, s1); + s1 = state_index (d, &follows, wchar_context (wc)); + realloc_trans_if_necessary (d, s1); } - free(match_lens); - free(follows.elems); + free (match_lens); + free (follows.elems); return s1; } + /* Initialize mblen_buf and inputwcs with data from the next line. */ static void prepare_wc_buf (const char *begin, const char *end) { +#if MBS_SUPPORT unsigned char eol = eolbyte; size_t remain_bytes, i; @@ -3191,14 +3252,14 @@ prepare_wc_buf (const char *begin, const char *end) if (remain_bytes == 0) { remain_bytes - = mbrtowc(inputwcs + i, begin + i, end - begin - i + 1, &mbs); + = mbrtowc (inputwcs + i, begin + i, end - begin - i + 1, &mbs); if (remain_bytes < 1 || remain_bytes == (size_t) -1 || remain_bytes == (size_t) -2 - || (remain_bytes == 1 && inputwcs[i] == (wchar_t)begin[i])) + || (remain_bytes == 1 && inputwcs[i] == (wchar_t) begin[i])) { remain_bytes = 0; - inputwcs[i] = (wchar_t)begin[i]; + inputwcs[i] = (wchar_t) begin[i]; mblen_buf[i] = 0; if (begin[i] == eol) break; @@ -3219,10 +3280,9 @@ prepare_wc_buf (const char *begin, const char *end) buf_end = (unsigned char *) (begin + i); mblen_buf[i] = 0; - inputwcs[i] = 0; /* sentinel */ -} - + inputwcs[i] = 0; /* sentinel */ #endif /* MBS_SUPPORT */ +} /* Search through a buffer looking for a match to the given struct dfa. Find the first occurrence of a string matching the regexp in the @@ -3231,36 +3291,24 @@ prepare_wc_buf (const char *begin, const char *end) points to the beginning of the buffer, and END points to the first byte after its end. Note however that we store a sentinel byte (usually newline) in *END, so the actual buffer must be one byte longer. - When NEWLINE is nonzero, newlines may appear in the matching string. + When ALLOW_NL is nonzero, newlines may appear in the matching string. If COUNT is non-NULL, increment *COUNT once for each newline processed. Finally, if BACKREF is non-NULL set *BACKREF to indicate whether we encountered a back-reference (1) or not (0). The caller may use this to decide whether to fall back on a backtracking matcher. */ char * dfaexec (struct dfa *d, char const *begin, char *end, - int newline, int *count, int *backref) + int allow_nl, size_t *count, int *backref) { - int s, s1, tmp; /* Current state. */ - unsigned char const *p; /* Current input character. */ - int **trans, *t; /* Copy of d->trans so it can be optimized + state_num s, s1; /* Current state. */ + unsigned char const *p; /* Current input character. */ + state_num **trans, *t; /* Copy of d->trans so it can be optimized into a register. */ - unsigned char eol = eolbyte; /* Likewise for eolbyte. */ + unsigned char eol = eolbyte; /* Likewise for eolbyte. */ unsigned char saved_end; - static int sbit[NOTCHAR]; /* Table for anding with d->success. */ - static int sbit_init; - - if (! sbit_init) - { - unsigned int i; - - sbit_init = 1; - for (i = 0; i < NOTCHAR; ++i) - sbit[i] = (IS_WORD_CONSTITUENT(i)) ? 2 : 1; - sbit[eol] = 4; - } - if (! d->tralloc) - build_state_zero(d); + if (!d->tralloc) + build_state_zero (d); s = s1 = 0; p = (unsigned char const *) begin; @@ -3268,26 +3316,23 @@ dfaexec (struct dfa *d, char const *begin, char *end, saved_end = *(unsigned char *) end; *end = eol; -#if MBS_SUPPORT if (d->mb_cur_max > 1) { - MALLOC(mblen_buf, unsigned char, end - begin + 2); - MALLOC(inputwcs, wchar_t, end - begin + 2); - memset(&mbs, 0, sizeof(mbstate_t)); + MALLOC (mblen_buf, end - begin + 2); + MALLOC (inputwcs, end - begin + 2); + memset (&mbs, 0, sizeof (mbstate_t)); prepare_wc_buf ((const char *) p, end); } -#endif /* MBS_SUPPORT */ for (;;) { -#if MBS_SUPPORT if (d->mb_cur_max > 1) - while ((t = trans[s])) + while ((t = trans[s]) != NULL) { if (p > buf_end) break; s1 = s; - SKIP_REMAINS_MB_IF_INITIAL_STATE(s, p); + SKIP_REMAINS_MB_IF_INITIAL_STATE (s, p); if (d->states[s].mbps.nelem == 0) { @@ -3302,27 +3347,32 @@ dfaexec (struct dfa *d, char const *begin, char *end, if (backref) { *backref = 1; - free(mblen_buf); - free(inputwcs); + free (mblen_buf); + free (inputwcs); *end = saved_end; return (char *) p; } /* Can match with a multibyte character (and multi character collating element). Transition table might be updated. */ - s = transit_state(d, s, &p); + s = transit_state (d, s, &p); trans = d->trans; } else -#endif /* MBS_SUPPORT */ - while ((t = trans[s]) != 0) { /* hand-optimized loop */ - s1 = t[*p++]; - if ((t = trans[s1]) == 0) { - tmp = s ; s = s1 ; s1 = tmp ; /* swap */ - break; + { + while ((t = trans[s]) != NULL) + { + s1 = t[*p++]; + if ((t = trans[s1]) == NULL) + { + state_num tmp = s; + s = s1; + s1 = tmp; /* swap */ + break; + } + s = t[*p++]; + } } - s = t[*p++]; - } if (s >= 0 && (char *) p <= end && d->fails[s]) { @@ -3330,29 +3380,25 @@ dfaexec (struct dfa *d, char const *begin, char *end, { if (backref) *backref = (d->states[s].backref != 0); -#if MBS_SUPPORT if (d->mb_cur_max > 1) { - free(mblen_buf); - free(inputwcs); + free (mblen_buf); + free (inputwcs); } -#endif /* MBS_SUPPORT */ *end = saved_end; return (char *) p; } s1 = s; -#if MBS_SUPPORT if (d->mb_cur_max > 1) { /* Can match with a multibyte character (and multicharacter collating element). Transition table might be updated. */ - s = transit_state(d, s, &p); + s = transit_state (d, s, &p); trans = d->trans; } else -#endif /* MBS_SUPPORT */ - s = d->fails[s][*p++]; + s = d->fails[s][*p++]; continue; } @@ -3362,34 +3408,30 @@ dfaexec (struct dfa *d, char const *begin, char *end, if (count) ++*count; -#if MBS_SUPPORT if (d->mb_cur_max > 1) prepare_wc_buf ((const char *) p, end); -#endif } /* Check if we've run off the end of the buffer. */ if ((char *) p > end) { -#if MBS_SUPPORT if (d->mb_cur_max > 1) { - free(mblen_buf); - free(inputwcs); + free (mblen_buf); + free (inputwcs); } -#endif /* MBS_SUPPORT */ *end = saved_end; return NULL; } if (s >= 0) { - build_state(s, d); + build_state (s, d); trans = d->trans; continue; } - if (p[-1] == eol && newline) + if (p[-1] == eol && allow_nl) { s = d->newlines[s1]; continue; @@ -3399,38 +3441,36 @@ dfaexec (struct dfa *d, char const *begin, char *end, } } -#if MBS_SUPPORT static void free_mbdata (struct dfa *d) { - unsigned int i; + size_t i; - free(d->multibyte_prop); + free (d->multibyte_prop); d->multibyte_prop = NULL; for (i = 0; i < d->nmbcsets; ++i) { - unsigned int j; + size_t j; struct mb_char_classes *p = &(d->mbcsets[i]); - free(p->chars); - free(p->ch_classes); - free(p->range_sts); - free(p->range_ends); + free (p->chars); + free (p->ch_classes); + free (p->range_sts); + free (p->range_ends); for (j = 0; j < p->nequivs; ++j) - free(p->equivs[j]); - free(p->equivs); + free (p->equivs[j]); + free (p->equivs); for (j = 0; j < p->ncoll_elems; ++j) - free(p->coll_elems[j]); - free(p->coll_elems); + free (p->coll_elems[j]); + free (p->coll_elems); } - free(d->mbcsets); + free (d->mbcsets); d->mbcsets = NULL; d->nmbcsets = 0; } -#endif /* Initialize the components of a dfa that the other routines don't initialize for themselves. */ @@ -3440,34 +3480,33 @@ dfainit (struct dfa *d) memset (d, 0, sizeof *d); d->calloc = 1; - MALLOC(d->charclasses, charclass, d->calloc); + MALLOC (d->charclasses, d->calloc); d->talloc = 1; - MALLOC(d->tokens, token, d->talloc); + MALLOC (d->tokens, d->talloc); -#if MBS_SUPPORT d->mb_cur_max = MB_CUR_MAX; + if (d->mb_cur_max > 1) { d->nmultibyte_prop = 1; - MALLOC(d->multibyte_prop, int, d->nmultibyte_prop); + MALLOC (d->multibyte_prop, d->nmultibyte_prop); d->mbcsets_alloc = 1; - MALLOC(d->mbcsets, struct mb_char_classes, d->mbcsets_alloc); + MALLOC (d->mbcsets, d->mbcsets_alloc); } -#endif } -#if MBS_SUPPORT static void dfaoptimize (struct dfa *d) { - unsigned int i; - if (!using_utf8()) + size_t i; + + if (!MBS_SUPPORT || !using_utf8 ()) return; for (i = 0; i < d->tindex; ++i) { - switch(d->tokens[i]) + switch (d->tokens[i]) { case ANYCHAR: /* Lowered. */ @@ -3483,60 +3522,55 @@ dfaoptimize (struct dfa *d) free_mbdata (d); d->mb_cur_max = 1; } -#endif /* Parse and analyze a single string of the given length. */ void dfacomp (char const *s, size_t len, struct dfa *d, int searchflag) { - dfainit(d); - dfaparse(s, len, d); - dfamust(d); -#if MBS_SUPPORT - dfaoptimize(d); -#endif - dfaanalyze(d, searchflag); + dfainit (d); + dfaparse (s, len, d); + dfamust (d); + dfaoptimize (d); + dfaanalyze (d, searchflag); } /* Free the storage held by the components of a dfa. */ void dfafree (struct dfa *d) { - int i; + size_t i; struct dfamust *dm, *ndm; - free(d->charclasses); - free(d->tokens); + free (d->charclasses); + free (d->tokens); -#if MBS_SUPPORT if (d->mb_cur_max > 1) - free_mbdata(d); -#endif /* MBS_SUPPORT */ + free_mbdata (d); - for (i = 0; i < d->sindex; ++i) { - free(d->states[i].elems.elems); -#if MBS_SUPPORT - free(d->states[i].mbps.elems); -#endif /* MBS_SUPPORT */ - } - free(d->states); + for (i = 0; i < d->sindex; ++i) + { + free (d->states[i].elems.elems); + if (MBS_SUPPORT) + free (d->states[i].mbps.elems); + } + free (d->states); for (i = 0; i < d->tindex; ++i) - free(d->follows[i].elems); - free(d->follows); + free (d->follows[i].elems); + free (d->follows); for (i = 0; i < d->tralloc; ++i) { - free(d->trans[i]); - free(d->fails[i]); + free (d->trans[i]); + free (d->fails[i]); } - free(d->realtrans); - free(d->fails); - free(d->newlines); - free(d->success); + free (d->realtrans); + free (d->fails); + free (d->newlines); + free (d->success); for (dm = d->musts; dm; dm = ndm) { ndm = dm->next; - free(dm->must); - free(dm); + free (dm->must); + free (dm); } } @@ -3628,20 +3662,12 @@ static char * icatalloc (char *old, char const *new) { char *result; - size_t oldsize, newsize; - - newsize = (new == NULL) ? 0 : strlen(new); - if (old == NULL) - oldsize = 0; - else if (newsize == 0) + size_t oldsize = old == NULL ? 0 : strlen (old); + size_t newsize = new == NULL ? 0 : strlen (new); + if (newsize == 0) return old; - else oldsize = strlen(old); - if (old == NULL) - result = malloc(newsize + 1); - else - result = realloc(old, oldsize + newsize + 1); - if (result != NULL && new != NULL) - strcpy(result + oldsize, new); + result = xrealloc (old, oldsize + newsize + 1); + memcpy (result + oldsize, new, newsize + 1); return result; } @@ -3651,15 +3677,15 @@ icpyalloc (char const *string) return icatalloc (NULL, string); } -static char * +static char *_GL_ATTRIBUTE_PURE istrstr (char const *lookin, char const *lookfor) { char const *cp; size_t len; - len = strlen(lookfor); + len = strlen (lookfor); for (cp = lookin; *cp != '\0'; ++cp) - if (strncmp(cp, lookfor, len) == 0) + if (strncmp (cp, lookfor, len) == 0) return (char *) cp; return NULL; } @@ -3667,13 +3693,13 @@ istrstr (char const *lookin, char const *lookfor) static void freelist (char **cpp) { - int i; + size_t i; if (cpp == NULL) return; for (i = 0; cpp[i] != NULL; ++i) { - free(cpp[i]); + free (cpp[i]); cpp[i] = NULL; } } @@ -3681,38 +3707,38 @@ freelist (char **cpp) static char ** enlist (char **cpp, char *new, size_t len) { - int i, j; + size_t i, j; if (cpp == NULL) return NULL; - if ((new = icpyalloc(new)) == NULL) + if ((new = icpyalloc (new)) == NULL) { - freelist(cpp); + freelist (cpp); return NULL; } new[len] = '\0'; /* Is there already something in the list that's new (or longer)? */ for (i = 0; cpp[i] != NULL; ++i) - if (istrstr(cpp[i], new) != NULL) + if (istrstr (cpp[i], new) != NULL) { - free(new); + free (new); return cpp; } /* Eliminate any obsoleted strings. */ j = 0; while (cpp[j] != NULL) - if (istrstr(new, cpp[j]) == NULL) + if (istrstr (new, cpp[j]) == NULL) ++j; else { - free(cpp[j]); + free (cpp[j]); if (--i == j) break; cpp[j] = cpp[i]; cpp[i] = NULL; } /* Add the new string. */ - cpp = xnrealloc(cpp, i + 2, sizeof *cpp); + REALLOC (cpp, i + 2); cpp[i] = new; cpp[i + 1] = NULL; return cpp; @@ -3731,7 +3757,7 @@ comsubs (char *left, char const *right) if (left == NULL || right == NULL) return NULL; - cpp = malloc(sizeof *cpp); + cpp = malloc (sizeof *cpp); if (cpp == NULL) return NULL; cpp[0] = NULL; @@ -3749,8 +3775,16 @@ comsubs (char *left, char const *right) } if (len == 0) continue; - if ((cpp = enlist(cpp, lcp, len)) == NULL) - break; + { + char **p = enlist (cpp, lcp, len); + if (p == NULL) + { + freelist (cpp); + cpp = NULL; + break; + } + cpp = p; + } } return cpp; } @@ -3758,13 +3792,13 @@ comsubs (char *left, char const *right) static char ** addlists (char **old, char **new) { - int i; + size_t i; if (old == NULL || new == NULL) return NULL; for (i = 0; new[i] != NULL; ++i) { - old = enlist(old, new[i], strlen(new[i])); + old = enlist (old, new[i], strlen (new[i])); if (old == NULL) break; } @@ -3778,11 +3812,11 @@ inboth (char **left, char **right) { char **both; char **temp; - int lnum, rnum; + size_t lnum, rnum; if (left == NULL || right == NULL) return NULL; - both = malloc(sizeof *both); + both = malloc (sizeof *both); if (both == NULL) return NULL; both[0] = NULL; @@ -3790,15 +3824,15 @@ inboth (char **left, char **right) { for (rnum = 0; right[rnum] != NULL; ++rnum) { - temp = comsubs(left[lnum], right[rnum]); + temp = comsubs (left[lnum], right[rnum]); if (temp == NULL) { - freelist(both); + freelist (both); return NULL; } - both = addlists(both, temp); - freelist(temp); - free(temp); + both = addlists (both, temp); + freelist (temp); + free (temp); if (both == NULL) return NULL; } @@ -3815,10 +3849,10 @@ typedef struct } must; static void -resetmust (must *mp) +resetmust (must * mp) { mp->left[0] = mp->right[0] = mp->is[0] = '\0'; - freelist(mp->in); + freelist (mp->in); } static void @@ -3827,8 +3861,8 @@ dfamust (struct dfa *d) must *musts; must *mp; char *result; - int ri; - int i; + size_t ri; + size_t i; int exact; token t; static must must0; @@ -3837,30 +3871,27 @@ dfamust (struct dfa *d) result = empty_string; exact = 0; - musts = xnmalloc(d->tindex + 1, sizeof *musts); + MALLOC (musts, d->tindex + 1); mp = musts; for (i = 0; i <= d->tindex; ++i) mp[i] = must0; for (i = 0; i <= d->tindex; ++i) { - mp[i].in = malloc(sizeof *mp[i].in); - mp[i].left = malloc(2); - mp[i].right = malloc(2); - mp[i].is = malloc(2); - if (mp[i].in == NULL || mp[i].left == NULL || - mp[i].right == NULL || mp[i].is == NULL) - goto done; + mp[i].in = xmalloc (sizeof *mp[i].in); + mp[i].left = xmalloc (2); + mp[i].right = xmalloc (2); + mp[i].is = xmalloc (2); mp[i].left[0] = mp[i].right[0] = mp[i].is[0] = '\0'; mp[i].in[0] = NULL; } #ifdef DEBUG - fprintf(stderr, "dfamust:\n"); + fprintf (stderr, "dfamust:\n"); for (i = 0; i < d->tindex; ++i) { - fprintf(stderr, " %d:", i); - prtok(d->tokens[i]); + fprintf (stderr, " %zd:", i); + prtok (d->tokens[i]); } - putc('\n', stderr); + putc ('\n', stderr); #endif for (ri = 0; ri < d->tindex; ++ri) { @@ -3877,13 +3908,13 @@ dfamust (struct dfa *d) case LIMWORD: case NOTLIMWORD: case BACKREF: - resetmust(mp); + resetmust (mp); break; case STAR: case QMARK: assert (musts < mp); --mp; - resetmust(mp); + resetmust (mp); break; case OR: assert (&musts[2] <= mp); @@ -3891,7 +3922,7 @@ dfamust (struct dfa *d) char **new; must *lmp; must *rmp; - int j, ln, rn, n; + size_t j, ln, rn, n; rmp = --mp; lmp = --mp; @@ -3904,8 +3935,8 @@ dfamust (struct dfa *d) ++i; lmp->left[i] = '\0'; /* Right side */ - ln = strlen(lmp->right); - rn = strlen(rmp->right); + ln = strlen (lmp->right); + rn = strlen (rmp->right); n = ln; if (n > rn) n = rn; @@ -3915,11 +3946,11 @@ dfamust (struct dfa *d) for (j = 0; j < i; ++j) lmp->right[j] = lmp->right[(ln - i) + j]; lmp->right[j] = '\0'; - new = inboth(lmp->in, rmp->in); + new = inboth (lmp->in, rmp->in); if (new == NULL) goto done; - freelist(lmp->in); - free(lmp->in); + freelist (lmp->in); + free (lmp->in); lmp->in = new; } break; @@ -3931,7 +3962,7 @@ dfamust (struct dfa *d) case END: assert (mp == &musts[1]); for (i = 0; musts[0].in[i] != NULL; ++i) - if (strlen(musts[0].in[i]) > strlen(result)) + if (strlen (musts[0].in[i]) > strlen (result)) result = musts[0].in[i]; if (STREQ (result, musts[0].is)) exact = 1; @@ -3945,46 +3976,39 @@ dfamust (struct dfa *d) rmp = --mp; lmp = --mp; /* In. Everything in left, plus everything in - right, plus catenation of + right, plus concatenation of left's right and right's left. */ - lmp->in = addlists(lmp->in, rmp->in); + lmp->in = addlists (lmp->in, rmp->in); if (lmp->in == NULL) goto done; - if (lmp->right[0] != '\0' && - rmp->left[0] != '\0') + if (lmp->right[0] != '\0' && rmp->left[0] != '\0') { char *tp; - tp = icpyalloc(lmp->right); - if (tp == NULL) - goto done; - tp = icatalloc(tp, rmp->left); - if (tp == NULL) - goto done; - lmp->in = enlist(lmp->in, tp, - strlen(tp)); - free(tp); + tp = icpyalloc (lmp->right); + tp = icatalloc (tp, rmp->left); + lmp->in = enlist (lmp->in, tp, strlen (tp)); + free (tp); if (lmp->in == NULL) goto done; } /* Left-hand */ if (lmp->is[0] != '\0') { - lmp->left = icatalloc(lmp->left, - rmp->left); + lmp->left = icatalloc (lmp->left, rmp->left); if (lmp->left == NULL) goto done; } /* Right-hand */ if (rmp->is[0] == '\0') lmp->right[0] = '\0'; - lmp->right = icatalloc(lmp->right, rmp->right); + lmp->right = icatalloc (lmp->right, rmp->right); if (lmp->right == NULL) goto done; /* Guaranteed to be */ if (lmp->is[0] != '\0' && rmp->is[0] != '\0') { - lmp->is = icatalloc(lmp->is, rmp->is); + lmp->is = icatalloc (lmp->is, rmp->is); if (lmp->is == NULL) goto done; } @@ -4002,60 +4026,54 @@ dfamust (struct dfa *d) /* not on *my* shift */ goto done; } - else if (t >= CSET -#if MBS_SUPPORT - || t == ANYCHAR - || t == MBCSET -#endif /* MBS_SUPPORT */ - ) + else if (t >= CSET || !MBS_SUPPORT || t == ANYCHAR || t == MBCSET) { /* easy enough */ - resetmust(mp); + resetmust (mp); } else { /* plain character */ - resetmust(mp); + resetmust (mp); mp->is[0] = mp->left[0] = mp->right[0] = t; mp->is[1] = mp->left[1] = mp->right[1] = '\0'; - mp->in = enlist(mp->in, mp->is, (size_t)1); + mp->in = enlist (mp->in, mp->is, (size_t) 1); if (mp->in == NULL) goto done; } break; } #ifdef DEBUG - fprintf(stderr, " node: %d:", ri); - prtok(d->tokens[ri]); - fprintf(stderr, "\n in:"); + fprintf (stderr, " node: %zd:", ri); + prtok (d->tokens[ri]); + fprintf (stderr, "\n in:"); for (i = 0; mp->in[i]; ++i) - fprintf(stderr, " \"%s\"", mp->in[i]); - fprintf(stderr, "\n is: \"%s\"\n", mp->is); - fprintf(stderr, " left: \"%s\"\n", mp->left); - fprintf(stderr, " right: \"%s\"\n", mp->right); + fprintf (stderr, " \"%s\"", mp->in[i]); + fprintf (stderr, "\n is: \"%s\"\n", mp->is); + fprintf (stderr, " left: \"%s\"\n", mp->left); + fprintf (stderr, " right: \"%s\"\n", mp->right); #endif ++mp; } - done: - if (strlen(result)) +done: + if (strlen (result)) { - MALLOC(dm, struct dfamust, 1); + MALLOC (dm, 1); dm->exact = exact; - MALLOC(dm->must, char, strlen(result) + 1); - strcpy(dm->must, result); + dm->must = xmemdup (result, strlen (result) + 1); dm->next = d->musts; d->musts = dm; } mp = musts; for (i = 0; i <= d->tindex; ++i) { - freelist(mp[i].in); - free(mp[i].in); - free(mp[i].left); - free(mp[i].right); - free(mp[i].is); + freelist (mp[i].in); + free (mp[i].in); + free (mp[i].left); + free (mp[i].right); + free (mp[i].is); } - free(mp); + free (mp); } struct dfa * @@ -4064,7 +4082,7 @@ dfaalloc (void) return xmalloc (sizeof (struct dfa)); } -struct dfamust * +struct dfamust *_GL_ATTRIBUTE_PURE dfamusts (struct dfa const *d) { return d->musts; diff --git a/contrib/grep/src/dfa.h b/contrib/grep/src/dfa.h index 30d1739e70..96dd4b86e3 100644 --- a/contrib/grep/src/dfa.h +++ b/contrib/grep/src/dfa.h @@ -1,5 +1,5 @@ /* dfa.h - declarations for GNU deterministic regexp compiler - Copyright (C) 1988, 1998, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 1988, 1998, 2007, 2009-2012 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 @@ -18,10 +18,6 @@ /* Written June, 1988 by Mike Haertel */ -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__ -# define __attribute__(x) -#endif - /* Element of a list of strings, at least one of which is known to appear in any R.E. matching the DFA. */ struct dfamust @@ -67,7 +63,7 @@ extern void dfacomp (char const *, size_t, struct dfa *, int); encountered a back-reference (1) or not (0). The caller may use this to decide whether to fall back on a backtracking matcher. */ extern char *dfaexec (struct dfa *d, char const *begin, char *end, - int newline, int *count, int *backref); + int newline, size_t *count, int *backref); /* Free the storage held by the components of a struct dfa. */ extern void dfafree (struct dfa *); @@ -86,7 +82,7 @@ extern void dfaanalyze (struct dfa *, int); /* Compute, for each possible character, the transitions out of a given state, storing them in an array of integers. */ -extern void dfastate (int, struct dfa *, int []); +extern void dfastate (ptrdiff_t, struct dfa *, ptrdiff_t []); /* Error handling. */ @@ -99,4 +95,4 @@ extern void dfawarn (const char *); /* dfaerror() is called by the regexp routines whenever an error occurs. It takes a single argument, a NUL-terminated string describing the error. The user must supply a dfaerror. */ -extern void dfaerror (const char *) __attribute__ ((noreturn)); +extern _Noreturn void dfaerror (const char *); diff --git a/contrib/grep/src/dfasearch.c b/contrib/grep/src/dfasearch.c index 3471308712..bd09aa67b3 100644 --- a/contrib/grep/src/dfasearch.c +++ b/contrib/grep/src/dfasearch.c @@ -1,5 +1,5 @@ /* dfasearch.c - searching subroutines using dfa and regex for grep. - Copyright 1992, 1998, 2000, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright 1992, 1998, 2000, 2007, 2009-2012 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 @@ -19,6 +19,7 @@ /* Written August 1992 by Mike Haertel. */ #include +#include "intprops.h" #include "search.h" #include "dfa.h" @@ -71,21 +72,15 @@ dfawarn (char const *mesg) /* 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. */ -static int kwset_exact_matches; +static size_t kwset_exact_matches; static char const * kwsincr_case (const char *must) { - const char *buf; - size_t n; - - n = strlen (must); -#if MBS_SUPPORT - if (match_icase && MB_CUR_MAX > 1) - buf = mbtolower (must, &n); - else -#endif - buf = must; + size_t n = strlen (must); + const char *buf = (match_icase && MB_CUR_MAX > 1 + ? mbtolower (must, &n) + : must); return kwsincr (kwset, buf, n); } @@ -217,10 +212,11 @@ EGexecute (char const *buf, size_t size, size_t *match_size, { char const *buflim, *beg, *end, *match, *best_match, *mb_start; char eol = eolbyte; - int backref, start, len, best_len; + int backref; + regoff_t start; + ptrdiff_t len, best_len; struct kwsmatch kwsm; size_t i, ret_val; -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { if (match_icase) @@ -233,7 +229,6 @@ EGexecute (char const *buf, size_t size, size_t *match_size, buf = case_buf; } } -#endif /* MBS_SUPPORT */ mb_start = buf; buflim = buf + size; @@ -261,13 +256,14 @@ EGexecute (char const *buf, size_t size, size_t *match_size, --beg; if (kwsm.index < kwset_exact_matches) { -#if MBS_SUPPORT + if (!MBS_SUPPORT) + goto success; + if (mb_start < beg) mb_start = beg; if (MB_CUR_MAX == 1 || !is_mb_middle (&mb_start, match, buflim, kwsm.size[0])) -#endif goto success; } if (dfaexec (dfa, beg, (char *) end, 0, NULL, &backref) == NULL) @@ -301,6 +297,11 @@ EGexecute (char const *buf, size_t size, size_t *match_size, end = buflim; } + /* 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 - buf - 1) + xalloc_die (); + /* If we've made it to this point, this means DFA has seen a probable match, and we need to run it through Regex. */ best_match = end; @@ -308,10 +309,13 @@ EGexecute (char const *buf, size_t size, size_t *match_size, for (i = 0; i < pcount; i++) { patterns[i].regexbuf.not_eol = 0; - if (0 <= (start = re_search (&(patterns[i].regexbuf), - buf, end - buf - 1, - beg - buf, end - beg - 1, - &(patterns[i].regs)))) + start = re_search (&(patterns[i].regexbuf), + buf, end - buf - 1, + beg - buf, end - beg - 1, + &(patterns[i].regs)); + if (start < -1) + xalloc_die (); + else if (0 <= start) { len = patterns[i].regs.end[0] - start; match = buf + start; @@ -328,7 +332,7 @@ EGexecute (char const *buf, size_t size, size_t *match_size, } /* If -w, check if the match aligns with word boundaries. We do this iteratively because: - (a) the line may contain more than one occurence of the + (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 @@ -348,6 +352,8 @@ EGexecute (char const *buf, size_t size, size_t *match_size, len = re_match (&(patterns[i].regexbuf), buf, match + len - beg, match - buf, &(patterns[i].regs)); + if (len < -1) + xalloc_die (); } if (len <= 0) { @@ -361,7 +367,11 @@ EGexecute (char const *buf, size_t size, size_t *match_size, match - buf, end - match - 1, &(patterns[i].regs)); if (start < 0) - break; + { + if (start < -1) + xalloc_die (); + break; + } len = patterns[i].regs.end[0] - start; match = buf + start; } diff --git a/contrib/grep/src/egrep.c b/contrib/grep/src/egrep.c index f6a1d59673..7dfff09fd3 100644 --- a/contrib/grep/src/egrep.c +++ b/contrib/grep/src/egrep.c @@ -15,4 +15,4 @@ struct matcher const matchers[] = { const char before_options[] = N_("PATTERN is an extended regular expression (ERE).\n"); const char after_options[] = -N_("Invocation as `egrep' is deprecated; use `grep -E' instead.\n"); +N_("Invocation as 'egrep' is deprecated; use 'grep -E' instead.\n"); diff --git a/contrib/grep/src/fgrep.c b/contrib/grep/src/fgrep.c index f91e62669a..a0940cc33f 100644 --- a/contrib/grep/src/fgrep.c +++ b/contrib/grep/src/fgrep.c @@ -9,4 +9,4 @@ struct matcher const matchers[] = { const char before_options[] = N_("PATTERN is a set of newline-separated fixed strings.\n"); const char after_options[] = -N_("Invocation as `fgrep' is deprecated; use `grep -F' instead.\n"); +N_("Invocation as 'fgrep' is deprecated; use 'grep -F' instead.\n"); diff --git a/contrib/grep/src/grep.c b/contrib/grep/src/grep.c index e12ae3dc5d..1b2198fd35 100644 --- a/contrib/grep/src/grep.c +++ b/contrib/grep/src/grep.c @@ -31,5 +31,5 @@ struct matcher const matchers[] = { const char before_options[] = N_("PATTERN is, by default, a basic regular expression (BRE).\n"); const char after_options[] = -N_("`egrep' means `grep -E'. `fgrep' means `grep -F'.\n\ -Direct invocation as either `egrep' or `fgrep' is deprecated.\n"); +N_("'egrep' means 'grep -E'. 'fgrep' means 'grep -F'.\n\ +Direct invocation as either 'egrep' or 'fgrep' is deprecated.\n"); diff --git a/contrib/grep/src/grep.h b/contrib/grep/src/grep.h index 1fef4b6c26..f5ab8bfce4 100644 --- a/contrib/grep/src/grep.h +++ b/contrib/grep/src/grep.h @@ -1,5 +1,5 @@ /* grep.h - interface to grep driver for searching subroutines. - Copyright (C) 1992, 1998, 2001, 2007, 2009-2011 Free Software Foundation, + Copyright (C) 1992, 1998, 2001, 2007, 2009-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -20,10 +20,6 @@ #ifndef GREP_GREP_H #define GREP_GREP_H 1 -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__ -# define __attribute__(x) -#endif - /* Function pointer types. */ typedef void (*compile_fp_t) (char const *, size_t); typedef size_t (*execute_fp_t) (char const *, size_t, size_t *, char const *); diff --git a/contrib/grep/src/kwsearch.c b/contrib/grep/src/kwsearch.c index ead4a0e372..f1a802e783 100644 --- a/contrib/grep/src/kwsearch.c +++ b/contrib/grep/src/kwsearch.c @@ -1,5 +1,5 @@ /* kwsearch.c - searching subroutines using kwset for grep. - Copyright 1992, 1998, 2000, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright 1992, 1998, 2000, 2007, 2009-2012 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 @@ -32,21 +32,19 @@ static kwset_t kwset; void Fcompile (char const *pattern, size_t size) { - char const *beg, *end, *lim, *err, *pat; - size_t psize; + char const *err; + size_t psize = size; + char const *pat = (match_icase && MB_CUR_MAX > 1 + ? mbtolower (pattern, &psize) + : pattern); kwsinit (&kwset); - psize = size; -#if MBS_SUPPORT - if (match_icase && MB_CUR_MAX > 1) - pat = mbtolower (pattern, &psize); - else -#endif - pat = pattern; - beg = pat; + char const *beg = pat; do { + char const *lim; + char const *end; for (lim = beg;; ++lim) { end = lim; @@ -85,7 +83,6 @@ Fexecute (char const *buf, size_t size, size_t *match_size, char eol = eolbyte; struct kwsmatch kwsmatch; size_t ret_val; -#if MBS_SUPPORT if (MB_CUR_MAX > 1) { if (match_icase) @@ -96,7 +93,6 @@ Fexecute (char const *buf, size_t size, size_t *match_size, buf = case_buf; } } -#endif /* MBS_SUPPORT */ for (mb_start = beg = start_ptr ? start_ptr : buf; beg <= buf + size; beg++) { @@ -104,9 +100,8 @@ Fexecute (char const *buf, size_t size, size_t *match_size, if (offset == (size_t) -1) goto failure; len = kwsmatch.size[0]; -#if MBS_SUPPORT - if (MB_CUR_MAX > 1 && is_mb_middle (&mb_start, beg + offset, buf + size, - len)) + if (MB_CUR_MAX > 1 + && is_mb_middle (&mb_start, beg + offset, buf + size, len)) { /* The match was a part of multibyte character, advance at least one byte to ensure no infinite loop happens. */ @@ -120,7 +115,6 @@ Fexecute (char const *buf, size_t size, size_t *match_size, beg += mb_len - 1; continue; } -#endif /* MBS_SUPPORT */ beg += offset; if (start_ptr && !match_words) goto success_in_beg_and_len; diff --git a/contrib/grep/src/kwset.c b/contrib/grep/src/kwset.c index ba556bbcce..cd40953921 100644 --- a/contrib/grep/src/kwset.c +++ b/contrib/grep/src/kwset.c @@ -1,5 +1,5 @@ /* kwset.c - search for any of a set of keywords. - Copyright (C) 1989, 1998, 2000, 2005, 2007, 2009-2011 Free Software + Copyright (C) 1989, 1998, 2000, 2005, 2007, 2009-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ -/* The algorithm implemented by these routines bears a startling resemblence +/* The algorithm implemented by these routines bears a startling resemblance to one discovered by Beate Commentz-Walter, although it is not identical. See "A String Matching Algorithm Fast on the Average," Technical Report, IBM-Germany, Scientific Center Heidelberg, Tiergartenstrasse 15, D-6900 @@ -62,21 +62,21 @@ struct tree /* Node of a trie representing a set of reversed keywords. */ struct trie { - unsigned int accepting; /* Word index of accepted word, or zero. */ + size_t accepting; /* Word index of accepted word, or zero. */ 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. */ int depth; /* Depth of this node from the root. */ int shift; /* Shift function for search failures. */ - int maxshift; /* Max shift of self and descendents. */ + int maxshift; /* Max shift of self and descendants. */ }; /* Structure returned opaquely to the caller, containing everything. */ struct kwset { struct obstack obstack; /* Obstack for node allocation. */ - int words; /* Number of words in the trie. */ + ptrdiff_t words; /* Number of words in the trie. */ struct trie *trie; /* The trie itself. */ int mind; /* Minimum depth of an accepting node. */ int maxd; /* Maximum depth of any node. */ @@ -314,7 +314,7 @@ treefails (struct tree const *tree, struct trie const *fail, treefails(tree->rlink, fail, recourse); /* Find, in the chain of fails going back to the root, the first - node that has a descendent on the current label. */ + node that has a descendant on the current label. */ while (fail) { link = fail->links; @@ -350,7 +350,7 @@ treedelta (struct tree const *tree, } /* Return true if A has every label in B. */ -static int +static int _GL_ATTRIBUTE_PURE hasevery (struct tree const *a, struct tree const *b) { if (!b) @@ -432,16 +432,16 @@ kwsprep (kwset_t kws) computing the delta table, failure function, and shift function. */ for (curr = last = kwset->trie; curr; curr = curr->next) { - /* Enqueue the immediate descendents in the level order queue. */ + /* Enqueue the immediate descendants in the level order queue. */ enqueue(curr->links, &last); curr->shift = kwset->mind; curr->maxshift = kwset->mind; - /* Update the delta table for the descendents of this node. */ + /* Update the delta table for the descendants of this node. */ treedelta(curr->links, curr->depth, delta); - /* Compute the failure function for the decendents of this node. */ + /* Compute the failure function for the descendants of this node. */ treefails(curr->links, curr->fail, kwset->trie); /* Update the shifts at each node in the current node's chain @@ -456,7 +456,7 @@ kwsprep (kwset_t kws) fail->shift = curr->depth - fail->depth; /* If the current node is accepting then the shift at the - fail and its descendents should be no larger than 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; @@ -497,7 +497,7 @@ kwsprep (kwset_t kws) } /* Fast boyer-moore search. */ -static size_t +static size_t _GL_ATTRIBUTE_PURE bmexec (kwset_t kws, char const *text, size_t size) { struct kwset const *kwset; diff --git a/contrib/grep/src/kwset.h b/contrib/grep/src/kwset.h index 07cf4a42b4..01775e1b94 100644 --- a/contrib/grep/src/kwset.h +++ b/contrib/grep/src/kwset.h @@ -1,5 +1,5 @@ /* kwset.h - header declaring the keyword set library. - Copyright (C) 1989, 1998, 2005, 2007, 2009-2011 Free Software Foundation, + Copyright (C) 1989, 1998, 2005, 2007, 2009-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -23,7 +23,7 @@ struct kwsmatch { - int index; /* Index number of matching keyword. */ + size_t index; /* Index number of matching keyword. */ size_t offset[1]; /* Offset of each submatch. */ size_t size[1]; /* Length of each submatch. */ }; diff --git a/contrib/grep/src/main.c b/contrib/grep/src/main.c index 4e01a17769..c5a848980c 100644 --- a/contrib/grep/src/main.c +++ b/contrib/grep/src/main.c @@ -1,5 +1,5 @@ /* grep.c - main driver file for grep. - Copyright (C) 1992, 1997-2002, 2004-2011 Free Software Foundation, Inc. + Copyright (C) 1992, 1997-2002, 2004-2012 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 @@ -21,30 +21,29 @@ #include #include #include -#if defined HAVE_SETRLIMIT -# include -# include -#endif #include "mbsupport.h" #include #include #include +#include #include #include "system.h" #include "argmatch.h" #include "c-ctype.h" #include "closeout.h" +#include "colorize.h" #include "error.h" #include "exclude.h" #include "exitfail.h" +#include "fcntl-safer.h" +#include "fts_.h" #include "getopt.h" #include "grep.h" #include "intprops.h" -#include "isdir.h" #include "progname.h" #include "propername.h" -#include "savedir.h" +#include "quote.h" #include "version-etc.h" #include "xalloc.h" #include "xstrtol.h" @@ -59,14 +58,10 @@ proper_name ("Mike Haertel"), \ _("others, see ") -struct stats -{ - struct stats const *parent; - struct stat stat; -}; - -/* base of chain of stat buffers, used to detect directory loops */ -static struct stats stats_base; +/* 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; @@ -203,55 +198,64 @@ static const char *context_line_color = ""; /* default color pair */ 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"; -#define SGR_START sgr_start static const char *sgr_end = "\33[m\33[K"; -#define SGR_END sgr_end -/* SGR utility macros. */ -#define PR_SGR_FMT(fmt, s) do { if (*(s)) printf((fmt), (s)); } while (0) -#define PR_SGR_FMT_IF(fmt, s) \ - do { if (color_option && *(s)) printf((fmt), (s)); } while (0) -#define PR_SGR_START(s) PR_SGR_FMT( SGR_START, (s)) -#define PR_SGR_END(s) PR_SGR_FMT( SGR_END, (s)) -#define PR_SGR_START_IF(s) PR_SGR_FMT_IF(SGR_START, (s)) -#define PR_SGR_END_IF(s) PR_SGR_FMT_IF(SGR_END, (s)) +/* 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; - const char *(*fct)(void); + void (*fct) (void); }; -static const char * -color_cap_mt_fct(void) +static void +color_cap_mt_fct (void) { /* Our caller just set selected_match_color. */ context_match_color = selected_match_color; - - return NULL; } -static const char * -color_cap_rv_fct(void) +static void +color_cap_rv_fct (void) { /* By this point, it was 1 (or already -1). */ color_option = -1; /* That's still != 0. */ - - return NULL; } -static const char * -color_cap_ne_fct(void) +static void +color_cap_ne_fct (void) { sgr_start = "\33[%sm"; sgr_end = "\33[m"; - - return NULL; } /* For GREP_COLORS. */ -static struct color_cap color_dict[] = +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 */ @@ -334,7 +338,7 @@ static struct option const long_options[] = {"only-matching", no_argument, NULL, 'o'}, {"quiet", no_argument, NULL, 'q'}, {"recursive", no_argument, NULL, 'r'}, - {"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'}, @@ -354,9 +358,11 @@ int match_lines; unsigned char eolbyte; /* For error messages. */ -/* The name the program was run with, stripped of any leading path. */ +/* The input file name, or (if standard input) "-" or a --label argument. */ static char const *filename; +static size_t filename_prefix_len; static int errseen; +static int write_error_seen; enum directories_type { @@ -378,18 +384,29 @@ 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_DEVICES; + } devices = READ_COMMAND_LINE_DEVICES; -static int grepdir (char const *, struct stats const *); +static int grepfile (int, char const *, int, int); +static int grepdesc (int, int); #if defined HAVE_DOS_FILE_CONTENTS static inline int undossify_input (char *, size_t); #endif +static int +is_device_mode (mode_t m) +{ + return S_ISCHR (m) || S_ISBLK (m) || S_ISSOCK (m) || S_ISFIFO (m); +} + /* Functions we'll use to search. */ static compile_fp_t compile; static execute_fp_t execute; @@ -403,17 +420,30 @@ suppressible_error (char const *mesg, int errnum) errseen = 1; } -/* Convert STR to a positive integer, storing the result in *OUT. +/* 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 (! write_error_seen) + close_stdout (); +} + +/* 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. */ + 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, int *out) +context_length_arg (char const *str, intmax_t *out) { - uintmax_t value; - if (! (xstrtoumax (str, 0, 10, &value, "") == LONGINT_OK - && 0 <= (*out = value) - && *out == value)) + switch (xstrtoimax (str, 0, 10, out, "")) { + case LONGINT_OK: + case LONGINT_OVERFLOW: + if (0 <= *out) + break; + /* Fall through. */ + default: error (EXIT_TROUBLE, 0, "%s: %s", str, _("invalid context length argument")); } @@ -446,7 +476,7 @@ static off_t after_last_match; /* Pointer after last matching line that /* Reset the buffer for a new file, returning zero if we should skip it. Initialize on the first time through. */ static int -reset (int fd, char const *file, struct stats *stats) +reset (int fd, struct stat const *st) { if (! pagesize) { @@ -461,16 +491,16 @@ reset (int fd, char const *file, struct stats *stats) bufbeg[-1] = eolbyte; bufdesc = fd; - if (S_ISREG (stats->stat.st_mode)) + if (S_ISREG (st->st_mode)) { - if (file) + if (fd != STDIN_FILENO) bufoffset = 0; else { bufoffset = lseek (fd, 0, SEEK_CUR); if (bufoffset < 0) { - error (0, errno, _("lseek failed")); + suppressible_error (_("lseek failed"), errno); return 0; } } @@ -483,7 +513,7 @@ reset (int fd, char const *file, struct stats *stats) to the beginning of the buffer contents, and 'buflim' points just after the end. Return zero if there's an error. */ static int -fillbuf (size_t save, struct stats const *stats) +fillbuf (size_t save, struct stat const *st) { size_t fillsize = 0; int cc = 1; @@ -516,9 +546,9 @@ fillbuf (size_t save, struct stats const *stats) 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 (S_ISREG (stats->stat.st_mode)) + if (S_ISREG (st->st_mode)) { - off_t to_be_read = stats->stat.st_size - bufoffset; + 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 @@ -581,12 +611,12 @@ static int out_invert; /* Print nonmatching stuff. */ static int out_file; /* Print filenames. */ static int out_line; /* Print line numbers. */ static int out_byte; /* Print byte offsets. */ -static int out_before; /* Lines of leading context. */ -static int out_after; /* Lines of trailing context. */ +static intmax_t out_before; /* Lines of leading context. */ +static intmax_t out_after; /* Lines of trailing context. */ static int count_matches; /* Count matching lines. */ static int list_files; /* List matching files. */ static int no_filenames; /* Suppress file names. */ -static off_t max_count; /* Stop after outputting this many +static intmax_t max_count; /* Stop after outputting this many lines from an input file. */ static int line_buffered; /* If nonzero, use line buffering, i.e. fflush everyline out. */ @@ -600,8 +630,8 @@ static char const *lastout; /* Pointer after last character output; NULL if no character has been output or if it's conceptually before bufbeg. */ static uintmax_t totalnl; /* Total newline count before lastnl. */ -static off_t outleft; /* Maximum number of lines to be output. */ -static int pending; /* Pending lines of output. +static intmax_t outleft; /* Maximum number of lines to be output. */ +static intmax_t pending; /* Pending lines of output. Always kept 0 if out_quiet is true. */ static int done_on_match; /* Stop scanning file on first match. */ static int exit_on_match; /* Exit on first match. */ @@ -641,18 +671,18 @@ nlscan (char const *lim) static void print_filename (void) { - PR_SGR_START_IF(filename_color); - fputs(filename, stdout); - PR_SGR_END_IF(filename_color); + pr_sgr_start_if (filename_color); + fputs (filename, stdout); + pr_sgr_end_if (filename_color); } /* Print a character separator. */ static void print_sep (char sep) { - PR_SGR_START_IF(sep_color); - fputc(sep, stdout); - PR_SGR_END_IF(sep_color); + pr_sgr_start_if (sep_color); + fputc (sep, stdout); + pr_sgr_end_if (sep_color); } /* Print a line number or a byte offset. */ @@ -677,9 +707,9 @@ print_offset (uintmax_t pos, int min_width, const char *color) while (--min_width >= 0) *--p = ' '; - PR_SGR_START_IF(color); + pr_sgr_start_if (color); fwrite (p, 1, buf + sizeof buf - p, stdout); - PR_SGR_END_IF(color); + pr_sgr_end_if (color); } /* Print a whole line head (filename, line, byte). */ @@ -690,11 +720,11 @@ print_line_head (char const *beg, char const *lim, int sep) if (out_file) { - print_filename(); + print_filename (); if (filename_mask) pending_sep = 1; else - fputc(0, stdout); + fputc (0, stdout); } if (out_line) @@ -706,7 +736,7 @@ print_line_head (char const *beg, char const *lim, int sep) lastnl = lim; } if (pending_sep) - print_sep(sep); + print_sep (sep); print_offset (totalnl, 4, line_num_color); pending_sep = 1; } @@ -718,7 +748,7 @@ print_line_head (char const *beg, char const *lim, int sep) pos = dossified_pos (pos); #endif if (pending_sep) - print_sep(sep); + print_sep (sep); print_offset (pos, 6, byte_num_color); pending_sep = 1; } @@ -730,9 +760,9 @@ print_line_head (char const *beg, char const *lim, int sep) (and its combining and wide characters) filenames and you're wasting your efforts. */ if (align_tabs) - fputs("\t\b", stdout); + fputs ("\t\b", stdout); - print_sep(sep); + print_sep (sep); } } @@ -746,8 +776,8 @@ print_line_middle (const char *beg, const char *lim, const char *mid = NULL; while (cur < lim - && ((match_offset = execute(beg, lim - beg, &match_size, - beg + (cur - beg))) != (size_t) -1)) + && ((match_offset = execute (beg, lim - beg, &match_size, + beg + (cur - beg))) != (size_t) -1)) { char const *b = beg + match_offset; @@ -769,11 +799,11 @@ print_line_middle (const char *beg, const char *lim, /* This function is called on a matching line only, but is it selected or rejected/context? */ if (only_matching) - print_line_head(b, lim, out_invert ? SEP_CHAR_REJECTED - : SEP_CHAR_SELECTED); + print_line_head (b, lim, (out_invert ? SEP_CHAR_REJECTED + : SEP_CHAR_SELECTED)); else { - PR_SGR_START(line_color); + pr_sgr_start (line_color); if (mid) { cur = mid; @@ -782,11 +812,11 @@ print_line_middle (const char *beg, const char *lim, fwrite (cur, sizeof (char), b - cur, stdout); } - PR_SGR_START_IF(match_color); + pr_sgr_start_if (match_color); fwrite (b, sizeof (char), match_size, stdout); - PR_SGR_END_IF(match_color); + pr_sgr_end_if (match_color); if (only_matching) - fputs("\n", stdout); + fputs ("\n", stdout); } cur = b + match_size; } @@ -802,7 +832,7 @@ print_line_middle (const char *beg, const char *lim, static const char * print_line_tail (const char *beg, const char *lim, const char *line_color) { - size_t eol_size; + size_t eol_size; size_t tail_size; eol_size = (lim > beg && lim[-1] == eolbyte); @@ -811,10 +841,10 @@ print_line_tail (const char *beg, const char *lim, const char *line_color) if (tail_size > 0) { - PR_SGR_START(line_color); - fwrite(beg, 1, tail_size, stdout); + pr_sgr_start (line_color); + fwrite (beg, 1, tail_size, stdout); beg += tail_size; - PR_SGR_END(line_color); + pr_sgr_end (line_color); } return beg; @@ -828,38 +858,41 @@ prline (char const *beg, char const *lim, int sep) const char *match_color; if (!only_matching) - print_line_head(beg, lim, sep); + print_line_head (beg, lim, sep); matching = (sep == SEP_CHAR_SELECTED) ^ !!out_invert; if (color_option) { - line_color = ( (sep == SEP_CHAR_SELECTED) + 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; + ? 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) + 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); + beg = print_line_middle (beg, lim, line_color, match_color); /* FIXME: this test may be removable. */ if (!only_matching && *line_color) - beg = print_line_tail(beg, lim, line_color); + beg = print_line_tail (beg, lim, line_color); } if (!only_matching && lim > beg) fwrite (beg, 1, lim - beg, stdout); if (ferror (stdout)) - error (0, errno, _("writing output")); + { + write_error_seen = 1; + error (EXIT_TROUBLE, 0, _("write error")); + } lastout = lim; @@ -880,8 +913,8 @@ prpending (char const *lim) size_t match_size; --pending; if (outleft - || ((execute(lastout, nl + 1 - lastout, - &match_size, NULL) == (size_t) -1) + || ((execute (lastout, nl + 1 - lastout, + &match_size, NULL) == (size_t) -1) == !out_invert)) prline (lastout, nl + 1, SEP_CHAR_REJECTED); else @@ -892,12 +925,12 @@ prpending (char const *lim) /* Print the lines between BEG and LIM. Deal with context crap. If NLINESP is non-null, store a count of lines between BEG and LIM. */ static void -prtext (char const *beg, char const *lim, int *nlinesp) +prtext (char const *beg, char const *lim, intmax_t *nlinesp) { static int used; /* avoid printing SEP_STR_GROUP before any output */ char const *bp, *p; char eol = eolbyte; - int i, n; + intmax_t i, n; if (!out_quiet && pending > 0) prpending (beg); @@ -919,10 +952,10 @@ prtext (char const *beg, char const *lim, int *nlinesp) discontiguous from the last output in the file. */ if ((out_before || out_after) && used && p != lastout && group_separator) { - PR_SGR_START_IF(sep_color); + pr_sgr_start_if (sep_color); fputs (group_separator, stdout); - PR_SGR_END_IF(sep_color); - fputc('\n', stdout); + pr_sgr_end_if (sep_color); + fputc ('\n', stdout); } while (p < beg) @@ -950,9 +983,8 @@ prtext (char const *beg, char const *lim, int *nlinesp) /* relying on it that this function is never called when outleft = 0. */ after_last_match = bufoffset - (buflim - p); } - else - if (!out_quiet) - prline (beg, lim, SEP_CHAR_SELECTED); + else if (!out_quiet) + prline (beg, lim, SEP_CHAR_SELECTED); pending = out_quiet ? 0 : out_after; used = 1; @@ -977,7 +1009,7 @@ do_execute (char const *buf, size_t size, size_t *match_size, char const *start_ perform the memchr if line-by-line matching is necessary, or just return buf + size otherwise. */ if (MB_CUR_MAX == 1 || !match_icase) - return execute(buf, size, match_size, start_ptr); + return execute (buf, size, match_size, start_ptr); for (line_next = buf; line_next < buf + size; ) { @@ -1002,18 +1034,18 @@ do_execute (char const *buf, size_t size, size_t *match_size, char const *start_ /* Scan the specified portion of the buffer, matching lines (or between matching lines if OUT_INVERT is true). Return a count of lines printed. */ -static int +static intmax_t grepbuf (char const *beg, char const *lim) { - int nlines, n; + intmax_t nlines, n; char const *p; size_t match_offset; size_t match_size; nlines = 0; p = beg; - while ((match_offset = do_execute(p, lim - p, &match_size, - NULL)) != (size_t) -1) + while ((match_offset = do_execute (p, lim - p, &match_size, + NULL)) != (size_t) -1) { char const *b = p + match_offset; char const *endp = b + match_size; @@ -1022,7 +1054,7 @@ grepbuf (char const *beg, char const *lim) break; if (!out_invert) { - prtext (b, endp, (int *) 0); + prtext (b, endp, NULL); nlines++; outleft--; if (!outleft || done_on_match) @@ -1055,10 +1087,10 @@ grepbuf (char const *beg, char const *lim) /* Search a given file. Normally, return a count of lines printed; but if the file is a directory and we search it recursively, then return -2 if there was a match, and -1 otherwise. */ -static int -grep (int fd, char const *file, struct stats *stats) +static intmax_t +grep (int fd, struct stat const *st) { - int nlines, i; + intmax_t nlines, i; int not_text; size_t residue, save; char oldc; @@ -1066,19 +1098,9 @@ grep (int fd, char const *file, struct stats *stats) char *lim; char eol = eolbyte; - if (!reset (fd, file, stats)) + if (! reset (fd, st)) return 0; - if (file && directories == RECURSE_DIRECTORIES - && S_ISDIR (stats->stat.st_mode)) - { - /* Close fd now, so that we don't open a lot of file descriptors - when we recurse deeply. */ - if (close (fd) != 0) - error (0, errno, "%s", file); - return grepdir (file, stats) - 2; - } - totalcc = 0; lastout = 0; totalnl = 0; @@ -1090,10 +1112,9 @@ grep (int fd, char const *file, struct stats *stats) residue = 0; save = 0; - if (! fillbuf (save, stats)) + if (! fillbuf (save, st)) { - if (! is_EISDIR (errno, file)) - suppressible_error (filename, errno); + suppressible_error (filename, errno); return 0; } @@ -1135,7 +1156,7 @@ grep (int fd, char const *file, struct stats *stats) nlines += grepbuf (beg, lim); if (pending) prpending (lim); - if((!outleft && !pending) || (nlines && done_on_match && !out_invert)) + if ((!outleft && !pending) || (nlines && done_on_match && !out_invert)) goto finish_grep; } @@ -1162,10 +1183,9 @@ grep (int fd, char const *file, struct stats *stats) totalcc = add_count (totalcc, buflim - bufbeg - save); if (out_line) nlscan (beg); - if (! fillbuf (save, stats)) + if (! fillbuf (save, st)) { - if (! is_EISDIR (errno, file)) - suppressible_error (filename, errno); + suppressible_error (filename, errno); goto finish_grep; } } @@ -1187,72 +1207,199 @@ grep (int fd, char const *file, struct stats *stats) } static int -grepfile (char const *file, struct stats *stats) +grepdirent (FTS *fts, FTSENT *ent) { - int desc; - int count; - int status; + int follow, dirdesc; + int command_line = ent->fts_level == FTS_ROOTLEVEL; + struct stat *st = ent->fts_statp; - if (! file) + if (ent->fts_info == FTS_DP) { - desc = 0; - filename = label ? label : _("(standard input)"); + if (directories == RECURSE_DIRECTORIES && command_line) + out_file &= ~ (2 * !no_filenames); + return 1; } - else + + if ((ent->fts_info == FTS_D || ent->fts_info == FTS_DC + || ent->fts_info == FTS_DNR) + ? (directories == SKIP_DIRECTORIES + || (! (command_line && filename_prefix_len != 0) + && excluded_directory_patterns + && excluded_file_name (excluded_directory_patterns, + ent->fts_name))) + : ((included_patterns + && excluded_file_name (included_patterns, ent->fts_name)) + || (excluded_patterns + && excluded_file_name (excluded_patterns, ent->fts_name)))) { - if (stat (file, &stats->stat) != 0) + fts_set (fts, ent, FTS_SKIP); + return 1; + } + + filename = ent->fts_path + filename_prefix_len; + follow = (fts->fts_options & FTS_LOGICAL + || (fts->fts_options & FTS_COMFOLLOW && command_line)); + + switch (ent->fts_info) + { + case FTS_D: + if (directories == RECURSE_DIRECTORIES) { - suppressible_error (file, errno); + out_file |= 2 * !no_filenames; return 1; } - if (directories == SKIP_DIRECTORIES && S_ISDIR (stats->stat.st_mode)) - return 1; - if (devices == SKIP_DEVICES && (S_ISCHR (stats->stat.st_mode) - || S_ISBLK (stats->stat.st_mode) - || S_ISSOCK (stats->stat.st_mode) - || S_ISFIFO (stats->stat.st_mode))) - return 1; - while ((desc = open (file, O_RDONLY)) < 0 && errno == EINTR) - continue; - - if (desc < 0) + fts_set (fts, ent, FTS_SKIP); + break; + + case FTS_DC: + if (!suppress_errors) + error (0, 0, _("warning: %s: %s"), filename, + _("recursive directory loop")); + return 1; + + case FTS_DNR: + case FTS_ERR: + case FTS_NS: + suppressible_error (filename, ent->fts_errno); + return 1; + + case FTS_DEFAULT: + case FTS_NSOK: + if (devices == SKIP_DEVICES + || (devices == READ_COMMAND_LINE_DEVICES && !command_line)) { - int e = errno; - - if (is_EISDIR (e, file) && directories == RECURSE_DIRECTORIES) + struct stat st1; + if (! st->st_mode) { - if (stat (file, &stats->stat) != 0) + /* 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) { - error (0, errno, "%s", file); + suppressible_error (filename, errno); return 1; } - - return grepdir (file, stats); + st = &st1; } + if (is_device_mode (st->st_mode)) + return 1; + } + break; - if (!suppress_errors) - { - if (directories == SKIP_DIRECTORIES) - switch (e) - { -#if defined EISDIR - case EISDIR: - return 1; -#endif - case EACCES: - /* When skipping directories, don't worry about - directories that can't be opened. */ - if (isdir (file)) - return 1; - break; - } - } + case FTS_F: + case FTS_SLNONE: + break; - suppressible_error (file, e); - return 1; - } + case FTS_SL: + case FTS_W: + return 1; + + default: + abort (); + } + + dirdesc = ((fts->fts_options & (FTS_NOCHDIR | FTS_CWDFD)) == FTS_CWDFD + ? fts->fts_cwd_fd + : AT_FDCWD); + return grepfile (dirdesc, ent->fts_accpath, follow, command_line); +} + +static int +grepfile (int dirdesc, char const *name, int follow, int command_line) +{ + int desc = openat_safer (dirdesc, name, O_RDONLY | (follow ? 0 : O_NOFOLLOW)); + if (desc < 0) + { + if (follow || (errno != ELOOP && errno != EMLINK)) + suppressible_error (filename, errno); + return 1; + } + return grepdesc (desc, command_line); +} + +static int +grepdesc (int desc, int command_line) +{ + intmax_t count; + int status = 1; + 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 (filename, errno); + goto closeout; + } + 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 (filename, errno); + + fts_arg[0] = (char *) filename; + fts_arg[1] = NULL; + fts = fts_open (fts_arg, opts, NULL); - filename = file; + if (!fts) + xalloc_die (); + while ((ent = fts_read (fts))) + status &= grepdirent (fts, ent); + if (errno) + suppressible_error (filename, errno); + if (fts_close (fts) != 0) + suppressible_error (filename, 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 == 0 && 1 < max_count + && S_ISREG (out_stat.st_mode) && out_stat.st_ino + && SAME_INODE (st, out_stat)) + { + if (! suppress_errors) + error (0, 0, _("input file %s is also the output"), quote (filename)); + errseen = 1; + goto closeout; } #if defined SET_BINARY @@ -1262,7 +1409,7 @@ grepfile (char const *file, struct stats *stats) SET_BINARY (desc); #endif - count = grep (desc, file, stats); + count = grep (desc, &st); if (count < 0) status = count + 2; else @@ -1271,106 +1418,54 @@ grepfile (char const *file, struct stats *stats) { if (out_file) { - print_filename(); + print_filename (); if (filename_mask) - print_sep(SEP_CHAR_SELECTED); + print_sep (SEP_CHAR_SELECTED); else - fputc(0, stdout); + fputc (0, stdout); } - printf ("%d\n", count); + printf ("%" PRIdMAX "\n", count); } status = !count; if (list_files == 1 - 2 * status) { - print_filename(); - fputc('\n' & filename_mask, stdout); + print_filename (); + fputc ('\n' & filename_mask, stdout); } - if (! file) + if (desc == STDIN_FILENO) { off_t required_offset = outleft ? bufoffset : after_last_match; if (required_offset != bufoffset && lseek (desc, required_offset, SEEK_SET) < 0 - && S_ISREG (stats->stat.st_mode)) - error (0, errno, "%s", filename); + && S_ISREG (st.st_mode)) + suppressible_error (filename, errno); } - else - while (close (desc) != 0) - if (errno != EINTR) - { - error (0, errno, "%s", file); - break; - } } + closeout: + if (desc != STDIN_FILENO && close (desc) != 0) + suppressible_error (filename, errno); return status; } static int -grepdir (char const *dir, struct stats const *stats) +grep_command_line_arg (char const *arg) { - struct stats const *ancestor; - char *name_space; - int status = 1; - if ( excluded_directory_patterns && - excluded_file_name (excluded_directory_patterns, dir) ) { - return 1; - } - - - /* Mingw32 does not support st_ino. No known working hosts use zero - for st_ino, so assume that the Mingw32 bug applies if it's zero. */ - if (stats->stat.st_ino) - for (ancestor = stats; (ancestor = ancestor->parent) != 0; ) - if (ancestor->stat.st_ino == stats->stat.st_ino - && ancestor->stat.st_dev == stats->stat.st_dev) - { - if (!suppress_errors) - error (0, 0, _("warning: %s: %s"), dir, - _("recursive directory loop")); - return 1; - } - - name_space = savedir (dir, stats->stat.st_size, included_patterns, - excluded_patterns, excluded_directory_patterns); - - if (! name_space) + if (STREQ (arg, "-")) { - if (errno) - suppressible_error (dir, errno); - else - xalloc_die (); + filename = label ? label : _("(standard input)"); + return grepdesc (STDIN_FILENO, 1); } else { - size_t dirlen = strlen (dir); - int needs_slash = ! (dirlen == FILE_SYSTEM_PREFIX_LEN (dir) - || ISSLASH (dir[dirlen - 1])); - char *file = NULL; - char const *namep = name_space; - struct stats child; - child.parent = stats; - out_file += !no_filenames; - while (*namep) - { - size_t namelen = strlen (namep); - file = xrealloc (file, dirlen + 1 + namelen + 1); - strcpy (file, dir); - file[dirlen] = '/'; - strcpy (file + dirlen + needs_slash, namep); - namep += namelen + 1; - status &= grepfile (file, &child); - } - out_file -= !no_filenames; - free (file); - free (name_space); + filename = arg; + return grepfile (AT_FDCWD, arg, 1, 1); } - - return status; } -void usage (int status) __attribute__ ((noreturn)); +_Noreturn void usage (int); void usage (int status) { @@ -1378,7 +1473,7 @@ usage (int status) { fprintf (stderr, _("Usage: %s [OPTION]... PATTERN [FILE]...\n"), program_name); - fprintf (stderr, _("Try `%s --help' for more information.\n"), + fprintf (stderr, _("Try '%s --help' for more information.\n"), program_name); } else @@ -1386,7 +1481,7 @@ usage (int status) printf (_("Usage: %s [OPTION]... PATTERN [FILE]...\n"), program_name); printf (_("\ Search for PATTERN in each FILE or standard input.\n")); - printf ("%s", gettext (before_options)); + fputs (_(before_options), stdout); printf (_("\ Example: %s -i 'hello world' menu.h main.c\n\ \n\ @@ -1412,7 +1507,7 @@ Miscellaneous:\n\ -v, --invert-match select non-matching lines\n\ -V, --version print version information and exit\n\ --help display this help and exit\n\ - --mmap ignored for backwards compatibility\n")); + --mmap deprecated no-op; evokes a warning\n")); printf (_("\ \n\ Output control:\n\ @@ -1420,9 +1515,9 @@ Output control:\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 the filename for each match\n\ - -h, --no-filename suppress the prefixing filename on output\n\ - --label=LABEL print LABEL as filename for standard input\n\ + -H, --with-filename print the file name for each match\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 the part of a line matching PATTERN\n\ @@ -1437,7 +1532,8 @@ Output control:\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, -r, --recursive equivalent to --directories=recurse\n\ + -r, --recursive like --directories=recurse\n\ + -R, --dereference-recursive likewise, but follow all symlinks\n\ ")); printf (_("\ --include=FILE_PATTERN search only files that match FILE_PATTERN\n\ @@ -1463,14 +1559,16 @@ Context control:\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)\n\ - -u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS)\n\ + -U, --binary do not strip CR characters at EOL (MSDOS/Windows)\n\ + -u, --unix-byte-offsets report offsets as if CRs were not there\n\ + (MSDOS/Windows)\n\ \n")); - printf ("%s", _(after_options)); + fputs (_(after_options), stdout); printf (_("\ -With no FILE, or when FILE is -, read standard input. If less than two FILEs\n\ -are given, assume -h. Exit status is 0 if any line was selected, 1 otherwise;\n\ -if any error occurs and -q was not given, the exit status is 2.\n")); +When FILE is -, read standard input. With no FILE, read . if a command-line\n\ +-r is given, - otherwise. If fewer than two FILEs are given, 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")); printf (_("\nReport bugs to: %s\n"), PACKAGE_BUGREPORT); printf (_("GNU Grep home page: <%s>\n"), "http://www.gnu.org/software/grep/"); @@ -1525,50 +1623,17 @@ setmatcher (char const *m) } } -static void -set_limits(void) -{ -#if defined HAVE_SETRLIMIT && defined RLIMIT_STACK - struct rlimit rlim; - - /* I think every platform needs to do this, so that regex.c - doesn't oveflow the stack. The default value of - `re_max_failures' is too large for some platforms: it needs - more than 3MB-large stack. - - The test for HAVE_SETRLIMIT should go into `configure'. */ - if (!getrlimit (RLIMIT_STACK, &rlim)) - { - long newlim; - extern long int re_max_failures; /* from regex.c */ - - /* Approximate the amount regex.c needs, plus some more. */ - newlim = re_max_failures * 2 * 20 * sizeof (char *); - if (newlim > rlim.rlim_max) - { - newlim = rlim.rlim_max; - re_max_failures = newlim / (2 * 20 * sizeof (char *)); - } - if (rlim.rlim_cur < newlim) - { - rlim.rlim_cur = newlim; - setrlimit (RLIMIT_STACK, &rlim); - } - } -#endif -} - /* Find the white-space-separated options specified by OPTIONS, and using BUF to store copies of these options, set ARGV[0], ARGV[1], etc. to the option copies. Return the number N of options found. Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0] etc. Backslash can be used to escape whitespace (and backslashes). */ -static int +static size_t prepend_args (char const *options, char *buf, char **argv) { char const *o = options; char *b = buf; - int n = 0; + size_t n = 0; for (;;) { @@ -1591,24 +1656,31 @@ prepend_args (char const *options, char *buf, char **argv) /* Prepend the whitespace-separated options in OPTIONS to the argument vector of a main program with argument count *PARGC and argument - vector *PARGV. */ -static void + vector *PARGV. Return the number of options prepended. */ +static int prepend_default_options (char const *options, int *pargc, char ***pargv) { if (options && *options) { char *buf = xmalloc (strlen (options) + 1); - int prepended = prepend_args (options, buf, (char **) NULL); + size_t prepended = prepend_args (options, buf, NULL); int argc = *pargc; - char * const *argv = *pargv; - char **pp = xmalloc ((prepended + argc + 1) * sizeof *pp); + char *const *argv = *pargv; + char **pp; + enum { MAX_ARGS = MIN (INT_MAX, SIZE_MAX / sizeof *pp - 1) }; + if (MAX_ARGS - argc < prepended) + xalloc_die (); + pp = xmalloc ((prepended + argc + 1) * sizeof *pp); *pargc = prepended + argc; *pargv = pp; *pp++ = *argv++; pp += prepend_args (options, buf, pp); while ((*pp++ = *argv++)) continue; + return prepended; } + + return 0; } /* Get the next non-digit option from ARGC and ARGV. @@ -1616,11 +1688,11 @@ prepend_default_options (char const *options, int *pargc, char ***pargv) 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, int *default_context) +get_nondigit_option (int argc, char *const *argv, intmax_t *default_context) { static int prev_digit_optind = -1; int opt, this_digit_optind, was_digit; - char buf[sizeof (uintmax_t) * CHAR_BIT + 4]; + char buf[INT_BUFSIZE_BOUND (intmax_t) + 4]; char *p = buf; was_digit = 0; @@ -1677,12 +1749,12 @@ parse_grep_colors (void) char *name; char *val; - p = getenv("GREP_COLORS"); /* Plural! */ + p = getenv ("GREP_COLORS"); /* Plural! */ if (p == NULL || *p == '\0') return; /* Work off a writable copy. */ - q = xstrdup(p); + q = xstrdup (p); name = q; val = NULL; @@ -1691,7 +1763,7 @@ parse_grep_colors (void) if (*q == ':' || *q == '\0') { char c = *q; - struct color_cap *cap; + struct color_cap const *cap; *q++ = '\0'; /* Terminate name or val. */ /* Empty name without val (empty cap) @@ -1700,29 +1772,10 @@ parse_grep_colors (void) if (STREQ (cap->name, name)) break; /* If name unknown, go on for forward compatibility. */ - if (cap->name) - { - if (cap->var) - { - if (val) - *(cap->var) = val; - else - error(0, 0, _("in GREP_COLORS=\"%s\", the \"%s\" capacity " - "needs a value (\"=...\"); skipped"), p, name); - } - else if (val) - error(0, 0, _("in GREP_COLORS=\"%s\", the \"%s\" capacity " - "is boolean and cannot take a value (\"=%s\"); skipped"), - p, name, val); - } + if (cap->var && val) + *(cap->var) = val; if (cap->fct) - { - const char *err_str = cap->fct(); - - if (err_str) - error(0, 0, _("in GREP_COLORS=\"%s\", the \"%s\" capacity %s"), - p, name, err_str); - } + cap->fct (); if (c == '\0') return; name = q; @@ -1731,7 +1784,7 @@ parse_grep_colors (void) else if (*q == '=') { if (q == name || val) - goto ill_formed; + return; *q++ = '\0'; /* Terminate name. */ val = q; /* Can be the empty string. */ } @@ -1740,11 +1793,7 @@ parse_grep_colors (void) else if (*q == ';' || (*q >= '0' && *q <= '9')) q++; /* Accumulate val. Protect the terminal from being sent crap. */ else - goto ill_formed; - - ill_formed: - error(0, 0, _("stopped processing of ill-formed GREP_COLORS=\"%s\" " - "at remaining substring \"%s\""), p, q); + return; } int @@ -1753,10 +1802,11 @@ main (int argc, char **argv) char *keys; size_t keycc, oldcc, keyalloc; int with_filenames; - int opt, cc, status; - int default_context; + size_t cc; + int opt, status, prepended; + int prev_optind, last_recursive; + intmax_t default_context; FILE *fp; - exit_failure = EXIT_TROUBLE; initialize_main (&argc, &argv); set_program_name (argv[0]); @@ -1768,11 +1818,11 @@ main (int argc, char **argv) eolbyte = '\n'; filename_mask = ~0; - max_count = TYPE_MAXIMUM (off_t); + max_count = INTMAX_MAX; /* The value -1 means to use DEFAULT_CONTEXT. */ out_after = out_before = -1; - /* Default before/after context: chaged by -C/-NUM options */ + /* Default before/after context: changed by -C/-NUM options */ default_context = 0; /* Changed by -o option */ only_matching = 0; @@ -1787,12 +1837,14 @@ main (int argc, char **argv) #endif exit_failure = EXIT_TROUBLE; - atexit (close_stdout); + atexit (clean_up_stdout); - prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv); + last_recursive = 0; + prepended = prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv); setmatcher (NULL); - while ((opt = get_nondigit_option (argc, argv, &default_context)) != -1) + while (prev_optind = optind, + (opt = get_nondigit_option (argc, argv, &default_context)) != -1) switch (opt) { case 'A': @@ -1882,6 +1934,8 @@ main (int argc, char **argv) case 'd': directories = XARGMATCH ("--directories", optarg, directories_args, directories_types); + if (directories == RECURSE_DIRECTORIES) + last_recursive = prev_optind; break; case 'e': @@ -1905,10 +1959,10 @@ main (int argc, char **argv) { keycc += cc; if (keycc == keyalloc - 1) - keys = xrealloc (keys, keyalloc *= 2); + keys = x2nrealloc (keys, &keyalloc, sizeof *keys); } if (fp != stdin) - fclose(fp); + fclose (fp); /* Append final newline if file ended in non-newline. */ if (oldcc != keycc && keys[keycc - 1] != '\n') keys[keycc++] = '\n'; @@ -1935,23 +1989,15 @@ main (int argc, char **argv) break; case 'm': - { - uintmax_t value; - switch (xstrtoumax (optarg, 0, 10, &value, "")) - { - case LONGINT_OK: - max_count = value; - if (0 <= max_count && max_count == value) - break; - /* Fall through. */ - case LONGINT_OVERFLOW: - max_count = TYPE_MAXIMUM (off_t); - break; - - default: - error (EXIT_TROUBLE, 0, _("invalid max count")); - } - } + switch (xstrtoimax (optarg, 0, 10, &max_count, "")) + { + case LONGINT_OK: + case LONGINT_OVERFLOW: + break; + + default: + error (EXIT_TROUBLE, 0, _("invalid max count")); + } break; case 'n': @@ -1968,8 +2014,11 @@ main (int argc, char **argv) break; case 'R': + fts_options = basic_fts_options | FTS_LOGICAL; + /* Fall through. */ case 'r': directories = RECURSE_DIRECTORIES; + last_recursive = prev_optind; break; case 's': @@ -2008,29 +2057,22 @@ main (int argc, char **argv) break; case COLOR_OPTION: - if(optarg) { - if(!strcasecmp(optarg, "always") || !strcasecmp(optarg, "yes") || - !strcasecmp(optarg, "force")) - color_option = 1; - else if(!strcasecmp(optarg, "never") || !strcasecmp(optarg, "no") || - !strcasecmp(optarg, "none")) - color_option = 0; - else if(!strcasecmp(optarg, "auto") || !strcasecmp(optarg, "tty") || - !strcasecmp(optarg, "if-tty")) - color_option = 2; - else - show_help = 1; - } else - color_option = 2; - if (color_option == 2) + if (optarg) { - char const *t; - if (isatty (STDOUT_FILENO) && (t = getenv ("TERM")) - && !STREQ (t, "dumb")) + if (!strcasecmp (optarg, "always") || !strcasecmp (optarg, "yes") + || !strcasecmp (optarg, "force")) color_option = 1; - else + else if (!strcasecmp (optarg, "never") || !strcasecmp (optarg, "no") + || !strcasecmp (optarg, "none")) color_option = 0; + else if (!strcasecmp (optarg, "auto") || !strcasecmp (optarg, "tty") + || !strcasecmp (optarg, "if-tty")) + color_option = 2; + else + show_help = 1; } + else + color_option = 2; break; case EXCLUDE_OPTION: @@ -2074,6 +2116,9 @@ main (int argc, char **argv) break; case MMAP_OPTION: + error (0, 0, _("the --mmap option has been a no-op since 2010")); + break; + case 0: /* long options */ break; @@ -2084,6 +2129,10 @@ main (int argc, char **argv) } + if (color_option == 2) + color_option = isatty (STDOUT_FILENO) && should_colorize (); + init_colorize (); + /* POSIX.2 says that -q overrides -l, which in turn overrides the other output options. */ if (exit_on_match) @@ -2108,19 +2157,23 @@ main (int argc, char **argv) selected_match_color = context_match_color = userval; /* New GREP_COLORS has priority. */ - parse_grep_colors(); + parse_grep_colors (); } if (show_version) { - version_etc (stdout, program_name, PACKAGE_NAME, VERSION, AUTHORS, \ - (char *) NULL); \ - exit (EXIT_SUCCESS); \ + version_etc (stdout, program_name, PACKAGE_NAME, VERSION, AUTHORS, + (char *) NULL); + exit (EXIT_SUCCESS); } if (show_help) usage (EXIT_SUCCESS); + struct stat tmp_stat; + if (fstat (STDOUT_FILENO, &tmp_stat) == 0 && S_ISREG (tmp_stat.st_mode)) + out_stat = tmp_stat; + if (keys) { if (keycc == 0) @@ -2133,19 +2186,17 @@ main (int argc, char **argv) /* Strip trailing newline. */ --keycc; } + else if (optind < argc) + { + /* A copy must be made in case of an xrealloc() or free() later. */ + keycc = strlen (argv[optind]); + keys = xmalloc (keycc + 1); + strcpy (keys, argv[optind++]); + } else - if (optind < argc) - { - /* A copy must be made in case of an xrealloc() or free() later. */ - keycc = strlen(argv[optind]); - keys = xmalloc(keycc + 1); - strcpy(keys, argv[optind++]); - } - else - usage (EXIT_TROUBLE); + usage (EXIT_TROUBLE); - set_limits(); - compile(keys, keycc); + compile (keys, keycc); free (keys); if ((argc - optind > 1 && !no_filenames) || with_filenames) @@ -2161,29 +2212,24 @@ main (int argc, char **argv) if (max_count == 0) exit (EXIT_FAILURE); + if (fts_options & FTS_LOGICAL && devices == READ_COMMAND_LINE_DEVICES) + devices = READ_DEVICES; + if (optind < argc) { - status = 1; - do - { - char *file = argv[optind]; - if ((included_patterns || excluded_patterns) - && !isdir (file)) - { - if (included_patterns - && excluded_file_name (included_patterns, file)) - continue; - if (excluded_patterns - && excluded_file_name (excluded_patterns, file)) - continue; - } - status &= grepfile (STREQ (file, "-") ? (char *) NULL : file, - &stats_base); - } - while ( ++optind < argc); + status = 1; + do + status &= grep_command_line_arg (argv[optind]); + while (++optind < argc); + } + else if (directories == RECURSE_DIRECTORIES && prepended < last_recursive) + { + /* Grep through ".", omitting leading "./" from diagnostics. */ + filename_prefix_len = 2; + status = grep_command_line_arg ("."); } else - status = grepfile ((char *) NULL, &stats_base); + status = grep_command_line_arg ("-"); /* We register via atexit() to test stdout. */ exit (errseen ? EXIT_TROUBLE : status); diff --git a/contrib/grep/src/mbsupport.h b/contrib/grep/src/mbsupport.h index 007f412a46..c4b7b4ec89 100644 --- a/contrib/grep/src/mbsupport.h +++ b/contrib/grep/src/mbsupport.h @@ -1,6 +1,6 @@ /* mbsupport.h --- Localize determination of whether we have multibyte stuff. - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright (C) 2004-2005, 2007, 2009-2012 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 @@ -17,19 +17,13 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* This file is needed so that we test for i18n support in just one place. - This gives us a consistent definition for all uses of MBS_SUPPORT. This - follows the ``Don't Repeat Yourself'' principle from "The Pragmatic - Programmer". - - The tests should be *all* the ones that are needed for an individual - application. */ - #include -#if defined HAVE_WCSCOLL && defined HAVE_ISWCTYPE +#ifndef MBS_SUPPORT # define MBS_SUPPORT 1 -#else -# define MBS_SUPPORT 0 +#endif + +#if ! MBS_SUPPORT +# undef MB_CUR_MAX +# define MB_CUR_MAX 1 #endif diff --git a/contrib/grep/src/pcresearch.c b/contrib/grep/src/pcresearch.c index f8581e083d..2994e65338 100644 --- a/contrib/grep/src/pcresearch.c +++ b/contrib/grep/src/pcresearch.c @@ -1,5 +1,5 @@ /* pcresearch.c - searching subroutines using PCRE for grep. - Copyright 2000, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright 2000, 2007, 2009-2012 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 @@ -101,19 +101,14 @@ Pcompile (char const *pattern, size_t size) #endif } -/* Pexecute is a no-return function when building --without-pcre. */ -#if !HAVE_LIBPCRE -# define WITHOUT_PCRE_NORETURN _GL_ATTRIBUTE_NORETURN -#else -# define WITHOUT_PCRE_NORETURN /* empty */ -#endif - -size_t WITHOUT_PCRE_NORETURN +size_t Pexecute (char const *buf, size_t size, size_t *match_size, char const *start_ptr) { #if !HAVE_LIBPCRE - abort (); + /* We can't get here, because Pcompile would have been called earlier. */ + error (EXIT_TROUBLE, 0, _("internal error")); + return -1; #else /* This array must have at least two elements; everything after that is just for performance improvement in pcre_exec. */ @@ -139,6 +134,9 @@ Pexecute (char const *buf, size_t size, size_t *match_size, if (start_ptr && start_ptr >= line_end) continue; + if (INT_MAX < line_end - line_buf) + error (EXIT_TROUBLE, 0, _("exceeded PCRE's line length limit")); + e = pcre_exec (cre, extra, line_buf, line_end - line_buf, start_ofs < 0 ? 0 : start_ofs, 0, sub, sizeof sub / sizeof *sub); diff --git a/contrib/grep/src/search.h b/contrib/grep/src/search.h index c48bbab03c..3074407e7e 100644 --- a/contrib/grep/src/search.h +++ b/contrib/grep/src/search.h @@ -1,5 +1,5 @@ /* search.c - searching subroutines using dfa, kwset and regex for grep. - Copyright 1992, 1998, 2000, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright 1992, 1998, 2000, 2007, 2009-2012 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 @@ -38,10 +38,8 @@ /* searchutils.c */ extern void kwsinit (kwset_t *); -#if MBS_SUPPORT extern char *mbtolower (const char *, size_t *); extern bool is_mb_middle (const char **, const char *, const char *, size_t); -#endif /* dfasearch.c */ extern void GEAcompile (char const *, size_t, reg_syntax_t); diff --git a/contrib/grep/src/searchutils.c b/contrib/grep/src/searchutils.c index 9dac023e8c..b787fe673a 100644 --- a/contrib/grep/src/searchutils.c +++ b/contrib/grep/src/searchutils.c @@ -1,5 +1,5 @@ /* searchutils.c - helper subroutines for grep's matchers. - Copyright 1992, 1998, 2000, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright 1992, 1998, 2000, 2007, 2009-2012 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 @@ -28,11 +28,7 @@ kwsinit (kwset_t *kwset) static char trans[NCHAR]; int i; - if (match_icase -#if MBS_SUPPORT - && MB_CUR_MAX == 1 -#endif - ) + if (match_icase && MB_CUR_MAX == 1) { for (i = 0; i < NCHAR; ++i) trans[i] = tolower (i); diff --git a/contrib/grep/src/system.h b/contrib/grep/src/system.h index 199b48536a..426d89376b 100644 --- a/contrib/grep/src/system.h +++ b/contrib/grep/src/system.h @@ -1,5 +1,5 @@ /* Portability cruft. Include after config.h and sys/types.h. - Copyright 1996, 1998-2000, 2007, 2009-2011 Free Software Foundation, Inc. + Copyright 1996, 1998-2000, 2007, 2009-2012 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 @@ -27,17 +27,12 @@ #include "configmake.h" #include "dirname.h" #include "minmax.h" +#include "same-inode.h" #if O_BINARY # define HAVE_DOS_FILE_CONTENTS 1 #endif -#ifdef EISDIR -# define is_EISDIR(e, f) ((e) == EISDIR) -#else -# define is_EISDIR(e, f) 0 -#endif - #include #include #include @@ -53,7 +48,7 @@ enum { EXIT_TROUBLE = 2 }; #include #ifndef initialize_main -#define initialize_main(argcp, argvp) +# define initialize_main(argcp, argvp) #endif #include "unlocked-io.h" -- 2.41.0