fix(libc): translate Windows fscanf guest arguments
This commit is contained in:
parent
5b359092d8
commit
73facbc3d1
|
|
@ -7,8 +7,9 @@
|
|||
|
||||
namespace LibcDetail {
|
||||
|
||||
inline int ScanWindows(const char* input, const char* format, const void* source) {
|
||||
if (!input || !format || !source) { errno = 22; return EOF; }
|
||||
template <typename TScanner>
|
||||
inline int ScanWindowsArguments_nid_no_patch(const char* format, const void* source, TScanner scan) {
|
||||
if (!format || !source) { errno = 22; return EOF; }
|
||||
std::string translated;
|
||||
std::vector<void*> pointers;
|
||||
FormatArguments args(source);
|
||||
|
|
@ -45,7 +46,21 @@ inline int ScanWindows(const char* input, const char* format, const void* source
|
|||
}
|
||||
if (!suppressed) pointers.push_back(args.Next<void*>());
|
||||
}
|
||||
return std::vsscanf(input, translated.c_str(), reinterpret_cast<char*>(pointers.data()));
|
||||
return scan(translated.c_str(), reinterpret_cast<char*>(pointers.data()));
|
||||
}
|
||||
|
||||
inline int ScanWindows(const char* input, const char* format, const void* source) {
|
||||
if (!input) { errno = 22; return EOF; }
|
||||
return ScanWindowsArguments_nid_no_patch(format, source, [input](const char* translated, char* pointers) {
|
||||
return std::vsscanf(input, translated, pointers);
|
||||
});
|
||||
}
|
||||
|
||||
inline int ScanFileWindows_nid_no_patch(std::FILE* stream, const char* format, const void* source) {
|
||||
if (!stream) { errno = 22; return EOF; }
|
||||
return ScanWindowsArguments_nid_no_patch(format, source, [stream](const char* translated, char* pointers) {
|
||||
return std::vfscanf(stream, translated, pointers);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ int APS5_VABI fscanf_nid_postfix(FileStream* stream, const char* format, ...) {
|
|||
#ifdef _WIN32
|
||||
__builtin_sysv_va_list args;
|
||||
__builtin_sysv_va_start(args, format);
|
||||
const int result = std::vfscanf(native, format, *reinterpret_cast<std::va_list*>(args));
|
||||
const int result = LibcDetail::ScanFileWindows_nid_no_patch(native, format, args);
|
||||
__builtin_sysv_va_end(args);
|
||||
#else
|
||||
std::va_list args;
|
||||
|
|
|
|||
|
|
@ -168,15 +168,41 @@ int main() {
|
|||
FileStream scanned(std::tmpfile());
|
||||
Require(fprintf_nid_postfix(&scanned, "%d %s", 42, "answer") == 9);
|
||||
std::rewind(scanned.GetHandle());
|
||||
#ifndef _WIN32
|
||||
Require(fscanf_nid_postfix(&scanned, "%*d") == 0);
|
||||
Require(ftello_nid_postfix(&scanned) == 2);
|
||||
std::rewind(scanned.GetHandle());
|
||||
int scannedNumber = 0;
|
||||
char scannedWord[16]{};
|
||||
std::fputs("fscanf: suppressed conversion passed; assigning register arguments\n", stderr);
|
||||
std::fflush(stderr);
|
||||
Require(fscanf_nid_postfix(&scanned, "%d %15s", &scannedNumber, scannedWord) == 2);
|
||||
Require(scannedNumber == 42 && std::strcmp(scannedWord, "answer") == 0);
|
||||
Require(fscanf_nid_postfix(&scanned, "%d", &scannedNumber) == EOF);
|
||||
#endif
|
||||
Require(feof_nid_postfix(&scanned) && (scanned.GuestState().flags & 0x20));
|
||||
scanned.Close();
|
||||
|
||||
FileStream scanMany(std::tmpfile());
|
||||
Require(std::fputs("7 1 2 3 4 5 6 7 8 4294967297 -4294967298 4294967299 abc %!", scanMany.GetHandle()) >= 0);
|
||||
std::rewind(scanMany.GetHandle());
|
||||
int numbers[8]{};
|
||||
std::int64_t large = 0, negative = 0;
|
||||
std::uint64_t sized = 0;
|
||||
char letters[4]{};
|
||||
std::int64_t consumed = -1;
|
||||
Require(fscanf_nid_postfix(&scanMany, "%*d %d %d %d %d %d %d %d %d %ld %jd %zu %3[a-z] %%%ln",
|
||||
&numbers[0], &numbers[1], &numbers[2], &numbers[3], &numbers[4], &numbers[5], &numbers[6], &numbers[7],
|
||||
&large, &negative, &sized, letters, &consumed) == 12);
|
||||
for (int i = 0; i < 8; ++i) Require(numbers[i] == i + 1);
|
||||
Require(large == INT64_C(4294967297) && negative == -INT64_C(4294967298) && sized == UINT64_C(4294967299));
|
||||
Require(std::strcmp(letters, "abc") == 0 && consumed == ftello_nid_postfix(&scanMany));
|
||||
Require(fgetc_nid_postfix(&scanMany) == '!');
|
||||
int unmatched = 123;
|
||||
Require(fseeko_nid_postfix(&scanMany, -1, SEEK_CUR) == 0);
|
||||
Require(fscanf_nid_postfix(&scanMany, "%d", &unmatched) == 0 && unmatched == 123);
|
||||
Require(fgetc_nid_postfix(&scanMany) == '!');
|
||||
Require(fscanf_nid_postfix(&scanMany, "%d", &unmatched) == EOF && unmatched == 123);
|
||||
scanMany.Close();
|
||||
|
||||
FileStream positioned(std::tmpfile());
|
||||
constexpr std::int64_t largeOffset = INT64_C(4294967313);
|
||||
Require(fseeko_nid_postfix(&positioned, largeOffset, SEEK_SET) == 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue