Zephyr Project API  3.2.0
A Scalable Open Source RTOS
cbprintf_internal.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef ZEPHYR_INCLUDE_SYS_CBPRINTF_INTERNAL_H_
8#define ZEPHYR_INCLUDE_SYS_CBPRINTF_INTERNAL_H_
9
10#include <errno.h>
11#include <stdarg.h>
12#include <stddef.h>
13#include <stdint.h>
14#include <zephyr/toolchain.h>
15#include <zephyr/sys/util.h>
16#include <zephyr/sys/__assert.h>
17
18/*
19 * Special alignment cases
20 */
21
22#if defined(__i386__)
23/* there are no gaps on the stack */
24#define VA_STACK_ALIGN(type) 1
25#elif defined(__sparc__)
26/* there are no gaps on the stack */
27#define VA_STACK_ALIGN(type) 1
28#elif defined(__x86_64__)
29#define VA_STACK_MIN_ALIGN 8
30#elif defined(__aarch64__)
31#define VA_STACK_MIN_ALIGN 8
32#elif defined(__riscv)
33#ifdef CONFIG_RISCV_ISA_RV32E
34#define VA_STACK_ALIGN(type) 4
35#else
36#define VA_STACK_MIN_ALIGN (__riscv_xlen / 8)
37#endif /* CONFIG_RISCV_ISA_RV32E */
38#endif
39
40/*
41 * Default alignment values if not specified by architecture config
42 */
43
44#ifndef VA_STACK_MIN_ALIGN
45#define VA_STACK_MIN_ALIGN 1
46#endif
47
48#ifndef VA_STACK_ALIGN
49#define VA_STACK_ALIGN(type) MAX(VA_STACK_MIN_ALIGN, __alignof__(type))
50#endif
51
52static inline void z_cbprintf_wcpy(int *dst, int *src, size_t len)
53{
54 for (size_t i = 0; i < len; i++) {
55 dst[i] = src[i];
56 }
57}
58
60
61#ifdef __cplusplus
62extern "C" {
63#endif
64
65
66#if defined(__sparc__)
67/* The SPARC V8 ABI guarantees that the arguments of a variable argument
68 * list function are stored on the stack at addresses which are 32-bit
69 * aligned. It means that variables of type unit64_t and double may not
70 * be properly aligned on the stack.
71 *
72 * The compiler is aware of the ABI and takes care of this. However,
73 * as we are directly accessing the variable argument list here, we need
74 * to take the alignment into consideration and copy 64-bit arguments
75 * as 32-bit words.
76 */
77#define Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY 1
78#else
79#define Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY 0
80#endif
81
88#ifdef __cplusplus
89#define Z_CBPRINTF_IS_PCHAR(x, flags) \
90 z_cbprintf_cxx_is_pchar(x, (flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO)
91#else
92#define Z_CBPRINTF_IS_PCHAR(x, flags) \
93 _Generic((x) + 0, \
94 /* char * */ \
95 char * : 1, \
96 const char * : ((flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO) ? 0 : 1, \
97 volatile char * : 1, \
98 const volatile char * : 1, \
99 /* unsigned char * */ \
100 unsigned char * : 1, \
101 const unsigned char * : ((flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO) ? 0 : 1, \
102 volatile unsigned char * : 1, \
103 const volatile unsigned char * : 1,\
104 /* wchar_t * */ \
105 wchar_t * : 1, \
106 const wchar_t * : ((flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO) ? 0 : 1, \
107 volatile wchar_t * : 1, \
108 const volatile wchar_t * : 1, \
109 default : \
110 0)
111#endif
112
113/* @brief Check if argument is a certain type of char pointer. What exectly is checked
114 * depends on @p flags. If flags is 0 then 1 is returned if @p x is a char pointer.
115 *
116 * @param idx Argument index.
117 * @param x Argument.
118 * @param flags Flags. See @p CBPRINTF_PACKAGE_FLAGS.
119 *
120 * @retval 1 if @p x is char pointer meeting criteria identified by @p flags.
121 * @retval 0 otherwise.
122 */
123#define Z_CBPRINTF_IS_X_PCHAR(idx, x, flags) \
124 (idx < Z_CBPRINTF_PACKAGE_FIRST_RO_STR_CNT_GET(flags) ? \
125 0 : Z_CBPRINTF_IS_PCHAR(x, flags))
126
135#define Z_CBPRINTF_HAS_PCHAR_ARGS(flags, fmt, ...) \
136 (FOR_EACH_IDX_FIXED_ARG(Z_CBPRINTF_IS_X_PCHAR, (+), flags, __VA_ARGS__))
137
138#define Z_CBPRINTF_PCHAR_COUNT(flags, ...) \
139 COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
140 (0), \
141 (Z_CBPRINTF_HAS_PCHAR_ARGS(flags, __VA_ARGS__)))
142
151#if Z_C_GENERIC
152#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(flags, ...) ({\
153 _Pragma("GCC diagnostic push") \
154 _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
155 int _rv; \
156 if ((flags) & CBPRINTF_PACKAGE_ADD_RW_STR_POS) { \
157 _rv = 0; \
158 } else { \
159 _rv = Z_CBPRINTF_PCHAR_COUNT(flags, __VA_ARGS__) > 0 ? 1 : 0; \
160 } \
161 _Pragma("GCC diagnostic pop")\
162 _rv; \
163})
164#else
165#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(flags, ...) 1
166#endif
167
177#ifdef __cplusplus
178#define Z_CBPRINTF_ARG_SIZE(v) z_cbprintf_cxx_arg_size(v)
179#else
180#define Z_CBPRINTF_ARG_SIZE(v) ({\
181 __auto_type __v = (v) + 0; \
182 /* Static code analysis may complain about unused variable. */ \
183 (void)__v; \
184 size_t __arg_size = _Generic((v), \
185 float : sizeof(double), \
186 default : \
187 sizeof((__v)) \
188 ); \
189 __arg_size; \
190})
191#endif
192
199#ifdef __cplusplus
200#define Z_CBPRINTF_STORE_ARG(buf, arg) z_cbprintf_cxx_store_arg(buf, arg)
201#else
202#define Z_CBPRINTF_STORE_ARG(buf, arg) do { \
203 if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { \
204 /* If required, copy arguments by word to avoid unaligned access.*/ \
205 __auto_type _v = (arg) + 0; \
206 double _d = _Generic((arg) + 0, \
207 float : (arg) + 0, \
208 default : \
209 0.0); \
210 /* Static code analysis may complain about unused variable. */ \
211 (void)_v; \
212 (void)_d; \
213 size_t arg_size = Z_CBPRINTF_ARG_SIZE(arg); \
214 size_t _wsize = arg_size / sizeof(int); \
215 z_cbprintf_wcpy((int *)buf, \
216 (int *) _Generic((arg) + 0, float : &_d, default : &_v), \
217 _wsize); \
218 } else { \
219 *_Generic((arg) + 0, \
220 char : (int *)buf, \
221 unsigned char: (int *)buf, \
222 short : (int *)buf, \
223 unsigned short : (int *)buf, \
224 int : (int *)buf, \
225 unsigned int : (unsigned int *)buf, \
226 long : (long *)buf, \
227 unsigned long : (unsigned long *)buf, \
228 long long : (long long *)buf, \
229 unsigned long long : (unsigned long long *)buf, \
230 float : (double *)buf, \
231 double : (double *)buf, \
232 long double : (long double *)buf, \
233 default : \
234 (const void **)buf) = arg; \
235 } \
236} while (false)
237#endif
238
245#ifdef __cplusplus
246#define Z_CBPRINTF_ALIGNMENT(_arg) z_cbprintf_cxx_alignment(_arg)
247#else
248#define Z_CBPRINTF_ALIGNMENT(_arg) \
249 MAX(_Generic((_arg) + 0, \
250 float : VA_STACK_ALIGN(double), \
251 double : VA_STACK_ALIGN(double), \
252 long double : VA_STACK_ALIGN(long double), \
253 long long : VA_STACK_ALIGN(long long), \
254 unsigned long long : VA_STACK_ALIGN(long long), \
255 default : \
256 __alignof__((_arg) + 0)), VA_STACK_MIN_ALIGN)
257#endif
258
269#ifdef __cplusplus
270#if defined(__x86_64__) || defined(__riscv) || defined(__aarch64__)
271#define Z_CBPRINTF_IS_LONGDOUBLE(x) 0
272#else
273#define Z_CBPRINTF_IS_LONGDOUBLE(x) z_cbprintf_cxx_is_longdouble(x)
274#endif
275#else
276#define Z_CBPRINTF_IS_LONGDOUBLE(x) \
277 _Generic((x) + 0, long double : 1, default : 0)
278#endif
279
295#define Z_CBPRINTF_PACK_ARG2(arg_idx, _buf, _idx, _align_offset, _max, _arg) \
296do { \
297 BUILD_ASSERT(!((sizeof(double) < VA_STACK_ALIGN(long double)) && \
298 Z_CBPRINTF_IS_LONGDOUBLE(_arg) && \
299 !IS_ENABLED(CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE)),\
300 "Packaging of long double not enabled in Kconfig."); \
301 while (_align_offset % Z_CBPRINTF_ALIGNMENT(_arg) != 0UL) { \
302 _idx += sizeof(int); \
303 _align_offset += sizeof(int); \
304 } \
305 uint32_t _arg_size = Z_CBPRINTF_ARG_SIZE(_arg); \
306 uint32_t _loc = _idx / sizeof(int); \
307 if (arg_idx < 1 + _fros_cnt) { \
308 if (_ros_pos_en) { \
309 _ros_pos_buf[_ros_pos_idx++] = _loc; \
310 } \
311 } else if (Z_CBPRINTF_IS_PCHAR(_arg, 0)) { \
312 if (_cros_en) { \
313 if (Z_CBPRINTF_IS_X_PCHAR(arg_idx, _arg, _flags)) { \
314 if (_rws_pos_en) { \
315 _rws_buffer[_rws_pos_idx++] = arg_idx - 1; \
316 _rws_buffer[_rws_pos_idx++] = _loc; \
317 } \
318 } else { \
319 if (_ros_pos_en) { \
320 _ros_pos_buf[_ros_pos_idx++] = _loc; \
321 } \
322 } \
323 } else if (_rws_pos_en) { \
324 _rws_buffer[_rws_pos_idx++] = arg_idx - 1; \
325 _rws_buffer[_rws_pos_idx++] = _idx / sizeof(int); \
326 } \
327 } \
328 if (_buf && _idx < (int)_max) { \
329 Z_CBPRINTF_STORE_ARG(&_buf[_idx], _arg); \
330 } \
331 _idx += _arg_size; \
332 _align_offset += _arg_size; \
333} while (false)
334
341#define Z_CBPRINTF_PACK_ARG(arg_idx, arg) \
342 Z_CBPRINTF_PACK_ARG2(arg_idx, _pbuf, _pkg_len, _pkg_offset, _pmax, arg)
343
344/* When using clang additional warning needs to be suppressed since each
345 * argument of fmt string is used for sizeof() which results in the warning
346 * if argument is a string literal. Suppression is added here instead of
347 * the macro which generates the warning to not slow down the compiler.
348 */
349#ifdef __clang__
350#define Z_CBPRINTF_SUPPRESS_SIZEOF_ARRAY_DECAY \
351 _Pragma("GCC diagnostic ignored \"-Wsizeof-array-decay\"")
352#else
353#define Z_CBPRINTF_SUPPRESS_SIZEOF_ARRAY_DECAY
354#endif
355
356/* Allocation to avoid using VLA and alloca. Alloc frees space when leaving
357 * a function which can lead to increased stack usage if logging is used
358 * multiple times. VLA is not always available.
359 *
360 * Use large array when optimization is off to avoid increased stack usage.
361 */
362#ifdef CONFIG_NO_OPTIMIZATIONS
363#define Z_CBPRINTF_ON_STACK_ALLOC(_name, _len) \
364 __ASSERT(_len <= 32, "Too many string arguments."); \
365 uint8_t _name##_buf32[32]; \
366 _name = _name##_buf32
367#else
368#define Z_CBPRINTF_ON_STACK_ALLOC(_name, _len) \
369 __ASSERT(_len <= 32, "Too many string arguments."); \
370 uint8_t _name##_buf4[4]; \
371 uint8_t _name##_buf8[8]; \
372 uint8_t _name##_buf12[12]; \
373 uint8_t _name##_buf16[16]; \
374 uint8_t _name##_buf32[32]; \
375 _name = (_len) <= 4 ? _name##_buf4 : \
376 ((_len) <= 8 ? _name##_buf8 : \
377 ((_len) <= 12 ? _name##_buf12 : \
378 ((_len) <= 16 ? _name##_buf16 : \
379 _name##_buf32)))
380#endif
381
382/* When the first argument of Z_CBPRINTF_STATIC_PACKAGE_GENERIC() is a
383 * static memory location, some compiler warns you if you compare the
384 * location against NULL. ___is_null() is used to kill this warning.
385 *
386 * The warnings would be visible when you built with -save-temps=obj,
387 * our standard debugging tip for macro problems.
388 *
389 * https://github.com/zephyrproject-rtos/zephyr/issues/51528
390 */
391static ALWAYS_INLINE bool ___is_null(void *p)
392{
393 return p == NULL;
394}
395
411#define Z_CBPRINTF_STATIC_PACKAGE_GENERIC(buf, _inlen, _outlen, _align_offset, \
412 flags, ... /* fmt, ... */) \
413do { \
414 _Pragma("GCC diagnostic push") \
415 _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
416 Z_CBPRINTF_SUPPRESS_SIZEOF_ARRAY_DECAY \
417 BUILD_ASSERT(!IS_ENABLED(CONFIG_XTENSA) || \
418 (IS_ENABLED(CONFIG_XTENSA) && \
419 !(_align_offset % CBPRINTF_PACKAGE_ALIGNMENT)), \
420 "Xtensa requires aligned package."); \
421 BUILD_ASSERT((_align_offset % sizeof(int)) == 0, \
422 "Alignment offset must be multiply of a word."); \
423 IF_ENABLED(CONFIG_CBPRINTF_STATIC_PACKAGE_CHECK_ALIGNMENT, \
424 (__ASSERT(!((uintptr_t)buf & (CBPRINTF_PACKAGE_ALIGNMENT - 1)), \
425 "Buffer must be aligned.");)) \
426 uint32_t _flags = flags; \
427 bool _ros_pos_en = (_flags) & CBPRINTF_PACKAGE_ADD_RO_STR_POS; \
428 bool _rws_pos_en = (_flags) & CBPRINTF_PACKAGE_ADD_RW_STR_POS; \
429 bool _cros_en = (_flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO; \
430 uint8_t *_pbuf = buf; \
431 uint8_t _rws_pos_idx = 0; \
432 uint8_t _ros_pos_idx = 0; \
433 /* Variable holds count of all string pointer arguments. */ \
434 uint8_t _alls_cnt = Z_CBPRINTF_PCHAR_COUNT(0, __VA_ARGS__); \
435 uint8_t _fros_cnt = Z_CBPRINTF_PACKAGE_FIRST_RO_STR_CNT_GET(_flags); \
436 /* Variable holds count of non const string pointers. */ \
437 uint8_t _rws_cnt = _cros_en ? \
438 Z_CBPRINTF_PCHAR_COUNT(_flags, __VA_ARGS__) : _alls_cnt - _fros_cnt; \
439 uint8_t _ros_cnt = _ros_pos_en ? (1 + _alls_cnt - _rws_cnt) : 0; \
440 uint8_t *_ros_pos_buf; \
441 Z_CBPRINTF_ON_STACK_ALLOC(_ros_pos_buf, _ros_cnt); \
442 uint8_t *_rws_buffer; \
443 Z_CBPRINTF_ON_STACK_ALLOC(_rws_buffer, 2 * _rws_cnt); \
444 size_t _pmax = !___is_null(buf) ? _inlen : INT32_MAX; \
445 int _pkg_len = 0; \
446 int _total_len = 0; \
447 int _pkg_offset = _align_offset; \
448 union cbprintf_package_hdr *_len_loc; \
449 /* If string has rw string arguments CBPRINTF_PACKAGE_ADD_RW_STR_POS is a must. */ \
450 if (_rws_cnt && !((_flags) & CBPRINTF_PACKAGE_ADD_RW_STR_POS)) { \
451 _outlen = -EINVAL; \
452 break; \
453 } \
454 /* package starts with string address and field with length */ \
455 if (_pmax < sizeof(*_len_loc)) { \
456 _outlen = -ENOSPC; \
457 break; \
458 } \
459 _len_loc = (union cbprintf_package_hdr *)_pbuf; \
460 _pkg_len += sizeof(*_len_loc); \
461 _pkg_offset += sizeof(*_len_loc); \
462 /* Pack remaining arguments */\
463 FOR_EACH_IDX(Z_CBPRINTF_PACK_ARG, (;), __VA_ARGS__);\
464 _total_len = _pkg_len; \
465 /* Append string indexes to the package. */ \
466 _total_len += _ros_cnt; \
467 _total_len += 2 * _rws_cnt; \
468 if (_pbuf != NULL) { \
469 /* Append string locations. */ \
470 uint8_t *_pbuf_loc = &_pbuf[_pkg_len]; \
471 for (size_t i = 0; i < _ros_cnt; i++) { \
472 *_pbuf_loc++ = _ros_pos_buf[i]; \
473 } \
474 for (size_t i = 0; i < (2 * _rws_cnt); i++) { \
475 *_pbuf_loc++ = _rws_buffer[i]; \
476 } \
477 } \
478 /* Store length */ \
479 _outlen = (_total_len > (int)_pmax) ? -ENOSPC : _total_len; \
480 /* Store length in the header, set number of dumped strings to 0 */ \
481 if (_pbuf != NULL) { \
482 union cbprintf_package_hdr hdr = { \
483 .desc = { \
484 .len = (uint8_t)(_pkg_len / sizeof(int)), \
485 .str_cnt = 0, \
486 .ro_str_cnt = _ros_cnt, \
487 .rw_str_cnt = _rws_cnt, \
488 } \
489 }; \
490 IF_ENABLED(CONFIG_CBPRINTF_PACKAGE_HEADER_STORE_CREATION_FLAGS, \
491 (hdr.desc.pkg_flags = flags)); \
492 *_len_loc = hdr; \
493 } \
494 _Pragma("GCC diagnostic pop") \
495} while (false)
496
497#if Z_C_GENERIC
498#define Z_CBPRINTF_STATIC_PACKAGE(packaged, inlen, outlen, align_offset, flags, \
499 ... /* fmt, ... */) \
500 Z_CBPRINTF_STATIC_PACKAGE_GENERIC(packaged, inlen, outlen, \
501 align_offset, flags, __VA_ARGS__)
502#else
503#define Z_CBPRINTF_STATIC_PACKAGE(packaged, inlen, outlen, align_offset, flags, \
504 ... /* fmt, ... */) \
505do { \
506 /* Small trick needed to avoid warning on always true */ \
507 if (((uintptr_t)packaged + 1) != 1) { \
508 outlen = cbprintf_package(packaged, inlen, flags, __VA_ARGS__); \
509 } else { \
510 outlen = cbprintf_package(NULL, align_offset, flags, __VA_ARGS__); \
511 } \
512} while (false)
513#endif /* Z_C_GENERIC */
514
515#ifdef __cplusplus
516}
517#endif
518
519#ifdef CONFIG_CBPRINTF_PACKAGE_SUPPORT_TAGGED_ARGUMENTS
520#ifdef __cplusplus
521/*
522 * Remove qualifiers like const, volatile. And also transform
523 * C++ argument reference back to its basic type.
524 */
525#define Z_CBPRINTF_ARG_REMOVE_QUAL(arg) \
526 z_cbprintf_cxx_remove_cv < \
527 z_cbprintf_cxx_remove_reference < decltype(arg) > ::type \
528 > ::type
529
530/*
531 * Get the type of elements in an array.
532 */
533#define Z_CBPRINTF_CXX_ARG_ARRAY_TYPE(arg) \
534 z_cbprintf_cxx_remove_cv < \
535 z_cbprintf_cxx_remove_extent < decltype(arg) > ::type \
536 > ::type
537
538/*
539 * Determine if incoming type is char.
540 */
541#define Z_CBPRINTF_CXX_ARG_IS_TYPE_CHAR(type) \
542 (z_cbprintf_cxx_is_same_type < type, \
543 char > :: value ? \
544 true : \
545 (z_cbprintf_cxx_is_same_type < type, \
546 const char > :: value ? \
547 true : \
548 (z_cbprintf_cxx_is_same_type < type, \
549 volatile char > :: value ? \
550 true : \
551 (z_cbprintf_cxx_is_same_type < type, \
552 const volatile char > :: value ? \
553 true : \
554 false))))
555
556/*
557 * Figure out if this is a char array since (char *) and (char[])
558 * are of different types in C++.
559 */
560#define Z_CBPRINTF_CXX_ARG_IS_CHAR_ARRAY(arg) \
561 (z_cbprintf_cxx_is_array < decltype(arg) > :: value ? \
562 (Z_CBPRINTF_CXX_ARG_IS_TYPE_CHAR(Z_CBPRINTF_CXX_ARG_ARRAY_TYPE(arg)) ? \
563 true : \
564 false) : \
565 false)
566
567/*
568 * Note that qualifiers of char * must be explicitly matched
569 * due to type matching in C++, where remove_cv() does not work.
570 */
571#define Z_CBPRINTF_ARG_TYPE(arg) \
572 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
573 char > ::value ? \
574 CBPRINTF_PACKAGE_ARG_TYPE_CHAR : \
575 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
576 unsigned char > ::value ? \
577 CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_CHAR : \
578 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
579 short > ::value ? \
580 CBPRINTF_PACKAGE_ARG_TYPE_SHORT : \
581 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
582 unsigned short > ::value ? \
583 CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_SHORT : \
584 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
585 int > ::value ? \
586 CBPRINTF_PACKAGE_ARG_TYPE_INT : \
587 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
588 unsigned int > ::value ? \
589 CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_INT : \
590 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
591 long > ::value ? \
592 CBPRINTF_PACKAGE_ARG_TYPE_LONG : \
593 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
594 unsigned long > ::value ? \
595 CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_LONG : \
596 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
597 long long > ::value ? \
598 CBPRINTF_PACKAGE_ARG_TYPE_LONG_LONG : \
599 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
600 unsigned long long > ::value ? \
601 CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_LONG_LONG : \
602 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
603 float > ::value ? \
604 CBPRINTF_PACKAGE_ARG_TYPE_FLOAT : \
605 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
606 double > ::value ? \
607 CBPRINTF_PACKAGE_ARG_TYPE_DOUBLE : \
608 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
609 long double > ::value ? \
610 CBPRINTF_PACKAGE_ARG_TYPE_LONG_DOUBLE : \
611 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
612 char * > :: value ? \
613 CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR : \
614 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
615 const char * > :: value ? \
616 CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR : \
617 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
618 volatile char * > :: value ? \
619 CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR : \
620 (z_cbprintf_cxx_is_same_type < Z_CBPRINTF_ARG_REMOVE_QUAL(arg), \
621 const volatile char * > :: value ? \
622 CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR : \
623 (Z_CBPRINTF_CXX_ARG_IS_CHAR_ARRAY(arg) ? \
624 CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR : \
625 CBPRINTF_PACKAGE_ARG_TYPE_PTR_VOID))))))))))))))))))
626#else
627#define Z_CBPRINTF_ARG_TYPE(arg) \
628 _Generic(arg, \
629 char : CBPRINTF_PACKAGE_ARG_TYPE_CHAR, \
630 unsigned char : CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_CHAR, \
631 short : CBPRINTF_PACKAGE_ARG_TYPE_SHORT, \
632 unsigned short : CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_SHORT, \
633 int : CBPRINTF_PACKAGE_ARG_TYPE_INT, \
634 unsigned int : CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_INT, \
635 long : CBPRINTF_PACKAGE_ARG_TYPE_LONG, \
636 unsigned long : CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_LONG, \
637 long long : CBPRINTF_PACKAGE_ARG_TYPE_LONG_LONG, \
638 unsigned long long : CBPRINTF_PACKAGE_ARG_TYPE_UNSIGNED_LONG_LONG, \
639 float : CBPRINTF_PACKAGE_ARG_TYPE_FLOAT, \
640 double : CBPRINTF_PACKAGE_ARG_TYPE_DOUBLE, \
641 long double : CBPRINTF_PACKAGE_ARG_TYPE_LONG_DOUBLE, \
642 char * : CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR, \
643 const char * : CBPRINTF_PACKAGE_ARG_TYPE_PTR_CHAR, \
644 void * : CBPRINTF_PACKAGE_ARG_TYPE_PTR_VOID, \
645 default : \
646 CBPRINTF_PACKAGE_ARG_TYPE_PTR_VOID \
647 )
648#endif /* _cplusplus */
649
650#define Z_CBPRINTF_TAGGED_EMPTY_ARGS(...) \
651 CBPRINTF_PACKAGE_ARG_TYPE_END
652
653#define Z_CBPRINTF_TAGGED_ARGS_3(arg) \
654 Z_CBPRINTF_ARG_TYPE(arg), arg
655
656#define Z_CBPRINTF_TAGGED_ARGS_2(...) \
657 FOR_EACH(Z_CBPRINTF_TAGGED_ARGS_3, (,), __VA_ARGS__), \
658 CBPRINTF_PACKAGE_ARG_TYPE_END
659
660#define Z_CBPRINTF_TAGGED_ARGS(_num_args, ...) \
661 COND_CODE_0(_num_args, \
662 (CBPRINTF_PACKAGE_ARG_TYPE_END), \
663 (Z_CBPRINTF_TAGGED_ARGS_2(__VA_ARGS__)))
664
665#endif /* CONFIG_CBPRINTF_PACKAGE_SUPPORT_TAGGED_ARGUMENTS */
666
667#endif /* ZEPHYR_INCLUDE_SYS_CBPRINTF_INTERNAL_H_ */
#define ALWAYS_INLINE
Definition: common.h:124
System error numbers.
struct k_pipe p
Definition: kobject.c:1322
Macros to abstract toolchain specific capabilities.
Misc utilities.