vac: add -a and -x flags
Thanks to Michael Kaminsky for the suggestion.
This commit is contained in:
parent
d9841dc7ad
commit
e05b0ff3eb
11 changed files with 551 additions and 83 deletions
180
src/cmd/vac/glob.c
Normal file
180
src/cmd/vac/glob.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue