source: trunk/libs/newlib/src/newlib/libc/posix/fnmatch.c @ 577

Last change on this file since 577 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 1989, 1993, 1994
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Guido van Rossum.
7 *
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 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#ifndef _NO_FNMATCH
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char sccsid[] = "@(#)fnmatch.c   8.2 (Berkeley) 4/16/94";
37#endif /* LIBC_SCCS and not lint */
38#include <sys/cdefs.h>
39
40/*
41 * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
42 * Compares a filename or pathname to a pattern.
43 */
44
45#include <ctype.h>
46#include <fnmatch.h>
47#include <string.h>
48#include <stdio.h>
49
50#include "collate.h"
51
52#define EOS     '\0'
53
54#define RANGE_MATCH     1
55#define RANGE_NOMATCH   0
56#define RANGE_ERROR     (-1)
57
58static int rangematch(const char *, char, int, char **);
59
60int
61fnmatch(pattern, string, flags)
62        const char *pattern, *string;
63        int flags;
64{
65        const char *stringstart;
66        char *newp;
67        char c, test;
68
69        for (stringstart = string;;)
70                switch (c = *pattern++) {
71                case EOS:
72                        if ((flags & FNM_LEADING_DIR) && *string == '/')
73                                return (0);
74                        return (*string == EOS ? 0 : FNM_NOMATCH);
75                case '?':
76                        if (*string == EOS)
77                                return (FNM_NOMATCH);
78                        if (*string == '/' && (flags & FNM_PATHNAME))
79                                return (FNM_NOMATCH);
80                        if (*string == '.' && (flags & FNM_PERIOD) &&
81                            (string == stringstart ||
82                            ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
83                                return (FNM_NOMATCH);
84                        ++string;
85                        break;
86                case '*':
87                        c = *pattern;
88                        /* Collapse multiple stars. */
89                        while (c == '*')
90                                c = *++pattern;
91
92                        if (*string == '.' && (flags & FNM_PERIOD) &&
93                            (string == stringstart ||
94                            ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
95                                return (FNM_NOMATCH);
96
97                        /* Optimize for pattern with * at end or before /. */
98                        if (c == EOS)
99                                if (flags & FNM_PATHNAME)
100                                        return ((flags & FNM_LEADING_DIR) ||
101                                            strchr(string, '/') == NULL ?
102                                            0 : FNM_NOMATCH);
103                                else
104                                        return (0);
105                        else if (c == '/' && flags & FNM_PATHNAME) {
106                                if ((string = strchr(string, '/')) == NULL)
107                                        return (FNM_NOMATCH);
108                                break;
109                        }
110
111                        /* General case, use recursion. */
112                        while ((test = *string) != EOS) {
113                                if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
114                                        return (0);
115                                if (test == '/' && flags & FNM_PATHNAME)
116                                        break;
117                                ++string;
118                        }
119                        return (FNM_NOMATCH);
120                case '[':
121                        if (*string == EOS)
122                                return (FNM_NOMATCH);
123                        if (*string == '/' && (flags & FNM_PATHNAME))
124                                return (FNM_NOMATCH);
125                        if (*string == '.' && (flags & FNM_PERIOD) &&
126                            (string == stringstart ||
127                            ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
128                                return (FNM_NOMATCH);
129
130                        switch (rangematch(pattern, *string, flags, &newp)) {
131                        case RANGE_ERROR:
132                                goto norm;
133                        case RANGE_MATCH:
134                                pattern = newp;
135                                break;
136                        case RANGE_NOMATCH:
137                                return (FNM_NOMATCH);
138                        }
139                        ++string;
140                        break;
141                case '\\':
142                        if (!(flags & FNM_NOESCAPE)) {
143                                if ((c = *pattern++) == EOS) {
144                                        c = '\\';
145                                        --pattern;
146                                }
147                        }
148                        /* FALLTHROUGH */
149                default:
150                norm:
151                        if (c == *string)
152                                ;
153                        else if ((flags & FNM_CASEFOLD) &&
154                                 (tolower((unsigned char)c) ==
155                                  tolower((unsigned char)*string)))
156                                ;
157                        else
158                                return (FNM_NOMATCH);
159                        string++;
160                        break;
161                }
162        /* NOTREACHED */
163}
164
165static int
166rangematch(pattern, test, flags, newp)
167        const char *pattern;
168        char test;
169        int flags;
170        char **newp;
171{
172        int negate, ok;
173        char c, c2;
174
175        /*
176         * A bracket expression starting with an unquoted circumflex
177         * character produces unspecified results (IEEE 1003.2-1992,
178         * 3.13.2).  This implementation treats it like '!', for
179         * consistency with the regular expression syntax.
180         * J.T. Conklin (conklin@ngai.kaleida.com)
181         */
182        if ( (negate = (*pattern == '!' || *pattern == '^')) )
183                ++pattern;
184
185        if (flags & FNM_CASEFOLD)
186                test = tolower((unsigned char)test);
187
188        /*
189         * A right bracket shall lose its special meaning and represent
190         * itself in a bracket expression if it occurs first in the list.
191         * -- POSIX.2 2.8.3.2
192         */
193        ok = 0;
194        c = *pattern++;
195        do {
196                if (c == '\\' && !(flags & FNM_NOESCAPE))
197                        c = *pattern++;
198                if (c == EOS)
199                        return (RANGE_ERROR);
200
201                if (c == '/' && (flags & FNM_PATHNAME))
202                        return (RANGE_NOMATCH);
203
204                if (flags & FNM_CASEFOLD)
205                        c = tolower((unsigned char)c);
206
207                if (*pattern == '-'
208                    && (c2 = *(pattern+1)) != EOS && c2 != ']') {
209                        pattern += 2;
210                        if (c2 == '\\' && !(flags & FNM_NOESCAPE))
211                                c2 = *pattern++;
212                        if (c2 == EOS)
213                                return (RANGE_ERROR);
214
215                        if (flags & FNM_CASEFOLD)
216                                c2 = tolower((unsigned char)c2);
217
218                        if (__collate_load_error ?
219                            c <= test && test <= c2 :
220                               __collate_range_cmp(c, test) <= 0
221                            && __collate_range_cmp(test, c2) <= 0
222                           )
223                                ok = 1;
224                } else if (c == test)
225                        ok = 1;
226        } while ((c = *pattern++) != ']');
227
228        *newp = (char *)pattern;
229        return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
230}
231
232#endif /* !_NO_FNMATCH  */
Note: See TracBrowser for help on using the repository browser.