From ab4ade6b89dea88f786dc1789c406709a53240ec Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Sat, 28 Mar 2026 00:50:55 -0600 Subject: [PATCH] added PRINTF_NO_FLOAT and PRINTF_LONG_DOUBLE --- src/libc/printf/makefile | 27 +++-- src/libc/printf/nanoprintf_default.c | 24 +++++ .../{nanoprintf.c => nanoprintf_impl.h} | 51 ++++------ src/libc/printf/nanoprintf_longdouble.c | 24 +++++ src/libc/printf/nanoprintf_nofloat.c | 24 +++++ src/makefile.mk | 12 ++- test/standalone/asprintf_fprintf/makefile | 1 + test/standalone/printf_nofloat/autotest.json | 40 ++++++++ test/standalone/printf_nofloat/makefile | 19 ++++ test/standalone/printf_nofloat/src/main.c | 98 +++++++++++++++++++ 10 files changed, 279 insertions(+), 41 deletions(-) create mode 100644 src/libc/printf/nanoprintf_default.c rename src/libc/printf/{nanoprintf.c => nanoprintf_impl.h} (82%) create mode 100644 src/libc/printf/nanoprintf_longdouble.c create mode 100644 src/libc/printf/nanoprintf_nofloat.c create mode 100644 test/standalone/printf_nofloat/autotest.json create mode 100644 test/standalone/printf_nofloat/makefile create mode 100644 test/standalone/printf_nofloat/src/main.c diff --git a/src/libc/printf/makefile b/src/libc/printf/makefile index b07b48213..6b2a67e59 100644 --- a/src/libc/printf/makefile +++ b/src/libc/printf/makefile @@ -16,18 +16,27 @@ include $(CURDIR)/../../common.mk -OBJECTS = -OBJECTS += $(patsubst %.c,build/%.c.o,$(wildcard *.c)) -OBJECTS += $(patsubst %.cpp,build/%.cpp.o,$(wildcard *.cpp)) -OBJECTS += $(patsubst %.src,build/%.o,$(wildcard *.src)) +OBJECTS_DEFAULT = build/nanoprintf_default.c.o +OBJECTS_NOFLOAT = build/nanoprintf_nofloat.c.o +OBJECTS_LONGDOUBLE = build/nanoprintf_longdouble.c.o -LIB_NANOPRINTF := libnanoprintf.a +LIB_NANOPRINTF_DEFAULT := libnanoprintf_default.a +LIB_NANOPRINTF_NOFLOAT := libnanoprintf_nofloat.a +LIB_NANOPRINTF_LONGDOUBLE := libnanoprintf_longdouble.a .SECONDARY: -all: build/$(LIB_NANOPRINTF) +all: build/$(LIB_NANOPRINTF_DEFAULT) build/$(LIB_NANOPRINTF_NOFLOAT) build/$(LIB_NANOPRINTF_LONGDOUBLE) -build/$(LIB_NANOPRINTF): $(OBJECTS) +build/$(LIB_NANOPRINTF_DEFAULT): $(OBJECTS_DEFAULT) + $(Q)$(call MKDIR,build) + $(Q)$(EZAR) rcs $@ $^ + +build/$(LIB_NANOPRINTF_NOFLOAT): $(OBJECTS_NOFLOAT) + $(Q)$(call MKDIR,build) + $(Q)$(EZAR) rcs $@ $^ + +build/$(LIB_NANOPRINTF_LONGDOUBLE): $(OBJECTS_LONGDOUBLE) $(Q)$(call MKDIR,build) $(Q)$(EZAR) rcs $@ $^ @@ -44,6 +53,8 @@ clean: install: all $(Q)$(call MKDIR,$(INSTALL_LIBC)) - $(Q)$(call COPY,$(call NATIVEPATH,build/$(LIB_NANOPRINTF)),$(INSTALL_LIBC)) + $(Q)$(call COPY,$(call NATIVEPATH,build/$(LIB_NANOPRINTF_DEFAULT)),$(INSTALL_LIBC)) + $(Q)$(call COPY,$(call NATIVEPATH,build/$(LIB_NANOPRINTF_NOFLOAT)),$(INSTALL_LIBC)) + $(Q)$(call COPY,$(call NATIVEPATH,build/$(LIB_NANOPRINTF_LONGDOUBLE)),$(INSTALL_LIBC)) .PHONY: all clean install diff --git a/src/libc/printf/nanoprintf_default.c b/src/libc/printf/nanoprintf_default.c new file mode 100644 index 000000000..c41c4f6dc --- /dev/null +++ b/src/libc/printf/nanoprintf_default.c @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// Configuration +//------------------------------------------------------------------------------ + +/** + * @remarks don't set this above 40, or there is a chance that + * frameset will exceed 127 (generating slower code). + */ +#define NANOPRINTF_CONVERSION_BUFFER_SIZE 24 + +// custom nanoprintf flag to enable/disable long double formatting +#define NANOPRINTF_USE_LONG_DOUBLE_PRECISION 0 + +#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_ALT_FORM_FLAG 1 +#define NANOPRINTF_USE_FLOAT_HEX_FORMAT_SPECIFIER 0 + +#include "nanoprintf_impl.h" diff --git a/src/libc/printf/nanoprintf.c b/src/libc/printf/nanoprintf_impl.h similarity index 82% rename from src/libc/printf/nanoprintf.c rename to src/libc/printf/nanoprintf_impl.h index 18759a235..6c7df91bd 100644 --- a/src/libc/printf/nanoprintf.c +++ b/src/libc/printf/nanoprintf_impl.h @@ -1,3 +1,22 @@ +//------------------------------------------------------------------------------ +// Common Config +//------------------------------------------------------------------------------ + +#define NANOPRINTF_IMPLEMENTATION +#define NANOPRINTF_VISIBILITY_STATIC +#define NANOPRINTF_STATIC_GLOBALS + +#if NANOPRINTF_USE_LONG_DOUBLE_PRECISION == 1 +#define NANOPRINTF_CONVERSION_FLOAT_TYPE unsigned long long +#else +#define NANOPRINTF_CONVERSION_FLOAT_TYPE unsigned long +#endif + +// Not applicable since sizeof(float) == sizeof(double) on the ez80 +#define NANOPRINTF_USE_FLOAT_SINGLE_PRECISION 0 + +//------------------------------------------------------------------------------ + #include #include #include @@ -6,16 +25,6 @@ #include #include /* malloc */ -#define NANOPRINTF_IMPLEMENTATION -#define NANOPRINTF_VISIBILITY_STATIC -#define NANOPRINTF_STATIC_GLOBALS - -/** - * @remarks don't set this above 40, or there is a chance that - * frameset will exceed 127 (generating slower code). - */ -#define NANOPRINTF_CONVERSION_BUFFER_SIZE 24 - static void npf_putc_std(int c, void *ctx) { (void)ctx; outchar((char)c); @@ -25,28 +34,6 @@ static void npf_fputc_std(int c, void *ctx) { fputc(c, (FILE*)ctx); } -// This is a custom nanoprintf flag -#define NANOPRINTF_USE_LONG_DOUBLE_PRECISION 1 - -#if NANOPRINTF_USE_LONG_DOUBLE_PRECISION == 1 -#define NANOPRINTF_CONVERSION_FLOAT_TYPE unsigned long long -#else -#define NANOPRINTF_CONVERSION_FLOAT_TYPE unsigned long -#endif - -#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 1 -#define NANOPRINTF_USE_ALT_FORM_FLAG 1 -#define NANOPRINTF_USE_FLOAT_HEX_FORMAT_SPECIFIER 0 - -// Not applicable since sizeof(float) == sizeof(double) on the ez80 -#define NANOPRINTF_USE_FLOAT_SINGLE_PRECISION 0 - #include "nanoprintf.h" int vsnprintf(char *__restrict buffer, size_t bufsz, char const *__restrict format, va_list vlist) { diff --git a/src/libc/printf/nanoprintf_longdouble.c b/src/libc/printf/nanoprintf_longdouble.c new file mode 100644 index 000000000..91aeb88a5 --- /dev/null +++ b/src/libc/printf/nanoprintf_longdouble.c @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// Configuration +//------------------------------------------------------------------------------ + +/** + * @remarks don't set this above 40, or there is a chance that + * frameset will exceed 127 (generating slower code). + */ +#define NANOPRINTF_CONVERSION_BUFFER_SIZE 24 + +// custom nanoprintf flag to enable/disable long double formatting +#define NANOPRINTF_USE_LONG_DOUBLE_PRECISION 1 + +#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_ALT_FORM_FLAG 1 +#define NANOPRINTF_USE_FLOAT_HEX_FORMAT_SPECIFIER 0 + +#include "nanoprintf_impl.h" diff --git a/src/libc/printf/nanoprintf_nofloat.c b/src/libc/printf/nanoprintf_nofloat.c new file mode 100644 index 000000000..2b5514657 --- /dev/null +++ b/src/libc/printf/nanoprintf_nofloat.c @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// Configuration +//------------------------------------------------------------------------------ + +/** + * @remarks don't set this above 40, or there is a chance that + * frameset will exceed 127 (generating slower code). + */ +#define NANOPRINTF_CONVERSION_BUFFER_SIZE 36 + +// custom nanoprintf flag to enable/disable long double formatting +#define NANOPRINTF_USE_LONG_DOUBLE_PRECISION 0 + +#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0 +#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 1 +#define NANOPRINTF_USE_ALT_FORM_FLAG 1 +#define NANOPRINTF_USE_FLOAT_HEX_FORMAT_SPECIFIER 0 + +#include "nanoprintf_impl.h" diff --git a/src/makefile.mk b/src/makefile.mk index 3e64c5867..b5e2c05e0 100644 --- a/src/makefile.mk +++ b/src/makefile.mk @@ -300,7 +300,17 @@ LIB_SOFTFLOAT = $(call FORWARD_PATH,$(CEDEV_TOOLCHAIN)/lib/softfloat/libsoftfloa # include printf ifeq ($(HAS_PRINTF),YES) -LIB_PRINTF = $(call FORWARD_PATH,$(CEDEV_TOOLCHAIN)/lib/libc/libnanoprintf.a) + +ifeq ($(PRINTF_LONG_DOUBLE),YES) +LIB_PRINTF = $(call FORWARD_PATH,$(CEDEV_TOOLCHAIN)/lib/libc/libnanoprintf_longdouble.a) +else +ifeq ($(PRINTF_NO_FLOAT),YES) +LIB_PRINTF = $(call FORWARD_PATH,$(CEDEV_TOOLCHAIN)/lib/libc/libnanoprintf_nofloat.a) +else +LIB_PRINTF = $(call FORWARD_PATH,$(CEDEV_TOOLCHAIN)/lib/libc/libnanoprintf_default.a) +endif +endif + else LIB_PRINTF = SPRINTF_SYMBOL = --defsym _sprintf=0x0000BC diff --git a/test/standalone/asprintf_fprintf/makefile b/test/standalone/asprintf_fprintf/makefile index 3fcadd6c2..3c0ca9da4 100644 --- a/test/standalone/asprintf_fprintf/makefile +++ b/test/standalone/asprintf_fprintf/makefile @@ -14,6 +14,7 @@ CXXFLAGS = -Wall -Wextra -Wformat=2 -Wshadow -Oz HAS_MATH_ERRNO = YES PREFER_OS_LIBC = NO HAS_PRINTF = YES +PRINTF_LONG_DOUBLE = YES # ---------------------------- diff --git a/test/standalone/printf_nofloat/autotest.json b/test/standalone/printf_nofloat/autotest.json new file mode 100644 index 000000000..00cb31d03 --- /dev/null +++ b/test/standalone/printf_nofloat/autotest.json @@ -0,0 +1,40 @@ +{ + "transfer_files": [ + "bin/DEMO.8xp" + ], + "target": { + "name": "DEMO", + "isASM": true + }, + "sequence": [ + "action|launch", + "delay|1000", + "hashWait|1", + "key|enter", + "delay|300", + "hashWait|2" + ], + "hashes": { + "1": { + "description": "All tests passed", + "timeout": 5000, + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "38E2AD5A" + ] + }, + "2": { + "description": "Exit", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "FFAF89BA", + "101734A5", + "9DA19F44", + "A32840C8", + "349F4775" + ] + } + } +} diff --git a/test/standalone/printf_nofloat/makefile b/test/standalone/printf_nofloat/makefile new file mode 100644 index 000000000..15494874a --- /dev/null +++ b/test/standalone/printf_nofloat/makefile @@ -0,0 +1,19 @@ +# ---------------------------- +# Makefile Options +# ---------------------------- + +NAME = DEMO +ICON = icon.png +DESCRIPTION = "CE C Toolchain Demo" +COMPRESSED = NO +ARCHIVED = NO + +CFLAGS = -Wall -Wextra -Wshadow -Oz +CXXFLAGS = -Wall -Wextra -Wshadow -Oz + +HAS_PRINTF = YES +PRINTF_NO_FLOAT = YES + +# ---------------------------- + +include $(shell cedev-config --makefile) diff --git a/test/standalone/printf_nofloat/src/main.c b/test/standalone/printf_nofloat/src/main.c new file mode 100644 index 000000000..d3f267800 --- /dev/null +++ b/test/standalone/printf_nofloat/src/main.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define C(expr) if (!(expr)) { return __LINE__; } + +int run_tests(void) { + char buf[40]; + memset(buf, '\0', sizeof(buf)); + { + // do a very simple test to see if nanoprintf_nofloat is working + int value = 123; + const char * truth = "123"; + C(snprintf(buf, sizeof(buf), "%d", value) == 3); + C(strcmp(buf, truth) == 0); + } + { + // make sure we are not using boot_sprintf + intmax_t value = 0x123456789ABCDEF; + const char * truth = "0X123456789ABCDEF"; + C(sprintf(buf, "%#jX", value) == 17); + C(strcmp(buf, truth) == 0); + } + { + // test writeback formatting + int offset_1 = 0x555555; + char offset_2 = 0xAA; + int value_1 = 456; + unsigned value_2 = 77; + const char * truth = "+456%77"; + C(snprintf(buf, sizeof(buf), "%+i%n%%%u%hhn", value_1, &offset_1, value_2, &offset_2) == 7); + C(offset_1 == 4); + C(offset_2 == 7); + C(strcmp(buf, truth) == 0); + } + // we have now proven that nanoprintf_nofloat works with integers + { + /** + * Since we are linking nanoprintf_nofloat, we should test that floats + * do not work. This means that it shouldn't print 1.000000 or + * something else like that. Otherwise main thing we are testing for + * is that no crashes occur. + */ + double value_1 = 1.0; + long double value_2 = 1.0L; + + snprintf(buf, sizeof(buf) - 1, "%f", value_1); + // make sure we did not just print garbage + C(strnlen(buf, sizeof(buf)) < sizeof(buf)); + // test that we did not print a number + C(strchr(buf, '1') == NULL); + C(strchr(buf, '0') == NULL); + C(strchr(buf, '.') == NULL); + + sprintf(buf, "%lf", value_1); + // make sure we did not just print garbage + C(strnlen(buf, sizeof(buf)) < sizeof(buf)); + // test that we did not print a number + C(strchr(buf, '1') == NULL); + C(strchr(buf, '0') == NULL); + C(strchr(buf, '.') == NULL); + + snprintf(buf, sizeof(buf) - 1, "%Lf", value_2); + // make sure we did not just print garbage + C(strnlen(buf, sizeof(buf)) < sizeof(buf)); + // test that we did not print a number + C(strchr(buf, '1') == NULL); + C(strchr(buf, '0') == NULL); + C(strchr(buf, '.') == NULL); + } + + return 0; +} + +int main(void) { + os_ClrHome(); + int failed_test = run_tests(); + if (failed_test != 0) { + char buf[sizeof("Failed test L-8388608")]; + boot_sprintf(buf, "Failed test L%d", failed_test); + puts(buf); + } else { + puts("All tests passed"); + } + + while (!os_GetCSC()); + + return 0; +}