1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#pragma once 14 15#include <utils/attribute.h> 16 17#if (defined(__clang__) && __has_feature(c_generic_selections)) || \ 18 (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && __STDC_VERSION__ >= 201112L) 19 20 /* On a fully-compliant C11 compiler, we provide a generic mechanism for printing a variable. 21 * 22 * Example usage: 23 * 24 * int i = 42; 25 * printf(FORMAT_STRING(i), i); 26 * 27 * Some known gotchas: 28 * - Character literals are ints, so you will need to cast them to get sensible results: 29 * FORMAT_STRING((char)'a') 30 * - String literals are character arrays, so you will need to also cast them: 31 * FORMAT_STRING((char*)"hello world") 32 */ 33 34 #define FORMAT_STRING(x) _Generic((x), \ 35 char: "%c", \ 36 signed char: "%hhd", \ 37 unsigned char: "%hhu", \ 38 short: "%hd", \ 39 unsigned short: "%hu", \ 40 int: "%d", \ 41 unsigned int: "%u", \ 42 long: "%ld", \ 43 unsigned long: "%lu", \ 44 long long: "%lld", \ 45 unsigned long long: "%llu", \ 46 double: "%f", \ 47 long double: "%Lf", \ 48 float: "%f", \ 49 char*: "%s", \ 50 void*: "%p", \ 51 \ 52 /* The remaining cases are not necessary on GCC, where lvalue conversion is performed, */ \ 53 /* but are needed for Clang, which does not do this conversion. */ \ 54 \ 55 const char: "%c", \ 56 const signed char: "%hhd", \ 57 const unsigned char: "%hhu", \ 58 const short: "%hd", \ 59 const unsigned short: "%hu", \ 60 const int: "%d", \ 61 const unsigned int: "%u", \ 62 const long: "%ld", \ 63 const unsigned long: "%lu", \ 64 const long long: "%lld", \ 65 const unsigned long long: "%llu", \ 66 const double: "%f", \ 67 const long double: "%Lf", \ 68 const float: "%f", \ 69 const char*: "%s", \ 70 const void*: "%p", \ 71 volatile char: "%c", \ 72 volatile signed char: "%hhd", \ 73 volatile unsigned char: "%hhu", \ 74 volatile short: "%hd", \ 75 volatile unsigned short: "%hu", \ 76 volatile int: "%d", \ 77 volatile unsigned int: "%u", \ 78 volatile long: "%ld", \ 79 volatile unsigned long: "%lu", \ 80 volatile long long: "%lld", \ 81 volatile unsigned long long: "%llu", \ 82 volatile double: "%f", \ 83 volatile long double: "%Lf", \ 84 volatile float: "%f", \ 85 volatile char*: "%s", \ 86 volatile void*: "%p" \ 87 \ 88 /* We assume that no one needs to print a const- *and* volatile-qualified variable. */ \ 89 ) 90 91#else 92 93 /* In an unsupported compiler configuration, trigger a compile-time error if the user has 94 * attempted to use FORMAT_STRING. 95 */ 96 97 extern const char *FORMAT_STRING(void *dummy, ...) 98 ERROR("FORMAT_STRING requires full C11 compiler support"); 99 100#endif 101