mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2025-12-17 05:54:07 +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:
|
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)
|
- __%d__ - signed value (decimal)
|
||||||
- __%i__ - same as __%i__
|
- __%i__ - same as __%d__
|
||||||
- __%u__ - unsigned value (decimal)
|
- __%u__ - unsigned value (decimal)
|
||||||
- __%f__ - float/Double (if float support is activated)
|
- __%f__ - float/Double (if float support is activated)
|
||||||
- __%g__ - same as __%f__
|
- __%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")
|
- __%s__ - a string (e.g. "string")
|
||||||
- __%%__ - The "%" symbol (escaped)
|
- __%%__ - 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:_
|
_Example:_
|
||||||
|
|
||||||
```C
|
```C
|
||||||
@@ -267,6 +276,7 @@ TEST_PRINTF("Pointer %p\n", &a);
|
|||||||
TEST_PRINTF("Character %c\n", 'F');
|
TEST_PRINTF("Character %c\n", 'F');
|
||||||
TEST_PRINTF("String %s\n", "My string");
|
TEST_PRINTF("String %s\n", "My string");
|
||||||
TEST_PRINTF("Percent %%\n");
|
TEST_PRINTF("Percent %%\n");
|
||||||
|
TEST_PRINTF("Unsigned long long %llu\n", 922337203685477580);
|
||||||
TEST_PRINTF("Color Red \033[41mFAIL\033[0m\n");
|
TEST_PRINTF("Color Red \033[41mFAIL\033[0m\n");
|
||||||
TEST_PRINTF("\n");
|
TEST_PRINTF("\n");
|
||||||
TEST_PRINTF("Multiple (%d) (%i) (%u) (%x)\n", -100, 0, 200, 0x12345);
|
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
|
#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
|
* printf helper function
|
||||||
*-----------------------------------------------*/
|
*-----------------------------------------------*/
|
||||||
#ifdef UNITY_INCLUDE_PRINT_FORMATTED
|
|
||||||
static void UnityPrintFVA(const char* format, va_list va)
|
static void UnityPrintFVA(const char* format, va_list va)
|
||||||
{
|
{
|
||||||
const char* pch = format;
|
const char* pch = format;
|
||||||
@@ -1841,12 +1927,17 @@ static void UnityPrintFVA(const char* format, va_list va)
|
|||||||
|
|
||||||
if (pch != NULL)
|
if (pch != NULL)
|
||||||
{
|
{
|
||||||
|
int length_mod_size;
|
||||||
|
enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size);
|
||||||
|
pch += length_mod_size;
|
||||||
|
|
||||||
switch (*pch)
|
switch (*pch)
|
||||||
{
|
{
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
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);
|
UnityPrintNumber((UNITY_INT)number);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1861,21 +1952,31 @@ static void UnityPrintFVA(const char* format, va_list va)
|
|||||||
#endif
|
#endif
|
||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
const unsigned int number = va_arg(va, unsigned int);
|
UNITY_UINT number;
|
||||||
UnityPrintNumberUnsigned((UNITY_UINT)number);
|
UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int);
|
||||||
|
UnityPrintNumberUnsigned(number);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'b':
|
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;
|
const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1;
|
||||||
UNITY_OUTPUT_CHAR('0');
|
UNITY_OUTPUT_CHAR('0');
|
||||||
UNITY_OUTPUT_CHAR('b');
|
UNITY_OUTPUT_CHAR('b');
|
||||||
UnityPrintMask(mask, (UNITY_UINT)number);
|
UnityPrintMask(mask, number);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x':
|
case 'x':
|
||||||
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':
|
case 'p':
|
||||||
{
|
{
|
||||||
const unsigned int number = va_arg(va, unsigned int);
|
const unsigned int number = va_arg(va, unsigned int);
|
||||||
|
|||||||
Reference in New Issue
Block a user