diff mbox series

[25/32] tools/nolibc: allow different write callbacks in printf

Message ID 20250304-nolibc-kselftest-harness-v1-25-adca7cd231e2@linutronix.de (mailing list archive)
State New
Headers show
Series kselftest harness and nolibc compatibility | expand

Commit Message

Thomas Weißschuh March 4, 2025, 7:10 a.m. UTC
Decouple the formatting logic from the writing logic to later enable
writing straight to a buffer in sprintf().

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
 tools/include/nolibc/stdio.h | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

Comments

Willy Tarreau March 4, 2025, 7:59 a.m. UTC | #1
On Tue, Mar 04, 2025 at 08:10:55AM +0100, Thomas Weißschuh wrote:
> Decouple the formatting logic from the writing logic to later enable
> writing straight to a buffer in sprintf().
> 
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> ---
>  tools/include/nolibc/stdio.h | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
> index 262d0da4da9062e0c83b55661b2509f36548cf88..434fbaddae7a216159fecf618da85889d631dff7 100644
> --- a/tools/include/nolibc/stdio.h
> +++ b/tools/include/nolibc/stdio.h
> @@ -208,13 +208,15 @@ char *fgets(char *s, int size, FILE *stream)
>  }
>  
>  
> -/* minimal vfprintf(). It supports the following formats:
> +/* minimal printf(). It supports the following formats:
>   *  - %[l*]{d,u,c,x,p}
>   *  - %s
>   *  - unknown modifiers are ignored.
>   */
> -static __attribute__((unused, format(printf, 2, 0)))
> -int vfprintf(FILE *stream, const char *fmt, va_list args)
> +typedef int (*_printf_cb)(intptr_t state, const char *buf, size_t size);

Keep in mind these ones will appear in the application, so you'd rather
appropriate the type name by prefixing it with "nolibc" as we've done in
a few macros and internal structs.

> +static __attribute__((unused, format(printf, 3, 0)))
> +int _printf(_printf_cb cb, intptr_t state, const char *fmt, va_list args)
       ^^^^^^^
Here as well, since it's not meant to be exposed to the application.

> +static int _fprintf_cb(intptr_t state, const char *buf, size_t size)

Likewise here I think.

Willy
Thomas Weißschuh March 4, 2025, 11:10 a.m. UTC | #2
On Tue, Mar 04, 2025 at 08:59:23AM +0100, Willy Tarreau wrote:
> On Tue, Mar 04, 2025 at 08:10:55AM +0100, Thomas Weißschuh wrote:
> > Decouple the formatting logic from the writing logic to later enable
> > writing straight to a buffer in sprintf().
> > 
> > Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> > ---
> >  tools/include/nolibc/stdio.h | 21 +++++++++++++++++----
> >  1 file changed, 17 insertions(+), 4 deletions(-)
> > 
> > diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
> > index 262d0da4da9062e0c83b55661b2509f36548cf88..434fbaddae7a216159fecf618da85889d631dff7 100644
> > --- a/tools/include/nolibc/stdio.h
> > +++ b/tools/include/nolibc/stdio.h
> > @@ -208,13 +208,15 @@ char *fgets(char *s, int size, FILE *stream)
> >  }
> >  
> >  
> > -/* minimal vfprintf(). It supports the following formats:
> > +/* minimal printf(). It supports the following formats:
> >   *  - %[l*]{d,u,c,x,p}
> >   *  - %s
> >   *  - unknown modifiers are ignored.
> >   */
> > -static __attribute__((unused, format(printf, 2, 0)))
> > -int vfprintf(FILE *stream, const char *fmt, va_list args)
> > +typedef int (*_printf_cb)(intptr_t state, const char *buf, size_t size);
> 
> Keep in mind these ones will appear in the application, so you'd rather
> appropriate the type name by prefixing it with "nolibc" as we've done in
> a few macros and internal structs.

Ack. Technically it should be fine as names with leading underscores are
reserved for the implementation, but let's make it clearer.

> > +static __attribute__((unused, format(printf, 3, 0)))
> > +int _printf(_printf_cb cb, intptr_t state, const char *fmt, va_list args)
>        ^^^^^^^
> Here as well, since it's not meant to be exposed to the application.

Ack.

> > +static int _fprintf_cb(intptr_t state, const char *buf, size_t size)
> 
> Likewise here I think.

Ack, also to the same remarks in the other patches.
diff mbox series

Patch

diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 262d0da4da9062e0c83b55661b2509f36548cf88..434fbaddae7a216159fecf618da85889d631dff7 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -208,13 +208,15 @@  char *fgets(char *s, int size, FILE *stream)
 }
 
 
-/* minimal vfprintf(). It supports the following formats:
+/* minimal printf(). It supports the following formats:
  *  - %[l*]{d,u,c,x,p}
  *  - %s
  *  - unknown modifiers are ignored.
  */
-static __attribute__((unused, format(printf, 2, 0)))
-int vfprintf(FILE *stream, const char *fmt, va_list args)
+typedef int (*_printf_cb)(intptr_t state, const char *buf, size_t size);
+
+static __attribute__((unused, format(printf, 3, 0)))
+int _printf(_printf_cb cb, intptr_t state, const char *fmt, va_list args)
 {
 	char escape, lpref, c;
 	unsigned long long v;
@@ -304,7 +306,7 @@  int vfprintf(FILE *stream, const char *fmt, va_list args)
 			outstr = fmt;
 			len = ofs - 1;
 		flush_str:
-			if (_fwrite(outstr, len, stream) != 0)
+			if (cb(state, outstr, len) != 0)
 				break;
 
 			written += len;
@@ -321,6 +323,17 @@  int vfprintf(FILE *stream, const char *fmt, va_list args)
 	return written;
 }
 
+static int _fprintf_cb(intptr_t state, const char *buf, size_t size)
+{
+	return _fwrite(buf, size, (FILE *)state);
+}
+
+static __attribute__((unused, format(printf, 2, 0)))
+int vfprintf(FILE *stream, const char *fmt, va_list args)
+{
+	return _printf(_fprintf_cb, (intptr_t)stream, fmt, args);
+}
+
 static __attribute__((unused, format(printf, 1, 0)))
 int vprintf(const char *fmt, va_list args)
 {