[PATCH] handle casing of i/I in Turkic languages

Thomas Wolff <[email protected]> Mon, 2 Feb 2026 14:21:57 +0100
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
0001-towupper-towlower-handle-special-casing-of-i-I-for-T.patch (text/plain, 2.4 KB)
From 99df2722cb39dcf0290dfcd14d7e81ec87853e15 Mon Sep 17 00:00:00 2001
From: Thomas Wolff <[email protected]>
Date: Mon, 2 Feb 2026 00:00:00 +0000
Subject: [PATCH] towupper/towlower: handle special casing of "i"/"I" for
 Turkic languages

---
 newlib/libc/ctype/towctrans.c   |  2 +-
 newlib/libc/ctype/towctrans_l.c | 23 +++++++++++++++++++----
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/newlib/libc/ctype/towctrans.c b/newlib/libc/ctype/towctrans.c
index 176aa3d9d..2cd34184e 100644
--- a/newlib/libc/ctype/towctrans.c
+++ b/newlib/libc/ctype/towctrans.c
@@ -81,7 +81,7 @@ _towctrans_r (struct _reent *r,
 	wctrans_t w)
 {
   if (w == WCT_TOLOWER || w == WCT_TOUPPER)
-    return towctrans_l (c, w, 0);
+    return towctrans_l (c, w, LC_GLOBAL_LOCALE);
   else
     {
       // skipping this because it was causing trouble (cygwin crash)
diff --git a/newlib/libc/ctype/towctrans_l.c b/newlib/libc/ctype/towctrans_l.c
index e94d6f492..2b843f302 100644
--- a/newlib/libc/ctype/towctrans_l.c
+++ b/newlib/libc/ctype/towctrans_l.c
@@ -72,9 +72,21 @@ bisearch (wint_t ucs, const struct caseconv_entry *table, int max)
   return 0;
 }
 
+static int
+isturk (struct __locale_t *locale)
+{
+  const char * loc = getlocalename_l (LC_CTYPE, locale);
+  if (!loc)
+    return 0;
+  return 0 == strncmp (loc, "tr", 2) || 0 == strncmp (loc, "az", 2);
+}
+
 static wint_t
-toulower (wint_t c)
+toulower (wint_t c, struct __locale_t *locale)
 {
+  if (c == 'I' && isturk (locale))
+    return 0x131; // LATIN SMALL LETTER DOTLESS I
+
   const struct caseconv_entry * cce =
     bisearch(c, caseconv_table,
              sizeof(caseconv_table) / sizeof(*caseconv_table) - 1);
@@ -108,8 +120,11 @@ toulower (wint_t c)
 }
 
 static wint_t
-touupper (wint_t c)
+touupper (wint_t c, struct __locale_t *locale)
 {
+  if (c == 'i' && isturk (locale))
+    return 0x130; // LATIN CAPITAL LETTER I WITH DOT ABOVE
+
   const struct caseconv_entry * cce =
     bisearch(c, caseconv_table,
              sizeof(caseconv_table) / sizeof(*caseconv_table) - 1);
@@ -151,9 +166,9 @@ towctrans_l (wint_t c, wctrans_t w, struct __locale_t *locale)
   wint_t u = _jp2uc_l (c, locale);
   wint_t res;
   if (w == WCT_TOLOWER)
-    res = toulower (u);
+    res = toulower (u, locale);
   else if (w == WCT_TOUPPER)
-    res = touupper (u);
+    res = touupper (u, locale);
   else
     {
       // skipping the errno setting that was previously involved
-- 
2.51.0