ReactOS 0.4.15-dev-7659-ga55345b
fnmatch.c File Reference
#include <schily/mconfig.h>
#include <schily/fnmatch.h>
#include <schily/limits.h>
#include <schily/string.h>
#include <schily/wchar.h>
#include <schily/wctype.h>
#include <schily/libport.h>
Include dependency graph for fnmatch.c:

Go to the source code of this file.

Macros

#define EOS   '\0'
 
#define RANGE_MATCH   1
 
#define RANGE_NOMATCH   0
 
#define RANGE_ERROR   (-1)
 
#define CL_SIZE   32 /* Max size for '[: :]' */
 

Functions

static int rangematch __PR ((const char *, wchar_t, int, char **, mbstate_t *))
 
static int fnmatch1 __PR ((const char *, const char *, const char *, int, mbstate_t, mbstate_t))
 
int fnmatch (char *pattern, const char *string, int flags) const
 
int js_fnmatch (char *pattern, const char *string, int flags) const
 
static int fnmatch1 (char *pattern, const char *string, const char *stringstart, int flags, mbstate_t patmbs, mbstate_t strmbs) const
 
static int rangematch (char *pattern, wchar_t test, int flags, char **newp, mbstate_t *patmbs) const
 

Variables

static UConst char sccsid []
 

Macro Definition Documentation

◆ CL_SIZE

#define CL_SIZE   32 /* Max size for '[: :]' */

Definition at line 80 of file fnmatch.c.

◆ EOS

#define EOS   '\0'

Definition at line 74 of file fnmatch.c.

◆ RANGE_ERROR

#define RANGE_ERROR   (-1)

Definition at line 78 of file fnmatch.c.

◆ RANGE_MATCH

#define RANGE_MATCH   1

Definition at line 76 of file fnmatch.c.

◆ RANGE_NOMATCH

#define RANGE_NOMATCH   0

Definition at line 77 of file fnmatch.c.

Function Documentation

◆ __PR() [1/2]

static int fnmatch1 __PR ( (const char *, const char *, const char *, int, mbstate_t, mbstate_t )
static

◆ __PR() [2/2]

static int rangematch __PR ( (const char *, wchar_t, int, char **, mbstate_t *)  )
static

◆ fnmatch()

int fnmatch ( char pattern,
const char string,
int  flags 
) const

Definition at line 100 of file fnmatch.c.

104{
105 return (js_fnmatch(pattern, string, flags));
106}
int js_fnmatch(char *pattern, const char *string, int flags) const
Definition: fnmatch.c:111
GLubyte * pattern
Definition: glext.h:7787
GLbitfield flags
Definition: glext.h:7161

◆ fnmatch1()

static int fnmatch1 ( char pattern,
const char string,
const char stringstart,
int  flags,
mbstate_t  patmbs,
mbstate_t  strmbs 
) const
static

Definition at line 130 of file fnmatch.c.

137{
138 const char *bt_pattern, *bt_string;
139 mbstate_t bt_patmbs, bt_strmbs;
140 char *newp;
141 char c;
142 wchar_t pc, sc;
143 size_t pclen, sclen;
144
145 bt_pattern = bt_string = NULL;
146 for (;;) {
147 pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
148 if (pclen == (size_t)-1 || pclen == (size_t)-2)
149 return (FNM_NOMATCH);
150 pattern += pclen;
151 sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs);
152 if (sclen == (size_t)-1 || sclen == (size_t)-2) {
153 sc = (unsigned char)*string;
154 sclen = 1;
155 memset(&strmbs, 0, sizeof (strmbs));
156 }
157 switch (pc) {
158 case EOS:
159 if ((flags & FNM_LEADING_DIR) && sc == '/')
160 return (0);
161 if (sc == EOS)
162 return (0);
163 goto backtrack;
164 case '?':
165 if (sc == EOS)
166 return (FNM_NOMATCH);
167 if (sc == '/' && (flags & FNM_PATHNAME))
168 goto backtrack;
169 if (sc == '.' && (flags & FNM_PERIOD) &&
170 (string == stringstart ||
171 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
172 goto backtrack;
173 string += sclen;
174 break;
175 case '*':
176 c = *pattern;
177 /* Collapse multiple stars. */
178 while (c == '*')
179 c = *++pattern;
180
181 if (sc == '.' && (flags & FNM_PERIOD) &&
182 (string == stringstart ||
183 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
184 goto backtrack;
185
186 /* Optimize for pattern with * at end or before /. */
187 if (c == EOS) {
188 if (flags & FNM_PATHNAME)
189 return ((flags & FNM_LEADING_DIR) ||
190 strchr(string, '/') == NULL ?
191 0 : FNM_NOMATCH);
192 else
193 return (0);
194 } else if (c == '/' && flags & FNM_PATHNAME) {
195 if ((string = strchr(string, '/')) == NULL)
196 return (FNM_NOMATCH);
197 break;
198 }
199
200 /*
201 * First try the shortest match for the '*' that
202 * could work. We can forget any earlier '*' since
203 * there is no way having it match more characters
204 * can help us, given that we are already here.
205 */
206 bt_pattern = pattern, bt_patmbs = patmbs;
207 bt_string = string, bt_strmbs = strmbs;
208 break;
209 case '[':
210 if (sc == EOS)
211 return (FNM_NOMATCH);
212 if (sc == '/' && (flags & FNM_PATHNAME))
213 goto backtrack;
214 if (sc == '.' && (flags & FNM_PERIOD) &&
215 (string == stringstart ||
216 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
217 goto backtrack;
218
219 switch (rangematch(pattern, sc, flags, &newp,
220 &patmbs)) {
221 case RANGE_ERROR:
222 goto norm;
223 case RANGE_MATCH:
224 pattern = newp;
225 break;
226 case RANGE_NOMATCH:
227 goto backtrack;
228 }
229 string += sclen;
230 break;
231 case '\\':
232 if (!(flags & FNM_NOESCAPE)) {
233 pclen = mbrtowc(&pc, pattern, MB_LEN_MAX,
234 &patmbs);
235 if (pclen == (size_t)-1 || pclen == (size_t)-2)
236 return (FNM_NOMATCH);
237 if (pclen == 0)
238 return (FNM_NOMATCH);
239 pattern += pclen;
240 }
241 /* FALLTHROUGH */
242 default:
243 norm:
244 string += sclen;
245 if (pc == sc) {
246 ;
247 } else if ((flags & FNM_CASEFOLD) &&
248 (towlower(pc) == towlower(sc))) {
249 ;
250 } else {
251 backtrack:
252 /*
253 * If we have a mismatch (other than hitting
254 * the end of the string), go back to the last
255 * '*' seen and have it match one additional
256 * character.
257 */
258 if (bt_pattern == NULL)
259 return (FNM_NOMATCH);
260 sclen = mbrtowc(&sc, bt_string, MB_LEN_MAX,
261 &bt_strmbs);
262 if (sclen == (size_t)-1 ||
263 sclen == (size_t)-2) {
264 sc = (unsigned char)*bt_string;
265 sclen = 1;
266 memset(&bt_strmbs, 0,
267 sizeof (bt_strmbs));
268 }
269 if (sc == EOS)
270 return (FNM_NOMATCH);
271 if (sc == '/' && flags & FNM_PATHNAME)
272 return (FNM_NOMATCH);
273 bt_string += sclen;
274 pattern = bt_pattern, patmbs = bt_patmbs;
275 string = bt_string, strmbs = bt_strmbs;
276 }
277 break;
278 }
279 }
280 /* NOTREACHED */
281}
_Tp _STLP_CALL norm(const complex< _Tp > &__z)
Definition: _complex.h:741
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define NULL
Definition: types.h:112
unsigned char
Definition: typeof.h:29
#define RANGE_NOMATCH
Definition: fnmatch.c:77
#define RANGE_ERROR
Definition: fnmatch.c:78
#define EOS
Definition: fnmatch.c:74
#define RANGE_MATCH
Definition: fnmatch.c:76
static int rangematch(char *pattern, wchar_t test, int flags, char **newp, mbstate_t *patmbs) const
Definition: fnmatch.c:289
#define FNM_NOESCAPE
Definition: fnmatch.h:72
#define FNM_LEADING_DIR
Definition: fnmatch.h:90
#define FNM_PERIOD
Definition: fnmatch.h:78
#define FNM_CASEFOLD
Definition: fnmatch.h:87
#define FNM_PATHNAME
Definition: fnmatch.h:75
#define FNM_NOMATCH
Definition: fnmatch.h:62
const GLubyte * c
Definition: glext.h:8905
#define MB_LEN_MAX
Definition: limits.h:35
#define c
Definition: ke_i.h:80
char string[160]
Definition: util.h:11
#define memset(x, y, z)
Definition: compat.h:39
#define mbrtowc(wp, cp, len, sp)
Definition: wchar.h:158
#define towlower(c)
Definition: wctype.h:97

Referenced by js_fnmatch().

◆ js_fnmatch()

int js_fnmatch ( char pattern,
const char string,
int  flags 
) const

Definition at line 111 of file fnmatch.c.

115{
116 /*
117 * SunPro C gives a warning if we do not initialize an object:
118 * static const mbstate_t initial;
119 * GCC gives a warning if we try to initialize it.
120 * As the POSIX standard forbids mbstate_t from being an array,
121 * we do not need "const", the var is always copied when used as
122 * a parapemeter for fnmatch1();
123 */
124 static mbstate_t initial;
125
126 return (fnmatch1(pattern, string, string, flags, initial, initial));
127}
static int fnmatch1(char *pattern, const char *string, const char *stringstart, int flags, mbstate_t patmbs, mbstate_t strmbs) const
Definition: fnmatch.c:130

Referenced by fnmatch().

◆ rangematch()

static int rangematch ( char pattern,
wchar_t  test,
int  flags,
char **  newp,
mbstate_t patmbs 
) const
static

Definition at line 289 of file fnmatch.c.

296{
297 int negate, ok;
298 wchar_t c, c2;
299 wchar_t otest = test;
300 size_t pclen;
301 const char *origpat;
302#ifdef XXX_COLLATE
303 struct xlocale_collate *table = (struct xlocale_collate *)
304 __get_locale()->components[XLC_COLLATE];
305#endif
306
307 /*
308 * A bracket expression starting with an unquoted circumflex
309 * character produces unspecified results (IEEE 1003.2-1992,
310 * 3.13.2). This implementation treats it like '!', for
311 * consistency with the regular expression syntax.
312 * J.T. Conklin (conklin@ngai.kaleida.com)
313 */
314 if ((negate = (*pattern == '!' || *pattern == '^')))
315 ++pattern;
316
317 if (flags & FNM_CASEFOLD)
318 test = towlower(test);
319
320 /*
321 * A right bracket shall lose its special meaning and represent
322 * itself in a bracket expression if it occurs first in the list.
323 * -- POSIX.2 2.8.3.2
324 */
325 ok = 0;
326 origpat = pattern;
327 for (;;) {
328 int quoted = 0;
329
330 if (*pattern == ']' && pattern > origpat) {
331 pattern++;
332 break;
333 } else if (*pattern == '\0') {
334 return (RANGE_ERROR);
335 } else if (*pattern == '/' && (flags & FNM_PATHNAME)) {
336 return (RANGE_NOMATCH);
337 } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE)) {
338 pattern++;
339 quoted++;
340 }
341 pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs);
342 if (pclen == (size_t)-1 || pclen == (size_t)-2)
343 return (RANGE_NOMATCH);
344 pattern += pclen;
345
346 if (!quoted && c == '[') {
347 if (pattern[0] == ':') {
348 char class[CL_SIZE+1];
349 char *pc = class;
350 const char *p;
351
352 p = pattern + 1; /* Eat ':' */
353 for (;;) {
354 if (*p == '\0')
355 return (RANGE_ERROR);
356 if (*p == ':' && p[1] == ']')
357 break;
358 if (pc >= &class[CL_SIZE])
359 return (RANGE_ERROR);
360 *pc++ = *p++;
361 }
362 if (pc == class)
363 return (RANGE_ERROR);
364 *pc = '\0';
365 pattern = p + 2; /* Skip ":]" */
366 if (iswctype(otest, wctype(class))) {
367 ok = 1;
368 } else if (flags & FNM_CASEFOLD) {
369 /*
370 * Convert to the other case
371 */
372 if (strcmp(class, "upper") == 0)
373 if (iswctype(otest,
374 wctype("lower")))
375 ok = 1;
376 else if (strcmp(class, "lower") == 0)
377 if (iswctype(otest,
378 wctype("upper")))
379 ok = 1;
380 }
381 continue;
382 }
383 }
384
385 if (flags & FNM_CASEFOLD)
386 c = towlower(c);
387
388 if (*pattern == '-' && *(pattern + 1) != EOS &&
389 *(pattern + 1) != ']') {
390 if (*++pattern == '\\' && !(flags & FNM_NOESCAPE))
391 if (*pattern != EOS)
392 pattern++;
393 pclen = mbrtowc(&c2, pattern, MB_LEN_MAX, patmbs);
394 if (pclen == (size_t)-1 || pclen == (size_t)-2)
395 return (RANGE_NOMATCH);
396 pattern += pclen;
397 if (c2 == EOS)
398 return (RANGE_ERROR);
399
400 if (flags & FNM_CASEFOLD)
401 c2 = towlower(c2);
402
403#ifdef XXX_COLLATE
404 if (table->__collate_load_error ?
405 c <= test && test <= c2 :
406 __wcollate_range_cmp(c, test) <= 0 &&
407 __wcollate_range_cmp(test, c2) <= 0)
408 ok = 1;
409#else
410 if (c <= test && test <= c2)
411 ok = 1;
412#endif
413 } else if (c == test)
414 ok = 1;
415 }
416
417 *newp = (char *)pattern;
418 return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
419}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ok(value,...)
Definition: atltest.h:57
#define CL_SIZE
Definition: fnmatch.c:80
int __cdecl iswctype(wint_t wc, wctype_t wctypeFlags)
Definition: freeldr.c:99
GLfloat GLfloat p
Definition: glext.h:8902
wctype_t __cdecl wctype(const char *)
#define test
Definition: rosglue.h:37

Referenced by fnmatch1().

Variable Documentation

◆ sccsid

UConst char sccsid[]
static
Initial value:
=
"@(#)fnmatch.c 8.24 17/08/30 2005-2017 J. Schilling from 8.2 (Berkeley)"

Definition at line 4 of file fnmatch.c.