root/maint/gnulib/lib/fnmatch.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. is_char_class
  2. fnmatch

   1 /* Copyright (C) 1991-2021 Free Software Foundation, Inc.
   2    This file is part of the GNU C Library.
   3 
   4    The GNU C Library is free software; you can redistribute it and/or
   5    modify it under the terms of the GNU Lesser General Public
   6    License as published by the Free Software Foundation; either
   7    version 2.1 of the License, or (at your option) any later version.
   8 
   9    The GNU C Library is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12    Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public
  15    License along with the GNU C Library; if not, see
  16    <https://www.gnu.org/licenses/>.  */
  17 
  18 #ifndef _LIBC
  19 # include <libc-config.h>
  20 #endif
  21 
  22 /* Enable GNU extensions in fnmatch.h.  */
  23 #ifndef _GNU_SOURCE
  24 # define _GNU_SOURCE    1
  25 #endif
  26 
  27 #include <fnmatch.h>
  28 
  29 #include <assert.h>
  30 #include <errno.h>
  31 #include <ctype.h>
  32 #include <string.h>
  33 #include <stdlib.h>
  34 #if defined _LIBC || HAVE_ALLOCA
  35 # include <alloca.h>
  36 #endif
  37 #include <wchar.h>
  38 #include <wctype.h>
  39 #include <stddef.h>
  40 #include <stdbool.h>
  41 
  42 /* We need some of the locale data (the collation sequence information)
  43    but there is no interface to get this information in general.  Therefore
  44    we support a correct implementation only in glibc.  */
  45 #ifdef _LIBC
  46 # include "../locale/localeinfo.h"
  47 # include "../locale/coll-lookup.h"
  48 # include <shlib-compat.h>
  49 
  50 # define CONCAT(a,b) __CONCAT(a,b)
  51 # define btowc __btowc
  52 # define iswctype __iswctype
  53 # define mbsrtowcs __mbsrtowcs
  54 # define mempcpy __mempcpy
  55 # define strnlen __strnlen
  56 # define towlower __towlower
  57 # define wcscat __wcscat
  58 # define wcslen __wcslen
  59 # define wctype __wctype
  60 # define wmemchr __wmemchr
  61 # define wmempcpy __wmempcpy
  62 # define fnmatch __fnmatch
  63 extern int fnmatch (const char *pattern, const char *string, int flags);
  64 #endif
  65 
  66 #ifdef _LIBC
  67 # if __GNUC__ >= 7
  68 #  define FALLTHROUGH __attribute__ ((__fallthrough__))
  69 # else
  70 #  define FALLTHROUGH ((void) 0)
  71 # endif
  72 #else
  73 # include "attribute.h"
  74 #endif
  75 
  76 #include <intprops.h>
  77 #include <flexmember.h>
  78 
  79 #ifdef _LIBC
  80 typedef ptrdiff_t idx_t;
  81 #else
  82 # include "idx.h"
  83 #endif
  84 
  85 /* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
  86 #define NO_LEADING_PERIOD(flags) \
  87   ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
  88 
  89 #ifndef _LIBC
  90 # if HAVE_ALLOCA
  91 /* The OS usually guarantees only one guard page at the bottom of the stack,
  92    and a page size can be as small as 4096 bytes.  So we cannot safely
  93    allocate anything larger than 4096 bytes.  Also care for the possibility
  94    of a few compiler-allocated temporary stack slots.  */
  95 #  define __libc_use_alloca(n) ((n) < 4032)
  96 # else
  97 /* Just use malloc.  */
  98 #  define __libc_use_alloca(n) false
  99 #  undef alloca
 100 #  define alloca(n) malloc (n)
 101 # endif
 102 # define alloca_account(size, avar) ((avar) += (size), alloca (size))
 103 #endif
 104 
 105 /* Provide support for user-defined character classes, based on the functions
 106    from ISO C 90 amendment 1.  */
 107 #ifdef CHARCLASS_NAME_MAX
 108 # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
 109 #else
 110 /* This shouldn't happen but some implementation might still have this
 111    problem.  Use a reasonable default value.  */
 112 # define CHAR_CLASS_MAX_LENGTH 256
 113 #endif
 114 
 115 #define IS_CHAR_CLASS(string) wctype (string)
 116 
 117 /* Avoid depending on library functions or files
 118    whose names are inconsistent.  */
 119 
 120 /* Global variable.  */
 121 static int posixly_correct;
 122 
 123 /* Note that this evaluates C many times.  */
 124 #define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
 125 #define CHAR    char
 126 #define UCHAR   unsigned char
 127 #define INT     int
 128 #define FCT     internal_fnmatch
 129 #define EXT     ext_match
 130 #define END     end_pattern
 131 #define STRUCT  fnmatch_struct
 132 #define L_(CS)  CS
 133 #define BTOWC(C) btowc (C)
 134 #define STRLEN(S) strlen (S)
 135 #define STRCAT(D, S) strcat (D, S)
 136 #define MEMPCPY(D, S, N) mempcpy (D, S, N)
 137 #define MEMCHR(S, C, N) memchr (S, C, N)
 138 #define WIDE_CHAR_VERSION 0
 139 #ifdef _LIBC
 140 # include <locale/weight.h>
 141 # define FINDIDX findidx
 142 #endif
 143 #include "fnmatch_loop.c"
 144 
 145 
 146 #define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
 147 #define CHAR    wchar_t
 148 #define UCHAR   wint_t
 149 #define INT     wint_t
 150 #define FCT     internal_fnwmatch
 151 #define EXT     ext_wmatch
 152 #define END     end_wpattern
 153 #define L_(CS)  L##CS
 154 #define BTOWC(C) (C)
 155 #define STRLEN(S) wcslen (S)
 156 #define STRCAT(D, S) wcscat (D, S)
 157 #define MEMPCPY(D, S, N) wmempcpy (D, S, N)
 158 #define MEMCHR(S, C, N) wmemchr (S, C, N)
 159 #define WIDE_CHAR_VERSION 1
 160 #ifdef _LIBC
 161 /* Change the name the header defines so it doesn't conflict with
 162    the <locale/weight.h> version included above.  */
 163 # define findidx findidxwc
 164 # include <locale/weightwc.h>
 165 # undef findidx
 166 # define FINDIDX findidxwc
 167 #endif
 168 
 169 #undef IS_CHAR_CLASS
 170 /* We have to convert the wide character string in a multibyte string.  But
 171    we know that the character class names consist of alphanumeric characters
 172    from the portable character set, and since the wide character encoding
 173    for a member of the portable character set is the same code point as
 174    its single-byte encoding, we can use a simplified method to convert the
 175    string to a multibyte character string.  */
 176 static wctype_t
 177 is_char_class (const wchar_t *wcs)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179   char s[CHAR_CLASS_MAX_LENGTH + 1];
 180   char *cp = s;
 181 
 182   do
 183     {
 184       /* Test for a printable character from the portable character set.  */
 185 #ifdef _LIBC
 186       if (*wcs < 0x20 || *wcs > 0x7e
 187           || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
 188         return (wctype_t) 0;
 189 #else
 190       switch (*wcs)
 191         {
 192         case L' ': case L'!': case L'"': case L'#': case L'%':
 193         case L'&': case L'\'': case L'(': case L')': case L'*':
 194         case L'+': case L',': case L'-': case L'.': case L'/':
 195         case L'0': case L'1': case L'2': case L'3': case L'4':
 196         case L'5': case L'6': case L'7': case L'8': case L'9':
 197         case L':': case L';': case L'<': case L'=': case L'>':
 198         case L'?':
 199         case L'A': case L'B': case L'C': case L'D': case L'E':
 200         case L'F': case L'G': case L'H': case L'I': case L'J':
 201         case L'K': case L'L': case L'M': case L'N': case L'O':
 202         case L'P': case L'Q': case L'R': case L'S': case L'T':
 203         case L'U': case L'V': case L'W': case L'X': case L'Y':
 204         case L'Z':
 205         case L'[': case L'\\': case L']': case L'^': case L'_':
 206         case L'a': case L'b': case L'c': case L'd': case L'e':
 207         case L'f': case L'g': case L'h': case L'i': case L'j':
 208         case L'k': case L'l': case L'm': case L'n': case L'o':
 209         case L'p': case L'q': case L'r': case L's': case L't':
 210         case L'u': case L'v': case L'w': case L'x': case L'y':
 211         case L'z': case L'{': case L'|': case L'}': case L'~':
 212           break;
 213         default:
 214           return (wctype_t) 0;
 215         }
 216 #endif
 217 
 218       /* Avoid overrunning the buffer.  */
 219       if (cp == s + CHAR_CLASS_MAX_LENGTH)
 220         return (wctype_t) 0;
 221 
 222       *cp++ = (char) *wcs++;
 223     }
 224   while (*wcs != L'\0');
 225 
 226   *cp = '\0';
 227 
 228   return wctype (s);
 229 }
 230 #define IS_CHAR_CLASS(string) is_char_class (string)
 231 
 232 #include "fnmatch_loop.c"
 233 
 234 
 235 int
 236 fnmatch (const char *pattern, const char *string, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238   if (__glibc_unlikely (MB_CUR_MAX != 1))
 239     {
 240       mbstate_t ps;
 241       size_t n;
 242       const char *p;
 243       wchar_t *wpattern_malloc = NULL;
 244       wchar_t *wpattern;
 245       wchar_t *wstring_malloc = NULL;
 246       wchar_t *wstring;
 247       size_t alloca_used = 0;
 248 
 249       /* Convert the strings into wide characters.  */
 250       memset (&ps, '\0', sizeof (ps));
 251       p = pattern;
 252       n = strnlen (pattern, 1024);
 253       if (__glibc_likely (n < 1024))
 254         {
 255           wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
 256                                                  alloca_used);
 257           n = mbsrtowcs (wpattern, &p, n + 1, &ps);
 258           if (__glibc_unlikely (n == (size_t) -1))
 259             /* Something wrong.
 260                XXX Do we have to set 'errno' to something which mbsrtows hasn't
 261                already done?  */
 262             return -1;
 263           if (p)
 264             {
 265               memset (&ps, '\0', sizeof (ps));
 266               goto prepare_wpattern;
 267             }
 268         }
 269       else
 270         {
 271         prepare_wpattern:
 272           n = mbsrtowcs (NULL, &pattern, 0, &ps);
 273           if (__glibc_unlikely (n == (size_t) -1))
 274             /* Something wrong.
 275                XXX Do we have to set 'errno' to something which mbsrtows hasn't
 276                already done?  */
 277             return -1;
 278           if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
 279             {
 280               __set_errno (ENOMEM);
 281               return -2;
 282             }
 283           wpattern_malloc = wpattern
 284             = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
 285           assert (mbsinit (&ps));
 286           if (wpattern == NULL)
 287             return -2;
 288           (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
 289         }
 290 
 291       assert (mbsinit (&ps));
 292       n = strnlen (string, 1024);
 293       p = string;
 294       if (__glibc_likely (n < 1024))
 295         {
 296           wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
 297                                                 alloca_used);
 298           n = mbsrtowcs (wstring, &p, n + 1, &ps);
 299           if (__glibc_unlikely (n == (size_t) -1))
 300             {
 301               /* Something wrong.
 302                  XXX Do we have to set 'errno' to something which
 303                  mbsrtows hasn't already done?  */
 304             free_return:
 305               free (wpattern_malloc);
 306               return -1;
 307             }
 308           if (p)
 309             {
 310               memset (&ps, '\0', sizeof (ps));
 311               goto prepare_wstring;
 312             }
 313         }
 314       else
 315         {
 316         prepare_wstring:
 317           n = mbsrtowcs (NULL, &string, 0, &ps);
 318           if (__glibc_unlikely (n == (size_t) -1))
 319             /* Something wrong.
 320                XXX Do we have to set 'errno' to something which mbsrtows hasn't
 321                already done?  */
 322             goto free_return;
 323           if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
 324             {
 325               free (wpattern_malloc);
 326               __set_errno (ENOMEM);
 327               return -2;
 328             }
 329 
 330           wstring_malloc = wstring
 331             = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
 332           if (wstring == NULL)
 333             {
 334               free (wpattern_malloc);
 335               return -2;
 336             }
 337           assert (mbsinit (&ps));
 338           (void) mbsrtowcs (wstring, &string, n + 1, &ps);
 339         }
 340 
 341       int res = internal_fnwmatch (wpattern, wstring, wstring + n,
 342                                    flags & FNM_PERIOD, flags, NULL,
 343                                    alloca_used);
 344 
 345       free (wstring_malloc);
 346       free (wpattern_malloc);
 347 
 348       return res;
 349     }
 350 
 351   return internal_fnmatch (pattern, string, string + strlen (string),
 352                            flags & FNM_PERIOD, flags, NULL, 0);
 353 }
 354 
 355 #undef fnmatch
 356 versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
 357 #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
 358 strong_alias (__fnmatch, __fnmatch_old)
 359 compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
 360 #endif
 361 libc_hidden_ver (__fnmatch, fnmatch)

/* [previous][next][first][last][top][bottom][index][help] */