]> rtime.felk.cvut.cz Git - orte.git/blob - orte/liborte/fnmatch.c
63bebabbb8dbdc2aa0d4942dad1ad851fa6b42a5
[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     register const char *p = pattern, *n = string;
39     register unsigned char c;
40
41 /* Note that this evalutes C many times.  */
42 #define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
43
44 #ifdef _WIN32_ORTE
45     flags |= FNM_CASEFOLD;
46 #endif
47
48     while ((c = *p++) != '\0')
49     {
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                 {
66                     c = *p++;
67                     c = FOLD (c);
68                 }
69                 if (FOLD ((unsigned char)*n) != c)
70                     return FNM_NOMATCH;
71                 break;
72
73             case '*':
74                 if ((flags & FNM_PERIOD) && *n == '.' &&
75                     (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
76                     return FNM_NOMATCH;
77
78                 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
79                     if (((flags & FNM_FILE_NAME) && *n == '/') ||
80                         (c == '?' && *n == '\0'))
81                         return FNM_NOMATCH;
82
83                 if (c == '\0')
84                     return 0;
85
86                 {
87                     unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
88                     c1 = FOLD (c1);
89                     for (--p; *n != '\0'; ++n)
90                         if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
91                             fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
92                             return 0;
93                     return FNM_NOMATCH;
94                 }
95
96             case '[':
97                 {
98                     /* Nonzero if the sense of the character class is inverted.  */
99                     register int not;
100
101                     if (*n == '\0')
102                         return FNM_NOMATCH;
103
104                     if ((flags & FNM_PERIOD) && *n == '.' &&
105                     (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
106                         return FNM_NOMATCH;
107
108                     not = (*p == '!' || *p == '^');
109                     if (not)
110                         ++p;
111
112                     c = *p++;
113                     for (;;) {
114                         register unsigned char cstart = c, cend = c;
115
116                         if (!(flags & FNM_NOESCAPE) && c == '\\')
117                             cstart = cend = *p++;
118
119                         cstart = cend = FOLD (cstart);
120
121                         if (c == '\0')
122                         /* [ (unterminated) loses.  */
123                             return FNM_NOMATCH;
124
125                         c = *p++;
126                         c = FOLD (c);
127
128                         if ((flags & FNM_FILE_NAME) && c == '/')
129                         /* [/] can never match.  */
130                             return FNM_NOMATCH;
131
132                         if (c == '-' && *p != ']')
133                         {
134                             cend = *p++;
135                             if (!(flags & FNM_NOESCAPE) && cend == '\\')
136                                 cend = *p++;
137                             if (cend == '\0')
138                                 return FNM_NOMATCH;
139                             cend = FOLD (cend);
140
141                             c = *p++;
142                         }
143
144                         if (FOLD ((unsigned char)*n) >= cstart
145                         && FOLD ((unsigned char)*n) <= cend)
146                             goto matched;
147
148                         if (c == ']')
149                             break;
150                     }
151                     if (!not)
152                         return FNM_NOMATCH;
153                     break;
154
155                 matched:;
156                     /* Skip the rest of the [...] that already matched.  */
157                     while (c != ']') {
158                         if (c == '\0')
159                         /* [... (unterminated) loses.  */
160                             return FNM_NOMATCH;
161
162                         c = *p++;
163                         if (!(flags & FNM_NOESCAPE) && c == '\\')
164                         /* XXX 1003.2d11 is unclear if this is right.  */
165                         ++p;
166                     }
167                     if (not)
168                         return FNM_NOMATCH;
169                 }
170                 break;
171
172             default:
173                 if (c != FOLD ((unsigned char)*n))
174                     return FNM_NOMATCH;
175         }   // switch (c)
176
177         ++n;
178     }
179
180     if (*n == '\0')
181         return 0;
182
183     if ((flags & FNM_LEADING_DIR) && *n == '/')
184     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
185         return 0;
186
187     return FNM_NOMATCH;
188 }