Merge pull request #11051 from evedon/minimal-printf

Minimal printf addition
pull/11191/head
Martin Kojtal 2019-08-09 09:52:36 +01:00 committed by GitHub
commit fafd0a5480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 2561 additions and 11 deletions

View File

@ -28,7 +28,7 @@ static char buffer[256] = {0};
#define CLEAN_BUFFER memset(::buffer, 0x00, sizeof(::buffer))
#define NEGATIVE_INTEGERS -32768,-3214,-999,-100,-1,0,-1,-4231,-999,-4123,-32760,-99999
#define POSITIVE_INTEGERS 32768,3214,999,100,1,0,1,4231,999,4123,32760,99999
#define FLOATS 0.002,0.92430,15.91320,791.77368,6208.2,25719.4952,426815.982588,6429271.046,42468024.93,212006462.910
#define FLOATS 0.002,0.92430,15.91320,791.77368,6208.2,25719.4952,426815.982588,6429271.046,42468024.93,212006462.910,6579.048
using namespace utest::v1;
@ -47,7 +47,7 @@ void test_case_c_string_u_d()
TEST_ASSERT_EQUAL_STRING("32768 3214 999 100 1 0 1 4231 999 4123 32760 99999", buffer);
}
void test_case_c_string_x_E()
void test_case_c_string_x_X()
{
CLEAN_BUFFER;
sprintf(buffer, "%x %X %x %X %x %X %x %X %x %X %x %X", POSITIVE_INTEGERS);
@ -57,22 +57,22 @@ void test_case_c_string_x_E()
void test_case_c_string_f_f()
{
CLEAN_BUFFER;
sprintf(buffer, "%f %f %f %f %f %f %f %f %f %f", FLOATS);
TEST_ASSERT_EQUAL_STRING("0.002000 0.924300 15.913200 791.773680 6208.200000 25719.495200 426815.982588 6429271.046000 42468024.930000 212006462.910000", buffer);
sprintf(buffer, "%f %f %f %f %f %f %f %f %f %f %f", FLOATS);
TEST_ASSERT_EQUAL_STRING("0.002000 0.924300 15.913200 791.773680 6208.200000 25719.495200 426815.982588 6429271.046000 42468024.930000 212006462.910000 6579.048000", buffer);
}
void test_case_c_string_g_g()
{
CLEAN_BUFFER;
sprintf(buffer, "%g %g %g %g %g %g %g %g %g %g", FLOATS);
TEST_ASSERT_EQUAL_STRING("0.002 0.9243 15.9132 791.774 6208.2 25719.5 426816 6.42927e+06 4.2468e+07 2.12006e+08", buffer);
sprintf(buffer, "%g %g %g %g %g %g %g %g %g %g %g", FLOATS);
TEST_ASSERT_EQUAL_STRING("0.002 0.9243 15.9132 791.774 6208.2 25719.5 426816 6.42927e+06 4.2468e+07 2.12006e+08 6579.05", buffer);
}
void test_case_c_string_e_E()
{
CLEAN_BUFFER;
sprintf(buffer, "%e %E %e %E %e %E %e %E %e %E", FLOATS);
TEST_ASSERT_EQUAL_STRING("2.000000e-03 9.243000E-01 1.591320e+01 7.917737E+02 6.208200e+03 2.571950E+04 4.268160e+05 6.429271E+06 4.246802e+07 2.120065E+08", buffer);
sprintf(buffer, "%e %E %e %E %e %E %e %E %e %E %e", FLOATS);
TEST_ASSERT_EQUAL_STRING("2.000000e-03 9.243000E-01 1.591320e+01 7.917737E+02 6.208200e+03 2.571950E+04 4.268160e+05 6.429271E+06 4.246802e+07 2.120065E+08 6.579048e+03", buffer);
}
void test_case_c_string_strtok()
@ -112,10 +112,12 @@ Case cases[] = {
Case("C strings: strpbrk", test_case_c_string_strpbrk, greentea_failure_handler),
Case("C strings: %i %d integer formatting", test_case_c_string_i_d, greentea_failure_handler),
Case("C strings: %u %d integer formatting", test_case_c_string_u_d, greentea_failure_handler),
Case("C strings: %x %E integer formatting", test_case_c_string_x_E, greentea_failure_handler),
Case("C strings: %x %E integer formatting", test_case_c_string_x_X, greentea_failure_handler),
Case("C strings: %f %f float formatting", test_case_c_string_f_f, greentea_failure_handler),
#ifndef MBED_MINIMAL_PRINTF
Case("C strings: %e %E float formatting", test_case_c_string_e_E, greentea_failure_handler),
Case("C strings: %g %g float formatting", test_case_c_string_g_g, greentea_failure_handler),
#endif
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)

View File

@ -0,0 +1,11 @@
# Description
This document describes how to run minimal-printf tests.
## Running tests
You can use the following command to run tests:
`mbed test -m K64F -t GCC_ARM -n *printf* -v -c`
Do not use --profile minimal-printf so minimal-printf is not compared with itself.

View File

@ -0,0 +1,925 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef TARGET_LIKE_MBED
#include "mbed.h"
#endif
#include "mbed_printf.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include <inttypes.h>
#ifndef ULLONG_MAX
#define ULLONG_MAX UINT64_MAX
#endif
#ifndef LLONG_MAX
#define LLONG_MAX INT64_MAX
#endif
#ifndef LLONG_MIN
#define LLONG_MIN INT64_MIN
#endif
using namespace utest::v1;
static control_t test_printf_d(const size_t call_count)
{
int result_baseline;
int result_minimal;
int result_file;
/*************************************************************************/
/*************************************************************************/
result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MIN);
result_file = mbed_fprintf(stderr, "hhd: %hhd\r\n", SCHAR_MIN);
result_baseline = printf("hhd: %hhd\r\n", SCHAR_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MAX);
result_file = mbed_fprintf(stderr, "hhd: %hhd\r\n", SCHAR_MAX);
result_baseline = printf("hhd: %hhd\r\n", SCHAR_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN);
result_file = mbed_fprintf(stderr, "hd: %hd\r\n", SHRT_MIN);
result_baseline = printf("hd: %hd\r\n", SHRT_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX);
result_file = mbed_fprintf(stderr, "hd: %hd\r\n", SHRT_MAX);
result_baseline = printf("hd: %hd\r\n", SHRT_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("d: %d\r\n", INT_MIN);
result_file = mbed_fprintf(stderr, "d: %d\r\n", INT_MIN);
result_baseline = printf("d: %d\r\n", INT_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("d: %d\r\n", INT_MAX);
result_file = mbed_fprintf(stderr, "d: %d\r\n", INT_MAX);
result_baseline = printf("d: %d\r\n", INT_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN);
result_file = mbed_fprintf(stderr, "ld: %ld\r\n", LONG_MIN);
result_baseline = printf("ld: %ld\r\n", LONG_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX);
result_file = mbed_fprintf(stderr, "ld: %ld\r\n", LONG_MAX);
result_baseline = printf("ld: %ld\r\n", LONG_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN);
result_file = mbed_fprintf(stderr, "lld: %lld\r\n", LLONG_MIN);
result_baseline = printf("lld: %lld\r\n", LLONG_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MAX);
result_file = mbed_fprintf(stderr, "lld: %lld\r\n", LLONG_MAX);
result_baseline = printf("lld: %lld\r\n", LLONG_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#ifdef TARGET_LIKE_MBED
printf("%%jd not supported by mbed\r\n");
#else
result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN);
result_file = mbed_fprintf(stderr, "jd: %jd\r\n", INT32_MIN);
result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX);
result_file = mbed_fprintf(stderr, "jd: %jd\r\n", INT32_MAX);
result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%zd not supported by mbed\r\n");
#else
result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN);
result_file = mbed_fprintf(stderr, "zd: %zd\r\n", INT32_MIN);
result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX);
result_file = mbed_fprintf(stderr, "zd: %zd\r\n", INT32_MAX);
result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%td not supported by mbed\r\n");
#else
result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN);
result_file = mbed_fprintf(stderr, "td: %td\r\n", PTRDIFF_MIN);
result_baseline = printf("td: %td\r\n", PTRDIFF_MIN);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX);
result_file = mbed_fprintf(stderr, "td: %td\r\n", PTRDIFF_MAX);
result_baseline = printf("td: %td\r\n", PTRDIFF_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
return CaseNext;
}
static control_t test_printf_u(const size_t call_count)
{
int result_baseline;
int result_minimal;
int result_file;
/*************************************************************************/
/*************************************************************************/
result_minimal = mbed_printf("hhu: %hhu\r\n", 0);
result_file = mbed_fprintf(stderr, "hhu: %hhu\r\n", 0);
result_baseline = printf("hhu: %hhu\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hhu: %hhu\r\n", UCHAR_MAX);
result_file = mbed_fprintf(stderr, "hhu: %hhu\r\n", UCHAR_MAX);
result_baseline = printf("hhu: %hhu\r\n", UCHAR_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hu: %hu\r\n", 0);
result_file = mbed_fprintf(stderr, "hu: %hu\r\n", 0);
result_baseline = printf("hu: %hu\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX);
result_file = mbed_fprintf(stderr, "hu: %hu\r\n", USHRT_MAX);
result_baseline = printf("hu: %hu\r\n", USHRT_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("u: %u\r\n", 0);
result_file = mbed_fprintf(stderr, "u: %u\r\n", 0);
result_baseline = printf("u: %u\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("u: %u\r\n", UINT_MAX);
result_file = mbed_fprintf(stderr, "u: %u\r\n", UINT_MAX);
result_baseline = printf("u: %u\r\n", UINT_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("lu: %lu\r\n", 0UL);
result_file = mbed_fprintf(stderr, "lu: %lu\r\n", 0UL);
result_baseline = printf("lu: %lu\r\n", 0UL);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX);
result_file = mbed_fprintf(stderr, "lu: %lu\r\n", ULONG_MAX);
result_baseline = printf("lu: %lu\r\n", ULONG_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("llu: %llu\r\n", 0ULL);
result_file = mbed_fprintf(stderr, "llu: %llu\r\n", 0ULL);
result_baseline = printf("llu: %llu\r\n", 0ULL);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("llu: %llu\r\n", ULLONG_MAX);
result_file = mbed_fprintf(stderr, "llu: %llu\r\n", ULLONG_MAX);
result_baseline = printf("llu: %llu\r\n", ULLONG_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#ifdef TARGET_LIKE_MBED
printf("%%ju not supported by mbed\r\n");
#else
result_minimal = mbed_printf("ju: %ju\r\n", (uintmax_t) 0);
result_file = mbed_fprintf(stderr, "ju: %ju\r\n", (uintmax_t) 0);
result_baseline = printf("ju: %ju\r\n", (uintmax_t) 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX);
result_file = mbed_fprintf(stderr, "ju: %ju\r\n", UINTMAX_MAX);
result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%zu not supported by mbed\r\n");
#else
result_minimal = mbed_printf("zu: %zu\r\n", 0);
result_file = mbed_fprintf(stderr, "zu: %zu\r\n", 0);
result_baseline = printf("zu: %zu\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX);
result_file = mbed_fprintf(stderr, "zu: %zu\r\n", SIZE_MAX);
result_baseline = printf("zu: %zu\r\n", SIZE_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%tu not supported by mbed\r\n");
#else
result_minimal = mbed_printf("tu: %tu\r\n", 0);
result_file = mbed_fprintf(stderr, "tu: %tu\r\n", 0);
result_baseline = printf("tu: %tu\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX);
result_file = mbed_fprintf(stderr, "tu: %tu\r\n", UINTPTR_MAX);
result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
return CaseNext;
}
static control_t test_printf_x(const size_t call_count)
{
int result_baseline;
int result_minimal;
int result_file;
/*************************************************************************/
/*************************************************************************/
result_minimal = mbed_printf("hhX: %hhX\r\n", 0);
result_file = mbed_fprintf(stderr, "hhX: %hhX\r\n", 0);
result_baseline = printf("hhX: %hhX\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX);
result_file = mbed_fprintf(stderr, "hhX: %hhX\r\n", UCHAR_MAX);
result_baseline = printf("hhX: %hhX\r\n", UCHAR_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hX: %hX\r\n", 0);
result_file = mbed_fprintf(stderr, "hX: %hX\r\n", 0);
result_baseline = printf("hX: %hX\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX);
result_file = mbed_fprintf(stderr, "hX: %hX\r\n", USHRT_MAX);
result_baseline = printf("hX: %hX\r\n", USHRT_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("X: %X\r\n", 0);
result_file = mbed_fprintf(stderr, "X: %X\r\n", 0);
result_baseline = printf("X: %X\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("X: %X\r\n", UINT_MAX);
result_file = mbed_fprintf(stderr, "X: %X\r\n", UINT_MAX);
result_baseline = printf("X: %X\r\n", UINT_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("lX: %lX\r\n", 0UL);
result_file = mbed_fprintf(stderr, "lX: %lX\r\n", 0UL);
result_baseline = printf("lX: %lX\r\n", 0UL);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX);
result_file = mbed_fprintf(stderr, "lX: %lX\r\n", ULONG_MAX);
result_baseline = printf("lX: %lX\r\n", ULONG_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("llX: %llX\r\n", 0ULL);
result_file = mbed_fprintf(stderr, "llX: %llX\r\n", 0ULL);
result_baseline = printf("llX: %llX\r\n", 0ULL);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX);
result_file = mbed_fprintf(stderr, "llX: %llX\r\n", ULLONG_MAX);
result_baseline = printf("llX: %llX\r\n", ULLONG_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#ifdef TARGET_LIKE_MBED
printf("%%jX not supported by mbed\r\n");
#else
result_minimal = mbed_printf("jX: %jX\r\n", (uintmax_t) 0);
result_file = mbed_fprintf(stderr, "jX: %jX\r\n", (uintmax_t) 0);
result_baseline = printf("jX: %jX\r\n", (uintmax_t) 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX);
result_file = mbed_fprintf(stderr, "jX: %jX\r\n", UINTMAX_MAX);
result_baseline = printf("jX: %jX\r\n", UINTMAX_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%zX not supported by mbed\r\n");
#else
result_minimal = mbed_printf("zX: %zX\r\n", 0);
result_file = mbed_fprintf(stderr, "zX: %zX\r\n", 0);
result_baseline = printf("zX: %zX\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX);
result_file = mbed_fprintf(stderr, "zX: %zX\r\n", SIZE_MAX);
result_baseline = printf("zX: %zX\r\n", SIZE_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%tX not supported by mbed\r\n");
#else
result_minimal = mbed_printf("tX: %tX\r\n", 0);
result_file = mbed_fprintf(stderr, "tX: %tX\r\n", 0);
result_baseline = printf("tX: %tX\r\n", 0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX);
result_file = mbed_fprintf(stderr, "tX: %tX\r\n", UINTPTR_MAX);
result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_file);
#endif
result_minimal = mbed_printf("x: %x\r\n", 11259375);
result_baseline = printf("x: %x\r\n", 11259375);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext;
}
/******************************************************************************/
/* */
/* SNPRINTF */
/* */
/******************************************************************************/
static control_t test_snprintf_d(const size_t call_count)
{
char buffer_baseline[100];
char buffer_minimal[100];
int result_baseline;
int result_minimal;
/*************************************************************************/
/*************************************************************************/
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhd: %hhd\r\n", SCHAR_MIN);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhd: %hhd\r\n", SCHAR_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhd: %hhd\r\n", SCHAR_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hd: %hd\r\n", SHRT_MIN);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hd: %hd\r\n", SHRT_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hd: %hd\r\n", SHRT_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "d: %d\r\n", INT_MIN);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "d: %d\r\n", INT_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "d: %d\r\n", INT_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ld: %ld\r\n", LONG_MIN);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ld: %ld\r\n", LONG_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ld: %ld\r\n", LONG_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lld: %lld\r\n", LLONG_MIN);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lld: %lld\r\n", LLONG_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lld: %lld\r\n", LLONG_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#ifdef TARGET_LIKE_MBED
printf("%%jd not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", (intmax_t) INT32_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", (intmax_t) INT32_MIN);
TEST_ASSERT_EQUAL_STRING("jd: -2147483648\r\n", buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", (intmax_t) INT32_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", (intmax_t) INT32_MAX);
TEST_ASSERT_EQUAL_STRING("jd: 2147483647\r\n", buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%zd not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", (ssize_t) INT32_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", (ssize_t) INT32_MIN);
TEST_ASSERT_EQUAL_STRING("zd: -2147483648\r\n", buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", (ssize_t) INT32_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", (ssize_t) INT32_MAX);
TEST_ASSERT_EQUAL_STRING("zd: 2147483647\r\n", buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%td not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MIN);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "td: %td\r\n", PTRDIFF_MIN);
TEST_ASSERT_EQUAL_STRING("td: -2147483648\r\n", buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "td: %td\r\n", PTRDIFF_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "td: %td\r\n", PTRDIFF_MAX);
TEST_ASSERT_EQUAL_STRING("td: 2147483647\r\n", buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
return CaseNext;
}
static control_t test_snprintf_u(const size_t call_count)
{
char buffer_baseline[100];
char buffer_minimal[100];
int result_baseline;
int result_minimal;
/*************************************************************************/
/*************************************************************************/
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhu: %hhu\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhu: %hhu\r\n", UCHAR_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhu: %hhu\r\n", UCHAR_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hu: %hu\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hu: %hu\r\n", USHRT_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hu: %hu\r\n", USHRT_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "u: %u\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "u: %u\r\n", UINT_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "u: %u\r\n", UINT_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", 0UL);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lu: %lu\r\n", 0UL);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", ULONG_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lu: %lu\r\n", ULONG_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", 0ULL);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llu: %llu\r\n", 0ULL);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llu: %llu\r\n", ULLONG_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llu: %llu\r\n", ULLONG_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#ifdef TARGET_LIKE_MBED
printf("%%ju not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", (uintmax_t) 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", UINTMAX_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", UINTMAX_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%zu not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zu: %zu\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zu: %zu\r\n", SIZE_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zu: %zu\r\n", SIZE_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%tu not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tu: %tu\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tu: %tu\r\n", UINTPTR_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tu: %tu\r\n", UINTPTR_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
return CaseNext;
}
static control_t test_snprintf_x(const size_t call_count)
{
char buffer_baseline[100];
char buffer_minimal[100];
int result_baseline;
int result_minimal;
/*************************************************************************/
/*************************************************************************/
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhX: %hhX\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hhX: %hhX\r\n", UCHAR_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hhX: %hhX\r\n", UCHAR_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hX: %hX\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "hX: %hX\r\n", USHRT_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "hX: %hX\r\n", USHRT_MAX);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "X: %X\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "X: %X\r\n", UINT_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "X: %X\r\n", UINT_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", 0UL);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lX: %lX\r\n", 0UL);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", ULONG_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lX: %lX\r\n", ULONG_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", 0ULL);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llX: %llX\r\n", 0ULL);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", ULLONG_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llX: %llX\r\n", ULLONG_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#ifdef TARGET_LIKE_MBED
printf("%%jX not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", (uintmax_t) 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", (uintmax_t) 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", UINTMAX_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", UINTMAX_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%xX not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zX: %zX\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zX: %zX\r\n", SIZE_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zX: %zX\r\n", SIZE_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
#ifdef TARGET_LIKE_MBED
printf("%%tX not supported by mbed\r\n");
#else
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", 0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tX: %tX\r\n", 0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "tX: %tX\r\n", UINTPTR_MAX);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tX: %tX\r\n", UINTPTR_MAX);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
#endif
return CaseNext;
}
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
static control_t test_printf_f(const size_t call_count)
{
int result_baseline;
int result_minimal;
/*************************************************************************/
/*************************************************************************/
double pi = 3.14159265359;
result_minimal = mbed_printf("f: %f\r\n", 3.0089);
result_baseline = printf("f: %f\r\n", 3.0089);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_printf("f: %f\r\n", 7.0);
result_baseline = printf("f: %f\r\n", 7.0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_printf("f: %f\r\n", -1 * pi);
result_baseline = printf("f: %f\r\n", -1 * pi);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_printf("f: %f\r\n", 0.0);
result_baseline = printf("f: %f\r\n", 0.0);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_printf("f: %f\r\n", pi);
result_baseline = printf("f: %f\r\n", pi);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext;
}
static control_t test_snprintf_f(const size_t call_count)
{
char buffer_baseline[100];
char buffer_minimal[100];
int result_baseline;
int result_minimal;
/*************************************************************************/
/*************************************************************************/
double pi = 3.14159265359;
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 3.0089);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 3.0089);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 7.0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 7.0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", -1 * pi);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", -1 * pi);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 0.0);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 0.0);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", pi);
result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", pi);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext;
}
#endif
/* Generic buffer overflow test function.
* Template parameters:
* 'T' is the type being tested
* 'buf_size' is the buffer size used in tests
* Function parameters:
* 'fmt' is the format to use for sprintf
* 'data' is the data that will be printed
*/
template<typename T, size_t buf_size>
static control_t test_snprintf_buffer_overflow_generic(const char *fmt, T data)
{
char buffer_baseline[buf_size];
char buffer_minimal[buf_size];
int result_baseline;
int result_minimal;
/* empty buffer test */
result_minimal = mbed_snprintf(buffer_minimal, 0, fmt, data);
result_baseline = snprintf(buffer_baseline, 0, fmt, data);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
/* buffer isn't large enough, output needs to be truncated */
result_minimal = mbed_snprintf(buffer_minimal, buf_size - 2, fmt, data);
result_baseline = snprintf(buffer_baseline, buf_size - 2, fmt, data);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
/* buffer is one byte shorter than needed, string terminator must
be written and output must be truncated */
result_minimal = mbed_snprintf(buffer_minimal, buf_size - 1, fmt, data);
result_baseline = snprintf(buffer_baseline, buf_size - 1, fmt, data);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
/* buffer is just long enough */
result_minimal = mbed_snprintf(buffer_minimal, buf_size, fmt, data);
result_baseline = snprintf(buffer_baseline, buf_size, fmt, data);
TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal);
TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal);
return CaseNext;
}
/* Based on the generic buffer overflow function above, create tests for
each relevant data type. In each case, the buffer for printing will only
be large enough to fit the printed data. */
static control_t test_snprintf_buffer_overflow_d(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<int, sizeof("d: -1024")>("d: %d", -1024);
}
static control_t test_snprintf_buffer_overflow_ld(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<long, sizeof("ld: -1048576")>("ld: %ld", -1048576L);
}
static control_t test_snprintf_buffer_overflow_lld(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<long long, sizeof("lld: -1099511627776")>("lld: %lld", -1099511627776LL);
}
static control_t test_snprintf_buffer_overflow_u(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<unsigned int, sizeof("u: 1024")>("u: %u", 1024);
}
static control_t test_snprintf_buffer_overflow_lu(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<unsigned long, sizeof("lu: 1048576")>("lu: %lu", 1048576UL);
}
static control_t test_snprintf_buffer_overflow_llu(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<unsigned long long, sizeof("llu: 1099511627776")>("llu: %llu", 1099511627776ULL);
}
static control_t test_snprintf_buffer_overflow_x(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<unsigned int, sizeof("x: 0x400")>("x: 0x%x", 0x400);
}
static control_t test_snprintf_buffer_overflow_lx(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<unsigned long, sizeof("lx: 0x100000")>("lx: 0x%lx", 0x100000UL);
}
static control_t test_snprintf_buffer_overflow_llx(const size_t call_count)
{
return test_snprintf_buffer_overflow_generic<unsigned long long, sizeof("llx: 0x10000000000")>("llx: 0x%llx", 0x10000000000ULL);
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(30 * 60, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("printf %d", test_printf_d),
Case("snprintf %d", test_snprintf_d),
Case("printf %u", test_printf_u),
Case("snprintf %u", test_snprintf_u),
Case("printf %x", test_printf_x),
Case("snprintf %x", test_snprintf_x),
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
Case("printf %f", test_printf_f),
Case("snprintf %f", test_snprintf_f),
#endif
Case("snprintf buffer overflow %d", test_snprintf_buffer_overflow_d),
Case("snprintf buffer overflow %ld", test_snprintf_buffer_overflow_ld),
Case("snprintf buffer overflow %lld", test_snprintf_buffer_overflow_lld),
Case("snprintf buffer overflow %u", test_snprintf_buffer_overflow_u),
Case("snprintf buffer overflow %lu", test_snprintf_buffer_overflow_lu),
Case("snprintf buffer overflow %llu", test_snprintf_buffer_overflow_llu),
Case("snprintf buffer overflow %x", test_snprintf_buffer_overflow_x),
Case("snprintf buffer overflow %lx", test_snprintf_buffer_overflow_lx),
Case("snprintf buffer overflow %llx", test_snprintf_buffer_overflow_llx),
};
Specification specification(greentea_setup, cases, greentea_test_teardown_handler);
int main()
{
return !Harness::run(specification);
}

View File

@ -0,0 +1,67 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_printf_implementation.h"
#include <limits.h>
int mbed_printf(const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL);
va_end(arguments);
return result;
}
int mbed_snprintf(char *buffer, size_t length, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(buffer, length, format, arguments, NULL);
va_end(arguments);
return result;
}
int mbed_vprintf(const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL);
}
int mbed_vsnprintf(char *buffer, size_t length, const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(buffer, length, format, arguments, NULL);
}
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FILE_STREAM
int mbed_fprintf(FILE *stream, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream);
va_end(arguments);
return result;
}
int mbed_vfprintf(FILE *stream, const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream);
}
#endif

View File

@ -0,0 +1,75 @@
/* mbed Microcontroller Library
* Copyright (c) 2016 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PRINTF_H
#define MBED_PRINTF_H
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Minimal printf
*
* Prints directly to stdio/UART without using malloc.
*/
int mbed_printf(const char *format, ...);
/**
* Minimal snprintf
*
* Prints directly to buffer without using malloc.
*/
int mbed_snprintf(char *buffer, size_t length, const char *format, ...);
/**
* Minimal printf
*
* Prints directly to stdio/UART without using malloc.
*/
int mbed_vprintf(const char *format, va_list arguments);
/**
* Minimal snprintf
*
* Prints directly to buffer without using malloc.
*/
int mbed_vsnprintf(char *buffer, size_t length, const char *format, va_list arguments);
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FILE_STREAM
/**
* Minimal fprintf
*
* Prints directly to file stream without using malloc.
*/
int mbed_fprintf(FILE *stream, const char *format, ...);
/**
* Minimal vfprintf
*
* Prints directly to file stream without using malloc.
*/
int mbed_vfprintf(FILE *stream, const char *format, va_list arguments);
#endif
#ifdef __cplusplus
}
#endif
#endif // MBED_PRINTF_H

View File

@ -0,0 +1,7 @@
{
"target_overrides": {
"*": {
"platform.minimal-printf-enable-file-stream": 1
}
}
}

View File

@ -127,6 +127,26 @@
"use-mpu": {
"help": "Use the MPU if available to fault execution from RAM and writes to ROM. Can be disabled to reduce image size.",
"value": true
},
"minimal-printf-console-output": {
"help": "Console output when using mprintf profile. Options: UART, SWO",
"value": "UART"
},
"minimal-printf-enable-64-bit": {
"help": "Enable printing 64 bit integers when using mprintf profile",
"value": true
},
"minimal-printf-enable-file-stream": {
"help": "Enable printing to a FILE stream when using mprintf profile",
"value": true
},
"minimal-printf-enable-floating-point": {
"help": "Enable floating point printing when using mprintf profile",
"value": true
},
"minimal-printf-set-floating-point-max-decimals": {
"help": "Maximum number of decimals to be printed",
"value": 6
}
},
"target_overrides": {

View File

@ -0,0 +1,158 @@
# Minimal printf and snprintf
Library supports both printf and snprintf in 1252 bytes of flash.
Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored.
Supports:
* %d: signed integer [h, hh, (none), l, ll, z, j, t].
* %i: signed integer [h, hh, (none), l, ll, z, j, t].
* %u: unsigned integer [h, hh, (none), l, ll, z, j, t].
* %x: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., ff).
* %X: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., FF).
* %f: floating point (enabled by default).
* %F: floating point (enabled by default, treated as %f).
* %g: floating point (enabled by default, treated as %f).
* %G: floating point (enabled by default, treated as %f).
* %c: character.
* %s: string.
* %p: pointer (e.g. 0x00123456).
Unrecognized format specifiers are treated as ordinary characters.
Floating point limitations:
* All floating points are treated as %f.
* No support for inf, infinity or nan
## Configuration
Minimal printf is configured by the following parameters defined in `platform/mbed_lib.json`:
```
{
"name": "platform",
"config": {
"minimal-printf-console-output": {
"help": "Console output when using minimal-printf profile. Options: UART, SWO",
"value": "UART"
},
"minimal-printf-enable-64-bit": {
"help": "Enable printing 64 bit integers when using minimal-printf profile",
"value": true
},
"minimal-printf-enable-file-stream": {
"help": "Enable printing to a FILE stream when using minimal-printf profile",
"value": true
},
"minimal-printf-enable-floating-point": {
"help": "Enable floating point printing when using minimal-printf profile",
"value": true
},
"minimal-printf-set-floating-point-max-decimals": {
"help": "Maximum number of decimals to be printed",
"value": 6
}
}
}
```
By default, 64 bit integers, floating point and FILE stream printing are enabled.
If your target does not require some options then you can override the default configuration in your application `mbed_app.json` and achieve further memory optimisation (see next section for size comparison numbers).
In mbed_app.json:
```
"target_overrides": {
"*": {
"platform.minimal-printf-enable-file-stream": false,
"platform.minimal-printf-enable-floating-point": false,
"platform.minimal-printf-set-floating-point-max-decimals": 6,
"platform.minimal-printf-enable-64-bit": false
}
}
```
## Usage
To replace the standard implementation of the printf functions with the ones in this library:
Compile with mbed-cli using the custom `minimal-printf` profile. For example, to compile in release mode:
```
$ mbed compile -t <toolchain> -m <target> --profile release --profile minimal-printf
```
## Size comparison
### Blinky application
https://github.com/ARMmbed/mbed-os-example-blinky application compiled with the different toolchains.
Blinky application size on K64F/GCC_ARM
| | File stream | Floating point | 64 bit integers | Flash | RAM |
| - | - | - | - | - | - |
| mbed-printf | | | | 30,944 | 12,096 |
| mbed-printf | | | X | 31,084 | 12,096 |
| mbed-printf | | X | X | 33,824 | 12,096 |
| mbed-printf | X | X | X | 34,304 | 12,096 |
| std printf | X | X | X | 54,158 | 12,112 |
Blinky application size on K64F/ARMC6
| | File stream | Floating point | 64 bit integers | Flash | RAM |
| - | - | - | - | - | - |
| mbed-printf | | | | 31,543 | xxxxx |
| mbed-printf | | | X | 31,691 | xxxxx |
| mbed-printf | | X | X | 34,515 | xxxxx |
| mbed-printf | X | X | X | 34,647 | xxxxx |
| std printf | X | X | X | 37,458 | xxxxx |
Blinky application size on K64F/IAR
| | File stream | Floating point | 64 bit integers | Flash | RAM |
| - | - | - | - | - | - |
| mbed-printf | | | | 28,713 | 8,546 |
| mbed-printf | | | X | 28,853 | 8,546 |
| mbed-printf | | X | X | 30,661 | 8,546 |
| mbed-printf | X | X | X | 32,047 | 8,594 |
| std printf | X | X | X | 35,055 | 8,462 |
### Blinky bare metal application
https://github.com/ARMmbed/mbed-os-example-blinky-baremetal application compiled with the different toolchains.
Blinky application size on K64F/GCC_ARM
| | File stream | Floating point | 64 bit integers | Flash | RAM |
| - | - | - | - | - | - |
| mbed-printf | | | | 17,168 | 5,880 |
| mbed-printf | | | X | 17,308 | 5,880 |
| mbed-printf | | X | X | 20,044 | 5,880 |
| mbed-printf | X | X | X | 22,560 | 5,880 |
| std printf | X | X | X | 35,244 | 5,864 |
Blinky application size on K64F/ARMC6
| | File stream | Floating point | 64 bit integers | Flash | RAM |
| - | - | - | - | - | - |
| mbed-printf | | | | 19,496 | xxxxx |
| mbed-printf | | | X | 19,644 | xxxxx |
| mbed-printf | | X | X | 22,468 | xxxxx |
| mbed-printf | X | X | X | 23,060 | xxxxx |
| std printf | X | X | X | 25,393 | xxxxx |
Blinky application size on K64F/IAR
| | File stream | Floating point | 64 bit integers | Flash | RAM |
| - | - | - | - | - | - |
| mbed-printf | | | | 13,007 | 1,413 |
| mbed-printf | | | X | 13,147 | 1,413 |
| mbed-printf | | X | X | 14,955 | 1,413 |
| mbed-printf | X | X | X | 21,757 | 1,929 |
| std printf | X | X | X | 17,991 | 1,281 |

View File

@ -0,0 +1,375 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Arm Compiler uses dedicated functions for each format specifier used by
* [sn/v/vsn]printf. When minimal-printf overwrites [sn/v/vsn]printf the
* linker is unable to remove unused functions related to printf.
*
* The following stubs replace the built-in functions and helps the linker
* to resolve dependencies and correctly remove unused functions.
*/
#ifdef MBED_MINIMAL_PRINTF
#if defined(TOOLCHAIN_ARM)
#include "mbed_printf_implementation.h"
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
/**
* Arm Compiler uses __2[s/sn/vsn]printf internally.
*/
int $Sub$$__2printf(const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL);
va_end(arguments);
return result;
}
int $Sub$$__2sprintf(char *buffer, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(buffer, LONG_MAX, format, arguments, NULL);
va_end(arguments);
return result;
}
int $Sub$$__2snprintf(char *buffer, size_t length, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(buffer, length, format, arguments, NULL);
va_end(arguments);
return result;
}
int $Sub$$__2vprintf(char *buffer, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(buffer, LONG_MAX, format, arguments, NULL);
va_end(arguments);
return result;
}
int $Sub$$__2vsnprintf(char *buffer, size_t length, const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(buffer, length, format, arguments, NULL);
}
/**
* Replace the built-in functions which the linker is unable to prune with dummy stubs
* that take up less space.
*/
int $Sub$$_printf_a(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_c(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_char(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_char_common(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_char_file_locked(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_charcount(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_cs_common(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_d(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_dec(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_e(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_f(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_fp_dec(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_fp_dec_real(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_fp_hex(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_fp_hex_real(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_fp_infnan(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_g(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_hex_int_ll_ptr(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_hex_ptr(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_i(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_int_common(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_int_dec(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_int_hex(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_int_oct(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_l(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_lc(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_lcs_common(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_ll(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_ll_hex(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_ll_oct(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_lld(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_lli(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_llo(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_llu(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_llx(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_longlong_dec(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_longlong_hex(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_longlong_oct(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_ls(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_n(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_o(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_oct_int_ll(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_p(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_pad(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_percent(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_percent_end(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_s(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_str(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_string(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_truncate(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_truncate_signed(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_truncate_unsigned(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_u(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_wchar(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_wctomb(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_wstring(const char *format, ...)
{
return 0;
}
int $Sub$$_printf_x(const char *format, ...)
{
return 0;
}
#endif
#endif // MBED_MINIMAL_PRINTF

View File

@ -0,0 +1,725 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed_printf_implementation.h"
#include <stdbool.h>
#include <limits.h>
#include <stdint.h>
#include <stddef.h>
/***************************/
/* MBED */
/***************************/
#if TARGET_LIKE_MBED
#define CONSOLE_OUTPUT_UART 1
#define CONSOLE_OUTPUT_SWO 2
#define mbed_console_concat_(x) CONSOLE_OUTPUT_##x
#define mbed_console_concat(x) mbed_console_concat_(x)
#define CONSOLE_OUTPUT mbed_console_concat(MBED_CONF_PLATFORM_MINIMAL_PRINTF_CONSOLE_OUTPUT)
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
static char mbed_stdio_out_prev = 0;
#endif
#if CONSOLE_OUTPUT == CONSOLE_OUTPUT_UART
#if DEVICE_SERIAL
/*
Serial initialization and new line replacement is a direct copy from mbed_retarget.cpp
If the static modifier were to be removed, this part of the code would not be necessary.
*/
#include "hal/serial_api.h"
static serial_t stdio_uart = { 0 };
/* module variable for keeping track of initialization */
static bool not_initialized = true;
static void init_serial()
{
if (not_initialized) {
not_initialized = false;
serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
#if MBED_CONF_PLATFORM_STDIO_BAUD_RATE
serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
#endif
}
}
#define MBED_INITIALIZE_PRINT(x) { init_serial(); }
#define MBED_PRINT_CHARACTER(x) { serial_putc(&stdio_uart, x); }
#else
#define MBED_INITIALIZE_PRINT(x)
#define MBED_PRINT_CHARACTER(x)
#endif // if DEVICE_SERIAL
#elif CONSOLE_OUTPUT == CONSOLE_OUTPUT_SWO
#include "hal/itm_api.h"
#define MBED_INITIALIZE_PRINT(x) { mbed_itm_init(); }
#define MBED_PRINT_CHARACTER(x) { mbed_itm_send(ITM_PORT_SWO, x); }
#endif // if CONSOLE_OUTPUT
/***************************/
/* Linux */
/***************************/
#else
/* Linux implementation is for debug only */
#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 1
#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 6
#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_64_BIT 1
#define MBED_INITIALIZE_PRINT(x) { ; }
#define MBED_PRINT_CHARACTER(x) { printf("%c", x); }
#endif
#ifndef MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 0
#endif
#ifndef MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS
#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 6
#endif
#ifndef MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_64_BIT
#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_64_BIT 1
#endif
/**
* Check architecture and choose storage data type.
* On 32 bit machines, the default storage type is 32 bit wide
* unless 64 bit integers are enabled in the configuration.
*/
#if INTPTR_MAX == INT32_MAX
#define MBED_SIGNED_NATIVE_TYPE int32_t
#define MBED_UNSIGNED_NATIVE_TYPE uint32_t
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_64_BIT
#define MBED_SIGNED_STORAGE int64_t
#define MBED_UNSIGNED_STORAGE uint64_t
#else
#define MBED_SIGNED_STORAGE int32_t
#define MBED_UNSIGNED_STORAGE uint32_t
#endif
#elif INTPTR_MAX == INT64_MAX
#define MBED_SIGNED_NATIVE_TYPE int64_t
#define MBED_UNSIGNED_NATIVE_TYPE uint64_t
#define MBED_SIGNED_STORAGE int64_t
#define MBED_UNSIGNED_STORAGE uint64_t
#else
#error unsupported architecture
#endif
/**
* Precision defines
*/
#define PRECISION_DEFAULT (INT_MAX)
/**
* Enum for storing width modifier.
*/
typedef enum {
LENGTH_NONE = 0x00,
LENGTH_H = 0x11,
LENGTH_L = 0x21,
LENGTH_J = 0x31,
LENGTH_Z = 0x41,
LENGTH_T = 0x51,
LENGTH_CAPITAL_L = 0x61,
LENGTH_HH = 0x72,
LENGTH_LL = 0x82
} length_t;
/**
* Prototypes
*/
static void mbed_minimal_formatted_string_signed(char *buffer, size_t length, int *result, MBED_SIGNED_STORAGE value, FILE *stream);
static void mbed_minimal_formatted_string_unsigned(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream);
static void mbed_minimal_formatted_string_hexadecimal(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream, bool upper);
static void mbed_minimal_formatted_string_void_pointer(char *buffer, size_t length, int *result, const void *value, FILE *stream);
static void mbed_minimal_formatted_string_character(char *buffer, size_t length, int *result, char character, FILE *stream);
static void mbed_minimal_formatted_string_string(char *buffer, size_t length, int *result, const char *string, size_t precision, FILE *stream);
/**
* @brief Print a single character, checking for buffer and size overflows.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] data The char to be printed.
*/
static void mbed_minimal_putchar(char *buffer, size_t length, int *result, char data, FILE *stream)
{
/* only continue if 'result' doesn't overflow */
if ((*result >= 0) && (*result <= INT_MAX - 1)) {
/* write data only if there's enough space */
if ((size_t)*result < length) {
if (buffer) {
buffer[*result] = data;
} else {
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FILE_STREAM
if (stream) {
fputc(data, (FILE *) stream);
} else
#endif
{
MBED_PRINT_CHARACTER(data);
}
}
}
/* increment 'result' even if data was not written. This ensures that
'mbed_minimal_formatted_string' returns the correct value. */
*result += 1;
}
}
/**
* @brief Print signed integer.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The value to be printed.
*/
static void mbed_minimal_formatted_string_signed(char *buffer, size_t length, int *result, MBED_SIGNED_STORAGE value, FILE *stream)
{
MBED_UNSIGNED_STORAGE new_value = 0;
/* if value is negative print sign and treat as positive number */
if (value < 0) {
/* write sign */
mbed_minimal_putchar(buffer, length, result, '-', stream);
/* get absolute value using two's complement */
new_value = ~((MBED_UNSIGNED_STORAGE) value) + 1;
} else {
new_value = value;
}
/* use unsigned long int function */
mbed_minimal_formatted_string_unsigned(buffer, length, result, new_value, stream);
}
/**
* @brief Print unsigned integer.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The value to be printed.
*/
static void mbed_minimal_formatted_string_unsigned(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream)
{
/* treat 0 as a corner case */
if (value == 0) {
mbed_minimal_putchar(buffer, length, result, '0', stream);
} else {
/* allocate 3 digits per byte */
char scratch[sizeof(MBED_UNSIGNED_STORAGE) * 3] = { 0 };
size_t index = 0;
/* write numbers in reverse order to scratch pad */
for (; value > 0; index++) {
/* use '0' as base and add digit */
scratch[index] = '0' + (value % 10);
/* shift value one decimal position */
value = value / 10;
}
/* write scratch pad to buffer or output */
for (; index > 0; index--) {
mbed_minimal_putchar(buffer, length, result, scratch[index - 1], stream);
}
}
}
/**
* @brief Print hexadecimal.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The value to be printed.
* @param upper Flag to print the hexadecimal in upper or lower case.
*/
static void mbed_minimal_formatted_string_hexadecimal(char *buffer, size_t length, int *result, MBED_UNSIGNED_STORAGE value, FILE *stream, bool upper)
{
bool print_leading_zero = false;
for (int index = 7; index >= 0; index--) {
/* get most significant byte */
uint8_t output = value >> (8 * index);
/* only print leading zeros when set */
if (print_leading_zero || (output != 0) || (index == 0)) {
unsigned int nibble_one = (output >> 4);
unsigned int nibble_two = (output & 0x0F);
const char int2hex_lower[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
const char int2hex_upper[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
const char *int2hex = upper ? int2hex_upper : int2hex_lower;
if (print_leading_zero || nibble_one != 0) {
mbed_minimal_putchar(buffer, length, result, int2hex[nibble_one], stream);
}
mbed_minimal_putchar(buffer, length, result, int2hex[nibble_two], stream);
/* print zeroes after the first non-zero byte */
print_leading_zero = true;
}
}
}
/**
* @brief Print pointer.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The pointer to be printed.
*/
static void mbed_minimal_formatted_string_void_pointer(char *buffer, size_t length, int *result, const void *value, FILE *stream)
{
/* write leading 0x */
mbed_minimal_putchar(buffer, length, result, '0', stream);
mbed_minimal_putchar(buffer, length, result, 'x', stream);
/* write rest as a regular hexadecimal number */
mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value, stream, true);
}
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
/**
* @brief Write double.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The value to be printed.
*/
static void mbed_minimal_formatted_string_double(char *buffer, size_t length, int *result, double value, FILE *stream)
{
/* get integer part */
MBED_SIGNED_STORAGE integer = value;
/* write integer part */
mbed_minimal_formatted_string_signed(buffer, length, result, integer, stream);
/* write decimal point */
mbed_minimal_formatted_string_character(buffer, length, result, '.', stream);
/* get decimal part */
double precision = 1.0;
for (size_t index = 0; index < MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS; index++) {
precision *= 10;
}
value = (value - integer) * precision;
/* convert to unsigned integer */
MBED_UNSIGNED_STORAGE decimal = 0;
if (value < 0) {
MBED_SIGNED_STORAGE temp = value;
decimal = ~((MBED_UNSIGNED_STORAGE) temp) + 1;
} else {
decimal = value;
}
/* round up or down */
value -= decimal;
if (!((value > -0.5) && (value < 0.5))) {
decimal++;
}
/* convert precision to unsigned integer */
MBED_UNSIGNED_STORAGE precision_in_uint = precision;
precision_in_uint /= 10;
/* ensure that leading zeros are printed if decimal equals 0 */
MBED_UNSIGNED_STORAGE val = decimal ? decimal : decimal + 1;
while (precision_in_uint > val) {
/* print leading zeros */
mbed_minimal_putchar(buffer, length, result, '0', stream);
precision_in_uint /= 10;
}
/* write decimal part */
mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal, stream);
}
#endif
/**
* @brief Print character.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The character to be printed.
*/
static void mbed_minimal_formatted_string_character(char *buffer, size_t length, int *result, char character, FILE *stream)
{
/* write character */
if (buffer) {
mbed_minimal_putchar(buffer, length, result, character, stream);
} else {
/* convert \n to \r\n if enabled in platform configuration */
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
if (character == '\n' && mbed_stdio_out_prev != '\r') {
mbed_minimal_putchar(buffer, length, result, '\r', stream);
}
/* cache character */
mbed_stdio_out_prev = character;
#endif
mbed_minimal_putchar(buffer, length, result, character, stream);
}
}
/**
* @brief Print string with precision.
*
* @param buffer The buffer to store output (NULL for stdout).
* @param[in] length The length of the buffer.
* @param result The current output location.
* @param[in] value The string to be printed.
* @param[in] precision The maximum number of characters to be printed.
*/
static void mbed_minimal_formatted_string_string(char *buffer, size_t length, int *result, const char *string, size_t precision, FILE *stream)
{
while ((*string != '\0') && (precision)) {
mbed_minimal_putchar(buffer, length, result, *string, stream);
string++;
precision--;
}
}
/**
* @brief Parse formatted string and invoke write handlers based on type.
*
* @param buffer The buffer to write to, write to stdout if NULL.
* @param[in] length The length of the buffer.
* @param[in] format The formatted string.
* @param[in] arguments The va_list arguments.
*
* @return Number of characters written.
*/
int mbed_minimal_formatted_string(char *buffer, size_t length, const char *format, va_list arguments, FILE *stream)
{
/* initialize output if needed */
MBED_INITIALIZE_PRINT();
int result = 0;
bool empty_buffer = false;
/* ensure that function wasn't called with an empty buffer, or with or with
a buffer size that is larger than the maximum 'int' value, or with
a NULL format specifier */
if (format && length <= INT_MAX) {
/* Make sure that there's always space for the NULL terminator */
if (length > 0) {
length --;
} else {
/* the buffer is empty, there's no place to write the terminator */
empty_buffer = true;
}
/* parse string */
for (size_t index = 0; format[index] != '\0'; index++) {
/* format specifier begin */
if (format[index] == '%') {
size_t next_index = index + 1;
/**************************************************************
* skip and ignore flags [-+(space)#0]
*************************************************************/
if ((format[next_index] == '-') ||
(format[next_index] == '+') ||
(format[next_index] == ' ') ||
(format[next_index] == '#') ||
(format[next_index] == '0')) {
/* skip to next character */
next_index++;
}
/**************************************************************
* skip and ignore width [(number)*]
*************************************************************/
if (format[next_index] == '*') {
/* skip to next character */
next_index++;
/* discard argument */
va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
} else {
while ((format[next_index] >= '0') &&
(format[next_index] <= '9')) {
/* skip to next character */
next_index++;
}
}
/**************************************************************
* look for precision modifier
*************************************************************/
int precision = PRECISION_DEFAULT;
if ((format[next_index] == '.') &&
(format[next_index + 1] == '*')) {
next_index += 2;
/* read precision from argument list */
precision = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
} else if (format[next_index] == '.') {
/* precision modifier found, reset default to 0 and increment index */
next_index++;
precision = 0;
/* parse precision until not a decimal */
size_t inner_index = 0;
while ((format[next_index + inner_index] >= '0') &&
(format[next_index + inner_index] <= '9')) {
precision = precision * 10 + (format[next_index + inner_index] - '0');
inner_index++;
}
/* move index forward to point at next character */
next_index += inner_index;
}
/**************************************************************
* look for length modifier, default to NONE
*************************************************************/
length_t length_modifier = LENGTH_NONE;
/* look for two character length modifier */
if ((format[next_index] == 'h') && (format[next_index + 1] == 'h')) {
length_modifier = LENGTH_HH;
} else if ((format[next_index] == 'l') && (format[next_index + 1] == 'l')) {
length_modifier = LENGTH_LL;
}
/* look for one character length modifier if two character search failed */
else if (format[next_index] == 'h') {
length_modifier = LENGTH_H;
} else if (format[next_index] == 'l') {
length_modifier = LENGTH_L;
} else if (format[next_index] == 'j') {
length_modifier = LENGTH_J;
} else if (format[next_index] == 'z') {
length_modifier = LENGTH_Z;
} else if (format[next_index] == 't') {
length_modifier = LENGTH_T;
} else if (format[next_index] == 'L') {
length_modifier = LENGTH_CAPITAL_L;
}
/* increment index, length is encoded in modifier enum */
next_index += (length_modifier & 0x0F);
/**************************************************************
* read out character - this is a supported format character,
* '\0', or a not suported character
*************************************************************/
char next = format[next_index];
/* signed integer */
if ((next == 'd') || (next == 'i')) {
MBED_SIGNED_STORAGE value = 0;
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_64_BIT
/* if 64 bit is enabled and the integer types are larger than the native type */
if (((length_modifier == LENGTH_LL) && (sizeof(long long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
((length_modifier == LENGTH_L) && (sizeof(long int) > sizeof(MBED_SIGNED_NATIVE_TYPE))) ||
((length_modifier == LENGTH_NONE) && (sizeof(int) > sizeof(MBED_SIGNED_NATIVE_TYPE)))) {
/* use 64 bit storage type for readout */
value = va_arg(arguments, MBED_SIGNED_STORAGE);
} else
#endif
{
/* use native storage type (which can be 32 or 64 bit) */
value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
}
/* constrict value based on lenght modifier */
switch (length_modifier) {
case LENGTH_NONE:
value = (int) value;
break;
case LENGTH_HH:
value = (signed char) value;
break;
case LENGTH_H:
value = (short int) value;
break;
case LENGTH_L:
value = (long int) value;
break;
case LENGTH_LL:
value = (long long int) value;
break;
case LENGTH_J:
value = (intmax_t) value;
break;
case LENGTH_T:
value = (ptrdiff_t) value;
break;
default:
break;
}
index = next_index;
mbed_minimal_formatted_string_signed(buffer, length, &result, value, stream);
}
/* unsigned integer */
else if ((next == 'u') || (next == 'x') || (next == 'X')) {
MBED_UNSIGNED_STORAGE value = 0;
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_64_BIT
/* if 64 bit is enabled and the integer types are larger than the native type */
if (((length_modifier == LENGTH_LL) && (sizeof(unsigned long long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
((length_modifier == LENGTH_L) && (sizeof(unsigned long int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE))) ||
((length_modifier == LENGTH_NONE) && (sizeof(unsigned int) > sizeof(MBED_UNSIGNED_NATIVE_TYPE)))) {
/* use 64 bit storage type for readout */
value = va_arg(arguments, MBED_UNSIGNED_STORAGE);
} else
#endif
{
/* use native storage type (which can be 32 or 64 bit) */
value = va_arg(arguments, MBED_UNSIGNED_NATIVE_TYPE);
}
/* constrict value based on lenght modifier */
switch (length_modifier) {
case LENGTH_NONE:
value = (unsigned int) value;
break;
case LENGTH_HH:
value = (unsigned char) value;
break;
case LENGTH_H:
value = (unsigned short int) value;
break;
case LENGTH_L:
value = (unsigned long int) value;
break;
case LENGTH_LL:
value = (unsigned long long int) value;
break;
case LENGTH_J:
value = (uintmax_t) value;
break;
case LENGTH_Z:
value = (size_t) value;
break;
case LENGTH_T:
value = (ptrdiff_t) value;
break;
default:
break;
}
index = next_index;
/* write unsigned or hexadecimal */
if (next == 'u') {
mbed_minimal_formatted_string_unsigned(buffer, length, &result, value, stream);
} else {
mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value, stream, next == 'X');
}
}
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
/* treat all floating points the same */
else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G')) {
double value = va_arg(arguments, double);
index = next_index;
mbed_minimal_formatted_string_double(buffer, length, &result, value, stream);
}
#endif
/* character */
else if (next == 'c') {
char value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE);
index = next_index;
mbed_minimal_formatted_string_character(buffer, length, &result, value, stream);
}
/* string */
else if (next == 's') {
char *value = va_arg(arguments, char *);
index = next_index;
mbed_minimal_formatted_string_string(buffer, length, &result, value, precision, stream);
}
/* pointer */
else if (next == 'p') {
void *value = va_arg(arguments, void *);
index = next_index;
mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value, stream);
} else {
/* write all characters between format beginning and unrecognied modifier */
while (index < next_index) {
mbed_minimal_formatted_string_character(buffer, length, &result, format[index], stream);
index++;
}
/* if this is not the end of the string, write unrecognized modifier */
if (next != '\0') {
mbed_minimal_formatted_string_character(buffer, length, &result, format[index], stream);
} else {
/* break out of for loop */
break;
}
}
} else
/* not a format specifier */
{
/* write normal character */
mbed_minimal_formatted_string_character(buffer, length, &result, format[index], stream);
}
}
if (buffer && !empty_buffer) {
/* NULL-terminate the buffer no matter what. We use '<=' to compare instead of '<'
because we know that we initially reserved space for '\0' by decrementing length */
if ((size_t)result <= length) {
buffer[result] = '\0';
} else {
buffer[length] = '\0';
}
}
}
return result;
}

View File

@ -0,0 +1,24 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_PRINTF_IMPLEMENTATION_H
#define MBED_PRINTF_IMPLEMENTATION_H
#include <stdio.h>
#include <stdarg.h>
int mbed_minimal_formatted_string(char *buffer, size_t length, const char *format, va_list arguments, FILE *stream);
#endif

View File

@ -0,0 +1,141 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef MBED_MINIMAL_PRINTF
#include "mbed_printf_implementation.h"
#include <limits.h>
#if defined(__GNUC__) /* GCC */
#define SUPER_PRINTF __real_printf
#define SUB_PRINTF __wrap_printf
#define SUPER_SPRINTF __real_sprintf
#define SUB_SPRINTF __wrap_sprintf
#define SUPER_SNPRINTF __real_snprintf
#define SUB_SNPRINTF __wrap_snprintf
#define SUPER_VPRINTF __real_vprintf
#define SUB_VPRINTF __wrap_vprintf
#define SUPER_VSPRINTF __real_vsprintf
#define SUB_VSPRINTF __wrap_vsprintf
#define SUPER_VSNPRINTF __real_vsnprintf
#define SUB_VSNPRINTF __wrap_vsnprintf
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FILE_STREAM
#define SUPER_FPRINTF __real_fprintf
#define SUB_FPRINTF __wrap_fprintf
#define SUPER_VFPRINTF __real_vfprintf
#define SUB_VFPRINTF __wrap_vfprintf
#endif
#elif defined(TOOLCHAIN_ARM) /* ARMC5/ARMC6 */\
|| defined(__ICCARM__) /* IAR */
#define SUPER_PRINTF $Super$$printf
#define SUB_PRINTF $Sub$$printf
#define SUPER_SPRINTF $Super$$sprintf
#define SUB_SPRINTF $Sub$$sprintf
#define SUPER_SNPRINTF $Super$$snprintf
#define SUB_SNPRINTF $Sub$$snprintf
#define SUPER_VPRINTF $Super$$vprintf
#define SUB_VPRINTF $Sub$$vprintf
#define SUPER_VSPRINTF $Super$$vsprintf
#define SUB_VSPRINTF $Sub$$vsprintf
#define SUPER_VSNPRINTF $Super$$vsnprintf
#define SUB_VSNPRINTF $Sub$$vsnprintf
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FILE_STREAM
#define SUPER_FPRINTF $Super$$fprintf
#define SUB_FPRINTF $Sub$$fprintf
#define SUPER_VFPRINTF $Super$$vfprintf
#define SUB_VFPRINTF $Sub$$vfprintf
#endif
#else
#warning "This compiler is not yet supported."
#endif
// Prevent optimization of printf() by the ARMCC or IAR compiler.
// This is done to prevent optimization which can cause printf() to be
// substituted with a different function (e.g. puts()) and cause
// the output to be missing some strings.
// Note: Optimization prevention for other supported compilers is done
// via compiler optional command line arguments.
#if defined(__CC_ARM) /* ARMC5 */
#pragma push
#pragma O0
#elif defined(__ICCARM__) /* IAR */
#pragma optimize=none
#endif
int SUB_PRINTF(const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL);
va_end(arguments);
return result;
}
int SUB_SPRINTF(char *buffer, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(buffer, LONG_MAX, format, arguments, NULL);
va_end(arguments);
return result;
}
int SUB_SNPRINTF(char *buffer, size_t length, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(buffer, length, format, arguments, NULL);
va_end(arguments);
return result;
}
int SUB_VPRINTF(const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL);
}
int SUB_VSPRINTF(char *buffer, const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(buffer, LONG_MAX, format, arguments, NULL);
}
int SUB_VSNPRINTF(char *buffer, size_t length, const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(buffer, length, format, arguments, NULL);
}
#if MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FILE_STREAM
int SUB_FPRINTF(FILE *stream, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream);
va_end(arguments);
return result;
}
int SUB_VFPRINTF(FILE *stream, const char *format, va_list arguments)
{
return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, stream);
}
#endif
#endif // MBED_MINIMAL_PRINTF

View File

@ -215,7 +215,7 @@
<listOptionValue builtIn="false" value="&quot;${ProjDirPath}/{{file}}&quot;"/>
{% endfor %}
</option>
{% if opts['c']['compiler.std'] %}
{% if opts['c'].get('compiler.std') %}
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.std.{{u.id}}" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.std" value="ilg.gnuarmeclipse.managedbuild.cross.option.c.compiler.std.{{opts['c']['compiler.std']}}" valueType="enumerated"/>
{% endif %}
{% if opts['c']['otheroptimizations'] != '' %}
@ -263,7 +263,7 @@
<listOptionValue builtIn="false" value="&quot;${ProjDirPath}/{{file}}&quot;"/>
{% endfor %}
</option>
{% if opts['cpp']['compiler.std'] %}
{% if opts['cpp'].get('compiler.std') %}
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.std.{{u.id}}" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.std" value="ilg.gnuarmeclipse.managedbuild.cross.option.cpp.compiler.std.{{opts['cpp']['compiler.std']}}" valueType="enumerated"/>
{% endif %}

View File

@ -0,0 +1,20 @@
{
"GCC_ARM": {
"common": ["-DMBED_MINIMAL_PRINTF", "-fno-builtin-printf"],
"ld": ["-Wl,--wrap,printf", "-Wl,--wrap,sprintf", "-Wl,--wrap,snprintf",
"-Wl,--wrap,vprintf", "-Wl,--wrap,vsprintf", "-Wl,--wrap,vsnprintf",
"-Wl,--wrap,fprintf", "-Wl,--wrap,vfprintf"]
},
"ARMC6": {
"common": ["-DMBED_MINIMAL_PRINTF", "-fno-builtin-printf"]
},
"ARM": {
"common": ["-DMBED_MINIMAL_PRINTF"]
},
"uARM": {
"common": ["-DMBED_MINIMAL_PRINTF"]
},
"IAR": {
"common": ["-DMBED_MINIMAL_PRINTF"]
}
}