drm/i915: Update to Linux 4.6
[dragonfly.git] / contrib / grep / src / kwsearch.c
blob2997ae1acbc13e1d6ed620f14bd37537116b119f
1 /* kwsearch.c - searching subroutines using kwset for grep.
2 Copyright 1992, 1998, 2000, 2007, 2009-2015 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 3, or (at your option)
7 any later version.
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., 51 Franklin Street - Fifth Floor, Boston, MA
17 02110-1301, USA. */
19 /* Written August 1992 by Mike Haertel. */
21 #include <config.h>
22 #include "search.h"
24 /* Whether -w considers WC to be a word constituent. */
25 static bool
26 wordchar (wint_t wc)
28 return wc == L'_' || iswalnum (wc);
31 /* KWset compiled pattern. For Ecompile and Gcompile, we compile
32 a list of strings, at least one of which is known to occur in
33 any string matching the regexp. */
34 static kwset_t kwset;
36 void
37 Fcompile (char const *pattern, size_t size)
39 size_t total = size;
41 kwsinit (&kwset);
43 char const *p = pattern;
46 size_t len;
47 char const *sep = memchr (p, '\n', total);
48 if (sep)
50 len = sep - p;
51 sep++;
52 total -= (len + 1);
54 else
56 len = total;
57 total = 0;
60 char *buf = NULL;
61 if (match_lines)
63 buf = xmalloc (len + 2);
64 buf[0] = eolbyte;
65 memcpy (buf + 1, p, len);
66 buf[len + 1] = eolbyte;
67 p = buf;
68 len += 2;
70 kwsincr (kwset, p, len);
71 free (buf);
73 p = sep;
75 while (p);
77 kwsprep (kwset);
80 size_t
81 Fexecute (char const *buf, size_t size, size_t *match_size,
82 char const *start_ptr)
84 char const *beg, *try, *end, *mb_start;
85 size_t len;
86 char eol = eolbyte;
87 struct kwsmatch kwsmatch;
88 size_t ret_val;
90 for (mb_start = beg = start_ptr ? start_ptr : buf; beg <= buf + size; beg++)
92 size_t offset = kwsexec (kwset, beg - match_lines,
93 buf + size - beg + match_lines, &kwsmatch);
94 if (offset == (size_t) -1)
95 goto failure;
96 len = kwsmatch.size[0] - 2 * match_lines;
97 if (!match_lines && MB_CUR_MAX > 1 && !using_utf8 ()
98 && mb_goback (&mb_start, beg + offset, buf + size) != 0)
100 /* We have matched a single byte that is not at the beginning of a
101 multibyte character. mb_goback has advanced MB_START past that
102 multibyte character. Now, we want to position BEG so that the
103 next kwsexec search starts there. Thus, to compensate for the
104 for-loop's BEG++, above, subtract one here. This code is
105 unusually hard to reach, and exceptionally, let's show how to
106 trigger it here:
108 printf '\203AA\n'|LC_ALL=ja_JP.SHIFT_JIS src/grep -F A
110 That assumes the named locale is installed.
111 Note that your system's shift-JIS locale may have a different
112 name, possibly including "sjis". */
113 beg = mb_start - 1;
114 continue;
116 beg += offset;
117 if (start_ptr && !match_words)
118 goto success_in_beg_and_len;
119 if (match_lines)
121 len += start_ptr == NULL;
122 goto success_in_beg_and_len;
124 if (match_words)
125 for (try = beg; ; )
127 char const *bol = memrchr (buf, eol, beg - buf);
128 bol = bol ? bol + 1 : buf;
129 if (wordchar (mb_prev_wc (bol, try, buf + size)))
130 break;
131 if (wordchar (mb_next_wc (try + len, buf + size)))
133 if (!len)
134 break;
135 offset = kwsexec (kwset, beg, --len, &kwsmatch);
136 if (offset == (size_t) -1)
137 break;
138 try = beg + offset;
139 len = kwsmatch.size[0];
141 else if (!start_ptr)
142 goto success;
143 else
144 goto success_in_beg_and_len;
145 } /* for (try) */
146 else
147 goto success;
148 } /* for (beg in buf) */
150 failure:
151 return -1;
153 success:
154 end = memchr (beg + len, eol, (buf + size) - (beg + len));
155 end = end ? end + 1 : buf + size;
156 beg = memrchr (buf, eol, beg - buf);
157 beg = beg ? beg + 1 : buf;
158 len = end - beg;
159 success_in_beg_and_len:;
160 size_t off = beg - buf;
162 *match_size = len;
163 ret_val = off;
164 return ret_val;