]> rtime.felk.cvut.cz Git - orte.git/blob - orte/liborte/fnmatch.c
Reformat the sources with orte/uncrustify script
[orte.git] / orte / liborte / fnmatch.c
1 /*
2  *  $Id: fnmatch.c,v 0.0.0.1            2003/08/21
3  *
4  *  DEBUG:  section 3
5  *
6  *  -------------------------------------------------------------------
7  *                                ORTE
8  *                      Open Real-Time Ethernet
9  *
10  *                      Copyright (C) 2001-2006
11  *  Department of Control Engineering FEE CTU Prague, Czech Republic
12  *                      http://dce.felk.cvut.cz
13  *                      http://www.ocera.org
14  *
15  *  Author:              Petr Smolik    petr@smoliku.cz
16  *  Advisor:             Pavel Pisa
17  *  Project Responsible: Zdenek Hanzalek
18  *  --------------------------------------------------------------------
19  *
20  *  This program is free software; you can redistribute it and/or modify
21  *  it under the terms of the GNU General Public License as published by
22  *  the Free Software Foundation; either version 2 of the License, or
23  *  (at your option) any later version.
24  *
25  *  This program is distributed in the hope that it will be useful,
26  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  *  GNU General Public License for more details.
29  *
30  */
31
32 #include "orte_all.h"
33
34 /* Match STRING against the filename pattern PATTERN, returning zero if
35    it matches, nonzero if not.  */
36 int
37 fnmatch(const char *pattern, const char *string, int flags)
38 {
39   register const char *p = pattern, *n = string;
40   register unsigned char c;
41
42 /* Note that this evalutes C many times.  */
43 #define FOLD(c) ((flags & FNM_CASEFOLD) && isupper(c) ? tolower(c) : (c))
44
45 #ifdef _WIN32_ORTE
46   flags |= FNM_CASEFOLD;
47 #endif
48
49   while ((c = *p++) != '\0') {
50     c = FOLD(c);
51
52     switch (c) {
53       case '?':
54         if (*n == '\0')
55           return FNM_NOMATCH;
56         else if ((flags & FNM_FILE_NAME) && *n == '/')
57           return FNM_NOMATCH;
58         else if ((flags & FNM_PERIOD) && *n == '.' &&
59                  (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
60           return FNM_NOMATCH;
61         break;
62
63       case '\\':
64         if (!(flags & FNM_NOESCAPE)) {
65           c = *p++;
66           c = FOLD(c);
67         }
68         if (FOLD((unsigned char)*n) != c)
69           return FNM_NOMATCH;
70         break;
71
72       case '*':
73         if ((flags & FNM_PERIOD) && *n == '.' &&
74             (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
75           return FNM_NOMATCH;
76
77         for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
78           if (((flags & FNM_FILE_NAME) && *n == '/') ||
79               (c == '?' && *n == '\0'))
80             return FNM_NOMATCH;
81
82         if (c == '\0')
83           return 0;
84
85         {
86           unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
87           c1 = FOLD(c1);
88           for (--p; *n != '\0'; ++n)
89             if ((c == '[' || FOLD((unsigned char)*n) == c1) &&
90                 fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
91               return 0;
92           return FNM_NOMATCH;
93         }
94
95       case '[':
96       {
97         /* Nonzero if the sense of the character class is inverted.  */
98         register int not;
99
100         if (*n == '\0')
101           return FNM_NOMATCH;
102
103         if ((flags & FNM_PERIOD) && *n == '.' &&
104             (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
105           return FNM_NOMATCH;
106
107         not = (*p == '!' || *p == '^');
108         if (not)
109           ++p;
110
111         c = *p++;
112         for (;; ) {
113           register unsigned char cstart = c, cend = c;
114
115           if (!(flags & FNM_NOESCAPE) && c == '\\')
116             cstart = cend = *p++;
117
118           cstart = cend = FOLD(cstart);
119
120           if (c == '\0')
121             /* [ (unterminated) loses.  */
122             return FNM_NOMATCH;
123
124           c = *p++;
125           c = FOLD(c);
126
127           if ((flags & FNM_FILE_NAME) && c == '/')
128             /* [/] can never match.  */
129             return FNM_NOMATCH;
130
131           if (c == '-' && *p != ']') {
132             cend = *p++;
133             if (!(flags & FNM_NOESCAPE) && cend == '\\')
134               cend = *p++;
135             if (cend == '\0')
136               return FNM_NOMATCH;
137             cend = FOLD(cend);
138
139             c = *p++;
140           }
141
142           if (FOLD((unsigned char)*n) >= cstart
143               && FOLD((unsigned char)*n) <= cend)
144             goto matched;
145
146           if (c == ']')
147             break;
148         }
149         if (!not)
150           return FNM_NOMATCH;
151         break;
152
153 matched:;
154         /* Skip the rest of the [...] that already matched.  */
155         while (c != ']') {
156           if (c == '\0')
157             /* [... (unterminated) loses.  */
158             return FNM_NOMATCH;
159
160           c = *p++;
161           if (!(flags & FNM_NOESCAPE) && c == '\\')
162             /* XXX 1003.2d11 is unclear if this is right.  */
163             ++p;
164         }
165         if (not)
166           return FNM_NOMATCH;
167       }
168       break;
169
170       default:
171         if (c != FOLD((unsigned char)*n))
172           return FNM_NOMATCH;
173     }       // switch (c)
174
175     ++n;
176   }
177
178   if (*n == '\0')
179     return 0;
180
181   if ((flags & FNM_LEADING_DIR) && *n == '/')
182     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
183     return 0;
184
185   return FNM_NOMATCH;
186 }