Blob


1 #include "stdinc.h"
2 #include "vac.h"
3 #include "dat.h"
4 #include "fns.h"
5 #include "error.h"
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 //
17 Reprog*
18 glob2regexp(char *glob)
19 {
20 char *s, *p, *w;
21 Reprog *re;
22 int boe; // beginning of path element
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;
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;
104 typedef struct Pattern Pattern;
105 struct Pattern
107 Reprog *re;
108 int include;
109 };
111 Pattern *pattern;
112 int npattern;
114 void
115 loadexcludefile(char *file)
117 Biobuf *b;
118 char *p, *q;
119 int n, inc;
120 Reprog *re;
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;
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);
142 if(strchr(p+8, ' '))
143 fprint(2, "%s:%d: warning: space in pattern\n", file, n);
145 if((re = glob2regexp(p+8)) == nil)
146 sysfatal("%s:%d: bad glob pattern", file, n);
148 pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
149 pattern[npattern].re = re;
150 pattern[npattern].include = inc;
151 npattern++;
153 Bterm(b);
156 void
157 excludepattern(char *p)
159 Reprog *re;
161 if((re = glob2regexp(p)) == nil)
162 sysfatal("bad glob pattern %s", p);
164 pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
165 pattern[npattern].re = re;
166 pattern[npattern].include = 0;
167 npattern++;
170 int
171 includefile(char *file)
173 Pattern *p, *ep;
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;