Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / lib / libc / gen / fnmatch.c
CommitLineData
d4120dc2
KB
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Guido van Rossum.
7 *
af359dea
C
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
d4120dc2
KB
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
af359dea 38static char sccsid[] = "@(#)fnmatch.c 5.4 (Berkeley) 2/23/91";
d4120dc2
KB
39#endif /* LIBC_SCCS and not lint */
40
41/*
42 * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9).
43 * Compares a filename or pathname to a pattern.
44 */
45
46#include <unistd.h>
47#include <string.h>
48
49#define EOS '\0'
50
2a3f39bf
KB
51static char *
52rangematch(pattern, test)
53 register char *pattern, test;
54{
55 register char c, c2;
56 int negate, ok;
57
58 if (negate = (*pattern == '!'))
59 ++pattern;
60
61 /*
62 * TO DO: quoting
63 */
64
65 for (ok = 0; (c = *pattern++) != ']';) {
66 if (c == EOS)
67 return(NULL); /* illegal pattern */
68 if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') {
69 if (c <= test && test <= c2)
70 ok = 1;
71 pattern += 2;
72 }
73 else if (c == test)
74 ok = 1;
75 }
76 return(ok == negate ? NULL : pattern);
77}
78
d4120dc2 79fnmatch(pattern, string, flags)
c5980113
DS
80 register const char *pattern;
81 register const char *string;
d4120dc2
KB
82 int flags;
83{
84 register char c;
85 char test, *rangematch();
86
87 for (;;)
88 switch (c = *pattern++) {
89 case EOS:
90 return(*string == EOS);
91 case '?':
92 if ((test = *string++) == EOS ||
93 test == '/' && flags & FNM_PATHNAME)
94 return(0);
95 break;
96 case '*':
97 c = *pattern;
98 /* collapse multiple stars */
99 while (c == '*')
100 c = *++pattern;
101
102 /* optimize for pattern with * at end or before / */
103 if (c == EOS)
104 if (flags & FNM_PATHNAME)
105 return(!index(string, '/'));
106 else
107 return(1);
108 else if (c == '/' && flags & FNM_PATHNAME) {
109 if ((string = index(string, '/')) == NULL)
110 return(0);
111 break;
112 }
113
114 /* general case, use recursion */
115 while ((test = *string) != EOS) {
116 if (fnmatch(pattern, string, flags))
117 return(1);
118 if (test == '/' && flags & FNM_PATHNAME)
119 break;
120 ++string;
121 }
122 return(0);
123 case '[':
124 if ((test = *string++) == EOS ||
125 test == '/' && flags & FNM_PATHNAME)
126 return(0);
127 if ((pattern = rangematch(pattern, test)) == NULL)
128 return(0);
129 break;
130 case '\\':
131 if (flags & FNM_QUOTE) {
132 if ((c = *pattern++) == EOS) {
133 c = '\\';
134 --pattern;
135 }
136 if (c != *string++)
137 return(0);
138 break;
139 }
140 /* FALLTHROUGH */
141 default:
142 if (c != *string++)
143 return(0);
144 break;
145 }
146}