Last active
May 24, 2020 00:27
-
-
Save pkhuong/8e575dcade519d42436a302e9c8a5844 to your computer and use it in GitHub Desktop.
BridgeTC: a bridge from C types to C singleton values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -*- mode: C -*- */ | |
#if BRIDGETC_IMPL_DIGIT_1 == 0 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 1 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_1 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 1 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 2 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_2 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 2 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 3 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_3 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 3 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 4 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_4 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 4 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 5 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_5 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 5 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 6 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_6 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 6 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 7 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_7 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 7 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 8 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_8 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 8 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 9 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_9 | |
#elif BRIDGETC_IMPL_DIGIT_1 == 9 | |
# undef BRIDGETC_IMPL_DIGIT_1 | |
# define BRIDGETC_IMPL_DIGIT_1 0 | |
# undef BRIDGETC_IMPL_SEARCH_1 | |
# define BRIDGETC_IMPL_SEARCH_1 BRIDGETC_IMPL_SEARCH_1_0 | |
# include "bridgetc_digit_update_2.inc" | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -*- mode: C -*- */ | |
#if BRIDGETC_IMPL_DIGIT_2 == 0 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 1 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_1 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 1 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 2 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_2 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 2 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 3 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_3 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 3 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 4 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_4 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 4 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 5 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_5 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 5 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 6 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_6 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 6 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 7 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_7 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 7 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 8 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_8 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 8 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 9 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_9 | |
#elif BRIDGETC_IMPL_DIGIT_2 == 9 | |
# undef BRIDGETC_IMPL_DIGIT_2 | |
# define BRIDGETC_IMPL_DIGIT_2 0 | |
# undef BRIDGETC_IMPL_SEARCH_2 | |
# define BRIDGETC_IMPL_SEARCH_2 BRIDGETC_IMPL_SEARCH_2_0 | |
# error "BTC mapping limit exceeded (999)" | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#define BRIDGETC_IMPL_NEXT BRIDGETC_IMPL_ID(BRIDGETC_IMPL_DIGIT_2, BRIDGETC_IMPL_DIGIT_1, BRIDGETC_IMPL_DIGIT_0) | |
#define BRIDGETC_IMPL_ID(BTC_V0, BTC_V1, BTC_V2) BRIDGETC_IMPL_ID_(BTC_V0, BTC_V1, BTC_V2) | |
#define BRIDGETC_IMPL_ID_(BTC_V0, BTC_V1, BTC_V2) BTC_value_##BTC_V0##BTC_V1##BTC_V2 | |
#define BRIDGETC_IMPL_DIGIT_0 0 | |
#define BRIDGETC_IMPL_SEARCH_0(BTC_X, BTC_DEFAULT) BTC_DEFAULT | |
#define BRIDGETC_IMPL_DIGIT_1 0 | |
#define BRIDGETC_IMPL_SEARCH_1(BTC_X, BTC_DEFAULT) BTC_DEFAULT | |
#define BRIDGETC_IMPL_DIGIT_2 0 | |
#define BRIDGETC_IMPL_SEARCH_2(BTC_X, BTC_DEFAULT) BTC_DEFAULT | |
#define BRIDGETC_IMPL_SEARCH(BTC_X, BTC_DEFAULT, ...) \ | |
BRIDGETC_IMPL_SEARCH_0(BTC_X, \ | |
BRIDGETC_IMPL_SEARCH_1(BTC_X, \ | |
BRIDGETC_IMPL_SEARCH_2(BTC_X, BTC_DEFAULT))) | |
#define BTC_SEARCH(BTC_X, ...) BRIDGETC_IMPL_SEARCH(__typeof__(BTC_X), ##__VA_ARGS__, (void)0) | |
#define BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, BTC_V0, BTC_DEFAULT) \ | |
__builtin_choose_expr( \ | |
__builtin_types_compatible_p(BTC_X, \ | |
__typeof__(BRIDGETC_IMPL_ID(BTC_V2, BTC_V1, BTC_V0))), \ | |
BRIDGETC_IMPL_ID(BTC_V2, BTC_V1, BTC_V0), BTC_DEFAULT) | |
#define BRIDGETC_IMPL_SEARCH_0_(BTC_X, BTC_V0, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BRIDGETC_IMPL_DIGIT_2, BRIDGETC_IMPL_DIGIT_1, BTC_V0, BTC_DEFAULT) | |
#define BRIDGETC_IMPL_SEARCH_0_0(BTC_X, BTC_DEFAULT) \ | |
BTC_DEFAULT | |
#define BRIDGETC_IMPL_SEARCH_0_1(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT) | |
#define BRIDGETC_IMPL_SEARCH_0_2(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT)) | |
#define BRIDGETC_IMPL_SEARCH_0_3(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT))) | |
#define BRIDGETC_IMPL_SEARCH_0_4(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT)))) | |
#define BRIDGETC_IMPL_SEARCH_0_5(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT))))) | |
#define BRIDGETC_IMPL_SEARCH_0_6(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT)))))) | |
#define BRIDGETC_IMPL_SEARCH_0_7(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT))))))) | |
#define BRIDGETC_IMPL_SEARCH_0_8(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 7, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT)))))))) | |
#define BRIDGETC_IMPL_SEARCH_0_9(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 8, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 7, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_0_(BTC_X, 0, \ | |
BTC_DEFAULT))))))))) | |
#define BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, BTC_V1, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 0, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 1, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 2, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 3, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 4, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 5, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 6, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 7, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 8, \ | |
BRIDGETC_IMPL_TEST_0(BTC_X, BTC_V2, BTC_V1, 9, \ | |
BTC_DEFAULT)))))))))) | |
#define BRIDGETC_IMPL_SEARCH_1_(BTC_X, BTC_V1, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BRIDGETC_IMPL_DIGIT_2, BTC_V1, BTC_DEFAULT) | |
#define BRIDGETC_IMPL_SEARCH_1_0(BTC_X, BTC_DEFAULT) \ | |
BTC_DEFAULT | |
#define BRIDGETC_IMPL_SEARCH_1_1(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT) | |
#define BRIDGETC_IMPL_SEARCH_1_2(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT)) | |
#define BRIDGETC_IMPL_SEARCH_1_3(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT))) | |
#define BRIDGETC_IMPL_SEARCH_1_4(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT)))) | |
#define BRIDGETC_IMPL_SEARCH_1_5(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT))))) | |
#define BRIDGETC_IMPL_SEARCH_1_6(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT)))))) | |
#define BRIDGETC_IMPL_SEARCH_1_7(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT))))))) | |
#define BRIDGETC_IMPL_SEARCH_1_8(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 7, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT)))))))) | |
#define BRIDGETC_IMPL_SEARCH_1_9(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 8, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 7, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_1_(BTC_X, 0, \ | |
BTC_DEFAULT))))))))) | |
#define BRIDGETC_IMPL_TEST_2(BTC_X, BTC_V2, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 0, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 1, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 2, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 3, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 4, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 5, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 6, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 7, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 8, \ | |
BRIDGETC_IMPL_TEST_1(BTC_X, BTC_V2, 9, \ | |
BTC_DEFAULT)))))))))) | |
#define BRIDGETC_IMPL_SEARCH_2_(BTC_X, BTC_V2, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_TEST_2(BTC_X, BTC_V2, BTC_DEFAULT) | |
#define BRIDGETC_IMPL_SEARCH_2_0(BTC_X, BTC_DEFAULT) \ | |
BTC_DEFAULT | |
#define BRIDGETC_IMPL_SEARCH_2_1(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT) | |
#define BRIDGETC_IMPL_SEARCH_2_2(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT)) | |
#define BRIDGETC_IMPL_SEARCH_2_3(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT))) | |
#define BRIDGETC_IMPL_SEARCH_2_4(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT)))) | |
#define BRIDGETC_IMPL_SEARCH_2_5(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT))))) | |
#define BRIDGETC_IMPL_SEARCH_2_6(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT)))))) | |
#define BRIDGETC_IMPL_SEARCH_2_7(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT))))))) | |
#define BRIDGETC_IMPL_SEARCH_2_8(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 7, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT)))))))) | |
#define BRIDGETC_IMPL_SEARCH_2_9(BTC_X, BTC_DEFAULT) \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 8, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 7, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 6, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 5, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 4, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 3, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 2, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 1, \ | |
BRIDGETC_IMPL_SEARCH_2_(BTC_X, 0, \ | |
BTC_DEFAULT))))))))) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -*- mode: C -*- */ | |
#include "bridgetc_prologue.h" | |
#pragma GCC diagnostic push | |
#ifndef __clang__ | |
# pragma GCC diagnostic ignored "-Wold-style-declaration" | |
#endif | |
} static const __attribute__((__unused__)) BRIDGETC_IMPL_NEXT; | |
#pragma GCC diagnostic pop | |
_Static_assert(__builtin_types_compatible_p(void, \ | |
__typeof__(BTC_SEARCH(BRIDGETC_IMPL_NEXT))), \ | |
"Only one singleton may be associated with each type."); | |
static __typeof__(BRIDGETC_IMPL_NEXT) BRIDGETC_IMPL_NEXT = { | |
#if BRIDGETC_IMPL_DIGIT_0 == 0 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 1 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_1 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 1 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 2 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_2 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 2 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 3 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_3 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 3 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 4 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_4 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 4 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 5 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_5 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 5 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 6 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_6 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 6 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 7 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_7 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 7 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 8 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_8 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 8 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 9 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_9 | |
#elif BRIDGETC_IMPL_DIGIT_0 == 9 | |
# undef BRIDGETC_IMPL_DIGIT_0 | |
# define BRIDGETC_IMPL_DIGIT_0 0 | |
# undef BRIDGETC_IMPL_SEARCH_0 | |
# define BRIDGETC_IMPL_SEARCH_0 BRIDGETC_IMPL_SEARCH_0_0 | |
# include "bridgetc_digit_update_1.inc" | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Generator for type singletons in C. | |
# | |
# Let's say you have a data structure with some extensible behaviour | |
# (e.g., user-defined hashing and equality testing functions). One | |
# might use a vtable, but, in most cases, the calling code isn't | |
# late-bound: while containers might be type-generic, their users | |
# rarely are, in C. | |
# | |
# Ideally, we would have something like a vtable, except without any | |
# per-instance space usage overhead, and, ideally, transparent enough | |
# for C compilers to optimise away the indirection. | |
# | |
# That's what B(ridge)TC provides: a way to encode references to C | |
# variables in *C types*, and a conversion back from these types to | |
# the variables' values, all optimised away at compile-time. | |
# | |
# With apologies to Helen Fielding and her famous singleton, Bridget. | |
# The generator, as well as its output, is MIT Licensed. | |
# | |
# Copyright 2020 Paul Khuong | |
# | |
# Permission is hereby granted, free of charge, to any person | |
# obtaining a copy of this software and associated documentation files | |
# (the "Software"), to deal in the Software without restriction, | |
# including without limitation the rights to use, copy, modify, merge, | |
# publish, distribute, sublicense, and/or sell copies of the Software, | |
# and to permit persons to whom the Software is furnished to do so, | |
# subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be | |
# included in all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
# SOFTWARE. | |
FILE_PREFIX = "bridgetc" | |
IMPL = "BRIDGETC_IMPL" | |
NS = "BTC" | |
# We increment in CPP by storing different digits in different | |
# variables, and updating each with an #if ladder. | |
# Spread our state across 3 variables, which lets us count to 998 | |
# (there's an off by one that's not worth fixing). | |
NUM_DIGITS = 3 | |
# And count in radix 10; make this lower to have an easier time | |
# testing higher digit counts. | |
RADIX = 10 | |
assert RADIX <= 10, "Pasting digits stops working above 10" | |
IDENTIFIERS = [f"{NS}_V{i}" for i in range(NUM_DIGITS)] | |
DIGIT_VARS = [f"{IMPL}_DIGIT_{i}" for i in range(NUM_DIGITS)] | |
def enumerate_search_cases(digit, out): | |
acc = f"{NS}_DEFAULT" | |
for i in range(RADIX): | |
print( | |
f"""\ | |
#define {IMPL}_SEARCH_{digit}_{i}({NS}_X, {NS}_DEFAULT) \\ | |
{acc} | |
""", | |
file=out, | |
) | |
acc = f"{IMPL}_SEARCH_{digit}_({NS}_X, {i},\t\\\n\t{acc})" | |
def generate_prologue(path=f"{FILE_PREFIX}_prologue.h"): | |
id_list = ", ".join(IDENTIFIERS) | |
with open(path, "w") as out: | |
print( | |
f"""\ | |
#pragma once | |
#define {IMPL}_NEXT {IMPL}_ID({", ".join(reversed(DIGIT_VARS))}) | |
#define {IMPL}_ID({id_list}) {IMPL}_ID_({id_list}) | |
#define {IMPL}_ID_({id_list}) {NS}_value_##{"##".join(IDENTIFIERS)} | |
""", | |
file=out, | |
) | |
for i in range(NUM_DIGITS): | |
print(f"#define {IMPL}_DIGIT_{i} 0", file=out) | |
print( | |
f"#define {IMPL}_SEARCH_{i}({NS}_X, {NS}_DEFAULT) {NS}_DEFAULT", | |
file=out, | |
) | |
# The __builtin_types_compatible_p implementation needs to | |
# nest these search macros. The implementation is a bit nicer | |
# with _Generic. | |
search_expr = ( | |
"\\\n\t".join(f"{IMPL}_SEARCH_{i}({NS}_X, " for i in range(NUM_DIGITS)) | |
+ f"{NS}_DEFAULT" | |
+ NUM_DIGITS * ")" | |
) | |
print( | |
f""" | |
#define {IMPL}_SEARCH({NS}_X, {NS}_DEFAULT, ...) \\ | |
{search_expr} | |
#define {NS}_SEARCH({NS}_X, ...) {IMPL}_SEARCH(__typeof__({NS}_X), ##__VA_ARGS__, (void)0) | |
""", | |
file=out, | |
) | |
# Base case for the __builtin_types_compatible_p search. | |
rident = ", ".join(reversed(IDENTIFIERS)) | |
digits = list(reversed(DIGIT_VARS[1:])) | |
var = IDENTIFIERS[0] | |
print( | |
f"""\ | |
#define {IMPL}_TEST_0({NS}_X, {rident}, {NS}_DEFAULT) \\ | |
__builtin_choose_expr( \\ | |
__builtin_types_compatible_p({NS}_X, \\ | |
__typeof__({IMPL}_ID({rident}))), \\ | |
{IMPL}_ID({rident}), {NS}_DEFAULT) | |
#define {IMPL}_SEARCH_0_({NS}_X, {var}, {NS}_DEFAULT) \\ | |
{IMPL}_TEST_0({NS}_X, {", ".join(digits + [var])}, {NS}_DEFAULT) | |
""", | |
file=out, | |
) | |
enumerate_search_cases(0, out) | |
for i in range(1, NUM_DIGITS): | |
variant = list(reversed(IDENTIFIERS[i:])) | |
digits = list(reversed(DIGIT_VARS[i + 1 :])) | |
var = IDENTIFIERS[i] | |
prev_test = f"{IMPL}_TEST_{i - 1}" | |
acc = f"{NS}_DEFAULT" | |
for enumerated in reversed(range(RADIX)): | |
args = ", ".join(variant + [str(enumerated)]) | |
acc = f"{prev_test}({NS}_X, {args},\t\\\n\t{acc})" | |
print( | |
f"""\ | |
#define {IMPL}_TEST_{i}({NS}_X, {", ".join(variant)}, {NS}_DEFAULT) \\ | |
{acc} | |
#define {IMPL}_SEARCH_{i}_({NS}_X, {var}, {NS}_DEFAULT) \\ | |
{IMPL}_TEST_{i}({NS}_X, {", ".join(digits + [var])}, {NS}_DEFAULT) | |
""", | |
file=out, | |
) | |
enumerate_search_cases(i, out) | |
generate_prologue() | |
def generate_digit_update(digit, out): | |
var = f"{IMPL}_DIGIT_{digit}" | |
search = f"{IMPL}_SEARCH_{digit}" | |
conditional = "if" | |
for i in range(RADIX): | |
succ = (i + 1) % RADIX | |
print( | |
f"""\ | |
#{conditional} {var} == {i} | |
# undef {var} | |
# define {var} {succ} | |
# undef {search} | |
# define {search} {search}_{succ}\ | |
""", | |
file=out, | |
) | |
conditional = "elif" | |
next_digit = digit + 1 | |
if next_digit == NUM_DIGITS: | |
print( | |
f"""# error "BTC mapping limit exceeded ({RADIX ** NUM_DIGITS - 1})"\ | |
""", | |
file=out, | |
) | |
else: | |
print( | |
f"""# include "{FILE_PREFIX}_digit_update_{next_digit}.inc"\ | |
""", | |
file=out, | |
) | |
print("#endif", file=out) | |
for digit in range(1, NUM_DIGITS): | |
with open(f"{FILE_PREFIX}_digit_update_{digit}.inc", "w") as out: | |
print("/* -*- mode: C -*- */", file=out) | |
generate_digit_update(digit, out) | |
def generate_register(out): | |
print( | |
f"""\ | |
/* -*- mode: C -*- */ | |
#include "{FILE_PREFIX}_prologue.h" | |
#pragma GCC diagnostic push | |
#ifndef __clang__ | |
# pragma GCC diagnostic ignored "-Wold-style-declaration" | |
#endif | |
}} static const __attribute__((__unused__)) {IMPL}_NEXT; | |
#pragma GCC diagnostic pop | |
_Static_assert(__builtin_types_compatible_p(void, \\ | |
__typeof__({NS}_SEARCH({IMPL}_NEXT))), \\ | |
"Only one singleton may be associated with each type."); | |
static __typeof__({IMPL}_NEXT) {IMPL}_NEXT = {{ | |
""", | |
file=out, | |
) | |
generate_digit_update(0, out) | |
with open(f"{FILE_PREFIX}_register.inc", "w") as out: | |
generate_register(out) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct foo { | |
int x; | |
#include "bridgetc_register.inc" | |
.x = 42, | |
}; | |
struct bar { | |
double x; | |
#include "bridgetc_register.inc" | |
.x = 1.5, | |
}; | |
int | |
test_foo() | |
{ | |
struct { | |
__attribute__((packed)) struct foo tag[0]; | |
char v; | |
} test; | |
return BTC_SEARCH(test.tag[0]).x; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# gcc -E -W -Wall -O test.c -o - | grep -v '^#' | clang-format-4.0 | |
struct foo { | |
int x; | |
} static const __attribute__((__unused__)) BTC_value_000; | |
_Static_assert(__builtin_types_compatible_p(void, __typeof__((void)0)), | |
"Only one singleton may be associated with each type."); | |
static __typeof__(BTC_value_000) BTC_value_000 = { | |
.x = 42, | |
}; | |
struct bar { | |
double x; | |
} static const __attribute__((__unused__)) BTC_value_001; | |
_Static_assert(__builtin_types_compatible_p( | |
void, | |
__typeof__(__builtin_choose_expr( | |
__builtin_types_compatible_p(__typeof__(BTC_value_001), | |
__typeof__(BTC_value_000)), | |
BTC_value_000, (void)0))), | |
"Only one singleton may be associated with each type."); | |
static __typeof__(BTC_value_001) BTC_value_001 = { | |
.x = 1.5, | |
}; | |
int test_foo() { | |
struct { | |
__attribute__((packed)) struct foo tag[0]; | |
char v; | |
} test; | |
return __builtin_choose_expr( | |
__builtin_types_compatible_p(__typeof__(test.tag[0]), | |
__typeof__(BTC_value_001)), | |
BTC_value_001, | |
__builtin_choose_expr( | |
__builtin_types_compatible_p(__typeof__(test.tag[0]), | |
__typeof__(BTC_value_000)), | |
BTC_value_000, (void)0)) | |
.x; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.file "test.c" | |
.text | |
.globl test_foo | |
.type test_foo, @function | |
test_foo: | |
.LFB0: | |
.cfi_startproc | |
movl $42, %eax | |
ret | |
.cfi_endproc | |
.LFE0: | |
.size test_foo, .-test_foo | |
.ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516" | |
.section .note.GNU-stack,"",@progbits |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment