From d2e5a0c609fe0c2a6e826c7ec7e8e39d78bb5796 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 16 Nov 2025 13:07:10 -0500 Subject: [PATCH 1/4] libc: minimal: ctype: use unsigned int instead of unsigned The "check warns" workflow in CI warned over the use of `unsigned` as a shorthand for `unsigned int` in several locations in `lib/libc/minimal/include/ctype.h`. ``` UNSPECIFIED_INT: Prefer 'unsigned int' to bare use of 'unsigned' File:lib/libc/minimal/include/ctype.h ``` Adjust `unsigned` to `unsigned int` to avoid linter warnings. Signed-off-by: Chris Friedt --- lib/libc/minimal/include/ctype.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/libc/minimal/include/ctype.h b/lib/libc/minimal/include/ctype.h index f9a4bdf7b4c47..5cc70e273d3f3 100644 --- a/lib/libc/minimal/include/ctype.h +++ b/lib/libc/minimal/include/ctype.h @@ -15,42 +15,42 @@ extern "C" { static inline int isupper(int a) { - return (int)(((unsigned)(a)-(unsigned)'A') < 26U); + return (int)(((unsigned int)(a)-(unsigned int)'A') < 26U); } static inline int isalpha(int c) { - return (int)((((unsigned)c|32u)-(unsigned)'a') < 26U); + return (int)((((unsigned int)c|32u)-(unsigned int)'a') < 26U); } static inline int isspace(int c) { - return (int)(c == (int)' ' || ((unsigned)c-(unsigned)'\t') < 5U); + return (int)(c == (int)' ' || ((unsigned int)c-(unsigned int)'\t') < 5U); } static inline int isgraph(int c) { - return (int)((((unsigned)c) > ' ') && - (((unsigned)c) <= (unsigned)'~')); + return (int)((((unsigned int)c) > ' ') && + (((unsigned int)c) <= (unsigned int)'~')); } static inline int isprint(int c) { - return (int)((((unsigned)c) >= ' ') && - (((unsigned)c) <= (unsigned)'~')); + return (int)((((unsigned int)c) >= ' ') && + (((unsigned int)c) <= (unsigned int)'~')); } static inline int isdigit(int a) { - return (int)(((unsigned)(a)-(unsigned)'0') < 10U); + return (int)(((unsigned int)(a)-(unsigned int)'0') < 10U); } static inline int isxdigit(int a) { unsigned int ua = (unsigned int)a; - return (int)(((ua - (unsigned)'0') < 10U) || - ((ua | 32U) - (unsigned)'a' < 6U)); + return (int)(((ua - (unsigned int)'0') < 10U) || + ((ua | 32U) - (unsigned int)'a' < 6U)); } static inline int tolower(int chr) From c292638c2dac73ff9077003dc085149dc0c84383 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 16 Nov 2025 13:23:06 -0500 Subject: [PATCH 2/4] libc: minimal: ctype: express ctype limits in more direct fashion Based on review feedback, it was suggested to express ctype character checks in a more direct fashion, rather than using arithmetic, and allow the compiler to optimize as it sees fit. https://github.com/zephyrproject-rtos/zephyr/pull/99451#\ discussion_r2530339430 Signed-off-by: Chris Friedt --- lib/libc/minimal/include/ctype.h | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/libc/minimal/include/ctype.h b/lib/libc/minimal/include/ctype.h index 5cc70e273d3f3..352e077188a00 100644 --- a/lib/libc/minimal/include/ctype.h +++ b/lib/libc/minimal/include/ctype.h @@ -15,42 +15,47 @@ extern "C" { static inline int isupper(int a) { - return (int)(((unsigned int)(a)-(unsigned int)'A') < 26U); + return (int)(((int)'A' <= a) && (a <= (int)'Z')); } static inline int isalpha(int c) { - return (int)((((unsigned int)c|32u)-(unsigned int)'a') < 26U); + /* force to lowercase */ + c += 32U; + + return (int)(((int)'a' <= c) && (c <= (int)'z')); } static inline int isspace(int c) { - return (int)(c == (int)' ' || ((unsigned int)c-(unsigned int)'\t') < 5U); + return (int)((c == (int)' ') || (((int)'\t' <= c) && (c <= (int)'\r'))); } static inline int isgraph(int c) { - return (int)((((unsigned int)c) > ' ') && - (((unsigned int)c) <= (unsigned int)'~')); + return (int)(((int)' ' < c) && (c <= (int)'~')); } static inline int isprint(int c) { - return (int)((((unsigned int)c) >= ' ') && - (((unsigned int)c) <= (unsigned int)'~')); + return (int)(((int)' ' <= c) && (c <= (int)'~')); } static inline int isdigit(int a) { - return (int)(((unsigned int)(a)-(unsigned int)'0') < 10U); + return (int)(((int)'0' <= a) && (a <= (int)'9')); } static inline int isxdigit(int a) { - unsigned int ua = (unsigned int)a; + if (isdigit(a) != 0) { + return 1; + } + + /* force to lowercase */ + a += 32U; - return (int)(((ua - (unsigned int)'0') < 10U) || - ((ua | 32U) - (unsigned int)'a' < 6U)); + return (int)(((int)'a' <= a) && (a <= (int)'f')); } static inline int tolower(int chr) From 2033c7fde430c09ca766a1b10173703b746c404a Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 19 Nov 2025 10:46:49 -0500 Subject: [PATCH 3/4] libc: minimal: ctype: remove unnecessary casts A review comment in the PR below requested that unnecessary casts were removed from ctype.h in the PR below. https://github.com/zephyrproject-rtos/zephyr/pull/99451 Tested with manual compilation in C and C++ mode with the arguments ```shell gcc -Wconversion -Werror -Wall -Wextra -Wint-conversion clang -Wconversion -Werror -Wall -Wextra -Wint-conversion gcc -Wconversion -Werror -Wall -Wimplicit--Wextra clang++ -Wconversion -Werror -Wall -Wextra ``` and also with `-- -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y` Signed-off-by: Chris Friedt --- lib/libc/minimal/include/ctype.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lib/libc/minimal/include/ctype.h b/lib/libc/minimal/include/ctype.h index 352e077188a00..d6ead8d18fd95 100644 --- a/lib/libc/minimal/include/ctype.h +++ b/lib/libc/minimal/include/ctype.h @@ -15,35 +15,35 @@ extern "C" { static inline int isupper(int a) { - return (int)(((int)'A' <= a) && (a <= (int)'Z')); + return (('A' <= a) && (a <= 'Z')); } static inline int isalpha(int c) { /* force to lowercase */ - c += 32U; + c |= 32; - return (int)(((int)'a' <= c) && (c <= (int)'z')); + return (('a' <= c) && (c <= 'z')); } static inline int isspace(int c) { - return (int)((c == (int)' ') || (((int)'\t' <= c) && (c <= (int)'\r'))); + return ((c == ' ') || (('\t' <= c) && (c <= '\r'))); } static inline int isgraph(int c) { - return (int)(((int)' ' < c) && (c <= (int)'~')); + return ((' ' < c) && (c <= '~')); } static inline int isprint(int c) { - return (int)(((int)' ' <= c) && (c <= (int)'~')); + return ((' ' <= c) && (c <= '~')); } static inline int isdigit(int a) { - return (int)(((int)'0' <= a) && (a <= (int)'9')); + return (('0' <= a) && (a <= '9')); } static inline int isxdigit(int a) @@ -53,30 +53,29 @@ static inline int isxdigit(int a) } /* force to lowercase */ - a += 32U; + a |= 32; - return (int)(((int)'a' <= a) && (a <= (int)'f')); + return (('a' <= a) && (a <= 'f')); } static inline int tolower(int chr) { - return (chr >= (int)'A' && chr <= (int)'Z') ? (chr + 32) : (chr); + return (chr >= 'A' && chr <= 'Z') ? (chr + 32) : (chr); } static inline int toupper(int chr) { - return (int)((chr >= (int)'a' && chr <= - (int)'z') ? (chr - 32) : (chr)); + return ((chr >= 'a' && chr <= 'z') ? (chr - 32) : (chr)); } static inline int isalnum(int chr) { - return (int)(isalpha(chr) || isdigit(chr)); + return (isalpha(chr) || isdigit(chr)); } static inline int iscntrl(int c) { - return (int)((((unsigned int)c) <= 31U) || (((unsigned int)c) == 127U)); + return ((((unsigned int)c) <= 31U) || (((unsigned int)c) == 127U)); } #ifdef __cplusplus From 313c09194931e07576e913d257ab18d3742579b0 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 15 Nov 2025 16:51:03 -0500 Subject: [PATCH 4/4] libc: minimal: add missing ctype.h functions Add the functions below to the minimal libc ctype.h since they are missing, and are required as of C89 (C99 for `isblank()`) * `isblank()` * `islower()` * `ispunct()` Signed-off-by: Chris Friedt --- lib/libc/minimal/include/ctype.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/libc/minimal/include/ctype.h b/lib/libc/minimal/include/ctype.h index d6ead8d18fd95..82acd03351172 100644 --- a/lib/libc/minimal/include/ctype.h +++ b/lib/libc/minimal/include/ctype.h @@ -26,6 +26,11 @@ static inline int isalpha(int c) return (('a' <= c) && (c <= 'z')); } +static inline int isblank(int c) +{ + return ((c == ' ') || (c == '\t')); +} + static inline int isspace(int c) { return ((c == ' ') || (('\t' <= c) && (c <= '\r'))); @@ -46,6 +51,11 @@ static inline int isdigit(int a) return (('0' <= a) && (a <= '9')); } +static inline int islower(int c) +{ + return (('a' <= c) && (c <= 'z')); +} + static inline int isxdigit(int a) { if (isdigit(a) != 0) { @@ -73,6 +83,11 @@ static inline int isalnum(int chr) return (isalpha(chr) || isdigit(chr)); } +static inline int ispunct(int c) +{ + return (isgraph(c) && !isalnum(c)); +} + static inline int iscntrl(int c) { return ((((unsigned int)c) <= 31U) || (((unsigned int)c) == 127U));