#include "boost/preprocessor.hpp"
#define XXX_PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define XXX_PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#define XXX_PP_NARG_(...) \
XXX_PP_ARG_N(__VA_ARGS__)
#define XXX_PP_NARG(...) \
XXX_PP_NARG_(__VA_ARGS__,XXX_PP_RSEQ_N())
#define XXX_TUPLE_SIZE_INTERNAL(TUPLE) XXX_PP_NARG TUPLE
#define XXX_TUPLE_CHOICE(i) \
BOOST_PP_APPLY( \
BOOST_PP_TUPLE_ELEM( \
25, i, (\
(0), (1), (2), (3) , (4) , (5) , (6) , (7) , (8) , (9) , (10) , (11) \
, (12) , (13) , (14) , (15) , (16) , (17) , (18) , (19) , (20) , (21) \
, (22) , (23) , (24) \
) \
) \
)
#define BOOST_PP_BOOL_00 BOOST_PP_BOOL_0
#define BOOST_PP_BOOL_01 BOOST_PP_BOOL_1
#define BOOST_PP_BOOL_02 BOOST_PP_BOOL_2
#define BOOST_PP_BOOL_03 BOOST_PP_BOOL_3
#define BOOST_PP_BOOL_04 BOOST_PP_BOOL_4
#define BOOST_PP_BOOL_05 BOOST_PP_BOOL_5
#define BOOST_PP_BOOL_06 BOOST_PP_BOOL_6
#define BOOST_PP_BOOL_07 BOOST_PP_BOOL_7
#define BOOST_PP_BOOL_08 BOOST_PP_BOOL_8
#define BOOST_PP_BOOL_09 BOOST_PP_BOOL_9
#define BOOST_PP_BOOL_010 BOOST_PP_BOOL_10
#define BOOST_PP_BOOL_011 BOOST_PP_BOOL_11
#define BOOST_PP_BOOL_012 BOOST_PP_BOOL_12
#define BOOST_PP_BOOL_013 BOOST_PP_BOOL_13
#define BOOST_PP_BOOL_014 BOOST_PP_BOOL_14
#define BOOST_PP_BOOL_015 BOOST_PP_BOOL_15
#define BOOST_PP_BOOL_016 BOOST_PP_BOOL_16
#define BOOST_PP_BOOL_017 BOOST_PP_BOOL_17
#define BOOST_PP_BOOL_018 BOOST_PP_BOOL_18
#define BOOST_PP_BOOL_019 BOOST_PP_BOOL_19
#define BOOST_PP_BOOL_020 BOOST_PP_BOOL_20
#define BOOST_PP_BOOL_021 BOOST_PP_BOOL_21
#define BOOST_PP_BOOL_022 BOOST_PP_BOOL_22
#define BOOST_PP_BOOL_023 BOOST_PP_BOOL_23
#define BOOST_PP_BOOL_024 BOOST_PP_BOOL_24
#define BOOST_PP_BOOL_025 BOOST_PP_BOOL_25
#define BOOST_PP_BOOL_026 BOOST_PP_BOOL_26
#define BOOST_PP_BOOL_027 BOOST_PP_BOOL_27
#define BOOST_PP_BOOL_028 BOOST_PP_BOOL_28
#define BOOST_PP_BOOL_029 BOOST_PP_BOOL_29
#define BOOST_PP_BOOL_030 BOOST_PP_BOOL_30
#define BOOST_PP_BOOL_031 BOOST_PP_BOOL_31
#define BOOST_PP_BOOL_032 BOOST_PP_BOOL_32
#define BOOST_PP_BOOL_033 BOOST_PP_BOOL_33
#define BOOST_PP_BOOL_034 BOOST_PP_BOOL_34
#define BOOST_PP_BOOL_035 BOOST_PP_BOOL_35
#define BOOST_PP_BOOL_036 BOOST_PP_BOOL_36
#define BOOST_PP_BOOL_037 BOOST_PP_BOOL_37
#define BOOST_PP_BOOL_038 BOOST_PP_BOOL_38
#define BOOST_PP_BOOL_039 BOOST_PP_BOOL_39
#define BOOST_PP_BOOL_040 BOOST_PP_BOOL_40
#define BOOST_PP_BOOL_041 BOOST_PP_BOOL_41
#define BOOST_PP_BOOL_042 BOOST_PP_BOOL_42
#define BOOST_PP_BOOL_043 BOOST_PP_BOOL_43
#define BOOST_PP_BOOL_044 BOOST_PP_BOOL_44
#define BOOST_PP_BOOL_045 BOOST_PP_BOOL_45
#define BOOST_PP_BOOL_046 BOOST_PP_BOOL_46
#define BOOST_PP_BOOL_047 BOOST_PP_BOOL_47
#define BOOST_PP_BOOL_048 BOOST_PP_BOOL_48
#define BOOST_PP_BOOL_049 BOOST_PP_BOOL_49
#define BOOST_PP_BOOL_050 BOOST_PP_BOOL_50
#define BOOST_PP_BOOL_051 BOOST_PP_BOOL_51
#define BOOST_PP_BOOL_052 BOOST_PP_BOOL_52
#define BOOST_PP_BOOL_053 BOOST_PP_BOOL_53
#define BOOST_PP_BOOL_054 BOOST_PP_BOOL_54
#define BOOST_PP_BOOL_055 BOOST_PP_BOOL_55
#define BOOST_PP_BOOL_056 BOOST_PP_BOOL_56
#define BOOST_PP_BOOL_057 BOOST_PP_BOOL_57
#define BOOST_PP_BOOL_058 BOOST_PP_BOOL_58
#define BOOST_PP_BOOL_059 BOOST_PP_BOOL_59
#define BOOST_PP_BOOL_060 BOOST_PP_BOOL_60
#define BOOST_PP_BOOL_061 BOOST_PP_BOOL_61
#define BOOST_PP_BOOL_062 BOOST_PP_BOOL_62
#define BOOST_PP_BOOL_063 BOOST_PP_BOOL_63
#define BOOST_PP_DEC_00 BOOST_PP_DEC_0
#define BOOST_PP_DEC_01 BOOST_PP_DEC_1
#define BOOST_PP_DEC_02 BOOST_PP_DEC_2
#define BOOST_PP_DEC_03 BOOST_PP_DEC_3
#define BOOST_PP_DEC_04 BOOST_PP_DEC_4
#define BOOST_PP_DEC_05 BOOST_PP_DEC_5
#define BOOST_PP_DEC_06 BOOST_PP_DEC_6
#define BOOST_PP_DEC_07 BOOST_PP_DEC_7
#define BOOST_PP_DEC_08 BOOST_PP_DEC_8
#define BOOST_PP_DEC_09 BOOST_PP_DEC_9
#define BOOST_PP_DEC_010 BOOST_PP_DEC_10
#define BOOST_PP_DEC_011 BOOST_PP_DEC_11
#define BOOST_PP_DEC_012 BOOST_PP_DEC_12
#define BOOST_PP_DEC_013 BOOST_PP_DEC_13
#define BOOST_PP_DEC_014 BOOST_PP_DEC_14
#define BOOST_PP_DEC_015 BOOST_PP_DEC_15
#define BOOST_PP_DEC_016 BOOST_PP_DEC_16
#define BOOST_PP_DEC_017 BOOST_PP_DEC_17
#define BOOST_PP_DEC_018 BOOST_PP_DEC_18
#define BOOST_PP_DEC_019 BOOST_PP_DEC_19
#define BOOST_PP_DEC_020 BOOST_PP_DEC_20
#define BOOST_PP_DEC_021 BOOST_PP_DEC_21
#define BOOST_PP_DEC_022 BOOST_PP_DEC_22
#define BOOST_PP_DEC_023 BOOST_PP_DEC_23
#define BOOST_PP_DEC_024 BOOST_PP_DEC_24
#define BOOST_PP_DEC_025 BOOST_PP_DEC_25
#define BOOST_PP_DEC_026 BOOST_PP_DEC_26
#define BOOST_PP_DEC_027 BOOST_PP_DEC_27
#define BOOST_PP_DEC_028 BOOST_PP_DEC_28
#define BOOST_PP_DEC_029 BOOST_PP_DEC_29
#define BOOST_PP_DEC_030 BOOST_PP_DEC_30
#define BOOST_PP_DEC_031 BOOST_PP_DEC_31
#define BOOST_PP_DEC_032 BOOST_PP_DEC_32
#define BOOST_PP_DEC_033 BOOST_PP_DEC_33
#define BOOST_PP_DEC_034 BOOST_PP_DEC_34
#define BOOST_PP_DEC_035 BOOST_PP_DEC_35
#define BOOST_PP_DEC_036 BOOST_PP_DEC_36
#define BOOST_PP_DEC_037 BOOST_PP_DEC_37
#define BOOST_PP_DEC_038 BOOST_PP_DEC_38
#define BOOST_PP_DEC_039 BOOST_PP_DEC_39
#define BOOST_PP_DEC_040 BOOST_PP_DEC_40
#define BOOST_PP_DEC_041 BOOST_PP_DEC_41
#define BOOST_PP_DEC_042 BOOST_PP_DEC_42
#define BOOST_PP_DEC_043 BOOST_PP_DEC_43
#define BOOST_PP_DEC_044 BOOST_PP_DEC_44
#define BOOST_PP_DEC_045 BOOST_PP_DEC_45
#define BOOST_PP_DEC_046 BOOST_PP_DEC_46
#define BOOST_PP_DEC_047 BOOST_PP_DEC_47
#define BOOST_PP_DEC_048 BOOST_PP_DEC_48
#define BOOST_PP_DEC_049 BOOST_PP_DEC_49
#define BOOST_PP_DEC_050 BOOST_PP_DEC_50
#define BOOST_PP_DEC_051 BOOST_PP_DEC_51
#define BOOST_PP_DEC_052 BOOST_PP_DEC_52
#define BOOST_PP_DEC_053 BOOST_PP_DEC_53
#define BOOST_PP_DEC_054 BOOST_PP_DEC_54
#define BOOST_PP_DEC_055 BOOST_PP_DEC_55
#define BOOST_PP_DEC_056 BOOST_PP_DEC_56
#define BOOST_PP_DEC_057 BOOST_PP_DEC_57
#define BOOST_PP_DEC_058 BOOST_PP_DEC_58
#define BOOST_PP_DEC_059 BOOST_PP_DEC_59
#define BOOST_PP_DEC_060 BOOST_PP_DEC_60
#define BOOST_PP_DEC_061 BOOST_PP_DEC_61
#define BOOST_PP_DEC_062 BOOST_PP_DEC_62
#define BOOST_PP_DEC_063 BOOST_PP_DEC_63
#define XXX_TO_NUMx(x) 0 ## x
#define XXX_TO_NUM(x) BOOST_PP_ADD(0,XXX_TO_NUMx(x))
#define XXX_STRINGIZEX(x) # x
#define XXX_VSTRINGIZE_SINGLE(a,b,x) XXX_STRINGIZE(x)
#define XXX_VSTRINGIZE_TUPLE(tpl) XXX_TUPLE_FOR_EACH(XXX_VSTRINGIZE_SINGLE,,tpl)
#define XXX_TUPLE_SIZE(TUPLE) XXX_TO_NUM(XXX_TUPLE_CHOICE(XXX_TUPLE_SIZE_INTERNAL(TUPLE)))
#define XXX_TUPLE_FOR_EACH(MACRO,DATA,TUPLE) BOOST_PP_LIST_FOR_EACH(MACRO,DATA,BOOST_PP_TUPLE_TO_LIST(XXX_TUPLE_SIZE(TUPLE),TUPLE))
#define XXX_STRINGIZE(x) XXX_STRINGIZEX(x)
#define XXX_VSTRINGIZE(...) XXX_VSTRINGIZE_TUPLE((__VA_ARGS__))
#define XXX_CAST_TO_VOID_ELEMENT(r,data,elem) (void)(elem);
#define XXX_CAST_TO_VOID_INTERNAL(TUPLE) \
XXX_TUPLE_FOR_EACH(XXX_CAST_TO_VOID_ELEMENT,,TUPLE)
#define XXX_CAST_TO_VOID(...) XXX_CAST_TO_VOID_INTERNAL((__VA_ARGS__))
#define XXX_ENUM_EXTRACT_SP(en) BOOST_PP_TUPLE_ELEM(XXX_TUPLE_SIZE(en),0,en) = BOOST_PP_TUPLE_ELEM(XXX_TUPLE_SIZE(en),1,en)
#define XXX_ENUM_ELEMENT(r,data,elem) BOOST_PP_IF( XXX_TUPLE_SIZE(elem), XXX_ENUM_EXTRACT_SP(elem), elem) ,
#define XXX_ENUM_EXTRACT_ELEMENT(en) BOOST_PP_TUPLE_ELEM(XXX_TUPLE_SIZE(en),0,en)
#define XXX_ENUM_CASE_ELEMENT(en) BOOST_PP_IF( XXX_TUPLE_SIZE(en), XXX_ENUM_EXTRACT_ELEMENT(en), en )
#define XXX_ENUM_CASE(r,data,elem) case data :: XXX_ENUM_CASE_ELEMENT(elem) : return #data "::" XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem));
#define XXX_ENUM_IFELSE(r,data,elem) else if( en == data :: XXX_ENUM_CASE_ELEMENT(elem)) { return #data "::" XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem)); }
#define XXX_ENUM_CASTLIST(r,data,elem) { XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem)), data :: XXX_ENUM_CASE_ELEMENT(elem) },
#define XXX_ENUM_QUALIFIED_CASTLIST(r,data,elem) { #data "::" XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem)), data :: XXX_ENUM_CASE_ELEMENT(elem) },
#define XXX_ENUM_INTERNAL(TYPE,NAME,TUPLE) \
enum TYPE \
{ \
XXX_TUPLE_FOR_EACH(XXX_ENUM_ELEMENT,,TUPLE) \
BOOST_PP_CAT(last_enum_,NAME) \
}; \
\
inline \
const char* to_string( NAME en ) \
{ \
if(false) \
{ \
} \
XXX_TUPLE_FOR_EACH(XXX_ENUM_IFELSE,NAME,TUPLE) \
else if( en == NAME :: BOOST_PP_CAT(last_enum_,NAME) ) \
{ \
return XXX_VSTRINGIZE(NAME,::, BOOST_PP_CAT(last_enum_,NAME)); \
} \
else \
{ \
return "Invalid enum value specified for " # NAME; \
} \
} \
\
inline \
std::ostream& operator<<( std::ostream& os, const NAME& en ) \
{ \
os << to_string(en); \
return os; \
} \
\
\
inline \
NAME do_enum_cast( const std::string& s, const ::xxx::enum_cast_adl_helper<NAME>& ) \
{ \
static const std::unordered_map<std::string,NAME> map = \
{ \
XXX_TUPLE_FOR_EACH(XXX_ENUM_CASTLIST,NAME,TUPLE) \
XXX_TUPLE_FOR_EACH(XXX_ENUM_QUALIFIED_CASTLIST,NAME,TUPLE) \
}; \
\
auto cit = map.find(s); \
if( cit == map.end() ) \
{ \
/*XXX_THROW(xxx::exception,"Invalid value '%1%' to cast to enum " #NAME ,s);*/ \
throw std::runtime_error("Invalid value to cast to enum"); \
} \
return cit->second; \
}
#define XXX_ENUM(NAME,TUPLE) XXX_ENUM_INTERNAL(NAME,NAME,TUPLE)
#define XXX_ENUM_CLASS(NAME,TUPLE) XXX_ENUM_INTERNAL(class NAME,NAME,TUPLE)
#define XXX_ENUM_CLASS_TYPE(NAME,TYPE,TUPLE) XXX_ENUM_INTERNAL(class NAME : TYPE,NAME,TUPLE)
#define XXX_ENUM_TYPE(NAME,TYPE,TUPLE) XXX_ENUM_INTERNAL(NAME : TYPE,NAME,TUPLE)
#include <iostream>
#include <string>
#include <unordered_map>
namespace xxx
{
template<class T>
struct enum_cast_adl_helper { };
template<class E>
E enum_cast( const std::string& s )
{
return do_enum_cast(s,enum_cast_adl_helper<E>());
}
template<class E>
E enum_cast( const char* cs )
{
std::string s(cs);
return enum_cast<E>(s);
}
} // namespace xxx
XXX_ENUM(foo,(a,b,(c,42)));
int main(int argc, const char *argv[])
{
std::cout << "foo::a = " << foo::a << "\n";
std::cout << "(int)foo::c = " << (int)foo::c << "\n";
std::cout << "to_string(foo::b) = " << to_string(foo::b) << "\n";
std::cout << "xxx::enum_cast<foo>(\"b\") = " << xxx::enum_cast<foo>("b") << "\n";
}
// vim: tabstop=4 shiftwidth=4 noexpandtab
CiNpbmNsdWRlICJib29zdC9wcmVwcm9jZXNzb3IuaHBwIgoKCiNkZWZpbmUgWFhYX1BQX0FSR19OKCBcCiAgICAgICAgICBfMSwgXzIsIF8zLCBfNCwgXzUsIF82LCBfNywgXzgsIF85LF8xMCwgXAogICAgICAgICBfMTEsXzEyLF8xMyxfMTQsXzE1LF8xNixfMTcsXzE4LF8xOSxfMjAsIFwKICAgICAgICAgXzIxLF8yMixfMjMsXzI0LF8yNSxfMjYsXzI3LF8yOCxfMjksXzMwLCBcCiAgICAgICAgIF8zMSxfMzIsXzMzLF8zNCxfMzUsXzM2LF8zNyxfMzgsXzM5LF80MCwgXAogICAgICAgICBfNDEsXzQyLF80MyxfNDQsXzQ1LF80NixfNDcsXzQ4LF80OSxfNTAsIFwKICAgICAgICAgXzUxLF81MixfNTMsXzU0LF81NSxfNTYsXzU3LF81OCxfNTksXzYwLCBcCiAgICAgICAgIF82MSxfNjIsXzYzLE4sLi4uKSBOCgojZGVmaW5lIFhYWF9QUF9SU0VRX04oKSBcCiAgICAgICAgIDYzLDYyLDYxLDYwLCAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgIDU5LDU4LDU3LDU2LDU1LDU0LDUzLDUyLDUxLDUwLCBcCiAgICAgICAgIDQ5LDQ4LDQ3LDQ2LDQ1LDQ0LDQzLDQyLDQxLDQwLCBcCiAgICAgICAgIDM5LDM4LDM3LDM2LDM1LDM0LDMzLDMyLDMxLDMwLCBcCiAgICAgICAgIDI5LDI4LDI3LDI2LDI1LDI0LDIzLDIyLDIxLDIwLCBcCiAgICAgICAgIDE5LDE4LDE3LDE2LDE1LDE0LDEzLDEyLDExLDEwLCBcCiAgICAgICAgIDksOCw3LDYsNSw0LDMsMiwxLDAgCgojZGVmaW5lIFhYWF9QUF9OQVJHXyguLi4pIFwKICAgICAgICAgWFhYX1BQX0FSR19OKF9fVkFfQVJHU19fKQoKI2RlZmluZSBYWFhfUFBfTkFSRyguLi4pIFwKICAgICAgICAgWFhYX1BQX05BUkdfKF9fVkFfQVJHU19fLFhYWF9QUF9SU0VRX04oKSkKCiNkZWZpbmUgWFhYX1RVUExFX1NJWkVfSU5URVJOQUwoVFVQTEUpIFhYWF9QUF9OQVJHIFRVUExFCgojZGVmaW5lIFhYWF9UVVBMRV9DSE9JQ0UoaSkgXApCT09TVF9QUF9BUFBMWSggXApCT09TVF9QUF9UVVBMRV9FTEVNKCBcCjI1LCBpLCAoXAooMCksICgxKSwgKDIpLCAoMykgLCAoNCkgLCAoNSkgLCAoNikgLCAoNykgLCAoOCkgLCAoOSkgLCAoMTApICwgKDExKQkJXAosICgxMikgLCAoMTMpICwgKDE0KSAsICgxNSkgLCAoMTYpICwgKDE3KSAsICgxOCkgLCAoMTkpICwgKDIwKSAsICgyMSkJCVwKLCAoMjIpICwgKDIzKSAsICgyNCkgCVwKICkgXAopIFwKKQoKCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMCBCT09TVF9QUF9CT09MXzAKI2RlZmluZSBCT09TVF9QUF9CT09MXzAxIEJPT1NUX1BQX0JPT0xfMQojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDIgQk9PU1RfUFBfQk9PTF8yCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMyBCT09TVF9QUF9CT09MXzMKI2RlZmluZSBCT09TVF9QUF9CT09MXzA0IEJPT1NUX1BQX0JPT0xfNAojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDUgQk9PU1RfUFBfQk9PTF81CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNiBCT09TVF9QUF9CT09MXzYKI2RlZmluZSBCT09TVF9QUF9CT09MXzA3IEJPT1NUX1BQX0JPT0xfNwojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDggQk9PU1RfUFBfQk9PTF84CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wOSBCT09TVF9QUF9CT09MXzkKI2RlZmluZSBCT09TVF9QUF9CT09MXzAxMCBCT09TVF9QUF9CT09MXzEwCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMTEgQk9PU1RfUFBfQk9PTF8xMQojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDEyIEJPT1NUX1BQX0JPT0xfMTIKI2RlZmluZSBCT09TVF9QUF9CT09MXzAxMyBCT09TVF9QUF9CT09MXzEzCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMTQgQk9PU1RfUFBfQk9PTF8xNAojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDE1IEJPT1NUX1BQX0JPT0xfMTUKI2RlZmluZSBCT09TVF9QUF9CT09MXzAxNiBCT09TVF9QUF9CT09MXzE2CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMTcgQk9PU1RfUFBfQk9PTF8xNwojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDE4IEJPT1NUX1BQX0JPT0xfMTgKI2RlZmluZSBCT09TVF9QUF9CT09MXzAxOSBCT09TVF9QUF9CT09MXzE5CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMjAgQk9PU1RfUFBfQk9PTF8yMAojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDIxIEJPT1NUX1BQX0JPT0xfMjEKI2RlZmluZSBCT09TVF9QUF9CT09MXzAyMiBCT09TVF9QUF9CT09MXzIyCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMjMgQk9PU1RfUFBfQk9PTF8yMwojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDI0IEJPT1NUX1BQX0JPT0xfMjQKI2RlZmluZSBCT09TVF9QUF9CT09MXzAyNSBCT09TVF9QUF9CT09MXzI1CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMjYgQk9PU1RfUFBfQk9PTF8yNgojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDI3IEJPT1NUX1BQX0JPT0xfMjcKI2RlZmluZSBCT09TVF9QUF9CT09MXzAyOCBCT09TVF9QUF9CT09MXzI4CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMjkgQk9PU1RfUFBfQk9PTF8yOQojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDMwIEJPT1NUX1BQX0JPT0xfMzAKI2RlZmluZSBCT09TVF9QUF9CT09MXzAzMSBCT09TVF9QUF9CT09MXzMxCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMzIgQk9PU1RfUFBfQk9PTF8zMgojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDMzIEJPT1NUX1BQX0JPT0xfMzMKI2RlZmluZSBCT09TVF9QUF9CT09MXzAzNCBCT09TVF9QUF9CT09MXzM0CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMzUgQk9PU1RfUFBfQk9PTF8zNQojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDM2IEJPT1NUX1BQX0JPT0xfMzYKI2RlZmluZSBCT09TVF9QUF9CT09MXzAzNyBCT09TVF9QUF9CT09MXzM3CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wMzggQk9PU1RfUFBfQk9PTF8zOAojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDM5IEJPT1NUX1BQX0JPT0xfMzkKI2RlZmluZSBCT09TVF9QUF9CT09MXzA0MCBCT09TVF9QUF9CT09MXzQwCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNDEgQk9PU1RfUFBfQk9PTF80MQojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDQyIEJPT1NUX1BQX0JPT0xfNDIKI2RlZmluZSBCT09TVF9QUF9CT09MXzA0MyBCT09TVF9QUF9CT09MXzQzCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNDQgQk9PU1RfUFBfQk9PTF80NAojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDQ1IEJPT1NUX1BQX0JPT0xfNDUKI2RlZmluZSBCT09TVF9QUF9CT09MXzA0NiBCT09TVF9QUF9CT09MXzQ2CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNDcgQk9PU1RfUFBfQk9PTF80NwojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDQ4IEJPT1NUX1BQX0JPT0xfNDgKI2RlZmluZSBCT09TVF9QUF9CT09MXzA0OSBCT09TVF9QUF9CT09MXzQ5CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNTAgQk9PU1RfUFBfQk9PTF81MAojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDUxIEJPT1NUX1BQX0JPT0xfNTEKI2RlZmluZSBCT09TVF9QUF9CT09MXzA1MiBCT09TVF9QUF9CT09MXzUyCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNTMgQk9PU1RfUFBfQk9PTF81MwojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDU0IEJPT1NUX1BQX0JPT0xfNTQKI2RlZmluZSBCT09TVF9QUF9CT09MXzA1NSBCT09TVF9QUF9CT09MXzU1CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNTYgQk9PU1RfUFBfQk9PTF81NgojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDU3IEJPT1NUX1BQX0JPT0xfNTcKI2RlZmluZSBCT09TVF9QUF9CT09MXzA1OCBCT09TVF9QUF9CT09MXzU4CiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNTkgQk9PU1RfUFBfQk9PTF81OQojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDYwIEJPT1NUX1BQX0JPT0xfNjAKI2RlZmluZSBCT09TVF9QUF9CT09MXzA2MSBCT09TVF9QUF9CT09MXzYxCiNkZWZpbmUgQk9PU1RfUFBfQk9PTF8wNjIgQk9PU1RfUFBfQk9PTF82MgojZGVmaW5lIEJPT1NUX1BQX0JPT0xfMDYzIEJPT1NUX1BQX0JPT0xfNjMKCgojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMCBCT09TVF9QUF9ERUNfMAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMSBCT09TVF9QUF9ERUNfMQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMiBCT09TVF9QUF9ERUNfMgojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMyBCT09TVF9QUF9ERUNfMwojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNCBCT09TVF9QUF9ERUNfNAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNSBCT09TVF9QUF9ERUNfNQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNiBCT09TVF9QUF9ERUNfNgojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNyBCT09TVF9QUF9ERUNfNwojZGVmaW5lIEJPT1NUX1BQX0RFQ18wOCBCT09TVF9QUF9ERUNfOAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wOSBCT09TVF9QUF9ERUNfOQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMTAgQk9PU1RfUFBfREVDXzEwCiNkZWZpbmUgQk9PU1RfUFBfREVDXzAxMSBCT09TVF9QUF9ERUNfMTEKI2RlZmluZSBCT09TVF9QUF9ERUNfMDEyIEJPT1NUX1BQX0RFQ18xMgojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMTMgQk9PU1RfUFBfREVDXzEzCiNkZWZpbmUgQk9PU1RfUFBfREVDXzAxNCBCT09TVF9QUF9ERUNfMTQKI2RlZmluZSBCT09TVF9QUF9ERUNfMDE1IEJPT1NUX1BQX0RFQ18xNQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMTYgQk9PU1RfUFBfREVDXzE2CiNkZWZpbmUgQk9PU1RfUFBfREVDXzAxNyBCT09TVF9QUF9ERUNfMTcKI2RlZmluZSBCT09TVF9QUF9ERUNfMDE4IEJPT1NUX1BQX0RFQ18xOAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMTkgQk9PU1RfUFBfREVDXzE5CiNkZWZpbmUgQk9PU1RfUFBfREVDXzAyMCBCT09TVF9QUF9ERUNfMjAKI2RlZmluZSBCT09TVF9QUF9ERUNfMDIxIEJPT1NUX1BQX0RFQ18yMQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMjIgQk9PU1RfUFBfREVDXzIyCiNkZWZpbmUgQk9PU1RfUFBfREVDXzAyMyBCT09TVF9QUF9ERUNfMjMKI2RlZmluZSBCT09TVF9QUF9ERUNfMDI0IEJPT1NUX1BQX0RFQ18yNAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMjUgQk9PU1RfUFBfREVDXzI1CiNkZWZpbmUgQk9PU1RfUFBfREVDXzAyNiBCT09TVF9QUF9ERUNfMjYKI2RlZmluZSBCT09TVF9QUF9ERUNfMDI3IEJPT1NUX1BQX0RFQ18yNwojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMjggQk9PU1RfUFBfREVDXzI4CiNkZWZpbmUgQk9PU1RfUFBfREVDXzAyOSBCT09TVF9QUF9ERUNfMjkKI2RlZmluZSBCT09TVF9QUF9ERUNfMDMwIEJPT1NUX1BQX0RFQ18zMAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMzEgQk9PU1RfUFBfREVDXzMxCiNkZWZpbmUgQk9PU1RfUFBfREVDXzAzMiBCT09TVF9QUF9ERUNfMzIKI2RlZmluZSBCT09TVF9QUF9ERUNfMDMzIEJPT1NUX1BQX0RFQ18zMwojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMzQgQk9PU1RfUFBfREVDXzM0CiNkZWZpbmUgQk9PU1RfUFBfREVDXzAzNSBCT09TVF9QUF9ERUNfMzUKI2RlZmluZSBCT09TVF9QUF9ERUNfMDM2IEJPT1NUX1BQX0RFQ18zNgojZGVmaW5lIEJPT1NUX1BQX0RFQ18wMzcgQk9PU1RfUFBfREVDXzM3CiNkZWZpbmUgQk9PU1RfUFBfREVDXzAzOCBCT09TVF9QUF9ERUNfMzgKI2RlZmluZSBCT09TVF9QUF9ERUNfMDM5IEJPT1NUX1BQX0RFQ18zOQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNDAgQk9PU1RfUFBfREVDXzQwCiNkZWZpbmUgQk9PU1RfUFBfREVDXzA0MSBCT09TVF9QUF9ERUNfNDEKI2RlZmluZSBCT09TVF9QUF9ERUNfMDQyIEJPT1NUX1BQX0RFQ180MgojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNDMgQk9PU1RfUFBfREVDXzQzCiNkZWZpbmUgQk9PU1RfUFBfREVDXzA0NCBCT09TVF9QUF9ERUNfNDQKI2RlZmluZSBCT09TVF9QUF9ERUNfMDQ1IEJPT1NUX1BQX0RFQ180NQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNDYgQk9PU1RfUFBfREVDXzQ2CiNkZWZpbmUgQk9PU1RfUFBfREVDXzA0NyBCT09TVF9QUF9ERUNfNDcKI2RlZmluZSBCT09TVF9QUF9ERUNfMDQ4IEJPT1NUX1BQX0RFQ180OAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNDkgQk9PU1RfUFBfREVDXzQ5CiNkZWZpbmUgQk9PU1RfUFBfREVDXzA1MCBCT09TVF9QUF9ERUNfNTAKI2RlZmluZSBCT09TVF9QUF9ERUNfMDUxIEJPT1NUX1BQX0RFQ181MQojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNTIgQk9PU1RfUFBfREVDXzUyCiNkZWZpbmUgQk9PU1RfUFBfREVDXzA1MyBCT09TVF9QUF9ERUNfNTMKI2RlZmluZSBCT09TVF9QUF9ERUNfMDU0IEJPT1NUX1BQX0RFQ181NAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNTUgQk9PU1RfUFBfREVDXzU1CiNkZWZpbmUgQk9PU1RfUFBfREVDXzA1NiBCT09TVF9QUF9ERUNfNTYKI2RlZmluZSBCT09TVF9QUF9ERUNfMDU3IEJPT1NUX1BQX0RFQ181NwojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNTggQk9PU1RfUFBfREVDXzU4CiNkZWZpbmUgQk9PU1RfUFBfREVDXzA1OSBCT09TVF9QUF9ERUNfNTkKI2RlZmluZSBCT09TVF9QUF9ERUNfMDYwIEJPT1NUX1BQX0RFQ182MAojZGVmaW5lIEJPT1NUX1BQX0RFQ18wNjEgQk9PU1RfUFBfREVDXzYxCiNkZWZpbmUgQk9PU1RfUFBfREVDXzA2MiBCT09TVF9QUF9ERUNfNjIKI2RlZmluZSBCT09TVF9QUF9ERUNfMDYzIEJPT1NUX1BQX0RFQ182MwoKCiNkZWZpbmUgWFhYX1RPX05VTXgoeCkgMCAjIyB4CiNkZWZpbmUgWFhYX1RPX05VTSh4KSBCT09TVF9QUF9BREQoMCxYWFhfVE9fTlVNeCh4KSkKCgojZGVmaW5lIFhYWF9TVFJJTkdJWkVYKHgpICMgeAojZGVmaW5lIFhYWF9WU1RSSU5HSVpFX1NJTkdMRShhLGIseCkgWFhYX1NUUklOR0laRSh4KQojZGVmaW5lIFhYWF9WU1RSSU5HSVpFX1RVUExFKHRwbCkgWFhYX1RVUExFX0ZPUl9FQUNIKFhYWF9WU1RSSU5HSVpFX1NJTkdMRSwsdHBsKQoKCgoKCgojZGVmaW5lIFhYWF9UVVBMRV9TSVpFKFRVUExFKSBYWFhfVE9fTlVNKFhYWF9UVVBMRV9DSE9JQ0UoWFhYX1RVUExFX1NJWkVfSU5URVJOQUwoVFVQTEUpKSkKCgoKCiNkZWZpbmUgWFhYX1RVUExFX0ZPUl9FQUNIKE1BQ1JPLERBVEEsVFVQTEUpIEJPT1NUX1BQX0xJU1RfRk9SX0VBQ0goTUFDUk8sREFUQSxCT09TVF9QUF9UVVBMRV9UT19MSVNUKFhYWF9UVVBMRV9TSVpFKFRVUExFKSxUVVBMRSkpCgojZGVmaW5lIFhYWF9TVFJJTkdJWkUoeCkgWFhYX1NUUklOR0laRVgoeCkKCiNkZWZpbmUgWFhYX1ZTVFJJTkdJWkUoLi4uKSBYWFhfVlNUUklOR0laRV9UVVBMRSgoX19WQV9BUkdTX18pKQoKI2RlZmluZSBYWFhfQ0FTVF9UT19WT0lEX0VMRU1FTlQocixkYXRhLGVsZW0pICh2b2lkKShlbGVtKTsKI2RlZmluZSBYWFhfQ0FTVF9UT19WT0lEX0lOVEVSTkFMKFRVUExFKSAJCQkJCQkJCQkJXAoJWFhYX1RVUExFX0ZPUl9FQUNIKFhYWF9DQVNUX1RPX1ZPSURfRUxFTUVOVCwsVFVQTEUpCgojZGVmaW5lIFhYWF9DQVNUX1RPX1ZPSUQoLi4uKSBYWFhfQ0FTVF9UT19WT0lEX0lOVEVSTkFMKChfX1ZBX0FSR1NfXykpCgoKCiNkZWZpbmUgWFhYX0VOVU1fRVhUUkFDVF9TUChlbikgQk9PU1RfUFBfVFVQTEVfRUxFTShYWFhfVFVQTEVfU0laRShlbiksMCxlbikgPSBCT09TVF9QUF9UVVBMRV9FTEVNKFhYWF9UVVBMRV9TSVpFKGVuKSwxLGVuKQojZGVmaW5lIFhYWF9FTlVNX0VMRU1FTlQocixkYXRhLGVsZW0pIEJPT1NUX1BQX0lGKCBYWFhfVFVQTEVfU0laRShlbGVtKSwgWFhYX0VOVU1fRVhUUkFDVF9TUChlbGVtKSwgZWxlbSkgLAojZGVmaW5lIFhYWF9FTlVNX0VYVFJBQ1RfRUxFTUVOVChlbikgQk9PU1RfUFBfVFVQTEVfRUxFTShYWFhfVFVQTEVfU0laRShlbiksMCxlbikKI2RlZmluZSBYWFhfRU5VTV9DQVNFX0VMRU1FTlQoZW4pIEJPT1NUX1BQX0lGKCBYWFhfVFVQTEVfU0laRShlbiksIFhYWF9FTlVNX0VYVFJBQ1RfRUxFTUVOVChlbiksIGVuICkKCiNkZWZpbmUgWFhYX0VOVU1fQ0FTRShyLGRhdGEsZWxlbSkgY2FzZSBkYXRhIDo6IFhYWF9FTlVNX0NBU0VfRUxFTUVOVChlbGVtKSA6IHJldHVybiAjZGF0YSAiOjoiIFhYWF9TVFJJTkdJWkUoWFhYX0VOVU1fQ0FTRV9FTEVNRU5UKGVsZW0pKTsKCiNkZWZpbmUgWFhYX0VOVU1fSUZFTFNFKHIsZGF0YSxlbGVtKSBlbHNlIGlmKCBlbiA9PSBkYXRhIDo6IFhYWF9FTlVNX0NBU0VfRUxFTUVOVChlbGVtKSkgeyByZXR1cm4gI2RhdGEgIjo6IiBYWFhfU1RSSU5HSVpFKFhYWF9FTlVNX0NBU0VfRUxFTUVOVChlbGVtKSk7IH0KI2RlZmluZSBYWFhfRU5VTV9DQVNUTElTVChyLGRhdGEsZWxlbSkgeyBYWFhfU1RSSU5HSVpFKFhYWF9FTlVNX0NBU0VfRUxFTUVOVChlbGVtKSksIGRhdGEgOjogWFhYX0VOVU1fQ0FTRV9FTEVNRU5UKGVsZW0pIH0sCiNkZWZpbmUgWFhYX0VOVU1fUVVBTElGSUVEX0NBU1RMSVNUKHIsZGF0YSxlbGVtKSB7ICNkYXRhICI6OiIgWFhYX1NUUklOR0laRShYWFhfRU5VTV9DQVNFX0VMRU1FTlQoZWxlbSkpLCBkYXRhIDo6IFhYWF9FTlVNX0NBU0VfRUxFTUVOVChlbGVtKSB9LAoKI2RlZmluZSBYWFhfRU5VTV9JTlRFUk5BTChUWVBFLE5BTUUsVFVQTEUpCQkJCQkJCQlcCmVudW0gVFlQRSAJCQkJCQkJCQkJCQkJCQkJXAp7CQkJCQkJCQkJCQkJCQkJCQkJXAoJWFhYX1RVUExFX0ZPUl9FQUNIKFhYWF9FTlVNX0VMRU1FTlQsLFRVUExFKQkJCQkJCQlcCglCT09TVF9QUF9DQVQobGFzdF9lbnVtXyxOQU1FKQkJCQkJCQkJCQlcCn07CQkJCQkJCQkJCQkJCQkJCQkJXAoJCQkJCQkJCQkJCQkJCQkJCQlcCmlubGluZQkJCQkJCQkJCQkJCQkJCQkJXApjb25zdCBjaGFyKiB0b19zdHJpbmcoIE5BTUUgZW4gKQkJCQkJCQkJCQlcCnsJCQkJCQkJCQkJCQkJCQkJCQlcCglpZihmYWxzZSkJCQkJCQkJCQkJCQkJCQlcCgl7CQkJCQkJCQkJCQkJCQkJCQlcCgl9CQkJCQkJCQkJCQkJCQkJCQlcCglYWFhfVFVQTEVfRk9SX0VBQ0goWFhYX0VOVU1fSUZFTFNFLE5BTUUsVFVQTEUpCQkJCQkJXAoJZWxzZSBpZiggZW4gPT0gTkFNRSA6OiBCT09TVF9QUF9DQVQobGFzdF9lbnVtXyxOQU1FKSApCQkJCVwKCXsJCQkJCQkJCQkJCQkJCQkJCVwKCQlyZXR1cm4gWFhYX1ZTVFJJTkdJWkUoTkFNRSw6OiwgQk9PU1RfUFBfQ0FUKGxhc3RfZW51bV8sTkFNRSkpOwlcCgl9CQkJCQkJCQkJCQkJCQkJCQlcCgllbHNlIAkJCQkJCQkJCQkJCQkJCQlcCgl7CQkJCQkJCQkJCQkJCQkJCQlcCgkJcmV0dXJuICJJbnZhbGlkIGVudW0gdmFsdWUgc3BlY2lmaWVkIGZvciAiICMgTkFNRTsJCQkJXAoJfQkJCQkJCQkJCQkJCQkJCQkJXAp9CQkJCQkJCQkJCQkJCQkJCQkJXAoJCQkJCQkJCQkJCQkJCQkJCQlcCmlubGluZQkJCQkJCQkJCQkJCQkJCQkJXApzdGQ6Om9zdHJlYW0mIG9wZXJhdG9yPDwoIHN0ZDo6b3N0cmVhbSYgb3MsIGNvbnN0IE5BTUUmIGVuICkJCQlcCnsJCQkJCQkJCQkJCQkJCQkJCQlcCglvcyA8PCB0b19zdHJpbmcoZW4pOwkJCQkJCQkJCQkJCVwKCXJldHVybiBvczsJCQkJCQkJCQkJCQkJCQlcCn0JCQkJCQkJCQkJCQkJCQkJCQlcCgkJCQkJCQkJCQkJCQkJCQkJCVwKCQkJCQkJCQkJCQkJCQkJCQkJXAppbmxpbmUJCQkJCQkJCQkJCQkJCQkJCVwKTkFNRSBkb19lbnVtX2Nhc3QoIGNvbnN0IHN0ZDo6c3RyaW5nJiBzLCBjb25zdCA6Onh4eDo6ZW51bV9jYXN0X2FkbF9oZWxwZXI8TkFNRT4mICkJXAp7CQkJCQkJCQkJCQkJCQkJCQkJXAoJc3RhdGljIGNvbnN0IHN0ZDo6dW5vcmRlcmVkX21hcDxzdGQ6OnN0cmluZyxOQU1FPiBtYXAgPSAJCQlcCgkJewkJCQkJCQkJCQkJCQkJCQlcCgkJCVhYWF9UVVBMRV9GT1JfRUFDSChYWFhfRU5VTV9DQVNUTElTVCxOQU1FLFRVUExFKQkJCVwKCQkJWFhYX1RVUExFX0ZPUl9FQUNIKFhYWF9FTlVNX1FVQUxJRklFRF9DQVNUTElTVCxOQU1FLFRVUExFKQlcCgkJfTsJCQkJCQkJCQkJCQkJCQkJXAoJCQkJCQkJCQkJCQkJCQkJCQlcCglhdXRvIGNpdCA9IG1hcC5maW5kKHMpOwkJCQkJCQkJCQkJCVwKCWlmKCBjaXQgPT0gbWFwLmVuZCgpICkJCQkJCQkJCQkJCQlcCgl7CQkJCQkJCQkJCQkJCQkJCQlcCgkJLypYWFhfVEhST1coeHh4OjpleGNlcHRpb24sIkludmFsaWQgdmFsdWUgJyUxJScgdG8gY2FzdCB0byBlbnVtICIgI05BTUUgLHMpOyovCVwKCQl0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoIkludmFsaWQgdmFsdWUgdG8gY2FzdCB0byBlbnVtIik7CQlcCgl9CQkJCQkJCQkJCQkJCQkJCQlcCglyZXR1cm4gY2l0LT5zZWNvbmQ7CQkJCQkJCQkJCQkJCVwKfQoKI2RlZmluZSBYWFhfRU5VTShOQU1FLFRVUExFKSBYWFhfRU5VTV9JTlRFUk5BTChOQU1FLE5BTUUsVFVQTEUpCiNkZWZpbmUgWFhYX0VOVU1fQ0xBU1MoTkFNRSxUVVBMRSkgWFhYX0VOVU1fSU5URVJOQUwoY2xhc3MgTkFNRSxOQU1FLFRVUExFKQojZGVmaW5lIFhYWF9FTlVNX0NMQVNTX1RZUEUoTkFNRSxUWVBFLFRVUExFKSBYWFhfRU5VTV9JTlRFUk5BTChjbGFzcyBOQU1FIDogVFlQRSxOQU1FLFRVUExFKQojZGVmaW5lIFhYWF9FTlVNX1RZUEUoTkFNRSxUWVBFLFRVUExFKSBYWFhfRU5VTV9JTlRFUk5BTChOQU1FIDogVFlQRSxOQU1FLFRVUExFKQoKCgoKCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHVub3JkZXJlZF9tYXA+CgpuYW1lc3BhY2UgeHh4CnsKCnRlbXBsYXRlPGNsYXNzIFQ+CnN0cnVjdCBlbnVtX2Nhc3RfYWRsX2hlbHBlciB7IH07Cgp0ZW1wbGF0ZTxjbGFzcyBFPgpFIGVudW1fY2FzdCggY29uc3Qgc3RkOjpzdHJpbmcmIHMgKQp7CglyZXR1cm4gZG9fZW51bV9jYXN0KHMsZW51bV9jYXN0X2FkbF9oZWxwZXI8RT4oKSk7Cn0KCnRlbXBsYXRlPGNsYXNzIEU+CkUgZW51bV9jYXN0KCBjb25zdCBjaGFyKiBjcyApCnsKCXN0ZDo6c3RyaW5nIHMoY3MpOwoJcmV0dXJuIGVudW1fY2FzdDxFPihzKTsKfQoKfSAvLyBuYW1lc3BhY2UgeHh4CgoKWFhYX0VOVU0oZm9vLChhLGIsKGMsNDIpKSk7CgppbnQgbWFpbihpbnQgYXJnYywgY29uc3QgY2hhciAqYXJndltdKQp7CglzdGQ6OmNvdXQgPDwgImZvbzo6YSA9ICIgPDwgZm9vOjphIDw8ICJcbiI7CglzdGQ6OmNvdXQgPDwgIihpbnQpZm9vOjpjID0gIiA8PCAoaW50KWZvbzo6YyA8PCAiXG4iOwoJc3RkOjpjb3V0IDw8ICJ0b19zdHJpbmcoZm9vOjpiKSA9ICIgPDwgdG9fc3RyaW5nKGZvbzo6YikgPDwgIlxuIjsKCQoKCXN0ZDo6Y291dCA8PCAieHh4OjplbnVtX2Nhc3Q8Zm9vPihcImJcIikgPSAiIDw8IHh4eDo6ZW51bV9jYXN0PGZvbz4oImIiKSA8PCAiXG4iOwp9CgovLyB2aW06IHRhYnN0b3A9NCBzaGlmdHdpZHRoPTQgbm9leHBhbmR0YWI=