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