1 /* search.c - searching subroutines using dfa, kwset and regex for grep.
2 Copyright 1992, 1998, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 /* Written August 1992 by Mike Haertel. */
24 # define _GNU_SOURCE 1
30 #include <sys/types.h>
31 #if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H && defined HAVE_MBRTOWC
32 /* We can handle multibyte string. */
48 #ifdef HAVE_LANGINFO_CODESET
49 # include <langinfo.h>
52 #define NCHAR (UCHAR_MAX + 1)
54 /* For -w, we also consider _ to be word constituent. */
55 #define WCHAR(C) (ISALNUM(C) || (C) == '_')
57 /* DFA compiled regexp. */
58 static struct dfa dfa;
60 /* The Regex compiled patterns. */
61 static struct patterns
63 /* Regex compiled regexp. */
64 struct re_pattern_buffer regexbuf;
65 struct re_registers regs; /* This is here on account of a BRAIN-DEAD
66 Q@#%!# library interface in regex.c. */
69 struct patterns *patterns;
72 /* KWset compiled pattern. For Ecompile and Gcompile, we compile
73 a list of strings, at least one of which is known to occur in
74 any string matching the regexp. */
77 /* Number of compiled fixed strings known to exactly match the regexp.
78 If kwsexec returns < kwset_exact_matches, then we don't need to
79 call the regexp matcher at all. */
80 static int kwset_exact_matches;
82 /* UTF-8 encoding allows some optimizations that we can't otherwise
83 assume in a multibyte encoding. */
84 static int using_utf8;
86 static void kwsinit PARAMS ((void));
87 static void kwsmusts PARAMS ((void));
88 static void Gcompile PARAMS ((char const *, size_t));
89 static void Ecompile PARAMS ((char const *, size_t));
90 static size_t EGexecute PARAMS ((char const *, size_t, size_t *, int ));
91 static void Fcompile PARAMS ((char const *, size_t));
92 static size_t Fexecute PARAMS ((char const *, size_t, size_t *, int));
93 static void Pcompile PARAMS ((char const *, size_t ));
94 static size_t Pexecute PARAMS ((char const *, size_t, size_t *, int));
99 #ifdef HAVE_LANGINFO_CODESET
100 if (strcmp (nl_langinfo (CODESET), "UTF-8") == 0)
106 dfaerror (char const *mesg)
114 static char trans[NCHAR];
118 for (i = 0; i < NCHAR; ++i)
119 trans[i] = TOLOWER (i);
121 if (!(kwset = kwsalloc (match_icase ? trans : (char *) 0)))
122 error (2, 0, _("memory exhausted"));
125 /* If the DFA turns out to have some set of fixed strings one of
126 which must occur in the match, then we build a kwset matcher
127 to find those strings, and thus quickly filter out impossible
132 struct dfamust const *dm;
138 /* First, we compile in the substrings known to be exact
139 matches. The kwset matcher will return the index
140 of the matching string that it chooses. */
141 for (dm = dfa.musts; dm; dm = dm->next)
145 ++kwset_exact_matches;
146 if ((err = kwsincr (kwset, dm->must, strlen (dm->must))) != 0)
149 /* Now, we compile the substrings that will require
150 the use of the regexp matcher. */
151 for (dm = dfa.musts; dm; dm = dm->next)
155 if ((err = kwsincr (kwset, dm->must, strlen (dm->must))) != 0)
158 if ((err = kwsprep (kwset)) != 0)
164 Gcompile (char const *pattern, size_t size)
169 char const *motif = pattern;
172 re_set_syntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE | (match_icase ? RE_ICASE : 0));
173 dfasyntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE, match_icase, eolbyte);
175 /* For GNU regex compiler we have to pass the patterns separately to detect
176 errors like "[\nallo\n]\n". The patterns here are "[", "allo" and "]"
177 GNU regex should have raise a syntax error. The same for backref, where
178 the backref should have been local to each pattern. */
182 sep = memchr (motif, '\n', total);
195 patterns = realloc (patterns, (pcount + 1) * sizeof (*patterns));
196 if (patterns == NULL)
197 error (2, errno, _("memory exhausted"));
199 patterns[pcount] = patterns0;
201 if ((err = re_compile_pattern (motif, len,
202 &(patterns[pcount].regexbuf))) != 0)
207 } while (sep && total != 0);
209 /* In the match_words and match_lines cases, we use a different pattern
210 for the DFA matcher that will quickly throw out cases that won't work.
211 Then if DFA succeeds we do some hairy stuff using the regex matcher
212 to decide whether the match should really count. */
213 if (match_words || match_lines)
215 /* In the whole-word case, we use the pattern:
216 \(^\|[^[:alnum:]_]\)\(userpattern\)\([^[:alnum:]_]|$\).
217 In the whole-line case, we use the pattern:
218 ^\(userpattern\)$. */
220 static char const line_beg[] = "^\\(";
221 static char const line_end[] = "\\)$";
222 static char const word_beg[] = "\\(^\\|[^[:alnum:]_]\\)\\(";
223 static char const word_end[] = "\\)\\([^[:alnum:]_]\\|$\\)";
224 char *n = xmalloc (sizeof word_beg - 1 + size + sizeof word_end);
226 strcpy (n, match_lines ? line_beg : word_beg);
228 memcpy (n + i, pattern, size);
230 strcpy (n + i, match_lines ? line_end : word_end);
236 dfacomp (pattern, size, &dfa, 1);
241 Ecompile (char const *pattern, size_t size)
246 char const *motif = pattern;
249 if (strcmp (matcher, "awk") == 0)
251 re_set_syntax (RE_SYNTAX_AWK | (match_icase ? RE_ICASE : 0));
252 dfasyntax (RE_SYNTAX_AWK, match_icase, eolbyte);
256 re_set_syntax (RE_SYNTAX_POSIX_EGREP | (match_icase ? RE_ICASE : 0));
257 dfasyntax (RE_SYNTAX_POSIX_EGREP, match_icase, eolbyte);
260 /* For GNU regex compiler we have to pass the patterns separately to detect
261 errors like "[\nallo\n]\n". The patterns here are "[", "allo" and "]"
262 GNU regex should have raise a syntax error. The same for backref, where
263 the backref should have been local to each pattern. */
267 sep = memchr (motif, '\n', total);
280 patterns = realloc (patterns, (pcount + 1) * sizeof (*patterns));
281 if (patterns == NULL)
282 error (2, errno, _("memory exhausted"));
283 patterns[pcount] = patterns0;
285 if ((err = re_compile_pattern (motif, len,
286 &(patterns[pcount].regexbuf))) != 0)
291 } while (sep && total != 0);
293 /* In the match_words and match_lines cases, we use a different pattern
294 for the DFA matcher that will quickly throw out cases that won't work.
295 Then if DFA succeeds we do some hairy stuff using the regex matcher
296 to decide whether the match should really count. */
297 if (match_words || match_lines)
299 /* In the whole-word case, we use the pattern:
300 (^|[^[:alnum:]_])(userpattern)([^[:alnum:]_]|$).
301 In the whole-line case, we use the pattern:
304 static char const line_beg[] = "^(";
305 static char const line_end[] = ")$";
306 static char const word_beg[] = "(^|[^[:alnum:]_])(";
307 static char const word_end[] = ")([^[:alnum:]_]|$)";
308 char *n = xmalloc (sizeof word_beg - 1 + size + sizeof word_end);
310 strcpy (n, match_lines ? line_beg : word_beg);
312 memcpy (n + i, pattern, size);
314 strcpy (n + i, match_lines ? line_end : word_end);
320 dfacomp (pattern, size, &dfa, 1);
325 EGexecute (char const *buf, size_t size, size_t *match_size, int exact)
327 register char const *buflim, *beg, *end;
330 ptrdiff_t start, len;
331 struct kwsmatch kwsm;
334 static int use_dfa_checked = 0;
336 const char *last_char = NULL;
337 int mb_cur_max = MB_CUR_MAX;
339 memset (&mbs, '\0', sizeof (mbstate_t));
340 #endif /* MBS_SUPPORT */
342 if (!use_dfa_checked)
344 char *grep_use_dfa = getenv ("GREP_USE_DFA");
348 /* Turn off DFA when processing multibyte input. */
349 use_dfa = (MB_CUR_MAX == 1);
352 #endif /* MBS_SUPPORT */
356 use_dfa = atoi (grep_use_dfa);
364 for (beg = end = buf; end < buflim; beg = end)
370 /* Find a possible match using the KWset matcher. */
372 size_t bytes_left = 0;
373 #endif /* MBS_SUPPORT */
376 /* kwsexec doesn't work with match_icase and multibyte input. */
377 if (match_icase && mb_cur_max > 1)
381 #endif /* MBS_SUPPORT */
382 offset = kwsexec (kwset, beg, buflim - beg, &kwsm);
383 if (offset == (size_t) -1)
386 if (mb_cur_max > 1 && !using_utf8)
391 size_t mlen = mbrlen (beg, bytes_left, &mbs);
394 if (mlen == (size_t) -1 || mlen == 0)
396 /* Incomplete character: treat as single-byte. */
397 memset (&mbs, '\0', sizeof (mbstate_t));
403 if (mlen == (size_t) -2)
405 /* Offset points inside multibyte character:
407 memset (&mbs, '\0', sizeof (mbstate_t));
416 #endif /* MBS_SUPPORT */
418 /* Narrow down to the line containing the candidate, and
419 run it through DFA. */
420 end = memchr(beg, eol, buflim - beg);
423 if (mb_cur_max > 1 && bytes_left)
425 #endif /* MBS_SUPPORT */
426 while (beg > buf && beg[-1] != eol)
430 !(match_icase && mb_cur_max > 1) &&
431 #endif /* MBS_SUPPORT */
432 (kwsm.index < kwset_exact_matches))
433 goto success_in_beg_and_end;
435 dfaexec (&dfa, beg, end - beg, &backref) == (size_t) -1)
440 /* No good fixed strings; start with DFA. */
442 size_t bytes_left = 0;
443 #endif /* MBS_SUPPORT */
446 offset = dfaexec (&dfa, beg, buflim - beg, &backref);
447 if (offset == (size_t) -1)
449 /* Narrow down to the line we've found. */
451 if (mb_cur_max > 1 && !using_utf8)
456 size_t mlen = mbrlen (beg, bytes_left, &mbs);
459 if (mlen == (size_t) -1 || mlen == 0)
461 /* Incomplete character: treat as single-byte. */
462 memset (&mbs, '\0', sizeof (mbstate_t));
468 if (mlen == (size_t) -2)
470 /* Offset points inside multibyte character:
472 memset (&mbs, '\0', sizeof (mbstate_t));
481 #endif /* MBS_SUPPORT */
483 end = memchr (beg, eol, buflim - beg);
486 if (mb_cur_max > 1 && bytes_left)
488 #endif /* MBS_SUPPORT */
489 while (beg > buf && beg[-1] != eol)
492 /* Successful, no backreferences encountered! */
493 if (use_dfa && !backref)
494 goto success_in_beg_and_end;
499 /* If we've made it to this point, this means DFA has seen
500 a probable match, and we need to run it through Regex. */
501 for (i = 0; i < pcount; i++)
503 patterns[i].regexbuf.not_eol = 0;
504 if (0 <= (start = re_search (&(patterns[i].regexbuf), beg,
506 end - beg - 1, &(patterns[i].regs))))
508 len = patterns[i].regs.end[0] - start;
509 if (exact && !match_words)
510 goto success_in_start_and_len;
511 if ((!match_lines && !match_words)
512 || (match_lines && len == end - beg - 1))
513 goto success_in_beg_and_end;
514 /* If -w, check if the match aligns with word boundaries.
515 We do this iteratively because:
516 (a) the line may contain more than one occurence of the
518 (b) Several alternatives in the pattern might be valid at a
519 given point, and we may need to consider a shorter one to
520 find a word boundary. */
537 /* Locate the start of the multibyte character
538 before the match position (== beg + start). */
541 /* UTF-8 is a special case: scan backwards
542 until we find a 7-bit character or a
546 && (unsigned char) *s >= 0x80
547 && (unsigned char) *s <= 0xbf)
552 /* Scan forwards to find the start of the
553 last complete character before the
555 size_t bytes_left = start - 1;
557 while (bytes_left > 0)
559 mr = mbrlen (s, bytes_left, &mbs);
560 if (mr == (size_t) -1 || mr == 0)
562 memset (&mbs, '\0', sizeof (mbs));
567 if (mr == (size_t) -2)
569 memset (&mbs, '\0', sizeof (mbs));
576 mr = mbrtowc (&pwc, s, beg + start - s, &mbs);
577 if (mr == (size_t) -2 || mr == (size_t) -1 ||
580 memset (&mbs, '\0', sizeof (mbstate_t));
583 else if (!(iswalnum (pwc) || pwc == L'_')
584 && mr == beg + start - s)
588 #endif /* MBS_SUPPORT */
589 if (!WCHAR ((unsigned char) beg[start - 1]))
596 if (start + len == end - beg - 1)
606 mr = mbtowc (&nwc, beg + start + len,
607 end - beg - start - len - 1);
610 memset (&mbs, '\0', sizeof (mbstate_t));
613 else if (!iswalnum (nwc) && nwc != L'_')
617 #endif /* MBS_SUPPORT */
618 if (!WCHAR ((unsigned char) beg[start + len]))
625 /* Returns the whole line. */
626 goto success_in_beg_and_end;
628 /* Returns just this word match. */
629 goto success_in_start_and_len;
634 /* Try a shorter length anchored at the same place. */
636 patterns[i].regexbuf.not_eol = 1;
637 len = re_match (&(patterns[i].regexbuf), beg,
639 &(patterns[i].regs));
643 /* Try looking further on. */
644 if (start == end - beg - 1)
647 patterns[i].regexbuf.not_eol = 0;
648 start = re_search (&(patterns[i].regexbuf), beg,
650 start, end - beg - 1 - start,
651 &(patterns[i].regs));
652 len = patterns[i].regs.end[0] - start;
656 } /* for Regex patterns. */
657 } /* for (beg = end ..) */
662 success_in_beg_and_end:
667 success_in_start_and_len:
673 static int f_i_multibyte; /* whether we're using the new -Fi MB method */
677 size_t count, maxlen;
678 unsigned char *match;
683 Fcompile (char const *pattern, size_t size)
685 int mb_cur_max = MB_CUR_MAX;
686 char const *beg, *lim, *err;
690 /* Support -F -i for UTF-8 input. */
691 if (match_icase && mb_cur_max > 1)
694 wchar_t *wcpattern = xmalloc ((size + 1) * sizeof (wchar_t));
695 const char *patternend = pattern;
697 kwset_t fimb_kwset = NULL;
699 wchar_t *wcbeg, *wclim;
700 size_t allocated = 0;
702 memset (&mbs, '\0', sizeof (mbs));
703 # ifdef __GNU_LIBRARY__
704 wcsize = mbsnrtowcs (wcpattern, &patternend, size, size, &mbs);
705 if (patternend != pattern + size)
706 wcsize = (size_t) -1;
709 char *patterncopy = xmalloc (size + 1);
711 memcpy (patterncopy, pattern, size);
712 patterncopy[size] = '\0';
713 patternend = patterncopy;
714 wcsize = mbsrtowcs (wcpattern, &patternend, size, &mbs);
715 if (patternend != patterncopy + size)
716 wcsize = (size_t) -1;
726 kwsfree (fimb_kwset);
727 free (Fimb.patterns);
728 Fimb.patterns = NULL;
732 if (!(fimb_kwset = kwsalloc (NULL)))
733 error (2, 0, _("memory exhausted"));
735 starts = xmalloc (mb_cur_max * 3);
742 if (Fimb.count >= allocated)
748 Fimb.patterns = xrealloc (Fimb.patterns,
749 sizeof (wchar_t *) * allocated);
751 Fimb.patterns[Fimb.count++] = wcbeg;
753 wclim < wcpattern + wcsize && *wclim != L'\n'; ++wclim)
754 *wclim = towlower (*wclim);
756 wclen = wclim - wcbeg;
757 if (wclen > Fimb.maxlen)
763 if ((err = kwsincr (fimb_kwset, "", 0)) != 0)
767 for (i = 0; i < (1 << wclen); i++)
772 for (j = 0; j < wclen; ++j)
774 wchar_t wc = wcbeg[j];
786 if ((err = kwsincr (fimb_kwset, starts, p - starts)) != 0)
789 if (wclim < wcpattern + wcsize)
793 while (wcbeg < wcpattern + wcsize);
797 Fimb.match = xmalloc (Fimb.count);
798 if ((err = kwsprep (kwset)) != 0)
803 #endif /* MBS_SUPPORT */
810 for (lim = beg; lim < pattern + size && *lim != '\n'; ++lim)
812 if ((err = kwsincr (kwset, beg, lim - beg)) != 0)
814 if (lim < pattern + size)
818 while (beg < pattern + size);
820 if ((err = kwsprep (kwset)) != 0)
826 Fimbexec (const char *buf, size_t size, size_t *plen, int exact)
828 size_t len, letter, i;
834 assert (match_icase && f_i_multibyte == 1);
835 assert (MB_CUR_MAX > 1);
837 memset (&mbs, '\0', sizeof (mbs));
838 memset (Fimb.match, '\1', Fimb.count);
841 while (patterns_left && len <= size)
848 c = mbrtowc (&wc, buf + len, size - len, &mbs);
860 for (i = 0; i < Fimb.count; i++)
864 if (Fimb.patterns[i][letter] == L'\0')
868 if (!exact && !match_words)
872 /* For -w or exact look for longest match. */
874 Fimb.match[i] = '\0';
879 if (Fimb.patterns[i][letter] == wc)
882 Fimb.match[i] = '\0';
892 #endif /* MBS_SUPPORT */
895 Fexecute (char const *buf, size_t size, size_t *match_size, int exact)
897 register char const *beg, *try, *end;
900 struct kwsmatch kwsmatch;
903 int mb_cur_max = MB_CUR_MAX;
905 memset (&mbs, '\0', sizeof (mbstate_t));
906 const char *last_char = NULL;
907 #endif /* MBS_SUPPORT */
909 for (beg = buf; beg <= buf + size; ++beg)
912 offset = kwsexec (kwset, beg, buf + size - beg, &kwsmatch);
914 if (offset == (size_t) -1)
917 if (mb_cur_max > 1 && !using_utf8)
919 size_t bytes_left = offset;
922 size_t mlen = mbrlen (beg, bytes_left, &mbs);
925 if (mlen == (size_t) -1 || mlen == 0)
927 /* Incomplete character: treat as single-byte. */
928 memset (&mbs, '\0', sizeof (mbstate_t));
934 if (mlen == (size_t) -2)
936 /* Offset points inside multibyte character: no good. */
937 memset (&mbs, '\0', sizeof (mbstate_t));
952 #endif /* MBS_SUPPORT */
955 /* For f_i_multibyte, the string at beg now matches first 3 chars of
956 one of the search strings (less if there are shorter search strings).
957 See if this is a real match. */
959 && Fimbexec (beg, buf + size - beg, &kwsmatch.size[0], exact))
961 #endif /* MBS_SUPPORT */
962 len = kwsmatch.size[0];
963 if (exact && !match_words)
964 goto success_in_beg_and_len;
967 if (beg > buf && beg[-1] != eol)
969 if (beg + len < buf + size && beg[len] != eol)
973 else if (match_words)
991 && (unsigned char) *s >= 0x80
992 && (unsigned char) *s <= 0xbf)
997 mr = mbtowc (&pwc, s, beg - s);
999 memset (&mbs, '\0', sizeof (mbstate_t));
1000 else if ((iswalnum (pwc) || pwc == L'_')
1001 && mr == (int) (beg - s))
1005 #endif /* MBS_SUPPORT */
1006 if (WCHAR ((unsigned char) beg[-1]))
1015 mr = mbtowc (&nwc, beg + len, buf + size - beg - len);
1018 memset (&mbs, '\0', sizeof (mbstate_t));
1021 else if (!iswalnum (nwc) && nwc != L'_')
1025 #endif /* MBS_SUPPORT */
1026 if (beg + len >= buf + size || !WCHAR ((unsigned char) beg[len]))
1031 /* Returns the whole line now we know there's a word match. */
1034 /* Returns just this word match. */
1035 goto success_in_beg_and_len;
1039 /* Try a shorter length anchored at the same place. */
1041 offset = kwsexec (kwset, beg, len, &kwsmatch);
1044 goto next_char; /* Try a different anchor. */
1046 if (mb_cur_max > 1 && !using_utf8)
1048 size_t bytes_left = offset;
1051 size_t mlen = mbrlen (beg, bytes_left, &mbs);
1054 if (mlen == (size_t) -1 || mlen == 0)
1056 /* Incomplete character: treat as single-byte. */
1057 memset (&mbs, '\0', sizeof (mbstate_t));
1063 if (mlen == (size_t) -2)
1065 /* Offset points inside multibyte character:
1067 memset (&mbs, '\0', sizeof (mbstate_t));
1077 memset (&mbs, '\0', sizeof (mbstate_t));
1078 goto next_char; /* Try a different anchor. */
1082 #endif /* MBS_SUPPORT */
1085 /* The string at beg now matches first 3 chars of one of
1086 the search strings (less if there are shorter search
1087 strings). See if this is a real match. */
1089 && Fimbexec (beg, len - offset, &kwsmatch.size[0],
1092 #endif /* MBS_SUPPORT */
1093 len = kwsmatch.size[0];
1101 /* Advance to next character. For MB_CUR_MAX == 1 case this is handled
1107 unsigned char c = *beg;
1124 size_t l = mbrlen (beg, buf + size - beg, &mbs);
1130 memset (&mbs, '\0', sizeof (mbstate_t));
1133 #endif /* MBS_SUPPORT */
1141 if (mb_cur_max > 1 && !using_utf8)
1144 while (end < buf + size)
1146 size_t mlen = mbrlen (end, buf + size - end, &mbs);
1147 if (mlen == (size_t) -1 || mlen == (size_t) -2 || mlen == 0)
1149 memset (&mbs, '\0', sizeof (mbstate_t));
1152 if (mlen == 1 && *end == eol)
1159 #endif /* MBS_SUPPORT */
1160 end = memchr (beg + len, eol, (buf + size) - (beg + len));
1163 while (buf < beg && beg[-1] != eol)
1168 success_in_beg_and_len:
1174 /* Compiled internal form of a Perl regular expression. */
1177 /* Additional information about the pattern. */
1178 static pcre_extra *extra;
1182 Pcompile (char const *pattern, size_t size)
1185 error (2, 0, _("The -P option is not supported"));
1189 char *re = xmalloc (4 * size + 7);
1190 int flags = PCRE_MULTILINE | (match_icase ? PCRE_CASELESS : 0);
1191 char const *patlim = pattern + size;
1196 /* FIXME: Remove this restriction. */
1197 if (eolbyte != '\n')
1198 error (2, 0, _("The -P and -z options cannot be combined"));
1207 /* The PCRE interface doesn't allow NUL bytes in the pattern, so
1208 replace each NUL byte in the pattern with the four characters
1209 "\000", removing a preceding backslash if there are an odd
1210 number of backslashes before the NUL.
1212 FIXME: This method does not work with some multibyte character
1213 encodings, notably Shift-JIS, where a multibyte character can end
1214 in a backslash byte. */
1215 for (p = pattern; (pnul = memchr (p, '\0', patlim - p)); p = pnul + 1)
1217 memcpy (n, p, pnul - p);
1219 for (p = pnul; pattern < p && p[-1] == '\\'; p--)
1221 n -= (pnul - p) & 1;
1222 strcpy (n, "\\000");
1226 memcpy (n, p, patlim - p);
1234 cre = pcre_compile (re, flags, &ep, &e, pcre_maketables ());
1238 extra = pcre_study (cre, 0, &ep);
1247 Pexecute (char const *buf, size_t size, size_t *match_size, int exact)
1253 /* This array must have at least two elements; everything after that
1254 is just for performance improvement in pcre_exec. */
1257 int e = pcre_exec (cre, extra, buf, size, 0, 0,
1258 sub, sizeof sub / sizeof *sub);
1264 case PCRE_ERROR_NOMATCH:
1267 case PCRE_ERROR_NOMEMORY:
1268 error (2, 0, _("Memory exhausted"));
1276 /* Narrow down to the line we've found. */
1277 char const *beg = buf + sub[0];
1278 char const *end = buf + sub[1];
1279 char const *buflim = buf + size;
1283 end = memchr (end, eol, buflim - end);
1285 while (buf < beg && beg[-1] != eol)
1289 *match_size = end - beg;
1295 struct matcher const matchers[] = {
1296 { "default", Gcompile, EGexecute },
1297 { "grep", Gcompile, EGexecute },
1298 { "egrep", Ecompile, EGexecute },
1299 { "awk", Ecompile, EGexecute },
1300 { "fgrep", Fcompile, Fexecute },
1301 { "perl", Pcompile, Pexecute },