00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef P99_GENERIC_H_
00014 # define P99_GENERIC_H_
00015
00016 #include "p99_for.h"
00017
00022 #ifndef P00_DOXYGEN
00023
00024 #define P00_GENERIC_TYPE(T, EXP) T
00025 #define P00_GENERIC_SIZE_(UI, EXP) char(*)[UI]
00026 #define P00_GENERIC_EXP_(T, EXP) (EXP)
00027 #define P00_GENERIC_LIT_(T, EXP) (EXP){ 0 }
00028
00029 #define P00_GENERIC_SIZE_LIT(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_SIZE_, P00_GENERIC_LIT_, EXP, PAIR, I)
00030 #define P00_GENERIC_SIZE(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_SIZE_, P00_GENERIC_EXP_, EXP, PAIR, I)
00031 #define P00_GENERIC_EXP(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_TYPE, P00_GENERIC_EXP_, EXP, PAIR, I)
00032 #define P00_GENERIC_LIT(EXP, PAIR, I) P00_GENERIC_EXPRESSION(P00_GENERIC_TYPE, P00_GENERIC_LIT_, EXP, PAIR, I)
00033
00034 #if p99_has_extension(c_generic_selections)
00035
00036 #define P00_GENERIC_EXPRESSION(TOP, EOP, EXP, PAIR, I) \
00037 TOP PAIR: EOP PAIR
00038
00039 #define P00_GENERIC_(N, MOP, EXP, DEF, ...) \
00040 p99_extension \
00041 _Generic \
00042 ((EXP), \
00043 P99_IF_EMPTY(DEF)()(default: (DEF),) \
00044 P99_FOR((EXP), N, P00_SEQ, MOP, __VA_ARGS__) \
00045 )
00046
00047 #elif defined(__GNUC__)
00048
00049 #define P00_GENERIC_CLOSE(A,B,C) )
00050
00051 #define P00_GENERIC_EXPRESSION(TOP, EOP, EXP, PAIR, I) \
00052 __builtin_choose_expr \
00053 (__builtin_types_compatible_p(__typeof__ EXP, TOP PAIR), \
00054 EOP PAIR
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 __attribute__((__error__("Invalid choice in type generic expression")))
00069 extern size_t p00_invalid_type_in_generic(char const*);
00070
00071 #define P00_INVALID_TYPE_IN_GENERIC(EXP, STR) \
00072 p00_invalid_type_in_generic(__FILE__ \
00073 P99_STRINGIFY(:__LINE__) \
00074 ": invalid type generic choice `" \
00075 P99_STRINGIFY(EXP) \
00076 "` for " \
00077 STR)
00078
00079 #define P00_GENERIC_(N, MOP, EXP, DEF, ...) \
00080 P99_FOR((EXP), N, P00_SEQ, MOP, __VA_ARGS__), \
00081 P99_IF_EMPTY(DEF)(P00_INVALID_TYPE_IN_GENERIC(EXP, #__VA_ARGS__))(DEF) \
00082 P99_FOR(, N, P00_SER, P00_GENERIC_CLOSE, P99_DUPL(N, ))
00083
00084 #endif
00085
00086 #define P00_GENERIC0(MOP, EXP, DEF, ...) \
00087 P00_GENERIC_ \
00088 ( \
00089 P99_NARG(__VA_ARGS__), \
00090 P00_ROBUST(MOP), \
00091 P00_ROBUST(EXP), \
00092 P00_ROBUST(DEF), \
00093 __VA_ARGS__)
00094
00095 #define P00_GENERIC(N, ...) P99_IF_LT(N, 3)()(P00_GENERIC0(__VA_ARGS__))
00096
00097 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC, 0)
00098 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC, 2)
00099 #define P99_GENERIC(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_EXP, __VA_ARGS__)
00100
00101 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_LIT, 0)
00102 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_LIT, 2)
00103 #define P99_GENERIC_LIT(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_LIT, __VA_ARGS__)
00104
00105 #define P00_GENERIC_SIZE0(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_SIZE, __VA_ARGS__)
00106
00107 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 0)
00108 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 2)
00109 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE, 3)
00110 #define P99_GENERIC_SIZE(UI, ...) P00_GENERIC_SIZE0((char(*)[(size_t)(UI)]){ 0 }, __VA_ARGS__)
00111
00112 #define P00_GENERIC_SIZE_LIT0(...) P00_GENERIC(P99_NARG(__VA_ARGS__), P00_GENERIC_SIZE_LIT, __VA_ARGS__)
00113
00114 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 0)
00115 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 2)
00116 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GENERIC_SIZE_LIT, 3)
00117 #define P99_GENERIC_SIZE_LIT(UI, ...) P00_GENERIC_SIZE_LIT0((char(*)[(size_t)(UI)]){ 0 }, __VA_ARGS__)
00118
00119
00120 #if p99_has_extension(c_generic_selections)
00121
00122 # define P99_TYPED_TERN(COND, YES, NO) \
00123 (P99_GENERIC \
00124 ((char(*)[1 + !!(COND)]){ 0 }, \
00125 (NO), \
00126 (char(*)[2], (YES))))
00127
00128 #elif defined(__GNUC__)
00129
00130 # define P99_TYPED_TERN __builtin_choose_expr
00131
00132 #else
00133
00134 #define P99_TYPED_TERN(COND, YES, NO) only_implemented_with_C11_or_gcc
00135
00136
00137 #endif
00138
00139
00140 #define P00_TYPE_CHOICE(YES, T, I) (T, YES)
00141
00142 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 0)
00143 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 1)
00144 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHOICE, 2)
00145 #define P99_TYPE_CHOICE(EXP, YES, NO, ...) \
00146 P99_GENERIC \
00147 ((EXP), \
00148 NO, \
00149 P99_FOR(YES, P99_NARG(__VA_ARGS__), P00_SEQ, P00_TYPE_CHOICE, __VA_ARGS__))
00150
00151 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_UNSIGNED, 0)
00152 #define P99_TYPE_UNSIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_UNSIGNED_TYPES)
00153 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_SIGNED, 0)
00154 #define P99_TYPE_SIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_SIGNED_TYPES)
00155 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_REAL_FLOATING, 0)
00156 #define P99_TYPE_REAL_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_FLOATING_TYPES)
00157 #ifndef __STDC_NO_COMPLEX__
00158 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_COMPLEX, 0)
00159 # define P99_TYPE_COMPLEX(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_COMPLEX_TYPES)
00160 #endif
00161 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_FLOATING, 0)
00162 #define P99_TYPE_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_FLOATING_TYPES)
00163 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_BASIC, 0)
00164 #define P99_TYPE_BASIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_BASIC_TYPES)
00165 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_CHARACTER, 0)
00166 #define P99_TYPE_CHARACTER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_CHARACTER_TYPES)
00167 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_INTEGER, 0)
00168 #define P99_TYPE_INTEGER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_INTEGER_TYPES)
00169 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_REAL, 0)
00170 #define P99_TYPE_REAL(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_TYPES)
00171 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_TYPE_ARITHMETIC, 0)
00172 #define P99_TYPE_ARITHMETIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_ARITHMETIC_TYPES)
00173
00174 #define P00_SIZE_CHOICE(YES, UI, I) (char(*)[(size_t)(UI)], YES)
00175
00176 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 0)
00177 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 1)
00178 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_CHOICE, 2)
00179 #define P99_SIZE_CHOICE(UI, YES, NO, ...) \
00180 P99_GENERIC \
00181 ((char(*)[(size_t)(UI)])0, \
00182 NO, \
00183 P99_FOR(YES, P99_NARG(__VA_ARGS__), P00_SEQ, P00_SIZE_CHOICE, __VA_ARGS__))
00184
00185
00186 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_SIZE_INDICATOR, 0)
00187 #define P99_SIZE_INDICATOR(UI, ...) P99_SIZE_CHOICE(UI, 1, 0, __VA_ARGS__)
00188
00189
00190 #define P00_DECLARE_INLINE_EXPRESSION1(EXT, BASE, EXP, A) \
00191 p99_inline \
00192 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
00193 (P99_BUILTIN_TYPE(EXT) A) \
00194 { \
00195 return (EXP); \
00196 }
00197
00198 #define P00_DECLARE_INLINE_EXPRESSION2(EXT, BASE, EXP, A, B) \
00199 p99_inline \
00200 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
00201 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B) \
00202 { \
00203 return (EXP); \
00204 }
00205
00206 #define P00_DECLARE_INLINE_EXPRESSION3(EXT, BASE, EXP, A, B, C) \
00207 p99_inline \
00208 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
00209 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
00210 P99_BUILTIN_TYPE(EXT) C) \
00211 { \
00212 return (EXP); \
00213 }
00214
00215 #define P00_DECLARE_INLINE_EXPRESSION4(EXT, BASE, EXP, A, B, C, D) \
00216 p99_inline \
00217 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
00218 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
00219 P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D) \
00220 { \
00221 return (EXP); \
00222 }
00223
00224 #define P00_DECLARE_INLINE_EXPRESSION5(EXT, BASE, EXP, A, B, C, D, E) \
00225 p99_inline \
00226 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
00227 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
00228 P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D, \
00229 P99_BUILTIN_TYPE(EXT) E) \
00230 { \
00231 return (EXP); \
00232 }
00233
00234 #define P00_DECLARE_INLINE_EXPRESSION6(EXT, BASE, EXP, A, B, C, D, E, F) \
00235 p99_inline \
00236 P99_BUILTIN_TYPE(EXT) P99_PASTE3(p00_gen_, BASE, EXT) \
00237 (P99_BUILTIN_TYPE(EXT) A, P99_BUILTIN_TYPE(EXT) B, \
00238 P99_BUILTIN_TYPE(EXT) C, P99_BUILTIN_TYPE(EXT) D, \
00239 P99_BUILTIN_TYPE(EXT) E, P99_BUILTIN_TYPE(EXT) F) \
00240 { \
00241 return (EXP); \
00242 }
00243
00244 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 0)
00245 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 1)
00246 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_DECLARE_INLINE_EXPRESSION, 2)
00247 #define P99_DECLARE_INLINE_EXPRESSION(...) \
00248 P99_PASTE2(P00_DECLARE_INLINE_EXPRESSION, P99_MINUS(P99_NARG(__VA_ARGS__), 3))(__VA_ARGS__)
00249
00250 #define P00_DECLARE_INLINE_EXPRESSION_(...) P99_DECLARE_INLINE_EXPRESSION(__VA_ARGS__)
00251 #define P00_DECLARE_INLINE_EXPRESSION(ARGS, EXT, I) P00_DECLARE_INLINE_EXPRESSION_(EXT, P00_ROBUST ARGS)
00252
00253 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_DECLARE_INLINE_EXPRESSIONS, 0)
00254 #define P99_DECLARE_INLINE_EXPRESSIONS(NEPL, ...) \
00255 P99_FOR(NEPL, P99_NARG(__VA_ARGS__), P00_SER, P00_DECLARE_INLINE_EXPRESSION, __VA_ARGS__) \
00256 P99_MACRO_END(P99_DECLARE_INLINE_EXPRESSIONS, __VA_ARGS__)
00257
00258 extern void p00_invalid_function(void*, ...);
00259
00260 #define P00_GEN_EXPR(BASE, EXT, I) (P99_BUILTIN_TYPE(EXT), P99_PASTE3(p00_gen_, BASE, EXT))
00261
00262 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_GEN_EXPR, 0)
00263 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_EXPR, 1)
00264 #define P99_GEN_EXPR(BASE, EXPR, ...) \
00265 P99_GENERIC(EXPR, \
00266 p00_invalid_function, \
00267 P99_FOR(BASE, P99_NARG(__VA_ARGS__), P00_SEQ, P00_GEN_EXPR, __VA_ARGS__))
00268
00269
00270
00271
00272 P99_DECLARE_INLINE_EXPRESSIONS((maximum,
00273 (p00_a >= p00_b) ? p00_a : p00_b,
00274 p00_a, p00_b),
00275 P99_STD_REAL_EXTS
00276 );
00277
00278 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MAX, 0)
00279 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MAX, 1)
00280 #define P99_GEN_MAX(A, B) \
00281 P99_GEN_EXPR(maximum, ((A) >= (B)) ? (A) : (B), \
00282 P99_STD_REAL_EXTS \
00283 ) \
00284 ((A), (B))
00285
00286 P99_DECLARE_INLINE_EXPRESSIONS((minimum,
00287 (p00_a <= p00_b) ? p00_a : p00_b,
00288 p00_a, p00_b),
00289 P99_STD_REAL_EXTS
00290 );
00291
00292 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MIN, 0)
00293 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_MIN, 1)
00294 #define P99_GEN_MIN(A, B) \
00295 P99_GEN_EXPR(minimum, ((A) <= (B)) ? (A) : (B), \
00296 P99_STD_REAL_EXTS \
00297 ) \
00298 ((A), (B))
00299
00300
00301 P99_DECLARE_INLINE_EXPRESSIONS((abs,
00302 (p00_a >= 0) ? p00_a : -p00_a,
00303 p00_a),
00304 P99_STD_REAL_EXTS
00305 );
00306
00307 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_ABS, 0)
00308 #define P99_GEN_ABS(A) P99_GEN_EXPR(abs, ((A) >= 0) ? (A) : -(A), P99_STD_REAL_EXTS)(A)
00309
00310 #define p00_gen_sind sin
00311 #define p00_gen_sinf sinf
00312 #define p00_gen_sinld sinl
00313 #define p00_gen_sindc csin
00314 #define p00_gen_sinfc csinf
00315 #define p00_gen_sinldc csinl
00316
00317 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_GEN_SIN, 0)
00318 #define P99_GEN_SIN(A) P99_GEN_EXPR(sin, (A), P99_STD_FLOATING_EXTS)(A)
00319
00320 inline int* p00_generic_test(int * p00_a) {
00321 double *p00_x;
00322 switch (P99_GEN_ABS(*p00_a % 3)) {
00323 case 0:
00324 return P99_GENERIC(&*p00_a,
00325 ,
00326 (int*, p00_a),
00327 (double*, p00_x+1),
00328 (float*, p00_x+2));
00329 case 1:
00330 return P99_GENERIC(&*p00_a,
00331 ,
00332 (double[7], P99_GEN_SIN(((p00_x+0)))),
00333 (int*, p00_a),
00334 (float*, p00_x+2));
00335 default:
00336 return P99_GENERIC(&*p00_a,
00337 p00_x,
00338 (double*, p00_x+0),
00339 (float[7], p00_x+1),
00340 (int*, p00_a));
00341 }
00342 }
00343
00344 #else
00345
00442 #define P99_GENERIC(...)
00443
00463 #define P99_GENERIC_LIT(...)
00464
00496 #define P99_GENERIC_SIZE(UI, ...)
00497
00506 #define P99_GENERIC_SIZE_LIT(UI, ...)
00507
00517 #define P99_TYPED_TERN(COND, YES, NO)
00518
00525 #define P00_TYPE_CHOICE(YES, T, I) (T, YES)
00526
00534 #define P99_TYPE_CHOICE(EXP, YES, NO, ...)
00535
00542 #define P99_TYPE_UNSIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_UNSIGNED_TYPES)
00543 #define P99_TYPE_SIGNED(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_SIGNED_TYPES)
00544 #define P99_TYPE_REAL_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_FLOATING_TYPES)
00545 # define P99_TYPE_COMPLEX(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_COMPLEX_TYPES)
00546 #define P99_TYPE_FLOATING(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_FLOATING_TYPES)
00547 #define P99_TYPE_BASIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_BASIC_TYPES)
00548 #define P99_TYPE_CHARACTER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_CHARACTER_TYPES)
00549 #define P99_TYPE_INTEGER(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_INTEGER_TYPES)
00550 #define P99_TYPE_REAL(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_REAL_TYPES)
00551 #define P99_TYPE_ARITHMETIC(EXP) P99_TYPE_CHOICE((EXP), 1, 0, P99_STD_ARITHMETIC_TYPES)
00552
00570 #define P99_SIZE_CHOICE(UI, YES, NO, ...)
00571
00591 #define P99_SIZE_INDICATOR(UI, ...)
00592
00629 #define P99_DECLARE_INLINE_EXPRESSION(EXT, BASE, EXP, ...)
00630
00664 #define P99_DECLARE_INLINE_EXPRESSIONS(NEPL, ...)
00665
00666 extern void p00_invalid_function(void*, ...);
00667
00738 #define P99_GEN_EXPR(BASE, EXPR, ...)
00739
00740 #define P99_GEN_MAX(A, B) \
00741 P99_GEN_EXPR(maximum, ((A) >= (B)) ? (A) : (B), \
00742 P99_STD_REAL_EXTS \
00743 ) \
00744 ((A), (B))
00745
00746 #define P99_GEN_MIN(A, B) \
00747 P99_GEN_EXPR(minimum, ((A) <= (B)) ? (A) : (B), \
00748 P99_STD_REAL_EXTS \
00749 ) \
00750 ((A), (B))
00751
00752
00753 #define P99_GEN_ABS(A) P99_GEN_EXPR(abs, ((A) >= 0) ? (A) : -(A), P99_STD_REAL_EXTS)(A)
00754
00761 #define P99_GEN_SIN(A) P99_GEN_EXPR(sin, (A), P99_STD_FLOATING_EXTS)(A)
00762
00767 #endif
00768
00769
00770 #endif