Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkg/mpaland-printf: Add alternative stdio as package #20664

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions pkg/mpaland-printf/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
PKG_NAME=mpaland-printf
PKG_URL=https://github.com/mpaland/printf
# 4.0.0
PKG_VERSION=0dd4b64bc778bf55229428cefccba4c0a81f384b
PKG_LICENSE=MIT

include $(RIOTBASE)/pkg/pkg.mk

all:
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR) -f $(RIOTPKG)/$(PKG_NAME)/$(PKG_NAME).mk
4 changes: 4 additions & 0 deletions pkg/mpaland-printf/Makefile.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# mpaland's printf does not implement non-standard format specifiers. For
# AVR MCUs we do need the ability to print from PROGMEM, though. Hence, this
# is not compatible with AVR MCUs.
FEATURES_BLACKLIST += arch_avr8
9 changes: 9 additions & 0 deletions pkg/mpaland-printf/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# wrap stdio functions to use mpaland's printf instead of the one from the
# standard C lib
LINKFLAGS += -Wl,-wrap=printf
LINKFLAGS += -Wl,-wrap=sprintf
LINKFLAGS += -Wl,-wrap=snprintf
LINKFLAGS += -Wl,-wrap=vprintf
LINKFLAGS += -Wl,-wrap=vsnprintf
LINKFLAGS += -Wl,-wrap=putchar
LINKFLAGS += -Wl,-wrap=puts
29 changes: 29 additions & 0 deletions pkg/mpaland-printf/doc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @defgroup pkg_mpaland-printf mpaland's printf
* @ingroup pkg
* @brief mpaland's printf implementation is a lean, thread-safe and
* feature-complete printf implementation
*
* # License
*
* Licensed under the MIT license.
*
* # Usage
*
* Add `USEPKG += mpaland-printf` to the application's `Makefile` or compile
* using `USEPKG=mpaland-printf make BOARD=<BOARD> -C <APP_DIR>`.
*
* # Features
*
* The package implements all standard format specifiers. However, support
* for floating point is disabled by default due to the immense ROM overhead
* on MCUs without FPU.
*
* @note Support for floating point formatting can be enabled
* `printf_float` module, e.g. by adding
* `USEMODULE += printf_float` to the application's `Makefile`.
* @note Support for non-standard format specifiers such as needed for
* printing from flash on AVR MCUs are not implemented.
*
* @see https://github.com/mpaland/printf
*/
7 changes: 7 additions & 0 deletions pkg/mpaland-printf/mpaland-printf.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
MODULE := mpaland-printf

SRC := \
printf.c \
#

include $(RIOTBASE)/Makefile.base
50 changes: 50 additions & 0 deletions pkg/mpaland-printf/patches/0001-RIOT-integration.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
From 875a37ec418c41ffd060e39b2153357a32175ac5 Mon Sep 17 00:00:00 2001
From: Marian Buschsieweke <[email protected]>
Date: Sat, 11 May 2024 17:51:01 +0200
Subject: [PATCH 1/2] RIOT integration

Use stdio_write() from stdio_base.h for output
---
printf.c | 8 ++++++++
printf.h | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/printf.c b/printf.c
index 8a700ad..fd83570 100644
--- a/printf.c
+++ b/printf.c
@@ -34,6 +34,7 @@
#include <stdint.h>

#include "printf.h"
+#include "stdio_base.h"


// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
@@ -912,3 +913,10 @@ int fctprintf(void (*out)(char character, void* arg), void* arg, const char* for
va_end(va);
return ret;
}
+
+
+/* RIOT integration: Use stdio_write for output */
+static void _putchar(char character)
+{
+ stdio_write(&character, sizeof(character));
+}
diff --git a/printf.h b/printf.h
index 6075bc2..e185911 100644
--- a/printf.h
+++ b/printf.h
@@ -46,7 +46,7 @@ extern "C" {
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
-void _putchar(char character);
+static void _putchar(char character);


/**
--
2.45.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
From 6fcc450e49791de23446b26cb4b2dc388590c763 Mon Sep 17 00:00:00 2001
From: Marian Buschsieweke <[email protected]>
Date: Sat, 11 May 2024 17:51:38 +0200
Subject: [PATCH 2/2] Wrapper targets: Add endpoints for -Wl,wrap=...

This adds aliases needed to wrap printf() and friends.
---
printf.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)

diff --git a/printf.c b/printf.c
index fd83570..4694bab 100644
--- a/printf.c
+++ b/printf.c
@@ -32,6 +32,7 @@

#include <stdbool.h>
#include <stdint.h>
+#include <string.h>

#include "printf.h"
#include "stdio_base.h"
@@ -920,3 +921,40 @@ static void _putchar(char character)
{
stdio_write(&character, sizeof(character));
}
+
+
+/* provide entry points for linker to redirect stdio */
+__attribute__((alias("printf_")))
+int __wrap_printf(const char* format, ...);
+
+
+__attribute__((alias("sprintf_")))
+int __wrap_sprintf(char* buffer, const char* format, ...);
+
+
+__attribute__((alias("snprintf_")))
+int __wrap_snprintf(char* buffer, size_t count, const char* format, ...);
+
+
+__attribute__((alias("vprintf_")))
+int __wrap_vprintf(const char* format, va_list va);
+
+
+__attribute__((alias("vsnprintf_")))
+int __wrap_vsnprintf(char* buffer, size_t count, const char* format, va_list va);
+
+
+int __wrap_putchar(int c)
+{
+ _putchar((char)c);
+ return 1;
+}
+
+
+int __wrap_puts(const char *s)
+{
+ size_t len = strlen(s);
+ stdio_write(s, len);
+ stdio_write("\n", 1);
+ return len + 1;
+}
--
2.45.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
From 8436eab79cda1de6e81d5d1d00c379036efa3900 Mon Sep 17 00:00:00 2001
From: Marian Buschsieweke <[email protected]>
Date: Sat, 11 May 2024 18:38:51 +0200
Subject: [PATCH 3/3] RIOT integration: Enable floating support based on module
selection

---
printf.c | 94 ++++++++++++++++++++++++++++----------------------------
1 file changed, 47 insertions(+), 47 deletions(-)

diff --git a/printf.c b/printf.c
index e06c9aa..c4980e3 100644
--- a/printf.c
+++ b/printf.c
@@ -32,10 +32,10 @@

#include <stdbool.h>
#include <stdint.h>
-#include <string.h>
+#include <string.h>

#include "printf.h"
-#include "stdio_base.h"
+#include "stdio_base.h"


// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
@@ -62,7 +62,7 @@

// support for the floating point type (%f)
// default: activated
-#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
+#ifdef MODULE_PRINTF_FLOAT
#define PRINTF_SUPPORT_FLOAT
#endif

@@ -914,47 +914,47 @@ int fctprintf(void (*out)(char character, void* arg), void* arg, const char* for
va_end(va);
return ret;
}
-
-
-/* RIOT integration: Use stdio_write for output */
-static void _putchar(char character)
-{
- stdio_write(&character, sizeof(character));
-}
-
-
-/* provide entry points for linker to redirect stdio */
-__attribute__((alias("printf_")))
-int __wrap_printf(const char* format, ...);
-
-
-__attribute__((alias("sprintf_")))
-int __wrap_sprintf(char* buffer, const char* format, ...);
-
-
-__attribute__((alias("snprintf_")))
-int __wrap_snprintf(char* buffer, size_t count, const char* format, ...);
-
-
-__attribute__((alias("vprintf_")))
-int __wrap_vprintf(const char* format, va_list va);
-
-
-__attribute__((alias("vsnprintf_")))
-int __wrap_vsnprintf(char* buffer, size_t count, const char* format, va_list va);
-
-
-int __wrap_putchar(int c)
-{
- _putchar((char)c);
- return 1;
-}
-
-
-int __wrap_puts(const char *s)
-{
- size_t len = strlen(s);
- stdio_write(s, len);
- stdio_write("\n", 1);
- return len + 1;
-}
+
+
+/* RIOT integration: Use stdio_write for output */
+static void _putchar(char character)
+{
+ stdio_write(&character, sizeof(character));
+}
+
+
+/* provide entry points for linker to redirect stdio */
+__attribute__((alias("printf_")))
+int __wrap_printf(const char* format, ...);
+
+
+__attribute__((alias("sprintf_")))
+int __wrap_sprintf(char* buffer, const char* format, ...);
+
+
+__attribute__((alias("snprintf_")))
+int __wrap_snprintf(char* buffer, size_t count, const char* format, ...);
+
+
+__attribute__((alias("vprintf_")))
+int __wrap_vprintf(const char* format, va_list va);
+
+
+__attribute__((alias("vsnprintf_")))
+int __wrap_vsnprintf(char* buffer, size_t count, const char* format, va_list va);
+
+
+int __wrap_putchar(int c)
+{
+ _putchar((char)c);
+ return 1;
+}
+
+
+int __wrap_puts(const char *s)
+{
+ size_t len = strlen(s);
+ stdio_write(s, len);
+ stdio_write("\n", 1);
+ return len + 1;
+}
--
2.45.0

28 changes: 28 additions & 0 deletions pkg/mpaland-printf/patches/0004-Fix-parsing-of-int8_t.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
From 24d4f4ef60aaaef3c471eb248799ebefde33cc03 Mon Sep 17 00:00:00 2001
From: Marian Buschsieweke <[email protected]>
Date: Sat, 11 May 2024 22:42:21 +0200
Subject: [PATCH 4/4] Fix parsing of `int8_t`

The code assumes that `char` is signed, but the C standard allows
`char` to be either signed or unsigned. Instead, `singed char` and
`unsigned char` need to be used for portable code.
---
printf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/printf.c b/printf.c
index 5266cf7..440cfa6 100644
--- a/printf.c
+++ b/printf.c
@@ -734,7 +734,7 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
else {
- const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
+ const int value = (flags & FLAGS_CHAR) ? (signed char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
}
--
2.45.0

7 changes: 7 additions & 0 deletions tests/sys/snprintf/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include ../Makefile.sys_common

# avrlibc's snprintf doesn't support uint64_t / int64_t and even fails
# to compile due to PRI*64 macros not being defined
FEATURES_BLACKLIST := arch_avr8

include $(RIOTBASE)/Makefile.include
4 changes: 4 additions & 0 deletions tests/sys/snprintf/Makefile.board.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# newlib's printf is known to be incomplete, despite being bloated
ifneq (,$(filter newlib,$(USEMODULE)))
USEPKG += mpaland-printf
endif
6 changes: 6 additions & 0 deletions tests/sys/snprintf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# snprintf

This test aims to test if the stdio implementations correctly implements
standard format specifiers. Instead of relying on the transport of stdout to
be fast and reliable, it will use snprintf to format in-memory and compare
in the app with correctness.
Loading
Loading