chiark / gitweb /
1941f0e6517c472536b0acacbfa30a0e37460f53
[elogind.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 REENABLE_WARNING                                                \
59         _Pragma("GCC diagnostic pop")
60
61 /* automake test harness */
62 #define EXIT_TEST_SKIP 77
63
64 #define XSTRINGIFY(x) #x
65 #define STRINGIFY(x) XSTRINGIFY(x)
66
67 #define XCONCATENATE(x, y) x ## y
68 #define CONCATENATE(x, y) XCONCATENATE(x, y)
69
70 #define UNIQUE(prefix) CONCATENATE(prefix, __LINE__)
71
72 /* Rounds up */
73
74 #define ALIGN4(l) (((l) + 3) & ~3)
75 #define ALIGN8(l) (((l) + 7) & ~7)
76
77 #if __SIZEOF_POINTER__ == 8
78 #define ALIGN(l) ALIGN8(l)
79 #elif __SIZEOF_POINTER__ == 4
80 #define ALIGN(l) ALIGN4(l)
81 #else
82 #error "Wut? Pointers are neither 4 nor 8 bytes long?"
83 #endif
84
85 #define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) p))
86 #define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) p))
87 #define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) p))
88
89 static inline size_t ALIGN_TO(size_t l, size_t ali) {
90         return ((l + ali - 1) & ~(ali - 1));
91 }
92
93 #define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p))
94
95 #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
96
97 /*
98  * container_of - cast a member of a structure out to the containing structure
99  * @ptr: the pointer to the member.
100  * @type: the type of the container struct this is embedded in.
101  * @member: the name of the member within the struct.
102  *
103  */
104 #define container_of(ptr, type, member)                                 \
105         __extension__ ({                                                \
106                         const typeof( ((type *)0)->member ) *__mptr = (ptr); \
107                         (type *)( (char *)__mptr - offsetof(type,member) ); \
108                 })
109
110 #undef MAX
111 #define MAX(a,b)                                 \
112         __extension__ ({                         \
113                         typeof(a) _a = (a);      \
114                         typeof(b) _b = (b);      \
115                         _a > _b ? _a : _b;       \
116                 })
117
118 #define MAX3(x,y,z)                              \
119         __extension__ ({                         \
120                         typeof(x) _c = MAX(x,y); \
121                         MAX(_c, z);              \
122                 })
123
124 #undef MIN
125 #define MIN(a,b)                                \
126         __extension__ ({                        \
127                         typeof(a) _a = (a);     \
128                         typeof(b) _b = (b);     \
129                         _a < _b ? _a : _b;      \
130                 })
131
132 #define LESS_BY(A,B)                            \
133         __extension__ ({                        \
134                         typeof(A) _A = (A);     \
135                         typeof(B) _B = (B);     \
136                         _A > _B ? _A - _B : 0;  \
137                 })
138
139 #ifndef CLAMP
140 #define CLAMP(x, low, high)                                             \
141         __extension__ ({                                                \
142                         typeof(x) _x = (x);                             \
143                         typeof(low) _low = (low);                       \
144                         typeof(high) _high = (high);                    \
145                         ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
146                 })
147 #endif
148
149 #define assert_se(expr)                                                 \
150         do {                                                            \
151                 if (_unlikely_(!(expr)))                                \
152                         log_assert_failed(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
153         } while (false)                                                 \
154
155 /* We override the glibc assert() here. */
156 #undef assert
157 #ifdef NDEBUG
158 #define assert(expr) do {} while(false)
159 #else
160 #define assert(expr) assert_se(expr)
161 #endif
162
163 #define assert_not_reached(t)                                           \
164         do {                                                            \
165                 log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
166         } while (false)
167
168 #if defined(static_assert)
169 /* static_assert() is sometimes defined in a way that trips up
170  * -Wdeclaration-after-statement, hence let's temporarily turn off
171  * this warning around it. */
172 #define assert_cc(expr)                                                 \
173         DISABLE_WARNING_DECLARATION_AFTER_STATEMENT;                    \
174         static_assert(expr, #expr);                                     \
175         REENABLE_WARNING
176 #else
177 #define assert_cc(expr)                                                 \
178         DISABLE_WARNING_DECLARATION_AFTER_STATEMENT;                    \
179         struct UNIQUE(_assert_struct_) {                                \
180                 char x[(expr) ? 0 : -1];                                \
181         };                                                              \
182         REENABLE_WARNING
183 #endif
184
185 #define assert_return(expr, r)                                          \
186         do {                                                            \
187                 if (_unlikely_(!(expr))) {                              \
188                         log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
189                         return (r);                                     \
190                 }                                                       \
191         } while (false)
192
193 #define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
194 #define INT_TO_PTR(u) ((void *) ((intptr_t) (u)))
195 #define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
196 #define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
197
198 #define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
199 #define LONG_TO_PTR(u) ((void *) ((intptr_t) (u)))
200 #define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
201 #define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u)))
202
203 #define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p)))
204 #define INT32_TO_PTR(u) ((void *) ((intptr_t) (u)))
205 #define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
206 #define UINT32_TO_PTR(u) ((void *) ((uintptr_t) (u)))
207
208 #define PTR_TO_INT64(p) ((int64_t) ((intptr_t) (p)))
209 #define INT64_TO_PTR(u) ((void *) ((intptr_t) (u)))
210 #define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p)))
211 #define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u)))
212
213 #define memzero(x,l) (memset((x), 0, (l)))
214 #define zero(x) (memzero(&(x), sizeof(x)))
215
216 #define CHAR_TO_STR(x) ((char[2]) { x, 0 })
217
218 #define char_array_0(x) x[sizeof(x)-1] = 0;
219
220 #define IOVEC_SET_STRING(i, s)                  \
221         do {                                    \
222                 struct iovec *_i = &(i);        \
223                 char *_s = (char *)(s);         \
224                 _i->iov_base = _s;              \
225                 _i->iov_len = strlen(_s);       \
226         } while(false)
227
228 static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
229         unsigned j;
230         size_t r = 0;
231
232         for (j = 0; j < n; j++)
233                 r += i[j].iov_len;
234
235         return r;
236 }
237
238 static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
239         unsigned j;
240
241         for (j = 0; j < n; j++) {
242                 size_t sub;
243
244                 if (_unlikely_(k <= 0))
245                         break;
246
247                 sub = MIN(i[j].iov_len, k);
248                 i[j].iov_len -= sub;
249                 i[j].iov_base = (uint8_t*) i[j].iov_base + sub;
250                 k -= sub;
251         }
252
253         return k;
254 }
255
256 #define VA_FORMAT_ADVANCE(format, ap)                                   \
257 do {                                                                    \
258         int _argtypes[128];                                             \
259         size_t _i, _k;                                                  \
260         _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
261         assert(_k < ELEMENTSOF(_argtypes));                             \
262         for (_i = 0; _i < _k; _i++) {                                   \
263                 if (_argtypes[_i] & PA_FLAG_PTR)  {                     \
264                         (void) va_arg(ap, void*);                       \
265                         continue;                                       \
266                 }                                                       \
267                                                                         \
268                 switch (_argtypes[_i]) {                                \
269                 case PA_INT:                                            \
270                 case PA_INT|PA_FLAG_SHORT:                              \
271                 case PA_CHAR:                                           \
272                         (void) va_arg(ap, int);                         \
273                         break;                                          \
274                 case PA_INT|PA_FLAG_LONG:                               \
275                         (void) va_arg(ap, long int);                    \
276                         break;                                          \
277                 case PA_INT|PA_FLAG_LONG_LONG:                          \
278                         (void) va_arg(ap, long long int);               \
279                         break;                                          \
280                 case PA_WCHAR:                                          \
281                         (void) va_arg(ap, wchar_t);                     \
282                         break;                                          \
283                 case PA_WSTRING:                                        \
284                 case PA_STRING:                                         \
285                 case PA_POINTER:                                        \
286                         (void) va_arg(ap, void*);                       \
287                         break;                                          \
288                 case PA_FLOAT:                                          \
289                 case PA_DOUBLE:                                         \
290                         (void) va_arg(ap, double);                      \
291                         break;                                          \
292                 case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:                     \
293                         (void) va_arg(ap, long double);                 \
294                         break;                                          \
295                 default:                                                \
296                         assert_not_reached("Unknown format string argument."); \
297                 }                                                       \
298         }                                                               \
299 } while(false)
300
301  /* Because statfs.t_type can be int on some architectures, we have to cast
302   * the const magic to the type, otherwise the compiler warns about
303   * signed/unsigned comparison, because the magic can be 32 bit unsigned.
304  */
305 #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
306
307 /* Returns the number of chars needed to format variables of the
308  * specified type as a decimal string. Adds in extra space for a
309  * negative '-' prefix. */
310 #define DECIMAL_STR_MAX(type)                                           \
311         (2+(sizeof(type) <= 1 ? 3 :                                     \
312             sizeof(type) <= 2 ? 5 :                                     \
313             sizeof(type) <= 4 ? 10 :                                    \
314             sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
315
316 #define SET_FLAG(v, flag, b) \
317         (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
318
319 #define IN_SET(x, ...)                                                  \
320         ({                                                              \
321                 const typeof(x) _x = (x);                               \
322                 unsigned _i;                                            \
323                 bool _found = false;                                    \
324                 for (_i = 0; _i < sizeof((const typeof(_x)[]) { __VA_ARGS__ })/sizeof(const typeof(_x)); _i++) \
325                         if (((const typeof(_x)[]) { __VA_ARGS__ })[_i] == _x) { \
326                                 _found = true;                          \
327                                 break;                                  \
328                         }                                               \
329                 _found;                                                 \
330         })
331
332 /* Define C11 thread_local attribute even on older gcc compiler
333  * version */
334 #ifndef thread_local
335 /*
336  * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
337  * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
338  */
339 #if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
340 #define thread_local _Thread_local
341 #else
342 #define thread_local __thread
343 #endif
344 #endif
345
346 /* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
347  * compiler versions */
348 #ifndef noreturn
349 #if __STDC_VERSION__ >= 201112L
350 #define noreturn _Noreturn
351 #else
352 #define noreturn __attribute__((noreturn))
353 #endif
354 #endif
355
356 #include "log.h"