#include <string>
#include <iostream>
#include <utility>
#include <type_traits>
template <char... c> struct literal
{
static constexpr char str[sizeof...( c ) + 1] = { c... };
typedef literal type;
};
template <char... c>
constexpr char literal<c...>::str[];
template <typename... s> struct concat
: concat<typename s::type...> {};
template <char... c1, char... c2, typename... s> struct concat<literal<c1...>,literal<c2...>, s...>
: concat<literal<c1..., c2...>, s...> {};
template <char... c> struct concat<literal<c...>>
: literal<c...> {};
template <> struct concat<>
: literal<> {};
template <std::size_t N, typename L = literal<>> struct N_to_literal
: N_to_literal<N / 10, concat<literal<('0' + N % 10)>,L>> {};
template <typename L> struct N_to_literal<0, L>
: L {};
template <> struct N_to_literal<0, literal<>>
: literal<'0'> {};
template <typename T> struct tag {};
template <typename T, typename U> struct map_pair
{
friend U lookup(tag<T>, map_pair);
};
literal<'u','n','k','n','o','w','n'> lookup(...);
template <typename... T> struct type_map : T... {};
typedef type_map<
map_pair<void, literal<'v','o','i','d'>>,
map_pair<char, literal<'c','h','a','r'>>,
map_pair<signed char, literal<'s','i','g','n','e','d',' ','c','h','a','r'>>,
map_pair<unsigned char, literal<'u','n','s','i','g','n','e','d',' ','c','h','a','r'>>,
map_pair<short, literal<'s','h','o','r','t'>>,
map_pair<unsigned short, literal<'u','n','s','i','g','n','e','d',' ','s','h','o','r','t'>>,
map_pair<int, literal<'i','n','t'>>,
map_pair<unsigned, literal<'u','n','s','i','g','n','e','d'>>,
map_pair<long, literal<'l','o','n','g'>>,
map_pair<unsigned long, literal<'u','n','s','i','g','n','e','d',' ','l','o','n','g'>>,
map_pair<long long, literal<'l','o','n','g',' ','l','o','n','g'>>,
map_pair<unsigned long long, literal<'u','n','s','i','g','n','e','d',' ','l','o','n','g',' ','l','o','n','g'>>,
map_pair<wchar_t, literal<'w','c','h','a','r','_','t'>>,
map_pair<char16_t, literal<'c','h','a','r','1','6','_','t'>>,
map_pair<char32_t, literal<'c','h','a','r','3','2','_','t'>>,
map_pair<float, literal<'f','l','o','a','t'>>,
map_pair<double, literal<'d','o','u','b','l','e'>>,
map_pair<long double, literal<'l','o','n','g',' ','d','o','u','b','l','e'>>,
map_pair<std::nullptr_t, literal<':',':','s','t','d',':',':','n','u','l','l','p','t','r','_','t'>>> fundamental_types;
template <typename L, typename R, bool b> struct type_name_parts
{
typedef L left;
typedef R right;
static constexpr bool right_last = b;
};
template <typename T, typename M> struct derive_name_parts;
template <typename T, typename M = fundamental_types> struct type_name
: concat<typename derive_name_parts<T, M>::left, typename derive_name_parts<T, M>::right> {};
template <typename P, typename S> struct derive_left
: type_name_parts<
concat<typename P::left, std::conditional<P::right_last, literal<'('>, literal<>>, S>,
concat<std::conditional<P::right_last, literal<')'>, literal<>>, typename P::right>,
false> {};
template <typename P, typename S> struct derive_right
: type_name_parts<typename P::left, concat<S, typename P::right>, true> {};
template <typename M, typename...> struct pretty_args;
template <typename M> struct pretty_args<M>
: literal<> {};
template <typename M, typename T> struct pretty_args<M, T>
: type_name<T, M> {};
template <typename M, typename T, typename... Args> struct pretty_args<M, T, Args...>
: concat<pretty_args<M, T>,literal<','>, pretty_args<M, Args...>> {};
template <typename T, typename M> struct derive_name_parts
: type_name_parts<decltype(lookup(std::declval<tag<T>>(),std::declval<M>())), literal<>, false> {};
template <typename T, typename M> struct derive_name_parts<const T, M>
: derive_left<derive_name_parts<T, M>, literal<' ','c','o','n','s','t'>> {};
template <typename T, typename M> struct derive_name_parts<volatile T, M>
: derive_left<derive_name_parts<T, M>, literal<' ','v','o','l','a','t','i','l','e'>> {};
template <typename T, typename M> struct derive_name_parts<const volatile T, M>
: derive_left<derive_name_parts<T, M>, literal<' ','c','o','n','s','t',' ','v','o','l','a','t','i','l','e'>> {};
template <typename T, typename M> struct derive_name_parts<T*, M>
: derive_left<derive_name_parts<T, M>, literal<'*'>> {};
template <typename T, typename M> struct derive_name_parts<T&, M>
: derive_left<derive_name_parts<T, M>, literal<'&'>> {};
template <typename T, typename M> struct derive_name_parts<T&&, M>
: derive_left<derive_name_parts<T, M>, literal<'&','&'>> {};
template <typename T, typename M, std::size_t N> struct derive_name_parts<T[N], M>
: derive_right<derive_name_parts<T, M>, concat<literal<'['>,N_to_literal<N>,literal<']'>>> {};
template <typename T, typename M> struct derive_name_parts<T[], M>
: derive_right<derive_name_parts<T, M>, literal<'[',']'>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...), M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) volatile, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','v','o','l','a','t','i','l','e'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const volatile, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t',' ','v','o','l','a','t','i','l','e'>>> {};
#ifdef NO_BROKEN_REF_QUALIFIER
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) &, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','&'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const &, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t','&'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) volatile &, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','v','o','l','a','t','i','l','e','&'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const volatile &, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t',' ','v','o','l','a','t','i','l','e','&'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) &&, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','&','&'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const &&, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t','&','&'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) volatile &&, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','v','o','l','a','t','i','l','e','&','&'>>> {};
template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const volatile &&, M>
: derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t',' ','v','o','l','a','t','i','l','e','&','&'>>> {};
#endif
template <typename T, typename M, typename C> struct derive_name_parts<T C::*, M>
: derive_left<derive_name_parts<T, M>, concat<std::conditional<derive_name_parts<T, M>::right_last,literal<>,literal<' '>>, type_name<C, M>, literal<':',':','*'>>> {};
int main()
{
struct Foo;
std::cout << type_name<int>::type::str << '\n';
std::cout << type_name<int const>::type::str << '\n';
std::cout << type_name<int*>::type::str << '\n';
std::cout << type_name<int&&>::type::str << '\n';
std::cout << type_name<int[]>::type::str << '\n';
std::cout << type_name<int(void)>::type::str << '\n';
std::cout << type_name<int(*)[12345]>::type::str << '\n';
std::cout << type_name<void(int)>::type::str << '\n';
std::cout << type_name<int&(int*, char)>::type::str << '\n';
std::cout << type_name<int&(int*, char, int&(*&)(long,long long))>::type::str << '\n';
std::cout << type_name<Foo>::type::str << '\n';
std::cout << type_name<int Foo::*>::type::str << '\n';
std::cout << type_name<int (Foo::*)()>::type::str << '\n';
std::cout << type_name<int (Foo::*)(int, char)const volatile>::type::str << '\n';
typedef type_map<
fundamental_types,
map_pair<Foo, literal<'F','o','o'>>,
map_pair<std::string, literal<':',':','s','t','d',':',':','s','t','r','i','n','g'>>> more_types;
std::cout << type_name<Foo, more_types>::type::str << '\n';
std::cout << type_name<int Foo::*, more_types>::type::str << '\n';
std::cout << type_name<int (Foo::*)(), more_types>::type::str << '\n';
#ifdef NO_BROKEN_REF_QUALIFIER
std::cout << type_name<int (Foo::*)()&, more_types>::type::str << '\n';
#endif
std::cout << type_name<std::string (Foo::*)(int, char)const volatile, more_types>::type::str << '\n';
}
I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKdGVtcGxhdGUgPGNoYXIuLi4gYz4gc3RydWN0IGxpdGVyYWwKewogICAgc3RhdGljIGNvbnN0ZXhwciBjaGFyIHN0cltzaXplb2YuLi4oIGMgKSArIDFdID0geyBjLi4uIH07CiAgICB0eXBlZGVmIGxpdGVyYWwgdHlwZTsKfTsKdGVtcGxhdGUgPGNoYXIuLi4gYz4KY29uc3RleHByIGNoYXIgbGl0ZXJhbDxjLi4uPjo6c3RyW107Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gcz4gc3RydWN0IGNvbmNhdAogICAgOiBjb25jYXQ8dHlwZW5hbWUgczo6dHlwZS4uLj4ge307CnRlbXBsYXRlIDxjaGFyLi4uIGMxLCBjaGFyLi4uIGMyLCB0eXBlbmFtZS4uLiBzPiBzdHJ1Y3QgY29uY2F0PGxpdGVyYWw8YzEuLi4+LGxpdGVyYWw8YzIuLi4+LCBzLi4uPgogICAgOiBjb25jYXQ8bGl0ZXJhbDxjMS4uLiwgYzIuLi4+LCBzLi4uPiB7fTsKdGVtcGxhdGUgPGNoYXIuLi4gYz4gc3RydWN0IGNvbmNhdDxsaXRlcmFsPGMuLi4+PgogICAgOiBsaXRlcmFsPGMuLi4+IHt9Owp0ZW1wbGF0ZSA8PiBzdHJ1Y3QgY29uY2F0PD4KICAgIDogbGl0ZXJhbDw+IHt9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHR5cGVuYW1lIEwgPSBsaXRlcmFsPD4+IHN0cnVjdCBOX3RvX2xpdGVyYWwKICAgIDogTl90b19saXRlcmFsPE4gLyAxMCwgY29uY2F0PGxpdGVyYWw8KCcwJyArIE4gJSAxMCk+LEw+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIEw+IHN0cnVjdCBOX3RvX2xpdGVyYWw8MCwgTD4KICAgIDogTCB7fTsKdGVtcGxhdGUgPD4gc3RydWN0IE5fdG9fbGl0ZXJhbDwwLCBsaXRlcmFsPD4+CiAgICA6IGxpdGVyYWw8JzAnPiB7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPiBzdHJ1Y3QgdGFnIHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFU+IHN0cnVjdCBtYXBfcGFpcgp7CiAgICBmcmllbmQgVSBsb29rdXAodGFnPFQ+LCBtYXBfcGFpcik7Cn07CmxpdGVyYWw8J3UnLCduJywnaycsJ24nLCdvJywndycsJ24nPiBsb29rdXAoLi4uKTsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUPiBzdHJ1Y3QgdHlwZV9tYXAgOiBULi4uIHt9OwoKdHlwZWRlZiB0eXBlX21hcDwKICAgIG1hcF9wYWlyPHZvaWQsICAgICAgICAgICAgICAgbGl0ZXJhbDwndicsJ28nLCdpJywnZCc+PiwKICAgIG1hcF9wYWlyPGNoYXIsICAgICAgICAgICAgICAgbGl0ZXJhbDwnYycsJ2gnLCdhJywncic+PiwKICAgIG1hcF9wYWlyPHNpZ25lZCBjaGFyLCAgICAgICAgbGl0ZXJhbDwncycsJ2knLCdnJywnbicsJ2UnLCdkJywnICcsJ2MnLCdoJywnYScsJ3InPj4sCiAgICBtYXBfcGFpcjx1bnNpZ25lZCBjaGFyLCAgICAgIGxpdGVyYWw8J3UnLCduJywncycsJ2knLCdnJywnbicsJ2UnLCdkJywnICcsJ2MnLCdoJywnYScsJ3InPj4sCiAgICBtYXBfcGFpcjxzaG9ydCwgICAgICAgICAgICAgIGxpdGVyYWw8J3MnLCdoJywnbycsJ3InLCd0Jz4+LAogICAgbWFwX3BhaXI8dW5zaWduZWQgc2hvcnQsICAgICBsaXRlcmFsPCd1JywnbicsJ3MnLCdpJywnZycsJ24nLCdlJywnZCcsJyAnLCdzJywnaCcsJ28nLCdyJywndCc+PiwKICAgIG1hcF9wYWlyPGludCwgICAgICAgICAgICAgICAgbGl0ZXJhbDwnaScsJ24nLCd0Jz4+LAogICAgbWFwX3BhaXI8dW5zaWduZWQsICAgICAgICAgICBsaXRlcmFsPCd1JywnbicsJ3MnLCdpJywnZycsJ24nLCdlJywnZCc+PiwKICAgIG1hcF9wYWlyPGxvbmcsICAgICAgICAgICAgICAgbGl0ZXJhbDwnbCcsJ28nLCduJywnZyc+PiwKICAgIG1hcF9wYWlyPHVuc2lnbmVkIGxvbmcsICAgICAgbGl0ZXJhbDwndScsJ24nLCdzJywnaScsJ2cnLCduJywnZScsJ2QnLCcgJywnbCcsJ28nLCduJywnZyc+PiwKICAgIG1hcF9wYWlyPGxvbmcgbG9uZywgICAgICAgICAgbGl0ZXJhbDwnbCcsJ28nLCduJywnZycsJyAnLCdsJywnbycsJ24nLCdnJz4+LAogICAgbWFwX3BhaXI8dW5zaWduZWQgbG9uZyBsb25nLCBsaXRlcmFsPCd1JywnbicsJ3MnLCdpJywnZycsJ24nLCdlJywnZCcsJyAnLCdsJywnbycsJ24nLCdnJywnICcsJ2wnLCdvJywnbicsJ2cnPj4sCiAgICBtYXBfcGFpcjx3Y2hhcl90LCAgICAgICAgICAgIGxpdGVyYWw8J3cnLCdjJywnaCcsJ2EnLCdyJywnXycsJ3QnPj4sCiAgICBtYXBfcGFpcjxjaGFyMTZfdCwgICAgICAgICAgIGxpdGVyYWw8J2MnLCdoJywnYScsJ3InLCcxJywnNicsJ18nLCd0Jz4+LAogICAgbWFwX3BhaXI8Y2hhcjMyX3QsICAgICAgICAgICBsaXRlcmFsPCdjJywnaCcsJ2EnLCdyJywnMycsJzInLCdfJywndCc+PiwKICAgIG1hcF9wYWlyPGZsb2F0LCAgICAgICAgICAgICAgbGl0ZXJhbDwnZicsJ2wnLCdvJywnYScsJ3QnPj4sCiAgICBtYXBfcGFpcjxkb3VibGUsICAgICAgICAgICAgIGxpdGVyYWw8J2QnLCdvJywndScsJ2InLCdsJywnZSc+PiwKICAgIG1hcF9wYWlyPGxvbmcgZG91YmxlLCAgICAgICAgbGl0ZXJhbDwnbCcsJ28nLCduJywnZycsJyAnLCdkJywnbycsJ3UnLCdiJywnbCcsJ2UnPj4sCiAgICBtYXBfcGFpcjxzdGQ6Om51bGxwdHJfdCwgICAgIGxpdGVyYWw8JzonLCc6JywncycsJ3QnLCdkJywnOicsJzonLCduJywndScsJ2wnLCdsJywncCcsJ3QnLCdyJywnXycsJ3QnPj4+IGZ1bmRhbWVudGFsX3R5cGVzOwoKdGVtcGxhdGUgPHR5cGVuYW1lIEwsIHR5cGVuYW1lIFIsIGJvb2wgYj4gc3RydWN0IHR5cGVfbmFtZV9wYXJ0cwp7CiAgICB0eXBlZGVmIEwgbGVmdDsKICAgIHR5cGVkZWYgUiByaWdodDsKICAgIHN0YXRpYyBjb25zdGV4cHIgYm9vbCByaWdodF9sYXN0ID0gYjsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTSA9IGZ1bmRhbWVudGFsX3R5cGVzPiBzdHJ1Y3QgdHlwZV9uYW1lCiAgICA6IGNvbmNhdDx0eXBlbmFtZSBkZXJpdmVfbmFtZV9wYXJ0czxULCBNPjo6bGVmdCwgdHlwZW5hbWUgZGVyaXZlX25hbWVfcGFydHM8VCwgTT46OnJpZ2h0PiB7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBQLCB0eXBlbmFtZSBTPiBzdHJ1Y3QgZGVyaXZlX2xlZnQKICAgIDogdHlwZV9uYW1lX3BhcnRzPAogICAgICAgIGNvbmNhdDx0eXBlbmFtZSBQOjpsZWZ0LCBzdGQ6OmNvbmRpdGlvbmFsPFA6OnJpZ2h0X2xhc3QsIGxpdGVyYWw8JygnPiwgbGl0ZXJhbDw+PiwgUz4sCiAgICAgICAgY29uY2F0PHN0ZDo6Y29uZGl0aW9uYWw8UDo6cmlnaHRfbGFzdCwgbGl0ZXJhbDwnKSc+LCBsaXRlcmFsPD4+LCB0eXBlbmFtZSBQOjpyaWdodD4sCiAgICAgICAgZmFsc2U+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFAsIHR5cGVuYW1lIFM+IHN0cnVjdCBkZXJpdmVfcmlnaHQKICAgIDogdHlwZV9uYW1lX3BhcnRzPHR5cGVuYW1lIFA6OmxlZnQsIGNvbmNhdDxTLCB0eXBlbmFtZSBQOjpyaWdodD4sIHRydWU+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIE0sIHR5cGVuYW1lLi4uPiBzdHJ1Y3QgcHJldHR5X2FyZ3M7CnRlbXBsYXRlIDx0eXBlbmFtZSBNPiBzdHJ1Y3QgcHJldHR5X2FyZ3M8TT4KICAgIDogbGl0ZXJhbDw+IHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgTSwgdHlwZW5hbWUgVD4gc3RydWN0IHByZXR0eV9hcmdzPE0sIFQ+CiAgICA6IHR5cGVfbmFtZTxULCBNPiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIE0sIHR5cGVuYW1lIFQsIHR5cGVuYW1lLi4uIEFyZ3M+IHN0cnVjdCBwcmV0dHlfYXJnczxNLCBULCBBcmdzLi4uPgogICAgOiBjb25jYXQ8cHJldHR5X2FyZ3M8TSwgVD4sbGl0ZXJhbDwnLCc+LCBwcmV0dHlfYXJnczxNLCBBcmdzLi4uPj4ge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTT4gc3RydWN0IGRlcml2ZV9uYW1lX3BhcnRzCiAgICA6IHR5cGVfbmFtZV9wYXJ0czxkZWNsdHlwZShsb29rdXAoc3RkOjpkZWNsdmFsPHRhZzxUPj4oKSxzdGQ6OmRlY2x2YWw8TT4oKSkpLCBsaXRlcmFsPD4sIGZhbHNlPiB7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8Y29uc3QgVCwgTT4KICAgIDogZGVyaXZlX2xlZnQ8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT4sIGxpdGVyYWw8JyAnLCdjJywnbycsJ24nLCdzJywndCc+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIE0+IHN0cnVjdCBkZXJpdmVfbmFtZV9wYXJ0czx2b2xhdGlsZSBULCBNPgogICAgOiBkZXJpdmVfbGVmdDxkZXJpdmVfbmFtZV9wYXJ0czxULCBNPiwgbGl0ZXJhbDwnICcsJ3YnLCdvJywnbCcsJ2EnLCd0JywnaScsJ2wnLCdlJz4+IHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTT4gc3RydWN0IGRlcml2ZV9uYW1lX3BhcnRzPGNvbnN0IHZvbGF0aWxlIFQsIE0+CiAgICA6IGRlcml2ZV9sZWZ0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBsaXRlcmFsPCcgJywnYycsJ28nLCduJywncycsJ3QnLCcgJywndicsJ28nLCdsJywnYScsJ3QnLCdpJywnbCcsJ2UnPj4ge307CnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8VCosIE0+CiAgICA6IGRlcml2ZV9sZWZ0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBsaXRlcmFsPCcqJz4+IHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTT4gc3RydWN0IGRlcml2ZV9uYW1lX3BhcnRzPFQmLCBNPgogICAgOiBkZXJpdmVfbGVmdDxkZXJpdmVfbmFtZV9wYXJ0czxULCBNPiwgbGl0ZXJhbDwnJic+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIE0+IHN0cnVjdCBkZXJpdmVfbmFtZV9wYXJ0czxUJiYsIE0+CiAgICA6IGRlcml2ZV9sZWZ0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBsaXRlcmFsPCcmJywnJic+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIE0sIHN0ZDo6c2l6ZV90IE4+IHN0cnVjdCBkZXJpdmVfbmFtZV9wYXJ0czxUW05dLCBNPgogICAgOiBkZXJpdmVfcmlnaHQ8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT4sIGNvbmNhdDxsaXRlcmFsPCdbJz4sTl90b19saXRlcmFsPE4+LGxpdGVyYWw8J10nPj4+IHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTT4gc3RydWN0IGRlcml2ZV9uYW1lX3BhcnRzPFRbXSwgTT4KICAgIDogZGVyaXZlX3JpZ2h0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBsaXRlcmFsPCdbJywnXSc+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIE0sIHR5cGVuYW1lLi4uIEFyZ3M+IHN0cnVjdCBkZXJpdmVfbmFtZV9wYXJ0czxUKEFyZ3MuLi4pLCBNPgogICAgOiBkZXJpdmVfcmlnaHQ8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT4sIGNvbmNhdDxsaXRlcmFsPCcoJz4sIHByZXR0eV9hcmdzPE0sIEFyZ3MuLi4+LCBsaXRlcmFsPCcpJz4+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIE0sIHR5cGVuYW1lLi4uIEFyZ3M+IHN0cnVjdCBkZXJpdmVfbmFtZV9wYXJ0czxUKEFyZ3MuLi4pIGNvbnN0LCBNPgogICAgOiBkZXJpdmVfcmlnaHQ8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT4sIGNvbmNhdDxsaXRlcmFsPCcoJz4sIHByZXR0eV9hcmdzPE0sIEFyZ3MuLi4+LCBsaXRlcmFsPCcpJywnYycsJ28nLCduJywncycsJ3QnPj4+IHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTSwgdHlwZW5hbWUuLi4gQXJncz4gc3RydWN0IGRlcml2ZV9uYW1lX3BhcnRzPFQoQXJncy4uLikgdm9sYXRpbGUsIE0+CiAgICA6IGRlcml2ZV9yaWdodDxkZXJpdmVfbmFtZV9wYXJ0czxULCBNPiwgY29uY2F0PGxpdGVyYWw8JygnPiwgcHJldHR5X2FyZ3M8TSwgQXJncy4uLj4sIGxpdGVyYWw8JyknLCd2JywnbycsJ2wnLCdhJywndCcsJ2knLCdsJywnZSc+Pj4ge307CnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNLCB0eXBlbmFtZS4uLiBBcmdzPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8VChBcmdzLi4uKSBjb25zdCB2b2xhdGlsZSwgTT4KICAgIDogZGVyaXZlX3JpZ2h0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBjb25jYXQ8bGl0ZXJhbDwnKCc+LCBwcmV0dHlfYXJnczxNLCBBcmdzLi4uPiwgbGl0ZXJhbDwnKScsJ2MnLCdvJywnbicsJ3MnLCd0JywnICcsJ3YnLCdvJywnbCcsJ2EnLCd0JywnaScsJ2wnLCdlJz4+PiB7fTsKI2lmZGVmIE5PX0JST0tFTl9SRUZfUVVBTElGSUVSCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNLCB0eXBlbmFtZS4uLiBBcmdzPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8VChBcmdzLi4uKSAmLCBNPgogICAgOiBkZXJpdmVfcmlnaHQ8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT4sIGNvbmNhdDxsaXRlcmFsPCcoJz4sIHByZXR0eV9hcmdzPE0sIEFyZ3MuLi4+LCBsaXRlcmFsPCcpJywnJic+Pj4ge307CnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNLCB0eXBlbmFtZS4uLiBBcmdzPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8VChBcmdzLi4uKSBjb25zdCAmLCBNPgogICAgOiBkZXJpdmVfcmlnaHQ8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT4sIGNvbmNhdDxsaXRlcmFsPCcoJz4sIHByZXR0eV9hcmdzPE0sIEFyZ3MuLi4+LCBsaXRlcmFsPCcpJywnYycsJ28nLCduJywncycsJ3QnLCcmJz4+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIE0sIHR5cGVuYW1lLi4uIEFyZ3M+IHN0cnVjdCBkZXJpdmVfbmFtZV9wYXJ0czxUKEFyZ3MuLi4pIHZvbGF0aWxlICYsIE0+CiAgICA6IGRlcml2ZV9yaWdodDxkZXJpdmVfbmFtZV9wYXJ0czxULCBNPiwgY29uY2F0PGxpdGVyYWw8JygnPiwgcHJldHR5X2FyZ3M8TSwgQXJncy4uLj4sIGxpdGVyYWw8JyknLCd2JywnbycsJ2wnLCdhJywndCcsJ2knLCdsJywnZScsJyYnPj4+IHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTSwgdHlwZW5hbWUuLi4gQXJncz4gc3RydWN0IGRlcml2ZV9uYW1lX3BhcnRzPFQoQXJncy4uLikgY29uc3Qgdm9sYXRpbGUgJiwgTT4KICAgIDogZGVyaXZlX3JpZ2h0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBjb25jYXQ8bGl0ZXJhbDwnKCc+LCBwcmV0dHlfYXJnczxNLCBBcmdzLi4uPiwgbGl0ZXJhbDwnKScsJ2MnLCdvJywnbicsJ3MnLCd0JywnICcsJ3YnLCdvJywnbCcsJ2EnLCd0JywnaScsJ2wnLCdlJywnJic+Pj4ge307CnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNLCB0eXBlbmFtZS4uLiBBcmdzPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8VChBcmdzLi4uKSAmJiwgTT4KICAgIDogZGVyaXZlX3JpZ2h0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBjb25jYXQ8bGl0ZXJhbDwnKCc+LCBwcmV0dHlfYXJnczxNLCBBcmdzLi4uPiwgbGl0ZXJhbDwnKScsJyYnLCcmJz4+PiB7fTsKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIE0sIHR5cGVuYW1lLi4uIEFyZ3M+IHN0cnVjdCBkZXJpdmVfbmFtZV9wYXJ0czxUKEFyZ3MuLi4pIGNvbnN0ICYmLCBNPgogICAgOiBkZXJpdmVfcmlnaHQ8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT4sIGNvbmNhdDxsaXRlcmFsPCcoJz4sIHByZXR0eV9hcmdzPE0sIEFyZ3MuLi4+LCBsaXRlcmFsPCcpJywnYycsJ28nLCduJywncycsJ3QnLCcmJywnJic+Pj4ge307CnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNLCB0eXBlbmFtZS4uLiBBcmdzPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8VChBcmdzLi4uKSB2b2xhdGlsZSAmJiwgTT4KICAgIDogZGVyaXZlX3JpZ2h0PGRlcml2ZV9uYW1lX3BhcnRzPFQsIE0+LCBjb25jYXQ8bGl0ZXJhbDwnKCc+LCBwcmV0dHlfYXJnczxNLCBBcmdzLi4uPiwgbGl0ZXJhbDwnKScsJ3YnLCdvJywnbCcsJ2EnLCd0JywnaScsJ2wnLCdlJywnJicsJyYnPj4+IHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgTSwgdHlwZW5hbWUuLi4gQXJncz4gc3RydWN0IGRlcml2ZV9uYW1lX3BhcnRzPFQoQXJncy4uLikgY29uc3Qgdm9sYXRpbGUgJiYsIE0+CiAgICA6IGRlcml2ZV9yaWdodDxkZXJpdmVfbmFtZV9wYXJ0czxULCBNPiwgY29uY2F0PGxpdGVyYWw8JygnPiwgcHJldHR5X2FyZ3M8TSwgQXJncy4uLj4sIGxpdGVyYWw8JyknLCdjJywnbycsJ24nLCdzJywndCcsJyAnLCd2JywnbycsJ2wnLCdhJywndCcsJ2knLCdsJywnZScsJyYnLCcmJz4+PiB7fTsKI2VuZGlmCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBNLCB0eXBlbmFtZSBDPiBzdHJ1Y3QgZGVyaXZlX25hbWVfcGFydHM8VCBDOjoqLCBNPgogICAgOiBkZXJpdmVfbGVmdDxkZXJpdmVfbmFtZV9wYXJ0czxULCBNPiwgY29uY2F0PHN0ZDo6Y29uZGl0aW9uYWw8ZGVyaXZlX25hbWVfcGFydHM8VCwgTT46OnJpZ2h0X2xhc3QsbGl0ZXJhbDw+LGxpdGVyYWw8JyAnPj4sIHR5cGVfbmFtZTxDLCBNPiwgbGl0ZXJhbDwnOicsJzonLCcqJz4+PiB7fTsKCmludCBtYWluKCkKewogICAgc3RydWN0IEZvbzsKICAgIHN0ZDo6Y291dCA8PCB0eXBlX25hbWU8aW50Pjo6dHlwZTo6c3RyIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPGludCBjb25zdD46OnR5cGU6OnN0ciA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHR5cGVfbmFtZTxpbnQqPjo6dHlwZTo6c3RyIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPGludCYmPjo6dHlwZTo6c3RyIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPGludFtdPjo6dHlwZTo6c3RyIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPGludCh2b2lkKT46OnR5cGU6OnN0ciA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHR5cGVfbmFtZTxpbnQoKilbMTIzNDVdPjo6dHlwZTo6c3RyIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPHZvaWQoaW50KT46OnR5cGU6OnN0ciA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHR5cGVfbmFtZTxpbnQmKGludCosIGNoYXIpPjo6dHlwZTo6c3RyIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPGludCYoaW50KiwgY2hhciwgaW50JigqJikobG9uZyxsb25nIGxvbmcpKT46OnR5cGU6OnN0ciA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHR5cGVfbmFtZTxGb28+Ojp0eXBlOjpzdHIgPDwgJ1xuJzsKICAgIHN0ZDo6Y291dCA8PCB0eXBlX25hbWU8aW50IEZvbzo6Kj46OnR5cGU6OnN0ciA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHR5cGVfbmFtZTxpbnQgKEZvbzo6KikoKT46OnR5cGU6OnN0ciA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHR5cGVfbmFtZTxpbnQgKEZvbzo6KikoaW50LCBjaGFyKWNvbnN0IHZvbGF0aWxlPjo6dHlwZTo6c3RyIDw8ICdcbic7CgogICAgdHlwZWRlZiB0eXBlX21hcDwKICAgICAgICBmdW5kYW1lbnRhbF90eXBlcywKICAgICAgICBtYXBfcGFpcjxGb28sIGxpdGVyYWw8J0YnLCdvJywnbyc+PiwKICAgICAgICBtYXBfcGFpcjxzdGQ6OnN0cmluZywgbGl0ZXJhbDwnOicsJzonLCdzJywndCcsJ2QnLCc6JywnOicsJ3MnLCd0JywncicsJ2knLCduJywnZyc+Pj4gbW9yZV90eXBlczsKICAgIHN0ZDo6Y291dCA8PCB0eXBlX25hbWU8Rm9vLCBtb3JlX3R5cGVzPjo6dHlwZTo6c3RyIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPGludCBGb286OiosIG1vcmVfdHlwZXM+Ojp0eXBlOjpzdHIgPDwgJ1xuJzsKICAgIHN0ZDo6Y291dCA8PCB0eXBlX25hbWU8aW50IChGb286OiopKCksIG1vcmVfdHlwZXM+Ojp0eXBlOjpzdHIgPDwgJ1xuJzsKI2lmZGVmIE5PX0JST0tFTl9SRUZfUVVBTElGSUVSCiAgICBzdGQ6OmNvdXQgPDwgdHlwZV9uYW1lPGludCAoRm9vOjoqKSgpJiwgbW9yZV90eXBlcz46OnR5cGU6OnN0ciA8PCAnXG4nOwojZW5kaWYKICAgIHN0ZDo6Y291dCA8PCB0eXBlX25hbWU8c3RkOjpzdHJpbmcgKEZvbzo6KikoaW50LCBjaGFyKWNvbnN0IHZvbGF0aWxlLCBtb3JlX3R5cGVzPjo6dHlwZTo6c3RyIDw8ICdcbic7Cn0=