Loading...
Searching...
No Matches
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
31extern "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.