stdio.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2023 Otto-von-Guericke-Universität Magdeburg
3  * SPDX-License-Identifier: LGPL-2.1-only
4  */
5 
6 #pragma once
7 
23 #include_next "stdio.h"
24 
25 /* C++ does not support __flash. Hence, only wrap printf() and friends for
26  * C and let C++ use them unmodified. */
27 #ifdef __cplusplus
28 extern "C" {
29 }
30 #else
31 
32 #include "flash_utils.h"
33 
34 #ifdef DOXYGEN
57 #define printf(...) /* implementation details */
58 #else
59 /* this helper function-like macro takes at least 65 arguments and will
60  * "return" the 65 argument unmodified. It is not useful by itself, but
61  * needed to implement _SINGLEARG_OR_MULTIARG(). */
62 #define _TAKE_65TH_TOKEN( _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
63  _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
64  _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
65  _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
66  _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
67  _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
68  _61, _62, _63, _64, N, ...) N
69 
70 #define _EXPAND_HELPER(x) x
71 /* this function-like macro expands its argument */
72 #define _EXPAND(x) _EXPAND_HELPER(x)
73 
74 /* This function-like macro will expand to `SINGLEARG` if called with one
75  * argument and `MULTIARG` if called with more than one.
76  *
77  * (Implementation detail: It will not work with more than 64 arguments. But
78  * 64 arguments to one printf call ought to be enough for everyone...)
79  */
80 #define _SINGLEARG_OR_MULTIARG(...) \
81  _TAKE_65TH_TOKEN(__VA_ARGS__, \
82  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
83  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
84  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
85  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
86  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
87  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
88  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
89  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
90  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
91  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
92  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
93  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
94  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
95  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
96  MULTIARG, MULTIARG, MULTIARG, MULTIARG, \
97  MULTIARG, MULTIARG, MULTIARG, SINGLEARG)
98 #define _CONCAT_HELPER(a, b) a ## b
99 #define _CONCAT(a, b) _CONCAT_HELPER(a, b)
100 
101 /* Implementation for `printf(fmt)` */
102 #define _PRINTF_SINGLEARG(x) \
103  flash_printf(TO_FLASH(x))
104 /* Implementation for `printf(fmt, ...)` */
105 #define _PRINTF_MULTIARG(x, ...) \
106  flash_printf(TO_FLASH(x), __VA_ARGS__)
107 /* Dispatch to _PRINTF_SINGLEARG() and _PRINTF_MULTIARG() depending on the
108  * number of arguments. Special handling for `printf(fmt)` compared to
109  * `printf(fmt, ...)` is needed because the `__VA_ARGS__` part must contain
110  * at least one argument, which in case of `printf(fmt)` is not the case. */
111 #define printf(...) \
112  _EXPAND(_CONCAT(_PRINTF_, _SINGLEARG_OR_MULTIARG(__VA_ARGS__))(__VA_ARGS__))
113 
114 /* And now all other printf variants. For the v*printf() versions we do not
115  * need to differentiate, because they have always the same number of arguments
116  * (with the last being va_list). For the other printf variants, we again need
117  * to dispatch to a _SINGLEARG and a _MULTIARG version. */
118 #define vprintf(fmt, args) flash_vprintf(TO_FLASH(fmt), args)
119 
120 #define _FPRINTF_SINGLEARG(stream, x) \
121  flash_fprintf(stream, TO_FLASH(x))
122 #define _FPRINTF_MULTIARG(stream, x, ...) \
123  flash_fprintf(stream, TO_FLASH(x), __VA_ARGS__)
124 #define fprintf(stream, ...) \
125  _EXPAND(_CONCAT(_FPRINTF_, _SINGLEARG_OR_MULTIARG(__VA_ARGS__))(stream, __VA_ARGS__))
126 
127 #define vfprintf(stream, fmt, args) flash_vfprintf(stream, TO_FLASH(fmt), args)
128 
129 #define _SNPRINTF_SINGLEARG(buf, buf_len, fmt) \
130  flash_snprintf(buf, buf_len, TO_FLASH(fmt))
131 #define _SNPRINTF_MULTIARG(buf, buf_len, fmt, ...) \
132  flash_snprintf(buf, buf_len, TO_FLASH(fmt), __VA_ARGS__)
133 #define snprintf(buf, buf_len, ...) \
134  _EXPAND(_CONCAT(_SNPRINTF_, _SINGLEARG_OR_MULTIARG(__VA_ARGS__))(buf, buf_len, __VA_ARGS__))
135 
136 #define vsnprintf(buf, buf_len, fmt, args) flash_vsnprintf(buf, buf_len, TO_FLASH(fmt), args)
137 #endif
138 
139 #endif
140 
Utility functions, macros, and types for read-only memory.