home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / me34src.zip / me3 / util / wildmat.c < prev   
C/C++ Source or Header  |  1995-01-14  |  5KB  |  212 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. **  Rich $alz is now <rsalz@bbn.com>.
  8. **  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
  9. **  This can greatly speed up failing wildcard patterns.  For example:
  10. **    pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
  11. **    text 1:     -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
  12. **    text 2:     -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
  13. **  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
  14. **  the ABORT, then it takes 22310 calls to fail.  Ugh.
  15. **
  16. **  C Durland added:
  17. **    MS-DOS uses \ for path, so do nothing for \ in that case.
  18. **    Put man page at the end of this file.
  19. */
  20.  
  21. #include "os.h"        /* only used for MSDOZ, ATARI --CD */
  22.  
  23. #define TRUE        1
  24. #define FALSE        0
  25. #define ABORT        -1
  26.  
  27. #define NEGATE_CLASS    '^'
  28.  
  29. /* Forward declaration. */
  30. static int    DoMatch();
  31.  
  32. /*
  33. **  See if the text matches the p, which has an implied leading asterisk.
  34. */
  35. static int
  36. Star(text, p)
  37.     register char    *text;
  38.     register char    *p;
  39. {
  40.     register int    ret;
  41.  
  42.     do
  43.     ret = DoMatch(text++, p);
  44.     while (ret == FALSE);
  45.     return ret;
  46. }
  47.  
  48.  
  49. /*
  50. **  Match text and p, return TRUE, FALSE, or ABORT.
  51. */
  52. static int
  53. DoMatch(text, p)
  54.     register char    *text;
  55.     register char    *p;
  56. {
  57.     register int      last;
  58.     register int      matched;
  59.     register int      reverse;
  60.  
  61.     for ( ; *p; text++, p++) {
  62.     if (*text == '\0' && *p != '*')
  63.         return ABORT;
  64.     switch (*p) {
  65. #if !(MSDOZ || ATARI)        /* blame those bozos at Microsoft */
  66.     case '\\':
  67.         /* Literal match with following character. */
  68.         p++;
  69.         /* FALLTHROUGH */
  70. #endif
  71.     default:
  72.         if (*text != *p)
  73.         return FALSE;
  74.         continue;
  75.     case '?':
  76.         /* Match anything. */
  77.         continue;
  78.     case '*':
  79.         /* Trailing star matches everything. */
  80.         return *++p ? Star(text, p) : TRUE;
  81.     case '[':
  82.         if (reverse = p[1] == NEGATE_CLASS)
  83.         /* Inverted character class. */
  84.         p++;
  85.         for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  86.         /* This next line requires a good C compiler. */
  87.         if (*p == '-' ? *text <= *++p && *text >= last : *text == *p)
  88.             matched = TRUE;
  89.         if (matched == reverse)
  90.         return FALSE;
  91.         continue;
  92.     }
  93.     }
  94.  
  95.     return *text == '\0';
  96. }
  97.  
  98.  
  99. /*
  100. **  User-level routine.  Returns TRUE or FALSE.
  101. */
  102. int
  103. wildmat(text, p)
  104.     char    *text;
  105.     char    *p;
  106. {
  107.     return DoMatch(text, p) == TRUE;
  108. }
  109.  
  110.  
  111.  
  112. #ifdef    TEST
  113. #include <stdio.h>
  114.  
  115. /* Yes, we use gets not fgets.  Sue me. */
  116. extern char    *gets();
  117.  
  118.  
  119. main()
  120. {
  121.     char     p[80];
  122.     char     text[80];
  123.  
  124.     printf("Wildmat tester.  Enter pattern, then strings to test.\n");
  125.     printf("A blank line gets prompts for a new pattern; a blank pattern\n");
  126.     printf("exits the program.\n\n");
  127.  
  128.     for ( ; ; ) {
  129.     printf("Enter pattern:  ");
  130.     (void)fflush(stdout);
  131.     if (gets(pattern) == NULL || pattern[0] == '\n')
  132.         break;
  133.     for ( ; ; ) {
  134.         printf("Enter text:  ");
  135.         (void)fflush(stdout);
  136.         if (gets(text) == NULL)
  137.         exit(0);
  138.         if (text[0] == '\0')
  139.         /* Blank line; go back and get a new pattern. */
  140.         break;
  141.         printf("      %s\n", wildmat(text, pattern) ? "YES" : "NO");
  142.     }
  143.     }
  144.  
  145.     exit(0);
  146.     /* NOTREACHED */
  147. }
  148. #endif    /* TEST */
  149.  
  150.  
  151.  
  152. #if 0        /* the man page */
  153.  
  154.  WILDMAT(3)                                                       WILDMAT(3)
  155.  
  156.  
  157.  NAME
  158.       wildmat - perform shell-style wildcard matching
  159.  
  160.  SYNOPSIS
  161.       int
  162.       wildmat(text, pattern)
  163.           char       *text;
  164.           char       *pattern;
  165.  
  166.  DESCRIPTION
  167.       Wildmat compares the text against the pattern and returns non-zero if
  168.       the pattern matches the text.  The pattern is interpreted similar to
  169.       shell filename wildcards, and not as a full regular expression such as
  170.       those handled by the grep(1) family of programs or the regex(3) or
  171.       regexp(3) set of routines.
  172.  
  173.       The pattern is interpreted according to the following rules:
  174.  
  175.       \x   Turns off the special meaning of x and matches it directly; this
  176.            is used mostly before a question mark or asterisk, and is not
  177.            valid inside square brackets.
  178.  
  179.       ?    Matches any single character.
  180.  
  181.       *    Matches any sequence of zero or more characters.
  182.  
  183.       [x...y]
  184.            Matches any single character specified by the set x...y, where
  185.            any character other than minus sign or close bracket may appear
  186.            in the set.  A minus sign may be used to indicate a range of
  187.            characters.  That is, [0-5abc] is a shorthand for [012345abc].
  188.            More than one range may appear inside a character set; [0-9a-zA-
  189.            Z._] matches almost all of the legal characters for a host name.
  190.  
  191.       [^x...y]
  192.            This matches any character not in the set x...y, which is
  193.            interpreted as described above.
  194.  
  195.  BUGS
  196.       There is no way to specify a minus sign in a character range.
  197.  
  198.  HISTORY
  199.       Written by Rich $alz <rsalz@bbn.com> in 1986, and posted to Usenet
  200.       several times since then, most notably in comp.sources.misc in March,
  201.       1991.
  202.       Lars Mathiesen <thorinn@diku.dk> enhanced the multi-asterisk failure
  203.       mode in early 1991.
  204.  
  205.  SEE ALSO
  206.       grep(1), regex(3), regexp(3).
  207.  
  208.  
  209.                                     - 1 -       Formatted:  January 17, 1992
  210.  
  211. #endif
  212.