diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/vac/glob.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vac/glob.c')
-rwxr-xr-x | sys/src/cmd/vac/glob.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/sys/src/cmd/vac/glob.c b/sys/src/cmd/vac/glob.c new file mode 100755 index 000000000..863eb8486 --- /dev/null +++ b/sys/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; +} + |