Author: Dharanendiran <dharanendiran@timesys.com>
Date: Tue, 7 Jul 2026 10:05:17 +0530

---
 src/backend/regex/regc_pg_locale.c     | 88 ++++++++++++++++++++++++++
 src/backend/utils/adt/like.c           |  4 ++
 src/backend/utils/adt/like_support.c   |  4 ++
 src/backend/utils/adt/pg_locale_libc.c | 52 ++++++++++++++-
 4 files changed, 145 insertions(+), 3 deletions(-)

diff --git a/src/backend/regex/regc_pg_locale.c b/src/backend/regex/regc_pg_locale.c
index 78193cf..9fbe8a3 100644
--- a/src/backend/regex/regc_pg_locale.c
+++ b/src/backend/regex/regc_pg_locale.c
@@ -307,11 +307,19 @@ pg_wc_isdigit(pg_wchar c)
 			return pg_u_isdigit(c, !pg_regex_locale->info.builtin.casemap_full);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswdigit_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswdigit((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					isdigit_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					isdigit((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -334,11 +342,19 @@ pg_wc_isalpha(pg_wchar c)
 			return pg_u_isalpha(c);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswalpha_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswalpha((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					isalpha_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					isalpha((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -361,11 +377,19 @@ pg_wc_isalnum(pg_wchar c)
 			return pg_u_isalnum(c, !pg_regex_locale->info.builtin.casemap_full);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswalnum_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswalnum((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					isalnum_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					isalnum((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -397,11 +421,19 @@ pg_wc_isupper(pg_wchar c)
 			return pg_u_isupper(c);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswupper_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswupper((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					isupper_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					isupper((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -424,11 +456,19 @@ pg_wc_islower(pg_wchar c)
 			return pg_u_islower(c);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswlower_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswlower((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					islower_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					islower((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -451,11 +491,19 @@ pg_wc_isgraph(pg_wchar c)
 			return pg_u_isgraph(c);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswgraph_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswgraph((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					isgraph_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					isgraph((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -478,11 +526,19 @@ pg_wc_isprint(pg_wchar c)
 			return pg_u_isprint(c);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswprint_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswprint((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					isprint_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					isprint((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -505,11 +561,19 @@ pg_wc_ispunct(pg_wchar c)
 			return pg_u_ispunct(c, !pg_regex_locale->info.builtin.casemap_full);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswpunct_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswpunct((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					ispunct_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					ispunct((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -532,11 +596,19 @@ pg_wc_isspace(pg_wchar c)
 			return pg_u_isspace(c);
 		case PG_REGEX_STRATEGY_LIBC_WIDE:
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return iswspace_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return iswspace((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			return (c <= (pg_wchar) UCHAR_MAX &&
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					isspace_l((unsigned char) c, pg_regex_locale->info.lt));
+#else
+					isspace((unsigned char) c));
+#endif
 			break;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -563,14 +635,22 @@ pg_wc_toupper(pg_wchar c)
 			if (pg_regex_locale->is_default && c <= (pg_wchar) 127)
 				return pg_ascii_toupper((unsigned char) c);
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return towupper_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return towupper((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			/* force C behavior for ASCII characters, per comments above */
 			if (pg_regex_locale->is_default && c <= (pg_wchar) 127)
 				return pg_ascii_toupper((unsigned char) c);
 			if (c <= (pg_wchar) UCHAR_MAX)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return toupper_l((unsigned char) c, pg_regex_locale->info.lt);
+#else
+				return toupper((unsigned char) c);
+#endif
 			return c;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
@@ -597,14 +677,22 @@ pg_wc_tolower(pg_wchar c)
 			if (pg_regex_locale->is_default && c <= (pg_wchar) 127)
 				return pg_ascii_tolower((unsigned char) c);
 			if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return towlower_l((wint_t) c, pg_regex_locale->info.lt);
+#else
+				return towlower((wint_t) c);
+#endif
 			/* FALL THRU */
 		case PG_REGEX_STRATEGY_LIBC_1BYTE:
 			/* force C behavior for ASCII characters, per comments above */
 			if (pg_regex_locale->is_default && c <= (pg_wchar) 127)
 				return pg_ascii_tolower((unsigned char) c);
 			if (c <= (pg_wchar) UCHAR_MAX)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				return tolower_l((unsigned char) c, pg_regex_locale->info.lt);
+#else
+				return tolower((unsigned char) c);
+#endif
 			return c;
 		case PG_REGEX_STRATEGY_ICU:
 #ifdef USE_ICU
diff --git a/src/backend/utils/adt/like.c b/src/backend/utils/adt/like.c
index e69ca19..538616d 100644
--- a/src/backend/utils/adt/like.c
+++ b/src/backend/utils/adt/like.c
@@ -98,7 +98,11 @@ SB_lower_char(unsigned char c, pg_locale_t locale)
 	else if (locale->is_default)
 		return pg_tolower(c);
 	else
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 		return tolower_l(c, locale->info.lt);
+#else
+		return tolower(c);
+#endif
 }
 
 
diff --git a/src/backend/utils/adt/like_support.c b/src/backend/utils/adt/like_support.c
index 8fdc677..d72e70c 100644
--- a/src/backend/utils/adt/like_support.c
+++ b/src/backend/utils/adt/like_support.c
@@ -1501,7 +1501,11 @@ pattern_char_isalpha(char c, bool is_multibyte,
 		return IS_HIGHBIT_SET(c) ||
 			(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
 	else
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 		return isalpha_l((unsigned char) c, locale->info.lt);
+#else
+		return isalpha((unsigned char) c);
+#endif
 }
 
 
diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c
index c68fec2..b5fe9ec 100644
--- a/src/backend/utils/adt/pg_locale_libc.c
+++ b/src/backend/utils/adt/pg_locale_libc.c
@@ -25,7 +25,7 @@
 #include "utils/pg_locale.h"
 #include "utils/syscache.h"
 
-#ifdef __GLIBC__
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 #include <gnu/libc-version.h>
 #endif
 
@@ -33,6 +33,10 @@
 #include <shlwapi.h>
 #endif
 
+#if defined(__UCLIBC__)
+#define locale_t int
+#endif
+
 /*
  * Size of stack buffer to use for string transformations, used to avoid heap
  * allocations in typical cases. This should be large enough that most strings
@@ -179,7 +183,11 @@ strlower_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 			if (locale->is_default)
 				*p = pg_tolower((unsigned char) *p);
 			else
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				*p = tolower_l((unsigned char) *p, loc);
+#else
+				*p = tolower((unsigned char) *p);
+#endif
 		}
 	}
 
@@ -212,7 +220,11 @@ strlower_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 	char2wchar(workspace, srclen + 1, src, srclen, locale);
 
 	for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 		workspace[curr_char] = towlower_l(workspace[curr_char], loc);
+#else
+		workspace[curr_char] = towlower(workspace[curr_char]);
+#endif
 
 	/*
 	 * Make result large enough; case change might change number of bytes
@@ -269,11 +281,19 @@ strtitle_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 			else
 			{
 				if (wasalnum)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 					*p = tolower_l((unsigned char) *p, loc);
 				else
 					*p = toupper_l((unsigned char) *p, loc);
 			}
 			wasalnum = isalnum_l((unsigned char) *p, loc);
+#else
+					*p = tolower((unsigned char) *p);
+				else
+					*p = toupper((unsigned char) *p);
+			}
+			wasalnum = isalnum((unsigned char) *p);
+#endif
 		}
 	}
 
@@ -309,10 +329,17 @@ strtitle_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 	for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
 	{
 		if (wasalnum)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 			workspace[curr_char] = towlower_l(workspace[curr_char], loc);
 		else
 			workspace[curr_char] = towupper_l(workspace[curr_char], loc);
 		wasalnum = iswalnum_l(workspace[curr_char], loc);
+#else
+			workspace[curr_char] = towlower(workspace[curr_char]);
+		else
+			workspace[curr_char] = towupper(workspace[curr_char]);
+		wasalnum = iswalnum(workspace[curr_char]);
+#endif
 	}
 
 	/*
@@ -362,7 +389,11 @@ strupper_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 			if (locale->is_default)
 				*p = pg_toupper((unsigned char) *p);
 			else
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 				*p = toupper_l((unsigned char) *p, loc);
+#else
+				*p = toupper((unsigned char) *p);
+#endif
 		}
 	}
 
@@ -395,8 +426,11 @@ strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 	char2wchar(workspace, srclen + 1, src, srclen, locale);
 
 	for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 		workspace[curr_char] = towupper_l(workspace[curr_char], loc);
-
+#else
+		workspace[curr_char] = towupper(workspace[curr_char]);
+#endif
 	/*
 	 * Make result large enough; case change might change number of bytes
 	 */
@@ -608,7 +642,11 @@ strncoll_libc(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2,
 		arg2n = buf2;
 	}
 
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 	result = strcoll_l(arg1n, arg2n, locale->info.lt);
+#else
+	result = strcoll(arg1n, arg2n);
+#endif
 
 	if (buf != sbuf)
 		pfree(buf);
@@ -635,7 +673,11 @@ strnxfrm_libc(char *dest, size_t destsize, const char *src, ssize_t srclen,
 	Assert(locale->provider == COLLPROVIDER_LIBC);
 
 	if (srclen == -1)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 		return strxfrm_l(dest, src, destsize, locale->info.lt);
+#else
+		return strxfrm(dest, src, destsize);
+#endif
 
 	if (bufsize > TEXTBUFLEN)
 		buf = palloc(bufsize);
@@ -644,7 +686,11 @@ strnxfrm_libc(char *dest, size_t destsize, const char *src, ssize_t srclen,
 	memcpy(buf, src, srclen);
 	buf[srclen] = '\0';
 
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 	result = strxfrm_l(dest, buf, destsize, locale->info.lt);
+#else
+	result = strxfrm(dest, buf, destsize);
+#endif
 
 	if (buf != sbuf)
 		pfree(buf);
@@ -664,7 +710,7 @@ get_collation_actual_version_libc(const char *collcollate)
 		pg_strncasecmp("C.", collcollate, 2) != 0 &&
 		pg_strcasecmp("POSIX", collcollate) != 0)
 	{
-#if defined(__GLIBC__)
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
 		/* Use the glibc version because we don't have anything better. */
 		collversion = pstrdup(gnu_get_libc_version());
 #elif defined(LC_VERSION_MASK)
-- 
2.25.1

