Make unvis() have more reasonable argument types.
[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)
2a3f39bf 12static char sccsid[] = "@(#)fnmatch.c 5.3 (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
KB
53fnmatch(pattern, string, flags)
54 register char *pattern, *string;
55 int flags;
56{
57 register char c;
58 char test, *rangematch();
59
60 for (;;)
61 switch (c = *pattern++) {
62 case EOS:
63 return(*string == EOS);
64 case '?':
65 if ((test = *string++) == EOS ||
66 test == '/' && flags & FNM_PATHNAME)
67 return(0);
68 break;
69 case '*':
70 c = *pattern;
71 /* collapse multiple stars */
72 while (c == '*')
73 c = *++pattern;
74
75 /* optimize for pattern with * at end or before / */
76 if (c == EOS)
77 if (flags & FNM_PATHNAME)
78 return(!index(string, '/'));
79 else
80 return(1);
81 else if (c == '/' && flags & FNM_PATHNAME) {
82 if ((string = index(string, '/')) == NULL)
83 return(0);
84 break;
85 }
86
87 /* general case, use recursion */
88 while ((test = *string) != EOS) {
89 if (fnmatch(pattern, string, flags))
90 return(1);
91 if (test == '/' && flags & FNM_PATHNAME)
92 break;
93 ++string;
94 }
95 return(0);
96 case '[':
97 if ((test = *string++) == EOS ||
98 test == '/' && flags & FNM_PATHNAME)
99 return(0);
100 if ((pattern = rangematch(pattern, test)) == NULL)
101 return(0);
102 break;
103 case '\\':
104 if (flags & FNM_QUOTE) {
105 if ((c = *pattern++) == EOS) {
106 c = '\\';
107 --pattern;
108 }
109 if (c != *string++)
110 return(0);
111 break;
112 }
113 /* FALLTHROUGH */
114 default:
115 if (c != *string++)
116 return(0);
117 break;
118 }
119}