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 * 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 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 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