From 04b3e136474127117ccda35cca25df95470395af Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 16 Feb 2020 00:00:01 +0100 Subject: [PATCH 1/5] restore dtostrf+fix when float printing is disabled at link time --- cores/esp8266/core_esp8266_noniso.cpp | 83 +++++++++++++++++++++++++++ platform.txt | 5 +- tools/boards.txt.py | 1 + 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.cpp b/cores/esp8266/core_esp8266_noniso.cpp index 2d1fb71605..0368897c91 100644 --- a/cores/esp8266/core_esp8266_noniso.cpp +++ b/cores/esp8266/core_esp8266_noniso.cpp @@ -40,6 +40,87 @@ char* ultoa(unsigned long value, char* result, int base) { return utoa((unsigned int)value, result, base); } +#ifdef NOPRINTFLOAT + +char * dtostrf(double number, signed char width, unsigned char prec, char *s) { + bool negative = false; + + if (isnan(number)) { + strcpy(s, "nan"); + return s; + } + if (isinf(number)) { + strcpy(s, "inf"); + return s; + } + + char* out = s; + + int fillme = width; // how many cells to fill for the integer part + if (prec > 0) { + fillme -= (prec+1); + } + + // Handle negative numbers + if (number < 0.0) { + negative = true; + fillme--; + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + // I optimized out most of the divisions + double rounding = 2.0; + for (uint8_t i = 0; i < prec; ++i) + rounding *= 10.0; + rounding = 1.0 / rounding; + + number += rounding; + + // Figure out how big our number really is + double tenpow = 1.0; + int digitcount = 1; + double nextpow; + while (number >= (nextpow = (10.0 * tenpow))) { + tenpow = nextpow; + digitcount++; + } + + // minimal compensation for possible lack of precision + number *= 1 + std::numeric_limits::epsilon(); + + number /= tenpow; + fillme -= digitcount; + + // Pad unused cells with spaces + while (fillme-- > 0) { + *out++ = ' '; + } + + // Handle negative sign + if (negative) *out++ = '-'; + + // Print the digits, and if necessary, the decimal point + digitcount += prec; + int8_t digit = 0; + while (digitcount-- > 0) { + digit = (int8_t)number; + if (digit > 9) digit = 9; // insurance + *out++ = (char)('0' | digit); + if ((digitcount == prec) && (prec > 0)) { + *out++ = '.'; + } + number -= digit; + number *= 10.0; + } + + // make sure the string is terminated + *out = 0; + return s; +} + +#else // !NOPRINTFLOAT + char * dtostrf(double number, signed char width, unsigned char prec, char *s) { char fmt[32]; sprintf(fmt, "%%%d.%df", width, prec); @@ -47,4 +128,6 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { return s; } +#endif // !NOPRINTFLOAT + }; diff --git a/platform.txt b/platform.txt index 678be1ba9d..6c98206b04 100644 --- a/platform.txt +++ b/platform.txt @@ -38,6 +38,7 @@ build.stdcpp_lib=-lstdc++ build.stdcpp_level=-std=gnu++11 build.float=-u _printf_float -u _scanf_float +build.floatflags= build.led= # default SDK for all boards @@ -53,7 +54,7 @@ compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} +compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.floatflags} compiler.S.cmd=xtensa-lx106-elf-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls @@ -64,7 +65,7 @@ compiler.c.elf.cmd=xtensa-lx106-elf-gcc compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} +compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.floatflags} compiler.as.cmd=xtensa-lx106-elf-as diff --git a/tools/boards.txt.py b/tools/boards.txt.py index 47b80a93bd..018b451c4f 100755 --- a/tools/boards.txt.py +++ b/tools/boards.txt.py @@ -1588,6 +1588,7 @@ def all_boards (): if nofloat: print(id + '.build.float=') + print(id + '.build.floatflags=-DNOPRINTFLOAT') print('') From 799795d63ee6dd25c0a376e402b9d3a8150e1668 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 16 Feb 2020 01:26:03 +0100 Subject: [PATCH 2/5] fix include file --- cores/esp8266/core_esp8266_noniso.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/esp8266/core_esp8266_noniso.cpp b/cores/esp8266/core_esp8266_noniso.cpp index 0368897c91..12d5f19b2c 100644 --- a/cores/esp8266/core_esp8266_noniso.cpp +++ b/cores/esp8266/core_esp8266_noniso.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "stdlib_noniso.h" extern "C" { From c646c7ea05aa5f536c403ca9054d3e3bf1d95e6c Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 19 Feb 2020 14:32:51 +0100 Subject: [PATCH 3/5] fix with proposal per review --- cores/esp8266/core_esp8266_noniso.cpp | 26 ++++++++++++-------------- platform.txt | 5 ++--- tools/boards.txt.py | 1 - 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.cpp b/cores/esp8266/core_esp8266_noniso.cpp index 12d5f19b2c..e6c70b5991 100644 --- a/cores/esp8266/core_esp8266_noniso.cpp +++ b/cores/esp8266/core_esp8266_noniso.cpp @@ -41,9 +41,18 @@ char* ultoa(unsigned long value, char* result, int base) { return utoa((unsigned int)value, result, base); } -#ifdef NOPRINTFLOAT - char * dtostrf(double number, signed char width, unsigned char prec, char *s) { + if (!_printf_float) { + return __dtostrf(number, width, prec, s); + } else { + char fmt[32]; + sprintf(fmt, "%%%d.%df", width, prec); + sprintf(s, fmt, number); + return s; + } +} + +static char * __dtostrf(double number, signed char width, unsigned char prec, char *s) { bool negative = false; if (isnan(number)) { @@ -87,7 +96,7 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { digitcount++; } - // minimal compensation for possible lack of precision + // minimal compensation for possible lack of precision (#7087 addition) number *= 1 + std::numeric_limits::epsilon(); number /= tenpow; @@ -120,15 +129,4 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { return s; } -#else // !NOPRINTFLOAT - -char * dtostrf(double number, signed char width, unsigned char prec, char *s) { - char fmt[32]; - sprintf(fmt, "%%%d.%df", width, prec); - sprintf(s, fmt, number); - return s; -} - -#endif // !NOPRINTFLOAT - }; diff --git a/platform.txt b/platform.txt index 6c98206b04..678be1ba9d 100644 --- a/platform.txt +++ b/platform.txt @@ -38,7 +38,6 @@ build.stdcpp_lib=-lstdc++ build.stdcpp_level=-std=gnu++11 build.float=-u _printf_float -u _scanf_float -build.floatflags= build.led= # default SDK for all boards @@ -54,7 +53,7 @@ compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.floatflags} +compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} compiler.S.cmd=xtensa-lx106-elf-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls @@ -65,7 +64,7 @@ compiler.c.elf.cmd=xtensa-lx106-elf-gcc compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.floatflags} +compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} compiler.as.cmd=xtensa-lx106-elf-as diff --git a/tools/boards.txt.py b/tools/boards.txt.py index 018b451c4f..47b80a93bd 100755 --- a/tools/boards.txt.py +++ b/tools/boards.txt.py @@ -1588,7 +1588,6 @@ def all_boards (): if nofloat: print(id + '.build.float=') - print(id + '.build.floatflags=-DNOPRINTFLOAT') print('') From 390ca30a476c2e080fb5058d1df40a61d3686912 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 19 Feb 2020 23:58:14 +0100 Subject: [PATCH 4/5] fix --- cores/esp8266/core_esp8266_noniso.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.cpp b/cores/esp8266/core_esp8266_noniso.cpp index e6c70b5991..9866389ed9 100644 --- a/cores/esp8266/core_esp8266_noniso.cpp +++ b/cores/esp8266/core_esp8266_noniso.cpp @@ -41,17 +41,6 @@ char* ultoa(unsigned long value, char* result, int base) { return utoa((unsigned int)value, result, base); } -char * dtostrf(double number, signed char width, unsigned char prec, char *s) { - if (!_printf_float) { - return __dtostrf(number, width, prec, s); - } else { - char fmt[32]; - sprintf(fmt, "%%%d.%df", width, prec); - sprintf(s, fmt, number); - return s; - } -} - static char * __dtostrf(double number, signed char width, unsigned char prec, char *s) { bool negative = false; @@ -129,4 +118,18 @@ static char * __dtostrf(double number, signed char width, unsigned char prec, ch return s; } +// extern weak declaration (= function pointer) to check whether _printf_float is defined +extern int _printf_float () __attribute__((__weak__)); + +char * dtostrf(double number, signed char width, unsigned char prec, char *s) { + if (!_printf_float) { + return __dtostrf(number, width, prec, s); + } else { + char fmt[32]; + sprintf(fmt, "%%%d.%df", width, prec); + sprintf(s, fmt, number); + return s; + } +} + }; From 0c91b2ace7bad3cdba3a42667022fb1093ed6d92 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Fri, 21 Feb 2020 22:10:45 +0100 Subject: [PATCH 5/5] always use dtostrf --- cores/esp8266/core_esp8266_noniso.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.cpp b/cores/esp8266/core_esp8266_noniso.cpp index 9866389ed9..c742904d21 100644 --- a/cores/esp8266/core_esp8266_noniso.cpp +++ b/cores/esp8266/core_esp8266_noniso.cpp @@ -22,7 +22,6 @@ */ -#include #include #include #include @@ -41,7 +40,7 @@ char* ultoa(unsigned long value, char* result, int base) { return utoa((unsigned int)value, result, base); } -static char * __dtostrf(double number, signed char width, unsigned char prec, char *s) { +char * dtostrf(double number, signed char width, unsigned char prec, char *s) { bool negative = false; if (isnan(number)) { @@ -118,18 +117,4 @@ static char * __dtostrf(double number, signed char width, unsigned char prec, ch return s; } -// extern weak declaration (= function pointer) to check whether _printf_float is defined -extern int _printf_float () __attribute__((__weak__)); - -char * dtostrf(double number, signed char width, unsigned char prec, char *s) { - if (!_printf_float) { - return __dtostrf(number, width, prec, s); - } else { - char fmt[32]; - sprintf(fmt, "%%%d.%df", width, prec); - sprintf(s, fmt, number); - return s; - } -} - };