blob: d7d1c5b891b6a6481995e3c0989192a408d2be87 [file] [log] [blame]
Jack Rosenthal17f444f2020-03-31 18:47:491/* Copyright 2020 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#ifndef LITHIUM_MACROLIB_H_
7#define LITHIUM_MACROLIB_H_
8
9/**
10 * Lithium Macrolib
11 * ================
12 * Common macros, for creating macros, and for usage in code. Common
13 * macros which may be defined by other headers (outside of Lithium)
14 * will be undefined first.
15 */
16
17/**
18 * Macro Construction Macros
19 * -------------------------
20 */
21
22/**
23 * Takes any amount of arguments and produces nothing.
24 */
25#undef EMPTY
26#define EMPTY(...)
27
28/**
29 * Takes no arguments and produces a comma.
30 */
31#undef COMMA
32#define COMMA() ,
33
34/**
35 * Takes no arguments and produces a semicolon.
36 */
37#undef SEMICOLON
38#define SEMICOLON() ;
39
40/**
41 * Expand and stringify a token.
42 */
43#undef STRINGIFY
44#define STRINGIFY(token) #token
45
46/**
47 * Expand and concatenate two tokens.
48 */
49#undef CONCAT2
50#define CONCAT2(t1, t2) _LI_CONCAT2(t1, t2)
51#define _LI_CONCAT2(t1, t2) t1##t2
52
53/**
54 * Expand, stringify, and place a comma at the end of a token.
55 */
56#define STRINGIFY_C(token) #token,
57
58/**
59 * Expand and place a comma at the end of a token.
60 */
61#define PASTE_C(token) token,
62
63/**
64 * Preprocessor Lists (``PPLIST``)
65 * -------------------------------
66 * Preprocessor lists are an effective way to manage data lists using
67 * the preprocessor. The standard way to define a list is to define
68 * macro of one argument ``M``, and apply a macro ``M`` to each list
69 * element. For example::
70 *
71 * #define SENSORS_PPLIST(M) \
72 * M(ACCEL_SENSOR) \
73 * M(GYRO_SENSOR) \
74 * M(TEMP_SENSOR)
75 */
76
77/**
78 * Convert a ``PPLIST`` to a stringified and comma-separated
79 * list. Example usage::
80 *
81 * const char *const sensor_pretty_print[] =
82 * PPLIST_STRINGIFY(SENSORS_PPLIST);
83 */
84#define PPLIST_STRINGIFY(pplist) \
85 { \
86 pplist(STRINGIFY_C) \
87 }
88
89/**
90 * Convert a ``PPLIST`` to a comma-separated list. Example usage::
91 *
92 * enum sensor_type PPLIST_PASTE(SENSORS_PPLIST);
93 */
94#define PPLIST_PASTE(pplist) \
95 { \
96 pplist(PASTE_C) \
97 }
98
99/**
100 * Take advantage of division by zero to indicate a failure condition.
101 *
102 * :param value: The value to return.
103 * :param condition: The condition to assert at compile time.
104 * :return: The value passed as ``value``.
105 *
106 * If usage is guaranteed to be inside of a function, a braced group
107 * is recommended instead.
108 */
109#define STATIC_ASSERT_INLINE(value, condition) ((value) / !!(condition))
110
111/**
112 * Get the number of elements in an array.
113 *
114 * :param arr: An array.
115 * :return: The number of elements in the array.
116 *
117 * For type safety, this function will cause a division-by-zero
118 * compile-time check failure if a pointer is passed instead of an
119 * array.
120 */
121#define ARRAY_SIZE(arr) \
122 STATIC_ASSERT_INLINE(sizeof(arr) / sizeof((arr)[0]), \
123 !__builtin_types_compatible_p(typeof(arr), \
124 typeof(&(arr)[0])))
125
126/**
127 * Attributes
128 * ==========
129 * These are common attributes to be used on a function.
130 */
131
132/**
133 * Allow a static function to go unused.
134 */
135#undef __maybe_unused
136#define __maybe_unused __attribute__((unused))
137
138/**
139 * Run this function before ``main`` runs.
140 */
141#undef __constructor
142#define __constructor __attribute__((constructor))
143
144/**
145 * Run this function after ``main`` runs.
146 */
147#undef __destructor
148#define __destructor __attribute__((destructor))
149
150/**
151 * Discard this function at link time.
152 */
153#undef __discard
154#define __discard __attribute__((section("/DISCARD/")))
155
156/**
157 * This function does not return.
158 */
159#undef __noreturn
160#define __noreturn __attribute__((noreturn))
161
162/**
163 * Report an error message if this function is used.
164 *
165 * :param msg: The message to show as a compiler error.
166 *
167 * Due to limitations with Clang, this is equivalent to
168 * :c:macro:`__discard` on Clang.
169 */
170#undef __error_if_used
Jack Rosenthal225a1682020-04-02 14:52:51171#if defined(__GNUC__) && !defined(__clang__)
Jack Rosenthal17f444f2020-03-31 18:47:49172#define __error_if_used(msg) __attribute__((error(msg)))
173#else
174#define __error_if_used(msg) __discard
175#endif
176
177/* Make __auto_type available in C++ */
178#if defined(__cplusplus) && !defined(__auto_type)
179#define __auto_type auto
180#endif
181
182#endif /* LITHIUM_MACROLIB_H_ */