1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #ifndef MPL_BASE_H_INCLUDED
7 #define MPL_BASE_H_INCLUDED
8 
9 /* this file splits off the base functionality in MPL, which does not
10  * depend on any of the exposed features. */
11 
12 #include "mplconfig.h"
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdarg.h>
18 #include <stdint.h>
19 
20 #if defined MPL_HAVE_CTYPE_H
21 #include <ctype.h>
22 #endif /* MPL_HAVE_CTYPE_H */
23 
24 #if defined(MPL_HAVE_INTTYPES_H)
25 #include <inttypes.h>
26 #endif /* MPL_HAVE_INTTYPES_H */
27 
28 #if defined MPL_HAVE_IFADDRS_H
29 #include <ifaddrs.h>
30 #endif /* MPL_HAVE_IFADDRS_H */
31 
32 #if defined MPL_HAVE_ARPA_INET_H
33 #include <arpa/inet.h>
34 #endif /* MPL_HAVE_ARPA_INET_H */
35 
36 #if !defined ATTRIBUTE
37 #if defined MPL_HAVE_GCC_ATTRIBUTE
38 #define ATTRIBUTE(a_) __attribute__(a_)
39 #else /* MPL_HAVE_GCC_ATTRIBUTE */
40 #define ATTRIBUTE(a_)
41 #endif /* MPL_HAVE_GCC_ATTRIBUTE */
42 #endif /* ATTRIBUTE */
43 
44 #define MPL_UNUSED ATTRIBUTE((unused))
45 #ifdef MPL_ENABLE_ALWAYS_INLINE
46 #define MPL_STATIC_INLINE_PREFIX ATTRIBUTE((always_inline)) static inline
47 #define MPL_STATIC_INLINE_SUFFIX ATTRIBUTE((always_inline))
48 #else
49 #define MPL_STATIC_INLINE_PREFIX static inline
50 #define MPL_STATIC_INLINE_SUFFIX
51 #endif
52 
53 #ifdef MPL_HAVE_FUNC_ATTRIBUTE_FALLTHROUGH
54 #define MPL_FALLTHROUGH __attribute__((fallthrough))
55 #else
56 #define MPL_FALLTHROUGH
57 #endif
58 
59 #ifdef MPL_HAVE_VAR_ATTRIBUTE_ALIGNED
60 #define MPL_ATTR_ALIGNED(x) __attribute__((aligned(x)))
61 #else
62 #define MPL_ATTR_ALIGNED(x)
63 #endif
64 
65 #ifdef MPL_HAVE_VAR_ATTRIBUTE_USED
66 #define MPL_USED __attribute__((used))
67 #else
68 #define MPL_USED
69 #endif
70 
71 /* These likely/unlikely macros provide static branch prediction hints to the
72  * compiler, if such hints are available.  Simply wrap the relevant expression in
73  * the macro, like this:
74  *
75  * if (unlikely(ptr == NULL)) {
76  *     // ... some unlikely code path ...
77  * }
78  *
79  * They should be used sparingly, especially in upper-level code.  It's easy to
80  * incorrectly estimate branching likelihood, while the compiler can often do a
81  * decent job if left to its own devices.
82  *
83  * These macros are not namespaced because the namespacing is cumbersome.
84  */
85 #ifdef MPL_HAVE_BUILTIN_EXPECT
86 #define unlikely(x_) __builtin_expect(!!(x_),0)
87 #define likely(x_)   __builtin_expect(!!(x_),1)
88 #else
89 #define unlikely(x_) (x_)
90 #define likely(x_)   (x_)
91 #endif
92 
93 #ifdef MPL_HAVE_C11__STATIC_ASSERT
94 #define MPL_static_assert(cond_,msg_) _Static_assert(cond_,msg_)
95 #else
96 /* A hack:
97     When cond_ is false, result in compile-time duplicated case error.
98     When cond_ is true, compiler should optimize it away.
99     Since it is compile time error, we don't care (much) about how the error message look.
100  */
101 #define MPL_static_assert(cond_,msg_) \
102     do { switch(0) { case 0: case (cond_): default: break; } } while (0)
103 #endif
104 
105 #define MPL_COMPILE_TIME_ASSERT(cond_) MPL_static_assert(cond_, "MPL_COMPILE_TIME_ASSERT failure")
106 
107 #define MPL_QUOTE(A) MPL_QUOTE2(A)
108 #define MPL_QUOTE2(A) #A
109 
110 #define MPL_MAX(a,b)    (((a) > (b)) ? (a) : (b))
111 #define MPL_MIN(a,b)    (((a) < (b)) ? (a) : (b))
112 
113 /* Use this macro for each parameter to a function that is not referenced in
114    the body of the function */
115 #ifdef MPL_HAVE_WINDOWS_H
116 #define MPL_UNREFERENCED_ARG(a) a
117 #else
118 #define MPL_UNREFERENCED_ARG(a)
119 #endif
120 
121 /* macro for finding the enclosing structure of an element */
122 #define MPL_container_of(ptr, type, member) (type *)((char *)(ptr) - offsetof(type,member))
123 
124 /* This macro is used to silence warnings from the Mac OS X linker when
125  * an object file "has no symbols".  The unused attribute prevents a
126  * warning about the unused dummy variable while the used attribute
127  * prevents the compiler from discarding the symbol altogether.  This
128  * macro should be used at the top of any file that might not define any
129  * other variables or functions (perhaps due to conditional compilation
130  * via the preprocessor).  A semicolon is expected after each invocation
131  * of this macro. */
132 #define MPL_SUPPRESS_OSX_HAS_NO_SYMBOLS_WARNING \
133     static int MPL_UNIQUE_SYMBOL_NAME(dummy) ATTRIBUTE((unused)) MPL_USED = 0
134 
135 /* we jump through a couple of extra macro hoops to append the line
136  * number to the variable name in order to reduce the chance of a name
137  * collision with headers that might be included in the translation
138  * unit */
139 #define MPL_UNIQUE_SYMBOL_NAME(prefix_) MPL_UNIQUE_IMPL1_(prefix_##_unique_L,__LINE__)
140 #define MPL_UNIQUE_IMPL1_(prefix_,line_) MPL_UNIQUE_IMPL2_(prefix_,line_)
141 #define MPL_UNIQUE_IMPL2_(prefix_,line_) MPL_UNIQUE_IMPL3_(prefix_,line_)
142 #define MPL_UNIQUE_IMPL3_(prefix_,line_) prefix_##line_
143 
144 #ifdef MPL_HAVE_STDBOOL_H
145 #include <stdbool.h>
146 #else
147 #ifndef MPL_HAVE__BOOL
148 #ifdef __cplusplus
149 typedef bool _Bool;
150 #else
151 #define _Bool signed char
152 #endif
153 #endif
154 #define bool _Bool
155 #define false 0
156 #define true 1
157 #define __bool_true_false_are_defined 1
158 #endif
159 
160 #define MPL_ROUND_UP_ALIGN(a, alignment) (((a) + ((alignment) - 1)) & (~((alignment) - 1)))
161 #define MPL_ROUND_DOWN_ALIGN(a, alignment) ((a) & (~((alignment) - 1)))
162 
163 #endif /* MPL_BASE_H_INCLUDED */
164