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