ctest for int format specifiers and usage doc
This commit is contained in:
parent
f71b6b46e8
commit
ab0408ae5e
@ -665,8 +665,7 @@ static void terminate_pending_irp_threads(SERIAL_DEVICE* serial)
|
||||
}
|
||||
|
||||
CloseHandle(irpThread);
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "IRP thread terminated, CompletionId %"PRIuz"",
|
||||
id);
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "IRP thread terminated, CompletionId %p", (void*) id);
|
||||
}
|
||||
|
||||
ListDictionary_Clear(serial->IrpThreads);
|
||||
|
131
docs/PrintFormatSpecifiers.md
Normal file
131
docs/PrintFormatSpecifiers.md
Normal file
@ -0,0 +1,131 @@
|
||||
# Print Format Specifiers
|
||||
|
||||
## Lookup Table
|
||||
|
||||
We use the following format specifiers for all \*printf\* and WLog_* functions:
|
||||
|
||||
| Type | signed | unsigned | octal | hex | HEX |
|
||||
| ------------------ | --------- | --------- | --------- | --------- | --------- |
|
||||
| signed char | %hhd | | | | |
|
||||
| unsigned char | | %hhu | %hho | %hhx | %hhX |
|
||||
| short | %hd | | | | |
|
||||
| unsigned short | | %hu | %ho | %hx | %hX |
|
||||
| int | %d | | | | |
|
||||
| unsigned int | | %u | %o | %x | %X |
|
||||
| long | %ld | | | | |
|
||||
| unsigned long | | %lu | %lo | %lx | %lX |
|
||||
| long long | %lld | | | | |
|
||||
| unsigned long long | | %llu | %llo | %llx | %llX |
|
||||
| size_t | | %"PRIuz" | %"PRIoz" | %"PRIxz" | %"PRIXz" |
|
||||
| INT8 | %"PRId8" | | | | |
|
||||
| UINT8 | | %"PRIu8" | %"PRIo8" | %"PRIx8" | %"PRIX8" |
|
||||
| BOOLEAN | | %"PRIu8" | %"PRIo8" | %"PRIx8" | %"PRIX8" |
|
||||
| BYTE | | %"PRIu8" | %"PRIo8" | %"PRIx8" | %"PRIX8" |
|
||||
| CHAR | %"PRId8" | | | | |
|
||||
| UCHAR | | %"PRIu8" | %"PRIo8" | %"PRIx8" | %"PRIX8" |
|
||||
| INT16 | %"PRId16" | | | | |
|
||||
| UINT16 | | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
|
||||
| WORD | | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
|
||||
| WCHAR | | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
|
||||
| SHORT | %"PRId16" | | | | |
|
||||
| USHORT | | %"PRIu16" | %"PRIo16" | %"PRIx16" | %"PRIX16" |
|
||||
| INT32 | %"PRId32" | | | | |
|
||||
| UINT32 | | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
|
||||
| INT | %"PRId32" | | | | |
|
||||
| UINT | | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
|
||||
| LONG | %"PRId32" | | | | |
|
||||
| HRESULT | %"PRId32" | | | %"PRIx32" | %"PRIX32" |
|
||||
| NTSTATUS | %"PRId32" | | | %"PRIx32" | %"PRIX32" |
|
||||
| ULONG | | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
|
||||
| DWORD | | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
|
||||
| DWORD32 | | %"PRIu32" | %"PRIo32" | %"PRIx32" | %"PRIX32" |
|
||||
| BOOL | %"PRId32" | | | | |
|
||||
| INT64 | %"PRId64" | | | | |
|
||||
| LONG64 | %"PRId64" | | | | |
|
||||
| LONGLONG | %"PRId64" | | | | |
|
||||
| UINT64 | | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
|
||||
| ULONG64 | | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
|
||||
| ULONGLONG | | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
|
||||
| DWORDLONG | | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
|
||||
| QWORD | | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
|
||||
| ULONG64 | | %"PRIu64" | %"PRIo64" | %"PRIx64" | %"PRIX64" |
|
||||
|
||||
|
||||
## Pointers
|
||||
|
||||
When printing pointers you should cast the argument to ``(void*)``:
|
||||
|
||||
```c
|
||||
rdpContext *pContext;
|
||||
fprintf(stderr, "rdp context is %p\n", (void*) pContext);
|
||||
```
|
||||
|
||||
If you need more formatting options cast the pointer argument to `size_t` and use
|
||||
any %"PRI*z" format specifier:
|
||||
|
||||
```c
|
||||
rdpContext *pContext;
|
||||
fprintf(stderr, "rdp context is %" PRIuz " (0x%" PRIXz ")\n", (size_t) pContext, (size_t) pContext);
|
||||
```
|
||||
|
||||
|
||||
## Integer Promotion
|
||||
|
||||
Remember that integer types smaller than int are promoted when an operation is
|
||||
performed on them.
|
||||
|
||||
Wrong:
|
||||
|
||||
```c
|
||||
UINT8 a, b;
|
||||
fprintf(stderr, "a - b is %" PRIu8 "\n", a - b);
|
||||
// depending on the system's PRIu8 definition you might get:
|
||||
// warning: format specifies type 'unsigned char' but the argument has type 'int'
|
||||
```
|
||||
|
||||
Correct:
|
||||
|
||||
```c
|
||||
UINT8 a, b;
|
||||
fprintf(stderr, "a - b is %d\n", a - b);
|
||||
// or ...
|
||||
fprintf(stderr, "a - b is %" PRIu8 "\n", (UINT8) (a - b));
|
||||
```
|
||||
|
||||
## TCHAR
|
||||
|
||||
When using `_tprintf` or similar TCHAR formatting functions or macros you
|
||||
need to enclose the PRI format defines:
|
||||
|
||||
```c
|
||||
LPCTSTR lpFileName1;
|
||||
UINT64 fileSize1;
|
||||
|
||||
_tprintf(_T("The size of %s is %") _T(PRIu64) _T("\n"), lpFileName1, fileSize1);
|
||||
```
|
||||
|
||||
Since this makes the strings a lot harder to read try to avoid _tprintf if the
|
||||
arguments don't contain TCHAR types.
|
||||
|
||||
Note: If all compilers were C99 compliant we could simply write ...
|
||||
|
||||
```c
|
||||
_tprintf(_T("The size of %s is %") PRIu64 "\n"), lpFileName1, fileSize1);
|
||||
```
|
||||
|
||||
... since the standard says that only one of the character sequences must be
|
||||
prefixed by an encoding prefix and the rest of them are treated to have the
|
||||
same. However, Microsoft Visual Studio versions older than VS 2015 are not C99
|
||||
compliant in this regard.
|
||||
|
||||
See [How to use stdint types with _tprintf in Visual Studio 2013](http://stackoverflow.com/questions/41126081/how-to-use-stdint-types-with-tprintf-in-visual-studio-2013)
|
||||
for more information.
|
||||
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
- [[MS-DTYP] 2.2 Common Data Types](https://msdn.microsoft.com/en-us/library/cc230309.aspx)
|
||||
- [Understand integer conversion rules](https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+rules)
|
||||
- [Printf format strings](https://en.wikipedia.org/wiki/Printf_format_string)
|
||||
- [C data types - Basic Types](https://en.wikipedia.org/wiki/C_data_types#Basic_types)
|
@ -382,7 +382,7 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form
|
||||
body = strstr(pSrcData, "<BODY");
|
||||
|
||||
/* StartHTML */
|
||||
sprintf_s(num, sizeof(num), "%010lu", strlen(pDstData));
|
||||
sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
|
||||
CopyMemory(&pDstData[23], num, 10);
|
||||
|
||||
if (!body)
|
||||
@ -391,12 +391,12 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form
|
||||
strcat(pDstData, "<!--StartFragment-->");
|
||||
|
||||
/* StartFragment */
|
||||
sprintf_s(num, sizeof(num), "%010lu", strlen(pDstData));
|
||||
sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
|
||||
CopyMemory(&pDstData[69], num, 10);
|
||||
strcat(pDstData, pSrcData);
|
||||
|
||||
/* EndFragment */
|
||||
sprintf_s(num, sizeof(num), "%010lu", strlen(pDstData));
|
||||
sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
|
||||
CopyMemory(&pDstData[93], num, 10);
|
||||
strcat(pDstData, "<!--EndFragment-->");
|
||||
|
||||
@ -404,7 +404,7 @@ static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 form
|
||||
strcat(pDstData, "</BODY></HTML>");
|
||||
|
||||
/* EndHTML */
|
||||
sprintf_s(num, sizeof(num), "%010lu", strlen(pDstData));
|
||||
sprintf_s(num, sizeof(num), "%010"PRIuz"", strlen(pDstData));
|
||||
CopyMemory(&pDstData[43], num, 10);
|
||||
|
||||
*pSize = (UINT32) strlen(pDstData) + 1;
|
||||
|
@ -6,6 +6,7 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestTypes.c
|
||||
TestFormatSpecifiers.c
|
||||
TestAlignment.c
|
||||
TestString.c
|
||||
TestUnicodeConversion.c)
|
||||
|
155
winpr/libwinpr/crt/test/TestFormatSpecifiers.c
Normal file
155
winpr/libwinpr/crt/test/TestFormatSpecifiers.c
Normal file
@ -0,0 +1,155 @@
|
||||
#include <stdio.h>
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/string.h>
|
||||
|
||||
|
||||
int TestFormatSpecifiers(int argc, char* argv[])
|
||||
{
|
||||
unsigned errors = 0;
|
||||
|
||||
char fmt[4096];
|
||||
|
||||
/* size_t */
|
||||
{
|
||||
size_t arg = 0xabcd;
|
||||
const char *chk = "uz:43981 oz:125715 xz:abcd Xz:ABCD";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"uz:%" PRIuz " oz:%" PRIoz " xz:%" PRIxz " Xz:%" PRIXz"", arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed size_t test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT8 */
|
||||
{
|
||||
INT8 arg = -16;
|
||||
const char *chk = "d8:-16 x8:f0 X8:F0";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"d8:%" PRId8 " x8:%" PRIx8 " X8:%" PRIX8"", arg, (UINT8) arg, (UINT8) arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed INT8 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT8 */
|
||||
{
|
||||
UINT8 arg = 0xFE;
|
||||
const char *chk = "u8:254 o8:376 x8:fe X8:FE";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"u8:%" PRIu8 " o8:%" PRIo8 " x8:%" PRIx8 " X8:%" PRIX8"", arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed UINT8 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT16 */
|
||||
{
|
||||
INT16 arg = -16;
|
||||
const char *chk = "d16:-16 x16:fff0 X16:FFF0";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"d16:%" PRId16 " x16:%" PRIx16 " X16:%" PRIX16"", arg, (UINT16) arg, (UINT16) arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed INT16 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT16 */
|
||||
{
|
||||
UINT16 arg = 0xFFFE;
|
||||
const char *chk = "u16:65534 o16:177776 x16:fffe X16:FFFE";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"u16:%" PRIu16 " o16:%" PRIo16 " x16:%" PRIx16 " X16:%" PRIX16"", arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed UINT16 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT32 */
|
||||
{
|
||||
INT32 arg = -16;
|
||||
const char *chk = "d32:-16 x32:fffffff0 X32:FFFFFFF0";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"d32:%" PRId32 " x32:%" PRIx32 " X32:%" PRIX32"", arg, (UINT32) arg, (UINT32) arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed INT32 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT32 */
|
||||
{
|
||||
UINT32 arg = 0xFFFFFFFE;
|
||||
const char *chk = "u32:4294967294 o32:37777777776 x32:fffffffe X32:FFFFFFFE";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"u32:%" PRIu32 " o32:%" PRIo32 " x32:%" PRIx32 " X32:%" PRIX32"", arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed UINT16 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* INT64 */
|
||||
{
|
||||
INT64 arg = -16;
|
||||
const char *chk = "d64:-16 x64:fffffffffffffff0 X64:FFFFFFFFFFFFFFF0";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"d64:%" PRId64 " x64:%" PRIx64 " X64:%" PRIX64"", arg, (UINT64) arg, (UINT64) arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed INT64 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* UINT64 */
|
||||
{
|
||||
UINT64 arg = 0xFFFFFFFFFFFFFFFE;
|
||||
const char *chk = "u64:18446744073709551614 o64:1777777777777777777776 x64:fffffffffffffffe X64:FFFFFFFFFFFFFFFE";
|
||||
|
||||
sprintf_s(fmt, sizeof(fmt),
|
||||
"u64:%" PRIu64 " o64:%" PRIo64 " x64:%016" PRIx64 " X64:%016" PRIX64"", arg, arg, arg, arg);
|
||||
|
||||
if (strcmp(fmt, chk))
|
||||
{
|
||||
fprintf(stderr, "%s failed UINT64 test: got [%s] instead of [%s]\n", __FUNCTION__, fmt, chk);
|
||||
errors ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors)
|
||||
{
|
||||
fprintf(stderr, "%s produced %u errors\n", __FUNCTION__, errors);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ int TestGetNativeSystemInfo(int argc, char* argv[])
|
||||
printf("\tdwPageSize: 0x%08"PRIX32"\n", sysinfo.dwPageSize);
|
||||
printf("\tlpMinimumApplicationAddress: %p\n", sysinfo.lpMinimumApplicationAddress);
|
||||
printf("\tlpMaximumApplicationAddress: %p\n", sysinfo.lpMaximumApplicationAddress);
|
||||
printf("\tdwActiveProcessorMask: 0x%08"PRIXz"\n", sysinfo.dwActiveProcessorMask);
|
||||
printf("\tdwActiveProcessorMask: %p\n", (void*) sysinfo.dwActiveProcessorMask);
|
||||
printf("\tdwNumberOfProcessors: %"PRIu32"\n", sysinfo.dwNumberOfProcessors);
|
||||
printf("\tdwProcessorType: %"PRIu32"\n", sysinfo.dwProcessorType);
|
||||
printf("\tdwAllocationGranularity: %"PRIu32"\n", sysinfo.dwAllocationGranularity);
|
||||
|
Loading…
Reference in New Issue
Block a user