blob: 863eb848619be881ba23e577da0c7675eb9ed7d0 [file] [log] [blame]
#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;
}