xref: /netbsd-src/external/gpl2/gettext/dist/gettext-tools/libgrep/m-fgrep.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
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