Blame gettext-tools/gnulib-lib/fnmatch.c

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