diff --git a/components/esp_rom/patches/esp_rom_print.c b/components/esp_rom/patches/esp_rom_print.c index ce9505a1b1..f92f0e3dd7 100644 --- a/components/esp_rom/patches/esp_rom_print.c +++ b/components/esp_rom/patches/esp_rom_print.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "esp_rom_caps.h" #include "esp_rom_sys.h" #include "rom/ets_sys.h" @@ -54,7 +55,7 @@ static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap) islong, islonglong; long long val = 0; int res = 0, length = 0; - + // %[flags][left_prec][.right_prec][sub_type]type while ((c = *fmt++) != '\0') { if (c == '%') { c = *fmt++; @@ -75,13 +76,11 @@ static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap) } if (c == '.') { c = *fmt++; - zero_fill++; + zero_fill = false; while (is_digit(c)) { right_prec = (right_prec * 10) + (c - '0'); c = *fmt++; } - } else { - right_prec = left_prec; } sign = '\0'; if (c == 'l') { @@ -168,10 +167,14 @@ static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap) case 'S': cp = va_arg(ap, char *); if (cp == NULL) { - cp = (char *)""; + cp = (char *)""; } length = 0; while (cp[length] != '\0') length++; + if (right_prec) { + length = MIN(right_prec, length); + right_prec = 0; + } break; case 'c': case 'C': @@ -206,6 +209,10 @@ static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap) res += 2; } pad = left_prec - length; + right_prec = right_prec - length; + if (right_prec > 0) { + pad -= right_prec; + } if (sign != '\0') { pad--; } @@ -229,6 +236,10 @@ static int ets_vprintf(void (*putc)(char c), const char *fmt, va_list ap) (*putc)(sign); res++; } + while (right_prec-- > 0) { + (*putc)('0'); + res++; + } while (length-- > 0) { c = *cp++; (*putc)(c); diff --git a/components/esp_rom/test_apps/linux_rom_apis/main/CMakeLists.txt b/components/esp_rom/test_apps/linux_rom_apis/main/CMakeLists.txt index baaac73170..e43a09c326 100644 --- a/components/esp_rom/test_apps/linux_rom_apis/main/CMakeLists.txt +++ b/components/esp_rom/test_apps/linux_rom_apis/main/CMakeLists.txt @@ -1,4 +1,5 @@ idf_component_register(SRCS "rom_test.cpp" + "rom_printf_test.cpp" INCLUDE_DIRS "." REQUIRES esp_rom WHOLE_ARCHIVE) diff --git a/components/esp_rom/test_apps/linux_rom_apis/main/rom_printf_test.cpp b/components/esp_rom/test_apps/linux_rom_apis/main/rom_printf_test.cpp new file mode 100644 index 0000000000..5561cf6c67 --- /dev/null +++ b/components/esp_rom/test_apps/linux_rom_apis/main/rom_printf_test.cpp @@ -0,0 +1,104 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include +#include "esp_rom_sys.h" +#include "esp_err.h" + +#include + +using namespace std; + +#define BUFFER_SIZE (128) +static char s_print_buffer[BUFFER_SIZE]; +static unsigned s_counter = 0; + +static void reset_buffer(void) +{ + s_counter = 0; + memset(s_print_buffer, 0, BUFFER_SIZE); +} + +void putc_to_buffer(char c) +{ + s_print_buffer[s_counter++] = c; +} + +static esp_err_t test_printf(const char *format, ...) +{ + esp_err_t error = ESP_OK; + va_list list1, list2; + char expected_str[BUFFER_SIZE]; + char *tested_str = s_print_buffer; + + va_start(list1, format); + va_copy(list2, list1); + reset_buffer(); + int len1 = esp_rom_vprintf(format, list1); + int len2 = vsnprintf(expected_str, BUFFER_SIZE, format, list2); + va_end(list2); + va_end(list1); + + if (len1 != len2) { + error = ESP_FAIL; + } + if (strcmp(tested_str, expected_str) != 0) { + error = ESP_FAIL; + } + if (error) { + printf("BAD: "); + } else { + printf("OK : "); + } + printf("'%s' -> %s", format, tested_str); + if (error) { + printf(" != "); + } else { + printf(" == "); + } + printf("%s\n", expected_str); + + return error; +} + +TEST_CASE("Test precisions attrs of esp_rom_vprintf") +{ + esp_rom_install_channel_putc(1, putc_to_buffer); + esp_err_t error = ESP_OK; + error |= test_printf("[%d|%3d|%6d|%03d|%06d|%0d]", 1, 2, 3, 4, 5, 6); + error |= test_printf("[%d|%3d|%6d|%03d|%06d|%0d]", -1, -2, -3, -4, -5, -6); + error |= test_printf("[%d|%3d|%6d|%03d|%06d|%0d]", 10, 11, 12, 13, 14, 15); + error |= test_printf("[%d|%3d|%6d|%03d|%06d|%0d]", -10, -11, -12, -13, -14, -15); + error |= test_printf("[%d|%3d|%6d|%03d|%06d|%0d]", 12345, 12346, 12347, 12348, 12349, 12350); + error |= test_printf("[%d|%3d|%6d|%03d|%06d|%0d]", -12345, -12346, -12347, -12348, -12349, -12350); + + error |= test_printf("[%.3d|%.1d|%.0d|%0.0d|%0.3d|%0.1d|%03.3d]", 1, 2, 3, 4, 5, 6, 7); + error |= test_printf("[%.3d|%.1d|%.0d|%0.0d|%0.3d|%0.1d|%03.3d]", -1, -2, -3, -4, -5, -6, -7); + error |= test_printf("[%.3d|%.1d|%.0d|%0.0d|%0.3d|%0.1d|%03.3d]", 10, 11, 12, 13, 14, 15, 16); + error |= test_printf("[%.3d|%.1d|%.0d|%0.0d|%0.3d|%0.1d|%03.3d]", -10, -11, -12, -13, -14, -15, -16); + error |= test_printf("[%.3d|%.1d|%.0d|%0.0d|%0.3d|%0.1d|%03.3d]", 12345, 12346, 12347, 12348, 12349, 12350, 123451); + error |= test_printf("[%.3d|%.1d|%.0d|%0.0d|%0.3d|%0.1d|%03.3d]", -12345, -12346, -12347, -12348, -12349, -12350, 123451); + + error |= test_printf("[%6.4d|%06.4d|%04.6d|%4.6d|%8.4d|%08.4d]", 1, 2, 3, 4, 5, 6); + error |= test_printf("[%6.4d|%06.4d|%04.6d|%4.6d|%8.4d|%08.4d]", -1, -2, -3, -4, -5, -6); + error |= test_printf("[%6.4d|%06.4d|%04.6d|%4.6d|%8.4d|%08.4d]", 10, 11, 12, 13, 14, 15); + error |= test_printf("[%6.4d|%06.4d|%04.6d|%4.6d|%8.4d|%08.4d]", -10, -11, -12, -13, -14, -15); + error |= test_printf("[%6.4d|%06.4d|%04.6d|%4.6d|%8.4d|%08.4d]", 12340, 12341, 12342, 12343, 12344, 12345); + error |= test_printf("[%6.4d|%06.4d|%04.6d|%4.6d|%8.4d|%08.4d]", -12340, -12341, -12342, -12343, -12344, -12345); + + error |= test_printf("[%-20s]", "1TEST_STR"); + error |= test_printf("[%-20.5s]", "8TEST_STR"); + error |= test_printf("[%20s]", "2TEST_STR"); + error |= test_printf("[%3s]", "3TEST_STR"); + error |= test_printf("[%.3s]", "4TEST_STR"); + error |= test_printf("[%.20s]", "5TEST_STR"); + error |= test_printf("[%6.3s]", "6TEST_STR"); + error |= test_printf("[%06.3s]", "7TEST_STR"); + esp_rom_install_uart_printf(); + CHECK(error == ESP_OK); +}