GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/less/less/../pattern.c Lines: 30 55 54.5 %
Date: 2017-11-13 Branches: 11 34 32.4 %

Line Branch Exec Source
1
/*
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>
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
 *
9
 * For more information, see the README file.
10
 */
11
12
/*
13
 * Routines to do pattern matching.
14
 */
15
16
#include "less.h"
17
#include "pattern.h"
18
19
extern int caseless;
20
extern int less_is_more;
21
22
/*
23
 * Compile a search pattern, for future use by match_pattern.
24
 */
25
static int
26
compile_pattern2(char *pattern, int search_type, regex_t **comp_pattern)
27
{
28
	regex_t *comp;
29
30
6
	if (search_type & SRCH_NO_REGEX)
31
		return (0);
32
3
	comp = ecalloc(1, sizeof (regex_t));
33
3
	if (regcomp(comp, pattern, less_is_more ? 0 : REGCOMP_FLAG)) {
34
		free(comp);
35
		error("Invalid pattern", NULL);
36
		return (-1);
37
	}
38
3
	if (*comp_pattern != NULL)
39
		regfree(*comp_pattern);
40
3
	*comp_pattern = comp;
41
3
	return (0);
42
3
}
43
44
/*
45
 * Like compile_pattern2, but convert the pattern to lowercase if necessary.
46
 */
47
int
48
compile_pattern(char *pattern, int search_type, regex_t **comp_pattern)
49
{
50
	char *cvt_pattern;
51
	int result;
52
53
6
	if (caseless != OPT_ONPLUS) {
54
		cvt_pattern = pattern;
55
3
	} else {
56
		cvt_pattern = ecalloc(1, cvt_length(strlen(pattern)));
57
		cvt_text(cvt_pattern, pattern, NULL, NULL, CVT_TO_LC);
58
	}
59
3
	result = compile_pattern2(cvt_pattern, search_type, comp_pattern);
60
3
	if (cvt_pattern != pattern)
61
		free(cvt_pattern);
62
3
	return (result);
63
}
64
65
/*
66
 * Forget that we have a compiled pattern.
67
 */
68
void
69
uncompile_pattern(regex_t **pattern)
70
{
71
	if (*pattern != NULL)
72
		regfree(*pattern);
73
	*pattern = NULL;
74
}
75
76
/*
77
 * Simple pattern matching function.
78
 * It supports no metacharacters like *, etc.
79
 */
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++)
90
			if (pp == pattern_end || lp == buf_end)
91
				break;
92
		if (pp == pattern_end) {
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
 */
107
int
108
match_pattern(void *pattern, char *tpattern, char *line, int line_len,
109
    char **sp, char **ep, int notbol, int search_type)
110
{
111
	int matched;
112
20076
	regex_t *spattern = (regex_t *)pattern;
113
114
10038
	if (search_type & SRCH_NO_REGEX) {
115
		matched = match(tpattern, strlen(tpattern), line, line_len,
116
		    sp, ep);
117
	} else {
118
10038
		regmatch_t rm;
119
10038
		int flags = (notbol) ? REG_NOTBOL : 0;
120
#ifdef	REG_STARTEND
121
10038
		flags |= REG_STARTEND;
122
10038
		rm.rm_so = 0;
123
10038
		rm.rm_eo = line_len;
124
#endif
125
10038
		*sp = NULL;
126
10038
		*ep = NULL;
127
10038
		matched = !regexec(spattern, line, 1, &rm, flags);
128
10038
		if (matched) {
129
49
			*sp = line + rm.rm_so;
130
49
			*ep = line + rm.rm_eo;
131
49
		}
132
10038
	}
133
20076
	matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
134
9989
	    ((search_type & SRCH_NO_MATCH) && !matched);
135
10038
	return (matched);
136
}