match.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * match.c
  3. * wildcard matching functions
  4. *
  5. *
  6. * Once this code was working, I added support for % so that I could
  7. * use the same code both in Eggdrop and in my IrcII client.
  8. * Pleased with this, I added the option of a fourth wildcard, ~,
  9. * which matches varying amounts of whitespace (at LEAST one space,
  10. * though, for sanity reasons).
  11. *
  12. * This code would not have been possible without the prior work and
  13. * suggestions of various sourced. Special thanks to Robey for
  14. * all his time/help tracking down bugs and his ever-helpful advice.
  15. *
  16. * 04/09: Fixed the "*\*" against "*a" bug (caused an endless loop)
  17. *
  18. * Chris Fuller (aka Fred1@IRC & Fwitz@IRC)
  19. * crf@cfox.bchs.uh.edu
  20. *
  21. * I hereby release this code into the public domain
  22. *
  23. */
  24. #include "common.h"
  25. #include "match.h"
  26. #include "rfc1459.h"
  27. #define QUOTE '\\' /* quoting character (overrides wildcards) */
  28. #define WILDS '*' /* matches 0 or more characters (including spaces) */
  29. #define WILDP '%' /* matches 0 or more non-space characters */
  30. #define WILDQ '?' /* matches ecactly one character */
  31. #define WILDT '~' /* matches 1 or more spaces */
  32. #define NOMATCH 0
  33. #define MATCH (match+sofar)
  34. #define PERMATCH (match+saved+sofar)
  35. int wild_match_per(register char *m, register char *n)
  36. {
  37. /* null strings should never match */
  38. if ((m == 0) || (n == 0) || (!*n))
  39. return NOMATCH;
  40. char *ma = m, *lsm = NULL, *lsn = NULL, *lpm = NULL, *lpn = NULL;
  41. int match = 1, saved = 0, space;
  42. register int sofar = 0;
  43. while (*n) {
  44. if (*m == WILDT) { /* Match >=1 space */
  45. space = 0; /* Don't need any spaces */
  46. do {
  47. m++;
  48. space++;
  49. } /* Tally 1 more space ... */
  50. while ((*m == WILDT) || (*m == ' ')); /* for each space or ~ */
  51. sofar += space; /* Each counts as exact */
  52. while (*n == ' ') {
  53. n++;
  54. space--;
  55. } /* Do we have enough? */
  56. if (space <= 0)
  57. continue; /* Had enough spaces! */
  58. }
  59. /* Do the fallback */
  60. else {
  61. switch (*m) {
  62. case 0:
  63. do
  64. m--; /* Search backwards */
  65. while ((m > ma) && (*m == '?')); /* For first non-? char */
  66. if ((m > ma) ? ((*m == '*') && (m[-1] != QUOTE)) : (*m == '*'))
  67. return PERMATCH; /* nonquoted * = match */
  68. break;
  69. case WILDP:
  70. while (*(++m) == WILDP); /* Zap redundant %s */
  71. if (*m != WILDS) { /* Don't both if next=* */
  72. if (*n != ' ') { /* WILDS can't match ' ' */
  73. lpm = m;
  74. lpn = n; /* Save '%' fallback spot */
  75. saved += sofar;
  76. sofar = 0; /* And save tally count */
  77. }
  78. continue; /* Done with '%' */
  79. }
  80. /* FALL THROUGH */
  81. case WILDS:
  82. do
  83. m++; /* Zap redundant wilds */
  84. while ((*m == WILDS) || (*m == WILDP));
  85. lsm = m;
  86. lsn = n;
  87. lpm = 0; /* Save '*' fallback spot */
  88. match += (saved + sofar); /* Save tally count */
  89. saved = sofar = 0;
  90. continue; /* Done with '*' */
  91. case WILDQ:
  92. m++;
  93. n++;
  94. continue; /* Match one char */
  95. case QUOTE:
  96. m++; /* Handle quoting */
  97. }
  98. if (rfc_toupper(*m) == rfc_toupper(*n)) { /* If matching */
  99. m++;
  100. n++;
  101. sofar++;
  102. continue; /* Tally the match */
  103. }
  104. #ifdef WILDT
  105. }
  106. #endif
  107. if (lpm) { /* Try to fallback on '%' */
  108. n = ++lpn;
  109. m = lpm;
  110. sofar = 0; /* Restore position */
  111. if ((*n | 32) == 32)
  112. lpm = 0; /* Can't match 0 or ' ' */
  113. continue; /* Next char, please */
  114. }
  115. if (lsm) { /* Try to fallback on '*' */
  116. n = ++lsn;
  117. m = lsm; /* Restore position */
  118. saved = sofar = 0;
  119. continue; /* Next char, please */
  120. }
  121. return NOMATCH; /* No fallbacks=No match */
  122. }
  123. while ((*m == WILDS) || (*m == WILDP))
  124. m++; /* Zap leftover %s & *s */
  125. return (*m) ? NOMATCH : PERMATCH; /* End of both = match */
  126. }
  127. int wild_match(register char *m, register char *n)
  128. {
  129. char *ma = m, *na = n;
  130. /* null strings should never match */
  131. if ((ma == 0) || (na == 0) || (!*ma) || (!*na))
  132. return NOMATCH;
  133. char *lsm = NULL, *lsn = NULL;
  134. int match = 1;
  135. register int sofar = 0;
  136. /* find the end of each string */
  137. while (*(++m));
  138. m--;
  139. while (*(++n));
  140. n--;
  141. while (n >= na) {
  142. /* If the mask runs out of chars before the string, fall back on
  143. * a wildcard or fail. */
  144. if (m < ma) {
  145. if (lsm) {
  146. n = --lsn;
  147. m = lsm;
  148. if (n < na) lsm = 0;
  149. sofar = 0;
  150. }
  151. else return NOMATCH;
  152. }
  153. switch (*m) {
  154. case WILDS: /* Matches anything */
  155. do
  156. m--; /* Zap redundant wilds */
  157. while ((m >= ma) && (*m == WILDS));
  158. lsm = m;
  159. lsn = n;
  160. match += sofar;
  161. sofar = 0; /* Update fallback pos */
  162. if (m < ma) return MATCH;
  163. continue; /* Next char, please */
  164. case WILDQ:
  165. m--;
  166. n--;
  167. continue; /* '?' always matches */
  168. }
  169. if (rfc_toupper(*m) == rfc_toupper(*n)) { /* If matching char */
  170. m--;
  171. n--;
  172. sofar++; /* Tally the match */
  173. continue; /* Next char, please */
  174. }
  175. if (lsm) { /* To to fallback on '*' */
  176. n = --lsn;
  177. m = lsm;
  178. if (n < na)
  179. lsm = 0; /* Rewind to saved pos */
  180. sofar = 0;
  181. continue; /* Next char, please */
  182. }
  183. return NOMATCH; /* No fallback=No match */
  184. }
  185. while ((m >= ma) && (*m == WILDS))
  186. m--; /* Zap leftover %s & *s */
  187. return (m >= ma) ? NOMATCH : MATCH; /* Start of both = match */
  188. }