Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "stdinc.h"
2
#include "vac.h"
3
#include "dat.h"
4
#include "fns.h"
5
#include "error.h"
6
 
7
// Convert globbish pattern to regular expression
8
// The wildcards are
9
//
10
//	*	any non-slash characters
11
//	...	any characters including /
12
//	?	any single character except /
13
//	[a-z]	character class
14
//	[~a-z]	negated character class
15
//
16
 
17
Reprog*
18
glob2regexp(char *glob)
19
{
20
	char *s, *p, *w;
21
	Reprog *re;
22
	int boe;	// beginning of path element
23
 
24
	s = malloc(20*(strlen(glob)+1));
25
	if(s == nil)
26
		return nil;
27
	w = s;
28
	boe = 1;
29
	*w++ = '^';
30
	*w++ = '(';
31
	for(p=glob; *p; p++){
32
		if(p[0] == '.' && p[1] == '.' && p[2] == '.'){
33
			strcpy(w, ".*");
34
			w += strlen(w);
35
			p += 3-1;
36
			boe = 0;
37
			continue;
38
		}
39
		if(p[0] == '*'){
40
			if(boe)
41
				strcpy(w, "([^./][^/]*)?");
42
			else
43
				strcpy(w, "[^/]*");
44
			w += strlen(w);
45
			boe = 0;
46
			continue;
47
		}
48
		if(p[0] == '?'){
49
			if(boe)
50
				strcpy(w, "[^./]");
51
			else
52
				strcpy(w, "[^/]");
53
			w += strlen(w);
54
			boe = 0;
55
			continue;
56
		}
57
		if(p[0] == '['){
58
			*w++ = '[';
59
			if(*++p == '~'){
60
				*w++ = '^';
61
				p++;
62
			}
63
			while(*p != ']'){
64
				if(*p == '/')
65
					goto syntax;
66
				if(*p == '^' || *p == '\\')
67
					*w++ = '\\';
68
				*w++ = *p++;
69
			}
70
			*w++ = ']';
71
			boe = 0;
72
			continue;
73
		}
74
		if(strchr("()|^$[]*?+\\.", *p)){
75
			*w++ = '\\';
76
			*w++ = *p;
77
			boe = 0;
78
			continue;
79
		}
80
		if(*p == '/'){
81
			*w++ = '/';
82
			boe = 1;
83
			continue;
84
		}
85
		*w++ = *p;
86
		boe = 0;
87
		continue;
88
	}
89
	*w++ = ')';
90
	*w++ = '$';
91
	*w = 0;
92
 
93
	re = regcomp(s);
94
	if(re == nil){
95
	syntax:
96
		free(s);
97
		werrstr("glob syntax error");
98
		return nil;
99
	}
100
	free(s);
101
	return re;
102
}
103
 
104
typedef struct Pattern Pattern;
105
struct Pattern
106
{
107
	Reprog *re;
108
	int include;
109
};
110
 
111
Pattern *pattern;
112
int npattern;
113
 
114
void
115
loadexcludefile(char *file)
116
{
117
	Biobuf *b;
118
	char *p, *q;
119
	int n, inc;
120
	Reprog *re;
121
 
122
	if((b = Bopen(file, OREAD)) == nil)
123
		sysfatal("open %s: %r", file);
124
	for(n=1; (p=Brdstr(b, '\n', 1)) != nil; free(p), n++){
125
		q = p+strlen(p);
126
		while(q > p && isspace((uchar)*(q-1)))
127
			*--q = 0;
128
		switch(p[0]){
129
		case '\0':
130
		case '#':
131
			continue;
132
		}
133
 
134
		inc = 0;
135
		if(strncmp(p, "include ", 8) == 0){
136
			inc = 1;
137
		}else if(strncmp(p, "exclude ", 8) == 0){
138
			inc = 0;
139
		}else
140
			sysfatal("%s:%d: line does not begin with include or exclude", file, n);
141
 
142
		if(strchr(p+8, ' '))
143
			fprint(2, "%s:%d: warning: space in pattern\n", file, n);
144
 
145
		if((re = glob2regexp(p+8)) == nil)
146
			sysfatal("%s:%d: bad glob pattern", file, n);
147
 
148
		pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
149
		pattern[npattern].re = re;
150
		pattern[npattern].include = inc;
151
		npattern++;
152
	}
153
	Bterm(b);
154
}
155
 
156
void
157
excludepattern(char *p)
158
{
159
	Reprog *re;
160
 
161
	if((re = glob2regexp(p)) == nil)
162
		sysfatal("bad glob pattern %s", p);
163
 
164
	pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
165
	pattern[npattern].re = re;
166
	pattern[npattern].include = 0;
167
	npattern++;
168
}
169
 
170
int
171
includefile(char *file)
172
{
173
	Pattern *p, *ep;
174
 
175
	for(p=pattern, ep=p+npattern; p<ep; p++)
176
		if(regexec(p->re, file, nil, 0))
177
			return p->include;
178
	return 1;
179
}
180