P99
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
p99_generic.h
Go to the documentation of this file.
00001 /* This may look like nonsense, but it really is -*- mode: C -*-              */
00002 /*                                                                            */
00003 /* Except for parts copied from previous work and as explicitly stated below, */
00004 /* the authors and copyright holders for this work are as follows:            */
00005 /* (C) copyright  2012-2013 Jens Gustedt, INRIA, France                       */
00006 /* (C) copyright  2012 William Morris                                         */
00007 /*                                                                            */
00008 /* This file is free software; it is part of the P99 project.                 */
00009 /* You can redistribute it and/or modify it under the terms of the QPL as     */
00010 /* given in the file LICENSE. It is distributed without any warranty;         */
00011 /* without even the implied warranty of merchantability or fitness for a      */
00012 /* particular purpose.                                                        */
00013 /*                                                                            */
00014 #ifndef     P99_GENERIC_H_
00015 # define    P99_GENERIC_H_
00016 
00017 #include "p99_for.h"
00018 #include "p99_typenames.h"
00019 #include "p99_c99.h"
00020 
00025 #ifndef P00_DOXYGEN
00026 
00027 #define P00_GENERIC_TYPE(T, EXP) T
00028 #define P00_GENERIC_SIZE_(UI, EXP) char(*)[UI]
00029 #define P00_GENERIC_EXP_(T, EXP) (EXP)
00030 #define P00_GENERIC_LIT_(T, EXP) (EXP){ 0 }
00031 
00032 #define P00_GENERIC_SIZE_LIT(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_SIZE_, P00_GENERIC_LIT_, EXP, PAIR, I)
00033 #define P00_GENERIC_SIZE(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_SIZE_, P00_GENERIC_EXP_, EXP, PAIR, I)
00034 #define P00_GENERIC_EXP(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_TYPE, P00_GENERIC_EXP_, EXP, PAIR, I)
00035 #define P00_GENERIC_LIT(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_TYPE, P00_GENERIC_LIT_, EXP, PAIR, I)
00036 
00037 #if p99_has_extension(c_generic_selections)
00038 
00039 #define P00_GENERIC_EXPRESSION(TOP, EOP, EXP, PAIR, I)         \
00040 TOP PAIR: EOP PAIR
00041 
00042 #define P00_GENERIC_(N, MOP, EXP, DEF, ...)                    \
00043 p99_extension                                                  \
00044 _Generic                                                       \
00045 ((EXP),                                                        \
00046  P99_IF_EMPTY(DEF)()(default: (DEF),)                          \
00047  P99_FOR((EXP), N, P00_SEQ, MOP, __VA_ARGS__)                  \
00048  )
00049 
00050 #elif defined(__GNUC__)
00051 
00052 #define P00_GENERIC_CLOSE(A,B,C) )
00053 
00054 #define P00_GENERIC_EXPRESSION(TOP, EOP, EXP, PAIR, I)         \
00055 __builtin_choose_expr                                          \
00056 (__builtin_types_compatible_p(__typeof__ EXP, TOP PAIR),       \
00057  EOP PAIR
00058 
00059 /* If no default is given, the idea of _Generic is to abort
00060    compilation. To emulate this behavior we would have to produce an
00061    expression that is valid as such, but can't be used in any valid
00062    context. Such an expression doesn't exist, I think, since any valid
00063    expression can always be used in a void context.
00064 
00065    The idea for that case is to use an extern function that never will
00066    be defined and that bears a special attribute that inhibits this
00067    function to be called.  This function is then called through a
00068    sizeof expression for VLA with side effect, such that it only
00069    triggers when that particular branch is taken.
00070 
00071    Unfortunately gcc had this attribute only from about version 4.3,
00072    so for versions below that this only produces a link error, much
00073    later.
00074    */
00075 
00076 #if p99_has_attribute(error)
00077 __attribute__((__error__("Invalid choice in type generic expression")))
00078 #endif
00079 extern size_t p00_invalid_type_in_generic(char const*);
00080 
00081 #define P00_INVALID_TYPE_IN_GENERIC(EXP, STR)                  \
00082 p00_invalid_type_in_generic(__FILE__                           \
00083                             P99_STRINGIFY(:__LINE__)           \
00084                             ": invalid type generic choice `"  \
00085                             P99_STRINGIFY(EXP)                 \
00086                             "` for "                           \
00087                             STR)
00088 
00089 #define P00_GENERIC_(N, MOP, EXP, DEF, ...)                                \
00090   P99_FOR((EXP), N, P00_SEQ, MOP, __VA_ARGS__),                            \
00091     P99_IF_EMPTY(DEF)(P00_INVALID_TYPE_IN_GENERIC(EXP, #__VA_ARGS__))(DEF) \
00092     P99_FOR(, N, P00_SER, P00_GENERIC_CLOSE, P99_DUPL(N, ))
00093 
00094 #endif
00095 
00096 #define P00_GENERIC0(MOP, EXP, DEF, ...)                       \
00097 P00_GENERIC_                                                   \
00098 (                                                              \
00099  P99_NARG(__VA_ARGS__),                                        \
00100  P00_ROBUST(MOP),                                              \
00101  P00_ROBUST(EXP),                                              \
00102  P00_ROBUST(DEF),                                              \
00103  __VA_ARGS__)
00104 
00105 #define P00_GENERIC(N, ...) P99_IF_LT(N, 3)()(P00_GENERIC0(__VA_ARGS__))
00106 
00107 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC, 0)
00108 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC, 2)
00109 #define P99_GENERIC(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_EXP, __VA_ARGS__)
00110 
00111 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_LIT, 0)
00112 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_LIT, 2)
00113 #define P99_GENERIC_LIT(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_LIT, __VA_ARGS__)
00114 
00115 #define P00_GENERIC_SIZE0(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_SIZE, __VA_ARGS__)
00116 
00117 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 0)
00118 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 2)
00119 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 3)
00120 #define P99_GENERIC_SIZE(UI, ...) P00_GENERIC_SIZE0((char(*)[(size_t)(UI)]){ 0 }, __VA_ARGS__)
00121 
00122 #define P00_GENERIC_SIZE_LIT0(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_SIZE_LIT, __VA_ARGS__)
00123 
00124 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 0)
00125 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 2)
00126 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 3)
00127 #define P99_GENERIC_SIZE_LIT(UI, ...) P00_GENERIC_SIZE_LIT0((char(*)[(size_t)(UI)]){ 0 }, __VA_ARGS__)
00128 
00129 
00130 #if p99_has_extension(c_generic_selections)
00131 
00132 # define P99_TYPED_TERN(COND, YES, NO)                         \
00133 (P99_GENERIC                                                   \
00134  ((char(*)[1 + !!(COND)]){ 0 },                                \
00135   (NO),                                                        \
00136   (char(*)[2], (YES))))
00137 
00138 #elif defined(__GNUC__)
00139 
00140 # define P99_TYPED_TERN __builtin_choose_expr
00141 
00142 #else
00143 
00144 #define P99_TYPED_TERN(COND, YES, NO) only_implemented_with_C11_or_gcc
00145 
00146 
00147 #endif
00148 
00149 /* A first example for the usefulness of type generic
00150    expressions. Implement creal and cimag type generic functions
00151    ourselves. */
00152 #ifndef __STDC_NO_COMPLEX__
00153 # ifdef creal
00154 #  undef creal
00155 # endif
00156 # define creal(A)                                              \
00157 P99_GENERIC((A),                                               \
00158             p99_creall,                                        \
00159             (float _Complex, p99_crealf),                      \
00160             (float _Complex const, p99_crealf),                \
00161             (float _Complex volatile, p99_crealf),             \
00162             (float _Complex const volatile, p99_creal),        \
00163             (double _Complex, p99_creal),                      \
00164             (double _Complex const, p99_creal),                \
00165             (double _Complex volatile, p99_creal),             \
00166             (double _Complex const volatile, p99_creal))       \
00167  (A)
00168 
00169 # ifdef cimag
00170 #  undef cimag
00171 # endif
00172 # define cimag(A)                                              \
00173 P99_GENERIC((A),                                               \
00174             p99_cimagl,                                        \
00175             (float _Complex, p99_cimagf),                      \
00176             (float _Complex const, p99_cimagf),                \
00177             (float _Complex volatile, p99_cimagf),             \
00178             (float _Complex const volatile, p99_cimag),        \
00179             (double _Complex, p99_cimag),                      \
00180             (double _Complex const, p99_cimag),                \
00181             (double _Complex volatile, p99_cimag),             \
00182             (double _Complex const volatile, p99_cimag))       \
00183  (A)
00184 #endif
00185 
00186 #define P00_CHAR_SIGNED (CHAR_MAX < UCHAR_MAX)
00187 
00188 #define P00_RVALUE(X) (1 ? (X) : (X))
00189 
00190 #define P00_SVALUE(X) ((X)+0)
00191 
00192 #define P00_SVALUE_SIG(T, X)                                   \
00193   (T, (T)(intmax_t)(X)),                                       \
00194   (T const, (T)(intmax_t)(X)),                                 \
00195   (T volatile, (T)(intmax_t)(X)),                              \
00196   (T const volatile, (T)(intmax_t)(X)),                        \
00197   (_Atomic(T), (T)(intmax_t)(X)),                              \
00198   (_Atomic(T) const, (T)(intmax_t)(X)),                        \
00199   (_Atomic(T) volatile, (T)(intmax_t)(X)),                     \
00200   (_Atomic(T) const volatile, (T)(intmax_t)(X))
00201 
00202 #define P00_SVALUE_UNS(T, X)                                   \
00203   (T, (T)(uintmax_t)(X)),                                      \
00204   (T const, (T)(uintmax_t)(X)),                                \
00205   (T volatile, (T)(uintmax_t)(X)),                             \
00206   (T const volatile, (T)(uintmax_t)(X)),                       \
00207   (_Atomic(T), (T)(uintmax_t)(X)),                             \
00208   (_Atomic(T) const, (T)(uintmax_t)(X)),                       \
00209   (_Atomic(T) volatile, (T)(uintmax_t)(X)),                    \
00210   (_Atomic(T) const volatile, (T)(uintmax_t)(X))
00211 
00212 #define P00_SVALUE_QUAL(X, Q)                                                                           \
00213 (char Q, ((char)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar)(intmax_t)(X), (uchar)(uintmax_t)(X)))),         \
00214 (_Atomic(char) Q, ((char)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar)(intmax_t)(X), (uchar)(uintmax_t)(X))))
00215 
00216 #define P00_SVALUE_CHAR(X)                                     \
00217   P00_SVALUE_QUAL(X, ),                                        \
00218   P00_SVALUE_QUAL(X, const),                                   \
00219   P00_SVALUE_QUAL(X, volatile),                                \
00220   P00_SVALUE_QUAL(X, const volatile)
00221 
00222 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SVALUE, 0)
00223 #define P99_SVALUE(X)                                             \
00224 P99_GENERIC((X),                                                  \
00225             P00_SVALUE(X),                                        \
00226             (void*, (X)),                                         \
00227             /*(void const*, (X)),                                 \
00228             (void volatile*, (X)),                                \
00229             (void const volatile*, (X)),                          \
00230             (void*const, (X)),                                    \
00231             (void const*const, (X)),                              \
00232             (void volatile*const, (X)),                           \
00233             (void const volatile*const, (X)),                     \
00234             (void*volatile, (X)),                                 \
00235             (void const*volatile, (X)),                           \
00236             (void volatile*volatile, (X)),                        \
00237             (void const volatile*volatile, (X)),                  \
00238             (void*const volatile, (X)),                           \
00239             (void const*const volatile, (X)),                     \
00240             (void volatile*const volatile, (X)),                  \
00241             (void const volatile*const volatile, (X)),*/          \
00242             /* currently clang crashes with restrict */           \
00243             /*(void* restrict, (X)),                              \
00244             (void const* restrict, (X)),                          \
00245             (void volatile* restrict, (X)),                       \
00246             (void const volatile* restrict, (X)),                 \
00247             (void*const restrict, (X)),                           \
00248             (void const*const restrict, (X)),                     \
00249             (void volatile*const restrict, (X)),                  \
00250             (void const volatile*const restrict, (X)),            \
00251             (void*volatile restrict, (X)),                        \
00252             (void const*volatile restrict, (X)),                  \
00253             (void volatile*volatile restrict, (X)),               \
00254             (void const volatile*volatile restrict, (X)),         \
00255             (void*const volatile restrict, (X)),                  \
00256             (void const*const volatile restrict, (X)),            \
00257             (void volatile*const volatile restrict, (X)),         \
00258             (void const volatile*const volatile restrict, (X)),*/ \
00259             P00_SVALUE_CHAR(X),                                   \
00260             P00_SVALUE_SIG(schar, X),                             \
00261             P00_SVALUE_SIG(sshort, X),                            \
00262             P00_SVALUE_UNS(_Bool, X),                             \
00263             P00_SVALUE_UNS(uchar, X),                             \
00264             P00_SVALUE_UNS(ushort, X))
00265 
00266 #define P00_QVALUE_SIG(T, X)                                                  \
00267   (T, (T)(intmax_t)(X)),                                                      \
00268   (T const, (T const)(intmax_t const)(X)),                                    \
00269   (T volatile, (T volatile)(intmax_t volatile)(X)),                           \
00270   (T const volatile, (T const volatile)(intmax_t const volatile)(X)),         \
00271   (_Atomic(T), (T)(intmax_t)(X)),                                             \
00272   (_Atomic(T) const, (T const)(intmax_t const)(X)),                           \
00273   (_Atomic(T) volatile, (T volatile)(intmax_t volatile)(X)),                  \
00274   (_Atomic(T) const volatile, (T const volatile)(intmax_t const volatile)(X))
00275 
00276 #define P00_QVALUE_UNS(T, X)                                                   \
00277   (T, (T)(uintmax_t)(X)),                                                      \
00278   (T const, (T const)(uintmax_t const)(X)),                                    \
00279   (T volatile, (T volatile)(uintmax_t volatile)(X)),                           \
00280   (T const volatile, (T const volatile)(uintmax_t const volatile)(X)),         \
00281   (_Atomic(T), (T)(uintmax_t)(X)),                                             \
00282   (_Atomic(T) const, (T const)(uintmax_t const)(X)),                           \
00283   (_Atomic(T) volatile, (T volatile)(uintmax_t volatile)(X)),                  \
00284   (_Atomic(T) const volatile, (T const volatile)(uintmax_t const volatile)(X))
00285 
00286 #define P00_QVALUE_QUAL(X, Q)                                                                                     \
00287 (char Q, ((char Q)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar Q)(intmax_t Q)(X), (uchar Q)(uintmax_t Q)(X)))),         \
00288 (_Atomic(char) Q, ((char Q)P99_TYPED_TERN(P00_CHAR_SIGNED, (schar Q)(intmax_t Q)(X), (uchar Q)(uintmax_t Q)(X))))
00289 
00290 #define P00_QVALUE_CHAR(X)                                     \
00291   P00_QVALUE_QUAL(X, ),                                        \
00292   P00_QVALUE_QUAL(X, const),                                   \
00293   P00_QVALUE_QUAL(X, volatile),                                \
00294   P00_QVALUE_QUAL(X, const volatile)
00295 
00296 
00297 
00298 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_QVALUE, 0)
00299 #define P99_QVALUE(X)                                          \
00300 P99_GENERIC((X),                                               \
00301             P00_RVALUE(X),                                     \
00302             P00_QVALUE_CHAR(X),                                \
00303             P00_QVALUE_SIG(schar, X),                          \
00304             P00_QVALUE_SIG(sshort, X),                         \
00305             P00_QVALUE_UNS(_Bool, X),                          \
00306             P00_QVALUE_UNS(uchar, X),                          \
00307             P00_QVALUE_UNS(ushort, X))
00308 
00309 
00310 #define P00_TYPE_CHOICE(YES, T, I) (T, YES)
00311 
00312 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 0)
00313 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 1)
00314 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 2)
00315 #define P99_TYPE_CHOICE(EXP, YES, NO, ...)                                   \
00316 P99_GENERIC                                                                  \
00317 ((EXP),                                                                      \
00318  NO,                                                                         \
00319  P99_FOR(YES, P99_NARG(__VA_ARGS__), P00_SEQ, P00_TYPE_CHOICE, __VA_ARGS__))
00320 
00321 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_UNSIGNED, 0)
00322 #define P99_TYPE_UNSIGNED(EXP)      P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_UNSIGNED_TYPES)
00323 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_SIGNED, 0)
00324 #define P99_TYPE_SIGNED(EXP)        P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_SIGNED_TYPES)
00325 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_REAL_FLOATING, 0)
00326 #define P99_TYPE_REAL_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_FLOATING_TYPES)
00327 #ifndef __STDC_NO_COMPLEX__
00328 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_COMPLEX, 0)
00329 # define P99_TYPE_COMPLEX(EXP)       P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_COMPLEX_TYPES)
00330 #endif
00331 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_FLOATING, 0)
00332 #define P99_TYPE_FLOATING(EXP)      P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_FLOATING_TYPES)
00333 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_BASIC, 0)
00334 #define P99_TYPE_BASIC(EXP)         P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_BASIC_TYPES)
00335 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHARACTER, 0)
00336 #define P99_TYPE_CHARACTER(EXP)     P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_CHARACTER_TYPES)
00337 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_INTEGER, 0)
00338 #define P99_TYPE_INTEGER(EXP)       P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_INTEGER_TYPES)
00339 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_REAL, 0)
00340 #define P99_TYPE_REAL(EXP)          P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_TYPES)
00341 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_ARITHMETIC, 0)
00342 #define P99_TYPE_ARITHMETIC(EXP)    P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_ARITHMETIC_TYPES)
00343 
00344 #define P00_SIZE_CHOICE(YES, UI, I) (char(*)[(size_t)(UI)], YES)
00345 
00346 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 0)
00347 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 1)
00348 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 2)
00349 #define P99_SIZE_CHOICE(UI, YES, NO, ...)                                    \
00350 P99_GENERIC                                                                  \
00351  ((char(*)[(size_t)(UI)])0,                                                  \
00352  NO,                                                                         \
00353  P99_FOR(YES, P99_NARG(__VA_ARGS__), P00_SEQ, P00_SIZE_CHOICE, __VA_ARGS__))
00354 
00355 
00356 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_INDICATOR, 0)
00357 #define P99_SIZE_INDICATOR(UI, ...) P99_SIZE_CHOICE(UI, 1, 0, __VA_ARGS__)
00358 
00359 
00360 #define P00_DECLARE_INLINE_EXPRESSION1(EXT, BASE, EXP, A)      \
00361 P99_CONST_FUNCTION                                             \
00362 p99_inline                                                     \
00363 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT)          \
00364 (P99_BUILTIN_TYPE(EXT) A)                                      \
00365 {                                                              \
00366   return (EXP);                                                \
00367 }
00368 
00369 #define P00_DECLARE_INLINE_EXPRESSION2(EXT, BASE, EXP, A, B)   \
00370 P99_CONST_FUNCTION                                             \
00371 p99_inline                                                     \
00372 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT)          \
00373 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B)             \
00374 {                                                              \
00375   return (EXP);                                                \
00376 }
00377 
00378 #define P00_DECLARE_INLINE_EXPRESSION3(EXT, BASE, EXP, A, B, C) \
00379 p99_inline                                                      \
00380 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT)           \
00381 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B,              \
00382  P99_BUILTIN_TYPE(EXT) C)                                       \
00383 {                                                               \
00384   return (EXP);                                                 \
00385 }
00386 
00387 #define P00_DECLARE_INLINE_EXPRESSION4(EXT, BASE, EXP, A, B, C, D) \
00388 p99_inline                                                         \
00389 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT)              \
00390 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B,                 \
00391  P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D)                 \
00392 {                                                                  \
00393   return (EXP);                                                    \
00394 }
00395 
00396 #define P00_DECLARE_INLINE_EXPRESSION5(EXT, BASE, EXP, A, B, C, D, E) \
00397 p99_inline                                                            \
00398 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT)                 \
00399 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B,                    \
00400  P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D,                    \
00401  P99_BUILTIN_TYPE(EXT) E)                                             \
00402 {                                                                     \
00403   return (EXP);                                                       \
00404 }
00405 
00406 #define P00_DECLARE_INLINE_EXPRESSION6(EXT, BASE, EXP, A, B, C, D, E, F) \
00407 p99_inline                                                               \
00408 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT)                    \
00409 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B,                       \
00410  P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D,                       \
00411  P99_BUILTIN_TYPE(EXT) E, P99_BUILTIN_TYPE(EXT) F)                       \
00412 {                                                                        \
00413   return (EXP);                                                          \
00414 }
00415 
00416 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 0)
00417 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 1)
00418 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 2)
00419 #define P99_DECLARE_INLINE_EXPRESSION(...)                                                  \
00420 P99_PASTE2(P00_DECLARE_INLINE_EXPRESSION, P99_MINUS(P99_NARG(__VA_ARGS__), 3))(__VA_ARGS__)
00421 
00422 #define P00_DECLARE_INLINE_EXPRESSION_(...) P99_DECLARE_INLINE_EXPRESSION(__VA_ARGS__)
00423 #define P00_DECLARE_INLINE_EXPRESSION(ARGS, EXT, I) P00_DECLARE_INLINE_EXPRESSION_(EXT, P00_ROBUST ARGS)
00424 
00425 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_DECLARE_INLINE_EXPRESSIONS, 0)
00426 #define P99_DECLARE_INLINE_EXPRESSIONS(NEPL, ...)                                         \
00427 P99_FOR(NEPL, P99_NARG(__VA_ARGS__), P00_SER, P00_DECLARE_INLINE_EXPRESSION, __VA_ARGS__) \
00428 P99_MACRO_END(P99_DECLARE_INLINE_EXPRESSIONS, __VA_ARGS__)
00429 
00430 extern void p00_invalid_function(void*, ...);
00431 
00432 #define P00_GEN_EXPR(BASE, EXT, I) (P99_BUILTIN_TYPE(EXT), P99_PASTE3(p00_gen_, BASE, EXT))
00433 
00434 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_GEN_EXPR, 0)
00435 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_EXPR, 1)
00436 #define P99_GEN_EXPR(BASE, EXPR, ...)                                                 \
00437 P99_GENERIC(EXPR,                                                                     \
00438             p00_invalid_function,                                                     \
00439             P99_FOR(BASE, P99_NARG(__VA_ARGS__), P00_SEQ, P00_GEN_EXPR, __VA_ARGS__))
00440 
00441 
00442 
00443 
00444 P99_DECLARE_INLINE_EXPRESSIONS((maximum,
00445                                 (p00_a >= p00_b) ? p00_a : p00_b,
00446                                 p00_a, p00_b),
00447                                P99_STD_REAL_EXTS
00448                               );
00449 
00450 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MAX, 0)
00451 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MAX, 1)
00452 #define P99_GEN_MAX(A, B)                                      \
00453 P99_GEN_EXPR(maximum, ((A) >= (B)) ? (A) : (B),                \
00454              P99_STD_REAL_EXTS                                 \
00455              )                                                 \
00456 ((A), (B))
00457 
00458 P99_DECLARE_INLINE_EXPRESSIONS((minimum,
00459                                 (p00_a <= p00_b) ? p00_a : p00_b,
00460                                 p00_a, p00_b),
00461                                P99_STD_REAL_EXTS
00462                               );
00463 
00464 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MIN, 0)
00465 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MIN, 1)
00466 #define P99_GEN_MIN(A, B)                                      \
00467 P99_GEN_EXPR(minimum, ((A) <= (B)) ? (A) : (B),                \
00468              P99_STD_REAL_EXTS                                 \
00469              )                                                 \
00470 ((A), (B))
00471 
00472 
00473 P99_DECLARE_INLINE_EXPRESSIONS((abs,
00474                                 (p00_a >= 0) ? p00_a : -p00_a,
00475                                 p00_a),
00476                                P99_STD_SIGNED_EXTS, P99_STD_REAL_FLOATING_EXTS
00477                               );
00478 
00479 P99_DECLARE_INLINE_EXPRESSIONS((abs,
00480                                 p00_a,
00481                                 p00_a),
00482                                P99_STD_UNSIGNED_EXTS
00483                               );
00484 
00485 
00486 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_ABS, 0)
00487 #define P99_GEN_ABS(A) P99_GEN_EXPR(abs, ((A) >= 0) ? (A) : -(A), P99_STD_REAL_EXTS)(A)
00488 
00489 #define p00_gen_sind sin
00490 #define p00_gen_sinf sinf
00491 #define p00_gen_sinld sinl
00492 #define p00_gen_sindc csin
00493 #define p00_gen_sinfc csinf
00494 #define p00_gen_sinldc csinl
00495 
00496 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_SIN, 0)
00497 #define P99_GEN_SIN(A) P99_GEN_EXPR(sin, (A), P99_STD_FLOATING_EXTS)(A)
00498 
00499 inline int* p00_generic_test(int * p00_a) {
00500   double *p00_x;
00501   switch (P99_GEN_ABS(*p00_a % 3)) {
00502   case 0:
00503     return P99_GENERIC(&*p00_a,
00504                        /* empty default expression */,
00505                        (int*, p00_a),
00506                        (double*, p00_x+1),
00507                        (float*, p00_x+2));
00508 #ifndef P99_CSIN_BUG
00509   case 1:
00510     return P99_GENERIC(&*p00_a,
00511                        /* another form of empty default */,
00512                        (double[7], P99_GEN_SIN(((p00_x+0)))),
00513                        (int*, p00_a),
00514                        (float*, p00_x+2));
00515 #endif
00516   default:
00517     return P99_GENERIC(&*p00_a,
00518                        /* default expression: */ p00_x,
00519                        (double*, p00_x+0),
00520                        (float[7], p00_x+1),
00521                        (int*, p00_a));
00522   }
00523 }
00524 
00525 #else
00526 
00623 #define P99_GENERIC(...)
00624 
00644 #define P99_GENERIC_LIT(...)
00645 
00677 #define P99_GENERIC_SIZE(UI, ...)
00678 
00687 #define P99_GENERIC_SIZE_LIT(UI, ...)
00688 
00698 #define P99_TYPED_TERN(COND, YES, NO)
00699 
00706 #define P00_TYPE_CHOICE(YES, T, I) (T, YES)
00707 
00715 #define P99_TYPE_CHOICE(EXP, YES, NO, ...)
00716 
00723 #define P99_TYPE_UNSIGNED(EXP)      P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_UNSIGNED_TYPES)
00724 #define P99_TYPE_SIGNED(EXP)        P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_SIGNED_TYPES)
00725 #define P99_TYPE_REAL_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_FLOATING_TYPES)
00726 #define P99_TYPE_COMPLEX(EXP)       P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_COMPLEX_TYPES)
00727 #define P99_TYPE_FLOATING(EXP)      P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_FLOATING_TYPES)
00728 #define P99_TYPE_BASIC(EXP)         P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_BASIC_TYPES)
00729 #define P99_TYPE_CHARACTER(EXP)     P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_CHARACTER_TYPES)
00730 #define P99_TYPE_INTEGER(EXP)       P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_INTEGER_TYPES)
00731 #define P99_TYPE_REAL(EXP)          P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_TYPES)
00732 #define P99_TYPE_ARITHMETIC(EXP)    P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_ARITHMETIC_TYPES)
00733 
00751 #define P99_SIZE_CHOICE(UI, YES, NO, ...)
00752 
00772 #define P99_SIZE_INDICATOR(UI, ...)
00773 
00810 #define P99_DECLARE_INLINE_EXPRESSION(EXT, BASE, EXP, ...)
00811 
00846 #define P99_DECLARE_INLINE_EXPRESSIONS(NEPL, ...)
00847 
00848 extern void p00_invalid_function(void*, ...);
00849 
00920 #define P99_GEN_EXPR(BASE, EXPR, ...)
00921 
00922 #define P99_GEN_MAX(A, B)                                      \
00923 P99_GEN_EXPR(maximum, ((A) >= (B)) ? (A) : (B),                \
00924              P99_STD_REAL_EXTS                                 \
00925              )                                                 \
00926 ((A), (B))
00927 
00928 #define P99_GEN_MIN(A, B)                                      \
00929 P99_GEN_EXPR(minimum, ((A) <= (B)) ? (A) : (B),                \
00930              P99_STD_REAL_EXTS                                 \
00931              )                                                 \
00932 ((A), (B))
00933 
00934 
00935 #define P99_GEN_ABS(A) P99_GEN_EXPR(abs, ((A) >= 0) ? (A) : -(A), P99_STD_REAL_EXTS)(A)
00936 
00943 #define P99_GEN_SIN(A) P99_GEN_EXPR(sin, (A), P99_STD_FLOATING_EXTS)(A)
00944 
00949 #endif
00950 
00951 #define P00_OVALUES_(X, T, I) (T*, X[0])
00952 #define P00_OVALUES(X, ...) P99_FOR(X, P99_NARG(__VA_ARGS__), P00_SEQ, P00_OVALUES_, __VA_ARGS__)
00953 #define P00_OVALUE_(X, DEF, ...) P99_GENERIC(X, DEF, __VA_ARGS__)
00954 
00955 #define P00_OVALUES1_(X, T, I) (T*, X)
00956 #define P00_OVALUES1(X, ...) P99_FOR(X, P99_NARG(__VA_ARGS__), P00_SEQ, P00_OVALUES1_, __VA_ARGS__)
00957 #define P00_OVALUE1_(X, ...) P99_GENERIC(&(X[0]), , P00_OVALUES1(X, __VA_ARGS__))
00958 
00959 #define P00_AVALUES_(X, T, I) (T*, *(T(*)[1])X)
00960 #define P00_AVALUES(X, ...) P99_FOR(X, P99_NARG(__VA_ARGS__), P00_SEQ, P00_AVALUES_, __VA_ARGS__)
00961 #define P00_AVALUE_(X, DEF, ...) P99_GENERIC(X, DEF, __VA_ARGS__)
00962 
00963 
00964 #ifdef P00_DOXYGEN
00965 
00981 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OVALUE, 0)
00982 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 1)
00983 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 2)
00984 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 3)
00985 #define P99_OVALUE(X, ...)
00986 
01002 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_AVALUE, 0)
01003 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 1)
01004 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 2)
01005 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 3)
01006 #define P99_AVALUE(X, ...)
01007 
01024 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJSIZE, 0)
01025 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 1)
01026 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 2)
01027 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 3)
01028 #define P99_OBJSIZE(X, ...)
01029 
01046 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJLEN, 0)
01047 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 1)
01048 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 2)
01049 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 3)
01050 #define P99_OBJLEN(X, ...)
01051 #else
01052 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OVALUE, 0)
01053 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 1)
01054 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 2)
01055 P00_DOCUMENT_TYPE_ARGUMENT(P99_OVALUE, 3)
01056 #define P99_OVALUE(X, ...) P00_OVALUE_((X), P00_OVALUE1_((X), __VA_ARGS__), P00_OVALUES((X), __VA_ARGS__))
01057 
01058 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_AVALUE, 0)
01059 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 1)
01060 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 2)
01061 P00_DOCUMENT_TYPE_ARGUMENT(P99_AVALUE, 3)
01062 #define P99_AVALUE(X, ...) P00_AVALUE_((X), P00_OVALUE1_((X), __VA_ARGS__), P00_AVALUES((X), __VA_ARGS__))
01063 
01064 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJSIZE, 0)
01065 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 1)
01066 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 2)
01067 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJSIZE, 3)
01068 #define P99_OBJSIZE(X, ...) (sizeof P99_OVALUE(X, __VA_ARGS__))
01069 
01070 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_OBJLEN, 0)
01071 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 1)
01072 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 2)
01073 P00_DOCUMENT_TYPE_ARGUMENT(P99_OBJLEN, 3)
01074 #define P99_OBJLEN(X, ...) (P99_OBJSIZE(X, __VA_ARGS__)/(sizeof (X)[0]))
01075 #endif
01076 
01077 #define P00_SPRINT_DEFINE(T, ...)                                                             \
01078 p99_inline                                                                                    \
01079 char const* P99_PASTE2(p00_sprint_, T)(T p00_val, char*restrict p00_str, unsigned p00_form) { \
01080   enum { p00_len = P99_NARG(__VA_ARGS__), };                                                  \
01081   static char const*const p00_format[p00_len] = { __VA_ARGS__ };                              \
01082   char const*const p00_f = (p00_form < p00_len)                                               \
01083     ? p00_format[p00_form]                                                                    \
01084     : p00_format[0];                                                                          \
01085   sprintf(p00_str, p00_f, p00_val);                                                           \
01086   return p00_str;                                                                             \
01087 }                                                                                             \
01088 P99_MACRO_END(P00_SPRINT_DEFINE, T)
01089 
01090 P00_SPRINT_DEFINE(char, "%c");
01091 P00_SPRINT_DEFINE(schar, "%hhd");
01092 P00_SPRINT_DEFINE(uchar, "%hhu", "%#hhX", "%#hho");
01093 P00_SPRINT_DEFINE(short, "%hd");
01094 P00_SPRINT_DEFINE(ushort, "%hu", "%#hX", "%#ho");
01095 P00_SPRINT_DEFINE(int, "%d");
01096 P00_SPRINT_DEFINE(unsigned, "%u", "%#X", "%#o");
01097 P00_SPRINT_DEFINE(long, "%ld");
01098 P00_SPRINT_DEFINE(ulong, "%lu", "%#lX", "%#lo");
01099 P00_SPRINT_DEFINE(llong, "%lld");
01100 P00_SPRINT_DEFINE(ullong, "%llu", "%#llX", "%#llo");
01101 P00_SPRINT_DEFINE(float, "%g", "%a");
01102 P00_SPRINT_DEFINE(double, "%g", "%a");
01103 P00_SPRINT_DEFINE(ldouble, "%Lg", "%La");
01104 
01105 P99_CONST_FUNCTION
01106 p99_inline
01107 char const* p00_sprint__Bool(_Bool p00_val, char*restrict p00_str, unsigned p00_form) {
01108   P99_UNUSED(p00_str);
01109   P99_UNUSED(p00_form);
01110   char const*const p00_format[] = {
01111     "false", "true",
01112     "0", "1",
01113     "f", "t",
01114   };
01115   register unsigned const p00_len = P99_ALEN(p00_format) / 2;
01116   if (p00_form >= p00_len) p00_form = 0;
01117   return p00_format[p00_form * 2 + p00_val];
01118 }
01119 
01120 P99_CONST_FUNCTION
01121 p99_inline
01122 char const* p00_sprint_charp(char const* p00_val, char*restrict p00_str, unsigned p00_form) {
01123   P99_UNUSED(p00_str);
01124   P99_UNUSED(p00_form);
01125   return p00_val;
01126 }
01127 
01128 p99_inline
01129 char const* p00_sprint_voidp(void * p00_val, char*restrict p00_str, unsigned p00_form) {
01130   P99_UNUSED(p00_form);
01131   sprintf(p00_str, "%p", p00_val);
01132   return p00_str;
01133 }
01134 
01135 #ifndef __STDC_NO_COMPLEX__
01136 p99_inline
01137 char const* p00_sprint_cfloat(cfloat p00_val, char*restrict p00_str, unsigned p00_form) {
01138   char const*const p00_format[] = { "(%g, %g)", "(%a, %a)", };
01139   register unsigned const p00_len = P99_ALEN(p00_format);
01140   char const*const p00_f = (p00_form < p00_len)
01141                            ? p00_format[p00_form]
01142                            : p00_format[0];
01143   sprintf(p00_str, p00_f, creal(p00_val), cimag(p00_val));
01144   return p00_str;
01145 }
01146 
01147 p99_inline
01148 char const* p00_sprint_cdouble(cdouble p00_val, char*restrict p00_str, unsigned p00_form) {
01149   char const*const p00_format[] = { "(%g, %g)", "(%a, %a)", };
01150   register unsigned const p00_len = P99_ALEN(p00_format);
01151   char const*const p00_f = (p00_form < p00_len)
01152                            ? p00_format[p00_form]
01153                            : p00_format[0];
01154   sprintf(p00_str, p00_f, creal(p00_val), cimag(p00_val));
01155   return p00_str;
01156 }
01157 
01158 p99_inline
01159 char const* p00_sprint_cldouble(cldouble p00_val, char*restrict p00_str, unsigned p00_form) {
01160   char const*const p00_format[] = { "(%Lg, %Lg)", "(%La, %La)", };
01161   register unsigned const p00_len = P99_ALEN(p00_format);
01162   char const*const p00_f = (p00_form < p00_len)
01163                            ? p00_format[p00_form]
01164                            : p00_format[0];
01165   sprintf(p00_str, p00_f, creal(p00_val), cimag(p00_val));
01166   return p00_str;
01167 }
01168 #endif
01169 
01170 
01171 #ifdef p99x_uintmax
01172 #define UINT64_D19 UINT64_C(10000000000000000000)
01173 p99_inline
01174 void p00_sprint_p99x_uintmax_u_ite(p99x_uintmax p00_val, char*restrict p00_str) {
01175   uint64_t p00_ar[2*sizeof(p99x_uintmax)/sizeof(uint64_t)];
01176   size_t p00_pos = 0;
01177   for (; p00_val >= UINT64_D19; ++p00_pos) {
01178     /* These operations are expensive, so avoid them whenever we
01179        can. */
01180     p00_ar[p00_pos] = (uint64_t)(p00_val % UINT64_D19);
01181     p00_val /= UINT64_D19;
01182   }
01183   p00_str += sprintf(p00_str, "%" PRIu64, (uint64_t)p00_val);
01184   while (p00_pos) {
01185     --p00_pos;
01186     p00_str += sprintf(p00_str, "%019" PRIu64, p00_ar[p00_pos]);
01187   }
01188 }
01189 p99_inline
01190 char* p00_sprint_p99x_uintmax_u(p99x_uintmax p00_val, char*restrict p00_str) {
01191   p00_sprint_p99x_uintmax_u_ite(p00_val, p00_str);
01192   return p00_str;
01193 }
01194 #define UINT64_O21 (~(UINT64_C(1)<<63))
01195 p99_inline
01196 void p00_sprint_p99x_uintmax_o_ite(p99x_uintmax p00_val, char*restrict p00_str) {
01197   uint64_t p00_ar[3*sizeof(p99x_uintmax)/sizeof(uint64_t)];
01198   size_t p00_pos = 0;
01199   for (;;) {
01200     /* Mask and shift in that case are less expensive. */
01201     p00_ar[p00_pos] = ((uint64_t)p00_val) & UINT64_O21;
01202     p00_val >>= 63;
01203     if (!p00_val) break;
01204     ++p00_pos;
01205   }
01206   p00_str += sprintf(p00_str, "%#" PRIo64, p00_ar[p00_pos]);
01207   while (p00_pos) {
01208     --p00_pos;
01209     p00_str += sprintf(p00_str, "%021" PRIo64, p00_ar[p00_pos]);
01210   }
01211 }
01212 p99_inline
01213 char* p00_sprint_p99x_uintmax_o(p99x_uintmax p00_val, char*restrict p00_str) {
01214   p00_sprint_p99x_uintmax_o_ite(p00_val, p00_str);
01215   return p00_str;
01216 }
01217 p99_inline
01218 void p00_sprint_p99x_uintmax_X_ite(p99x_uintmax p00_val, char*restrict p00_str) {
01219   uint64_t p00_ar[2*sizeof(p99x_uintmax)/sizeof(uint64_t)];
01220   size_t p00_pos = 0;
01221   for (;;) {
01222     /* Mask and shift in that case are less expensive. */
01223     p00_ar[p00_pos] = (uint64_t)p00_val;
01224     p00_val >>= 64;
01225     if (!p00_val) break;
01226     ++p00_pos;
01227   }
01228   p00_str += sprintf(p00_str, "%#" PRIX64, p00_ar[p00_pos]);
01229   while (p00_pos) {
01230     --p00_pos;
01231     p00_str += sprintf(p00_str, "%016" PRIX64, p00_ar[p00_pos]);
01232   }
01233 }
01234 p99_inline
01235 char const* p00_sprint_p99x_uintmax_X(p99x_uintmax p00_val, char*restrict p00_str) {
01236   p00_sprint_p99x_uintmax_X_ite(p00_val, p00_str);
01237   return p00_str;
01238 }
01239 
01240 p99_inline
01241 char const* p00_sprint_p99x_intmax(p99x_intmax p00_val, char*restrict p00_str, unsigned p00_form) {
01242   P99_UNUSED(p00_form);
01243   if (p00_val < 0) {
01244     p00_str[0] = '-';
01245     p00_sprint_p99x_uintmax_u(-p00_val, p00_str + 1);
01246   } else {
01247     p00_sprint_p99x_uintmax_u(p00_val, p00_str);
01248   }
01249   return p00_str;
01250 }
01251 
01252 p99_inline
01253 char const* p00_sprint_p99x_uintmax(p99x_uintmax p00_val, char*restrict p00_str, unsigned p00_form) {
01254   switch (p00_form) {
01255   default: return p00_sprint_p99x_uintmax_u(p00_val, p00_str);
01256   case 1: return p00_sprint_p99x_uintmax_X(p00_val, p00_str);
01257   case 2: return p00_sprint_p99x_uintmax_o(p00_val, p00_str);
01258   }
01259 }
01260 #endif
01261 
01262 
01263 
01264 #define P00_SPRINT(NAME, T, I)                                 \
01265   (T, P99_PASTE2(p00_sprint_, T)),                             \
01266   (T const, P99_PASTE2(p00_sprint_, T)),                       \
01267   (T volatile, P99_PASTE2(p00_sprint_, T)),                    \
01268   (T const volatile, P99_PASTE2(p00_sprint_, T))
01269 
01270 
01271 #define P00_SPRINT_LIST_(...)                                        \
01272   P99_FOR(, P99_NARG(__VA_ARGS__), P00_SEQ, P00_SPRINT, __VA_ARGS__)
01273 
01274 #define P00_SPRINT_LIST() P00_SPRINT_LIST_(P99_EXT_ARITHMETIC_TYPES)
01275 
01276 #define P00_SPRINT_FORMAT_(X, A, ...)                                      \
01277 P99_GENERIC((X),                                                           \
01278             p00_sprint_voidp,                                              \
01279             (char*, p00_sprint_charp),                                     \
01280             (char const*, p00_sprint_charp),                               \
01281             (char*const, p00_sprint_charp),                                \
01282             (char const*const, p00_sprint_charp),                          \
01283             (char*volatile, p00_sprint_charp),                             \
01284             (char const*volatile, p00_sprint_charp),                       \
01285             (char*const volatile, p00_sprint_charp),                       \
01286             (char const*const volatile, p00_sprint_charp),                 \
01287             (char*restrict, p00_sprint_charp),                             \
01288             (char const*restrict, p00_sprint_charp),                       \
01289             (char*const restrict, p00_sprint_charp),                       \
01290             (char const*const restrict, p00_sprint_charp),                 \
01291             (char*volatile restrict, p00_sprint_charp),                    \
01292             (char const*volatile restrict, p00_sprint_charp),              \
01293             (char*const volatile restrict, p00_sprint_charp),              \
01294             (char const*const volatile restrict, p00_sprint_charp),        \
01295             __VA_ARGS__)((X),                                              \
01296                          /* be sure not to have an array for the sizeof */ \
01297                          /* times a rough estimate for octal conversion */ \
01298                          /* plus a rough offset for floating points */     \
01299                          (char[(sizeof(X+0)*22+64)/8]){ 0 },               \
01300                          (A))
01301 
01302 #define P00_SPRINT_FORMAT(...) P00_SPRINT_FORMAT_(__VA_ARGS__)
01303 
01331 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMAT, 0)
01332 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMAT, 2)
01333 #define P99_FORMAT(...)                                        \
01334 P00_SPRINT_FORMAT                                              \
01335  (P99_IF_LT(P99_NARG(__VA_ARGS__), 2)                          \
01336   (__VA_ARGS__, 0)                                             \
01337   (__VA_ARGS__),                                               \
01338   P00_SPRINT_LIST())
01339 
01340 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMATS, 0)
01341 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMATS, 1)
01342 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FORMATS, 2)
01343 #define P99_FORMATS(...) P99_SEQ(P99_FORMAT, __VA_ARGS__)
01344 #define P00_PRINTF(...) printf(__VA_ARGS__)
01345 
01346 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_PRINTF, 1)
01347 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_PRINTF, 2)
01348 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_PRINTF, 3)
01349 #define P99_PRINTF(FORMAT, ...) printf(FORMAT, P99_FORMATS(__VA_ARGS__))
01350 
01351 #define P00_FPRINTF(...) fprintf(__VA_ARGS__)
01352 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FPRINTF, 2)
01353 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FPRINTF, 3)
01354 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_FPRINTF, 4)
01355 #define P99_FPRINTF(F, FORMAT, ...) fprintf(F, FORMAT, P99_FORMATS(__VA_ARGS__))
01356 
01357 #define P00_SPRINTF(...) sprintf(__VA_ARGS__)
01358 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SPRINTF, 2)
01359 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SPRINTF, 3)
01360 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SPRINTF, 4)
01361 #define P99_SPRINTF(S, FORMAT, ...) sprintf(S, FORMAT, P99_FORMATS(__VA_ARGS__))
01362 
01363 #define P00_SNPRINTF(...) snprintf(__VA_ARGS__)
01364 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SNPRINTF, 3)
01365 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SNPRINTF, 4)
01366 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SNPRINTF, 5)
01367 #define P99_SNPRINTF(S, N, FORMAT, ...) snprintf(S, N, FORMAT, P99_FORMATS(__VA_ARGS__))
01368 
01369 #define P00_DEFINE_IN_RANGE(T)                                   \
01370 P99_CONST_FUNCTION                                               \
01371 p99_inline                                                       \
01372 bool P99_PASTE2(p00_in_range_, T)(T p00_r, T p00_s, T p00_len) { \
01373   return (p00_r >= p00_s) && ((p00_r - p00_s) < p00_len);        \
01374 }
01375 
01376 P99_CONST_FUNCTION
01377 p99_inline
01378 bool p00_in_range_voidp(void* p00_r_, void* p00_s_, size_t p00_len) {
01379   unsigned char* p00_r = p00_r_;
01380   unsigned char* p00_s = p00_s_;
01381   return (p00_r >= p00_s) && ((size_t)(p00_r - p00_s) < p00_len);
01382 }
01383 
01384 P99_SER(P00_DEFINE_IN_RANGE, P99_EXT_REAL_TYPES)
01385 
01386 #define P00_IN_RANGE_PART(NAME, T, I)                          \
01387   (T, P99_PASTE2(p00_in_range_, T)),                           \
01388   (T const, P99_PASTE2(p00_in_range_, T)),                     \
01389   (T volatile, P99_PASTE2(p00_in_range_, T)),                  \
01390   (T const volatile, P99_PASTE2(p00_in_range_, T))
01391 
01392 
01393 #define P00_IN_RANGE_LIST_(...)                                             \
01394   P99_FOR(, P99_NARG(__VA_ARGS__), P00_SEQ, P00_IN_RANGE_PART, __VA_ARGS__)
01395 
01396 #define P00_IN_RANGE_LIST() P00_IN_RANGE_LIST_(P99_EXT_REAL_TYPES)
01397 
01398 #define P00_IN_RANGE(R, S, L, ...)                                           \
01399 P99_GENERIC((1 ? (R) : (S)), p00_in_range_voidp, __VA_ARGS__)((R), (S), (L))
01400 
01411 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_IN_RANGE, 0)
01412 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_IN_RANGE, 1)
01413 #define P99_IN_RANGE(R, S, L) P00_IN_RANGE((R), (S), (L), P00_IN_RANGE_LIST())
01414 
01415 #endif
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines