A couple comment tweaks.
[rsync/rsync.git] / lib / wildmatch.c
1 /*
2 **  Do shell-style pattern matching for ?, \, [], and * characters.
3 **  It is 8bit clean.
4 **
5 **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
6 **  Rich $alz is now <rsalz@bbn.com>.
7 **
8 **  Modified by Wayne Davison to special-case '/' matching, to make '**'
9 **  work differently than '*', and to fix the character-class code.
10 */
11
12 #include "rsync.h"
13
14 /* What character marks an inverted character class? */
15 #define NEGATE_CLASS '!'
16
17 #define false 0
18 #define true 1
19
20 /* Look for pattern "p" in the "text" string. */
21 int
22 wildmatch(const char *p, const char *text)
23 {
24     int matched, special;
25     char ch, prev;
26
27     for ( ; (ch = *p) != '\0'; text++, p++) {
28         if (*text == '\0' && ch != '*')
29             return false;
30         switch (ch) {
31           case '\\':
32             /* Literal match with following character.  Note that the test
33              * in "default" handles the p[1] == '\0' failure case. */
34             ch = *++p;
35             /* FALLTHROUGH */
36           default:
37             if (*text != ch)
38                 return false;
39             continue;
40           case '?':
41             /* Match anything but '/'. */
42             if (*text == '/')
43                 return false;
44             continue;
45           case '*':
46             if (*++p == '*') {
47                 while (*++p == '*') {}
48                 special = true;
49             }
50             else
51                 special = false;
52             if (*p == '\0') {
53                 /* Trailing "**" matches everything. */
54                 return special? true : strchr(text, '/') == 0;
55             }
56             for ( ; *text; text++) {
57                 if (wildmatch(p, text))
58                     return true;
59                 if (!special && *text == '/')
60                     return false;
61             }
62             return false;
63           case '[':
64             special = *++p == NEGATE_CLASS ? true : false;
65             if (special) {
66                 /* Inverted character class. */
67                 p++;
68             }
69             prev = 0;
70             matched = false;
71             ch = *p;
72             if (ch == ']' || ch == '-') {
73                 if (*text == ch)
74                     matched = true;
75                 prev = ch;
76                 ch = *++p;
77             }
78             for ( ; ch != ']'; prev = ch, ch = *++p) {
79                 if (!ch)
80                     return false;
81                 if (ch == '-' && prev && p[1] && p[1] != ']') {
82                     if (*text <= *++p && *text >= prev)
83                         matched = true;
84                     ch = 0; /* This makes "prev" get set to 0. */
85                 }
86                 else if (*text == ch)
87                     matched = true;
88             }
89             if (matched == special)
90                 return false;
91             continue;
92         }
93     }
94
95     return *text == '\0';
96 }