| #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; |
| } |
| |