mirror of https://github.com/ARMmbed/mbed-os.git
Merge branch 'master-minimal-printf' into minimal-printf
commit
4018753837
|
@ -0,0 +1,118 @@
|
|||
// Jenkins configuration.
|
||||
properties ([
|
||||
buildDiscarder(
|
||||
logRotator(artifactDaysToKeepStr: '',
|
||||
artifactNumToKeepStr: '',
|
||||
daysToKeepStr: '30',
|
||||
numToKeepStr: '100'
|
||||
)
|
||||
)
|
||||
])
|
||||
|
||||
// RaaS credentials and settings.
|
||||
raas_username = "ci"
|
||||
raas_password = "ci"
|
||||
raas_timeout = 1200
|
||||
|
||||
// Test combinations, for each listed target, each toolchain is build and tested on RaaS instance.
|
||||
targets = [
|
||||
"K64F": ["toolchains": [ "ARM", "IAR", "GCC_ARM"], "raas": "https://eeva.mbedcloudtesting.com"],
|
||||
"NUCLEO_F429ZI": ["toolchains": [ "ARM", "IAR", "GCC_ARM"], "raas": "https://ruka.mbedcloudtesting.com"],
|
||||
]
|
||||
|
||||
// Map toolchains to compiler labels to find suitable node on Jenkins.
|
||||
def nodes = [
|
||||
ARM: "armcc",
|
||||
IAR: "iar_arm",
|
||||
GCC_ARM: "arm-none-eabi-gcc",
|
||||
SXOS: "linux"
|
||||
]
|
||||
|
||||
// Initial maps for parallel build steps
|
||||
def buildStepsForParallel = [:]
|
||||
def testStepsForParallel = [:]
|
||||
|
||||
for (target in targets.keySet()) {
|
||||
for (toolchain_key in targets[target]["toolchains"]) {
|
||||
echo "Include for build: ${target} ${toolchain_key}"
|
||||
|
||||
def stepName = "${target} ${toolchain_key}"
|
||||
buildStepsForParallel[stepName] = buildStep(target, nodes[toolchain_key], toolchain_key)
|
||||
}
|
||||
}
|
||||
|
||||
for (target in targets.keySet()) {
|
||||
for (toolchain_key in targets[target]["toolchains"]) {
|
||||
echo "Include for test: ${target} ${toolchain_key}"
|
||||
|
||||
def stepName = "${target} ${toolchain_key}"
|
||||
testStepsForParallel[stepName] = testStep(target, nodes[toolchain_key], toolchain_key)
|
||||
}
|
||||
}
|
||||
|
||||
// Actually run the steps in parallel - parallel takes a map as an argument, hence the above.
|
||||
timestamps {
|
||||
parallel buildStepsForParallel
|
||||
parallel testStepsForParallel
|
||||
}
|
||||
|
||||
// Create build steps for parallel execution.
|
||||
def buildStep(target, compilerLabel, toolchain) {
|
||||
return {
|
||||
stage("Build_${target}_${toolchain}") {
|
||||
node("${compilerLabel}") {
|
||||
deleteDir()
|
||||
|
||||
echo "buildStep: ${target} ${compilerLabel} ${toolchain}"
|
||||
dir("test") {
|
||||
|
||||
// checkout PR.
|
||||
checkout scm
|
||||
|
||||
// remove wrapper file so we don't compare minimal-printf with itself.
|
||||
sh "rm ./mbed_printf_wrapper.c"
|
||||
|
||||
// checkout newest Mbed OS release.
|
||||
sh "mbed new ."
|
||||
|
||||
// use default release profile for ARM and IAR.
|
||||
sh "mbed test -vv --compile -m ${target} -t ${toolchain} -n '*minimal-printf*' --build ci --stats-depth 10 --app-config ./TESTS/minimal-printf/compliance/test_app.json"
|
||||
|
||||
// stash build directory for testins step.
|
||||
stash name: "minimal-printf-greentea-${target}-${toolchain}", includes: "ci/**"
|
||||
}
|
||||
|
||||
step([$class: 'WsCleanup'])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def testStep(target, compilerLabel, toolchain) {
|
||||
return {
|
||||
stage("Light suite ${target}_${toolchain}") {
|
||||
node("${compilerLabel}") {
|
||||
deleteDir()
|
||||
|
||||
echo "testStep: ${target} ${toolchain}"
|
||||
|
||||
// unstash build directory containing greentea tests.
|
||||
unstash "minimal-printf-greentea-${target}-${toolchain}"
|
||||
|
||||
// setup RaaS environment.
|
||||
env.RAAS_USERNAME = raas_username
|
||||
env.RAAS_PASSWORD = raas_password
|
||||
env.RAAS_PYCLIENT_FORCE_REMOTE_ALLOCATION = 1
|
||||
env.RAAS_PYCLIENT_ALLOCATION_QUEUE_TIMEOUT = raas_timeout
|
||||
|
||||
raas = targets[target]["raas"]
|
||||
|
||||
// execute greentea on RaaS.
|
||||
execute("mbedgt -g ${target}:raas_client:${raas}:443 -vV --test-spec ./ci/test_spec.json --polling-timeout 240")
|
||||
|
||||
// Clean up workarea.
|
||||
step([$class: 'WsCleanup'])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
# 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.
|
||||
Floating point is disabled by default.
|
||||
Printing to a FILE stream is enabled by default.
|
||||
|
||||
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 (disabled by default).
|
||||
* %F: floating point (disabled by default, treated as %f).
|
||||
* %g: floating point (disabled by default, treated as %f).
|
||||
* %G: floating point (disabled by default, treated as %f).
|
||||
* %c: character.
|
||||
* %s: string.
|
||||
* %p: pointer (e.g. 0x00123456).
|
||||
|
||||
Unrecognized format specifiers are treated as ordinary characters.
|
||||
|
||||
Floating point support:
|
||||
* Floating point is disabled by default.
|
||||
* All floating points are treated as %f.
|
||||
* No support for inf, infinity or nan
|
||||
|
||||
To replace the standard implementations of the printf functions with the ones in this library:
|
||||
|
||||
* Add the library to your project.
|
||||
* Compile with mbed-cli using one of the custom profiles in the `profiles/` subdirectory. For
|
||||
example, to compile in release mode:
|
||||
|
||||
```
|
||||
$ mbed compile -t <toolchain> -m <target> --profile mbed-printf/profiles/release.json
|
||||
```
|
||||
|
||||
## Enabling floating point, FILE stream, 64 bit integers, new line conversion, and setting baud rate
|
||||
|
||||
In mbed_app.json:
|
||||
|
||||
```
|
||||
"target_overrides": {
|
||||
"*": {
|
||||
"platform.stdio-baud-rate": 115200,
|
||||
"platform.stdio-convert-newlines": false,
|
||||
"minimal-printf.enable-file-stream": true,
|
||||
"minimal-printf.enable-floating-point": true,
|
||||
"minimal-printf.set-floating-point-max-decimals": 6,
|
||||
"minimal-printf.enable-64-bit": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Size comparison
|
||||
|
||||
Example application compiled with minimal mbed OS (no RTOS) using this .mbedignore:
|
||||
|
||||
```
|
||||
mbed-os/rtos/*
|
||||
mbed-os/features/FEATURE_LWIP/*
|
||||
mbed-os/features/FEATURE_CLIENT/*
|
||||
mbed-os/features/FEATURE_COMMON_PAL/*
|
||||
mbed-os/features/FEATURE_UVISOR/*
|
||||
mbed-os/features/frameworks/*
|
||||
mbed-os/features/net/*
|
||||
mbed-os/features/netsocket/*
|
||||
mbed-os/features/storage/*
|
||||
mbed-os/events/*
|
||||
```
|
||||
|
||||
### Example application
|
||||
```
|
||||
#include "mbed.h"
|
||||
#include "mbed_printf.h"
|
||||
#include <limits.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
char buffer[1000];
|
||||
int result;
|
||||
|
||||
double pi = 3.14159265359;
|
||||
|
||||
#if 0
|
||||
result = printf("hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh", pi);
|
||||
printf("results: %d\r\n", result);
|
||||
|
||||
result = snprintf(buffer, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi);
|
||||
printf("%s\r\n", buffer);
|
||||
|
||||
printf("results: %d\r\n", result);
|
||||
|
||||
#else
|
||||
result = mbed_printf("hello world %ld %llu %02X %p %s %2.5f %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh", pi);
|
||||
mbed_printf("results: %d\r\n", result);
|
||||
|
||||
result = mbed_snprintf(buffer, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi);
|
||||
mbed_printf("%s\r\n", buffer);
|
||||
|
||||
mbed_printf("results: %d\r\n", result);
|
||||
#endif
|
||||
}
|
||||
```
|
||||
|
||||
### Full application size on K64F/GCC
|
||||
|
||||
| | Floating point | 64 bit integers | Flash | RAM |
|
||||
| - | - | - | - | - |
|
||||
| mbed-printf | | | 7772 | 2752 |
|
||||
| mbed-printf | | X | 8708 | 2752 |
|
||||
| mbed-printf | X | | 10368 | 2752 |
|
||||
| mbed-printf | X | X | 11360 | 2752 |
|
||||
| std printf | X | X | 37354 | 5364 |
|
|
@ -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_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_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);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"target_overrides": {
|
||||
"*": {
|
||||
"minimal-printf.enable-file-stream": 1
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "minimal-printf",
|
||||
"config": {
|
||||
"console-output": {
|
||||
"help": "Console output. Options: UART, SWO",
|
||||
"value": "UART"
|
||||
},
|
||||
"enable-64-bit": {
|
||||
"help": "Enable printing 64 bit integers",
|
||||
"value": true
|
||||
},
|
||||
"enable-file-stream": {
|
||||
"help": "Enable printing to a FILE stream",
|
||||
"value": true
|
||||
},
|
||||
"enable-floating-point": {
|
||||
"help": "Enable floating point printing",
|
||||
"value": false
|
||||
},
|
||||
"set-floating-point-max-decimals": {
|
||||
"help": "Maximum number of decimals to be printed",
|
||||
"value": 6
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* 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_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
|
|
@ -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_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
|
|
@ -0,0 +1,371 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -0,0 +1,805 @@
|
|||
/* 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_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_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 1
|
||||
#define MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 6
|
||||
#define MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT 1
|
||||
#define MBED_INITIALIZE_PRINT(x) { ; }
|
||||
#define MBED_PRINT_CHARACTER(x) { printf("%c", x); }
|
||||
#endif
|
||||
|
||||
#ifndef MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT
|
||||
#define MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 0
|
||||
#endif
|
||||
|
||||
#ifndef MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS
|
||||
#define MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 6
|
||||
#endif
|
||||
|
||||
#ifndef MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT
|
||||
#define MBED_CONF_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_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_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_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_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_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_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_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;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/* 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 <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments, FILE* stream);
|
|
@ -0,0 +1,128 @@
|
|||
/* 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>
|
||||
|
||||
#if defined(TOOLCHAIN_GCC)
|
||||
#define SUB_PRINTF __wrap_printf
|
||||
#define SUB_SPRINTF __wrap_sprintf
|
||||
#define SUB_SNPRINTF __wrap_snprintf
|
||||
#define SUB_VPRINTF __wrap_vprintf
|
||||
#define SUB_VSPRINTF __wrap_vsprintf
|
||||
#define SUB_VSNPRINTF __wrap_vsnprintf
|
||||
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FILE_STREAM
|
||||
#define SUB_FPRINTF __wrap_fprintf
|
||||
#define SUB_VFPRINTF __wrap_vfprintf
|
||||
#endif
|
||||
#elif defined(TOOLCHAIN_ARM)
|
||||
#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_MINIMAL_PRINTF_ENABLE_FILE_STREAM
|
||||
#define SUB_FPRINTF $Sub$$fprintf
|
||||
#define SUB_VFPRINTF $Sub$$vfprintf
|
||||
#endif
|
||||
#elif defined(__ICCARM__)
|
||||
#define SUPER_PRINTF $Super$$__iar_printf
|
||||
#define SUB_PRINTF $Sub$$__iar_printf
|
||||
#define SUPER_SPRINTF $Super$$__iar_sprintf
|
||||
#define SUB_SPRINTF $Sub$$__iar_sprintf
|
||||
#define SUPER_SNPRINTF $Super$$__iar_snprintf
|
||||
#define SUB_SNPRINTF $Sub$$__iar_snprintf
|
||||
#define SUPER_VPRINTF $Super$$__iar_vprintf
|
||||
#define SUB_VPRINTF $Sub$$__iar_vprintf
|
||||
#define SUPER_VSPRINTF $Super$$__iar_vsprintf
|
||||
#define SUB_VSPRINTF $Sub$$__iar_vsprintf
|
||||
#define SUPER_VSNPRINTF $Super$$__iar_vsnprintf
|
||||
#define SUB_VSNPRINTF $Sub$$__iar_vsnprintf
|
||||
#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FILE_STREAM
|
||||
#define SUB_FPRINTF $Sub$$fprintf
|
||||
#define SUB_VFPRINTF $Sub$$vfprintf
|
||||
#endif
|
||||
#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_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
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"GCC_ARM": {
|
||||
"common": ["-c", "-Wall", "-Wextra",
|
||||
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
|
||||
"-fmessage-length=0", "-fno-exceptions", "-fno-builtin",
|
||||
"-ffunction-sections", "-fdata-sections", "-funsigned-char",
|
||||
"-MMD", "-fno-delete-null-pointer-checks",
|
||||
"-fomit-frame-pointer", "-O0", "-g3", "-DMBED_DEBUG",
|
||||
"-DMBED_TRAP_ERRORS_ENABLED=1"],
|
||||
"asm": ["-x", "assembler-with-cpp"],
|
||||
"c": ["-std=gnu99"],
|
||||
"cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"],
|
||||
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
|
||||
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",
|
||||
"-Wl,-n",
|
||||
"-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": ["-c", "--target=arm-arm-none-eabi", "-mthumb", "-g", "-O1",
|
||||
"-Wno-armcc-pragma-push-pop", "-Wno-armcc-pragma-anon-unions",
|
||||
"-DMULADDC_CANNOT_USE_R7", "-fdata-sections",
|
||||
"-fno-exceptions", "-MMD", "-D_LIBCPP_EXTERN_TEMPLATE(...)=",
|
||||
"-fshort-enums", "-fshort-wchar", "-DMBED_DEBUG",
|
||||
"-DMBED_TRAP_ERRORS_ENABLED=1", "--ide=mbed"],
|
||||
"asm": ["--ide=mbed"],
|
||||
"c": ["-D__ASSERT_MSG", "-std=gnu99"],
|
||||
"cxx": ["-fno-rtti", "-std=gnu++98"],
|
||||
"ld": ["--verbose", "--remove", "--show_full_path", "--legacyalign", "--keep=os_cb_sections"]
|
||||
},
|
||||
"ARM": {
|
||||
"common": ["-c", "--gnu", "-Otime", "--split_sections",
|
||||
"--apcs=interwork", "--brief_diagnostics", "--restrict",
|
||||
"--multibyte_chars", "-O0", "-g", "-DMBED_DEBUG",
|
||||
"-DMBED_TRAP_ERRORS_ENABLED=1"],
|
||||
"asm": [],
|
||||
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
|
||||
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
|
||||
"ld": ["--show_full_path", "--keep=os_cb_sections"]
|
||||
},
|
||||
"uARM": {
|
||||
"common": ["-c", "--gnu", "-Otime", "--split_sections",
|
||||
"--apcs=interwork", "--brief_diagnostics", "--restrict",
|
||||
"--multibyte_chars", "-O0", "-D__MICROLIB", "-g",
|
||||
"--library_type=microlib", "-DMBED_RTOS_SINGLE_THREAD", "-DMBED_DEBUG",
|
||||
"-DMBED_TRAP_ERRORS_ENABLED=1"],
|
||||
"asm": [],
|
||||
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
|
||||
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
|
||||
"ld": ["--library_type=microlib"]
|
||||
},
|
||||
"IAR": {
|
||||
"common": [
|
||||
"--no_wrap_diagnostics", "-e",
|
||||
"--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-On", "-r", "-DMBED_DEBUG",
|
||||
"-DMBED_TRAP_ERRORS_ENABLED=1", "--enable_restrict"],
|
||||
"asm": [],
|
||||
"c": ["--vla", "--diag_suppress=Pe546"],
|
||||
"cxx": ["--guard_calls", "--no_static_destruction"],
|
||||
"ld": ["--skip_dynamic_initialization", "--threaded_lib"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"GCC_ARM": {
|
||||
"common": ["-c", "-Wall", "-Wextra",
|
||||
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
|
||||
"-fmessage-length=0", "-fno-exceptions", "-fno-builtin",
|
||||
"-ffunction-sections", "-fdata-sections", "-funsigned-char",
|
||||
"-MMD", "-fno-delete-null-pointer-checks",
|
||||
"-fomit-frame-pointer", "-Os", "-g1", "-DMBED_TRAP_ERRORS_ENABLED=1"],
|
||||
"asm": ["-x", "assembler-with-cpp"],
|
||||
"c": ["-std=gnu99"],
|
||||
"cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"],
|
||||
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
|
||||
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",
|
||||
"-Wl,-n",
|
||||
"-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": ["-c", "--target=arm-arm-none-eabi", "-mthumb", "-Os",
|
||||
"-Wno-armcc-pragma-push-pop", "-Wno-armcc-pragma-anon-unions",
|
||||
"-DMULADDC_CANNOT_USE_R7", "-fdata-sections",
|
||||
"-fno-exceptions", "-MMD", "-D_LIBCPP_EXTERN_TEMPLATE(...)=",
|
||||
"-fshort-enums", "-fshort-wchar", "-DMBED_TRAP_ERRORS_ENABLED=1", "--ide=mbed"],
|
||||
"asm": ["--ide=mbed"],
|
||||
"c": ["-D__ASSERT_MSG", "-std=gnu99"],
|
||||
"cxx": ["-fno-rtti", "-std=gnu++98"],
|
||||
"ld": ["--show_full_path", "--legacyalign", "--keep=os_cb_sections"]
|
||||
},
|
||||
"ARM": {
|
||||
"common": ["-c", "--gnu", "-Otime", "--split_sections",
|
||||
"--apcs=interwork", "--brief_diagnostics", "--restrict",
|
||||
"--multibyte_chars", "-O3", "-DMBED_TRAP_ERRORS_ENABLED=1"],
|
||||
"asm": [],
|
||||
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
|
||||
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
|
||||
"ld": ["--show_full_path", "--keep=os_cb_sections"]
|
||||
},
|
||||
"uARM": {
|
||||
"common": ["-c", "--gnu", "-Otime", "--split_sections",
|
||||
"--apcs=interwork", "--brief_diagnostics", "--restrict",
|
||||
"--multibyte_chars", "-O3", "-D__MICROLIB",
|
||||
"--library_type=microlib", "-DMBED_RTOS_SINGLE_THREAD",
|
||||
"-DMBED_TRAP_ERRORS_ENABLED=1"],
|
||||
"asm": [],
|
||||
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
|
||||
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
|
||||
"ld": ["--library_type=microlib"]
|
||||
},
|
||||
"IAR": {
|
||||
"common": [
|
||||
"--no_wrap_diagnostics", "-e",
|
||||
"--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Oh", "--enable_restrict",
|
||||
"-DMBED_TRAP_ERRORS_ENABLED=1"],
|
||||
"asm": [],
|
||||
"c": ["--vla", "--diag_suppress=Pe546"],
|
||||
"cxx": ["--guard_calls", "--no_static_destruction"],
|
||||
"ld": ["--skip_dynamic_initialization", "--threaded_lib"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"GCC_ARM": {
|
||||
"common": ["-c", "-Wall", "-Wextra",
|
||||
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
|
||||
"-fmessage-length=0", "-fno-exceptions", "-fno-builtin",
|
||||
"-ffunction-sections", "-fdata-sections", "-funsigned-char",
|
||||
"-MMD", "-fno-delete-null-pointer-checks",
|
||||
"-fomit-frame-pointer", "-Os", "-DNDEBUG", "-g1"],
|
||||
"asm": ["-x", "assembler-with-cpp"],
|
||||
"c": ["-std=gnu99"],
|
||||
"cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"],
|
||||
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
|
||||
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
|
||||
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",
|
||||
"-Wl,-n",
|
||||
"-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": ["-c", "--target=arm-arm-none-eabi", "-mthumb", "-Oz",
|
||||
"-Wno-armcc-pragma-push-pop", "-Wno-armcc-pragma-anon-unions",
|
||||
"-DMULADDC_CANNOT_USE_R7", "-fdata-sections",
|
||||
"-fno-exceptions", "-MMD", "-D_LIBCPP_EXTERN_TEMPLATE(...)=",
|
||||
"-fshort-enums", "-fshort-wchar", "-DNDEBUG", "--ide=mbed"],
|
||||
"asm": ["--ide=mbed"],
|
||||
"c": ["-D__ASSERT_MSG", "-std=gnu99"],
|
||||
"cxx": ["-fno-rtti", "-std=gnu++98"],
|
||||
"ld": ["--show_full_path", "--legacyalign"]
|
||||
},
|
||||
"ARM": {
|
||||
"common": ["-c", "--gnu", "-Ospace", "--split_sections",
|
||||
"--apcs=interwork", "--brief_diagnostics", "--restrict",
|
||||
"--multibyte_chars", "-O3", "-DNDEBUG"],
|
||||
"asm": [],
|
||||
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
|
||||
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
|
||||
"ld": ["--show_full_path", "--keep=os_cb_sections"]
|
||||
},
|
||||
"uARM": {
|
||||
"common": ["-c", "--gnu", "-Ospace", "--split_sections",
|
||||
"--apcs=interwork", "--brief_diagnostics", "--restrict",
|
||||
"--multibyte_chars", "-O3", "-D__MICROLIB",
|
||||
"--library_type=microlib", "-DMBED_RTOS_SINGLE_THREAD", "-DNDEBUG"],
|
||||
"asm": [],
|
||||
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
|
||||
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
|
||||
"ld": ["--library_type=microlib"]
|
||||
},
|
||||
"IAR": {
|
||||
"common": [
|
||||
"--no_wrap_diagnostics", "-e",
|
||||
"--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Ohz", "-DNDEBUG", "--enable_restrict"],
|
||||
"asm": [],
|
||||
"c": ["--vla", "--diag_suppress=Pe546"],
|
||||
"cxx": ["--guard_calls", "--no_static_destruction"],
|
||||
"ld": ["--skip_dynamic_initialization", "--threaded_lib"]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue