* [PATCH 1/5] posix: Sync regex code with gnulib
@ 2020-12-30 20:15 Adhemerval Zanella
2020-12-30 20:15 ` [PATCH 2/5] posix: Sync glob " Adhemerval Zanella
` (5 more replies)
0 siblings, 6 replies; 22+ messages in thread
From: Adhemerval Zanella @ 2020-12-30 20:15 UTC (permalink / raw)
To: libc-alpha, Paul Eggert; +Cc: bug-gnulib
It sync with gnulib commit 43ee1a6bf. The main change is 9682f18e9.
(which does not have a meaniful description).
Checked on x86_64-linux-gnu.
---
posix/regcomp.c | 2 +-
posix/regex.h | 17 ++++++++++++-----
posix/regex_internal.c | 19 ++++++++++---------
posix/regex_internal.h | 16 ++++++++++++----
4 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/posix/regcomp.c b/posix/regcomp.c
index 93bb0a0538..692928b0db 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -558,7 +558,7 @@ weak_alias (__regerror, regerror)
static const bitset_t utf8_sb_map =
{
/* Set the first 128 bits. */
-# if defined __GNUC__ && !defined __STRICT_ANSI__
+# if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__
[0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
# else
# if 4 * BITSET_WORD_BITS < ASCII_CHARS
diff --git a/posix/regex.h b/posix/regex.h
index 5fe41c8685..7418e6c76f 100644
--- a/posix/regex.h
+++ b/posix/regex.h
@@ -612,7 +612,9 @@ extern int re_exec (const char *);
'configure' might #define 'restrict' to those words, so pick a
different name. */
#ifndef _Restrict_
-# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
+# if defined __restrict \
+ || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \
+ || __clang_major__ >= 3
# define _Restrict_ __restrict
# elif 199901L <= __STDC_VERSION__ || defined restrict
# define _Restrict_ restrict
@@ -620,13 +622,18 @@ extern int re_exec (const char *);
# define _Restrict_
# endif
#endif
-/* For [restrict], use glibc's __restrict_arr if available.
- Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict]. */
+/* For the ISO C99 syntax
+ array_name[restrict]
+ use glibc's __restrict_arr if available.
+ Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode).
+ Other ISO C99 compilers support it as well. */
#ifndef _Restrict_arr_
# ifdef __restrict_arr
# define _Restrict_arr_ __restrict_arr
-# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \
- && !defined __GNUG__)
+# elif ((199901L <= __STDC_VERSION__ \
+ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \
+ || __clang_major__ >= 3) \
+ && !defined __cplusplus)
# define _Restrict_arr_ _Restrict_
# else
# define _Restrict_arr_
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index e1b6b4d5af..ed0a13461b 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -300,18 +300,20 @@ build_wcs_upper_buffer (re_string_t *pstr)
while (byte_idx < end_idx)
{
wchar_t wc;
+ unsigned char ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
- if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
- && mbsinit (&pstr->cur_state))
+ if (isascii (ch) && mbsinit (&pstr->cur_state))
{
- /* In case of a singlebyte character. */
- pstr->mbs[byte_idx]
- = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
/* The next step uses the assumption that wchar_t is encoded
ASCII-safe: all ASCII values can be converted like this. */
- pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
- ++byte_idx;
- continue;
+ wchar_t wcu = __towupper (ch);
+ if (isascii (wcu))
+ {
+ pstr->mbs[byte_idx] = wcu;
+ pstr->wcs[byte_idx] = wcu;
+ byte_idx++;
+ continue;
+ }
}
remain_len = end_idx - byte_idx;
@@ -348,7 +350,6 @@ build_wcs_upper_buffer (re_string_t *pstr)
{
/* It is an invalid character, an incomplete character
at the end of the string, or '\0'. Just use the byte. */
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
pstr->mbs[byte_idx] = ch;
/* And also cast it to wide char. */
pstr->wcs[byte_idx++] = (wchar_t) ch;
diff --git a/posix/regex_internal.h b/posix/regex_internal.h
index 8c42586c42..4a3cf779bf 100644
--- a/posix/regex_internal.h
+++ b/posix/regex_internal.h
@@ -77,6 +77,14 @@
# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
#endif
+/* regex code assumes isascii has its usual numeric meaning,
+ even if the portable character set uses EBCDIC encoding,
+ and even if wint_t is wider than int. */
+#ifndef _LIBC
+# undef isascii
+# define isascii(c) (((c) & ~0x7f) == 0)
+#endif
+
#ifdef _LIBC
# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
# define _RE_DEFINE_LOCALE_FUNCTIONS 1
@@ -335,7 +343,7 @@ typedef struct
Idx idx; /* for BACK_REF */
re_context_type ctx_type; /* for ANCHOR */
} opr;
-#if __GNUC__ >= 2 && !defined __STRICT_ANSI__
+#if (__GNUC__ >= 2 || defined __clang__) && !defined __STRICT_ANSI__
re_token_type_t type : 8;
#else
re_token_type_t type;
@@ -841,10 +849,10 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
#endif /* RE_ENABLE_I18N */
#ifndef FALLTHROUGH
-# if __GNUC__ < 7
-# define FALLTHROUGH ((void) 0)
-# else
+# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
# define FALLTHROUGH __attribute__ ((__fallthrough__))
+# else
+# define FALLTHROUGH ((void) 0)
# endif
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 2/5] posix: Sync glob code with gnulib
2020-12-30 20:15 [PATCH 1/5] posix: Sync regex code with gnulib Adhemerval Zanella
@ 2020-12-30 20:15 ` Adhemerval Zanella
2020-12-31 21:47 ` Paul Eggert
2020-12-30 20:15 ` [PATCH 3/5] Sync intprops.h " Adhemerval Zanella
` (4 subsequent siblings)
5 siblings, 1 reply; 22+ messages in thread
From: Adhemerval Zanella @ 2020-12-30 20:15 UTC (permalink / raw)
To: libc-alpha, Paul Eggert; +Cc: bug-gnulib
It sync with gnulib commit 43ee1a6bf and fixes and use-after-free
bug (gnulib commit 717766da8926e36). The main change over gnulib
is:
--- posix/glob.c
+++ lib/glob.c
@@ -59,6 +59,12 @@
# define readdir(str) __readdir64 (str)
# define getpwnam_r(name, bufp, buf, len, res) \
__getpwnam_r (name, bufp, buf, len, res)
+# ifndef __lstat64
+# define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
+# endif
+# ifndef __stat64
+# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
+# endif
# define struct_stat64 struct stat64
# define FLEXIBLE_ARRAY_MEMBER
# include <shlib-compat.h>
Which is required since xstat symbols are not used internally anymore.
Checked on x86_64-linux-gnu.
---
posix/glob.c | 1748 ++++++++++++++++++++--------------------
posix/glob_pattern_p.c | 2 +-
posix/globfree.c | 2 +-
3 files changed, 886 insertions(+), 866 deletions(-)
diff --git a/posix/glob.c b/posix/glob.c
index b4b34945e2..20239f780f 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -15,6 +15,16 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
+ optimizes away the pattern == NULL test below. */
+# define _GL_ARG_NONNULL(params)
+
+# include <config.h>
+
+#endif
+
#include <glob.h>
#include <errno.h>
@@ -26,7 +36,7 @@
#include <assert.h>
#include <unistd.h>
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
# define WINDOWS32
#endif
@@ -49,14 +59,19 @@
# define readdir(str) __readdir64 (str)
# define getpwnam_r(name, bufp, buf, len, res) \
__getpwnam_r (name, bufp, buf, len, res)
-# define struct_stat64 struct stat64
+# define struct_stat64 struct stat64
# define FLEXIBLE_ARRAY_MEMBER
# include <shlib-compat.h>
#else /* !_LIBC */
# define __glob glob
# define __getlogin_r(buf, len) getlogin_r (buf, len)
# define __lstat64(fname, buf) lstat (fname, buf)
+# if defined _WIN32 && !defined __CYGWIN__
+ /* Avoid GCC or clang warning. The original __stat64 macro is unused. */
+# undef __stat64
+# endif
# define __stat64(fname, buf) stat (fname, buf)
+# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
# define struct_stat64 struct stat
# ifndef __MVS__
# define __alloca alloca
@@ -73,7 +88,9 @@
\f
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
-typedef uint_fast8_t dirent_type;
+/* The type of ((struct dirent *) 0)->d_type is 'unsigned char' on most
+ platforms, but 'unsigned int' in the mingw from mingw.org. */
+typedef uint_fast32_t dirent_type;
#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
/* Any distinct values will do here.
@@ -112,9 +129,9 @@ readdir_result_type (struct readdir_result d)
/* Construct an initializer for a struct readdir_result object from a
struct dirent *. No copy of the name is made. */
#define READDIR_RESULT_INITIALIZER(source) \
- { \
- source->d_name, \
- D_TYPE_TO_RESULT (source) \
+ { \
+ source->d_name, \
+ D_TYPE_TO_RESULT (source) \
}
/* Call gl_readdir on STREAM. This macro can be overridden to reduce
@@ -204,7 +221,7 @@ glob_lstat (glob_t *pglob, int flags, const char *fullname)
static bool
size_add_wrapv (size_t a, size_t b, size_t *r)
{
-#if 5 <= __GNUC__ && !defined __ICC
+#if 7 <= __GNUC__ && !defined __ICC
return __builtin_add_overflow (a, b, r);
#else
*r = a + b;
@@ -221,8 +238,8 @@ glob_use_alloca (size_t alloca_used, size_t len)
}
static int glob_in_dir (const char *pattern, const char *directory,
- int flags, int (*errfunc) (const char *, int),
- glob_t *pglob, size_t alloca_used);
+ int flags, int (*errfunc) (const char *, int),
+ glob_t *pglob, size_t alloca_used);
static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
static int collated_compare (const void *, const void *) __THROWNL;
@@ -247,17 +264,17 @@ next_brace_sub (const char *cp, int flags)
while (*cp != '\0')
if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\')
{
- if (*++cp == '\0')
- break;
- ++cp;
+ if (*++cp == '\0')
+ break;
+ ++cp;
}
else
{
- if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
- break;
+ if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
+ break;
- if (*cp++ == '{')
- depth++;
+ if (*cp++ == '{')
+ depth++;
}
return *cp != '\0' ? cp : NULL;
@@ -278,7 +295,7 @@ next_brace_sub (const char *cp, int flags)
int
GLOB_ATTRIBUTE
__glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
- glob_t *pglob)
+ glob_t *pglob)
{
const char *filename;
char *dirname = NULL;
@@ -312,22 +329,22 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
pglob->gl_pathc = 0;
if (!(flags & GLOB_DOOFFS))
- pglob->gl_pathv = NULL;
+ pglob->gl_pathv = NULL;
else
- {
- size_t i;
+ {
+ size_t i;
- if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
- return GLOB_NOSPACE;
+ if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
+ return GLOB_NOSPACE;
- pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
- * sizeof (char *));
- if (pglob->gl_pathv == NULL)
- return GLOB_NOSPACE;
+ pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
+ * sizeof (char *));
+ if (pglob->gl_pathv == NULL)
+ return GLOB_NOSPACE;
- for (i = 0; i <= pglob->gl_offs; ++i)
- pglob->gl_pathv[i] = NULL;
- }
+ for (i = 0; i <= pglob->gl_offs; ++i)
+ pglob->gl_pathv[i] = NULL;
+ }
}
if (flags & GLOB_BRACE)
@@ -335,129 +352,129 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
const char *begin;
if (flags & GLOB_NOESCAPE)
- begin = strchr (pattern, '{');
+ begin = strchr (pattern, '{');
else
- {
- begin = pattern;
- while (1)
- {
- if (*begin == '\0')
- {
- begin = NULL;
- break;
- }
-
- if (*begin == '\\' && begin[1] != '\0')
- ++begin;
- else if (*begin == '{')
- break;
-
- ++begin;
- }
- }
+ {
+ begin = pattern;
+ while (1)
+ {
+ if (*begin == '\0')
+ {
+ begin = NULL;
+ break;
+ }
+
+ if (*begin == '\\' && begin[1] != '\0')
+ ++begin;
+ else if (*begin == '{')
+ break;
+
+ ++begin;
+ }
+ }
if (begin != NULL)
- {
- /* Allocate working buffer large enough for our work. Note that
- we have at least an opening and closing brace. */
- size_t firstc;
- char *alt_start;
- const char *p;
- const char *next;
- const char *rest;
- size_t rest_len;
- char *onealt;
- size_t pattern_len = strlen (pattern) - 1;
- int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
- if (alloca_onealt)
- onealt = alloca_account (pattern_len, alloca_used);
- else
- {
- onealt = malloc (pattern_len);
- if (onealt == NULL)
- return GLOB_NOSPACE;
- }
-
- /* We know the prefix for all sub-patterns. */
- alt_start = mempcpy (onealt, pattern, begin - pattern);
-
- /* Find the first sub-pattern and at the same time find the
- rest after the closing brace. */
- next = next_brace_sub (begin + 1, flags);
- if (next == NULL)
- {
- /* It is an invalid expression. */
- illegal_brace:
- if (__glibc_unlikely (!alloca_onealt))
- free (onealt);
- flags &= ~GLOB_BRACE;
- goto no_brace;
- }
-
- /* Now find the end of the whole brace expression. */
- rest = next;
- while (*rest != '}')
- {
- rest = next_brace_sub (rest + 1, flags);
- if (rest == NULL)
- /* It is an illegal expression. */
- goto illegal_brace;
- }
- /* Please note that we now can be sure the brace expression
- is well-formed. */
- rest_len = strlen (++rest) + 1;
-
- /* We have a brace expression. BEGIN points to the opening {,
- NEXT points past the terminator of the first element, and END
- points past the final }. We will accumulate result names from
- recursive runs for each brace alternative in the buffer using
- GLOB_APPEND. */
- firstc = pglob->gl_pathc;
-
- p = begin + 1;
- while (1)
- {
- int result;
-
- /* Construct the new glob expression. */
- mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
-
- result = __glob (onealt,
- ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
- | GLOB_APPEND),
- errfunc, pglob);
-
- /* If we got an error, return it. */
- if (result && result != GLOB_NOMATCH)
- {
- if (__glibc_unlikely (!alloca_onealt))
- free (onealt);
- if (!(flags & GLOB_APPEND))
- {
- globfree (pglob);
- pglob->gl_pathc = 0;
- }
- return result;
- }
-
- if (*next == '}')
- /* We saw the last entry. */
- break;
-
- p = next + 1;
- next = next_brace_sub (p, flags);
- assert (next != NULL);
- }
-
- if (__glibc_unlikely (!alloca_onealt))
- free (onealt);
-
- if (pglob->gl_pathc != firstc)
- /* We found some entries. */
- return 0;
- else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
- return GLOB_NOMATCH;
- }
+ {
+ /* Allocate working buffer large enough for our work. Note that
+ we have at least an opening and closing brace. */
+ size_t firstc;
+ char *alt_start;
+ const char *p;
+ const char *next;
+ const char *rest;
+ size_t rest_len;
+ char *onealt;
+ size_t pattern_len = strlen (pattern) - 1;
+ int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
+ if (alloca_onealt)
+ onealt = alloca_account (pattern_len, alloca_used);
+ else
+ {
+ onealt = malloc (pattern_len);
+ if (onealt == NULL)
+ return GLOB_NOSPACE;
+ }
+
+ /* We know the prefix for all sub-patterns. */
+ alt_start = mempcpy (onealt, pattern, begin - pattern);
+
+ /* Find the first sub-pattern and at the same time find the
+ rest after the closing brace. */
+ next = next_brace_sub (begin + 1, flags);
+ if (next == NULL)
+ {
+ /* It is an invalid expression. */
+ illegal_brace:
+ if (__glibc_unlikely (!alloca_onealt))
+ free (onealt);
+ flags &= ~GLOB_BRACE;
+ goto no_brace;
+ }
+
+ /* Now find the end of the whole brace expression. */
+ rest = next;
+ while (*rest != '}')
+ {
+ rest = next_brace_sub (rest + 1, flags);
+ if (rest == NULL)
+ /* It is an illegal expression. */
+ goto illegal_brace;
+ }
+ /* Please note that we now can be sure the brace expression
+ is well-formed. */
+ rest_len = strlen (++rest) + 1;
+
+ /* We have a brace expression. BEGIN points to the opening {,
+ NEXT points past the terminator of the first element, and END
+ points past the final }. We will accumulate result names from
+ recursive runs for each brace alternative in the buffer using
+ GLOB_APPEND. */
+ firstc = pglob->gl_pathc;
+
+ p = begin + 1;
+ while (1)
+ {
+ int result;
+
+ /* Construct the new glob expression. */
+ mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
+
+ result = __glob (onealt,
+ ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
+ | GLOB_APPEND),
+ errfunc, pglob);
+
+ /* If we got an error, return it. */
+ if (result && result != GLOB_NOMATCH)
+ {
+ if (__glibc_unlikely (!alloca_onealt))
+ free (onealt);
+ if (!(flags & GLOB_APPEND))
+ {
+ globfree (pglob);
+ pglob->gl_pathc = 0;
+ }
+ return result;
+ }
+
+ if (*next == '}')
+ /* We saw the last entry. */
+ break;
+
+ p = next + 1;
+ next = next_brace_sub (p, flags);
+ assert (next != NULL);
+ }
+
+ if (__glibc_unlikely (!alloca_onealt))
+ free (onealt);
+
+ if (pglob->gl_pathc != firstc)
+ /* We found some entries. */
+ return 0;
+ else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
+ return GLOB_NOMATCH;
+ }
}
no_brace:
@@ -479,33 +496,33 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (filename == NULL)
{
/* This can mean two things: a simple name or "~name". The latter
- case is nothing but a notation for a directory. */
+ case is nothing but a notation for a directory. */
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
- {
- dirname = (char *) pattern;
- dirlen = strlen (pattern);
-
- /* Set FILENAME to NULL as a special flag. This is ugly but
- other solutions would require much more code. We test for
- this special case below. */
- filename = NULL;
- }
+ {
+ dirname = (char *) pattern;
+ dirlen = strlen (pattern);
+
+ /* Set FILENAME to NULL as a special flag. This is ugly but
+ other solutions would require much more code. We test for
+ this special case below. */
+ filename = NULL;
+ }
else
- {
- if (__glibc_unlikely (pattern[0] == '\0'))
- {
- dirs.gl_pathv = NULL;
- goto no_matches;
- }
-
- filename = pattern;
- dirname = (char *) ".";
- dirlen = 0;
- }
+ {
+ if (__glibc_unlikely (pattern[0] == '\0'))
+ {
+ dirs.gl_pathv = NULL;
+ goto no_matches;
+ }
+
+ filename = pattern;
+ dirname = (char *) ".";
+ dirlen = 0;
+ }
}
else if (filename == pattern
- || (filename == pattern + 1 && pattern[0] == '\\'
- && (flags & GLOB_NOESCAPE) == 0))
+ || (filename == pattern + 1 && pattern[0] == '\\'
+ && (flags & GLOB_NOESCAPE) == 0))
{
/* "/pattern" or "\\/pattern". */
dirname = (char *) "/";
@@ -518,32 +535,32 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
dirlen = filename - pattern;
#if defined __MSDOS__ || defined WINDOWS32
if (*filename == ':'
- || (filename > pattern + 1 && filename[-1] == ':'))
- {
- char *drive_spec;
-
- ++dirlen;
- drive_spec = __alloca (dirlen + 1);
- *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
- /* For now, disallow wildcards in the drive spec, to
- prevent infinite recursion in glob. */
- if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
- return GLOB_NOMATCH;
- /* If this is "d:pattern", we need to copy ':' to DIRNAME
- as well. If it's "d:/pattern", don't remove the slash
- from "d:/", since "d:" and "d:/" are not the same.*/
- }
+ || (filename > pattern + 1 && filename[-1] == ':'))
+ {
+ char *drive_spec;
+
+ ++dirlen;
+ drive_spec = __alloca (dirlen + 1);
+ *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
+ /* For now, disallow wildcards in the drive spec, to
+ prevent infinite recursion in glob. */
+ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
+ return GLOB_NOMATCH;
+ /* If this is "d:pattern", we need to copy ':' to DIRNAME
+ as well. If it's "d:/pattern", don't remove the slash
+ from "d:/", since "d:" and "d:/" are not the same.*/
+ }
#endif
if (glob_use_alloca (alloca_used, dirlen + 1))
- newp = alloca_account (dirlen + 1, alloca_used);
+ newp = alloca_account (dirlen + 1, alloca_used);
else
- {
- newp = malloc (dirlen + 1);
- if (newp == NULL)
- return GLOB_NOSPACE;
- malloc_dirname = 1;
- }
+ {
+ newp = malloc (dirlen + 1);
+ if (newp == NULL)
+ return GLOB_NOSPACE;
+ malloc_dirname = 1;
+ }
*((char *) mempcpy (newp, pattern, dirlen)) = '\0';
dirname = newp;
++filename;
@@ -559,363 +576,366 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (filename[0] == '\0' && dirlen > 1 && !drive_root)
/* "pattern/". Expand "pattern", appending slashes. */
- {
- int orig_flags = flags;
- if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
- {
- /* "pattern\\/". Remove the final backslash if it hasn't
- been quoted. */
- char *p = (char *) &dirname[dirlen - 1];
-
- while (p > dirname && p[-1] == '\\') --p;
- if ((&dirname[dirlen] - p) & 1)
- {
- *(char *) &dirname[--dirlen] = '\0';
- flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
- }
- }
- int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
- if (val == 0)
- pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
- | (flags & GLOB_MARK));
- else if (val == GLOB_NOMATCH && flags != orig_flags)
- {
- /* Make sure globfree (&dirs); is a nop. */
- dirs.gl_pathv = NULL;
- flags = orig_flags;
- oldcount = pglob->gl_pathc + pglob->gl_offs;
- goto no_matches;
- }
- retval = val;
- goto out;
- }
+ {
+ int orig_flags = flags;
+ if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
+ {
+ /* "pattern\\/". Remove the final backslash if it hasn't
+ been quoted. */
+ char *p = (char *) &dirname[dirlen - 1];
+
+ while (p > dirname && p[-1] == '\\') --p;
+ if ((&dirname[dirlen] - p) & 1)
+ {
+ *(char *) &dirname[--dirlen] = '\0';
+ flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
+ }
+ }
+ int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+ if (val == 0)
+ pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
+ | (flags & GLOB_MARK));
+ else if (val == GLOB_NOMATCH && flags != orig_flags)
+ {
+ /* Make sure globfree (&dirs); is a nop. */
+ dirs.gl_pathv = NULL;
+ flags = orig_flags;
+ oldcount = pglob->gl_pathc + pglob->gl_offs;
+ goto no_matches;
+ }
+ retval = val;
+ goto out;
+ }
}
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
{
if (dirname[1] == '\0' || dirname[1] == '/'
- || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
- && (dirname[2] == '\0' || dirname[2] == '/')))
- {
- /* Look up home directory. */
- char *home_dir = getenv ("HOME");
- int malloc_home_dir = 0;
- if (home_dir == NULL || home_dir[0] == '\0')
- {
+ || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\'
+ && (dirname[2] == '\0' || dirname[2] == '/')))
+ {
+ /* Look up home directory. */
+ char *home_dir = getenv ("HOME");
+ int malloc_home_dir = 0;
+ if (home_dir == NULL || home_dir[0] == '\0')
+ {
#ifdef WINDOWS32
- /* Windows NT defines HOMEDRIVE and HOMEPATH. But give
- preference to HOME, because the user can change HOME. */
- const char *home_drive = getenv ("HOMEDRIVE");
- const char *home_path = getenv ("HOMEPATH");
-
- if (home_drive != NULL && home_path != NULL)
- {
- size_t home_drive_len = strlen (home_drive);
- size_t home_path_len = strlen (home_path);
- char *mem = alloca (home_drive_len + home_path_len + 1);
-
- memcpy (mem, home_drive, home_drive_len);
- memcpy (mem + home_drive_len, home_path, home_path_len + 1);
- home_dir = mem;
- }
- else
- home_dir = "c:/users/default"; /* poor default */
+ /* Windows NT defines HOMEDRIVE and HOMEPATH. But give
+ preference to HOME, because the user can change HOME. */
+ const char *home_drive = getenv ("HOMEDRIVE");
+ const char *home_path = getenv ("HOMEPATH");
+
+ if (home_drive != NULL && home_path != NULL)
+ {
+ size_t home_drive_len = strlen (home_drive);
+ size_t home_path_len = strlen (home_path);
+ char *mem = alloca (home_drive_len + home_path_len + 1);
+
+ memcpy (mem, home_drive, home_drive_len);
+ memcpy (mem + home_drive_len, home_path, home_path_len + 1);
+ home_dir = mem;
+ }
+ else
+ home_dir = "c:/users/default"; /* poor default */
#else
- int err;
- struct passwd *p;
- struct passwd pwbuf;
- struct scratch_buffer s;
- scratch_buffer_init (&s);
- while (true)
- {
- p = NULL;
- err = __getlogin_r (s.data, s.length);
- if (err == 0)
- {
+ int err;
+ struct passwd *p;
+ struct passwd pwbuf;
+ struct scratch_buffer s;
+ scratch_buffer_init (&s);
+ while (true)
+ {
+ p = NULL;
+ err = __getlogin_r (s.data, s.length);
+ if (err == 0)
+ {
# if defined HAVE_GETPWNAM_R || defined _LIBC
- size_t ssize = strlen (s.data) + 1;
- char *sdata = s.data;
- err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
- s.length - ssize, &p);
+ size_t ssize = strlen (s.data) + 1;
+ char *sdata = s.data;
+ err = getpwnam_r (sdata, &pwbuf, sdata + ssize,
+ s.length - ssize, &p);
# else
- p = getpwnam (s.data);
- if (p == NULL)
- err = errno;
+ p = getpwnam (s.data);
+ if (p == NULL)
+ err = errno;
# endif
- }
- if (err != ERANGE)
- break;
- if (!scratch_buffer_grow (&s))
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
- }
- if (err == 0)
- {
- home_dir = strdup (p->pw_dir);
- malloc_home_dir = 1;
- }
- scratch_buffer_free (&s);
- if (err == 0 && home_dir == NULL)
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
+ }
+ if (err != ERANGE)
+ break;
+ if (!scratch_buffer_grow (&s))
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ }
+ if (err == 0)
+ {
+ home_dir = strdup (p->pw_dir);
+ malloc_home_dir = 1;
+ }
+ scratch_buffer_free (&s);
+ if (err == 0 && home_dir == NULL)
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
#endif /* WINDOWS32 */
- }
- if (home_dir == NULL || home_dir[0] == '\0')
- {
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
- if (flags & GLOB_TILDE_CHECK)
- {
- retval = GLOB_NOMATCH;
- goto out;
- }
- else
- {
- home_dir = (char *) "~"; /* No luck. */
- malloc_home_dir = 0;
- }
- }
- /* Now construct the full directory. */
- if (dirname[1] == '\0')
- {
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
-
- dirname = home_dir;
- dirlen = strlen (dirname);
- malloc_dirname = malloc_home_dir;
- }
- else
- {
- char *newp;
- size_t home_len = strlen (home_dir);
- int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
- if (use_alloca)
- newp = alloca_account (home_len + dirlen, alloca_used);
- else
- {
- newp = malloc (home_len + dirlen);
- if (newp == NULL)
- {
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
- retval = GLOB_NOSPACE;
- goto out;
- }
- }
-
- mempcpy (mempcpy (newp, home_dir, home_len),
- &dirname[1], dirlen);
-
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
-
- dirname = newp;
- dirlen += home_len - 1;
- malloc_dirname = !use_alloca;
-
- if (__glibc_unlikely (malloc_home_dir))
- free (home_dir);
- }
- dirname_modified = 1;
- }
+ }
+ if (home_dir == NULL || home_dir[0] == '\0')
+ {
+ if (__glibc_unlikely (malloc_home_dir))
+ free (home_dir);
+ if (flags & GLOB_TILDE_CHECK)
+ {
+ retval = GLOB_NOMATCH;
+ goto out;
+ }
+ else
+ {
+ home_dir = (char *) "~"; /* No luck. */
+ malloc_home_dir = 0;
+ }
+ }
+ /* Now construct the full directory. */
+ if (dirname[1] == '\0')
+ {
+ if (__glibc_unlikely (malloc_dirname))
+ free (dirname);
+
+ dirname = home_dir;
+ dirlen = strlen (dirname);
+ malloc_dirname = malloc_home_dir;
+ }
+ else
+ {
+ char *newp;
+ size_t home_len = strlen (home_dir);
+ int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
+ if (use_alloca)
+ newp = alloca_account (home_len + dirlen, alloca_used);
+ else
+ {
+ newp = malloc (home_len + dirlen);
+ if (newp == NULL)
+ {
+ if (__glibc_unlikely (malloc_home_dir))
+ free (home_dir);
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ }
+
+ mempcpy (mempcpy (newp, home_dir, home_len),
+ &dirname[1], dirlen);
+
+ if (__glibc_unlikely (malloc_dirname))
+ free (dirname);
+
+ dirname = newp;
+ dirlen += home_len - 1;
+ malloc_dirname = !use_alloca;
+
+ if (__glibc_unlikely (malloc_home_dir))
+ free (home_dir);
+ }
+ dirname_modified = 1;
+ }
else
- {
+ {
#ifndef WINDOWS32
- char *end_name = strchr (dirname, '/');
- char *user_name;
- int malloc_user_name = 0;
- char *unescape = NULL;
-
- if (!(flags & GLOB_NOESCAPE))
- {
- if (end_name == NULL)
- {
- unescape = strchr (dirname, '\\');
- if (unescape)
- end_name = strchr (unescape, '\0');
- }
- else
- unescape = memchr (dirname, '\\', end_name - dirname);
- }
- if (end_name == NULL)
- user_name = dirname + 1;
- else
- {
- char *newp;
- if (glob_use_alloca (alloca_used, end_name - dirname))
- newp = alloca_account (end_name - dirname, alloca_used);
- else
- {
- newp = malloc (end_name - dirname);
- if (newp == NULL)
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
- malloc_user_name = 1;
- }
- if (unescape != NULL)
- {
- char *p = mempcpy (newp, dirname + 1,
- unescape - dirname - 1);
- char *q = unescape;
- while (q != end_name)
- {
- if (*q == '\\')
- {
- if (q + 1 == end_name)
- {
- /* "~fo\\o\\" unescape to user_name "foo\\",
- but "~fo\\o\\/" unescape to user_name
- "foo". */
- if (filename == NULL)
- *p++ = '\\';
- break;
- }
- ++q;
- }
- *p++ = *q++;
- }
- *p = '\0';
- }
- else
- *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
- = '\0';
- user_name = newp;
- }
-
- /* Look up specific user's home directory. */
- {
- struct passwd *p;
- struct scratch_buffer pwtmpbuf;
- scratch_buffer_init (&pwtmpbuf);
+ char *end_name = strchr (dirname, '/');
+ char *user_name;
+ int malloc_user_name = 0;
+ char *unescape = NULL;
+
+ if (!(flags & GLOB_NOESCAPE))
+ {
+ if (end_name == NULL)
+ {
+ unescape = strchr (dirname, '\\');
+ if (unescape)
+ end_name = strchr (unescape, '\0');
+ }
+ else
+ unescape = memchr (dirname, '\\', end_name - dirname);
+ }
+ if (end_name == NULL)
+ user_name = dirname + 1;
+ else
+ {
+ char *newp;
+ if (glob_use_alloca (alloca_used, end_name - dirname))
+ newp = alloca_account (end_name - dirname, alloca_used);
+ else
+ {
+ newp = malloc (end_name - dirname);
+ if (newp == NULL)
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ malloc_user_name = 1;
+ }
+ if (unescape != NULL)
+ {
+ char *p = mempcpy (newp, dirname + 1,
+ unescape - dirname - 1);
+ char *q = unescape;
+ while (q != end_name)
+ {
+ if (*q == '\\')
+ {
+ if (q + 1 == end_name)
+ {
+ /* "~fo\\o\\" unescape to user_name "foo\\",
+ but "~fo\\o\\/" unescape to user_name
+ "foo". */
+ if (filename == NULL)
+ *p++ = '\\';
+ break;
+ }
+ ++q;
+ }
+ *p++ = *q++;
+ }
+ *p = '\0';
+ }
+ else
+ *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
+ = '\0';
+ user_name = newp;
+ }
+
+ /* Look up specific user's home directory. */
+ {
+ struct passwd *p;
+ struct scratch_buffer pwtmpbuf;
+ scratch_buffer_init (&pwtmpbuf);
# if defined HAVE_GETPWNAM_R || defined _LIBC
- struct passwd pwbuf;
-
- while (getpwnam_r (user_name, &pwbuf,
- pwtmpbuf.data, pwtmpbuf.length, &p)
- == ERANGE)
- {
- if (!scratch_buffer_grow (&pwtmpbuf))
- {
- retval = GLOB_NOSPACE;
- goto out;
- }
- }
+ struct passwd pwbuf;
+
+ while (getpwnam_r (user_name, &pwbuf,
+ pwtmpbuf.data, pwtmpbuf.length, &p)
+ == ERANGE)
+ {
+ if (!scratch_buffer_grow (&pwtmpbuf))
+ {
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ }
# else
- p = getpwnam (user_name);
+ p = getpwnam (user_name);
# endif
- if (__glibc_unlikely (malloc_user_name))
- free (user_name);
-
- /* If we found a home directory use this. */
- if (p != NULL)
- {
- size_t home_len = strlen (p->pw_dir);
- size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
- char *d, *newp;
- bool use_alloca = glob_use_alloca (alloca_used,
- home_len + rest_len + 1);
-
- if (use_alloca)
- newp = alloca_account (home_len + rest_len + 1, alloca_used);
- else
- {
- newp = malloc (home_len + rest_len + 1);
- if (newp == NULL)
- {
- scratch_buffer_free (&pwtmpbuf);
- retval = GLOB_NOSPACE;
- goto out;
- }
- }
- d = mempcpy (newp, p->pw_dir, home_len);
- if (end_name != NULL)
- d = mempcpy (d, end_name, rest_len);
- *d = '\0';
-
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
- dirname = newp;
- malloc_dirname = !use_alloca;
-
- dirlen = home_len + rest_len;
- dirname_modified = 1;
- }
- else
- {
- if (flags & GLOB_TILDE_CHECK)
- {
- /* We have to regard it as an error if we cannot find the
- home directory. */
- retval = GLOB_NOMATCH;
- goto out;
- }
- }
- scratch_buffer_free (&pwtmpbuf);
- }
+ if (__glibc_unlikely (malloc_user_name))
+ free (user_name);
+
+ /* If we found a home directory use this. */
+ if (p != NULL)
+ {
+ size_t home_len = strlen (p->pw_dir);
+ size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+ /* dirname contains end_name; we can't free it now. */
+ char *prev_dirname =
+ (__glibc_unlikely (malloc_dirname) ? dirname : NULL);
+ char *d;
+
+ malloc_dirname = 0;
+
+ if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
+ dirname = alloca_account (home_len + rest_len + 1,
+ alloca_used);
+ else
+ {
+ dirname = malloc (home_len + rest_len + 1);
+ if (dirname == NULL)
+ {
+ free (prev_dirname);
+ scratch_buffer_free (&pwtmpbuf);
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ malloc_dirname = 1;
+ }
+ d = mempcpy (dirname, p->pw_dir, home_len);
+ if (end_name != NULL)
+ d = mempcpy (d, end_name, rest_len);
+ *d = '\0';
+
+ free (prev_dirname);
+
+ dirlen = home_len + rest_len;
+ dirname_modified = 1;
+ }
+ else
+ {
+ if (flags & GLOB_TILDE_CHECK)
+ {
+ /* We have to regard it as an error if we cannot find the
+ home directory. */
+ retval = GLOB_NOMATCH;
+ goto out;
+ }
+ }
+ scratch_buffer_free (&pwtmpbuf);
+ }
#endif /* !WINDOWS32 */
- }
+ }
}
/* Now test whether we looked for "~" or "~NAME". In this case we
can give the answer now. */
if (filename == NULL)
{
- size_t newcount = pglob->gl_pathc + pglob->gl_offs;
- char **new_gl_pathv;
-
- if (newcount > SIZE_MAX / sizeof (char *) - 2)
- {
- nospace:
- free (pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- pglob->gl_pathc = 0;
- retval = GLOB_NOSPACE;
- goto out;
- }
-
- new_gl_pathv = realloc (pglob->gl_pathv,
- (newcount + 2) * sizeof (char *));
- if (new_gl_pathv == NULL)
- goto nospace;
- pglob->gl_pathv = new_gl_pathv;
-
- if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
- {
- char *p;
- pglob->gl_pathv[newcount] = malloc (dirlen + 2);
- if (pglob->gl_pathv[newcount] == NULL)
- goto nospace;
- p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
- p[0] = '/';
- p[1] = '\0';
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
- }
- else
- {
- if (__glibc_unlikely (malloc_dirname))
- pglob->gl_pathv[newcount] = dirname;
- else
- {
- pglob->gl_pathv[newcount] = strdup (dirname);
- if (pglob->gl_pathv[newcount] == NULL)
- goto nospace;
- }
- }
- pglob->gl_pathv[++newcount] = NULL;
- ++pglob->gl_pathc;
- pglob->gl_flags = flags;
-
- return 0;
+ size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ char **new_gl_pathv;
+
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
+ {
+ nospace:
+ free (pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ pglob->gl_pathc = 0;
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+
+ new_gl_pathv = realloc (pglob->gl_pathv,
+ (newcount + 2) * sizeof (char *));
+ if (new_gl_pathv == NULL)
+ goto nospace;
+ pglob->gl_pathv = new_gl_pathv;
+
+ if (flags & GLOB_MARK && is_dir (dirname, flags, pglob))
+ {
+ char *p;
+ pglob->gl_pathv[newcount] = malloc (dirlen + 2);
+ if (pglob->gl_pathv[newcount] == NULL)
+ goto nospace;
+ p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
+ p[0] = '/';
+ p[1] = '\0';
+ if (__glibc_unlikely (malloc_dirname))
+ free (dirname);
+ }
+ else
+ {
+ if (__glibc_unlikely (malloc_dirname))
+ pglob->gl_pathv[newcount] = dirname;
+ else
+ {
+ pglob->gl_pathv[newcount] = strdup (dirname);
+ if (pglob->gl_pathv[newcount] == NULL)
+ goto nospace;
+ }
+ }
+ pglob->gl_pathv[++newcount] = NULL;
+ ++pglob->gl_pathc;
+ pglob->gl_flags = flags;
+
+ return 0;
}
meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
@@ -927,135 +947,135 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
if (meta & (GLOBPAT_SPECIAL | GLOBPAT_BRACKET))
{
/* The directory name contains metacharacters, so we
- have to glob for the directory, and then glob for
- the pattern in each directory found. */
+ have to glob for the directory, and then glob for
+ the pattern in each directory found. */
size_t i;
if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\')
- {
- /* "foo\\/bar". Remove the final backslash from dirname
- if it has not been quoted. */
- char *p = (char *) &dirname[dirlen - 1];
+ {
+ /* "foo\\/bar". Remove the final backslash from dirname
+ if it has not been quoted. */
+ char *p = (char *) &dirname[dirlen - 1];
- while (p > dirname && p[-1] == '\\') --p;
- if ((&dirname[dirlen] - p) & 1)
- *(char *) &dirname[--dirlen] = '\0';
- }
+ while (p > dirname && p[-1] == '\\') --p;
+ if ((&dirname[dirlen] - p) & 1)
+ *(char *) &dirname[--dirlen] = '\0';
+ }
if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0))
- {
- /* Use the alternative access functions also in the recursive
- call. */
- dirs.gl_opendir = pglob->gl_opendir;
- dirs.gl_readdir = pglob->gl_readdir;
- dirs.gl_closedir = pglob->gl_closedir;
- dirs.gl_stat = pglob->gl_stat;
- dirs.gl_lstat = pglob->gl_lstat;
- }
+ {
+ /* Use the alternative access functions also in the recursive
+ call. */
+ dirs.gl_opendir = pglob->gl_opendir;
+ dirs.gl_readdir = pglob->gl_readdir;
+ dirs.gl_closedir = pglob->gl_closedir;
+ dirs.gl_stat = pglob->gl_stat;
+ dirs.gl_lstat = pglob->gl_lstat;
+ }
status = __glob (dirname,
- ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
- | GLOB_NOSORT | GLOB_ONLYDIR),
- errfunc, &dirs);
+ ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
+ | GLOB_NOSORT | GLOB_ONLYDIR),
+ errfunc, &dirs);
if (status != 0)
- {
- if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
- {
- retval = status;
- goto out;
- }
- goto no_matches;
- }
+ {
+ if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
+ {
+ retval = status;
+ goto out;
+ }
+ goto no_matches;
+ }
/* We have successfully globbed the preceding directory name.
- For each name we found, call glob_in_dir on it and FILENAME,
- appending the results to PGLOB. */
+ For each name we found, call glob_in_dir on it and FILENAME,
+ appending the results to PGLOB. */
for (i = 0; i < dirs.gl_pathc; ++i)
- {
- size_t old_pathc;
-
- old_pathc = pglob->gl_pathc;
- status = glob_in_dir (filename, dirs.gl_pathv[i],
- ((flags | GLOB_APPEND)
- & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
- errfunc, pglob, alloca_used);
- if (status == GLOB_NOMATCH)
- /* No matches in this directory. Try the next. */
- continue;
-
- if (status != 0)
- {
- globfree (&dirs);
- globfree (pglob);
- pglob->gl_pathc = 0;
- retval = status;
- goto out;
- }
-
- /* Stick the directory on the front of each name. */
- if (prefix_array (dirs.gl_pathv[i],
- &pglob->gl_pathv[old_pathc + pglob->gl_offs],
- pglob->gl_pathc - old_pathc))
- {
- globfree (&dirs);
- globfree (pglob);
- pglob->gl_pathc = 0;
- retval = GLOB_NOSPACE;
- goto out;
- }
- }
+ {
+ size_t old_pathc;
+
+ old_pathc = pglob->gl_pathc;
+ status = glob_in_dir (filename, dirs.gl_pathv[i],
+ ((flags | GLOB_APPEND)
+ & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
+ errfunc, pglob, alloca_used);
+ if (status == GLOB_NOMATCH)
+ /* No matches in this directory. Try the next. */
+ continue;
+
+ if (status != 0)
+ {
+ globfree (&dirs);
+ globfree (pglob);
+ pglob->gl_pathc = 0;
+ retval = status;
+ goto out;
+ }
+
+ /* Stick the directory on the front of each name. */
+ if (prefix_array (dirs.gl_pathv[i],
+ &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+ pglob->gl_pathc - old_pathc))
+ {
+ globfree (&dirs);
+ globfree (pglob);
+ pglob->gl_pathc = 0;
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ }
flags |= GLOB_MAGCHAR;
/* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
- But if we have not found any matching entry and the GLOB_NOCHECK
- flag was set we must return the input pattern itself. */
+ But if we have not found any matching entry and the GLOB_NOCHECK
+ flag was set we must return the input pattern itself. */
if (pglob->gl_pathc + pglob->gl_offs == oldcount)
- {
- no_matches:
- /* No matches. */
- if (flags & GLOB_NOCHECK)
- {
- size_t newcount = pglob->gl_pathc + pglob->gl_offs;
- char **new_gl_pathv;
-
- if (newcount > SIZE_MAX / sizeof (char *) - 2)
- {
- nospace2:
- globfree (&dirs);
- retval = GLOB_NOSPACE;
- goto out;
- }
-
- new_gl_pathv = realloc (pglob->gl_pathv,
- (newcount + 2) * sizeof (char *));
- if (new_gl_pathv == NULL)
- goto nospace2;
- pglob->gl_pathv = new_gl_pathv;
-
- pglob->gl_pathv[newcount] = strdup (pattern);
- if (pglob->gl_pathv[newcount] == NULL)
- {
- globfree (&dirs);
- globfree (pglob);
- pglob->gl_pathc = 0;
- retval = GLOB_NOSPACE;
- goto out;
- }
-
- ++pglob->gl_pathc;
- ++newcount;
-
- pglob->gl_pathv[newcount] = NULL;
- pglob->gl_flags = flags;
- }
- else
- {
- globfree (&dirs);
- retval = GLOB_NOMATCH;
- goto out;
- }
- }
+ {
+ no_matches:
+ /* No matches. */
+ if (flags & GLOB_NOCHECK)
+ {
+ size_t newcount = pglob->gl_pathc + pglob->gl_offs;
+ char **new_gl_pathv;
+
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
+ {
+ nospace2:
+ globfree (&dirs);
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+
+ new_gl_pathv = realloc (pglob->gl_pathv,
+ (newcount + 2) * sizeof (char *));
+ if (new_gl_pathv == NULL)
+ goto nospace2;
+ pglob->gl_pathv = new_gl_pathv;
+
+ pglob->gl_pathv[newcount] = strdup (pattern);
+ if (pglob->gl_pathv[newcount] == NULL)
+ {
+ globfree (&dirs);
+ globfree (pglob);
+ pglob->gl_pathc = 0;
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+
+ ++pglob->gl_pathc;
+ ++newcount;
+
+ pglob->gl_pathv[newcount] = NULL;
+ pglob->gl_flags = flags;
+ }
+ else
+ {
+ globfree (&dirs);
+ retval = GLOB_NOMATCH;
+ goto out;
+ }
+ }
globfree (&dirs);
}
@@ -1065,57 +1085,57 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
int orig_flags = flags;
if (meta & GLOBPAT_BACKSLASH)
- {
- char *p = strchr (dirname, '\\'), *q;
- /* We need to unescape the dirname string. It is certainly
- allocated by alloca, as otherwise filename would be NULL
- or dirname wouldn't contain backslashes. */
- q = p;
- do
- {
- if (*p == '\\')
- {
- *q = *++p;
- --dirlen;
- }
- else
- *q = *p;
- ++q;
- }
- while (*p++ != '\0');
- dirname_modified = 1;
- }
+ {
+ char *p = strchr (dirname, '\\'), *q;
+ /* We need to unescape the dirname string. It is certainly
+ allocated by alloca, as otherwise filename would be NULL
+ or dirname wouldn't contain backslashes. */
+ q = p;
+ do
+ {
+ if (*p == '\\')
+ {
+ *q = *++p;
+ --dirlen;
+ }
+ else
+ *q = *p;
+ ++q;
+ }
+ while (*p++ != '\0');
+ dirname_modified = 1;
+ }
if (dirname_modified)
- flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
+ flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
- alloca_used);
+ alloca_used);
if (status != 0)
- {
- if (status == GLOB_NOMATCH && flags != orig_flags
- && pglob->gl_pathc + pglob->gl_offs == oldcount)
- {
- /* Make sure globfree (&dirs); is a nop. */
- dirs.gl_pathv = NULL;
- flags = orig_flags;
- goto no_matches;
- }
- retval = status;
- goto out;
- }
+ {
+ if (status == GLOB_NOMATCH && flags != orig_flags
+ && pglob->gl_pathc + pglob->gl_offs == oldcount)
+ {
+ /* Make sure globfree (&dirs); is a nop. */
+ dirs.gl_pathv = NULL;
+ flags = orig_flags;
+ goto no_matches;
+ }
+ retval = status;
+ goto out;
+ }
if (dirlen > 0)
- {
- /* Stick the directory on the front of each name. */
- if (prefix_array (dirname,
- &pglob->gl_pathv[old_pathc + pglob->gl_offs],
- pglob->gl_pathc - old_pathc))
- {
- globfree (pglob);
- pglob->gl_pathc = 0;
- retval = GLOB_NOSPACE;
- goto out;
- }
- }
+ {
+ /* Stick the directory on the front of each name. */
+ if (prefix_array (dirname,
+ &pglob->gl_pathv[old_pathc + pglob->gl_offs],
+ pglob->gl_pathc - old_pathc))
+ {
+ globfree (pglob);
+ pglob->gl_pathc = 0;
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ }
}
if (flags & GLOB_MARK)
@@ -1124,28 +1144,28 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
size_t i;
for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i)
- if (is_dir (pglob->gl_pathv[i], flags, pglob))
- {
- size_t len = strlen (pglob->gl_pathv[i]) + 2;
- char *new = realloc (pglob->gl_pathv[i], len);
- if (new == NULL)
- {
- globfree (pglob);
- pglob->gl_pathc = 0;
- retval = GLOB_NOSPACE;
- goto out;
- }
- strcpy (&new[len - 2], "/");
- pglob->gl_pathv[i] = new;
- }
+ if (is_dir (pglob->gl_pathv[i], flags, pglob))
+ {
+ size_t len = strlen (pglob->gl_pathv[i]) + 2;
+ char *new = realloc (pglob->gl_pathv[i], len);
+ if (new == NULL)
+ {
+ globfree (pglob);
+ pglob->gl_pathc = 0;
+ retval = GLOB_NOSPACE;
+ goto out;
+ }
+ strcpy (&new[len - 2], "/");
+ pglob->gl_pathv[i] = new;
+ }
}
if (!(flags & GLOB_NOSORT))
{
/* Sort the vector. */
qsort (&pglob->gl_pathv[oldcount],
- pglob->gl_pathc + pglob->gl_offs - oldcount,
- sizeof (char *), collated_compare);
+ pglob->gl_pathc + pglob->gl_offs - oldcount,
+ sizeof (char *), collated_compare);
}
out:
@@ -1197,14 +1217,14 @@ prefix_array (const char *dirname, char **array, size_t n)
if (dirlen > 1)
{
if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
- /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
- --dirlen;
+ /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
+ --dirlen;
else if (dirname[dirlen - 1] == ':')
- {
- /* DIRNAME is "d:". Use ':' instead of '/'. */
- --dirlen;
- dirsep_char = ':';
- }
+ {
+ /* DIRNAME is "d:". Use ':' instead of '/'. */
+ --dirlen;
+ dirsep_char = ':';
+ }
}
#endif
@@ -1213,16 +1233,16 @@ prefix_array (const char *dirname, char **array, size_t n)
size_t eltlen = strlen (array[i]) + 1;
char *new = malloc (dirlen + 1 + eltlen);
if (new == NULL)
- {
- while (i > 0)
- free (array[--i]);
- return 1;
- }
+ {
+ while (i > 0)
+ free (array[--i]);
+ return 1;
+ }
{
- char *endp = mempcpy (new, dirname, dirlen);
- *endp++ = dirsep_char;
- mempcpy (endp, array[i], eltlen);
+ char *endp = mempcpy (new, dirname, dirlen);
+ *endp++ = dirsep_char;
+ mempcpy (endp, array[i], eltlen);
}
free (array[i]);
array[i] = new;
@@ -1237,8 +1257,8 @@ prefix_array (const char *dirname, char **array, size_t n)
The GLOB_APPEND flag is assumed to be set (always appends). */
static int
glob_in_dir (const char *pattern, const char *directory, int flags,
- int (*errfunc) (const char *, int),
- glob_t *pglob, size_t alloca_used)
+ int (*errfunc) (const char *, int),
+ glob_t *pglob, size_t alloca_used)
{
size_t dirlen = strlen (directory);
void *stream = NULL;
@@ -1266,8 +1286,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
{
/* We need not do any tests. The PATTERN contains no meta
- characters and we must not return an error therefore the
- result will always contain exactly one name. */
+ characters and we must not return an error therefore the
+ result will always contain exactly one name. */
flags |= GLOB_NOCHECK;
}
else if (meta == GLOBPAT_NONE)
@@ -1281,102 +1301,102 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
if (alloca_fullname)
fullname = alloca_account (fullsize, alloca_used);
else
- {
- fullname = malloc (fullsize);
- if (fullname == NULL)
- return GLOB_NOSPACE;
- }
+ {
+ fullname = malloc (fullsize);
+ if (fullname == NULL)
+ return GLOB_NOSPACE;
+ }
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
- "/", 1),
- pattern, patlen + 1);
+ "/", 1),
+ pattern, patlen + 1);
if (glob_lstat (pglob, flags, fullname) == 0
- || errno == EOVERFLOW)
- /* We found this file to be existing. Now tell the rest
- of the function to copy this name into the result. */
- flags |= GLOB_NOCHECK;
+ || errno == EOVERFLOW)
+ /* We found this file to be existing. Now tell the rest
+ of the function to copy this name into the result. */
+ flags |= GLOB_NOCHECK;
if (__glibc_unlikely (!alloca_fullname))
- free (fullname);
+ free (fullname);
}
else
{
stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? (*pglob->gl_opendir) (directory)
- : opendir (directory));
+ ? (*pglob->gl_opendir) (directory)
+ : opendir (directory));
if (stream == NULL)
- {
- if (errno != ENOTDIR
- && ((errfunc != NULL && (*errfunc) (directory, errno))
- || (flags & GLOB_ERR)))
- return GLOB_ABORTED;
- }
+ {
+ if (errno != ENOTDIR
+ && ((errfunc != NULL && (*errfunc) (directory, errno))
+ || (flags & GLOB_ERR)))
+ return GLOB_ABORTED;
+ }
else
- {
- int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
- | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
- flags |= GLOB_MAGCHAR;
-
- while (1)
- {
- struct readdir_result d;
- {
- if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
- d = convert_dirent (GL_READDIR (pglob, stream));
- else
- {
+ {
+ int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+ | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
+ flags |= GLOB_MAGCHAR;
+
+ while (1)
+ {
+ struct readdir_result d;
+ {
+ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+ d = convert_dirent (GL_READDIR (pglob, stream));
+ else
+ {
#ifdef COMPILE_GLOB64
- d = convert_dirent (__readdir (stream));
+ d = convert_dirent (__readdir (stream));
#else
- d = convert_dirent64 (__readdir64 (stream));
+ d = convert_dirent64 (__readdir64 (stream));
#endif
- }
- }
- if (d.name == NULL)
- break;
-
- /* If we shall match only directories use the information
- provided by the dirent call if possible. */
- if (flags & GLOB_ONLYDIR)
- switch (readdir_result_type (d))
- {
- case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
- default: continue;
- }
-
- if (fnmatch (pattern, d.name, fnm_flags) == 0)
- {
- if (cur == names->count)
- {
- struct globnames *newnames;
- size_t count = names->count * 2;
- size_t nameoff = offsetof (struct globnames, name);
- size_t size = FLEXSIZEOF (struct globnames, name,
- count * sizeof (char *));
- if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
- < names->count)
- goto memory_error;
- if (glob_use_alloca (alloca_used, size))
- newnames = names_alloca
- = alloca_account (size, alloca_used);
- else if ((newnames = malloc (size))
- == NULL)
- goto memory_error;
- newnames->count = count;
- newnames->next = names;
- names = newnames;
- cur = 0;
- }
- names->name[cur] = strdup (d.name);
- if (names->name[cur] == NULL)
- goto memory_error;
- ++cur;
- ++nfound;
- if (SIZE_MAX - pglob->gl_offs <= nfound)
- goto memory_error;
- }
- }
- }
+ }
+ }
+ if (d.name == NULL)
+ break;
+
+ /* If we shall match only directories use the information
+ provided by the dirent call if possible. */
+ if (flags & GLOB_ONLYDIR)
+ switch (readdir_result_type (d))
+ {
+ case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
+ default: continue;
+ }
+
+ if (fnmatch (pattern, d.name, fnm_flags) == 0)
+ {
+ if (cur == names->count)
+ {
+ struct globnames *newnames;
+ size_t count = names->count * 2;
+ size_t nameoff = offsetof (struct globnames, name);
+ size_t size = FLEXSIZEOF (struct globnames, name,
+ count * sizeof (char *));
+ if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
+ < names->count)
+ goto memory_error;
+ if (glob_use_alloca (alloca_used, size))
+ newnames = names_alloca
+ = alloca_account (size, alloca_used);
+ else if ((newnames = malloc (size))
+ == NULL)
+ goto memory_error;
+ newnames->count = count;
+ newnames->next = names;
+ names = newnames;
+ cur = 0;
+ }
+ names->name[cur] = strdup (d.name);
+ if (names->name[cur] == NULL)
+ goto memory_error;
+ ++cur;
+ ++nfound;
+ if (SIZE_MAX - pglob->gl_offs <= nfound)
+ goto memory_error;
+ }
+ }
+ }
}
if (nfound == 0 && (flags & GLOB_NOCHECK))
@@ -1385,7 +1405,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
nfound = 1;
names->name[cur] = malloc (len + 1);
if (names->name[cur] == NULL)
- goto memory_error;
+ goto memory_error;
*((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
}
@@ -1396,80 +1416,80 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
result = 0;
if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
- < pglob->gl_offs + nfound + 1)
- goto memory_error;
+ < pglob->gl_offs + nfound + 1)
+ goto memory_error;
new_gl_pathv
- = realloc (pglob->gl_pathv,
- (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
- * sizeof (char *));
+ = realloc (pglob->gl_pathv,
+ (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
+ * sizeof (char *));
if (new_gl_pathv == NULL)
- {
- memory_error:
- while (1)
- {
- struct globnames *old = names;
- for (size_t i = 0; i < cur; ++i)
- free (names->name[i]);
- names = names->next;
- /* NB: we will not leak memory here if we exit without
- freeing the current block assigned to OLD. At least
- the very first block is always allocated on the stack
- and this is the block assigned to OLD here. */
- if (names == NULL)
- {
- assert (old == init_names);
- break;
- }
- cur = names->count;
- if (old == names_alloca)
- names_alloca = names;
- else
- free (old);
- }
- result = GLOB_NOSPACE;
- }
+ {
+ memory_error:
+ while (1)
+ {
+ struct globnames *old = names;
+ for (size_t i = 0; i < cur; ++i)
+ free (names->name[i]);
+ names = names->next;
+ /* NB: we will not leak memory here if we exit without
+ freeing the current block assigned to OLD. At least
+ the very first block is always allocated on the stack
+ and this is the block assigned to OLD here. */
+ if (names == NULL)
+ {
+ assert (old == init_names);
+ break;
+ }
+ cur = names->count;
+ if (old == names_alloca)
+ names_alloca = names;
+ else
+ free (old);
+ }
+ result = GLOB_NOSPACE;
+ }
else
- {
- while (1)
- {
- struct globnames *old = names;
- for (size_t i = 0; i < cur; ++i)
- new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
- = names->name[i];
- names = names->next;
- /* NB: we will not leak memory here if we exit without
- freeing the current block assigned to OLD. At least
- the very first block is always allocated on the stack
- and this is the block assigned to OLD here. */
- if (names == NULL)
- {
- assert (old == init_names);
- break;
- }
- cur = names->count;
- if (old == names_alloca)
- names_alloca = names;
- else
- free (old);
- }
-
- pglob->gl_pathv = new_gl_pathv;
-
- pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
- pglob->gl_flags = flags;
- }
+ {
+ while (1)
+ {
+ struct globnames *old = names;
+ for (size_t i = 0; i < cur; ++i)
+ new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++]
+ = names->name[i];
+ names = names->next;
+ /* NB: we will not leak memory here if we exit without
+ freeing the current block assigned to OLD. At least
+ the very first block is always allocated on the stack
+ and this is the block assigned to OLD here. */
+ if (names == NULL)
+ {
+ assert (old == init_names);
+ break;
+ }
+ cur = names->count;
+ if (old == names_alloca)
+ names_alloca = names;
+ else
+ free (old);
+ }
+
+ pglob->gl_pathv = new_gl_pathv;
+
+ pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+ pglob->gl_flags = flags;
+ }
}
if (stream != NULL)
{
save = errno;
if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
- (*pglob->gl_closedir) (stream);
+ (*pglob->gl_closedir) (stream);
else
- closedir (stream);
+ closedir (stream);
__set_errno (save);
}
diff --git a/posix/glob_pattern_p.c b/posix/glob_pattern_p.c
index f187baa1a5..436d38126d 100644
--- a/posix/glob_pattern_p.c
+++ b/posix/glob_pattern_p.c
@@ -17,7 +17,7 @@
<https://www.gnu.org/licenses/>. */
#ifndef _LIBC
-# include <config.h>
+# include <libc-config.h>
#endif
#include <glob.h>
diff --git a/posix/globfree.c b/posix/globfree.c
index 162b90341a..1144fdd69f 100644
--- a/posix/globfree.c
+++ b/posix/globfree.c
@@ -17,7 +17,7 @@
<https://www.gnu.org/licenses/>. */
#ifndef _LIBC
-# include <config.h>
+# include <libc-config.h>
#endif
#include <glob.h>
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 3/5] Sync intprops.h with gnulib
2020-12-30 20:15 [PATCH 1/5] posix: Sync regex code with gnulib Adhemerval Zanella
2020-12-30 20:15 ` [PATCH 2/5] posix: Sync glob " Adhemerval Zanella
@ 2020-12-30 20:15 ` Adhemerval Zanella
2020-12-31 21:47 ` Paul Eggert
2020-12-30 20:15 ` [PATCH 4/5] Sync flexmember.h " Adhemerval Zanella
` (3 subsequent siblings)
5 siblings, 1 reply; 22+ messages in thread
From: Adhemerval Zanella @ 2020-12-30 20:15 UTC (permalink / raw)
To: libc-alpha, Paul Eggert; +Cc: bug-gnulib
It sync with gnulib commit 43ee1a6bf.
Checked on x86_64-linux-gnu.
---
include/intprops.h | 70 ++++++++++++++++++++++++++++++++++++++--------
1 file changed, 58 insertions(+), 12 deletions(-)
diff --git a/include/intprops.h b/include/intprops.h
index 6de65b067d..52e60e5e2d 100644
--- a/include/intprops.h
+++ b/include/intprops.h
@@ -48,7 +48,7 @@
/* Minimum and maximum values for integer types and expressions. */
/* The width in bits of the integer type or expression T.
- Do not evaluate T.
+ Do not evaluate T. T must not be a bit-field expression.
Padding bits are not supported; this is checked at compile-time below. */
#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
@@ -70,7 +70,7 @@
? _GL_SIGNED_INT_MAXIMUM (e) \
: _GL_INT_NEGATE_CONVERT (e, 1))
#define _GL_SIGNED_INT_MAXIMUM(e) \
- (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1)
+ (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1)
/* Work around OpenVMS incompatibility with C99. */
#if !defined LLONG_MAX && defined __INT64_MAX
@@ -86,6 +86,7 @@
/* Does the __typeof__ keyword work? This could be done by
'configure', but for now it's easier to do it by hand. */
#if (2 <= __GNUC__ \
+ || (4 <= __clang_major__) \
|| (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
|| (0x5110 <= __SUNPRO_C && !__STDC__))
# define _GL_HAVE___TYPEOF__ 1
@@ -94,8 +95,9 @@
#endif
/* Return 1 if the integer type or expression T might be signed. Return 0
- if it is definitely unsigned. This macro does not evaluate its argument,
- and expands to an integer constant expression. */
+ if it is definitely unsigned. T must not be a bit-field expression.
+ This macro does not evaluate its argument, and expands to an
+ integer constant expression. */
#if _GL_HAVE___TYPEOF__
# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t))
#else
@@ -108,6 +110,8 @@
#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
/* Bound on length of the string representing an integer type or expression T.
+ T must not be a bit-field expression.
+
Subtract 1 for the sign bit if T is signed, and then add 1 more for
a minus sign if needed.
@@ -119,7 +123,7 @@
+ _GL_SIGNED_TYPE_OR_EXPR (t))
/* Bound on buffer size needed to represent an integer type or expression T,
- including the terminating null. */
+ including the terminating null. T must not be a bit-field expression. */
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
@@ -222,7 +226,9 @@
/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
(A, B, P) work when P is non-null. */
-#if 5 <= __GNUC__ && !defined __ICC
+/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x,
+ see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98269>. */
+#if 7 <= __GNUC__ && !defined __ICC
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
#elif defined __has_builtin
# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
@@ -239,8 +245,18 @@
#endif
/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
- __builtin_mul_overflow_p and __builtin_mul_overflow_p. */
-#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+ __builtin_sub_overflow_p and __builtin_mul_overflow_p. */
+#if defined __clang__ || defined __ICC
+/* Clang 11 lacks __builtin_mul_overflow_p, and even if it did it
+ would presumably run afoul of Clang bug 16404. ICC 2021.1's
+ __builtin_add_overflow_p etc. are not treated as integral constant
+ expressions even when all arguments are. */
+# define _GL_HAS_BUILTIN_OVERFLOW_P 0
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p)
+#else
+# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+#endif
/* The _GL*_OVERFLOW macros have the same restrictions as the
*_RANGE_OVERFLOW macros, except that they do not assume that operands
@@ -373,8 +389,9 @@
_GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
#endif
#if _GL_HAS_BUILTIN_MUL_OVERFLOW
-# if (9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
- || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__))
+# if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
+ || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \
+ && !defined __ICC)
# define INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
# else
/* Work around GCC bug 91450. */
@@ -395,7 +412,7 @@
For now, assume all versions of GCC-like compilers generate bogus
warnings for _Generic. This matters only for compilers that
lack relevant builtins. */
-#if __GNUC__
+#if __GNUC__ || defined __clang__
# define _GL__GENERIC_BOGUS 1
#else
# define _GL__GENERIC_BOGUS 0
@@ -565,7 +582,7 @@
? (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
? (a) < (tmax) / (b) \
: ((INT_NEGATE_OVERFLOW (b) \
- ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (b) - 1) \
+ ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (+ (b)) - 1) \
: (tmax) / -(b)) \
<= -1 - (a))) \
: INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
@@ -581,4 +598,33 @@
: (tmin) / (a) < (b)) \
: (tmax) / (b) < (a)))
+/* The following macros compute A + B, A - B, and A * B, respectively.
+ If no overflow occurs, they set *R to the result and return 1;
+ otherwise, they return 0 and may modify *R.
+
+ Example usage:
+
+ long int result;
+ if (INT_ADD_OK (a, b, &result))
+ printf ("result is %ld\n", result);
+ else
+ printf ("overflow\n");
+
+ A, B, and *R should be integers; they need not be the same type,
+ and they need not be all signed or all unsigned.
+
+ These macros work correctly on all known practical hosts, and do not rely
+ on undefined behavior due to signed arithmetic overflow.
+
+ These macros are not constant expressions.
+
+ These macros may evaluate their arguments zero or multiple times, so the
+ arguments should not have side effects.
+
+ These macros are tuned for B being a constant. */
+
+#define INT_ADD_OK(a, b, r) ! INT_ADD_WRAPV (a, b, r)
+#define INT_SUBTRACT_OK(a, b, r) ! INT_SUBTRACT_WRAPV (a, b, r)
+#define INT_MULTIPLY_OK(a, b, r) ! INT_MULTIPLY_WRAPV (a, b, r)
+
#endif /* _GL_INTPROPS_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 4/5] Sync flexmember.h with gnulib
2020-12-30 20:15 [PATCH 1/5] posix: Sync regex code with gnulib Adhemerval Zanella
2020-12-30 20:15 ` [PATCH 2/5] posix: Sync glob " Adhemerval Zanella
2020-12-30 20:15 ` [PATCH 3/5] Sync intprops.h " Adhemerval Zanella
@ 2020-12-30 20:15 ` Adhemerval Zanella
2020-12-31 21:48 ` Paul Eggert
2020-12-30 20:15 ` [PATCH 5/5] posix: Sync fnmatch " Adhemerval Zanella
` (2 subsequent siblings)
5 siblings, 1 reply; 22+ messages in thread
From: Adhemerval Zanella @ 2020-12-30 20:15 UTC (permalink / raw)
To: libc-alpha, Paul Eggert; +Cc: bug-gnulib
It sync with gnulib commit 43ee1a6bf.
---
posix/flexmember.h | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/posix/flexmember.h b/posix/flexmember.h
index 30e6a6b867..1e839f08c2 100644
--- a/posix/flexmember.h
+++ b/posix/flexmember.h
@@ -33,11 +33,26 @@
# define FLEXALIGNOF(type) _Alignof (type)
#endif
-/* Upper bound on the size of a struct of type TYPE with a flexible
- array member named MEMBER that is followed by N bytes of other data.
- This is not simply sizeof (TYPE) + N, since it may require
- alignment on unusually picky C11 platforms, and
- FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
+/* Yield a properly aligned upper bound on the size of a struct of
+ type TYPE with a flexible array member named MEMBER that is
+ followed by N bytes of other data. The result is suitable as an
+ argument to malloc. For example:
+
+ struct s { int n; char d[FLEXIBLE_ARRAY_MEMBER]; };
+ struct s *p = malloc (FLEXSIZEOF (struct s, d, n * sizeof (char)));
+
+ FLEXSIZEOF (TYPE, MEMBER, N) is not simply (sizeof (TYPE) + N),
+ since FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. Nor is
+ it simply (offsetof (TYPE, MEMBER) + N), as that might yield a size
+ that causes malloc to yield a pointer that is not properly aligned
+ for TYPE; for example, if sizeof (int) == alignof (int) == 4,
+ malloc (offsetof (struct s, d) + 3 * sizeof (char)) is equivalent
+ to malloc (7) and might yield a pointer that is not a multiple of 4
+ (which means the pointer is not properly aligned for struct s),
+ whereas malloc (FLEXSIZEOF (struct s, d, 3 * sizeof (char))) is
+ equivalent to malloc (8) and must yield a pointer that is a
+ multiple of 4.
+
Yield a value less than N if and only if arithmetic overflow occurs. */
#define FLEXSIZEOF(type, member, n) \
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 5/5] posix: Sync fnmatch with gnulib
2020-12-30 20:15 [PATCH 1/5] posix: Sync regex code with gnulib Adhemerval Zanella
` (2 preceding siblings ...)
2020-12-30 20:15 ` [PATCH 4/5] Sync flexmember.h " Adhemerval Zanella
@ 2020-12-30 20:15 ` Adhemerval Zanella
2020-12-31 21:54 ` Paul Eggert
2020-12-31 21:37 ` [PATCH 1/5] posix: Sync regex code " Paul Eggert
2021-01-19 14:16 ` Vaseeharan Vinayagamoorthy
5 siblings, 1 reply; 22+ messages in thread
From: Adhemerval Zanella @ 2020-12-30 20:15 UTC (permalink / raw)
To: libc-alpha, Paul Eggert; +Cc: bug-gnulib
It sync with gnulib commit 43ee1a6bf with following changes:
--- posix/fnmatch_loop.c
+++ ../../gnulib/gnulib-lib/lib/fnmatch_loop.c
@@ -978,12 +978,12 @@
bool no_leading_period, int flags, size_t alloca_used)
{
const CHAR *startp;
- ssize_t level;
+ size_t level;
struct patternlist
{
struct patternlist *next;
CHAR malloced;
- CHAR str[];
+ CHAR str[FLEXIBLE_ARRAY_MEMBER];
} *list = NULL;
struct patternlist **lastp = &list;
size_t pattern_len = STRLEN (pattern);
@@ -994,7 +994,7 @@
/* Parse the pattern. Store the individual parts in the list. */
level = 0;
- for (startp = p = pattern + 1; level >= 0; ++p)
+ for (startp = p = pattern + 1; ; ++p)
if (*p == L_('\0'))
{
/* This is an invalid pattern. */
@@ -1065,6 +1065,7 @@
*lastp = newp; \
lastp = &newp->next
NEW_PATTERN;
+ break;
}
}
else if (*p == L_('|'))
Because otherwise it triggers some glibc regressions:
FAIL: posix/tst-fnmatch
FAIL: posix/tst-fnmatch-mem
FAIL: posix/tst-fnmatch3
$ cat posix/tst-fnmatch.out
[...]
537: fnmatch ("x?y", "x/y/z", FNM_PATHNAME|FNM_LEADING_DIR) = FNM_NOMATCH
Didn't expect signal from child: got `Aborted'
$ cat posix/tst-fnmatch3.out
Didn't expect signal from child: got `Aborted'
It is due the loops returns early and hits the assert below.
Checked on x86_64-linux-gnu.
---
posix/fnmatch.c | 548 +++++-------
posix/fnmatch_loop.c | 1977 +++++++++++++++++++++---------------------
2 files changed, 1208 insertions(+), 1317 deletions(-)
diff --git a/posix/fnmatch.c b/posix/fnmatch.c
index 315584f900..c80809e783 100644
--- a/posix/fnmatch.c
+++ b/posix/fnmatch.c
@@ -15,38 +15,29 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#if HAVE_CONFIG_H
-# include <config.h>
+#ifndef _LIBC
+# include <libc-config.h>
#endif
/* Enable GNU extensions in fnmatch.h. */
#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
+# define _GNU_SOURCE 1
#endif
+#include <fnmatch.h>
+
#include <assert.h>
#include <errno.h>
-#include <fnmatch.h>
#include <ctype.h>
#include <string.h>
-
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#endif
-
-#ifdef _LIBC
+#include <stdlib.h>
+#if defined _LIBC || HAVE_ALLOCA
# include <alloca.h>
-#else
-# define alloca_account(size., var) alloca (size)
-#endif
-
-/* For platform which support the ISO C amendement 1 functionality we
- support user defined character classes. */
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
-# include <wchar.h>
-# include <wctype.h>
#endif
+#include <wchar.h>
+#include <wctype.h>
+#include <stddef.h>
+#include <stdbool.h>
/* We need some of the locale data (the collation sequence information)
but there is no interface to get this information in general. Therefore
@@ -57,199 +48,125 @@
# include <shlib-compat.h>
# define CONCAT(a,b) __CONCAT(a,b)
+# define btowc __btowc
+# define iswctype __iswctype
# define mbsrtowcs __mbsrtowcs
+# define mempcpy __mempcpy
+# define strnlen __strnlen
+# define towlower __towlower
+# define wcscat __wcscat
+# define wcslen __wcslen
+# define wctype __wctype
+# define wmemchr __wmemchr
+# define wmempcpy __wmempcpy
# define fnmatch __fnmatch
extern int fnmatch (const char *pattern, const char *string, int flags);
#endif
-/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
-#define NO_LEADING_PERIOD(flags) \
- ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
+#ifdef _LIBC
+# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
+# define FALLTHROUGH __attribute__ ((__fallthrough__))
+# else
+# define FALLTHROUGH ((void) 0)
+# endif
+#else
+# include "attribute.h"
+#endif
-#if defined _LIBC || !defined __GNU_LIBRARY__
+#include <intprops.h>
+#include <flexmember.h>
+#ifdef _LIBC
+typedef ptrdiff_t idx_t;
+#else
+# include "idx.h"
+#endif
-# if defined STDC_HEADERS || !defined isascii
-# define ISASCII(c) 1
-# else
-# define ISASCII(c) isascii(c)
-# endif
+/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
+#define NO_LEADING_PERIOD(flags) \
+ ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
-# ifdef isblank
-# define ISBLANK(c) (ISASCII (c) && isblank (c))
+#ifndef _LIBC
+# if HAVE_ALLOCA
+/* The OS usually guarantees only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ allocate anything larger than 4096 bytes. Also care for the possibility
+ of a few compiler-allocated temporary stack slots. */
+# define __libc_use_alloca(n) ((n) < 4032)
# else
-# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-# endif
-# ifdef isgraph
-# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
-# else
-# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+/* Just use malloc. */
+# define __libc_use_alloca(n) false
+# undef alloca
+# define alloca(n) malloc (n)
# endif
+# define alloca_account(size, avar) ((avar) += (size), alloca (size))
+#endif
-# define ISPRINT(c) (ISASCII (c) && isprint (c))
-# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
-# define ISALNUM(c) (ISASCII (c) && isalnum (c))
-# define ISALPHA(c) (ISASCII (c) && isalpha (c))
-# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
-# define ISLOWER(c) (ISASCII (c) && islower (c))
-# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
-# define ISSPACE(c) (ISASCII (c) && isspace (c))
-# define ISUPPER(c) (ISASCII (c) && isupper (c))
-# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
-
-# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-
-# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
-/* The GNU C library provides support for user-defined character classes
- and the functions from ISO C amendement 1. */
-# ifdef CHARCLASS_NAME_MAX
-# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
-# else
+/* Provide support for user-defined character classes, based on the functions
+ from ISO C 90 amendment 1. */
+#ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#else
/* This shouldn't happen but some implementation might still have this
problem. Use a reasonable default value. */
-# define CHAR_CLASS_MAX_LENGTH 256
-# endif
-
-# ifdef _LIBC
-# define IS_CHAR_CLASS(string) __wctype (string)
-# else
-# define IS_CHAR_CLASS(string) wctype (string)
-# endif
-
-# ifdef _LIBC
-# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
-# else
-# define ISWCTYPE(WC, WT) iswctype (WC, WT)
-# endif
-
-# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
-/* In this case we are implementing the multibyte character handling. */
-# define HANDLE_MULTIBYTE 1
-# endif
+# define CHAR_CLASS_MAX_LENGTH 256
+#endif
-# else
-# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
-
-# define IS_CHAR_CLASS(string) \
- (STREQ (string, "alpha") || STREQ (string, "upper") \
- || STREQ (string, "lower") || STREQ (string, "digit") \
- || STREQ (string, "alnum") || STREQ (string, "xdigit") \
- || STREQ (string, "space") || STREQ (string, "print") \
- || STREQ (string, "punct") || STREQ (string, "graph") \
- || STREQ (string, "cntrl") || STREQ (string, "blank"))
-# endif
+#define IS_CHAR_CLASS(string) wctype (string)
/* Avoid depending on library functions or files
whose names are inconsistent. */
-# if !defined _LIBC && !defined getenv
-extern char *getenv ();
-# endif
-
-# ifndef errno
-extern int errno;
-# endif
-
/* Global variable. */
static int posixly_correct;
-/* This function doesn't exist on most systems. */
-
-# if !defined HAVE___STRCHRNUL && !defined _LIBC
-static char *
-__strchrnul (const char *s, int c)
-{
- char *result = strchr (s, c);
- if (result == NULL)
- result = strchr (s, '\0');
- return result;
-}
-# endif
-
-# if HANDLE_MULTIBYTE && !defined HAVE___STRCHRNUL && !defined _LIBC
-static wchar_t *
-__wcschrnul (const wchar_t *s, wint_t c)
-{
- wchar_t *result = wcschr (s, c);
- if (result == NULL)
- result = wcschr (s, '\0');
- return result;
-}
-# endif
-
/* Note that this evaluates C many times. */
-# ifdef _LIBC
-# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
-# else
-# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
-# endif
-# define CHAR char
-# define UCHAR unsigned char
-# define INT int
-# define FCT internal_fnmatch
-# define EXT ext_match
-# define END end_pattern
-# define STRUCT fnmatch_struct
-# define L(CS) CS
-# ifdef _LIBC
-# define BTOWC(C) __btowc (C)
-# else
-# define BTOWC(C) btowc (C)
-# endif
-# define STRLEN(S) strlen (S)
-# define STRCAT(D, S) strcat (D, S)
-# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
-# define MEMCHR(S, C, N) memchr (S, C, N)
-# define STRCOLL(S1, S2) strcoll (S1, S2)
-# define WIDE_CHAR_VERSION 0
+#define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+#define CHAR char
+#define UCHAR unsigned char
+#define INT int
+#define FCT internal_fnmatch
+#define EXT ext_match
+#define END end_pattern
+#define STRUCT fnmatch_struct
+#define L_(CS) CS
+#define BTOWC(C) btowc (C)
+#define STRLEN(S) strlen (S)
+#define STRCAT(D, S) strcat (D, S)
+#define MEMPCPY(D, S, N) mempcpy (D, S, N)
+#define MEMCHR(S, C, N) memchr (S, C, N)
+#define WIDE_CHAR_VERSION 0
+#ifdef _LIBC
# include <locale/weight.h>
# define FINDIDX findidx
-# include "fnmatch_loop.c"
-
-
-# if HANDLE_MULTIBYTE
-/* Note that this evaluates C many times. */
-# ifdef _LIBC
-# define FOLD(c) ((flags & FNM_CASEFOLD) ? __towlower (c) : (c))
-# else
-# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? towlower (c) : (c))
-# endif
-# define CHAR wchar_t
-# define UCHAR wint_t
-# define INT wint_t
-# define FCT internal_fnwmatch
-# define EXT ext_wmatch
-# define END end_wpattern
-# define STRUCT fnwmatch_struct
-# define L(CS) L##CS
-# define BTOWC(C) (C)
-# define STRLEN(S) __wcslen (S)
-# define STRCAT(D, S) __wcscat (D, S)
-# define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
-# define MEMCHR(S, C, N) __wmemchr (S, C, N)
-# define STRCOLL(S1, S2) wcscoll (S1, S2)
-# ifdef _LIBC
-# define WMEMCMP(S1, S2, N) __wmemcmp (S1, S2, N)
-# else
-# define WMEMCMP(S1, S2, N) wmemcmp (S1, S2, N)
-# endif
-# define WIDE_CHAR_VERSION 1
+#endif
+#include "fnmatch_loop.c"
+
+
+#define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
+#define CHAR wchar_t
+#define UCHAR wint_t
+#define INT wint_t
+#define FCT internal_fnwmatch
+#define EXT ext_wmatch
+#define END end_wpattern
+#define L_(CS) L##CS
+#define BTOWC(C) (C)
+#define STRLEN(S) wcslen (S)
+#define STRCAT(D, S) wcscat (D, S)
+#define MEMPCPY(D, S, N) wmempcpy (D, S, N)
+#define MEMCHR(S, C, N) wmemchr (S, C, N)
+#define WIDE_CHAR_VERSION 1
+#ifdef _LIBC
/* Change the name the header defines so it doesn't conflict with
the <locale/weight.h> version included above. */
-# define findidx findidxwc
-# include <locale/weightwc.h>
-# undef findidx
-# define FINDIDX findidxwc
+# define findidx findidxwc
+# include <locale/weightwc.h>
+# undef findidx
+# define FINDIDX findidxwc
+#endif
-# undef IS_CHAR_CLASS
+#undef IS_CHAR_CLASS
/* We have to convert the wide character string in a multibyte string. But
we know that the character class names consist of alphanumeric characters
from the portable character set, and since the wide character encoding
@@ -265,42 +182,42 @@ is_char_class (const wchar_t *wcs)
do
{
/* Test for a printable character from the portable character set. */
-# ifdef _LIBC
+#ifdef _LIBC
if (*wcs < 0x20 || *wcs > 0x7e
- || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
- return (wctype_t) 0;
-# else
+ || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
+ return (wctype_t) 0;
+#else
switch (*wcs)
- {
- case L' ': case L'!': case L'"': case L'#': case L'%':
- case L'&': case L'\'': case L'(': case L')': case L'*':
- case L'+': case L',': case L'-': case L'.': case L'/':
- case L'0': case L'1': case L'2': case L'3': case L'4':
- case L'5': case L'6': case L'7': case L'8': case L'9':
- case L':': case L';': case L'<': case L'=': case L'>':
- case L'?':
- case L'A': case L'B': case L'C': case L'D': case L'E':
- case L'F': case L'G': case L'H': case L'I': case L'J':
- case L'K': case L'L': case L'M': case L'N': case L'O':
- case L'P': case L'Q': case L'R': case L'S': case L'T':
- case L'U': case L'V': case L'W': case L'X': case L'Y':
- case L'Z':
- case L'[': case L'\\': case L']': case L'^': case L'_':
- case L'a': case L'b': case L'c': case L'd': case L'e':
- case L'f': case L'g': case L'h': case L'i': case L'j':
- case L'k': case L'l': case L'm': case L'n': case L'o':
- case L'p': case L'q': case L'r': case L's': case L't':
- case L'u': case L'v': case L'w': case L'x': case L'y':
- case L'z': case L'{': case L'|': case L'}': case L'~':
- break;
- default:
- return (wctype_t) 0;
- }
-# endif
+ {
+ case L' ': case L'!': case L'"': case L'#': case L'%':
+ case L'&': case L'\'': case L'(': case L')': case L'*':
+ case L'+': case L',': case L'-': case L'.': case L'/':
+ case L'0': case L'1': case L'2': case L'3': case L'4':
+ case L'5': case L'6': case L'7': case L'8': case L'9':
+ case L':': case L';': case L'<': case L'=': case L'>':
+ case L'?':
+ case L'A': case L'B': case L'C': case L'D': case L'E':
+ case L'F': case L'G': case L'H': case L'I': case L'J':
+ case L'K': case L'L': case L'M': case L'N': case L'O':
+ case L'P': case L'Q': case L'R': case L'S': case L'T':
+ case L'U': case L'V': case L'W': case L'X': case L'Y':
+ case L'Z':
+ case L'[': case L'\\': case L']': case L'^': case L'_':
+ case L'a': case L'b': case L'c': case L'd': case L'e':
+ case L'f': case L'g': case L'h': case L'i': case L'j':
+ case L'k': case L'l': case L'm': case L'n': case L'o':
+ case L'p': case L'q': case L'r': case L's': case L't':
+ case L'u': case L'v': case L'w': case L'x': case L'y':
+ case L'z': case L'{': case L'|': case L'}': case L'~':
+ break;
+ default:
+ return (wctype_t) 0;
+ }
+#endif
/* Avoid overrunning the buffer. */
if (cp == s + CHAR_CLASS_MAX_LENGTH)
- return (wctype_t) 0;
+ return (wctype_t) 0;
*cp++ = (char) *wcs++;
}
@@ -308,23 +225,17 @@ is_char_class (const wchar_t *wcs)
*cp = '\0';
-# ifdef _LIBC
- return __wctype (s);
-# else
return wctype (s);
-# endif
}
-# define IS_CHAR_CLASS(string) is_char_class (string)
+#define IS_CHAR_CLASS(string) is_char_class (string)
-# include "fnmatch_loop.c"
-# endif
+#include "fnmatch_loop.c"
int
fnmatch (const char *pattern, const char *string, int flags)
{
-# if HANDLE_MULTIBYTE
- if (__builtin_expect (MB_CUR_MAX, 1) != 1)
+ if (__glibc_unlikely (MB_CUR_MAX != 1))
{
mbstate_t ps;
size_t n;
@@ -338,126 +249,113 @@ fnmatch (const char *pattern, const char *string, int flags)
/* Convert the strings into wide characters. */
memset (&ps, '\0', sizeof (ps));
p = pattern;
-#ifdef _LIBC
- n = __strnlen (pattern, 1024);
-#else
- n = strlen (pattern);
-#endif
+ n = strnlen (pattern, 1024);
if (__glibc_likely (n < 1024))
- {
- wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
- alloca_used);
- n = mbsrtowcs (wpattern, &p, n + 1, &ps);
- if (__glibc_unlikely (n == (size_t) -1))
- /* Something wrong.
- XXX Do we have to set `errno' to something which mbsrtows hasn't
- already done? */
- return -1;
- if (p)
- {
- memset (&ps, '\0', sizeof (ps));
- goto prepare_wpattern;
- }
- }
+ {
+ wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
+ alloca_used);
+ n = mbsrtowcs (wpattern, &p, n + 1, &ps);
+ if (__glibc_unlikely (n == (size_t) -1))
+ /* Something wrong.
+ XXX Do we have to set 'errno' to something which mbsrtows hasn't
+ already done? */
+ return -1;
+ if (p)
+ {
+ memset (&ps, '\0', sizeof (ps));
+ goto prepare_wpattern;
+ }
+ }
else
- {
- prepare_wpattern:
- n = mbsrtowcs (NULL, &pattern, 0, &ps);
- if (__glibc_unlikely (n == (size_t) -1))
- /* Something wrong.
- XXX Do we have to set `errno' to something which mbsrtows hasn't
- already done? */
- return -1;
- if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
- {
- __set_errno (ENOMEM);
- return -2;
- }
- wpattern_malloc = wpattern
- = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
- assert (mbsinit (&ps));
- if (wpattern == NULL)
- return -2;
- (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
- }
+ {
+ prepare_wpattern:
+ n = mbsrtowcs (NULL, &pattern, 0, &ps);
+ if (__glibc_unlikely (n == (size_t) -1))
+ /* Something wrong.
+ XXX Do we have to set 'errno' to something which mbsrtows hasn't
+ already done? */
+ return -1;
+ if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
+ {
+ __set_errno (ENOMEM);
+ return -2;
+ }
+ wpattern_malloc = wpattern
+ = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
+ assert (mbsinit (&ps));
+ if (wpattern == NULL)
+ return -2;
+ (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
+ }
assert (mbsinit (&ps));
-#ifdef _LIBC
- n = __strnlen (string, 1024);
-#else
- n = strlen (string);
-#endif
+ n = strnlen (string, 1024);
p = string;
if (__glibc_likely (n < 1024))
- {
- wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
- alloca_used);
- n = mbsrtowcs (wstring, &p, n + 1, &ps);
- if (__glibc_unlikely (n == (size_t) -1))
- {
- /* Something wrong.
- XXX Do we have to set `errno' to something which
- mbsrtows hasn't already done? */
- free_return:
- free (wpattern_malloc);
- return -1;
- }
- if (p)
- {
- memset (&ps, '\0', sizeof (ps));
- goto prepare_wstring;
- }
- }
+ {
+ wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
+ alloca_used);
+ n = mbsrtowcs (wstring, &p, n + 1, &ps);
+ if (__glibc_unlikely (n == (size_t) -1))
+ {
+ /* Something wrong.
+ XXX Do we have to set 'errno' to something which
+ mbsrtows hasn't already done? */
+ free_return:
+ free (wpattern_malloc);
+ return -1;
+ }
+ if (p)
+ {
+ memset (&ps, '\0', sizeof (ps));
+ goto prepare_wstring;
+ }
+ }
else
- {
- prepare_wstring:
- n = mbsrtowcs (NULL, &string, 0, &ps);
- if (__glibc_unlikely (n == (size_t) -1))
- /* Something wrong.
- XXX Do we have to set `errno' to something which mbsrtows hasn't
- already done? */
- goto free_return;
- if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
- {
- free (wpattern_malloc);
- __set_errno (ENOMEM);
- return -2;
- }
-
- wstring_malloc = wstring
- = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
- if (wstring == NULL)
- {
- free (wpattern_malloc);
- return -2;
- }
- assert (mbsinit (&ps));
- (void) mbsrtowcs (wstring, &string, n + 1, &ps);
- }
+ {
+ prepare_wstring:
+ n = mbsrtowcs (NULL, &string, 0, &ps);
+ if (__glibc_unlikely (n == (size_t) -1))
+ /* Something wrong.
+ XXX Do we have to set 'errno' to something which mbsrtows hasn't
+ already done? */
+ goto free_return;
+ if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
+ {
+ free (wpattern_malloc);
+ __set_errno (ENOMEM);
+ return -2;
+ }
+
+ wstring_malloc = wstring
+ = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
+ if (wstring == NULL)
+ {
+ free (wpattern_malloc);
+ return -2;
+ }
+ assert (mbsinit (&ps));
+ (void) mbsrtowcs (wstring, &string, n + 1, &ps);
+ }
int res = internal_fnwmatch (wpattern, wstring, wstring + n,
- flags & FNM_PERIOD, flags, NULL,
- alloca_used);
+ flags & FNM_PERIOD, flags, NULL,
+ alloca_used);
free (wstring_malloc);
free (wpattern_malloc);
return res;
}
-# endif /* mbstate_t and mbsrtowcs or _LIBC. */
return internal_fnmatch (pattern, string, string + strlen (string),
- flags & FNM_PERIOD, flags, NULL, 0);
+ flags & FNM_PERIOD, flags, NULL, 0);
}
-# ifdef _LIBC
-# undef fnmatch
+#undef fnmatch
versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
-# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
strong_alias (__fnmatch, __fnmatch_old)
compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
-# endif
+#endif
libc_hidden_ver (__fnmatch, fnmatch)
-# endif
-
-#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
index 0f890d4782..2804eae6b1 100644
--- a/posix/fnmatch_loop.c
+++ b/posix/fnmatch_loop.c
@@ -15,28 +15,30 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <stdint.h>
+#ifdef _LIBC
+# include <stdint.h>
+#endif
struct STRUCT
{
const CHAR *pattern;
const CHAR *string;
- int no_leading_period;
+ bool no_leading_period;
};
-/* Match STRING against the filename pattern PATTERN, returning zero if
+/* Match STRING against the file name pattern PATTERN, returning zero if
it matches, nonzero if not. */
static int FCT (const CHAR *pattern, const CHAR *string,
- const CHAR *string_end, int no_leading_period, int flags,
- struct STRUCT *ends, size_t alloca_used);
+ const CHAR *string_end, bool no_leading_period, int flags,
+ struct STRUCT *ends, size_t alloca_used);
static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
- const CHAR *string_end, int no_leading_period, int flags,
- size_t alloca_used);
+ const CHAR *string_end, bool no_leading_period, int flags,
+ size_t alloca_used);
static const CHAR *END (const CHAR *patternp);
static int
FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
- int no_leading_period, int flags, struct STRUCT *ends, size_t alloca_used)
+ bool no_leading_period, int flags, struct STRUCT *ends, size_t alloca_used)
{
const CHAR *p = pattern, *n = string;
UCHAR c;
@@ -50,882 +52,868 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
# endif
#endif
- while ((c = *p++) != L('\0'))
+ while ((c = *p++) != L_('\0'))
{
- int new_no_leading_period = 0;
+ bool new_no_leading_period = false;
c = FOLD (c);
switch (c)
- {
- case L('?'):
- if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
- {
- int res = EXT (c, p, n, string_end, no_leading_period,
- flags, alloca_used);
- if (res != -1)
- return res;
- }
-
- if (n == string_end)
- return FNM_NOMATCH;
- else if (*n == L('/') && (flags & FNM_FILE_NAME))
- return FNM_NOMATCH;
- else if (*n == L('.') && no_leading_period)
- return FNM_NOMATCH;
- break;
-
- case L('\\'):
- if (!(flags & FNM_NOESCAPE))
- {
- c = *p++;
- if (c == L('\0'))
- /* Trailing \ loses. */
- return FNM_NOMATCH;
- c = FOLD (c);
- }
- if (n == string_end || FOLD ((UCHAR) *n) != c)
- return FNM_NOMATCH;
- break;
-
- case L('*'):
- if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
- {
- int res = EXT (c, p, n, string_end, no_leading_period,
- flags, alloca_used);
- if (res != -1)
- return res;
- }
- else if (ends != NULL)
- {
- ends->pattern = p - 1;
- ends->string = n;
- ends->no_leading_period = no_leading_period;
- return 0;
- }
-
- if (n != string_end && *n == L('.') && no_leading_period)
- return FNM_NOMATCH;
-
- for (c = *p++; c == L('?') || c == L('*'); c = *p++)
- {
- if (*p == L('(') && (flags & FNM_EXTMATCH) != 0)
- {
- const CHAR *endp = END (p);
- if (endp != p)
- {
- /* This is a pattern. Skip over it. */
- p = endp;
- continue;
- }
- }
-
- if (c == L('?'))
- {
- /* A ? needs to match one character. */
- if (n == string_end)
- /* There isn't another character; no match. */
- return FNM_NOMATCH;
- else if (*n == L('/')
- && __builtin_expect (flags & FNM_FILE_NAME, 0))
- /* A slash does not match a wildcard under
- FNM_FILE_NAME. */
- return FNM_NOMATCH;
- else
- /* One character of the string is consumed in matching
- this ? wildcard, so *??? won't match if there are
- less than three characters. */
- ++n;
- }
- }
-
- if (c == L('\0'))
- /* The wildcard(s) is/are the last element of the pattern.
- If the name is a file name and contains another slash
- this means it cannot match, unless the FNM_LEADING_DIR
- flag is set. */
- {
- int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
-
- if (flags & FNM_FILE_NAME)
- {
- if (flags & FNM_LEADING_DIR)
- result = 0;
- else
- {
- if (MEMCHR (n, L('/'), string_end - n) == NULL)
- result = 0;
- }
- }
-
- return result;
- }
- else
- {
- const CHAR *endp;
- struct STRUCT end;
-
- end.pattern = NULL;
- endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'),
- string_end - n);
- if (endp == NULL)
- endp = string_end;
-
- if (c == L('[')
- || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
- && (c == L('@') || c == L('+') || c == L('!'))
- && *p == L('(')))
- {
- int flags2 = ((flags & FNM_FILE_NAME)
- ? flags : (flags & ~FNM_PERIOD));
-
- for (--p; n < endp; ++n, no_leading_period = 0)
- if (FCT (p, n, string_end, no_leading_period, flags2,
- &end, alloca_used) == 0)
- goto found;
- }
- else if (c == L('/') && (flags & FNM_FILE_NAME))
- {
- while (n < string_end && *n != L('/'))
- ++n;
- if (n < string_end && *n == L('/')
- && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
- NULL, alloca_used) == 0))
- return 0;
- }
- else
- {
- int flags2 = ((flags & FNM_FILE_NAME)
- ? flags : (flags & ~FNM_PERIOD));
-
- if (c == L('\\') && !(flags & FNM_NOESCAPE))
- c = *p;
- c = FOLD (c);
- for (--p; n < endp; ++n, no_leading_period = 0)
- if (FOLD ((UCHAR) *n) == c
- && (FCT (p, n, string_end, no_leading_period, flags2,
- &end, alloca_used) == 0))
- {
- found:
- if (end.pattern == NULL)
- return 0;
- break;
- }
- if (end.pattern != NULL)
- {
- p = end.pattern;
- n = end.string;
- no_leading_period = end.no_leading_period;
- continue;
- }
- }
- }
-
- /* If we come here no match is possible with the wildcard. */
- return FNM_NOMATCH;
-
- case L('['):
- {
- /* Nonzero if the sense of the character class is inverted. */
- const CHAR *p_init = p;
- const CHAR *n_init = n;
- int not;
- CHAR cold;
- UCHAR fn;
-
- if (posixly_correct == 0)
- posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
-
- if (n == string_end)
- return FNM_NOMATCH;
-
- if (*n == L('.') && no_leading_period)
- return FNM_NOMATCH;
-
- if (*n == L('/') && (flags & FNM_FILE_NAME))
- /* `/' cannot be matched. */
- return FNM_NOMATCH;
-
- not = (*p == L('!') || (posixly_correct < 0 && *p == L('^')));
- if (not)
- ++p;
-
- fn = FOLD ((UCHAR) *n);
-
- c = *p++;
- for (;;)
- {
- if (!(flags & FNM_NOESCAPE) && c == L('\\'))
- {
- if (*p == L('\0'))
- return FNM_NOMATCH;
- c = FOLD ((UCHAR) *p);
- ++p;
-
- goto normal_bracket;
- }
- else if (c == L('[') && *p == L(':'))
- {
- /* Leave room for the null. */
- CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
- size_t c1 = 0;
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
- wctype_t wt;
-#endif
- const CHAR *startp = p;
-
- for (;;)
- {
- if (c1 == CHAR_CLASS_MAX_LENGTH)
- /* The name is too long and therefore the pattern
- is ill-formed. */
- return FNM_NOMATCH;
-
- c = *++p;
- if (c == L(':') && p[1] == L(']'))
- {
- p += 2;
- break;
- }
- if (c < L('a') || c >= L('z'))
- {
- /* This cannot possibly be a character class name.
- Match it as a normal range. */
- p = startp;
- c = L('[');
- goto normal_bracket;
- }
- str[c1++] = c;
- }
- str[c1] = L('\0');
-
-#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
- wt = IS_CHAR_CLASS (str);
- if (wt == 0)
- /* Invalid character class name. */
- return FNM_NOMATCH;
-
-# if defined _LIBC && ! WIDE_CHAR_VERSION
- /* The following code is glibc specific but does
- there a good job in speeding up the code since
- we can avoid the btowc() call. */
- if (_ISCTYPE ((UCHAR) *n, wt))
- goto matched;
-# else
- if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
- goto matched;
-# endif
+ {
+ case L_('?'):
+ if (__glibc_unlikely (flags & FNM_EXTMATCH) && *p == '(')
+ {
+ int res = EXT (c, p, n, string_end, no_leading_period,
+ flags, alloca_used);
+ if (res != -1)
+ return res;
+ }
+
+ if (n == string_end)
+ return FNM_NOMATCH;
+ else if (*n == L_('/') && (flags & FNM_FILE_NAME))
+ return FNM_NOMATCH;
+ else if (*n == L_('.') && no_leading_period)
+ return FNM_NOMATCH;
+ break;
+
+ case L_('\\'):
+ if (!(flags & FNM_NOESCAPE))
+ {
+ c = *p++;
+ if (c == L_('\0'))
+ /* Trailing \ loses. */
+ return FNM_NOMATCH;
+ c = FOLD (c);
+ }
+ if (n == string_end || FOLD ((UCHAR) *n) != c)
+ return FNM_NOMATCH;
+ break;
+
+ case L_('*'):
+ if (__glibc_unlikely (flags & FNM_EXTMATCH) && *p == '(')
+ {
+ int res = EXT (c, p, n, string_end, no_leading_period,
+ flags, alloca_used);
+ if (res != -1)
+ return res;
+ }
+ else if (ends != NULL)
+ {
+ ends->pattern = p - 1;
+ ends->string = n;
+ ends->no_leading_period = no_leading_period;
+ return 0;
+ }
+
+ if (n != string_end && *n == L_('.') && no_leading_period)
+ return FNM_NOMATCH;
+
+ for (c = *p++; c == L_('?') || c == L_('*'); c = *p++)
+ {
+ if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0)
+ {
+ const CHAR *endp = END (p);
+ if (endp != p)
+ {
+ /* This is a pattern. Skip over it. */
+ p = endp;
+ continue;
+ }
+ }
+
+ if (c == L_('?'))
+ {
+ /* A ? needs to match one character. */
+ if (n == string_end)
+ /* There isn't another character; no match. */
+ return FNM_NOMATCH;
+ else if (*n == L_('/')
+ && __glibc_unlikely (flags & FNM_FILE_NAME))
+ /* A slash does not match a wildcard under
+ FNM_FILE_NAME. */
+ return FNM_NOMATCH;
+ else
+ /* One character of the string is consumed in matching
+ this ? wildcard, so *??? won't match if there are
+ less than three characters. */
+ ++n;
+ }
+ }
+
+ if (c == L_('\0'))
+ /* The wildcard(s) is/are the last element of the pattern.
+ If the name is a file name and contains another slash
+ this means it cannot match, unless the FNM_LEADING_DIR
+ flag is set. */
+ {
+ int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
+
+ if (flags & FNM_FILE_NAME)
+ {
+ if (flags & FNM_LEADING_DIR)
+ result = 0;
+ else
+ {
+ if (MEMCHR (n, L_('/'), string_end - n) == NULL)
+ result = 0;
+ }
+ }
+
+ return result;
+ }
+ else
+ {
+ const CHAR *endp;
+ struct STRUCT end;
+
+ end.pattern = NULL;
+ endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'),
+ string_end - n);
+ if (endp == NULL)
+ endp = string_end;
+
+ if (c == L_('[')
+ || (__glibc_unlikely (flags & FNM_EXTMATCH)
+ && (c == L_('@') || c == L_('+') || c == L_('!'))
+ && *p == L_('(')))
+ {
+ int flags2 = ((flags & FNM_FILE_NAME)
+ ? flags : (flags & ~FNM_PERIOD));
+
+ for (--p; n < endp; ++n, no_leading_period = false)
+ if (FCT (p, n, string_end, no_leading_period, flags2,
+ &end, alloca_used) == 0)
+ goto found;
+ }
+ else if (c == L_('/') && (flags & FNM_FILE_NAME))
+ {
+ while (n < string_end && *n != L_('/'))
+ ++n;
+ if (n < string_end && *n == L_('/')
+ && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
+ NULL, alloca_used) == 0))
+ return 0;
+ }
+ else
+ {
+ int flags2 = ((flags & FNM_FILE_NAME)
+ ? flags : (flags & ~FNM_PERIOD));
+
+ if (c == L_('\\') && !(flags & FNM_NOESCAPE))
+ c = *p;
+ c = FOLD (c);
+ for (--p; n < endp; ++n, no_leading_period = false)
+ if (FOLD ((UCHAR) *n) == c
+ && (FCT (p, n, string_end, no_leading_period, flags2,
+ &end, alloca_used) == 0))
+ {
+ found:
+ if (end.pattern == NULL)
+ return 0;
+ break;
+ }
+ if (end.pattern != NULL)
+ {
+ p = end.pattern;
+ n = end.string;
+ no_leading_period = end.no_leading_period;
+ continue;
+ }
+ }
+ }
+
+ /* If we come here no match is possible with the wildcard. */
+ return FNM_NOMATCH;
+
+ case L_('['):
+ {
+ /* Nonzero if the sense of the character class is inverted. */
+ const CHAR *p_init = p;
+ const CHAR *n_init = n;
+ bool not;
+ CHAR cold;
+ UCHAR fn;
+
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ if (n == string_end)
+ return FNM_NOMATCH;
+
+ if (*n == L_('.') && no_leading_period)
+ return FNM_NOMATCH;
+
+ if (*n == L_('/') && (flags & FNM_FILE_NAME))
+ /* '/' cannot be matched. */
+ return FNM_NOMATCH;
+
+ not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^')));
+ if (not)
+ ++p;
+
+ fn = FOLD ((UCHAR) *n);
+
+ c = *p++;
+ for (;;)
+ {
+ if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
+ {
+ if (*p == L_('\0'))
+ return FNM_NOMATCH;
+ c = FOLD ((UCHAR) *p);
+ ++p;
+
+ goto normal_bracket;
+ }
+ else if (c == L_('[') && *p == L_(':'))
+ {
+ /* Leave room for the null. */
+ CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
+ size_t c1 = 0;
+ wctype_t wt;
+ const CHAR *startp = p;
+
+ for (;;)
+ {
+ if (c1 == CHAR_CLASS_MAX_LENGTH)
+ /* The name is too long and therefore the pattern
+ is ill-formed. */
+ return FNM_NOMATCH;
+
+ c = *++p;
+ if (c == L_(':') && p[1] == L_(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c < L_('a') || c >= L_('z'))
+ {
+ /* This cannot possibly be a character class name.
+ Match it as a normal range. */
+ p = startp;
+ c = L_('[');
+ goto normal_bracket;
+ }
+ str[c1++] = c;
+ }
+ str[c1] = L_('\0');
+
+ wt = IS_CHAR_CLASS (str);
+ if (wt == 0)
+ /* Invalid character class name. */
+ return FNM_NOMATCH;
+
+#if defined _LIBC && ! WIDE_CHAR_VERSION
+ /* The following code is glibc specific but does
+ there a good job in speeding up the code since
+ we can avoid the btowc() call. */
+ if (_ISCTYPE ((UCHAR) *n, wt))
+ goto matched;
#else
- if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n))
- || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n))
- || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n))
- || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n))
- || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n))
- || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n))
- || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n))
- || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n))
- || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n))
- || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n))
- || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n))
- || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n)))
- goto matched;
+ if (iswctype (BTOWC ((UCHAR) *n), wt))
+ goto matched;
#endif
- c = *p++;
- }
+ c = *p++;
+ }
#ifdef _LIBC
- else if (c == L('[') && *p == L('='))
- {
- /* It's important that STR be a scalar variable rather
- than a one-element array, because GCC (at least 4.9.2
- -O2 on x86-64) can be confused by the array and
- diagnose a "used initialized" in a dead branch in the
- findidx function. */
- UCHAR str;
- uint32_t nrules =
- _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- const CHAR *startp = p;
-
- c = *++p;
- if (c == L('\0'))
- {
- p = startp;
- c = L('[');
- goto normal_bracket;
- }
- str = c;
-
- c = *++p;
- if (c != L('=') || p[1] != L(']'))
- {
- p = startp;
- c = L('[');
- goto normal_bracket;
- }
- p += 2;
-
- if (nrules == 0)
- {
- if ((UCHAR) *n == str)
- goto matched;
- }
- else
- {
- const int32_t *table;
+ else if (c == L_('[') && *p == L_('='))
+ {
+ /* It's important that STR be a scalar variable rather
+ than a one-element array, because GCC (at least 4.9.2
+ -O2 on x86-64) can be confused by the array and
+ diagnose a "used initialized" in a dead branch in the
+ findidx function. */
+ UCHAR str;
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+
+ c = *++p;
+ if (c == L_('\0'))
+ {
+ p = startp;
+ c = L_('[');
+ goto normal_bracket;
+ }
+ str = c;
+
+ c = *++p;
+ if (c != L_('=') || p[1] != L_(']'))
+ {
+ p = startp;
+ c = L_('[');
+ goto normal_bracket;
+ }
+ p += 2;
+
+ if (nrules == 0)
+ {
+ if ((UCHAR) *n == str)
+ goto matched;
+ }
+ else
+ {
+ const int32_t *table;
# if WIDE_CHAR_VERSION
- const int32_t *weights;
- const wint_t *extra;
+ const int32_t *weights;
+ const wint_t *extra;
# else
- const unsigned char *weights;
- const unsigned char *extra;
+ const unsigned char *weights;
+ const unsigned char *extra;
# endif
- const int32_t *indirect;
- int32_t idx;
- const UCHAR *cp = (const UCHAR *) &str;
+ const int32_t *indirect;
+ int32_t idx;
+ const UCHAR *cp = (const UCHAR *) &str;
# if WIDE_CHAR_VERSION
- table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
- weights = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
- extra = (const wint_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
- indirect = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+ weights = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+ extra = (const wint_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
# else
- table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- weights = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
- indirect = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ weights = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
# endif
- idx = FINDIDX (table, indirect, extra, &cp, 1);
- if (idx != 0)
- {
- /* We found a table entry. Now see whether the
- character we are currently at has the same
- equivalance class value. */
- int len = weights[idx & 0xffffff];
- int32_t idx2;
- const UCHAR *np = (const UCHAR *) n;
-
- idx2 = FINDIDX (table, indirect, extra,
- &np, string_end - n);
- if (idx2 != 0
- && (idx >> 24) == (idx2 >> 24)
- && len == weights[idx2 & 0xffffff])
- {
- int cnt = 0;
-
- idx &= 0xffffff;
- idx2 &= 0xffffff;
-
- while (cnt < len
- && (weights[idx + 1 + cnt]
- == weights[idx2 + 1 + cnt]))
- ++cnt;
-
- if (cnt == len)
- goto matched;
- }
- }
- }
-
- c = *p++;
- }
+ idx = FINDIDX (table, indirect, extra, &cp, 1);
+ if (idx != 0)
+ {
+ /* We found a table entry. Now see whether the
+ character we are currently at has the same
+ equivalence class value. */
+ int len = weights[idx & 0xffffff];
+ int32_t idx2;
+ const UCHAR *np = (const UCHAR *) n;
+
+ idx2 = FINDIDX (table, indirect, extra,
+ &np, string_end - n);
+ if (idx2 != 0
+ && (idx >> 24) == (idx2 >> 24)
+ && len == weights[idx2 & 0xffffff])
+ {
+ int cnt = 0;
+
+ idx &= 0xffffff;
+ idx2 &= 0xffffff;
+
+ while (cnt < len
+ && (weights[idx + 1 + cnt]
+ == weights[idx2 + 1 + cnt]))
+ ++cnt;
+
+ if (cnt == len)
+ goto matched;
+ }
+ }
+ }
+
+ c = *p++;
+ }
#endif
- else if (c == L('\0'))
- {
- /* [ unterminated, treat as normal character. */
- p = p_init;
- n = n_init;
- c = L('[');
- goto normal_match;
- }
- else
- {
- int is_range = 0;
+ else if (c == L_('\0'))
+ {
+ /* [ unterminated, treat as normal character. */
+ p = p_init;
+ n = n_init;
+ c = L_('[');
+ goto normal_match;
+ }
+ else
+ {
+ bool is_range = false;
#ifdef _LIBC
- int is_seqval = 0;
-
- if (c == L('[') && *p == L('.'))
- {
- uint32_t nrules =
- _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- const CHAR *startp = p;
- size_t c1 = 0;
-
- while (1)
- {
- c = *++p;
- if (c == L('.') && p[1] == L(']'))
- {
- p += 2;
- break;
- }
- if (c == '\0')
- return FNM_NOMATCH;
- ++c1;
- }
-
- /* We have to handling the symbols differently in
- ranges since then the collation sequence is
- important. */
- is_range = *p == L('-') && p[1] != L('\0');
-
- if (nrules == 0)
- {
- /* There are no names defined in the collation
- data. Therefore we only accept the trivial
- names consisting of the character itself. */
- if (c1 != 1)
- return FNM_NOMATCH;
-
- if (!is_range && *n == startp[1])
- goto matched;
-
- cold = startp[1];
- c = *p++;
- }
- else
- {
- int32_t table_size;
- const int32_t *symb_table;
- const unsigned char *extra;
- int32_t idx;
- int32_t elem;
+ bool is_seqval = false;
+
+ if (c == L_('[') && *p == L_('.'))
+ {
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+ size_t c1 = 0;
+
+ while (1)
+ {
+ c = *++p;
+ if (c == L_('.') && p[1] == L_(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c == '\0')
+ return FNM_NOMATCH;
+ ++c1;
+ }
+
+ /* We have to handling the symbols differently in
+ ranges since then the collation sequence is
+ important. */
+ is_range = *p == L_('-') && p[1] != L_('\0');
+
+ if (nrules == 0)
+ {
+ /* There are no names defined in the collation
+ data. Therefore we only accept the trivial
+ names consisting of the character itself. */
+ if (c1 != 1)
+ return FNM_NOMATCH;
+
+ if (!is_range && *n == startp[1])
+ goto matched;
+
+ cold = startp[1];
+ c = *p++;
+ }
+ else
+ {
+ int32_t table_size;
+ const int32_t *symb_table;
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
# if WIDE_CHAR_VERSION
- CHAR *wextra;
+ CHAR *wextra;
# endif
- table_size =
- _NL_CURRENT_WORD (LC_COLLATE,
- _NL_COLLATE_SYMB_HASH_SIZEMB);
- symb_table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_TABLEMB);
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_EXTRAMB);
-
- for (elem = 0; elem < table_size; elem++)
- if (symb_table[2 * elem] != 0)
- {
- idx = symb_table[2 * elem + 1];
- /* Skip the name of collating element. */
- idx += 1 + extra[idx];
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ for (elem = 0; elem < table_size; elem++)
+ if (symb_table[2 * elem] != 0)
+ {
+ idx = symb_table[2 * elem + 1];
+ /* Skip the name of collating element. */
+ idx += 1 + extra[idx];
# if WIDE_CHAR_VERSION
- /* Skip the byte sequence of the
- collating element. */
- idx += 1 + extra[idx];
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
-
- wextra = (CHAR *) &extra[idx + 4];
-
- if (/* Compare the length of the sequence. */
- c1 == wextra[0]
- /* Compare the wide char sequence. */
- && WMEMCMP (startp + 1, &wextra[1],
- c1) == 0)
- /* Yep, this is the entry. */
- break;
+ /* Skip the byte sequence of the
+ collating element. */
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+
+ wextra = (CHAR *) &extra[idx + 4];
+
+ if (/* Compare the length of the sequence. */
+ c1 == wextra[0]
+ /* Compare the wide char sequence. */
+ && (__wmemcmp (startp + 1, &wextra[1],
+ c1)
+ == 0))
+ /* Yep, this is the entry. */
+ break;
# else
- if (/* Compare the length of the sequence. */
- c1 == extra[idx]
- /* Compare the byte sequence. */
- && memcmp (startp + 1,
- &extra[idx + 1], c1) == 0)
- /* Yep, this is the entry. */
- break;
+ if (/* Compare the length of the sequence. */
+ c1 == extra[idx]
+ /* Compare the byte sequence. */
+ && memcmp (startp + 1,
+ &extra[idx + 1], c1) == 0)
+ /* Yep, this is the entry. */
+ break;
# endif
- }
+ }
- if (elem < table_size)
- {
- /* Compare the byte sequence but only if
- this is not part of a range. */
- if (! is_range
+ if (elem < table_size)
+ {
+ /* Compare the byte sequence but only if
+ this is not part of a range. */
+ if (! is_range
# if WIDE_CHAR_VERSION
- && WMEMCMP (n, &wextra[1], c1) == 0
+ && __wmemcmp (n, &wextra[1], c1) == 0
# else
- && memcmp (n, &extra[idx + 1], c1) == 0
+ && memcmp (n, &extra[idx + 1], c1) == 0
# endif
- )
- {
- n += c1 - 1;
- goto matched;
- }
-
- /* Get the collation sequence value. */
- is_seqval = 1;
+ )
+ {
+ n += c1 - 1;
+ goto matched;
+ }
+
+ /* Get the collation sequence value. */
+ is_seqval = true;
# if WIDE_CHAR_VERSION
- cold = wextra[1 + wextra[0]];
+ cold = wextra[1 + wextra[0]];
# else
- idx += 1 + extra[idx];
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
- cold = *((int32_t *) &extra[idx]);
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+ cold = *((int32_t *) &extra[idx]);
# endif
- c = *p++;
- }
- else if (c1 == 1)
- {
- /* No valid character. Match it as a
- single byte. */
- if (!is_range && *n == startp[1])
- goto matched;
-
- cold = startp[1];
- c = *p++;
- }
- else
- return FNM_NOMATCH;
- }
- }
- else
+ c = *p++;
+ }
+ else if (c1 == 1)
+ {
+ /* No valid character. Match it as a
+ single byte. */
+ if (!is_range && *n == startp[1])
+ goto matched;
+
+ cold = startp[1];
+ c = *p++;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+ }
+ else
#endif
- {
- c = FOLD (c);
- normal_bracket:
-
- /* We have to handling the symbols differently in
- ranges since then the collation sequence is
- important. */
- is_range = (*p == L('-') && p[1] != L('\0')
- && p[1] != L(']'));
-
- if (!is_range && c == fn)
- goto matched;
-
- /* This is needed if we goto normal_bracket; from
- outside of is_seqval's scope. */
- is_seqval = 0;
- cold = c;
- c = *p++;
- }
-
- if (c == L('-') && *p != L(']'))
- {
+ {
+ c = FOLD (c);
+ normal_bracket:
+
+ /* We have to handling the symbols differently in
+ ranges since then the collation sequence is
+ important. */
+ is_range = (*p == L_('-') && p[1] != L_('\0')
+ && p[1] != L_(']'));
+
+ if (!is_range && c == fn)
+ goto matched;
+
+#if _LIBC
+ /* This is needed if we goto normal_bracket; from
+ outside of is_seqval's scope. */
+ is_seqval = false;
+#endif
+ cold = c;
+ c = *p++;
+ }
+
+ if (c == L_('-') && *p != L_(']'))
+ {
#if _LIBC
- /* We have to find the collation sequence
- value for C. Collation sequence is nothing
- we can regularly access. The sequence
- value is defined by the order in which the
- definitions of the collation values for the
- various characters appear in the source
- file. A strange concept, nowhere
- documented. */
- uint32_t fcollseq;
- uint32_t lcollseq;
- UCHAR cend = *p++;
+ /* We have to find the collation sequence
+ value for C. Collation sequence is nothing
+ we can regularly access. The sequence
+ value is defined by the order in which the
+ definitions of the collation values for the
+ various characters appear in the source
+ file. A strange concept, nowhere
+ documented. */
+ uint32_t fcollseq;
+ uint32_t lcollseq;
+ UCHAR cend = *p++;
# if WIDE_CHAR_VERSION
- /* Search in the `names' array for the characters. */
- fcollseq = __collseq_table_lookup (collseq, fn);
- if (fcollseq == ~((uint32_t) 0))
- /* XXX We don't know anything about the character
- we are supposed to match. This means we are
- failing. */
- goto range_not_matched;
-
- if (is_seqval)
- lcollseq = cold;
- else
- lcollseq = __collseq_table_lookup (collseq, cold);
+ /* Search in the 'names' array for the characters. */
+ fcollseq = __collseq_table_lookup (collseq, fn);
+ if (fcollseq == ~((uint32_t) 0))
+ /* XXX We don't know anything about the character
+ we are supposed to match. This means we are
+ failing. */
+ goto range_not_matched;
+
+ if (is_seqval)
+ lcollseq = cold;
+ else
+ lcollseq = __collseq_table_lookup (collseq, cold);
# else
- fcollseq = collseq[fn];
- lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
+ fcollseq = collseq[fn];
+ lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
# endif
- is_seqval = 0;
- if (cend == L('[') && *p == L('.'))
- {
- uint32_t nrules =
- _NL_CURRENT_WORD (LC_COLLATE,
- _NL_COLLATE_NRULES);
- const CHAR *startp = p;
- size_t c1 = 0;
-
- while (1)
- {
- c = *++p;
- if (c == L('.') && p[1] == L(']'))
- {
- p += 2;
- break;
- }
- if (c == '\0')
- return FNM_NOMATCH;
- ++c1;
- }
-
- if (nrules == 0)
- {
- /* There are no names defined in the
- collation data. Therefore we only
- accept the trivial names consisting
- of the character itself. */
- if (c1 != 1)
- return FNM_NOMATCH;
-
- cend = startp[1];
- }
- else
- {
- int32_t table_size;
- const int32_t *symb_table;
- const unsigned char *extra;
- int32_t idx;
- int32_t elem;
+ is_seqval = false;
+ if (cend == L_('[') && *p == L_('.'))
+ {
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+ size_t c1 = 0;
+
+ while (1)
+ {
+ c = *++p;
+ if (c == L_('.') && p[1] == L_(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c == '\0')
+ return FNM_NOMATCH;
+ ++c1;
+ }
+
+ if (nrules == 0)
+ {
+ /* There are no names defined in the
+ collation data. Therefore we only
+ accept the trivial names consisting
+ of the character itself. */
+ if (c1 != 1)
+ return FNM_NOMATCH;
+
+ cend = startp[1];
+ }
+ else
+ {
+ int32_t table_size;
+ const int32_t *symb_table;
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
# if WIDE_CHAR_VERSION
- CHAR *wextra;
+ CHAR *wextra;
# endif
- table_size =
- _NL_CURRENT_WORD (LC_COLLATE,
- _NL_COLLATE_SYMB_HASH_SIZEMB);
- symb_table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_TABLEMB);
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_EXTRAMB);
-
- for (elem = 0; elem < table_size; elem++)
- if (symb_table[2 * elem] != 0)
- {
- idx = symb_table[2 * elem + 1];
- /* Skip the name of collating
- element. */
- idx += 1 + extra[idx];
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ for (elem = 0; elem < table_size; elem++)
+ if (symb_table[2 * elem] != 0)
+ {
+ idx = symb_table[2 * elem + 1];
+ /* Skip the name of collating
+ element. */
+ idx += 1 + extra[idx];
# if WIDE_CHAR_VERSION
- /* Skip the byte sequence of the
- collating element. */
- idx += 1 + extra[idx];
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
-
- wextra = (CHAR *) &extra[idx + 4];
-
- if (/* Compare the length of the
- sequence. */
- c1 == wextra[0]
- /* Compare the wide char sequence. */
- && WMEMCMP (startp + 1, &wextra[1],
- c1) == 0)
- /* Yep, this is the entry. */
- break;
+ /* Skip the byte sequence of the
+ collating element. */
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+
+ wextra = (CHAR *) &extra[idx + 4];
+
+ if (/* Compare the length of the
+ sequence. */
+ c1 == wextra[0]
+ /* Compare the wide char sequence. */
+ && (__wmemcmp (startp + 1,
+ &wextra[1], c1)
+ == 0))
+ /* Yep, this is the entry. */
+ break;
# else
- if (/* Compare the length of the
- sequence. */
- c1 == extra[idx]
- /* Compare the byte sequence. */
- && memcmp (startp + 1,
- &extra[idx + 1], c1) == 0)
- /* Yep, this is the entry. */
- break;
+ if (/* Compare the length of the
+ sequence. */
+ c1 == extra[idx]
+ /* Compare the byte sequence. */
+ && memcmp (startp + 1,
+ &extra[idx + 1], c1) == 0)
+ /* Yep, this is the entry. */
+ break;
# endif
- }
+ }
- if (elem < table_size)
- {
- /* Get the collation sequence value. */
- is_seqval = 1;
+ if (elem < table_size)
+ {
+ /* Get the collation sequence value. */
+ is_seqval = true;
# if WIDE_CHAR_VERSION
- cend = wextra[1 + wextra[0]];
+ cend = wextra[1 + wextra[0]];
# else
- idx += 1 + extra[idx];
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
- cend = *((int32_t *) &extra[idx]);
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+ cend = *((int32_t *) &extra[idx]);
# endif
- }
- else if (c1 == 1)
- {
- cend = startp[1];
- c = *p++;
- }
- else
- return FNM_NOMATCH;
- }
- }
- else
- {
- if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
- cend = *p++;
- if (cend == L('\0'))
- return FNM_NOMATCH;
- cend = FOLD (cend);
- }
-
- /* XXX It is not entirely clear to me how to handle
- characters which are not mentioned in the
- collation specification. */
- if (
+ }
+ else if (c1 == 1)
+ {
+ cend = startp[1];
+ c = *p++;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+ }
+ else
+ {
+ if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
+ cend = *p++;
+ if (cend == L_('\0'))
+ return FNM_NOMATCH;
+ cend = FOLD (cend);
+ }
+
+ /* XXX It is not entirely clear to me how to handle
+ characters which are not mentioned in the
+ collation specification. */
+ if (
# if WIDE_CHAR_VERSION
- lcollseq == 0xffffffff ||
+ lcollseq == 0xffffffff ||
# endif
- lcollseq <= fcollseq)
- {
- /* We have to look at the upper bound. */
- uint32_t hcollseq;
-
- if (is_seqval)
- hcollseq = cend;
- else
- {
+ lcollseq <= fcollseq)
+ {
+ /* We have to look at the upper bound. */
+ uint32_t hcollseq;
+
+ if (is_seqval)
+ hcollseq = cend;
+ else
+ {
# if WIDE_CHAR_VERSION
- hcollseq =
- __collseq_table_lookup (collseq, cend);
- if (hcollseq == ~((uint32_t) 0))
- {
- /* Hum, no information about the upper
- bound. The matching succeeds if the
- lower bound is matched exactly. */
- if (lcollseq != fcollseq)
- goto range_not_matched;
-
- goto matched;
- }
+ hcollseq =
+ __collseq_table_lookup (collseq, cend);
+ if (hcollseq == ~((uint32_t) 0))
+ {
+ /* Hum, no information about the upper
+ bound. The matching succeeds if the
+ lower bound is matched exactly. */
+ if (lcollseq != fcollseq)
+ goto range_not_matched;
+
+ goto matched;
+ }
# else
- hcollseq = collseq[cend];
+ hcollseq = collseq[cend];
# endif
- }
+ }
- if (lcollseq <= hcollseq && fcollseq <= hcollseq)
- goto matched;
- }
+ if (lcollseq <= hcollseq && fcollseq <= hcollseq)
+ goto matched;
+ }
# if WIDE_CHAR_VERSION
- range_not_matched:
+ range_not_matched:
# endif
#else
- /* We use a boring value comparison of the character
- values. This is better than comparing using
- `strcoll' since the latter would have surprising
- and sometimes fatal consequences. */
- UCHAR cend = *p++;
-
- if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
- cend = *p++;
- if (cend == L('\0'))
- return FNM_NOMATCH;
-
- /* It is a range. */
- if (cold <= fn && fn <= cend)
- goto matched;
+ /* We use a boring value comparison of the character
+ values. This is better than comparing using
+ 'strcoll' since the latter would have surprising
+ and sometimes fatal consequences. */
+ UCHAR cend = *p++;
+
+ if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
+ cend = *p++;
+ if (cend == L_('\0'))
+ return FNM_NOMATCH;
+
+ /* It is a range. */
+ if ((UCHAR) cold <= fn && fn <= cend)
+ goto matched;
#endif
- c = *p++;
- }
- }
-
- if (c == L(']'))
- break;
- }
-
- if (!not)
- return FNM_NOMATCH;
- break;
-
- matched:
- /* Skip the rest of the [...] that already matched. */
- while ((c = *p++) != L (']'))
- {
- if (c == L('\0'))
- /* [... (unterminated) loses. */
- return FNM_NOMATCH;
-
- if (!(flags & FNM_NOESCAPE) && c == L('\\'))
- {
- if (*p == L('\0'))
- return FNM_NOMATCH;
- /* XXX 1003.2d11 is unclear if this is right. */
- ++p;
- }
- else if (c == L('[') && *p == L(':'))
- {
- int c1 = 0;
- const CHAR *startp = p;
-
- while (1)
- {
- c = *++p;
- if (++c1 == CHAR_CLASS_MAX_LENGTH)
- return FNM_NOMATCH;
-
- if (*p == L(':') && p[1] == L(']'))
- break;
-
- if (c < L('a') || c >= L('z'))
- {
- p = startp - 2;
- break;
- }
- }
- p += 2;
- }
- else if (c == L('[') && *p == L('='))
- {
- c = *++p;
- if (c == L('\0'))
- return FNM_NOMATCH;
- c = *++p;
- if (c != L('=') || p[1] != L(']'))
- return FNM_NOMATCH;
- p += 2;
- }
- else if (c == L('[') && *p == L('.'))
- {
- while (1)
- {
- c = *++p;
- if (c == L('\0'))
- return FNM_NOMATCH;
-
- if (c == L('.') && p[1] == L(']'))
- break;
- }
- p += 2;
- }
- }
- if (not)
- return FNM_NOMATCH;
- }
- break;
-
- case L('+'):
- case L('@'):
- case L('!'):
- if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
- {
- int res = EXT (c, p, n, string_end, no_leading_period, flags,
- alloca_used);
- if (res != -1)
- return res;
- }
- goto normal_match;
-
- case L('/'):
- if (NO_LEADING_PERIOD (flags))
- {
- if (n == string_end || c != (UCHAR) *n)
- return FNM_NOMATCH;
-
- new_no_leading_period = 1;
- break;
- }
- /* FALLTHROUGH */
- default:
- normal_match:
- if (n == string_end || c != FOLD ((UCHAR) *n))
- return FNM_NOMATCH;
- }
+ c = *p++;
+ }
+ }
+
+ if (c == L_(']'))
+ break;
+ }
+
+ if (!not)
+ return FNM_NOMATCH;
+ break;
+
+ matched:
+ /* Skip the rest of the [...] that already matched. */
+ while ((c = *p++) != L_(']'))
+ {
+ if (c == L_('\0'))
+ /* [... (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
+ {
+ if (*p == L_('\0'))
+ return FNM_NOMATCH;
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
+ else if (c == L_('[') && *p == L_(':'))
+ {
+ int c1 = 0;
+ const CHAR *startp = p;
+
+ while (1)
+ {
+ c = *++p;
+ if (++c1 == CHAR_CLASS_MAX_LENGTH)
+ return FNM_NOMATCH;
+
+ if (*p == L_(':') && p[1] == L_(']'))
+ break;
+
+ if (c < L_('a') || c >= L_('z'))
+ {
+ p = startp - 2;
+ break;
+ }
+ }
+ p += 2;
+ }
+ else if (c == L_('[') && *p == L_('='))
+ {
+ c = *++p;
+ if (c == L_('\0'))
+ return FNM_NOMATCH;
+ c = *++p;
+ if (c != L_('=') || p[1] != L_(']'))
+ return FNM_NOMATCH;
+ p += 2;
+ }
+ else if (c == L_('[') && *p == L_('.'))
+ {
+ while (1)
+ {
+ c = *++p;
+ if (c == L_('\0'))
+ return FNM_NOMATCH;
+
+ if (c == L_('.') && p[1] == L_(']'))
+ break;
+ }
+ p += 2;
+ }
+ }
+ if (not)
+ return FNM_NOMATCH;
+ }
+ break;
+
+ case L_('+'):
+ case L_('@'):
+ case L_('!'):
+ if (__glibc_unlikely (flags & FNM_EXTMATCH) && *p == '(')
+ {
+ int res = EXT (c, p, n, string_end, no_leading_period, flags,
+ alloca_used);
+ if (res != -1)
+ return res;
+ }
+ goto normal_match;
+
+ case L_('/'):
+ if (NO_LEADING_PERIOD (flags))
+ {
+ if (n == string_end || c != (UCHAR) *n)
+ return FNM_NOMATCH;
+
+ new_no_leading_period = true;
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ normal_match:
+ if (n == string_end || c != FOLD ((UCHAR) *n))
+ return FNM_NOMATCH;
+ }
no_leading_period = new_no_leading_period;
++n;
@@ -934,7 +922,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
if (n == string_end)
return 0;
- if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/'))
+ if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/'))
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
return 0;
@@ -948,37 +936,37 @@ END (const CHAR *pattern)
const CHAR *p = pattern;
while (1)
- if (*++p == L('\0'))
+ if (*++p == L_('\0'))
/* This is an invalid pattern. */
return pattern;
- else if (*p == L('['))
+ else if (*p == L_('['))
{
- /* Handle brackets special. */
- if (posixly_correct == 0)
- posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
-
- /* Skip the not sign. We have to recognize it because of a possibly
- following ']'. */
- if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
- ++p;
- /* A leading ']' is recognized as such. */
- if (*p == L(']'))
- ++p;
- /* Skip over all characters of the list. */
- while (*p != L(']'))
- if (*p++ == L('\0'))
- /* This is no valid pattern. */
- return pattern;
+ /* Handle brackets special. */
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ /* Skip the not sign. We have to recognize it because of a possibly
+ following ']'. */
+ if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
+ ++p;
+ /* A leading ']' is recognized as such. */
+ if (*p == L_(']'))
+ ++p;
+ /* Skip over all characters of the list. */
+ while (*p != L_(']'))
+ if (*p++ == L_('\0'))
+ /* This is no valid pattern. */
+ return pattern;
}
- else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
- || *p == L('!')) && p[1] == L('('))
+ else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
+ || *p == L_('!')) && p[1] == L_('('))
{
- p = END (p + 1);
- if (*p == L('\0'))
- /* This is an invalid pattern. */
- return pattern;
+ p = END (p + 1);
+ if (*p == L_('\0'))
+ /* This is an invalid pattern. */
+ return pattern;
}
- else if (*p == L(')'))
+ else if (*p == L_(')'))
break;
return p + 1;
@@ -987,19 +975,19 @@ END (const CHAR *pattern)
static int
EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
- int no_leading_period, int flags, size_t alloca_used)
+ bool no_leading_period, int flags, size_t alloca_used)
{
const CHAR *startp;
- int level;
+ ssize_t level;
struct patternlist
{
struct patternlist *next;
CHAR malloced;
- CHAR str[0];
+ CHAR str[];
} *list = NULL;
struct patternlist **lastp = &list;
size_t pattern_len = STRLEN (pattern);
- int any_malloced = 0;
+ bool any_malloced = false;
const CHAR *p;
const CHAR *rs;
int retval = 0;
@@ -1007,174 +995,180 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
/* Parse the pattern. Store the individual parts in the list. */
level = 0;
for (startp = p = pattern + 1; level >= 0; ++p)
- if (*p == L('\0'))
+ if (*p == L_('\0'))
{
- /* This is an invalid pattern. */
- retval = -1;
- goto out;
+ /* This is an invalid pattern. */
+ retval = -1;
+ goto out;
}
- else if (*p == L('['))
+ else if (*p == L_('['))
{
- /* Handle brackets special. */
- if (posixly_correct == 0)
- posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
-
- /* Skip the not sign. We have to recognize it because of a possibly
- following ']'. */
- if (*++p == L('!') || (posixly_correct < 0 && *p == L('^')))
- ++p;
- /* A leading ']' is recognized as such. */
- if (*p == L(']'))
- ++p;
- /* Skip over all characters of the list. */
- while (*p != L(']'))
- if (*p++ == L('\0'))
- {
- /* This is no valid pattern. */
- retval = -1;
- goto out;
- }
+ /* Handle brackets special. */
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ /* Skip the not sign. We have to recognize it because of a possibly
+ following ']'. */
+ if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
+ ++p;
+ /* A leading ']' is recognized as such. */
+ if (*p == L_(']'))
+ ++p;
+ /* Skip over all characters of the list. */
+ while (*p != L_(']'))
+ if (*p++ == L_('\0'))
+ {
+ /* This is no valid pattern. */
+ retval = -1;
+ goto out;
+ }
}
- else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
- || *p == L('!')) && p[1] == L('('))
+ else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
+ || *p == L_('!')) && p[1] == L_('('))
/* Remember the nesting level. */
++level;
- else if (*p == L(')'))
+ else if (*p == L_(')'))
{
- if (level-- == 0)
- {
- /* This means we found the end of the pattern. */
+ if (level-- == 0)
+ {
+ /* This means we found the end of the pattern. */
#define NEW_PATTERN \
- struct patternlist *newp; \
- size_t slen = (opt == L('?') || opt == L('@') \
- ? pattern_len : (p - startp + 1)); \
- slen = sizeof (struct patternlist) + (slen * sizeof (CHAR)); \
- int malloced = ! __libc_use_alloca (alloca_used + slen); \
- if (__builtin_expect (malloced, 0)) \
- { \
- newp = malloc (slen); \
- if (newp == NULL) \
- { \
- retval = -2; \
- goto out; \
- } \
- any_malloced = 1; \
- } \
- else \
- newp = alloca_account (slen, alloca_used); \
- newp->next = NULL; \
- newp->malloced = malloced; \
- *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
- *lastp = newp; \
- lastp = &newp->next
- NEW_PATTERN;
- }
+ struct patternlist *newp; \
+ size_t plen = (opt == L_('?') || opt == L_('@') \
+ ? pattern_len : (p - startp + 1UL)); \
+ idx_t slen = FLEXSIZEOF (struct patternlist, str, 0); \
+ idx_t new_used = alloca_used + slen; \
+ idx_t plensize; \
+ if (INT_MULTIPLY_WRAPV (plen, sizeof (CHAR), &plensize) \
+ || INT_ADD_WRAPV (new_used, plensize, &new_used)) \
+ { \
+ retval = -2; \
+ goto out; \
+ } \
+ slen += plensize; \
+ bool malloced = ! __libc_use_alloca (new_used); \
+ if (__glibc_unlikely (malloced)) \
+ { \
+ newp = malloc (slen); \
+ if (newp == NULL) \
+ { \
+ retval = -2; \
+ goto out; \
+ } \
+ any_malloced = true; \
+ } \
+ else \
+ newp = alloca_account (slen, alloca_used); \
+ newp->next = NULL; \
+ newp->malloced = malloced; \
+ *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \
+ *lastp = newp; \
+ lastp = &newp->next
+ NEW_PATTERN;
+ }
}
- else if (*p == L('|'))
+ else if (*p == L_('|'))
{
- if (level == 0)
- {
- NEW_PATTERN;
- startp = p + 1;
- }
+ if (level == 0)
+ {
+ NEW_PATTERN;
+ startp = p + 1;
+ }
}
assert (list != NULL);
- assert (p[-1] == L(')'));
+ assert (p[-1] == L_(')'));
#undef NEW_PATTERN
switch (opt)
{
- case L('*'):
+ case L_('*'):
if (FCT (p, string, string_end, no_leading_period, flags, NULL,
- alloca_used) == 0)
- goto success;
- /* FALLTHROUGH */
-
- case L('+'):
+ alloca_used) == 0)
+ goto success;
+ FALLTHROUGH;
+ case L_('+'):
do
- {
- for (rs = string; rs <= string_end; ++rs)
- /* First match the prefix with the current pattern with the
- current pattern. */
- if (FCT (list->str, string, rs, no_leading_period,
- flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
- NULL, alloca_used) == 0
- /* This was successful. Now match the rest with the rest
- of the pattern. */
- && (FCT (p, rs, string_end,
- rs == string
- ? no_leading_period
- : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
- flags & FNM_FILE_NAME
- ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
- /* This didn't work. Try the whole pattern. */
- || (rs != string
- && FCT (pattern - 1, rs, string_end,
- rs == string
- ? no_leading_period
- : (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
- ? 1 : 0),
- flags & FNM_FILE_NAME
- ? flags : flags & ~FNM_PERIOD, NULL,
- alloca_used) == 0)))
- /* It worked. Signal success. */
- goto success;
- }
+ {
+ for (rs = string; rs <= string_end; ++rs)
+ /* First match the prefix with the current pattern with the
+ current pattern. */
+ if (FCT (list->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+ NULL, alloca_used) == 0
+ /* This was successful. Now match the rest with the rest
+ of the pattern. */
+ && (FCT (p, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+ flags & FNM_FILE_NAME
+ ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
+ /* This didn't work. Try the whole pattern. */
+ || (rs != string
+ && FCT (pattern - 1, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+ flags & FNM_FILE_NAME
+ ? flags : flags & ~FNM_PERIOD, NULL,
+ alloca_used) == 0)))
+ /* It worked. Signal success. */
+ goto success;
+ }
while ((list = list->next) != NULL);
/* None of the patterns lead to a match. */
retval = FNM_NOMATCH;
break;
- case L('?'):
+ case L_('?'):
if (FCT (p, string, string_end, no_leading_period, flags, NULL,
- alloca_used) == 0)
- goto success;
- /* FALLTHROUGH */
-
- case L('@'):
+ alloca_used) == 0)
+ goto success;
+ FALLTHROUGH;
+ case L_('@'):
do
- /* I cannot believe it but `strcat' is actually acceptable
- here. Match the entire string with the prefix from the
- pattern list and the rest of the pattern following the
- pattern list. */
- if (FCT (STRCAT (list->str, p), string, string_end,
- no_leading_period,
- flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
- NULL, alloca_used) == 0)
- /* It worked. Signal success. */
- goto success;
+ /* I cannot believe it but 'strcat' is actually acceptable
+ here. Match the entire string with the prefix from the
+ pattern list and the rest of the pattern following the
+ pattern list. */
+ if (FCT (STRCAT (list->str, p), string, string_end,
+ no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+ NULL, alloca_used) == 0)
+ /* It worked. Signal success. */
+ goto success;
while ((list = list->next) != NULL);
/* None of the patterns lead to a match. */
retval = FNM_NOMATCH;
break;
- case L('!'):
+ case L_('!'):
for (rs = string; rs <= string_end; ++rs)
- {
- struct patternlist *runp;
-
- for (runp = list; runp != NULL; runp = runp->next)
- if (FCT (runp->str, string, rs, no_leading_period,
- flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
- NULL, alloca_used) == 0)
- break;
-
- /* If none of the patterns matched see whether the rest does. */
- if (runp == NULL
- && (FCT (p, rs, string_end,
- rs == string
- ? no_leading_period
- : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
- flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
- NULL, alloca_used) == 0))
- /* This is successful. */
- goto success;
- }
+ {
+ struct patternlist *runp;
+
+ for (runp = list; runp != NULL; runp = runp->next)
+ if (FCT (runp->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+ NULL, alloca_used) == 0)
+ break;
+
+ /* If none of the patterns matched see whether the rest does. */
+ if (runp == NULL
+ && (FCT (p, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
+ NULL, alloca_used) == 0))
+ /* This is successful. */
+ goto success;
+ }
/* None of the patterns together with the rest of the pattern
- lead to a match. */
+ lead to a match. */
retval = FNM_NOMATCH;
break;
@@ -1189,10 +1183,10 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
if (any_malloced)
while (list != NULL)
{
- struct patternlist *old = list;
- list = list->next;
- if (old->malloced)
- free (old);
+ struct patternlist *old = list;
+ list = list->next;
+ if (old->malloced)
+ free (old);
}
return retval;
@@ -1209,10 +1203,9 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
#undef STRUCT
#undef MEMPCPY
#undef MEMCHR
-#undef STRCOLL
#undef STRLEN
#undef STRCAT
-#undef L
+#undef L_
#undef BTOWC
#undef WIDE_CHAR_VERSION
#undef FINDIDX
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2020-12-30 20:15 [PATCH 1/5] posix: Sync regex code with gnulib Adhemerval Zanella
` (3 preceding siblings ...)
2020-12-30 20:15 ` [PATCH 5/5] posix: Sync fnmatch " Adhemerval Zanella
@ 2020-12-31 21:37 ` Paul Eggert
2021-01-19 14:16 ` Vaseeharan Vinayagamoorthy
5 siblings, 0 replies; 22+ messages in thread
From: Paul Eggert @ 2020-12-31 21:37 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, bug-gnulib
This patch looks good to me, thanks.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 2/5] posix: Sync glob code with gnulib
2020-12-30 20:15 ` [PATCH 2/5] posix: Sync glob " Adhemerval Zanella
@ 2020-12-31 21:47 ` Paul Eggert
0 siblings, 0 replies; 22+ messages in thread
From: Paul Eggert @ 2020-12-31 21:47 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, bug-gnulib
[-- Attachment #1: Type: text/plain, Size: 922 bytes --]
On 12/30/20 12:15 PM, Adhemerval Zanella wrote:
> It sync with gnulib commit 43ee1a6bf and fixes and use-after-free
> bug (gnulib commit 717766da8926e36). The main change over gnulib
> is:
>
> --- posix/glob.c
> +++ lib/glob.c
> @@ -59,6 +59,12 @@
> # define readdir(str) __readdir64 (str)
> # define getpwnam_r(name, bufp, buf, len, res) \
> __getpwnam_r (name, bufp, buf, len, res)
> +# ifndef __lstat64
> +# define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
> +# endif
> +# ifndef __stat64
> +# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
> +# endif
> # define struct_stat64 struct stat64
> # define FLEXIBLE_ARRAY_MEMBER
> # include <shlib-compat.h>
Thanks, the code patch looks fine. You can now simplify its commit
message because I just now propagated the above fix into Gnulib, by
installing the attached patch into Gnulib.
[-- Attachment #2: 0001-glob-merge-proposed-glibc-changes.patch --]
[-- Type: text/x-patch, Size: 1582 bytes --]
From 562592fc53384f9b9ecdd40577cc94c10c3f7eea Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 31 Dec 2020 09:05:13 -0800
Subject: [PATCH 1/2] glob: merge proposed glibc changes
This merges the change proposed by Adhemerval Zanella in:
https://sourceware.org/pipermail/libc-alpha/2020-December/121211.html
* lib/glob.c (__lstat64, __stat64) [_LIBC]: Remove.
---
ChangeLog | 7 +++++++
lib/glob.c | 6 ------
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7dd4ffdd6..5da7c043a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2020-12-31 Paul Eggert <eggert@cs.ucla.edu>
+
+ glob: merge proposed glibc changes
+ This merges the change proposed by Adhemerval Zanella in:
+ https://sourceware.org/pipermail/libc-alpha/2020-December/121211.html
+ * lib/glob.c (__lstat64, __stat64) [_LIBC]: Remove.
+
2020-12-31 Bruno Haible <bruno@clisp.org>
memalign: Work around Solaris bug.
diff --git a/lib/glob.c b/lib/glob.c
index 3c444d3b1..20239f780 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -59,12 +59,6 @@
# define readdir(str) __readdir64 (str)
# define getpwnam_r(name, bufp, buf, len, res) \
__getpwnam_r (name, bufp, buf, len, res)
-# ifndef __lstat64
-# define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf)
-# endif
-# ifndef __stat64
-# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
-# endif
# define struct_stat64 struct stat64
# define FLEXIBLE_ARRAY_MEMBER
# include <shlib-compat.h>
--
2.27.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 3/5] Sync intprops.h with gnulib
2020-12-30 20:15 ` [PATCH 3/5] Sync intprops.h " Adhemerval Zanella
@ 2020-12-31 21:47 ` Paul Eggert
0 siblings, 0 replies; 22+ messages in thread
From: Paul Eggert @ 2020-12-31 21:47 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, bug-gnulib
Thanks, this patch looks fine.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 4/5] Sync flexmember.h with gnulib
2020-12-30 20:15 ` [PATCH 4/5] Sync flexmember.h " Adhemerval Zanella
@ 2020-12-31 21:48 ` Paul Eggert
0 siblings, 0 replies; 22+ messages in thread
From: Paul Eggert @ 2020-12-31 21:48 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, bug-gnulib
Thanks, this patch looks fine.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 5/5] posix: Sync fnmatch with gnulib
2020-12-30 20:15 ` [PATCH 5/5] posix: Sync fnmatch " Adhemerval Zanella
@ 2020-12-31 21:54 ` Paul Eggert
0 siblings, 0 replies; 22+ messages in thread
From: Paul Eggert @ 2020-12-31 21:54 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, bug-gnulib
[-- Attachment #1: Type: text/plain, Size: 730 bytes --]
On 12/30/20 12:15 PM, Adhemerval Zanella wrote:
> - ssize_t level;
> + size_t level;
'level' should be ptrdiff_t not ssize_t, for portability to
(now-ancient, but still allowed by POSIX) hosts where ssize_t is 32 bits
and size_t is 64 bits.
> - CHAR str[];
> + CHAR str[FLEXIBLE_ARRAY_MEMBER];
This assumes C99 flex array members which is fine for glibc but dubious
for Gnulib; it should be safer to use __flexarr.
> Because otherwise it triggers some glibc regressions:
Thanks for spotting that. I installed the attached patch into Gnulib,
which should fix the glibc regressions and the other abovementioned
glitches, so that you should now be able to sync fnmatch from Gnulib
unchanged.
[-- Attachment #2: 0002-fnmatch-merge-from-glibc-proposal.patch --]
[-- Type: text/x-patch, Size: 3575 bytes --]
From a7ad4b110fd6b7dde424dceb46c9c09c31cfbe69 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 31 Dec 2020 13:35:53 -0800
Subject: [PATCH 2/2] fnmatch: merge from glibc + proposal
This merges the change proposed by Adhemerval Zanella in:
https://sourceware.org/pipermail/libc-alpha/2020-December/121212.html
which fixes a Gnulib bug that led to a failed assert.
* lib/fnmatch_loop.c (EXT): Use signed level, not unsigned, and
check that it stays nonnegative. Use __flexarr instead of
FLEXIBLE_ARRAY_MEMBER, to port better to glibc.
* tests/test-fnmatch.c (main): New test cases, taken from glibc.
---
ChangeLog | 9 +++++++++
lib/fnmatch_loop.c | 7 +++----
tests/test-fnmatch.c | 10 ++++++++++
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5da7c043a..661a1ee94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2020-12-31 Paul Eggert <eggert@cs.ucla.edu>
+ fnmatch: merge from glibc + proposal
+ This merges the change proposed by Adhemerval Zanella in:
+ https://sourceware.org/pipermail/libc-alpha/2020-December/121212.html
+ which fixes a Gnulib bug that led to a failed assert.
+ * lib/fnmatch_loop.c (EXT): Use signed level, not unsigned, and
+ check that it stays nonnegative. Use __flexarr instead of
+ FLEXIBLE_ARRAY_MEMBER, to port better to glibc.
+ * tests/test-fnmatch.c (main): New test cases, taken from glibc.
+
glob: merge proposed glibc changes
This merges the change proposed by Adhemerval Zanella in:
https://sourceware.org/pipermail/libc-alpha/2020-December/121211.html
diff --git a/lib/fnmatch_loop.c b/lib/fnmatch_loop.c
index c533107a2..e5dac38b4 100644
--- a/lib/fnmatch_loop.c
+++ b/lib/fnmatch_loop.c
@@ -978,12 +978,12 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
bool no_leading_period, int flags, size_t alloca_used)
{
const CHAR *startp;
- size_t level;
+ ptrdiff_t level;
struct patternlist
{
struct patternlist *next;
CHAR malloced;
- CHAR str[FLEXIBLE_ARRAY_MEMBER];
+ CHAR str __flexarr;
} *list = NULL;
struct patternlist **lastp = &list;
size_t pattern_len = STRLEN (pattern);
@@ -994,7 +994,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
/* Parse the pattern. Store the individual parts in the list. */
level = 0;
- for (startp = p = pattern + 1; ; ++p)
+ for (startp = p = pattern + 1; level >= 0; ++p)
if (*p == L_('\0'))
{
/* This is an invalid pattern. */
@@ -1065,7 +1065,6 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
*lastp = newp; \
lastp = &newp->next
NEW_PATTERN;
- break;
}
}
else if (*p == L_('|'))
diff --git a/tests/test-fnmatch.c b/tests/test-fnmatch.c
index a094c1fa7..1d58689cf 100644
--- a/tests/test-fnmatch.c
+++ b/tests/test-fnmatch.c
@@ -52,5 +52,15 @@ main ()
*/
ASSERT (res = fnmatch ("[/b", "[/b", 0) == 0);
+ ASSERT (fnmatch ("[[:alpha:]'[:alpha:]\0]", "a", 0) == FNM_NOMATCH);
+ ASSERT (fnmatch ("[a[.\0.]]", "a", 0) == FNM_NOMATCH);
+#ifdef FNM_EXTMATCH
+ ASSERT (fnmatch ("**(!()", "**(!()", FNM_EXTMATCH) == 0);
+#endif
+#ifdef FNM_LEADING_DIR
+ ASSERT (fnmatch ("x?y", "x/y/z", FNM_PATHNAME | FNM_LEADING_DIR)
+ == FNM_NOMATCH);
+#endif
+
return 0;
}
--
2.27.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2020-12-30 20:15 [PATCH 1/5] posix: Sync regex code with gnulib Adhemerval Zanella
` (4 preceding siblings ...)
2020-12-31 21:37 ` [PATCH 1/5] posix: Sync regex code " Paul Eggert
@ 2021-01-19 14:16 ` Vaseeharan Vinayagamoorthy
2021-01-19 14:43 ` Adhemerval Zanella
5 siblings, 1 reply; 22+ messages in thread
From: Vaseeharan Vinayagamoorthy @ 2021-01-19 14:16 UTC (permalink / raw)
To: Adhemerval Zanella, libc-alpha@sourceware.org, Paul Eggert
Cc: bug-gnulib@gnu.org
After this commit [1], I am seeing -Werror=undef when bootstapping glibc on aarch64-none-linux-gnu :
In file included from regex.c:70:0:
regex_internal.h:852:26: error: "__clang_major__" is not defined [-Werror=undef]
# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
^~~~~~~~~~~~~~~
The build/host/target setup is:
Build: aarch64-none-linux-gnu (Ubuntu 14.04)
Host: aarch64-none-linux-gnu
Target: aarch64-none-linux-gnu
[1]
commit c2a150d089fa096cb5f9e342da80fb30dc0d1953
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
AuthorDate: Tue Dec 29 17:32:25 2020 -0300
Commit: Adhemerval Zanella <adhemerval.zanella@linaro.org>
CommitDate: Mon Jan 4 08:38:52 2021 -0300
posix: Sync regex code with gnulib
It sync with gnulib commit 43ee1a6bf. The main change is 9682f18e9.
(which does not have a meaniful description).
Checked on x86_64-linux-gnu.
On 30/12/2020, 20:15, "Libc-alpha on behalf of Adhemerval Zanella via Libc-alpha" <libc-alpha-bounces@sourceware.org on behalf of libc-alpha@sourceware.org> wrote:
It sync with gnulib commit 43ee1a6bf. The main change is 9682f18e9.
(which does not have a meaniful description).
Checked on x86_64-linux-gnu.
---
posix/regcomp.c | 2 +-
posix/regex.h | 17 ++++++++++++-----
posix/regex_internal.c | 19 ++++++++++---------
posix/regex_internal.h | 16 ++++++++++++----
4 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/posix/regcomp.c b/posix/regcomp.c
index 93bb0a0538..692928b0db 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -558,7 +558,7 @@ weak_alias (__regerror, regerror)
static const bitset_t utf8_sb_map =
{
/* Set the first 128 bits. */
-# if defined __GNUC__ && !defined __STRICT_ANSI__
+# if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__
[0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
# else
# if 4 * BITSET_WORD_BITS < ASCII_CHARS
diff --git a/posix/regex.h b/posix/regex.h
index 5fe41c8685..7418e6c76f 100644
--- a/posix/regex.h
+++ b/posix/regex.h
@@ -612,7 +612,9 @@ extern int re_exec (const char *);
'configure' might #define 'restrict' to those words, so pick a
different name. */
#ifndef _Restrict_
-# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
+# if defined __restrict \
+ || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \
+ || __clang_major__ >= 3
# define _Restrict_ __restrict
# elif 199901L <= __STDC_VERSION__ || defined restrict
# define _Restrict_ restrict
@@ -620,13 +622,18 @@ extern int re_exec (const char *);
# define _Restrict_
# endif
#endif
-/* For [restrict], use glibc's __restrict_arr if available.
- Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict]. */
+/* For the ISO C99 syntax
+ array_name[restrict]
+ use glibc's __restrict_arr if available.
+ Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode).
+ Other ISO C99 compilers support it as well. */
#ifndef _Restrict_arr_
# ifdef __restrict_arr
# define _Restrict_arr_ __restrict_arr
-# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \
- && !defined __GNUG__)
+# elif ((199901L <= __STDC_VERSION__ \
+ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \
+ || __clang_major__ >= 3) \
+ && !defined __cplusplus)
# define _Restrict_arr_ _Restrict_
# else
# define _Restrict_arr_
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index e1b6b4d5af..ed0a13461b 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -300,18 +300,20 @@ build_wcs_upper_buffer (re_string_t *pstr)
while (byte_idx < end_idx)
{
wchar_t wc;
+ unsigned char ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
- if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
- && mbsinit (&pstr->cur_state))
+ if (isascii (ch) && mbsinit (&pstr->cur_state))
{
- /* In case of a singlebyte character. */
- pstr->mbs[byte_idx]
- = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
/* The next step uses the assumption that wchar_t is encoded
ASCII-safe: all ASCII values can be converted like this. */
- pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
- ++byte_idx;
- continue;
+ wchar_t wcu = __towupper (ch);
+ if (isascii (wcu))
+ {
+ pstr->mbs[byte_idx] = wcu;
+ pstr->wcs[byte_idx] = wcu;
+ byte_idx++;
+ continue;
+ }
}
remain_len = end_idx - byte_idx;
@@ -348,7 +350,6 @@ build_wcs_upper_buffer (re_string_t *pstr)
{
/* It is an invalid character, an incomplete character
at the end of the string, or '\0'. Just use the byte. */
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
pstr->mbs[byte_idx] = ch;
/* And also cast it to wide char. */
pstr->wcs[byte_idx++] = (wchar_t) ch;
diff --git a/posix/regex_internal.h b/posix/regex_internal.h
index 8c42586c42..4a3cf779bf 100644
--- a/posix/regex_internal.h
+++ b/posix/regex_internal.h
@@ -77,6 +77,14 @@
# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
#endif
+/* regex code assumes isascii has its usual numeric meaning,
+ even if the portable character set uses EBCDIC encoding,
+ and even if wint_t is wider than int. */
+#ifndef _LIBC
+# undef isascii
+# define isascii(c) (((c) & ~0x7f) == 0)
+#endif
+
#ifdef _LIBC
# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
# define _RE_DEFINE_LOCALE_FUNCTIONS 1
@@ -335,7 +343,7 @@ typedef struct
Idx idx; /* for BACK_REF */
re_context_type ctx_type; /* for ANCHOR */
} opr;
-#if __GNUC__ >= 2 && !defined __STRICT_ANSI__
+#if (__GNUC__ >= 2 || defined __clang__) && !defined __STRICT_ANSI__
re_token_type_t type : 8;
#else
re_token_type_t type;
@@ -841,10 +849,10 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
#endif /* RE_ENABLE_I18N */
#ifndef FALLTHROUGH
-# if __GNUC__ < 7
-# define FALLTHROUGH ((void) 0)
-# else
+# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
# define FALLTHROUGH __attribute__ ((__fallthrough__))
+# else
+# define FALLTHROUGH ((void) 0)
# endif
#endif
--
2.25.1
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-19 14:16 ` Vaseeharan Vinayagamoorthy
@ 2021-01-19 14:43 ` Adhemerval Zanella
2021-01-19 15:43 ` Bruno Haible
2021-01-19 16:52 ` Florian Weimer
0 siblings, 2 replies; 22+ messages in thread
From: Adhemerval Zanella @ 2021-01-19 14:43 UTC (permalink / raw)
To: Vaseeharan Vinayagamoorthy, libc-alpha@sourceware.org,
Paul Eggert
Cc: bug-gnulib@gnu.org
On 19/01/2021 11:16, Vaseeharan Vinayagamoorthy wrote:
> After this commit [1], I am seeing -Werror=undef when bootstapping glibc on aarch64-none-linux-gnu :
>
> In file included from regex.c:70:0:
> regex_internal.h:852:26: error: "__clang_major__" is not defined [-Werror=undef]
> # if (__GNUC__ >= 7) || (__clang_major__ >= 10)
> ^~~~~~~~~~~~~~~
>
> The build/host/target setup is:
> Build: aarch64-none-linux-gnu (Ubuntu 14.04)
> Host: aarch64-none-linux-gnu
> Target: aarch64-none-linux-gnu
>
> [1]
> commit c2a150d089fa096cb5f9e342da80fb30dc0d1953
> Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> AuthorDate: Tue Dec 29 17:32:25 2020 -0300
> Commit: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> CommitDate: Mon Jan 4 08:38:52 2021 -0300
>
> posix: Sync regex code with gnulib
>
> It sync with gnulib commit 43ee1a6bf. The main change is 9682f18e9.
> (which does not have a meaniful description).
>
> Checked on x86_64-linux-gnu.
Does the following help:
--
diff --git a/posix/regex_internal.h b/posix/regex_internal.h
index e31ac92674..944de219c3 100644
--- a/posix/regex_internal.h
+++ b/posix/regex_internal.h
@@ -849,7 +849,7 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
#endif /* RE_ENABLE_I18N */
#ifndef FALLTHROUGH
-# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
+# if (__GNUC__ >= 7) || (defined __clang_major__ &&__clang_major__ >= 10)
# define FALLTHROUGH __attribute__ ((__fallthrough__))
# else
# define FALLTHROUGH ((void) 0)
--
Paul, this seemed to a common pattern scatter on multiple file in gnulib.
Wouldn't be better to consolidate it on cdefs.h?
> On 30/12/2020, 20:15, "Libc-alpha on behalf of Adhemerval Zanella via Libc-alpha" <libc-alpha-bounces@sourceware.org on behalf of libc-alpha@sourceware.org> wrote:
>
> It sync with gnulib commit 43ee1a6bf. The main change is 9682f18e9.
> (which does not have a meaniful description).
>
> Checked on x86_64-linux-gnu.
> ---
> posix/regcomp.c | 2 +-
> posix/regex.h | 17 ++++++++++++-----
> posix/regex_internal.c | 19 ++++++++++---------
> posix/regex_internal.h | 16 ++++++++++++----
> 4 files changed, 35 insertions(+), 19 deletions(-)
>
> diff --git a/posix/regcomp.c b/posix/regcomp.c
> index 93bb0a0538..692928b0db 100644
> --- a/posix/regcomp.c
> +++ b/posix/regcomp.c
> @@ -558,7 +558,7 @@ weak_alias (__regerror, regerror)
> static const bitset_t utf8_sb_map =
> {
> /* Set the first 128 bits. */
> -# if defined __GNUC__ && !defined __STRICT_ANSI__
> +# if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__
> [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
> # else
> # if 4 * BITSET_WORD_BITS < ASCII_CHARS
> diff --git a/posix/regex.h b/posix/regex.h
> index 5fe41c8685..7418e6c76f 100644
> --- a/posix/regex.h
> +++ b/posix/regex.h
> @@ -612,7 +612,9 @@ extern int re_exec (const char *);
> 'configure' might #define 'restrict' to those words, so pick a
> different name. */
> #ifndef _Restrict_
> -# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__)
> +# if defined __restrict \
> + || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \
> + || __clang_major__ >= 3
> # define _Restrict_ __restrict
> # elif 199901L <= __STDC_VERSION__ || defined restrict
> # define _Restrict_ restrict
> @@ -620,13 +622,18 @@ extern int re_exec (const char *);
> # define _Restrict_
> # endif
> #endif
> -/* For [restrict], use glibc's __restrict_arr if available.
> - Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict]. */
> +/* For the ISO C99 syntax
> + array_name[restrict]
> + use glibc's __restrict_arr if available.
> + Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode).
> + Other ISO C99 compilers support it as well. */
> #ifndef _Restrict_arr_
> # ifdef __restrict_arr
> # define _Restrict_arr_ __restrict_arr
> -# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \
> - && !defined __GNUG__)
> +# elif ((199901L <= __STDC_VERSION__ \
> + || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \
> + || __clang_major__ >= 3) \
> + && !defined __cplusplus)
> # define _Restrict_arr_ _Restrict_
> # else
> # define _Restrict_arr_
> diff --git a/posix/regex_internal.c b/posix/regex_internal.c
> index e1b6b4d5af..ed0a13461b 100644
> --- a/posix/regex_internal.c
> +++ b/posix/regex_internal.c
> @@ -300,18 +300,20 @@ build_wcs_upper_buffer (re_string_t *pstr)
> while (byte_idx < end_idx)
> {
> wchar_t wc;
> + unsigned char ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
>
> - if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
> - && mbsinit (&pstr->cur_state))
> + if (isascii (ch) && mbsinit (&pstr->cur_state))
> {
> - /* In case of a singlebyte character. */
> - pstr->mbs[byte_idx]
> - = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
> /* The next step uses the assumption that wchar_t is encoded
> ASCII-safe: all ASCII values can be converted like this. */
> - pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
> - ++byte_idx;
> - continue;
> + wchar_t wcu = __towupper (ch);
> + if (isascii (wcu))
> + {
> + pstr->mbs[byte_idx] = wcu;
> + pstr->wcs[byte_idx] = wcu;
> + byte_idx++;
> + continue;
> + }
> }
>
> remain_len = end_idx - byte_idx;
> @@ -348,7 +350,6 @@ build_wcs_upper_buffer (re_string_t *pstr)
> {
> /* It is an invalid character, an incomplete character
> at the end of the string, or '\0'. Just use the byte. */
> - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
> pstr->mbs[byte_idx] = ch;
> /* And also cast it to wide char. */
> pstr->wcs[byte_idx++] = (wchar_t) ch;
> diff --git a/posix/regex_internal.h b/posix/regex_internal.h
> index 8c42586c42..4a3cf779bf 100644
> --- a/posix/regex_internal.h
> +++ b/posix/regex_internal.h
> @@ -77,6 +77,14 @@
> # define isblank(ch) ((ch) == ' ' || (ch) == '\t')
> #endif
>
> +/* regex code assumes isascii has its usual numeric meaning,
> + even if the portable character set uses EBCDIC encoding,
> + and even if wint_t is wider than int. */
> +#ifndef _LIBC
> +# undef isascii
> +# define isascii(c) (((c) & ~0x7f) == 0)
> +#endif
> +
> #ifdef _LIBC
> # ifndef _RE_DEFINE_LOCALE_FUNCTIONS
> # define _RE_DEFINE_LOCALE_FUNCTIONS 1
> @@ -335,7 +343,7 @@ typedef struct
> Idx idx; /* for BACK_REF */
> re_context_type ctx_type; /* for ANCHOR */
> } opr;
> -#if __GNUC__ >= 2 && !defined __STRICT_ANSI__
> +#if (__GNUC__ >= 2 || defined __clang__) && !defined __STRICT_ANSI__
> re_token_type_t type : 8;
> #else
> re_token_type_t type;
> @@ -841,10 +849,10 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
> #endif /* RE_ENABLE_I18N */
>
> #ifndef FALLTHROUGH
> -# if __GNUC__ < 7
> -# define FALLTHROUGH ((void) 0)
> -# else
> +# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
> # define FALLTHROUGH __attribute__ ((__fallthrough__))
> +# else
> +# define FALLTHROUGH ((void) 0)
> # endif
> #endif
>
> --
> 2.25.1
>
>
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-19 14:43 ` Adhemerval Zanella
@ 2021-01-19 15:43 ` Bruno Haible
2021-01-20 2:55 ` Paul Eggert
2021-01-19 16:52 ` Florian Weimer
1 sibling, 1 reply; 22+ messages in thread
From: Bruno Haible @ 2021-01-19 15:43 UTC (permalink / raw)
To: bug-gnulib
Cc: Paul Eggert, libc-alpha@sourceware.org,
Vaseeharan Vinayagamoorthy, Adhemerval Zanella
Adhemerval Zanella wrote:
> -# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
> +# if (__GNUC__ >= 7) || (defined __clang_major__ &&__clang_major__ >= 10)
I would write it as:
+# if (__GNUC__ >= 7) || (defined __clang__ && __clang_major__ >= 10)
because 'defined __clang__' is the widely known way to test for a clang
(or derivate) compiler.
Bruno
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-19 14:43 ` Adhemerval Zanella
2021-01-19 15:43 ` Bruno Haible
@ 2021-01-19 16:52 ` Florian Weimer
2021-01-19 17:11 ` Adhemerval Zanella
1 sibling, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-01-19 16:52 UTC (permalink / raw)
To: Adhemerval Zanella via Libc-alpha
Cc: Paul Eggert, bug-gnulib@gnu.org, Vaseeharan Vinayagamoorthy,
Adhemerval Zanella
* Adhemerval Zanella via Libc-alpha:
> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
> Wouldn't be better to consolidate it on cdefs.h?
gnulib shouldn't be using cdefs.h on glibc systems, so I think a
separate header would be needed.
Thanks,
Florian
--
Red Hat GmbH, https://de.redhat.com/ , Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Brian Klemm, Laurie Krebs, Michael O'Neill
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-19 16:52 ` Florian Weimer
@ 2021-01-19 17:11 ` Adhemerval Zanella
2021-01-19 17:16 ` Florian Weimer
0 siblings, 1 reply; 22+ messages in thread
From: Adhemerval Zanella @ 2021-01-19 17:11 UTC (permalink / raw)
To: Florian Weimer, Adhemerval Zanella via Libc-alpha
Cc: Paul Eggert, bug-gnulib@gnu.org, Vaseeharan Vinayagamoorthy
On 19/01/2021 13:52, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
>
>> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
>> Wouldn't be better to consolidate it on cdefs.h?
>
> gnulib shouldn't be using cdefs.h on glibc systems, so I think a
> separate header would be needed.
What is the problem of using cdefs.h for internal implementation?
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-19 17:11 ` Adhemerval Zanella
@ 2021-01-19 17:16 ` Florian Weimer
2021-01-19 17:18 ` Adhemerval Zanella
0 siblings, 1 reply; 22+ messages in thread
From: Florian Weimer @ 2021-01-19 17:16 UTC (permalink / raw)
To: Adhemerval Zanella
Cc: bug-gnulib@gnu.org, Paul Eggert,
Adhemerval Zanella via Libc-alpha, Vaseeharan Vinayagamoorthy
* Adhemerval Zanella:
> On 19/01/2021 13:52, Florian Weimer wrote:
>> * Adhemerval Zanella via Libc-alpha:
>>
>>> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
>>> Wouldn't be better to consolidate it on cdefs.h?
>>
>> gnulib shouldn't be using cdefs.h on glibc systems, so I think a
>> separate header would be needed.
>
> What is the problem of using cdefs.h for internal implementation?
Isn't regex_internal.h sync'ed with gnulib?
Thanks,
Florian
--
Red Hat GmbH, https://de.redhat.com/ , Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Brian Klemm, Laurie Krebs, Michael O'Neill
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-19 17:16 ` Florian Weimer
@ 2021-01-19 17:18 ` Adhemerval Zanella
0 siblings, 0 replies; 22+ messages in thread
From: Adhemerval Zanella @ 2021-01-19 17:18 UTC (permalink / raw)
To: Florian Weimer
Cc: bug-gnulib@gnu.org, Paul Eggert,
Adhemerval Zanella via Libc-alpha, Vaseeharan Vinayagamoorthy
On 19/01/2021 14:16, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> On 19/01/2021 13:52, Florian Weimer wrote:
>>> * Adhemerval Zanella via Libc-alpha:
>>>
>>>> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
>>>> Wouldn't be better to consolidate it on cdefs.h?
>>>
>>> gnulib shouldn't be using cdefs.h on glibc systems, so I think a
>>> separate header would be needed.
>>
>> What is the problem of using cdefs.h for internal implementation?
>
> Isn't regex_internal.h sync'ed with gnulib?
Yes, and gnulib also has an internal cdefs (which we should sync btw).
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-19 15:43 ` Bruno Haible
@ 2021-01-20 2:55 ` Paul Eggert
2021-01-20 11:27 ` Adhemerval Zanella
0 siblings, 1 reply; 22+ messages in thread
From: Paul Eggert @ 2021-01-20 2:55 UTC (permalink / raw)
To: Bruno Haible
Cc: bug-gnulib, libc-alpha@sourceware.org, Vaseeharan Vinayagamoorthy,
Adhemerval Zanella
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
On 1/19/21 7:43 AM, Bruno Haible wrote:
> Adhemerval Zanella wrote:
>> -# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
>> +# if (__GNUC__ >= 7) || (defined __clang_major__ &&__clang_major__ >= 10)
> I would write it as:
>
> +# if (__GNUC__ >= 7) || (defined __clang__ && __clang_major__ >= 10)
This line should be used only if _LIBC is defined, so we can simplify it
to just "#if __GNUC__ >= 7" and thus not worry about Clang.
I see that Gnulib wasn't consistent about this, so I installed the
attached patch to Gnulib to fix the issue here and elsewhere. The idea
is that the Gnulib regex_internal.h can be copied back to glibc, and
that the other uses in Gnulib should be similar.
On 1/19/21 6:43 AM, Adhemerval Zanella wrote:
> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
> Wouldn't be better to consolidate it on cdefs.h?
We could append something like the following to cdefs.h, and switch to
__attribute_fallthrough__ for modules shared between the two systems. Is
that something you'd like to pursue? (We should also sync Gnulib cdefs.h
back to glibc of course.)
#if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
# define __attribute_fallthrough__ [[__fallthrough__]]
#elif __GNUC_PREREQ (7, 0) || __glibc_has_attribute (__fallthrough__)
# define __attribute_fallthrough__ __attribute__ ((__fallthrough__))
#else
# define __attribute_fallthrough__ ((void) 0)
#endif
[-- Attachment #2: 0001-fnmatch-regex-fts-FALLTHROUGH-consistency.patch --]
[-- Type: text/x-patch, Size: 3792 bytes --]
From 5c52f00c69f39fe86ec087654893087a83290ee7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 19 Jan 2021 18:35:30 -0800
Subject: [PATCH] fnmatch, regex, fts: FALLTHROUGH consistency
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Be more consistent about how FALLTHROUGH is defined.
For Gnulib, use attribute.h. For glibc, use __GNUC__ >= 7.
Problem for glibc reported by Vaseeharan Vinayagamoorthy in:
https://sourceware.org/pipermail/libc-alpha/2021-January/121778.html
* lib/fnmatch.c (FALLTHROUGH) [_LIBC]:
* lib/regex_internal.h (FALLTHROUGH) [_LIBC]:
Don’t worry about Clang, as it’s not needed and provokes GCC.
* lib/fts.c (FALLTHROUGH) [!_LIBC]:
* lib/regex_internal.h (FALLTHROUGH) [!_LIBC]:
Rely on attribute.h for FALLTHROUGH
* modules/regex: Depend on attribute module.
---
ChangeLog | 15 +++++++++++++++
lib/fnmatch.c | 2 +-
lib/fts.c | 4 ++--
lib/regex_internal.h | 6 ++++--
modules/regex | 1 +
5 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 269577caa..290fa1b4c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2021-01-19 Paul Eggert <eggert@cs.ucla.edu>
+
+ fnmatch, regex, fts: FALLTHROUGH consistency
+ Be more consistent about how FALLTHROUGH is defined.
+ For Gnulib, use attribute.h. For glibc, use __GNUC__ >= 7.
+ Problem for glibc reported by Vaseeharan Vinayagamoorthy in:
+ https://sourceware.org/pipermail/libc-alpha/2021-January/121778.html
+ * lib/fnmatch.c (FALLTHROUGH) [_LIBC]:
+ * lib/regex_internal.h (FALLTHROUGH) [_LIBC]:
+ Don’t worry about Clang, as it’s not needed and provokes GCC.
+ * lib/fts.c (FALLTHROUGH) [!_LIBC]:
+ * lib/regex_internal.h (FALLTHROUGH) [!_LIBC]:
+ Rely on attribute.h for FALLTHROUGH
+ * modules/regex: Depend on attribute module.
+
2021-01-19 KO Myung-Hun <komh78@gmail.com>
spawn-pipe: Fix SIGSEGV on OS/2 kLIBC.
diff --git a/lib/fnmatch.c b/lib/fnmatch.c
index 5896812c9..b8a71f164 100644
--- a/lib/fnmatch.c
+++ b/lib/fnmatch.c
@@ -64,7 +64,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
#endif
#ifdef _LIBC
-# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
+# if __GNUC__ >= 7
# define FALLTHROUGH __attribute__ ((__fallthrough__))
# else
# define FALLTHROUGH ((void) 0)
diff --git a/lib/fts.c b/lib/fts.c
index 8a9b5ed96..e6603f40e 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -200,8 +200,8 @@ enum Fts_stat
while (false)
#endif
-#ifndef FALLTHROUGH
-# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
+#ifdef _LIBC
+# if __GNUC__ >= 7
# define FALLTHROUGH __attribute__ ((__fallthrough__))
# else
# define FALLTHROUGH ((void) 0)
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index b4f91d9ec..3fa2bf1aa 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -830,12 +830,14 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
}
#endif /* RE_ENABLE_I18N */
-#ifndef FALLTHROUGH
-# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
+#ifdef _LIBC
+# if __GNUC__ >= 7
# define FALLTHROUGH __attribute__ ((__fallthrough__))
# else
# define FALLTHROUGH ((void) 0)
# endif
+#else
+# include "attribute.h"
#endif
#endif /* _REGEX_INTERNAL_H */
diff --git a/modules/regex b/modules/regex
index 20cbe375a..a32c46e18 100644
--- a/modules/regex
+++ b/modules/regex
@@ -16,6 +16,7 @@ Depends-on:
c99
extensions
ssize_t
+attribute [test $ac_use_included_regex = yes]
btowc [test $ac_use_included_regex = yes]
builtin-expect [test $ac_use_included_regex = yes]
dynarray [test $ac_use_included_regex = yes]
--
2.27.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-20 2:55 ` Paul Eggert
@ 2021-01-20 11:27 ` Adhemerval Zanella
2021-01-20 15:32 ` Vaseeharan Vinayagamoorthy
2021-01-20 17:46 ` Paul Eggert
0 siblings, 2 replies; 22+ messages in thread
From: Adhemerval Zanella @ 2021-01-20 11:27 UTC (permalink / raw)
To: Paul Eggert, Bruno Haible
Cc: bug-gnulib, libc-alpha@sourceware.org, Vaseeharan Vinayagamoorthy
On 19/01/2021 23:55, Paul Eggert wrote:
> On 1/19/21 7:43 AM, Bruno Haible wrote:
>> Adhemerval Zanella wrote:
>>> -# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
>>> +# if (__GNUC__ >= 7) || (defined __clang_major__ &&__clang_major__ >= 10)
>> I would write it as:
>>
>> +# if (__GNUC__ >= 7) || (defined __clang__ && __clang_major__ >= 10)
>
> This line should be used only if _LIBC is defined, so we can simplify it to just "#if __GNUC__ >= 7" and thus not worry about Clang.
>
> I see that Gnulib wasn't consistent about this, so I installed the attached patch to Gnulib to fix the issue here and elsewhere. The idea is that the Gnulib regex_internal.h can be copied back to glibc, and that the other uses in Gnulib should be similar.
Thanks, I will check with a bootstrap build and sync regex_internal.h
with glibc.
>
> On 1/19/21 6:43 AM, Adhemerval Zanella wrote:
>
>> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
>> Wouldn't be better to consolidate it on cdefs.h?
>
> We could append something like the following to cdefs.h, and switch to __attribute_fallthrough__ for modules shared between the two systems. Is that something you'd like to pursue? (We should also sync Gnulib cdefs.h back to glibc of course.)
>
> #if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
> # define __attribute_fallthrough__ [[__fallthrough__]]
> #elif __GNUC_PREREQ (7, 0) || __glibc_has_attribute (__fallthrough__)
> # define __attribute_fallthrough__ __attribute__ ((__fallthrough__))
> #else
> # define __attribute_fallthrough__ ((void) 0)
> #endif
Yes, for 2.34 I will send some patches to sync the remaining gnulib
files and document from our part the shared files.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-20 11:27 ` Adhemerval Zanella
@ 2021-01-20 15:32 ` Vaseeharan Vinayagamoorthy
2021-01-20 16:05 ` Adhemerval Zanella
2021-01-20 17:46 ` Paul Eggert
1 sibling, 1 reply; 22+ messages in thread
From: Vaseeharan Vinayagamoorthy @ 2021-01-20 15:32 UTC (permalink / raw)
To: Adhemerval Zanella, Paul Eggert, Bruno Haible
Cc: bug-gnulib@gnu.org, libc-alpha@sourceware.org
Thanks for the fix, Adhemerval Zanella.
I assume you would fix this in other files too, for example I think a similar patch is needed for posix/fnmatch.c.
fnmatch.c:67:26: error: "__clang_major__" is not defined [-Werror=undef]
# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
^~~~~~~~~~~~~~~
On 20/01/2021, 11:27, "Adhemerval Zanella" <adhemerval.zanella@linaro.org> wrote:
On 19/01/2021 23:55, Paul Eggert wrote:
> On 1/19/21 7:43 AM, Bruno Haible wrote:
>> Adhemerval Zanella wrote:
>>> -# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
>>> +# if (__GNUC__ >= 7) || (defined __clang_major__ &&__clang_major__ >= 10)
>> I would write it as:
>>
>> +# if (__GNUC__ >= 7) || (defined __clang__ && __clang_major__ >= 10)
>
> This line should be used only if _LIBC is defined, so we can simplify it to just "#if __GNUC__ >= 7" and thus not worry about Clang.
>
> I see that Gnulib wasn't consistent about this, so I installed the attached patch to Gnulib to fix the issue here and elsewhere. The idea is that the Gnulib regex_internal.h can be copied back to glibc, and that the other uses in Gnulib should be similar.
Thanks, I will check with a bootstrap build and sync regex_internal.h
with glibc.
>
> On 1/19/21 6:43 AM, Adhemerval Zanella wrote:
>
>> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
>> Wouldn't be better to consolidate it on cdefs.h?
>
> We could append something like the following to cdefs.h, and switch to __attribute_fallthrough__ for modules shared between the two systems. Is that something you'd like to pursue? (We should also sync Gnulib cdefs.h back to glibc of course.)
>
> #if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
> # define __attribute_fallthrough__ [[__fallthrough__]]
> #elif __GNUC_PREREQ (7, 0) || __glibc_has_attribute (__fallthrough__)
> # define __attribute_fallthrough__ __attribute__ ((__fallthrough__))
> #else
> # define __attribute_fallthrough__ ((void) 0)
> #endif
Yes, for 2.34 I will send some patches to sync the remaining gnulib
files and document from our part the shared files.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-20 15:32 ` Vaseeharan Vinayagamoorthy
@ 2021-01-20 16:05 ` Adhemerval Zanella
0 siblings, 0 replies; 22+ messages in thread
From: Adhemerval Zanella @ 2021-01-20 16:05 UTC (permalink / raw)
To: Vaseeharan Vinayagamoorthy, Paul Eggert, Bruno Haible
Cc: bug-gnulib@gnu.org, libc-alpha@sourceware.org
Right, this did not showed up on build-many-glibc.py. My plan is to touch
as little code as possible since we are in slush freeze and sync again with
gnulib once we set development for 2.34.
I will fix this as well.
On 20/01/2021 12:32, Vaseeharan Vinayagamoorthy wrote:
> Thanks for the fix, Adhemerval Zanella.
> I assume you would fix this in other files too, for example I think a similar patch is needed for posix/fnmatch.c.
>
> fnmatch.c:67:26: error: "__clang_major__" is not defined [-Werror=undef]
> # if (__GNUC__ >= 7) || (__clang_major__ >= 10)
> ^~~~~~~~~~~~~~~
>
>
>
> On 20/01/2021, 11:27, "Adhemerval Zanella" <adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 19/01/2021 23:55, Paul Eggert wrote:
> > On 1/19/21 7:43 AM, Bruno Haible wrote:
> >> Adhemerval Zanella wrote:
> >>> -# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
> >>> +# if (__GNUC__ >= 7) || (defined __clang_major__ &&__clang_major__ >= 10)
> >> I would write it as:
> >>
> >> +# if (__GNUC__ >= 7) || (defined __clang__ && __clang_major__ >= 10)
> >
> > This line should be used only if _LIBC is defined, so we can simplify it to just "#if __GNUC__ >= 7" and thus not worry about Clang.
> >
> > I see that Gnulib wasn't consistent about this, so I installed the attached patch to Gnulib to fix the issue here and elsewhere. The idea is that the Gnulib regex_internal.h can be copied back to glibc, and that the other uses in Gnulib should be similar.
>
> Thanks, I will check with a bootstrap build and sync regex_internal.h
> with glibc.
>
> >
> > On 1/19/21 6:43 AM, Adhemerval Zanella wrote:
> >
> >> Paul, this seemed to a common pattern scatter on multiple file in gnulib.
> >> Wouldn't be better to consolidate it on cdefs.h?
> >
> > We could append something like the following to cdefs.h, and switch to __attribute_fallthrough__ for modules shared between the two systems. Is that something you'd like to pursue? (We should also sync Gnulib cdefs.h back to glibc of course.)
> >
> > #if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
> > # define __attribute_fallthrough__ [[__fallthrough__]]
> > #elif __GNUC_PREREQ (7, 0) || __glibc_has_attribute (__fallthrough__)
> > # define __attribute_fallthrough__ __attribute__ ((__fallthrough__))
> > #else
> > # define __attribute_fallthrough__ ((void) 0)
> > #endif
>
> Yes, for 2.34 I will send some patches to sync the remaining gnulib
> files and document from our part the shared files.
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 1/5] posix: Sync regex code with gnulib
2021-01-20 11:27 ` Adhemerval Zanella
2021-01-20 15:32 ` Vaseeharan Vinayagamoorthy
@ 2021-01-20 17:46 ` Paul Eggert
1 sibling, 0 replies; 22+ messages in thread
From: Paul Eggert @ 2021-01-20 17:46 UTC (permalink / raw)
To: Adhemerval Zanella
Cc: bug-gnulib, libc-alpha@sourceware.org, Vaseeharan Vinayagamoorthy
On 1/20/21 3:27 AM, Adhemerval Zanella wrote:
>> #if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
>> # define __attribute_fallthrough__ [[__fallthrough__]]
>> #elif __GNUC_PREREQ (7, 0) || __glibc_has_attribute (__fallthrough__)
>> # define __attribute_fallthrough__ __attribute__ ((__fallthrough__))
>> #else
>> # define __attribute_fallthrough__ ((void) 0)
>> #endif
> Yes, for 2.34 I will send some patches to sync the remaining gnulib
> files and document from our part the shared files.
On thinking about it more (for 2.34), I find that I would prefer the
current Gnulib practice of using 'FALLTHROUGH;' to using
'__attribute_fallthrough__;' in code, and so suggest Gnulib's approach
of having an attribute.h file (purely for internal glibc use) that has
"#define FALLTHROUGH __attribute__ (__fallthrough__)' etc.
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2021-01-20 17:55 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-30 20:15 [PATCH 1/5] posix: Sync regex code with gnulib Adhemerval Zanella
2020-12-30 20:15 ` [PATCH 2/5] posix: Sync glob " Adhemerval Zanella
2020-12-31 21:47 ` Paul Eggert
2020-12-30 20:15 ` [PATCH 3/5] Sync intprops.h " Adhemerval Zanella
2020-12-31 21:47 ` Paul Eggert
2020-12-30 20:15 ` [PATCH 4/5] Sync flexmember.h " Adhemerval Zanella
2020-12-31 21:48 ` Paul Eggert
2020-12-30 20:15 ` [PATCH 5/5] posix: Sync fnmatch " Adhemerval Zanella
2020-12-31 21:54 ` Paul Eggert
2020-12-31 21:37 ` [PATCH 1/5] posix: Sync regex code " Paul Eggert
2021-01-19 14:16 ` Vaseeharan Vinayagamoorthy
2021-01-19 14:43 ` Adhemerval Zanella
2021-01-19 15:43 ` Bruno Haible
2021-01-20 2:55 ` Paul Eggert
2021-01-20 11:27 ` Adhemerval Zanella
2021-01-20 15:32 ` Vaseeharan Vinayagamoorthy
2021-01-20 16:05 ` Adhemerval Zanella
2021-01-20 17:46 ` Paul Eggert
2021-01-19 16:52 ` Florian Weimer
2021-01-19 17:11 ` Adhemerval Zanella
2021-01-19 17:16 ` Florian Weimer
2021-01-19 17:18 ` Adhemerval Zanella
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).