summaryrefslogtreecommitdiff
path: root/3rdparty/plibsys/src/pstdarg.h
blob: bd12f8ae638d6a29f77e334c18b4e8ac9eb0ffc1 (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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*
 * The MIT License
 *
 * Copyright (C) 2017 Jean-Damien Durand <jeandamiendurand@free.fr>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * 'Software'), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @file pstdarg.h
 * @brief Variable arguments
 * @author Jean-Damien Durand
 *
 * Functions declared with a variable number of arguments use macros to step
 * through them.
 *
 * The #p_va_list type must be declared in such function, #p_va_start,
 * #p_va_arg and #p_va_end are used to initialize, to step through and to end
 * the navigation, respectively.
 *
 * A variable number of arguments can be propagated to another function which
 * accepts a #p_va_list parameter, using #p_va_copy.
 *
 * Any use of #p_va_start or #p_va_copy must have a corresponding #p_va_end.
 *
 * Using a variable number of parameters requires a known-in-advance contract
 * between the caller and the callee on the number of parameters and their types.
 * Note, that this mechanism is a weakly typed: the compiler will always apply
 * default type promotion, regardless if you explicitely typecast an argument in
 * the stack, i.e.:
 * - Integer arguments of types lower than #pint are always promoted to #pint,
 *   or #puint if #pint is not enough.
 * - Arguments of type @a float are always promoted to @a double.
 * - Arrays are always promoted to pointers.
 *
 * You need to be very careful when using variable arguments. Improper usage may
 * lead to program crash. In order to avoid type casting mistakes, consider
 * using macros for variable arguments with explicit type casting provided below.
 * Though you still can use #p_va_arg if you know what are you doing.
 *
 * Please note, that stdarg.h implementation is not compatible with varargs.h,
 * and only one of them should be used in a compilation unit. You must be sure
 * that you don't use varargs.h along with the current implmenetation, otherwise
 * runtime failures are inevitable.
 */

#if !defined (PLIBSYS_H_INSIDE) && !defined (PLIBSYS_COMPILATION)
#  error "Header files shouldn't be included directly, consider using <plibsys.h> instead."
#endif

#ifndef PLIBSYS_HEADER_PSTDARG_H
#define PLIBSYS_HEADER_PSTDARG_H

#include <pmacros.h>
#include <ptypes.h>

#include <stdio.h>
#include <stdarg.h>
#ifndef PLIBSYS_VA_COPY
#  include <string.h>
#endif

/**
 * @brief Opaque type holding variable number of arguments navigation.
 * @since 0.0.4
 */
#define p_va_list va_list

/**
 * @brief Initializes navigation through a variable number of arguments.
 * @param ap Declared object of type #p_va_list.
 * @param last Name of the last argument before @a ap.
 * @since 0.0.4
 * @note There must be a corresponding call to #p_va_end(ap) afterwards.
 */
#define p_va_start(ap, last) va_start(ap, last)

/**
 * @brief Gets the next argument in the list.
 * @param ap Declared object of type va_list, previously initalized with
 * #p_va_start.
 * @param type Type of the next argument.
 * @return Value of the next argument.
 * @since 0.0.4
 */

#define p_va_arg(ap, type) (type) va_arg(ap, type)

/**
 * @brief Ends the navigation.
 * @param ap Declared object of type #p_va_list.
 * @since 0.0.4
 * @note There must be a corresponding call to #p_va_start(ap) before.
 */
#define p_va_end(ap) va_end(ap)

/**
 * @brief Copies a navigation object.
 * @param dst Destination object of type #p_va_list.
 * @param src Source object of type #p_va_list.
 * @since 0.0.4
 * @note The state of @a src is copied as well, @a dst is initialized as if
 * #p_va_start(dst) would have been called. There must be a corresponding call
 * to #p_va_end(dst) afterwards.
 */
#ifdef PLIBSYS_VA_COPY
#  define p_va_copy(dst, src) PLIBSYS_VA_COPY(dst, src)
#else
#  define p_va_copy(dst, src) ((void) memcpy (&(dst), &(src), sizeof (va_list)))
#endif

/**
 * @def pint8_va_arg
 * @brief Unstacks a #pint8 variable.
 * @param ap #p_va_list stack.
 * @return #pint8 value.
 * @since 0.0.4
 */
#define pint8_va_arg(ap)		((pint8) p_va_arg(ap, pint))

/**
 * @def puint8_va_arg
 * @brief Unstacks a #puint8 variable.
 * @param ap #p_va_list stack.
 * @return #puint8 value.
 * @since 0.0.4
 */
#define puint8_va_arg(ap)		((puint8) p_va_arg(ap, puint))

/**
 * @def pint16_va_arg
 * @brief Unstacks a #pint16 variable.
 * @param ap #p_va_list stack.
 * @return #pint16 value.
 * @since 0.0.4
 */
#define pint16_va_arg(ap)		((pint16) p_va_arg(ap, pint))

/**
 * @def puint16_va_arg
 * @brief Unstacks a #puint16 variable.
 * @param ap #p_va_list stack.
 * @return #puint16 value.
 * @since 0.0.4
 */
#define puint16_va_arg(ap)		((puint16) p_va_arg(ap, puint))

/**
 * @def pint32_va_arg
 * @brief Unstacks a #pint32 variable.
 * @param ap #p_va_list stack.
 * @return #pint32 value.
 * @since 0.0.4
 */
#define pint32_va_arg(ap)		((pint32) p_va_arg(ap, pint))

/**
 * @def puint32_va_arg
 * @brief Unstacks a #puint32 variable.
 * @param ap #p_va_list stack.
 * @return #puint32 value.
 * @since 0.0.4
 */
#define puint32_va_arg(ap)		((puint32) p_va_arg(ap, puint))

/**
 * @def pint64_va_arg
 * @brief Unstacks a #pint64 variable.
 * @param ap #p_va_list stack.
 * @return #pint64 value.
 * @since 0.0.4
 */
#define pint64_va_arg(ap)		(p_va_arg(ap, pint64))

/**
 * @def puint64_va_arg
 * @brief Unstacks a #puint64 variable.
 * @param ap #p_va_list stack.
 * @return #puint64 value.
 * @since 0.0.4
 */
#define puint64_va_arg(ap)		(p_va_arg(ap, puint64))

/**
 * @def ppointer_va_arg
 * @brief Unstacks a #ppointer variable.
 * @param ap #p_va_list stack.
 * @return #ppointer value.
 * @since 0.0.4
 */
#define ppointer_va_arg(ap)		(p_va_arg(ap, ppointer))

/**
 * @def pconstpointer_va_arg
 * @brief Unstacks a #pconstpointer variable.
 * @param ap #p_va_list stack.
 * @return #pconstpointer value.
 * @since 0.0.4
 */
#define pconstpointer_va_arg(ap)	(p_va_arg(ap, pconstpointer))

/**
 * @def pboolean_va_arg
 * @brief Unstacks a #pboolean variable.
 * @param ap #p_va_list stack.
 * @return #pboolean value.
 * @since 0.0.4
 */
#define pboolean_va_arg(ap)		((pboolean) p_va_arg(ap, pint))

/**
 * @def pchar_va_arg
 * @brief Unstacks a #pchar variable.
 * @param ap #p_va_list stack.
 * @return #pchar value.
 * @since 0.0.4
 */
#define pchar_va_arg(ap)		((pchar) p_va_arg(ap, pint))

/**
 * @def pshort_va_arg
 * @brief Unstacks a #pshort variable.
 * @param ap #p_va_list stack.
 * @return #pshort value.
 * @since 0.0.4
 */
#define pshort_va_arg(ap)		((pshort) p_va_arg(ap, pint))

/**
 * @def pint_va_arg
 * @brief Unstacks a #pint variable.
 * @param ap #p_va_list stack.
 * @return #pint value.
 * @since 0.0.4
 */
#define pint_va_arg(ap)			(p_va_arg(ap, pint))

/**
 * @def plong_va_arg
 * @brief Unstacks a #plong variable.
 * @param ap #p_va_list stack.
 * @return #plong value.
 * @since 0.0.4
 */
#define plong_va_arg(ap)		(p_va_arg(ap, plong))

/**
 * @def puchar_va_arg
 * @brief Unstacks a #puchar variable.
 * @param ap #p_va_list stack.
 * @return #puchar value.
 * @since 0.0.4
 */
#define puchar_va_arg(ap)		((puchar) p_va_arg(ap, puint))

/**
 * @def pushort_va_arg
 * @brief Unstacks a #pushort variable.
 * @param ap #p_va_list stack.
 * @return #pushort value.
 * @since 0.0.4
 */
#define pushort_va_arg(ap)		((pushort) p_va_arg(ap, puint))

/**
 * @def puint_va_arg
 * @brief Unstacks a #puint variable.
 * @param ap #p_va_list stack.
 * @return #puint value.
 * @since 0.0.4
 */
#define puint_va_arg(ap)		(p_va_arg(ap, puint))

/**
 * @def pulong_va_arg
 * @brief Unstacks a #pulong variable.
 * @param ap #p_va_list stack.
 * @return #pulong value.
 * @since 0.0.4
 */
#define pulong_va_arg(ap)		(p_va_arg(ap, pulong))

/**
 * @def pfloat_va_arg
 * @brief Unstacks a #pfloat variable.
 * @param ap #p_va_list stack.
 * @return #pfloat value.
 * @since 0.0.4
 */
#define pfloat_va_arg(ap)		((pfloat) p_va_arg(ap, pdouble))

/**
 * @def pdouble_va_arg
 * @brief Unstacks a #pdouble variable.
 * @param ap #p_va_list stack.
 * @return #pdouble value.
 * @since 0.0.4
 */
#define pdouble_va_arg(ap)		(p_va_arg(ap, pdouble))

#endif /* PLIBSYS_HEADER_PSTDARG_H */