1 /* Pattern Matcher for Fixed String search.
2 Copyright (C) 1992, 1998, 2000, 2005 Free Software Foundation, Inc.
3
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)
7 any later version.
8
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.
13
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 Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 /* Specification. */
23 #include "libgrep.h"
24
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "error.h"
30 #include "exitfail.h"
31 #include "xalloc.h"
32 #include "m-common.h"
33
34 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
35 # define IN_CTYPE_DOMAIN(c) 1
36 #else
37 # define IN_CTYPE_DOMAIN(c) isascii(c)
38 #endif
39 #define ISALNUM(C) (IN_CTYPE_DOMAIN (C) && isalnum (C))
40
41 static void *
Fcompile(const char * pattern,size_t pattern_size,bool match_icase,bool match_words,bool match_lines,char eolbyte)42 Fcompile (const char *pattern, size_t pattern_size,
43 bool match_icase, bool match_words, bool match_lines,
44 char eolbyte)
45 {
46 struct compiled_kwset *ckwset;
47 const char *beg, *lim, *err;
48
49 ckwset = (struct compiled_kwset *) xmalloc (sizeof (struct compiled_kwset));
50 kwsinit (ckwset, match_icase, match_words, match_lines, eolbyte);
51
52 beg = pattern;
53 do
54 {
55 for (lim = beg; lim < pattern + pattern_size && *lim != '\n'; ++lim)
56 ;
57 if ((err = kwsincr (ckwset->kwset, beg, lim - beg)) != NULL)
58 error (exit_failure, 0, err);
59 if (lim < pattern + pattern_size)
60 ++lim;
61 beg = lim;
62 }
63 while (beg < pattern + pattern_size);
64
65 if ((err = kwsprep (ckwset->kwset)) != NULL)
66 error (exit_failure, 0, err);
67 return ckwset;
68 }
69
70 static size_t
Fexecute(const void * compiled_pattern,const char * buf,size_t buf_size,size_t * match_size,bool exact)71 Fexecute (const void *compiled_pattern, const char *buf, size_t buf_size,
72 size_t *match_size, bool exact)
73 {
74 struct compiled_kwset *ckwset = (struct compiled_kwset *) compiled_pattern;
75 register const char *beg, *try, *end;
76 register size_t len;
77 char eol = ckwset->eolbyte;
78 struct kwsmatch kwsmatch;
79 #ifdef MBS_SUPPORT
80 char *mb_properties;
81 if (MB_CUR_MAX > 1)
82 mb_properties = check_multibyte_string (buf, buf_size);
83 #endif /* MBS_SUPPORT */
84
85 for (beg = buf; beg <= buf + buf_size; ++beg)
86 {
87 size_t offset =
88 kwsexec (ckwset->kwset, beg, buf + buf_size - beg, &kwsmatch);
89 if (offset == (size_t) -1)
90 {
91 #ifdef MBS_SUPPORT
92 if (MB_CUR_MAX > 1)
93 free (mb_properties);
94 #endif /* MBS_SUPPORT */
95 return offset;
96 }
97 #ifdef MBS_SUPPORT
98 if (MB_CUR_MAX > 1 && mb_properties[offset+beg-buf] == 0)
99 continue; /* It is a part of multibyte character. */
100 #endif /* MBS_SUPPORT */
101 beg += offset;
102 len = kwsmatch.size[0];
103 if (exact)
104 {
105 *match_size = len;
106 #ifdef MBS_SUPPORT
107 if (MB_CUR_MAX > 1)
108 free (mb_properties);
109 #endif /* MBS_SUPPORT */
110 return beg - buf;
111 }
112 if (ckwset->match_lines)
113 {
114 if (beg > buf && beg[-1] != eol)
115 continue;
116 if (beg + len < buf + buf_size && beg[len] != eol)
117 continue;
118 goto success;
119 }
120 else if (ckwset->match_words)
121 for (try = beg; len; )
122 {
123 if (try > buf && IS_WORD_CONSTITUENT ((unsigned char) try[-1]))
124 break;
125 if (try + len < buf + buf_size
126 && IS_WORD_CONSTITUENT ((unsigned char) try[len]))
127 {
128 offset = kwsexec (ckwset->kwset, beg, --len, &kwsmatch);
129 if (offset == (size_t) -1)
130 {
131 #ifdef MBS_SUPPORT
132 if (MB_CUR_MAX > 1)
133 free (mb_properties);
134 #endif /* MBS_SUPPORT */
135 return offset;
136 }
137 try = beg + offset;
138 len = kwsmatch.size[0];
139 }
140 else
141 goto success;
142 }
143 else
144 goto success;
145 }
146
147 #ifdef MBS_SUPPORT
148 if (MB_CUR_MAX > 1)
149 free (mb_properties);
150 #endif /* MBS_SUPPORT */
151 return -1;
152
153 success:
154 end = memchr (beg + len, eol, (buf + buf_size) - (beg + len));
155 end++;
156 while (buf < beg && beg[-1] != eol)
157 --beg;
158 *match_size = end - beg;
159 #ifdef MBS_SUPPORT
160 if (MB_CUR_MAX > 1)
161 free (mb_properties);
162 #endif /* MBS_SUPPORT */
163 return beg - buf;
164 }
165
166 static void
Ffree(void * compiled_pattern)167 Ffree (void *compiled_pattern)
168 {
169 struct compiled_kwset *ckwset = (struct compiled_kwset *) compiled_pattern;
170
171 free (ckwset->trans);
172 free (ckwset);
173 }
174
175 matcher_t matcher_fgrep =
176 {
177 Fcompile,
178 Fexecute,
179 Ffree
180 };
181
182