chiark / gitweb /
macro.h: let F_TYPE_CMP() macro fail to compile, if second parameter is not const
[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_attr_(a,b) __attribute__ ((format (printf, a, b)))
31 #define _sentinel_ __attribute__ ((sentinel))
32 #define _noreturn_ __attribute__((noreturn))
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 _introspect_(x) __attribute__((section("introspect." x)))
47 #define _alignas_(x) __attribute__((aligned(__alignof(x))))
48 #define _cleanup_(x) __attribute__((cleanup(x)))
49
50 /* automake test harness */
51 #define EXIT_TEST_SKIP 77
52
53 #define XSTRINGIFY(x) #x
54 #define STRINGIFY(x) XSTRINGIFY(x)
55
56 /* Rounds up */
57
58 #define ALIGN4(l) (((l) + 3) & ~3)
59 #define ALIGN8(l) (((l) + 7) & ~7)
60
61 #if __SIZEOF_POINTER__ == 8
62 #define ALIGN(l) ALIGN8(l)
63 #elif __SIZEOF_POINTER__ == 4
64 #define ALIGN(l) ALIGN4(l)
65 #else
66 #error "Wut? Pointers are neither 4 nor 8 bytes long?"
67 #endif
68
69 #define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) p))
70 #define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) p))
71 #define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) p))
72
73 static inline size_t ALIGN_TO(size_t l, size_t ali) {
74         return ((l + ali - 1) & ~(ali - 1));
75 }
76
77 #define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p))
78
79 #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
80
81 /*
82  * container_of - cast a member of a structure out to the containing structure
83  * @ptr: the pointer to the member.
84  * @type: the type of the container struct this is embedded in.
85  * @member: the name of the member within the struct.
86  *
87  */
88 #define container_of(ptr, type, member)                                 \
89         __extension__ ({                                                \
90                         const typeof( ((type *)0)->member ) *__mptr = (ptr); \
91                         (type *)( (char *)__mptr - offsetof(type,member) ); \
92                 })
93
94 #undef MAX
95 #define MAX(a,b)                                 \
96         __extension__ ({                         \
97                         typeof(a) _a = (a);      \
98                         typeof(b) _b = (b);      \
99                         _a > _b ? _a : _b;       \
100                 })
101
102 #define MAX3(x,y,z)                              \
103         __extension__ ({                         \
104                         typeof(x) _c = MAX(x,y); \
105                         MAX(_c, z);              \
106                 })
107
108 #undef MIN
109 #define MIN(a,b)                                \
110         __extension__ ({                        \
111                         typeof(a) _a = (a);     \
112                         typeof(b) _b = (b);     \
113                         _a < _b ? _a : _b;      \
114                 })
115
116 #ifndef CLAMP
117 #define CLAMP(x, low, high)                                             \
118         __extension__ ({                                                \
119                         typeof(x) _x = (x);                             \
120                         typeof(low) _low = (low);                       \
121                         typeof(high) _high = (high);                    \
122                         ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
123                 })
124 #endif
125
126 #define assert_se(expr)                                                 \
127         do {                                                            \
128                 if (_unlikely_(!(expr)))                                \
129                         log_assert_failed(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
130         } while (false)                                                 \
131
132 /* We override the glibc assert() here. */
133 #undef assert
134 #ifdef NDEBUG
135 #define assert(expr) do {} while(false)
136 #else
137 #define assert(expr) assert_se(expr)
138 #endif
139
140 #define assert_not_reached(t)                                           \
141         do {                                                            \
142                 log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
143         } while (false)
144
145 #if defined(static_assert)
146 #define assert_cc(expr)                         \
147         do {                                    \
148                 static_assert(expr, #expr);     \
149         } while (false)
150 #else
151 #define assert_cc(expr)                         \
152         do {                                    \
153                 switch (0) {                    \
154                 case 0:                         \
155                 case !!(expr):                  \
156                         ;                       \
157                 }                               \
158         } while (false)
159 #endif
160
161 #define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
162 #define UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
163
164 #define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
165 #define UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
166
167 #define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
168 #define ULONG_TO_PTR(u) ((void*) ((uintptr_t) (u)))
169
170 #define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
171 #define INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
172
173 #define TO_INT32(p) ((int32_t) ((intptr_t) (p)))
174 #define INT32_TO_PTR(u) ((void*) ((intptr_t) (u)))
175
176 #define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
177 #define LONG_TO_PTR(u) ((void*) ((intptr_t) (u)))
178
179 #define memzero(x,l) (memset((x), 0, (l)))
180 #define zero(x) (memzero(&(x), sizeof(x)))
181
182 #define CHAR_TO_STR(x) ((char[2]) { x, 0 })
183
184 #define char_array_0(x) x[sizeof(x)-1] = 0;
185
186 #define IOVEC_SET_STRING(i, s)                  \
187         do {                                    \
188                 struct iovec *_i = &(i);        \
189                 char *_s = (char *)(s);         \
190                 _i->iov_base = _s;              \
191                 _i->iov_len = strlen(_s);       \
192         } while(false)
193
194 static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
195         unsigned j;
196         size_t r = 0;
197
198         for (j = 0; j < n; j++)
199                 r += i[j].iov_len;
200
201         return r;
202 }
203
204 static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
205         unsigned j;
206
207         for (j = 0; j < n; j++) {
208                 size_t sub;
209
210                 if (_unlikely_(k <= 0))
211                         break;
212
213                 sub = MIN(i[j].iov_len, k);
214                 i[j].iov_len -= sub;
215                 i[j].iov_base = (uint8_t*) i[j].iov_base + sub;
216                 k -= sub;
217         }
218
219         return k;
220 }
221
222 #define VA_FORMAT_ADVANCE(format, ap)                                   \
223 do {                                                                    \
224         int _argtypes[128];                                             \
225         size_t _i, _k;                                                  \
226         _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
227         assert(_k < ELEMENTSOF(_argtypes));                             \
228         for (_i = 0; _i < _k; _i++) {                                   \
229                 if (_argtypes[_i] & PA_FLAG_PTR)  {                     \
230                         (void) va_arg(ap, void*);                       \
231                         continue;                                       \
232                 }                                                       \
233                                                                         \
234                 switch (_argtypes[_i]) {                                \
235                 case PA_INT:                                            \
236                 case PA_INT|PA_FLAG_SHORT:                              \
237                 case PA_CHAR:                                           \
238                         (void) va_arg(ap, int);                         \
239                         break;                                          \
240                 case PA_INT|PA_FLAG_LONG:                               \
241                         (void) va_arg(ap, long int);                    \
242                         break;                                          \
243                 case PA_INT|PA_FLAG_LONG_LONG:                          \
244                         (void) va_arg(ap, long long int);               \
245                         break;                                          \
246                 case PA_WCHAR:                                          \
247                         (void) va_arg(ap, wchar_t);                     \
248                         break;                                          \
249                 case PA_WSTRING:                                        \
250                 case PA_STRING:                                         \
251                 case PA_POINTER:                                        \
252                         (void) va_arg(ap, void*);                       \
253                         break;                                          \
254                 case PA_FLOAT:                                          \
255                 case PA_DOUBLE:                                         \
256                         (void) va_arg(ap, double);                      \
257                         break;                                          \
258                 case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:                     \
259                         (void) va_arg(ap, long double);                 \
260                         break;                                          \
261                 default:                                                \
262                         assert_not_reached("Unknown format string argument."); \
263                 }                                                       \
264         }                                                               \
265 } while(false)
266
267 /* Remove this macro, when the kernel has f_type as unsigned int or long
268  * for every architecure. Currently some 64bit architecures (like s390x)
269  * have int in the kernel, but long in userspace for f_type, so glibc
270  * extends the int to long and carries over the sign. Negative numbers are
271  * caused by the 32bit magic constants in linux/magic.h stuffed into the
272  * signed int in the kernel and these negative numbers are extended to
273  * long, which cannot be simply compared to the magic constants anymore.
274  */
275 #define F_TYPE_CMP(f_type, magic)                                       \
276         __extension__ ({                                                \
277                         __SWORD_TYPE _f = (f_type);                     \
278                         const __SWORD_TYPE _c = (magic);                \
279                         const int _c32 = 1 ? (magic)                    \
280                                     : sizeof((int[magic]){0});          \
281                         (_f == _c || _f == _c32 );                      \
282                 })
283
284
285 /* Returns the number of chars needed to format variables of the
286  * specified type as a decimal string. Adds in extra space for a
287  * negative '-' prefix. */
288
289 #define DECIMAL_STR_MAX(type)                                           \
290         (1+(sizeof(type) <= 1 ? 3 :                                     \
291             sizeof(type) <= 2 ? 5 :                                     \
292             sizeof(type) <= 4 ? 10 :                                    \
293             sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
294
295 #include "log.h"