189 lines · 3.3 KB · C
RawDownload
/*  * 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;}