From 659fe9fdd14b0772f4e9722b751b9b010665e053 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 19 Dec 2022 18:56:54 +0100 Subject: stdio-common: Introduce buffers for implementing printf These buffers will eventually be used instead of FILE * objects to implement printf functions. The multibyte buffer is struct __printf_buffer, the wide buffer is struct __wprintf_buffer. To enable writing type-generic code, the header files printf_buffer-char.h and printf_buffer-wchar_t.h define the Xprintf macro differently, enabling Xprintf (buffer) to stand for __printf_buffer and __wprintf_buffer as appropriate. For common cases, macros like Xprintf_buffer are provided as a more syntactically convenient shortcut. Buffer-specific flush callbacks are implemented with a switch statement instead of a function pointer, to avoid hardening issues similar to those of libio vtables. struct __printf_buffer_as_file is needed to support custom printf specifiers because the public interface for that requires passing a FILE *, which is why there is a trapdoor back from these buffers to FILE * streams. Since the immediate user of these interfaces knows when processing has finished, there is no flush callback for the end of processing, only a flush callback for the intermediate buffer flush. Reviewed-by: Adhemerval Zanella --- stdio-common/printf_buffer_as_file.h | 87 ++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 stdio-common/printf_buffer_as_file.h (limited to 'stdio-common/printf_buffer_as_file.h') diff --git a/stdio-common/printf_buffer_as_file.h b/stdio-common/printf_buffer_as_file.h new file mode 100644 index 0000000000..8ac707f2d0 --- /dev/null +++ b/stdio-common/printf_buffer_as_file.h @@ -0,0 +1,87 @@ +/* FILE * interface to a struct __*printf_buffer. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Registered printf format specifier callbacks produce data via a + FILE * stream. struct __printf_buffer_as_file enables vfprintf to + create a suitable stdio stream. Likewise struct + __wprintf_buffer_as_file for vfwprintf. */ + +#ifndef PRINTF_BUFFER_AS_FILE_H +#define PRINTF_BUFFER_AS_FILE_H + +#include + +struct __printf_buffer; + +struct __printf_buffer_as_file +{ + /* Interface to libio. */ + FILE stream; + const struct _IO_jump_t *vtable; + + /* Pointer to the underlying buffer. */ + struct __printf_buffer *next; +}; + +/* Initialization *FP so that data written to its FILE * stream ends + up in NEXT. */ +void __printf_buffer_as_file_init (struct __printf_buffer_as_file *fp, + struct __printf_buffer *next) + attribute_hidden; + +/* Returns the FILE * that can be used to write data to the + buffer. */ +static inline FILE * +__printf_buffer_as_file_get (struct __printf_buffer_as_file *file) +{ + return &file->stream; +} + +/* Transfers all pending data from the FILE * to the underlying + buffer. Returns true if there have been no errors. */ +bool __printf_buffer_as_file_terminate (struct __printf_buffer_as_file *) + attribute_hidden; + +/* Wide variant follows. */ + +struct __wprintf_buffer; +struct __wprintf_buffer_as_file +{ + /* Interface to libio. */ + FILE stream; + const struct _IO_jump_t *vtable; + struct _IO_wide_data wide_stream; + + /* Pointer to the underlying buffer. */ + struct __wprintf_buffer *next; +}; + +void __wprintf_buffer_as_file_init (struct __wprintf_buffer_as_file *fp, + struct __wprintf_buffer *next) + attribute_hidden; + +static inline FILE * +__wprintf_buffer_as_file_get (struct __wprintf_buffer_as_file *file) +{ + return &file->stream; +} + +bool __wprintf_buffer_as_file_terminate (struct __wprintf_buffer_as_file *) + attribute_hidden; + +#endif /* PRINTF_BUFFER_AS_FILE_H */ -- cgit v1.2.3