Blob
1 #include "stdinc.h"2 #include "vac.h"3 #include "dat.h"4 #include "fns.h"5 #include "error.h"7 // Convert globbish pattern to regular expression8 // The wildcards are9 //10 // * any non-slash characters11 // ... any characters including /12 // ? any single character except /13 // [a-z] character class14 // [~a-z] negated character class15 //17 Reprog*18 glob2regexp(char *glob)19 {20 char *s, *p, *w;21 Reprog *re;22 int boe; // beginning of path element24 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 else43 strcpy(w, "[^/]*");44 w += strlen(w);45 boe = 0;46 continue;47 }48 if(p[0] == '?'){49 if(boe)50 strcpy(w, "[^./]");51 else52 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;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 }104 typedef struct Pattern Pattern;105 struct Pattern106 {107 Reprog *re;108 int include;109 };111 Pattern *pattern;112 int npattern;114 void115 loadexcludefile(char *file)116 {117 Biobuf *b;118 char *p, *q;119 int n, inc;120 Reprog *re;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 }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 }else140 sysfatal("%s:%d: line does not begin with include or exclude", file, n);142 if(strchr(p+8, ' '))143 fprint(2, "%s:%d: warning: space in pattern\n", file, n);145 if((re = glob2regexp(p+8)) == nil)146 sysfatal("%s:%d: bad glob pattern", file, n);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 }156 void157 excludepattern(char *p)158 {159 Reprog *re;161 if((re = glob2regexp(p)) == nil)162 sysfatal("bad glob pattern %s", p);164 pattern = vtrealloc(pattern, (npattern+1)*sizeof pattern[0]);165 pattern[npattern].re = re;166 pattern[npattern].include = 0;167 npattern++;168 }170 int171 includefile(char *file)172 {173 Pattern *p, *ep;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 }