From f35f863bdb5e1c50524112ef2148e485591210a9 Mon Sep 17 00:00:00 2001 From: local-dev Date: Wed, 27 May 2026 14:03:17 -0700 Subject: [PATCH] fix(libc): guard _jp2uc_l/_uc2jp_l calls in towctrans_l with _MB_CAPABLE When _MB_CAPABLE is undefined, jp2uc.c wraps the bodies of _jp2uc_l and _uc2jp_l in `#ifdef _MB_CAPABLE`, so the symbols are not defined. towctrans_l, however, called both helpers unconditionally: wint_t u = _jp2uc_l (c, locale); ... return _uc2jp_l (res, locale); The result was that builds without _MB_CAPABLE linked successfully only because nothing referenced towctrans_l; the moment something did (for example `--whole-archive libc.a` when packaging a static runtime), the link failed with undefined references to _jp2uc_l and _uc2jp_l. Every other caller of these helpers in newlib already guards them behind `#ifdef _MB_CAPABLE` (iswalnum_l.c, iswalpha_l.c, iswlower_l.c, iswupper_l.c, iswprint_l.c, iswpunct_l.c, iswspace_l.c, iswgraph_l.c, iswblank_l.c, iswcntrl_l.c, wcwidth.c, wcswidth.c). towctrans_l was the lone outlier. This patch wraps the Unicode case-conversion machinery (caseconv_table, bisearch, toulower, touupper, and the original Unicode-table towctrans_l body) in `#ifdef _MB_CAPABLE`, and provides a no-MB implementation that matches what towlower_l.c / towupper_l.c already do in the no-MB build: delegate to the narrow-ctype-backed towlower / towupper. This keeps direct callers of towctrans / towctrans_l consistent with the sibling locale wrappers in the same configuration and avoids -Wunused-function on the otherwise-dead static helpers. The _MB_CAPABLE-on path is functionally unchanged: the preprocessor selects exactly the same code as before. The same bug exists in upstream sourceware newlib; this fix is being landed in nanvix/newlib first to unblock dependent work, and will be proposed upstream separately. Verified by cross-compiling the patched file with i686-nanvix-gcc: - without _MB_CAPABLE: towctrans_l defined, no undefined references to _jp2uc_l/_uc2jp_l (the bug fix); towlower/towupper are the only newly-referenced externals. - with -D_MB_CAPABLE: towctrans_l defined, _jp2uc_l/_uc2jp_l referenced exactly as before; caseconv_table emitted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- newlib/libc/ctype/towctrans_l.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/newlib/libc/ctype/towctrans_l.c b/newlib/libc/ctype/towctrans_l.c index b829266a49..b8e900b5aa 100644 --- a/newlib/libc/ctype/towctrans_l.c +++ b/newlib/libc/ctype/towctrans_l.c @@ -5,6 +5,8 @@ //#include #include "local.h" +#ifdef _MB_CAPABLE + /* struct caseconv_entry describes the case conversion behaviour of a range of Unicode characters. @@ -160,3 +162,27 @@ towctrans_l (wint_t c, wctrans_t w, struct __locale_t *locale) else return c; } + +#else /* !_MB_CAPABLE */ + +/* When _MB_CAPABLE is not defined, newlib does not compile the + JIS<->Unicode helpers (_jp2uc_l / _uc2jp_l) used above; their bodies + in jp2uc.c are wrapped in #ifdef _MB_CAPABLE. In this configuration + the sibling locale wrappers towlower_l / towupper_l do not call + towctrans_l at all -- they delegate directly to the narrow-ctype- + backed towlower / towupper (see towlower_l.c, towupper_l.c). Mirror + that behavior here so direct callers of towctrans / towctrans_l with + WCT_TOLOWER or WCT_TOUPPER see the same result as towlower_l / + towupper_l in the same configuration. */ +wint_t +towctrans_l (wint_t c, wctrans_t w, struct __locale_t *locale) +{ + (void) locale; + if (w == WCT_TOLOWER) + return towlower (c); + if (w == WCT_TOUPPER) + return towupper (c); + return c; +} + +#endif /* _MB_CAPABLE */