Changed the build rule for wildtest.
[rsync/rsync.git] / lib / wildmatch.c
CommitLineData
446ee5b1
WD
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**
7a1f46b6
WD
8** Modified by Wayne Davison to special-case '/' matching, to make '**'
9** work differently than '*', and to fix the character-class code.
446ee5b1
WD
10*/
11
12#include "rsync.h"
13
14/* What character marks an inverted character class? */
15#define NEGATE_CLASS '!'
16
710faea9
WD
17#define FALSE 0
18#define TRUE 1
19#define ABORT -1
446ee5b1 20
710faea9 21static int domatch(const char *p, const char *text)
446ee5b1
WD
22{
23 int matched, special;
24 char ch, prev;
25
26 for ( ; (ch = *p) != '\0'; text++, p++) {
27 if (*text == '\0' && ch != '*')
710faea9 28 return FALSE;
446ee5b1
WD
29 switch (ch) {
30 case '\\':
31 /* Literal match with following character. Note that the test
32 * in "default" handles the p[1] == '\0' failure case. */
33 ch = *++p;
34 /* FALLTHROUGH */
35 default:
36 if (*text != ch)
710faea9 37 return FALSE;
446ee5b1
WD
38 continue;
39 case '?':
40 /* Match anything but '/'. */
41 if (*text == '/')
710faea9 42 return FALSE;
446ee5b1
WD
43 continue;
44 case '*':
45 if (*++p == '*') {
46 while (*++p == '*') {}
710faea9 47 special = TRUE;
446ee5b1
WD
48 }
49 else
710faea9 50 special = FALSE;
446ee5b1 51 if (*p == '\0') {
710faea9
WD
52 /* Trailing "**" matches everything. Trailing "*" matches
53 * only if there are no more slash characters. */
54 return special? TRUE : strchr(text, '/') == 0;
446ee5b1
WD
55 }
56 for ( ; *text; text++) {
710faea9
WD
57 if ((matched = domatch(p, text)) != FALSE)
58 return matched;
446ee5b1 59 if (!special && *text == '/')
710faea9 60 return FALSE;
446ee5b1 61 }
710faea9 62 return ABORT;
446ee5b1 63 case '[':
710faea9 64 special = *++p == NEGATE_CLASS ? TRUE : FALSE;
446ee5b1
WD
65 if (special) {
66 /* Inverted character class. */
67 p++;
68 }
69 prev = 0;
710faea9 70 matched = FALSE;
446ee5b1
WD
71 ch = *p;
72 if (ch == ']' || ch == '-') {
73 if (*text == ch)
710faea9 74 matched = TRUE;
446ee5b1
WD
75 prev = ch;
76 ch = *++p;
77 }
78 for ( ; ch != ']'; prev = ch, ch = *++p) {
79 if (!ch)
710faea9 80 return FALSE;
446ee5b1
WD
81 if (ch == '-' && prev && p[1] && p[1] != ']') {
82 if (*text <= *++p && *text >= prev)
710faea9 83 matched = TRUE;
7a1f46b6 84 ch = 0; /* This makes "prev" get set to 0. */
446ee5b1
WD
85 }
86 else if (*text == ch)
710faea9 87 matched = TRUE;
446ee5b1
WD
88 }
89 if (matched == special)
710faea9 90 return FALSE;
446ee5b1
WD
91 continue;
92 }
93 }
94
95 return *text == '\0';
96}
710faea9
WD
97
98int wildmatch(const char *p, const char *text)
99{
100 return domatch(p, text) == TRUE;
101}