aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/vac/glob.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2008-07-03 01:34:48 -0400
committerRuss Cox <rsc@swtch.com>2008-07-03 01:34:48 -0400
commite05b0ff3ebd8086809714527a27b412345ff4d72 (patch)
tree44dcf95f09055fb28e406a845b2d7fec4c3bd15b /src/cmd/vac/glob.c
parentd9841dc7adc0ad99e56cf508d5d6b6d2e59afbb5 (diff)
downloadplan9port-e05b0ff3ebd8086809714527a27b412345ff4d72.tar.gz
plan9port-e05b0ff3ebd8086809714527a27b412345ff4d72.tar.bz2
plan9port-e05b0ff3ebd8086809714527a27b412345ff4d72.zip
vac: add -a and -x flags
Thanks to Michael Kaminsky for the suggestion.
Diffstat (limited to 'src/cmd/vac/glob.c')
-rw-r--r--src/cmd/vac/glob.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/cmd/vac/glob.c b/src/cmd/vac/glob.c
new file mode 100644
index 00000000..863eb848
--- /dev/null
+++ b/src/cmd/vac/glob.c
@@ -0,0 +1,180 @@
+#include "stdinc.h"
+#include "vac.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+// Convert globbish pattern to regular expression
+// The wildcards are
+//
+// * any non-slash characters
+// ... any characters including /
+// ? any single character except /
+// [a-z] character class
+// [~a-z] negated character class
+//
+
+Reprog*
+glob2regexp(char *glob)
+{
+ char *s, *p, *w;
+ Reprog *re;
+ int boe; // beginning of path element
+
+ s = malloc(20*(strlen(glob)+1));
+ if(s == nil)
+ return nil;
+ w = s;
+ boe = 1;
+ *w++ = '^';
+ *w++ = '(';
+ for(p=glob; *p; p++){
+ if(p[0] == '.' && p[1] == '.' && p[2] == '.'){
+ strcpy(w, ".*");
+ w += strlen(w);
+ p += 3-1;
+ boe = 0;
+ continue;
+ }
+ if(p[0] == '*'){
+ if(boe)
+ strcpy(w, "([^./][^/]*)?");
+ else
+ strcpy(w, "[^/]*");
+ w += strlen(w);
+ boe = 0;
+ continue;
+ }
+ if(p[0] == '?'){
+ if(boe)
+ strcpy(w, "[^./]");
+ else
+ strcpy(w, "[^/]");
+ w += strlen(w);
+ boe = 0;
+ continue;
+ }
+ if(p[0] == '['){
+ *w++ = '[';
+ if(*++p == '~'){
+ *w++ = '^';
+ p++;
+ }
+ while(*p != ']'){
+ if(*p == '/')
+ goto syntax;
+ if(*p == '^' || *p == '\\')
+ *w++ = '\\';
+ *w++ = *p++;
+ }
+ *w++ = ']';
+ boe = 0;
+ continue;
+ }
+ if(strchr("()|^$[]*?+\\.", *p)){
+ *w++ = '\\';
+ *w++ = *p;
+ boe = 0;
+ continue;
+ }
+ if(*p == '/'){
+ *w++ = '/';
+ boe = 1;
+ continue;
+ }
+ *w++ = *p;
+ boe = 0;
+ continue;
+ }
+ *w++ = ')';
+ *w++ = '$';
+ *w = 0;
+
+ re = regcomp(s);
+ if(re == nil){
+ syntax:
+ free(s);
+ werrstr("glob syntax error");
+ return nil;
+ }
+ free(s);
+ return re;
+}
+
+typedef struct Pattern Pattern;
+struct Pattern
+{
+ Reprog *re;
+ int include;
+};
+
+Pattern *pattern;
+int npattern;
+
+void
+loadexcludefile(char *file)
+{
+ Biobuf *b;
+ char *p, *q;
+ int n, inc;
+ Reprog *re;
+
+ if((b = Bopen(file, OREAD)) == nil)
+ sysfatal("open %s: %r", file);
+ for(n=1; (p=Brdstr(b, '\n', 1)) != nil; free(p), n++){
+ q = p+strlen(p);
+ while(q > p && isspace((uchar)*(q-1)))
+ *--q = 0;
+ switch(p[0]){
+ case '\0':
+ case '#':
+ continue;
+ }
+
+ inc = 0;
+ if(strncmp(p, "include ", 8) == 0){
+ inc = 1;
+ }else if(strncmp(p, "exclude ", 8) == 0){
+ inc = 0;
+ }else
+ sysfatal("%s:%d: line does not begin with include or exclude", file, n);
+
+ if(strchr(p+8, ' '))
+ fprint(2, "%s:%d: warning: space in pattern\n", file, n);
+
+ if((re = glob2regexp(p+8)) == nil)
+ sysfatal("%s:%d: bad glob pattern", file, n);
+
+ pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
+ pattern[npattern].re = re;
+ pattern[npattern].include = inc;
+ npattern++;
+ }
+ Bterm(b);
+}
+
+void
+excludepattern(char *p)
+{
+ Reprog *re;
+
+ if((re = glob2regexp(p)) == nil)
+ sysfatal("bad glob pattern %s", p);
+
+ pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
+ pattern[npattern].re = re;
+ pattern[npattern].include = 0;
+ npattern++;
+}
+
+int
+includefile(char *file)
+{
+ Pattern *p, *ep;
+
+ for(p=pattern, ep=p+npattern; p<ep; p++)
+ if(regexec(p->re, file, nil, 0))
+ return p->include;
+ return 1;
+}
+