csh: Stop ignoring -Wformat warnings.
[dragonfly.git] / contrib / grep / src / kwsearch.c
blob6bd516a93ad5b42637aac32fccf1d1ad56732fff
1 /* kwsearch.c - searching subroutines using kwset for grep.
2 Copyright 1992, 1998, 2000, 2007, 2009-2014 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;
40 mb_len_map_t *map = NULL;
41 char const *pat = (match_icase && MB_CUR_MAX > 1
42 ? mbtoupper (pattern, &total, &map)
43 : pattern);
45 kwsinit (&kwset);
47 char const *p = pat;
50 size_t len;
51 char const *sep = memchr (p, '\n', total);
52 if (sep)
54 len = sep - p;
55 sep++;
56 total -= (len + 1);
58 else
60 len = total;
61 total = 0;
64 char *buf = NULL;
65 if (match_lines)
67 buf = xmalloc (len + 2);
68 buf[0] = eolbyte;
69 memcpy (buf + 1, p, len);
70 buf[len + 1] = eolbyte;
71 p = buf;
72 len += 2;
74 kwsincr (kwset, p, len);
75 free (buf);
77 p = sep;
79 while (p);
81 kwsprep (kwset);
84 /* Apply the MAP (created by mbtoupper) to the uppercase-buffer-relative
85 *OFF and *LEN, converting them to be relative to the original buffer. */
87 static void
88 mb_case_map_apply (mb_len_map_t const *map, size_t *off, size_t *len)
90 if (map)
92 size_t off_incr = 0;
93 size_t len_incr = 0;
94 size_t k;
95 for (k = 0; k < *off; k++)
96 off_incr += map[k];
97 for (; k < *off + *len; k++)
98 len_incr += map[k];
99 *off += off_incr;
100 *len += len_incr;
104 size_t
105 Fexecute (char const *buf, size_t size, size_t *match_size,
106 char const *start_ptr)
108 char const *beg, *try, *end, *mb_start;
109 size_t len;
110 char eol = eolbyte;
111 struct kwsmatch kwsmatch;
112 size_t ret_val;
113 mb_len_map_t *map = NULL;
115 if (MB_CUR_MAX > 1)
117 if (match_icase)
119 char *case_buf = mbtoupper (buf, &size, &map);
120 if (start_ptr)
121 start_ptr = case_buf + (start_ptr - buf);
122 buf = case_buf;
126 for (mb_start = beg = start_ptr ? start_ptr : buf; beg <= buf + size; beg++)
128 size_t offset = kwsexec (kwset, beg - match_lines,
129 buf + size - beg + match_lines, &kwsmatch);
130 if (offset == (size_t) -1)
131 goto failure;
132 len = kwsmatch.size[0] - match_lines;
133 if (!match_lines && MB_CUR_MAX > 1 && !using_utf8 ()
134 && mb_goback (&mb_start, beg + offset, buf + size) != 0)
136 /* The match was a part of multibyte character, advance at least
137 one byte to ensure no infinite loop happens. */
138 beg = mb_start;
139 continue;
141 beg += offset;
142 if (start_ptr && !match_words)
143 goto success_in_beg_and_len;
144 if (match_lines)
145 goto success_in_beg_and_len;
146 if (match_words)
147 for (try = beg; ; )
149 if (wordchar (mb_prev_wc (buf, try, buf + size)))
150 break;
151 if (wordchar (mb_next_wc (try + len, buf + size)))
153 if (!len)
154 break;
155 offset = kwsexec (kwset, beg, --len, &kwsmatch);
156 if (offset == (size_t) -1)
157 break;
158 try = beg + offset;
159 len = kwsmatch.size[0];
161 else if (!start_ptr)
162 goto success;
163 else
164 goto success_in_beg_and_len;
165 } /* for (try) */
166 else
167 goto success;
168 } /* for (beg in buf) */
170 failure:
171 return -1;
173 success:
174 if ((end = memchr (beg + len, eol, (buf + size) - (beg + len))) != NULL)
175 end++;
176 else
177 end = buf + size;
178 while (buf < beg && beg[-1] != eol)
179 --beg;
180 len = end - beg;
181 success_in_beg_and_len:;
182 size_t off = beg - buf;
183 mb_case_map_apply (map, &off, &len);
185 *match_size = len;
186 ret_val = off;
187 return ret_val;