new copyright notice
[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)
269a7923 12static char sccsid[] = "@(#)fnmatch.c 5.2 (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
25fnmatch(pattern, string, flags)
26 register char *pattern, *string;
27 int flags;
28{
29 register char c;
30 char test, *rangematch();
31
32 for (;;)
33 switch (c = *pattern++) {
34 case EOS:
35 return(*string == EOS);
36 case '?':
37 if ((test = *string++) == EOS ||
38 test == '/' && flags & FNM_PATHNAME)
39 return(0);
40 break;
41 case '*':
42 c = *pattern;
43 /* collapse multiple stars */
44 while (c == '*')
45 c = *++pattern;
46
47 /* optimize for pattern with * at end or before / */
48 if (c == EOS)
49 if (flags & FNM_PATHNAME)
50 return(!index(string, '/'));
51 else
52 return(1);
53 else if (c == '/' && flags & FNM_PATHNAME) {
54 if ((string = index(string, '/')) == NULL)
55 return(0);
56 break;
57 }
58
59 /* general case, use recursion */
60 while ((test = *string) != EOS) {
61 if (fnmatch(pattern, string, flags))
62 return(1);
63 if (test == '/' && flags & FNM_PATHNAME)
64 break;
65 ++string;
66 }
67 return(0);
68 case '[':
69 if ((test = *string++) == EOS ||
70 test == '/' && flags & FNM_PATHNAME)
71 return(0);
72 if ((pattern = rangematch(pattern, test)) == NULL)
73 return(0);
74 break;
75 case '\\':
76 if (flags & FNM_QUOTE) {
77 if ((c = *pattern++) == EOS) {
78 c = '\\';
79 --pattern;
80 }
81 if (c != *string++)
82 return(0);
83 break;
84 }
85 /* FALLTHROUGH */
86 default:
87 if (c != *string++)
88 return(0);
89 break;
90 }
91}
92
93static char *
94rangematch(pattern, test)
95 register char *pattern, test;
96{
97 register char c, c2;
98 int negate, ok;
99
100 if (negate = (*pattern == '!'))
101 ++pattern;
102
103 /*
104 * TO DO: quoting
105 */
106
107 for (ok = 0; (c = *pattern++) != ']';) {
108 if (c == EOS)
109 return(NULL); /* illegal pattern */
110 if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') {
111 if (c <= test && test <= c2)
112 ok = 1;
113 pattern += 2;
114 }
115 else if (c == test)
116 ok = 1;
117 }
118 return(ok == negate ? NULL : pattern);
119}