The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
build.h
Go to the documentation of this file.
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: 1235e2791efab10c56b8bc9685c3cd0c6a367eec $
20 *
21 * @file include/build.h
22 * @brief Source control functions
23 *
24 * @copyright 2013 The FreeRADIUS server project
25 */
26
27#ifdef __cplusplus
28extern "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/** Result of an ordering comparison
104 *
105 * CMP_ERR means the comparison itself failed (corrupt or invalid operand),
106 * not that the operands were unequal. A comparator returning CMP_ERR also
107 * pushes a fr_strerror describing the operand problem.
108 *
109 * CMP_ERR is negative, so sign-test idioms (ret < 0) misread an error as
110 * "less than". Any consumer which can receive CMP_ERR must check for the
111 * value explicitly before interpreting the sign.
112 */
113typedef enum : int8_t {
114 CMP_ERR = INT8_MIN, //!< comparison failed
115 CMP_LT = -1, //!< a < b
116 CMP_EQ = 0, //!< a == b
117 CMP_GT = 1 //!< a > b
119
120/** Evaluates to +1 for a > b, and -1 for a < b
121 */
122#define CMP_PREFER_SMALLER(_a,_b) ((fr_cmp_ret_t)(((_a) > (_b)) - ((_a) < (_b))))
123
124/** Evaluates to -1 for a > b, and +1 for a < b
125 */
126#define CMP_PREFER_LARGER(_a,_b) ((fr_cmp_ret_t)(((_a) < (_b)) - ((_a) > (_b))))
127
128/** Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want _an_ ordering.
129 */
130#define CMP(_a, _b) CMP_PREFER_SMALLER(_a, _b)
131
132/** Return if the comparison is not 0 (is unequal)
133 *
134 * @param[in] _a pointer to first structure.
135 * @param[in] _b pointer to second structure.
136 * @param[in] _field within the structs to compare.
137 * @return The result of the comparison.
138 */
139#define CMP_RETURN(_a, _b, _field) \
140do { \
141 fr_cmp_ret_t _ret = CMP((_a)->_field, (_b)->_field); \
142 if (_ret != 0) return _ret; \
143} while (0)
144
145/** memcmp function which has similar behaviour as strncmp
146 *
147 * @param[in] a First thing to compare.
148 * @param[in] b Second thing to compare.
149 * @param[in] a_len Length of first thing.
150 * @param[in] b_len Length of second thing.
151 * @return
152 * - +1 if a > b
153 * - 0 if a == b
154 * - -1 if a < b
155 */
156static inline fr_cmp_ret_t memcmp_return(void const *a, void const *b, size_t a_len, size_t b_len)
157{
158 size_t cmp_len;
159 fr_cmp_ret_t ret;
160
161 if (!a_len && b_len) return CMP_LT;
162 if (a_len && !b_len) return CMP_GT;
163 if (!a_len && !b_len) return CMP_EQ;
164
165 cmp_len = (a_len < b_len) ? a_len : b_len;
166
167 ret = CMP(memcmp(a, b, cmp_len), 0); /* memcmp() can't be passed a NULL pointer */
168 if (ret != 0) return ret;
169
170 return CMP(a_len, b_len);
171}
172
173/** Return if the contents of the specified field is not identical between the specified structures
174 *
175 * @param[in] _a pointer to first structure.
176 * @param[in] _b pointer to second structure.
177 * @param[in] _field within the structs to compare.
178 * @param[in] _len_field within the structs, specifying the length of the data.
179 * @return The result of the comparison.
180 */
181#define MEMCMP_RETURN(_a, _b, _field, _len_field) \
182do { \
183 fr_cmp_ret_t _ret = memcmp_return((_a)->_field, (_b)->_field, (_a)->_len_field, (_b)->_len_field); \
184 if (_ret != 0) return _ret; \
185} while (0)
186
187/** Return the comparison of two opaque fields of a structure
188 *
189 * @param[in] _a pointer to first structure.
190 * @param[in] _b pointer to second structure.
191 * @param[in] _field within the structs to compare.
192 * @param[in] _len_field within the structs, specifying the length of the data.
193 * @return The result of the comparison.
194 */
195#define MEMCMP_FIELDS(_a, _b, _field, _len_field) \
196 memcmp_return((_a)->_field, (_b)->_field, (_a)->_len_field, (_b)->_len_field)
197
198/** Remove const qualification from a pointer
199 *
200 * @param[in] _type The non-const version of the type.
201 * @param[in] _ptr to de-const.
202 */
203#define UNCONST(_type, _ptr) ((_type)((uintptr_t)(_ptr)))
204
205/** Typeof field
206 *
207 * @param[in] _type struct type containing the field.
208 * @param[in] _field to return the type of.
209 */
210#define typeof_field(_type, _field) __typeof__(((_type *)NULL)->_field)
211
212/** HEX concatenation macros
213 *
214 */
215#ifndef HEXIFY
216# define XHEXIFY4(b1,b2,b3,b4) (0x ## b1 ## b2 ## b3 ## b4)
217# define HEXIFY4(b1,b2,b3,b4) XHEXIFY4(b1, b2, b3, b4)
218
219# define XHEXIFY3(b1,b2,b3) (0x ## b1 ## b2 ## b3)
220# define HEXIFY3(b1,b2,b3) XHEXIFY3(b1, b2, b3)
221
222# define XHEXIFY2(b1,b2) (0x ## b1 ## b2)
223# define HEXIFY2(b1,b2) XHEXIFY2(b1, b2)
224
225# define XHEXIFY(b1) (0x ## b1)
226# define HEXIFY(b1) XHEXIFY(b1)
227#endif
228
229/** The ubiquitous stringify macros
230 *
231 */
232#define XSTRINGIFY(x) #x
233#define STRINGIFY(x) XSTRINGIFY(x)
234#define JOINSTR(x,y) XSTRINGIFY(x ## y)
235
236/** Join two values without stringifying
237 *
238 * Useful for calling different macros based on the output of
239*/
240#define _JOIN(x,y) x ## y
241#define JOIN(x,y) _JOIN(x,y)
242
243/** Helper for initialising arrays of string literals
244 */
245#define L(_str) { _str, sizeof(_str) - 1 }
246
247/** Fill macros for array initialisation
248 */
249#define F1(_idx, _val) [_idx] = _val
250#define F2(_idx, _val) F1(_idx, _val), F1(_idx + 1, _val)
251#define F4(_idx, _val) F2(_idx, _val), F2(_idx + 2, _val)
252#define F8(_idx, _val) F4(_idx, _val), F4(_idx + 4, _val)
253#define F16(_idx, _val) F8(_idx, _val), F8(_idx + 8, _val)
254#define F32(_idx, _val) F16(_idx, _val), F16(_idx + 16, _val)
255#define F64(_idx, _val) F32(_idx, _val), F32(_idx + 32, _val)
256#define F128(_idx, _val) F64(_idx, _val), F64(_idx + 64, _val)
257#define F256(_idx, _val) F128(_idx, _val), F128(_idx + 128, _val)
258
259/** Variadic macro framework
260 */
261
262/**
263 * The VA_NARG macro evaluates to the number of arguments that have been
264 * passed to it.
265 *
266 * Laurent Deniau, "__VA_NARG__," 17 January 2006, <comp.std.c> (29 November 2007).
267 */
268#define VA_ARG_N( \
269 _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
270 _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
271 _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
272 _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
273 _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
274 _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
275 _61,_62,_63,N,...) N
276
277#define VA_RSEQ_N() \
278 63,62,61,60, \
279 59,58,57,56,55,54,53,52,51,50, \
280 49,48,47,46,45,44,43,42,41,40, \
281 39,38,37,36,35,34,33,32,31,30, \
282 29,28,27,26,25,24,23,22,21,20, \
283 19,18,17,16,15,14,13,12,11,10, \
284 9,8,7,6,5,4,3,2,1,0
285
286#define _VA_NARG(...) VA_ARG_N(__VA_ARGS__)
287
288/** Return the number of variadic arguments up to 64
289 *
290 * @param[in] ... Variadic arguments to count.
291 */
292#define VA_NARG(...) _VA_NARG(__VA_ARGS__, VA_RSEQ_N())
293
294/** Rescan an argument list enough times for VA_FOR_EACH to unroll 256 elements
295 *
296 * Each level rescans four times. Four levels give 4^4 rescans, and the
297 * preprocessor performs one step of the VA_FOR_EACH recursion per rescan.
298 */
299#define _VA_EXPAND(...) _VA_EXPAND4(_VA_EXPAND4(_VA_EXPAND4(_VA_EXPAND4(__VA_ARGS__))))
300#define _VA_EXPAND4(...) _VA_EXPAND3(_VA_EXPAND3(_VA_EXPAND3(_VA_EXPAND3(__VA_ARGS__))))
301#define _VA_EXPAND3(...) _VA_EXPAND2(_VA_EXPAND2(_VA_EXPAND2(_VA_EXPAND2(__VA_ARGS__))))
302#define _VA_EXPAND2(...) _VA_EXPAND1(_VA_EXPAND1(_VA_EXPAND1(_VA_EXPAND1(__VA_ARGS__))))
303#define _VA_EXPAND1(...) __VA_ARGS__
304
305/** Empty parentheses, applied to a deferred macro name on the next rescan
306 */
307#define _VA_PARENS ()
308
309/** Apply a macro to each variadic argument, producing a comma separated list
310 *
311 * VA_FOR_EACH(F, a, b, c) expands to F(a), F(b), F(c). With no variadic
312 * arguments the macro expands to nothing.
313 *
314 * Each step writes the helper's name next to _VA_PARENS instead of calling
315 * the helper. A macro may not expand itself. The deferred call is what
316 * lets the next rescan perform the next step. __VA_OPT__ ends the recursion
317 * when the list is exhausted. _VA_EXPAND supplies the rescans that drive the
318 * steps, which caps the list at 256 elements.
319 *
320 * @param[in] _macro Macro to apply. Takes one argument.
321 * @param[in] ... Variadic arguments to apply the macro to.
322 */
323#define VA_FOR_EACH(_macro, ...) \
324 __VA_OPT__(_VA_EXPAND(_VA_FOR_EACH(_macro, __VA_ARGS__)))
325#define _VA_FOR_EACH(_macro, _a, ...) \
326 _macro(_a) __VA_OPT__(, _VA_FOR_EACH_AGAIN _VA_PARENS (_macro, __VA_ARGS__))
327#define _VA_FOR_EACH_AGAIN() _VA_FOR_EACH
328
329/** Apply a two argument macro to each variadic argument, with a fixed first argument
330 *
331 * VA_FOR_EACH_ARG(F, x, a, b) expands to F(x, a), F(x, b). See VA_FOR_EACH
332 * for the mechanism and the 256 element cap.
333 *
334 * @param[in] _macro Macro to apply. Takes two arguments.
335 * @param[in] _arg Passed as the first argument on every application.
336 * @param[in] ... Variadic arguments to apply the macro to.
337 */
338#define VA_FOR_EACH_ARG(_macro, _arg, ...) \
339 __VA_OPT__(_VA_EXPAND(_VA_FOR_EACH_ARG(_macro, _arg, __VA_ARGS__)))
340#define _VA_FOR_EACH_ARG(_macro, _arg, _a, ...) \
341 _macro(_arg, _a) __VA_OPT__(, _VA_FOR_EACH_ARG_AGAIN _VA_PARENS (_macro, _arg, __VA_ARGS__))
342#define _VA_FOR_EACH_ARG_AGAIN() _VA_FOR_EACH_ARG
343
344#define _VA_STRINGIFY_ONE(_a) #_a
345
346/** Produce a comma separated list of string literals, one per variadic argument
347 *
348 * Each argument becomes the source text the caller wrote.
349 * VA_STRINGIFY(request->reply, len + 1) expands to "request->reply", "len + 1".
350 * Expansion is limited to 256 arguments by VA_FOR_EACH.
351 *
352 * @param[in] ... Variadic arguments to stringify.
353 */
354#define VA_STRINGIFY(...) VA_FOR_EACH(_VA_STRINGIFY_ONE, __VA_ARGS__)
355
356
357/** Pass caller information to the function
358 *
359 */
360#ifndef NDEBUG
361# define NDEBUG_LOCATION_ARGS char const *file, int line,
362# define NDEBUG_LOCATION_VALS file, line,
363# define NDEBUG_LOCATION_FMT "%s[%d]: "
364# define NDEBUG_LOCATION_EXP __FILE__, __LINE__,
365# define NDEBUG_LOCATION_NONNULL(_num) ((_num) + 2)
366#else
367# define NDEBUG_LOCATION_ARGS
368# define NDEBUG_LOCATION_VALS
369# define NDEBUG_LOCATION_FMT ""
370# define NDEBUG_LOCATION_EXP
371# define NDEBUG_LOCATION_NONNULL(_num) (_num)
372#endif
373
374/** Check if a given variable is the _const or not
375 *
376 * @param[in] _type The base type of the variable (should not be marked const)
377 * @param[in] _var to check.
378 */
379#define IS_CONST(_type, _var) \
380 _Generic((_var), \
381 _type: false, \
382 const _type: true \
383 )
384
385/** Check if a given variable is the const or unconst version of a type
386 *
387 * Expands to _var if _var matches type, otherwise throws a compiler error.
388 *
389 * Useful for creating typesafe wrapper macros around functions which take
390 * void *s.
391 *
392 * @param[in] _type The base type of the variable (should not be marked const)
393 * @param[in] _var to check.
394 */
395#define IS_TYPE(_type, _var) \
396 _Generic((_var), \
397 _type: _var, \
398 const _type: _var \
399 )
400/*
401 * Mark variables as unused
402 */
403#define UNUSED_VAR(_x) ((void)_x)
404
405/** Pad _x to the next multiple of _y
406 *
407 */
408#define PAD(_x, _y) (_y - ((_x) % _y))
409
410/** Should be placed before the function return type
411 *
412 */
413#define NEVER_RETURNS _Noreturn
414#define HIDDEN CC_HINT(visibility("hidden"))
415#define UNUSED CC_HINT(unused)
416
417/** clang 10 doesn't recognised the FALL-THROUGH comment anymore
418 */
419#if (defined(__clang__) && (__clang_major__ >= 10)) || (defined(__GNUC__) && __GNUC__ >= 7)
420# define FALL_THROUGH CC_HINT(fallthrough)
421#else
422# define FALL_THROUGH ((void)0)
423#endif
424
425#ifndef NDEBUG
426# define NDEBUG_UNUSED
427#else
428# define NDEBUG_UNUSED UNUSED
429#endif
430
431#define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */
432
433/*
434 * struct field size
435 */
436#define SIZEOF_MEMBER(_t, _m) sizeof(((_t *)0)->_m)
437#define NUM_ELEMENTS(_t) (sizeof((_t)) / sizeof((_t)[0]))
438
439/*
440 * For use with multidimensional arrays where
441 * the deeper array element has a size smaller than
442 * a pointer i.e. char foo[n][m]
443 */
444#define NUM_PTR_ELEMENTS(_t) (sizeof((_t)) / sizeof(void *))
445
446/*
447 * Type checking
448 */
449
450/** Check if two types are compatible (the C11 way)
451 *
452 * Expands to 1 if types are compatible, else 0.
453 *
454 * @param[in] _x pointer to check.
455 * @param[in] _t type to check compatibility with.
456 */
457#define IS_COMPATIBLE(_x, _t) _Generic(_x, _t:1, default: 0)
458
459/** Check if a field in a struct is compatible (the C11 way)
460 *
461 * Expands to 1 if types are compatible, else 0.
462 *
463 * @param[in] _s struct to check.
464 * @param[in] _f field in struct.
465 * @param[in] _t type to check compatibility with.
466 */
467#define IS_FIELD_COMPATIBLE(_s, _f, _t) _Generic(((_s *)0)->_f, _t:1, default: 0)
468
469/*
470 * Only use GCC __attribute__ if were building with a GCClike
471 * compiler.
472 */
473#ifdef __GNUC__
474# define CC_HINT(...) __attribute__((__VA_ARGS__))
475# define likely(_x) __builtin_expect((_x), 1)
476# define unlikely(_x) __builtin_expect((_x), 0)
477# define unpredictable(_x) __builtin_unpredictable((_x))
478# ifdef __clang__
479# define assume(_x) __builtin_assume(_x)
480# else
481# define assume(_x) do { if (!_x) __builtin_unreachable(); } while (0)
482# endif
483#else
484# define CC_HINT(...)
485# define likely(_x) _x
486# define unlikely(_x) _x
487# define unpredictable(_x) _x
488# define assume(_x)
489#endif
490
491/*
492 * GNU version check
493 */
494#ifdef __GNUC__
495 #ifndef __GNUC_PREREQ__
496 #define __GNUC_PREREQ__(x, y) \
497 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
498 (__GNUC__ > (x)))
499 #endif
500#else
501 #define __GNUC_PREREQ__(x, y) 0
502#endif
503
504
505/*
506 * Macros to add pragmas
507 */
508#define PRAGMA(_x) _Pragma(#_x)
509
510/*
511 * Handle acquire/release macros
512 */
513#if defined(__clang__) && (__clang_major__ >= 13)
514# define CC_ACQUIRE_HANDLE(_tag) CC_HINT(acquire_handle(_tag))
515# define CC_USE_HANDLE(_tag) CC_HINT(use_handle(_tag))
516# define CC_RELEASE_HANDLE(_tag) CC_HINT(release_handle(_tag))
517#else
518# define CC_ACQUIRE_HANDLE(_tag)
519# define CC_USE_HANDLE(_tag)
520# define CC_RELEASE_HANDLE(_tag)
521#endif
522
523/*
524 * Disable various forms of ubsan
525 */
526#ifndef __has_feature
527# define __has_feature(_x) 0
528#endif
529#if defined(__clang__) && __has_feature(undefined_behavior_sanitizer)
530# define CC_NO_UBSAN(_sanitize) __attribute__((no_sanitize(STRINGIFY(_sanitize))))
531#elif __GNUC_PREREQ__(4, 9) && defined(__SANITIZE_UNDEFINED__)
532# define CC_NO_UBSAN(_sanitize) __attribute__((no_sanitize_undefined))
533#else
534# define CC_NO_UBSAN(_sanitize)
535#endif
536
537/*
538 * Disable sanitizers for undefined behaviour
539 */
540#if defined(__clang__)
541# define CC_NO_SANITIZE_UNDEFINED(_what) CC_HINT(no_sanitize(_what))
542#else
543# define CC_NO_SANITIZE_UNDEFINED(_what)
544#endif
545
546/*
547 * Macros for controlling warnings in GCC >= 4.2 and clang >= 2.8
548 *
549 * A compiler warns about a diagnostic name which the compiler does
550 * not implement (-Wunknown-warning-option in clang, -Wpragmas in
551 * GCC). For a diagnostic which only some compilers implement, such
552 * as a clang-only diagnostic, use DIAG_OFF_OPTIONAL() and
553 * DIAG_ON_OPTIONAL(). DIAG_OFF_OPTIONAL() and DIAG_ON_OPTIONAL()
554 * ignore the unknown name diagnostic while changing the specified
555 * diagnostic, then set the unknown name diagnostic to produce a
556 * warning rather than restoring the earlier state.
557 */
558#if defined(__clang__) && ((__clang_major__ * 100) + __clang_minor__ >= 208)
559# define DIAG_PRAGMA(_x) PRAGMA(clang diagnostic _x)
560# define DIAG_OFF(_x) DIAG_PRAGMA(ignored JOINSTR(-W,_x))
561# define DIAG_ON(_x) DIAG_PRAGMA(warning JOINSTR(-W,_x))
562# define DIAG_OFF_OPTIONAL(_x) DIAG_OFF(unknown-warning-option) DIAG_OFF(_x) DIAG_ON(unknown-warning-option)
563# define DIAG_ON_OPTIONAL(_x) DIAG_OFF(unknown-warning-option) DIAG_ON(_x) DIAG_ON(unknown-warning-option)
564# define DIAG_PUSH() DIAG_PRAGMA(push)
565# define DIAG_POP() DIAG_PRAGMA(pop)
566#elif !defined(__clang__) && defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
567# define DIAG_PRAGMA(_x) PRAGMA(GCC diagnostic _x)
568# define DIAG_OFF(_x) DIAG_PRAGMA(ignored JOINSTR(-W,_x))
569# define DIAG_ON(_x) DIAG_PRAGMA(warning JOINSTR(-W,_x))
570# define DIAG_OFF_OPTIONAL(_x) DIAG_OFF(pragmas) DIAG_OFF(_x) DIAG_ON(pragmas)
571# define DIAG_ON_OPTIONAL(_x) DIAG_OFF(pragmas) DIAG_ON(_x) DIAG_ON(pragmas)
572# define DIAG_PUSH() DIAG_PRAGMA(push)
573# define DIAG_POP() DIAG_PRAGMA(pop)
574#else
575# define DIAG_OFF(_x)
576# define DIAG_ON(_x)
577# define DIAG_OFF_OPTIONAL(_x)
578# define DIAG_ON_OPTIONAL(_x)
579# define DIAG_PUSH()
580# define DIAG_POP()
581#endif
582
583/*
584 * For dealing with APIs which are only deprecated in OSX (like the OpenSSL API)
585 */
586#ifdef __APPLE__
587# define USES_APPLE_DEPRECATED_API DIAG_OFF(deprecated-declarations)
588# define USES_APPLE_RST DIAG_ON(deprecated-declarations)
589#else
590# define USES_APPLE_DEPRECATED_API
591# define USES_APPLE_RST
592#endif
593
594#if defined(__GNUC__)
595/* force inclusion of ident keywords in the face of optimization */
596# define RCSID(id) static char const rcsid[] __attribute__ ((used)) = id;
597# define RCSIDH(h, id) static char const rcsid_ ## h [] __attribute__ ((used)) = id;
598#elif defined(__SUNPRO_C)
599/* put ident keyword into comment section (nicer than gcc way) */
600# define RCSID(id) PRAGMA(sun ident id)
601# define RCSIDH(h, id) PRAGMA(sun ident id)
602#else
603# define RCSID(id)
604# define RCSIDH(h, id)
605#endif
606#ifdef __cplusplus
607}
608#endif
609
610/*
611 * For closing macros which open a code block e.g. fr_rb_inorder_foreach
612 */
613#define endforeach }
614
615/* Explicitly evaluate and ignore an expression
616 *
617 * Why this macro?
618 * 1. gcc will warn about unused return values, even with the traditional cast to void.
619 * 2. There are cases in which an error case wants to clean up, but the function to
620 * clean up itself returns a status. In this context you don't care, but then you
621 * have the Scylla of unused return value and the Charybdis of Coverity complaining
622 * about an if that doesn't affect control flow. The following evaluates _expr and
623 * stores it in a variable marked as unused
624 * @param _expr The expression to be evaluated and ignored
625 * @param _type The type of the expression
626 */
627#define IGNORE(_expr, _type) \
628 do { \
629 _type ignored UNUSED = (_expr); \
630 } while (0)
631
632/** Force a compilation error if strncpy() is used.
633 *
634 */
635extern char *dont_use_strncpy(char *dst, char const *src, size_t len);
636#undef strncpy
637#define strncpy(_dst, _src, _len) dont_use_strncpy()
static fr_cmp_ret_t memcmp_return(void const *a, void const *b, size_t a_len, size_t b_len)
memcmp function which has similar behaviour as strncmp
Definition build.h:156
char * dont_use_strncpy(char *dst, char const *src, size_t len)
Force a compilation error if strncpy() is used.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:130
fr_cmp_ret_t
Result of an ordering comparison.
Definition build.h:113
@ CMP_GT
a > b
Definition build.h:117
@ CMP_LT
a < b
Definition build.h:115
@ CMP_ERR
comparison failed
Definition build.h:114
@ CMP_EQ
a == b
Definition build.h:116
static fr_sbuff_err_t char size_t * len
Definition value.h:1061