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