Skip to content

feat(libSceLibcInternal): implement the ctype<wchar_t> widen and narrow members - #15744

Closed
B-Howell wants to merge 1 commit into
boykopovar:mainfrom
B-Howell:feat/r3-ctype-wchar-widen
Closed

B-Howell wants to merge 1 commit into
boykopovar:mainfrom
B-Howell:feat/r3-ctype-wchar-widen

Conversation

@B-Howell

@B-Howell B-Howell commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

What

Implements the four std::ctype<wchar_t> widen and narrow members that libSceLibcInternal declared as stubs throwing through NotImplemented_nid_no_patch in InventoryExports2.cpp:

Symbol NID Behaviour
_ZNKSt5ctypeIwE8do_widenEc h3PbnNnZ-gI btowc of the byte, cut to the 16-bit wchar_t
_ZNKSt5ctypeIwE8do_widenEPKcS2_Pw KM0b6O8show widens each byte of [first, last) into the destination, returns last
_ZNKSt5ctypeIwE9do_narrowEwc V+c0E+Uqcww wctob of the character, or the default when it has no one-byte form
_ZNKSt5ctypeIwE9do_narrowEPKwS2_cPc Vf68JAD5rbM narrows each element of [first, last) into the destination, returns last

The reference is the Dinkumware ctype<wchar_t> in microsoft/STL stl/inc/xlocale at e1ed302, lines 2999 to 3037. There, _Dowiden is return _Mbrtowc(&_Wc, &_Byte, 1, &_Mbst, &_Cvt) < 0 ? static_cast<wchar_t>(WEOF) : _Wc; with a fresh mbstate_t, _Donarrow is return _Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1 ? _Dflt : _Buf[0];, and both range forms loop *_Dest = _Dowiden(*_First) (or _Donarrow) up to _Last and return _First. ISO C defines btowc as exactly that one-byte mbrtowc from the initial shift state (WEOF unless (unsigned char)c is a valid single-byte character) and wctob as that wcrtomb which must produce one byte (EOF otherwise), so the members run the existing libc btowc_nid_postfix and wctob_nid_postfix (declared in prx/libc/include/Api.hpp). The byte is passed as unsigned char, so '\xff' is not read as EOF. wchar_t is 16 bits here, as in libc's mbtowc and numpunct<wchar_t>, so WEOF becomes 0xffff. The NIDs were checked by computing them from the mangled names with tools/nid_names.py compute_nid.

No libc export is added: the members live in libSceLibcInternal and call libc through its header, as AlignedNew.cpp does.

Changes:

  • core/libs/prx/libSceLibcInternal/WideCtype.cpp: the four members, exported under their NIDs. They are declared in prx/libSceLibcInternal/include/Api.hpp and built by CMakeLists.txt.
  • core/libs/prx/libSceLibcInternal/InventoryExports2.cpp: the four stubs are removed.
  • core/libs/tests/GuestLibcInternalWideCtype.cpp (guest_libc_internal_wide_ctype): checks do_widen(char) for every char value, including that errno becomes 86 (EILSEQ) for the bytes btowc rejects (0x80 to 0xbf, 0xf0 to 0xff) and stays 0 for incomplete lead bytes; checks do_narrow(wchar_t, char) for every 16-bit value with the defaults ? and \x80; checks a full range and a sub-range of both range forms, with \0, 0x7f, 0x80, 0xc3, 0xff, 0xe9, 0x20ac and 0xffff and an untouched guard element after the destination; and checks empty ranges with a null destination.
  • docs/dev/debt/libSceLibcInternal.md: the four names are cut from their "signatures and behavior are unverified" entry. A Functional entry records the reference, and that the facet is not read: the console keeps the conversion state of the facet's locale in it (_Cvt), so a facet built for a locale other than C converts as libc's C locale does here, and the console bodies were not read.

tools/progress.py collect_libraries(): origin/main b11c7bf84f has 9921 done of 37146 (libSceLibcInternal 92 done, 1045 todo). This branch has 9925 done of 37146 (libSceLibcInternal 96 done, 1041 todo). Done goes up by 4, and the todo names removed are exactly the four stubs. No new todo appears.

Wide stream formatting and parsing widen and narrow through ctype<wchar_t> (num_put and time_put stage 2, pattern scanning). This is runtime completeness; no title trace calls them yet.

Tested

Only the libraries and the focused test target were built (ninja -j3 guest_libc_internal_wide_ctype_tests libSceLibcInternal). No title was run.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

🤖 Generated with Claude Code

…ow members

do_widen(char), do_widen(range), do_narrow(wchar_t, char) and
do_narrow(range) of ctype<wchar_t> run libc btowc and wctob, the
one-byte mbrtowc and wcrtomb that Dinkumware's _Dowiden and _Donarrow
perform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the open PR limit Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20 label Nov 4, 2026
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

Thank you for your contribution! Authors with no pull requests merged into main can have 1 open pull request at a time, authors with at least 1 merged can have 20, and from 20 merged there is no limit. This PR has been automatically closed and labeled "open PR limit" because that limit was reached. This is not a judgment of the quality of your changes: reopen it once one of your open pull requests is merged or closed.

@github-actions github-actions Bot closed this Nov 4, 2026
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

Progress report (b11c7bf → 22335bf)

📈 System libraries: 26.72% (+0.01%, +4 implemented, -4 removed functions)

✅ 4 implemented
Library Name
libSceLibcInternal sceLibcInternalWideCtypeNarrowRange_nid_no_patch
libSceLibcInternal sceLibcInternalWideCtypeNarrow_nid_no_patch
libSceLibcInternal sceLibcInternalWideCtypeWidenRange_nid_no_patch
libSceLibcInternal sceLibcInternalWideCtypeWiden_nid_no_patch
🗑️ 4 removed
Library Name
libSceLibcInternal sceLibcInternalUnknown_KM0b6O8show_nid_no_patch
libSceLibcInternal sceLibcInternalUnknown_V_c0E_Uqcww_nid_no_patch
libSceLibcInternal sceLibcInternalUnknown_Vf68JAD5rbM_nid_no_patch
libSceLibcInternal sceLibcInternalUnknown_h3PbnNnZ_gI_nid_no_patch

Changed libraries (implemented exports)

Library Before After Change
libSceLibcInternal 92/1137 (8.09%) 96/1137 (8.44%) +0.35%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

open PR limit Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant