summaryrefslogtreecommitdiffstats
path: root/lib/dpkg/macros.h
blob: 72d2143e6e0d16f62ccd090ab7a0032d5b0ea479 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
 * libdpkg - Debian packaging suite library routines
 * macros.h - C language support macros
 *
 * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef LIBDPKG_MACROS_H
#define LIBDPKG_MACROS_H

/**
 * @defgroup macros C language support macros
 * @ingroup dpkg-public
 * @{
 */

#ifndef LIBDPKG_VOLATILE_API
#error "The libdpkg API is to be considered volatile, please read 'README.api'."
#endif

/* Language definitions. */

/* Supported since gcc 5.1.0 and clang 2.9.0. For attributes that appeared
 * before these versions, in addition we need to do version checks.  */
#ifndef __has_attribute
#define __has_attribute(x)	0
#endif

#ifdef __GNUC__
#define DPKG_GCC_VERSION (__GNUC__ << 8 | __GNUC_MINOR__)
#else
#define DPKG_GCC_VERSION 0
#endif

#if DPKG_GCC_VERSION >= 0x0300 || __has_attribute(__unused__)
#define DPKG_ATTR_UNUSED	__attribute__((__unused__))
#else
#define DPKG_ATTR_UNUSED
#endif

#if DPKG_GCC_VERSION >= 0x0300 || __has_attribute(__const__)
#define DPKG_ATTR_CONST		__attribute__((__const__))
#else
#define DPKG_ATTR_CONST
#endif

#if DPKG_GCC_VERSION >= 0x0300 || __has_attribute(__pure__)
#define DPKG_ATTR_PURE		__attribute__((__pure__))
#else
#define DPKG_ATTR_PURE
#endif

#if DPKG_GCC_VERSION >= 0x0300 || __has_attribute(__malloc__)
#define DPKG_ATTR_MALLOC	__attribute__((__malloc__))
#else
#define DPKG_ATTR_MALLOC
#endif

#if DPKG_GCC_VERSION >= 0x0300 || __has_attribute(__noreturn__)
#define DPKG_ATTR_NORET		__attribute__((__noreturn__))
#else
#define DPKG_ATTR_NORET
#endif

#if DPKG_GCC_VERSION >= 0x0300 || __has_attribute(__format__)
#define DPKG_ATTR_FMT(t, f, a)	__attribute__((__format__(t, f, a)))
#define DPKG_ATTR_PRINTF(n)	DPKG_ATTR_FMT(__printf__, n, n + 1)
#define DPKG_ATTR_VPRINTF(n)	DPKG_ATTR_FMT(__printf__, n, 0)
#else
#define DPKG_ATTR_FMT(t, f, a)
#define DPKG_ATTR_PRINTF(n)
#define DPKG_ATTR_VPRINTF(n)
#endif

#if DPKG_GCC_VERSION > 0x0302 || __has_attribute(__nonnull__)
#define DPKG_ATTR_NONNULL(...)	__attribute__((__nonnull__(__VA_ARGS__)))
#else
#define DPKG_ATTR_NONNULL(...)
#endif

#if DPKG_GCC_VERSION > 0x0302 || __has_attribute(__warn_unused_result__)
#define DPKG_ATTR_REQRET	__attribute__((__warn_unused_result__))
#else
#define DPKG_ATTR_REQRET
#endif

#if DPKG_GCC_VERSION >= 0x0400 || __has_attribute(__sentinel__)
#define DPKG_ATTR_SENTINEL	__attribute__((__sentinel__))
#else
#define DPKG_ATTR_SENTINEL
#endif

#if DPKG_GCC_VERSION >= 0x0801 || __has_attribute(__nonstring__)
#define DPKG_ATTR_NONSTRING	__attribute__((__nonstring__))
#else
#define DPKG_ATTR_NONSTRING
#endif

#if defined(__cplusplus) && __cplusplus >= 201103L
#define DPKG_ATTR_THROW(exception)
#define DPKG_ATTR_NOEXCEPT		noexcept
#elif defined(__cplusplus)
#define DPKG_ATTR_THROW(exception)	throw(exception)
#define DPKG_ATTR_NOEXCEPT		throw()
#endif

#ifdef __cplusplus
#define DPKG_BEGIN_DECLS	extern "C" {
#define DPKG_END_DECLS		}
#else
#define DPKG_BEGIN_DECLS
#define DPKG_END_DECLS
#endif

/**
 * @def DPKG_NULL
 *
 * A null pointer constant that works on C or C++.
 *
 * To be used only on header files, where having to conditionalize the code
 * to use either NULL or nullptr would be too cumbersome. Non-header files
 * should use the appropriate constant directly.
 */
#if defined(__cplusplus)
#define DPKG_NULL      nullptr
#else
#define DPKG_NULL      NULL
#endif

/**
 * @def DPKG_STATIC_CAST
 *
 * Cast an expression to a given type that works on C or C++.
 *
 * To be used only on header files, where having to conditionalize the code
 * to use either NULL or nullptr would be too cumbersome. Non-header files
 * should use the appropriate constant directly.
 */
#if defined(__cplusplus)
#define DPKG_STATIC_CAST(type, expr) static_cast<type>(expr)
#else
#define DPKG_STATIC_CAST(type, expr) (type)(expr)
#endif

/**
 * @def DPKG_BIT
 *
 * Return the integer value of bit n.
 */
#define DPKG_BIT(n)	(1UL << (n))

/**
 * @def array_count
 *
 * Returns the amount of items in an array.
 */
#ifndef array_count
#define array_count(a) (sizeof(a) / sizeof((a)[0]))
#endif

/* For C++ use native implementations from STL or similar. */
#ifndef __cplusplus
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif

#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#endif

/**
 * @def clamp
 *
 * Returns a normalized value within the low and high limits.
 *
 * @param v The value to clamp.
 * @param l The low limit.
 * @param h The high limit.
 */
/* For C++ use native implementations from STL or similar. */
#ifndef __cplusplus
#ifndef clamp
#define clamp(v, l, h) ((v) > (h) ? (h) : ((v) < (l) ? (l) : (v)))
#endif
#endif

/** @} */

#endif /* LIBDPKG_MACROS_H */