diff options
author | Russ Cox <rsc@swtch.com> | 2008-07-03 01:34:48 -0400 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2008-07-03 01:34:48 -0400 |
commit | e05b0ff3ebd8086809714527a27b412345ff4d72 (patch) | |
tree | 44dcf95f09055fb28e406a845b2d7fec4c3bd15b /src/cmd/vac/glob.c | |
parent | d9841dc7adc0ad99e56cf508d5d6b6d2e59afbb5 (diff) | |
download | plan9port-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.c | 180 |
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; +} + |