P99
p99_generic.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the authors and copyright holders for this work are as follows: */
5 /* (C) copyright 2012-2015 Jens Gustedt, INRIA, France */
6 /* (C) copyright 2012 William Morris */
7 /* */
8 /* This file is free software; it is part of the P99 project. */
9 /* */
10 /* Licensed under the Apache License, Version 2.0 (the "License"); */
11 /* you may not use this file except in compliance with the License. */
12 /* You may obtain a copy of the License at */
13 /* */
14 /* http://www.apache.org/licenses/LICENSE-2.0 */
15 /* */
16 /* Unless required by applicable law or agreed to in writing, software */
17 /* distributed under the License is distributed on an "AS IS" BASIS, */
18 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
19 /* See the License for the specific language governing permissions and */
20 /* limitations under the License. */
21 /* */
22 #ifndef P99_GENERIC_H_
23 # define P99_GENERIC_H_
24 
25 #include "p99_for.h"
26 #include "p99_enum.h"
27 #include "p99_typenames.h"
28 #include "p99_c99.h"
29 
34 #ifndef P00_DOXYGEN
35 
36 #define P00_GENERIC_TYPE(T, ...) T
37 #define P00_GENERIC_SIZE_(UI, ...) char(*)[UI]
38 #define P00_GENERIC_EXP_(T, ...) (__VA_ARGS__)
39 #define P00_GENERIC_LIT_(T, EXP) (EXP){ 0 }
40 
41 #define P00_GENERIC_SIZE_LIT(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_SIZE_, P00_GENERIC_LIT_, EXP, PAIR, I)
42 #define P00_GENERIC_SIZE(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_SIZE_, P00_GENERIC_EXP_, EXP, PAIR, I)
43 #define P00_GENERIC_EXP(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_TYPE, P00_GENERIC_EXP_, EXP, PAIR, I)
44 #define P00_GENERIC_LIT(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_TYPE, P00_GENERIC_LIT_, EXP, PAIR, I)
45 
46 #if p99_has_extension(c_generic_selections)
47 
48 #define P00_GENERIC_EXPRESSION(TOP, EOP, EXP, PAIR, I) \
49 TOP PAIR: EOP PAIR
50 
51 #define P00_GENERIC_(N, MOP, EXP, DEF, ...) \
52 p99_extension \
53 _Generic \
54 ((EXP), \
55  P99_IF_EMPTY(DEF)()(default: (DEF),) \
56  P99_FOR((EXP), N, P00_SEQ, MOP, __VA_ARGS__) \
57  )
58 
59 #elif defined(__GNUC__)
60 
61 #define P00_GENERIC_CLOSE(A,B,C) )
62 
63 #define P00_GENERIC_EXPRESSION(TOP, EOP, EXP, PAIR, I) \
64 __builtin_choose_expr \
65 (__builtin_types_compatible_p(__typeof__ EXP, TOP PAIR), \
66  EOP PAIR
67 
68 /* If no default is given, the idea of _Generic is to abort
69  compilation. To emulate this behavior we would have to produce an
70  expression that is valid as such, but can't be used in any valid
71  context. Such an expression doesn't exist, I think, since any valid
72  expression can always be used in a void context.
73 
74  The idea for that case is to use an extern function that never will
75  be defined and that bears a special attribute that inhibits this
76  function to be called. This function is then called through a
77  sizeof expression for VLA with side effect, such that it only
78  triggers when that particular branch is taken.
79 
80  Unfortunately gcc had this attribute only from about version 4.3,
81  so for versions below that this only produces a link error, much
82  later.
83  */
84 
85 #if p99_has_attribute(error)
86 __attribute__((__error__("Invalid choice in type generic expression")))
87 #endif
88 extern size_t p00_invalid_type_in_generic(char const*);
89 
90 #define P00_INVALID_TYPE_IN_GENERIC(EXP, STR) \
91 p00_invalid_type_in_generic(__FILE__ \
92  P99_STRINGIFY(:__LINE__) \
93  ": invalid type generic choice `" \
94  P99_STRINGIFY(EXP) \
95  "` for " \
96  STR)
97 
98 #define P00_GENERIC_(N, MOP, EXP, DEF, ...) \
99  P99_FOR((EXP), N, P00_SEQ, MOP, __VA_ARGS__), \
100  P99_IF_EMPTY(DEF)(P00_INVALID_TYPE_IN_GENERIC(EXP, #__VA_ARGS__))(DEF) \
101  P99_FOR(, N, P00_SER, P00_GENERIC_CLOSE, P99_DUPL(N, ))
102 
103 #endif
104 
105 #define P00_GENERIC0(MOP, EXP, DEF, ...) \
106 P00_GENERIC_ \
107 ( \
108  P99_NARG(__VA_ARGS__), \
109  P00_ROBUST(MOP), \
110  P00_ROBUST(EXP), \
111  P00_ROBUST(DEF), \
112  __VA_ARGS__)
113 
114 #define P00_GENERIC(N, ...) P99_IF_LT(N, 3)()(P00_GENERIC0(__VA_ARGS__))
115 
116 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC, 0)
117 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC, 2)
118 #define P99_GENERIC(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_EXP, __VA_ARGS__)
119 
120 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_LIT, 0)
121 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_LIT, 2)
122 #define P99_GENERIC_LIT(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_LIT, __VA_ARGS__)
123 
124 #define P00_GENERIC_SIZE0(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_SIZE, __VA_ARGS__)
125 
126 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 0)
127 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 2)
128 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 3)
129 #define P99_GENERIC_SIZE(UI, ...) P00_GENERIC_SIZE0((char(*)[(size_t)(UI)]){ 0 }, __VA_ARGS__)
130 
131 #define P00_GENERIC_SIZE_LIT0(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_SIZE_LIT, __VA_ARGS__)
132 
133 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 0)
134 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 2)
135 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 3)
136 #define P99_GENERIC_SIZE_LIT(UI, ...) P00_GENERIC_SIZE_LIT0((char(*)[(size_t)(UI)]){ 0 }, __VA_ARGS__)
137 
138 
139 #if p99_has_extension(c_generic_selections)
140 
141 # define P99_TYPED_TERN(COND, YES, NO) \
142 (P99_GENERIC \
143  ((char(*)[1 + !!(COND)]){ 0 }, \
144  (NO), \
145  (char(*)[2], (YES))))
146 
147 #elif defined(__GNUC__)
148 
149 # define P99_TYPED_TERN __builtin_choose_expr
150 
151 #else
152 
153 #define P99_TYPED_TERN(COND, YES, NO) only_implemented_with_C11_or_gcc
154 
155 
156 #endif
157 
158 /* A first example for the usefulness of type generic
159  expressions. Implement creal and cimag type generic functions
160  ourselves. */
161 #ifndef __STDC_NO_COMPLEX__
162 # ifdef creal
163 # undef creal
164 # endif
165 # define creal(A) \
166 P99_GENERIC((A)+0, \
167  p99_creall, \
168  (float _Complex, p99_crealf), \
169  (double _Complex, p99_creal)) \
170  (A)
171 
172 # ifdef cimag
173 # undef cimag
174 # endif
175 # define cimag(A) \
176 P99_GENERIC((A)+0, \
177  p99_cimagl, \
178  (float _Complex, p99_cimagf), \
179  (double _Complex, p99_cimag)) \
180  (A)
181 #endif
182 
183 #define P00_CHAR_SIGNED (CHAR_MAX < UCHAR_MAX)
184 
185 #define P00_RVALUE(X) (1 ? (X) : (X))
186 
187 #define P00_SVALUE(X) ((X)+0)
188 
189 #define P00_SVALUE_SIG(T, X) \
190  (T, (T)(intmax_t)(X)), \
191  (T const, (T)(intmax_t)(X)), \
192  (T volatile, (T)(intmax_t)(X)), \
193  (T const volatile, (T)(intmax_t)(X)), \
194  (_Atomic(T), (T)(intmax_t)(X)), \
195  (_Atomic(T) const, (T)(intmax_t)(X)), \
196  (_Atomic(T) volatile, (T)(intmax_t)(X)), \
197  (_Atomic(T) const volatile, (T)(intmax_t)(X))
198 
199 #define P00_SVALUE_UNS(T, X) \
200  (T, (T)(uintmax_t)(X)), \
201  (T const, (T)(uintmax_t)(X)), \
202  (T volatile, (T)(uintmax_t)(X)), \
203  (T const volatile, (T)(uintmax_t)(X)), \
204  (_Atomic(T), (T)(uintmax_t)(X)), \
205  (_Atomic(T) const, (T)(uintmax_t)(X)), \
206  (_Atomic(T) volatile, (T)(uintmax_t)(X)), \
207  (_Atomic(T) const volatile, (T)(uintmax_t)(X))
208 
209 #define P00_SVALUE_QUAL(X, Q) \
210 (char Q, ((char)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar)(intmax_t)(X), (uchar)(uintmax_t)(X)))), \
211 (_Atomic(char) Q, ((char)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar)(intmax_t)(X), (uchar)(uintmax_t)(X))))
212 
213 #define P00_SVALUE_CHAR(X) \
214  P00_SVALUE_QUAL(X, ), \
215  P00_SVALUE_QUAL(X, const), \
216  P00_SVALUE_QUAL(X, volatile), \
217  P00_SVALUE_QUAL(X, const volatile)
218 
219 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SVALUE, 0)
220 #define P99_SVALUE(X) \
221 P99_GENERIC((X), \
222  P00_SVALUE(X), \
223  (void*, (X)), \
224  /*(void const*, (X)), \
225  (void volatile*, (X)), \
226  (void const volatile*, (X)), \
227  (void*const, (X)), \
228  (void const*const, (X)), \
229  (void volatile*const, (X)), \
230  (void const volatile*const, (X)), \
231  (void*volatile, (X)), \
232  (void const*volatile, (X)), \
233  (void volatile*volatile, (X)), \
234  (void const volatile*volatile, (X)), \
235  (void*const volatile, (X)), \
236  (void const*const volatile, (X)), \
237  (void volatile*const volatile, (X)), \
238  (void const volatile*const volatile, (X)),*/ \
239  /* currently clang crashes with restrict */ \
240  /*(void* restrict, (X)), \
241  (void const* restrict, (X)), \
242  (void volatile* restrict, (X)), \
243  (void const volatile* restrict, (X)), \
244  (void*const restrict, (X)), \
245  (void const*const restrict, (X)), \
246  (void volatile*const restrict, (X)), \
247  (void const volatile*const restrict, (X)), \
248  (void*volatile restrict, (X)), \
249  (void const*volatile restrict, (X)), \
250  (void volatile*volatile restrict, (X)), \
251  (void const volatile*volatile restrict, (X)), \
252  (void*const volatile restrict, (X)), \
253  (void const*const volatile restrict, (X)), \
254  (void volatile*const volatile restrict, (X)), \
255  (void const volatile*const volatile restrict, (X)),*/ \
256  P00_SVALUE_CHAR(X), \
257  P00_SVALUE_SIG(schar, X), \
258  P00_SVALUE_SIG(sshort, X), \
259  P00_SVALUE_UNS(_Bool, X), \
260  P00_SVALUE_UNS(uchar, X), \
261  P00_SVALUE_UNS(ushort, X))
262 
263 #define P00_QVALUE_SIG(T, X) \
264  (T, (T)(intmax_t)(X)), \
265  (T const, (T const)(intmax_t const)(X)), \
266  (T volatile, (T volatile)(intmax_t volatile)(X)), \
267  (T const volatile, (T const volatile)(intmax_t const volatile)(X)), \
268  (_Atomic(T), (T)(intmax_t)(X)), \
269  (_Atomic(T) const, (T const)(intmax_t const)(X)), \
270  (_Atomic(T) volatile, (T volatile)(intmax_t volatile)(X)), \
271  (_Atomic(T) const volatile, (T const volatile)(intmax_t const volatile)(X))
272 
273 #define P00_QVALUE_UNS(T, X) \
274  (T, (T)(uintmax_t)(X)), \
275  (T const, (T const)(uintmax_t const)(X)), \
276  (T volatile, (T volatile)(uintmax_t volatile)(X)), \
277  (T const volatile, (T const volatile)(uintmax_t const volatile)(X)), \
278  (_Atomic(T), (T)(uintmax_t)(X)), \
279  (_Atomic(T) const, (T const)(uintmax_t const)(X)), \
280  (_Atomic(T) volatile, (T volatile)(uintmax_t volatile)(X)), \
281  (_Atomic(T) const volatile, (T const volatile)(uintmax_t const volatile)(X))
282 
283 #define P00_QVALUE_QUAL(X, Q) \
284 (char Q, ((char Q)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar Q)(intmax_t Q)(X), (uchar Q)(uintmax_t Q)(X)))), \
285 (_Atomic(char) Q, ((char Q)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar Q)(intmax_t Q)(X), (uchar Q)(uintmax_t Q)(X))))
286 
287 #define P00_QVALUE_CHAR(X) \
288  P00_QVALUE_QUAL(X, ), \
289  P00_QVALUE_QUAL(X, const), \
290  P00_QVALUE_QUAL(X, volatile), \
291  P00_QVALUE_QUAL(X, const volatile)
292 
293 
294 
295 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_QVALUE, 0)
296 #define P99_QVALUE(X) \
297 P99_GENERIC((X), \
298  P00_RVALUE(X), \
299  P00_QVALUE_CHAR(X), \
300  P00_QVALUE_SIG(schar, X), \
301  P00_QVALUE_SIG(sshort, X), \
302  P00_QVALUE_UNS(_Bool, X), \
303  P00_QVALUE_UNS(uchar, X), \
304  P00_QVALUE_UNS(ushort, X))
305 
306 
307 #define P00_TYPE_CHOICE(YES, T, I) (T, YES)
308 
309 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 0)
310 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 1)
311 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 2)
312 #define P99_TYPE_CHOICE(EXP, YES, NO, ...) \
313 P99_GENERIC \
314 ((EXP), \
315  NO, \
316  P99_FOR(YES, P99_NARG(__VA_ARGS__), P00_SEQ, P00_TYPE_CHOICE, __VA_ARGS__))
317 
318 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_UNSIGNED, 0)
319 #define P99_TYPE_UNSIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_UNSIGNED_TYPES)
320 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_SIGNED, 0)
321 #define P99_TYPE_SIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_SIGNED_TYPES)
322 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_REAL_FLOATING, 0)
323 #define P99_TYPE_REAL_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_FLOATING_TYPES)
324 #ifndef __STDC_NO_COMPLEX__
325 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_COMPLEX, 0)
326 # define P99_TYPE_COMPLEX(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_COMPLEX_TYPES)
327 #endif
328 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_FLOATING, 0)
329 #define P99_TYPE_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_FLOATING_TYPES)
330 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_BASIC, 0)
331 #define P99_TYPE_BASIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_BASIC_TYPES)
332 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHARACTER, 0)
333 #define P99_TYPE_CHARACTER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_CHARACTER_TYPES)
334 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_INTEGER, 0)
335 #define P99_TYPE_INTEGER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_INTEGER_TYPES)
336 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_REAL, 0)
337 #define P99_TYPE_REAL(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_TYPES)
338 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_ARITHMETIC, 0)
339 #define P99_TYPE_ARITHMETIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_ARITHMETIC_TYPES)
340 
341 #define P00_SIZE_CHOICE(YES, UI, I) (char(*)[(size_t)(UI)], YES)
342 
343 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 0)
344 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 1)
345 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 2)
346 #define P99_SIZE_CHOICE(UI, YES, NO, ...) \
347 P99_GENERIC \
348  ((char(*)[(size_t)(UI)])0, \
349  NO, \
350  P99_FOR(YES, P99_NARG(__VA_ARGS__), P00_SEQ, P00_SIZE_CHOICE, __VA_ARGS__))
351 
352 
353 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_INDICATOR, 0)
354 #define P99_SIZE_INDICATOR(UI, ...) P99_SIZE_CHOICE(UI, 1, 0, __VA_ARGS__)
355 
356 
357 #define P00_DECLARE_INLINE_EXPRESSION1(EXT, BASE, EXP, A) \
358 P99_CONST_FUNCTION \
359 p99_inline \
360 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
361 (P99_BUILTIN_TYPE(EXT) A) \
362 { \
363  return (EXP); \
364 }
365 
366 #define P00_DECLARE_INLINE_EXPRESSION2(EXT, BASE, EXP, A, B) \
367 P99_CONST_FUNCTION \
368 p99_inline \
369 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
370 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B) \
371 { \
372  return (EXP); \
373 }
374 
375 #define P00_DECLARE_INLINE_EXPRESSION3(EXT, BASE, EXP, A, B, C) \
376 p99_inline \
377 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
378 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
379  P99_BUILTIN_TYPE(EXT) C) \
380 { \
381  return (EXP); \
382 }
383 
384 #define P00_DECLARE_INLINE_EXPRESSION4(EXT, BASE, EXP, A, B, C, D) \
385 p99_inline \
386 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
387 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
388  P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D) \
389 { \
390  return (EXP); \
391 }
392 
393 #define P00_DECLARE_INLINE_EXPRESSION5(EXT, BASE, EXP, A, B, C, D, E) \
394 p99_inline \
395 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
396 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
397  P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D, \
398  P99_BUILTIN_TYPE(EXT) E) \
399 { \
400  return (EXP); \
401 }
402 
403 #define P00_DECLARE_INLINE_EXPRESSION6(EXT, BASE, EXP, A, B, C, D, E, F) \
404 p99_inline \
405 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
406 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
407  P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D, \
408  P99_BUILTIN_TYPE(EXT) E, P99_BUILTIN_TYPE(EXT) F) \
409 { \
410  return (EXP); \
411 }
412 
413 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 0)
414 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 1)
415 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 2)
416 #define P99_DECLARE_INLINE_EXPRESSION(...) \
417 P99_PASTE2(P00_DECLARE_INLINE_EXPRESSION, P99_MINUS(P99_NARG(__VA_ARGS__), 3))(__VA_ARGS__)
418 
419 #define P00_DECLARE_INLINE_EXPRESSION_(...) P99_DECLARE_INLINE_EXPRESSION(__VA_ARGS__)
420 #define P00_DECLARE_INLINE_EXPRESSION(ARGS, EXT, I) P00_DECLARE_INLINE_EXPRESSION_(EXT, P00_ROBUST ARGS)
421 
422 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_DECLARE_INLINE_EXPRESSIONS, 0)
423 #define P99_DECLARE_INLINE_EXPRESSIONS(NEPL, ...) \
424 P99_FOR(NEPL, P99_NARG(__VA_ARGS__), P00_SER, P00_DECLARE_INLINE_EXPRESSION, __VA_ARGS__) \
425 P99_MACRO_END(P99_DECLARE_INLINE_EXPRESSIONS, __VA_ARGS__)
426 
427 extern void p00_invalid_function(void*, ...);
428 
429 #define P00_GEN_EXPR(BASE, EXT, I) (P99_BUILTIN_TYPE(EXT), P99_PASTE3(p00_gen_, BASE, EXT))
430 
431 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_GEN_EXPR, 0)
432 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_EXPR, 1)
433 #define P99_GEN_EXPR(BASE, EXPR, ...) \
434 P99_GENERIC(EXPR, \
435  p00_invalid_function, \
436  P99_FOR(BASE, P99_NARG(__VA_ARGS__), P00_SEQ, P00_GEN_EXPR, __VA_ARGS__))
437 
438 
439 
440 
442  (p00_a >= p00_b) ? p00_a : p00_b,
443  p00_a, p00_b),
445  );
446 
447 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MAX, 0)
448 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MAX, 1)
449 #define P99_GEN_MAX(A, B) \
450 P99_GEN_EXPR(maximum, ((A) >= (B)) ? (A) : (B), \
451  P99_STD_REAL_EXTS \
452  ) \
453 ((A), (B))
454 
456  (p00_a <= p00_b) ? p00_a : p00_b,
457  p00_a, p00_b),
459  );
460 
461 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MIN, 0)
462 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MIN, 1)
463 #define P99_GEN_MIN(A, B) \
464 P99_GEN_EXPR(minimum, ((A) <= (B)) ? (A) : (B), \
465  P99_STD_REAL_EXTS \
466  ) \
467 ((A), (B))
468 
469 
471  (p00_a >= 0) ? p00_a : -p00_a,
472  p00_a),
474  );
475 
477  p00_a,
478  p00_a),
480  );
481 
482 
483 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_ABS, 0)
484 #define P99_GEN_ABS(A) P99_GEN_EXPR(abs, ((A) >= 0) ? (A) : -(A), P99_STD_REAL_EXTS)(A)
485 
486 #define p00_gen_sind sin
487 #define p00_gen_sinf sinf
488 #define p00_gen_sinld sinl
489 #define p00_gen_sindc csin
490 #define p00_gen_sinfc csinf
491 #define p00_gen_sinldc csinl
492 
493 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_SIN, 0)
494 #define P99_GEN_SIN(A) P99_GEN_EXPR(sin, (A), P99_STD_FLOATING_EXTS)(A)
495 
496 inline int* p00_generic_test(int * p00_a) {
497  double *p00_x = 0;
498  switch (P99_GEN_ABS(*p00_a % 3)) {
499  case 0:
500  return P99_GENERIC(&*p00_a,
501  /* empty default expression */,
502  (int*, p00_a),
503  (double*, p00_x+1),
504  (float*, p00_x+2));
505 #ifndef P99_CSIN_BUG
506  case 1:
507  return P99_GENERIC(&*p00_a,
508  /* another form of empty default */,
509  (double[7], P99_GEN_SIN(((p00_x+0)))),
510  (int*, p00_a),
511  (float*, p00_x+2));
512 #endif
513  default:
514  return P99_GENERIC(&*p00_a,
515  /* default expression: */ p00_x,
516  (double*, p00_x+0),
517  (float[7], p00_x+1),
518  (int*, p00_a));
519  }
520 }
521 
522 #else
523 
707 #define P99_GENERIC(...)
708 
728 #define P99_GENERIC_LIT(...)
729 
761 #define P99_GENERIC_SIZE(UI, ...)
762 
771 #define P99_GENERIC_SIZE_LIT(UI, ...)
772 
782 #define P99_TYPED_TERN(COND, YES, NO)
783 
790 #define P00_TYPE_CHOICE(YES, T, I) (T, YES)
791 
799 #define P99_TYPE_CHOICE(EXP, YES, NO, ...)
800 
807 #define P99_TYPE_UNSIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_UNSIGNED_TYPES)
808 #define P99_TYPE_SIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_SIGNED_TYPES)
809 #define P99_TYPE_REAL_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_FLOATING_TYPES)
810 #define P99_TYPE_COMPLEX(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_COMPLEX_TYPES)
811 #define P99_TYPE_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_FLOATING_TYPES)
812 #define P99_TYPE_BASIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_BASIC_TYPES)
813 #define P99_TYPE_CHARACTER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_CHARACTER_TYPES)
814 #define P99_TYPE_INTEGER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_INTEGER_TYPES)
815 #define P99_TYPE_REAL(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_TYPES)
816 #define P99_TYPE_ARITHMETIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_ARITHMETIC_TYPES)
817 
835 #define P99_SIZE_CHOICE(UI, YES, NO, ...)
836 
856 #define P99_SIZE_INDICATOR(UI, ...)
857 
890 #define P99_DECLARE_INLINE_EXPRESSION(EXT, BASE, EXP, ...)
891 
926 #define P99_DECLARE_INLINE_EXPRESSIONS(NEPL, ...)
927 
928 extern void p00_invalid_function(void*, ...);
929 
1000 #define P99_GEN_EXPR(BASE, EXPR, ...)
1001 
1002 #define P99_GEN_MAX(A, B) \
1003 P99_GEN_EXPR(maximum, ((A) >= (B)) ? (A) : (B), \
1004  P99_STD_REAL_EXTS \
1005  ) \
1006 ((A), (B))
1007 
1008 #define P99_GEN_MIN(A, B) \
1009 P99_GEN_EXPR(minimum, ((A) <= (B)) ? (A) : (B), \
1010  P99_STD_REAL_EXTS \
1011  ) \
1012 ((A), (B))
1013 
1014 
1015 #define P99_GEN_ABS(A) P99_GEN_EXPR(abs, ((A) >= 0) ? (A) : -(A), P99_STD_REAL_EXTS)(A)
1016 
1023 #define P99_GEN_SIN(A) P99_GEN_EXPR(sin, (A), P99_STD_FLOATING_EXTS)(A)
1024 
1025 #endif
1026 
1039 #define P00_OVALUES_(X, T, I) (T*, X[0])
1040 #define P00_OVALUES(X, ...) P99_FOR(X, P99_NARG(__VA_ARGS__), P00_SEQ, P00_OVALUES_, __VA_ARGS__)
1041 #define P00_OVALUE_(X, DEF, ...) P99_GENERIC(X, DEF, __VA_ARGS__)
1042 
1043 #define P00_OVALUES1_(X, T, I) (T*, X)
1044 #define P00_OVALUES1(X, ...) P99_FOR(X, P99_NARG(__VA_ARGS__), P00_SEQ, P00_OVALUES1_, __VA_ARGS__)
1045 #define P00_OVALUE1_(X, ...) P99_GENERIC(&(X[0]), , P00_OVALUES1(X, __VA_ARGS__))
1046 
1047 #define P00_AVALUES_(X, T, I) (T*, *(T(*)[1])X)
1048 #define P00_AVALUES(X, ...) P99_FOR(X, P99_NARG(__VA_ARGS__), P00_SEQ, P00_AVALUES_, __VA_ARGS__)
1049 #define P00_AVALUE_(X, DEF, ...) P99_GENERIC(X, DEF, __VA_ARGS__)
1050 
1051 
1052 #ifdef P00_DOXYGEN
1053 
1069 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OVALUE, 0)
1070 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 1)
1071 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 2)
1072 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 3)
1073 #define P99_OVALUE(X, ...)
1074 
1090 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_AVALUE, 0)
1091 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 1)
1092 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 2)
1093 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 3)
1094 #define P99_AVALUE(X, ...)
1095 
1112 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJSIZE, 0)
1113 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 1)
1114 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 2)
1115 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 3)
1116 #define P99_OBJSIZE(X, ...)
1117 
1134 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJLEN, 0)
1135 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 1)
1136 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 2)
1137 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 3)
1138 #define P99_OBJLEN(X, ...)
1139 #else
1140 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OVALUE, 0)
1141 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 1)
1142 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 2)
1143 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 3)
1144 #define P99_OVALUE(X, ...) P00_OVALUE_((X), P00_OVALUE1_((X), __VA_ARGS__), P00_OVALUES((X), __VA_ARGS__))
1145 
1146 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_AVALUE, 0)
1147 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 1)
1148 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 2)
1149 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 3)
1150 #define P99_AVALUE(X, ...) P00_AVALUE_((X), P00_OVALUE1_((X), __VA_ARGS__), P00_AVALUES((X), __VA_ARGS__))
1151 
1152 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJSIZE, 0)
1153 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 1)
1154 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 2)
1155 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 3)
1156 #define P99_OBJSIZE(X, ...) (sizeof P99_OVALUE(X, __VA_ARGS__))
1157 
1158 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJLEN, 0)
1159 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 1)
1160 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 2)
1161 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 3)
1162 #define P99_OBJLEN(X, ...) (P99_OBJSIZE(X, __VA_ARGS__)/(sizeof (X)[0]))
1163 #endif
1164 
1178 #define P00_SPRINT_DEFINE(T, ...) \
1179 p99_inline \
1180 char const* P99_PASTE2(p00_sprint_, T)(T p00_val, char*restrict p00_str, unsigned p00_form) { \
1181  enum { p00_len = P99_NARG(__VA_ARGS__), }; \
1182  static char const*const p00_format[p00_len] = { __VA_ARGS__ }; \
1183  char const*const p00_f = (p00_form < p00_len) \
1184  ? p00_format[p00_form] \
1185  : p00_format[0]; \
1186  sprintf(p00_str, p00_f, p00_val); \
1187  return p00_str; \
1188 } \
1189 P99_MACRO_END(P00_SPRINT_DEFINE, T)
1190 
1191 P00_SPRINT_DEFINE(char, "%c");
1192 P00_SPRINT_DEFINE(schar, "%hhd");
1193 P00_SPRINT_DEFINE(uchar, "%hhu", "%#hhX", "%#hho");
1194 P00_SPRINT_DEFINE(short, "%hd");
1195 P00_SPRINT_DEFINE(ushort, "%hu", "%#hX", "%#ho");
1196 P00_SPRINT_DEFINE(int, "%d");
1197 P00_SPRINT_DEFINE(unsigned, "%u", "%#X", "%#o");
1198 P00_SPRINT_DEFINE(long, "%ld");
1199 P00_SPRINT_DEFINE(ulong, "%lu", "%#lX", "%#lo");
1200 P00_SPRINT_DEFINE(llong, "%lld");
1201 P00_SPRINT_DEFINE(ullong, "%llu", "%#llX", "%#llo");
1202 P00_SPRINT_DEFINE(float, "%g", "%a");
1203 P00_SPRINT_DEFINE(double, "%g", "%a");
1204 P00_SPRINT_DEFINE(ldouble, "%Lg", "%La");
1205 
1207 p99_inline
1208 char const* p00_sprint__Bool(_Bool p00_val, char*restrict p00_str, unsigned p00_form) {
1209  P99_UNUSED(p00_str);
1210  P99_UNUSED(p00_form);
1211  char const*const p00_format[] = {
1212  "false", "true",
1213  "0", "1",
1214  "f", "t",
1215  };
1216  register unsigned const p00_len = P99_ALEN(p00_format) / 2;
1217  if (p00_form >= p00_len) p00_form = 0;
1218  return p00_format[p00_form * 2 + p00_val];
1219 }
1220 
1222 p99_inline
1223 char const volatile* p00_sprint_charp(char const volatile* p00_val, char*restrict p00_str, unsigned p00_form) {
1224  P99_UNUSED(p00_str);
1225  P99_UNUSED(p00_form);
1226  return p00_val;
1227 }
1228 
1229 p99_inline
1230 char const* p00_sprint_voidp(void const volatile* p00_val, char*restrict p00_str, unsigned p00_form) {
1231  P99_UNUSED(p00_form);
1232  sprintf(p00_str, "%p", p00_val);
1233  return p00_str;
1234 }
1235 
1236 #ifndef __STDC_NO_COMPLEX__
1237 p99_inline
1238 char const* p00_sprint_cfloat(cfloat p00_val, char*restrict p00_str, unsigned p00_form) {
1239  char const*const p00_format[] = { "(%g, %g)", "(%a, %a)", };
1240  register unsigned const p00_len = P99_ALEN(p00_format);
1241  char const*const p00_f = (p00_form < p00_len)
1242  ? p00_format[p00_form]
1243  : p00_format[0];
1244  sprintf(p00_str, p00_f, creal(p00_val), cimag(p00_val));
1245  return p00_str;
1246 }
1247 
1248 p99_inline
1249 char const* p00_sprint_cdouble(cdouble p00_val, char*restrict p00_str, unsigned p00_form) {
1250  char const*const p00_format[] = { "(%g, %g)", "(%a, %a)", };
1251  register unsigned const p00_len = P99_ALEN(p00_format);
1252  char const*const p00_f = (p00_form < p00_len)
1253  ? p00_format[p00_form]
1254  : p00_format[0];
1255  sprintf(p00_str, p00_f, creal(p00_val), cimag(p00_val));
1256  return p00_str;
1257 }
1258 
1259 p99_inline
1260 char const* p00_sprint_cldouble(cldouble p00_val, char*restrict p00_str, unsigned p00_form) {
1261  char const*const p00_format[] = { "(%Lg, %Lg)", "(%La, %La)", };
1262  register unsigned const p00_len = P99_ALEN(p00_format);
1263  char const*const p00_f = (p00_form < p00_len)
1264  ? p00_format[p00_form]
1265  : p00_format[0];
1266  sprintf(p00_str, p00_f, creal(p00_val), cimag(p00_val));
1267  return p00_str;
1268 }
1269 #endif
1270 
1271 
1272 #ifdef p99x_uintmax
1273 #define UINT64_D19 UINT64_C(10000000000000000000)
1274 p99_inline
1275 void p00_sprint_p99x_uintmax_u_ite(p99x_uintmax p00_val, char*restrict p00_str) {
1276  uint64_t p00_ar[2*sizeof(p99x_uintmax)/sizeof(uint64_t)];
1277  size_t p00_pos = 0;
1278  for (; p00_val >= UINT64_D19; ++p00_pos) {
1279  /* These operations are expensive, so avoid them whenever we
1280  can. */
1281  p00_ar[p00_pos] = (uint64_t)(p00_val % UINT64_D19);
1282  p00_val /= UINT64_D19;
1283  }
1284  p00_str += sprintf(p00_str, "%" PRIu64, (uint64_t)p00_val);
1285  while (p00_pos) {
1286  --p00_pos;
1287  p00_str += sprintf(p00_str, "%019" PRIu64, p00_ar[p00_pos]);
1288  }
1289 }
1290 p99_inline
1291 char* p00_sprint_p99x_uintmax_u(p99x_uintmax p00_val, char*restrict p00_str) {
1292  p00_sprint_p99x_uintmax_u_ite(p00_val, p00_str);
1293  return p00_str;
1294 }
1295 #define UINT64_O21 (~(UINT64_C(1)<<63))
1296 p99_inline
1297 void p00_sprint_p99x_uintmax_o_ite(p99x_uintmax p00_val, char*restrict p00_str) {
1298  uint64_t p00_ar[3*sizeof(p99x_uintmax)/sizeof(uint64_t)];
1299  size_t p00_pos = 0;
1300  for (;;) {
1301  /* Mask and shift in that case are less expensive. */
1302  p00_ar[p00_pos] = ((uint64_t)p00_val) & UINT64_O21;
1303  p00_val >>= 63;
1304  if (!p00_val) break;
1305  ++p00_pos;
1306  }
1307  p00_str += sprintf(p00_str, "%#" PRIo64, p00_ar[p00_pos]);
1308  while (p00_pos) {
1309  --p00_pos;
1310  p00_str += sprintf(p00_str, "%021" PRIo64, p00_ar[p00_pos]);
1311  }
1312 }
1313 p99_inline
1314 char* p00_sprint_p99x_uintmax_o(p99x_uintmax p00_val, char*restrict p00_str) {
1315  p00_sprint_p99x_uintmax_o_ite(p00_val, p00_str);
1316  return p00_str;
1317 }
1318 p99_inline
1319 void p00_sprint_p99x_uintmax_X_ite(p99x_uintmax p00_val, char*restrict p00_str) {
1320  uint64_t p00_ar[2*sizeof(p99x_uintmax)/sizeof(uint64_t)];
1321  size_t p00_pos = 0;
1322  for (;;) {
1323  /* Mask and shift in that case are less expensive. */
1324  p00_ar[p00_pos] = (uint64_t)p00_val;
1325  p00_val >>= 64;
1326  if (!p00_val) break;
1327  ++p00_pos;
1328  }
1329  p00_str += sprintf(p00_str, "%#" PRIX64, p00_ar[p00_pos]);
1330  while (p00_pos) {
1331  --p00_pos;
1332  p00_str += sprintf(p00_str, "%016" PRIX64, p00_ar[p00_pos]);
1333  }
1334 }
1335 p99_inline
1336 char const* p00_sprint_p99x_uintmax_X(p99x_uintmax p00_val, char*restrict p00_str) {
1337  p00_sprint_p99x_uintmax_X_ite(p00_val, p00_str);
1338  return p00_str;
1339 }
1340 
1341 p99_inline
1342 char const* p00_sprint_p99x_intmax(p99x_intmax p00_val, char*restrict p00_str, unsigned p00_form) {
1343  P99_UNUSED(p00_form);
1344  if (p00_val < 0) {
1345  p00_str[0] = '-';
1346  p00_sprint_p99x_uintmax_u(-p00_val, p00_str + 1);
1347  } else {
1348  p00_sprint_p99x_uintmax_u(p00_val, p00_str);
1349  }
1350  return p00_str;
1351 }
1352 
1353 p99_inline
1354 char const* p00_sprint_p99x_uintmax(p99x_uintmax p00_val, char*restrict p00_str, unsigned p00_form) {
1355  switch (p00_form) {
1356  default: return p00_sprint_p99x_uintmax_u(p00_val, p00_str);
1357  case 1: return p00_sprint_p99x_uintmax_X(p00_val, p00_str);
1358  case 2: return p00_sprint_p99x_uintmax_o(p00_val, p00_str);
1359  }
1360 }
1361 #endif
1362 
1363 #define P00_SPRINT(NAME, T, I) (T, P99_PASTE2(p00_sprint_, T))
1364 
1365 #define P00_SPRINT_LIST_(...) \
1366  P99_FOR(, P99_NARG(__VA_ARGS__), P00_SEQ, P00_SPRINT, __VA_ARGS__)
1367 
1368 #define P00_SPRINT_LIST() P00_SPRINT_LIST_(P99_EXT_ARITHMETIC_TYPES)
1369 
1370 #define P00_SPRINT_FORMAT_(X, A, ...) \
1371 P99_GENERIC((X)+0, \
1372  p00_sprint_voidp, \
1373  (char*, p00_sprint_charp), \
1374  (char const*, p00_sprint_charp), \
1375  __VA_ARGS__)((X), \
1376  P99_GENERIC((X)+0, \
1377  /* be sure not to have an array for the sizeof */ \
1378  /* times a rough estimate for octal conversion */ \
1379  /* plus a rough offset for floating points */ \
1380  (char[(sizeof(X+0)*22+64)/8]){ 0 }, \
1381  (char*, 0), \
1382  (char const*, 0) \
1383  ), \
1384  (A))
1385 
1386 #define P00_SPRINT_FORMAT(...) P00_SPRINT_FORMAT_(__VA_ARGS__)
1387 
1415 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMAT, 0)
1416 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMAT, 2)
1417 #define P99_FORMAT(...) \
1418 P00_SPRINT_FORMAT \
1419  (P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
1420  (__VA_ARGS__, 0) \
1421  (__VA_ARGS__), \
1422  P00_SPRINT_LIST())
1423 
1424 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMATS, 0)
1425 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMATS, 1)
1426 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMATS, 2)
1427 #define P99_FORMATS(...) P99_SEQ(P99_FORMAT, __VA_ARGS__)
1428 #define P00_PRINTF(...) printf(__VA_ARGS__)
1429 
1430 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_PRINTF, 1)
1431 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_PRINTF, 2)
1432 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_PRINTF, 3)
1433 #define P99_PRINTF(FORMAT, ...) printf(FORMAT, P99_FORMATS(__VA_ARGS__))
1434 
1435 #define P00_FPRINTF(...) fprintf(__VA_ARGS__)
1436 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FPRINTF, 2)
1437 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FPRINTF, 3)
1438 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FPRINTF, 4)
1439 #define P99_FPRINTF(F, FORMAT, ...) fprintf(F, FORMAT, P99_FORMATS(__VA_ARGS__))
1440 
1441 #define P00_SPRINTF(...) sprintf(__VA_ARGS__)
1442 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SPRINTF, 2)
1443 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SPRINTF, 3)
1444 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SPRINTF, 4)
1445 #define P99_SPRINTF(S, FORMAT, ...) sprintf(S, FORMAT, P99_FORMATS(__VA_ARGS__))
1446 
1447 #define P00_SNPRINTF(...) snprintf(__VA_ARGS__)
1448 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SNPRINTF, 3)
1449 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SNPRINTF, 4)
1450 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SNPRINTF, 5)
1451 #define P99_SNPRINTF(S, N, FORMAT, ...) snprintf(S, N, FORMAT, P99_FORMATS(__VA_ARGS__))
1452 
1457 #define P00_DEFINE_IN_RANGE(T) \
1458 P99_CONST_FUNCTION \
1459 p99_inline \
1460 bool P99_PASTE2(p00_in_range_, T)(T p00_r, T p00_s, T p00_len) { \
1461  return (p00_r >= p00_s) && ((p00_r - p00_s) < p00_len); \
1462 }
1463 
1465 p99_inline
1466 bool p00_in_range_voidp(void* p00_r_, void* p00_s_, size_t p00_len) {
1467  unsigned char* p00_r = p00_r_;
1468  unsigned char* p00_s = p00_s_;
1469  return (p00_r >= p00_s) && ((size_t)(p00_r - p00_s) < p00_len);
1470 }
1471 
1472 #ifndef P00_DOXYGEN
1473 P99_SER(P00_DEFINE_IN_RANGE, P99_EXT_REAL_TYPES)
1474 #endif
1475 
1476 #define P00_IN_RANGE_PART(NAME, T, I) (T, P99_PASTE2(p00_in_range_, T))
1477 
1478 
1479 #define P00_IN_RANGE_LIST_(...) \
1480  P99_FOR(, P99_NARG(__VA_ARGS__), P00_SEQ, P00_IN_RANGE_PART, __VA_ARGS__)
1481 
1482 #define P00_IN_RANGE_LIST() P00_IN_RANGE_LIST_(P99_EXT_REAL_TYPES)
1483 
1484 #define P00_IN_RANGE(R, S, L, ...) \
1485 P99_GENERIC((1 ? (R) : (S)), p00_in_range_voidp, __VA_ARGS__)((R), (S), (L))
1486 
1497 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_IN_RANGE, 0)
1498 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_IN_RANGE, 1)
1499 #define P99_IN_RANGE(R, S, L) P00_IN_RANGE((R), (S), (L), P00_IN_RANGE_LIST())
1500 
1507 #define P00_VOID_QUAL_(QUAL, ...) (void QUAL*, __VA_ARGS__)
1508 #define P00_VOID_QUAL(LIST) P00_VOID_QUAL_ LIST
1509 
1510 #define P00_VOIDIFY_LIST(...) P99_SEQ(P00_VOID_QUAL, __VA_ARGS__)
1511 
1550 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_PQUALIFIED, 0)
1551 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_PQUALIFIED, 1)
1552 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_PQUALIFIED, 2)
1553 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_PQUALIFIED, 3)
1554 #define P99_GENERIC_PQUALIFIED(PEXP, ...) \
1555 P99_GENERIC( \
1556  /* The second case is subtle. If we would chose (void*)0 */ \
1557  /* this would be a null pointer constant and the return */ \
1558  /* type would be the type of PEXP. If it is another type */ \
1559  /* of void* expression the return is a qualified version */ \
1560  /* of void*. */ \
1561 (1 ? (PEXP) : (void*)1),, \
1562  P00_VOIDIFY_LIST(__VA_ARGS__))
1563 
1585 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_PCONST, 0)
1586 #define P99_GENERIC_PCONST(PEXP, NCONST, CONST) \
1587 P99_GENERIC((1 ? (PEXP) : (void volatile*)1),, \
1588  P00_VOID_QUAL_(volatile, NCONST), \
1589  P00_VOID_QUAL_(volatile const, CONST) \
1590  )
1591 
1605 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_PVOLATILE, 0)
1606 #define P99_GENERIC_PVOLATILE(PEXP, NVOLATILE, VOLATILE) \
1607 P99_GENERIC((1 ? (PEXP) : (void const*)1),, \
1608  P00_VOID_QUAL_(const, NVOLATILE), \
1609  P00_VOID_QUAL_(const volatile, VOLATILE) \
1610  )
1611 
1625 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_PCONSTVOLATILE, 0)
1626 #define P99_GENERIC_PCONSTVOLATILE(PEXP, NON, FULL) \
1627 P99_GENERIC((1 ? (PEXP) : (void*)1), \
1628  NVOLATILE, \
1629  P00_VOID_QUAL_(const volatile, VOLATILE) \
1630  )
1631 
1632 
1639 P00_DOCUMENT_TYPE_ARGUMENT(P99_GENERIC_TQUALIFIED, 0)
1640 #define P99_GENERIC_TQUALIFIED(T, ...) \
1641 P99_GENERIC_PQUALIFIED((&(T)P99_INIT), ...)
1642 
1649 P00_DOCUMENT_TYPE_ARGUMENT(P99_GENERIC_TCONST, 0)
1650 #define P99_GENERIC_TCONST(T, NCONST, CONST) \
1651 P99_GENERIC_PCONST((&(T)P99_INIT), NCONST, CONST)
1652 
1659 P00_DOCUMENT_TYPE_ARGUMENT(P99_GENERIC_TVOLATILE, 0)
1660 #define P99_GENERIC_TVOLATILE(T, NVOLATILE, VOLATILE) \
1661 P99_GENERIC_PVOLATILE((&(T)P99_INIT), NVOLATILE, VOLATILE)
1662 
1669 P00_DOCUMENT_TYPE_ARGUMENT(P99_GENERIC_TCONSTVOLATILE, 0)
1670 #define P99_GENERIC_TCONSTVOLATILE(T, NON, FULL) \
1671 P99_GENERIC_PCONSTVOLATILE((&(T)P99_INIT), NON, FULL)
1672 
1673 
1684 #define P00_GENERIC_VOIDPTR_OR_INTEGER(PEXP, TRUE, FALSE) \
1685 P99_GENERIC((1 ? (void*)0 : (PEXP)), \
1686  FALSE, \
1687  (void*, TRUE) \
1688  )
1689 
1690 #define P00_IS_VOIDPTR_OR_INTEGER(PEXP) P00_GENERIC_VOIDPTR_OR_INTEGER(PEXP, true, false)
1691 
1692 typedef struct p00_nullptr_test p00_nullptr_test;
1693 
1694 #define P00_GENERIC_NULLPTR_CONSTANT(PEXP, TRUE, FALSE) \
1695 P99_GENERIC((1 ? (p00_nullptr_test*)0 : (PEXP)), \
1696  FALSE, \
1697  (p00_nullptr_test*, TRUE) \
1698  )
1699 
1700 #define P00_IS_NULLPTR_CONSTANT(PEXP) P00_GENERIC_NULLPTR_CONSTANT(PEXP, true, false)
1701 
1702 #define P99_GENERIC_NULLPTR_CONSTANT_(PEXP, TRUE, FALSE) \
1703 P00_GENERIC_NULLPTR_CONSTANT(PEXP, \
1704  TRUE, \
1705  FALSE)
1706 
1707 #define P99_GENERIC_NULLPTR_CONSTANT(PEXP, TRUE, FALSE) \
1708 P99_GENERIC_NULLPTR_CONSTANT_(P00_GENERIC_VOIDPTR_OR_INTEGER(PEXP, PEXP, (void*)1), \
1709  TRUE, \
1710  FALSE)
1711 
1712 
1740 #define P99_IS_NULLPTR_CONSTANT(PEXP) P99_GENERIC_NULLPTR_CONSTANT((PEXP), true, false)
1741 
1742 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_INTEGRAL_CONSTANT, 0)
1743 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_INTEGRAL_CONSTANT, 2)
1744 #define P99_GENERIC_INTEGRAL_CONSTANT(EXP, TRUE, FALSE) \
1745 P99_GENERIC((EXP), \
1746  P99_GENERIC_NULLPTR_CONSTANT((void*)(ptrdiff_t)((EXP)-(EXP)), TRUE, FALSE), \
1747  /* avoid to test with arithmetic for void* expressions */ \
1748  (void*, FALSE), \
1749  (void const*, FALSE), \
1750  (void volatile*, FALSE), \
1751  (void const volatile*, FALSE) \
1752  )
1753 
1788 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_IS_INTEGRAL_CONSTANT, 0)
1789 #define P99_IS_INTEGRAL_CONSTANT(EXP) P99_GENERIC_INTEGRAL_CONSTANT((EXP), true, false)
1790 
1791 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_NULLPTR, 0)
1792 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_NULLPTR, 1)
1793 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_NULLPTR, 2)
1794 #define P99_GENERIC_NULLPTR(PEXP, TRUE, FALSE) \
1795 (P99_GENERIC_NULLPTR_CONSTANT(PEXP, TRUE, FALSE) \
1796  &&!P99_GENERIC_INTEGRAL_CONSTANT(PEXP, TRUE, FALSE))
1797 
1809 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_IS_NULLPTR, 0)
1810 #define P99_IS_NULLPTR(PEXP) P99_GENERIC_NULLPTR((PEXP), true, false)
1811 
1820 #endif
P99_SIZE_CHOICE
#define P99_SIZE_CHOICE(UI, YES, NO,...)
Classify expression UI according to its value and return YES if the value is in the list and NO,...
Definition: p99_generic.h:835
P99_OBJLEN
#define P99_OBJLEN(X,...)
For a pointer or array expression X return the length of the underlying array object.
Definition: p99_generic.h:1138
P99_AVALUE
#define P99_AVALUE(X,...)
For a pointer or array expression X return the underlying array.
Definition: p99_generic.h:1094
p99_for.h
A preprocessor for loop implementation and some derived list handling macros.
P99_GENERIC_PQUALIFIED
#define P99_GENERIC_PQUALIFIED(PEXP,...)
Generic choice based on the qualification of the target of a pointer expression.
Definition: p99_generic.h:1554
P99_FPRINTF
#define P99_FPRINTF(F, FORMAT,...)
Definition: p99_generic.h:1439
P99_GENERIC_LIT
#define P99_GENERIC_LIT(...)
For each generic choice return a compound literal of the chosen type.
Definition: p99_generic.h:728
p99_c99.h
C99 specific include files that are required by the standard.
P99_SIZE_INDICATOR
#define P99_SIZE_INDICATOR(UI,...)
Classify expression UI according to its value and return 1 if the value is in the list and 0,...
Definition: p99_generic.h:856
P99_GENERIC_PVOLATILE
#define P99_GENERIC_PVOLATILE(PEXP, NVOLATILE, VOLATILE)
Generic choice based on the qualification of the target of a pointer expression.
Definition: p99_generic.h:1606
P99_GENERIC
#define P99_GENERIC(...)
Type generic expression in anticipation of C11 _Generic.
Definition: p99_generic.h:707
P99_SER
#define P99_SER(MACRO,...)
Apply the macro MACRO to the rest of the argument list.
Definition: p99_for.h:264
P99_TYPE_REAL
#define P99_TYPE_REAL(EXP)
Definition: p99_generic.h:815
P99_GENERIC_PCONSTVOLATILE
#define P99_GENERIC_PCONSTVOLATILE(PEXP, NON, FULL)
Generic choice based on the qualification of the target of a pointer expression.
Definition: p99_generic.h:1626
P99_ALEN
#define P99_ALEN(ARR, N)
Produce the length of the argument array ARR in terms of number of elements.
Definition: p99_for.h:678
P99_IS_NULLPTR
#define P99_IS_NULLPTR(PEXP)
Test if the expression EXP is a null pointer in the sense of the C standard.
Definition: p99_generic.h:1810
P99_GENERIC_NULLPTR
#define P99_GENERIC_NULLPTR(PEXP, TRUE, FALSE)
Definition: p99_generic.h:1794
p99_typenames.h
Declare types derived from the standard types.
P99_IN_RANGE
#define P99_IN_RANGE(R, S, L)
check if R is in the range [S, S + L)
Definition: p99_generic.h:1499
P99_FORMATS
#define P99_FORMATS(...)
Definition: p99_generic.h:1427
ulong
unsigned long ulong
a ‘one token’ abreviation for unsigned long
Definition: p99_typenames.h:38
schar
signed char schar
a ‘one token’ abreviation for signed char
Definition: p99_typenames.h:45
P99_TYPE_CHOICE
#define P99_TYPE_CHOICE(EXP, YES, NO,...)
Classify expression EXP according to its type and return YES if the type is in the list and NO,...
Definition: p99_generic.h:799
P99_SPRINTF
#define P99_SPRINTF(S, FORMAT,...)
Definition: p99_generic.h:1445
ldouble
long double ldouble
a ‘one token’ abreviation for long double
Definition: p99_typenames.h:49
P99_EXT_REAL_TYPES
#define P99_EXT_REAL_TYPES
Definition: p99_type.h:313
P99_DECLARE_INLINE_EXPRESSION
#define P99_DECLARE_INLINE_EXPRESSION(EXT, BASE, EXP,...)
Declare an inline function of basename BASE for expression EXP, applied to the builtin type EXT.
Definition: p99_generic.h:890
cfloat
float _Complex cfloat
a ‘one token’ abreviation for float _Complex
Definition: p99_typenames.h:51
p99_inline
#define p99_inline
Try to force a function always to be inlined.
Definition: p99_compiler.h:496
cdouble
double _Complex cdouble
a ‘one token’ abreviation for double _Complex
Definition: p99_typenames.h:52
P99_IS_INTEGRAL_CONSTANT
#define P99_IS_INTEGRAL_CONSTANT(EXP)
Test if the expression EXP is an integral constant in the sense of the C standard.
Definition: p99_generic.h:1789
p99x_intmax
intmax_t p99x_intmax
A signed integer type of maximal width that exceeds the C99 specifications.
Definition: p99_int.h:134
P99_GEN_EXPR
#define P99_GEN_EXPR(BASE, EXPR,...)
Produce a type generic expression that can be used as if it were an inline function.
Definition: p99_generic.h:1000
P99_TYPE_ARITHMETIC
#define P99_TYPE_ARITHMETIC(EXP)
Definition: p99_generic.h:816
P99_UNUSED
#define P99_UNUSED(...)
check if the list of expressions is syntactically valid but don't evaluate it
Definition: p99_enum.h:215
p99x_uintmax
uintmax_t p99x_uintmax
An unsigned integer type of maximal width that exceeds the C99 specifications.
Definition: p99_int.h:118
P99_GEN_ABS
#define P99_GEN_ABS(A)
Definition: p99_generic.h:1015
P99_GENERIC_TCONSTVOLATILE
#define P99_GENERIC_TCONSTVOLATILE(T, NON, FULL)
Generic choice based on the qualification of a type expression.
Definition: p99_generic.h:1670
P99_GEN_MAX
#define P99_GEN_MAX(A, B)
Definition: p99_generic.h:1002
P99_OVALUE
#define P99_OVALUE(X,...)
For a pointer or array expression X return the underlying object.
Definition: p99_generic.h:1073
P99_GENERIC_SIZE_LIT
#define P99_GENERIC_SIZE_LIT(UI,...)
Similar to P99_GENERIC_SIZE but returns a compound literal of the chosen type.
Definition: p99_generic.h:771
P99_TYPE_FLOATING
#define P99_TYPE_FLOATING(EXP)
Definition: p99_generic.h:811
ullong
unsigned long long ullong
a ‘one token’ abreviation for unsigned long long
Definition: p99_typenames.h:48
P99_GEN_SIN
#define P99_GEN_SIN(A)
Type generic macro to compute the sine of A.
Definition: p99_generic.h:1023
P99_STD_REAL_FLOATING_EXTS
#define P99_STD_REAL_FLOATING_EXTS
Definition: p99_type.h:252
P99_TYPE_INTEGER
#define P99_TYPE_INTEGER(EXP)
Definition: p99_generic.h:814
p99_enum.h
P99_STD_SIGNED_EXTS
#define P99_STD_SIGNED_EXTS
Definition: p99_type.h:224
P99_GENERIC_PCONST
#define P99_GENERIC_PCONST(PEXP, NCONST, CONST)
Generic choice based on the qualification of the target of a pointer expression.
Definition: p99_generic.h:1586
P99_GENERIC_TVOLATILE
#define P99_GENERIC_TVOLATILE(T, NVOLATILE, VOLATILE)
Generic choice based on the qualification of a type expression.
Definition: p99_generic.h:1660
P99_DECLARE_INLINE_EXPRESSIONS
#define P99_DECLARE_INLINE_EXPRESSIONS(NEPL,...)
Declare a whole bunch of inline functions of basename BASE for expression EXP, applied to the builtin...
Definition: p99_generic.h:926
llong
long long llong
a ‘one token’ abreviation for long long
Definition: p99_typenames.h:46
P99_CONST_FUNCTION
#define P99_CONST_FUNCTION
On architectures that support this, assert that a function is "const", i.e only depends on parameters...
Definition: p99_compiler.h:622
P99_STD_UNSIGNED_EXTS
#define P99_STD_UNSIGNED_EXTS
Definition: p99_type.h:217
P99_TYPE_BASIC
#define P99_TYPE_BASIC(EXP)
Definition: p99_generic.h:812
P99_TYPE_COMPLEX
#define P99_TYPE_COMPLEX(EXP)
Definition: p99_generic.h:810
P99_GENERIC_SIZE
#define P99_GENERIC_SIZE(UI,...)
Similar to P99_GENERIC but the choice is not according to the type of the expression UI but to its un...
Definition: p99_generic.h:761
ushort
unsigned short ushort
a ‘one token’ abreviation for unsigned short
Definition: p99_typenames.h:42
cldouble
long double _Complex cldouble
a ‘one token’ abreviation for long double _Complex
Definition: p99_typenames.h:53
P99_TYPE_SIGNED
#define P99_TYPE_SIGNED(EXP)
Definition: p99_generic.h:808
P99_TYPE_REAL_FLOATING
#define P99_TYPE_REAL_FLOATING(EXP)
Definition: p99_generic.h:809
P99_GENERIC_TCONST
#define P99_GENERIC_TCONST(T, NCONST, CONST)
Generic choice based on the qualification of a type expression.
Definition: p99_generic.h:1650
P99_OBJSIZE
#define P99_OBJSIZE(X,...)
For a pointer or array expression X return the size of the underlying object.
Definition: p99_generic.h:1116
P99_TYPE_CHARACTER
#define P99_TYPE_CHARACTER(EXP)
Definition: p99_generic.h:813
P99_GENERIC_INTEGRAL_CONSTANT
#define P99_GENERIC_INTEGRAL_CONSTANT(EXP, TRUE, FALSE)
Definition: p99_generic.h:1744
P99_PRINTF
#define P99_PRINTF(FORMAT,...)
Definition: p99_generic.h:1433
P99_GEN_MIN
#define P99_GEN_MIN(A, B)
Definition: p99_generic.h:1008
P99_STD_REAL_EXTS
#define P99_STD_REAL_EXTS
Definition: p99_type.h:294
P99_SNPRINTF
#define P99_SNPRINTF(S, N, FORMAT,...)
Definition: p99_generic.h:1451
P99_FORMAT
#define P99_FORMAT(...)
Definition: p99_generic.h:1417
P99_GENERIC_TQUALIFIED
#define P99_GENERIC_TQUALIFIED(T,...)
Generic choice based on the qualification of a type expression.
Definition: p99_generic.h:1640
P99_TYPE_UNSIGNED
#define P99_TYPE_UNSIGNED(EXP)
Definition: p99_generic.h:807
uchar
unsigned char uchar
a ‘one token’ abreviation for unsigned char
Definition: p99_typenames.h:44