diff --git a/include/sys/cbprintf.h b/include/sys/cbprintf.h index 674a557ec2bde..e32c88fc7f89e 100644 --- a/include/sys/cbprintf.h +++ b/include/sys/cbprintf.h @@ -69,26 +69,6 @@ typedef int (*cbprintf_cb)(/* int c, void *ctx */); __printf_like(3, 4) int cbprintf(cbprintf_cb out, void *ctx, const char *format, ...); -/** @brief Calculate the number of words required for arguments to a cbprintf - * format specification. - * - * This can be used in cases where the arguments must be copied off the stack - * into separate storage for processing the conversion in another context. - * - * @note The length returned does not count bytes. It counts native words - * defined as the size of an `int`. - * - * @note If `CONFIG_CBPRINTF_NANO` is selected the count will be incorrect if - * any passed arguments require more than one `int`. - * - * @param format a standard ISO C format string with characters and conversion - * specifications. - * - * @return the number of `int` elements required to provide all arguments - * required for the conversion. - */ -size_t cbprintf_arglen(const char *format); - /** @brief varargs-aware *printf-like output through a callback. * * This is essentially vsprintf() except the output is generated diff --git a/lib/os/cbprintf_complete.c b/lib/os/cbprintf_complete.c index fb431f57c4258..c30cd52a82881 100644 --- a/lib/os/cbprintf_complete.c +++ b/lib/os/cbprintf_complete.c @@ -54,15 +54,15 @@ typedef uint32_t uint_value_type; /* The allowed types of length modifier. */ enum length_mod_enum { - LENGTH_NONE, - LENGTH_HH, - LENGTH_H, - LENGTH_L, - LENGTH_LL, - LENGTH_J, - LENGTH_Z, - LENGTH_T, - LENGTH_UPPER_L, + LENGTH_NONE, /* int */ + LENGTH_HH, /* char */ + LENGTH_H, /* short */ + LENGTH_L, /* long */ + LENGTH_LL, /* long long */ + LENGTH_J, /* intmax */ + LENGTH_Z, /* size_t */ + LENGTH_T, /* ptrdiff_t */ + LENGTH_UPPER_L, /* long double */ }; /* Categories of conversion specifiers. */ @@ -79,12 +79,53 @@ enum specifier_cat_enum { SPECIFIER_FP, }; +#define CHAR_IS_SIGNED (CHAR_MIN != 0) +#if CHAR_IS_SIGNED +#define CASE_SINT_CHAR case 'c': +#define CASE_UINT_CHAR +#else +#define CASE_SINT_CHAR +#define CASE_UINT_CHAR case 'c': +#endif + +/* We need two pieces of information about wchar_t: + * * WCHAR_IS_SIGNED: whether it's signed or unsigned; + * * WINT_TYPE: the type to use when extracting it from va_args + * + * The former can be determined from the value of WCHAR_MIN if it's defined. + * It's not for minimal libc, so treat it as whatever char is. + * + * The latter should be wint_t, but minimal libc doesn't provide it. We can + * substitute wchar_t as long as that type does not undergo default integral + * promotion as an argument. But it does for at least one toolchain (xtensa), + * and where it does we need to use the promoted type in va_arg() to avoid + * build errors, otherwise we can use the base type. We can tell that + * integral promotion occurs if WCHAR_MAX is strictly less than INT_MAX. + */ +#ifndef WCHAR_MIN +#define WCHAR_IS_SIGNED CHAR_IS_SIGNED +#if WCHAR_IS_SIGNED +#define WINT_TYPE int +#else /* wchar signed */ +#define WINT_TYPE unsigned int +#endif /* wchar signed */ +#else /* WCHAR_MIN defined */ +#define WCHAR_IS_SIGNED ((WCHAR_MIN - 0) != 0) +#if WCHAR_MAX < INT_MAX +/* Signed or unsigned, it'll be int */ +#define WINT_TYPE int +#else /* wchar rank vs int */ +#define WINT_TYPE wchar_t +#endif /* wchar rank vs int */ +#endif /* WCHAR_MIN defined */ + /* Case label to identify conversions for signed integral values. The * corresponding argument_value tag is sint and category is * SPECIFIER_SINT. */ #define SINT_CONV_CASES \ 'd': \ + CASE_SINT_CHAR \ case 'i' /* Case label to identify conversions for signed integral arguments. @@ -92,8 +133,8 @@ enum specifier_cat_enum { * SPECIFIER_UINT. */ #define UINT_CONV_CASES \ - 'c': \ - case 'o': \ + 'o': \ + CASE_UINT_CHAR \ case 'u': \ case 'x': \ case 'X' @@ -360,10 +401,8 @@ static inline const char *extract_width(struct conversion *conv, if (sp != wp) { conv->width_present = true; conv->width_value = width; - if (width != conv->width_value) { - /* Lost width data */ - conv->unsupported = true; - } + conv->unsupported |= ((conv->width_value < 0) + || (width != (size_t)conv->width_value)); } return sp; @@ -396,10 +435,8 @@ static inline const char *extract_prec(struct conversion *conv, size_t prec = extract_decimal(&sp); conv->prec_value = prec; - if (prec != conv->prec_value) { - /* Lost precision data */ - conv->unsupported = true; - } + conv->unsupported |= ((conv->prec_value < 0) + || (prec != (size_t)conv->prec_value)); return sp; } @@ -493,7 +530,7 @@ static inline const char *extract_specifier(struct conversion *conv, } /* For c LENGTH_NONE and LENGTH_L would be ok, - * but we don't support wide characters. + * but we don't support formatting wide characters. */ if (conv->specifier == 'c') { unsupported = (conv->length_mod != LENGTH_NONE); @@ -620,84 +657,6 @@ static inline const char *extract_conversion(struct conversion *conv, return sp; } - -/* Get the number of int-sized objects required to provide the arguments for - * the conversion. - * - * This has a role in the logging subsystem where the arguments must - * be captured for formatting in another thread. - * - * If the conversion specifier is invalid the calculated length may - * not match what was actually passed as arguments. - */ -static size_t conversion_arglen(const struct conversion *conv) -{ - enum specifier_cat_enum specifier_cat - = (enum specifier_cat_enum)conv->specifier_cat; - enum length_mod_enum length_mod - = (enum length_mod_enum)conv->length_mod; - size_t words = 0; - - /* If the conversion is invalid behavior is undefined. What - * this does is try to consume the argument anyway, in hopes - * that subsequent valid arguments will format correctly. - */ - - /* Percent has no arguments */ - if (conv->specifier == '%') { - return words; - } - - if (conv->width_star) { - words += sizeof(int) / sizeof(int); - } - - if (conv->prec_star) { - words += sizeof(int) / sizeof(int); - } - - if ((specifier_cat == SPECIFIER_SINT) - || (specifier_cat == SPECIFIER_UINT)) { - /* The size of integral values is the same regardless - * of signedness. - */ - switch (length_mod) { - case LENGTH_NONE: - case LENGTH_HH: - case LENGTH_H: - words += sizeof(int) / sizeof(int); - break; - case LENGTH_L: - words += sizeof(long) / sizeof(int); - break; - case LENGTH_LL: - words += sizeof(long long) / sizeof(int); - break; - case LENGTH_J: - words += sizeof(intmax_t) / sizeof(int); - break; - case LENGTH_Z: - words += sizeof(size_t) / sizeof(int); - break; - case LENGTH_T: - words += sizeof(ptrdiff_t) / sizeof(int); - break; - default: - break; - } - } else if (specifier_cat == SPECIFIER_FP) { - if (length_mod == LENGTH_UPPER_L) { - words += sizeof(long double) / sizeof(int); - } else { - words += sizeof(double) / sizeof(int); - } - } else if (specifier_cat == SPECIFIER_PTR) { - words += sizeof(void *) / sizeof(int); - } - - return words; -} - #ifdef CONFIG_64BIT static void _ldiv5(uint64_t *v) @@ -1492,7 +1451,13 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap) value->sint = va_arg(ap, int); break; case LENGTH_L: - value->sint = va_arg(ap, long); + if (WCHAR_IS_SIGNED + && (conv->specifier == 'c')) { + value->sint = (wchar_t)va_arg(ap, + WINT_TYPE); + } else { + value->sint = va_arg(ap, long); + } break; case LENGTH_LL: value->sint = @@ -1529,7 +1494,13 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap) value->uint = va_arg(ap, unsigned int); break; case LENGTH_L: - value->uint = va_arg(ap, unsigned long); + if ((!WCHAR_IS_SIGNED) + && (conv->specifier == 'c')) { + value->uint = (wchar_t)va_arg(ap, + WINT_TYPE); + } else { + value->uint = va_arg(ap, unsigned long); + } break; case LENGTH_LL: value->uint = @@ -1597,7 +1568,7 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap) } case 'c': bps = buf; - buf[0] = value->uint; + buf[0] = CHAR_IS_SIGNED ? value->sint : value->uint; bpe = buf + 1; break; case 'd': @@ -1827,20 +1798,3 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap) #undef OUTS #undef OUTC } - -size_t cbprintf_arglen(const char *format) -{ - size_t rv = 0; - struct conversion conv; - - while (*format) { - if (*format == '%') { - format = extract_conversion(&conv, format); - rv += conversion_arglen(&conv); - } else { - ++format; - } - } - - return rv; -} diff --git a/lib/os/cbprintf_nano.c b/lib/os/cbprintf_nano.c index 76d3da13a7cbb..e26d4277d9af4 100644 --- a/lib/os/cbprintf_nano.c +++ b/lib/os/cbprintf_nano.c @@ -294,22 +294,3 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fmt, va_list ap) return count; } - -size_t cbprintf_arglen(const char *format) -{ - size_t rv = 0; - bool last_pct = false; - - while (*format != 0) { - if (*format == '%') { - last_pct = !last_pct; - } else if (last_pct) { - ++rv; - last_pct = false; - } else { - } - ++format; - } - - return rv; -} diff --git a/tests/unit/cbprintf/main.c b/tests/unit/cbprintf/main.c index 1e4f0b6c76847..3c562206d2e33 100644 --- a/tests/unit/cbprintf/main.c +++ b/tests/unit/cbprintf/main.c @@ -17,10 +17,10 @@ #include /* Unit testing doesn't use Kconfig, so if we're not building from - * sanitycheck force selection of all features. If we are use flags - * to determine which features are desired. Yes, this is a mess. + * twister force selection of all features. If we are use flags to + * determine which features are desired. Yes, this is a mess. */ -#ifndef VIA_SANITYCHECK +#ifndef VIA_TWISTER /* Set this to truthy to use libc's snprintf as external validation. * This should be used with all options enabled. */ @@ -58,34 +58,43 @@ #define CONFIG_CBPRINTF_REDUCED_INTEGRAL 1 #endif -#else /* VIA_SANITYCHECK */ -#if (VIA_SANITYCHECK & 0x01) != 0 +#else /* VIA_TWISTER */ +#if (VIA_TWISTER & 0x01) != 0 #define CONFIG_CBPRINTF_FULL_INTEGRAL 1 #else #define CONFIG_CBPRINTF_REDUCED_INTEGRAL 1 #endif -#if (VIA_SANITYCHECK & 0x02) != 0 +#if (VIA_TWISTER & 0x02) != 0 #define CONFIG_CBPRINTF_FP_SUPPORT 1 #endif -#if (VIA_SANITYCHECK & 0x04) != 0 +#if (VIA_TWISTER & 0x04) != 0 #define CONFIG_CBPRINTF_FP_A_SUPPORT 1 #endif -#if (VIA_SANITYCHECK & 0x08) != 0 +#if (VIA_TWISTER & 0x08) != 0 #define CONFIG_CBPRINTF_N_SPECIFIER 1 #endif -#if (VIA_SANITYCHECK & 0x40) != 0 +#if (VIA_TWISTER & 0x40) != 0 #define CONFIG_CBPRINTF_FP_ALWAYS_A 1 #endif -#if (VIA_SANITYCHECK & 0x80) != 0 +#if (VIA_TWISTER & 0x80) != 0 #define CONFIG_CBPRINTF_NANO 1 #else /* 0x80 */ #define CONFIG_CBPRINTF_COMPLETE 1 #endif /* 0x80 */ -#if (VIA_SANITYCHECK & 0x100) != 0 +#if (VIA_TWISTER & 0x100) != 0 #define CONFIG_CBPRINTF_LIBC_SUBSTS 1 #endif -#endif /* VIA_SANITYCHECK */ +#endif /* VIA_TWISTER */ + +/* Can't use IS_ENABLED on symbols that don't start with CONFIG_ + * without checkpatch complaints, so do something else. + */ +#if USE_LIBC +#define ENABLED_USE_LIBC true +#else +#define ENABLED_USE_LIBC false +#endif #include "../../../lib/os/cbprintf.c" @@ -292,12 +301,12 @@ static void test_c(void) PRF_CHECK("a", rc); if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("short test for nano"); + TC_PRINT("short test for nano\n"); return; } rc = TEST_PRF("%lc", (wint_t)'a'); - if (IS_ENABLED(USE_LIBC)) { + if (ENABLED_USE_LIBC) { PRF_CHECK("a", rc); } else { PRF_CHECK("%lc", rc); @@ -337,7 +346,7 @@ static void test_s(void) } if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("short test for nano"); + TC_PRINT("short test for nano\n"); return; } @@ -345,7 +354,7 @@ static void test_s(void) PRF_CHECK("/123/12//", rc); rc = TEST_PRF("%ls", ws); - if (IS_ENABLED(USE_LIBC)) { + if (ENABLED_USE_LIBC) { PRF_CHECK("abc", rc); } else { PRF_CHECK("%ls", rc); @@ -361,7 +370,7 @@ static void test_v_c(void) rc = rawprf("%c", 'a'); zassert_equal(rc, 1, NULL); zassert_equal(buf[0], 'a', NULL); - if (!IS_ENABLED(USE_LIBC)) { + if (!ENABLED_USE_LIBC) { zassert_equal(buf[1], 'b', "wth %x", buf[1]); } } @@ -414,7 +423,7 @@ static void test_d_length(void) } if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("short test for nano"); + TC_PRINT("short test for nano\n"); return; } @@ -450,7 +459,7 @@ static void test_d_flags(void) int rc; if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("skipped test for nano"); + TC_PRINT("skipped test for nano\n"); return; } @@ -509,7 +518,7 @@ static void test_x_length(void) } if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("short test for nano"); + TC_PRINT("short test for nano\n"); return; } @@ -569,7 +578,7 @@ static void test_x_flags(void) int rc; if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("skipped test for nano"); + TC_PRINT("skipped test for nano\n"); return; } @@ -602,7 +611,7 @@ static void test_o(void) int rc; if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("skipped test for nano"); + TC_PRINT("skipped test for nano\n"); return; } @@ -615,7 +624,7 @@ static void test_o(void) static void test_fp_value(void) { if (!IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) { - TC_PRINT("skipping unsupported feature"); + TC_PRINT("skipping unsupported feature\n"); return; } @@ -808,7 +817,7 @@ static void test_fp_value(void) static void test_fp_length(void) { if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("skipped test for nano"); + TC_PRINT("skipped test for nano\n"); return; } @@ -830,7 +839,7 @@ static void test_fp_length(void) } rc = TEST_PRF("/%Lg/", (long double)dv); - if (IS_ENABLED(USE_LIBC)) { + if (ENABLED_USE_LIBC) { PRF_CHECK("/1.2345/", rc); } else { PRF_CHECK("/%Lg/", rc); @@ -849,7 +858,7 @@ static void test_fp_length(void) static void test_fp_flags(void) { if (!IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)) { - TC_PRINT("skipping unsupported feature"); + TC_PRINT("skipping unsupported feature\n"); return; } @@ -882,7 +891,7 @@ static void test_fp_flags(void) static void test_star_width(void) { if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("skipped test for nano"); + TC_PRINT("skipped test for nano\n"); return; } @@ -898,7 +907,7 @@ static void test_star_width(void) static void test_star_precision(void) { if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("skipped test for nano"); + TC_PRINT("skipped test for nano\n"); return; } @@ -927,11 +936,11 @@ static void test_star_precision(void) static void test_n(void) { if (!IS_ENABLED(CONFIG_CBPRINTF_N_SPECIFIER)) { - TC_PRINT("skipping unsupported feature"); + TC_PRINT("skipping unsupported feature\n"); return; } if (IS_ENABLED(CONFIG_CBPRINTF_NANO)) { - TC_PRINT("skipped test for nano"); + TC_PRINT("skipped test for nano\n"); return; } @@ -975,40 +984,10 @@ static void test_n(void) #define EXPECTED_1ARG(_t) (IS_ENABLED(CONFIG_CBPRINTF_NANO) \ ? 1U : (sizeof(_t) / sizeof(int))) -static void test_arglen(void) -{ - zassert_equal(cbprintf_arglen("/%hhd/"), 1U, NULL); - zassert_equal(cbprintf_arglen("/%hd/"), 1U, NULL); - zassert_equal(cbprintf_arglen("/%d/"), 1U, NULL); - zassert_equal(cbprintf_arglen("/%ld/"), - EXPECTED_1ARG(long), NULL); - zassert_equal(cbprintf_arglen("/%lld/"), - EXPECTED_1ARG(long long), NULL); - zassert_equal(cbprintf_arglen("/%jd/"), - EXPECTED_1ARG(intmax_t), NULL); - zassert_equal(cbprintf_arglen("/%zd/"), - EXPECTED_1ARG(size_t), NULL); - zassert_equal(cbprintf_arglen("/%td/"), - EXPECTED_1ARG(ptrdiff_t), NULL); - zassert_equal(cbprintf_arglen("/%f/"), - EXPECTED_1ARG(double), NULL); - zassert_equal(cbprintf_arglen("/%Lf/"), - EXPECTED_1ARG(long double), NULL); - zassert_equal(cbprintf_arglen("/%p/"), - EXPECTED_1ARG(void *), NULL); - - zassert_equal(cbprintf_arglen("/%%/"), 0U, NULL); - zassert_equal(cbprintf_arglen("/%*d%/"), 2U, NULL); - zassert_equal(cbprintf_arglen("/%.*d%/"), 2U, NULL); - zassert_equal(cbprintf_arglen("/%*.*d%/"), - IS_ENABLED(CONFIG_CBPRINTF_NANO) ? 2U : 3U, - NULL); -} - static void test_p(void) { - if (IS_ENABLED(USE_LIBC)) { - TC_PRINT("skipping on libc"); + if (ENABLED_USE_LIBC) { + TC_PRINT("skipping on libc\n"); return; } @@ -1124,7 +1103,7 @@ void test_main(void) } TC_PRINT("Opts: " COND_CODE_1(M64_MODE, ("m64"), ("m32")) "\n"); - if (IS_ENABLED(USE_LIBC)) { + if (ENABLED_USE_LIBC) { TC_PRINT(" LIBC"); } if (IS_ENABLED(CONFIG_CBPRINTF_COMPLETE)) { @@ -1173,7 +1152,6 @@ void test_main(void) ztest_unit_test(test_star_precision), ztest_unit_test(test_n), ztest_unit_test(test_p), - ztest_unit_test(test_arglen), ztest_unit_test(test_libc_substs), ztest_unit_test(test_nop) ); diff --git a/tests/unit/cbprintf/testcase.yaml b/tests/unit/cbprintf/testcase.yaml index a7cfe65a15941..01d9054babc1f 100644 --- a/tests/unit/cbprintf/testcase.yaml +++ b/tests/unit/cbprintf/testcase.yaml @@ -4,49 +4,49 @@ common: tests: utilities.prf.m32v00: # REDUCED - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x00 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x00 utilities.prf.m32v01: # FULL - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x01 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x01 utilities.prf.m32v02: # REDUCED + FP - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x02 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x02 utilities.prf.m32v03: # FULL + FP - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x03 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x03 utilities.prf.m32v07: # FULL + FP + FP_A - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x07 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x07 utilities.prf.m32v08: # %n - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x08 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x08 utilities.prf.m32v80: # NANO - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x80 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x80 utilities.prf.m32v101: # FULL + LIBC - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x101 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x101 utilities.prf.m32v181: # NANO + FULL + LIBC - extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x181 + extra_args: M64_MODE=0 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x181 utilities.prf.m64v00: # m64 - extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x00 + extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x00 utilities.prf.m64v01: # m64 FULL - extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x01 + extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x01 utilities.prf.m64v03: # m64 FULL & FP - extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x03 + extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x03 utilities.prf.m64v17: # m64 FULL & FP & FP_A - extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x07 + extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x07 utilities.prf.m64v80: # NANO - extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x80 + extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x80 utilities.prf.m64v101: # FULL + LIBC - extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x101 + extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x101 utilities.prf.m64v181: # NANO + FULL + LIBC - extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_SANITYCHECK=0x181 + extra_args: M64_MODE=1 EXTRA_CPPFLAGS=-DVIA_TWISTER=0x181