Coverage Report

Created: 2026-05-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/freeradius-devel/build.h
Line
Count
Source
1
#pragma once
2
/*
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16
 */
17
18
/**
19
 * $Id: 659bd9cbea4f2c878d98360b18c1f4aa43fe8d55 $
20
 *
21
 * @file include/build.h
22
 * @brief Source control functions
23
 *
24
 * @copyright 2013 The FreeRADIUS server project
25
 */
26
27
#ifdef __cplusplus
28
extern "C" {
29
#endif
30
31
/** For systems with an old version libc, define static_assert.
32
 *
33
 */
34
#ifndef static_assert
35
# if __STDC_VERSION__ < 202000
36
#  define static_assert _Static_assert
37
# endif
38
# else
39
#  include <assert.h>
40
#endif
41
42
/*
43
 *  Static analyzers don't notice or can't infer some properties
44
 *  of the code, and hence may give false positives. To deal with
45
 *  them, there is some conditionally compiled code in various
46
 *  places. The following lets the code change minimally if and
47
 *  when new static analyzers are added.
48
 */
49
#ifdef __clang_analyzer__
50
#define STATIC_ANALYZER 1
51
#endif
52
#ifdef __COVERITY__
53
#define STATIC_ANALYZER 1
54
#endif
55
56
/*
57
 *  Reduce spurious errors from static analyzers by having
58
 *  all paths that find the da to be NULL, result
59
 *  in program exit.
60
 */
61
#ifdef STATIC_ANALYZER
62
#  define WITH_VERIFY_PTR 1
63
#endif
64
65
/*
66
 *  GCC uses __SANITIZE_ADDRESS__, clang uses __has_feature, which
67
 *  GCC complains about.
68
 */
69
#ifndef __SANITIZE_ADDRESS__
70
#ifdef __has_feature
71
#if __has_feature(address_sanitizer)
72
#define __SANITIZE_ADDRESS__ (1)
73
#endif
74
#endif
75
#endif
76
77
/*
78
 *  Basic headers we want everywhere
79
 */
80
#include <stdbool.h>
81
#include <stdint.h>
82
#include <stddef.h>
83
#include <string.h>
84
85
/*
86
 *  These are compile time options to toggle whether
87
 *  we're building with thread support.
88
 *
89
 *  With EMSCRIPTEN threading support isn't guaranteed
90
 *  as many browsers have explicitly disabled support
91
 *  due to spectre attacks.
92
 */
93
#if (defined(__EMSCRIPTEN__) && defined(__EMSCRIPTEN_PTHREADS__)) || !defined(__EMSCRIPTEN__) && defined(HAVE_PTHREAD_H)
94
#  define HAVE_PTHREADS 1
95
#endif
96
97
/*
98
 *  GCC will sometimes define "unix" as well as "__unix",
99
 *  which gets confusing and is unnecessary.
100
 */
101
#undef unix
102
103
/** Evaluates to +1 for a > b, and -1 for a < b
104
 */
105
86.9k
#define CMP_PREFER_SMALLER(_a,_b) (((_a) > (_b)) - ((_a) < (_b)))
106
107
/** Evaluates to -1 for a > b, and +1 for a < b
108
 */
109
0
#define CMP_PREFER_LARGER(_a,_b)  (((_a) < (_b)) - ((_a) > (_b)))
110
111
/** Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want _an_ ordering.
112
 */
113
86.9k
#define CMP(_a, _b)     CMP_PREFER_SMALLER(_a, _b)
114
115
/** Return if the comparison is not 0 (is unequal)
116
 *
117
 * @param[in] _a  pointer to first structure.
118
 * @param[in] _b  pointer to second structure.
119
 * @param[in] _field  within the structs to compare.
120
 * @return The result of the comparison.
121
 */
122
0
#define CMP_RETURN(_a, _b, _field) \
123
0
do { \
124
0
  int8_t _ret = CMP((_a)->_field, (_b)->_field); \
125
0
  if (_ret != 0) return _ret; \
126
0
} while (0)
127
128
/** memcmp function which has similar behaviour as strncmp
129
 *
130
 * @param[in] a     First thing to compare.
131
 * @param[in] b     Second thing to compare.
132
 * @param[in] a_len   Length of first thing.
133
 * @param[in] b_len   Length of second thing.
134
 * @return
135
 *  - +1 if a > b
136
 *  - 0 if a == b
137
 *  - -1 if a < b
138
 */
139
static inline int8_t memcmp_return(void const *a, void const *b, size_t a_len, size_t b_len)
140
0
{
141
0
  size_t cmp_len;
142
0
  int8_t ret;
143
144
0
  if (!a_len && b_len) return -1;
145
0
  if (a_len && !b_len) return +1;
146
0
  if (!a_len && !b_len) return 0;
147
148
0
  cmp_len = (a_len < b_len) ? a_len : b_len;
149
150
0
  ret = CMP(memcmp(a, b, cmp_len), 0); /* memcmp() can't be passed a NULL pointer */
151
0
  if (ret != 0) return ret;
152
153
0
  return CMP(a_len, b_len);
154
0
}
Unexecuted instantiation: fuzzer_dhcpv6.c:memcmp_return
Unexecuted instantiation: fuzzer_util.c:memcmp_return
Unexecuted instantiation: fuzzer_dhcpv4.c:memcmp_return
Unexecuted instantiation: fuzzer_cbor.c:memcmp_return
Unexecuted instantiation: fuzzer_der.c:memcmp_return
Unexecuted instantiation: fuzzer_dns.c:memcmp_return
Unexecuted instantiation: fuzzer_tacacs.c:memcmp_return
Unexecuted instantiation: fuzzer_json.c:memcmp_return
Unexecuted instantiation: fuzzer_bfd.c:memcmp_return
Unexecuted instantiation: fuzzer_radius.c:memcmp_return
Unexecuted instantiation: fuzzer_tftp.c:memcmp_return
Unexecuted instantiation: fuzzer_vmps.c:memcmp_return
Unexecuted instantiation: atexit.c:memcmp_return
Unexecuted instantiation: backtrace.c:memcmp_return
Unexecuted instantiation: base16.c:memcmp_return
Unexecuted instantiation: base32.c:memcmp_return
Unexecuted instantiation: base64.c:memcmp_return
Unexecuted instantiation: calc.c:memcmp_return
Unexecuted instantiation: cap.c:memcmp_return
Unexecuted instantiation: chap.c:memcmp_return
Unexecuted instantiation: cbor.c:memcmp_return
Unexecuted instantiation: dbuff.c:memcmp_return
Unexecuted instantiation: debug.c:memcmp_return
Unexecuted instantiation: decode.c:memcmp_return
Unexecuted instantiation: dict_ext.c:memcmp_return
Unexecuted instantiation: dict_fixup.c:memcmp_return
Unexecuted instantiation: dict_print.c:memcmp_return
Unexecuted instantiation: dict_test.c:memcmp_return
Unexecuted instantiation: dict_tokenize.c:memcmp_return
Unexecuted instantiation: dict_unknown.c:memcmp_return
Unexecuted instantiation: dict_util.c:memcmp_return
Unexecuted instantiation: dict_validate.c:memcmp_return
Unexecuted instantiation: dl.c:memcmp_return
Unexecuted instantiation: dns.c:memcmp_return
Unexecuted instantiation: edit.c:memcmp_return
Unexecuted instantiation: encode.c:memcmp_return
Unexecuted instantiation: event.c:memcmp_return
Unexecuted instantiation: timer.c:memcmp_return
Unexecuted instantiation: ext.c:memcmp_return
Unexecuted instantiation: fifo.c:memcmp_return
Unexecuted instantiation: file.c:memcmp_return
Unexecuted instantiation: fopencookie.c:memcmp_return
Unexecuted instantiation: fring.c:memcmp_return
Unexecuted instantiation: getaddrinfo.c:memcmp_return
Unexecuted instantiation: hash.c:memcmp_return
Unexecuted instantiation: heap.c:memcmp_return
Unexecuted instantiation: hmac_md5.c:memcmp_return
Unexecuted instantiation: hmac_sha1.c:memcmp_return
Unexecuted instantiation: htrie.c:memcmp_return
Unexecuted instantiation: hw.c:memcmp_return
Unexecuted instantiation: inet.c:memcmp_return
Unexecuted instantiation: iovec.c:memcmp_return
Unexecuted instantiation: isaac.c:memcmp_return
Unexecuted instantiation: log.c:memcmp_return
Unexecuted instantiation: lst.c:memcmp_return
Unexecuted instantiation: machine.c:memcmp_return
Unexecuted instantiation: md4.c:memcmp_return
Unexecuted instantiation: md5.c:memcmp_return
Unexecuted instantiation: minmax_heap.c:memcmp_return
Unexecuted instantiation: misc.c:memcmp_return
Unexecuted instantiation: missing.c:memcmp_return
Unexecuted instantiation: net.c:memcmp_return
Unexecuted instantiation: packet.c:memcmp_return
Unexecuted instantiation: pair.c:memcmp_return
Unexecuted instantiation: pair_inline.c:memcmp_return
Unexecuted instantiation: pair_legacy.c:memcmp_return
Unexecuted instantiation: pair_print.c:memcmp_return
Unexecuted instantiation: pair_tokenize.c:memcmp_return
Unexecuted instantiation: paths.c:memcmp_return
Unexecuted instantiation: pcap.c:memcmp_return
Unexecuted instantiation: perm.c:memcmp_return
Unexecuted instantiation: print.c:memcmp_return
Unexecuted instantiation: proto.c:memcmp_return
Unexecuted instantiation: rand.c:memcmp_return
Unexecuted instantiation: rb.c:memcmp_return
Unexecuted instantiation: rb_expire.c:memcmp_return
Unexecuted instantiation: regex.c:memcmp_return
Unexecuted instantiation: retry.c:memcmp_return
Unexecuted instantiation: sbuff.c:memcmp_return
Unexecuted instantiation: sem.c:memcmp_return
Unexecuted instantiation: semaphore.c:memcmp_return
Unexecuted instantiation: sha1.c:memcmp_return
Unexecuted instantiation: size.c:memcmp_return
Unexecuted instantiation: skip.c:memcmp_return
Unexecuted instantiation: snprintf.c:memcmp_return
Unexecuted instantiation: socket.c:memcmp_return
Unexecuted instantiation: stats.c:memcmp_return
Unexecuted instantiation: strerror.c:memcmp_return
Unexecuted instantiation: strlcat.c:memcmp_return
Unexecuted instantiation: strlcpy.c:memcmp_return
Unexecuted instantiation: struct.c:memcmp_return
Unexecuted instantiation: syserror.c:memcmp_return
Unexecuted instantiation: table.c:memcmp_return
Unexecuted instantiation: talloc.c:memcmp_return
Unexecuted instantiation: time.c:memcmp_return
Unexecuted instantiation: timeval.c:memcmp_return
Unexecuted instantiation: token.c:memcmp_return
Unexecuted instantiation: trie.c:memcmp_return
Unexecuted instantiation: types.c:memcmp_return
Unexecuted instantiation: udp.c:memcmp_return
Unexecuted instantiation: udp_queue.c:memcmp_return
Unexecuted instantiation: udpfromto.c:memcmp_return
Unexecuted instantiation: uri.c:memcmp_return
Unexecuted instantiation: value.c:memcmp_return
Unexecuted instantiation: version.c:memcmp_return
Unexecuted instantiation: fuzzer.c:memcmp_return
Unexecuted instantiation: base.c:memcmp_return
Unexecuted instantiation: raw.c:memcmp_return
Unexecuted instantiation: encode.c:memcmp_return
Unexecuted instantiation: json.c:memcmp_return
Unexecuted instantiation: jpath.c:memcmp_return
Unexecuted instantiation: bio.c:memcmp_return
Unexecuted instantiation: cache.c:memcmp_return
Unexecuted instantiation: cert.c:memcmp_return
Unexecuted instantiation: conf.c:memcmp_return
Unexecuted instantiation: ctx.c:memcmp_return
Unexecuted instantiation: engine.c:memcmp_return
Unexecuted instantiation: pairs.c:memcmp_return
Unexecuted instantiation: session.c:memcmp_return
Unexecuted instantiation: utils.c:memcmp_return
Unexecuted instantiation: verify.c:memcmp_return
Unexecuted instantiation: virtual_server.c:memcmp_return
Unexecuted instantiation: list.c:memcmp_return
Unexecuted instantiation: tcp.c:memcmp_return
Unexecuted instantiation: abinary.c:memcmp_return
Unexecuted instantiation: auth.c:memcmp_return
Unexecuted instantiation: cf_file.c:memcmp_return
Unexecuted instantiation: cf_parse.c:memcmp_return
Unexecuted instantiation: cf_util.c:memcmp_return
Unexecuted instantiation: client.c:memcmp_return
Unexecuted instantiation: command.c:memcmp_return
Unexecuted instantiation: connection.c:memcmp_return
Unexecuted instantiation: dependency.c:memcmp_return
Unexecuted instantiation: dl_module.c:memcmp_return
Unexecuted instantiation: exec.c:memcmp_return
Unexecuted instantiation: exec_legacy.c:memcmp_return
Unexecuted instantiation: exfile.c:memcmp_return
Unexecuted instantiation: global_lib.c:memcmp_return
Unexecuted instantiation: main_config.c:memcmp_return
Unexecuted instantiation: main_loop.c:memcmp_return
Unexecuted instantiation: map.c:memcmp_return
Unexecuted instantiation: map_proc.c:memcmp_return
Unexecuted instantiation: module.c:memcmp_return
Unexecuted instantiation: module_method.c:memcmp_return
Unexecuted instantiation: module_rlm.c:memcmp_return
Unexecuted instantiation: paircmp.c:memcmp_return
Unexecuted instantiation: pairmove.c:memcmp_return
Unexecuted instantiation: password.c:memcmp_return
Unexecuted instantiation: pool.c:memcmp_return
Unexecuted instantiation: rcode.c:memcmp_return
Unexecuted instantiation: request.c:memcmp_return
Unexecuted instantiation: request_data.c:memcmp_return
Unexecuted instantiation: section.c:memcmp_return
Unexecuted instantiation: snmp.c:memcmp_return
Unexecuted instantiation: state.c:memcmp_return
Unexecuted instantiation: tmpl_dcursor.c:memcmp_return
Unexecuted instantiation: tmpl_eval.c:memcmp_return
Unexecuted instantiation: tmpl_tokenize.c:memcmp_return
Unexecuted instantiation: time_tracking.c:memcmp_return
Unexecuted instantiation: trigger.c:memcmp_return
Unexecuted instantiation: trunk.c:memcmp_return
Unexecuted instantiation: users_file.c:memcmp_return
Unexecuted instantiation: util.c:memcmp_return
Unexecuted instantiation: virtual_servers.c:memcmp_return
Unexecuted instantiation: call.c:memcmp_return
Unexecuted instantiation: call_env.c:memcmp_return
Unexecuted instantiation: caller.c:memcmp_return
Unexecuted instantiation: catch.c:memcmp_return
Unexecuted instantiation: child_request.c:memcmp_return
Unexecuted instantiation: compile.c:memcmp_return
Unexecuted instantiation: condition.c:memcmp_return
Unexecuted instantiation: detach.c:memcmp_return
Unexecuted instantiation: finally.c:memcmp_return
Unexecuted instantiation: foreach.c:memcmp_return
Unexecuted instantiation: function.c:memcmp_return
Unexecuted instantiation: group.c:memcmp_return
Unexecuted instantiation: interpret.c:memcmp_return
Unexecuted instantiation: interpret_synchronous.c:memcmp_return
Unexecuted instantiation: io.c:memcmp_return
Unexecuted instantiation: limit.c:memcmp_return
Unexecuted instantiation: load_balance.c:memcmp_return
Unexecuted instantiation: map_builtin.c:memcmp_return
Unexecuted instantiation: mod_action.c:memcmp_return
Unexecuted instantiation: parallel.c:memcmp_return
Unexecuted instantiation: return.c:memcmp_return
Unexecuted instantiation: subrequest.c:memcmp_return
Unexecuted instantiation: switch.c:memcmp_return
Unexecuted instantiation: timeout.c:memcmp_return
Unexecuted instantiation: tmpl.c:memcmp_return
Unexecuted instantiation: try.c:memcmp_return
Unexecuted instantiation: transaction.c:memcmp_return
Unexecuted instantiation: xlat.c:memcmp_return
Unexecuted instantiation: xlat_alloc.c:memcmp_return
Unexecuted instantiation: xlat_builtin.c:memcmp_return
Unexecuted instantiation: xlat_eval.c:memcmp_return
Unexecuted instantiation: xlat_expr.c:memcmp_return
Unexecuted instantiation: xlat_func.c:memcmp_return
Unexecuted instantiation: xlat_inst.c:memcmp_return
Unexecuted instantiation: xlat_pair.c:memcmp_return
Unexecuted instantiation: xlat_purify.c:memcmp_return
Unexecuted instantiation: xlat_redundant.c:memcmp_return
Unexecuted instantiation: xlat_tokenize.c:memcmp_return
Unexecuted instantiation: app_io.c:memcmp_return
Unexecuted instantiation: atomic_queue.c:memcmp_return
Unexecuted instantiation: channel.c:memcmp_return
Unexecuted instantiation: control.c:memcmp_return
Unexecuted instantiation: coord.c:memcmp_return
Unexecuted instantiation: coord_pair.c:memcmp_return
Unexecuted instantiation: load.c:memcmp_return
Unexecuted instantiation: master.c:memcmp_return
Unexecuted instantiation: message.c:memcmp_return
Unexecuted instantiation: network.c:memcmp_return
Unexecuted instantiation: queue.c:memcmp_return
Unexecuted instantiation: ring_buffer.c:memcmp_return
Unexecuted instantiation: schedule.c:memcmp_return
Unexecuted instantiation: thread.c:memcmp_return
Unexecuted instantiation: worker.c:memcmp_return
Unexecuted instantiation: vmps.c:memcmp_return
155
156
/** Return if the contents of the specified field is not identical between the specified structures
157
 *
158
 * @param[in] _a    pointer to first structure.
159
 * @param[in] _b    pointer to second structure.
160
 * @param[in] _field    within the structs to compare.
161
 * @param[in] _len_field  within the structs, specifying the length of the data.
162
 * @return The result of the comparison.
163
 */
164
#define MEMCMP_RETURN(_a, _b, _field, _len_field) \
165
do { \
166
  int8_t _ret = memcmp_return((_a)->_field, (_b)->_field, (_a)->_len_field, (_b)->_len_field); \
167
  if (_ret != 0) return _ret; \
168
} while (0)
169
170
/** Return the comparison of two opaque fields of a structure
171
 *
172
 * @param[in] _a    pointer to first structure.
173
 * @param[in] _b    pointer to second structure.
174
 * @param[in] _field    within the structs to compare.
175
 * @param[in] _len_field  within the structs, specifying the length of the data.
176
 * @return The result of the comparison.
177
 */
178
#define MEMCMP_FIELDS(_a, _b, _field, _len_field) \
179
0
  memcmp_return((_a)->_field, (_b)->_field, (_a)->_len_field, (_b)->_len_field)
180
181
/** Remove const qualification from a pointer
182
 *
183
 * @param[in] _type The non-const version of the type.
184
 * @param[in] _ptr  to de-const.
185
 */
186
25.2M
#define UNCONST(_type, _ptr)    ((_type)((uintptr_t)(_ptr)))
187
188
/** Typeof field
189
 *
190
 * @param[in] _type struct type containing the field.
191
 * @param[in] _field  to return the type of.
192
 */
193
1.65k
#define typeof_field(_type, _field) __typeof__(((_type *)NULL)->_field)
194
195
/** HEX concatenation macros
196
 *
197
 */
198
#ifndef HEXIFY
199
#  define XHEXIFY4(b1,b2,b3,b4) (0x ## b1 ## b2 ## b3 ## b4)
200
#  define HEXIFY4(b1,b2,b3,b4)  XHEXIFY4(b1, b2, b3, b4)
201
202
#  define XHEXIFY3(b1,b2,b3)  (0x ## b1 ## b2 ## b3)
203
#  define HEXIFY3(b1,b2,b3) XHEXIFY3(b1, b2, b3)
204
205
5.17M
#  define XHEXIFY2(b1,b2) (0x ## b1 ## b2)
206
5.17M
#  define HEXIFY2(b1,b2)  XHEXIFY2(b1, b2)
207
208
0
#  define XHEXIFY(b1)   (0x ## b1)
209
0
#  define HEXIFY(b1)    XHEXIFY(b1)
210
#endif
211
212
/** The ubiquitous stringify macros
213
 *
214
 */
215
0
#define XSTRINGIFY(x) #x
216
0
#define STRINGIFY(x)  XSTRINGIFY(x)
217
#define JOINSTR(x,y)  XSTRINGIFY(x ## y)
218
219
/** Join two values without stringifying
220
 *
221
 * Useful for calling different macros based on the output of
222
*/
223
19.4k
#define _JOIN(x,y)  x ## y
224
38.9k
#define JOIN(x,y) _JOIN(x,y)
225
226
/** Helper for initialising arrays of string literals
227
 */
228
47.9k
#define L(_str)   { _str, sizeof(_str) - 1 }
229
230
/** Fill macros for array initialisation
231
 */
232
#define F1(_idx, _val)    [_idx] = _val
233
#define F2(_idx, _val)    F1(_idx, _val), F1(_idx + 1, _val)
234
#define F4(_idx, _val)    F2(_idx, _val), F2(_idx + 2, _val)
235
#define F8(_idx, _val)    F4(_idx, _val), F4(_idx + 4, _val)
236
#define F16(_idx, _val)   F8(_idx, _val), F8(_idx + 8, _val)
237
#define F32(_idx, _val)   F16(_idx, _val), F16(_idx + 16, _val)
238
#define F64(_idx, _val)   F32(_idx, _val), F32(_idx + 32, _val)
239
#define F128(_idx, _val)  F64(_idx, _val), F64(_idx + 64, _val)
240
#define F256(_idx, _val)  F128(_idx, _val), F128(_idx + 128, _val)
241
242
/** Variadic macro framework
243
 */
244
245
/**
246
 * The VA_NARG macro evaluates to the number of arguments that have been
247
 * passed to it.
248
 *
249
 * Laurent Deniau, "__VA_NARG__," 17 January 2006, <comp.std.c> (29 November 2007).
250
 */
251
#define VA_ARG_N( \
252
        _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,  \
253
        _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
254
        _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
255
        _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
256
        _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
257
        _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
258
        _61,_62,_63,N,...) N
259
260
#define VA_RSEQ_N() \
261
        63,62,61,60,                   \
262
        59,58,57,56,55,54,53,52,51,50, \
263
        49,48,47,46,45,44,43,42,41,40, \
264
        39,38,37,36,35,34,33,32,31,30, \
265
        29,28,27,26,25,24,23,22,21,20, \
266
        19,18,17,16,15,14,13,12,11,10, \
267
        9,8,7,6,5,4,3,2,1,0
268
269
#define _VA_NARG(...)   VA_ARG_N(__VA_ARGS__)
270
271
/** Return the number of variadic arguments up to 64
272
 *
273
 * @param[in] ... Variadic arguments to count.
274
 */
275
#define VA_NARG(...)    _VA_NARG(__VA_ARGS__, VA_RSEQ_N())
276
277
278
/** Pass caller information to the function
279
 *
280
 */
281
#ifndef NDEBUG
282
#  define NDEBUG_LOCATION_ARGS      char const *file, int line,
283
27.1k
#  define NDEBUG_LOCATION_VALS      file, line,
284
#  define NDEBUG_LOCATION_FMT     "%s[%d]: "
285
5.14M
#  define NDEBUG_LOCATION_EXP     __FILE__, __LINE__,
286
#  define NDEBUG_LOCATION_NONNULL(_num)   ((_num) + 2)
287
#else
288
#  define NDEBUG_LOCATION_ARGS
289
#  define NDEBUG_LOCATION_VALS
290
#  define NDEBUG_LOCATION_FMT     ""
291
#  define NDEBUG_LOCATION_EXP
292
#  define NDEBUG_LOCATION_NONNULL(_num)   (_num)
293
#endif
294
295
/** Check if a given variable is the _const or not
296
 *
297
 * @param[in] _type The base type of the variable (should not be marked const)
298
 * @param[in] _var  to check.
299
 */
300
#define IS_CONST(_type, _var) \
301
0
  _Generic((_var), \
302
0
     _type: false, \
303
0
     const _type: true \
304
0
  )
305
306
/** Check if a given variable is the const or unconst version of a type
307
 *
308
 * Expands to _var if _var matches type, otherwise throws a compiler error.
309
 *
310
 * Useful for creating typesafe wrapper macros around functions which take
311
 * void *s.
312
 *
313
 * @param[in] _type The base type of the variable (should not be marked const)
314
 * @param[in] _var  to check.
315
 */
316
#define IS_TYPE(_type, _var) \
317
  _Generic((_var), \
318
     _type: _var, \
319
     const _type: _var \
320
  )
321
/*
322
 *  Mark variables as unused
323
 */
324
#define UNUSED_VAR(_x) ((void)_x)
325
326
/** Pad _x to the next multiple of _y
327
 *
328
 */
329
#define PAD(_x, _y)   (_y - ((_x) % _y))
330
331
/** Should be placed before the function return type
332
 *
333
 */
334
#define NEVER_RETURNS   _Noreturn
335
#define HIDDEN      CC_HINT(visibility("hidden"))
336
#define UNUSED      CC_HINT(unused)
337
338
/** clang 10 doesn't recognised the FALL-THROUGH comment anymore
339
 */
340
#if (defined(__clang__) && (__clang_major__ >= 10)) || (defined(__GNUC__) && __GNUC__ >= 7)
341
17.6k
#  define FALL_THROUGH    CC_HINT(fallthrough)
342
#else
343
#  define FALL_THROUGH    ((void)0)
344
#endif
345
346
#ifndef NDEBUG
347
#  define NDEBUG_UNUSED
348
#else
349
#  define NDEBUG_UNUSED   UNUSED
350
#endif
351
352
#define BLANK_FORMAT    " " /* GCC_LINT whines about empty formats */
353
354
/*
355
 *  struct field size
356
 */
357
#define SIZEOF_MEMBER(_t, _m) sizeof(((_t *)0)->_m)
358
53.0k
#define NUM_ELEMENTS(_t) (sizeof((_t)) / sizeof((_t)[0]))
359
360
/*
361
 *  For use with multidimensional arrays where
362
 *  the deeper array element has a size smaller than
363
 *  a pointer i.e. char foo[n][m]
364
 */
365
#define NUM_PTR_ELEMENTS(_t) (sizeof((_t)) / sizeof(void *))
366
367
/*
368
 *  Type checking
369
 */
370
371
/** Check if two types are compatible (the C11 way)
372
 *
373
 * Expands to 1 if types are compatible, else 0.
374
 *
375
 * @param[in] _x pointer to check.
376
 * @param[in] _t type to check compatibility with.
377
 */
378
#define IS_COMPATIBLE(_x, _t) _Generic(_x, _t:1, default: 0)
379
380
/** Check if a field in a struct is compatible (the C11 way)
381
 *
382
 * Expands to 1 if types are compatible, else 0.
383
 *
384
 * @param[in] _s struct to check.
385
 * @param[in] _f field in struct.
386
 * @param[in] _t type to check compatibility with.
387
 */
388
#define IS_FIELD_COMPATIBLE(_s, _f, _t) _Generic(((_s *)0)->_f, _t:1, default: 0)
389
390
/*
391
 *  Only use GCC __attribute__ if were building with a GCClike
392
 *  compiler.
393
 */
394
#ifdef __GNUC__
395
17.6k
#  define CC_HINT(...)    __attribute__((__VA_ARGS__))
396
46.0M
#  define likely(_x)    __builtin_expect((_x), 1)
397
419M
#  define unlikely(_x)    __builtin_expect((_x), 0)
398
#  define unpredictable(_x) __builtin_unpredictable((_x))
399
#  ifdef __clang__
400
#    define assume(_x)            __builtin_assume(_x)
401
#  else
402
#    define assume(_x)    do { if (!_x) __builtin_unreachable(); } while (0)
403
#  endif
404
#else
405
#  define CC_HINT(...)
406
#  define likely(_x) _x
407
#  define unlikely(_x) _x
408
#  define unpredictable(_x) _x
409
#  define assume(_x)
410
#endif
411
412
/*
413
 *  GNU version check
414
 */
415
#ifdef __GNUC__
416
  #ifndef __GNUC_PREREQ__
417
    #define __GNUC_PREREQ__(x, y)           \
418
  ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) ||      \
419
   (__GNUC__ > (x)))
420
  #endif
421
#else
422
  #define __GNUC_PREREQ__(x, y) 0
423
#endif
424
425
426
/*
427
 *  Macros to add pragmas
428
 */
429
#define PRAGMA(_x) _Pragma(#_x)
430
431
/*
432
 *  Handle acquire/release macros
433
 */
434
#if defined(__clang__) && (__clang_major__ >= 13)
435
#  define CC_ACQUIRE_HANDLE(_tag) CC_HINT(acquire_handle(_tag))
436
#  define CC_USE_HANDLE(_tag) CC_HINT(use_handle(_tag))
437
#  define CC_RELEASE_HANDLE(_tag) CC_HINT(release_handle(_tag))
438
#else
439
#  define CC_ACQUIRE_HANDLE(_tag)
440
#  define CC_USE_HANDLE(_tag)
441
#  define CC_RELEASE_HANDLE(_tag)
442
#endif
443
444
/*
445
 *      Disable various forms of ubsan
446
 */
447
#ifndef __has_feature
448
#  define __has_feature(_x) 0
449
#endif
450
#if defined(__clang__) && __has_feature(undefined_behavior_sanitizer)
451
#  define CC_NO_UBSAN(_sanitize)        __attribute__((no_sanitize(STRINGIFY(_sanitize))))
452
#elif __GNUC_PREREQ__(4, 9) && defined(__SANITIZE_UNDEFINED__)
453
#  define CC_NO_UBSAN(_sanitize)        __attribute__((no_sanitize_undefined))
454
#else
455
#  define CC_NO_UBSAN(_sanitize)
456
#endif
457
458
/*
459
 *  Disable sanitizers for undefined behaviour
460
 */
461
#if defined(__clang__)
462
#  define CC_NO_SANITIZE_UNDEFINED(_what) CC_HINT(no_sanitize(_what))
463
#else
464
#  define CC_NO_SANITIZE_UNDEFINED(_what)
465
#endif
466
467
/*
468
 *  Macros for controlling warnings in GCC >= 4.2 and clang >= 2.8
469
 */
470
#if defined(__clang__) && ((__clang_major__ * 100) + __clang_minor__ >= 208)
471
#  define DIAG_UNKNOWN_PRAGMAS unknown-pragmas
472
#  define DIAG_PRAGMA(_x) PRAGMA(clang diagnostic _x)
473
#  define DIAG_OFF(_x) DIAG_PRAGMA(ignored JOINSTR(-W,_x))
474
#  define DIAG_ON(_x) DIAG_PRAGMA(warning JOINSTR(-W,_x))
475
#  define DIAG_PUSH() DIAG_PRAGMA(push)
476
#  define DIAG_POP() DIAG_PRAGMA(pop)
477
#elif !defined(__clang__) && defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
478
#  define DIAG_UNKNOWN_PRAGMAS pragmas
479
#  define DIAG_PRAGMA(_x) PRAGMA(GCC diagnostic _x)
480
#  define DIAG_OFF(_x) DIAG_PRAGMA(ignored JOINSTR(-W,_x))
481
#  define DIAG_ON(_x)  DIAG_PRAGMA(warning JOINSTR(-W,_x))
482
#  define DIAG_PUSH() DIAG_PRAGMA(push)
483
#  define DIAG_POP() DIAG_PRAGMA(pop)
484
#else
485
#  define DIAG_UNKNOWN_PRAGMAS
486
#  define DIAG_OFF(_x)
487
#  define DIAG_ON(_x)
488
#  define DIAG_PUSH()
489
#  define DIAG_POP()
490
#endif
491
492
/*
493
 *  For dealing with APIs which are only deprecated in OSX (like the OpenSSL API)
494
 */
495
#ifdef __APPLE__
496
#  define USES_APPLE_DEPRECATED_API DIAG_OFF(deprecated-declarations)
497
#  define USES_APPLE_RST DIAG_ON(deprecated-declarations)
498
#else
499
#  define USES_APPLE_DEPRECATED_API
500
#  define USES_APPLE_RST
501
#endif
502
503
#if defined(__GNUC__)
504
/* force inclusion of ident keywords in the face of optimization */
505
#  define RCSID(id) static char const rcsid[] __attribute__ ((used)) = id;
506
#  define RCSIDH(h, id) static char const rcsid_ ## h [] __attribute__ ((used)) = id;
507
#elif defined(__SUNPRO_C)
508
/* put ident keyword into comment section (nicer than gcc way) */
509
#  define RCSID(id) PRAGMA(sun ident id)
510
#  define RCSIDH(h, id) PRAGMA(sun ident id)
511
#else
512
#  define RCSID(id)
513
#  define RCSIDH(h, id)
514
#endif
515
#ifdef __cplusplus
516
}
517
#endif
518
519
/*
520
 *  For closing macros which open a code block e.g. fr_rb_inorder_foreach
521
 */
522
0
#define endforeach }
523
524
/* Explicitly evaluate and ignore an expression
525
 *
526
 * Why this macro?
527
 * 1. gcc will warn about unused return values, even with the traditional cast to void.
528
 * 2. There are cases in which an error case wants to clean up, but the function to
529
 *    clean up itself returns a status. In this context you don't care, but then you
530
 *    have the Scylla of unused return value and the Charybdis of Coverity complaining
531
 *    about an if that doesn't affect control flow. The following evaluates _expr and
532
 *    stores it in a variable marked as unused
533
 * @param _expr   The expression to be evaluated and ignored
534
 * @param _type   The type of the expression
535
 */
536
#define IGNORE(_expr, _type) \
537
0
  do { \
538
0
    _type ignored UNUSED = (_expr); \
539
0
  } while (0)
540
541
/** Force a compilation error if strncpy() is used.
542
 *
543
 */
544
extern char *dont_use_strncpy(char *dst, char const *src, size_t len);
545
#undef strncpy
546
#define strncpy(_dst, _src, _len) dont_use_strncpy()