2 * Copyright (C) 1984-2012 Mark Nudelman
3 * Modified for use with illumos by Garrett D'Amore.
4 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
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.
9 * For more information, see the README file.
13 * Routines to do pattern matching.
20 extern int less_is_more
;
23 * Compile a search pattern, for future use by match_pattern.
26 compile_pattern2(char *pattern
, int search_type
, regex_t
**comp_pattern
)
30 if (search_type
& SRCH_NO_REGEX
)
32 comp
= ecalloc(1, sizeof (regex_t
));
33 if (regcomp(comp
, pattern
, less_is_more
? 0 : REGCOMP_FLAG
)) {
35 error("Invalid pattern", NULL
);
38 if (*comp_pattern
!= NULL
)
39 regfree(*comp_pattern
);
45 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
48 compile_pattern(char *pattern
, int search_type
, regex_t
**comp_pattern
)
53 if (caseless
!= OPT_ONPLUS
) {
54 cvt_pattern
= pattern
;
56 cvt_pattern
= ecalloc(1, cvt_length(strlen(pattern
)));
57 cvt_text(cvt_pattern
, pattern
, NULL
, NULL
, CVT_TO_LC
);
59 result
= compile_pattern2(cvt_pattern
, search_type
, comp_pattern
);
60 if (cvt_pattern
!= pattern
)
66 * Forget that we have a compiled pattern.
69 uncompile_pattern(regex_t
**pattern
)
77 * Simple pattern matching function.
78 * It supports no metacharacters like *, etc.
81 match(char *pattern
, int pattern_len
, char *buf
, int buf_len
,
82 char **pfound
, char **pend
)
85 char *pattern_end
= pattern
+ pattern_len
;
86 char *buf_end
= buf
+ buf_len
;
88 for (; buf
< buf_end
; buf
++) {
89 for (pp
= pattern
, lp
= buf
; *pp
== *lp
; pp
++, lp
++)
90 if (pp
== pattern_end
|| lp
== buf_end
)
92 if (pp
== pattern_end
) {
104 * Perform a pattern match with the previously compiled pattern.
105 * Set sp and ep to the start and end of the matched string.
108 match_pattern(void *pattern
, char *tpattern
, char *line
, int line_len
,
109 char **sp
, char **ep
, int notbol
, int search_type
)
112 regex_t
*spattern
= (regex_t
*)pattern
;
114 if (search_type
& SRCH_NO_REGEX
) {
115 matched
= match(tpattern
, strlen(tpattern
), line
, line_len
,
119 int flags
= (notbol
) ? REG_NOTBOL
: 0;
121 flags
|= REG_STARTEND
;
127 matched
= !regexec(spattern
, line
, 1, &rm
, flags
);
129 *sp
= line
+ rm
.rm_so
;
130 *ep
= line
+ rm
.rm_eo
;
133 matched
= (!(search_type
& SRCH_NO_MATCH
) && matched
) ||
134 ((search_type
& SRCH_NO_MATCH
) && !matched
);