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