ReactOS  0.4.13-dev-482-ge57f103
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 rangematch __PR ( (const char *, wchar_t, int, char **, mbstate_t *)  )
static

◆ __PR() [2/2]

static int fnmatch1 __PR ( (const char *, const char *, const char *, int, mbstate_t, 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
GLbitfield flags
Definition: glext.h:7161
GLubyte * pattern
Definition: glext.h:7787

Referenced by disk_query_directory(), and gen_matches().

◆ 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 }
#define FNM_PATHNAME
Definition: fnmatch.h:75
_Tp _STLP_CALL norm(const complex< _Tp > &__z)
Definition: _complex.h:741
#define EOS
Definition: fnmatch.c:74
#define RANGE_NOMATCH
Definition: fnmatch.c:77
#define RANGE_ERROR
Definition: fnmatch.c:78
#define FNM_LEADING_DIR
Definition: fnmatch.h:90
size_t __cdecl mbrtowc(_Pre_maybenull_ _Post_z_ wchar_t *_DstCh, _In_reads_bytes_opt_(_SizeInBytes) _Pre_opt_z_ const char *_SrcCh, _In_ size_t _SizeInBytes, _Out_opt_ mbstate_t *_State)
smooth NULL
Definition: ftsmooth.c:416
unsigned char
Definition: typeof.h:29
#define FNM_NOESCAPE
Definition: fnmatch.h:72
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
#define FNM_PERIOD
Definition: fnmatch.h:78
char string[160]
Definition: util.h:11
static int rangematch(char *pattern, wchar_t test, int flags, char **newp, mbstate_t *patmbs) const
Definition: fnmatch.c:289
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define c
Definition: ke_i.h:80
#define towlower(c)
Definition: wctype.h:97
#define FNM_NOMATCH
Definition: fnmatch.h:62
#define FNM_CASEFOLD
Definition: fnmatch.h:87
#define RANGE_MATCH
Definition: fnmatch.c:76
#define memset(x, y, z)
Definition: compat.h:39
#define MB_LEN_MAX
Definition: limits.h:35
GLubyte * pattern
Definition: glext.h:7787

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
GLbitfield flags
Definition: glext.h:7161
GLubyte * pattern
Definition: glext.h:7787

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 }
#define FNM_PATHNAME
Definition: fnmatch.h:75
#define EOS
Definition: fnmatch.c:74
#define RANGE_NOMATCH
Definition: fnmatch.c:77
#define RANGE_ERROR
Definition: fnmatch.c:78
#define test
Definition: rosglue.h:37
#define ok(value,...)
size_t __cdecl mbrtowc(_Pre_maybenull_ _Post_z_ wchar_t *_DstCh, _In_reads_bytes_opt_(_SizeInBytes) _Pre_opt_z_ const char *_SrcCh, _In_ size_t _SizeInBytes, _Out_opt_ mbstate_t *_State)
#define FNM_NOESCAPE
Definition: fnmatch.h:72
const GLubyte * c
Definition: glext.h:8905
int __cdecl iswctype(wint_t wc, wctype_t wctypeFlags)
Definition: freeldr.c:86
#define CL_SIZE
Definition: fnmatch.c:80
GLbitfield flags
Definition: glext.h:7161
wctype_t __cdecl wctype(const char *)
#define c
Definition: ke_i.h:80
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define towlower(c)
Definition: wctype.h:97
#define FNM_CASEFOLD
Definition: fnmatch.h:87
GLfloat GLfloat p
Definition: glext.h:8902
#define RANGE_MATCH
Definition: fnmatch.c:76
#define MB_LEN_MAX
Definition: limits.h:35
GLubyte * pattern
Definition: glext.h:7787

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.