/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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; voidloadexcludefile(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);} voidexcludepattern(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++;} intincludefile(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;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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;
}