#define root and root's parent fts_level values in <fts.h>
[unix-history] / 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 *
269a7923 8 * %sccs.include.redist.c%
d4120dc2
KB
9 */
10
11#if defined(LIBC_SCCS) && !defined(lint)
c5980113 12static char sccsid[] = "@(#)fnmatch.c 5.4 (Berkeley) %G%";
d4120dc2
KB
13#endif /* LIBC_SCCS and not lint */
14
15/*
16 * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9).
17 * Compares a filename or pathname to a pattern.
18 */
19
20#include <unistd.h>
21#include <string.h>
22
23#define EOS '\0'
24
2a3f39bf
KB
25static char *
26rangematch(pattern, test)
27 register char *pattern, test;
28{
29 register char c, c2;
30 int negate, ok;
31
32 if (negate = (*pattern == '!'))
33 ++pattern;
34
35 /*
36 * TO DO: quoting
37 */
38
39 for (ok = 0; (c = *pattern++) != ']';) {
40 if (c == EOS)
41 return(NULL); /* illegal pattern */
42 if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') {
43 if (c <= test && test <= c2)
44 ok = 1;
45 pattern += 2;
46 }
47 else if (c == test)
48 ok = 1;
49 }
50 return(ok == negate ? NULL : pattern);
51}
52
d4120dc2 53fnmatch(pattern, string, flags)
c5980113
DS
54 register const char *pattern;
55 register const char *string;
d4120dc2
KB
56 int flags;
57{
58 register char c;
59 char test, *rangematch();
60
61 for (;;)
62 switch (c = *pattern++) {
63 case EOS:
64 return(*string == EOS);
65 case '?':
66 if ((test = *string++) == EOS ||
67 test == '/' && flags & FNM_PATHNAME)
68 return(0);
69 break;
70 case '*':
71 c = *pattern;
72 /* collapse multiple stars */
73 while (c == '*')
74 c = *++pattern;
75
76 /* optimize for pattern with * at end or before / */
77 if (c == EOS)
78 if (flags & FNM_PATHNAME)
79 return(!index(string, '/'));
80 else
81 return(1);
82 else if (c == '/' && flags & FNM_PATHNAME) {
83 if ((string = index(string, '/')) == NULL)
84 return(0);
85 break;
86 }
87
88 /* general case, use recursion */
89 while ((test = *string) != EOS) {
90 if (fnmatch(pattern, string, flags))
91 return(1);
92 if (test == '/' && flags & FNM_PATHNAME)
93 break;
94 ++string;
95 }
96 return(0);
97 case '[':
98 if ((test = *string++) == EOS ||
99 test == '/' && flags & FNM_PATHNAME)
100 return(0);
101 if ((pattern = rangematch(pattern, test)) == NULL)
102 return(0);
103 break;
104 case '\\':
105 if (flags & FNM_QUOTE) {
106 if ((c = *pattern++) == EOS) {
107 c = '\\';
108 --pattern;
109 }
110 if (c != *string++)
111 return(0);
112 break;
113 }
114 /* FALLTHROUGH */
115 default:
116 if (c != *string++)
117 return(0);
118 break;
119 }
120}