wildmat.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:4k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /*
  2.  * @(#)wildmat.c 1.3 87/11/06 Public Domain.
  3.  *
  4. From: rs@mirror.TMC.COM (Rich Salz)
  5. Newsgroups: net.sources
  6. Subject: Small shell-style pattern matcher
  7. Message-ID: <596@mirror.TMC.COM>
  8. Date: 27 Nov 86 00:06:40 GMT
  9. There have been several regular-expression subroutines and one or two
  10. filename-globbing routines in mod.sources.  They handle lots of
  11. complicated patterns.  This small piece of code handles the *?[]
  12. wildcard characters the way the standard Unix(tm) shells do, with the
  13. addition that "[^.....]" is an inverse character class -- it matches
  14. any character not in the range ".....".  Read the comments for more
  15. info.
  16. For my application, I had first ripped off a copy of the "glob" routine
  17. from within the find(1) source, but that code is bad news:  it recurses
  18. on every character in the pattern.  I'm putting this replacement in the
  19. public domain.  It's small, tight, and iterative.  Compile with -DTEST
  20. to get a test driver.  After you're convinced it works, install in
  21. whatever way is appropriate for you.
  22. I would like to hear of bugs, but am not interested in additions; if I
  23. were, I'd use the code I mentioned above.
  24. */
  25. /*
  26. **  Do shell-style pattern matching for ?, , [], and * characters.
  27. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  28. **  could cause a segmentation violation.
  29. **
  30. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  31. */
  32. /*
  33.  * Modified 6Nov87 by John Gilmore (hoptoad!gnu) to return a "match"
  34.  * if the pattern is immediately followed by a "/", as well as .
  35.  * This matches what "tar" does for matching whole subdirectories.
  36.  *
  37.  * The "*" code could be sped up by only recursing one level instead
  38.  * of two for each trial pattern, perhaps, and not recursing at all
  39.  * if a literal match of the next 2 chars would fail.
  40.  */
  41. /* Modified by Anders Klemets to take an array of pointers as an optional
  42.    argument. Each part of the string that matches '*' is returned as a
  43.    null-terminated, malloced string in this array.
  44.  */
  45. #include "global.h"
  46. static int Star(char *s,char *p,char **argv);
  47. static int
  48. Star(s,p,argv)
  49. register char *s;
  50. register char *p;
  51. register char **argv;
  52. {
  53. char *cp = s;
  54. while (wildmat(cp, p, argv) == FALSE)
  55. if(*++cp == '')
  56. return -1;
  57. return cp - s;
  58. }
  59. int
  60. wildmat(s,p,argv)
  61. register char *s;
  62. register char *p;
  63. register char **argv;
  64. {
  65. register int last;
  66. register int matched;
  67. register int reverse;
  68. register int cnt;
  69. for(; *p; s++,p++){
  70. switch(*p){
  71. case '\':
  72. /* Literal match with following character; fall through. */
  73. p++;
  74. default:
  75. if(*s != *p)
  76. return FALSE;
  77. continue;
  78. case '?':
  79. /* Match anything. */
  80. if(*s == '')
  81. return FALSE;
  82. continue;
  83. case '*':
  84. /* Trailing star matches everything. */
  85. if(argv == NULL)
  86. return *++p ? 1 + Star(s, p, NULL) : TRUE;
  87. if(*++p == ''){
  88. cnt = strlen(s);
  89. } else {
  90. if((cnt = Star(s, p, argv+1)) == -1)
  91. return FALSE;
  92. }
  93. *argv = mallocw(cnt+1);
  94. strncpy(*argv,s,cnt);
  95. *(*argv + cnt) = '';
  96. return TRUE;
  97. case '[':
  98. /* [^....] means inverse character class. */
  99. reverse = (p[1] == '^') ? TRUE : FALSE;
  100. if(reverse)
  101. p++;
  102. for(last = 0400, matched = FALSE; *++p && *p != ']'; last = *p){
  103. /* This next line requires a good C compiler. */
  104. if(*p == '-' ? *s <= *++p && *s >= last : *s == *p)
  105. matched = TRUE;
  106. }
  107. if(matched == reverse)
  108. return FALSE;
  109. continue;
  110. }
  111. }
  112. /* For "tar" use, matches that end at a slash also work. --hoptoad!gnu */
  113. return *s == '' || *s == '/';
  114. }
  115. #ifdef TEST
  116. #include <stdio.h>
  117. extern char *gets();
  118. main()
  119. {
  120. char pattern[80];
  121. char text[80];
  122. char *argv[80], *cp;
  123. int cnt;
  124.     
  125. while (TRUE){
  126. printf("Enter pattern:  ");
  127. if(gets(pattern) == NULL)
  128. break;
  129. while (TRUE){
  130. bzero(argv,80*sizeof(char *);
  131. printf("Enter text:  ");
  132. if(gets(text) == NULL)
  133. exit(0);
  134. if(text[0] == '')
  135. /* Blank line; go back and get a new pattern. */
  136. break;
  137. printf("      %dn", wildmat(text, pattern, argv);
  138. for(cnt = 0; argv[cnt] != NULL; ++cnt){
  139. printf("String %d is: '%s'n",cnt,argv[cnt]);
  140. free(argv[cnt]);
  141. }
  142. }
  143. }
  144. exit(0);
  145. }
  146. #endif /* TEST */