s/qmail 4.2.29a
Next generation secure email transport
Loading...
Searching...
No Matches
wildmat.c
Go to the documentation of this file.
1/*** wildmat.c.orig Wed Dec 3 11:46:31 1997 */
2/* $Revision: 1.1 $
3**
4** Do shell-style pattern matching for ?, \, [], and * characters.
5** Might not be robust in face of malformed patterns; e.g., "foo[a-"
6** could cause a segmentation violation. It is 8bit clean.
7**
8** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
9** Rich $alz is now <rsalz@osf.org>.
10** April, 1991: Replaced mutually-recursive calls with in-line code
11** for the star character.
12**
13** Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
14** This can greatly speed up failing wildcard patterns. For example:
15** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
16** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
17** text 2: -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
18** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without
19** the ABORT code, it takes 22310 calls to fail. Ugh. The following
20** explanation is from Lars:
21** The precondition that must be fulfilled is that DoMatch will consume
22** at least one character in text. This is true if *p is neither '*' nor
23** '\0'.) The last return has ABORT instead of FALSE to avoid quadratic
24** behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx". With
25** FALSE, each star-loop has to run to the end of the text; with ABORT
26** only the last one does.
27**
28** Once the control of one instance of DoMatch enters the star-loop, that
29** instance will return either TRUE or ABORT, and any calling instance
30** will therefore return immediately after (without calling recursively
31** again). In effect, only one star-loop is ever active. It would be
32** possible to modify the code to maintain this context explicitly,
33** eliminating all recursive calls at the cost of some complication and
34** loss of clarity (and the ABORT stuff seems to be unclear enough by
35** itself). I think it would be unwise to try to get this into a
36** released version unless you have a good test data base to try it out
37** on.
38*/
39
40#define TRUE 1
41#define FALSE 0
42#define ABORT -1
43
44/* What character marks an inverted character class? */
45#define NEGATE_CLASS '^'
46/* Is "*" a common pattern? */
47#define OPTIMIZE_JUST_STAR
48/* Do tar(1) matching rules, which ignore a trailing slash? */
49#undef MATCH_TAR_PATTERN
50
51/*
52** Match text and p, return TRUE, FALSE, or ABORT.
53*/
54static int DoMatch(register char *text, register char *p)
55{
56 register int last;
57 register int matched;
58 register int reverse;
59
60 for (; *p; text++, p++) {
61 if (*text == '\0' && *p != '*')
62 return ABORT;
63 switch (*p) {
64 case '\\': /* Literal match with following character. */
65 p++;
66 case '?': /* Match anything. */
67 continue;
68 case '*': /* Consecutive stars act just like one. */
69 while (*++p == '*')
70 continue;
71 if (*p == '\0') return TRUE; /* Trailing star matches everything. */
72 while (*text)
73 if ((matched = DoMatch(text++, p)) != FALSE) return matched;
74 return ABORT;
75 case '[':
76 reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
77 if (reverse) p++; /* Inverted character class. */
78 matched = FALSE;
79 if (p[1] == ']' || p[1] == '-')
80 if (*++p == *text) matched = TRUE;
81 for (last = *p; *++p && *p != ']'; last = *p) /* This next line requires a good C compiler. */
82 if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p)
83 matched = TRUE;
84 if (matched == reverse) return FALSE;
85 continue;
86 default: /* FALLTHROUGH */
87 if (*text != *p) return FALSE;
88 continue;
89 }
90 }
91
92#ifdef MATCH_TAR_PATTERN
93 if (*text == '/')
94 return TRUE;
95#endif /* MATCH_TAR_ATTERN */
96 return *text == '\0';
97}
98
99/*
100** User-level routine. Returns TRUE or FALSE.
101*/
102int wildmat(char *text,char *p)
103{
104#ifdef OPTIMIZE_JUST_STAR
105 if (p[0] == '*' && p[1] == '\0')
106 return TRUE;
107#endif /* OPTIMIZE_JUST_STAR */
108 return DoMatch(text, p) == TRUE;
109}
void p(char *, char *, int, int, int)
Definition: install.c:39
stralloc text
Definition: maildirwatch.c:21
int last
Definition: qmail-pop3d.c:125
#define NEGATE_CLASS
Definition: wildmat.c:45
int wildmat(char *text, char *p)
Definition: wildmat.c:102
#define ABORT
Definition: wildmat.c:42
#define TRUE
Definition: wildmat.c:40
#define FALSE
Definition: wildmat.c:41