Annotation of src/usr.bin/less/pattern.c, Revision 1.1.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: