245 |
static struct exclude *included_patterns; |
static struct exclude *included_patterns; |
246 |
/* Short options. */ |
/* Short options. */ |
247 |
static char const short_options[] = |
static char const short_options[] = |
248 |
"0123456789A:B:C:D:EFGHIPTUVX:abcd:e:f:hiKLlm:noqRrsuvwxyZz"; |
"0123456789A:B:C:D:HITUVabcd:e:f:hiKLlm:noqRrsuvwxyZz" |
249 |
|
#ifdef GREP_PROGRAM |
250 |
|
"EFGPX:" |
251 |
|
#endif |
252 |
|
; |
253 |
|
|
254 |
/* Non-boolean long options that have no corresponding short equivalents. */ |
/* Non-boolean long options that have no corresponding short equivalents. */ |
255 |
enum |
enum |
266 |
/* Long options equivalences. */ |
/* Long options equivalences. */ |
267 |
static struct option const long_options[] = |
static struct option const long_options[] = |
268 |
{ |
{ |
269 |
|
#ifdef GREP_PROGRAM |
270 |
|
{"basic-regexp", no_argument, NULL, 'G'}, |
271 |
|
{"extended-regexp", no_argument, NULL, 'E'}, |
272 |
|
{"fixed-regexp", no_argument, NULL, 'F'}, |
273 |
|
{"fixed-strings", no_argument, NULL, 'F'}, |
274 |
|
{"perl-regexp", no_argument, NULL, 'P'}, |
275 |
|
#endif |
276 |
{"after-context", required_argument, NULL, 'A'}, |
{"after-context", required_argument, NULL, 'A'}, |
|
{"basic-regexp", no_argument, NULL, 'G'}, |
|
277 |
{"before-context", required_argument, NULL, 'B'}, |
{"before-context", required_argument, NULL, 'B'}, |
278 |
{"binary-files", required_argument, NULL, BINARY_FILES_OPTION}, |
{"binary-files", required_argument, NULL, BINARY_FILES_OPTION}, |
279 |
{"byte-offset", no_argument, NULL, 'b'}, |
{"byte-offset", no_argument, NULL, 'b'}, |
283 |
{"count", no_argument, NULL, 'c'}, |
{"count", no_argument, NULL, 'c'}, |
284 |
{"devices", required_argument, NULL, 'D'}, |
{"devices", required_argument, NULL, 'D'}, |
285 |
{"directories", required_argument, NULL, 'd'}, |
{"directories", required_argument, NULL, 'd'}, |
|
{"extended-regexp", no_argument, NULL, 'E'}, |
|
286 |
{"exclude", required_argument, NULL, EXCLUDE_OPTION}, |
{"exclude", required_argument, NULL, EXCLUDE_OPTION}, |
287 |
{"exclude-from", required_argument, NULL, EXCLUDE_FROM_OPTION}, |
{"exclude-from", required_argument, NULL, EXCLUDE_FROM_OPTION}, |
288 |
{"file", required_argument, NULL, 'f'}, |
{"file", required_argument, NULL, 'f'}, |
289 |
{"files-with-matches", no_argument, NULL, 'l'}, |
{"files-with-matches", no_argument, NULL, 'l'}, |
290 |
{"files-without-match", no_argument, NULL, 'L'}, |
{"files-without-match", no_argument, NULL, 'L'}, |
|
{"fixed-regexp", no_argument, NULL, 'F'}, |
|
|
{"fixed-strings", no_argument, NULL, 'F'}, |
|
291 |
{"help", no_argument, &show_help, 1}, |
{"help", no_argument, &show_help, 1}, |
292 |
{"include", required_argument, NULL, INCLUDE_OPTION}, |
{"include", required_argument, NULL, INCLUDE_OPTION}, |
293 |
{"ignore-case", no_argument, NULL, 'i'}, |
{"ignore-case", no_argument, NULL, 'i'}, |
303 |
{"null", no_argument, NULL, 'Z'}, |
{"null", no_argument, NULL, 'Z'}, |
304 |
{"null-data", no_argument, NULL, 'z'}, |
{"null-data", no_argument, NULL, 'z'}, |
305 |
{"only-matching", no_argument, NULL, 'o'}, |
{"only-matching", no_argument, NULL, 'o'}, |
|
{"perl-regexp", no_argument, NULL, 'P'}, |
|
306 |
{"quiet", no_argument, NULL, 'q'}, |
{"quiet", no_argument, NULL, 'q'}, |
307 |
{"recursive", no_argument, NULL, 'r'}, |
{"recursive", no_argument, NULL, 'r'}, |
308 |
{"recursive", no_argument, NULL, 'R'}, |
{"recursive", no_argument, NULL, 'R'}, |
351 |
#endif |
#endif |
352 |
|
|
353 |
/* Functions we'll use to search. */ |
/* Functions we'll use to search. */ |
354 |
static void (*compile) PARAMS ((char const *, size_t)); |
#ifdef GREP_PROGRAM |
355 |
static size_t (*execute) PARAMS ((char const *, size_t, size_t *, int)); |
static compile_fp_t compile; |
356 |
|
static execute_fp_t execute; |
357 |
|
#endif |
358 |
|
|
359 |
/* Like error, but suppress the diagnostic if requested. */ |
/* Like error, but suppress the diagnostic if requested. */ |
360 |
static void |
static void |
782 |
} |
} |
783 |
|
|
784 |
while ( lim > beg |
while ( lim > beg |
785 |
&& ( (match_offset = (*execute) (ibeg, lim - beg, &match_size, 1)) |
&& ( (match_offset = execute(ibeg, lim - beg, &match_size, 1)) |
786 |
!= (size_t) -1)) |
!= (size_t) -1)) |
787 |
{ |
{ |
788 |
char const *b = beg + match_offset; |
char const *b = beg + match_offset; |
904 |
size_t match_size; |
size_t match_size; |
905 |
--pending; |
--pending; |
906 |
if (outleft |
if (outleft |
907 |
|| (((*execute) (lastout, nl + 1 - lastout, &match_size, 0) == (size_t) -1) |
|| ((execute(lastout, nl + 1 - lastout, &match_size, 0) == (size_t) -1) |
908 |
== !out_invert)) |
== !out_invert)) |
909 |
prline (lastout, nl + 1, SEP_CHAR_CONTEXT); |
prline (lastout, nl + 1, SEP_CHAR_CONTEXT); |
910 |
else |
else |
994 |
|
|
995 |
nlines = 0; |
nlines = 0; |
996 |
p = beg; |
p = beg; |
997 |
while ((match_offset = (*execute) (p, lim - p, &match_size, 0)) != (size_t) -1) |
while ((match_offset = execute(p, lim - p, &match_size, 0)) != (size_t) -1) |
998 |
{ |
{ |
999 |
char const *b = p + match_offset; |
char const *b = p + match_offset; |
1000 |
char const *endp = b + match_size; |
char const *endp = b + match_size; |
1362 |
{ |
{ |
1363 |
printf (_("Usage: %s [OPTION]... PATTERN [FILE]...\n"), program_name); |
printf (_("Usage: %s [OPTION]... PATTERN [FILE]...\n"), program_name); |
1364 |
printf (_("\ |
printf (_("\ |
1365 |
Search for PATTERN in each FILE or standard input.\n\ |
Search for PATTERN in each FILE or standard input.\n")); |
1366 |
|
#if defined(EGREP_PROGRAM) |
1367 |
|
printf (_("\ |
1368 |
|
PATTERN is an extended regular expression (ERE).\n")); |
1369 |
|
#elif defined(FGREP_PROGRAM) |
1370 |
|
printf (_("\ |
1371 |
|
PATTERN is a set of newline-separated fixed strings.\n")); |
1372 |
|
#else |
1373 |
|
printf (_("\ |
1374 |
|
PATTERN is, by default, a basic regular expression (BRE).\n")); |
1375 |
|
#endif /* ?GREP_PROGRAM */ |
1376 |
|
printf (_("\ |
1377 |
Example: %s -i 'hello world' menu.h main.c\n\ |
Example: %s -i 'hello world' menu.h main.c\n\ |
1378 |
\n\ |
\n\ |
1379 |
Regexp selection and interpretation:\n"), program_name); |
Regexp selection and interpretation:\n"), program_name); |
1380 |
|
#ifdef GREP_PROGRAM |
1381 |
printf (_("\ |
printf (_("\ |
1382 |
-E, --extended-regexp PATTERN is an extended regular expression\n\ |
-E, --extended-regexp PATTERN is an extended regular expression (ERE)\n\ |
1383 |
-F, --fixed-strings PATTERN is a set of newline-separated strings\n\ |
-F, --fixed-strings PATTERN is a set of newline-separated fixed strings\n\ |
1384 |
-G, --basic-regexp PATTERN is a basic regular expression\n\ |
-G, --basic-regexp PATTERN is a basic regular expression (BRE)\n\ |
1385 |
-P, --perl-regexp PATTERN is a Perl regular expression\n")); |
-P, --perl-regexp PATTERN is a Perl regular expression\n")); |
1386 |
/* -X is undocumented on purpose. */ |
/* -X is undocumented on purpose. */ |
1387 |
|
#endif /* GREP_PROGRAM */ |
1388 |
printf (_("\ |
printf (_("\ |
1389 |
-e, --regexp=PATTERN use PATTERN as a regular expression\n\ |
-e, --regexp=PATTERN use PATTERN for matching\n\ |
1390 |
-f, --file=FILE obtain PATTERN from FILE\n\ |
-f, --file=FILE obtain PATTERN from FILE\n\ |
1391 |
-i, --ignore-case ignore case distinctions\n\ |
-i, --ignore-case ignore case distinctions\n\ |
1392 |
-w, --word-regexp force PATTERN to match only whole words\n\ |
-w, --word-regexp force PATTERN to match only whole words\n\ |
1441 |
WHEN is `always', `never', or `auto'\n\ |
WHEN is `always', `never', or `auto'\n\ |
1442 |
-U, --binary do not strip CR characters at EOL (MSDOS)\n\ |
-U, --binary do not strip CR characters at EOL (MSDOS)\n\ |
1443 |
-u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS)\n\ |
-u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS)\n\ |
1444 |
\n\ |
\n")); |
1445 |
|
#if defined(EGREP_PROGRAM) |
1446 |
|
printf (_("\ |
1447 |
|
Invocation as `egrep' is deprecated; use `grep -E' instead.\n")); |
1448 |
|
#elif defined(FGREP_PROGRAM) |
1449 |
|
printf (_("\ |
1450 |
|
Invocation as `fgrep' is deprecated; use `grep -F' instead.\n")); |
1451 |
|
#else |
1452 |
|
printf (_("\ |
1453 |
`egrep' means `grep -E'. `fgrep' means `grep -F'.\n\ |
`egrep' means `grep -E'. `fgrep' means `grep -F'.\n\ |
1454 |
|
Direct invocation as either `egrep' or `fgrep' is deprecated.\n")); |
1455 |
|
#endif /* ?GREP_PROGRAM */ |
1456 |
|
printf (_("\ |
1457 |
With no FILE, or when FILE is -, read standard input. If less than two FILEs\n\ |
With no FILE, or when FILE is -, read standard input. If less than two FILEs\n\ |
1458 |
are given, assume -h. Exit status is 0 if any line was selected, 1 otherwise;\n\ |
are given, assume -h. Exit status is 0 if any line was selected, 1 otherwise;\n\ |
1459 |
if any error occurs and -q was not given, the exit status is 2.\n")); |
if any error occurs and -q was not given, the exit status is 2.\n")); |
1462 |
exit (status); |
exit (status); |
1463 |
} |
} |
1464 |
|
|
1465 |
|
#ifdef GREP_PROGRAM |
1466 |
|
static char const *matcher; |
1467 |
|
|
1468 |
/* Set the matcher to M, reporting any conflicts. */ |
/* Set the matcher to M, reporting any conflicts. */ |
1469 |
static void |
static void |
1470 |
setmatcher (char const *m) |
setmatcher (char const *m) |
1480 |
install_matcher (char const *name) |
install_matcher (char const *name) |
1481 |
{ |
{ |
1482 |
int i; |
int i; |
|
#if defined(HAVE_SETRLIMIT) |
|
|
struct rlimit rlim; |
|
|
#endif |
|
1483 |
|
|
1484 |
for (i = 0; matchers[i].compile; i++) |
for (i = 0; matchers[i].compile; i++) |
1485 |
if (strcmp (name, matchers[i].name) == 0) |
if (strcmp (name, matchers[i].name) == 0) |
1486 |
{ |
{ |
1487 |
compile = matchers[i].compile; |
compile = matchers[i].compile; |
1488 |
execute = matchers[i].execute; |
execute = matchers[i].execute; |
1489 |
|
return 1; |
1490 |
|
} |
1491 |
|
return 0; |
1492 |
|
} |
1493 |
|
#endif /* GREP_PROGRAM */ |
1494 |
|
|
1495 |
|
static void |
1496 |
|
set_limits(void) |
1497 |
|
{ |
1498 |
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK) |
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_STACK) |
1499 |
/* I think every platform needs to do this, so that regex.c |
struct rlimit rlim; |
|
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. |
|
1500 |
|
|
1501 |
The test for HAVE_SETRLIMIT should go into `configure'. */ |
/* I think every platform needs to do this, so that regex.c |
1502 |
if (!getrlimit (RLIMIT_STACK, &rlim)) |
doesn't oveflow the stack. The default value of |
1503 |
{ |
`re_max_failures' is too large for some platforms: it needs |
1504 |
long newlim; |
more than 3MB-large stack. |
|
extern long int re_max_failures; /* from regex.c */ |
|
1505 |
|
|
1506 |
/* Approximate the amount regex.c needs, plus some more. */ |
The test for HAVE_SETRLIMIT should go into `configure'. */ |
1507 |
newlim = re_max_failures * 2 * 20 * sizeof (char *); |
if (!getrlimit (RLIMIT_STACK, &rlim)) |
1508 |
if (newlim > rlim.rlim_max) |
{ |
1509 |
{ |
long newlim; |
1510 |
newlim = rlim.rlim_max; |
extern long int re_max_failures; /* from regex.c */ |
1511 |
re_max_failures = newlim / (2 * 20 * sizeof (char *)); |
|
1512 |
} |
/* Approximate the amount regex.c needs, plus some more. */ |
1513 |
if (rlim.rlim_cur < newlim) |
newlim = re_max_failures * 2 * 20 * sizeof (char *); |
1514 |
{ |
if (newlim > rlim.rlim_max) |
1515 |
rlim.rlim_cur = newlim; |
{ |
1516 |
setrlimit (RLIMIT_STACK, &rlim); |
newlim = rlim.rlim_max; |
1517 |
} |
re_max_failures = newlim / (2 * 20 * sizeof (char *)); |
1518 |
} |
} |
1519 |
|
if (rlim.rlim_cur < newlim) |
1520 |
|
{ |
1521 |
|
rlim.rlim_cur = newlim; |
1522 |
|
setrlimit (RLIMIT_STACK, &rlim); |
1523 |
|
} |
1524 |
|
} |
1525 |
#endif |
#endif |
|
return 1; |
|
|
} |
|
|
return 0; |
|
1526 |
} |
} |
1527 |
|
|
1528 |
/* Find the white-space-separated options specified by OPTIONS, and |
/* Find the white-space-separated options specified by OPTIONS, and |
1781 |
|
|
1782 |
initialize_main (&argc, &argv); |
initialize_main (&argc, &argv); |
1783 |
program_name = argv[0]; |
program_name = argv[0]; |
|
if (program_name && strrchr (program_name, '/')) |
|
|
program_name = strrchr (program_name, '/') + 1; |
|
|
|
|
|
if (!strcmp(program_name, "egrep")) |
|
|
setmatcher ("egrep"); |
|
|
if (!strcmp(program_name, "fgrep")) |
|
|
setmatcher ("fgrep"); |
|
|
|
|
|
#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 (program_name) |
|
|
{ |
|
|
char *p = program_name; |
|
|
char *bslash = strrchr (argv[0], '\\'); |
|
|
|
|
|
if (bslash && bslash >= program_name) /* for mixed forward/backslash case */ |
|
|
program_name = bslash + 1; |
|
|
else if (program_name == argv[0] |
|
|
&& argv[0][0] && argv[0][1] == ':') /* "c:progname" */ |
|
|
program_name = 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 (program_name, '.')) && strcmp (p, ".exe") == 0) |
|
|
*p = '\0'; |
|
|
} |
|
|
#endif |
|
1784 |
|
|
1785 |
keys = NULL; |
keys = NULL; |
1786 |
keycc = 0; |
keycc = 0; |
1836 |
error (2, 0, _("unknown devices method")); |
error (2, 0, _("unknown devices method")); |
1837 |
break; |
break; |
1838 |
|
|
1839 |
|
#ifdef GREP_PROGRAM |
1840 |
case 'E': |
case 'E': |
1841 |
setmatcher ("egrep"); |
setmatcher ("egrep"); |
1842 |
break; |
break; |
1853 |
setmatcher ("grep"); |
setmatcher ("grep"); |
1854 |
break; |
break; |
1855 |
|
|
1856 |
|
case 'X': /* undocumented on purpose */ |
1857 |
|
setmatcher (optarg); |
1858 |
|
break; |
1859 |
|
#endif /* GREP_PROGRAM */ |
1860 |
|
|
1861 |
case 'H': |
case 'H': |
1862 |
with_filenames = 1; |
with_filenames = 1; |
1863 |
break; |
break; |
1886 |
show_version = 1; |
show_version = 1; |
1887 |
break; |
break; |
1888 |
|
|
|
case 'X': /* undocumented on purpose */ |
|
|
setmatcher (optarg); |
|
|
break; |
|
|
|
|
1889 |
case 'a': |
case 'a': |
1890 |
binary_files = TEXT_BINARY_FILES; |
binary_files = TEXT_BINARY_FILES; |
1891 |
break; |
break; |
2130 |
parse_grep_colors(); |
parse_grep_colors(); |
2131 |
} |
} |
2132 |
|
|
|
if (! matcher) |
|
|
matcher = "grep"; |
|
|
|
|
2133 |
if (show_version) |
if (show_version) |
2134 |
{ |
{ |
2135 |
printf ("%s\n\n", PACKAGE_STRING); |
printf ("%s\n\n", PACKAGE_STRING); |
2136 |
printf (_("\ |
printf (_("\ |
2137 |
Copyright (C) 1988, 1992-1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.\n")); |
Copyright (C) 1988, 1992-2002, 2004, 2005 Free Software Foundation, Inc.\n")); |
2138 |
printf (_("\ |
printf (_("\ |
2139 |
This is free software; see the source for copying conditions. There is NO\n\ |
This is free software; see the source for copying conditions. There is NO\n\ |
2140 |
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")); |
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n")); |
2141 |
printf ("\n"); |
printf ("\n"); |
2142 |
exit (0); |
exit (0); |
2166 |
else |
else |
2167 |
usage (2); |
usage (2); |
2168 |
|
|
2169 |
|
#ifdef GREP_PROGRAM |
2170 |
|
if (! matcher) |
2171 |
|
matcher = "grep"; |
2172 |
|
|
2173 |
if (!install_matcher (matcher) && !install_matcher ("default")) |
if (!install_matcher (matcher) && !install_matcher ("default")) |
2174 |
abort (); |
abort (); |
2175 |
|
#endif /* GREP_PROGRAM */ |
2176 |
|
|
2177 |
|
set_limits(); |
2178 |
|
|
2179 |
#ifdef MBS_SUPPORT |
#ifdef MBS_SUPPORT |
2180 |
if (match_icase) |
if (match_icase) |
2181 |
mb_icase_keys (&keys, &keycc); |
mb_icase_keys (&keys, &keycc); |
2182 |
#endif /* MBS_SUPPORT */ |
#endif /* MBS_SUPPORT */ |
2183 |
|
|
2184 |
(*compile)(keys, keycc); |
compile(keys, keycc); |
2185 |
|
|
2186 |
if ((argc - optind > 1 && !no_filenames) || with_filenames) |
if ((argc - optind > 1 && !no_filenames) || with_filenames) |
2187 |
out_file = 1; |
out_file = 1; |