plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

glob.c (2991B)


      1 #include "stdinc.h"
      2 #include "vac.h"
      3 #include "dat.h"
      4 #include "fns.h"
      5 #include "error.h"
      6 
      7 // Convert globbish pattern to regular expression
      8 // The wildcards are
      9 //
     10 //	*	any non-slash characters
     11 //	...	any characters including /
     12 //	?	any single character except /
     13 //	[a-z]	character class
     14 //	[~a-z]	negated character class
     15 //
     16 
     17 Reprog*
     18 glob2regexp(char *glob)
     19 {
     20 	char *s, *p, *w;
     21 	Reprog *re;
     22 	int boe;	// beginning of path element
     23 
     24 	s = malloc(20*(strlen(glob)+1));
     25 	if(s == nil)
     26 		return nil;
     27 	w = s;
     28 	boe = 1;
     29 	*w++ = '^';
     30 	*w++ = '(';
     31 	for(p=glob; *p; p++){
     32 		if(p[0] == '.' && p[1] == '.' && p[2] == '.'){
     33 			strcpy(w, ".*");
     34 			w += strlen(w);
     35 			p += 3-1;
     36 			boe = 0;
     37 			continue;
     38 		}
     39 		if(p[0] == '*'){
     40 			if(boe)
     41 				strcpy(w, "([^./][^/]*)?");
     42 			else
     43 				strcpy(w, "[^/]*");
     44 			w += strlen(w);
     45 			boe = 0;
     46 			continue;
     47 		}
     48 		if(p[0] == '?'){
     49 			if(boe)
     50 				strcpy(w, "[^./]");
     51 			else
     52 				strcpy(w, "[^/]");
     53 			w += strlen(w);
     54 			boe = 0;
     55 			continue;
     56 		}
     57 		if(p[0] == '['){
     58 			*w++ = '[';
     59 			if(*++p == '~'){
     60 				*w++ = '^';
     61 				p++;
     62 			}
     63 			while(*p != ']'){
     64 				if(*p == '/')
     65 					goto syntax;
     66 				if(*p == '^' || *p == '\\')
     67 					*w++ = '\\';
     68 				*w++ = *p++;
     69 			}
     70 			*w++ = ']';
     71 			boe = 0;
     72 			continue;
     73 		}
     74 		if(strchr("()|^$[]*?+\\.", *p)){
     75 			*w++ = '\\';
     76 			*w++ = *p;
     77 			boe = 0;
     78 			continue;
     79 		}
     80 		if(*p == '/'){
     81 			*w++ = '/';
     82 			boe = 1;
     83 			continue;
     84 		}
     85 		*w++ = *p;
     86 		boe = 0;
     87 		continue;
     88 	}
     89 	*w++ = ')';
     90 	*w++ = '$';
     91 	*w = 0;
     92 
     93 	re = regcomp(s);
     94 	if(re == nil){
     95 	syntax:
     96 		free(s);
     97 		werrstr("glob syntax error");
     98 		return nil;
     99 	}
    100 	free(s);
    101 	return re;
    102 }
    103 
    104 typedef struct Pattern Pattern;
    105 struct Pattern
    106 {
    107 	Reprog *re;
    108 	int include;
    109 };
    110 
    111 Pattern *pattern;
    112 int npattern;
    113 
    114 void
    115 loadexcludefile(char *file)
    116 {
    117 	Biobuf *b;
    118 	char *p, *q;
    119 	int n, inc;
    120 	Reprog *re;
    121 
    122 	if((b = Bopen(file, OREAD)) == nil)
    123 		sysfatal("open %s: %r", file);
    124 	for(n=1; (p=Brdstr(b, '\n', 1)) != nil; free(p), n++){
    125 		q = p+strlen(p);
    126 		while(q > p && isspace((uchar)*(q-1)))
    127 			*--q = 0;
    128 		switch(p[0]){
    129 		case '\0':
    130 		case '#':
    131 			continue;
    132 		}
    133 
    134 		inc = 0;
    135 		if(strncmp(p, "include ", 8) == 0){
    136 			inc = 1;
    137 		}else if(strncmp(p, "exclude ", 8) == 0){
    138 			inc = 0;
    139 		}else
    140 			sysfatal("%s:%d: line does not begin with include or exclude", file, n);
    141 
    142 		if(strchr(p+8, ' '))
    143 			fprint(2, "%s:%d: warning: space in pattern\n", file, n);
    144 
    145 		if((re = glob2regexp(p+8)) == nil)
    146 			sysfatal("%s:%d: bad glob pattern", file, n);
    147 
    148 		pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
    149 		pattern[npattern].re = re;
    150 		pattern[npattern].include = inc;
    151 		npattern++;
    152 	}
    153 	Bterm(b);
    154 }
    155 
    156 void
    157 excludepattern(char *p)
    158 {
    159 	Reprog *re;
    160 
    161 	if((re = glob2regexp(p)) == nil)
    162 		sysfatal("bad glob pattern %s", p);
    163 
    164 	pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);
    165 	pattern[npattern].re = re;
    166 	pattern[npattern].include = 0;
    167 	npattern++;
    168 }
    169 
    170 int
    171 includefile(char *file)
    172 {
    173 	Pattern *p, *ep;
    174 
    175 	for(p=pattern, ep=p+npattern; p<ep; p++)
    176 		if(regexec(p->re, file, nil, 0))
    177 			return p->include;
    178 	return 1;
    179 }