pattern.c (1ea316270f1f75922ac53976d5d8808a41442f46) | pattern.c (f6b74a7d164b5fada266d00e723155a178a4529f) |
---|---|
1/* | 1/* |
2 * Copyright (C) 1984-2015 Mark Nudelman | 2 * Copyright (C) 1984-2017 Mark Nudelman |
3 * 4 * You may distribute under the terms of either the GNU General Public 5 * License or the Less License, as specified in the README file. 6 * 7 * For more information, see the README file. 8 */ 9 10/* 11 * Routines to do pattern matching. 12 */ 13 14#include "less.h" | 3 * 4 * You may distribute under the terms of either the GNU General Public 5 * License or the Less License, as specified in the README file. 6 * 7 * For more information, see the README file. 8 */ 9 10/* 11 * Routines to do pattern matching. 12 */ 13 14#include "less.h" |
15#include "pattern.h" | |
16 17extern int caseless; 18 19/* 20 * Compile a search pattern, for future use by match_pattern. 21 */ 22 static int | 15 16extern int caseless; 17 18/* 19 * Compile a search pattern, for future use by match_pattern. 20 */ 21 static int |
23compile_pattern2(char *pattern, int search_type, void **comp_pattern, int show_error) | 22compile_pattern2(pattern, search_type, comp_pattern, show_error) 23 char *pattern; 24 int search_type; 25 PATTERN_TYPE *comp_pattern; 26 int show_error; |
24{ 25 if (search_type & SRCH_NO_REGEX) 26 return (0); 27 { 28#if HAVE_GNU_REGEX 29 struct re_pattern_buffer *comp = (struct re_pattern_buffer *) 30 ecalloc(1, sizeof(struct re_pattern_buffer)); | 27{ 28 if (search_type & SRCH_NO_REGEX) 29 return (0); 30 { 31#if HAVE_GNU_REGEX 32 struct re_pattern_buffer *comp = (struct re_pattern_buffer *) 33 ecalloc(1, sizeof(struct re_pattern_buffer)); |
31 struct re_pattern_buffer **pcomp = 32 (struct re_pattern_buffer **) comp_pattern; | |
33 re_set_syntax(RE_SYNTAX_POSIX_EXTENDED); 34 if (re_compile_pattern(pattern, strlen(pattern), comp)) 35 { 36 free(comp); 37 if (show_error) 38 error("Invalid pattern", NULL_PARG); 39 return (-1); 40 } | 34 re_set_syntax(RE_SYNTAX_POSIX_EXTENDED); 35 if (re_compile_pattern(pattern, strlen(pattern), comp)) 36 { 37 free(comp); 38 if (show_error) 39 error("Invalid pattern", NULL_PARG); 40 return (-1); 41 } |
41 if (*pcomp != NULL) 42 regfree(*pcomp); 43 *pcomp = comp; | 42 if (*comp_pattern != NULL) 43 { 44 regfree(*comp_pattern); 45 free(*comp_pattern); 46 } 47 *comp_pattern = comp; |
44#endif 45#if HAVE_POSIX_REGCOMP 46 regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t)); | 48#endif 49#if HAVE_POSIX_REGCOMP 50 regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t)); |
47 regex_t **pcomp = (regex_t **) comp_pattern; | |
48 if (regcomp(comp, pattern, REGCOMP_FLAG)) 49 { 50 free(comp); 51 if (show_error) 52 error("Invalid pattern", NULL_PARG); 53 return (-1); 54 } | 51 if (regcomp(comp, pattern, REGCOMP_FLAG)) 52 { 53 free(comp); 54 if (show_error) 55 error("Invalid pattern", NULL_PARG); 56 return (-1); 57 } |
55 if (*pcomp != NULL) 56 regfree(*pcomp); 57 *pcomp = comp; | 58 if (*comp_pattern != NULL) 59 { 60 regfree(*comp_pattern); 61 free(*comp_pattern); 62 } 63 *comp_pattern = comp; |
58#endif 59#if HAVE_PCRE 60 pcre *comp; | 64#endif 65#if HAVE_PCRE 66 pcre *comp; |
61 pcre **pcomp = (pcre **) comp_pattern; | |
62 constant char *errstring; 63 int erroffset; 64 PARG parg; 65 comp = pcre_compile(pattern, 0, 66 &errstring, &erroffset, NULL); 67 if (comp == NULL) 68 { 69 parg.p_string = (char *) errstring; 70 if (show_error) 71 error("%s", &parg); 72 return (-1); 73 } | 67 constant char *errstring; 68 int erroffset; 69 PARG parg; 70 comp = pcre_compile(pattern, 0, 71 &errstring, &erroffset, NULL); 72 if (comp == NULL) 73 { 74 parg.p_string = (char *) errstring; 75 if (show_error) 76 error("%s", &parg); 77 return (-1); 78 } |
74 *pcomp = comp; | 79 *comp_pattern = comp; |
75#endif 76#if HAVE_RE_COMP 77 PARG parg; | 80#endif 81#if HAVE_RE_COMP 82 PARG parg; |
78 int *pcomp = (int *) comp_pattern; | |
79 if ((parg.p_string = re_comp(pattern)) != NULL) 80 { 81 if (show_error) 82 error("%s", &parg); 83 return (-1); 84 } | 83 if ((parg.p_string = re_comp(pattern)) != NULL) 84 { 85 if (show_error) 86 error("%s", &parg); 87 return (-1); 88 } |
85 *pcomp = 1; | 89 *comp_pattern = 1; |
86#endif 87#if HAVE_REGCMP 88 char *comp; | 90#endif 91#if HAVE_REGCMP 92 char *comp; |
89 char **pcomp = (char **) comp_pattern; | |
90 if ((comp = regcmp(pattern, 0)) == NULL) 91 { 92 if (show_error) 93 error("Invalid pattern", NULL_PARG); 94 return (-1); 95 } | 93 if ((comp = regcmp(pattern, 0)) == NULL) 94 { 95 if (show_error) 96 error("Invalid pattern", NULL_PARG); 97 return (-1); 98 } |
96 if (pcomp != NULL) 97 free(*pcomp); 98 *pcomp = comp; | 99 if (comp_pattern != NULL) 100 free(*comp_pattern); 101 *comp_pattern = comp; |
99#endif 100#if HAVE_V8_REGCOMP 101 struct regexp *comp; | 102#endif 103#if HAVE_V8_REGCOMP 104 struct regexp *comp; |
102 struct regexp **pcomp = (struct regexp **) comp_pattern; | |
103 reg_show_error = show_error; 104 comp = regcomp(pattern); 105 reg_show_error = 1; 106 if (comp == NULL) 107 { 108 /* 109 * regcomp has already printed an error message 110 * via regerror(). 111 */ 112 return (-1); 113 } | 105 reg_show_error = show_error; 106 comp = regcomp(pattern); 107 reg_show_error = 1; 108 if (comp == NULL) 109 { 110 /* 111 * regcomp has already printed an error message 112 * via regerror(). 113 */ 114 return (-1); 115 } |
114 if (*pcomp != NULL) 115 free(*pcomp); 116 *pcomp = comp; | 116 if (*comp_pattern != NULL) 117 free(*comp_pattern); 118 *comp_pattern = comp; |
117#endif 118 } 119 return (0); 120} 121 122/* 123 * Like compile_pattern2, but convert the pattern to lowercase if necessary. 124 */ 125 public int | 119#endif 120 } 121 return (0); 122} 123 124/* 125 * Like compile_pattern2, but convert the pattern to lowercase if necessary. 126 */ 127 public int |
126compile_pattern(char *pattern, int search_type, void **comp_pattern) | 128compile_pattern(pattern, search_type, comp_pattern) 129 char *pattern; 130 int search_type; 131 PATTERN_TYPE *comp_pattern; |
127{ 128 char *cvt_pattern; 129 int result; 130 131 if (caseless != OPT_ONPLUS) 132 cvt_pattern = pattern; 133 else 134 { --- 5 unchanged lines hidden (view full) --- 140 free(cvt_pattern); 141 return (result); 142} 143 144/* 145 * Forget that we have a compiled pattern. 146 */ 147 public void | 132{ 133 char *cvt_pattern; 134 int result; 135 136 if (caseless != OPT_ONPLUS) 137 cvt_pattern = pattern; 138 else 139 { --- 5 unchanged lines hidden (view full) --- 145 free(cvt_pattern); 146 return (result); 147} 148 149/* 150 * Forget that we have a compiled pattern. 151 */ 152 public void |
148uncompile_pattern(void **pattern) | 153uncompile_pattern(pattern) 154 PATTERN_TYPE *pattern; |
149{ 150#if HAVE_GNU_REGEX | 155{ 156#if HAVE_GNU_REGEX |
151 struct re_pattern_buffer **pcomp = (struct re_pattern_buffer **) pattern; 152 if (*pcomp != NULL) 153 regfree(*pcomp); 154 *pcomp = NULL; | 157 if (*pattern != NULL) 158 { 159 regfree(*pattern); 160 free(*pattern); 161 } 162 *pattern = NULL; |
155#endif 156#if HAVE_POSIX_REGCOMP | 163#endif 164#if HAVE_POSIX_REGCOMP |
157 regex_t **pcomp = (regex_t **) pattern; 158 if (*pcomp != NULL) 159 regfree(*pcomp); 160 *pcomp = NULL; | 165 if (*pattern != NULL) 166 { 167 regfree(*pattern); 168 free(*pattern); 169 } 170 *pattern = NULL; |
161#endif 162#if HAVE_PCRE | 171#endif 172#if HAVE_PCRE |
163 pcre **pcomp = (pcre **) pattern; 164 if (*pcomp != NULL) 165 pcre_free(*pcomp); 166 *pcomp = NULL; | 173 if (*pattern != NULL) 174 pcre_free(*pattern); 175 *pattern = NULL; |
167#endif 168#if HAVE_RE_COMP | 176#endif 177#if HAVE_RE_COMP |
169 int *pcomp = (int *) pattern; 170 *pcomp = 0; | 178 *pattern = 0; |
171#endif 172#if HAVE_REGCMP | 179#endif 180#if HAVE_REGCMP |
173 char **pcomp = (char **) pattern; 174 if (*pcomp != NULL) 175 free(*pcomp); 176 *pcomp = NULL; | 181 if (*pattern != NULL) 182 free(*pattern); 183 *pattern = NULL; |
177#endif 178#if HAVE_V8_REGCOMP | 184#endif 185#if HAVE_V8_REGCOMP |
179 struct regexp **pcomp = (struct regexp **) pattern; 180 if (*pcomp != NULL) 181 free(*pcomp); 182 *pcomp = NULL; | 186 if (*pattern != NULL) 187 free(*pattern); 188 *pattern = NULL; |
183#endif 184} 185 186/* 187 * Can a pattern be successfully compiled? 188 */ 189 public int | 189#endif 190} 191 192/* 193 * Can a pattern be successfully compiled? 194 */ 195 public int |
190valid_pattern(char *pattern) | 196valid_pattern(pattern) 197 char *pattern; |
191{ | 198{ |
192 void *comp_pattern; | 199 PATTERN_TYPE comp_pattern; |
193 int result; 194 195 CLEAR_PATTERN(comp_pattern); 196 result = compile_pattern2(pattern, 0, &comp_pattern, 0); 197 if (result != 0) 198 return (0); 199 uncompile_pattern(&comp_pattern); 200 return (1); 201} 202 203/* 204 * Is a compiled pattern null? 205 */ 206 public int | 200 int result; 201 202 CLEAR_PATTERN(comp_pattern); 203 result = compile_pattern2(pattern, 0, &comp_pattern, 0); 204 if (result != 0) 205 return (0); 206 uncompile_pattern(&comp_pattern); 207 return (1); 208} 209 210/* 211 * Is a compiled pattern null? 212 */ 213 public int |
207is_null_pattern(void *pattern) | 214is_null_pattern(pattern) 215 PATTERN_TYPE pattern; |
208{ 209#if HAVE_GNU_REGEX 210 return (pattern == NULL); 211#endif 212#if HAVE_POSIX_REGCOMP 213 return (pattern == NULL); 214#endif 215#if HAVE_PCRE --- 13 unchanged lines hidden (view full) --- 229#endif 230} 231 232/* 233 * Simple pattern matching function. 234 * It supports no metacharacters like *, etc. 235 */ 236 static int | 216{ 217#if HAVE_GNU_REGEX 218 return (pattern == NULL); 219#endif 220#if HAVE_POSIX_REGCOMP 221 return (pattern == NULL); 222#endif 223#if HAVE_PCRE --- 13 unchanged lines hidden (view full) --- 237#endif 238} 239 240/* 241 * Simple pattern matching function. 242 * It supports no metacharacters like *, etc. 243 */ 244 static int |
237match(char *pattern, int pattern_len, char *buf, int buf_len, char **pfound, char **pend) | 245match(pattern, pattern_len, buf, buf_len, pfound, pend) 246 char *pattern; 247 int pattern_len; 248 char *buf; 249 int buf_len; 250 char **pfound, **pend; |
238{ 239 char *pp, *lp; 240 char *pattern_end = pattern + pattern_len; 241 char *buf_end = buf + buf_len; 242 243 for ( ; buf < buf_end; buf++) 244 { 245 for (pp = pattern, lp = buf; ; pp++, lp++) --- 19 unchanged lines hidden (view full) --- 265 return (0); 266} 267 268/* 269 * Perform a pattern match with the previously compiled pattern. 270 * Set sp and ep to the start and end of the matched string. 271 */ 272 public int | 251{ 252 char *pp, *lp; 253 char *pattern_end = pattern + pattern_len; 254 char *buf_end = buf + buf_len; 255 256 for ( ; buf < buf_end; buf++) 257 { 258 for (pp = pattern, lp = buf; ; pp++, lp++) --- 19 unchanged lines hidden (view full) --- 278 return (0); 279} 280 281/* 282 * Perform a pattern match with the previously compiled pattern. 283 * Set sp and ep to the start and end of the matched string. 284 */ 285 public int |
273match_pattern(void *pattern, char *tpattern, char *line, int line_len, char **sp, char **ep, int notbol, int search_type) | 286match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type) 287 PATTERN_TYPE pattern; 288 char *tpattern; 289 char *line; 290 int line_len; 291 char **sp; 292 char **ep; 293 int notbol; 294 int search_type; |
274{ 275 int matched; | 295{ 296 int matched; |
276#if HAVE_GNU_REGEX 277 struct re_pattern_buffer *spattern = (struct re_pattern_buffer *) pattern; 278#endif 279#if HAVE_POSIX_REGCOMP 280 regex_t *spattern = (regex_t *) pattern; 281#endif 282#if HAVE_PCRE 283 pcre *spattern = (pcre *) pattern; 284#endif 285#if HAVE_RE_COMP 286 int spattern = (int) pattern; 287#endif 288#if HAVE_REGCMP 289 char *spattern = (char *) pattern; 290#endif 291#if HAVE_V8_REGCOMP 292 struct regexp *spattern = (struct regexp *) pattern; 293#endif | |
294 295 *sp = *ep = NULL; 296#if NO_REGEX 297 search_type |= SRCH_NO_REGEX; 298#endif 299 if (search_type & SRCH_NO_REGEX) 300 matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep); 301 else 302 { 303#if HAVE_GNU_REGEX 304 { 305 struct re_registers search_regs; | 297 298 *sp = *ep = NULL; 299#if NO_REGEX 300 search_type |= SRCH_NO_REGEX; 301#endif 302 if (search_type & SRCH_NO_REGEX) 303 matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep); 304 else 305 { 306#if HAVE_GNU_REGEX 307 { 308 struct re_registers search_regs; |
306 spattern->not_bol = notbol; 307 spattern->regs_allocated = REGS_UNALLOCATED; 308 matched = re_search(spattern, line, line_len, 0, line_len, &search_regs) >= 0; | 309 pattern->not_bol = notbol; 310 pattern->regs_allocated = REGS_UNALLOCATED; 311 matched = re_search(pattern, line, line_len, 0, line_len, &search_regs) >= 0; |
309 if (matched) 310 { 311 *sp = line + search_regs.start[0]; 312 *ep = line + search_regs.end[0]; 313 } 314 } 315#endif 316#if HAVE_POSIX_REGCOMP 317 { 318 regmatch_t rm; 319 int flags = (notbol) ? REG_NOTBOL : 0; 320#ifdef REG_STARTEND 321 flags |= REG_STARTEND; 322 rm.rm_so = 0; 323 rm.rm_eo = line_len; 324#endif | 312 if (matched) 313 { 314 *sp = line + search_regs.start[0]; 315 *ep = line + search_regs.end[0]; 316 } 317 } 318#endif 319#if HAVE_POSIX_REGCOMP 320 { 321 regmatch_t rm; 322 int flags = (notbol) ? REG_NOTBOL : 0; 323#ifdef REG_STARTEND 324 flags |= REG_STARTEND; 325 rm.rm_so = 0; 326 rm.rm_eo = line_len; 327#endif |
325 matched = !regexec(spattern, line, 1, &rm, flags); | 328 matched = !regexec(pattern, line, 1, &rm, flags); |
326 if (matched) 327 { 328#ifndef __WATCOMC__ 329 *sp = line + rm.rm_so; 330 *ep = line + rm.rm_eo; 331#else 332 *sp = rm.rm_sp; 333 *ep = rm.rm_ep; 334#endif 335 } 336 } 337#endif 338#if HAVE_PCRE 339 { 340 int flags = (notbol) ? PCRE_NOTBOL : 0; 341 int ovector[3]; | 329 if (matched) 330 { 331#ifndef __WATCOMC__ 332 *sp = line + rm.rm_so; 333 *ep = line + rm.rm_eo; 334#else 335 *sp = rm.rm_sp; 336 *ep = rm.rm_ep; 337#endif 338 } 339 } 340#endif 341#if HAVE_PCRE 342 { 343 int flags = (notbol) ? PCRE_NOTBOL : 0; 344 int ovector[3]; |
342 matched = pcre_exec(spattern, NULL, line, line_len, | 345 matched = pcre_exec(pattern, NULL, line, line_len, |
343 0, flags, ovector, 3) >= 0; 344 if (matched) 345 { 346 *sp = line + ovector[0]; 347 *ep = line + ovector[1]; 348 } 349 } 350#endif 351#if HAVE_RE_COMP 352 matched = (re_exec(line) == 1); 353 /* 354 * re_exec doesn't seem to provide a way to get the matched string. 355 */ 356 *sp = *ep = NULL; 357#endif 358#if HAVE_REGCMP | 346 0, flags, ovector, 3) >= 0; 347 if (matched) 348 { 349 *sp = line + ovector[0]; 350 *ep = line + ovector[1]; 351 } 352 } 353#endif 354#if HAVE_RE_COMP 355 matched = (re_exec(line) == 1); 356 /* 357 * re_exec doesn't seem to provide a way to get the matched string. 358 */ 359 *sp = *ep = NULL; 360#endif 361#if HAVE_REGCMP |
359 *ep = regex(spattern, line); | 362 *ep = regex(pattern, line); |
360 matched = (*ep != NULL); 361 if (matched) 362 *sp = __loc1; 363#endif 364#if HAVE_V8_REGCOMP 365#if HAVE_REGEXEC2 | 363 matched = (*ep != NULL); 364 if (matched) 365 *sp = __loc1; 366#endif 367#if HAVE_V8_REGCOMP 368#if HAVE_REGEXEC2 |
366 matched = regexec2(spattern, line, notbol); | 369 matched = regexec2(pattern, line, notbol); |
367#else | 370#else |
368 matched = regexec(spattern, line); | 371 matched = regexec(pattern, line); |
369#endif 370 if (matched) 371 { | 372#endif 373 if (matched) 374 { |
372 *sp = spattern->startp[0]; 373 *ep = spattern->endp[0]; | 375 *sp = pattern->startp[0]; 376 *ep = pattern->endp[0]; |
374 } 375#endif 376 } 377 matched = (!(search_type & SRCH_NO_MATCH) && matched) || 378 ((search_type & SRCH_NO_MATCH) && !matched); 379 return (matched); 380} 381 | 377 } 378#endif 379 } 380 matched = (!(search_type & SRCH_NO_MATCH) && matched) || 381 ((search_type & SRCH_NO_MATCH) && !matched); 382 return (matched); 383} 384 |