diff options
| author | Ruslan Ermilov <ru@FreeBSD.org> | 1999-12-31 09:56:08 +0000 |
|---|---|---|
| committer | Ruslan Ermilov <ru@FreeBSD.org> | 1999-12-31 09:56:08 +0000 |
| commit | e6959636b0c97362a905f97bd2b32e1a6b1cfe70 (patch) | |
| tree | 29cf0ac1e17b8c349dcfd689f7be002b89812bea /gnu/usr.bin | |
| parent | 449fe084ed15705947e07235de166744a748eff2 (diff) | |
Notes
Diffstat (limited to 'gnu/usr.bin')
| -rw-r--r-- | gnu/usr.bin/grep/AUTHORS | 14 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/COPYING | 11 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/Makefile | 56 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/NEWS | 64 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/PROJECTS | 15 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/README | 12 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/config.h | 2 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/dfa.c | 431 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/dfa.h | 51 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/getopt.c | 617 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/getopt.h | 40 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/getpagesize.h | 73 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/grep.1 | 273 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/grep.c | 1429 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/grep.h | 37 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/kwset.c | 75 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/kwset.h | 36 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/obstack.c | 225 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/obstack.h | 241 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/search.c | 109 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/tests/check.sh | 24 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/tests/scriptgen.awk | 10 | ||||
| -rw-r--r-- | gnu/usr.bin/grep/tests/spencer.tests | 122 |
23 files changed, 2449 insertions, 1518 deletions
diff --git a/gnu/usr.bin/grep/AUTHORS b/gnu/usr.bin/grep/AUTHORS index e3e033b19a02..65ff8a1cd26e 100644 --- a/gnu/usr.bin/grep/AUTHORS +++ b/gnu/usr.bin/grep/AUTHORS @@ -20,10 +20,22 @@ non-matching text before calling the regexp matcher was originally due to James Woods. He also contributed some code to early versions of GNU grep. -Finally, I would like to thank Andrew Hume for many fascinating discussions +Mike Haertel would like to thank Andrew Hume for many fascinating discussions of string searching issues over the years. Hume & Sunday's excellent paper on fast string searching (AT&T Bell Laboratories CSTR #156) describes some of the history of the subject, as well as providing exhaustive performance analysis of various implementation alternatives. The inner loop of GNU grep is similar to Hume & Sunday's recommended "Tuned Boyer Moore" inner loop. + +More work was done on regex.[ch] by Ulrich Drepper and Arnold +Robbins. Regex is now part of GNU C library, see this package +for complete details and credits. + +Arnold Robbins contributed to improve dfa.[ch]. In fact +it came straight from gawk-3.0.3 with small editing and fixes. + +Many folks contributed see THANKS, if I omited someone please +send me email. + +Alain Magloire is the current maintainer. diff --git a/gnu/usr.bin/grep/COPYING b/gnu/usr.bin/grep/COPYING index a43ea2126fb6..d60c31a97a54 100644 --- a/gnu/usr.bin/grep/COPYING +++ b/gnu/usr.bin/grep/COPYING @@ -2,7 +2,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - Appendix: How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> + Copyright (C) <year> <name of author> 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 @@ -305,14 +305,15 @@ the "copyright" line and a pointer to where the full notice is found. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/gnu/usr.bin/grep/Makefile b/gnu/usr.bin/grep/Makefile index 3efc561fbbb7..b1875fedabe5 100644 --- a/gnu/usr.bin/grep/Makefile +++ b/gnu/usr.bin/grep/Makefile @@ -1,35 +1,51 @@ # $FreeBSD$ -GREP_LIBZ= YES -GREP_FTS= YES +GREP_LIBZ=YES PROG= grep -SRCS= dfa.c grep.c getopt.c kwset.c obstack.c search.c -CFLAGS+=-DGREP -DHAVE_STRING_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_UNISTD_H=1 \ - -DHAVE_GETPAGESIZE=1 -DHAVE_MEMCHR=1 -DHAVE_STRERROR=1 \ - -DHAVE_VALLOC=1 +SRCS= dfa.c getopt.c getopt1.c grep.c kwset.c obstack.c savedir.c search.c \ + stpcpy.c -LINKS+= ${BINDIR}/grep ${BINDIR}/egrep \ +CFLAGS+=-I${.CURDIR} -DHAVE_CONFIG_H + +LINKS+= ${BINDIR}/grep ${BINDIR}/egrep \ ${BINDIR}/grep ${BINDIR}/fgrep -MLINKS= grep.1 egrep.1 grep.1 fgrep.1 +MLINKS= grep.1 egrep.1 grep.1 fgrep.1 -DPADD+= ${LIBGNUREGEX} -LDADD+= -lgnuregex +DPADD+= ${LIBGNUREGEX} +LDADD+= -lgnuregex .if defined(GREP_LIBZ) && !empty(GREP_LIBZ) -LDADD+= -lz -DPADD+= ${LIBZ} -CFLAGS+= -DHAVE_LIBZ=1 -LINKS+= ${BINDIR}/grep ${BINDIR}/zgrep \ +LDADD+= -lz +DPADD+= ${LIBZ} +CFLAGS+=-DHAVE_LIBZ=1 +LINKS+= ${BINDIR}/grep ${BINDIR}/zgrep \ ${BINDIR}/grep ${BINDIR}/zegrep \ - ${BINDIR}/grep ${BINDIR}/zfgrep -MLINKS+= grep.1 zgrep.1 grep.1 zegrep.1 grep.1 zfgrep.1 -.endif -.if defined(GREP_FTS) && !empty(GREP_FTS) -CFLAGS+= -DHAVE_FTS=1 + ${BINDIR}/grep ${BINDIR}/zfgrep +MLINKS+=grep.1 zgrep.1 grep.1 zegrep.1 grep.1 zfgrep.1 .endif +SUBDIR+=doc + check: all - sh ${.CURDIR}/tests/check.sh ${.CURDIR}/tests + @failed=0; total=0; \ + for tst in ${TESTS}; do \ + total=$$(($$total+1)); \ + if GREP=${.OBJDIR}/${PROG} srcdir=${.CURDIR}/tests \ + ${.CURDIR}/tests/$$tst; then \ + echo "PASS: $$tst"; \ + else \ + failed=$$(($$failed+1)); \ + echo "FAIL: $$tst"; \ + fi; \ + done; \ + if [ "$$failed" -eq 0 ]; then \ + echo "All $$total tests passed"; \ + else \ + echo "$$failed of $$total tests failed"; \ + fi + +TESTS= warning.sh khadafy.sh spencer1.sh bre.sh ere.sh status.sh empty.sh \ + options.sh .include <bsd.prog.mk> diff --git a/gnu/usr.bin/grep/NEWS b/gnu/usr.bin/grep/NEWS index eb0b513d6cc6..d55d88c33891 100644 --- a/gnu/usr.bin/grep/NEWS +++ b/gnu/usr.bin/grep/NEWS @@ -1,3 +1,67 @@ +Version 2.3: + + - When searching a binary file FOO, grep now just reports + `Binary file FOO matches' instead of outputting binary data. + This is typically more useful than the old behavior, + and it is also more consistent with other utilities like `diff'. + A file is considered to be binary if it contains a NUL (i.e. zero) byte. + + The new -a or --text option causes `grep' to assume that all + input is text. (This option has the same meaning as with `diff'.) + Use it if you want binary data in your output. + + - `grep' now searches directories just like ordinary files; it no longer + silently skips directories. This is the traditional behavior of + Unix text utilities (in particular, of traditional `grep'). + Hence `grep PATTERN DIRECTORY' should report + `grep: DIRECTORY: Is a directory' on hosts where the operating system + does not permit programs to read directories directly, and + `grep: DIRECTORY: Binary file matches' (or nothing) otherwise. + + The new -d ACTION or --directories=ACTION option affects directory handling. + `-d skip' causes `grep' to silently skip directories, as in grep 2.2; + `-d read' (the default) causes `grep' to read directories if possible, + as in earlier versions of grep. + + - The MS-DOS and Microsoft Windows ports now behave identically to the + GNU and Unix ports with respect to binary files and directories. + +Version 2.2: + +Bug fix release. + + - Status error number fix. + - Skipping directories removed. + - Many typos fix. + - -f /dev/null fix(not to consider as an empty pattern). + - Checks for wctype/wchar. + - -E was using the wrong matcher fix. + - bug in regex char class fix + - Fixes for DJGPP + +Version 2.1: + +This is a bug fix release(see Changelog) i.e. no new features. + + - More compliance to GNU standard. + - Long options. + - Internationalisation. + - Use automake/autoconf. + - Directory hierarchy change. + - Sigvec with -e on Linux corrected. + - Sigvec with -f on Linux corrected. + - Sigvec with the mmap() corrected. + - Bug in kwset corrected. + - -q, -L and -l stop on first match. + - New and improve regex.[ch] from Ulrich Drepper. + - New and improve dfa.[ch] from Arnold Robbins. + - Prototypes for over zealous C compiler. + - Not scanning a file, if it's a directory + (cause problems on Sun). + - Ported to MS-DOS/MS-Windows with DJGPP tools. + +See Changelog for the full story and proper credits. + Version 2.0: The most important user visible change is that egrep and fgrep have diff --git a/gnu/usr.bin/grep/PROJECTS b/gnu/usr.bin/grep/PROJECTS deleted file mode 100644 index 67e9a2aad6ab..000000000000 --- a/gnu/usr.bin/grep/PROJECTS +++ /dev/null @@ -1,15 +0,0 @@ -Write Texinfo documentation for grep. The manual page would be a good -place to start, but Info documents are also supposed to contain a -tutorial and examples. - -Fix the DFA matcher to never use exponential space. (Fortunately, these -cases are rare.) - -Improve the performance of the regex backtracking matcher. This matcher -is agonizingly slow, and is responsible for grep sometimes being slower -than Unix grep when backreferences are used. - -Provide support for the Posix [= =] and [. .] constructs. This is -difficult because it requires locale-dependent details of the character -set and collating sequence, but Posix does not standardize any method -for accessing this information! diff --git a/gnu/usr.bin/grep/README b/gnu/usr.bin/grep/README index bc34a859063d..66c1bb2ba784 100644 --- a/gnu/usr.bin/grep/README +++ b/gnu/usr.bin/grep/README @@ -1,6 +1,6 @@ -This is GNU grep 2.0, the "fastest grep in the west" (we hope). All +This is GNU grep, the "fastest grep in the west" (we hope). All bugs reported in previous releases have been fixed. Many exciting new -bugs have probably been introduced in this major revision. +bugs have probably been introduced in this revision. GNU grep is provided "as is" with no warranty. The exact terms under which you may use and (re)distribute this program are detailed @@ -14,15 +14,13 @@ look at every character. The result is typically many times faster than Unix grep or egrep. (Regular expressions containing backreferencing will run more slowly, however.) -See the file AUTHORS for a list of authors and other contributors. +See the files AUTHORS and THANKS for a list of authors and other contributors. See the file INSTALL for compilation and installation instructions. -See the file MANIFEST for a list of files in this distribution. - See the file NEWS for a description of major changes in this release. -See the file PROJECTS if you want to be mentioned in AUTHORS. +See the file TODO for ideas on how you could help us improve grep. -Send bug reports to bug-gnu-utils@prep.ai.mit.edu. Be sure to +Send bug reports to bug-gnu-utils@gnu.org. Be sure to include the word "grep" in your Subject: header field. diff --git a/gnu/usr.bin/grep/config.h b/gnu/usr.bin/grep/config.h index 415df26b1997..b51c72957f85 100644 --- a/gnu/usr.bin/grep/config.h +++ b/gnu/usr.bin/grep/config.h @@ -23,7 +23,7 @@ /* #undef HAVE_ALLOCA_H */ /* Define if you have a working `mmap' system call. */ -#define HAVE_MMAP 1 +/* #undef HAVE_MMAP */ /* Define as __inline if that's what the C compiler calls it. */ /* #undef inline */ diff --git a/gnu/usr.bin/grep/dfa.c b/gnu/usr.bin/grep/dfa.c index 4b9eb2eda08a..9f20c37d7908 100644 --- a/gnu/usr.bin/grep/dfa.c +++ b/gnu/usr.bin/grep/dfa.c @@ -1,5 +1,5 @@ /* dfa.c - deterministic extended regexp routines for GNU - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1998 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,19 +13,25 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Written June, 1988 by Mike Haertel Modified July, 1988 by Arthur David Olson to assist BMG speedups */ +/* $FreeBSD$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + #include <assert.h> #include <ctype.h> #include <stdio.h> +#include <sys/types.h> #ifdef STDC_HEADERS #include <stdlib.h> #else -#include <sys/types.h> extern char *calloc(), *malloc(), *realloc(); extern void free(); #endif @@ -38,59 +44,140 @@ extern void free(); #include <strings.h> #endif +#ifndef DEBUG /* use the same approach as regex.c */ +#undef assert +#define assert(e) +#endif /* DEBUG */ + #ifndef isgraph -#define isgraph(C) (isprint((unsigned char)C) && !isspace((unsigned char)C)) +#define isgraph(C) (isprint(C) && !isspace(C)) #endif -#define ISALPHA(C) isalpha((unsigned char)C) -#define ISUPPER(C) isupper((unsigned char)C) -#define ISLOWER(C) islower((unsigned char)C) -#define ISDIGIT(C) isdigit((unsigned char)C) -#define ISXDIGIT(C) isxdigit((unsigned char)C) -#define ISSPACE(C) isspace((unsigned char)C) -#define ISPUNCT(C) ispunct((unsigned char)C) -#define ISALNUM(C) isalnum((unsigned char)C) -#define ISPRINT(C) isprint((unsigned char)C) -#define ISGRAPH(C) isgraph((unsigned char)C) -#define ISCNTRL(C) iscntrl((unsigned char)C) +#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) +#define ISALPHA(C) isalpha(C) +#define ISUPPER(C) isupper(C) +#define ISLOWER(C) islower(C) +#define ISDIGIT(C) isdigit(C) +#define ISXDIGIT(C) isxdigit(C) +#define ISSPACE(C) isspace(C) +#define ISPUNCT(C) ispunct(C) +#define ISALNUM(C) isalnum(C) +#define ISPRINT(C) isprint(C) +#define ISGRAPH(C) isgraph(C) +#define ISCNTRL(C) iscntrl(C) +#else +#define ISALPHA(C) (isascii(C) && isalpha(C)) +#define ISUPPER(C) (isascii(C) && isupper(C)) +#define ISLOWER(C) (isascii(C) && islower(C)) +#define ISDIGIT(C) (isascii(C) && isdigit(C)) +#define ISXDIGIT(C) (isascii(C) && isxdigit(C)) +#define ISSPACE(C) (isascii(C) && isspace(C)) +#define ISPUNCT(C) (isascii(C) && ispunct(C)) +#define ISALNUM(C) (isascii(C) && isalnum(C)) +#define ISPRINT(C) (isascii(C) && isprint(C)) +#define ISGRAPH(C) (isascii(C) && isgraph(C)) +#define ISCNTRL(C) (isascii(C) && iscntrl(C)) +#endif -#include "dfa.h" -#include <gnuregex.h> +/* If we (don't) have I18N. */ +/* glibc defines _ */ +#ifndef _ +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# ifndef _ +# define _(Str) gettext (Str) +# endif +# else +# define _(Str) (Str) +# endif +#endif -#if __STDC__ -typedef void *ptr_t; +#ifdef __FreeBSD__ +#include <gnuregex.h> #else -typedef char *ptr_t; +#include "regex.h" #endif +#include "dfa.h" -static void dfamust(); +/* HPUX, define those as macros in sys/param.h */ +#ifdef setbit +# undef setbit +#endif +#ifdef clrbit +# undef clrbit +#endif + +static void dfamust PARAMS ((struct dfa *dfa)); + +static ptr_t xcalloc PARAMS ((size_t n, size_t s)); +static ptr_t xmalloc PARAMS ((size_t n)); +static ptr_t xrealloc PARAMS ((ptr_t p, size_t n)); +#ifdef DEBUG +static void prtok PARAMS ((token t)); +#endif +static int tstbit PARAMS ((int b, charclass c)); +static void setbit PARAMS ((int b, charclass c)); +static void clrbit PARAMS ((int b, charclass c)); +static void copyset PARAMS ((charclass src, charclass dst)); +static void zeroset PARAMS ((charclass s)); +static void notset PARAMS ((charclass s)); +static int equal PARAMS ((charclass s1, charclass s2)); +static int charclass_index PARAMS ((charclass s)); +static int looking_at PARAMS ((const char *s)); +static token lex PARAMS ((void)); +static void addtok PARAMS ((token t)); +static void atom PARAMS ((void)); +static int nsubtoks PARAMS ((int tindex)); +static void copytoks PARAMS ((int tindex, int ntokens)); +static void closure PARAMS ((void)); +static void branch PARAMS ((void)); +static void regexp PARAMS ((int toplevel)); +static void copy PARAMS ((position_set *src, position_set *dst)); +static void insert PARAMS ((position p, position_set *s)); +static void merge PARAMS ((position_set *s1, position_set *s2, position_set *m)); +static void delete PARAMS ((position p, position_set *s)); +static int state_index PARAMS ((struct dfa *d, position_set *s, + int newline, int letter)); +static void build_state PARAMS ((int s, struct dfa *d)); +static void build_state_zero PARAMS ((struct dfa *d)); +static char *icatalloc PARAMS ((char *old, char *new)); +static char *icpyalloc PARAMS ((char *string)); +static char *istrstr PARAMS ((char *lookin, char *lookfor)); +static void ifree PARAMS ((char *cp)); +static void freelist PARAMS ((char **cpp)); +static char **enlist PARAMS ((char **cpp, char *new, size_t len)); +static char **comsubs PARAMS ((char *left, char *right)); +static char **addlists PARAMS ((char **old, char **new)); +static char **inboth PARAMS ((char **left, char **right)); #ifdef __FreeBSD__ -static int collate_range_cmp (a, b) - int a, b; +static int +collate_range_cmp(c1, c2) + int c1, c2; { + static char s1[2], s2[2]; int r; - static char s[2][2]; - if ((unsigned char)a == (unsigned char)b) + if (c1 == c2) return 0; - s[0][0] = a; - s[1][0] = b; - if ((r = strcoll(s[0], s[1])) == 0) - r = (unsigned char)a - (unsigned char)b; + s1[0] = c1; + s2[0] = c2; + if ((r = strcoll(s1, s2)) == 0) + r = c1 - c2; + return r; } #endif static ptr_t xcalloc(n, s) - int n; + size_t n; size_t s; { ptr_t r = calloc(n, s); if (!r) - dfaerror("Memory exhausted"); + dfaerror(_("Memory exhausted")); return r; } @@ -102,7 +189,7 @@ xmalloc(n) assert(n != 0); if (!r) - dfaerror("Memory exhausted"); + dfaerror(_("Memory exhausted")); return r; } @@ -115,11 +202,11 @@ xrealloc(p, n) assert(n != 0); if (!r) - dfaerror("Memory exhausted"); + dfaerror(_("Memory exhausted")); return r; } -#define CALLOC(p, t, n) ((p) = (t *) xcalloc((n), sizeof (t))) +#define CALLOC(p, t, n) ((p) = (t *) xcalloc((size_t)(n), sizeof (t))) #define MALLOC(p, t, n) ((p) = (t *) xmalloc((n) * sizeof (t))) #define REALLOC(p, t, n) ((p) = (t *) xrealloc((ptr_t) (p), (n) * sizeof (t))) @@ -261,7 +348,7 @@ charclass_index(s) } /* Syntax bits controlling the behavior of the lexical analyzer. */ -static int syntax_bits, syntax_bits_set; +static reg_syntax_t syntax_bits, syntax_bits_set; /* Flag for case-folding letters into sets. */ static int case_fold; @@ -269,7 +356,7 @@ static int case_fold; /* Entry point to set syntax options. */ void dfasyntax(bits, fold) - int bits; + reg_syntax_t bits; int fold; { syntax_bits_set = 1; @@ -284,7 +371,7 @@ dfasyntax(bits, fold) static char *lexstart; /* Pointer to beginning of input string. */ static char *lexptr; /* Pointer to next input character. */ -static lexleft; /* Number of characters remaining. */ +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 (, | only by zero-width characters. */ @@ -298,12 +385,16 @@ static int minrep, maxrep; /* Repeat counts for {m,n}. */ if (eoferr != 0) \ dfaerror(eoferr); \ else \ - return END; \ + return lasttok = END; \ (c) = (unsigned char) *lexptr++; \ --lexleft; \ } +#ifdef __STDC__ +#define FUNC(F, P) static int F(int c) { return P(c); } +#else #define FUNC(F, P) static int F(c) int c; { return P(c); } +#endif FUNC(is_alpha, ISALPHA) FUNC(is_upper, ISUPPER) @@ -317,32 +408,42 @@ FUNC(is_print, ISPRINT) FUNC(is_graph, ISGRAPH) FUNC(is_cntrl, ISCNTRL) +static int is_blank(c) +int c; +{ + return (c == ' ' || c == '\t'); +} + /* 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. */ static struct { - char *name; - int (*pred)(); + const char *name; + int (*pred) PARAMS ((int)); } prednames[] = { - ":alpha:]", is_alpha, - ":upper:]", is_upper, - ":lower:]", is_lower, - ":digit:]", is_digit, - ":xdigit:]", is_xdigit, - ":space:]", is_space, - ":punct:]", is_punct, - ":alnum:]", is_alnum, - ":print:]", is_print, - ":graph:]", is_graph, - ":cntrl:]", is_cntrl, - 0 + { ":alpha:]", is_alpha }, + { ":upper:]", is_upper }, + { ":lower:]", is_lower }, + { ":digit:]", is_digit }, + { ":xdigit:]", is_xdigit }, + { ":space:]", is_space }, + { ":punct:]", is_punct }, + { ":alnum:]", is_alnum }, + { ":print:]", is_print }, + { ":graph:]", is_graph }, + { ":cntrl:]", is_cntrl }, + { ":blank:]", is_blank }, + { 0 } }; +/* Return non-zero if C is a `word-constituent' byte; zero otherwise. */ +#define IS_WORD_CONSTITUENT(C) (ISALNUM(C) || (C) == '_') + static int looking_at(s) - char *s; + const char *s; { - int len; + size_t len; len = strlen(s); if (lexleft < len) @@ -373,7 +474,7 @@ lex() if (backslash) goto normal_char; if (lexleft == 0) - dfaerror("Unfinished \\ escape"); + dfaerror(_("Unfinished \\ escape")); backslash = 1; break; @@ -419,23 +520,33 @@ lex() } goto normal_char; + case '`': + if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) + 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 */ + goto normal_char; + case '<': - if (backslash) + if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = BEGWORD; goto normal_char; case '>': - if (backslash) + if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = ENDWORD; goto normal_char; case 'b': - if (backslash) + if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = LIMWORD; goto normal_char; case 'B': - if (backslash) + if (backslash && !(syntax_bits & RE_NO_GNU_OPS)) return lasttok = NOTLIMWORD; goto normal_char; @@ -475,24 +586,24 @@ lex() {M,} - minimum count, maximum is infinity {,M} - 0 through M {M,N} - M through N */ - FETCH(c, "unfinished repeat count"); + FETCH(c, _("unfinished repeat count")); if (ISDIGIT(c)) { minrep = c - '0'; for (;;) { - FETCH(c, "unfinished repeat count"); + FETCH(c, _("unfinished repeat count")); if (!ISDIGIT(c)) break; minrep = 10 * minrep + c - '0'; } } else if (c != ',') - dfaerror("malformed repeat count"); + dfaerror(_("malformed repeat count")); if (c == ',') for (;;) { - FETCH(c, "unfinished repeat count"); + FETCH(c, _("unfinished repeat count")); if (!ISDIGIT(c)) break; maxrep = 10 * maxrep + c - '0'; @@ -502,11 +613,11 @@ lex() if (!(syntax_bits & RE_NO_BK_BRACES)) { if (c != '\\') - dfaerror("malformed repeat count"); - FETCH(c, "unfinished repeat count"); + dfaerror(_("malformed repeat count")); + FETCH(c, _("unfinished repeat count")); } if (c != '}') - dfaerror("malformed repeat count"); + dfaerror(_("malformed repeat count")); laststart = 0; return lasttok = REPMN; @@ -556,11 +667,11 @@ lex() case 'w': case 'W': - if (!backslash) + if (!backslash || (syntax_bits & RE_NO_GNU_OPS)) goto normal_char; zeroset(ccl); for (c2 = 0; c2 < NOTCHAR; ++c2) - if (ISALNUM(c2)) + if (IS_WORD_CONSTITUENT(c2)) setbit(c2, ccl); if (c == 'W') notset(ccl); @@ -571,10 +682,10 @@ lex() if (backslash) goto normal_char; zeroset(ccl); - FETCH(c, "Unbalanced ["); + FETCH(c, _("Unbalanced [")); if (c == '^') { - FETCH(c, "Unbalanced ["); + FETCH(c, _("Unbalanced [")); invert = 1; } else @@ -591,20 +702,25 @@ lex() for (c1 = 0; prednames[c1].name; ++c1) if (looking_at(prednames[c1].name)) { + int (*pred)() = prednames[c1].pred; + if (case_fold + && (pred == is_upper || pred == is_lower)) + pred = is_alpha; + for (c2 = 0; c2 < NOTCHAR; ++c2) - if ((*prednames[c1].pred)(c2)) + if ((*pred)(c2)) setbit(c2, ccl); lexptr += strlen(prednames[c1].name); lexleft -= strlen(prednames[c1].name); - FETCH(c1, "Unbalanced ["); + FETCH(c1, _("Unbalanced [")); goto skip; } if (c == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) - FETCH(c, "Unbalanced ["); - FETCH(c1, "Unbalanced ["); + FETCH(c, _("Unbalanced [")); + FETCH(c1, _("Unbalanced [")); if (c1 == '-') { - FETCH(c2, "Unbalanced ["); + FETCH(c2, _("Unbalanced [")); if (c2 == ']') { /* In the case [x-], the - is an ordinary hyphen, @@ -617,31 +733,28 @@ lex() { if (c2 == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) - FETCH(c2, "Unbalanced ["); - FETCH(c1, "Unbalanced ["); + FETCH(c2, _("Unbalanced [")); + FETCH(c1, _("Unbalanced [")); } } else c2 = c; #ifdef __FreeBSD__ - { token c3; - - if (collate_range_cmp(c, c2) > 0) { - FETCH(c2, "Invalid range"); - goto skip; - } + if (collate_range_cmp(c, c2) <= 0) + { + token c3; - for (c3 = 0; c3 < NOTCHAR; ++c3) - if ( collate_range_cmp(c, c3) <= 0 - && collate_range_cmp(c3, c2) <= 0 - ) { + for (c3 = 0; c3 < NOTCHAR; ++c3) { + if (collate_range_cmp(c, c3) <= 0 && + collate_range_cmp(c3, c2) <= 0) { setbit(c3, ccl); if (case_fold) if (ISUPPER(c3)) - setbit(tolower((unsigned char)c3), ccl); - else if (ISLOWER(c3)) - setbit(toupper((unsigned char)c3), ccl); + setbit(tolower(c3), ccl); + else if (ISLOWER(c)) + setbit(toupper(c3), ccl); } + } } #else while (c <= c2) @@ -649,9 +762,9 @@ lex() setbit(c, ccl); if (case_fold) if (ISUPPER(c)) - setbit(tolower((unsigned char)c), ccl); + setbit(tolower(c), ccl); else if (ISLOWER(c)) - setbit(toupper((unsigned char)c), ccl); + setbit(toupper(c), ccl); ++c; } #endif @@ -675,10 +788,10 @@ lex() { zeroset(ccl); setbit(c, ccl); - if (isupper((unsigned char)c)) - setbit(tolower((unsigned char)c), ccl); + if (isupper(c)) + setbit(tolower(c), ccl); else - setbit(toupper((unsigned char)c), ccl); + setbit(toupper(c), ccl); return lasttok = CSET + charclass_index(ccl); } return c; @@ -688,12 +801,13 @@ lex() /* The above loop should consume at most a backslash and some other character. */ abort(); + return END; /* keeps pedantic compilers happy. */ } /* Recursive descent parser for regular expressions. */ static token tok; /* Lookahead token. */ -static depth; /* Current depth of a hypothetical stack +static int 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 @@ -761,12 +875,6 @@ addtok(t) The parser builds a parse tree in postfix form in an array of tokens. */ -#if __STDC__ -static void regexp(int); -#else -static void regexp(); -#endif - static void atom() { @@ -782,7 +890,7 @@ atom() tok = lex(); regexp(0); if (tok != RPAREN) - dfaerror("Unbalanced ("); + dfaerror(_("Unbalanced (")); tok = lex(); } else @@ -792,6 +900,7 @@ atom() /* Return the number of tokens in the given subexpression. */ static int nsubtoks(tindex) +int tindex; { int ntoks1; @@ -902,7 +1011,7 @@ dfaparse(s, len, d) parens = 0; if (! syntax_bits_set) - dfaerror("No syntax specified"); + dfaerror(_("No syntax specified")); tok = lex(); depth = d->depth; @@ -910,7 +1019,7 @@ dfaparse(s, len, d) regexp(1); if (tok != END) - dfaerror("Unbalanced )"); + dfaerror(_("Unbalanced )")); addtok(END - d->nregexps); addtok(CAT); @@ -949,7 +1058,7 @@ insert(p, s) position t1, t2; for (i = 0; i < s->nelem && p.index < s->elems[i].index; ++i) - ; + continue; if (i < s->nelem && p.index == s->elems[i].index) s->elems[i].constraint |= p.constraint; else @@ -1082,7 +1191,9 @@ state_index(d, s, newline, letter) that position with the elements of its follow labeled with an appropriate constraint. Repeat exhaustively until no funny positions are left. S->elems must be large enough to hold the result. */ -void +static void epsclosure PARAMS ((position_set *s, struct dfa *d)); + +static void epsclosure(s, d) position_set *s; struct dfa *d; @@ -1484,7 +1595,7 @@ dfastate(s, d, trans) 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 initialized; /* Flag for static initialization. */ + static int initialized; /* Flag for static initialization. */ int i, j, k; /* Initialize the set of letters, if necessary. */ @@ -1492,7 +1603,7 @@ dfastate(s, d, trans) { initialized = 1; for (i = 0; i < NOTCHAR; ++i) - if (ISALNUM(i)) + if (IS_WORD_CONSTITUENT(i)) setbit(i, letters); setbit('\n', newline); } @@ -1531,7 +1642,7 @@ dfastate(s, d, trans) /* If there are no characters left, there's no point in going on. */ for (j = 0; j < CHARCLASS_INTS && !matches[j]; ++j) - ; + continue; if (j == CHARCLASS_INTS) continue; } @@ -1549,7 +1660,7 @@ dfastate(s, d, trans) matches. */ intersectf = 0; for (k = 0; k < CHARCLASS_INTS; ++k) - (intersect[k] = matches[k] & labels[j][k]) ? intersectf = 1 : 0; + (intersect[k] = matches[k] & labels[j][k]) ? (intersectf = 1) : 0; if (! intersectf) continue; @@ -1560,8 +1671,8 @@ dfastate(s, d, trans) /* Even an optimizing compiler can't know this for sure. */ int match = matches[k], label = labels[j][k]; - (leftovers[k] = ~match & label) ? leftoversf = 1 : 0; - (matches[k] = match & ~label) ? matchesf = 1 : 0; + (leftovers[k] = ~match & label) ? (leftoversf = 1) : 0; + (matches[k] = match & ~label) ? (matchesf = 1) : 0; } /* If there were leftovers, create a new group labeled with them. */ @@ -1625,12 +1736,8 @@ dfastate(s, d, trans) else state_letter = state; for (i = 0; i < NOTCHAR; ++i) - if (i == '\n') - trans[i] = state_newline; - else if (ISALNUM(i)) - trans[i] = state_letter; - else - trans[i] = state; + trans[i] = (IS_WORD_CONSTITUENT(i)) ? state_letter : state; + trans['\n'] = state_newline; } else for (i = 0; i < NOTCHAR; ++i) @@ -1688,7 +1795,7 @@ dfastate(s, d, trans) if (c == '\n') trans[c] = state_newline; - else if (ISALNUM(c)) + else if (IS_WORD_CONSTITUENT(c)) trans[c] = state_letter; else if (c < NOTCHAR) trans[c] = state; @@ -1822,12 +1929,12 @@ dfaexec(d, begin, end, newline, count, backref) int *count; int *backref; { - register s, s1, tmp; /* Current state. */ + register int s, s1, tmp; /* Current state. */ register unsigned char *p; /* Current input character. */ - register **trans, *t; /* Copy of d->trans so it can be optimized + register int **trans, *t; /* Copy of d->trans so it can be optimized into a register. */ - static sbit[NOTCHAR]; /* Table for anding with d->success. */ - static sbit_init; + static int sbit[NOTCHAR]; /* Table for anding with d->success. */ + static int sbit_init; if (! sbit_init) { @@ -1835,12 +1942,8 @@ dfaexec(d, begin, end, newline, count, backref) sbit_init = 1; for (i = 0; i < NOTCHAR; ++i) - if (i == '\n') - sbit[i] = 4; - else if (ISALNUM(i)) - sbit[i] = 2; - else - sbit[i] = 1; + sbit[i] = (IS_WORD_CONSTITUENT(i)) ? 2 : 1; + sbit['\n'] = 4; } if (! d->tralloc) @@ -1853,30 +1956,21 @@ dfaexec(d, begin, end, newline, count, backref) for (;;) { - /* The dreaded inner loop. */ - if ((t = trans[s]) != 0) - do - { - s1 = t[*p++]; - if (! (t = trans[s1])) - goto last_was_s; - s = t[*p++]; - } - while ((t = trans[s]) != 0); - goto last_was_s1; - last_was_s: - tmp = s, s = s1, s1 = tmp; - last_was_s1: + while ((t = trans[s]) != 0) { /* hand-optimized loop */ + s1 = t[*p++]; + if ((t = trans[s1]) == 0) { + tmp = s ; s = s1 ; s1 = tmp ; /* swap */ + break; + } + s = t[*p++]; + } if (s >= 0 && p <= (unsigned char *) end && d->fails[s]) { if (d->success[s] & sbit[*p]) { if (backref) - if (d->states[s].backref) - *backref = 1; - else - *backref = 0; + *backref = (d->states[s].backref != 0); return (char *) p; } @@ -1940,24 +2034,24 @@ dfacomp(s, len, d, searchflag) { if (case_fold) /* dummy folding in service of dfamust() */ { - char *copy; + char *lcopy; int i; - copy = malloc(len); - if (!copy) - dfaerror("out of memory"); + lcopy = malloc(len); + if (!lcopy) + dfaerror(_("out of memory")); /* This is a kludge. */ case_fold = 0; for (i = 0; i < len; ++i) - if (ISUPPER(s[i])) - copy[i] = tolower((unsigned char)s[i]); + if (ISUPPER ((unsigned char) s[i])) + lcopy[i] = tolower ((unsigned char) s[i]); else - copy[i] = s[i]; + lcopy[i] = s[i]; dfainit(d); - dfaparse(copy, len, d); - free(copy); + dfaparse(lcopy, len, d); + free(lcopy); dfamust(d); d->cindex = d->tindex = d->depth = d->nleaves = d->nregexps = 0; case_fold = 1; @@ -1995,9 +2089,10 @@ dfafree(d) free((ptr_t) d->trans[i]); else if (d->fails[i]) free((ptr_t) d->fails[i]); - free((ptr_t) d->realtrans); - free((ptr_t) d->fails); - free((ptr_t) d->newlines); + if (d->realtrans) free((ptr_t) d->realtrans); + if (d->fails) free((ptr_t) d->fails); + if (d->newlines) free((ptr_t) d->newlines); + if (d->success) free((ptr_t) d->success); for (dm = d->musts; dm; dm = ndm) { ndm = dm->next; @@ -2092,7 +2187,7 @@ icatalloc(old, new) char *new; { char *result; - int oldsize, newsize; + size_t oldsize, newsize; newsize = (new == NULL) ? 0 : strlen(new); if (old == NULL) @@ -2122,7 +2217,7 @@ istrstr(lookin, lookfor) char *lookfor; { char *cp; - int len; + size_t len; len = strlen(lookfor); for (cp = lookin; *cp != '\0'; ++cp) @@ -2158,7 +2253,7 @@ static char ** enlist(cpp, new, len) char **cpp; char *new; - int len; + size_t len; { int i, j; @@ -2210,7 +2305,7 @@ comsubs(left, right) char **cpp; char *lcp; char *rcp; - int i, len; + size_t i, len; if (left == NULL || right == NULL) return NULL; @@ -2225,7 +2320,7 @@ comsubs(left, right) while (rcp != NULL) { for (i = 1; lcp[i] != '\0' && lcp[i] == rcp[i]; ++i) - ; + continue; if (i > len) len = i; rcp = index(rcp + 1, *lcp); @@ -2285,6 +2380,7 @@ inboth(left, right) } both = addlists(both, temp); freelist(temp); + free(temp); if (both == NULL) return NULL; } @@ -2321,8 +2417,9 @@ struct dfa *dfa; token t; static must must0; struct dfamust *dm; + static char empty_string[] = ""; - result = ""; + result = empty_string; exact = 0; musts = (must *) malloc((dfa->tindex + 1) * sizeof *musts); if (musts == NULL) @@ -2509,7 +2606,7 @@ struct dfa *dfa; 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, 1); + mp->in = enlist(mp->in, mp->is, (size_t)1); if (mp->in == NULL) goto done; } diff --git a/gnu/usr.bin/grep/dfa.h b/gnu/usr.bin/grep/dfa.h index 32e05fc2aa4a..1e125158dd38 100644 --- a/gnu/usr.bin/grep/dfa.h +++ b/gnu/usr.bin/grep/dfa.h @@ -1,5 +1,5 @@ /* dfa.h - declarations for GNU deterministic regexp compiler - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1998 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,23 +13,44 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Written June, 1988 by Mike Haertel */ +/* $FreeBSD$ */ + /* FIXME: 2. We should not export so much of the DFA internals. In addition to clobbering modularity, we eat up valuable name space. */ +# undef PARAMS +#if __STDC__ +# ifndef _PTR_T +# define _PTR_T + typedef void * ptr_t; +# endif +# define PARAMS(x) x +#else +# ifndef _PTR_T +# define _PTR_T + typedef char * ptr_t; +# endif +# define PARAMS(x) () +#endif + /* Number of bits in an unsigned char. */ +#ifndef CHARBITS #define CHARBITS 8 +#endif /* First integer value that is greater than any character code. */ #define NOTCHAR (1 << CHARBITS) /* INTBITS need not be exact, just a lower bound. */ +#ifndef INTBITS #define INTBITS (CHARBITS * sizeof (int)) +#endif /* Number of ints required to hold a bit for every character. */ #define CHARCLASS_INTS ((NOTCHAR + INTBITS - 1) / INTBITS) @@ -301,16 +322,14 @@ struct dfa /* Entry points. */ -#if __STDC__ - /* dfasyntax() takes two arguments; the first sets the syntax bits described earlier in this file, and the second sets the case-folding flag. */ -extern void dfasyntax(int, int); +extern void dfasyntax PARAMS ((reg_syntax_t, int)); /* Compile the given string of the given length into the given struct dfa. Final argument is a flag specifying whether to build a searching or an exact matcher. */ -extern void dfacomp(char *, size_t, struct dfa *, int); +extern void dfacomp PARAMS ((char *, size_t, struct dfa *, int)); /* Execute the given struct dfa on the buffer of characters. The first char * points to the beginning, and the second points to the @@ -324,26 +343,26 @@ extern void dfacomp(char *, size_t, struct dfa *, int); order to verify backreferencing; otherwise the flag will be cleared. Returns NULL if no match is found, or a pointer to the first character after the first & shortest matching string in the buffer. */ -extern char *dfaexec(struct dfa *, char *, char *, int, int *, int *); +extern char *dfaexec PARAMS ((struct dfa *, char *, char *, int, int *, int *)); /* Free the storage held by the components of a struct dfa. */ -extern void dfafree(struct dfa *); +extern void dfafree PARAMS ((struct dfa *)); /* Entry points for people who know what they're doing. */ /* Initialize the components of a struct dfa. */ -extern void dfainit(struct dfa *); +extern void dfainit PARAMS ((struct dfa *)); /* Incrementally parse a string of given length into a struct dfa. */ -extern void dfaparse(char *, size_t, struct dfa *); +extern void dfaparse PARAMS ((char *, size_t, struct dfa *)); /* Analyze a parsed regexp; second argument tells whether to build a searching or an exact matcher. */ -extern void dfaanalyze(struct dfa *, int); +extern void dfaanalyze PARAMS ((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 PARAMS ((int, struct dfa *, int [])); /* Error handling. */ @@ -351,10 +370,4 @@ extern void dfastate(int, struct dfa *, int []); takes a single argument, a NUL-terminated string describing the error. The default dfaerror() prints the error message to stderr and exits. The user can provide a different dfafree() if so desired. */ -extern void dfaerror(char *); - -#else /* ! __STDC__ */ -extern void dfasyntax(), dfacomp(), dfafree(), dfainit(), dfaparse(); -extern void dfaanalyze(), dfastate(), dfaerror(); -extern char *dfaexec(); -#endif /* ! __STDC__ */ +extern void dfaerror PARAMS ((const char *)); diff --git a/gnu/usr.bin/grep/getopt.c b/gnu/usr.bin/grep/getopt.c index a59a01339835..f919ed7e4d31 100644 --- a/gnu/usr.bin/grep/getopt.c +++ b/gnu/usr.bin/grep/getopt.c @@ -3,52 +3,45 @@ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! - Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 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 2, or (at your option) any - later version. + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. - This program is distributed in the hope that it will be useful, + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* $FreeBSD$ */ -/* NOTE!!! AIX requires this to be the first thing in the file. - Do not put ANYTHING before it! */ -#if !defined (__GNUC__) && defined (_AIX) - #pragma alloca +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO #endif #ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef __GNUC__ -#define alloca __builtin_alloca -#else /* not __GNUC__ */ -#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))) -#include <alloca.h> -#else -#ifndef _AIX -char *alloca (); +#include <config.h> #endif -#endif /* alloca.h */ -#endif /* not __GNUC__ */ -#if !__STDC__ && !defined(const) && IN_GCC +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const #define const #endif - -/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ -#ifndef _NO_PROTO -#define _NO_PROTO #endif #include <stdio.h> @@ -61,24 +54,49 @@ char *alloca (); 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__) +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ -#undef alloca /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include <stdlib.h> -#else /* Not GNU C library. */ -#define __alloca alloca +#include <unistd.h> #endif /* GNU C library. */ -/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a - long-named option. Because this is not POSIX.2 compliant, it is - being phased out. */ -/* #define GETOPT_COMPAT */ +#ifdef VMS +#include <unixlib.h> +#if HAVE_STRING_H - 0 +#include <string.h> +#endif +#endif + +#if defined (WIN32) && !defined (__CYGWIN32__) +/* It's not Unix, really. See? Capital letters. */ +#include <windows.h> +#define getpid() GetCurrentProcessId() +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +#ifdef HAVE_LIBINTL_H +# include <libintl.h> +# define _(msgid) gettext (msgid) +#else +# define _(msgid) (msgid) +#endif +#endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user @@ -102,7 +120,7 @@ char *alloca (); Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ -char *optarg = 0; +char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller @@ -110,14 +128,20 @@ char *optarg = 0; On entry to `getopt', zero means this is the first call; initialize. - When `getopt' returns EOF, 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 how much of ARGV has been scanned so far. */ -/* XXX 1003.2 says this must be 1 before any call. */ -int optind = 0; +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. @@ -166,12 +190,15 @@ int optopt = '?'; 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 EOF with `optind' != ARGC. */ + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries @@ -180,7 +207,6 @@ static enum in GCC. */ #include <string.h> #define my_index strchr -#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) #else /* Avoid depending on library functions or files @@ -202,17 +228,19 @@ my_index (str, chr) return 0; } -static void -my_bcopy (from, to, size) - const char *from; - char *to; - int size; -{ - int i; - for (i = 0; i < size; i++) - to[i] = from[i]; -} -#endif /* GNU C library. */ +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ @@ -223,6 +251,31 @@ my_bcopy (from, to, size) static int first_nonopt; static int last_nonopt; +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +static const char *nonoption_flags; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void store_args (int argc, char *const *argv) __attribute__ ((unused)); +static void +store_args (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +text_set_element (__libc_subinit, store_args); +#endif + /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. @@ -232,27 +285,126 @@ static int last_nonopt; `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ +#if defined (__STDC__) && __STDC__ +static void exchange (char **); +#endif + static void exchange (argv) char **argv; { - int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); - char **temp = (char **) __alloca (nonopts_size); + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; - /* Interchange the two blocks of data in ARGV. */ + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ - my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); - my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], - (optind - last_nonopt) * sizeof (char *)); - my_bcopy ((char *) temp, - (char *) &argv[first_nonopt + optind - last_nonopt], - nonopts_size); + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } + +/* Initialize the internal data when the first call is made. */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + /* Bash 2.0 puts a special variable in the environment for each + command it runs, specifying which ARGV elements are the results of + file name wildcard expansion and therefore should not be + considered as options. */ + char var[100]; + sprintf (var, "_%d_GNU_nonoption_argv_flags_", getpid ()); + nonoption_flags = getenv (var); + if (nonoption_flags == NULL) + nonoption_flags_len = 0; + else + nonoption_flags_len = strlen (nonoption_flags); + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. @@ -267,7 +419,7 @@ exchange (argv) 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 `EOF'. + 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.) @@ -319,41 +471,38 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int *longind; int long_only; { - int option_index; - - optarg = 0; - - /* Initialize the internal data when the first call is made. - Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ + optarg = NULL; - if (optind == 0) + if (!__getopt_initialized || optind == 0) { - first_nonopt = last_nonopt = optind = 1; - - nextchar = NULL; - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (getenv ("POSIXLY_CORRECT") != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; + optstring = _getopt_initialize (argc, argv, optstring); + optind = 1; /* Don't scan ARGV[0], the program name. */ + __getopt_initialized = 1; } + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + if (nextchar == NULL || *nextchar == '\0') { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, @@ -364,21 +513,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) else if (last_nonopt != optind) first_nonopt = optind; - /* Now skip any additional non-options + /* Skip any additional non-options and extend the range of non-options previously skipped. */ - while (optind < argc - && (argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL - || argv[optind][0] != '+' || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) + while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } - /* 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. */ @@ -405,56 +548,64 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; - return EOF; + return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ - if ((argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL - || argv[optind][0] != '+' || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) + if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) - return EOF; + return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. - Start decoding its characters. */ + Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + if (longopts != NULL - && ((argv[optind][0] == '-' - && (argv[optind][1] == '-' || long_only)) -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ - )) + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { + char *nameend; const struct option *p; - char *s = nextchar; + const struct option *pfound = NULL; int exact = 0; int ambig = 0; - const struct option *pfound = NULL; - int indfound; + int indfound = -1; + int option_index; - while (*s && *s != '=') - s++; + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; - /* Test all options for either exact match or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; - p++, option_index++) - if (!strncmp (p->name, nextchar, s - nextchar)) + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) { - if (s - nextchar == strlen (p->name)) + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; @@ -469,17 +620,18 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) indfound = option_index; } else - /* Second nonexact match found. */ + /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) - fprintf (stderr, "%s: option `%s' is ambiguous\n", + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; + optopt = 0; return '?'; } @@ -487,28 +639,29 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { option_index = indfound; optind++; - if (*s) + if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) - optarg = s + 1; + optarg = nameend + 1; else { if (opterr) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - "%s: option `--%s' doesn't allow an argument\n", - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - "%s: option `%c%s' doesn't allow an argument\n", - argv[0], argv[optind - 1][0], pfound->name); - } + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + nextchar += strlen (nextchar); + + optopt = pfound->val; return '?'; } } @@ -519,9 +672,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) else { if (opterr) - fprintf (stderr, "%s: option `%s' requires an argument\n", - argv[0], argv[optind - 1]); + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); nextchar += strlen (nextchar); + optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } @@ -535,34 +690,33 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } return pfound->val; } + /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ - fprintf (stderr, "%s: unrecognized option `--%s'\n", + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ - fprintf (stderr, "%s: unrecognized option `%c%s'\n", + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; + optopt = 0; return '?'; } } - /* Look at and handle the next option-character. */ + /* Look at and handle the next short option-character. */ { char c = *nextchar++; @@ -576,20 +730,141 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { if (opterr) { -#if 0 - if (c < 040 || c >= 0177) - fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else - fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); -#else - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); -#endif + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); } optopt = c; return '?'; } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } if (temp[1] == ':') { if (temp[2] == ':') @@ -601,7 +876,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) optind++; } else - optarg = 0; + optarg = NULL; nextchar = NULL; } else @@ -618,14 +893,10 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { if (opterr) { -#if 0 - fprintf (stderr, "%s: option `-%c' requires an argument\n", - argv[0], c); -#else /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "%s: option requires an argument -- %c\n", - argv[0], c); -#endif + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); } optopt = c; if (optstring[0] == ':') @@ -656,7 +927,7 @@ getopt (argc, argv, optstring) 0); } -#endif /* _LIBC or not __GNU_LIBRARY__. */ +#endif /* Not ELIDE_CODE. */ #ifdef TEST @@ -676,7 +947,7 @@ main (argc, argv) int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); - if (c == EOF) + if (c == -1) break; switch (c) diff --git a/gnu/usr.bin/grep/getopt.h b/gnu/usr.bin/grep/getopt.h index 45541f5ac0f9..4209871f7a2e 100644 --- a/gnu/usr.bin/grep/getopt.h +++ b/gnu/usr.bin/grep/getopt.h @@ -1,19 +1,25 @@ /* Declarations for getopt. - Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1989,90,91,92,93,94,96,97, 98 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 2, or (at your option) any - later version. + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. - This program is distributed in the hope that it will be useful, + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* $FreeBSD$ */ #ifndef _GETOPT_H #define _GETOPT_H 1 @@ -36,7 +42,7 @@ extern char *optarg; On entry to `getopt', zero means this is the first call; initialize. - When `getopt' returns EOF, 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 @@ -76,7 +82,7 @@ extern int optopt; struct option { -#if __STDC__ +#if defined (__STDC__) && __STDC__ const char *name; #else char *name; @@ -94,15 +100,15 @@ struct option #define required_argument 1 #define optional_argument 2 -#if __STDC__ -#if defined(__GNU_LIBRARY__) +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); -#endif /* not __GNU_LIBRARY__ */ +#endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, @@ -120,7 +126,7 @@ extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); -#endif /* not __STDC__ */ +#endif /* __STDC__ */ #ifdef __cplusplus } diff --git a/gnu/usr.bin/grep/getpagesize.h b/gnu/usr.bin/grep/getpagesize.h index e6bd5610678a..4d562216f797 100644 --- a/gnu/usr.bin/grep/getpagesize.h +++ b/gnu/usr.bin/grep/getpagesize.h @@ -1,42 +1,43 @@ -#ifdef BSD -#ifndef BSD4_1 -#define HAVE_GETPAGESIZE -#endif -#endif +/* Emulate getpagesize on systems that lack it. */ -#ifndef HAVE_GETPAGESIZE - -#ifdef VMS -#define getpagesize() 512 -#endif +/* $FreeBSD$ */ -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef _SC_PAGESIZE -#define getpagesize() sysconf(_SC_PAGESIZE) -#else +#ifndef HAVE_GETPAGESIZE -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> +# ifdef VMS +# define getpagesize() 512 +# endif -#ifdef EXEC_PAGESIZE -#define getpagesize() EXEC_PAGESIZE -#else -#ifdef NBPG -#define getpagesize() NBPG * CLSIZE -#ifndef CLSIZE -#define CLSIZE 1 -#endif /* no CLSIZE */ -#else /* no NBPG */ -#define getpagesize() NBPC -#endif /* no NBPG */ -#endif /* no EXEC_PAGESIZE */ -#else /* !HAVE_SYS_PARAM_H */ -#define getpagesize() 8192 /* punt totally */ -#endif /* !HAVE_SYS_PARAM_H */ -#endif /* no _SC_PAGESIZE */ +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif -#endif /* not HAVE_GETPAGESIZE */ +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ +#endif /* no HAVE_GETPAGESIZE */ diff --git a/gnu/usr.bin/grep/grep.1 b/gnu/usr.bin/grep/grep.1 index 6f5c48a9bfd9..75361a9a80fd 100644 --- a/gnu/usr.bin/grep/grep.1 +++ b/gnu/usr.bin/grep/grep.1 @@ -1,18 +1,29 @@ -.TH GREP 1 "1992 September 10" "GNU Project" +.\" grep man page +.\" $FreeBSD$ +.de Id +.ds Dt \\$4 +.. +.Id $Id: grep.1,v 1.1 1998/11/22 06:45:20 alainm Exp $ +.TH GREP 1 \*(Dt "GNU Project" .SH NAME grep, egrep, fgrep, zgrep \- print lines matching a pattern .SH SYNOPSIS .B grep -[\-[AB] num] -[\-HRPS] -[\-CEFGLVabchilnqsvwx] -[\-e expr] -[\-f file] -files... - +[-[AB] NUM] [-CEFGVZabchiLlnqrsvwxyUu] [-e PATTERN | -f FILE] +[-d ACTION] [--directories=ACTION] +[--extended-regexp] [--fixed-strings] [--basic-regexp] +[--regexp=PATTERN] [--file=FILE] [--ignore-case] [--word-regexp] +[--line-regexp] [--line-regexp] [--no-messages] [--revert-match] +[--version] [--help] [--byte-offset] [--line-number] +[--with-filename] [--no-filename] [--quiet] [--silent] [--text] +[--files-without-match] [--files-with-matcces] [--count] +[--before-context=NUM] [--after-context=NUM] [--context] +[--binary] [--unix-byte-offsets] [--recursive] +[--decompress] +.I files... .SH DESCRIPTION .PP -.B Grep +.B grep searches the named input .I files (or standard input if no files are named, or @@ -30,17 +41,17 @@ There are three major variants of controlled by the following options. .PD 0 .TP -.B \-G +.B \-G, --basic-regexp Interpret .I pattern as a basic regular expression (see below). This is the default. .TP -.B \-E +.B \-E, --extended-regexp Interpret .I pattern as an extended regular expression (see below). .TP -.B \-F +.B \-F, --fixed-strings Interpret .I pattern as a list of fixed strings, separated by newlines, @@ -51,19 +62,17 @@ In addition, two variant programs and .B fgrep are available. -.B Egrep +.B egrep is similar (but not identical) to .BR "grep\ \-E" , and is compatible with the historical Unix .BR egrep . -.B Fgrep +.B fgrep is the same as .BR "grep\ \-F" . -When called as -.BR zgrep , -the -.BR \-Z -option is assumed. +.B zgrep +is the same as +.BR "grep\ \-Z" . .PD .LP All variants of @@ -71,90 +80,157 @@ All variants of understand the following options: .PD 0 .TP -.BI \- num -Matches will be printed with -.I num -lines of leading and trailing context. However, -.B grep -will never print any given line more than once. -.TP -.BI \-A " num" +.BI \-A " NUM" ", --after-context=" NUM Print -.I num +.I NUM lines of trailing context after matching lines. .TP -.BI \-B " num" +.BI \-B " NUM" ", --before-context=" NUM Print -.I num +.I NUM lines of leading context before matching lines. .TP -.B \-C -Equivalent to -.BR \-2 . +.BI \-C ,\ --context"[=NUM]" +Print +.I NUM +lines (default 2) of output context. +.TP +.BI \- NUM \ +Same as --context=NUM lines of leading and trailing context. However, +.B grep +will never print any given line more than once. .TP -.B \-V +.B \-V, --version Print the version number of .B grep to standard error. This version number should be included in all bug reports (see below). .TP -.B \-a -Don't search in binary files. -.TP -.B \-b +.B \-b, --byte-offset Print the byte offset within the input file before each line of output. .TP -.B \-c +.B \-c, --count Suppress normal output; instead print a count of matching lines for each input file. With the -.B \-v +.B \-v, --revert-match option (see below), count non-matching lines. .TP -.BI \-e " pattern" +.BI \-d " ACTION" ", --directories=" ACTION +If an input file is a directory, use +.I ACTION +to process it. By default, +.I ACTION +is +.BR read , +which means that directories are read just as if they were ordinary files. +If +.I ACTION +is +.BR skip , +directories are silently skipped. +If +.I ACTION +is +.BR recurse , +.B +grep reads all files under each directory, recursively; +this is equivalent to the +.B \-r +option. +.TP +.BI \-e " PATTERN" ", --regexp=" PATTERN Use -.I pattern +.I PATTERN as the pattern; useful to protect patterns beginning with .BR \- . .TP -.BI \-f " file" -Obtain the pattern from -.IR file . +.BI \-f " FILE" ", --file=" FILE +Obtain patterns from +.IR FILE , +one per line. +The empty file contains zero patterns, and therfore matches nothing. .TP -.B \-h +.B \-h, --no-filename Suppress the prefixing of filenames on output when multiple files are searched. .TP -.B \-i +.B \-i, --ignore-case Ignore case distinctions in both the .I pattern and the input files. .TP -.B \-L +.B \-L, --files-without-match Suppress normal output; instead print the name of each input file from which no output would -normally have been printed. +normally have been printed. The scanning will stop +on the first match. .TP -.B \-l +.B \-l, --files-with-matches Suppress normal output; instead print the name of each input file from which output -would normally have been printed. +would normally have been printed. The scanning will +stop on the first match. .TP -.B \-n +.B \-n, --line-number Prefix each line of output with the line number within its input file. .TP -.B \-q -Quiet; suppress normal output. -.TP +.B \-q, --quiet, --silent +Quiet; suppress normal output. The scanning will stop +on the first match. +Also see the .B \-s +or +.B --no-messages +option below. +.TP +.B \-r, --recursive +Read all files under each directory, recursively; +this is equivalent to the +.B "\-d recurse" +option. +.TP +.B \-s, --no-messages Suppress error messages about nonexistent or unreadable files. +Portability note: unlike GNU +.BR grep , +BSD +.B grep +does not comply with POSIX.2, because BSD +.B grep +lacks a +.B \-q +option and its +.B \-s +option behaves like GNU +.BR grep 's +.B \-q +option. +Shell scripts intended to be portable to BSD +.B grep +should avoid both +.B \-q +and +.B \-s +and should redirect output to /dev/null instead. .TP -.B \-v +.B \-a, --text +Do not suppress output lines that contain binary data. +Normally, if the first few bytes of a file indicate that +the file contains binary data, +.B grep +outputs only a message saying that the file matches the pattern. +This option causes +.B grep +to act as if the file is a text file, +even if it would otherwise be treated as binary. +.TP +.B \-v, --revert-match Invert the sense of matching, to select non-matching lines. .TP -.B \-w +.B \-w, --word-regexp Select only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word constituent @@ -162,44 +238,48 @@ character. Similarly, it must be either at the end of the line or followed by a non-word constituent character. Word-constituent characters are letters, digits, and the underscore. .TP -.B \-x +.B \-x, --line-regexp Select only those matches that exactly match the whole line. - -.PP -Following options are only available if compiled with FTS library: -.PD 0 -.TP -.BI \-H -If the -.I \-R -option is specified, symbolic links on the command line -are followed. (Symbolic links encountered in the tree traversal -are not followed.) .TP -.BI \-L -If the -.I \-R -option is specified, all symbolic links are followed. +.B \-y +Obsolete synonym for +.BR \-i . .TP -.BI \-P -If the -.I \-R -option is specified, no symbolic links are followed. +.B \-U, --binary +Treat the file(s) as binary. By default, under MS-DOS and MS-Windows, +.BR grep +guesses the file type by looking at the contents of the first 32KB +read from the file. If +.BR grep +decides the file is a text file, it strips the CR characters from the +original file contents (to make regular expressions with +.B ^ +and +.B $ +work correctly). Specifying +.B \-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 CR/LF +pairs at the end of each line, this will cause some regular +expressions to fail. This option is only supported on MS-DOS and +MS-Windows. .TP -.BI \-R -Search in the file hierarchies -rooted in the files instead of just the files themselves. - +.B \-u, --unix-byte-offsets +Report Unix-style byte offsets. This switch causes +.B grep +to report byte offsets as if the file were Unix-style text file, i.e. with +CR characters stripped off. This will produce results identical to running +.B grep +on a Unix machine. This option has no effect unless +.B \-b +option is also used; it is only supported on MS-DOS and MS-Windows. +.PD .LP -Following option is only available if compiled with zlib library: +Following option is only available if compiled with zlib(3) library: .PD 0 .TP -.BI \-Z -If the -.I \-Z -option is specified, the input data will be -decompressed before searching. -.TP +.B \-Z, --decompress +Decompress the input data before searching. .PD .SH "REGULAR EXPRESSIONS" .PP @@ -207,7 +287,7 @@ A regular expression is a pattern that describes a set of strings. Regular expressions are constructed analogously to arithmetic expressions, by using various operators to combine smaller expressions. .PP -.B Grep +.B grep understands two different versions of regular expression syntax: ``basic'' and ``extended.'' In .RB "GNU\ " grep , @@ -251,7 +331,7 @@ Their names are self explanatory, and they are .BR [:upper:] , and .BR [:xdigit:]. -For example, +For example, .B [[:alnum:]] means .BR [0-9A-Za-z] , @@ -300,8 +380,7 @@ matches the empty string provided it's .I not at the edge of a word. .PP -A regular expression matching a single character may be followed -by one of several repetition operators: +A regular expression may be followed by one of several repetition operators: .PD 0 .TP .B ? @@ -383,6 +462,14 @@ the metacharacter .B { loses its special meaning; instead use .BR \e{ . +.SH ENVIRONMENT +The environment variable +.B GREP_OPTIONS +can hold a set of default +options for +.I grep. +These options are interpreted first and can be overwritten by explicit command +line parameters. .SH DIAGNOSTICS .PP Normally, exit status is 0 if matches were found, @@ -395,7 +482,7 @@ other system errors. .SH BUGS .PP Email bug reports to -.BR bug-gnu-utils@prep.ai.mit.edu . +.BR bug-gnu-utils@gnu.org . Be sure to include the word ``grep'' somewhere in the ``Subject:'' field. .PP Large repetition counts in the diff --git a/gnu/usr.bin/grep/grep.c b/gnu/usr.bin/grep/grep.c index 72349860c9f6..569f43a5c34a 100644 --- a/gnu/usr.bin/grep/grep.c +++ b/gnu/usr.bin/grep/grep.c @@ -1,5 +1,5 @@ /* grep.c - main driver file for grep. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1997, 1998, 1999 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,260 +13,334 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ - Written July 1992 by Mike Haertel. +/* Written July 1992 by Mike Haertel. */ +/* Builtin decompression 1997 by Wolfram Schneider <wosch@FreeBSD.org>. */ - Recursive searching and builtin decompression (libz) - 1996/1997 by Wolfram Schneider <wosch@FreeBSD.org>. */ +/* $FreeBSD$ */ -#include <errno.h> -#include <stdio.h> -#ifdef __FreeBSD__ -#include <locale.h> -#endif - -#ifndef errno -extern int errno; +#ifdef HAVE_CONFIG_H +# include <config.h> #endif - -#ifdef STDC_HEADERS -#include <stdlib.h> -#else #include <sys/types.h> -extern char *malloc(), *realloc(); -extern void free(); -#endif - -#if defined(STDC_HEADERS) || defined(HAVE_STRING_H) -#include <string.h> -#ifdef NEED_MEMORY_H -#include <memory.h> -#endif -#else -#include <strings.h> -#ifdef __STDC__ -extern void *memchr(); -#else -extern char *memchr(); -#endif -#define strrchr rindex +#include <sys/stat.h> +#if defined(HAVE_MMAP) +# include <sys/mman.h> #endif - -#ifdef HAVE_UNISTD_H -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#else -#define O_RDONLY 0 -#define STDIN_FILENO 0 -extern int open(), read(), close(); +#if defined(HAVE_SETRLIMIT) +# include <sys/time.h> +# include <sys/resource.h> #endif - +#include <stdio.h> +#include "system.h" +#include "getopt.h" #include "getpagesize.h" #include "grep.h" +#include "savedir.h" #undef MAX #define MAX(A,B) ((A) > (B) ? (A) : (B)) -/* Provide missing ANSI features if necessary. */ +struct stats +{ + struct stats *parent; + struct stat stat; +}; -#ifndef HAVE_STRERROR -extern int sys_nerr; -extern char *sys_errlist[]; -#define strerror(E) ((E) < sys_nerr ? sys_errlist[(E)] : "bogus error number") -#endif +/* base of chain of stat buffers, used to detect directory loops */ +static struct stats stats_base; -#ifndef HAVE_MEMCHR -#ifdef __STDC__ -#define VOID void -#else -#define VOID char -#endif -VOID * -memchr(vp, c, n) - VOID *vp; - int c; - size_t n; -{ - unsigned char *p; +/* if non-zero, display usage information and exit */ +static int show_help; - for (p = (unsigned char *) vp; n--; ++p) - if (*p == c) - return (VOID *) p; - return 0; -} -#endif +/* If non-zero, print the version on standard output and exit. */ +static int show_version; -/* traverse a file hierarchy library */ -#if HAVE_FTS > 0 -#include <sys/types.h> -#include <sys/stat.h> -#include <fts.h> +/* Long options equivalences. */ +static struct option long_options[] = +{ + {"after-context", required_argument, NULL, 'A'}, + {"basic-regexp", no_argument, NULL, 'G'}, + {"before-context", required_argument, NULL, 'B'}, + {"byte-offset", no_argument, NULL, 'b'}, + {"context", optional_argument, NULL, 'C'}, + {"count", no_argument, NULL, 'c'}, + {"directories", required_argument, NULL, 'd'}, + {"extended-regexp", no_argument, NULL, 'E'}, + {"file", required_argument, NULL, 'f'}, + {"files-with-matches", no_argument, NULL, 'l'}, + {"files-without-match", no_argument, NULL, 'L'}, + {"fixed-regexp", no_argument, NULL, 'F'}, + {"fixed-strings", no_argument, NULL, 'F'}, + {"help", no_argument, &show_help, 1}, + {"ignore-case", no_argument, NULL, 'i'}, + {"line-number", no_argument, NULL, 'n'}, + {"line-regexp", no_argument, NULL, 'x'}, + {"no-filename", no_argument, NULL, 'h'}, + {"no-messages", no_argument, NULL, 's'}, + {"quiet", no_argument, NULL, 'q'}, + {"recursive", no_argument, NULL, 'r'}, + {"regexp", required_argument, NULL, 'e'}, + {"revert-match", no_argument, NULL, 'v'}, + {"silent", no_argument, NULL, 'q'}, + {"text", no_argument, NULL, 'a'}, +#if O_BINARY + {"binary", no_argument, NULL, 'U'}, + {"unix-byte-offsets", no_argument, NULL, 'u'}, #endif - -/* don't search in binary files */ -int aflag; + {"version", no_argument, NULL, 'V'}, + {"with-filename", no_argument, NULL, 'H'}, + {"word-regexp", no_argument, NULL, 'w'}, +#if HAVE_LIBZ > 0 + {"decompress", no_argument, NULL, 'Z'}, +#endif + {0, 0, 0, 0} +}; /* Define flags declared in grep.h. */ -char *matcher; +char const *matcher; int match_icase; int match_words; int match_lines; -/* Functions we'll use to search. */ -static void (*compile)(); -static char *(*execute)(); - /* For error messages. */ static char *prog; -static char *filename; +static char const *filename; static int errseen; +/* How to handle directories. */ +static enum + { + READ_DIRECTORIES, + RECURSE_DIRECTORIES, + SKIP_DIRECTORIES + } directories; + +static int ck_atoi PARAMS ((char const *, int *)); +static void usage PARAMS ((int)) __attribute__((noreturn)); +static void error PARAMS ((const char *, int)); +static int setmatcher PARAMS ((char const *)); +static char *page_alloc PARAMS ((size_t, char **)); +static int reset PARAMS ((int, char const *, struct stats *)); +static int fillbuf PARAMS ((size_t, struct stats *)); +static int grepbuf PARAMS ((char *, char *)); +static void prtext PARAMS ((char *, char *, int *)); +static void prpending PARAMS ((char *)); +static void prline PARAMS ((char *, char *, int)); +static void print_offset_sep PARAMS ((off_t, int)); +static void nlscan PARAMS ((char *)); +static int grep PARAMS ((int, char const *, struct stats *)); +static int grepdir PARAMS ((char const *, struct stats *)); +static int grepfile PARAMS ((char const *, struct stats *)); +#if O_BINARY +static inline int undossify_input PARAMS ((register char *, size_t)); +#endif + +/* Functions we'll use to search. */ +static void (*compile) PARAMS ((char *, size_t)); +static char *(*execute) PARAMS ((char *, size_t, char **)); + /* Print a message and possibly an error string. Remember that something awful happened. */ static void -error(mesg, errnum) -#ifdef __STDC__ - const -#endif - char *mesg; +error (mesg, errnum) + const char *mesg; int errnum; { if (errnum) - fprintf(stderr, "%s: %s: %s\n", prog, mesg, strerror(errnum)); + fprintf (stderr, "%s: %s: %s\n", prog, mesg, strerror (errnum)); else - fprintf(stderr, "%s: %s\n", prog, mesg); + fprintf (stderr, "%s: %s\n", prog, mesg); errseen = 1; } -/* Like error(), but die horribly after printing. */ +/* Like error (), but die horribly after printing. */ void -fatal(mesg, errnum) -#ifdef __STDC__ - const -#endif - char *mesg; +fatal (mesg, errnum) + const char *mesg; int errnum; { - error(mesg, errnum); - exit(2); + error (mesg, errnum); + exit (2); } /* Interface to handle errors and fix library lossage. */ char * -xmalloc(size) +xmalloc (size) size_t size; { char *result; - result = malloc(size); + result = malloc (size); if (size && !result) - fatal("memory exhausted", 0); + fatal (_("memory exhausted"), 0); return result; } /* Interface to handle errors and fix some library lossage. */ char * -xrealloc(ptr, size) +xrealloc (ptr, size) char *ptr; size_t size; { char *result; if (ptr) - result = realloc(ptr, size); + result = realloc (ptr, size); else - result = malloc(size); + result = malloc (size); if (size && !result) - fatal("memory exhausted", 0); + fatal (_("memory exhausted"), 0); return result; } -#if !defined(HAVE_VALLOC) -#define valloc malloc -#else -#ifdef __STDC__ -extern void *valloc(size_t); -#else -extern char *valloc(); -#endif -#endif +/* Convert STR to a positive integer, storing the result in *OUT. + If STR is not a valid integer, return -1 (otherwise 0). */ +static int +ck_atoi (str, out) + char const *str; + int *out; +{ + char const *p; + for (p = str; *p; p++) + if (*p < '0' || *p > '9') + return -1; + + *out = atoi (optarg); + return 0; +} + /* Hairy buffering mechanism for grep. The intent is to keep all reads aligned on a page boundary and multiples of the page size. */ +static char *ubuffer; /* Unaligned base of buffer. */ static char *buffer; /* Base of buffer. */ static size_t bufsalloc; /* Allocated size of buffer save region. */ static size_t bufalloc; /* Total buffer size. */ static int bufdesc; /* File descriptor. */ static char *bufbeg; /* Beginning of user-visible stuff. */ static char *buflim; /* Limit of user-visible stuff. */ +static size_t pagesize; /* alignment of memory pages */ -#if defined(HAVE_WORKING_MMAP) -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> - +#if defined(HAVE_MMAP) static int bufmapped; /* True for ordinary files. */ -static struct stat bufstat; /* From fstat(). */ static off_t bufoffset; /* What read() normally remembers. */ +static off_t initial_bufoffset; /* Initial value of bufoffset. */ #endif #if HAVE_LIBZ > 0 #include <zlib.h> -static gzFile gzbufdesc; /* zlib file descriptor. */ -static int Zflag; /* uncompress before searching */ +static gzFile gzbufdesc; /* zlib file descriptor. */ +static int Zflag; /* uncompress before searching. */ #endif -/* Reset the buffer for a new file. Initialize - on the first time through. */ -void -reset(fd) - int fd; +/* Return VAL aligned to the next multiple of ALIGNMENT. VAL can be + an integer or a pointer. Both args must be free of side effects. */ +#define ALIGN_TO(val, alignment) \ + ((size_t) (val) % (alignment) == 0 \ + ? (val) \ + : (val) + ((alignment) - (size_t) (val) % (alignment))) + +/* Return the address of a new page-aligned buffer of size SIZE. Set + *UP to the newly allocated (but possibly unaligned) buffer used to + *build the aligned buffer. To free the buffer, free (*UP). */ +static char * +page_alloc (size, up) + size_t size; + char **up; { - static int initialized; + /* HAVE_WORKING_VALLOC means that valloc is properly declared, and + you can free the result of valloc. This symbol is not (yet) + autoconfigured. It can be useful to define HAVE_WORKING_VALLOC + while debugging, since some debugging memory allocators might + catch more bugs if this symbol is enabled. */ +#if HAVE_WORKING_VALLOC + *up = valloc (size); + return *up; +#else + size_t asize = size + pagesize - 1; + if (size <= asize) + { + *up = malloc (asize); + if (*up) + return ALIGN_TO (*up, pagesize); + } + return NULL; +#endif +} - if (!initialized) +/* Reset the buffer for a new file, returning zero if we should skip it. + Initialize on the first time through. */ +static int +reset (fd, file, stats) + int fd; + char const *file; + struct stats *stats; +{ + if (pagesize == 0) { - initialized = 1; + size_t ubufsalloc; + pagesize = getpagesize (); + if (pagesize == 0) + abort (); #ifndef BUFSALLOC - bufsalloc = MAX(8192, getpagesize()); + ubufsalloc = MAX (8192, pagesize); #else - bufsalloc = BUFSALLOC; + ubufsalloc = BUFSALLOC; #endif + bufsalloc = ALIGN_TO (ubufsalloc, pagesize); bufalloc = 5 * bufsalloc; /* The 1 byte of overflow is a kludge for dfaexec(), which inserts a sentinel newline at the end of the buffer being searched. There's gotta be a better way... */ - buffer = valloc(bufalloc + 1); - if (!buffer) - fatal("memory exhausted", 0); + if (bufsalloc < ubufsalloc + || bufalloc / 5 != bufsalloc || bufalloc + 1 < bufalloc + || ! (buffer = page_alloc (bufalloc + 1, &ubuffer))) + fatal (_("memory exhausted"), 0); bufbeg = buffer; buflim = buffer; } #if HAVE_LIBZ > 0 if (Zflag) { gzbufdesc = gzdopen(fd, "r"); - if (gzbufdesc == NULL) - fatal("memory exhausted", 0); + if (gzbufdesc == NULL) + fatal(_("memory exhausted"), 0); } #endif - bufdesc = fd; -#if defined(HAVE_WORKING_MMAP) + bufdesc = fd; + + if ( +#if defined(HAVE_MMAP) + 1 +#else + directories != READ_DIRECTORIES +#endif + ) + if (fstat (fd, &stats->stat) != 0) + { + error ("fstat", errno); + return 0; + } + if (directories == SKIP_DIRECTORIES && S_ISDIR (stats->stat.st_mode)) + return 0; +#if defined(HAVE_MMAP) if ( #if HAVE_LIBZ > 0 - Zflag || + Zflag || #endif - fstat(fd, &bufstat) < 0 || !S_ISREG(bufstat.st_mode)) + !S_ISREG (stats->stat.st_mode)) bufmapped = 0; else { bufmapped = 1; - bufoffset = lseek(fd, 0, 1); + bufoffset = initial_bufoffset = file ? 0 : lseek (fd, 0, 1); } #endif + return 1; } /* Read new stuff into the buffer, saving the specified @@ -274,60 +348,63 @@ reset(fd) to the beginning of the buffer contents, and 'buflim' points just after the end. Return count of new stuff. */ static int -fillbuf(save) +fillbuf (save, stats) size_t save; + struct stats *stats; { - char *nbuffer, *dp, *sp; int cc; -#if defined(HAVE_WORKING_MMAP) +#if defined(HAVE_MMAP) caddr_t maddr; #endif - static int pagesize; - - if (pagesize == 0 && (pagesize = getpagesize()) == 0) - abort(); if (save > bufsalloc) { + char *nubuffer; + char *nbuffer; + while (save > bufsalloc) bufsalloc *= 2; bufalloc = 5 * bufsalloc; - nbuffer = valloc(bufalloc + 1); - if (!nbuffer) - fatal("memory exhausted", 0); + if (bufalloc / 5 != bufsalloc || bufalloc + 1 < bufalloc + || ! (nbuffer = page_alloc (bufalloc + 1, &nubuffer))) + fatal (_("memory exhausted"), 0); + + bufbeg = nbuffer + bufsalloc - save; + memcpy (bufbeg, buflim - save, save); + free (ubuffer); + ubuffer = nubuffer; + buffer = nbuffer; } else - nbuffer = buffer; - - sp = buflim - save; - dp = nbuffer + bufsalloc - save; - bufbeg = dp; - while (save--) - *dp++ = *sp++; - - /* We may have allocated a new, larger buffer. Since - there is no portable vfree(), we just have to forget - about the old one. Sorry. */ - buffer = nbuffer; + { + bufbeg = buffer + bufsalloc - save; + memcpy (bufbeg, buflim - save, save); + } -#if defined(HAVE_WORKING_MMAP) +#if defined(HAVE_MMAP) if (bufmapped && bufoffset % pagesize == 0 - && bufstat.st_size - bufoffset >= bufalloc - bufsalloc) + && stats->stat.st_size - bufoffset >= bufalloc - bufsalloc) { maddr = buffer + bufsalloc; - maddr = mmap(maddr, bufalloc - bufsalloc, PROT_READ | PROT_WRITE, + maddr = mmap (maddr, bufalloc - bufsalloc, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, bufdesc, bufoffset); if (maddr == (caddr_t) -1) { - fprintf(stderr, "%s: warning: %s: %s\n", filename, - strerror(errno)); + /* This used to issue a warning, but on some hosts + (e.g. Solaris 2.5) mmap can fail merely because some + other process has an advisory read lock on the file. + There's no point alarming the user about this misfeature. */ +#if 0 + fprintf (stderr, _("%s: warning: %s: %s\n"), prog, filename, + strerror (errno)); +#endif goto tryread; } #if 0 /* You might thing this (or MADV_WILLNEED) would help, but it doesn't, at least not on a Sun running 4.1. In fact, it actually slows us down about 30%! */ - madvise(maddr, bufalloc - bufsalloc, MADV_SEQUENTIAL); + madvise (maddr, bufalloc - bufsalloc, MADV_SEQUENTIAL); #endif cc = bufalloc - bufsalloc; bufoffset += cc; @@ -341,22 +418,27 @@ fillbuf(save) if (bufmapped) { bufmapped = 0; - lseek(bufdesc, bufoffset, 0); + if (bufoffset != initial_bufoffset) + lseek (bufdesc, bufoffset, 0); } #if HAVE_LIBZ > 0 - if (Zflag) - cc = gzread(gzbufdesc, buffer + bufsalloc, bufalloc - bufsalloc); - else + if (Zflag) + cc = gzread (gzbufdesc, buffer + bufsalloc, bufalloc - bufsalloc); + else #endif - cc = read(bufdesc, buffer + bufsalloc, bufalloc - bufsalloc); + cc = read (bufdesc, buffer + bufsalloc, bufalloc - bufsalloc); } #else #if HAVE_LIBZ > 0 - if (Zflag) - cc = gzread(gzbufdesc, buffer + bufsalloc, bufalloc - bufsalloc); + if (Zflag) + cc = gzread (gzbufdesc, buffer + bufsalloc, bufalloc - bufsalloc); else #endif - cc = read(bufdesc, buffer + bufsalloc, bufalloc - bufsalloc); + cc = read (bufdesc, buffer + bufsalloc, bufalloc - bufsalloc); +#endif /*HAVE_MMAP*/ +#if O_BINARY + if (cc > 0) + cc = undossify_input (buffer + bufsalloc, cc); #endif if (cc > 0) buflim = buffer + bufsalloc + cc; @@ -366,6 +448,7 @@ fillbuf(save) } /* Flags controlling the style of output. */ +static int always_text; /* Assume the input is always text. */ static int out_quiet; /* Suppress all normal output. */ static int out_invert; /* Print nonmatching stuff. */ static int out_file; /* Print filenames. */ @@ -373,19 +456,27 @@ 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 int count_matches; /* print a count of matching lines */ +static int count_matches; /* Count matching lines. */ +static int list_files; /* List matching files. */ +static int no_filenames; /* Suppress file names. */ +static int suppress_errors; /* Suppress diagnostics. */ /* Internal variables to keep track of byte count, context, etc. */ -static size_t totalcc; /* Total character count before bufbeg. */ +static off_t totalcc; /* Total character count before bufbeg. */ static char *lastnl; /* Pointer after last newline counted. */ static char *lastout; /* Pointer after last character output; NULL if no character has been output or if it's conceptually before bufbeg. */ -static size_t totalnl; /* Total newline count before lastnl. */ +static off_t totalnl; /* Total newline count before lastnl. */ static int pending; /* Pending lines of output. */ +static int done_on_match; /* Stop scanning file on first match */ + +#if O_BINARY +# include "dosbuf.c" +#endif static void -nlscan(lim) +nlscan (lim) char *lim; { char *beg; @@ -397,30 +488,55 @@ nlscan(lim) } static void -prline(beg, lim, sep) +print_offset_sep (pos, sep) + off_t pos; + int sep; +{ + /* Do not rely on printf to print pos, since off_t may be longer than long, + and long long is not portable. */ + + char buf[sizeof pos * CHAR_BIT]; + char *p = buf + sizeof buf - 1; + *p = sep; + + do + *--p = '0' + pos % 10; + while ((pos /= 10) != 0); + + fwrite (p, 1, buf + sizeof buf - p, stdout); +} + +static void +prline (beg, lim, sep) char *beg; char *lim; - char sep; + int sep; { if (out_file) - printf("%s%c", filename, sep); + printf ("%s%c", filename, sep); if (out_line) { - nlscan(beg); - printf("%d%c", ++totalnl, sep); + nlscan (beg); + print_offset_sep (++totalnl, sep); lastnl = lim; } if (out_byte) - printf("%lu%c", (unsigned long)(totalcc + (beg - bufbeg)), sep); - fwrite(beg, 1, lim - beg, stdout); - if (ferror(stdout)) - error("writing output", errno); + { + off_t pos = totalcc + (beg - bufbeg); +#if O_BINARY + pos = dossified_pos (pos); +#endif + print_offset_sep (pos, sep); + } + fwrite (beg, 1, lim - beg, stdout); + if (ferror (stdout)) + error (_("writing output"), errno); lastout = lim; } /* Print pending lines of trailing context prior to LIM. */ static void -prpending(lim) +prpending (lim) char *lim; { char *nl; @@ -430,18 +546,18 @@ prpending(lim) while (pending > 0 && lastout < lim) { --pending; - if ((nl = memchr(lastout, '\n', lim - lastout)) != 0) + if ((nl = memchr (lastout, '\n', lim - lastout)) != 0) ++nl; else nl = lim; - prline(lastout, nl, '-'); + prline (lastout, nl, '-'); } } /* 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(beg, lim, nlinesp) +prtext (beg, lim, nlinesp) char *beg; char *lim; int *nlinesp; @@ -451,7 +567,7 @@ prtext(beg, lim, nlinesp) int i, n; if (!out_quiet && pending > 0) - prpending(beg); + prpending (beg); p = beg; @@ -469,12 +585,12 @@ prtext(beg, lim, nlinesp) /* We only print the "--" separator if our output is discontiguous from the last output in the file. */ if ((out_before || out_after) && used && p != lastout) - puts("--"); + puts ("--"); while (p < beg) { - nl = memchr(p, '\n', beg - p); - prline(p, nl + 1, '-'); + nl = memchr (p, '\n', beg - p); + prline (p, nl + 1, '-'); p = nl + 1; } } @@ -484,19 +600,19 @@ prtext(beg, lim, nlinesp) /* Caller wants a line count. */ for (n = 0; p < lim; ++n) { - if ((nl = memchr(p, '\n', lim - p)) != 0) + if ((nl = memchr (p, '\n', lim - p)) != 0) ++nl; else nl = lim; if (!out_quiet) - prline(p, nl, ':'); + prline (p, nl, ':'); p = nl; } *nlinesp = n; } else if (!out_quiet) - prline(beg, lim, ':'); + prline (beg, lim, ':'); pending = out_after; used = 1; @@ -506,7 +622,7 @@ prtext(beg, lim, nlinesp) between matching lines if OUT_INVERT is true). Return a count of lines printed. */ static int -grepbuf(beg, lim) +grepbuf (beg, lim) char *beg; char *lim; { @@ -523,59 +639,57 @@ grepbuf(beg, lim) break; if (!out_invert) { - prtext(b, endp, (int *) 0); + prtext (b, endp, (int *) 0); nlines += 1; + if (done_on_match) + return nlines; } else if (p < b) { - prtext(p, b, &n); + prtext (p, b, &n); nlines += n; } p = endp; } if (out_invert && p < lim) { - prtext(p, lim, &n); + prtext (p, lim, &n); nlines += n; } return nlines; } - -/* - * try to guess if buf belong to a binary file - */ - -int isBinaryFile(buf, len) - char *buf; - int len; -{ -#define BINARY_BUF_LEN 32 - int i; - - len = (len < BINARY_BUF_LEN ? len : BINARY_BUF_LEN); - - /* look for non-printable chars */ - for(i = 0; i < len; i++, buf++) - if (!isprint(*buf) && !isspace(*buf)) - return(1); - - return(0); -} - - - -/* Search a given file. Return a count of lines printed. */ +/* 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(fd) +grep (fd, file, stats) int fd; + char const *file; + struct stats *stats; { int nlines, i; + int not_text; size_t residue, save; char *beg, *lim; - int first, cc; - reset(fd); + if (!reset (fd, file, stats)) + 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 HAVE_LIBZ > 0 + if (Zflag) + gzclose(gzbufdesc); + else +#endif + if (close (fd) != 0) + error (file, errno); + return grepdir (file, stats) - 2; + } totalcc = 0; lastout = 0; @@ -585,22 +699,21 @@ grep(fd) nlines = 0; residue = 0; save = 0; - first = 0; - cc = 0; - for (;;) + if (fillbuf (save, stats) < 0) { - if ((cc = fillbuf(save)) < 0) - { - error(filename, errno); - return nlines; - } + if (! (is_EISDIR (errno, file) && suppress_errors)) + error (filename, errno); + return nlines; + } - /* skip binary files */ - if (!first && aflag && isBinaryFile(bufbeg, cc)) - return(0); - first++; + not_text = (! (always_text | out_quiet) + && memchr (bufbeg, '\0', buflim - bufbeg)); + done_on_match += not_text; + out_quiet += not_text; + for (;;) + { lastnl = bufbeg; if (lastout) lastout = bufbeg; @@ -612,12 +725,11 @@ grep(fd) residue = buflim - lim; if (beg < lim) { - nlines += grepbuf(beg, lim); + nlines += grepbuf (beg, lim); if (pending) - prpending(lim); - /* optimization */ - if (nlines && out_quiet && !count_matches) - return(nlines); + prpending (lim); + if (nlines && done_on_match && !out_invert) + goto finish_grep; } i = 0; beg = lim; @@ -633,107 +745,449 @@ grep(fd) save = residue + lim - beg; totalcc += buflim - bufbeg - save; if (out_line) - nlscan(beg); + nlscan (beg); + if (fillbuf (save, stats) < 0) + { + if (! (is_EISDIR (errno, file) && suppress_errors)) + error (filename, errno); + goto finish_grep; + } } if (residue) { - nlines += grepbuf(bufbeg + save - residue, buflim); + nlines += grepbuf (bufbeg + save - residue, buflim); if (pending) - prpending(buflim); + prpending (buflim); } + + finish_grep: + done_on_match -= not_text; + out_quiet -= not_text; + if ((not_text & ~out_quiet) && nlines != 0) + printf (_("Binary file %s matches\n"), filename); return nlines; } -static char version[] = "GNU grep version 2.0"; - -#define GETOPT_STD "0123456789A:B:CEFGLVX:abce:f:hilnqsvwxy" -#if HAVE_FTS > 0 -#define GETOPT_FTS "HPRS" -#else -#define GETOPT_FTS "" +static int +grepfile (file, stats) + char const *file; + struct stats *stats; +{ + int desc; + int count; + int status; + + if (! file) + { + desc = 0; + filename = _("(standard input)"); + } + else + { + desc = open (file, O_RDONLY); + + if (desc < 0) + { + int e = errno; + + if (is_EISDIR (e, file) && directories == RECURSE_DIRECTORIES) + { + if (stat (file, &stats->stat) != 0) + { + error (file, errno); + return 1; + } + + return grepdir (file, stats); + } + + if (!suppress_errors) + { + if (directories == SKIP_DIRECTORIES) + switch (e) + { +#ifdef EISDIR + case EISDIR: + return 1; #endif + case EACCES: + /* When skipping directories, don't worry about + directories that can't be opened. */ + if (stat (file, &stats->stat) == 0 + && S_ISDIR (stats->stat.st_mode)) + return 1; + break; + } + + error (file, e); + } + + return 1; + } + + filename = file; + } + +#if O_BINARY + /* Set input to binary mode. Pipes are simulated with files + on DOS, so this includes the case of "foo | grep bar". */ + if (!isatty (desc)) + SET_BINARY (desc); +#endif + + count = grep (desc, file, stats); + if (count < 0) + status = count + 2; + else + { + if (count_matches) + { + if (out_file) + printf ("%s:", filename); + printf ("%d\n", count); + } + + if (count) + { + status = 0; + if (list_files == 1) + printf ("%s\n", filename); + } + else + { + status = 1; + if (list_files == -1) + printf ("%s\n", filename); + } + #if HAVE_LIBZ > 0 -#define GETOPT_Z "Z" -#else -#define GETOPT_Z "" + if (Zflag) + gzclose(gzbufdesc); + else #endif + if (file && close (desc) != 0) + error (file, errno); + } + + return status; +} + +static int +grepdir (dir, stats) + char const *dir; + struct stats *stats; +{ + int status = 1; + struct stats *ancestor; + char *name_space; + + 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) + fprintf (stderr, _("%s: warning: %s: %s\n"), prog, dir, + _("recursive directory loop")); + return 1; + } + + name_space = savedir (dir, (unsigned) stats->stat.st_size); + + if (! name_space) + { + if (errno) + { + if (!suppress_errors) + error (dir, errno); + } + else + fatal (_("Memory exhausted"), 0); + } + else + { + size_t dirlen = strlen (dir); + int needs_slash = ! (dirlen == FILESYSTEM_PREFIX_LEN (dir) + || IS_SLASH (dir[dirlen - 1])); + char *file = NULL; + char *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; + if (file) + free (file); + free (name_space); + } + + return status; +} static void -usage() +usage(status) +int status; { - fprintf(stderr, "usage: %s [-[AB] <num>] [-CEFGLVX%s%s%s", - prog, GETOPT_FTS, GETOPT_Z, - "abchilnqsvwxy]\n [-e <expr>] [-f file] [files ...]\n"); - exit(2); + if (status != 0) + { + fprintf (stderr, _("Usage: %s [OPTION]... PATTERN [FILE]...\n"), prog); + fprintf (stderr, _("Try `%s --help' for more information.\n"), prog); + } + else + { + printf (_("Usage: %s [OPTION]... PATTERN [FILE] ...\n"), prog); + printf (_("\ +Search for PATTERN in each FILE or standard input.\n\ +\n\ +Regexp selection and interpretation:\n\ + -E, --extended-regexp PATTERN is an extended regular expression\n\ + -F, --fixed-regexp PATTERN is a fixed string separated by newlines\n\ + -G, --basic-regexp PATTERN is a basic regular expression\n\ + -e, --regexp=PATTERN use PATTERN as a regular expression\n\ + -f, --file=FILE obtain PATTERN from FILE\n\ + -i, --ignore-case ignore case distinctions\n\ + -w, --word-regexp force PATTERN to match only whole words\n\ + -x, --line-regexp force PATTERN to match only whole lines\n")); + printf (_("\ +\n\ +Miscellaneous:\n\ + -s, --no-messages suppress error messages\n\ + -v, --revert-match select non-matching lines\n\ + -V, --version print version information and exit\n\ + -Z, --decompress decompress input before searching (HAVE_LIBZ=1)\n\ + --help display this help and exit\n")); + printf (_("\ +\n\ +Output control:\n\ + -b, --byte-offset print the byte offset with output lines\n\ + -n, --line-number print line number with output lines\n\ + -H, --with-filename print the filename for each match\n\ + -h, --no-filename suppress the prefixing filename on output\n\ + -q, --quiet, --silent suppress all normal output\n\ + -a, --text do not suppress binary output\n\ + -d, --directories=ACTION how to handle directories\n\ + ACTION is 'read', 'recurse', or 'skip'.\n\ + -r, --recursive equivalent to --directories=recurse.\n\ + -L, --files-without-match only print FILE names containing no match\n\ + -l, --files-with-matches only print FILE names containing matches\n\ + -c, --count only print a count of matching lines per FILE\n")); + printf (_("\ +\n\ +Context control:\n\ + -B, --before-context=NUM print NUM lines of leading context\n\ + -A, --after-context=NUM print NUM lines of trailing context\n\ + -C, --context[=NUM] print NUM (default 2) lines of output context\n\ + unless overriden by -A or -B\n\ + -NUM same as --context=NUM\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\ +\n\ +If no -[GEF], then `egrep' assumes -E, `fgrep' -F, else -G.\n\ +With no FILE, or when FILE is -, read standard input. If less than\n\ +two FILEs given, assume -h. Exit with 0 if matches, with 1 if none.\n\ +Exit with 2 if syntax errors or system errors.\n")); + printf (_("\nReport bugs to <bug-gnu-utils@gnu.org>.\n")); + } + exit (status); } /* Go through the matchers vector and look for the specified matcher. If we find it, install it in compile and execute, and return 1. */ -int -setmatcher(name) - char *name; +static int +setmatcher (name) + char const *name; { int i; +#ifdef HAVE_SETRLIMIT + struct rlimit rlim; +#endif for (i = 0; matchers[i].name; ++i) - if (strcmp(name, matchers[i].name) == 0) + if (strcmp (name, matchers[i].name) == 0) { compile = matchers[i].compile; execute = matchers[i].execute; +#if HAVE_SETRLIMIT && defined(RLIMIT_STACK) + /* 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 return 1; } return 0; } +/* 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 +prepend_args (options, buf, argv) + char const *options; + char *buf; + char **argv; +{ + char const *o = options; + char *b = buf; + int n = 0; + + for (;;) + { + while (ISSPACE ((unsigned char) *o)) + o++; + if (!*o) + return n; + if (argv) + argv[n] = b; + n++; + + do + if ((*b++ = *o++) == '\\' && *o) + b[-1] = *o++; + while (*o && ! ISSPACE ((unsigned char) *o)); + + *b++ = '\0'; + } +} +/* 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 +prepend_default_options (options, pargc, pargv) + char const *options; + int *pargc; + char ***pargv; +{ + if (options) + { + char *buf = xmalloc (strlen (options) + 1); + int prepended = prepend_args (options, buf, (char **) NULL); + int argc = *pargc; + char * const *argv = *pargv; + char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp); + *pargc = prepended + argc; + *pargv = pp; + *pp++ = *argv++; + pp += prepend_args (options, buf, pp); + while ((*pp++ = *argv++)) + continue; + } +} int -main(argc, argv) +main (argc, argv) int argc; char *argv[]; { char *keys; size_t keycc, oldcc, keyalloc; - int keyfound, no_filenames, list_files, suppress_errors; - int opt, cc, desc, count, status; + int with_filenames; + int opt, cc, status; + unsigned digit_args_val, default_context; FILE *fp; extern char *optarg; extern int optind; -#if HAVE_FTS > 0 - int Rflag, Hflag, Pflag, Lflag; - FTS *ftsp; - FTSENT *ftsent; - int fts_options; + + initialize_main (&argc, &argv); + prog = argv[0]; + if (prog && strrchr (prog, '/')) + prog = strrchr (prog, '/') + 1; + +#if HAVE_LIBZ > 0 + if (prog[0] == 'z') { + Zflag = 1; + ++prog; + } #endif -#ifdef __FreeBSD__ - (void) setlocale(LC_ALL, ""); +#if defined(__MSDOS__) || defined(_WIN32) + /* DOS and MS-Windows use backslashes as directory separators, and usually + have an .exe suffix. They also have case-insensitive filesystems. */ + if (prog) + { + char *p = prog; + char *bslash = strrchr (argv[0], '\\'); + + if (bslash && bslash >= prog) /* for mixed forward/backslash case */ + prog = bslash + 1; + else if (prog == argv[0] + && argv[0][0] && argv[0][1] == ':') /* "c:progname" */ + prog = argv[0] + 2; + + /* Collapse the letter-case, so `strcmp' could be used hence. */ + for ( ; *p; p++) + if (*p >= 'A' && *p <= 'Z') + *p += 'a' - 'A'; + + /* Remove the .exe extension, if any. */ + if ((p = strrchr (prog, '.')) && strcmp (p, ".exe") == 0) + *p = '\0'; + } #endif - prog = argv[0]; - if (prog && strrchr(prog, '/')) - prog = strrchr(prog, '/') + 1; keys = NULL; keycc = 0; - keyfound = 0; - count_matches = 0; - no_filenames = 0; - list_files = 0; - suppress_errors = 0; + with_filenames = 0; matcher = NULL; - aflag = 0; -#if HAVE_FTS > 0 - Rflag = Hflag = Pflag = Lflag = 0; + + /* The value -1 means to use DEFAULT_CONTEXT. */ + out_after = out_before = -1; + /* Default before/after context: chaged by -C/-NUM options */ + default_context = 0; + /* Accumulated value of individual digits in a -NUM option */ + digit_args_val = 0; + + +/* Internationalization. */ +#if HAVE_SETLOCALE + setlocale (LC_ALL, ""); #endif -#if HAVE_LIBZ > 0 - if (*prog == 'z') { - prog++; - Zflag = 1; - } +#if ENABLE_NLS + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); #endif - while ((opt = getopt(argc, argv, - GETOPT_STD/**/GETOPT_FTS/**/GETOPT_Z)) != -1) + prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv); + + while ((opt = getopt_long (argc, argv, +#if O_BINARY + "0123456789A:B:C::EFGHVX:abcd:e:f:hiLlnqrsvwxyUu", +#elif HAVE_LIBZ > 0 + "0123456789A:B:C::EFGHRVX:Zabcd:e:f:hiLlnqrsvwxy", +#else + "0123456789A:B:C::EFGHRVX:abcd:e:f:hiLlnqrsvwxy", +#endif + long_options, NULL)) != EOF) switch (opt) { case '0': @@ -746,43 +1200,66 @@ main(argc, argv) case '7': case '8': case '9': - out_before = 10 * out_before + opt - '0'; - out_after = 10 * out_after + opt - '0'; + digit_args_val = 10 * digit_args_val + opt - '0'; + default_context = digit_args_val; break; case 'A': - out_after = atoi(optarg); - if (out_after < 0) - usage(); + if (optarg) + { + if (ck_atoi (optarg, &out_after)) + fatal (_("invalid context length argument"), 0); + } break; case 'B': - out_before = atoi(optarg); - if (out_before < 0) - usage(); + if (optarg) + { + if (ck_atoi (optarg, &out_before)) + fatal (_("invalid context length argument"), 0); + } break; case 'C': - out_before = out_after = 2; + /* Set output match context, but let any explicit leading or + trailing amount specified with -A or -B stand. */ + if (optarg) + { + if (ck_atoi (optarg, &default_context)) + fatal (_("invalid context length argument"), 0); + } + else + default_context = 2; break; case 'E': - if (matcher && strcmp(matcher, "egrep") != 0) - fatal("you may specify only one of -E, -F, or -G", 0); + if (matcher && strcmp (matcher, "posix-egrep") != 0) + fatal (_("you may specify only one of -E, -F, or -G"), 0); matcher = "posix-egrep"; break; case 'F': if (matcher && strcmp(matcher, "fgrep") != 0) - fatal("you may specify only one of -E, -F, or -G", 0);; + fatal(_("you may specify only one of -E, -F, or -G"), 0);; matcher = "fgrep"; break; case 'G': - if (matcher && strcmp(matcher, "grep") != 0) - fatal("you may specify only one of -E, -F, or -G", 0); + if (matcher && strcmp (matcher, "grep") != 0) + fatal (_("you may specify only one of -E, -F, or -G"), 0); matcher = "grep"; break; + case 'H': + with_filenames = 1; + break; +#if O_BINARY + case 'U': + dos_use_file_type = DOS_BINARY; + break; + case 'u': + dos_report_unix_offset = 1; + break; +#endif case 'V': - fprintf(stderr, "%s\n", version); + show_version = 1; break; case 'X': if (matcher) - fatal("matcher already specified", 0); + fatal (_("matcher already specified"), 0); matcher = optarg; break; #if HAVE_LIBZ > 0 @@ -790,32 +1267,8 @@ main(argc, argv) Zflag = 1; break; #endif -#if HAVE_FTS > 0 - /* symbolic links on the command line are followed */ - case 'H': - Hflag = 1; - Lflag = Pflag = 0; - break; - - /* no symbolic links are followed */ - case 'P': - Pflag = 1; - Hflag = Lflag = 0; - break; - - /* traverse file hierarchies */ - case 'R': - Rflag = 1; - break; - - /* all symbolic links are followed */ - case 'S': - Lflag = 1; - Hflag = Pflag = 0; - break; -#endif case 'a': - aflag = 1; + always_text = 1; break; case 'b': out_byte = 1; @@ -824,38 +1277,43 @@ main(argc, argv) out_quiet = 1; count_matches = 1; break; + case 'd': + if (strcmp (optarg, "read") == 0) + directories = READ_DIRECTORIES; + else if (strcmp (optarg, "skip") == 0) + directories = SKIP_DIRECTORIES; + else if (strcmp (optarg, "recurse") == 0) + directories = RECURSE_DIRECTORIES; + else + fatal (_("unknown directories method"), 0); + break; case 'e': - cc = strlen(optarg); - keys = xrealloc(keys, keycc + cc + 1); - if (keyfound) - keys[keycc++] = '\n'; - strcpy(&keys[keycc], optarg); + cc = strlen (optarg); + keys = xrealloc (keys, keycc + cc + 1); + strcpy (&keys[keycc], optarg); keycc += cc; - keyfound = 1; + keys[keycc++] = '\n'; break; case 'f': - fp = strcmp(optarg, "-") != 0 ? fopen(optarg, "r") : stdin; + fp = strcmp (optarg, "-") != 0 ? fopen (optarg, "r") : stdin; if (!fp) - fatal(optarg, errno); - for (keyalloc = 1; keyalloc <= keycc; keyalloc *= 2) + fatal (optarg, errno); + for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2) ; - keys = xrealloc(keys, keyalloc); + keys = xrealloc (keys, keyalloc); oldcc = keycc; - if (keyfound) - keys[keycc++] = '\n'; - while (!feof(fp) - && (cc = fread(keys + keycc, 1, keyalloc - keycc, fp)) > 0) + while (!feof (fp) + && (cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) > 0) { keycc += cc; - if (keycc == keyalloc) - keys = xrealloc(keys, keyalloc *= 2); + if (keycc == keyalloc - 1) + keys = xrealloc (keys, keyalloc *= 2); } if (fp != stdin) fclose(fp); - /* Nuke the final newline to avoid matching a null string. */ - if (keycc - oldcc > 0 && keys[keycc - 1] == '\n') - --keycc; - keyfound = 1; + /* Append final newline if file ended in non-newline. */ + if (oldcc != keycc && keys[keycc - 1] != '\n') + keys[keycc++] = '\n'; break; case 'h': no_filenames = 1; @@ -869,17 +1327,24 @@ main(argc, argv) Inspired by the same option in Hume's gre. */ out_quiet = 1; list_files = -1; + done_on_match = 1; break; case 'l': out_quiet = 1; list_files = 1; + done_on_match = 1; break; case 'n': out_line = 1; break; case 'q': + done_on_match = 1; out_quiet = 1; break; + case 'R': + case 'r': + directories = RECURSE_DIRECTORIES; + break; case 's': suppress_errors = 1; break; @@ -892,212 +1357,88 @@ main(argc, argv) case 'x': match_lines = 1; break; + case 0: + /* long options */ + break; default: - usage(); + usage (2); break; } - if (!keyfound) + if (out_after < 0) + out_after = default_context; + if (out_before < 0) + out_before = default_context; + + if (show_version) + { + printf (_("grep (GNU grep) %s\n"), VERSION); + printf ("\n"); + printf (_("\ +Copyright (C) 1988, 1992-1998, 1999 Free Software Foundation, Inc.\n")); + printf (_("\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")); + printf ("\n"); + exit (0); + } + + if (show_help) + usage (0); + + if (keys) + { + if (keycc == 0) + /* No keys were specified (e.g. -f /dev/null). Match nothing. */ + out_invert ^= 1; + else + /* Strip trailing newline. */ + --keycc; + } + else if (optind < argc) { keys = argv[optind++]; - keycc = strlen(keys); + keycc = strlen (keys); } else - usage(); + usage (2); - if (!matcher) + if (! matcher) matcher = prog; - if (!setmatcher(matcher) && !setmatcher("default")) - abort(); + if (!setmatcher (matcher) && !setmatcher ("default")) + abort (); (*compile)(keys, keycc); -#if HAVE_FTS > 0 - if ((argc - optind > 1 || Rflag) && !no_filenames) -#else - if (argc - optind > 1 && !no_filenames) -#endif + if ((argc - optind > 1 && !no_filenames) || with_filenames) out_file = 1; - status = 1; - -#if HAVE_FTS > 0 - if (Rflag) { - fts_options = FTS_PHYSICAL | FTS_NOCHDIR; - - if (Hflag) - fts_options |= FTS_COMFOLLOW; - - if (Lflag) { - fts_options |= FTS_LOGICAL; - fts_options &= ~FTS_PHYSICAL; - } - - if (Pflag) { - fts_options &= ~FTS_LOGICAL & ~FTS_COMFOLLOW; - fts_options |= FTS_PHYSICAL; - } - } - - if (Rflag && optind < argc) { - int i; - - /* replace "-" with "/dev/stdin" */ - for (i = optind; i < argc; i++) - if (strcmp(argv[i], "-") == 0) - *(argv + i) = "/dev/stdin"; - - if ((ftsp = fts_open(argv + optind, fts_options, - (int(*)())NULL)) == NULL) { - if (!suppress_errors) - error("", errno); - } else { - - while((ftsent = fts_read(ftsp)) != NULL) { - filename = ftsent->fts_accpath; - - switch(ftsent->fts_info) { - - /* regular file */ - case FTS_F: - break; - - /* directory */ - case FTS_D: - case FTS_DC: - case FTS_DP: - continue; break; - - /* errors */ - case FTS_DNR: - error(filename, errno); - continue; break; - - case FTS_ERR: - case FTS_NS: - error(filename, ftsent->fts_errno); - continue; break; - - /* dead symlink */ - case FTS_SLNONE: - continue; break; - - /* symlink, don't skip */ - case FTS_SL: - break; - - default: - /* - if (!suppress_errors) - fprintf(stderr, "%s: ignored\n", filename); - continue; break; - */ - - } - - if ((desc = open(filename, O_RDONLY)) == -1) { - error(filename, errno); - continue; - } - - count = grep(desc); - if (count_matches) - { - if (out_file) - printf("%s:", filename); - printf("%d\n", count); - } - if (count) - { - status = 0; - if (list_files == 1) - printf("%s\n", filename); - } - else if (list_files == -1) - printf("%s\n", filename); - - if (desc != STDIN_FILENO) { -#if HAVE_LIBZ > 0 - if (Zflag) - gzclose(gzbufdesc); - else +#if O_BINARY + /* Output is set to binary mode because we shouldn't convert + NL to CR-LF pairs, especially when grepping binary files. */ + if (!isatty (1)) + SET_BINARY (1); #endif - close(desc); - } - } - - if (fts_close(ftsp) == -1) - error("fts_close", errno); - } - /* ! Rflag */ - } else -#endif /* HAVE_FTS */ - - /* search in file names from arguments, not from stdin */ if (optind < argc) - - while (optind < argc) - { - desc = strcmp(argv[optind], "-") ? - open(argv[optind], O_RDONLY) : STDIN_FILENO; - if (desc < 0) - { - if (!suppress_errors) - error(argv[optind], errno); - } - else - { - filename = desc == STDIN_FILENO ? - "(standard input)" : argv[optind]; - count = grep(desc); - if (count_matches) - { - if (out_file) - printf("%s:", filename); - printf("%d\n", count); - } - if (count) - { - status = 0; - if (list_files == 1) - printf("%s\n", filename); - } - else if (list_files == -1) - printf("%s\n", filename); - - if (desc != STDIN_FILENO) { -#if HAVE_LIBZ > 0 - if (Zflag) - gzclose(gzbufdesc); - else -#endif - close(desc); - - } - } - ++optind; - } - - /* read input from stdin */ - else { - filename = "(standard input)"; - count = grep(STDIN_FILENO); - if (count_matches) - printf("%d\n", count); - if (count) + status = 1; + do { - status = 0; - if (list_files == 1) - printf("(standard input)\n"); + char *file = argv[optind]; + status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file, + &stats_base); } - else if (list_files == -1) - printf("(standard input)\n"); + while ( ++optind < argc); } + else + status = grepfile ((char *) NULL, &stats_base); + + if (fclose (stdout) == EOF) + error (_("writing output"), errno); - exit(errseen ? 2 : status); + exit (errseen ? 2 : status); } diff --git a/gnu/usr.bin/grep/grep.h b/gnu/usr.bin/grep/grep.h index a3316c501fb1..e12cff5f27be 100644 --- a/gnu/usr.bin/grep/grep.h +++ b/gnu/usr.bin/grep/grep.h @@ -1,5 +1,5 @@ /* grep.h - interface to grep driver for searching subroutines. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1998 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,11 +13,18 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ -#if __STDC__ +/* $FreeBSD$ */ -extern void fatal(const char *, int); +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__ +# define __attribute__(x) +#endif + +extern void fatal PARAMS ((const char *, int)) __attribute__((noreturn)); +extern char *xmalloc PARAMS ((size_t size)); +extern char *xrealloc PARAMS ((char *ptr, size_t size)); /* Grep.c expects the matchers vector to be terminated by an entry with a NULL name, and to contain at least @@ -26,25 +33,15 @@ extern void fatal(const char *, int); extern struct matcher { char *name; - void (*compile)(char *, size_t); - char *(*execute)(char *, size_t, char **); -} matchers[]; - -#else - -extern void fatal(); - -extern struct matcher -{ - char *name; - void (*compile)(); - char *(*execute)(); + void (*compile) PARAMS ((char *, size_t)); + char *(*execute) PARAMS ((char *, size_t, char **)); } matchers[]; -#endif - /* Exported from grep.c. */ -extern char *matcher; +extern char const *matcher; + +/* Exported from fgrepmat.c, egrepmat.c, grepmat.c. */ +extern char const default_matcher[]; /* The following flags are exported from grep for the matchers to look at. */ diff --git a/gnu/usr.bin/grep/kwset.c b/gnu/usr.bin/grep/kwset.c index 68871cb36a66..adde8a754733 100644 --- a/gnu/usr.bin/grep/kwset.c +++ b/gnu/usr.bin/grep/kwset.c @@ -1,10 +1,9 @@ /* kwset.c - search for any of a set of keywords. - Copyright 1989 Free Software Foundation - Written August 1989 by Mike Haertel. + Copyright (C) 1989, 1998 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 1, or (at your option) + the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,11 +13,15 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ +/* Written August 1989 by Mike Haertel. The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ +/* $FreeBSD$ */ + /* The algorithm implemented by these routines bears a startling resemblence to one discovered by Beate Commentz-Walter, although it is not identical. See "A String Matching Algorithm Fast on the Average," Technical Report, @@ -27,45 +30,20 @@ String Matching: An Aid to Bibliographic Search," CACM June 1975, Vol. 18, No. 6, which describes the failure function used below. */ -/* $FreeBSD$ */ - - -#ifdef STDC_HEADERS -#include <limits.h> -#include <stdlib.h> -#else -#define INT_MAX 2147483647 -#define UCHAR_MAX 255 -#ifdef __STDC__ -#include <stddef.h> -#else -#include <sys/types.h> -#endif -extern char *malloc(); -extern void free(); -#endif - -#ifdef HAVE_MEMCHR -#include <string.h> -#ifdef NEED_MEMORY_H -#include <memory.h> -#endif -#else -#ifdef __STDC__ -extern void *memchr(); -#else -extern char *memchr(); -#endif +#ifdef HAVE_CONFIG_H +# include <config.h> #endif +#include <sys/types.h> +#include "system.h" +#include "kwset.h" +#include "obstack.h" #ifdef GREP extern char *xmalloc(); -#define malloc xmalloc +# undef malloc +# define malloc xmalloc #endif -#include "kwset.h" -#include "obstack.h" - #define NCHAR (UCHAR_MAX + 1) #define obstack_chunk_alloc malloc #define obstack_chunk_free free @@ -108,6 +86,15 @@ struct kwset char *trans; /* Character translation table. */ }; +/* prototypes */ +static void enqueue PARAMS((struct tree *, struct trie **)); +static void treefails PARAMS((register struct tree *, struct trie *, struct trie *)); +static void treedelta PARAMS((register struct tree *,register unsigned int, unsigned char *)); +static int hasevery PARAMS((register struct tree *, register struct tree *)); +static void treenext PARAMS((struct tree *, struct trie **)); +static char * bmexec PARAMS((kwset_t, char *, size_t)); +static char * cwexec PARAMS((kwset_t, char *, size_t, struct kwsmatch *)); + /* Allocate and initialize a keyword set object, returning an opaque pointer to it. Return NULL if memory is not available. */ kwset_t @@ -196,13 +183,13 @@ kwsincr(kws, text, len) link = (struct tree *) obstack_alloc(&kwset->obstack, sizeof (struct tree)); if (!link) - return "memory exhausted"; + return _("memory exhausted"); link->llink = 0; link->rlink = 0; link->trie = (struct trie *) obstack_alloc(&kwset->obstack, sizeof (struct trie)); if (!link->trie) - return "memory exhausted"; + return _("memory exhausted"); link->trie->accepting = 0; link->trie->links = 0; link->trie->parent = trie; @@ -251,6 +238,8 @@ kwsincr(kws, text, len) r->balance = t->balance != (char) -1 ? 0 : 1; t->balance = 0; break; + default: + abort (); } break; case 2: @@ -269,8 +258,12 @@ kwsincr(kws, text, len) r->balance = t->balance != (char) -1 ? 0 : 1; t->balance = 0; break; + default: + abort (); } break; + default: + abort (); } if (dirs[depth - 1] == L) @@ -623,6 +616,10 @@ cwexec(kws, text, len, kwsmatch) register struct tree *tree; register char *trans; +#ifdef lint + accept = NULL; +#endif + /* Initialize register copies and look for easy ways out. */ kwset = (struct kwset *) kws; if (len < kwset->mind) diff --git a/gnu/usr.bin/grep/kwset.h b/gnu/usr.bin/grep/kwset.h index 95f62e715d98..f812b2e51806 100644 --- a/gnu/usr.bin/grep/kwset.h +++ b/gnu/usr.bin/grep/kwset.h @@ -1,10 +1,9 @@ /* kwset.h - header declaring the keyword set library. - Copyright 1989 Free Software Foundation - Written August 1989 by Mike Haertel. + Copyright (C) 1989, 1998 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 1, or (at your option) + the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,11 +13,15 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ +/* Written August 1989 by Mike Haertel. The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ +/* $FreeBSD$ */ + struct kwsmatch { int index; /* Index number of matching keyword. */ @@ -26,24 +29,22 @@ struct kwsmatch size_t size[1]; /* Length of each submatch. */ }; -#if __STDC__ - -typedef void *kwset_t; +typedef ptr_t kwset_t; /* Return an opaque pointer to a newly allocated keyword set, or NULL if enough memory cannot be obtained. The argument if non-NULL specifies a table of character translations to be applied to all pattern and search text. */ -extern kwset_t kwsalloc(char *); +extern kwset_t kwsalloc PARAMS((char *)); /* Incrementally extend the keyword set to include the given string. Return NULL for success, or an error message. Remember an index number for each keyword included in the set. */ -extern char *kwsincr(kwset_t, char *, size_t); +extern char *kwsincr PARAMS((kwset_t, char *, size_t)); /* When the keyword set has been completely built, prepare it for use. Return NULL for success, or an error message. */ -extern char *kwsprep(kwset_t); +extern char *kwsprep PARAMS((kwset_t)); /* Search through the given buffer for a member of the keyword set. Return a pointer to the leftmost longest match found, or NULL if @@ -51,19 +52,8 @@ extern char *kwsprep(kwset_t); the matching substring in the integer it points to. Similarly, if foundindex is non-NULL, store the index of the particular keyword found therein. */ -extern char *kwsexec(kwset_t, char *, size_t, struct kwsmatch *); +extern char *kwsexec PARAMS((kwset_t, char *, size_t, struct kwsmatch *)); /* Deallocate the given keyword set and all its associated storage. */ -extern void kwsfree(kwset_t); - -#else - -typedef char *kwset_t; - -extern kwset_t kwsalloc(); -extern char *kwsincr(); -extern char *kwsprep(); -extern char *kwsexec(); -extern void kwsfree(); +extern void kwsfree PARAMS((kwset_t)); -#endif diff --git a/gnu/usr.bin/grep/obstack.c b/gnu/usr.bin/grep/obstack.c index 7b9d3b9046d4..c77fdd4b9283 100644 --- a/gnu/usr.bin/grep/obstack.c +++ b/gnu/usr.bin/grep/obstack.c @@ -1,5 +1,10 @@ -/* obstack.c - subroutines used implicitly by object stack macros - Copyright (C) 1988, 1993 Free Software Foundation, Inc. +/* obstack.h - object stack macros + Copyright (C) 1988,89,90,91,92,93,94,96,97, 98 Free Software Foundation, Inc. + + the C library, however. The master source lives in /gd/gnu/lib. + +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 @@ -12,26 +17,44 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +along with this program; if not, write to the Free Software Foundation, +Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* $FreeBSD$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include "obstack.h" -/* This is just to get __GNU_LIBRARY__ defined. */ -#include <stdio.h> +/* NOTE BEFORE MODIFYING THIS FILE: This version number must be + incremented whenever callers compiled using an old obstack.h can no + longer properly call the functions in this obstack.c. */ +#define OBSTACK_INTERFACE_VERSION 1 /* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling + actually compiling the library itself, and the installed library + supports the same library interface we do. This code is part of the GNU + 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 files, - it is simpler to just do this in the source for each such file. */ + 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 <stdio.h> /* Random thing to get __GNU_LIBRARY__. */ +#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 +#include <gnu-versions.h> +#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif -#if defined (_LIBC) || !defined (__GNU_LIBRARY__) +#ifndef ELIDE_CODE -#ifdef __STDC__ + +#if defined (__STDC__) && __STDC__ #define POINTER void * #else #define POINTER char * @@ -40,7 +63,7 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Determine default alignment. */ struct fooalign {char x; double d;}; #define DEFAULT_ALIGNMENT \ - ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0)) + ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0)) /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. But in fact it might be less smart and round addresses to as much as DEFAULT_ROUNDING. So we prepare for it to do that. */ @@ -55,6 +78,28 @@ union fooround {long x; double d;}; #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'. + This variable by default points to the internal function + `print_and_abort'. */ +#if defined (__STDC__) && __STDC__ +static void print_and_abort (void); +void (*obstack_alloc_failed_handler) (void) = print_and_abort; +#else +static void print_and_abort (); +void (*obstack_alloc_failed_handler) () = print_and_abort; +#endif + +/* Exit value used when `print_and_abort' is used. */ +#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +int obstack_exit_failure = EXIT_FAILURE; + /* The non-GNU-C macros copy the obstack into this global variable to avoid multiple evaluation. */ @@ -66,37 +111,61 @@ struct obstack *_obstack; For free, do not use ?:, since some compilers, like the MIPS compilers, do not allow (expr) ? void : void. */ +#if defined (__STDC__) && __STDC__ #define CALL_CHUNKFUN(h, size) \ (((h) -> use_extra_arg) \ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ - : (*(h)->chunkfun) ((size))) + : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) #define CALL_FREEFUN(h, old_chunk) \ do { \ if ((h) -> use_extra_arg) \ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ else \ - (*(h)->freefun) ((old_chunk)); \ + (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ } while (0) +#else +#define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size))) + +#define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(void (*) ()) (h)->freefun) ((old_chunk)); \ + } while (0) +#endif /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). Objects start on multiples of ALIGNMENT (0 means use default). CHUNKFUN is the function to use to allocate chunks, - and FREEFUN the function to free them. */ + and FREEFUN the function to free them. -void + Return nonzero if successful, zero if out of memory. + To recover from an out of memory error, + free up some memory, then call this again. */ + +int _obstack_begin (h, size, alignment, chunkfun, freefun) struct obstack *h; int size; int alignment; +#if defined (__STDC__) && __STDC__ + POINTER (*chunkfun) (long); + void (*freefun) (void *); +#else POINTER (*chunkfun) (); void (*freefun) (); +#endif { - register struct _obstack_chunk* chunk; /* points to new chunk */ + register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) - alignment = DEFAULT_ALIGNMENT; + alignment = (int) DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { @@ -114,34 +183,48 @@ _obstack_begin (h, size, alignment, chunkfun, freefun) size = 4096 - extra; } +#if defined (__STDC__) && __STDC__ + h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; +#else h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; h->freefun = freefun; +#endif h->chunk_size = size; h->alignment_mask = alignment - 1; h->use_extra_arg = 0; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*obstack_alloc_failed_handler) (); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; } -void +int _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) struct obstack *h; int size; int alignment; +#if defined (__STDC__) && __STDC__ + POINTER (*chunkfun) (POINTER, long); + void (*freefun) (POINTER, POINTER); +#else POINTER (*chunkfun) (); void (*freefun) (); +#endif POINTER arg; { - register struct _obstack_chunk* chunk; /* points to new chunk */ + register struct _obstack_chunk *chunk; /* points to new chunk */ if (alignment == 0) - alignment = DEFAULT_ALIGNMENT; + alignment = (int) DEFAULT_ALIGNMENT; if (size == 0) /* Default size is what GNU malloc can fit in a 4096-byte block. */ { @@ -159,20 +242,29 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) size = 4096 - extra; } +#if defined(__STDC__) && __STDC__ + h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; +#else h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; h->freefun = freefun; +#endif h->chunk_size = size; h->alignment_mask = alignment - 1; h->extra_arg = arg; h->use_extra_arg = 1; chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*obstack_alloc_failed_handler) (); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size; chunk->prev = 0; /* The initial chunk now contains no empty object. */ h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; } /* Allocate a new current chunk for the obstack *H @@ -186,12 +278,12 @@ _obstack_newchunk (h, length) struct obstack *h; int length; { - register struct _obstack_chunk* old_chunk = h->chunk; - register struct _obstack_chunk* new_chunk; + register struct _obstack_chunk *old_chunk = h->chunk; + register struct _obstack_chunk *new_chunk; register long new_size; - register int obj_size = h->next_free - h->object_base; - register int i; - int already; + register long obj_size = h->next_free - h->object_base; + register long i; + long already; /* Compute size for new chunk. */ new_size = (obj_size + length) + (obj_size >> 3) + 100; @@ -199,7 +291,10 @@ _obstack_newchunk (h, length) new_size = h->chunk_size; /* Allocate and initialize the new chunk. */ - new_chunk = h->chunk = CALL_CHUNKFUN (h, new_size); + new_chunk = CALL_CHUNKFUN (h, new_size); + if (!new_chunk) + (*obstack_alloc_failed_handler) (); + h->chunk = new_chunk; new_chunk->prev = old_chunk; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; @@ -242,19 +337,25 @@ _obstack_newchunk (h, length) This is here for debugging. If you use it in a program, you are probably losing. */ +#if defined (__STDC__) && __STDC__ +/* Suppress -Wmissing-prototypes warning. We don't want to declare this in + obstack.h because it is just for debugging. */ +int _obstack_allocated_p (struct obstack *h, POINTER obj); +#endif + int _obstack_allocated_p (h, obj) struct obstack *h; POINTER obj; { - register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ - register struct _obstack_chunk* plp; /* point to previous chunk if any */ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = (h)->chunk; /* We use >= rather than > since the object cannot be exactly at the beginning of the chunk but might be an empty object exactly - at the end of an adjacent chunk. */ - while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) + at the end of an adjacent chunk. */ + while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; lp = plp; @@ -275,14 +376,14 @@ _obstack_free (h, obj) struct obstack *h; POINTER obj; { - register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ - register struct _obstack_chunk* plp; /* point to previous chunk if any */ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = h->chunk; /* We use >= because there cannot be an object at the beginning of a chunk. But there can be an empty object at that address at the end of another chunk. */ - while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) + while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; CALL_FREEFUN (h, lp); @@ -293,7 +394,7 @@ _obstack_free (h, obj) } if (lp) { - h->object_base = h->next_free = (char *)(obj); + h->object_base = h->next_free = (char *) (obj); h->chunk_limit = lp->limit; h->chunk = lp; } @@ -309,14 +410,14 @@ obstack_free (h, obj) struct obstack *h; POINTER obj; { - register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ - register struct _obstack_chunk* plp; /* point to previous chunk if any */ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ lp = h->chunk; /* We use >= because there cannot be an object at the beginning of a chunk. But there can be an empty object at that address at the end of another chunk. */ - while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj)) + while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) { plp = lp->prev; CALL_FREEFUN (h, lp); @@ -327,7 +428,7 @@ obstack_free (h, obj) } if (lp) { - h->object_base = h->next_free = (char *)(obj); + h->object_base = h->next_free = (char *) (obj); h->chunk_limit = lp->limit; h->chunk = lp; } @@ -336,6 +437,39 @@ obstack_free (h, obj) abort (); } +int +_obstack_memory_used (h) + struct obstack *h; +{ + register struct _obstack_chunk* lp; + register int nbytes = 0; + + for (lp = h->chunk; lp != 0; lp = lp->prev) + { + nbytes += lp->limit - (char *) lp; + } + return nbytes; +} + +/* Define the error handler. */ +#ifndef _ +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# ifndef _ +# define _(Str) gettext (Str) +# endif +# else +# define _(Str) (Str) +# endif +#endif + +static void +print_and_abort () +{ + fputs (_("memory exhausted\n"), stderr); + exit (obstack_exit_failure); +} + #if 0 /* These are now turned off because the applications do not use it and it uses bcopy via obstack_grow, which causes trouble on sysV. */ @@ -343,7 +477,7 @@ obstack_free (h, obj) /* Now define the functional versions of the obstack macros. Define them to simply use the corresponding macros to do the job. */ -#ifdef __STDC__ +#if defined (__STDC__) && __STDC__ /* These function definitions do not work with non-ANSI preprocessors; they won't pass through the macro names in parentheses. */ @@ -374,6 +508,13 @@ int (obstack_room) (obstack) return obstack_room (obstack); } +int (obstack_make_room) (obstack, length) + struct obstack *obstack; + int length; +{ + return obstack_make_room (obstack, length); +} + void (obstack_grow) (obstack, pointer, length) struct obstack *obstack; POINTER pointer; @@ -451,4 +592,4 @@ POINTER (obstack_copy0) (obstack, pointer, length) #endif /* 0 */ -#endif /* _LIBC or not __GNU_LIBRARY__. */ +#endif /* !ELIDE_CODE */ diff --git a/gnu/usr.bin/grep/obstack.h b/gnu/usr.bin/grep/obstack.h index 09d2c324b38c..df785c3b5e9d 100644 --- a/gnu/usr.bin/grep/obstack.h +++ b/gnu/usr.bin/grep/obstack.h @@ -1,5 +1,10 @@ /* obstack.h - object stack macros - Copyright (C) 1988, 1992 Free Software Foundation, Inc. + Copyright (C) 1988,89,90,91,92,93,94,96,97, 98 Free Software Foundation, Inc. + + the C library, however. The master source lives in /gd/gnu/lib. + +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 @@ -12,8 +17,10 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ +along with this program; if not, write to the Free Software Foundation, +Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* $FreeBSD$ */ /* Summary: @@ -100,47 +107,59 @@ Summary: /* Don't do the contents of this file more than once. */ -#ifndef __OBSTACKS__ -#define __OBSTACKS__ +#ifndef _OBSTACK_H +#define _OBSTACK_H 1 + +#ifdef __cplusplus +extern "C" { +#endif -/* We use subtraction of (char *)0 instead of casting to int +/* We use subtraction of (char *) 0 instead of casting to int because on word-addressable machines a simple cast to int may ignore the byte-within-word field of the pointer. */ #ifndef __PTR_TO_INT -#define __PTR_TO_INT(P) ((P) - (char *)0) +#define __PTR_TO_INT(P) ((P) - (char *) 0) #endif #ifndef __INT_TO_PTR -#define __INT_TO_PTR(P) ((P) + (char *)0) +#define __INT_TO_PTR(P) ((P) + (char *) 0) #endif /* We need the type of the resulting object. In ANSI C it is ptrdiff_t but in traditional C it is usually long. If we are in ANSI C and don't already have ptrdiff_t get it. */ -#if defined (__STDC__) && ! defined (offsetof) +#if defined (__STDC__) && __STDC__ && ! defined (offsetof) #if defined (__GNUC__) && defined (IN_GCC) /* On Next machine, the system's stddef.h screws up if included - after we have defined just ptrdiff_t, so include all of gstddef.h. + after we have defined just ptrdiff_t, so include all of stddef.h. Otherwise, define just ptrdiff_t, which is all we need. */ #ifndef __NeXT__ #define __need_ptrdiff_t #endif +#endif -/* While building GCC, the stddef.h that goes with GCC has this name. */ -#include "gstddef.h" -#else #include <stddef.h> #endif -#endif -#ifdef __STDC__ +#if defined (__STDC__) && __STDC__ #define PTR_INT_TYPE ptrdiff_t #else #define PTR_INT_TYPE long #endif +#if defined (_LIBC) || defined (HAVE_STRING_H) +#include <string.h> +#define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) +#else +#ifdef memcpy +#define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) +#else +#define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N)) +#endif +#endif + struct _obstack_chunk /* Lives at front of each chunk. */ { char *limit; /* 1 past end of this chunk */ @@ -151,39 +170,54 @@ struct _obstack_chunk /* Lives at front of each chunk. */ struct obstack /* control current object in current chunk */ { long chunk_size; /* preferred size to allocate chunks in */ - struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */ + struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ char *object_base; /* address of object we are building */ char *next_free; /* where to add next char to current object */ char *chunk_limit; /* address of char after current chunk */ PTR_INT_TYPE temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ +#if defined (__STDC__) && __STDC__ + /* 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); + void (*freefun) (void *, struct _obstack_chunk *); + void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ +#else struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ void (*freefun) (); /* User's function to free a chunk. */ char *extra_arg; /* first arg for chunk alloc/dealloc funcs */ +#endif unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ unsigned maybe_empty_object:1;/* There is a possibility that the current chunk contains a zero-length object. This prevents freeing the chunk if we allocate a bigger chunk to replace it. */ + unsigned alloc_failed:1; /* No longer used, as we now call the failed + handler on error, but retained for binary + compatibility. */ }; /* Declare the external functions we use; they are in obstack.c. */ -#ifdef __STDC__ +#if defined (__STDC__) && __STDC__ extern void _obstack_newchunk (struct obstack *, int); extern void _obstack_free (struct obstack *, void *); -extern void _obstack_begin (struct obstack *, int, int, - void *(*) (), void (*) ()); -extern void _obstack_begin_1 (struct obstack *, int, int, - void *(*) (), void (*) (), void *); +extern int _obstack_begin (struct obstack *, int, int, + void *(*) (long), void (*) (void *)); +extern int _obstack_begin_1 (struct obstack *, int, int, + void *(*) (void *, long), + void (*) (void *, void *), void *); +extern int _obstack_memory_used (struct obstack *); #else extern void _obstack_newchunk (); extern void _obstack_free (); -extern void _obstack_begin (); -extern void _obstack_begin_1 (); +extern int _obstack_begin (); +extern int _obstack_begin_1 (); +extern int _obstack_memory_used (); #endif -#ifdef __STDC__ +#if defined (__STDC__) && __STDC__ /* Do the function-declarations after the structs but before defining the macros. */ @@ -211,6 +245,7 @@ void * obstack_finish (struct obstack *obstack); int obstack_object_size (struct obstack *obstack); int obstack_room (struct obstack *obstack); +void obstack_make_room (struct obstack *obstack, int size); void obstack_1grow_fast (struct obstack *obstack, int data_char); void obstack_ptr_grow_fast (struct obstack *obstack, void *data); void obstack_int_grow_fast (struct obstack *obstack, int data); @@ -220,11 +255,24 @@ void * obstack_base (struct obstack *obstack); void * obstack_next_free (struct obstack *obstack); int obstack_alignment_mask (struct obstack *obstack); int obstack_chunk_size (struct obstack *obstack); +int obstack_memory_used (struct obstack *obstack); #endif /* __STDC__ */ /* Non-ANSI C cannot really support alternative functions for these macros, so we do not declare them. */ + +/* Error handler called when `obstack_chunk_alloc' failed to allocate + more memory. This can be set to a user defined function. The + default action is to print a message and abort. */ +#if defined (__STDC__) && __STDC__ +extern void (*obstack_alloc_failed_handler) (void); +#else +extern void (*obstack_alloc_failed_handler) (); +#endif + +/* 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. Note that this might not be the final address of the object @@ -244,6 +292,35 @@ int obstack_chunk_size (struct obstack *obstack); #define obstack_alignment_mask(h) ((h)->alignment_mask) +/* To prevent prototype warnings provide complete argument list in + standard C version. */ +#if defined (__STDC__) && __STDC__ + +#define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free) + +#define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free) + +#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) (long)) (chunkfun), (void (*) (void *)) (freefun)) + +#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) (void *, long)) (chunkfun), \ + (void (*) (void *, void *)) (freefun), (arg)) + +#define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) + +#define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) + +#else + #define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) @@ -260,12 +337,25 @@ int obstack_chunk_size (struct obstack *obstack); _obstack_begin_1 ((h), (size), (alignment), \ (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg)) +#define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun)) + +#define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)()) (newfreefun)) + +#endif + #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) #define obstack_blank_fast(h,n) ((h)->next_free += (n)) + +#define obstack_memory_used(h) _obstack_memory_used (h) -#if defined (__GNUC__) && defined (__STDC__) -#if __GNUC__ < 2 || defined(NeXT) +#if defined (__GNUC__) && defined (__STDC__) && __STDC__ +/* 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__. */ +#if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) #define __extension__ #endif @@ -284,18 +374,21 @@ int obstack_chunk_size (struct obstack *obstack); ({ struct obstack *__o = (OBSTACK); \ (unsigned) (__o->chunk_limit - __o->next_free); }) -/* Note that the call to _obstack_newchunk is enclosed in (..., 0) - so that we can avoid having void expressions - in the arms of the conditional expression. - Casting the third operand to void was tried before, - but some compilers won't accept it. */ +#define obstack_make_room(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + (void) 0; }) + #define obstack_grow(OBSTACK,where,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ - ((__o->next_free + __len > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, __len), 0) : 0); \ - bcopy (where, __o->next_free, __len); \ + if (__o->next_free + __len > __o->chunk_limit) \ + _obstack_newchunk (__o, __len); \ + _obstack_memcpy (__o->next_free, (char *) (where), __len); \ __o->next_free += __len; \ (void) 0; }) @@ -303,18 +396,18 @@ __extension__ \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ - ((__o->next_free + __len + 1 > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, __len + 1), 0) : 0), \ - bcopy (where, __o->next_free, __len), \ - __o->next_free += __len, \ + if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, __len + 1); \ + _obstack_memcpy (__o->next_free, (char *) (where), __len); \ + __o->next_free += __len; \ *(__o->next_free)++ = 0; \ (void) 0; }) #define obstack_1grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - ((__o->next_free + 1 > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, 1), 0) : 0), \ + if (__o->next_free + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, 1); \ *(__o->next_free)++ = (datum); \ (void) 0; }) @@ -325,28 +418,28 @@ __extension__ \ #define obstack_ptr_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - ((__o->next_free + sizeof (void *) > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, sizeof (void *)), 0) : 0), \ + if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (void *)); \ *((void **)__o->next_free)++ = ((void *)datum); \ (void) 0; }) #define obstack_int_grow(OBSTACK,datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - ((__o->next_free + sizeof (int) > __o->chunk_limit) \ - ? (_obstack_newchunk (__o, sizeof (int)), 0) : 0), \ + if (__o->next_free + sizeof (int) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (int)); \ *((int *)__o->next_free)++ = ((int)datum); \ (void) 0; }) -#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr) -#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) +#define obstack_ptr_grow_fast(h,aptr) (*((void **) (h)->next_free)++ = (void *)aptr) +#define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint) #define obstack_blank(OBSTACK,length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ int __len = (length); \ - ((__o->chunk_limit - __o->next_free < __len) \ - ? (_obstack_newchunk (__o, __len), 0) : 0); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ __o->next_free += __len; \ (void) 0; }) @@ -373,15 +466,16 @@ __extension__ \ #define obstack_finish(OBSTACK) \ __extension__ \ ({ struct obstack *__o1 = (OBSTACK); \ - void *value = (void *) __o1->object_base; \ + void *value; \ + value = (void *) __o1->object_base; \ if (__o1->next_free == value) \ __o1->maybe_empty_object = 1; \ __o1->next_free \ = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ & ~ (__o1->alignment_mask)); \ - ((__o1->next_free - (char *)__o1->chunk \ - > __o1->chunk_limit - (char *)__o1->chunk) \ - ? (__o1->next_free = __o1->chunk_limit) : 0); \ + if (__o1->next_free - (char *)__o1->chunk \ + > __o1->chunk_limit - (char *)__o1->chunk) \ + __o1->next_free = __o1->chunk_limit; \ __o1->object_base = __o1->next_free; \ value; }) @@ -401,44 +495,55 @@ __extension__ \ #define obstack_room(h) \ (unsigned) ((h)->chunk_limit - (h)->next_free) +/* Note that the call to _obstack_newchunk is enclosed in (..., 0) + so that we can avoid having void expressions + in the arms of the conditional expression. + Casting the third operand to void was tried before, + but some compilers won't accept it. */ + +#define obstack_make_room(h,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0)) + #define obstack_grow(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ - bcopy (where, (h)->next_free, (h)->temp), \ + _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \ (h)->next_free += (h)->temp) #define obstack_grow0(h,where,length) \ ( (h)->temp = (length), \ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ - bcopy (where, (h)->next_free, (h)->temp), \ + _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \ (h)->next_free += (h)->temp, \ *((h)->next_free)++ = 0) #define obstack_1grow(h,datum) \ ( (((h)->next_free + 1 > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), 1), 0) : 0), \ - *((h)->next_free)++ = (datum)) + (*((h)->next_free)++ = (datum))) #define obstack_ptr_grow(h,datum) \ ( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ - *((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum)) + (*((char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *) datum))) #define obstack_int_grow(h,datum) \ ( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ - *((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum)) + (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = ((int) datum))) -#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr) -#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint) +#define obstack_ptr_grow_fast(h,aptr) (*((char **) (h)->next_free)++ = (char *) aptr) +#define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint) #define obstack_blank(h,length) \ ( (h)->temp = (length), \ (((h)->chunk_limit - (h)->next_free < (h)->temp) \ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ - (h)->next_free += (h)->temp) + ((h)->next_free += (h)->temp)) #define obstack_alloc(h,length) \ (obstack_blank ((h), (length)), obstack_finish ((h))) @@ -457,22 +562,22 @@ __extension__ \ (h)->next_free \ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ & ~ ((h)->alignment_mask)), \ - (((h)->next_free - (char *)(h)->chunk \ - > (h)->chunk_limit - (char *)(h)->chunk) \ + (((h)->next_free - (char *) (h)->chunk \ + > (h)->chunk_limit - (char *) (h)->chunk) \ ? ((h)->next_free = (h)->chunk_limit) : 0), \ (h)->object_base = (h)->next_free, \ __INT_TO_PTR ((h)->temp)) -#ifdef __STDC__ +#if defined (__STDC__) && __STDC__ #define obstack_free(h,obj) \ -( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ +( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ? (int) ((h)->next_free = (h)->object_base \ = (h)->temp + (char *) (h)->chunk) \ : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) #else #define obstack_free(h,obj) \ -( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \ +( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ ? (int) ((h)->next_free = (h)->object_base \ = (h)->temp + (char *) (h)->chunk) \ @@ -481,4 +586,8 @@ __extension__ \ #endif /* not __GNUC__ or not __STDC__ */ -#endif /* not __OBSTACKS__ */ +#ifdef __cplusplus +} /* C++ */ +#endif + +#endif /* obstack.h */ diff --git a/gnu/usr.bin/grep/search.c b/gnu/usr.bin/grep/search.c index f0e3d5cfc35a..a3ca56c399ed 100644 --- a/gnu/usr.bin/grep/search.c +++ b/gnu/usr.bin/grep/search.c @@ -1,5 +1,5 @@ /* search.c - searching subroutines using dfa, kwset and regex for grep. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1998 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,80 +13,44 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ - Written August 1992 by Mike Haertel. */ +/* Written August 1992 by Mike Haertel. */ -#include <ctype.h> +/* $FreeBSD$ */ -#ifdef STDC_HEADERS -#include <limits.h> -#include <stdlib.h> -#else -#define UCHAR_MAX 255 -#include <sys/types.h> -extern char *malloc(); -#endif - -#ifdef HAVE_MEMCHR -#include <string.h> -#ifdef NEED_MEMORY_H -#include <memory.h> -#endif -#else -#ifdef __STDC__ -extern void *memchr(); -#else -extern char *memchr(); +#ifdef HAVE_CONFIG_H +# include <config.h> #endif -#endif - -#if defined(HAVE_STRING_H) || defined(STDC_HEADERS) -#undef bcopy -#define bcopy(s, d, n) memcpy((d), (s), (n)) -#endif - -#if defined(isascii) && !defined(__FreeBSD__) -#define ISALNUM(C) (isascii(C) && isalnum(C)) -#define ISUPPER(C) (isascii(C) && isupper(C)) +#include <sys/types.h> +#include "system.h" +#include "grep.h" +#ifdef __FreeBSD__ +#include <gnuregex.h> #else -#define ISALNUM(C) isalnum((unsigned char)C) -#define ISUPPER(C) isupper((unsigned char)C) +#include "regex.h" #endif - -#define TOLOWER(C) (ISUPPER(C) ? tolower((unsigned char)C) : (C)) - -#include "grep.h" #include "dfa.h" #include "kwset.h" -#include "gnuregex.h" #define NCHAR (UCHAR_MAX + 1) -#if __STDC__ -static void Gcompile(char *, size_t); -static void Ecompile(char *, size_t); -static char *EGexecute(char *, size_t, char **); -static void Fcompile(char *, size_t); -static char *Fexecute(char *, size_t, char **); -#else -static void Gcompile(); -static void Ecompile(); -static char *EGexecute(); -static void Fcompile(); -static char *Fexecute(); -#endif +static void Gcompile PARAMS((char *, size_t)); +static void Ecompile PARAMS((char *, size_t)); +static char *EGexecute PARAMS((char *, size_t, char **)); +static void Fcompile PARAMS((char *, size_t)); +static char *Fexecute PARAMS((char *, size_t, char **)); +static void kwsinit PARAMS((void)); /* Here is the matchers vector for the main program. */ struct matcher matchers[] = { { "default", Gcompile, EGexecute }, { "grep", Gcompile, EGexecute }, - { "ggrep", Gcompile, EGexecute }, { "egrep", Ecompile, EGexecute }, { "posix-egrep", Ecompile, EGexecute }, - { "gegrep", Ecompile, EGexecute }, + { "awk", Ecompile, EGexecute }, { "fgrep", Fcompile, Fexecute }, - { "gfgrep", Fcompile, Fexecute }, { 0, 0, 0 }, }; @@ -111,7 +75,7 @@ static int lastexact; void dfaerror(mesg) - char *mesg; + const char *mesg; { fatal(mesg, 0); } @@ -173,10 +137,7 @@ Gcompile(pattern, size) char *pattern; size_t size; { -#ifdef __STDC__ - const -#endif - char *err; + const char *err; re_set_syntax(RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE); dfasyntax(RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE, match_icase); @@ -184,8 +145,6 @@ Gcompile(pattern, size) if ((err = re_compile_pattern(pattern, size, ®ex)) != 0) fatal(err, 0); - dfainit(&dfa); - /* In the match_words and match_lines cases, we use a different pattern for the DFA matcher that will quickly throw out cases that won't work. Then if DFA succeeds we do some hairy stuff using the regex matcher @@ -209,7 +168,7 @@ Gcompile(pattern, size) strcpy(n, "\\(^\\|[^0-9A-Za-z_]\\)\\("); i = strlen(n); - bcopy(pattern, n + i, size); + memcpy(n + i, pattern, size); i += size; if (match_words) @@ -231,16 +190,18 @@ Ecompile(pattern, size) char *pattern; size_t size; { -#ifdef __STDC__ - const -#endif - char *err; + const char *err; if (strcmp(matcher, "posix-egrep") == 0) { re_set_syntax(RE_SYNTAX_POSIX_EGREP); dfasyntax(RE_SYNTAX_POSIX_EGREP, match_icase); } + else if (strcmp(matcher, "awk") == 0) + { + re_set_syntax(RE_SYNTAX_AWK); + dfasyntax(RE_SYNTAX_AWK, match_icase); + } else { re_set_syntax(RE_SYNTAX_EGREP); @@ -250,8 +211,6 @@ Ecompile(pattern, size) if ((err = re_compile_pattern(pattern, size, ®ex)) != 0) fatal(err, 0); - dfainit(&dfa); - /* In the match_words and match_lines cases, we use a different pattern for the DFA matcher that will quickly throw out cases that won't work. Then if DFA succeeds we do some hairy stuff using the regex matcher @@ -275,7 +234,7 @@ Ecompile(pattern, size) strcpy(n, "(^|[^0-9A-Za-z_])("); i = strlen(n); - bcopy(pattern, n + i, size); + memcpy(n + i, pattern, size); i += size; if (match_words) @@ -358,7 +317,8 @@ EGexecute(buf, size, endp) if ((start = re_search(®ex, beg, end - beg, 0, end - beg, ®s)) >= 0) { len = regs.end[0] - start; - if (!match_lines && !match_words || match_lines && len == end - beg) + if ((!match_lines && !match_words) + || (match_lines && len == end - beg)) goto success; /* If -w, check if the match aligns with word boundaries. We do this iteratively because: @@ -369,8 +329,9 @@ EGexecute(buf, size, endp) if (match_words) while (start >= 0) { - if ((start == 0 || !WCHAR(beg[start - 1])) - && (len == end - beg || !WCHAR(beg[start + len]))) + if ((start == 0 || !WCHAR ((unsigned char) beg[start - 1])) + && (len == end - beg + || !WCHAR ((unsigned char) beg[start + len]))) goto success; if (len > 0) { diff --git a/gnu/usr.bin/grep/tests/check.sh b/gnu/usr.bin/grep/tests/check.sh deleted file mode 100644 index d2c8fdbc64dc..000000000000 --- a/gnu/usr.bin/grep/tests/check.sh +++ /dev/null @@ -1,24 +0,0 @@ -#! /bin/sh -# Regression test for GNU grep. -# Usage: regress.sh [testdir] - -testdir=${1-tests} - -failures=0 - -# The Khadafy test is brought to you by Scott Anderson . . . -./grep -E -f $testdir/khadafy.regexp $testdir/khadafy.lines > khadafy.out -if cmp $testdir/khadafy.lines khadafy.out -then - : -else - echo Khadafy test failed -- output left on khadafy.out - failures=1 -fi - -# . . . and the following by Henry Spencer. - -${AWK-awk} -F: -f $testdir/scriptgen.awk $testdir/spencer.tests > tmp.script - -sh tmp.script && exit $failures -exit 1 diff --git a/gnu/usr.bin/grep/tests/scriptgen.awk b/gnu/usr.bin/grep/tests/scriptgen.awk deleted file mode 100644 index 44ef4df16e53..000000000000 --- a/gnu/usr.bin/grep/tests/scriptgen.awk +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN { print "failures=0"; } -$0 !~ /^#/ && NF == 3 { - print "echo '" $3 "' | ./grep -E -e '" $2 "' > /dev/null 2>&1"; - print "if [ $? != " $1 " ]" - print "then" - printf "\techo Spencer test \\#%d failed\n", ++n - print "\tfailures=1" - print "fi" -} -END { print "exit $failures"; } diff --git a/gnu/usr.bin/grep/tests/spencer.tests b/gnu/usr.bin/grep/tests/spencer.tests deleted file mode 100644 index cb506d79af0b..000000000000 --- a/gnu/usr.bin/grep/tests/spencer.tests +++ /dev/null @@ -1,122 +0,0 @@ -0:abc:abc -1:abc:xbc -1:abc:axc -1:abc:abx -0:abc:xabcy -0:abc:ababc -0:ab*c:abc -0:ab*bc:abc -0:ab*bc:abbc -0:ab*bc:abbbbc -0:ab+bc:abbc -1:ab+bc:abc -1:ab+bc:abq -0:ab+bc:abbbbc -0:ab?bc:abbc -0:ab?bc:abc -1:ab?bc:abbbbc -0:ab?c:abc -0:^abc$:abc -1:^abc$:abcc -0:^abc:abcc -1:^abc$:aabc -0:abc$:aabc -0:^:abc -0:$:abc -0:a.c:abc -0:a.c:axc -0:a.*c:axyzc -1:a.*c:axyzd -1:a[bc]d:abc -0:a[bc]d:abd -1:a[b-d]e:abd -0:a[b-d]e:ace -0:a[b-d]:aac -0:a[-b]:a- -0:a[b-]:a- -2:a[b-a]:- -2:a[]b:- -2:a[:- -0:a]:a] -0:a[]]b:a]b -0:a[^bc]d:aed -1:a[^bc]d:abd -0:a[^-b]c:adc -1:a[^-b]c:a-c -1:a[^]b]c:a]c -0:a[^]b]c:adc -0:ab|cd:abc -0:ab|cd:abcd -0:()ef:def -0:()*:- -1:*a:- -0:^*:- -0:$*:- -1:(*)b:- -1:$b:b -2:a\:- -0:a\(b:a(b -0:a\(*b:ab -0:a\(*b:a((b -1:a\x:a\x -2:abc):- -2:(abc:- -0:((a)):abc -0:(a)b(c):abc -0:a+b+c:aabbabc -0:a**:- -0:a*?:- -0:(a*)*:- -0:(a*)+:- -0:(a|)*:- -0:(a*|b)*:- -0:(a+|b)*:ab -0:(a+|b)+:ab -0:(a+|b)?:ab -0:[^ab]*:cde -0:(^)*:- -0:(ab|)*:- -2:)(:- -1:abc: -1:abc: -0:a*: -0:([abc])*d:abbbcd -0:([abc])*bcd:abcd -0:a|b|c|d|e:e -0:(a|b|c|d|e)f:ef -0:((a*|b))*:- -0:abcd*efg:abcdefg -0:ab*:xabyabbbz -0:ab*:xayabbbz -0:(ab|cd)e:abcde -0:[abhgefdc]ij:hij -1:^(ab|cd)e:abcde -0:(abc|)ef:abcdef -0:(a|b)c*d:abcd -0:(ab|ab*)bc:abc -0:a([bc]*)c*:abc -0:a([bc]*)(c*d):abcd -0:a([bc]+)(c*d):abcd -0:a([bc]*)(c+d):abcd -0:a[bcd]*dcdcde:adcdcde -1:a[bcd]+dcdcde:adcdcde -0:(ab|a)b*c:abc -0:((a)(b)c)(d):abcd -0:[A-Za-z_][A-Za-z0-9_]*:alpha -0:^a(bc+|b[eh])g|.h$:abh -0:(bc+d$|ef*g.|h?i(j|k)):effgz -0:(bc+d$|ef*g.|h?i(j|k)):ij -1:(bc+d$|ef*g.|h?i(j|k)):effg -1:(bc+d$|ef*g.|h?i(j|k)):bcdd -0:(bc+d$|ef*g.|h?i(j|k)):reffgz -1:((((((((((a)))))))))):- -0:(((((((((a))))))))):a -1:multiple words of text:uh-uh -0:multiple words:multiple words, yeah -0:(.*)c(.*):abcde -1:\((.*),:(.*)\) -1:[k]:ab -0:abcd:abcd -0:a(bc)d:abcd -0:a[-]?c:ac -0:(....).*\1:beriberi |
