feat(libc): expose guest vsprintf formatting
This commit is contained in:
parent
6cdf4a5be1
commit
f37fffdacd
|
|
@ -152,6 +152,14 @@ int APS5_VABI vprintf_nid_postfix(const char* str, VaList* c) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int APS5_VABI vsprintf_nid_postfix(char* str, const char* format, VaList* args) {
|
||||
#ifdef _WIN32
|
||||
return LibcDetail::FormatWindows(str, SIZE_MAX, format, args);
|
||||
#else
|
||||
return std::vsprintf(str, format, *reinterpret_cast<std::va_list*>(args));
|
||||
#endif
|
||||
}
|
||||
|
||||
int APS5_VABI vsnprintf_nid_postfix(char* str, size_t size, const char* format, VaList* c) {
|
||||
#ifdef _WIN32
|
||||
return LibcDetail::FormatWindows(str, size, format, c);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ extern FileStream* __stderrp_nid_postfix;
|
|||
extern int __isthreaded_nid_postfix;
|
||||
int APS5_VABI fprintf_nid_postfix(FileStream*, const char*, ...);
|
||||
int APS5_VABI vfprintf_nid_postfix(FileStream*, const char*, void*);
|
||||
int APS5_VABI vsprintf_nid_postfix(char*, const char*, void*);
|
||||
int APS5_VABI fgetc_nid_postfix(FileStream*);
|
||||
int APS5_VABI fputc_nid_postfix(int, FileStream*);
|
||||
int APS5_VABI __srget_nid_postfix(FileStream*);
|
||||
|
|
@ -48,7 +49,35 @@ static int APS5_VABI WriteFormatted(FileStream* stream, const char* format, ...)
|
|||
#endif
|
||||
return result;
|
||||
}
|
||||
static int APS5_VABI FormatString(char* buffer, const char* format, ...) {
|
||||
#ifdef _WIN32
|
||||
__builtin_sysv_va_list args;
|
||||
__builtin_sysv_va_start(args, format);
|
||||
#else
|
||||
std::va_list args;
|
||||
va_start(args, format);
|
||||
#endif
|
||||
const int result = vsprintf_nid_postfix(buffer, format, args);
|
||||
#ifdef _WIN32
|
||||
__builtin_sysv_va_end(args);
|
||||
#else
|
||||
va_end(args);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
int main() {
|
||||
char stringOutput[256];
|
||||
std::memset(stringOutput, '!', sizeof(stringOutput));
|
||||
std::int64_t count = -1;
|
||||
const char expectedString[] = "guest:4294967297: 3.50:1,2,3,4,5,6,7,8:%";
|
||||
const int written = FormatString(stringOutput, "%s:%ld:%*.*f:%d,%d,%d,%d,%d,%d,%d,%d:%%%ln",
|
||||
"guest", std::int64_t{4294967297}, 6, 2, 3.5, 1, 2, 3, 4, 5, 6, 7, 8, &count);
|
||||
Require(written == sizeof(expectedString) - 1 && count == written);
|
||||
Require(std::strcmp(stringOutput, expectedString) == 0 && stringOutput[written + 1] == '!');
|
||||
Require(FormatString(stringOutput, "%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.2Lf",
|
||||
1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 1.25L) == 25);
|
||||
Require(std::strcmp(stringOutput, "1 2 3 4 5 6 7 8 9 10 1.25") == 0);
|
||||
Require(FormatString(stringOutput, "") == 0 && stringOutput[0] == '\0');
|
||||
Require(__isthreaded_nid_postfix == 1);
|
||||
Require(__stdoutp_nid_postfix == &_Stdout_nid_postfix);
|
||||
Require(__stderrp_nid_postfix == &_Stderr_nid_postfix);
|
||||
|
|
|
|||
|
|
@ -541,3 +541,19 @@ empty and singleton arrays, and unchanged input bytes. All twenty-nine tests
|
|||
have passed (the new test was rerun after correcting its padding-byte snapshot).
|
||||
The unchanged game resolves bsearch and stops at `jbz9I9vkqkk` (`vsprintf`),
|
||||
still before guest entry with exit `0xc0000139`.
|
||||
|
||||
## Follow-up: unbounded varargs formatting
|
||||
|
||||
Added vsprintf through the existing guest varargs formatter on Windows and the
|
||||
native SysV va_list path on Linux. The caller remains responsible for buffer
|
||||
capacity, as with the C interface. Windows tests cover mixed integer/string/
|
||||
floating arguments, guest 64-bit long, width and precision arguments, register
|
||||
overflow onto the stack, long double, percent escapes, count writes, empty
|
||||
output, termination, and the byte immediately after the output. The formatter's
|
||||
existing unsupported conversions still fail explicitly; this does not establish
|
||||
complete printf compatibility or Linux runtime validation.
|
||||
|
||||
All twenty-nine CTest cases pass. The unchanged Quake II executable now resolves
|
||||
vsprintf and stops at `Jc6E7N+dHz0` (`system`), before guest entry, with exit
|
||||
`0xc0000139`. No game frame has been rendered. Upstream was fetched again and
|
||||
had no new commits to merge.
|
||||
|
|
|
|||
Loading…
Reference in New Issue