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