Annotation of src/usr.bin/less/pattern.c, Revision 1.1
1.1 ! shadchin 1: /*
! 2: * Copyright (C) 1984-2011 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 about less, or for information on how to
! 8: * contact the author, see the README file.
! 9: */
! 10:
! 11: /*
! 12: * Routines to do pattern matching.
! 13: */
! 14:
! 15: #include "less.h"
! 16: #include "pattern.h"
! 17:
! 18: extern int caseless;
! 19:
! 20: /*
! 21: * Compile a search pattern, for future use by match_pattern.
! 22: */
! 23: static int
! 24: compile_pattern2(pattern, search_type, comp_pattern)
! 25: char *pattern;
! 26: int search_type;
! 27: void **comp_pattern;
! 28: {
! 29: if ((search_type & SRCH_NO_REGEX) == 0)
! 30: {
! 31: #if HAVE_POSIX_REGCOMP
! 32: regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
! 33: regex_t **pcomp = (regex_t **) comp_pattern;
! 34: if (regcomp(comp, pattern, REGCOMP_FLAG))
! 35: {
! 36: free(comp);
! 37: error("Invalid pattern", NULL_PARG);
! 38: return (-1);
! 39: }
! 40: if (*pcomp != NULL)
! 41: regfree(*pcomp);
! 42: *pcomp = comp;
! 43: #endif
! 44: #if HAVE_PCRE
! 45: pcre *comp;
! 46: pcre **pcomp = (pcre **) comp_pattern;
! 47: const char *errstring;
! 48: int erroffset;
! 49: PARG parg;
! 50: comp = pcre_compile(pattern, 0,
! 51: &errstring, &erroffset, NULL);
! 52: if (comp == NULL)
! 53: {
! 54: parg.p_string = (char *) errstring;
! 55: error("%s", &parg);
! 56: return (-1);
! 57: }
! 58: *pcomp = comp;
! 59: #endif
! 60: #if HAVE_RE_COMP
! 61: PARG parg;
! 62: int *pcomp = (int *) comp_pattern;
! 63: if ((parg.p_string = re_comp(pattern)) != NULL)
! 64: {
! 65: error("%s", &parg);
! 66: return (-1);
! 67: }
! 68: *pcomp = 1;
! 69: #endif
! 70: #if HAVE_REGCMP
! 71: char *comp;
! 72: char **pcomp = (char **) comp_pattern;
! 73: if ((comp = regcmp(pattern, 0)) == NULL)
! 74: {
! 75: error("Invalid pattern", NULL_PARG);
! 76: return (-1);
! 77: }
! 78: if (pcomp != NULL)
! 79: free(*pcomp);
! 80: *pcomp = comp;
! 81: #endif
! 82: #if HAVE_V8_REGCOMP
! 83: struct regexp *comp;
! 84: struct regexp **pcomp = (struct regexp **) comp_pattern;
! 85: if ((comp = regcomp(pattern)) == NULL)
! 86: {
! 87: /*
! 88: * regcomp has already printed an error message
! 89: * via regerror().
! 90: */
! 91: return (-1);
! 92: }
! 93: if (*pcomp != NULL)
! 94: free(*pcomp);
! 95: *pcomp = comp;
! 96: #endif
! 97: }
! 98: return (0);
! 99: }
! 100:
! 101: /*
! 102: * Like compile_pattern2, but convert the pattern to lowercase if necessary.
! 103: */
! 104: public int
! 105: compile_pattern(pattern, search_type, comp_pattern)
! 106: char *pattern;
! 107: int search_type;
! 108: void **comp_pattern;
! 109: {
! 110: char *cvt_pattern;
! 111: int result;
! 112:
! 113: if (caseless != OPT_ONPLUS)
! 114: cvt_pattern = pattern;
! 115: else
! 116: {
! 117: cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
! 118: cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC);
! 119: }
! 120: result = compile_pattern2(cvt_pattern, search_type, comp_pattern);
! 121: if (cvt_pattern != pattern)
! 122: free(cvt_pattern);
! 123: return (result);
! 124: }
! 125:
! 126: /*
! 127: * Forget that we have a compiled pattern.
! 128: */
! 129: public void
! 130: uncompile_pattern(pattern)
! 131: void **pattern;
! 132: {
! 133: #if HAVE_POSIX_REGCOMP
! 134: regex_t **pcomp = (regex_t **) pattern;
! 135: if (*pcomp != NULL)
! 136: regfree(*pcomp);
! 137: *pcomp = NULL;
! 138: #endif
! 139: #if HAVE_PCRE
! 140: pcre **pcomp = (pcre **) pattern;
! 141: if (*pcomp != NULL)
! 142: pcre_free(*pcomp);
! 143: *pcomp = NULL;
! 144: #endif
! 145: #if HAVE_RE_COMP
! 146: int *pcomp = (int *) pattern;
! 147: *pcomp = 0;
! 148: #endif
! 149: #if HAVE_REGCMP
! 150: char **pcomp = (char **) pattern;
! 151: if (*pcomp != NULL)
! 152: free(*pcomp);
! 153: *pcomp = NULL;
! 154: #endif
! 155: #if HAVE_V8_REGCOMP
! 156: struct regexp **pcomp = (struct regexp **) pattern;
! 157: if (*pcomp != NULL)
! 158: free(*pcomp);
! 159: *pcomp = NULL;
! 160: #endif
! 161: }
! 162:
! 163: /*
! 164: * Is a compiled pattern null?
! 165: */
! 166: public int
! 167: is_null_pattern(pattern)
! 168: void *pattern;
! 169: {
! 170: #if HAVE_POSIX_REGCOMP
! 171: return (pattern == NULL);
! 172: #endif
! 173: #if HAVE_PCRE
! 174: return (pattern == NULL);
! 175: #endif
! 176: #if HAVE_RE_COMP
! 177: return (pattern == 0);
! 178: #endif
! 179: #if HAVE_REGCMP
! 180: return (pattern == NULL);
! 181: #endif
! 182: #if HAVE_V8_REGCOMP
! 183: return (pattern == NULL);
! 184: #endif
! 185: #if NO_REGEX
! 186: return (search_pattern != NULL);
! 187: #endif
! 188: }
! 189:
! 190: /*
! 191: * Simple pattern matching function.
! 192: * It supports no metacharacters like *, etc.
! 193: */
! 194: static int
! 195: match(pattern, pattern_len, buf, buf_len, pfound, pend)
! 196: char *pattern;
! 197: int pattern_len;
! 198: char *buf;
! 199: int buf_len;
! 200: char **pfound, **pend;
! 201: {
! 202: register char *pp, *lp;
! 203: register char *pattern_end = pattern + pattern_len;
! 204: register char *buf_end = buf + buf_len;
! 205:
! 206: for ( ; buf < buf_end; buf++)
! 207: {
! 208: for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++)
! 209: if (pp == pattern_end || lp == buf_end)
! 210: break;
! 211: if (pp == pattern_end)
! 212: {
! 213: if (pfound != NULL)
! 214: *pfound = buf;
! 215: if (pend != NULL)
! 216: *pend = lp;
! 217: return (1);
! 218: }
! 219: }
! 220: return (0);
! 221: }
! 222:
! 223: /*
! 224: * Perform a pattern match with the previously compiled pattern.
! 225: * Set sp and ep to the start and end of the matched string.
! 226: */
! 227: public int
! 228: match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type)
! 229: void *pattern;
! 230: char *tpattern;
! 231: char *line;
! 232: int line_len;
! 233: char **sp;
! 234: char **ep;
! 235: int notbol;
! 236: int search_type;
! 237: {
! 238: int matched;
! 239: #if HAVE_POSIX_REGCOMP
! 240: regex_t *spattern = (regex_t *) pattern;
! 241: #endif
! 242: #if HAVE_PCRE
! 243: pcre *spattern = (pcre *) pattern;
! 244: #endif
! 245: #if HAVE_RE_COMP
! 246: int spattern = (int) pattern;
! 247: #endif
! 248: #if HAVE_REGCMP
! 249: char *spattern = (char *) pattern;
! 250: #endif
! 251: #if HAVE_V8_REGCOMP
! 252: struct regexp *spattern = (struct regexp *) pattern;
! 253: #endif
! 254:
! 255: if (search_type & SRCH_NO_REGEX)
! 256: matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
! 257: else
! 258: {
! 259: #if HAVE_POSIX_REGCOMP
! 260: {
! 261: regmatch_t rm;
! 262: int flags = (notbol) ? REG_NOTBOL : 0;
! 263: matched = !regexec(spattern, line, 1, &rm, flags);
! 264: if (matched)
! 265: {
! 266: #ifndef __WATCOMC__
! 267: *sp = line + rm.rm_so;
! 268: *ep = line + rm.rm_eo;
! 269: #else
! 270: *sp = rm.rm_sp;
! 271: *ep = rm.rm_ep;
! 272: #endif
! 273: }
! 274: }
! 275: #endif
! 276: #if HAVE_PCRE
! 277: {
! 278: int flags = (notbol) ? PCRE_NOTBOL : 0;
! 279: int ovector[3];
! 280: matched = pcre_exec(spattern, NULL, line, line_len,
! 281: 0, flags, ovector, 3) >= 0;
! 282: if (matched)
! 283: {
! 284: *sp = line + ovector[0];
! 285: *ep = line + ovector[1];
! 286: }
! 287: }
! 288: #endif
! 289: #if HAVE_RE_COMP
! 290: matched = (re_exec(line) == 1);
! 291: /*
! 292: * re_exec doesn't seem to provide a way to get the matched string.
! 293: */
! 294: *sp = *ep = NULL;
! 295: #endif
! 296: #if HAVE_REGCMP
! 297: *ep = regex(spattern, line);
! 298: matched = (*ep != NULL);
! 299: if (matched)
! 300: *sp = __loc1;
! 301: #endif
! 302: #if HAVE_V8_REGCOMP
! 303: #if HAVE_REGEXEC2
! 304: matched = regexec2(spattern, line, notbol);
! 305: #else
! 306: matched = regexec(spattern, line);
! 307: #endif
! 308: if (matched)
! 309: {
! 310: *sp = spattern->startp[0];
! 311: *ep = spattern->endp[0];
! 312: }
! 313: #endif
! 314: #if NO_REGEX
! 315: matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
! 316: #endif
! 317: }
! 318: matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
! 319: ((search_type & SRCH_NO_MATCH) && !matched);
! 320: return (matched);
! 321: }
! 322: