home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / ils / wildmat.c < prev   
Encoding:
C/C++ Source or Header  |  1992-02-28  |  2.6 KB  |  122 lines

  1. /*
  2. **  Do shell-style pattern matching for ?, \, [], and * characters.
  3. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  4. **  could cause a segmentation violation.  It is 8bit clean.
  5. **
  6. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  7. **  Special thanks to Lars Mathiesen for the ABORT code.  This can greatly
  8. **  speed up failing wildcard patterns.  For example:
  9. **    pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
  10. **    text 1:     -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
  11. **    text 2:     -adobe-courier-bold-o-normal--12-120-75-75-p-70-iso8859-1
  12. **  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
  13. **  the ABORT, then it takes 22310 calls to fail.  Ugh.
  14. */
  15.  
  16. #define TRUE        1
  17. #define FALSE        0
  18. #define ABORT        -1
  19.  
  20. static int
  21. Star(s, p)
  22.     register char    *s;
  23.     register char    *p;
  24. {
  25.     while (wildmat(s, p) == FALSE)
  26.     if (*++s == '\0')
  27.         return ABORT;
  28.     return TRUE;
  29. }
  30.  
  31.  
  32. static int
  33. DoMatch(s, p)
  34.     register char    *s;
  35.     register char    *p;
  36. {
  37.     register int      last;
  38.     register int      matched;
  39.     register int      reverse;
  40.  
  41.     for ( ; *p; s++, p++) {
  42.     if (*s == '\0')
  43.         return ABORT;
  44.     switch (*p) {
  45.     case '\\':
  46.         /* Literal match with following character. */
  47.         p++;
  48.         /* FALLTHROUGH */
  49.     default:
  50.         if (*s != *p)
  51.         return FALSE;
  52.         continue;
  53.     case '?':
  54.         /* Match anything. */
  55.         continue;
  56.     case '*':
  57.         /* Trailing star matches everything. */
  58.         return *++p ? Star(s, p) : TRUE;
  59.     case '[':
  60.         /* [^....] means inverse character class. */
  61.         if (reverse = p[1] == '^')
  62.         p++;
  63.         for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  64.         /* This next line requires a good C compiler. */
  65.         if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
  66.             matched = TRUE;
  67.         if (matched == reverse)
  68.         return FALSE;
  69.         continue;
  70.     }
  71.     }
  72.  
  73.     return *s == '\0';
  74. }
  75.  
  76.  
  77. int
  78. wildmat(s, p)
  79.     char    *s;
  80.     char    *p;
  81. {
  82.     return DoMatch(s, p) == TRUE;
  83. }
  84.  
  85.  
  86.  
  87. #ifdef    TEST
  88. #include <stdio.h>
  89.  
  90. /* Yes, we use gets not fgets.  Sue me. */
  91. extern char    *gets();
  92.  
  93.  
  94. main()
  95. {
  96.     char     pattern[80];
  97.     char     text[80];
  98.  
  99.     printf("Wildmat tester.  Enter pattern, then strings to test.\n");
  100.     printf("A blank line gets prompts for a new pattern; a blank pattern\n");
  101.     printf("exits the program.\n\n");
  102.  
  103.     for ( ; ; ) {
  104.     printf("Enter pattern:  ");
  105.     if (gets(pattern) == NULL)
  106.         break;
  107.     for ( ; ; ) {
  108.         printf("Enter text:  ");
  109.         if (gets(text) == NULL)
  110.         exit(0);
  111.         if (text[0] == '\0')
  112.         /* Blank line; go back and get a new pattern. */
  113.         break;
  114.         printf("      %s\n", wildmat(text, pattern) ? "YES" : "NO");
  115.     }
  116.     }
  117.  
  118.     exit(0);
  119.     /* NOTREACHED */
  120. }
  121. #endif    /* TEST */
  122.