mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2025-12-18 23:11:11 +08:00
Support long and long long types in TEST_PRINTF
This change helps Unity parse and print correctly in cases where a long
or long long type is passed to TEST_PRINTF.
Example situations:
```C
// With %u:
TEST_PRINTF("%u %d\n", ((1ULL << 63) - 1), 5); // --> prints 11982546 -1 (both arguments incorrect because only 4 of the 8 bytes were read out of the va_list)
// With %llu, UNITY_SUPPORT_64=0
TEST_PRINTF("%llu %d\n", ((1ULL << 63) - 1), 5); // --> prints 4294967295 5 (first argument wrapped, second argument intact)
// With %llu, UNITY_SUPPORT_64=1
TEST_PRINTF("%llu %d\n", ((1ULL << 63) - 1), 5); // --> prints 9223372036854775807 5 (both arguments correct)
```
This commit is contained in:
@@ -240,7 +240,7 @@ _Example:_
|
||||
Unity provides a simple (and very basic) printf-like string output implementation, which is able to print a string modified by the following format string modifiers:
|
||||
|
||||
- __%d__ - signed value (decimal)
|
||||
- __%i__ - same as __%i__
|
||||
- __%i__ - same as __%d__
|
||||
- __%u__ - unsigned value (decimal)
|
||||
- __%f__ - float/Double (if float support is activated)
|
||||
- __%g__ - same as __%f__
|
||||
@@ -252,6 +252,15 @@ Unity provides a simple (and very basic) printf-like string output implementatio
|
||||
- __%s__ - a string (e.g. "string")
|
||||
- __%%__ - The "%" symbol (escaped)
|
||||
|
||||
Length specifiers are also supported. If you are using long long types, make sure UNITY_SUPPORT_64 is true to ensure they are printed correctly.
|
||||
|
||||
- __%ld__ - signed long value (decimal)
|
||||
- __%lld__ - signed long long value (decimal)
|
||||
- __%lu__ - unsigned long value (decimal)
|
||||
- __%llu__ - unsigned long long value (decimal)
|
||||
- __%lx__ - unsigned long value (hexadecimal)
|
||||
- __%llx__ - unsigned long long value (hexadecimal)
|
||||
|
||||
_Example:_
|
||||
|
||||
```C
|
||||
@@ -267,6 +276,7 @@ TEST_PRINTF("Pointer %p\n", &a);
|
||||
TEST_PRINTF("Character %c\n", 'F');
|
||||
TEST_PRINTF("String %s\n", "My string");
|
||||
TEST_PRINTF("Percent %%\n");
|
||||
TEST_PRINTF("Unsigned long long %llu\n", 922337203685477580);
|
||||
TEST_PRINTF("Color Red \033[41mFAIL\033[0m\n");
|
||||
TEST_PRINTF("\n");
|
||||
TEST_PRINTF("Multiple (%d) (%i) (%u) (%x)\n", -100, 0, 200, 0x12345);
|
||||
|
||||
113
src/unity.c
113
src/unity.c
@@ -1823,10 +1823,96 @@ UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_INCLUDE_PRINT_FORMATTED
|
||||
|
||||
/*-----------------------------------------------
|
||||
* printf length modifier helpers
|
||||
*-----------------------------------------------*/
|
||||
|
||||
enum UnityLengthModifier {
|
||||
UNITY_LENGTH_MODIFIER_NONE,
|
||||
UNITY_LENGTH_MODIFIER_LONG_LONG,
|
||||
UNITY_LENGTH_MODIFIER_LONG,
|
||||
};
|
||||
|
||||
#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \
|
||||
do { \
|
||||
switch (LENGTH_MOD) \
|
||||
{ \
|
||||
case UNITY_LENGTH_MODIFIER_LONG_LONG: \
|
||||
{ \
|
||||
NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \
|
||||
break; \
|
||||
} \
|
||||
case UNITY_LENGTH_MODIFIER_LONG: \
|
||||
{ \
|
||||
NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \
|
||||
break; \
|
||||
} \
|
||||
case UNITY_LENGTH_MODIFIER_NONE: \
|
||||
default: \
|
||||
{ \
|
||||
NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length)
|
||||
{
|
||||
enum UnityLengthModifier length_mod;
|
||||
switch (pch[0])
|
||||
{
|
||||
case 'l':
|
||||
{
|
||||
if (pch[1] == 'l')
|
||||
{
|
||||
*length = 2;
|
||||
length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG;
|
||||
}
|
||||
else
|
||||
{
|
||||
*length = 1;
|
||||
length_mod = UNITY_LENGTH_MODIFIER_LONG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
{
|
||||
// short and char are converted to int
|
||||
length_mod = UNITY_LENGTH_MODIFIER_NONE;
|
||||
if (pch[1] == 'h')
|
||||
{
|
||||
*length = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*length = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'j':
|
||||
case 'z':
|
||||
case 't':
|
||||
case 'L':
|
||||
{
|
||||
// Not supported, but should gobble up the length specifier anyway
|
||||
length_mod = UNITY_LENGTH_MODIFIER_NONE;
|
||||
*length = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
length_mod = UNITY_LENGTH_MODIFIER_NONE;
|
||||
*length = 0;
|
||||
}
|
||||
}
|
||||
return length_mod;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------
|
||||
* printf helper function
|
||||
*-----------------------------------------------*/
|
||||
#ifdef UNITY_INCLUDE_PRINT_FORMATTED
|
||||
static void UnityPrintFVA(const char* format, va_list va)
|
||||
{
|
||||
const char* pch = format;
|
||||
@@ -1841,12 +1927,17 @@ static void UnityPrintFVA(const char* format, va_list va)
|
||||
|
||||
if (pch != NULL)
|
||||
{
|
||||
int length_mod_size;
|
||||
enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size);
|
||||
pch += length_mod_size;
|
||||
|
||||
switch (*pch)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
const int number = va_arg(va, int);
|
||||
UNITY_INT number;
|
||||
UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int);
|
||||
UnityPrintNumber((UNITY_INT)number);
|
||||
break;
|
||||
}
|
||||
@@ -1861,21 +1952,31 @@ static void UnityPrintFVA(const char* format, va_list va)
|
||||
#endif
|
||||
case 'u':
|
||||
{
|
||||
const unsigned int number = va_arg(va, unsigned int);
|
||||
UnityPrintNumberUnsigned((UNITY_UINT)number);
|
||||
UNITY_UINT number;
|
||||
UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
|
||||
UnityPrintNumberUnsigned(number);
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
{
|
||||
const unsigned int number = va_arg(va, unsigned int);
|
||||
UNITY_UINT number;
|
||||
UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
|
||||
const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1;
|
||||
UNITY_OUTPUT_CHAR('0');
|
||||
UNITY_OUTPUT_CHAR('b');
|
||||
UnityPrintMask(mask, (UNITY_UINT)number);
|
||||
UnityPrintMask(mask, number);
|
||||
break;
|
||||
}
|
||||
case 'x':
|
||||
case 'X':
|
||||
{
|
||||
UNITY_UINT number;
|
||||
UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
|
||||
UNITY_OUTPUT_CHAR('0');
|
||||
UNITY_OUTPUT_CHAR('x');
|
||||
UnityPrintNumberHex(number, 8);
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
{
|
||||
const unsigned int number = va_arg(va, unsigned int);
|
||||
|
||||
Reference in New Issue
Block a user