glob.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "../wolfiphone.h"
  16. /* Like glob_match, but match PATTERN against any final segment of TEXT. */
  17. static int glob_match_after_star( char *pattern, char *text )
  18. {
  19. register char *p = pattern, *t = text;
  20. register char c, c1;
  21. while( (c = *p++) == '?' || c == '*' )
  22. {
  23. if( c == '?' && *t++ == '\0' )
  24. {
  25. return 0;
  26. }
  27. }
  28. if( c == '\0' )
  29. {
  30. return 1;
  31. }
  32. if( c == '\\' )
  33. {
  34. c1 = *p;
  35. }
  36. else
  37. {
  38. c1 = c;
  39. }
  40. while( 1 )
  41. {
  42. if( (c == '[' || *t == c1) && glob_match( p - 1, t ) )
  43. {
  44. return 1;
  45. }
  46. if( *t++ == '\0' )
  47. {
  48. return 0;
  49. }
  50. }
  51. }
  52. /* Return nonzero if PATTERN has any special globbing chars in it. */
  53. static int glob_pattern_p( char *pattern )
  54. {
  55. register char *p = pattern;
  56. register char c;
  57. int open = 0;
  58. while( (c = *p++) != '\0' )
  59. {
  60. switch( c )
  61. {
  62. case '?':
  63. case '*':
  64. return 1;
  65. case '[': /* Only accept an open brace if there is a close */
  66. open++; /* brace to match it. Bracket expressions must be */
  67. continue; /* complete, according to Posix.2 */
  68. case ']':
  69. if( open )
  70. {
  71. return 1;
  72. }
  73. continue;
  74. case '\\':
  75. if( *p++ == '\0' )
  76. {
  77. return 0;
  78. }
  79. }
  80. }
  81. return 0;
  82. }
  83. /* Match the pattern PATTERN against the string TEXT;
  84. return 1 if it matches, 0 otherwise.
  85. A match means the entire string TEXT is used up in matching.
  86. In the pattern string, `*' matches any sequence of characters,
  87. `?' matches any character, [SET] matches any character in the specified set,
  88. [!SET] matches any character not in the specified set.
  89. A set is composed of characters or ranges; a range looks like
  90. character hyphen character (as in 0-9 or A-Z).
  91. [0-9a-zA-Z_] is the set of characters allowed in C identifiers.
  92. Any other character in the pattern must be matched exactly.
  93. To suppress the special syntactic significance of any of `[]*?!-\',
  94. and match the character exactly, precede it with a `\'.
  95. */
  96. int glob_match(char *pattern, char *text)
  97. {
  98. register char *p = pattern, *t = text;
  99. register char c;
  100. while ((c = *p++) != '\0')
  101. switch (c) {
  102. case '?':
  103. if (*t == '\0')
  104. return 0;
  105. else
  106. ++t;
  107. break;
  108. case '\\':
  109. if (*p++ != *t++)
  110. return 0;
  111. break;
  112. case '*':
  113. return glob_match_after_star(p, t);
  114. case '[':
  115. {
  116. register char c1 = *t++;
  117. int invert;
  118. if (!c1)
  119. return (0);
  120. invert = ((*p == '!') || (*p == '^'));
  121. if (invert)
  122. p++;
  123. c = *p++;
  124. while (1) {
  125. register char cstart = c, cend = c;
  126. if (c == '\\') {
  127. cstart = *p++;
  128. cend = cstart;
  129. }
  130. if (c == '\0')
  131. return 0;
  132. c = *p++;
  133. if (c == '-' && *p != ']') {
  134. cend = *p++;
  135. if (cend == '\\')
  136. cend = *p++;
  137. if (cend == '\0')
  138. return 0;
  139. c = *p++;
  140. }
  141. if (c1 >= cstart && c1 <= cend)
  142. goto match;
  143. if (c == ']')
  144. break;
  145. }
  146. if (!invert)
  147. return 0;
  148. break;
  149. match:
  150. /* Skip the rest of the [...] construct that already matched. */
  151. while (c != ']') {
  152. if (c == '\0')
  153. return 0;
  154. c = *p++;
  155. if (c == '\0')
  156. return 0;
  157. else if (c == '\\')
  158. ++p;
  159. }
  160. if (invert)
  161. return 0;
  162. break;
  163. }
  164. default:
  165. if (c != *t++)
  166. return 0;
  167. }
  168. return *t == '\0';
  169. }