-- v2: shlwapi: Output unrecognized format symbol in wvnsprintf(). shlwapi: Skip duplicate '#' in WPRINTF_ParseFormat(). shlwapi: Skip some spaces in WPRINTF_ParseFormat(). shlwapi: Handle ll in WPRINTF_ParseFormat(). shlwapi: Fix char width modifiers handling in WPRINTF_ParseFormat(). shlwapi: Handle repeated modifiers in WPRINTF_ParseFormat(). shlwapi/tests: Add some tests for printf format.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/shlwapi/tests/string.c | 109 ++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+)
diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index 8379a523733..b0562bda6e0 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -1689,6 +1689,114 @@ static void test_StrCatChainW(void) ok(buf[5] == 'e', "Expected buf[5] = 'e', got %x\n", buf[5]); }
+static void test_printf_format(void) +{ + const struct + { + const char *spec; + unsigned int arg_size; + const char *expected; + const WCHAR *expectedw; + ULONG64 arg; + const void *argw; + } + tests[] = + { + { "%qu", 0, "qu", NULL, 10 }, + { "%lu", sizeof(ULONG), "10", NULL, 10 }, + { "%#lx", sizeof(ULONG), "0xa", NULL, 10 }, + { "%hu", sizeof(ULONG), "10", NULL, 10 }, + { "%s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, + { "%S", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%ls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%lS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%hs", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, + { "%hS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, + { "%ws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%c", sizeof(SHORT), "\xc8", L"\x95c8", 0x95c8 }, + { "%lc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%C", sizeof(SHORT), "\x3f", L"\xc8", 0x95c8 }, + { "%lC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%hc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, + { "%I64u", sizeof(ULONG64), "10", NULL, 10 }, + { "%I64s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, + { "%q%u", sizeof(ULONG), "q10", NULL, 10 }, + }; + WCHAR ws[256], expectedw[256], specw[256]; + unsigned int i, j; + char expected[256], spec[256], s[256]; + int len; + + *s = 0; + WideCharToMultiByte(CP_ACP, 0, L"\x95c8", -1, s, ARRAY_SIZE(s), NULL, NULL); + if (strcmp(s, "\x3f")) + { + /* The test is not designed for testing locale but some of the test expected results depend on locale. */ + skip("An English locale is required for the printf tests.\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + strcpy(spec, tests[i].spec); + winetest_push_context("%s", spec); + strcat(spec,"|%s"); + *s = 0; + *ws = 0; + j = 0; + do + specw[j] = spec[j]; + while (specw[j++]); + switch (tests[i].arg_size) + { + case 0: + wnsprintfA(s, ARRAY_SIZE(s), spec, "end"); + if (tests[i].argw) + len = wnsprintfW(ws, ARRAY_SIZE(ws), specw, L"end"); + else + len = wnsprintfW(ws, ARRAY_SIZE(ws), specw, L"end"); + break; + case 1: + case 2: + case 4: + wnsprintfA(s, ARRAY_SIZE(s), spec, (ULONG)tests[i].arg, "end"); + if (tests[i].argw) + len = wnsprintfW(ws, ARRAY_SIZE(ws), specw, tests[i].argw, L"end"); + else + len = wnsprintfW(ws, ARRAY_SIZE(ws), specw, (ULONG)tests[i].arg, L"end"); + break; + case 8: + wnsprintfA(s, ARRAY_SIZE(s), spec, (ULONG64)tests[i].arg, "end"); + if (tests[i].argw) + len = wnsprintfW(ws, ARRAY_SIZE(ws), specw, tests[i].argw, L"end"); + else + len = wnsprintfW(ws, ARRAY_SIZE(ws), specw, (ULONG64)tests[i].arg, L"end"); + break; + default: + len = 0; + ok(0, "unknown length %u.\n", tests[i].arg_size); + break; + } + strcpy(expected, tests[i].expected); + strcat(expected, "|end"); + ok(len == strlen(expected), "got len %d, expected %Id.\n", len, strlen(expected)); + ok(!strcmp(s, expected), "got %s, expected %s.\n", debugstr_a(s), debugstr_a(expected)); + if (tests[i].expectedw) + { + wcscpy(expectedw, tests[i].expectedw); + wcscat(expectedw, L"|end"); + } + else + { + for (j = 0; j < len; ++j) + expectedw[j] = expected[j]; + } + expectedw[len] = 0; + ok(!wcscmp(ws, expectedw), "got %s, expected %s.\n", debugstr_w(ws), debugstr_w(expectedw)); + winetest_pop_context(); + } +} + START_TEST(string) { HMODULE hShlwapi; @@ -1777,6 +1885,7 @@ START_TEST(string) test_StrStrNW(); test_StrStrNIW(); test_StrCatChainW(); + test_printf_format();
CoUninitialize(); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/shlwapi/tests/string.c | 11 +++++++++++ dlls/shlwapi/wsprintf.c | 38 +++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index b0562bda6e0..9794b9b2024 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -1703,9 +1703,13 @@ static void test_printf_format(void) tests[] = { { "%qu", 0, "qu", NULL, 10 }, + { "%ll", 0, "", NULL, 10 }, { "%lu", sizeof(ULONG), "10", NULL, 10 }, { "%#lx", sizeof(ULONG), "0xa", NULL, 10 }, { "%hu", sizeof(ULONG), "10", NULL, 10 }, + { "%hhu", sizeof(ULONG), "10", NULL, 10 }, + { "%hwu", sizeof(ULONG), "10", NULL, 10 }, + { "%whu", sizeof(ULONG), "10", NULL, 10 }, { "%s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, { "%S", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, { "%ls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, @@ -1713,12 +1717,19 @@ static void test_printf_format(void) { "%hs", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, { "%hS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, { "%ws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%hhs", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, + { "%hhS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, + { "%wwws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, { "%c", sizeof(SHORT), "\xc8", L"\x95c8", 0x95c8 }, { "%lc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, { "%C", sizeof(SHORT), "\x3f", L"\xc8", 0x95c8 }, { "%lC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, { "%hc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, + { "%hhc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, + { "%hhhc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, { "%I64u", sizeof(ULONG64), "10", NULL, 10 }, + { "%llI64u", sizeof(ULONG64), "10", NULL, 10 }, + { "%I64llu", sizeof(ULONG64), "10", NULL, 10 }, { "%I64s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, { "%q%u", sizeof(ULONG), "q10", NULL, 10 }, }; diff --git a/dlls/shlwapi/wsprintf.c b/dlls/shlwapi/wsprintf.c index fbd2a7e75bf..ed385081821 100644 --- a/dlls/shlwapi/wsprintf.c +++ b/dlls/shlwapi/wsprintf.c @@ -110,14 +110,19 @@ static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res ) p++; } } - if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; } - else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; } - else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; } - else if (*p == 'I') + while (*p && strchr("lhwI", *p)) { - if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } - else if (p[1] == '3' && p[2] == '2') p += 3; - else { res->flags |= WPRINTF_INTPTR; p++; } + switch (*p) + { + case 'l': res->flags |= WPRINTF_LONG; ++p; break; + case 'I': + if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } + else if (p[1] == '3' && p[2] == '2') p += 3; + else { res->flags |= WPRINTF_INTPTR; p++; } + break; + case 'h': res->flags |= WPRINTF_SHORT; ++p; break; + case 'w': res->flags |= WPRINTF_WIDE; ++p; break; + } } switch(*p) { @@ -192,14 +197,19 @@ static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) p++; } } - if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; } - else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; } - else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; } - else if (*p == 'I') + while (*p && strchr("lhwI", *p)) { - if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } - else if (p[1] == '3' && p[2] == '2') p += 3; - else { res->flags |= WPRINTF_INTPTR; p++; } + switch (*p) + { + case 'l': res->flags |= WPRINTF_LONG; ++p; break; + case 'I': + if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } + else if (p[1] == '3' && p[2] == '2') p += 3; + else { res->flags |= WPRINTF_INTPTR; p++; } + break; + case 'h': res->flags |= WPRINTF_SHORT; ++p; break; + case 'w': res->flags |= WPRINTF_WIDE; ++p; break; + } } switch(*p) {
From: Paul Gofman pgofman@codeweavers.com
--- dlls/shlwapi/tests/string.c | 26 ++++++++++++++++++++++++++ dlls/shlwapi/wsprintf.c | 18 +++++++++--------- 2 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index 9794b9b2024..d176bc63019 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -1717,16 +1717,42 @@ static void test_printf_format(void) { "%hs", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, { "%hS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, { "%ws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%wS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, { "%hhs", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, { "%hhS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, + { "%wws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%wwS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, { "%wwws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%wwwS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%hws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%hwS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%whs", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%whS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%hwls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%hwlls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%hwlS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%hwllS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%lhws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%llhws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%lhwS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%llhwS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, { "%c", sizeof(SHORT), "\xc8", L"\x95c8", 0x95c8 }, { "%lc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%lllc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%lllllc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, { "%C", sizeof(SHORT), "\x3f", L"\xc8", 0x95c8 }, { "%lC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%lllC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%lllllC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, { "%hc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, { "%hhc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, { "%hhhc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, + { "%wc", sizeof(BYTE), "\x3f", L"\x95c8", 0x95c8 }, + { "%wC", sizeof(BYTE), "\x3f", L"\x95c8", 0x95c8 }, + { "%hwc", sizeof(BYTE), "\x3f", L"\xc8", 0x95c8 }, + { "%whc", sizeof(BYTE), "\x3f", L"\xc8", 0x95c8 }, + { "%hwC", sizeof(BYTE), "\x3f", L"\xc8", 0x95c8 }, + { "%whC", sizeof(BYTE), "\x3f", L"\xc8", 0x95c8 }, { "%I64u", sizeof(ULONG64), "10", NULL, 10 }, { "%llI64u", sizeof(ULONG64), "10", NULL, 10 }, { "%I64llu", sizeof(ULONG64), "10", NULL, 10 }, diff --git a/dlls/shlwapi/wsprintf.c b/dlls/shlwapi/wsprintf.c index ed385081821..eb64b5e3845 100644 --- a/dlls/shlwapi/wsprintf.c +++ b/dlls/shlwapi/wsprintf.c @@ -114,7 +114,7 @@ static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res ) { switch (*p) { - case 'l': res->flags |= WPRINTF_LONG; ++p; break; + case 'l': res->flags |= WPRINTF_LONG | WPRINTF_WIDE; ++p; break; case 'I': if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } else if (p[1] == '3' && p[2] == '2') p += 3; @@ -127,20 +127,20 @@ static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res ) switch(*p) { case 'c': - res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR; + res->type = (res->flags & WPRINTF_WIDE) ? WPR_WCHAR : WPR_CHAR; break; case 'C': - res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR; + res->type = (res->flags & (WPRINTF_SHORT | WPRINTF_WIDE)) == WPRINTF_SHORT ? WPR_CHAR : WPR_WCHAR; break; case 'd': case 'i': res->type = WPR_SIGNED; break; case 's': - res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING; + res->type = (res->flags & WPRINTF_WIDE) ? WPR_WSTRING : WPR_STRING; break; case 'S': - res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING; + res->type = (res->flags & (WPRINTF_SHORT | WPRINTF_WIDE)) == WPRINTF_SHORT ? WPR_STRING : WPR_WSTRING; break; case 'u': res->type = WPR_UNSIGNED; @@ -201,7 +201,7 @@ static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) { switch (*p) { - case 'l': res->flags |= WPRINTF_LONG; ++p; break; + case 'l': res->flags |= WPRINTF_LONG | WPRINTF_WIDE; ++p; break; case 'I': if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } else if (p[1] == '3' && p[2] == '2') p += 3; @@ -217,17 +217,17 @@ static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR; break; case 'C': - res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR; + res->type = (res->flags & (WPRINTF_SHORT | WPRINTF_WIDE)) == WPRINTF_WIDE ? WPR_WCHAR : WPR_CHAR; break; case 'd': case 'i': res->type = WPR_SIGNED; break; case 's': - res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING; + res->type = (res->flags & WPRINTF_SHORT) ? WPR_STRING : WPR_WSTRING; break; case 'S': - res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING; + res->type = (res->flags & (WPRINTF_SHORT | WPRINTF_WIDE)) == WPRINTF_WIDE ? WPR_WSTRING : WPR_STRING; break; case 'u': res->type = WPR_UNSIGNED;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/shlwapi/tests/string.c | 15 +++++++++++++++ dlls/shlwapi/wsprintf.c | 20 ++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index d176bc63019..6ff1fa75c7e 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -1705,15 +1705,26 @@ static void test_printf_format(void) { "%qu", 0, "qu", NULL, 10 }, { "%ll", 0, "", NULL, 10 }, { "%lu", sizeof(ULONG), "10", NULL, 10 }, + { "%llu", sizeof(ULONG64), "10", NULL, 10 }, + { "%lllllllu", sizeof(ULONG64), "10", NULL, 10 }, { "%#lx", sizeof(ULONG), "0xa", NULL, 10 }, + { "%#llx", sizeof(ULONG64), "0x1000000000", NULL, 0x1000000000 }, + { "%#lllx", sizeof(ULONG64), "0x1000000000", NULL, 0x1000000000 }, { "%hu", sizeof(ULONG), "10", NULL, 10 }, { "%hhu", sizeof(ULONG), "10", NULL, 10 }, { "%hwu", sizeof(ULONG), "10", NULL, 10 }, { "%whu", sizeof(ULONG), "10", NULL, 10 }, + { "%04lhlwllx", sizeof(ULONG64), "1000000010", NULL, 0x1000000010 }, { "%s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, { "%S", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, { "%ls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, { "%lS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%lls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, + { "%llS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, + { "%llls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%lllS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, + { "%lllls", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, + { "%llllS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, { "%hs", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, { "%hS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str" }, { "%ws", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str" }, @@ -1738,11 +1749,15 @@ static void test_printf_format(void) { "%llhwS", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, { "%c", sizeof(SHORT), "\xc8", L"\x95c8", 0x95c8 }, { "%lc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%llc", sizeof(SHORT), "\xc8", L"\x95c8", 0x95c8 }, { "%lllc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%llllc", sizeof(SHORT), "\xc8", L"\x95c8", 0x95c8 }, { "%lllllc", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, { "%C", sizeof(SHORT), "\x3f", L"\xc8", 0x95c8 }, { "%lC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%llC", sizeof(SHORT), "\x3f", L"\xc8", 0x95c8 }, { "%lllC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, + { "%llllC", sizeof(SHORT), "\x3f", L"\xc8", 0x95c8 }, { "%lllllC", sizeof(SHORT), "\x3f", L"\x95c8", 0x95c8 }, { "%hc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, { "%hhc", sizeof(BYTE), "\xc8", L"\xc8", 0x95c8 }, diff --git a/dlls/shlwapi/wsprintf.c b/dlls/shlwapi/wsprintf.c index eb64b5e3845..771c130be70 100644 --- a/dlls/shlwapi/wsprintf.c +++ b/dlls/shlwapi/wsprintf.c @@ -114,7 +114,15 @@ static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res ) { switch (*p) { - case 'l': res->flags |= WPRINTF_LONG | WPRINTF_WIDE; ++p; break; + case 'l': + ++p; + if (*p == 'l') + { + res->flags |= WPRINTF_I64; + ++p; + } + else res->flags |= WPRINTF_LONG | WPRINTF_WIDE; + break; case 'I': if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } else if (p[1] == '3' && p[2] == '2') p += 3; @@ -201,7 +209,15 @@ static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) { switch (*p) { - case 'l': res->flags |= WPRINTF_LONG | WPRINTF_WIDE; ++p; break; + case 'l': + ++p; + if (*p == 'l') + { + res->flags |= WPRINTF_I64; + ++p; + } + else res->flags |= WPRINTF_LONG | WPRINTF_WIDE; + break; case 'I': if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; } else if (p[1] == '3' && p[2] == '2') p += 3;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/shlwapi/tests/string.c | 5 +++++ dlls/shlwapi/wsprintf.c | 4 ++++ 2 files changed, 9 insertions(+)
diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index 6ff1fa75c7e..80811ab9683 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -1773,6 +1773,11 @@ static void test_printf_format(void) { "%I64llu", sizeof(ULONG64), "10", NULL, 10 }, { "%I64s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, { "%q%u", sizeof(ULONG), "q10", NULL, 10 }, + { "%u% ", sizeof(ULONG), "10", NULL, 10 }, + { "% ll u", 0, " u", NULL, 10 }, + { "% llu", sizeof(ULONG64), "10", NULL, 10 }, + { "%# llx", sizeof(ULONG64), "0xa", NULL, 10 }, + { "% #llx", sizeof(ULONG64), "0xa", NULL, 10 }, }; WCHAR ws[256], expectedw[256], specw[256]; unsigned int i, j; diff --git a/dlls/shlwapi/wsprintf.c b/dlls/shlwapi/wsprintf.c index 771c130be70..b4113d2d563 100644 --- a/dlls/shlwapi/wsprintf.c +++ b/dlls/shlwapi/wsprintf.c @@ -90,11 +90,13 @@ static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res ) { LPCSTR p = format;
+ while (*p == ' ') ++p; res->flags = 0; res->width = 0; res->precision = 0; if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; } if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } + while (*p == ' ') ++p; if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; } while ((*p >= '0') && (*p <= '9')) /* width field */ { @@ -185,11 +187,13 @@ static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) { LPCWSTR p = format;
+ while (*p == ' ') ++p; res->flags = 0; res->width = 0; res->precision = 0; if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; } if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } + while (*p == ' ') ++p; if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; } while ((*p >= '0') && (*p <= '9')) /* width field */ {
From: Paul Gofman pgofman@codeweavers.com
--- dlls/shlwapi/tests/string.c | 2 ++ dlls/shlwapi/wsprintf.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index 80811ab9683..a407d3e1bd1 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -1714,6 +1714,8 @@ static void test_printf_format(void) { "%hhu", sizeof(ULONG), "10", NULL, 10 }, { "%hwu", sizeof(ULONG), "10", NULL, 10 }, { "%whu", sizeof(ULONG), "10", NULL, 10 }, + { "%##lhllwlx", sizeof(ULONG64), "0x1000000010", NULL, 0x1000000010 }, + { "%##lhlwlx", sizeof(ULONG), "0x10", NULL, 0x1000000010 }, { "%04lhlwllx", sizeof(ULONG64), "1000000010", NULL, 0x1000000010 }, { "%s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, { "%S", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)L"str", "str" }, diff --git a/dlls/shlwapi/wsprintf.c b/dlls/shlwapi/wsprintf.c index b4113d2d563..abf217e9474 100644 --- a/dlls/shlwapi/wsprintf.c +++ b/dlls/shlwapi/wsprintf.c @@ -95,7 +95,7 @@ static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res ) res->width = 0; res->precision = 0; if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; } - if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } + while (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } while (*p == ' ') ++p; if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; } while ((*p >= '0') && (*p <= '9')) /* width field */ @@ -192,7 +192,7 @@ static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) res->width = 0; res->precision = 0; if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; } - if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } + while (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } while (*p == ' ') ++p; if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; } while ((*p >= '0') && (*p <= '9')) /* width field */
From: Paul Gofman pgofman@codeweavers.com
--- dlls/shlwapi/tests/string.c | 2 ++ dlls/shlwapi/wsprintf.c | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index a407d3e1bd1..69983e827b3 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -1775,7 +1775,9 @@ static void test_printf_format(void) { "%I64llu", sizeof(ULONG64), "10", NULL, 10 }, { "%I64s", sizeof(ULONG_PTR), "str", NULL, (ULONG_PTR)"str", L"str" }, { "%q%u", sizeof(ULONG), "q10", NULL, 10 }, + { "%lhw%u", 0, "%u", NULL, 10 }, { "%u% ", sizeof(ULONG), "10", NULL, 10 }, + { "%u% %u", sizeof(ULONG), "10%u", NULL, 10 }, { "% ll u", 0, " u", NULL, 10 }, { "% llu", sizeof(ULONG64), "10", NULL, 10 }, { "%# llx", sizeof(ULONG64), "0xa", NULL, 10 }, diff --git a/dlls/shlwapi/wsprintf.c b/dlls/shlwapi/wsprintf.c index abf217e9474..daff024d9c3 100644 --- a/dlls/shlwapi/wsprintf.c +++ b/dlls/shlwapi/wsprintf.c @@ -483,6 +483,7 @@ INT WINAPI wvnsprintfA( LPSTR buffer, INT maxlen, LPCSTR spec, va_list args ) p += len - sign; break; case WPR_UNKNOWN: + if (*spec) *p++ = *spec++; continue; } if (format.flags & WPRINTF_LEFTALIGN) @@ -603,6 +604,7 @@ INT WINAPI wvnsprintfW( LPWSTR buffer, INT maxlen, LPCWSTR spec, va_list args ) for (i = sign; i < len; i++) *p++ = (BYTE)number[i]; break; case WPR_UNKNOWN: + if (*spec) *p++ = *spec++; continue; } if (format.flags & WPRINTF_LEFTALIGN)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=148941
Your paranoid android.
=== w7u_el (32 bit report) ===
shlwapi: string.c:1856: Test failed: %C: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %llC: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %llllC: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %hc: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %hhc: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %hhhc: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %hwc: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %whc: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %hwC: got L"\0398|end", expected L"\00c8|end". string.c:1856: Test failed: %whC: got L"\0398|end", expected L"\00c8|end".
=== w10pro64_ar (64 bit report) ===
shlwapi: string.c:1856: Test failed: %C: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %llC: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %llllC: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hhc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hhhc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hwc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %whc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hwC: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %whC: got L"\0628|end", expected L"\00c8|end".
=== w10pro64_ja (64 bit report) ===
shlwapi: string.c:1856: Test failed: %C: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %llC: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %llllC: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hhc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hhhc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hwc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %whc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hwC: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %whC: got L"\ff88|end", expected L"\00c8|end".
=== debian11 (32 bit ar:MA report) ===
shlwapi: string.c:1856: Test failed: %C: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %llC: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %llllC: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hhc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hhhc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hwc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %whc: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %hwC: got L"\0628|end", expected L"\00c8|end". string.c:1856: Test failed: %whC: got L"\0628|end", expected L"\00c8|end".
=== debian11 (32 bit he:IL report) ===
shlwapi: string.c:1856: Test failed: %C: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %llC: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %llllC: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %hc: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %hhc: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %hhhc: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %hwc: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %whc: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %hwC: got L"\05b8|end", expected L"\00c8|end". string.c:1856: Test failed: %whC: got L"\05b8|end", expected L"\00c8|end".
=== debian11 (32 bit ja:JP report) ===
shlwapi: string.c:1856: Test failed: %C: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %llC: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %llllC: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hhc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hhhc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hwc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %whc: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %hwC: got L"\ff88|end", expected L"\00c8|end". string.c:1856: Test failed: %whC: got L"\ff88|end", expected L"\00c8|end".