Skip to content

feat(libc): scan 16-bit wide conversions on Linux - #5285

Closed
Nixitov wants to merge 1 commit into
boykopovar:mainfrom
Nixitov:feat/wide-scan-linux
Closed

Nixitov wants to merge 1 commit into
boykopovar:mainfrom
Nixitov:feat/wide-scan-linux

Conversation

@Nixitov

@Nixitov Nixitov commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

What

On Linux the scanf family threw for the 16-bit wide conversions (%ls, %lc, %l[, %S, %C) because glibc would store a 32-bit wchar_t per character into the guest's 16-bit buffer. vsscanf/sscanf now scan them here instead:

  • %ls, %S and %lc, %C decode the input's UTF-8 into the guest's 16-bit buffer independently of the host locale, as the narrow printf family already encodes wide arguments; a code point above U+FFFF becomes a surrogate pair.
  • %l[ is scanned through the host's wide scanset.
  • The scan runs directive by directive, the way the existing ScanGuest already does for the _s forms, so the non-wide conversions keep the host's behaviour and the wide ones no longer reach glibc's wchar_t.

fscanf and the _s forms still throw for wide conversions on Linux; only the buffer scans (vsscanf/sscanf) changed.

Tested

Windows 11, MinGW-w64 GCC 15.2.0 (WinLibs r7), Release.

  • guest_wide_formatting gains CheckScanning: wide strings, two of them, a mixed %d %ls, a field width, %lc, %n, leading whitespace, and (Linux only) accented UTF-8 and a non-BMP code point. It passes, and guest_formatting passes.
  • python tools/check_conventions.py --base origin/main passes.
  • The new Linux scanner is exercised by the Linux CI build; this machine runs the existing Windows path (ScanWindows), so the Linux branch was not run locally. The behaviour is recorded in docs/dev/debt/libc.md.

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
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Progress report (016db92 → d2bb74f)

📈 System libraries: 88.22% (+0.03%, +1 implemented functions)

✅ 1 implemented
Library Name
libc vsscanf_nid_postfix

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#4966 core/libs/prx/libc/src/Formatting.cpp L377, L396
#5222 core/libs/prx/libc/src/Formatting.cpp L11
#5330 core/libs/prx/libc/src/Formatting.cpp L11
#5606 core/libs/prx/libc/src/Formatting.cpp L374, L393, L396
docs/dev/debt/libc.md L56

@Nixitov

Nixitov commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks bot. This is an adjacent, same-file overlap rather than duplicated logic: this PR adds the Linux 16-bit wide conversions (%ls, %lc, %S, %C) to vsscanf/sscanf in Formatting.cpp and its test. #4966 (suppressed conversions before EOF) and #5222 (EOF stickiness) also touch the scanf code nearby.

Nothing here depends on them; whoever lands second just needs a small rebase. I'm happy to rebase this after either lands, and to reconcile the input-failure/EOF return values with #5222's ScanResultAtEndOfFile so the wide scanner follows the same rule.

AI-assisted: yes

danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 13, 2026
danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 13, 2026
Conflict with boykopovar#5285 (same author, same file): kept boykopovar#5291's ScanWideFile next to boykopovar#5285's code.
danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 13, 2026
Since the port of boykopovar#5285 sscanf scans %ls on Linux too: %ls reads every non-white-space character, and guest_formatting no longer expects a rejection.
The scanf family threw for %ls, %lc, %l[, %S and %C on Linux because glibc would store a 32-bit wchar_t per character into the guest's 16-bit buffer. Scan them directly, decoding UTF-8 independently of the host locale as the narrow printf family does, and leave the non-wide conversions on the host.
@Nixitov
Nixitov force-pushed the feat/wide-scan-linux branch from c836266 to d2bb74f Compare October 14, 2026 01:53
Nixitov added a commit to Nixitov/AnyPS5 that referenced this pull request Oct 14, 2026
fscanf still threw for %ls, %lc, %l[, %S and %C on Linux. Scan them like vsscanf/sscanf, decoding the stream's UTF-8 into the guest's 16-bit buffer independently of the host locale, and leave the non-wide conversions on the host. Depends on boykopovar#5285.
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title is known to reach this. With the queue at 700+ open PRs, please hold off on new PRs that don't name a title needing the change until it's down. If a title stops on this on current main, reopen with the title ID and the log line.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants