From 02840194abccf259df1d4bfad650b792625e74ed Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sat, 14 Oct 2017 20:55:13 -0500 Subject: [PATCH 01/36] Initial commit --- features/minimal-printf/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 features/minimal-printf/README.md diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md new file mode 100644 index 0000000000..7f59dffb83 --- /dev/null +++ b/features/minimal-printf/README.md @@ -0,0 +1 @@ +# mbed-printf \ No newline at end of file From 9a21fe521b706e4a62377f673c8f4fd22e20fe57 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sat, 14 Oct 2017 19:16:50 -0700 Subject: [PATCH 02/36] Minimal printf Supports %d %u %X %p %s Doesn't use malloc --- features/minimal-printf/mbed_printf.c | 352 ++++++++++++++++++++++++++ features/minimal-printf/mbed_printf.h | 58 +++++ 2 files changed, 410 insertions(+) create mode 100755 features/minimal-printf/mbed_printf.c create mode 100755 features/minimal-printf/mbed_printf.h diff --git a/features/minimal-printf/mbed_printf.c b/features/minimal-printf/mbed_printf.c new file mode 100755 index 0000000000..a43ae0ebb2 --- /dev/null +++ b/features/minimal-printf/mbed_printf.c @@ -0,0 +1,352 @@ +/* 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. + */ + +#include "mbed_printf.h" + +#include +#include +#include +#include + +#if TARGET_LIKE_MBED +#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) { printf("%c", x); } +#endif + +static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value); +static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value); +static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value); +static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value); +static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character); +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string); + +/* module variable for keeping track of initialization */ +static bool not_initialized = true; + +static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value) +{ + /* only continue if buffer can fit at least 1 characters */ + if ((*result + 1) <= length) + { + unsigned long int new_value = 0; + + /* if value is negative print sign and treat as positive number */ + if (value < 0) + { + /* write sign */ + if (buffer) + { + buffer[*result] = '-'; + } + else + { + MBED_PRINT_CHARACTER('-'); + } + + *result += 1; + + /* get absolute value */ + new_value = (unsigned long int) (-1 * value); + } + else + { + new_value = (unsigned long int) value; + } + + /* use unsigned long int function */ + mbed_minimal_formatted_string_unsigned_long_int(buffer, length, result, new_value); + } +} + +static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value) +{ + /* only continue if buffer can fit at least 1 characters */ + if ((*result + 1) <= length) + { + /* treat 0 as a corner case */ + if (value == 0) + { + if (buffer) + { + buffer[*result] = '0'; + } + else + { + MBED_PRINT_CHARACTER('0'); + } + + *result += 1; + } + else + { + char scratch[sizeof(unsigned long int) * 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 ( ; (*result < length) && (index > 0); index--) + { + if (buffer) + { + buffer[*result] = scratch[index - 1]; + } + else + { + MBED_PRINT_CHARACTER(scratch[index - 1]); + } + + *result += 1; + } + } + } +} + +static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value) +{ + /* only continue if buffer can fit at least 2 characters */ + if ((*result + 2) <= length) + { + char nibble_one = (value & 0xFF) >> 4; + char nibble_two = (value & 0x0F); + + const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + if (buffer) + { + buffer[*result] = int2hex[nibble_one]; + buffer[*result + 1] = int2hex[nibble_two]; + } + else + { + MBED_PRINT_CHARACTER(int2hex[nibble_one]); + MBED_PRINT_CHARACTER(int2hex[nibble_two]); + } + + *result += 2; + } +} + +static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value) +{ + /* only continue if buffer can fit '0x' and twice the size of a void* */ + if ((*result + 2 + 2 * sizeof(void*)) <= length) + { + if (buffer) + { + buffer[*result] = '0'; + buffer[*result + 1] = 'x'; + } + else + { + MBED_PRINT_CHARACTER('0'); + MBED_PRINT_CHARACTER('x'); + } + + *result += 2; + + for (size_t index = 0; index < sizeof(void*); index++) + { + unsigned char byte = (unsigned char) (((unsigned long int) value) >> (8 * (sizeof(void*) - index - 1))); + + mbed_minimal_formatted_string_unsigned_char(buffer, length, result, byte); + } + } +} + +static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character) +{ + /* only continue if the buffer can fit 1 character */ + if ((*result + 1) <= length) + { + if (buffer) + { + buffer[*result] = (char) character; + } + else + { + MBED_PRINT_CHARACTER((char) character); + } + + *result += 1; + } +} + +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string) +{ + /* only continue if the buffer can fit at least 1 character */ + if ((*result + 1) <= length) + { + /* count characters in string */ + size_t remaining = length - *result; + size_t string_length = 0; + + /* only count characters that will fit into buffer */ + while ((string[string_length] != '\0') && (string_length < remaining)) + { + string_length++; + } + + /* copy string to buffer */ + if (buffer) + { + for (size_t index = 0; index < string_length; index++) + { + buffer[*result + index] = string[index]; + } + } + /* print string */ + else + { + for (size_t index = 0; index < string_length; index++) + { + MBED_PRINT_CHARACTER(string[index]); + } + } + + /* add length to counter */ + *result += string_length; + } +} + +static int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments) +{ + int result = 0; + + /* if writing to buffer, reserve space for NULL termination */ + if (buffer) + { + length--; + } + + /* parse string */ + for (size_t index = 0; format[index] != '\0'; index++) + { + /* format specifier begin */ + if (format[index] == '%') + { + char next = format[index + 1]; + + if (next == 'd') + { + long int value = va_arg(arguments, long int); + index++; + + mbed_minimal_formatted_string_long_int(buffer, length, &result, value); + } + else if (next == 'u') + { + unsigned long int value = va_arg(arguments, unsigned long int); + index++; + + mbed_minimal_formatted_string_unsigned_long_int(buffer, length, &result, value); + } + else if (next == 'X') + { + int value = va_arg(arguments, int); + index++; + + mbed_minimal_formatted_string_unsigned_char(buffer, length, &result, value); + } + else if (next == 'p') + { + void* value = va_arg(arguments, void*); + index++; + + mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); + } + else if (next == 'c') + { + int value = va_arg(arguments, int); + index++; + + mbed_minimal_formatted_string_character(buffer, length, &result, value); + } + else if (next == 's') + { + char* value = va_arg(arguments, char*); + index++; + + mbed_minimal_formatted_string_string(buffer, length, &result, value); + } + else if (next == '\0') + { + mbed_minimal_formatted_string_character(buffer, length, &result, '%'); + } + else + { + mbed_minimal_formatted_string_character(buffer, length, &result, '%'); + } + } + else + { + mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); + } + } + + /* if writing to buffer, NULL terminate string in reserved space*/ + if (buffer) + { + buffer[result] = '\0'; + } + + return result; +} + +int mbed_printf(const char *format, ...) +{ + if (not_initialized) + { + not_initialized = false; + MBED_INITIALIZE_PRINT(); + } + + va_list arguments; + va_start(arguments, format); + int result = mbed_minimal_formatted_string(NULL, ULONG_MAX, format, arguments); + va_end(arguments); + + return result; +} + +int mbed_snprintf(char* buffer, size_t length, const char* format, ...) +{ + if (not_initialized) + { + not_initialized = false; + MBED_INITIALIZE_PRINT(); + } + + va_list arguments; + va_start(arguments, format); + int result = mbed_minimal_formatted_string(buffer, length, format, arguments); + va_end(arguments); + + return result; +} diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h new file mode 100755 index 0000000000..76b3f5e09d --- /dev/null +++ b/features/minimal-printf/mbed_printf.h @@ -0,0 +1,58 @@ +/* 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 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Minimal printf + * + * Prints directly to stdio/UART without using malloc. + * Doesn't suppoet any modifiers. + * + * Supports: + * %d: signed long int + * %u: unsigned long int + * %p: void* (e.g. 0x00123456) + * %s: string + * %X: unsigned char printed as hexadecimal number (e.g., FF) + */ +int mbed_printf(const char *format, ...); + +/** + * Minimal snprintf + * + * Prints directly to buffer without using malloc. + * Doesn't suppoet any modifiers. + * + * Supports: + * %d: signed long int + * %u: unsigned long int + * %p: void* (e.g. 0x00123456) + * %s: string + * %X: unsigned char printed as hexadecimal number (e.g., FF) + */ +int mbed_snprintf(char* buffer, size_t length, const char* format, ...); + +#ifdef __cplusplus +} +#endif + +#endif // MBED_PRINTF_H From 45afbf6bf357c843e295cf076e1f5d365776d1aa Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sat, 14 Oct 2017 21:20:10 -0500 Subject: [PATCH 03/36] Update README.md --- features/minimal-printf/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md index 7f59dffb83..2ea089b716 100644 --- a/features/minimal-printf/README.md +++ b/features/minimal-printf/README.md @@ -1 +1,11 @@ -# mbed-printf \ No newline at end of file +# Minimal printf + +Prints directly to stdio/UART without using malloc. +Doesn't support any modifiers. + +Supports: +* %d: signed long int +* %u: unsigned long int +* %p: void* (e.g. 0x00123456) +* %s: string +* %X: unsigned char printed as hexadecimal number (e.g., FF) From 15e566faad20ef2cb8e2c2a1e88c93e4fabc7175 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sat, 14 Oct 2017 20:03:30 -0700 Subject: [PATCH 04/36] Add mbed initialization --- features/minimal-printf/mbed_printf.c | 51 ++++++++++++++++++++------- features/minimal-printf/mbed_printf.h | 2 ++ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/features/minimal-printf/mbed_printf.c b/features/minimal-printf/mbed_printf.c index a43ae0ebb2..3fef0a5d74 100755 --- a/features/minimal-printf/mbed_printf.c +++ b/features/minimal-printf/mbed_printf.c @@ -21,9 +21,45 @@ #include #include +/* module variable for keeping track of initialization */ +static bool not_initialized = true; + +/***************************/ +/* MBED */ +/***************************/ #if TARGET_LIKE_MBED +#include "hal/serial_api.h" + +#if DEVICE_SERIAL +static int stdio_uart_inited = 0; +static serial_t stdio_uart = { 0 }; +#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES +static char stdio_in_prev = 0; +static char stdio_out_prev = 0; +#endif +#endif + +static void init_serial() +{ + if (not_initialized) + { + not_initialized = false; + +#if DEVICE_SERIAL + 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 +#endif + } +} + #define MBED_INITIALIZE_PRINT(x) { init_serial(); } #define MBED_PRINT_CHARACTER(x) { serial_putc(&stdio_uart, x); } + +/***************************/ +/* Linux */ +/***************************/ #else #define MBED_INITIALIZE_PRINT(x) { ; } #define MBED_PRINT_CHARACTER(x) { printf("%c", x); } @@ -36,9 +72,6 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character); static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string); -/* module variable for keeping track of initialization */ -static bool not_initialized = true; - static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value) { /* only continue if buffer can fit at least 1 characters */ @@ -321,11 +354,7 @@ static int mbed_minimal_formatted_string(char* buffer, size_t length, const char int mbed_printf(const char *format, ...) { - if (not_initialized) - { - not_initialized = false; - MBED_INITIALIZE_PRINT(); - } + MBED_INITIALIZE_PRINT(); va_list arguments; va_start(arguments, format); @@ -337,11 +366,7 @@ int mbed_printf(const char *format, ...) int mbed_snprintf(char* buffer, size_t length, const char* format, ...) { - if (not_initialized) - { - not_initialized = false; - MBED_INITIALIZE_PRINT(); - } + MBED_INITIALIZE_PRINT(); va_list arguments; va_start(arguments, format); diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h index 76b3f5e09d..d6308f0352 100755 --- a/features/minimal-printf/mbed_printf.h +++ b/features/minimal-printf/mbed_printf.h @@ -17,6 +17,8 @@ #ifndef MBED_PRINTF_H #define MBED_PRINTF_H +#include + #ifdef __cplusplus extern "C" { #endif From 63d33c68b9c8ca658e5cfa5ca284f6ebb3e5abab Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sat, 14 Oct 2017 20:12:17 -0700 Subject: [PATCH 05/36] Fix compile warnings --- features/minimal-printf/mbed_printf.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/features/minimal-printf/mbed_printf.c b/features/minimal-printf/mbed_printf.c index 3fef0a5d74..7fa9cd7969 100755 --- a/features/minimal-printf/mbed_printf.c +++ b/features/minimal-printf/mbed_printf.c @@ -31,12 +31,11 @@ static bool not_initialized = true; #include "hal/serial_api.h" #if DEVICE_SERIAL -static int stdio_uart_inited = 0; static serial_t stdio_uart = { 0 }; -#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES -static char stdio_in_prev = 0; -static char stdio_out_prev = 0; -#endif +//#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES +//static char stdio_in_prev = 0; +//static char stdio_out_prev = 0; +//#endif #endif static void init_serial() @@ -75,7 +74,7 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value) { /* only continue if buffer can fit at least 1 characters */ - if ((*result + 1) <= length) + if ((*result + 1) <= (int) length) { unsigned long int new_value = 0; @@ -110,7 +109,7 @@ static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value) { /* only continue if buffer can fit at least 1 characters */ - if ((*result + 1) <= length) + if ((*result + 1) <= (int) length) { /* treat 0 as a corner case */ if (value == 0) @@ -143,7 +142,7 @@ static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t } /* write scratch pad to buffer or output */ - for ( ; (*result < length) && (index > 0); index--) + for ( ; (*result < (int) length) && (index > 0); index--) { if (buffer) { @@ -163,10 +162,10 @@ static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value) { /* only continue if buffer can fit at least 2 characters */ - if ((*result + 2) <= length) + if ((*result + 2) <= (int) length) { - char nibble_one = (value & 0xFF) >> 4; - char nibble_two = (value & 0x0F); + unsigned int nibble_one = (value & 0xFF) >> 4; + unsigned int nibble_two = (value & 0x0F); const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; @@ -216,7 +215,7 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character) { /* only continue if the buffer can fit 1 character */ - if ((*result + 1) <= length) + if ((*result + 1) <= (int) length) { if (buffer) { @@ -234,7 +233,7 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string) { /* only continue if the buffer can fit at least 1 character */ - if ((*result + 1) <= length) + if ((*result + 1) <= (int) length) { /* count characters in string */ size_t remaining = length - *result; From a70a5332a860811c6ad6641a15c7a60d93ba5c20 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sat, 14 Oct 2017 22:21:38 -0500 Subject: [PATCH 06/36] Update README.md --- features/minimal-printf/README.md | 159 ++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md index 2ea089b716..7440b50ceb 100644 --- a/features/minimal-printf/README.md +++ b/features/minimal-printf/README.md @@ -9,3 +9,162 @@ Supports: * %p: void* (e.g. 0x00123456) * %s: string * %X: unsigned char printed as hexadecimal number (e.g., FF) + +## 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 + +int main() +{ + char buffer[1000]; + int result; + +#if 0 + result = printf("hello world %d %u %X %p %s %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh"); + printf("results: %d\r\n", result); + + result = snprintf(buffer, 1000, "hello world %d %u %X %p %s %% %\r\n", LONG_MIN, 0, 0, buffer, "muh"); + printf("%s\r\n", buffer); + + printf("results: %d\r\n", result); + +#else + result = mbed_printf("hello world %d %u %X %p %s %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh"); + mbed_printf("results: %d\r\n", result); + + result = mbed_snprintf(buffer, 1000, "hello world %d %u %X %p %s %% %\r\n", LONG_MIN, 0, 0, buffer, "muh"); + mbed_printf("%s\r\n", buffer); + + mbed_printf("results: %d\r\n", result); +#endif +} +``` + +### K64F standard printf + +``` ++------------------------------------------+-------+-------+------+ +| Module | .text | .data | .bss | ++------------------------------------------+-------+-------+------+ +| [fill] | 52 | 4 | 2071 | +| [lib]/c.a/lib_a-callocr.o | 96 | 0 | 0 | +| [lib]/c.a/lib_a-closer.o | 36 | 0 | 0 | +| [lib]/c.a/lib_a-ctype_.o | 257 | 0 | 0 | +| [lib]/c.a/lib_a-dtoa.o | 3948 | 0 | 0 | +| [lib]/c.a/lib_a-errno.o | 12 | 0 | 0 | +| [lib]/c.a/lib_a-fclose.o | 196 | 0 | 0 | +| [lib]/c.a/lib_a-fflush.o | 404 | 0 | 0 | +| [lib]/c.a/lib_a-findfp.o | 204 | 0 | 0 | +| [lib]/c.a/lib_a-fputwc.o | 264 | 0 | 0 | +| [lib]/c.a/lib_a-freer.o | 620 | 0 | 0 | +| [lib]/c.a/lib_a-fstatr.o | 40 | 0 | 0 | +| [lib]/c.a/lib_a-fvwrite.o | 752 | 0 | 0 | +| [lib]/c.a/lib_a-fwalk.o | 84 | 0 | 0 | +| [lib]/c.a/lib_a-impure.o | 0 | 1068 | 0 | +| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | +| [lib]/c.a/lib_a-isattyr.o | 36 | 0 | 0 | +| [lib]/c.a/lib_a-locale.o | 42 | 364 | 0 | +| [lib]/c.a/lib_a-localeconv.o | 28 | 0 | 0 | +| [lib]/c.a/lib_a-lock.o | 16 | 0 | 33 | +| [lib]/c.a/lib_a-lseekr.o | 44 | 0 | 0 | +| [lib]/c.a/lib_a-makebuf.o | 240 | 0 | 0 | +| [lib]/c.a/lib_a-mallocr.o | 1376 | 1040 | 52 | +| [lib]/c.a/lib_a-mbtowc_r.o | 44 | 0 | 0 | +| [lib]/c.a/lib_a-memchr.o | 160 | 0 | 0 | +| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | +| [lib]/c.a/lib_a-memmove.o | 200 | 0 | 0 | +| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | +| [lib]/c.a/lib_a-mprec.o | 1776 | 0 | 0 | +| [lib]/c.a/lib_a-printf.o | 40 | 0 | 0 | +| [lib]/c.a/lib_a-readr.o | 44 | 0 | 0 | +| [lib]/c.a/lib_a-reallocr.o | 844 | 0 | 0 | +| [lib]/c.a/lib_a-reent.o | 0 | 0 | 4 | +| [lib]/c.a/lib_a-sbrkr.o | 36 | 0 | 0 | +| [lib]/c.a/lib_a-snprintf.o | 152 | 0 | 0 | +| [lib]/c.a/lib_a-stdio.o | 136 | 0 | 0 | +| [lib]/c.a/lib_a-strlen.o | 220 | 0 | 0 | +| [lib]/c.a/lib_a-svfiprintf.o | 252 | 0 | 0 | +| [lib]/c.a/lib_a-svfprintf.o | 5370 | 0 | 0 | +| [lib]/c.a/lib_a-vfiprintf.o | 148 | 0 | 0 | +| [lib]/c.a/lib_a-vfprintf.o | 5754 | 0 | 0 | +| [lib]/c.a/lib_a-wbuf.o | 176 | 0 | 0 | +| [lib]/c.a/lib_a-wcrtomb.o | 84 | 0 | 0 | +| [lib]/c.a/lib_a-wctomb_r.o | 28 | 0 | 0 | +| [lib]/c.a/lib_a-writer.o | 44 | 0 | 0 | +| [lib]/c.a/lib_a-wsetup.o | 200 | 0 | 0 | +| [lib]/gcc.a/_aeabi_uldivmod.o | 48 | 0 | 0 | +| [lib]/gcc.a/_arm_addsubdf3.o | 880 | 0 | 0 | +| [lib]/gcc.a/_arm_cmpdf2.o | 272 | 0 | 0 | +| [lib]/gcc.a/_arm_fixdfsi.o | 80 | 0 | 0 | +| [lib]/gcc.a/_arm_muldivdf3.o | 1060 | 0 | 0 | +| [lib]/gcc.a/_arm_unorddf2.o | 44 | 0 | 0 | +| [lib]/gcc.a/_dvmd_tls.o | 4 | 0 | 0 | +| [lib]/gcc.a/_udivmoddi4.o | 732 | 0 | 0 | +| [lib]/misc/ | 248 | 4 | 28 | +| main.o | 169 | 0 | 0 | +| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | +| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | +| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | +| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | +| mbed-os/platform/mbed_alloc_wrappers.o | 16 | 0 | 0 | +| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | +| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | +| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | +| mbed-os/platform/mbed_retarget.o | 646 | 4 | 266 | +| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | +| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | +| mbed-os/targets/TARGET_Freescale | 4834 | 12 | 384 | +| Subtotals | 34882 | 2496 | 2868 | ++------------------------------------------+-------+-------+------+ +Total Static RAM memory (data + bss): 5364 bytes +Total Flash memory (text + data): 37378 bytes +``` + +### K64F minimal printf + +``` ++------------------------------------------+-------+-------+------+ +| Module | .text | .data | .bss | ++------------------------------------------+-------+-------+------+ +| [fill] | 15 | 3 | 2102 | +| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | +| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | +| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | +| [lib]/misc/ | 248 | 4 | 28 | +| main.o | 169 | 0 | 0 | +| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | +| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | +| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | +| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | +| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | +| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | +| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | +| mbed-os/platform/mbed_retarget.o | 20 | 0 | 0 | +| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | +| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | +| mbed-os/targets/TARGET_Freescale | 4758 | 12 | 384 | +| mbed-printf/mbed_printf.o | 820 | 1 | 188 | +| Subtotals | 7424 | 20 | 2732 | ++------------------------------------------+-------+-------+------+ +Total Static RAM memory (data + bss): 2752 bytes +Total Flash memory (text + data): 7444 bytes +``` From 4fd19a0d821696f00f3cfddf0f7a2de70d8dc390 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sun, 15 Oct 2017 19:26:01 -0700 Subject: [PATCH 07/36] Support for floating points (disabled by default) Use mbed_app.json to enable floating points. Automatically ignore flags and width specifiers. --- features/minimal-printf/README.md | 161 ++++++++++++++++++-------- features/minimal-printf/mbed_lib.json | 13 +++ features/minimal-printf/mbed_printf.c | 155 ++++++++++++++++++++----- 3 files changed, 249 insertions(+), 80 deletions(-) mode change 100644 => 100755 features/minimal-printf/README.md create mode 100755 features/minimal-printf/mbed_lib.json diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md old mode 100644 new mode 100755 index 7440b50ceb..b21d3bd483 --- a/features/minimal-printf/README.md +++ b/features/minimal-printf/README.md @@ -1,14 +1,37 @@ -# Minimal printf +# Minimal printf and snprintf -Prints directly to stdio/UART without using malloc. -Doesn't support any modifiers. +Library supports both printf and snprintf in 960 bytes of flash. + +Prints directly to stdio/UART without using malloc. All flags, length, and precision modifiers are ignored. Floating point is disabled by default. + +Supports: +* %d: signed long int. +* %i: signed long int. +* %u: unsigned long int. +* %x: unsigned char printed as hexadecimal number (e.g., FF). +* %X: unsigned char printed as hexadecimal number (e.g., FF). +* %f: floating point (disabled by default). +* %F: floating point (disabled by default). +* %g: floating point (disabled by default). +* %G: floating point (disabled by default). +* %c: character. +* %s: string. +* %p: pointer (e.g. 0x00123456). + +## Enabling floating point and setting baud rate + +In mbed_app.json: + +``` + "target_overrides": { + "*": { + "platform.stdio-baud-rate": 115200, + "minimal-printf.floating-point": true, + "minimal-printf.floating-point-max-decimals": 10 + } + } +``` -Supports: -* %d: signed long int -* %u: unsigned long int -* %p: void* (e.g. 0x00123456) -* %s: string -* %X: unsigned char printed as hexadecimal number (e.g., FF) ## Size comparison @@ -33,39 +56,107 @@ mbed-os/events/* #include "mbed_printf.h" #include -int main() +int main() { char buffer[1000]; int result; + double pi = 3.14159265359; + #if 0 - result = printf("hello world %d %u %X %p %s %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh"); + 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 %% %\r\n", LONG_MIN, 0, 0, buffer, "muh"); + 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 %d %u %X %p %s %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh"); + 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 %% %\r\n", LONG_MIN, 0, 0, buffer, "muh"); + 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 } ``` -### K64F standard printf + +### K64F GCC minimal printf without floating point ``` +------------------------------------------+-------+-------+------+ | Module | .text | .data | .bss | +------------------------------------------+-------+-------+------+ -| [fill] | 52 | 4 | 2071 | +| [fill] | 16 | 3 | 2102 | +| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | +| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | +| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | +| [lib]/misc/ | 248 | 4 | 28 | +| main.o | 256 | 0 | 0 | +| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | +| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | +| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | +| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | +| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | +| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | +| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | +| mbed-os/platform/mbed_retarget.o | 20 | 0 | 0 | +| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | +| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | +| mbed-os/targets/TARGET_Freescale | 4758 | 12 | 384 | +| mbed-printf/mbed_printf.o | 960 | 1 | 188 | +| Subtotals | 7652 | 20 | 2732 | ++------------------------------------------+-------+-------+------+ +Total Static RAM memory (data + bss): 2752 bytes +Total Flash memory (text + data): 7672 bytes +``` + + +### K64F GCC minimal printf with floating point + +``` ++------------------------------------------+-------+-------+------+ +| Module | .text | .data | .bss | ++------------------------------------------+-------+-------+------+ +| [fill] | 24 | 3 | 2102 | +| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | +| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | +| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | +| [lib]/gcc.a/_arm_addsubdf3.o | 880 | 0 | 0 | +| [lib]/gcc.a/_arm_fixdfsi.o | 80 | 0 | 0 | +| [lib]/gcc.a/_arm_muldivdf3.o | 1060 | 0 | 0 | +| [lib]/misc/ | 248 | 4 | 28 | +| main.o | 256 | 0 | 0 | +| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | +| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | +| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | +| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | +| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | +| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | +| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | +| mbed-os/platform/mbed_retarget.o | 20 | 0 | 0 | +| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | +| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | +| mbed-os/targets/TARGET_Freescale | 4758 | 12 | 384 | +| mbed-printf/mbed_printf.o | 1160 | 1 | 188 | +| Subtotals | 9880 | 20 | 2732 | ++------------------------------------------+-------+-------+------+ +Total Static RAM memory (data + bss): 2752 bytes +Total Flash memory (text + data): 9900 bytes +``` + + +### K64F GCC standard printf + +``` ++------------------------------------------+-------+-------+------+ +| Module | .text | .data | .bss | ++------------------------------------------+-------+-------+------+ +| [fill] | 62 | 4 | 2071 | | [lib]/c.a/lib_a-callocr.o | 96 | 0 | 0 | | [lib]/c.a/lib_a-closer.o | 36 | 0 | 0 | | [lib]/c.a/lib_a-ctype_.o | 257 | 0 | 0 | @@ -120,7 +211,7 @@ int main() | [lib]/gcc.a/_dvmd_tls.o | 4 | 0 | 0 | | [lib]/gcc.a/_udivmoddi4.o | 732 | 0 | 0 | | [lib]/misc/ | 248 | 4 | 28 | -| main.o | 169 | 0 | 0 | +| main.o | 215 | 0 | 0 | | mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | | mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | | mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | @@ -133,38 +224,8 @@ int main() | mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | | mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | | mbed-os/targets/TARGET_Freescale | 4834 | 12 | 384 | -| Subtotals | 34882 | 2496 | 2868 | +| Subtotals | 34938 | 2496 | 2868 | +------------------------------------------+-------+-------+------+ Total Static RAM memory (data + bss): 5364 bytes -Total Flash memory (text + data): 37378 bytes -``` - -### K64F minimal printf - -``` -+------------------------------------------+-------+-------+------+ -| Module | .text | .data | .bss | -+------------------------------------------+-------+-------+------+ -| [fill] | 15 | 3 | 2102 | -| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | -| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | -| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | -| [lib]/misc/ | 248 | 4 | 28 | -| main.o | 169 | 0 | 0 | -| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | -| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | -| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | -| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | -| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | -| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | -| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | -| mbed-os/platform/mbed_retarget.o | 20 | 0 | 0 | -| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | -| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | -| mbed-os/targets/TARGET_Freescale | 4758 | 12 | 384 | -| mbed-printf/mbed_printf.o | 820 | 1 | 188 | -| Subtotals | 7424 | 20 | 2732 | -+------------------------------------------+-------+-------+------+ -Total Static RAM memory (data + bss): 2752 bytes -Total Flash memory (text + data): 7444 bytes +Total Flash memory (text + data): 37434 bytes ``` diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json new file mode 100755 index 0000000000..5b536f7b76 --- /dev/null +++ b/features/minimal-printf/mbed_lib.json @@ -0,0 +1,13 @@ +{ + "name": "minimal-printf", + "config": { + "floating-point": { + "help": "Enable floating point printing", + "value": false + }, + "floating-point-max-decimals": { + "help": "Maximum number of decimals to be printed", + "value": 3 + } + } +} diff --git a/features/minimal-printf/mbed_printf.c b/features/minimal-printf/mbed_printf.c index 7fa9cd7969..e8db354c45 100755 --- a/features/minimal-printf/mbed_printf.c +++ b/features/minimal-printf/mbed_printf.c @@ -38,7 +38,7 @@ static serial_t stdio_uart = { 0 }; //#endif #endif -static void init_serial() +static void init_serial() { if (not_initialized) { @@ -60,6 +60,8 @@ static void init_serial() /* Linux */ /***************************/ #else +#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT 1 +#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS 10 #define MBED_INITIALIZE_PRINT(x) { ; } #define MBED_PRINT_CHARACTER(x) { printf("%c", x); } #endif @@ -71,10 +73,18 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character); static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string); +#ifndef MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT +#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT 0 +#endif + +#ifndef MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS +#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS 0 +#endif + static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value) { /* only continue if buffer can fit at least 1 characters */ - if ((*result + 1) <= (int) length) + if ((*result + 1) <= (long int) length) { unsigned long int new_value = 0; @@ -109,7 +119,7 @@ static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value) { /* only continue if buffer can fit at least 1 characters */ - if ((*result + 1) <= (int) length) + if ((*result + 1) <= (long int) length) { /* treat 0 as a corner case */ if (value == 0) @@ -127,6 +137,7 @@ static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t } else { + /* allocate 3 digits per byte */ char scratch[sizeof(unsigned long int) * 3] = { 0 }; size_t index = 0; @@ -142,7 +153,7 @@ static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t } /* write scratch pad to buffer or output */ - for ( ; (*result < (int) length) && (index > 0); index--) + for ( ; (*result < (long int) length) && (index > 0); index--) { if (buffer) { @@ -162,12 +173,12 @@ static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value) { /* only continue if buffer can fit at least 2 characters */ - if ((*result + 2) <= (int) length) + if ((*result + 2) <= (long int) length) { unsigned int nibble_one = (value & 0xFF) >> 4; unsigned int nibble_two = (value & 0x0F); - const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; if (buffer) @@ -212,10 +223,47 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng } } +#if MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT +static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value) +{ + /* only continue if buffer can fit at least 1 characters */ + if ((*result + 1) <= (long int) length) + { + /* get integer part */ + long int integer = value; + + /* write integer part */ + mbed_minimal_formatted_string_long_int(buffer, length, result, integer); + + /* write decimal point */ + mbed_minimal_formatted_string_character(buffer, length, result, '.'); + + /* get decimal part */ + double precision = 1.0; + + for (size_t index = 0; index < MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS; index++) + { + precision *= 10; + } + + long int decimal = (value - integer) * precision; + + /* take absolute value */ + if (decimal < 0) + { + decimal = -1 * decimal; + } + + /* write decimal part */ + mbed_minimal_formatted_string_long_int(buffer, length, result, decimal); + } +} +#endif + static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character) { /* only continue if the buffer can fit 1 character */ - if ((*result + 1) <= (int) length) + if ((*result + 1) <= (long int) length) { if (buffer) { @@ -233,7 +281,7 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string) { /* only continue if the buffer can fit at least 1 character */ - if ((*result + 1) <= (int) length) + if ((*result + 1) <= (long int) length) { /* count characters in string */ size_t remaining = length - *result; @@ -251,7 +299,7 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in for (size_t index = 0; index < string_length; index++) { buffer[*result + index] = string[index]; - } + } } /* print string */ else @@ -282,63 +330,110 @@ static int mbed_minimal_formatted_string(char* buffer, size_t length, const char { /* format specifier begin */ if (format[index] == '%') - { - char next = format[index + 1]; + { + size_t next_index = index + 1; - if (next == 'd') + /* while there is room in buffer and format string is not empty */ + while ((next_index < length) && (format[next_index] != '\0') && + /* skip all size modifiers */ + (((format[next_index] >= '0') && (format[next_index] <= '9')) || + (format[next_index] == 'h') || + (format[next_index] == 'l') || + (format[next_index] == 'j') || + (format[next_index] == 'z') || + (format[next_index] == 't') || + (format[next_index] == 'L') || + (format[next_index] == '.'))) + { + /* skip to next character */ + next_index++; + } + + /* read out character - this a supported format character, '\0', or a not suported character */ + char next = format[next_index]; + + /* signed integer */ + if ((next == 'd') || (next == 'i')) { long int value = va_arg(arguments, long int); - index++; + index = next_index; mbed_minimal_formatted_string_long_int(buffer, length, &result, value); } + /* unsigned integer */ else if (next == 'u') { unsigned long int value = va_arg(arguments, unsigned long int); - index++; + index = next_index; mbed_minimal_formatted_string_unsigned_long_int(buffer, length, &result, value); } - else if (next == 'X') + /* treat both hexadecimeal modifiers the same */ + else if ((next == 'x') || (next == 'X')) { int value = va_arg(arguments, int); - index++; + index = next_index; mbed_minimal_formatted_string_unsigned_char(buffer, length, &result, value); } - else if (next == 'p') +#if MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT + /* treat all floating points the same */ + else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G')) { - void* value = va_arg(arguments, void*); - index++; + double value = va_arg(arguments, double); + index = next_index; - mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); + mbed_minimal_formatted_string_double(buffer, length, &result, value); } +#endif + /* character */ else if (next == 'c') { int value = va_arg(arguments, int); - index++; + index = next_index; mbed_minimal_formatted_string_character(buffer, length, &result, value); } + /* string */ else if (next == 's') { char* value = va_arg(arguments, char*); - index++; + index = next_index; mbed_minimal_formatted_string_string(buffer, length, &result, value); } - else if (next == '\0') + /* pointer */ + else if (next == 'p') { - mbed_minimal_formatted_string_character(buffer, length, &result, '%'); + void* value = va_arg(arguments, void*); + index = next_index; + + mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); } - else + else { - mbed_minimal_formatted_string_character(buffer, length, &result, '%'); + /* write all characters between format beginning and unrecognied modifier */ + while (index < next_index) + { + mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); + 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]); + } + else + { + /* break out of for loop */ + break; + } } } else { - mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); + mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); } } @@ -357,10 +452,10 @@ int mbed_printf(const char *format, ...) va_list arguments; va_start(arguments, format); - int result = mbed_minimal_formatted_string(NULL, ULONG_MAX, format, arguments); + int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments); va_end(arguments); - return result; + return result; } int mbed_snprintf(char* buffer, size_t length, const char* format, ...) @@ -372,5 +467,5 @@ int mbed_snprintf(char* buffer, size_t length, const char* format, ...) int result = mbed_minimal_formatted_string(buffer, length, format, arguments); va_end(arguments); - return result; + return result; } From 2206ae598ec3c1d26707df3b040e06f010784985 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sun, 15 Oct 2017 21:25:24 -0700 Subject: [PATCH 08/36] Add variable list versions of printf and snprintf This makes it possible to use the minimal printf and snprintf through mbed_retarget.cpp --- features/minimal-printf/mbed_printf.c | 10 +++++++ features/minimal-printf/mbed_printf.h | 42 +++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/features/minimal-printf/mbed_printf.c b/features/minimal-printf/mbed_printf.c index e8db354c45..d6800d7782 100755 --- a/features/minimal-printf/mbed_printf.c +++ b/features/minimal-printf/mbed_printf.c @@ -469,3 +469,13 @@ int mbed_snprintf(char* buffer, size_t length, const char* format, ...) return result; } + +int mbed_vprintf(const char* format, va_list arguments) +{ + return mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments); +} + +int mbed_vsnprintf(char* buffer, size_t length, const char* format, va_list arguments) +{ + return mbed_minimal_formatted_string(buffer, length, format, arguments); +} diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h index d6308f0352..f64358f1bf 100755 --- a/features/minimal-printf/mbed_printf.h +++ b/features/minimal-printf/mbed_printf.h @@ -26,10 +26,10 @@ extern "C" { /** * Minimal printf * - * Prints directly to stdio/UART without using malloc. - * Doesn't suppoet any modifiers. + * Prints directly to stdio/UART without using malloc. + * Doesn't suppoet any modifiers. * - * Supports: + * Supports: * %d: signed long int * %u: unsigned long int * %p: void* (e.g. 0x00123456) @@ -41,10 +41,10 @@ int mbed_printf(const char *format, ...); /** * Minimal snprintf * - * Prints directly to buffer without using malloc. - * Doesn't suppoet any modifiers. + * Prints directly to buffer without using malloc. + * Doesn't suppoet any modifiers. * - * Supports: + * Supports: * %d: signed long int * %u: unsigned long int * %p: void* (e.g. 0x00123456) @@ -53,6 +53,36 @@ int mbed_printf(const char *format, ...); */ int mbed_snprintf(char* buffer, size_t length, const char* format, ...); +/** + * Minimal printf + * + * Prints directly to stdio/UART without using malloc. + * Doesn't suppoet any modifiers. + * + * Supports: + * %d: signed long int + * %u: unsigned long int + * %p: void* (e.g. 0x00123456) + * %s: string + * %X: unsigned char printed as hexadecimal number (e.g., FF) + */ +int mbed_vprintf(const char* format, va_list arguments); + +/** + * Minimal snprintf + * + * Prints directly to buffer without using malloc. + * Doesn't suppoet any modifiers. + * + * Supports: + * %d: signed long int + * %u: unsigned long int + * %p: void* (e.g. 0x00123456) + * %s: string + * %X: unsigned char printed as hexadecimal number (e.g., FF) + */ +int mbed_vsnprintf(char* buffer, size_t length, const char* format, va_list arguments); + #ifdef __cplusplus } #endif From 3be1165fe73d0b683e027fea005eeecd0f6bd4f1 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Thu, 26 Oct 2017 07:28:15 -0700 Subject: [PATCH 09/36] Add support for width specifiers --- features/minimal-printf/README.md | 14 +- .../TESTS/minimal-printf/compliance/main.cpp | 594 ++++++++++++++++ features/minimal-printf/mbed_lib.json | 10 +- features/minimal-printf/mbed_printf.c | 436 +----------- features/minimal-printf/mbed_printf.h | 32 - .../mbed_printf_implementation.c | 635 ++++++++++++++++++ .../mbed_printf_implementation.h | 24 + features/minimal-printf/mbed_printf_wrapper.c | 79 +++ 8 files changed, 1348 insertions(+), 476 deletions(-) create mode 100755 features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp mode change 100755 => 100644 features/minimal-printf/mbed_printf.c create mode 100755 features/minimal-printf/mbed_printf_implementation.c create mode 100644 features/minimal-printf/mbed_printf_implementation.h create mode 100644 features/minimal-printf/mbed_printf_wrapper.c diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md index b21d3bd483..1838368a45 100755 --- a/features/minimal-printf/README.md +++ b/features/minimal-printf/README.md @@ -1,15 +1,15 @@ # Minimal printf and snprintf -Library supports both printf and snprintf in 960 bytes of flash. +Library supports both printf and snprintf in 1252 bytes of flash. -Prints directly to stdio/UART without using malloc. All flags, length, and precision modifiers are ignored. Floating point is disabled by default. +Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored. Floating point is disabled by default. Supports: -* %d: signed long int. -* %i: signed long int. -* %u: unsigned long int. -* %x: unsigned char printed as hexadecimal number (e.g., FF). -* %X: unsigned char printed as hexadecimal number (e.g., FF). +* %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). * %g: floating point (disabled by default). diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp new file mode 100755 index 0000000000..e526476f69 --- /dev/null +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -0,0 +1,594 @@ +/* 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.h" +#include "mbed_printf.h" + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include +#include +#include +#include + +#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; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MIN); + result_baseline = printf("hhd: %hhd\r\n", SCHAR_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MAX); + result_baseline = printf("hhd: %hhd\r\n", SCHAR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN); + result_baseline = printf("hd: %hd\r\n", SHRT_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX); + result_baseline = printf("hd: %hd\r\n", SHRT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("d: %d\r\n", INT_MIN); + result_baseline = printf("d: %d\r\n", INT_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("d: %d\r\n", INT_MAX); + result_baseline = printf("d: %d\r\n", INT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN); + result_baseline = printf("ld: %ld\r\n", LONG_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX); + result_baseline = printf("ld: %ld\r\n", LONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN); + result_baseline = printf("lld: %lld\r\n", LLONG_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MAX); + result_baseline = printf("lld: %lld\r\n", LLONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + printf("%%jd not supported by mbed\r\n"); + + result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN); + result_baseline = printf("jd: %jd\r\n", INT32_MIN); + TEST_ASSERT_EQUAL_INT(18, result_minimal); + + result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX); + result_baseline = printf("jd: %jd\r\n", INT32_MAX); + TEST_ASSERT_EQUAL_INT(17, result_minimal); + + printf("%%zd not supported by mbed\r\n"); + + result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN); + result_baseline = printf("zd: %zd\r\n", INT32_MIN); + TEST_ASSERT_EQUAL_INT(18, result_minimal); + + result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX); + result_baseline = printf("zd: %zd\r\n", INT32_MAX); + TEST_ASSERT_EQUAL_INT(17, result_minimal); + + printf("%%td not supported by mbed\r\n"); + + result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN); + result_baseline = printf("td: %td\r\n", PTRDIFF_MIN); + TEST_ASSERT_EQUAL_INT(18, result_minimal); + + result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); + result_baseline = printf("td: %td\r\n", PTRDIFF_MAX); + TEST_ASSERT_EQUAL_INT(17, result_minimal); + + return CaseNext; +} + +static control_t test_printf_u(const size_t call_count) +{ + int result_baseline; + int result_minimal; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhu: %hhu\r\n", 0); + result_baseline = printf("hhu: %hhu\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hhu: %hhu\r\n", UCHAR_MAX); + result_baseline = printf("hhu: %hhu\r\n", UCHAR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hu: %hu\r\n", 0); + result_baseline = printf("hu: %hu\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX); + result_baseline = printf("hu: %hu\r\n", USHRT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("u: %u\r\n", 0); + result_baseline = printf("u: %u\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("u: %u\r\n", UINT_MAX); + result_baseline = printf("u: %u\r\n", UINT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lu: %lu\r\n", 0); + result_baseline = printf("lu: %lu\r\n", 0UL); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX); + result_baseline = printf("lu: %lu\r\n", ULONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("llu: %llu\r\n", 0); + result_baseline = printf("llu: %llu\r\n", 0ULL); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("llu: %llu\r\n", ULLONG_MAX); + result_baseline = printf("llu: %llu\r\n", ULLONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("ju: %ju\r\n", 0); + result_baseline = printf("ju: %ju\r\n",(uintmax_t) 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); + + result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); + result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX); + TEST_ASSERT_EQUAL_INT(8, result_minimal); + + result_minimal = mbed_printf("zu: %zu\r\n", 0); + result_baseline = printf("zu: %zu\r\n", 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); + + result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); + result_baseline = printf("zu: %zu\r\n", SIZE_MAX); + TEST_ASSERT_EQUAL_INT(17, result_minimal); + + result_minimal = mbed_printf("tu: %tu\r\n", 0); + result_baseline = printf("tu: %tu\r\n", 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); + + result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); + result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX); + TEST_ASSERT_EQUAL_INT(27, result_minimal); + + return CaseNext; +} + +static control_t test_printf_x(const size_t call_count) +{ + int result_baseline; + int result_minimal; + + /*************************************************************************/ + /*************************************************************************/ + printf("%%x always prints even characters\r\n"); + + result_minimal = mbed_printf("hhx: %hhx\r\n", 0); + result_baseline = printf("hhx: %hhx\r\n", 0); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("hhx: %hhx\r\n", UCHAR_MAX); + result_baseline = printf("hhx: %hhx\r\n", UCHAR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hx: %hx\r\n", 0); + result_baseline = printf("hx: %hx\r\n", 0); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("hx: %hx\r\n", USHRT_MAX); + result_baseline = printf("hx: %hx\r\n", USHRT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("x: %x\r\n", 0); + result_baseline = printf("x: %x\r\n", 0); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("x: %x\r\n", UINT_MAX); + result_baseline = printf("x: %x\r\n", UINT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("x: %x\r\n", 0); + result_baseline = printf("x: %x\r\n", 0); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("lx: %lx\r\n", ULONG_MAX); + result_baseline = printf("lx: %lx\r\n", ULONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("llx: %llx\r\n", 0); + result_baseline = printf("llx: %llx\r\n", 0ULL); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("llx: %llx\r\n", ULLONG_MAX); + result_baseline = printf("llx: %llx\r\n", ULLONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("jx: %jx\r\n", 0); + result_baseline = printf("jx: %jx\r\n", (uintmax_t) 0); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("jx: %jx\r\n", UINTMAX_MAX); + result_baseline = printf("jx: %jx\r\n", UINTMAX_MAX); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("zx: %zx\r\n", 0); + result_baseline = printf("zx: %zx\r\n", 0); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("zx: %zx\r\n", SIZE_MAX); + result_baseline = printf("zx: %zx\r\n", SIZE_MAX); + TEST_ASSERT_EQUAL_INT(15, result_minimal); + + result_minimal = mbed_printf("tx: %tx\r\n", 0); + result_baseline = printf("tx: %tx\r\n", 0); + TEST_ASSERT_EQUAL_INT(9, result_minimal); + + result_minimal = mbed_printf("tx: %tx\r\n", UINTPTR_MAX); + result_baseline = printf("tx: %tx\r\n", UINTPTR_MAX); + TEST_ASSERT_EQUAL_INT(23, result_minimal); + +// result_minimal = mbed_snprintf(buffer_minimal, 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); + + 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); + + printf("%%jd not supported by mbed\r\n"); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", INT32_MIN); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", INT32_MIN); + TEST_ASSERT_EQUAL_STRING("jd: -2147483648\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(18, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", INT32_MAX); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", INT32_MAX); + TEST_ASSERT_EQUAL_STRING("jd: 2147483647\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(17, result_minimal); + + printf("%%zd not supported by mbed\r\n"); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", INT32_MIN); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", INT32_MIN); + TEST_ASSERT_EQUAL_STRING("zd: -2147483648\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(18, result_minimal); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", INT32_MAX); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", INT32_MAX); + TEST_ASSERT_EQUAL_STRING("zd: 2147483647\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(17, result_minimal); + + printf("%%td not supported by mbed\r\n"); + + 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(18, 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(17, result_minimal); + + 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", 0); + 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", 0); + 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); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", 0); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0); + TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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(8, result_minimal); + + 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("zu: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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(17, result_minimal); + + 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("tu: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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(27, result_minimal); + + 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; + + /*************************************************************************/ + /*************************************************************************/ + printf("%%x always prints even characters\r\n"); + + 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(9, 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(9, 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_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", 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(9, 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), "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(9, 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", 0); + 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(9, 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); + + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jx: %jx\r\n", 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(9, 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(9, result_minimal); + + 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(9, 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(15, result_minimal); + + 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(9, 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(23, result_minimal); + +// result_minimal = mbed_snprintf(buffer_minimal, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi); +// mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "%s\r\n", buffer); + +// mbed_printf("results: %d\r\n", result); + + return CaseNext; +} + +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("printf %u", test_printf_u), + Case("printf %x", test_printf_x), + Case("snprintf %d", test_snprintf_d), + Case("snprintf %u", test_snprintf_u), + Case("snprintf %x", test_snprintf_x), +}; + +Specification specification(greentea_setup, cases, greentea_test_teardown_handler); + +int main() +{ + return !Harness::run(specification); +} diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json index 5b536f7b76..1a595a0d33 100755 --- a/features/minimal-printf/mbed_lib.json +++ b/features/minimal-printf/mbed_lib.json @@ -1,13 +1,17 @@ { "name": "minimal-printf", "config": { - "floating-point": { + "enable-floating-point": { "help": "Enable floating point printing", "value": false }, - "floating-point-max-decimals": { + "set-floating-point-max-decimals": { "help": "Maximum number of decimals to be printed", - "value": 3 + "value": 16 + }, + "enable-64-bit": { + "help": "Enable printing 64 bit integers", + "value": true } } } diff --git a/features/minimal-printf/mbed_printf.c b/features/minimal-printf/mbed_printf.c old mode 100755 new mode 100644 index d6800d7782..41566989e9 --- a/features/minimal-printf/mbed_printf.c +++ b/features/minimal-printf/mbed_printf.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited + * 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. @@ -14,442 +14,12 @@ * limitations under the License. */ -#include "mbed_printf.h" +#include "mbed_printf_implementation.h" -#include -#include #include -#include - -/* module variable for keeping track of initialization */ -static bool not_initialized = true; - -/***************************/ -/* MBED */ -/***************************/ -#if TARGET_LIKE_MBED -#include "hal/serial_api.h" - -#if DEVICE_SERIAL -static serial_t stdio_uart = { 0 }; -//#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES -//static char stdio_in_prev = 0; -//static char stdio_out_prev = 0; -//#endif -#endif - -static void init_serial() -{ - if (not_initialized) - { - not_initialized = false; - -#if DEVICE_SERIAL - 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 -#endif - } -} - -#define MBED_INITIALIZE_PRINT(x) { init_serial(); } -#define MBED_PRINT_CHARACTER(x) { serial_putc(&stdio_uart, x); } - -/***************************/ -/* Linux */ -/***************************/ -#else -#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT 1 -#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS 10 -#define MBED_INITIALIZE_PRINT(x) { ; } -#define MBED_PRINT_CHARACTER(x) { printf("%c", x); } -#endif - -static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value); -static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value); -static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value); -static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value); -static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character); -static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string); - -#ifndef MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT -#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT 0 -#endif - -#ifndef MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS -#define MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS 0 -#endif - -static void mbed_minimal_formatted_string_long_int(char* buffer, size_t length, int* result, long int value) -{ - /* only continue if buffer can fit at least 1 characters */ - if ((*result + 1) <= (long int) length) - { - unsigned long int new_value = 0; - - /* if value is negative print sign and treat as positive number */ - if (value < 0) - { - /* write sign */ - if (buffer) - { - buffer[*result] = '-'; - } - else - { - MBED_PRINT_CHARACTER('-'); - } - - *result += 1; - - /* get absolute value */ - new_value = (unsigned long int) (-1 * value); - } - else - { - new_value = (unsigned long int) value; - } - - /* use unsigned long int function */ - mbed_minimal_formatted_string_unsigned_long_int(buffer, length, result, new_value); - } -} - -static void mbed_minimal_formatted_string_unsigned_long_int(char* buffer, size_t length, int* result, unsigned long int value) -{ - /* only continue if buffer can fit at least 1 characters */ - if ((*result + 1) <= (long int) length) - { - /* treat 0 as a corner case */ - if (value == 0) - { - if (buffer) - { - buffer[*result] = '0'; - } - else - { - MBED_PRINT_CHARACTER('0'); - } - - *result += 1; - } - else - { - /* allocate 3 digits per byte */ - char scratch[sizeof(unsigned long int) * 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 ( ; (*result < (long int) length) && (index > 0); index--) - { - if (buffer) - { - buffer[*result] = scratch[index - 1]; - } - else - { - MBED_PRINT_CHARACTER(scratch[index - 1]); - } - - *result += 1; - } - } - } -} - -static void mbed_minimal_formatted_string_unsigned_char(char* buffer, size_t length, int* result, int value) -{ - /* only continue if buffer can fit at least 2 characters */ - if ((*result + 2) <= (long int) length) - { - unsigned int nibble_one = (value & 0xFF) >> 4; - unsigned int nibble_two = (value & 0x0F); - - const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - if (buffer) - { - buffer[*result] = int2hex[nibble_one]; - buffer[*result + 1] = int2hex[nibble_two]; - } - else - { - MBED_PRINT_CHARACTER(int2hex[nibble_one]); - MBED_PRINT_CHARACTER(int2hex[nibble_two]); - } - - *result += 2; - } -} - -static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value) -{ - /* only continue if buffer can fit '0x' and twice the size of a void* */ - if ((*result + 2 + 2 * sizeof(void*)) <= length) - { - if (buffer) - { - buffer[*result] = '0'; - buffer[*result + 1] = 'x'; - } - else - { - MBED_PRINT_CHARACTER('0'); - MBED_PRINT_CHARACTER('x'); - } - - *result += 2; - - for (size_t index = 0; index < sizeof(void*); index++) - { - unsigned char byte = (unsigned char) (((unsigned long int) value) >> (8 * (sizeof(void*) - index - 1))); - - mbed_minimal_formatted_string_unsigned_char(buffer, length, result, byte); - } - } -} - -#if MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT -static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value) -{ - /* only continue if buffer can fit at least 1 characters */ - if ((*result + 1) <= (long int) length) - { - /* get integer part */ - long int integer = value; - - /* write integer part */ - mbed_minimal_formatted_string_long_int(buffer, length, result, integer); - - /* write decimal point */ - mbed_minimal_formatted_string_character(buffer, length, result, '.'); - - /* get decimal part */ - double precision = 1.0; - - for (size_t index = 0; index < MBED_CONF_MINIMAL_PRINTF_FLOATING_POINT_MAX_DECIMALS; index++) - { - precision *= 10; - } - - long int decimal = (value - integer) * precision; - - /* take absolute value */ - if (decimal < 0) - { - decimal = -1 * decimal; - } - - /* write decimal part */ - mbed_minimal_formatted_string_long_int(buffer, length, result, decimal); - } -} -#endif - -static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, int character) -{ - /* only continue if the buffer can fit 1 character */ - if ((*result + 1) <= (long int) length) - { - if (buffer) - { - buffer[*result] = (char) character; - } - else - { - MBED_PRINT_CHARACTER((char) character); - } - - *result += 1; - } -} - -static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string) -{ - /* only continue if the buffer can fit at least 1 character */ - if ((*result + 1) <= (long int) length) - { - /* count characters in string */ - size_t remaining = length - *result; - size_t string_length = 0; - - /* only count characters that will fit into buffer */ - while ((string[string_length] != '\0') && (string_length < remaining)) - { - string_length++; - } - - /* copy string to buffer */ - if (buffer) - { - for (size_t index = 0; index < string_length; index++) - { - buffer[*result + index] = string[index]; - } - } - /* print string */ - else - { - for (size_t index = 0; index < string_length; index++) - { - MBED_PRINT_CHARACTER(string[index]); - } - } - - /* add length to counter */ - *result += string_length; - } -} - -static int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments) -{ - int result = 0; - - /* if writing to buffer, reserve space for NULL termination */ - if (buffer) - { - length--; - } - - /* parse string */ - for (size_t index = 0; format[index] != '\0'; index++) - { - /* format specifier begin */ - if (format[index] == '%') - { - size_t next_index = index + 1; - - /* while there is room in buffer and format string is not empty */ - while ((next_index < length) && (format[next_index] != '\0') && - /* skip all size modifiers */ - (((format[next_index] >= '0') && (format[next_index] <= '9')) || - (format[next_index] == 'h') || - (format[next_index] == 'l') || - (format[next_index] == 'j') || - (format[next_index] == 'z') || - (format[next_index] == 't') || - (format[next_index] == 'L') || - (format[next_index] == '.'))) - { - /* skip to next character */ - next_index++; - } - - /* read out character - this a supported format character, '\0', or a not suported character */ - char next = format[next_index]; - - /* signed integer */ - if ((next == 'd') || (next == 'i')) - { - long int value = va_arg(arguments, long int); - index = next_index; - - mbed_minimal_formatted_string_long_int(buffer, length, &result, value); - } - /* unsigned integer */ - else if (next == 'u') - { - unsigned long int value = va_arg(arguments, unsigned long int); - index = next_index; - - mbed_minimal_formatted_string_unsigned_long_int(buffer, length, &result, value); - } - /* treat both hexadecimeal modifiers the same */ - else if ((next == 'x') || (next == 'X')) - { - int value = va_arg(arguments, int); - index = next_index; - - mbed_minimal_formatted_string_unsigned_char(buffer, length, &result, value); - } -#if MBED_CONF_MINIMAL_PRINTF_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); - } -#endif - /* character */ - else if (next == 'c') - { - int value = va_arg(arguments, int); - index = next_index; - - mbed_minimal_formatted_string_character(buffer, length, &result, value); - } - /* string */ - else if (next == 's') - { - char* value = va_arg(arguments, char*); - index = next_index; - - mbed_minimal_formatted_string_string(buffer, length, &result, value); - } - /* pointer */ - else if (next == 'p') - { - void* value = va_arg(arguments, void*); - index = next_index; - - mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); - } - else - { - /* write all characters between format beginning and unrecognied modifier */ - while (index < next_index) - { - mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); - 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]); - } - else - { - /* break out of for loop */ - break; - } - } - } - else - { - mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); - } - } - - /* if writing to buffer, NULL terminate string in reserved space*/ - if (buffer) - { - buffer[result] = '\0'; - } - - return result; -} int mbed_printf(const char *format, ...) { - MBED_INITIALIZE_PRINT(); - va_list arguments; va_start(arguments, format); int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments); @@ -460,8 +30,6 @@ int mbed_printf(const char *format, ...) int mbed_snprintf(char* buffer, size_t length, const char* format, ...) { - MBED_INITIALIZE_PRINT(); - va_list arguments; va_start(arguments, format); int result = mbed_minimal_formatted_string(buffer, length, format, arguments); diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h index f64358f1bf..b1617a0f2a 100755 --- a/features/minimal-printf/mbed_printf.h +++ b/features/minimal-printf/mbed_printf.h @@ -27,14 +27,6 @@ extern "C" { * Minimal printf * * Prints directly to stdio/UART without using malloc. - * Doesn't suppoet any modifiers. - * - * Supports: - * %d: signed long int - * %u: unsigned long int - * %p: void* (e.g. 0x00123456) - * %s: string - * %X: unsigned char printed as hexadecimal number (e.g., FF) */ int mbed_printf(const char *format, ...); @@ -42,14 +34,6 @@ int mbed_printf(const char *format, ...); * Minimal snprintf * * Prints directly to buffer without using malloc. - * Doesn't suppoet any modifiers. - * - * Supports: - * %d: signed long int - * %u: unsigned long int - * %p: void* (e.g. 0x00123456) - * %s: string - * %X: unsigned char printed as hexadecimal number (e.g., FF) */ int mbed_snprintf(char* buffer, size_t length, const char* format, ...); @@ -57,14 +41,6 @@ int mbed_snprintf(char* buffer, size_t length, const char* format, ...); * Minimal printf * * Prints directly to stdio/UART without using malloc. - * Doesn't suppoet any modifiers. - * - * Supports: - * %d: signed long int - * %u: unsigned long int - * %p: void* (e.g. 0x00123456) - * %s: string - * %X: unsigned char printed as hexadecimal number (e.g., FF) */ int mbed_vprintf(const char* format, va_list arguments); @@ -72,14 +48,6 @@ int mbed_vprintf(const char* format, va_list arguments); * Minimal snprintf * * Prints directly to buffer without using malloc. - * Doesn't suppoet any modifiers. - * - * Supports: - * %d: signed long int - * %u: unsigned long int - * %p: void* (e.g. 0x00123456) - * %s: string - * %X: unsigned char printed as hexadecimal number (e.g., FF) */ int mbed_vsnprintf(char* buffer, size_t length, const char* format, va_list arguments); diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c new file mode 100755 index 0000000000..99d4b14f2b --- /dev/null +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -0,0 +1,635 @@ +/* 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" + + + +/***************************/ +/* MBED */ +/***************************/ +#if TARGET_LIKE_MBED +#include "hal/serial_api.h" + +#if DEVICE_SERIAL +static serial_t stdio_uart = { 0 }; +#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES +static char mbed_stdio_out_prev = 0; +#endif +#endif + +/* module variable for keeping track of initialization */ +static bool not_initialized = true; + +static void init_serial() +{ + if (not_initialized) + { + not_initialized = false; + +#if DEVICE_SERIAL + 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 +#endif + } +} + +#define MBED_INITIALIZE_PRINT(x) { init_serial(); } +#define MBED_PRINT_CHARACTER(x) { serial_putc(&stdio_uart, x); } + +/***************************/ +/* Linux */ +/***************************/ +#else +#define MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 1 +#define MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 16 +#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 16 +#endif + +#ifndef MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT +#define MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT 1 +#endif + +#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 + +typedef enum { + LENGTH_NONE, + LENGTH_HH, + LENGTH_H, + LENGTH_L, + LENGTH_LL, + LENGTH_J, + LENGTH_Z, + LENGTH_T, + LENGTH_CAPITAL_L +} length_t; + +static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value); +static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); +static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); + +static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value); +static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character); +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string); + +static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value) +{ + /* only continue if buffer can fit at least 1 characters */ + if ((size_t)(*result + 1) <= length) + { + MBED_UNSIGNED_STORAGE new_value = 0; + + /* if value is negative print sign and treat as positive number */ + if (value < 0) + { + /* write sign */ + if (buffer) + { + buffer[*result] = '-'; + } + else + { + MBED_PRINT_CHARACTER('-'); + } + + *result += 1; + + /* get absolute value */ + new_value = (-1 * value); + } + else + { + new_value = value; + } + + /* use unsigned long int function */ + mbed_minimal_formatted_string_unsigned(buffer, length, result, new_value); + } +} + +static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value) +{ + /* only continue if buffer can fit at least 1 characters */ + if ((size_t)(*result + 1) <= length) + { + /* treat 0 as a corner case */ + if (value == 0) + { + if (buffer) + { + buffer[*result] = '0'; + } + else + { + MBED_PRINT_CHARACTER('0'); + } + + *result += 1; + } + 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 ( ; ((size_t)*result < length) && (index > 0); index--) + { + if (buffer) + { + buffer[*result] = scratch[index - 1]; + } + else + { + MBED_PRINT_CHARACTER(scratch[index - 1]); + } + + *result += 1; + } + } + } +} + +static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value) +{ + bool print_leading_zero = false; + + /* only continue each loop if buffer can fit at least 2 characters */ + for (ssize_t index = 7; (((size_t)(*result + 2) <= length)) && (index >= 0); index--) + { + uint8_t output = value >> (8 * index); + + if (print_leading_zero || (output != 0) || (index == 0)) + { + print_leading_zero = true; + + unsigned int nibble_one = (output >> 4); + unsigned int nibble_two = (output & 0x0F); + + const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + if (buffer) + { + buffer[*result] = int2hex[nibble_one]; + buffer[*result + 1] = int2hex[nibble_two]; + } + else + { + MBED_PRINT_CHARACTER(int2hex[nibble_one]); + MBED_PRINT_CHARACTER(int2hex[nibble_two]); + } + + *result += 2; + } + } +} + +static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value) +{ + /* only continue if buffer can fit '0x' and twice the size of a void* */ + if ((*result + 2 + 2 * sizeof(void*)) <= length) + { + if (buffer) + { + buffer[*result] = '0'; + buffer[*result + 1] = 'x'; + } + else + { + MBED_PRINT_CHARACTER('0'); + MBED_PRINT_CHARACTER('x'); + } + + *result += 2; + + mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value); + } +} + +#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT +static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value) +{ + /* only continue if buffer can fit at least 1 characters */ + if ((size_t)(*result + 1) <= length) + { + /* get integer part */ + long int integer = value; + + /* write integer part */ + mbed_minimal_formatted_string_signed(buffer, length, result, integer); + + /* write decimal point */ + mbed_minimal_formatted_string_character(buffer, length, result, '.'); + + /* 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; + } + + long int decimal = (value - integer) * precision; + + /* take absolute value */ + if (decimal < 0) + { + decimal = -1 * decimal; + } + + /* write decimal part */ + mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal); + } +} +#endif + +static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character) +{ + /* only continue if the buffer can fit 1 character */ + if ((size_t)(*result + 1) <= length) + { + if (buffer) + { + buffer[*result] = character; + } + else + { +#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES + if (character == '\n' && mbed_stdio_out_prev != '\r') + { + MBED_PRINT_CHARACTER('\r'); + *result += 1; + } + mbed_stdio_out_prev = character; +#endif + + MBED_PRINT_CHARACTER(character); + } + + *result += 1; + } +} + +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string) +{ + /* only continue if the buffer can fit at least 1 character */ + if ((*result + 1) <= (long int) length) + { + /* count characters in string */ + size_t remaining = length - *result; + size_t string_length = 0; + + /* only count characters that will fit into buffer */ + while ((string[string_length] != '\0') && (string_length < remaining)) + { + string_length++; + } + + /* copy string to buffer */ + if (buffer) + { + for (size_t index = 0; index < string_length; index++) + { + buffer[*result + index] = string[index]; + } + } + /* print string */ + else + { + for (size_t index = 0; index < string_length; index++) + { + MBED_PRINT_CHARACTER(string[index]); + } + } + + /* add length to counter */ + *result += string_length; + } +} + +int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments) +{ + MBED_INITIALIZE_PRINT(); + + int result = 0; + + /* if writing to buffer, reserve space for NULL termination */ + if (buffer) + { + length--; + } + + /* parse string */ + for (size_t index = 0; format[index] != '\0'; index++) + { + /* format specifier begin */ + if (format[index] == '%') + { + size_t next_index = index + 1; + + /* while there is room in buffer and format string is not empty */ + while ((next_index < length) && (format[next_index] != '\0') && + /* skip all flags and precision modifiers */ + (((format[next_index] >= '0') && (format[next_index] <= '9')) || + (format[next_index] == '-') || + (format[next_index] == '+') || + (format[next_index] == '#') || + (format[next_index] == '.'))) + { + /* skip to next character */ + next_index++; + } + + length_t length_modifier = LENGTH_NONE; + + /* look for two character length modifier */ + if (format[next_index + 1] != '\0') + { + 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; + } + + /* increment next_index if length modifier was found */ + if (length_modifier != LENGTH_NONE) + { + next_index += 2; + } + } + + /* look for one character length modifier if two character search failed */ + if ((length_modifier == LENGTH_NONE) && (format[next_index] != '\0')) + { + 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 next_index if length modifier was found */ + if (length_modifier != LENGTH_NONE) + { + next_index++; + } + } + + /* read out character - this 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 (((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)))) + { + value = va_arg(arguments, MBED_SIGNED_STORAGE); + } + else +#endif + { + value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE); + } + + 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_Z: + value = (ssize_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); + } + /* unsigned integer */ + else if ((next == 'u') || (next == 'x') || (next == 'X')) + { + MBED_UNSIGNED_STORAGE value = 0; + +#if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT + 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)))) + { + value = va_arg(arguments, MBED_UNSIGNED_STORAGE); + } + else +#endif + { + value = va_arg(arguments, MBED_UNSIGNED_NATIVE_TYPE); + } + + 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; + + if (next == 'u') + { + mbed_minimal_formatted_string_unsigned(buffer, length, &result, value); + } + else + { + mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value); + } + } +#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); + } +#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); + } + /* string */ + else if (next == 's') + { + char* value = va_arg(arguments, char*); + index = next_index; + + mbed_minimal_formatted_string_string(buffer, length, &result, value); + } + /* pointer */ + else if (next == 'p') + { + void* value = va_arg(arguments, void*); + index = next_index; + + mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); + } + else + { + /* write all characters between format beginning and unrecognied modifier */ + while (index < next_index) + { + mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); + 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]); + } + else + { + /* break out of for loop */ + break; + } + } + } + else + { + mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); + } + } + + /* if writing to buffer, NULL terminate string in reserved space*/ + if (buffer) + { + buffer[result] = '\0'; + } + + return result; +} diff --git a/features/minimal-printf/mbed_printf_implementation.h b/features/minimal-printf/mbed_printf_implementation.h new file mode 100644 index 0000000000..337727a52b --- /dev/null +++ b/features/minimal-printf/mbed_printf_implementation.h @@ -0,0 +1,24 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +//#include +//#include +//#include +//#include + +int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments); diff --git a/features/minimal-printf/mbed_printf_wrapper.c b/features/minimal-printf/mbed_printf_wrapper.c new file mode 100644 index 0000000000..f6b0d76435 --- /dev/null +++ b/features/minimal-printf/mbed_printf_wrapper.c @@ -0,0 +1,79 @@ +/* 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 + +#if defined(TOOLCHAIN_GCC) +#define SUB_PRINTF __wrap_printf +#define SUB_SNPRINTF __wrap_snprintf +#define SUB_SPRINTF __wrap_sprintf +#define SUB_VSNPRINTF __wrap_vsnprintf +#elif defined(TOOLCHAIN_ARM) +#define SUPER_PRINTF $Super$$printf +#define SUB_PRINTF $Sub$$printf +#define SUPER_SNPRINTF $Super$$snprintf +#define SUB_SNPRINTF $Sub$$snprintf +#define SUPER_SPRINTF $Super$$sprintf +#define SUB_SPRINTF $Sub$$sprintf +#define SUPER_VSNPRINTF $Super$$vsnprintf +#define SUB_VSNPRINTF $Sub$$vsnprintf +#elif defined(__ICCARM__) +#define SUPER_PRINTF $Super$$__iar_printf +#define SUB_PRINTF $Sub$$__iar_printf +#define SUPER_SNPRINTF $Super$$__iar_snprintf +#define SUB_SNPRINTF $Sub$$__iar_snprintf +#define SUPER_SPRINTF $Super$$__iar_sprintf +#define SUB_SPRINTF $Sub$$__iar_sprintf +#define SUPER_VSNPRINTF $Super$$__iar_vsnprintf +#define SUB_VSNPRINTF $Sub$$__iar_vsnprintf +#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); + 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); + 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); + va_end(arguments); + + return result; +} + +int SUB_VSNPRINTF(char* buffer, size_t length, const char* format, va_list arguments) +{ + return mbed_minimal_formatted_string(buffer, length, format, arguments); +} From 3da20573282450b10b4d613859441dfd207b3e1f Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Thu, 26 Oct 2017 08:56:00 -0700 Subject: [PATCH 10/36] Add test case --- .../TESTS/minimal-printf/compliance/main.cpp | 457 +++++++++--------- features/minimal-printf/mbed_printf.h | 1 + .../mbed_printf_implementation.h | 4 - 3 files changed, 229 insertions(+), 233 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index e526476f69..4c253c83a0 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -56,28 +56,28 @@ static control_t test_printf_d(const size_t call_count) result_baseline = printf("hhd: %hhd\r\n", SCHAR_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN); - result_baseline = printf("hd: %hd\r\n", SHRT_MIN); + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN); + result_baseline = printf("hd: %hd\r\n", SHRT_MIN); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX); - result_baseline = printf("hd: %hd\r\n", SHRT_MAX); + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX); + result_baseline = printf("hd: %hd\r\n", SHRT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("d: %d\r\n", INT_MIN); - result_baseline = printf("d: %d\r\n", INT_MIN); + result_minimal = mbed_printf("d: %d\r\n", INT_MIN); + result_baseline = printf("d: %d\r\n", INT_MIN); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("d: %d\r\n", INT_MAX); - result_baseline = printf("d: %d\r\n", INT_MAX); + result_minimal = mbed_printf("d: %d\r\n", INT_MAX); + result_baseline = printf("d: %d\r\n", INT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN); - result_baseline = printf("ld: %ld\r\n", LONG_MIN); + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN); + result_baseline = printf("ld: %ld\r\n", LONG_MIN); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX); - result_baseline = printf("ld: %ld\r\n", LONG_MAX); + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX); + result_baseline = printf("ld: %ld\r\n", LONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN); @@ -90,34 +90,34 @@ static control_t test_printf_d(const size_t call_count) printf("%%jd not supported by mbed\r\n"); - result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN); - result_baseline = printf("jd: %jd\r\n", INT32_MIN); - TEST_ASSERT_EQUAL_INT(18, result_minimal); - - result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX); - result_baseline = printf("jd: %jd\r\n", INT32_MAX); + result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN); + result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MIN); TEST_ASSERT_EQUAL_INT(17, result_minimal); + result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX); + result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MAX); + TEST_ASSERT_EQUAL_INT(16, result_minimal); + printf("%%zd not supported by mbed\r\n"); - result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN); - result_baseline = printf("zd: %zd\r\n", INT32_MIN); - TEST_ASSERT_EQUAL_INT(18, result_minimal); - - result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX); - result_baseline = printf("zd: %zd\r\n", INT32_MAX); + result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN); + result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MIN); TEST_ASSERT_EQUAL_INT(17, result_minimal); + result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX); + result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MAX); + TEST_ASSERT_EQUAL_INT(16, result_minimal); + printf("%%td not supported by mbed\r\n"); - result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN); - result_baseline = printf("td: %td\r\n", PTRDIFF_MIN); - TEST_ASSERT_EQUAL_INT(18, result_minimal); - - result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); - result_baseline = printf("td: %td\r\n", PTRDIFF_MAX); + result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN); + result_baseline = printf("td: %td\r\n", PTRDIFF_MIN); TEST_ASSERT_EQUAL_INT(17, result_minimal); + result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); + result_baseline = printf("td: %td\r\n", PTRDIFF_MAX); + TEST_ASSERT_EQUAL_INT(16, result_minimal); + return CaseNext; } @@ -136,28 +136,28 @@ static control_t test_printf_u(const size_t call_count) result_baseline = printf("hhu: %hhu\r\n", UCHAR_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("hu: %hu\r\n", 0); - result_baseline = printf("hu: %hu\r\n", 0); + result_minimal = mbed_printf("hu: %hu\r\n", 0); + result_baseline = printf("hu: %hu\r\n", 0); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX); - result_baseline = printf("hu: %hu\r\n", USHRT_MAX); + result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX); + result_baseline = printf("hu: %hu\r\n", USHRT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("u: %u\r\n", 0); - result_baseline = printf("u: %u\r\n", 0); + result_minimal = mbed_printf("u: %u\r\n", 0); + result_baseline = printf("u: %u\r\n", 0); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("u: %u\r\n", UINT_MAX); - result_baseline = printf("u: %u\r\n", UINT_MAX); + result_minimal = mbed_printf("u: %u\r\n", UINT_MAX); + result_baseline = printf("u: %u\r\n", UINT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("lu: %lu\r\n", 0); - result_baseline = printf("lu: %lu\r\n", 0UL); + result_minimal = mbed_printf("lu: %lu\r\n", 0); + result_baseline = printf("lu: %lu\r\n", 0UL); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX); - result_baseline = printf("lu: %lu\r\n", ULONG_MAX); + result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX); + result_baseline = printf("lu: %lu\r\n", ULONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("llu: %llu\r\n", 0); @@ -168,29 +168,29 @@ static control_t test_printf_u(const size_t call_count) result_baseline = printf("llu: %llu\r\n", ULLONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("ju: %ju\r\n", 0); - result_baseline = printf("ju: %ju\r\n",(uintmax_t) 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + result_minimal = mbed_printf("ju: %ju\r\n", 0); + result_baseline = printf("ju: %ju\r\n",(uintmax_t) 0); + TEST_ASSERT_EQUAL_INT(7, result_minimal); - result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); - result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); + result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX); + TEST_ASSERT_EQUAL_INT(7, result_minimal); - result_minimal = mbed_printf("zu: %zu\r\n", 0); - result_baseline = printf("zu: %zu\r\n", 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + result_minimal = mbed_printf("zu: %zu\r\n", 0); + result_baseline = printf("zu: %zu\r\n", 0); + TEST_ASSERT_EQUAL_INT(7, result_minimal); - result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); - result_baseline = printf("zu: %zu\r\n", SIZE_MAX); - TEST_ASSERT_EQUAL_INT(17, result_minimal); + result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); + result_baseline = printf("zu: %zu\r\n", SIZE_MAX); + TEST_ASSERT_EQUAL_INT(16, result_minimal); - result_minimal = mbed_printf("tu: %tu\r\n", 0); - result_baseline = printf("tu: %tu\r\n", 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + result_minimal = mbed_printf("tu: %tu\r\n", 0); + result_baseline = printf("tu: %tu\r\n", 0); + TEST_ASSERT_EQUAL_INT(7, result_minimal); - result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); - result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX); - TEST_ASSERT_EQUAL_INT(27, result_minimal); + result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); + result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX); + TEST_ASSERT_EQUAL_INT(26, result_minimal); return CaseNext; } @@ -204,69 +204,69 @@ static control_t test_printf_x(const size_t call_count) /*************************************************************************/ printf("%%x always prints even characters\r\n"); - result_minimal = mbed_printf("hhx: %hhx\r\n", 0); - result_baseline = printf("hhx: %hhx\r\n", 0); + result_minimal = mbed_printf("hhX: %hhX\r\n", 0); + result_baseline = printf("hhX: %hhX\r\n", 0); TEST_ASSERT_EQUAL_INT(9, result_minimal); - result_minimal = mbed_printf("hhx: %hhx\r\n", UCHAR_MAX); - result_baseline = printf("hhx: %hhx\r\n", UCHAR_MAX); + result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX); + result_baseline = printf("hhX: %hhX\r\n", UCHAR_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("hx: %hx\r\n", 0); - result_baseline = printf("hx: %hx\r\n", 0); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + result_minimal = mbed_printf("hX: %hX\r\n", 0); + result_baseline = printf("hX: %hX\r\n", 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); - result_minimal = mbed_printf("hx: %hx\r\n", USHRT_MAX); - result_baseline = printf("hx: %hx\r\n", USHRT_MAX); + result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX); + result_baseline = printf("hX: %hX\r\n", USHRT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("x: %x\r\n", 0); - result_baseline = printf("x: %x\r\n", 0); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + result_minimal = mbed_printf("X: %X\r\n", 0); + result_baseline = printf("X: %X\r\n", 0); + TEST_ASSERT_EQUAL_INT(7, result_minimal); - result_minimal = mbed_printf("x: %x\r\n", UINT_MAX); - result_baseline = printf("x: %x\r\n", UINT_MAX); + result_minimal = mbed_printf("X: %X\r\n", UINT_MAX); + result_baseline = printf("X: %X\r\n", UINT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("x: %x\r\n", 0); - result_baseline = printf("x: %x\r\n", 0); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + result_minimal = mbed_printf("lX: %lX\r\n", 0); + result_baseline = printf("lX: %lX\r\n", 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); - result_minimal = mbed_printf("lx: %lx\r\n", ULONG_MAX); - result_baseline = printf("lx: %lx\r\n", ULONG_MAX); + result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX); + result_baseline = printf("lX: %lX\r\n", ULONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("llx: %llx\r\n", 0); - result_baseline = printf("llx: %llx\r\n", 0ULL); + result_minimal = mbed_printf("llX: %llX\r\n", 0); + result_baseline = printf("llX: %llX\r\n", 0ULL); TEST_ASSERT_EQUAL_INT(9, result_minimal); - result_minimal = mbed_printf("llx: %llx\r\n", ULLONG_MAX); - result_baseline = printf("llx: %llx\r\n", ULLONG_MAX); + result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX); + result_baseline = printf("llX: %llX\r\n", ULLONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("jx: %jx\r\n", 0); - result_baseline = printf("jx: %jx\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + result_minimal = mbed_printf("jX: %jX\r\n", 0); + result_baseline = printf("jX: %jX\r\n", (uintmax_t) 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); - result_minimal = mbed_printf("jx: %jx\r\n", UINTMAX_MAX); - result_baseline = printf("jx: %jx\r\n", UINTMAX_MAX); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX); + result_baseline = printf("jX: %jX\r\n", UINTMAX_MAX); + TEST_ASSERT_EQUAL_INT(8, result_minimal); - result_minimal = mbed_printf("zx: %zx\r\n", 0); - result_baseline = printf("zx: %zx\r\n", 0); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + result_minimal = mbed_printf("zX: %zX\r\n", 0); + result_baseline = printf("zX: %zX\r\n", 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); - result_minimal = mbed_printf("zx: %zx\r\n", SIZE_MAX); - result_baseline = printf("zx: %zx\r\n", SIZE_MAX); - TEST_ASSERT_EQUAL_INT(15, result_minimal); + result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX); + result_baseline = printf("zX: %zX\r\n", SIZE_MAX); + TEST_ASSERT_EQUAL_INT(14, result_minimal); - result_minimal = mbed_printf("tx: %tx\r\n", 0); - result_baseline = printf("tx: %tx\r\n", 0); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + result_minimal = mbed_printf("tX: %tX\r\n", 0); + result_baseline = printf("tX: %tX\r\n", 0); + TEST_ASSERT_EQUAL_INT(8, result_minimal); - result_minimal = mbed_printf("tx: %tx\r\n", UINTPTR_MAX); - result_baseline = printf("tx: %tx\r\n", UINTPTR_MAX); - TEST_ASSERT_EQUAL_INT(23, result_minimal); + result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX); + result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX); + TEST_ASSERT_EQUAL_INT(22, result_minimal); // result_minimal = mbed_snprintf(buffer_minimal, 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); @@ -301,33 +301,33 @@ static control_t test_snprintf_d(const size_t call_count) 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); + 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); + 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); + 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); + 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); + 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); + 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); @@ -343,40 +343,40 @@ static control_t test_snprintf_d(const size_t call_count) printf("%%jd not supported by mbed\r\n"); - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", INT32_MIN); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", INT32_MIN); - TEST_ASSERT_EQUAL_STRING("jd: -2147483648\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(18, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", INT32_MAX); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jd: %jd\r\n", INT32_MAX); - TEST_ASSERT_EQUAL_STRING("jd: 2147483647\r\n", buffer_minimal); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", 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(17, result_minimal); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", 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(16, result_minimal); + printf("%%zd not supported by mbed\r\n"); - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", INT32_MIN); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", INT32_MIN); - TEST_ASSERT_EQUAL_STRING("zd: -2147483648\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(18, result_minimal); - - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", INT32_MAX); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zd: %zd\r\n", INT32_MAX); - TEST_ASSERT_EQUAL_STRING("zd: 2147483647\r\n", buffer_minimal); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", 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(17, result_minimal); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", 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(16, result_minimal); + printf("%%td not supported by mbed\r\n"); - 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(18, 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); + 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(17, 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(16, result_minimal); + return CaseNext; } @@ -399,33 +399,33 @@ static control_t test_snprintf_u(const size_t call_count) 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); + 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); + 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); + 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); + 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", 0); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lu: %lu\r\n", 0UL); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lu: %lu\r\n", 0); + 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); + 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); @@ -439,35 +439,35 @@ static control_t test_snprintf_u(const size_t call_count) 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", 0); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", 0); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0); + TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(7, 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(8, 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("ju: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(7, result_minimal); - 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("zu: 0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + 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("zu: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(7, 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(17, 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("zu: 4294967295\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(16, result_minimal); - 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("tu: 0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + 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("tu: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(7, 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(27, 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("tu: 18446744073709551615\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(26, result_minimal); return CaseNext; } @@ -483,85 +483,84 @@ static control_t test_snprintf_x(const size_t call_count) /*************************************************************************/ printf("%%x always prints even characters\r\n"); - 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); + 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("hhX: 00\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(9, 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); + 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(9, 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("hX: 00\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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); + 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("X: 00\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(7, 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), "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(9, result_minimal); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", 0); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lX: %lX\r\n", 0UL); + TEST_ASSERT_EQUAL_STRING("lX: 00\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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); + 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), "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); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", 0); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llX: %llX\r\n", 0ULL); + TEST_ASSERT_EQUAL_STRING("llX: 00\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(9, 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); + 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); - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llx: %llx\r\n", 0); - 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(9, result_minimal); + result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", 0); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", (uintmax_t) 0); + TEST_ASSERT_EQUAL_STRING("jX: 00\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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); + 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("jX: 00\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, result_minimal); - result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jx: %jx\r\n", 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(9, result_minimal); + 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("zX: 00\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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(9, 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("zX: FFFFFFFF\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(14, result_minimal); - 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(9, result_minimal); + 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("tX: 00\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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(15, result_minimal); - - 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(9, 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(23, 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("tX: FFFFFFFFFFFFFFFF\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(22, result_minimal); // result_minimal = mbed_snprintf(buffer_minimal, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi); // mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "%s\r\n", buffer); diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h index b1617a0f2a..0b8f6652bf 100755 --- a/features/minimal-printf/mbed_printf.h +++ b/features/minimal-printf/mbed_printf.h @@ -18,6 +18,7 @@ #define MBED_PRINTF_H #include +#include #ifdef __cplusplus extern "C" { diff --git a/features/minimal-printf/mbed_printf_implementation.h b/features/minimal-printf/mbed_printf_implementation.h index 337727a52b..a74d469dbf 100644 --- a/features/minimal-printf/mbed_printf_implementation.h +++ b/features/minimal-printf/mbed_printf_implementation.h @@ -16,9 +16,5 @@ #include #include -//#include -//#include -//#include -//#include int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments); From 8ec1d473a102d264ea23fe4df244ce583940de80 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Thu, 26 Oct 2017 13:28:08 -0700 Subject: [PATCH 11/36] Fixed bug in getting absolute value --- .../TESTS/minimal-printf/compliance/main.cpp | 71 +++++++-- features/minimal-printf/mbed_lib.json | 2 +- .../mbed_printf_implementation.c | 145 ++++++++++++++++-- 3 files changed, 194 insertions(+), 24 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index 4c253c83a0..6a8694c790 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -229,7 +229,7 @@ static control_t test_printf_x(const size_t call_count) TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("lX: %lX\r\n", 0); - result_baseline = printf("lX: %lX\r\n", 0); + result_baseline = printf("lX: %lX\r\n", 0UL); TEST_ASSERT_EQUAL_INT(8, result_minimal); result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX); @@ -268,11 +268,6 @@ static control_t test_printf_x(const size_t call_count) result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX); TEST_ASSERT_EQUAL_INT(22, result_minimal); -// result_minimal = mbed_snprintf(buffer_minimal, 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); - return CaseNext; } @@ -562,10 +557,60 @@ static control_t test_snprintf_x(const size_t call_count) TEST_ASSERT_EQUAL_STRING("tX: FFFFFFFFFFFFFFFF\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(22, result_minimal); -// result_minimal = mbed_snprintf(buffer_minimal, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi); -// mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "%s\r\n", buffer); + return CaseNext; +} -// mbed_printf("results: %d\r\n", result); +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", -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); + result_baseline = printf("f: %f\r\n", 0); + TEST_ASSERT_EQUAL_INT(8, 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", -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); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 0); + TEST_ASSERT_EQUAL_STRING("f: 0.0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(8, 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; } @@ -578,11 +623,15 @@ utest::v1::status_t greentea_setup(const size_t number_of_cases) Case cases[] = { Case("printf %d", test_printf_d), - Case("printf %u", test_printf_u), - Case("printf %x", test_printf_x), 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 }; Specification specification(greentea_setup, cases, greentea_test_teardown_handler); diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json index 1a595a0d33..c7d6fb3098 100755 --- a/features/minimal-printf/mbed_lib.json +++ b/features/minimal-printf/mbed_lib.json @@ -7,7 +7,7 @@ }, "set-floating-point-max-decimals": { "help": "Maximum number of decimals to be printed", - "value": 16 + "value": 6 }, "enable-64-bit": { "help": "Enable printing 64 bit integers", diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 99d4b14f2b..6d91b84b6f 100755 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -22,6 +22,10 @@ /* MBED */ /***************************/ #if TARGET_LIKE_MBED +/* + 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" #if DEVICE_SERIAL @@ -56,8 +60,10 @@ static void init_serial() /* 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 16 +#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 @@ -67,13 +73,18 @@ static void init_serial() #endif #ifndef MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS -#define MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS 16 +#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 @@ -94,6 +105,9 @@ static void init_serial() #error unsupported architecture #endif +/** + * Enum for storing width modifier. + */ typedef enum { LENGTH_NONE, LENGTH_HH, @@ -106,14 +120,24 @@ typedef enum { LENGTH_CAPITAL_L } length_t; +/** + * Prototypes + */ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value); static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); - static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value); static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character); static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string); +/** + * @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) { /* only continue if buffer can fit at least 1 characters */ @@ -136,8 +160,8 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in *result += 1; - /* get absolute value */ - new_value = (-1 * value); + /* get absolute value using two's complement */ + new_value = ~((MBED_UNSIGNED_STORAGE) value) + 1; } else { @@ -149,6 +173,14 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in } } +/** + * @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) { /* only continue if buffer can fit at least 1 characters */ @@ -203,6 +235,14 @@ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, } } +/** + * @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. + */ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value) { bool print_leading_zero = false; @@ -210,10 +250,13 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt /* only continue each loop if buffer can fit at least 2 characters */ for (ssize_t index = 7; (((size_t)(*result + 2) <= length)) && (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)) { + /* print zeroes after the first non-zero byte */ print_leading_zero = true; unsigned int nibble_one = (output >> 4); @@ -222,6 +265,7 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + /* write to buffer or stdout */ if (buffer) { buffer[*result] = int2hex[nibble_one]; @@ -238,11 +282,20 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt } } +/** + * @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, void* value) { /* only continue if buffer can fit '0x' and twice the size of a void* */ if ((*result + 2 + 2 * sizeof(void*)) <= length) { + /* write leading 0x */ if (buffer) { buffer[*result] = '0'; @@ -256,18 +309,27 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng *result += 2; + /* write rest as a regular hexadecimal number */ mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value); } } #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) { /* only continue if buffer can fit at least 1 characters */ if ((size_t)(*result + 1) <= length) { /* get integer part */ - long int integer = value; + MBED_SIGNED_STORAGE integer = value; /* write integer part */ mbed_minimal_formatted_string_signed(buffer, length, result, integer); @@ -283,12 +345,27 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in precision *= 10; } - long int decimal = (value - integer) * precision; + value = (value - integer) * precision; - /* take absolute value */ - if (decimal < 0) + /* convert to unsigned integer */ + MBED_UNSIGNED_STORAGE decimal = 0; + + if (value < 0) { - decimal = -1 * decimal; + 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++; } /* write decimal part */ @@ -297,26 +374,39 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in } #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) { /* only continue if the buffer can fit 1 character */ if ((size_t)(*result + 1) <= length) { + /* write character */ if (buffer) { buffer[*result] = character; } 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_PRINT_CHARACTER('\r'); *result += 1; } + + /* cache character */ mbed_stdio_out_prev = character; #endif + /* write character to stdout */ MBED_PRINT_CHARACTER(character); } @@ -324,10 +414,18 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, } } +/** + * @brief Print string. + * + * @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. + */ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string) { /* only continue if the buffer can fit at least 1 character */ - if ((*result + 1) <= (long int) length) + if ((size_t)(*result + 1) <= length) { /* count characters in string */ size_t remaining = length - *result; @@ -361,8 +459,19 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in } } +/** + * @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) { + /* initialize output if needed */ MBED_INITIALIZE_PRINT(); int result = 0; @@ -394,6 +503,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma next_index++; } + /* look for length modifier, default to NONE */ length_t length_modifier = LENGTH_NONE; /* look for two character length modifier */ @@ -450,7 +560,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma } } - /* read out character - this a supported format character, '\0', or a not suported character */ + /* read out character - this is a supported format character, '\0', or a not suported character */ char next = format[next_index]; /* signed integer */ @@ -459,18 +569,22 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma 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: @@ -511,18 +625,22 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma 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: @@ -555,6 +673,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma index = next_index; + /* write unsigned or hexadecimal */ if (next == 'u') { mbed_minimal_formatted_string_unsigned(buffer, length, &result, value); @@ -620,7 +739,9 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma } } else + /* not a format specifier */ { + /* write normal character */ mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); } } From ab700c02dfb82f59ee7c72e1d997ac0b352f2a1b Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Thu, 26 Oct 2017 13:41:32 -0700 Subject: [PATCH 12/36] Fix file permissions --- features/minimal-printf/README.md | 0 features/minimal-printf/mbed_lib.json | 0 features/minimal-printf/mbed_printf.h | 0 features/minimal-printf/mbed_printf_implementation.c | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 features/minimal-printf/README.md mode change 100755 => 100644 features/minimal-printf/mbed_lib.json mode change 100755 => 100644 features/minimal-printf/mbed_printf.h mode change 100755 => 100644 features/minimal-printf/mbed_printf_implementation.c diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md old mode 100755 new mode 100644 diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json old mode 100755 new mode 100644 diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h old mode 100755 new mode 100644 diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c old mode 100755 new mode 100644 From dddce560323fe274a32ae854ef968f6176d27ce7 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Thu, 26 Oct 2017 16:03:40 -0500 Subject: [PATCH 13/36] Update README.md --- features/minimal-printf/README.md | 160 +++--------------------------- 1 file changed, 13 insertions(+), 147 deletions(-) diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md index 1838368a45..c6b877f1a8 100644 --- a/features/minimal-printf/README.md +++ b/features/minimal-printf/README.md @@ -18,7 +18,7 @@ Supports: * %s: string. * %p: pointer (e.g. 0x00123456). -## Enabling floating point and setting baud rate +## Enabling floating point, 64 bit integers, new line conversion, and setting baud rate In mbed_app.json: @@ -26,8 +26,10 @@ In mbed_app.json: "target_overrides": { "*": { "platform.stdio-baud-rate": 115200, - "minimal-printf.floating-point": true, - "minimal-printf.floating-point-max-decimals": 10 + "platform.stdio-convert-newlines": false, + "minimal-printf.enable-floating-point": false, + "minimal-printf.set-floating-point-max-decimals": 6, + "minimal-printf.enable-64-bit": true } } ``` @@ -84,148 +86,12 @@ int main() } ``` +### Full application size on K64F/GCC -### K64F GCC minimal printf without floating point - -``` -+------------------------------------------+-------+-------+------+ -| Module | .text | .data | .bss | -+------------------------------------------+-------+-------+------+ -| [fill] | 16 | 3 | 2102 | -| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | -| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | -| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | -| [lib]/misc/ | 248 | 4 | 28 | -| main.o | 256 | 0 | 0 | -| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | -| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | -| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | -| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | -| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | -| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | -| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | -| mbed-os/platform/mbed_retarget.o | 20 | 0 | 0 | -| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | -| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | -| mbed-os/targets/TARGET_Freescale | 4758 | 12 | 384 | -| mbed-printf/mbed_printf.o | 960 | 1 | 188 | -| Subtotals | 7652 | 20 | 2732 | -+------------------------------------------+-------+-------+------+ -Total Static RAM memory (data + bss): 2752 bytes -Total Flash memory (text + data): 7672 bytes -``` - - -### K64F GCC minimal printf with floating point - -``` -+------------------------------------------+-------+-------+------+ -| Module | .text | .data | .bss | -+------------------------------------------+-------+-------+------+ -| [fill] | 24 | 3 | 2102 | -| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | -| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | -| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | -| [lib]/gcc.a/_arm_addsubdf3.o | 880 | 0 | 0 | -| [lib]/gcc.a/_arm_fixdfsi.o | 80 | 0 | 0 | -| [lib]/gcc.a/_arm_muldivdf3.o | 1060 | 0 | 0 | -| [lib]/misc/ | 248 | 4 | 28 | -| main.o | 256 | 0 | 0 | -| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | -| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | -| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | -| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | -| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | -| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | -| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | -| mbed-os/platform/mbed_retarget.o | 20 | 0 | 0 | -| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | -| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | -| mbed-os/targets/TARGET_Freescale | 4758 | 12 | 384 | -| mbed-printf/mbed_printf.o | 1160 | 1 | 188 | -| Subtotals | 9880 | 20 | 2732 | -+------------------------------------------+-------+-------+------+ -Total Static RAM memory (data + bss): 2752 bytes -Total Flash memory (text + data): 9900 bytes -``` - - -### K64F GCC standard printf - -``` -+------------------------------------------+-------+-------+------+ -| Module | .text | .data | .bss | -+------------------------------------------+-------+-------+------+ -| [fill] | 62 | 4 | 2071 | -| [lib]/c.a/lib_a-callocr.o | 96 | 0 | 0 | -| [lib]/c.a/lib_a-closer.o | 36 | 0 | 0 | -| [lib]/c.a/lib_a-ctype_.o | 257 | 0 | 0 | -| [lib]/c.a/lib_a-dtoa.o | 3948 | 0 | 0 | -| [lib]/c.a/lib_a-errno.o | 12 | 0 | 0 | -| [lib]/c.a/lib_a-fclose.o | 196 | 0 | 0 | -| [lib]/c.a/lib_a-fflush.o | 404 | 0 | 0 | -| [lib]/c.a/lib_a-findfp.o | 204 | 0 | 0 | -| [lib]/c.a/lib_a-fputwc.o | 264 | 0 | 0 | -| [lib]/c.a/lib_a-freer.o | 620 | 0 | 0 | -| [lib]/c.a/lib_a-fstatr.o | 40 | 0 | 0 | -| [lib]/c.a/lib_a-fvwrite.o | 752 | 0 | 0 | -| [lib]/c.a/lib_a-fwalk.o | 84 | 0 | 0 | -| [lib]/c.a/lib_a-impure.o | 0 | 1068 | 0 | -| [lib]/c.a/lib_a-init.o | 80 | 0 | 0 | -| [lib]/c.a/lib_a-isattyr.o | 36 | 0 | 0 | -| [lib]/c.a/lib_a-locale.o | 42 | 364 | 0 | -| [lib]/c.a/lib_a-localeconv.o | 28 | 0 | 0 | -| [lib]/c.a/lib_a-lock.o | 16 | 0 | 33 | -| [lib]/c.a/lib_a-lseekr.o | 44 | 0 | 0 | -| [lib]/c.a/lib_a-makebuf.o | 240 | 0 | 0 | -| [lib]/c.a/lib_a-mallocr.o | 1376 | 1040 | 52 | -| [lib]/c.a/lib_a-mbtowc_r.o | 44 | 0 | 0 | -| [lib]/c.a/lib_a-memchr.o | 160 | 0 | 0 | -| [lib]/c.a/lib_a-memcpy.o | 308 | 0 | 0 | -| [lib]/c.a/lib_a-memmove.o | 200 | 0 | 0 | -| [lib]/c.a/lib_a-memset.o | 156 | 0 | 0 | -| [lib]/c.a/lib_a-mprec.o | 1776 | 0 | 0 | -| [lib]/c.a/lib_a-printf.o | 40 | 0 | 0 | -| [lib]/c.a/lib_a-readr.o | 44 | 0 | 0 | -| [lib]/c.a/lib_a-reallocr.o | 844 | 0 | 0 | -| [lib]/c.a/lib_a-reent.o | 0 | 0 | 4 | -| [lib]/c.a/lib_a-sbrkr.o | 36 | 0 | 0 | -| [lib]/c.a/lib_a-snprintf.o | 152 | 0 | 0 | -| [lib]/c.a/lib_a-stdio.o | 136 | 0 | 0 | -| [lib]/c.a/lib_a-strlen.o | 220 | 0 | 0 | -| [lib]/c.a/lib_a-svfiprintf.o | 252 | 0 | 0 | -| [lib]/c.a/lib_a-svfprintf.o | 5370 | 0 | 0 | -| [lib]/c.a/lib_a-vfiprintf.o | 148 | 0 | 0 | -| [lib]/c.a/lib_a-vfprintf.o | 5754 | 0 | 0 | -| [lib]/c.a/lib_a-wbuf.o | 176 | 0 | 0 | -| [lib]/c.a/lib_a-wcrtomb.o | 84 | 0 | 0 | -| [lib]/c.a/lib_a-wctomb_r.o | 28 | 0 | 0 | -| [lib]/c.a/lib_a-writer.o | 44 | 0 | 0 | -| [lib]/c.a/lib_a-wsetup.o | 200 | 0 | 0 | -| [lib]/gcc.a/_aeabi_uldivmod.o | 48 | 0 | 0 | -| [lib]/gcc.a/_arm_addsubdf3.o | 880 | 0 | 0 | -| [lib]/gcc.a/_arm_cmpdf2.o | 272 | 0 | 0 | -| [lib]/gcc.a/_arm_fixdfsi.o | 80 | 0 | 0 | -| [lib]/gcc.a/_arm_muldivdf3.o | 1060 | 0 | 0 | -| [lib]/gcc.a/_arm_unorddf2.o | 44 | 0 | 0 | -| [lib]/gcc.a/_dvmd_tls.o | 4 | 0 | 0 | -| [lib]/gcc.a/_udivmoddi4.o | 732 | 0 | 0 | -| [lib]/misc/ | 248 | 4 | 28 | -| main.o | 215 | 0 | 0 | -| mbed-os/hal/mbed_gpio.o | 96 | 0 | 0 | -| mbed-os/hal/mbed_pinmap_common.o | 212 | 0 | 0 | -| mbed-os/hal/mbed_ticker_api.o | 214 | 0 | 0 | -| mbed-os/hal/mbed_us_ticker_api.o | 44 | 0 | 24 | -| mbed-os/platform/mbed_alloc_wrappers.o | 16 | 0 | 0 | -| mbed-os/platform/mbed_board.o | 90 | 0 | 0 | -| mbed-os/platform/mbed_critical.o | 56 | 0 | 5 | -| mbed-os/platform/mbed_error.o | 32 | 0 | 1 | -| mbed-os/platform/mbed_retarget.o | 646 | 4 | 266 | -| mbed-os/platform/mbed_sdk_boot.o | 74 | 0 | 0 | -| mbed-os/platform/mbed_wait_api_no_rtos.o | 32 | 0 | 0 | -| mbed-os/targets/TARGET_Freescale | 4834 | 12 | 384 | -| Subtotals | 34938 | 2496 | 2868 | -+------------------------------------------+-------+-------+------+ -Total Static RAM memory (data + bss): 5364 bytes -Total Flash memory (text + data): 37434 bytes -``` +| | 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 | From cad10ad56930074ef5024d82b5f71b588c05f5f4 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Fri, 27 Oct 2017 14:44:31 +0300 Subject: [PATCH 14/36] Add compile profiles --- features/minimal-printf/README.md | 10 ++++ features/minimal-printf/profiles/debug.json | 46 +++++++++++++++++++ features/minimal-printf/profiles/develop.json | 46 +++++++++++++++++++ features/minimal-printf/profiles/release.json | 46 +++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 features/minimal-printf/profiles/debug.json create mode 100644 features/minimal-printf/profiles/develop.json create mode 100644 features/minimal-printf/profiles/release.json diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md index c6b877f1a8..107ff7591f 100644 --- a/features/minimal-printf/README.md +++ b/features/minimal-printf/README.md @@ -18,6 +18,16 @@ Supports: * %s: string. * %p: pointer (e.g. 0x00123456). +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 -m --profile mbed-printf/profiles/release.json +``` + ## Enabling floating point, 64 bit integers, new line conversion, and setting baud rate In mbed_app.json: diff --git a/features/minimal-printf/profiles/debug.json b/features/minimal-printf/profiles/debug.json new file mode 100644 index 0000000000..f10ec679df --- /dev/null +++ b/features/minimal-printf/profiles/debug.json @@ -0,0 +1,46 @@ +{ + "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"], + "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,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit", + "-Wl,-n", "-Wl,--wrap,printf", "-Wl,--wrap,snprintf", + "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] + }, + "ARM": { + "common": ["-c", "--gnu", "-Otime", "--split_sections", + "--apcs=interwork", "--brief_diagnostics", "--restrict", + "--multibyte_chars", "-O0", "-g"], + "asm": [], + "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], + "cxx": ["--cpp", "--no_rtti", "--no_vla"], + "ld": [] + }, + "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"], + "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"], + "asm": [], + "c": ["--vla"], + "cxx": ["--guard_calls", "--no_static_destruction"], + "ld": ["--skip_dynamic_initialization", "--threaded_lib"] + } +} diff --git a/features/minimal-printf/profiles/develop.json b/features/minimal-printf/profiles/develop.json new file mode 100644 index 0000000000..f0f42bd91c --- /dev/null +++ b/features/minimal-printf/profiles/develop.json @@ -0,0 +1,46 @@ +{ + "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"], + "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,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit", + "-Wl,-n", "-Wl,--wrap,printf", "-Wl,--wrap,snprintf", + "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] + }, + "ARM": { + "common": ["-c", "--gnu", "-Otime", "--split_sections", + "--apcs=interwork", "--brief_diagnostics", "--restrict", + "--multibyte_chars", "-O3"], + "asm": [], + "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], + "cxx": ["--cpp", "--no_rtti", "--no_vla"], + "ld": [] + }, + "uARM": { + "common": ["-c", "--gnu", "-Otime", "--split_sections", + "--apcs=interwork", "--brief_diagnostics", "--restrict", + "--multibyte_chars", "-O3", "-D__MICROLIB", + "--library_type=microlib", "-DMBED_RTOS_SINGLE_THREAD"], + "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"], + "asm": [], + "c": ["--vla"], + "cxx": ["--guard_calls", "--no_static_destruction"], + "ld": ["--skip_dynamic_initialization", "--threaded_lib"] + } +} diff --git a/features/minimal-printf/profiles/release.json b/features/minimal-printf/profiles/release.json new file mode 100644 index 0000000000..90578b053c --- /dev/null +++ b/features/minimal-printf/profiles/release.json @@ -0,0 +1,46 @@ +{ + "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"], + "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,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit", + "-Wl,-n", "-Wl,--wrap,printf", "-Wl,--wrap,snprintf", + "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] + }, + "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": [] + }, + "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"], + "asm": [], + "c": ["--vla"], + "cxx": ["--guard_calls", "--no_static_destruction"], + "ld": ["--skip_dynamic_initialization", "--threaded_lib"] + } +} From 2e988a3649a517acf21dfd55d4536966b2124b01 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Mon, 30 Oct 2017 19:10:19 +0200 Subject: [PATCH 15/36] Add "-g" to 'release' and 'develop' profiles This is used by mbed-os-linker-report and doesn't increase the code size. --- features/minimal-printf/profiles/develop.json | 2 +- features/minimal-printf/profiles/release.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/minimal-printf/profiles/develop.json b/features/minimal-printf/profiles/develop.json index f0f42bd91c..37bbf12e84 100644 --- a/features/minimal-printf/profiles/develop.json +++ b/features/minimal-printf/profiles/develop.json @@ -5,7 +5,7 @@ "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", "-fno-delete-null-pointer-checks", - "-fomit-frame-pointer", "-Os"], + "-fomit-frame-pointer", "-Os", "-g"], "asm": ["-x", "assembler-with-cpp"], "c": ["-std=gnu99"], "cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"], diff --git a/features/minimal-printf/profiles/release.json b/features/minimal-printf/profiles/release.json index 90578b053c..1c8174aaad 100644 --- a/features/minimal-printf/profiles/release.json +++ b/features/minimal-printf/profiles/release.json @@ -5,7 +5,7 @@ "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", "-fno-delete-null-pointer-checks", - "-fomit-frame-pointer", "-Os", "-DNDEBUG"], + "-fomit-frame-pointer", "-Os", "-DNDEBUG", "-g"], "asm": ["-x", "assembler-with-cpp"], "c": ["-std=gnu99"], "cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"], From 75845c3dc736b3bf12e4259237587019a07ec92b Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Thu, 2 Nov 2017 17:02:17 +0000 Subject: [PATCH 16/36] Remove references to ssize_t in the code ssize_t doesn't exist at all in armcc. --- features/minimal-printf/mbed_printf_implementation.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 6d91b84b6f..6fa3881a99 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -248,7 +248,7 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt bool print_leading_zero = false; /* only continue each loop if buffer can fit at least 2 characters */ - for (ssize_t index = 7; (((size_t)(*result + 2) <= length)) && (index >= 0); index--) + for (int index = 7; (((size_t)(*result + 2) <= length)) && (index >= 0); index--) { /* get most significant byte */ uint8_t output = value >> (8 * index); @@ -605,9 +605,6 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma case LENGTH_J: value = (intmax_t) value; break; - case LENGTH_Z: - value = (ssize_t) value; - break; case LENGTH_T: value = (ptrdiff_t) value; break; From de7024f7abd13faa4cfee5e1235b76a2656361c9 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sun, 12 Nov 2017 15:14:38 -0800 Subject: [PATCH 17/36] Add missing include stdbool.h --- features/minimal-printf/mbed_printf_implementation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 6fa3881a99..388623685d 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -16,7 +16,7 @@ #include "mbed_printf_implementation.h" - +#include /***************************/ /* MBED */ From a5f07166f909ee4e4f51ba8919dd9b67b451a7ee Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Thu, 22 Mar 2018 18:47:39 +0200 Subject: [PATCH 18/36] [BUGFIX][IOTUC-18] Library fixes This commit adds mostly integer (and buffer) overflow checks for the current buffer index (`result` variable). --- .../mbed_printf_implementation.c | 506 +++++++++--------- 1 file changed, 256 insertions(+), 250 deletions(-) diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 388623685d..e018ff7f5a 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -17,6 +17,7 @@ #include "mbed_printf_implementation.h" #include +#include /***************************/ /* MBED */ @@ -126,9 +127,9 @@ typedef enum { static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value); static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); -static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, void* value); +static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value); static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character); -static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string); +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string); /** * @brief Print signed integer. @@ -141,7 +142,7 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value) { /* only continue if buffer can fit at least 1 characters */ - if ((size_t)(*result + 1) <= length) + if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { MBED_UNSIGNED_STORAGE new_value = 0; @@ -184,7 +185,7 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value) { /* only continue if buffer can fit at least 1 characters */ - if ((size_t)(*result + 1) <= length) + if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* treat 0 as a corner case */ if (value == 0) @@ -218,7 +219,7 @@ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, } /* write scratch pad to buffer or output */ - for ( ; ((size_t)*result < length) && (index > 0); index--) + for ( ; (*result <= INT_MAX- 1) && ((size_t)*result < length) && (index > 0); index--) { if (buffer) { @@ -248,7 +249,7 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt bool print_leading_zero = false; /* only continue each loop if buffer can fit at least 2 characters */ - for (int index = 7; (((size_t)(*result + 2) <= length)) && (index >= 0); index--) + for (int index = 7; (*result >= 0) && (*result <= INT_MAX - 2) && ((size_t)*result + 2 <= length) && (index >= 0); index--) { /* get most significant byte */ uint8_t output = value >> (8 * index); @@ -290,10 +291,11 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt * @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, void* value) +static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value) { /* only continue if buffer can fit '0x' and twice the size of a void* */ - if ((*result + 2 + 2 * sizeof(void*)) <= length) + size_t needed = 2 + 2 * sizeof(void*); + if ((*result >= 0) && ((size_t)*result <= INT_MAX - needed) && ((size_t)*result + needed <= length)) { /* write leading 0x */ if (buffer) @@ -326,7 +328,7 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value) { /* only continue if buffer can fit at least 1 characters */ - if ((size_t)(*result + 1) <= length) + if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* get integer part */ MBED_SIGNED_STORAGE integer = value; @@ -385,7 +387,7 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character) { /* only continue if the buffer can fit 1 character */ - if ((size_t)(*result + 1) <= length) + if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* write character */ if (buffer) @@ -422,10 +424,10 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, * @param result The current output location. * @param[in] value The string to be printed. */ -static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, char* string) +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string) { /* only continue if the buffer can fit at least 1 character */ - if ((size_t)(*result + 1) <= length) + if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* count characters in string */ size_t remaining = length - *result; @@ -440,6 +442,11 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in /* copy string to buffer */ if (buffer) { + /* ensure that the value of "result" doesn't overflow */ + if (string_length + *result > INT_MAX) + { + string_length = (size_t)INT_MAX - *result; + } for (size_t index = 0; index < string_length; index++) { buffer[*result + index] = string[index]; @@ -476,277 +483,276 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma int result = 0; - /* if writing to buffer, reserve space for NULL termination */ - if (buffer) + /* ensure that function wasn't called with an empty buffer, or with + a buffer size that is larger than the maximum 'int' value */ + if (length > 0 && length <= INT_MAX) { - length--; - } - - /* parse string */ - for (size_t index = 0; format[index] != '\0'; index++) - { - /* format specifier begin */ - if (format[index] == '%') + /* parse string */ + for (size_t index = 0; format[index] != '\0'; index++) { - size_t next_index = index + 1; - - /* while there is room in buffer and format string is not empty */ - while ((next_index < length) && (format[next_index] != '\0') && - /* skip all flags and precision modifiers */ - (((format[next_index] >= '0') && (format[next_index] <= '9')) || - (format[next_index] == '-') || - (format[next_index] == '+') || - (format[next_index] == '#') || - (format[next_index] == '.'))) + /* format specifier begin */ + if (format[index] == '%') { - /* skip to next character */ - next_index++; - } + size_t next_index = index + 1; - /* look for length modifier, default to NONE */ - length_t length_modifier = LENGTH_NONE; - - /* look for two character length modifier */ - if (format[next_index + 1] != '\0') - { - 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; - } - - /* increment next_index if length modifier was found */ - if (length_modifier != LENGTH_NONE) - { - next_index += 2; - } - } - - /* look for one character length modifier if two character search failed */ - if ((length_modifier == LENGTH_NONE) && (format[next_index] != '\0')) - { - 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 next_index if length modifier was found */ - if (length_modifier != LENGTH_NONE) + /* while format string is not empty */ + while ((format[next_index] != '\0') && + /* skip all flags and precision modifiers */ + (((format[next_index] >= '0') && (format[next_index] <= '9')) || + (format[next_index] == '-') || + (format[next_index] == '+') || + (format[next_index] == '#') || + (format[next_index] == '.'))) { + /* skip to next character */ next_index++; } - } - /* read out character - this is a supported format character, '\0', or a not suported character */ - char next = format[next_index]; + /* look for length modifier, default to NONE */ + length_t length_modifier = LENGTH_NONE; - /* 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)))) + /* look for two character length modifier */ + if (format[next_index + 1] != '\0') { - /* 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); + 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; + } + + /* increment next_index if length modifier was found */ + if (length_modifier != LENGTH_NONE) + { + next_index += 2; + } } - /* constrict value based on lenght modifier */ - switch (length_modifier) + /* look for one character length modifier if two character search failed */ + if ((length_modifier == LENGTH_NONE) && (format[next_index] != '\0')) { - 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; + 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 next_index if length modifier was found */ + if (length_modifier != LENGTH_NONE) + { + next_index++; + } } - index = next_index; + /* read out character - this is a supported format character, '\0', or a not suported character */ + char next = format[next_index]; - mbed_minimal_formatted_string_signed(buffer, length, &result, value); - } - /* 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)))) + /* signed integer */ + if ((next == 'd') || (next == 'i')) { - /* use 64 bit storage type for readout */ - value = va_arg(arguments, MBED_UNSIGNED_STORAGE); + 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); } - else -#endif + /* unsigned integer */ + else if ((next == 'u') || (next == 'x') || (next == 'X')) { - /* use native storage type (which can be 32 or 64 bit) */ - value = va_arg(arguments, MBED_UNSIGNED_NATIVE_TYPE); + 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); + } + else + { + mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value); + } } - - /* constrict value based on lenght modifier */ - switch (length_modifier) + #if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT + /* treat all floating points the same */ + else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G')) { - 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; + double value = va_arg(arguments, double); + index = next_index; + + mbed_minimal_formatted_string_double(buffer, length, &result, value); } - - index = next_index; - - /* write unsigned or hexadecimal */ - if (next == 'u') + #endif + /* character */ + else if (next == 'c') { - mbed_minimal_formatted_string_unsigned(buffer, length, &result, value); + char value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE); + index = next_index; + + mbed_minimal_formatted_string_character(buffer, length, &result, value); + } + /* string */ + else if (next == 's') + { + char* value = va_arg(arguments, char*); + index = next_index; + + mbed_minimal_formatted_string_string(buffer, length, &result, value); + } + /* pointer */ + else if (next == 'p') + { + void* value = va_arg(arguments, void*); + index = next_index; + + mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); } else { - mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value); + /* write all characters between format beginning and unrecognied modifier */ + while (index < next_index) + { + mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); + 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]); + } + else + { + /* break out of for loop */ + break; + } } } -#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); - } -#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); - } - /* string */ - else if (next == 's') - { - char* value = va_arg(arguments, char*); - index = next_index; - - mbed_minimal_formatted_string_string(buffer, length, &result, value); - } - /* pointer */ - else if (next == 'p') - { - void* value = va_arg(arguments, void*); - index = next_index; - - mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); - } else + /* not a format specifier */ { - /* write all characters between format beginning and unrecognied modifier */ - while (index < next_index) - { - mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); - 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]); - } - else - { - /* break out of for loop */ - break; - } + /* write normal character */ + mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); } } - else - /* not a format specifier */ - { - /* write normal character */ - mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); - } - } - /* if writing to buffer, NULL terminate string in reserved space*/ - if (buffer) - { - buffer[result] = '\0'; + /* if writing to buffer, NULL terminate string in reserved space*/ + if (buffer && ((size_t)result < length)) + { + buffer[result] = '\0'; + } } return result; From 2a01a54e17b857672181625fb4100582b61eb4d5 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Fri, 23 Mar 2018 10:23:48 +0200 Subject: [PATCH 19/36] Address code review issues - Improved comments to explain the checks on 'result'. - Check for non-NULL format specifier. --- .../mbed_printf_implementation.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index e018ff7f5a..7a63c12cfd 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -141,7 +141,8 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in */ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value) { - /* only continue if buffer can fit at least 1 characters */ + /* only continue if buffer can fit at least 1 character and if + 'result' doesn't overflow */ if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { MBED_UNSIGNED_STORAGE new_value = 0; @@ -184,7 +185,8 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in */ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value) { - /* only continue if buffer can fit at least 1 characters */ + /* only continue if buffer can fit at least 1 character and if + 'result' doesn't overflow */ if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* treat 0 as a corner case */ @@ -248,7 +250,8 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt { bool print_leading_zero = false; - /* only continue each loop if buffer can fit at least 2 characters */ + /* only continue each loop if buffer can fit at least 2 characters + and if 'result' doesn't overflow */ for (int index = 7; (*result >= 0) && (*result <= INT_MAX - 2) && ((size_t)*result + 2 <= length) && (index >= 0); index--) { /* get most significant byte */ @@ -293,7 +296,8 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt */ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value) { - /* only continue if buffer can fit '0x' and twice the size of a void* */ + /* only continue if buffer can fit '0x' and twice the size of a void* + and if 'result' doesn't overflow */ size_t needed = 2 + 2 * sizeof(void*); if ((*result >= 0) && ((size_t)*result <= INT_MAX - needed) && ((size_t)*result + needed <= length)) { @@ -327,7 +331,8 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng */ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value) { - /* only continue if buffer can fit at least 1 characters */ + /* only continue if buffer can fit at least 1 character and if + 'result' doesn't overflow */ if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* get integer part */ @@ -386,7 +391,8 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in */ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character) { - /* only continue if the buffer can fit 1 character */ + /* only continue if the buffer can fit 1 character and if + 'result' doesn't overflow */ if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* write character */ @@ -426,7 +432,8 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, */ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string) { - /* only continue if the buffer can fit at least 1 character */ + /* only continue if the buffer can fit at least 1 character and if + 'result' doesn't overflow */ if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) { /* count characters in string */ @@ -483,9 +490,10 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma int result = 0; - /* ensure that function wasn't called with an empty buffer, or with - a buffer size that is larger than the maximum 'int' value */ - if (length > 0 && length <= INT_MAX) + /* 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 > 0 && length <= INT_MAX) { /* parse string */ for (size_t index = 0; format[index] != '\0'; index++) From fbbffd613e16618c904c8d261559b3f752cc0feb Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Wed, 25 Apr 2018 19:00:55 +0300 Subject: [PATCH 20/36] Disabled tests that aren't relevant on mbed targets The minimal-printf implementation supports a number of length modifiers (j, z and t) that are not supported by the native mbed OS libc implementation. The compliance test has tests for these modifiers, which means that it isn't possible to check the output of mbed-printf against a known good implementation (libc's printf) when running on mbed OS. This, in turn, can give the impression that the tests for these modifiers pass, when that might not be the case. To address this issue, this PR removes the tests for these modifiers in mbed OS. This PR was created because some of the tests for these modifiers actually fail in Linux, for example: ``` >>> Running case #3: 'printf %u'... hhu: 0 hhu: 0 hhu: 255 hhu: 255 hu: 0 hu: 0 hu: 65535 hu: 65535 u: 0 u: 0 u: 4294967295 u: 4294967295 lu: 0 lu: 0 lu: 4294967295 lu: 4294967295 llu: 0 llu: 0 llu: 18446744073709551615 llu: 18446744073709551615 ju: 0 ju: 0 ju: 4294967295 ju: 18446744073709551615 :188::FAIL: Expected 7 Was 16 >>> 'printf %u': 0 passed, 1 failed with reason 'Assertion Failed' ``` --- .../TESTS/minimal-printf/compliance/main.cpp | 74 +++++++++++++++++-- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index 6a8694c790..ca9e82cb1b 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -14,7 +14,9 @@ * limitations under the License. */ +#ifdef TARGET_LIKE_MBED #include "mbed.h" +#endif #include "mbed_printf.h" #include "utest/utest.h" @@ -88,8 +90,9 @@ static control_t test_printf_d(const size_t call_count) result_baseline = printf("lld: %lld\r\n", LLONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#ifdef TARGET_LIKE_MBED printf("%%jd not supported by mbed\r\n"); - +#else result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN); result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MIN); TEST_ASSERT_EQUAL_INT(17, result_minimal); @@ -97,9 +100,11 @@ static control_t test_printf_d(const size_t call_count) result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX); result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MAX); TEST_ASSERT_EQUAL_INT(16, result_minimal); +#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_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MIN); TEST_ASSERT_EQUAL_INT(17, result_minimal); @@ -107,9 +112,11 @@ static control_t test_printf_d(const size_t call_count) result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX); result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MAX); TEST_ASSERT_EQUAL_INT(16, result_minimal); +#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_baseline = printf("td: %td\r\n", PTRDIFF_MIN); TEST_ASSERT_EQUAL_INT(17, result_minimal); @@ -117,6 +124,7 @@ static control_t test_printf_d(const size_t call_count) result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); result_baseline = printf("td: %td\r\n", PTRDIFF_MAX); TEST_ASSERT_EQUAL_INT(16, result_minimal); +#endif return CaseNext; } @@ -168,6 +176,9 @@ static control_t test_printf_u(const size_t call_count) result_baseline = printf("llu: %llu\r\n", ULLONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#ifdef TARGET_LIKE_MBED + printf("%%ju not supported by mbed\r\n"); +#else result_minimal = mbed_printf("ju: %ju\r\n", 0); result_baseline = printf("ju: %ju\r\n",(uintmax_t) 0); TEST_ASSERT_EQUAL_INT(7, result_minimal); @@ -175,7 +186,11 @@ static control_t test_printf_u(const size_t call_count) result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX); TEST_ASSERT_EQUAL_INT(7, result_minimal); +#endif +#ifdef TARGET_LIKE_MBED + printf("%%zu not supported by mbed\r\n"); +#else result_minimal = mbed_printf("zu: %zu\r\n", 0); result_baseline = printf("zu: %zu\r\n", 0); TEST_ASSERT_EQUAL_INT(7, result_minimal); @@ -183,7 +198,11 @@ static control_t test_printf_u(const size_t call_count) result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); result_baseline = printf("zu: %zu\r\n", SIZE_MAX); TEST_ASSERT_EQUAL_INT(16, result_minimal); +#endif +#ifdef TARGET_LIKE_MBED + printf("%%tu not supported by mbed\r\n"); +#else result_minimal = mbed_printf("tu: %tu\r\n", 0); result_baseline = printf("tu: %tu\r\n", 0); TEST_ASSERT_EQUAL_INT(7, result_minimal); @@ -191,6 +210,7 @@ static control_t test_printf_u(const size_t call_count) result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX); TEST_ASSERT_EQUAL_INT(26, result_minimal); +#endif return CaseNext; } @@ -244,6 +264,9 @@ static control_t test_printf_x(const size_t call_count) result_baseline = printf("llX: %llX\r\n", ULLONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#ifdef TARGET_LIKE_MBED + printf("%%jX not supported by mbed\r\n"); +#else result_minimal = mbed_printf("jX: %jX\r\n", 0); result_baseline = printf("jX: %jX\r\n", (uintmax_t) 0); TEST_ASSERT_EQUAL_INT(8, result_minimal); @@ -251,7 +274,11 @@ static control_t test_printf_x(const size_t call_count) result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX); result_baseline = printf("jX: %jX\r\n", UINTMAX_MAX); TEST_ASSERT_EQUAL_INT(8, result_minimal); +#endif +#ifdef TARGET_LIKE_MBED + printf("%%zX not supported by mbed\r\n"); +#else result_minimal = mbed_printf("zX: %zX\r\n", 0); result_baseline = printf("zX: %zX\r\n", 0); TEST_ASSERT_EQUAL_INT(8, result_minimal); @@ -259,7 +286,11 @@ static control_t test_printf_x(const size_t call_count) result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX); result_baseline = printf("zX: %zX\r\n", SIZE_MAX); TEST_ASSERT_EQUAL_INT(14, result_minimal); +#endif +#ifdef TARGET_LIKE_MBED + printf("%%tX not supported by mbed\r\n"); +#else result_minimal = mbed_printf("tX: %tX\r\n", 0); result_baseline = printf("tX: %tX\r\n", 0); TEST_ASSERT_EQUAL_INT(8, result_minimal); @@ -267,6 +298,7 @@ static control_t test_printf_x(const size_t call_count) result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX); result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX); TEST_ASSERT_EQUAL_INT(22, result_minimal); +#endif return CaseNext; } @@ -336,8 +368,9 @@ static control_t test_snprintf_d(const size_t call_count) 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", 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); @@ -347,9 +380,11 @@ static control_t test_snprintf_d(const size_t call_count) 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(16, 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", 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); @@ -359,9 +394,11 @@ static control_t test_snprintf_d(const size_t call_count) 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(16, 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); @@ -371,6 +408,7 @@ static control_t test_snprintf_d(const size_t call_count) 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(16, result_minimal); +#endif return CaseNext; } @@ -434,6 +472,9 @@ static control_t test_snprintf_u(const size_t call_count) 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", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0); TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal); @@ -443,7 +484,11 @@ static control_t test_snprintf_u(const size_t call_count) result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", UINTMAX_MAX); TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(7, 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("zu: 0\r\n", buffer_minimal); @@ -453,7 +498,11 @@ static control_t test_snprintf_u(const size_t call_count) result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zu: %zu\r\n", SIZE_MAX); TEST_ASSERT_EQUAL_STRING("zu: 4294967295\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(16, 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("tu: 0\r\n", buffer_minimal); @@ -463,6 +512,7 @@ static control_t test_snprintf_u(const size_t call_count) result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tu: %tu\r\n", UINTPTR_MAX); TEST_ASSERT_EQUAL_STRING("tu: 18446744073709551615\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(26, result_minimal); +#endif return CaseNext; } @@ -527,6 +577,9 @@ static control_t test_snprintf_x(const size_t call_count) 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", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", (uintmax_t) 0); TEST_ASSERT_EQUAL_STRING("jX: 00\r\n", buffer_minimal); @@ -536,7 +589,11 @@ static control_t test_snprintf_x(const size_t call_count) result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", UINTMAX_MAX); TEST_ASSERT_EQUAL_STRING("jX: 00\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(8, 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("zX: 00\r\n", buffer_minimal); @@ -546,7 +603,11 @@ static control_t test_snprintf_x(const size_t call_count) result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "zX: %zX\r\n", SIZE_MAX); TEST_ASSERT_EQUAL_STRING("zX: FFFFFFFF\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(14, 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("tX: 00\r\n", buffer_minimal); @@ -556,6 +617,7 @@ static control_t test_snprintf_x(const size_t call_count) result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "tX: %tX\r\n", UINTPTR_MAX); TEST_ASSERT_EQUAL_STRING("tX: FFFFFFFFFFFFFFFF\r\n", buffer_minimal); TEST_ASSERT_EQUAL_INT(22, result_minimal); +#endif return CaseNext; } From 362dd3fbcf1dc96c07f93fca80375756ef6386ed Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Wed, 25 Apr 2018 22:31:16 +0300 Subject: [PATCH 21/36] Bugfixes for the implementation and the compliance test In the implementation, don't always display double hex digits when printing with "%X". This is in line with the behaviour observed both in mbed OS's printf (Newlib) and Linux's printf (glibc). In the tests, always compare the baseline result with the result returned by the minimal printf implementation, instead of comparing with a constant value. --- .../TESTS/minimal-printf/compliance/main.cpp | 118 +++++++++--------- .../mbed_printf_implementation.c | 17 ++- 2 files changed, 70 insertions(+), 65 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index ca9e82cb1b..79e33589aa 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -95,11 +95,11 @@ static control_t test_printf_d(const size_t call_count) #else result_minimal = mbed_printf("jd: %jd\r\n", INT32_MIN); result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MIN); - TEST_ASSERT_EQUAL_INT(17, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("jd: %jd\r\n", INT32_MAX); result_baseline = printf("jd: %jd\r\n", (intmax_t) INT32_MAX); - TEST_ASSERT_EQUAL_INT(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -107,11 +107,11 @@ static control_t test_printf_d(const size_t call_count) #else result_minimal = mbed_printf("zd: %zd\r\n", INT32_MIN); result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MIN); - TEST_ASSERT_EQUAL_INT(17, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("zd: %zd\r\n", INT32_MAX); result_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MAX); - TEST_ASSERT_EQUAL_INT(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -119,11 +119,11 @@ static control_t test_printf_d(const size_t call_count) #else result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MIN); result_baseline = printf("td: %td\r\n", PTRDIFF_MIN); - TEST_ASSERT_EQUAL_INT(17, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); result_baseline = printf("td: %td\r\n", PTRDIFF_MAX); - TEST_ASSERT_EQUAL_INT(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif return CaseNext; @@ -181,11 +181,11 @@ static control_t test_printf_u(const size_t call_count) #else result_minimal = mbed_printf("ju: %ju\r\n", 0); result_baseline = printf("ju: %ju\r\n",(uintmax_t) 0); - TEST_ASSERT_EQUAL_INT(7, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX); - TEST_ASSERT_EQUAL_INT(7, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -193,11 +193,11 @@ static control_t test_printf_u(const size_t call_count) #else result_minimal = mbed_printf("zu: %zu\r\n", 0); result_baseline = printf("zu: %zu\r\n", 0); - TEST_ASSERT_EQUAL_INT(7, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); result_baseline = printf("zu: %zu\r\n", SIZE_MAX); - TEST_ASSERT_EQUAL_INT(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -205,11 +205,11 @@ static control_t test_printf_u(const size_t call_count) #else result_minimal = mbed_printf("tu: %tu\r\n", 0); result_baseline = printf("tu: %tu\r\n", 0); - TEST_ASSERT_EQUAL_INT(7, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX); - TEST_ASSERT_EQUAL_INT(26, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif return CaseNext; @@ -222,11 +222,9 @@ static control_t test_printf_x(const size_t call_count) /*************************************************************************/ /*************************************************************************/ - printf("%%x always prints even characters\r\n"); - result_minimal = mbed_printf("hhX: %hhX\r\n", 0); result_baseline = printf("hhX: %hhX\r\n", 0); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX); result_baseline = printf("hhX: %hhX\r\n", UCHAR_MAX); @@ -234,7 +232,7 @@ static control_t test_printf_x(const size_t call_count) result_minimal = mbed_printf("hX: %hX\r\n", 0); result_baseline = printf("hX: %hX\r\n", 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX); result_baseline = printf("hX: %hX\r\n", USHRT_MAX); @@ -242,7 +240,7 @@ static control_t test_printf_x(const size_t call_count) result_minimal = mbed_printf("X: %X\r\n", 0); result_baseline = printf("X: %X\r\n", 0); - TEST_ASSERT_EQUAL_INT(7, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("X: %X\r\n", UINT_MAX); result_baseline = printf("X: %X\r\n", UINT_MAX); @@ -250,7 +248,7 @@ static control_t test_printf_x(const size_t call_count) result_minimal = mbed_printf("lX: %lX\r\n", 0); result_baseline = printf("lX: %lX\r\n", 0UL); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX); result_baseline = printf("lX: %lX\r\n", ULONG_MAX); @@ -258,7 +256,7 @@ static control_t test_printf_x(const size_t call_count) result_minimal = mbed_printf("llX: %llX\r\n", 0); result_baseline = printf("llX: %llX\r\n", 0ULL); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX); result_baseline = printf("llX: %llX\r\n", ULLONG_MAX); @@ -269,11 +267,11 @@ static control_t test_printf_x(const size_t call_count) #else result_minimal = mbed_printf("jX: %jX\r\n", 0); result_baseline = printf("jX: %jX\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX); result_baseline = printf("jX: %jX\r\n", UINTMAX_MAX); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -281,11 +279,11 @@ static control_t test_printf_x(const size_t call_count) #else result_minimal = mbed_printf("zX: %zX\r\n", 0); result_baseline = printf("zX: %zX\r\n", 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX); result_baseline = printf("zX: %zX\r\n", SIZE_MAX); - TEST_ASSERT_EQUAL_INT(14, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -293,11 +291,11 @@ static control_t test_printf_x(const size_t call_count) #else result_minimal = mbed_printf("tX: %tX\r\n", 0); result_baseline = printf("tX: %tX\r\n", 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX); result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX); - TEST_ASSERT_EQUAL_INT(22, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif return CaseNext; @@ -374,12 +372,12 @@ static control_t test_snprintf_d(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", 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(17, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jd: %jd\r\n", 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(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -388,12 +386,12 @@ static control_t test_snprintf_d(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", 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(17, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "zd: %zd\r\n", 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(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -402,12 +400,12 @@ static control_t test_snprintf_d(const size_t call_count) 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(17, result_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(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif return CaseNext; @@ -478,12 +476,12 @@ static control_t test_snprintf_u(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0); TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(7, result_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("ju: 0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(7, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -492,12 +490,12 @@ static control_t test_snprintf_u(const size_t call_count) 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("zu: 0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(7, result_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("zu: 4294967295\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(16, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -506,12 +504,12 @@ static control_t test_snprintf_u(const size_t call_count) 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("tu: 0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(7, result_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("tu: 18446744073709551615\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(26, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif return CaseNext; @@ -526,12 +524,10 @@ static control_t test_snprintf_x(const size_t call_count) /*************************************************************************/ /*************************************************************************/ - printf("%%x always prints even characters\r\n"); - 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("hhX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + TEST_ASSERT_EQUAL_STRING("hhX: 0\r\n", 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); @@ -540,8 +536,8 @@ static control_t test_snprintf_x(const size_t call_count) 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("hX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_STRING("hX: 0\r\n", 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); @@ -549,8 +545,8 @@ static control_t test_snprintf_x(const size_t call_count) 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("X: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(7, result_minimal); + TEST_ASSERT_EQUAL_STRING("X: 0\r\n", 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); @@ -559,8 +555,8 @@ static control_t test_snprintf_x(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lX: %lX\r\n", 0UL); - TEST_ASSERT_EQUAL_STRING("lX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_STRING("lX: 0\r\n", 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); @@ -569,8 +565,8 @@ static control_t test_snprintf_x(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llX: %llX\r\n", 0ULL); - TEST_ASSERT_EQUAL_STRING("llX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(9, result_minimal); + TEST_ASSERT_EQUAL_STRING("llX: 0\r\n", 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); @@ -582,13 +578,13 @@ static control_t test_snprintf_x(const size_t call_count) #else result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_STRING("jX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_STRING("jX: 0\r\n", 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("jX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_STRING("jX: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -596,13 +592,13 @@ static control_t test_snprintf_x(const size_t call_count) #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("zX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_STRING("zX: 0\r\n", 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("zX: FFFFFFFF\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(14, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif #ifdef TARGET_LIKE_MBED @@ -610,13 +606,13 @@ static control_t test_snprintf_x(const size_t call_count) #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("tX: 00\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + TEST_ASSERT_EQUAL_STRING("tX: 0\r\n", 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("tX: FFFFFFFFFFFFFFFF\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(22, result_minimal); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif return CaseNext; @@ -638,7 +634,7 @@ static control_t test_printf_f(const size_t call_count) result_minimal = mbed_printf("f: %f\r\n", 0); result_baseline = printf("f: %f\r\n", 0); - TEST_ASSERT_EQUAL_INT(8, result_minimal); + 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); @@ -667,7 +663,7 @@ static control_t test_snprintf_f(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 0); TEST_ASSERT_EQUAL_STRING("f: 0.0\r\n", buffer_minimal); - TEST_ASSERT_EQUAL_INT(8, result_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); diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 7a63c12cfd..404815fa0b 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -18,6 +18,8 @@ #include #include +#include +#include /***************************/ /* MBED */ @@ -272,16 +274,23 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt /* write to buffer or stdout */ if (buffer) { - buffer[*result] = int2hex[nibble_one]; - buffer[*result + 1] = int2hex[nibble_two]; + if (nibble_one != 0) { + buffer[*result] = int2hex[nibble_one]; + *result += 1; + } + buffer[*result] = int2hex[nibble_two]; + *result += 1; } else { - MBED_PRINT_CHARACTER(int2hex[nibble_one]); + if (nibble_one != 0) { + MBED_PRINT_CHARACTER(int2hex[nibble_one]); + *result += 1; + } MBED_PRINT_CHARACTER(int2hex[nibble_two]); + *result += 1; } - *result += 2; } } } From c6cac23960259e6e75a6cc3de83dac1e363409fb Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Thu, 26 Apr 2018 13:31:53 +0300 Subject: [PATCH 22/36] Implementation fixes The printf(3) man page says "The functions snprintf() and vsnprintf() do not write more than size bytes (including the terminating null byte ('\0')). If the output was truncated due to this limit, then the return value is the number of characters (excluding the terminating null byte) which would have been written to the final string if enough space had been available." The last part of this spec (returning the number of characters which would have been written to the string if enough space had been available) was not implemented in minimal-printf. This PR changes that by redirecting all the processed characters through the "minimal_printf_putchar" helper function. This function will not write to the buffer if there's no space left, but it will always increment the number of written characters, in order to match the above description. minimal_printf_putchar also contains checks for overflows, so these checks are no longer needed in the rest of the code. Other changes: - In some cases, mbed_minimal_formatted_string didn't put the string terminator in the output buffer. This PR ensures that this always happens. - Fixed a bug in printed hexadecimal numbers introduced by a previous commit. - Added buffer overflow tests for snprintf. --- .../TESTS/minimal-printf/compliance/main.cpp | 103 +++++ .../mbed_printf_implementation.c | 388 +++++++----------- 2 files changed, 262 insertions(+), 229 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index 79e33589aa..c5aa85e93c 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -618,6 +618,7 @@ static control_t test_snprintf_x(const size_t call_count) return CaseNext; } +#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT static control_t test_printf_f(const size_t call_count) { int result_baseline; @@ -672,6 +673,99 @@ static control_t test_snprintf_f(const size_t call_count) 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 +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("d: %d", -1024); +} + +static control_t test_snprintf_buffer_overflow_ld(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("ld: %ld", -1048576L); +} + +static control_t test_snprintf_buffer_overflow_lld(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lld: %lld", -1099511627776LL); +} + +static control_t test_snprintf_buffer_overflow_u(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("u: %u", 1024); +} + +static control_t test_snprintf_buffer_overflow_lu(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lu: %lu", 1048576UL); +} + +static control_t test_snprintf_buffer_overflow_llu(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("llu: %llu", 1099511627776ULL); +} + +static control_t test_snprintf_buffer_overflow_x(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("x: 0x%x", 0x400); +} + +static control_t test_snprintf_buffer_overflow_lx(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lx: 0x%lx", 0x100000UL); +} + +static control_t test_snprintf_buffer_overflow_llx(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("llx: 0x%llx", 0x10000000000ULL); +} utest::v1::status_t greentea_setup(const size_t number_of_cases) { @@ -690,6 +784,15 @@ Case cases[] = { 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); diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 404815fa0b..4c7f0c354d 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -133,6 +133,37 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character); static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string); +/** + * @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) +{ + /* 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 + { + 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. * @@ -143,38 +174,24 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in */ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value) { - /* only continue if buffer can fit at least 1 character and if - 'result' doesn't overflow */ - if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) + MBED_UNSIGNED_STORAGE new_value = 0; + + /* if value is negative print sign and treat as positive number */ + if (value < 0) { - MBED_UNSIGNED_STORAGE new_value = 0; + /* write sign */ + mbed_minimal_putchar(buffer, length, result, '-'); - /* if value is negative print sign and treat as positive number */ - if (value < 0) - { - /* write sign */ - if (buffer) - { - buffer[*result] = '-'; - } - else - { - MBED_PRINT_CHARACTER('-'); - } - - *result += 1; - - /* 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); + /* 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); } /** @@ -187,55 +204,32 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in */ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value) { - /* only continue if buffer can fit at least 1 character and if - 'result' doesn't overflow */ - if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) + /* treat 0 as a corner case */ + if (value == 0) { - /* treat 0 as a corner case */ - if (value == 0) - { - if (buffer) - { - buffer[*result] = '0'; - } - else - { - MBED_PRINT_CHARACTER('0'); - } + mbed_minimal_putchar(buffer, length, result, '0'); + } + else + { + /* allocate 3 digits per byte */ + char scratch[sizeof(MBED_UNSIGNED_STORAGE) * 3] = { 0 }; - *result += 1; + 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; } - else + + /* write scratch pad to buffer or output */ + for ( ; index > 0; index--) { - /* 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 ( ; (*result <= INT_MAX- 1) && ((size_t)*result < length) && (index > 0); index--) - { - if (buffer) - { - buffer[*result] = scratch[index - 1]; - } - else - { - MBED_PRINT_CHARACTER(scratch[index - 1]); - } - - *result += 1; - } + mbed_minimal_putchar(buffer, length, result, scratch[index - 1]); } } } @@ -252,9 +246,7 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt { bool print_leading_zero = false; - /* only continue each loop if buffer can fit at least 2 characters - and if 'result' doesn't overflow */ - for (int index = 7; (*result >= 0) && (*result <= INT_MAX - 2) && ((size_t)*result + 2 <= length) && (index >= 0); index--) + for (int index = 7; index >= 0; index--) { /* get most significant byte */ uint8_t output = value >> (8 * index); @@ -262,35 +254,19 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt /* only print leading zeros when set */ if (print_leading_zero || (output != 0) || (index == 0)) { - /* print zeroes after the first non-zero byte */ - print_leading_zero = true; - unsigned int nibble_one = (output >> 4); unsigned int nibble_two = (output & 0x0F); const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - /* write to buffer or stdout */ - if (buffer) - { - if (nibble_one != 0) { - buffer[*result] = int2hex[nibble_one]; - *result += 1; - } - buffer[*result] = int2hex[nibble_two]; - *result += 1; - } - else - { - if (nibble_one != 0) { - MBED_PRINT_CHARACTER(int2hex[nibble_one]); - *result += 1; - } - MBED_PRINT_CHARACTER(int2hex[nibble_two]); - *result += 1; + if (print_leading_zero || nibble_one != 0) { + mbed_minimal_putchar(buffer, length, result, int2hex[nibble_one]); } + mbed_minimal_putchar(buffer, length, result, int2hex[nibble_two]); + /* print zeroes after the first non-zero byte */ + print_leading_zero = true; } } } @@ -305,28 +281,12 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt */ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value) { - /* only continue if buffer can fit '0x' and twice the size of a void* - and if 'result' doesn't overflow */ - size_t needed = 2 + 2 * sizeof(void*); - if ((*result >= 0) && ((size_t)*result <= INT_MAX - needed) && ((size_t)*result + needed <= length)) - { - /* write leading 0x */ - if (buffer) - { - buffer[*result] = '0'; - buffer[*result + 1] = 'x'; - } - else - { - MBED_PRINT_CHARACTER('0'); - MBED_PRINT_CHARACTER('x'); - } + /* write leading 0x */ + mbed_minimal_putchar(buffer, length, result, '0'); + mbed_minimal_putchar(buffer, length, result, 'x'); - *result += 2; - - /* write rest as a regular hexadecimal number */ - mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value); - } + /* write rest as a regular hexadecimal number */ + mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value); } #if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT @@ -340,53 +300,48 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng */ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, int* result, double value) { - /* only continue if buffer can fit at least 1 character and if - 'result' doesn't overflow */ - if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) + /* get integer part */ + MBED_SIGNED_STORAGE integer = value; + + /* write integer part */ + mbed_minimal_formatted_string_signed(buffer, length, result, integer); + + /* write decimal point */ + mbed_minimal_formatted_string_character(buffer, length, result, '.'); + + /* get decimal part */ + double precision = 1.0; + + for (size_t index = 0; index < MBED_CONF_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS; index++) { - /* get integer part */ - MBED_SIGNED_STORAGE integer = value; - - /* write integer part */ - mbed_minimal_formatted_string_signed(buffer, length, result, integer); - - /* write decimal point */ - mbed_minimal_formatted_string_character(buffer, length, result, '.'); - - /* 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++; - } - - /* write decimal part */ - mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal); + 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++; + } + + /* write decimal part */ + mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal); } #endif @@ -400,34 +355,24 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in */ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character) { - /* only continue if the buffer can fit 1 character and if - 'result' doesn't overflow */ - if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) + /* write character */ + if (buffer) { - /* write character */ - if (buffer) - { - buffer[*result] = character; - } - else - { - /* convert \n to \r\n if enabled in platform configuration */ + mbed_minimal_putchar(buffer, length, result, character); + } + 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_PRINT_CHARACTER('\r'); - *result += 1; - } - - /* cache character */ - mbed_stdio_out_prev = character; -#endif - - /* write character to stdout */ - MBED_PRINT_CHARACTER(character); + if (character == '\n' && mbed_stdio_out_prev != '\r') + { + mbed_minimal_putchar(buffer, length, result, '\r'); } - *result += 1; + /* cache character */ + mbed_stdio_out_prev = character; +#endif + mbed_minimal_putchar(buffer, length, result, character); } } @@ -441,44 +386,10 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, */ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string) { - /* only continue if the buffer can fit at least 1 character and if - 'result' doesn't overflow */ - if ((*result >= 0) && (*result <= INT_MAX - 1) && ((size_t)*result + 1 <= length)) + while (*string != '\0') { - /* count characters in string */ - size_t remaining = length - *result; - size_t string_length = 0; - - /* only count characters that will fit into buffer */ - while ((string[string_length] != '\0') && (string_length < remaining)) - { - string_length++; - } - - /* copy string to buffer */ - if (buffer) - { - /* ensure that the value of "result" doesn't overflow */ - if (string_length + *result > INT_MAX) - { - string_length = (size_t)INT_MAX - *result; - } - for (size_t index = 0; index < string_length; index++) - { - buffer[*result + index] = string[index]; - } - } - /* print string */ - else - { - for (size_t index = 0; index < string_length; index++) - { - MBED_PRINT_CHARACTER(string[index]); - } - } - - /* add length to counter */ - *result += string_length; + mbed_minimal_putchar(buffer, length, result, *string); + string ++; } } @@ -498,12 +409,23 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma 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 > 0 && length <= INT_MAX) + if (format && length >= 0 && 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++) { @@ -765,10 +687,18 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma } } - /* if writing to buffer, NULL terminate string in reserved space*/ - if (buffer && ((size_t)result < length)) + if (buffer && !empty_buffer) { - buffer[result] = '\0'; + /* 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'; + } } } From 541455d75f0bcdba31759469621c33f7e37ec1f4 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Tue, 1 May 2018 12:27:28 +0300 Subject: [PATCH 23/36] TEST_ASSERT_EQUAL_STRING always tests against the base version --- .../TESTS/minimal-printf/compliance/main.cpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index c5aa85e93c..021d999d82 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -475,12 +475,12 @@ static control_t test_snprintf_u(const size_t call_count) #else result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "ju: %ju\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "ju: %ju\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_STRING("ju: 0\r\n", buffer_minimal); + 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("ju: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif @@ -489,12 +489,12 @@ static control_t test_snprintf_u(const size_t call_count) #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("zu: 0\r\n", buffer_minimal); + 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("zu: 4294967295\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif @@ -503,12 +503,12 @@ static control_t test_snprintf_u(const size_t call_count) #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("tu: 0\r\n", buffer_minimal); + 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("tu: 18446744073709551615\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif @@ -526,7 +526,7 @@ static control_t test_snprintf_x(const size_t call_count) /*************************************************************************/ 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("hhX: 0\r\n", buffer_minimal); + 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); @@ -536,7 +536,7 @@ static control_t test_snprintf_x(const size_t call_count) 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("hX: 0\r\n", buffer_minimal); + 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); @@ -545,7 +545,7 @@ static control_t test_snprintf_x(const size_t call_count) 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("X: 0\r\n", buffer_minimal); + 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); @@ -555,7 +555,7 @@ static control_t test_snprintf_x(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "lX: %lX\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "lX: %lX\r\n", 0UL); - TEST_ASSERT_EQUAL_STRING("lX: 0\r\n", buffer_minimal); + 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); @@ -565,7 +565,7 @@ static control_t test_snprintf_x(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "llX: %llX\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "llX: %llX\r\n", 0ULL); - TEST_ASSERT_EQUAL_STRING("llX: 0\r\n", buffer_minimal); + 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); @@ -578,12 +578,12 @@ static control_t test_snprintf_x(const size_t call_count) #else result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "jX: %jX\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "jX: %jX\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_STRING("jX: 0\r\n", buffer_minimal); + 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("jX: 0\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif @@ -592,12 +592,12 @@ static control_t test_snprintf_x(const size_t call_count) #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("zX: 0\r\n", buffer_minimal); + 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("zX: FFFFFFFF\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif @@ -606,12 +606,12 @@ static control_t test_snprintf_x(const size_t call_count) #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("tX: 0\r\n", buffer_minimal); + 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("tX: FFFFFFFFFFFFFFFF\r\n", buffer_minimal); + TEST_ASSERT_EQUAL_STRING(buffer_baseline, buffer_minimal); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #endif @@ -663,7 +663,7 @@ static control_t test_snprintf_f(const size_t call_count) result_minimal = mbed_snprintf(buffer_minimal, sizeof(buffer_minimal), "f: %f\r\n", 0); result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 0); - TEST_ASSERT_EQUAL_STRING("f: 0.0\r\n", buffer_minimal); + 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); From cbdb3fe3fde38e2e6558fde246b1527796c2ace1 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Sun, 6 May 2018 20:07:24 -0700 Subject: [PATCH 24/36] Optional SWO output instead of UART Change the default output from STDIO UART to SWO by overriding: "minimal-printf.console-output": "SWO" --- features/minimal-printf/mbed_lib.json | 4 +++ .../mbed_printf_implementation.c | 36 +++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json index c7d6fb3098..1709e339f4 100644 --- a/features/minimal-printf/mbed_lib.json +++ b/features/minimal-printf/mbed_lib.json @@ -12,6 +12,10 @@ "enable-64-bit": { "help": "Enable printing 64 bit integers", "value": true + }, + "console-output": { + "help": "Console output. Options: UART, SWO", + "value": "UART" } } } diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 4c7f0c354d..4b8cd1a4ac 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -25,18 +25,26 @@ /* 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" -#if DEVICE_SERIAL static serial_t stdio_uart = { 0 }; -#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES -static char mbed_stdio_out_prev = 0; -#endif -#endif /* module variable for keeping track of initialization */ static bool not_initialized = true; @@ -47,11 +55,9 @@ static void init_serial() { not_initialized = false; -#if DEVICE_SERIAL 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 #endif } } @@ -59,6 +65,22 @@ static void init_serial() #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 */ /***************************/ From 71966b6e5a940c99e44129efb4129884a0723c22 Mon Sep 17 00:00:00 2001 From: Alon Nof Date: Mon, 17 Dec 2018 12:38:42 +0200 Subject: [PATCH 25/36] remove warning: comparison of an unsigned value (#13) remove compile warning: comparison of an unsigned value is always true --- features/minimal-printf/mbed_printf_implementation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index 4b8cd1a4ac..eca418ae17 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -436,7 +436,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma /* 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 >= 0 && length <= INT_MAX) + if (format && length <= INT_MAX) { /* Make sure that there's always space for the NULL terminator */ if (length > 0) From 0ee94bc8c48a55853d7832401b9db3a31d935b9d Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Wed, 27 Mar 2019 07:19:39 -0700 Subject: [PATCH 26/36] Add consistent casts and widths to constants --- .../TESTS/minimal-printf/compliance/main.cpp | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index 021d999d82..c1426c5784 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -160,7 +160,7 @@ static control_t test_printf_u(const size_t call_count) result_baseline = printf("u: %u\r\n", UINT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("lu: %lu\r\n", 0); + result_minimal = mbed_printf("lu: %lu\r\n", 0UL); result_baseline = printf("lu: %lu\r\n", 0UL); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); @@ -168,7 +168,7 @@ static control_t test_printf_u(const size_t call_count) result_baseline = printf("lu: %lu\r\n", ULONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("llu: %llu\r\n", 0); + result_minimal = mbed_printf("llu: %llu\r\n", 0ULL); result_baseline = printf("llu: %llu\r\n", 0ULL); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); @@ -179,8 +179,8 @@ static control_t test_printf_u(const size_t call_count) #ifdef TARGET_LIKE_MBED printf("%%ju not supported by mbed\r\n"); #else - result_minimal = mbed_printf("ju: %ju\r\n", 0); - result_baseline = printf("ju: %ju\r\n",(uintmax_t) 0); + result_minimal = mbed_printf("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); result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); @@ -246,7 +246,7 @@ static control_t test_printf_x(const size_t call_count) result_baseline = printf("X: %X\r\n", UINT_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("lX: %lX\r\n", 0); + result_minimal = mbed_printf("lX: %lX\r\n", 0UL); result_baseline = printf("lX: %lX\r\n", 0UL); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); @@ -254,7 +254,7 @@ static control_t test_printf_x(const size_t call_count) result_baseline = printf("lX: %lX\r\n", ULONG_MAX); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - result_minimal = mbed_printf("llX: %llX\r\n", 0); + result_minimal = mbed_printf("llX: %llX\r\n", 0ULL); result_baseline = printf("llX: %llX\r\n", 0ULL); TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); @@ -265,7 +265,7 @@ static control_t test_printf_x(const size_t call_count) #ifdef TARGET_LIKE_MBED printf("%%jX not supported by mbed\r\n"); #else - result_minimal = mbed_printf("jX: %jX\r\n", 0); + result_minimal = mbed_printf("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); @@ -369,12 +369,12 @@ static control_t test_snprintf_d(const size_t call_count) #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", INT32_MIN); + 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", INT32_MAX); + 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); @@ -383,12 +383,12 @@ static control_t test_snprintf_d(const size_t call_count) #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", INT32_MIN); + 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", INT32_MAX); + 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); @@ -450,7 +450,7 @@ static control_t test_snprintf_u(const size_t call_count) 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", 0); + 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); @@ -460,7 +460,7 @@ static control_t test_snprintf_u(const size_t call_count) 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", 0); + 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); @@ -473,7 +473,7 @@ static control_t test_snprintf_u(const size_t call_count) #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", 0); + 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); @@ -553,7 +553,7 @@ static control_t test_snprintf_x(const size_t call_count) 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", 0); + 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); @@ -563,7 +563,7 @@ static control_t test_snprintf_x(const size_t call_count) 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", 0); + 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); @@ -576,7 +576,7 @@ static control_t test_snprintf_x(const size_t call_count) #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", 0); + 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); From 8701e0f4c4bc9b61cd7c7a6feee7e56b798c5a66 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Mon, 1 Apr 2019 09:09:06 -0700 Subject: [PATCH 27/36] Fix file endings Make all files have Unix style line endings. --- .../TESTS/minimal-printf/compliance/main.cpp | 1606 ++++++++--------- features/minimal-printf/mbed_lib.json | 42 +- features/minimal-printf/mbed_printf.h | 118 +- .../mbed_printf_implementation.h | 40 +- features/minimal-printf/mbed_printf_wrapper.c | 158 +- 5 files changed, 982 insertions(+), 982 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index c1426c5784..e288547fad 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -1,803 +1,803 @@ -/* 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 -#include -#include -#include - -#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; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MIN); - result_baseline = printf("hhd: %hhd\r\n", SCHAR_MIN); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MAX); - result_baseline = printf("hhd: %hhd\r\n", SCHAR_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN); - result_baseline = printf("hd: %hd\r\n", SHRT_MIN); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX); - result_baseline = printf("hd: %hd\r\n", SHRT_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("d: %d\r\n", INT_MIN); - result_baseline = printf("d: %d\r\n", INT_MIN); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("d: %d\r\n", INT_MAX); - result_baseline = printf("d: %d\r\n", INT_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN); - result_baseline = printf("ld: %ld\r\n", LONG_MIN); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX); - result_baseline = printf("ld: %ld\r\n", LONG_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN); - result_baseline = printf("lld: %lld\r\n", LLONG_MIN); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MAX); - result_baseline = printf("lld: %lld\r\n", LLONG_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - -#ifdef TARGET_LIKE_MBED - printf("%%jd not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("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); - - result_minimal = mbed_printf("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); -#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_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MIN); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("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); -#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_baseline = printf("td: %td\r\n", PTRDIFF_MIN); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); - result_baseline = printf("td: %td\r\n", PTRDIFF_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - - return CaseNext; -} - -static control_t test_printf_u(const size_t call_count) -{ - int result_baseline; - int result_minimal; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_printf("hhu: %hhu\r\n", 0); - result_baseline = printf("hhu: %hhu\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hhu: %hhu\r\n", UCHAR_MAX); - result_baseline = printf("hhu: %hhu\r\n", UCHAR_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hu: %hu\r\n", 0); - result_baseline = printf("hu: %hu\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX); - result_baseline = printf("hu: %hu\r\n", USHRT_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("u: %u\r\n", 0); - result_baseline = printf("u: %u\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("u: %u\r\n", UINT_MAX); - result_baseline = printf("u: %u\r\n", UINT_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("lu: %lu\r\n", 0UL); - result_baseline = printf("lu: %lu\r\n", 0UL); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX); - result_baseline = printf("lu: %lu\r\n", ULONG_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("llu: %llu\r\n", 0ULL); - result_baseline = printf("llu: %llu\r\n", 0ULL); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("llu: %llu\r\n", ULLONG_MAX); - result_baseline = printf("llu: %llu\r\n", ULLONG_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - -#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_baseline = printf("ju: %ju\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); - result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX); - 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_printf("zu: %zu\r\n", 0); - result_baseline = printf("zu: %zu\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); - result_baseline = printf("zu: %zu\r\n", SIZE_MAX); - 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_printf("tu: %tu\r\n", 0); - result_baseline = printf("tu: %tu\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); - result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - - return CaseNext; -} - -static control_t test_printf_x(const size_t call_count) -{ - int result_baseline; - int result_minimal; - - /*************************************************************************/ - /*************************************************************************/ - result_minimal = mbed_printf("hhX: %hhX\r\n", 0); - result_baseline = printf("hhX: %hhX\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX); - result_baseline = printf("hhX: %hhX\r\n", UCHAR_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hX: %hX\r\n", 0); - result_baseline = printf("hX: %hX\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX); - result_baseline = printf("hX: %hX\r\n", USHRT_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("X: %X\r\n", 0); - result_baseline = printf("X: %X\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("X: %X\r\n", UINT_MAX); - result_baseline = printf("X: %X\r\n", UINT_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("lX: %lX\r\n", 0UL); - result_baseline = printf("lX: %lX\r\n", 0UL); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX); - result_baseline = printf("lX: %lX\r\n", ULONG_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("llX: %llX\r\n", 0ULL); - result_baseline = printf("llX: %llX\r\n", 0ULL); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX); - result_baseline = printf("llX: %llX\r\n", ULLONG_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - -#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_baseline = printf("jX: %jX\r\n", (uintmax_t) 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX); - result_baseline = printf("jX: %jX\r\n", UINTMAX_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - -#ifdef TARGET_LIKE_MBED - printf("%%zX not supported by mbed\r\n"); -#else - result_minimal = mbed_printf("zX: %zX\r\n", 0); - result_baseline = printf("zX: %zX\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX); - result_baseline = printf("zX: %zX\r\n", SIZE_MAX); - 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_printf("tX: %tX\r\n", 0); - result_baseline = printf("tX: %tX\r\n", 0); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); - - result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX); - result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX); - TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); -#endif - - 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", -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); - result_baseline = printf("f: %f\r\n", 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", -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); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\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), "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 -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("d: %d", -1024); -} - -static control_t test_snprintf_buffer_overflow_ld(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("ld: %ld", -1048576L); -} - -static control_t test_snprintf_buffer_overflow_lld(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("lld: %lld", -1099511627776LL); -} - -static control_t test_snprintf_buffer_overflow_u(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("u: %u", 1024); -} - -static control_t test_snprintf_buffer_overflow_lu(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("lu: %lu", 1048576UL); -} - -static control_t test_snprintf_buffer_overflow_llu(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("llu: %llu", 1099511627776ULL); -} - -static control_t test_snprintf_buffer_overflow_x(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("x: 0x%x", 0x400); -} - -static control_t test_snprintf_buffer_overflow_lx(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("lx: 0x%lx", 0x100000UL); -} - -static control_t test_snprintf_buffer_overflow_llx(const size_t call_count) -{ - return test_snprintf_buffer_overflow_generic("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); -} +/* 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 +#include +#include +#include + +#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; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MIN); + result_baseline = printf("hhd: %hhd\r\n", SCHAR_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hhd: %hhd\r\n", SCHAR_MAX); + result_baseline = printf("hhd: %hhd\r\n", SCHAR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MIN); + result_baseline = printf("hd: %hd\r\n", SHRT_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hd: %hd\r\n", SHRT_MAX); + result_baseline = printf("hd: %hd\r\n", SHRT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("d: %d\r\n", INT_MIN); + result_baseline = printf("d: %d\r\n", INT_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("d: %d\r\n", INT_MAX); + result_baseline = printf("d: %d\r\n", INT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MIN); + result_baseline = printf("ld: %ld\r\n", LONG_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("ld: %ld\r\n", LONG_MAX); + result_baseline = printf("ld: %ld\r\n", LONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MIN); + result_baseline = printf("lld: %lld\r\n", LLONG_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lld: %lld\r\n", LLONG_MAX); + result_baseline = printf("lld: %lld\r\n", LLONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + +#ifdef TARGET_LIKE_MBED + printf("%%jd not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("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); + + result_minimal = mbed_printf("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); +#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_baseline = printf("zd: %zd\r\n", (ssize_t) INT32_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("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); +#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_baseline = printf("td: %td\r\n", PTRDIFF_MIN); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("td: %td\r\n", PTRDIFF_MAX); + result_baseline = printf("td: %td\r\n", PTRDIFF_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + + return CaseNext; +} + +static control_t test_printf_u(const size_t call_count) +{ + int result_baseline; + int result_minimal; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhu: %hhu\r\n", 0); + result_baseline = printf("hhu: %hhu\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hhu: %hhu\r\n", UCHAR_MAX); + result_baseline = printf("hhu: %hhu\r\n", UCHAR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hu: %hu\r\n", 0); + result_baseline = printf("hu: %hu\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hu: %hu\r\n", USHRT_MAX); + result_baseline = printf("hu: %hu\r\n", USHRT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("u: %u\r\n", 0); + result_baseline = printf("u: %u\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("u: %u\r\n", UINT_MAX); + result_baseline = printf("u: %u\r\n", UINT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lu: %lu\r\n", 0UL); + result_baseline = printf("lu: %lu\r\n", 0UL); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lu: %lu\r\n", ULONG_MAX); + result_baseline = printf("lu: %lu\r\n", ULONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("llu: %llu\r\n", 0ULL); + result_baseline = printf("llu: %llu\r\n", 0ULL); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("llu: %llu\r\n", ULLONG_MAX); + result_baseline = printf("llu: %llu\r\n", ULLONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + +#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_baseline = printf("ju: %ju\r\n", (uintmax_t) 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("ju: %ju\r\n", UINTMAX_MAX); + result_baseline = printf("ju: %ju\r\n", UINTMAX_MAX); + 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_printf("zu: %zu\r\n", 0); + result_baseline = printf("zu: %zu\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("zu: %zu\r\n", SIZE_MAX); + result_baseline = printf("zu: %zu\r\n", SIZE_MAX); + 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_printf("tu: %tu\r\n", 0); + result_baseline = printf("tu: %tu\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("tu: %tu\r\n", UINTPTR_MAX); + result_baseline = printf("tu: %tu\r\n", UINTPTR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + + return CaseNext; +} + +static control_t test_printf_x(const size_t call_count) +{ + int result_baseline; + int result_minimal; + + /*************************************************************************/ + /*************************************************************************/ + result_minimal = mbed_printf("hhX: %hhX\r\n", 0); + result_baseline = printf("hhX: %hhX\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hhX: %hhX\r\n", UCHAR_MAX); + result_baseline = printf("hhX: %hhX\r\n", UCHAR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hX: %hX\r\n", 0); + result_baseline = printf("hX: %hX\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("hX: %hX\r\n", USHRT_MAX); + result_baseline = printf("hX: %hX\r\n", USHRT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("X: %X\r\n", 0); + result_baseline = printf("X: %X\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("X: %X\r\n", UINT_MAX); + result_baseline = printf("X: %X\r\n", UINT_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lX: %lX\r\n", 0UL); + result_baseline = printf("lX: %lX\r\n", 0UL); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("lX: %lX\r\n", ULONG_MAX); + result_baseline = printf("lX: %lX\r\n", ULONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("llX: %llX\r\n", 0ULL); + result_baseline = printf("llX: %llX\r\n", 0ULL); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("llX: %llX\r\n", ULLONG_MAX); + result_baseline = printf("llX: %llX\r\n", ULLONG_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + +#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_baseline = printf("jX: %jX\r\n", (uintmax_t) 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("jX: %jX\r\n", UINTMAX_MAX); + result_baseline = printf("jX: %jX\r\n", UINTMAX_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + +#ifdef TARGET_LIKE_MBED + printf("%%zX not supported by mbed\r\n"); +#else + result_minimal = mbed_printf("zX: %zX\r\n", 0); + result_baseline = printf("zX: %zX\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("zX: %zX\r\n", SIZE_MAX); + result_baseline = printf("zX: %zX\r\n", SIZE_MAX); + 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_printf("tX: %tX\r\n", 0); + result_baseline = printf("tX: %tX\r\n", 0); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); + + result_minimal = mbed_printf("tX: %tX\r\n", UINTPTR_MAX); + result_baseline = printf("tX: %tX\r\n", UINTPTR_MAX); + TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); +#endif + + 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", -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); + result_baseline = printf("f: %f\r\n", 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", -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); + result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\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), "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 +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("d: %d", -1024); +} + +static control_t test_snprintf_buffer_overflow_ld(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("ld: %ld", -1048576L); +} + +static control_t test_snprintf_buffer_overflow_lld(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lld: %lld", -1099511627776LL); +} + +static control_t test_snprintf_buffer_overflow_u(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("u: %u", 1024); +} + +static control_t test_snprintf_buffer_overflow_lu(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lu: %lu", 1048576UL); +} + +static control_t test_snprintf_buffer_overflow_llu(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("llu: %llu", 1099511627776ULL); +} + +static control_t test_snprintf_buffer_overflow_x(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("x: 0x%x", 0x400); +} + +static control_t test_snprintf_buffer_overflow_lx(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("lx: 0x%lx", 0x100000UL); +} + +static control_t test_snprintf_buffer_overflow_llx(const size_t call_count) +{ + return test_snprintf_buffer_overflow_generic("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); +} diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json index 1709e339f4..bdf04a34e8 100644 --- a/features/minimal-printf/mbed_lib.json +++ b/features/minimal-printf/mbed_lib.json @@ -1,21 +1,21 @@ -{ - "name": "minimal-printf", - "config": { - "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 - }, - "enable-64-bit": { - "help": "Enable printing 64 bit integers", - "value": true - }, - "console-output": { - "help": "Console output. Options: UART, SWO", - "value": "UART" - } - } -} +{ + "name": "minimal-printf", + "config": { + "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 + }, + "enable-64-bit": { + "help": "Enable printing 64 bit integers", + "value": true + }, + "console-output": { + "help": "Console output. Options: UART, SWO", + "value": "UART" + } + } +} diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h index 0b8f6652bf..ad561fc439 100644 --- a/features/minimal-printf/mbed_printf.h +++ b/features/minimal-printf/mbed_printf.h @@ -1,59 +1,59 @@ -/* 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 -#include - -#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); - -#ifdef __cplusplus -} -#endif - -#endif // MBED_PRINTF_H +/* 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 +#include + +#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); + +#ifdef __cplusplus +} +#endif + +#endif // MBED_PRINTF_H diff --git a/features/minimal-printf/mbed_printf_implementation.h b/features/minimal-printf/mbed_printf_implementation.h index a74d469dbf..dc9d305f6d 100644 --- a/features/minimal-printf/mbed_printf_implementation.h +++ b/features/minimal-printf/mbed_printf_implementation.h @@ -1,20 +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 -#include - -int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments); +/* 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 +#include + +int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments); diff --git a/features/minimal-printf/mbed_printf_wrapper.c b/features/minimal-printf/mbed_printf_wrapper.c index f6b0d76435..be3d9dd44f 100644 --- a/features/minimal-printf/mbed_printf_wrapper.c +++ b/features/minimal-printf/mbed_printf_wrapper.c @@ -1,79 +1,79 @@ -/* 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 - -#if defined(TOOLCHAIN_GCC) -#define SUB_PRINTF __wrap_printf -#define SUB_SNPRINTF __wrap_snprintf -#define SUB_SPRINTF __wrap_sprintf -#define SUB_VSNPRINTF __wrap_vsnprintf -#elif defined(TOOLCHAIN_ARM) -#define SUPER_PRINTF $Super$$printf -#define SUB_PRINTF $Sub$$printf -#define SUPER_SNPRINTF $Super$$snprintf -#define SUB_SNPRINTF $Sub$$snprintf -#define SUPER_SPRINTF $Super$$sprintf -#define SUB_SPRINTF $Sub$$sprintf -#define SUPER_VSNPRINTF $Super$$vsnprintf -#define SUB_VSNPRINTF $Sub$$vsnprintf -#elif defined(__ICCARM__) -#define SUPER_PRINTF $Super$$__iar_printf -#define SUB_PRINTF $Sub$$__iar_printf -#define SUPER_SNPRINTF $Super$$__iar_snprintf -#define SUB_SNPRINTF $Sub$$__iar_snprintf -#define SUPER_SPRINTF $Super$$__iar_sprintf -#define SUB_SPRINTF $Sub$$__iar_sprintf -#define SUPER_VSNPRINTF $Super$$__iar_vsnprintf -#define SUB_VSNPRINTF $Sub$$__iar_vsnprintf -#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); - 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); - 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); - va_end(arguments); - - return result; -} - -int SUB_VSNPRINTF(char* buffer, size_t length, const char* format, va_list arguments) -{ - return mbed_minimal_formatted_string(buffer, length, format, arguments); -} +/* 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 + +#if defined(TOOLCHAIN_GCC) +#define SUB_PRINTF __wrap_printf +#define SUB_SNPRINTF __wrap_snprintf +#define SUB_SPRINTF __wrap_sprintf +#define SUB_VSNPRINTF __wrap_vsnprintf +#elif defined(TOOLCHAIN_ARM) +#define SUPER_PRINTF $Super$$printf +#define SUB_PRINTF $Sub$$printf +#define SUPER_SNPRINTF $Super$$snprintf +#define SUB_SNPRINTF $Sub$$snprintf +#define SUPER_SPRINTF $Super$$sprintf +#define SUB_SPRINTF $Sub$$sprintf +#define SUPER_VSNPRINTF $Super$$vsnprintf +#define SUB_VSNPRINTF $Sub$$vsnprintf +#elif defined(__ICCARM__) +#define SUPER_PRINTF $Super$$__iar_printf +#define SUB_PRINTF $Sub$$__iar_printf +#define SUPER_SNPRINTF $Super$$__iar_snprintf +#define SUB_SNPRINTF $Sub$$__iar_snprintf +#define SUPER_SPRINTF $Super$$__iar_sprintf +#define SUB_SPRINTF $Sub$$__iar_sprintf +#define SUPER_VSNPRINTF $Super$$__iar_vsnprintf +#define SUB_VSNPRINTF $Sub$$__iar_vsnprintf +#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); + 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); + 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); + va_end(arguments); + + return result; +} + +int SUB_VSNPRINTF(char* buffer, size_t length, const char* format, va_list arguments) +{ + return mbed_minimal_formatted_string(buffer, length, format, arguments); +} From b6411116057311745ab5f8eaa89a41c91161a663 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Tue, 2 Apr 2019 07:25:43 -0700 Subject: [PATCH 28/36] Add Jenkins file Build [ARM, IAR, GCC_ARM] and test [K64F, NUCLEO_F429ZI]. --- features/minimal-printf/Jenkinsfile | 120 ++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 features/minimal-printf/Jenkinsfile diff --git a/features/minimal-printf/Jenkinsfile b/features/minimal-printf/Jenkinsfile new file mode 100644 index 0000000000..43123237d8 --- /dev/null +++ b/features/minimal-printf/Jenkinsfile @@ -0,0 +1,120 @@ +// 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": "eeva.mbedcloudtesting.com"], + "NUCLEO_F429ZI": ["toolchains": [ "ARM", "IAR", "GCC_ARM"], "raas": "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 + + // checkout newest Mbed OS release. + sh "mbed new ." + + if (toolchain == "GCC_ARM") { + // use custom release profile from minimal-printf to override functions in GCC. + sh "mbed test -vv --compile -m ${target} -t ${toolchain} -n '*minimal-printf*' --build ci --stats-depth 10 --profile ./profiles/release.json" + } else { + // 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" + } + + // 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 --grm ${target}:raas_client:${raas}:80 -vV --test-spec ./ci/test_spec.json --polling-timeout 240") + + // Clean up workarea. + step([$class: 'WsCleanup']) + } + } + } +} From 92089f66de8554b5208d174f02e8ad74c5b4530c Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Fri, 29 Mar 2019 07:01:07 -0700 Subject: [PATCH 29/36] Optimize Arm Compiler 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 with dummy versions that take up less space. --- .../mbed_printf_armlink_overrides.c | 371 ++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 features/minimal-printf/mbed_printf_armlink_overrides.c diff --git a/features/minimal-printf/mbed_printf_armlink_overrides.c b/features/minimal-printf/mbed_printf_armlink_overrides.c new file mode 100644 index 0000000000..eda0ad453d --- /dev/null +++ b/features/minimal-printf/mbed_printf_armlink_overrides.c @@ -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 +#include +#include + +/** + * 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); + 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); + 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); + 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); + 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); +} + +/** + * 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 From aa8915611a4920fc29ea48b6a10c4f2f41c47ca2 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Thu, 11 Apr 2019 03:13:00 -0700 Subject: [PATCH 30/36] Update Mbed OS compile profiles to include Arm Compiler 6 Compiler profiles are only necessary for GCC but with updated profiles the user can choose to use either. --- features/minimal-printf/profiles/debug.json | 32 ++++++++++++++----- features/minimal-printf/profiles/develop.json | 27 ++++++++++++---- features/minimal-printf/profiles/release.json | 21 +++++++++--- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/features/minimal-printf/profiles/debug.json b/features/minimal-printf/profiles/debug.json index f10ec679df..c1fe9cc869 100644 --- a/features/minimal-printf/profiles/debug.json +++ b/features/minimal-printf/profiles/debug.json @@ -5,30 +5,45 @@ "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", "-fno-delete-null-pointer-checks", - "-fomit-frame-pointer", "-O0", "-g3"], + "-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,_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,snprintf", "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] }, + "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"], + "--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": [] + "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"], + "--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"], @@ -36,10 +51,11 @@ }, "IAR": { "common": [ - "--no_wrap_diagnostics", "-e", - "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-On", "-r"], + "--no_wrap_diagnostics", "-e", + "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-On", "-r", "-DMBED_DEBUG", + "-DMBED_TRAP_ERRORS_ENABLED=1", "--enable_restrict"], "asm": [], - "c": ["--vla"], + "c": ["--vla", "--diag_suppress=Pe546"], "cxx": ["--guard_calls", "--no_static_destruction"], "ld": ["--skip_dynamic_initialization", "--threaded_lib"] } diff --git a/features/minimal-printf/profiles/develop.json b/features/minimal-printf/profiles/develop.json index 37bbf12e84..8191522a58 100644 --- a/features/minimal-printf/profiles/develop.json +++ b/features/minimal-printf/profiles/develop.json @@ -5,30 +5,42 @@ "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", "-fno-delete-null-pointer-checks", - "-fomit-frame-pointer", "-Os", "-g"], + "-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,_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,snprintf", "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] }, + "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"], + "--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": [] + "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"], + "--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"], @@ -37,9 +49,10 @@ "IAR": { "common": [ "--no_wrap_diagnostics", "-e", - "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Oh"], + "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Oh", "--enable_restrict", + "-DMBED_TRAP_ERRORS_ENABLED=1"], "asm": [], - "c": ["--vla"], + "c": ["--vla", "--diag_suppress=Pe546"], "cxx": ["--guard_calls", "--no_static_destruction"], "ld": ["--skip_dynamic_initialization", "--threaded_lib"] } diff --git a/features/minimal-printf/profiles/release.json b/features/minimal-printf/profiles/release.json index 1c8174aaad..34c56b0361 100644 --- a/features/minimal-printf/profiles/release.json +++ b/features/minimal-printf/profiles/release.json @@ -5,16 +5,27 @@ "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", "-ffunction-sections", "-fdata-sections", "-funsigned-char", "-MMD", "-fno-delete-null-pointer-checks", - "-fomit-frame-pointer", "-Os", "-DNDEBUG", "-g"], + "-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,_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,snprintf", "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] }, + "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", @@ -22,7 +33,7 @@ "asm": [], "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], "cxx": ["--cpp", "--no_rtti", "--no_vla"], - "ld": [] + "ld": ["--show_full_path", "--keep=os_cb_sections"] }, "uARM": { "common": ["-c", "--gnu", "-Ospace", "--split_sections", @@ -37,9 +48,9 @@ "IAR": { "common": [ "--no_wrap_diagnostics", "-e", - "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Ohz", "-DNDEBUG"], + "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Ohz", "-DNDEBUG", "--enable_restrict"], "asm": [], - "c": ["--vla"], + "c": ["--vla", "--diag_suppress=Pe546"], "cxx": ["--guard_calls", "--no_static_destruction"], "ld": ["--skip_dynamic_initialization", "--threaded_lib"] } From 705d428fde6391df7d4a1e0908c2181d0305caf1 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Wed, 27 Mar 2019 06:23:59 -0700 Subject: [PATCH 31/36] Improve conformity * Parse each specifier based on this pattern: %[flags][width][.precision][length]specifier http://www.cplusplus.com/reference/cstdio/printf/ * Flags and width are still ignored. * Precision is supported for strings (string precision is used by Pelion Client). * Length is supported. --- features/minimal-printf/mbed_lib.json | 16 +- .../mbed_printf_implementation.c | 215 +++++++++++------- 2 files changed, 141 insertions(+), 90 deletions(-) diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json index bdf04a34e8..690783f8de 100644 --- a/features/minimal-printf/mbed_lib.json +++ b/features/minimal-printf/mbed_lib.json @@ -1,6 +1,14 @@ { "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-floating-point": { "help": "Enable floating point printing", "value": false @@ -8,14 +16,6 @@ "set-floating-point-max-decimals": { "help": "Maximum number of decimals to be printed", "value": 6 - }, - "enable-64-bit": { - "help": "Enable printing 64 bit integers", - "value": true - }, - "console-output": { - "help": "Console output. Options: UART, SWO", - "value": "UART" } } } diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index eca418ae17..cbebfce575 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -130,19 +130,24 @@ static void init_serial() #error unsupported architecture #endif +/** + * Precision defines + */ +#define PRECISION_DEFAULT (INT_MAX) + /** * Enum for storing width modifier. */ typedef enum { - LENGTH_NONE, - LENGTH_HH, - LENGTH_H, - LENGTH_L, - LENGTH_LL, - LENGTH_J, - LENGTH_Z, - LENGTH_T, - LENGTH_CAPITAL_L + 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; /** @@ -153,7 +158,7 @@ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value); static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character); -static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string); +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string, size_t precision); /** * @brief Print a single character, checking for buffer and size overflows. @@ -399,19 +404,21 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, } /** - * @brief Print string. + * @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 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) +static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string, size_t precision) { - while (*string != '\0') + while ((*string != '\0') && (precision)) { mbed_minimal_putchar(buffer, length, result, *string); - string ++; + string++; + precision--; } } @@ -456,77 +463,121 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma { size_t next_index = index + 1; - /* while format string is not empty */ - while ((format[next_index] != '\0') && - /* skip all flags and precision modifiers */ - (((format[next_index] >= '0') && (format[next_index] <= '9')) || - (format[next_index] == '-') || - (format[next_index] == '+') || - (format[next_index] == '#') || - (format[next_index] == '.'))) + /************************************************************** + * 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++; } - /* look for length modifier, default to NONE */ - length_t length_modifier = LENGTH_NONE; - - /* look for two character length modifier */ - if (format[next_index + 1] != '\0') + /************************************************************** + * skip and ignore width [(number)*] + *************************************************************/ + if (format[next_index] == '*') { - 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; - } + /* skip to next character */ + next_index++; - /* increment next_index if length modifier was found */ - if (length_modifier != LENGTH_NONE) - { - next_index += 2; - } + /* discard argument */ + va_arg(arguments, MBED_SIGNED_NATIVE_TYPE); } - - /* look for one character length modifier if two character search failed */ - if ((length_modifier == LENGTH_NONE) && (format[next_index] != '\0')) + 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 next_index if length modifier was found */ - if (length_modifier != LENGTH_NONE) + while ((format[next_index] >= '0') && + (format[next_index] <= '9')) { + /* skip to next character */ next_index++; } } - /* read out character - this is a supported format character, '\0', or a not suported character */ + /************************************************************** + * 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 */ @@ -534,7 +585,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma { MBED_SIGNED_STORAGE value = 0; - #if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT +#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))) || @@ -544,7 +595,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma value = va_arg(arguments, MBED_SIGNED_STORAGE); } else - #endif +#endif { /* use native storage type (which can be 32 or 64 bit) */ value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE); @@ -587,7 +638,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma { MBED_UNSIGNED_STORAGE value = 0; - #if MBED_CONF_MINIMAL_PRINTF_ENABLE_64_BIT +#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))) || @@ -597,7 +648,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma value = va_arg(arguments, MBED_UNSIGNED_STORAGE); } else - #endif +#endif { /* use native storage type (which can be 32 or 64 bit) */ value = va_arg(arguments, MBED_UNSIGNED_NATIVE_TYPE); @@ -646,7 +697,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value); } } - #if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT +#if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT /* treat all floating points the same */ else if ((next == 'f') || (next == 'F') || (next == 'g') || (next == 'G')) { @@ -655,7 +706,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma mbed_minimal_formatted_string_double(buffer, length, &result, value); } - #endif +#endif /* character */ else if (next == 'c') { @@ -670,7 +721,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma char* value = va_arg(arguments, char*); index = next_index; - mbed_minimal_formatted_string_string(buffer, length, &result, value); + mbed_minimal_formatted_string_string(buffer, length, &result, value, precision); } /* pointer */ else if (next == 'p') From 9c157de2897cd0355086657120a3c34961623078 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Wed, 17 Apr 2019 14:14:40 -0700 Subject: [PATCH 32/36] Remove wrapper file in CI So we don't compare minimal-printf with itself. --- features/minimal-printf/Jenkinsfile | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/features/minimal-printf/Jenkinsfile b/features/minimal-printf/Jenkinsfile index 43123237d8..5750722b68 100644 --- a/features/minimal-printf/Jenkinsfile +++ b/features/minimal-printf/Jenkinsfile @@ -69,16 +69,14 @@ def buildStep(target, compilerLabel, toolchain) { // 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 ." - if (toolchain == "GCC_ARM") { - // use custom release profile from minimal-printf to override functions in GCC. - sh "mbed test -vv --compile -m ${target} -t ${toolchain} -n '*minimal-printf*' --build ci --stats-depth 10 --profile ./profiles/release.json" - } else { - // 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" - } + // 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" // stash build directory for testins step. stash name: "minimal-printf-greentea-${target}-${toolchain}", includes: "ci/**" From c975429e3d47d1b85b79d46c1a4f13ac16e90b81 Mon Sep 17 00:00:00 2001 From: Marcus Chang Date: Tue, 30 Apr 2019 07:06:44 -0700 Subject: [PATCH 33/36] Change CI from using HTTP to HTTPS for connecting to RaaS --- features/minimal-printf/Jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/minimal-printf/Jenkinsfile b/features/minimal-printf/Jenkinsfile index 5750722b68..d3f26004eb 100644 --- a/features/minimal-printf/Jenkinsfile +++ b/features/minimal-printf/Jenkinsfile @@ -16,8 +16,8 @@ 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": "eeva.mbedcloudtesting.com"], - "NUCLEO_F429ZI": ["toolchains": [ "ARM", "IAR", "GCC_ARM"], "raas": "ruka.mbedcloudtesting.com"], + "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. @@ -108,7 +108,7 @@ def testStep(target, compilerLabel, toolchain) { raas = targets[target]["raas"] // execute greentea on RaaS. - execute("mbedgt --grm ${target}:raas_client:${raas}:80 -vV --test-spec ./ci/test_spec.json --polling-timeout 240") + execute("mbedgt -g ${target}:raas_client:${raas}:443 -vV --test-spec ./ci/test_spec.json --polling-timeout 240") // Clean up workarea. step([$class: 'WsCleanup']) From 96b5c1d6d4ebb5fbc0b1360543054fd74d41ae2d Mon Sep 17 00:00:00 2001 From: Evelyne Donnaes Date: Tue, 2 Jul 2019 11:09:49 +0100 Subject: [PATCH 34/36] Fixed floating point support (#24) This PR adds: * Support for hexadecimal printing in lower case * Fixes to floating point printing (leading zeros in decimal part) --- .../TESTS/minimal-printf/compliance/main.cpp | 31 ++++++++++++++++--- .../mbed_printf_implementation.c | 26 +++++++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index e288547fad..5ca2c86279 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -298,6 +298,10 @@ static control_t test_printf_x(const size_t call_count) TEST_ASSERT_EQUAL_INT(result_baseline, result_minimal); #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; } @@ -629,12 +633,21 @@ static control_t test_printf_f(const size_t call_count) 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); - result_baseline = printf("f: %f\r\n", 0); + 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); @@ -656,13 +669,23 @@ static control_t test_snprintf_f(const size_t call_count) 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); - result_baseline = snprintf(buffer_baseline, sizeof(buffer_baseline), "f: %f\r\n", 0); + 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); diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index cbebfce575..eda78ee8d4 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -155,7 +155,7 @@ typedef enum { */ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value); static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); -static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); +static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value, bool upper); static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value); static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character); static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string, size_t precision); @@ -268,8 +268,9 @@ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, * @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) +static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value, bool upper) { bool print_leading_zero = false; @@ -284,8 +285,11 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt unsigned int nibble_one = (output >> 4); unsigned int nibble_two = (output & 0x0F); - const char int2hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + 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]); @@ -313,7 +317,7 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng mbed_minimal_putchar(buffer, length, result, 'x'); /* write rest as a regular hexadecimal number */ - mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value); + mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value, true); } #if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT @@ -367,6 +371,18 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in 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'); + precision_in_uint /= 10; + } + /* write decimal part */ mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal); } @@ -694,7 +710,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma } else { - mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value); + mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value, next == 'X'); } } #if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT From d8350738d3ea07f8a6e129546a14ba3ef5685fca Mon Sep 17 00:00:00 2001 From: Marcus Chang <7205609+marcuschangarm@users.noreply.github.com> Date: Thu, 4 Jul 2019 04:46:31 -0500 Subject: [PATCH 35/36] Add support for fprintf and vfprintf (#21) Debug print is routed to stderr which relies on [v]fprintf. This change adds support for overwriting the build-in [v]fprintf. --- features/minimal-printf/Jenkinsfile | 2 +- features/minimal-printf/README.md | 24 +++-- .../TESTS/minimal-printf/compliance/main.cpp | 99 +++++++++++++++++++ .../minimal-printf/compliance/test_app.json | 7 ++ features/minimal-printf/mbed_lib.json | 4 + features/minimal-printf/mbed_printf.c | 25 ++++- features/minimal-printf/mbed_printf.h | 16 +++ .../mbed_printf_armlink_overrides.c | 10 +- .../mbed_printf_implementation.c | 94 ++++++++++-------- .../mbed_printf_implementation.h | 2 +- features/minimal-printf/mbed_printf_wrapper.c | 85 ++++++++++++---- features/minimal-printf/profiles/debug.json | 6 +- features/minimal-printf/profiles/develop.json | 6 +- features/minimal-printf/profiles/release.json | 6 +- 14 files changed, 302 insertions(+), 84 deletions(-) create mode 100644 features/minimal-printf/TESTS/minimal-printf/compliance/test_app.json diff --git a/features/minimal-printf/Jenkinsfile b/features/minimal-printf/Jenkinsfile index d3f26004eb..88d62a4b90 100644 --- a/features/minimal-printf/Jenkinsfile +++ b/features/minimal-printf/Jenkinsfile @@ -76,7 +76,7 @@ def buildStep(target, compilerLabel, toolchain) { 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" + 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/**" diff --git a/features/minimal-printf/README.md b/features/minimal-printf/README.md index 107ff7591f..7d85c77e69 100644 --- a/features/minimal-printf/README.md +++ b/features/minimal-printf/README.md @@ -2,22 +2,31 @@ 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. +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). * %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). -* %g: floating point (disabled by default). -* %G: 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. @@ -28,7 +37,7 @@ To replace the standard implementations of the printf functions with the ones in $ mbed compile -t -m --profile mbed-printf/profiles/release.json ``` -## Enabling floating point, 64 bit integers, new line conversion, and setting baud rate +## Enabling floating point, FILE stream, 64 bit integers, new line conversion, and setting baud rate In mbed_app.json: @@ -37,7 +46,8 @@ In mbed_app.json: "*": { "platform.stdio-baud-rate": 115200, "platform.stdio-convert-newlines": false, - "minimal-printf.enable-floating-point": 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 } diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp index 5ca2c86279..e5d0c741fb 100755 --- a/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/main.cpp @@ -47,83 +47,116 @@ 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; @@ -133,83 +166,116 @@ 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; @@ -219,83 +285,116 @@ 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); diff --git a/features/minimal-printf/TESTS/minimal-printf/compliance/test_app.json b/features/minimal-printf/TESTS/minimal-printf/compliance/test_app.json new file mode 100644 index 0000000000..0a9cc69416 --- /dev/null +++ b/features/minimal-printf/TESTS/minimal-printf/compliance/test_app.json @@ -0,0 +1,7 @@ +{ + "target_overrides": { + "*": { + "minimal-printf.enable-file-stream": 1 + } + } +} diff --git a/features/minimal-printf/mbed_lib.json b/features/minimal-printf/mbed_lib.json index 690783f8de..4157696583 100644 --- a/features/minimal-printf/mbed_lib.json +++ b/features/minimal-printf/mbed_lib.json @@ -9,6 +9,10 @@ "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 diff --git a/features/minimal-printf/mbed_printf.c b/features/minimal-printf/mbed_printf.c index 41566989e9..d344f60e9e 100644 --- a/features/minimal-printf/mbed_printf.c +++ b/features/minimal-printf/mbed_printf.c @@ -22,7 +22,7 @@ int mbed_printf(const char *format, ...) { va_list arguments; va_start(arguments, format); - int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments); + int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL); va_end(arguments); return result; @@ -32,7 +32,7 @@ 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); + int result = mbed_minimal_formatted_string(buffer, length, format, arguments, NULL); va_end(arguments); return result; @@ -40,10 +40,27 @@ int mbed_snprintf(char* buffer, size_t length, const char* format, ...) int mbed_vprintf(const char* format, va_list arguments) { - return mbed_minimal_formatted_string(NULL, LONG_MAX, format, 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); + 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 diff --git a/features/minimal-printf/mbed_printf.h b/features/minimal-printf/mbed_printf.h index ad561fc439..edd82e701a 100644 --- a/features/minimal-printf/mbed_printf.h +++ b/features/minimal-printf/mbed_printf.h @@ -52,6 +52,22 @@ int mbed_vprintf(const char* format, va_list arguments); */ 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 diff --git a/features/minimal-printf/mbed_printf_armlink_overrides.c b/features/minimal-printf/mbed_printf_armlink_overrides.c index eda0ad453d..dd345940c7 100644 --- a/features/minimal-printf/mbed_printf_armlink_overrides.c +++ b/features/minimal-printf/mbed_printf_armlink_overrides.c @@ -38,7 +38,7 @@ int $Sub$$__2printf(const char *format, ...) { va_list arguments; va_start(arguments, format); - int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments); + int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL); va_end(arguments); return result; @@ -48,7 +48,7 @@ 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); + int result = mbed_minimal_formatted_string(buffer, LONG_MAX, format, arguments, NULL); va_end(arguments); return result; @@ -58,7 +58,7 @@ 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); + int result = mbed_minimal_formatted_string(buffer, length, format, arguments, NULL); va_end(arguments); return result; @@ -68,7 +68,7 @@ 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); + int result = mbed_minimal_formatted_string(buffer, LONG_MAX, format, arguments, NULL); va_end(arguments); return result; @@ -76,7 +76,7 @@ int $Sub$$__2vprintf(char* buffer, const char* format, ...) int $Sub$$__2vsnprintf(char* buffer, size_t length, const char* format, va_list arguments) { - return mbed_minimal_formatted_string(buffer, length, format, arguments); + return mbed_minimal_formatted_string(buffer, length, format, arguments, NULL); } /** diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index eda78ee8d4..f030443941 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -153,12 +153,13 @@ typedef enum { /** * Prototypes */ -static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, int* result, MBED_SIGNED_STORAGE value); -static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value); -static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t length, int* result, MBED_UNSIGNED_STORAGE value, bool upper); -static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t length, int* result, const void* value); -static void mbed_minimal_formatted_string_character(char* buffer, size_t length, int* result, char character); -static void mbed_minimal_formatted_string_string(char* buffer, size_t length, int* result, const char* string, size_t precision); +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. @@ -168,7 +169,7 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in * @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) +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)) @@ -182,7 +183,16 @@ static void mbed_minimal_putchar(char *buffer, size_t length, int* result, char } else { - MBED_PRINT_CHARACTER(data); +#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 @@ -199,7 +209,7 @@ static void mbed_minimal_putchar(char *buffer, size_t length, int* result, char * @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) +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; @@ -207,7 +217,7 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in if (value < 0) { /* write sign */ - mbed_minimal_putchar(buffer, length, result, '-'); + mbed_minimal_putchar(buffer, length, result, '-', stream); /* get absolute value using two's complement */ new_value = ~((MBED_UNSIGNED_STORAGE) value) + 1; @@ -218,7 +228,7 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in } /* use unsigned long int function */ - mbed_minimal_formatted_string_unsigned(buffer, length, result, new_value); + mbed_minimal_formatted_string_unsigned(buffer, length, result, new_value, stream); } /** @@ -229,12 +239,12 @@ static void mbed_minimal_formatted_string_signed(char* buffer, size_t length, in * @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) +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'); + mbed_minimal_putchar(buffer, length, result, '0', stream); } else { @@ -256,7 +266,7 @@ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, /* write scratch pad to buffer or output */ for ( ; index > 0; index--) { - mbed_minimal_putchar(buffer, length, result, scratch[index - 1]); + mbed_minimal_putchar(buffer, length, result, scratch[index - 1], stream); } } } @@ -270,7 +280,7 @@ static void mbed_minimal_formatted_string_unsigned(char* buffer, size_t length, * @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, bool upper) +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; @@ -292,9 +302,9 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt const char *int2hex = upper ? int2hex_upper : int2hex_lower; if (print_leading_zero || nibble_one != 0) { - mbed_minimal_putchar(buffer, length, result, int2hex[nibble_one]); + mbed_minimal_putchar(buffer, length, result, int2hex[nibble_one], stream); } - mbed_minimal_putchar(buffer, length, result, int2hex[nibble_two]); + mbed_minimal_putchar(buffer, length, result, int2hex[nibble_two], stream); /* print zeroes after the first non-zero byte */ print_leading_zero = true; @@ -310,14 +320,14 @@ static void mbed_minimal_formatted_string_hexadecimal(char* buffer, size_t lengt * @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) +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'); - mbed_minimal_putchar(buffer, length, result, 'x'); + 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, true); + mbed_minimal_formatted_string_hexadecimal(buffer, length, result, (ptrdiff_t) value, stream, true); } #if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT @@ -329,16 +339,16 @@ static void mbed_minimal_formatted_string_void_pointer(char* buffer, size_t leng * @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) +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); + mbed_minimal_formatted_string_signed(buffer, length, result, integer, stream); /* write decimal point */ - mbed_minimal_formatted_string_character(buffer, length, result, '.'); + mbed_minimal_formatted_string_character(buffer, length, result, '.', stream); /* get decimal part */ double precision = 1.0; @@ -384,7 +394,7 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in } /* write decimal part */ - mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal); + mbed_minimal_formatted_string_unsigned(buffer, length, result, decimal, stream); } #endif @@ -396,12 +406,12 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in * @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) +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); + mbed_minimal_putchar(buffer, length, result, character, stream); } else { @@ -409,13 +419,13 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES if (character == '\n' && mbed_stdio_out_prev != '\r') { - mbed_minimal_putchar(buffer, length, result, '\r'); + mbed_minimal_putchar(buffer, length, result, '\r', stream); } /* cache character */ mbed_stdio_out_prev = character; #endif - mbed_minimal_putchar(buffer, length, result, character); + mbed_minimal_putchar(buffer, length, result, character, stream); } } @@ -428,11 +438,11 @@ static void mbed_minimal_formatted_string_character(char* buffer, size_t length, * @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) +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); + mbed_minimal_putchar(buffer, length, result, *string, stream); string++; precision--; } @@ -448,7 +458,7 @@ static void mbed_minimal_formatted_string_string(char* buffer, size_t length, in * * @return Number of characters written. */ -int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments) +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(); @@ -647,7 +657,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma index = next_index; - mbed_minimal_formatted_string_signed(buffer, length, &result, value); + mbed_minimal_formatted_string_signed(buffer, length, &result, value, stream); } /* unsigned integer */ else if ((next == 'u') || (next == 'x') || (next == 'X')) @@ -706,11 +716,11 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma /* write unsigned or hexadecimal */ if (next == 'u') { - mbed_minimal_formatted_string_unsigned(buffer, length, &result, value); + mbed_minimal_formatted_string_unsigned(buffer, length, &result, value, stream); } else { - mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value, next == 'X'); + mbed_minimal_formatted_string_hexadecimal(buffer, length, &result, value, stream, next == 'X'); } } #if MBED_CONF_MINIMAL_PRINTF_ENABLE_FLOATING_POINT @@ -720,7 +730,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma double value = va_arg(arguments, double); index = next_index; - mbed_minimal_formatted_string_double(buffer, length, &result, value); + mbed_minimal_formatted_string_double(buffer, length, &result, value, stream); } #endif /* character */ @@ -729,7 +739,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma char value = va_arg(arguments, MBED_SIGNED_NATIVE_TYPE); index = next_index; - mbed_minimal_formatted_string_character(buffer, length, &result, value); + mbed_minimal_formatted_string_character(buffer, length, &result, value, stream); } /* string */ else if (next == 's') @@ -737,7 +747,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma char* value = va_arg(arguments, char*); index = next_index; - mbed_minimal_formatted_string_string(buffer, length, &result, value, precision); + mbed_minimal_formatted_string_string(buffer, length, &result, value, precision, stream); } /* pointer */ else if (next == 'p') @@ -745,21 +755,21 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma void* value = va_arg(arguments, void*); index = next_index; - mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value); + 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]); + 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]); + mbed_minimal_formatted_string_character(buffer, length, &result, format[index], stream); } else { @@ -772,7 +782,7 @@ int mbed_minimal_formatted_string(char* buffer, size_t length, const char* forma /* not a format specifier */ { /* write normal character */ - mbed_minimal_formatted_string_character(buffer, length, &result, format[index]); + mbed_minimal_formatted_string_character(buffer, length, &result, format[index], stream); } } diff --git a/features/minimal-printf/mbed_printf_implementation.h b/features/minimal-printf/mbed_printf_implementation.h index dc9d305f6d..c84b2ecc76 100644 --- a/features/minimal-printf/mbed_printf_implementation.h +++ b/features/minimal-printf/mbed_printf_implementation.h @@ -17,4 +17,4 @@ #include #include -int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments); +int mbed_minimal_formatted_string(char* buffer, size_t length, const char* format, va_list arguments, FILE* stream); diff --git a/features/minimal-printf/mbed_printf_wrapper.c b/features/minimal-printf/mbed_printf_wrapper.c index be3d9dd44f..1b0f9ac716 100644 --- a/features/minimal-printf/mbed_printf_wrapper.c +++ b/features/minimal-printf/mbed_printf_wrapper.c @@ -20,44 +20,56 @@ #if defined(TOOLCHAIN_GCC) #define SUB_PRINTF __wrap_printf -#define SUB_SNPRINTF __wrap_snprintf #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_SNPRINTF $Super$$snprintf -#define SUB_SNPRINTF $Sub$$snprintf #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_SNPRINTF $Super$$__iar_snprintf -#define SUB_SNPRINTF $Sub$$__iar_snprintf #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); - 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); + int result = mbed_minimal_formatted_string(NULL, LONG_MAX, format, arguments, NULL); va_end(arguments); return result; @@ -67,13 +79,50 @@ 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); + 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); + 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 diff --git a/features/minimal-printf/profiles/debug.json b/features/minimal-printf/profiles/debug.json index c1fe9cc869..9ee8975476 100644 --- a/features/minimal-printf/profiles/debug.json +++ b/features/minimal-printf/profiles/debug.json @@ -13,8 +13,10 @@ "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,snprintf", - "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] + "-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", diff --git a/features/minimal-printf/profiles/develop.json b/features/minimal-printf/profiles/develop.json index 8191522a58..9dd949e6ae 100644 --- a/features/minimal-printf/profiles/develop.json +++ b/features/minimal-printf/profiles/develop.json @@ -12,8 +12,10 @@ "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,snprintf", - "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] + "-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", diff --git a/features/minimal-printf/profiles/release.json b/features/minimal-printf/profiles/release.json index 34c56b0361..06caecfad4 100644 --- a/features/minimal-printf/profiles/release.json +++ b/features/minimal-printf/profiles/release.json @@ -12,8 +12,10 @@ "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,snprintf", - "-Wl,--wrap,sprintf", "-Wl,--wrap,vsnprintf", "-Wl,--wrap,vprintf"] + "-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", From 1624de29e9f3f9e6d18e3f5855f61cb662684a20 Mon Sep 17 00:00:00 2001 From: Evelyne Donnaes Date: Fri, 5 Jul 2019 15:24:44 +0100 Subject: [PATCH 36/36] Fixed compilation error (#25) --- features/minimal-printf/mbed_printf_implementation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/minimal-printf/mbed_printf_implementation.c b/features/minimal-printf/mbed_printf_implementation.c index f030443941..5365365b43 100644 --- a/features/minimal-printf/mbed_printf_implementation.c +++ b/features/minimal-printf/mbed_printf_implementation.c @@ -389,7 +389,7 @@ static void mbed_minimal_formatted_string_double(char* buffer, size_t length, in MBED_UNSIGNED_STORAGE val = decimal ? decimal : decimal + 1; while (precision_in_uint > val) { /* print leading zeros */ - mbed_minimal_putchar(buffer, length, result, '0'); + mbed_minimal_putchar(buffer, length, result, '0', stream); precision_in_uint /= 10; }