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