glob.c 3.3 KB

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