From 711b8041ee9b4f2f89fd7cd7ccf32e4650deae75 Mon Sep 17 00:00:00 2001 From: Harun Spago Date: Sun, 5 Oct 2025 22:50:01 +0200 Subject: [PATCH 1/7] posix: c_lib_ext: fnmatch: add support for posix character classes Implemented match_posix_class function that was needed to match the possible posix classes like alnum, alpha etc... Signed-off-by: Harun Spago --- lib/posix/c_lib_ext/fnmatch.c | 170 ++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/lib/posix/c_lib_ext/fnmatch.c b/lib/posix/c_lib_ext/fnmatch.c index 911b6f41afa70..23e67b7c2e8c2 100644 --- a/lib/posix/c_lib_ext/fnmatch.c +++ b/lib/posix/c_lib_ext/fnmatch.c @@ -48,6 +48,146 @@ #define EOS '\0' +#define MATCH_CLASS6(p,a,b,c,d,e,f,g) \ + ((p)[0]==(a) && (p)[1]==(b) && (p)[2]==(c) && (p)[3]==(d) && (p)[4]==(e) && (p)[5]==(f) && (p)[6]==(g)) + +#define MATCH_CLASS7(p,a,b,c,d,e,f,g,h) \ + ((p)[0]==(a) && (p)[1]==(b) && (p)[2]==(c) && (p)[3]==(d) && (p)[4]==(e) && (p)[5]==(f) && (p)[6]==(g) && (p)[7]==(h)) + +enum fnm_char_class { + FNM_CC_ALNUM, + FNM_CC_ALPHA, + FNM_CC_BLANK, + FNM_CC_CNTRL, + FNM_CC_DIGIT, + FNM_CC_GRAPH, + FNM_CC_LOWER, + FNM_CC_PRINT, + FNM_CC_PUNCT, + FNM_CC_SPACE, + FNM_CC_UPPER, + FNM_CC_XDIGIT, + FNM_CC_INVALID, +}; + +static bool fnm_cc_is_valid(const char *pattern, size_t psize, enum fnm_char_class *cc) +{ + if (psize < 4 || *pattern != ':') + return false; + + pattern++; /* skip ':' */ + psize--; + + /* Each class name ends with ":]" */ + switch (pattern[0]) { + case 'a': + if (MATCH_CLASS6(pattern,'a','l','n','u','m',':',']')) { + *cc = FNM_CC_ALNUM; + return true; + } + if (MATCH_CLASS6(pattern,'a','l','p','h','a',':',']')) { + *cc = FNM_CC_ALPHA; + return true; + } + break; + + case 'b': + if (MATCH_CLASS6(pattern,'b','l','a','n','k',':',']')) { + *cc = FNM_CC_BLANK; + return true; + } + break; + + case 'c': + if (MATCH_CLASS6(pattern,'c','n','t','r','l',':',']')) { + *cc = FNM_CC_CNTRL; + return true; + } + break; + + case 'd': + if (MATCH_CLASS6(pattern,'d','i','g','i','t',':',']')) { + *cc = FNM_CC_DIGIT; + return true; + } + break; + + case 'g': + if (MATCH_CLASS6(pattern,'g','r','a','p','h',':',']')) { + *cc = FNM_CC_GRAPH; + return true; + } + break; + + case 'l': + if (MATCH_CLASS6(pattern,'l','o','w','e','r',':',']')) { + *cc = FNM_CC_LOWER; + return true; + } + break; + + case 'p': + if (MATCH_CLASS6(pattern,'p','r','i','n','t',':',']')) { + *cc = FNM_CC_PRINT; + return true; + } + if (MATCH_CLASS6(pattern,'p','u','n','c','t',':',']')) { + *cc = FNM_CC_PUNCT; + return true; + } + break; + + case 's': + if (MATCH_CLASS6(pattern,'s','p','a','c','e',':',']')) { + *cc = FNM_CC_SPACE; + return true; + } + break; + + case 'u': + if (MATCH_CLASS6(pattern,'u','p','p','e','r',':',']')) { + *cc = FNM_CC_UPPER; + return true; + } + break; + + case 'x': + if (MATCH_CLASS7(pattern,'x','d','i','g','i','t',':',']')) { + *cc = FNM_CC_XDIGIT; + return true; + } + break; + + default: + break; + } + + return false; +} + +static inline int fnm_cc_match(int c, enum fnm_char_class cc) +{ + switch (cc) { + case FNM_CC_ALNUM: return isalnum(c); + case FNM_CC_ALPHA: return isalpha(c); + case FNM_CC_BLANK: return isblank(c); + case FNM_CC_CNTRL: return iscntrl(c); + case FNM_CC_DIGIT: return isdigit(c); + case FNM_CC_GRAPH: return isgraph(c); + case FNM_CC_LOWER: return islower(c); + case FNM_CC_PRINT: return isprint(c); + case FNM_CC_PUNCT: return ispunct(c); + case FNM_CC_SPACE: return isspace(c); + case FNM_CC_UPPER: return isupper(c); + case FNM_CC_XDIGIT: return isxdigit(c); + default: + break; + } + + return 0; +} + + static inline int foldcase(int ch, int flags) { @@ -60,6 +200,24 @@ static inline int foldcase(int ch, int flags) #define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) +static bool match_posix_class(const char **pattern, int test) +{ + enum fnm_char_class cc; + + const char *p = *pattern; + size_t remaining = strlen(p); + + if (!fnm_cc_is_valid(p, remaining, &cc)) + return false; + + /* move pattern pointer past ":]" */ + const char *end = strstr(p, ":]"); + if (end) + *pattern = end + 2; + + return fnm_cc_match(test, cc); +} + static const char *rangematch(const char *pattern, int test, int flags) { bool negate, ok, need; @@ -99,6 +257,18 @@ static const char *rangematch(const char *pattern, int test, int flags) return NULL; } + if (c == '[' && *pattern == ':') { + if (match_posix_class(&pattern, test)) { + ok = true; + continue; + } else { + // skip over class if unrecognized + while (*pattern && !(*pattern == ':' && *(pattern+1) == ']')) pattern++; + if (*pattern) pattern += 2; + continue; + } + } + if (*pattern == '-') { c2 = FOLDCASE(*(pattern + 1), flags); if (c2 != EOS && c2 != ']') { From ccd6baaf07044bda1fb55cbc885c5a841ae98d4c Mon Sep 17 00:00:00 2001 From: Harun Spago Date: Sat, 11 Oct 2025 20:45:14 +0200 Subject: [PATCH 2/7] tests: posix: lib: src: fnmatch: fixed #55186 Uncommented posix class test cases in fnmatch tests Signed-off-by: Harun Spago --- tests/posix/c_lib_ext/src/fnmatch.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/posix/c_lib_ext/src/fnmatch.c b/tests/posix/c_lib_ext/src/fnmatch.c index 42c84d7ca1a0f..d561761799d61 100644 --- a/tests/posix/c_lib_ext/src/fnmatch.c +++ b/tests/posix/c_lib_ext/src/fnmatch.c @@ -13,8 +13,6 @@ */ ZTEST(posix_c_lib_ext, test_fnmatch) { - /* Note: commented out lines indicate known problems to be addressed in #55186 */ - zassert_ok(fnmatch("*.c", "foo.c", 0)); zassert_ok(fnmatch("*.c", ".c", 0)); zassert_equal(fnmatch("*.a", "foo.c", 0), FNM_NOMATCH); @@ -73,7 +71,7 @@ ZTEST(posix_c_lib_ext, test_fnmatch) zassert_equal(fnmatch("*/*", "a/.b", FNM_PATHNAME | FNM_PERIOD), FNM_NOMATCH); zassert_ok(fnmatch("*?*/*", "a/.b", FNM_PERIOD)); zassert_ok(fnmatch("*[.]/b", "a./b", FNM_PATHNAME | FNM_PERIOD)); - /* zassert_ok(fnmatch("*[[:alpha:]]/""*[[:alnum:]]", "a/b", FNM_PATHNAME)); */ + zassert_ok(fnmatch("*[[:alpha:]]/""*[[:alnum:]]", "a/b", FNM_PATHNAME)); zassert_not_equal(fnmatch("*[![:digit:]]*/[![:d-d]", "a/b", FNM_PATHNAME), 0); zassert_not_equal(fnmatch("*[![:digit:]]*/[[:d-d]", "a/[", FNM_PATHNAME), 0); zassert_not_equal(fnmatch("*[![:digit:]]*/[![:d-d]", "a/[", FNM_PATHNAME), 0); From cde5eab2162aebd3a9e434485c8a2365a25f3ff7 Mon Sep 17 00:00:00 2001 From: Harun Spago Date: Sun, 16 Nov 2025 21:58:14 +0100 Subject: [PATCH 3/7] tests: posix: c_lib_ext: src: fnmatch: added test cases for POSIX character classes Added test cases for POSIX character classes in fnmatch tests. Signed-off-by: Harun Spago --- tests/posix/c_lib_ext/src/fnmatch.c | 62 +++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/posix/c_lib_ext/src/fnmatch.c b/tests/posix/c_lib_ext/src/fnmatch.c index d561761799d61..696feb66387cc 100644 --- a/tests/posix/c_lib_ext/src/fnmatch.c +++ b/tests/posix/c_lib_ext/src/fnmatch.c @@ -6,6 +6,22 @@ #include #include +#include + +/* + * Note: the \x00 control character is specifically excluded below, since testing for it is + * equivalent to reading past the end of a '\0'-terminated string (i.e. can fault). + */ +#define TEST_BLANK_CHARS " \t" +#define TEST_CNTRL_CHARS \ + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16" \ + "\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f" +#define TEST_DIGIT_CHARS "0123456789" +#define TEST_LOWER_CHARS "abcdefghijklmnopqrstuvwxyz" +#define TEST_PUNCT_CHARS "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" +#define TEST_SPACE_CHARS " \f\n\r\t\v" +#define TEST_UPPER_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define TEST_XDIGIT_CHARS TEST_DIGIT_CHARS "ABCDEFabcdef" /* * Adapted from @@ -78,4 +94,50 @@ ZTEST(posix_c_lib_ext, test_fnmatch) zassert_ok(fnmatch("a?b", "a.b", FNM_PATHNAME | FNM_PERIOD)); zassert_ok(fnmatch("a*b", "a.b", FNM_PATHNAME | FNM_PERIOD)); zassert_ok(fnmatch("a[.]b", "a.b", FNM_PATHNAME | FNM_PERIOD)); + + /* Additional test cases for POSIX character classes (C-locale only) */ + static const struct test_data_s { + const char *pattern; + const char *match; + const char *nomatch; + } test_data[] = { + {"[[:alnum:]]", TEST_DIGIT_CHARS TEST_UPPER_CHARS TEST_LOWER_CHARS, " "}, + {"[[:alpha:]]", TEST_UPPER_CHARS TEST_LOWER_CHARS, "0"}, + {"[[:blank:]]", TEST_BLANK_CHARS, "x"}, + {"[[:cntrl:]]", TEST_CNTRL_CHARS, "x"}, + {"[[:digit:]]", TEST_DIGIT_CHARS, "a"}, + {"[[:graph:]]", TEST_DIGIT_CHARS TEST_UPPER_CHARS TEST_LOWER_CHARS TEST_PUNCT_CHARS, + " "}, + {"[[:lower:]]", TEST_LOWER_CHARS, "X"}, + {"[[:print:]]", + TEST_DIGIT_CHARS TEST_UPPER_CHARS TEST_LOWER_CHARS TEST_PUNCT_CHARS " ", "\t"}, + {"[[:punct:]]", TEST_PUNCT_CHARS, "x"}, + {"[[:space:]]", TEST_SPACE_CHARS, "x"}, + {"[[:upper:]]", TEST_UPPER_CHARS, "x"}, + {"[[:xdigit:]]", TEST_XDIGIT_CHARS, "h"}, + }; + + ARRAY_FOR_EACH_PTR(test_data, data) { + /* ensure that characters in "nomatch" do not match "pattern" */ + for (size_t j = 0; j < strlen(data->nomatch); j++) { + char input[] = {data->nomatch[j], '\0'}; + + zexpect_equal(fnmatch(data->pattern, input, 0), FNM_NOMATCH, + "pattern \"%s\" unexpectedly matched char 0x%02x (%c)", + data->pattern, data->nomatch[j], + isprint(data->nomatch[j]) ? data->nomatch[j] : '.'); + } + + /* ensure that characters in "match" do match "pattern" */ + for (size_t j = 0; j < strlen(data->match); j++) { + char input[] = {data->match[j], '\0'}; + + zexpect_ok(fnmatch(data->pattern, input, 0), + "pattern \"%s\" did not match char 0x%02x (%c)", data->pattern, + data->match[j], isprint(data->match[j]) ? data->match[j] : '.'); + } + } + + /* ensure that an invalid character class generates an error */ + zassert_equal(fnmatch("[[:foobarbaz:]]", "Z", 0), FNM_NOMATCH); } From b96116fe5c12359ff669161037e2aeeef27fe818 Mon Sep 17 00:00:00 2001 From: Harun Spago Date: Sun, 16 Nov 2025 21:24:35 +0100 Subject: [PATCH 4/7] include: zephyr: posix: removed FNM_NOSYS and FNM_NORES Removed two error codes since they are not official posix errors Signed-off-by: Harun Spago --- include/zephyr/posix/fnmatch.h | 17 +++++++++++++---- lib/posix/c_lib_ext/fnmatch.c | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/zephyr/posix/fnmatch.h b/include/zephyr/posix/fnmatch.h index 41e77aa70c149..6079bd16fc821 100644 --- a/include/zephyr/posix/fnmatch.h +++ b/include/zephyr/posix/fnmatch.h @@ -36,9 +36,7 @@ #ifndef _FNMATCH_H_ #define _FNMATCH_H_ -#define FNM_NOMATCH 1 /* Match failed. */ -#define FNM_NOSYS 2 /* Function not implemented. */ -#define FNM_NORES 3 /* Out of resources */ +#define FNM_NOMATCH 1 /**< Match failed */ #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ @@ -50,7 +48,18 @@ extern "C" { #endif -int fnmatch(const char *, const char *, int); +/** + * @brief Check if a filename or input string matches a shell-style matching pattern. + * + * @param pattern pattern that is matched against @param string + * @param string input string to match against @param pattern + * @param flags flags used to signal special matching conditions such as @ref FNM_NOESCAPE + * + * + * @retval 0 pattern found in string + * @retval FNM_NOMATCH pattern not found in string + */ +int fnmatch(const char *pattern, const char *string, int flags); #ifdef __cplusplus } diff --git a/lib/posix/c_lib_ext/fnmatch.c b/lib/posix/c_lib_ext/fnmatch.c index 23e67b7c2e8c2..407ebc00d2a20 100644 --- a/lib/posix/c_lib_ext/fnmatch.c +++ b/lib/posix/c_lib_ext/fnmatch.c @@ -303,7 +303,7 @@ static int fnmatchx(const char *pattern, const char *string, int flags, size_t r } if (recursion-- == 0) { - return FNM_NORES; + return FNM_NOMATCH; } for (stringstart = string;;) { From 32ec2faf151b6a55b689f57af070ec35153c1132 Mon Sep 17 00:00:00 2001 From: Harun Spago Date: Sat, 11 Oct 2025 21:49:05 +0200 Subject: [PATCH 5/7] posix: c_lib_ext: fnmatch: added Doxygen Added Doxygen on new functions and on fnmatch function Signed-off-by: Harun Spago --- include/zephyr/posix/fnmatch.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/zephyr/posix/fnmatch.h b/include/zephyr/posix/fnmatch.h index 6079bd16fc821..0f278fc5d38f0 100644 --- a/include/zephyr/posix/fnmatch.h +++ b/include/zephyr/posix/fnmatch.h @@ -38,11 +38,11 @@ #define FNM_NOMATCH 1 /**< Match failed */ -#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ -#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ -#define FNM_PERIOD 0x04 /* Period must be matched by period. */ -#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */ -#define FNM_LEADING_DIR 0x10 /* Ignore / after Imatch. */ +#define FNM_NOESCAPE 0x01 /**< Disable backslash escaping */ +#define FNM_PATHNAME 0x02 /**< Slash must be matched by slash */ +#define FNM_PERIOD 0x04 /**< Period must be matched by period */ +#define FNM_CASEFOLD 0x08 /**< Pattern is matched case-insensitive */ +#define FNM_LEADING_DIR 0x10 /**< Only match the initial segment of a string up to the first '/' */ #ifdef __cplusplus extern "C" { From ea3bad20f5d8ba2efc536e93c36ea5bcff1905e7 Mon Sep 17 00:00:00 2001 From: Harun Spago Date: Sat, 11 Oct 2025 22:03:01 +0200 Subject: [PATCH 6/7] posix: c_lib_ext: fnmatch: resolved SonarQube issues Resolved all sonar qube issues Signed-off-by: Harun Spago --- lib/posix/c_lib_ext/fnmatch.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/posix/c_lib_ext/fnmatch.c b/lib/posix/c_lib_ext/fnmatch.c index 407ebc00d2a20..a9b43deed3366 100644 --- a/lib/posix/c_lib_ext/fnmatch.c +++ b/lib/posix/c_lib_ext/fnmatch.c @@ -72,8 +72,9 @@ enum fnm_char_class { static bool fnm_cc_is_valid(const char *pattern, size_t psize, enum fnm_char_class *cc) { - if (psize < 4 || *pattern != ':') + if (psize < 4 || *pattern != ':') { return false; + } pattern++; /* skip ':' */ psize--; @@ -187,7 +188,6 @@ static inline int fnm_cc_match(int c, enum fnm_char_class cc) return 0; } - static inline int foldcase(int ch, int flags) { @@ -207,13 +207,15 @@ static bool match_posix_class(const char **pattern, int test) const char *p = *pattern; size_t remaining = strlen(p); - if (!fnm_cc_is_valid(p, remaining, &cc)) + if (!fnm_cc_is_valid(p, remaining, &cc)) { return false; + } /* move pattern pointer past ":]" */ const char *end = strstr(p, ":]"); - if (end) + if (end) { *pattern = end + 2; + } return fnm_cc_match(test, cc); } @@ -262,9 +264,14 @@ static const char *rangematch(const char *pattern, int test, int flags) ok = true; continue; } else { - // skip over class if unrecognized - while (*pattern && !(*pattern == ':' && *(pattern+1) == ']')) pattern++; - if (*pattern) pattern += 2; + /* skip over class if unrecognized */ + while (*pattern && !(*pattern == ':' && *(pattern + 1) == ']')) { + pattern++; + } + + if (*pattern) { + pattern += 2; + } continue; } } From 6ba774e62445c4a18bde1c3563224a3baa5e583e Mon Sep 17 00:00:00 2001 From: Harun Spago Date: Tue, 14 Oct 2025 23:14:59 +0200 Subject: [PATCH 7/7] posix: c_lib_ext: formated code using clang-format Formated fnmatch c and h files and test files using clang-format Signed-off-by: Harun Spago --- include/zephyr/posix/fnmatch.h | 12 +++--- lib/posix/c_lib_ext/fnmatch.c | 75 ++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/include/zephyr/posix/fnmatch.h b/include/zephyr/posix/fnmatch.h index 0f278fc5d38f0..3171898264f28 100644 --- a/include/zephyr/posix/fnmatch.h +++ b/include/zephyr/posix/fnmatch.h @@ -38,11 +38,13 @@ #define FNM_NOMATCH 1 /**< Match failed */ -#define FNM_NOESCAPE 0x01 /**< Disable backslash escaping */ -#define FNM_PATHNAME 0x02 /**< Slash must be matched by slash */ -#define FNM_PERIOD 0x04 /**< Period must be matched by period */ -#define FNM_CASEFOLD 0x08 /**< Pattern is matched case-insensitive */ -#define FNM_LEADING_DIR 0x10 /**< Only match the initial segment of a string up to the first '/' */ +#define FNM_NOESCAPE 0x01 /**< Disable backslash escaping */ +#define FNM_PATHNAME 0x02 /**< Slash must be matched by slash */ +#define FNM_PERIOD 0x04 /**< Period must be matched by period */ +#define FNM_CASEFOLD 0x08 /**< Pattern is matched case-insensitive */ +#define FNM_LEADING_DIR \ + 0x10 /**< Only match the initial segment of a string up to the first '/' \ + */ #ifdef __cplusplus extern "C" { diff --git a/lib/posix/c_lib_ext/fnmatch.c b/lib/posix/c_lib_ext/fnmatch.c index a9b43deed3366..09e0bda4e9074 100644 --- a/lib/posix/c_lib_ext/fnmatch.c +++ b/lib/posix/c_lib_ext/fnmatch.c @@ -48,11 +48,13 @@ #define EOS '\0' -#define MATCH_CLASS6(p,a,b,c,d,e,f,g) \ - ((p)[0]==(a) && (p)[1]==(b) && (p)[2]==(c) && (p)[3]==(d) && (p)[4]==(e) && (p)[5]==(f) && (p)[6]==(g)) +#define MATCH_CLASS6(p, a, b, c, d, e, f, g) \ + ((p)[0] == (a) && (p)[1] == (b) && (p)[2] == (c) && (p)[3] == (d) && (p)[4] == (e) && \ + (p)[5] == (f) && (p)[6] == (g)) -#define MATCH_CLASS7(p,a,b,c,d,e,f,g,h) \ - ((p)[0]==(a) && (p)[1]==(b) && (p)[2]==(c) && (p)[3]==(d) && (p)[4]==(e) && (p)[5]==(f) && (p)[6]==(g) && (p)[7]==(h)) +#define MATCH_CLASS7(p, a, b, c, d, e, f, g, h) \ + ((p)[0] == (a) && (p)[1] == (b) && (p)[2] == (c) && (p)[3] == (d) && (p)[4] == (e) && \ + (p)[5] == (f) && (p)[6] == (g) && (p)[7] == (h)) enum fnm_char_class { FNM_CC_ALNUM, @@ -76,84 +78,84 @@ static bool fnm_cc_is_valid(const char *pattern, size_t psize, enum fnm_char_cla return false; } - pattern++; /* skip ':' */ + pattern++; /* skip ':' */ psize--; /* Each class name ends with ":]" */ switch (pattern[0]) { case 'a': - if (MATCH_CLASS6(pattern,'a','l','n','u','m',':',']')) { + if (MATCH_CLASS6(pattern, 'a', 'l', 'n', 'u', 'm', ':', ']')) { *cc = FNM_CC_ALNUM; return true; } - if (MATCH_CLASS6(pattern,'a','l','p','h','a',':',']')) { + if (MATCH_CLASS6(pattern, 'a', 'l', 'p', 'h', 'a', ':', ']')) { *cc = FNM_CC_ALPHA; return true; } break; - + case 'b': - if (MATCH_CLASS6(pattern,'b','l','a','n','k',':',']')) { + if (MATCH_CLASS6(pattern, 'b', 'l', 'a', 'n', 'k', ':', ']')) { *cc = FNM_CC_BLANK; return true; } break; case 'c': - if (MATCH_CLASS6(pattern,'c','n','t','r','l',':',']')) { + if (MATCH_CLASS6(pattern, 'c', 'n', 't', 'r', 'l', ':', ']')) { *cc = FNM_CC_CNTRL; return true; } break; case 'd': - if (MATCH_CLASS6(pattern,'d','i','g','i','t',':',']')) { + if (MATCH_CLASS6(pattern, 'd', 'i', 'g', 'i', 't', ':', ']')) { *cc = FNM_CC_DIGIT; return true; } break; case 'g': - if (MATCH_CLASS6(pattern,'g','r','a','p','h',':',']')) { + if (MATCH_CLASS6(pattern, 'g', 'r', 'a', 'p', 'h', ':', ']')) { *cc = FNM_CC_GRAPH; return true; } break; case 'l': - if (MATCH_CLASS6(pattern,'l','o','w','e','r',':',']')) { + if (MATCH_CLASS6(pattern, 'l', 'o', 'w', 'e', 'r', ':', ']')) { *cc = FNM_CC_LOWER; return true; } break; case 'p': - if (MATCH_CLASS6(pattern,'p','r','i','n','t',':',']')) { + if (MATCH_CLASS6(pattern, 'p', 'r', 'i', 'n', 't', ':', ']')) { *cc = FNM_CC_PRINT; return true; } - if (MATCH_CLASS6(pattern,'p','u','n','c','t',':',']')) { + if (MATCH_CLASS6(pattern, 'p', 'u', 'n', 'c', 't', ':', ']')) { *cc = FNM_CC_PUNCT; return true; } break; case 's': - if (MATCH_CLASS6(pattern,'s','p','a','c','e',':',']')) { + if (MATCH_CLASS6(pattern, 's', 'p', 'a', 'c', 'e', ':', ']')) { *cc = FNM_CC_SPACE; return true; } break; case 'u': - if (MATCH_CLASS6(pattern,'u','p','p','e','r',':',']')) { + if (MATCH_CLASS6(pattern, 'u', 'p', 'p', 'e', 'r', ':', ']')) { *cc = FNM_CC_UPPER; return true; } break; case 'x': - if (MATCH_CLASS7(pattern,'x','d','i','g','i','t',':',']')) { + if (MATCH_CLASS7(pattern, 'x', 'd', 'i', 'g', 'i', 't', ':', ']')) { *cc = FNM_CC_XDIGIT; return true; } @@ -169,18 +171,30 @@ static bool fnm_cc_is_valid(const char *pattern, size_t psize, enum fnm_char_cla static inline int fnm_cc_match(int c, enum fnm_char_class cc) { switch (cc) { - case FNM_CC_ALNUM: return isalnum(c); - case FNM_CC_ALPHA: return isalpha(c); - case FNM_CC_BLANK: return isblank(c); - case FNM_CC_CNTRL: return iscntrl(c); - case FNM_CC_DIGIT: return isdigit(c); - case FNM_CC_GRAPH: return isgraph(c); - case FNM_CC_LOWER: return islower(c); - case FNM_CC_PRINT: return isprint(c); - case FNM_CC_PUNCT: return ispunct(c); - case FNM_CC_SPACE: return isspace(c); - case FNM_CC_UPPER: return isupper(c); - case FNM_CC_XDIGIT: return isxdigit(c); + case FNM_CC_ALNUM: + return isalnum(c); + case FNM_CC_ALPHA: + return isalpha(c); + case FNM_CC_BLANK: + return isblank(c); + case FNM_CC_CNTRL: + return iscntrl(c); + case FNM_CC_DIGIT: + return isdigit(c); + case FNM_CC_GRAPH: + return isgraph(c); + case FNM_CC_LOWER: + return islower(c); + case FNM_CC_PRINT: + return isprint(c); + case FNM_CC_PUNCT: + return ispunct(c); + case FNM_CC_SPACE: + return isspace(c); + case FNM_CC_UPPER: + return isupper(c); + case FNM_CC_XDIGIT: + return isxdigit(c); default: break; } @@ -213,6 +227,7 @@ static bool match_posix_class(const char **pattern, int test) /* move pattern pointer past ":]" */ const char *end = strstr(p, ":]"); + if (end) { *pattern = end + 2; }