wildmat.c
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:5k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /*  $Revision: 1.1 $
  2. **
  3. **  Do shell-style pattern matching for ?, , [], and * characters.
  4. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  5. **  could cause a segmentation violation.  It is 8bit clean.
  6. **
  7. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  8. **  Rich $alz is now <rsalz@osf.org>.
  9. **  April, 1991:  Replaced mutually-recursive calls with in-line code
  10. **  for the star character.
  11. **
  12. **  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
  13. **  This can greatly speed up failing wildcard patterns.  For example:
  14. ** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
  15. ** text 1:  -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
  16. ** text 2:  -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
  17. **  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
  18. **  the ABORT code, it takes 22310 calls to fail.  Ugh.  The following
  19. **  explanation is from Lars:
  20. **  The precondition that must be fulfilled is that DoMatch will consume
  21. **  at least one character in text.  This is true if *p is neither '*' nor
  22. **  ''.)  The last return has ABORT instead of FALSE to avoid quadratic
  23. **  behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx".  With
  24. **  FALSE, each star-loop has to run to the end of the text; with ABORT
  25. **  only the last one does.
  26. **
  27. **  Once the control of one instance of DoMatch enters the star-loop, that
  28. **  instance will return either TRUE or ABORT, and any calling instance
  29. **  will therefore return immediately after (without calling recursively
  30. **  again).  In effect, only one star-loop is ever active.  It would be
  31. **  possible to modify the code to maintain this context explicitly,
  32. **  eliminating all recursive calls at the cost of some complication and
  33. **  loss of clarity (and the ABORT stuff seems to be unclear enough by
  34. **  itself).  I think it would be unwise to try to get this into a
  35. **  released version unless you have a good test data base to try it out
  36. **  on.
  37. */
  38. #define TRUE 1
  39. #define FALSE 0
  40. #define ABORT -1
  41.  /* What character marks an inverted character class? */
  42. #define NEGATE_CLASS '^'
  43.  /* Is "*" a common pattern? */
  44. #define OPTIMIZE_JUST_STAR
  45.  /* Do tar(1) matching rules, which ignore a trailing slash? */
  46. #undef MATCH_TAR_PATTERN
  47. /*
  48. **  Match text and p, return TRUE, FALSE, or ABORT.
  49. */
  50. static int
  51. DoMatch(text, p)
  52. register char *text;
  53. register char *p;
  54. {
  55. register int last;
  56. register int matched;
  57. register int reverse;
  58. for (; *p; text++, p++) {
  59. if (*text == '' && *p != '*')
  60. return ABORT;
  61. switch (*p) {
  62. case '\':
  63. /* Literal match with following character. */
  64. p++;
  65. /* FALLTHROUGH */
  66. default:
  67. if (*text != *p)
  68. return FALSE;
  69. continue;
  70. case '?':
  71. /* Match anything. */
  72. continue;
  73. case '*':
  74. while (*++p == '*')
  75. /* Consecutive stars act just like one. */
  76. continue;
  77. if (*p == '')
  78. /* Trailing star matches everything. */
  79. return TRUE;
  80. while (*text)
  81. if ((matched = DoMatch(text++, p)) != FALSE)
  82. return matched;
  83. return ABORT;
  84. case '[':
  85. reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
  86. if (reverse)
  87. /* Inverted character class. */
  88. p++;
  89. matched = FALSE;
  90. if (p[1] == ']' || p[1] == '-')
  91. if (*++p == *text)
  92. matched = TRUE;
  93. for (last = *p; *++p && *p != ']'; last = *p)
  94. /* This next line requires a good C compiler. */
  95. if (*p == '-' && p[1] != ']'
  96. ? *text <= *++p && *text >= last : *text == *p)
  97. matched = TRUE;
  98. if (matched == reverse)
  99. return FALSE;
  100. continue;
  101. }
  102. }
  103. #ifdef MATCH_TAR_PATTERN
  104. if (*text == '/')
  105. return TRUE;
  106. #endif /* MATCH_TAR_ATTERN */
  107. return *text == '';
  108. }
  109. /*
  110. **  User-level routine.  Returns TRUE or FALSE.
  111. */
  112. int
  113. wildmat(text, p)
  114. char   *text;
  115. char   *p;
  116. {
  117. #ifdef OPTIMIZE_JUST_STAR
  118. if (p[0] == '*' && p[1] == '')
  119. return TRUE;
  120. #endif /* OPTIMIZE_JUST_STAR */
  121. return DoMatch(text, p) == TRUE;
  122. }
  123. #if defined(TEST)
  124. #include <stdio.h>
  125. int
  126. main()
  127. {
  128. char    p[80];
  129. char    text[80];
  130. printf("Wildmat tester.  Enter pattern, then strings to test.n");
  131. printf("A blank line gets prompts for a new pattern; a blank patternn");
  132. printf("exits the program.n");
  133. for (;;) {
  134. printf("nEnter pattern:  ");
  135. (void) fflush(stdout);
  136. if (fgets(p,80,stdin) == NULL || p[0] == '')
  137. break;
  138. else {
  139. p[79] = 0;
  140. p[strlen(p)-1] = 0;
  141. }
  142.   for (;;) {
  143. printf("Enter text:  ");
  144. (void) fflush(stdout);
  145. if (fgets(text,80,stdin) == NULL)
  146. exit(0);
  147. text[79] = '';
  148. text[strlen(text)-1] = 0;
  149. if (text[0] == '')
  150. /* Blank line; go back and get a new pattern. */
  151. break;
  152. printf("      %sn", wildmat(text, p) ? "YES" : "NO");
  153. }
  154. }
  155. exit(0);
  156. /* NOTREACHED */
  157. }
  158. #endif /* defined(TEST) */