Blame lib/fnmatch.c

Packit Service fdd496
/* Copyright (C) 1991-1993, 1996-2007, 2009-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This program is free software; you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3, or (at your option)
Packit Service fdd496
   any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
#ifndef _LIBC
Packit Service fdd496
# include <config.h>
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Enable GNU extensions in fnmatch.h.  */
Packit Service fdd496
#ifndef _GNU_SOURCE
Packit Service fdd496
# define _GNU_SOURCE    1
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#include <fnmatch.h>
Packit Service fdd496
Packit Service fdd496
#include <alloca.h>
Packit Service fdd496
#include <assert.h>
Packit Service fdd496
#include <ctype.h>
Packit Service fdd496
#include <errno.h>
Packit Service fdd496
#include <stddef.h>
Packit Service fdd496
#include <stdbool.h>
Packit Service fdd496
#include <stdlib.h>
Packit Service fdd496
#include <string.h>
Packit Service fdd496
Packit Service fdd496
#define WIDE_CHAR_SUPPORT \
Packit Service fdd496
  (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \
Packit Service fdd496
   && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY))
Packit Service fdd496
Packit Service fdd496
/* For platform which support the ISO C amendment 1 functionality we
Packit Service fdd496
   support user defined character classes.  */
Packit Service fdd496
#if defined _LIBC || WIDE_CHAR_SUPPORT
Packit Service fdd496
# include <wctype.h>
Packit Service fdd496
# include <wchar.h>
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* We need some of the locale data (the collation sequence information)
Packit Service fdd496
   but there is no interface to get this information in general.  Therefore
Packit Service fdd496
   we support a correct implementation only in glibc.  */
Packit Service fdd496
#ifdef _LIBC
Packit Service fdd496
# include "../locale/localeinfo.h"
Packit Service fdd496
# include "../locale/elem-hash.h"
Packit Service fdd496
# include "../locale/coll-lookup.h"
Packit Service fdd496
# include <shlib-compat.h>
Packit Service fdd496
Packit Service fdd496
# define CONCAT(a,b) __CONCAT(a,b)
Packit Service fdd496
# define mbsrtowcs __mbsrtowcs
Packit Service fdd496
# define fnmatch __fnmatch
Packit Service fdd496
extern int fnmatch (const char *pattern, const char *string, int flags);
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifndef SIZE_MAX
Packit Service fdd496
# define SIZE_MAX ((size_t) -1)
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#include "flexmember.h"
Packit Service fdd496
Packit Service fdd496
#ifndef FALLTHROUGH
Packit Service fdd496
# if __GNUC__ < 7
Packit Service fdd496
#  define FALLTHROUGH ((void) 0)
Packit Service fdd496
# else
Packit Service fdd496
#  define FALLTHROUGH __attribute__ ((__fallthrough__))
Packit Service fdd496
# endif
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
Packit Service fdd496
#define NO_LEADING_PERIOD(flags) \
Packit Service fdd496
  ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
Packit Service fdd496
Packit Service fdd496
/* Comment out all this code if we are using the GNU C Library, and are not
Packit Service fdd496
   actually compiling the library itself, and have not detected a bug
Packit Service fdd496
   in the library.  This code is part of the GNU C
Packit Service fdd496
   Library, but also included in many other GNU distributions.  Compiling
Packit Service fdd496
   and linking in this code is a waste when using the GNU C library
Packit Service fdd496
   (especially if it is a shared library).  Rather than having every GNU
Packit Service fdd496
   program understand 'configure --with-gnu-libc' and omit the object files,
Packit Service fdd496
   it is simpler to just do this in the source for each such file.  */
Packit Service fdd496
Packit Service fdd496
#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
# if ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK))
Packit Service fdd496
#  define isblank(c) ((c) == ' ' || (c) == '\t')
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
# define STREQ(s1, s2) (strcmp (s1, s2) == 0)
Packit Service fdd496
Packit Service fdd496
# if defined _LIBC || WIDE_CHAR_SUPPORT
Packit Service fdd496
/* The GNU C library provides support for user-defined character classes
Packit Service fdd496
   and the functions from ISO C amendment 1.  */
Packit Service fdd496
#  ifdef CHARCLASS_NAME_MAX
Packit Service fdd496
#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
Packit Service fdd496
#  else
Packit Service fdd496
/* This shouldn't happen but some implementation might still have this
Packit Service fdd496
   problem.  Use a reasonable default value.  */
Packit Service fdd496
#   define CHAR_CLASS_MAX_LENGTH 256
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
#  ifdef _LIBC
Packit Service fdd496
#   define IS_CHAR_CLASS(string) __wctype (string)
Packit Service fdd496
#  else
Packit Service fdd496
#   define IS_CHAR_CLASS(string) wctype (string)
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
#  ifdef _LIBC
Packit Service fdd496
#   define ISWCTYPE(WC, WT)     __iswctype (WC, WT)
Packit Service fdd496
#  else
Packit Service fdd496
#   define ISWCTYPE(WC, WT)     iswctype (WC, WT)
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
#  if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
Packit Service fdd496
/* In this case we are implementing the multibyte character handling.  */
Packit Service fdd496
#   define HANDLE_MULTIBYTE     1
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
# else
Packit Service fdd496
#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, 'xdigit'.  */
Packit Service fdd496
Packit Service fdd496
#  define IS_CHAR_CLASS(string)                                               \
Packit Service fdd496
   (STREQ (string, "alpha") || STREQ (string, "upper")                        \
Packit Service fdd496
    || STREQ (string, "lower") || STREQ (string, "digit")                     \
Packit Service fdd496
    || STREQ (string, "alnum") || STREQ (string, "xdigit")                    \
Packit Service fdd496
    || STREQ (string, "space") || STREQ (string, "print")                     \
Packit Service fdd496
    || STREQ (string, "punct") || STREQ (string, "graph")                     \
Packit Service fdd496
    || STREQ (string, "cntrl") || STREQ (string, "blank"))
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
/* Avoid depending on library functions or files
Packit Service fdd496
   whose names are inconsistent.  */
Packit Service fdd496
Packit Service fdd496
/* Global variable.  */
Packit Service fdd496
static int posixly_correct;
Packit Service fdd496
Packit Service fdd496
# ifndef internal_function
Packit Service fdd496
/* Inside GNU libc we mark some function in a special way.  In other
Packit Service fdd496
   environments simply ignore the marking.  */
Packit Service fdd496
#  define internal_function
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
/* Note that this evaluates C many times.  */
Packit Service fdd496
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
Packit Service fdd496
# define CHAR   char
Packit Service fdd496
# define UCHAR  unsigned char
Packit Service fdd496
# define INT    int
Packit Service fdd496
# define FCT    internal_fnmatch
Packit Service fdd496
# define EXT    ext_match
Packit Service fdd496
# define END    end_pattern
Packit Service fdd496
# define L_(CS) CS
Packit Service fdd496
# ifdef _LIBC
Packit Service fdd496
#  define BTOWC(C)      __btowc (C)
Packit Service fdd496
# else
Packit Service fdd496
#  define BTOWC(C)      btowc (C)
Packit Service fdd496
# endif
Packit Service fdd496
# define STRLEN(S) strlen (S)
Packit Service fdd496
# define STRCAT(D, S) strcat (D, S)
Packit Service fdd496
# ifdef _LIBC
Packit Service fdd496
#  define MEMPCPY(D, S, N) __mempcpy (D, S, N)
Packit Service fdd496
# else
Packit Service fdd496
#  if HAVE_MEMPCPY
Packit Service fdd496
#   define MEMPCPY(D, S, N) mempcpy (D, S, N)
Packit Service fdd496
#  else
Packit Service fdd496
#   define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
Packit Service fdd496
#  endif
Packit Service fdd496
# endif
Packit Service fdd496
# define MEMCHR(S, C, N) memchr (S, C, N)
Packit Service fdd496
# include "fnmatch_loop.c"
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
# if HANDLE_MULTIBYTE
Packit Service fdd496
#  define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
Packit Service fdd496
#  define CHAR  wchar_t
Packit Service fdd496
#  define UCHAR wint_t
Packit Service fdd496
#  define INT   wint_t
Packit Service fdd496
#  define FCT   internal_fnwmatch
Packit Service fdd496
#  define EXT   ext_wmatch
Packit Service fdd496
#  define END   end_wpattern
Packit Service fdd496
#  define L_(CS)        L##CS
Packit Service fdd496
#  define BTOWC(C)      (C)
Packit Service fdd496
#  ifdef _LIBC
Packit Service fdd496
#   define STRLEN(S) __wcslen (S)
Packit Service fdd496
#   define STRCAT(D, S) __wcscat (D, S)
Packit Service fdd496
#   define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
Packit Service fdd496
#  else
Packit Service fdd496
#   define STRLEN(S) wcslen (S)
Packit Service fdd496
#   define STRCAT(D, S) wcscat (D, S)
Packit Service fdd496
#   if HAVE_WMEMPCPY
Packit Service fdd496
#    define MEMPCPY(D, S, N) wmempcpy (D, S, N)
Packit Service fdd496
#   else
Packit Service fdd496
#    define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N))
Packit Service fdd496
#   endif
Packit Service fdd496
#  endif
Packit Service fdd496
#  define MEMCHR(S, C, N) wmemchr (S, C, N)
Packit Service fdd496
#  define WIDE_CHAR_VERSION 1
Packit Service fdd496
Packit Service fdd496
#  undef IS_CHAR_CLASS
Packit Service fdd496
/* We have to convert the wide character string in a multibyte string.  But
Packit Service fdd496
   we know that the character class names consist of alphanumeric characters
Packit Service fdd496
   from the portable character set, and since the wide character encoding
Packit Service fdd496
   for a member of the portable character set is the same code point as
Packit Service fdd496
   its single-byte encoding, we can use a simplified method to convert the
Packit Service fdd496
   string to a multibyte character string.  */
Packit Service fdd496
static wctype_t
Packit Service fdd496
is_char_class (const wchar_t *wcs)
Packit Service fdd496
{
Packit Service fdd496
  char s[CHAR_CLASS_MAX_LENGTH + 1];
Packit Service fdd496
  char *cp = s;
Packit Service fdd496
Packit Service fdd496
  do
Packit Service fdd496
    {
Packit Service fdd496
      /* Test for a printable character from the portable character set.  */
Packit Service fdd496
#  ifdef _LIBC
Packit Service fdd496
      if (*wcs < 0x20 || *wcs > 0x7e
Packit Service fdd496
          || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
Packit Service fdd496
        return (wctype_t) 0;
Packit Service fdd496
#  else
Packit Service fdd496
      switch (*wcs)
Packit Service fdd496
        {
Packit Service fdd496
        case L' ': case L'!': case L'"': case L'#': case L'%':
Packit Service fdd496
        case L'&': case L'\'': case L'(': case L')': case L'*':
Packit Service fdd496
        case L'+': case L',': case L'-': case L'.': case L'/':
Packit Service fdd496
        case L'0': case L'1': case L'2': case L'3': case L'4':
Packit Service fdd496
        case L'5': case L'6': case L'7': case L'8': case L'9':
Packit Service fdd496
        case L':': case L';': case L'<': case L'=': case L'>':
Packit Service fdd496
        case L'?':
Packit Service fdd496
        case L'A': case L'B': case L'C': case L'D': case L'E':
Packit Service fdd496
        case L'F': case L'G': case L'H': case L'I': case L'J':
Packit Service fdd496
        case L'K': case L'L': case L'M': case L'N': case L'O':
Packit Service fdd496
        case L'P': case L'Q': case L'R': case L'S': case L'T':
Packit Service fdd496
        case L'U': case L'V': case L'W': case L'X': case L'Y':
Packit Service fdd496
        case L'Z':
Packit Service fdd496
        case L'[': case L'\\': case L']': case L'^': case L'_':
Packit Service fdd496
        case L'a': case L'b': case L'c': case L'd': case L'e':
Packit Service fdd496
        case L'f': case L'g': case L'h': case L'i': case L'j':
Packit Service fdd496
        case L'k': case L'l': case L'm': case L'n': case L'o':
Packit Service fdd496
        case L'p': case L'q': case L'r': case L's': case L't':
Packit Service fdd496
        case L'u': case L'v': case L'w': case L'x': case L'y':
Packit Service fdd496
        case L'z': case L'{': case L'|': case L'}': case L'~':
Packit Service fdd496
          break;
Packit Service fdd496
        default:
Packit Service fdd496
          return (wctype_t) 0;
Packit Service fdd496
        }
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
      /* Avoid overrunning the buffer.  */
Packit Service fdd496
      if (cp == s + CHAR_CLASS_MAX_LENGTH)
Packit Service fdd496
        return (wctype_t) 0;
Packit Service fdd496
Packit Service fdd496
      *cp++ = (char) *wcs++;
Packit Service fdd496
    }
Packit Service fdd496
  while (*wcs != L'\0');
Packit Service fdd496
Packit Service fdd496
  *cp = '\0';
Packit Service fdd496
Packit Service fdd496
#  ifdef _LIBC
Packit Service fdd496
  return __wctype (s);
Packit Service fdd496
#  else
Packit Service fdd496
  return wctype (s);
Packit Service fdd496
#  endif
Packit Service fdd496
}
Packit Service fdd496
#  define IS_CHAR_CLASS(string) is_char_class (string)
Packit Service fdd496
Packit Service fdd496
#  include "fnmatch_loop.c"
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
int
Packit Service fdd496
fnmatch (const char *pattern, const char *string, int flags)
Packit Service fdd496
{
Packit Service fdd496
# if HANDLE_MULTIBYTE
Packit Service fdd496
#  define ALLOCA_LIMIT 2000
Packit Service fdd496
  if (__builtin_expect (MB_CUR_MAX, 1) != 1)
Packit Service fdd496
    {
Packit Service fdd496
      mbstate_t ps;
Packit Service fdd496
      size_t patsize;
Packit Service fdd496
      size_t strsize;
Packit Service fdd496
      size_t totsize;
Packit Service fdd496
      wchar_t *wpattern;
Packit Service fdd496
      wchar_t *wstring;
Packit Service fdd496
      int res;
Packit Service fdd496
Packit Service fdd496
      /* Calculate the size needed to convert the strings to
Packit Service fdd496
         wide characters.  */
Packit Service fdd496
      memset (&ps, '\0', sizeof (ps));
Packit Service fdd496
      patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
Packit Service fdd496
      if (__builtin_expect (patsize != 0, 1))
Packit Service fdd496
        {
Packit Service fdd496
          assert (mbsinit (&ps);;
Packit Service fdd496
          strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
Packit Service fdd496
          if (__builtin_expect (strsize != 0, 1))
Packit Service fdd496
            {
Packit Service fdd496
              assert (mbsinit (&ps);;
Packit Service fdd496
              totsize = patsize + strsize;
Packit Service fdd496
              if (__builtin_expect (! (patsize <= totsize
Packit Service fdd496
                                       && totsize <= SIZE_MAX / sizeof (wchar_t)),
Packit Service fdd496
                                    0))
Packit Service fdd496
                {
Packit Service fdd496
                  errno = ENOMEM;
Packit Service fdd496
                  return -1;
Packit Service fdd496
                }
Packit Service fdd496
Packit Service fdd496
              /* Allocate room for the wide characters.  */
Packit Service fdd496
              if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
Packit Service fdd496
                wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
Packit Service fdd496
              else
Packit Service fdd496
                {
Packit Service fdd496
                  wpattern = malloc (totsize * sizeof (wchar_t));
Packit Service fdd496
                  if (__builtin_expect (! wpattern, 0))
Packit Service fdd496
                    {
Packit Service fdd496
                      errno = ENOMEM;
Packit Service fdd496
                      return -1;
Packit Service fdd496
                    }
Packit Service fdd496
                }
Packit Service fdd496
              wstring = wpattern + patsize;
Packit Service fdd496
Packit Service fdd496
              /* Convert the strings into wide characters.  */
Packit Service fdd496
              mbsrtowcs (wpattern, &pattern, patsize, &ps);
Packit Service fdd496
              assert (mbsinit (&ps);;
Packit Service fdd496
              mbsrtowcs (wstring, &string, strsize, &ps);
Packit Service fdd496
Packit Service fdd496
              res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
Packit Service fdd496
                                       flags & FNM_PERIOD, flags);
Packit Service fdd496
Packit Service fdd496
              if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
Packit Service fdd496
                free (wpattern);
Packit Service fdd496
              return res;
Packit Service fdd496
            }
Packit Service fdd496
        }
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
# endif /* HANDLE_MULTIBYTE */
Packit Service fdd496
Packit Service fdd496
  return internal_fnmatch (pattern, string, string + strlen (string),
Packit Service fdd496
                           flags & FNM_PERIOD, flags);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# ifdef _LIBC
Packit Service fdd496
#  undef fnmatch
Packit Service fdd496
versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
Packit Service fdd496
#  if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
Packit Service fdd496
strong_alias (__fnmatch, __fnmatch_old)
Packit Service fdd496
compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
Packit Service fdd496
#  endif
Packit Service fdd496
libc_hidden_ver (__fnmatch, fnmatch)
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
#endif  /* _LIBC or not __GNU_LIBRARY__.  */