Annotation of src/usr.bin/less/pattern.c, Revision 1.9
1.1 shadchin 1: /*
1.3 shadchin 2: * Copyright (C) 1984-2012 Mark Nudelman
1.7 nicm 3: * Modified for use with illumos by Garrett D'Amore.
4: * Copyright 2014 Garrett D'Amore <garrett@damore.org>
1.1 shadchin 5: *
6: * You may distribute under the terms of either the GNU General Public
7: * License or the Less License, as specified in the README file.
8: *
1.3 shadchin 9: * For more information, see the README file.
1.6 nicm 10: */
1.1 shadchin 11:
12: /*
13: * Routines to do pattern matching.
14: */
15:
16: #include "less.h"
17: #include "pattern.h"
18:
19: extern int caseless;
1.2 millert 20: extern int less_is_more;
1.1 shadchin 21:
22: /*
23: * Compile a search pattern, for future use by match_pattern.
24: */
1.6 nicm 25: static int
26: compile_pattern2(char *pattern, int search_type, regex_t **comp_pattern)
1.1 shadchin 27: {
1.6 nicm 28: regex_t *comp;
29:
1.3 shadchin 30: if (search_type & SRCH_NO_REGEX)
31: return (0);
1.6 nicm 32: comp = ecalloc(1, sizeof (regex_t));
33: if (regcomp(comp, pattern, less_is_more ? 0 : REGCOMP_FLAG)) {
1.3 shadchin 34: free(comp);
1.8 deraadt 35: error("Invalid pattern", NULL);
1.3 shadchin 36: return (-1);
37: }
1.6 nicm 38: if (*comp_pattern != NULL)
39: regfree(*comp_pattern);
40: *comp_pattern = comp;
1.1 shadchin 41: return (0);
42: }
43:
44: /*
45: * Like compile_pattern2, but convert the pattern to lowercase if necessary.
46: */
1.6 nicm 47: int
48: compile_pattern(char *pattern, int search_type, regex_t **comp_pattern)
1.1 shadchin 49: {
50: char *cvt_pattern;
51: int result;
52:
1.6 nicm 53: if (caseless != OPT_ONPLUS) {
1.1 shadchin 54: cvt_pattern = pattern;
1.6 nicm 55: } else {
56: cvt_pattern = ecalloc(1, cvt_length(strlen(pattern)));
57: cvt_text(cvt_pattern, pattern, NULL, NULL, CVT_TO_LC);
1.1 shadchin 58: }
59: result = compile_pattern2(cvt_pattern, search_type, comp_pattern);
60: if (cvt_pattern != pattern)
61: free(cvt_pattern);
62: return (result);
63: }
64:
65: /*
66: * Forget that we have a compiled pattern.
67: */
1.6 nicm 68: void
69: uncompile_pattern(regex_t **pattern)
1.1 shadchin 70: {
1.6 nicm 71: if (*pattern != NULL)
72: regfree(*pattern);
73: *pattern = NULL;
1.1 shadchin 74: }
75:
76: /*
77: * Simple pattern matching function.
78: * It supports no metacharacters like *, etc.
79: */
1.6 nicm 80: static int
81: match(char *pattern, int pattern_len, char *buf, int buf_len,
82: char **pfound, char **pend)
83: {
84: char *pp, *lp;
85: char *pattern_end = pattern + pattern_len;
86: char *buf_end = buf + buf_len;
87:
88: for (; buf < buf_end; buf++) {
89: for (pp = pattern, lp = buf; *pp == *lp; pp++, lp++)
1.1 shadchin 90: if (pp == pattern_end || lp == buf_end)
91: break;
1.6 nicm 92: if (pp == pattern_end) {
1.1 shadchin 93: if (pfound != NULL)
94: *pfound = buf;
95: if (pend != NULL)
96: *pend = lp;
97: return (1);
98: }
99: }
100: return (0);
101: }
102:
103: /*
104: * Perform a pattern match with the previously compiled pattern.
105: * Set sp and ep to the start and end of the matched string.
106: */
1.6 nicm 107: int
108: match_pattern(void *pattern, char *tpattern, char *line, int line_len,
109: char **sp, char **ep, int notbol, int search_type)
1.1 shadchin 110: {
111: int matched;
1.6 nicm 112: regex_t *spattern = (regex_t *)pattern;
1.1 shadchin 113:
1.6 nicm 114: if (search_type & SRCH_NO_REGEX) {
115: matched = match(tpattern, strlen(tpattern), line, line_len,
116: sp, ep);
117: } else {
1.1 shadchin 118: regmatch_t rm;
119: int flags = (notbol) ? REG_NOTBOL : 0;
1.6 nicm 120: #ifdef REG_STARTEND
1.4 guenther 121: flags |= REG_STARTEND;
122: rm.rm_so = 0;
123: rm.rm_eo = line_len;
124: #endif
1.1 shadchin 125: matched = !regexec(spattern, line, 1, &rm, flags);
1.6 nicm 126: if (matched) {
1.1 shadchin 127: *sp = line + rm.rm_so;
128: *ep = line + rm.rm_eo;
129: }
130: }
131: matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
1.6 nicm 132: ((search_type & SRCH_NO_MATCH) && !matched);
1.1 shadchin 133: return (matched);
134: }