]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/macro.h
macro: make sure we can use IN_SET() also with complex function calls as first argument
[thirdparty/systemd.git] / src / shared / macro.h
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 #pragma once
4
5 /***
6 This file is part of systemd.
7
8 Copyright 2010 Lennart Poettering
9
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 ***/
23
24 #include <assert.h>
25 #include <sys/param.h>
26 #include <sys/types.h>
27 #include <sys/uio.h>
28 #include <inttypes.h>
29
30 #define _printf_(a,b) __attribute__ ((format (printf, a, b)))
31 #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
32 #define _sentinel_ __attribute__ ((sentinel))
33 #define _unused_ __attribute__ ((unused))
34 #define _destructor_ __attribute__ ((destructor))
35 #define _pure_ __attribute__ ((pure))
36 #define _const_ __attribute__ ((const))
37 #define _deprecated_ __attribute__ ((deprecated))
38 #define _packed_ __attribute__ ((packed))
39 #define _malloc_ __attribute__ ((malloc))
40 #define _weak_ __attribute__ ((weak))
41 #define _likely_(x) (__builtin_expect(!!(x),1))
42 #define _unlikely_(x) (__builtin_expect(!!(x),0))
43 #define _public_ __attribute__ ((visibility("default")))
44 #define _hidden_ __attribute__ ((visibility("hidden")))
45 #define _weakref_(x) __attribute__((weakref(#x)))
46 #define _alignas_(x) __attribute__((aligned(__alignof(x))))
47 #define _cleanup_(x) __attribute__((cleanup(x)))
48
49 /* Temporarily disable some warnings */
50 #define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
51 _Pragma("GCC diagnostic push"); \
52 _Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"")
53
54 #define DISABLE_WARNING_FORMAT_NONLITERAL \
55 _Pragma("GCC diagnostic push"); \
56 _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
57
58 #define DISABLE_WARNING_MISSING_PROTOTYPES \
59 _Pragma("GCC diagnostic push"); \
60 _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"")
61
62 #define DISABLE_WARNING_NONNULL \
63 _Pragma("GCC diagnostic push"); \
64 _Pragma("GCC diagnostic ignored \"-Wnonnull\"")
65
66 #define REENABLE_WARNING \
67 _Pragma("GCC diagnostic pop")
68
69 /* automake test harness */
70 #define EXIT_TEST_SKIP 77
71
72 #define XSTRINGIFY(x) #x
73 #define STRINGIFY(x) XSTRINGIFY(x)
74
75 #define XCONCATENATE(x, y) x ## y
76 #define CONCATENATE(x, y) XCONCATENATE(x, y)
77
78 #define UNIQUE(prefix) CONCATENATE(prefix, __LINE__)
79
80 /* Rounds up */
81
82 #define ALIGN4(l) (((l) + 3) & ~3)
83 #define ALIGN8(l) (((l) + 7) & ~7)
84
85 #if __SIZEOF_POINTER__ == 8
86 #define ALIGN(l) ALIGN8(l)
87 #elif __SIZEOF_POINTER__ == 4
88 #define ALIGN(l) ALIGN4(l)
89 #else
90 #error "Wut? Pointers are neither 4 nor 8 bytes long?"
91 #endif
92
93 #define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) p))
94 #define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) p))
95 #define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) p))
96
97 static inline size_t ALIGN_TO(size_t l, size_t ali) {
98 return ((l + ali - 1) & ~(ali - 1));
99 }
100
101 #define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p, ali))
102
103 #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
104
105 /*
106 * container_of - cast a member of a structure out to the containing structure
107 * @ptr: the pointer to the member.
108 * @type: the type of the container struct this is embedded in.
109 * @member: the name of the member within the struct.
110 *
111 */
112 #define container_of(ptr, type, member) \
113 __extension__ ({ \
114 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
115 (type *)( (char *)__mptr - offsetof(type,member) ); \
116 })
117
118 #undef MAX
119 #define MAX(a,b) \
120 __extension__ ({ \
121 typeof(a) _a = (a); \
122 typeof(b) _b = (b); \
123 _a > _b ? _a : _b; \
124 })
125
126 #define MAX3(x,y,z) \
127 __extension__ ({ \
128 typeof(x) _c = MAX(x,y); \
129 MAX(_c, z); \
130 })
131
132 #undef MIN
133 #define MIN(a,b) \
134 __extension__ ({ \
135 typeof(a) _a = (a); \
136 typeof(b) _b = (b); \
137 _a < _b ? _a : _b; \
138 })
139
140 #define LESS_BY(A,B) \
141 __extension__ ({ \
142 typeof(A) _A = (A); \
143 typeof(B) _B = (B); \
144 _A > _B ? _A - _B : 0; \
145 })
146
147 #ifndef CLAMP
148 #define CLAMP(x, low, high) \
149 __extension__ ({ \
150 typeof(x) _x = (x); \
151 typeof(low) _low = (low); \
152 typeof(high) _high = (high); \
153 ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
154 })
155 #endif
156
157 #define assert_se(expr) \
158 do { \
159 if (_unlikely_(!(expr))) \
160 log_assert_failed(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
161 } while (false) \
162
163 /* We override the glibc assert() here. */
164 #undef assert
165 #ifdef NDEBUG
166 #define assert(expr) do {} while(false)
167 #else
168 #define assert(expr) assert_se(expr)
169 #endif
170
171 #define assert_not_reached(t) \
172 do { \
173 log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
174 } while (false)
175
176 #if defined(static_assert)
177 /* static_assert() is sometimes defined in a way that trips up
178 * -Wdeclaration-after-statement, hence let's temporarily turn off
179 * this warning around it. */
180 #define assert_cc(expr) \
181 DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
182 static_assert(expr, #expr); \
183 REENABLE_WARNING
184 #else
185 #define assert_cc(expr) \
186 DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
187 struct UNIQUE(_assert_struct_) { \
188 char x[(expr) ? 0 : -1]; \
189 }; \
190 REENABLE_WARNING
191 #endif
192
193 #define assert_return(expr, r) \
194 do { \
195 if (_unlikely_(!(expr))) { \
196 log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
197 return (r); \
198 } \
199 } while (false)
200
201 #define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
202 #define INT_TO_PTR(u) ((void *) ((intptr_t) (u)))
203 #define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
204 #define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
205
206 #define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
207 #define LONG_TO_PTR(u) ((void *) ((intptr_t) (u)))
208 #define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
209 #define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u)))
210
211 #define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p)))
212 #define INT32_TO_PTR(u) ((void *) ((intptr_t) (u)))
213 #define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
214 #define UINT32_TO_PTR(u) ((void *) ((uintptr_t) (u)))
215
216 #define PTR_TO_INT64(p) ((int64_t) ((intptr_t) (p)))
217 #define INT64_TO_PTR(u) ((void *) ((intptr_t) (u)))
218 #define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p)))
219 #define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u)))
220
221 #define memzero(x,l) (memset((x), 0, (l)))
222 #define zero(x) (memzero(&(x), sizeof(x)))
223
224 #define CHAR_TO_STR(x) ((char[2]) { x, 0 })
225
226 #define char_array_0(x) x[sizeof(x)-1] = 0;
227
228 #define IOVEC_SET_STRING(i, s) \
229 do { \
230 struct iovec *_i = &(i); \
231 char *_s = (char *)(s); \
232 _i->iov_base = _s; \
233 _i->iov_len = strlen(_s); \
234 } while(false)
235
236 static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
237 unsigned j;
238 size_t r = 0;
239
240 for (j = 0; j < n; j++)
241 r += i[j].iov_len;
242
243 return r;
244 }
245
246 static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
247 unsigned j;
248
249 for (j = 0; j < n; j++) {
250 size_t sub;
251
252 if (_unlikely_(k <= 0))
253 break;
254
255 sub = MIN(i[j].iov_len, k);
256 i[j].iov_len -= sub;
257 i[j].iov_base = (uint8_t*) i[j].iov_base + sub;
258 k -= sub;
259 }
260
261 return k;
262 }
263
264 #define VA_FORMAT_ADVANCE(format, ap) \
265 do { \
266 int _argtypes[128]; \
267 size_t _i, _k; \
268 _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
269 assert(_k < ELEMENTSOF(_argtypes)); \
270 for (_i = 0; _i < _k; _i++) { \
271 if (_argtypes[_i] & PA_FLAG_PTR) { \
272 (void) va_arg(ap, void*); \
273 continue; \
274 } \
275 \
276 switch (_argtypes[_i]) { \
277 case PA_INT: \
278 case PA_INT|PA_FLAG_SHORT: \
279 case PA_CHAR: \
280 (void) va_arg(ap, int); \
281 break; \
282 case PA_INT|PA_FLAG_LONG: \
283 (void) va_arg(ap, long int); \
284 break; \
285 case PA_INT|PA_FLAG_LONG_LONG: \
286 (void) va_arg(ap, long long int); \
287 break; \
288 case PA_WCHAR: \
289 (void) va_arg(ap, wchar_t); \
290 break; \
291 case PA_WSTRING: \
292 case PA_STRING: \
293 case PA_POINTER: \
294 (void) va_arg(ap, void*); \
295 break; \
296 case PA_FLOAT: \
297 case PA_DOUBLE: \
298 (void) va_arg(ap, double); \
299 break; \
300 case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \
301 (void) va_arg(ap, long double); \
302 break; \
303 default: \
304 assert_not_reached("Unknown format string argument."); \
305 } \
306 } \
307 } while(false)
308
309 /* Because statfs.t_type can be int on some architectures, we have to cast
310 * the const magic to the type, otherwise the compiler warns about
311 * signed/unsigned comparison, because the magic can be 32 bit unsigned.
312 */
313 #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
314
315 /* Returns the number of chars needed to format variables of the
316 * specified type as a decimal string. Adds in extra space for a
317 * negative '-' prefix. */
318 #define DECIMAL_STR_MAX(type) \
319 (2+(sizeof(type) <= 1 ? 3 : \
320 sizeof(type) <= 2 ? 5 : \
321 sizeof(type) <= 4 ? 10 : \
322 sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
323
324 #define SET_FLAG(v, flag, b) \
325 (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
326
327 #define IN_SET(x, y, ...) \
328 ({ \
329 const typeof(y) _y = (y); \
330 const typeof(_y) _x = (x); \
331 unsigned _i; \
332 bool _found = false; \
333 for (_i = 0; _i < 1 + sizeof((const typeof(_x)[]) { __VA_ARGS__ })/sizeof(const typeof(_x)); _i++) \
334 if (((const typeof(_x)[]) { _y, __VA_ARGS__ })[_i] == _x) { \
335 _found = true; \
336 break; \
337 } \
338 _found; \
339 })
340
341 /* Define C11 thread_local attribute even on older gcc compiler
342 * version */
343 #ifndef thread_local
344 /*
345 * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
346 * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
347 */
348 #if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
349 #define thread_local _Thread_local
350 #else
351 #define thread_local __thread
352 #endif
353 #endif
354
355 /* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
356 * compiler versions */
357 #ifndef noreturn
358 #if __STDC_VERSION__ >= 201112L
359 #define noreturn _Noreturn
360 #else
361 #define noreturn __attribute__((noreturn))
362 #endif
363 #endif
364
365 #include "log.h"