// http://a...content-available-to-author-only...l.com/1950.html
#include <memory.h>
#include <assert.h>
template<typename M>
class CMockObject
{
#define DECL_TEN(hundreds, tens) \
FINAL_V_DECL(hundreds, tens, 0) \
FINAL_V_DECL(hundreds, tens, 1) \
FINAL_V_DECL(hundreds, tens, 2) \
FINAL_V_DECL(hundreds, tens, 3) \
FINAL_V_DECL(hundreds, tens, 4) \
FINAL_V_DECL(hundreds, tens, 5) \
FINAL_V_DECL(hundreds, tens, 6) \
FINAL_V_DECL(hundreds, tens, 7) \
FINAL_V_DECL(hundreds, tens, 8) \
FINAL_V_DECL(hundreds, tens, 9)
#define DECL_HUNDRED(hundreds)\
DECL_TEN(hundreds, 0) \
DECL_TEN(hundreds, 1) \
DECL_TEN(hundreds, 2) \
DECL_TEN(hundreds, 3) \
DECL_TEN(hundreds, 4) \
DECL_TEN(hundreds, 5) \
DECL_TEN(hundreds, 6) \
DECL_TEN(hundreds, 7) \
DECL_TEN(hundreds, 8) \
DECL_TEN(hundreds, 9)
#define DECL_RETRIEVER \
DECL_HUNDRED(0) \
DECL_HUNDRED(1) \
DECL_HUNDRED(2) \
DECL_HUNDRED(3) \
DECL_HUNDRED(4) \
DECL_HUNDRED(5) \
DECL_HUNDRED(6) \
DECL_HUNDRED(7) \
DECL_HUNDRED(8) \
DECL_HUNDRED(9)
#define FINAL_V_DECL(hundreds, tens, units) \
virtual int V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
class CThisCallVtIdxRetriever
{
DECL_RETRIEVER
};
#if defined(_WIN32) && !defined(_WIN64)
#undef FINAL_V_DECL
#define FINAL_V_DECL(hundreds, tens, units) \
virtual int __cdecl V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
class CCdeclVtIdxRetriever
{
DECL_RETRIEVER
};
#undef FINAL_V_DECL
#define FINAL_V_DECL(hundreds, tens, units) \
virtual int __stdcall V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
class CStdCallVtIdxRetriever
{
DECL_RETRIEVER
};
#undef FINAL_V_DECL
#define FINAL_V_DECL(hundreds, tens, units) \
virtual int __fastcall V##hundreds##tens##units() { return hundreds * 100 + tens * 10 + units; };
class CFastCallVtIdxRetriever
{
DECL_RETRIEVER
};
#endif
#undef DECL_RETRIEVER
#undef DECL_HUNDRED
#undef DECL_TEN
#undef FINAL_V_DECL
protected:
void** const m_ppVT;
CMockObject()
: m_ppVT(new void*[1000])
{
memset(m_ppVT, 0, sizeof(void*) * 1000);
static_cast<M*>(this)->ExecuteStructors(true);
}
~CMockObject()
{
static_cast<M*>(this)->ExecuteStructors(false);
delete[] m_ppVT;
}
private:
template <typename SRC_FUN, typename MOCK_FUN>
void DoInstantiateThisCall(SRC_FUN pFun, MOCK_FUN pSubst)
{
int (CThisCallVtIdxRetriever::*pV)() = (int (CThisCallVtIdxRetriever::*)()) pFun;
const int idx = (CThisCallVtIdxRetriever().*pV)();
memcpy(m_ppVT + idx, &pSubst, sizeof(void*));
}
#if defined(_WIN32) && !defined(_WIN64)
template <typename SRC_FUN, typename MOCK_FUN>
void DoInstantiateCdecl(SRC_FUN pFun, MOCK_FUN pSubst)
{
int (__cdecl CCdeclVtIdxRetriever::*pV)() = (int (__cdecl CCdeclVtIdxRetriever::*)()) pFun;
const int idx = (CCdeclVtIdxRetriever().*pV)();
((MOCK_FUN*) m_ppVT)[idx] = pSubst;
}
template <typename SRC_FUN, typename MOCK_FUN>
void DoInstantiateStdCall(SRC_FUN pFun, MOCK_FUN pSubst)
{
int (__stdcall CStdCallVtIdxRetriever::*pV)() = (int (__stdcall CStdCallVtIdxRetriever::*)()) pFun;
const int idx = (CStdCallVtIdxRetriever().*pV)();
((MOCK_FUN*) m_ppVT)[idx] = pSubst;
}
template <typename SRC_FUN, typename MOCK_FUN>
void DoInstantiateFastCall(SRC_FUN pFun, MOCK_FUN pSubst)
{
int (__fastcall CFastCallVtIdxRetriever::*pV)() = (int (__fastcall CFastCallVtIdxRetriever::*)()) pFun;
const int idx = (CFastCallVtIdxRetriever().*pV)();
((MOCK_FUN*) m_ppVT)[idx] = pSubst;
}
#endif
protected:
#define PARAMS_MACRO_1(macro) macro(1)
#define PARAMS_MACRO_2(macro) PARAMS_MACRO_1(macro), macro(2)
#define PARAMS_MACRO_3(macro) PARAMS_MACRO_2(macro), macro(3)
#define PARAMS_MACRO_4(macro) PARAMS_MACRO_3(macro), macro(4)
#define PARAMS_MACRO_5(macro) PARAMS_MACRO_4(macro), macro(5)
#define PARAMS_MACRO_6(macro) PARAMS_MACRO_5(macro), macro(6)
#define PARAMS_MACRO_7(macro) PARAMS_MACRO_6(macro), macro(7)
#define PARAMS_MACRO_8(macro) PARAMS_MACRO_7(macro), macro(8)
#define PARAMS_MACRO_9(macro) PARAMS_MACRO_8(macro), macro(9)
#define ARGS_MACRO_TEMPL(v) typename P##v
#define ARGS_MACRO_DECL(v) P##v
#define DO_INVOKE_PARAMS_MACRO(macro, convention, modifier, varargs0, DoInstantiate, Instantiate, ...) \
template<macro(ARGS_MACRO_TEMPL), typename R, typename SRC, typename MOCK> \
void Instantiate(R (convention SRC::*pFun)(macro(ARGS_MACRO_DECL) __VA_ARGS__) modifier \
, R (convention MOCK::*pSubst)(macro(ARGS_MACRO_DECL) __VA_ARGS__) modifier) \
{ \
DoInstantiate(pFun, pSubst); \
}
#define DO_DECL_INSTANTIATE_NO_PARAMS(convention, modifier, varargs0, DoInstantiate, Instantiate, ...) \
template<typename R, typename SRC, typename MOCK> \
void Instantiate(R (convention SRC::*pFun)(varargs0) modifier \
, R (convention MOCK::*pSubst)(varargs0) modifier) \
{ \
DoInstantiate(pFun, pSubst); \
}
#define DECL_EMPTY
#define DECL_VARARGS_0 ...
#define DECL_VARARGS_X , ...
#define DECL_INSTANTIATE_NO_PARAMS(args) DO_DECL_INSTANTIATE_NO_PARAMS args
#define INVOKE_PARAMS_MACRO(args) DO_INVOKE_PARAMS_MACRO args
#define DECL_INSTANTIATE(...) \
DECL_INSTANTIATE_NO_PARAMS((__VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_1, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_2, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_3, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_4, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_5, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_6, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_7, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_8, __VA_ARGS__)) \
INVOKE_PARAMS_MACRO((PARAMS_MACRO_9, __VA_ARGS__))
#define DECL_INSTANTIATE_CONVENTION(convention, CustomInstantiate) \
DECL_INSTANTIATE(DECL_EMPTY convention, DECL_EMPTY, DECL_EMPTY, CustomInstantiate, Instantiate, DECL_EMPTY) \
DECL_INSTANTIATE(DECL_EMPTY convention, const, DECL_EMPTY, CustomInstantiate, Instantiate, DECL_EMPTY)
DECL_INSTANTIATE_CONVENTION(DECL_EMPTY, DoInstantiateThisCall)
#if defined(_WIN32) && !defined(_WIN64)
DECL_INSTANTIATE_CONVENTION(__cdecl, DoInstantiateCdecl)
DECL_INSTANTIATE_CONVENTION(__stdcall, DoInstantiateStdCall)
DECL_INSTANTIATE_CONVENTION(__fastcall, DoInstantiateFastCall)
#endif
#if defined(_WIN32) && !defined(_WIN64)
DECL_INSTANTIATE(__cdecl, DECL_EMPTY, DECL_VARARGS_0, DoInstantiateCdecl, InstantiateVA, DECL_VARARGS_X)
DECL_INSTANTIATE(__cdecl, const, DECL_VARARGS_0, DoInstantiateCdecl, InstantiateVA, DECL_VARARGS_X)
#else
DECL_INSTANTIATE(DECL_EMPTY, DECL_EMPTY,DECL_VARARGS_0, DoInstantiateThisCall, InstantiateVA, DECL_VARARGS_X)
DECL_INSTANTIATE(DECL_EMPTY, const, DECL_VARARGS_0, DoInstantiateThisCall, InstantiateVA, DECL_VARARGS_X)
#endif
#undef INVOKE_PARAMS_MACRO
#undef ARGS_MACRO_TEMPL
#undef ARGS_MACRO_DECL
#undef PARAMS_MACRO_1
#undef PARAMS_MACRO_2
#undef PARAMS_MACRO_3
#undef PARAMS_MACRO_4
#undef PARAMS_MACRO_5
#undef PARAMS_MACRO_6
#undef PARAMS_MACRO_7
#undef PARAMS_MACRO_8
#undef PARAMS_MACRO_9
#undef DECL_INSTANTIATE
#undef DECL_EMPTY
#undef DECL_VARARGS_0
#undef DECL_VARARGS_X
template<typename T, typename C> void ExecuteStructor(T C::*r, bool construct)
{
C* other = (C*) this;
if (construct)
{
::new(&((*other).*r)) T();
}
else
{
((*other).*r).~T();
}
}
};
#define DECLARE_MOCK_MEMBERS(src, mock) \
public: \
typedef src TMockOrigin; \
char m_membersAllocBuffer[sizeof(src)]; \
public: \
void ExecuteStructors(bool construct) \
{ \
int iMemberCountN = -1; \
EnumerateStructors(iMemberCountN, construct); \
iMemberCountN = ~iMemberCountN; \
if (construct) \
{ \
int i = 0; \
try \
{ \
for (; i < iMemberCountN; ++i) \
{ \
ExecuteNthStructor(i, construct); \
} \
} \
catch (...) \
{ \
for (; i >= 0; --i) \
{ \
ExecuteNthStructor(i, false); \
} \
throw; \
} \
} \
else \
for (int i = iMemberCountN; --i >= 0; ) \
{ \
ExecuteNthStructor(i, construct); \
} \
} \
void ExecuteNthStructor(int iMemberToCall, bool construct) \
{ \
EnumerateStructors(iMemberToCall, construct); \
assert(0 == iMemberToCall); \
} \
void EnumerateStructors(int& iMemberToCall, bool construct)
// It is not necessary to declare POD types
#define DECLARE_MOCK_MEMBER(member) \
if (0 == iMemberToCall) \
{ \
ExecuteStructor(&TMockOrigin::member, construct); \
return; \
} \
--iMemberToCall;
// That's an example of its usage:
// #include "MockObject.h"
#include <iostream>
#include <sstream>
using std::string;
using std::ostringstream;
using std::cerr;
class A
{
public:
virtual string Dummy0(int*);
virtual string Dummy0(int) const;
virtual void Dummy2(const char*);
virtual int Dummy3();
virtual int Dummy3Const() const;
virtual string SomeOtherTest(int i, int& j);
virtual int TakeThree(int i, int j, int k);
virtual int TakeFour(int i, int j, int k, int l);
virtual int TakeThreeConst(int i, int j, int k) const;
virtual int TakeFourConst(int i, int j, int k, int l) const;
virtual int TakeFive(int i, int j, int k, int l, int m);
virtual int TakeFiveConst(int i, int j, int k, int l, int m) const;
virtual double TakeFive2(int i, int j, int k, int l, int m);
virtual double Test2ThisCall(int i, int& j);
#if defined(_WIN32)
virtual void __stdcall StdCall(char*);
virtual double __cdecl Test2Cdecl(int i, int& j);
virtual double __stdcall Test2StdCall(int i, int& j);
virtual double __fastcall Test2FastCall(int i, int& j);
#endif
virtual double TestVarArgsThisCall(int i, ...);
virtual double TestVarArgs0ThisCall(...);
int dummy;
string buffer2;
int dummy2;
string buffer;
};
class CXTest : public CMockObject<CXTest>
{
public:
CXTest()
{
Instantiate(static_cast<string (A::*)(int) const>(&A::Dummy0), &CXTest::DoTest);
Instantiate(static_cast<string (A::*)(int*)>(&A::Dummy0), &CXTest::DoAnotherTest);
Instantiate(&A::Dummy2, &CXTest::YetAnotherTest);
Instantiate(&A::Dummy3, &CXTest::NoParamsTest);
Instantiate(&A::Dummy3Const, &CXTest::NoParamsTestConst);
Instantiate(&A::TakeThree, &CXTest::TakeThree);
Instantiate(&A::TakeFour, &CXTest::TakeFour);
Instantiate(&A::TakeThreeConst, &CXTest::TakeThreeConst);
Instantiate(&A::TakeFourConst, &CXTest::TakeFourConst);
Instantiate(&A::TakeFive, &CXTest::TakeFive);
Instantiate(&A::TakeFive2, &CXTest::TakeFive2);
Instantiate(&A::TakeFiveConst, &CXTest::TakeFiveConst);
Instantiate(&A::SomeOtherTest, &CXTest::SomeOtherTest);
Instantiate(&A::Test2ThisCall, &CXTest::Test2ThisCall);
#if defined(_WIN32)
Instantiate(&A::StdCall, &CXTest::StdCall);
Instantiate(&A::Test2Cdecl, &CXTest::Test2Cdecl);
Instantiate(&A::Test2StdCall, &CXTest::Test2StdCall);
Instantiate(&A::Test2FastCall, &CXTest::Test2FastCall);
#endif
InstantiateVA(&A::TestVarArgsThisCall, &CXTest::TestVarArgsThisCall);
InstantiateVA(&A::TestVarArgs0ThisCall, &CXTest::TestVarArgs0ThisCall);
}
DECLARE_MOCK_MEMBERS(A, CXTest)
{
DECLARE_MOCK_MEMBER(buffer)
DECLARE_MOCK_MEMBER(buffer2)
}
string DoTest(int i) const
{
ostringstream s;
s << i;
return s.str();
}
string DoAnotherTest(int* i)
{
ostringstream s;
s << -*i;
return s.str();
}
void YetAnotherTest(const char* p)
{
((A*)this)->buffer = p;
}
int NoParamsTest()
{
return ((A*)this)->dummy;
}
int NoParamsTestConst() const
{
return ((A*)this)->dummy;
}
string SomeOtherTest(int i, int& j)
{
j = i;
return ((A*)this)->buffer2;
}
int TakeThree(int i, int j, int k)
{
return i + j + k;
}
int TakeFour(int i, int j, int k, int l)
{
return i + j + k + l;
}
int TakeThreeConst(int i, int j, int k) const
{
return i + j + k;
}
int TakeFourConst(int i, int j, int k, int l) const
{
return i + j + k + l;
}
int TakeFive(int i, int j, int k, int l, int m)
{
return i + j + k + l + m;
}
double TakeFive2(int i, int j, int k, int l, int m)
{
return i + j + k + l + m;
}
int TakeFiveConst(int i, int j, int k, int l, int m) const
{
return i + j + k + l + m;
}
double Test2ThisCall(int i, int& j)
{
return 0.1;
}
#if defined(_WIN32)
void __stdcall StdCall(char* p)
{
((A*)this)->buffer = p;
}
double __cdecl Test2Cdecl(int i, int& j)
{
return 0.2;
}
double __stdcall Test2StdCall(int i, int& j)
{
return 0.3;
}
double __fastcall Test2FastCall(int i, int& j)
{
return 0.4;
}
#endif
double TestVarArgsThisCall(int i, ...)
{
return 11.;
}
double TestVarArgs0ThisCall(...)
{
return 21.;
}
};
#define CHECK_EQUAL(a, b) \
if ((a) == (b)); else cerr << "CHECK_EQUAL failed at " __FILE__ "(" << __LINE__ << ")\n";
int main()
{
CXTest test;
A* pA = (A*) &test;
CHECK_EQUAL("777", pA->Dummy0(777));
int i = 999;
CHECK_EQUAL("-999", pA->Dummy0(&i));
pA->Dummy2("YetAnotherTest");
CHECK_EQUAL("YetAnotherTest", pA->buffer);
pA->dummy = 3456;
CHECK_EQUAL(3456, pA->Dummy3());
CHECK_EQUAL(3456, pA->Dummy3Const());
int j = 0;
pA->buffer2 = "This would be to miss an opportunity.";
CHECK_EQUAL("This would be to miss an opportunity.", pA->SomeOtherTest(i, j));
CHECK_EQUAL(i, j);
CHECK_EQUAL(6, pA->TakeThree(1, 2, 3));
CHECK_EQUAL(10, pA->TakeFour(1, 2, 3, 4));
CHECK_EQUAL(6, pA->TakeThreeConst(1, 2, 3));
CHECK_EQUAL(10, pA->TakeFourConst(1, 2, 3, 4));
CHECK_EQUAL(15, pA->TakeFive(1, 2, 3, 4, 5));
CHECK_EQUAL(15, pA->TakeFiveConst(1, 2, 3, 4, 5));
CHECK_EQUAL(0.1, pA->Test2ThisCall(1, j));
#if defined(_WIN32)
pA->StdCall("StdCallTest");
CHECK_EQUAL("StdCallTest", pA->buffer);
CHECK_EQUAL(0.2, pA->Test2Cdecl(1, j));
CHECK_EQUAL(0.3, pA->Test2StdCall(1, j));
CHECK_EQUAL(0.4, pA->Test2FastCall(1, j));
#endif
CHECK_EQUAL(11., pA->TestVarArgsThisCall(1, j));
CHECK_EQUAL(21., pA->TestVarArgs0ThisCall(1, j));
std::cout << "ok.\n";
}
Ly8gaHR0cDovL2EuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmwuY29tLzE5NTAuaHRtbAoKI2luY2x1ZGUgPG1lbW9yeS5oPgojaW5jbHVkZSA8YXNzZXJ0Lmg+CgoKdGVtcGxhdGU8dHlwZW5hbWUgTT4KY2xhc3MgQ01vY2tPYmplY3QKewoKICAgICNkZWZpbmUgREVDTF9URU4oaHVuZHJlZHMsIHRlbnMpICAgIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDApIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDEpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDIpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDMpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDQpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDUpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDYpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDcpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDgpIFwKICAgICAgICBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIDkpCgogICAgI2RlZmluZSBERUNMX0hVTkRSRUQoaHVuZHJlZHMpXAogICAgICAgIERFQ0xfVEVOKGh1bmRyZWRzLCAwKSBcCiAgICAgICAgREVDTF9URU4oaHVuZHJlZHMsIDEpIFwKICAgICAgICBERUNMX1RFTihodW5kcmVkcywgMikgXAogICAgICAgIERFQ0xfVEVOKGh1bmRyZWRzLCAzKSBcCiAgICAgICAgREVDTF9URU4oaHVuZHJlZHMsIDQpIFwKICAgICAgICBERUNMX1RFTihodW5kcmVkcywgNSkgXAogICAgICAgIERFQ0xfVEVOKGh1bmRyZWRzLCA2KSBcCiAgICAgICAgREVDTF9URU4oaHVuZHJlZHMsIDcpIFwKICAgICAgICBERUNMX1RFTihodW5kcmVkcywgOCkgXAogICAgICAgIERFQ0xfVEVOKGh1bmRyZWRzLCA5KQoKICAgICNkZWZpbmUgREVDTF9SRVRSSUVWRVIgXAogICAgICAgIERFQ0xfSFVORFJFRCgwKSBcCiAgICAgICAgREVDTF9IVU5EUkVEKDEpIFwKICAgICAgICBERUNMX0hVTkRSRUQoMikgXAogICAgICAgIERFQ0xfSFVORFJFRCgzKSBcCiAgICAgICAgREVDTF9IVU5EUkVEKDQpIFwKICAgICAgICBERUNMX0hVTkRSRUQoNSkgXAogICAgICAgIERFQ0xfSFVORFJFRCg2KSBcCiAgICAgICAgREVDTF9IVU5EUkVEKDcpIFwKICAgICAgICBERUNMX0hVTkRSRUQoOCkgXAogICAgICAgIERFQ0xfSFVORFJFRCg5KQoKICAgICNkZWZpbmUgRklOQUxfVl9ERUNMKGh1bmRyZWRzLCB0ZW5zLCB1bml0cykgXAogICAgICAgIHZpcnR1YWwgaW50IFYjI2h1bmRyZWRzIyN0ZW5zIyN1bml0cygpIHsgcmV0dXJuIGh1bmRyZWRzICogMTAwICsgdGVucyAqIDEwICsgdW5pdHM7IH07CgogICAgY2xhc3MgQ1RoaXNDYWxsVnRJZHhSZXRyaWV2ZXIKICAgIHsKICAgICAgICBERUNMX1JFVFJJRVZFUgogICAgfTsKCiNpZiBkZWZpbmVkKF9XSU4zMikgJiYgIWRlZmluZWQoX1dJTjY0KQogICAgI3VuZGVmIEZJTkFMX1ZfREVDTAogICAgI2RlZmluZSBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIHVuaXRzKSBcCiAgICAgICAgdmlydHVhbCBpbnQgX19jZGVjbCBWIyNodW5kcmVkcyMjdGVucyMjdW5pdHMoKSB7IHJldHVybiBodW5kcmVkcyAqIDEwMCArIHRlbnMgKiAxMCArIHVuaXRzOyB9OwoKICAgIGNsYXNzIENDZGVjbFZ0SWR4UmV0cmlldmVyCiAgICB7CiAgICAgICAgREVDTF9SRVRSSUVWRVIKICAgIH07CgogICAgI3VuZGVmIEZJTkFMX1ZfREVDTAogICAgI2RlZmluZSBGSU5BTF9WX0RFQ0woaHVuZHJlZHMsIHRlbnMsIHVuaXRzKSBcCiAgICAgICAgdmlydHVhbCBpbnQgX19zdGRjYWxsIFYjI2h1bmRyZWRzIyN0ZW5zIyN1bml0cygpIHsgcmV0dXJuIGh1bmRyZWRzICogMTAwICsgdGVucyAqIDEwICsgdW5pdHM7IH07CgogICAgY2xhc3MgQ1N0ZENhbGxWdElkeFJldHJpZXZlcgogICAgewogICAgICAgIERFQ0xfUkVUUklFVkVSCiAgICB9OwoKICAgICN1bmRlZiBGSU5BTF9WX0RFQ0wKICAgICNkZWZpbmUgRklOQUxfVl9ERUNMKGh1bmRyZWRzLCB0ZW5zLCB1bml0cykgXAogICAgICAgIHZpcnR1YWwgaW50IF9fZmFzdGNhbGwgViMjaHVuZHJlZHMjI3RlbnMjI3VuaXRzKCkgeyByZXR1cm4gaHVuZHJlZHMgKiAxMDAgKyB0ZW5zICogMTAgKyB1bml0czsgfTsKCiAgICBjbGFzcyBDRmFzdENhbGxWdElkeFJldHJpZXZlcgogICAgewogICAgICAgIERFQ0xfUkVUUklFVkVSCiAgICB9OwojZW5kaWYKCiAgICAjdW5kZWYgREVDTF9SRVRSSUVWRVIKICAgICN1bmRlZiBERUNMX0hVTkRSRUQKICAgICN1bmRlZiBERUNMX1RFTgogICAgI3VuZGVmIEZJTkFMX1ZfREVDTAoKcHJvdGVjdGVkOgogICAgdm9pZCoqIGNvbnN0IG1fcHBWVDsKCiAgICBDTW9ja09iamVjdCgpCiAgICAgICAgOiBtX3BwVlQobmV3IHZvaWQqWzEwMDBdKQogICAgewogICAgICAgIG1lbXNldChtX3BwVlQsIDAsIHNpemVvZih2b2lkKikgKiAxMDAwKTsKICAgICAgICBzdGF0aWNfY2FzdDxNKj4odGhpcyktPkV4ZWN1dGVTdHJ1Y3RvcnModHJ1ZSk7CiAgICB9CiAgICB+Q01vY2tPYmplY3QoKQogICAgewogICAgICAgIHN0YXRpY19jYXN0PE0qPih0aGlzKS0+RXhlY3V0ZVN0cnVjdG9ycyhmYWxzZSk7CiAgICAgICAgZGVsZXRlW10gbV9wcFZUOwogICAgfQoKcHJpdmF0ZToKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBTUkNfRlVOLCB0eXBlbmFtZSBNT0NLX0ZVTj4KICAgIHZvaWQgRG9JbnN0YW50aWF0ZVRoaXNDYWxsKFNSQ19GVU4gcEZ1biwgTU9DS19GVU4gcFN1YnN0KQogICAgewogICAgICAgIGludCAoQ1RoaXNDYWxsVnRJZHhSZXRyaWV2ZXI6OipwVikoKSA9IChpbnQgKENUaGlzQ2FsbFZ0SWR4UmV0cmlldmVyOjoqKSgpKSBwRnVuOwogICAgICAgIGNvbnN0IGludCBpZHggPSAoQ1RoaXNDYWxsVnRJZHhSZXRyaWV2ZXIoKS4qcFYpKCk7CiAgICAgICAgbWVtY3B5KG1fcHBWVCArIGlkeCwgJnBTdWJzdCwgc2l6ZW9mKHZvaWQqKSk7CiAgICB9CiAjaWYgZGVmaW5lZChfV0lOMzIpICYmICFkZWZpbmVkKF9XSU42NCkKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBTUkNfRlVOLCB0eXBlbmFtZSBNT0NLX0ZVTj4KICAgIHZvaWQgRG9JbnN0YW50aWF0ZUNkZWNsKFNSQ19GVU4gcEZ1biwgTU9DS19GVU4gcFN1YnN0KQogICAgewogICAgICAgIGludCAoX19jZGVjbCBDQ2RlY2xWdElkeFJldHJpZXZlcjo6KnBWKSgpID0gKGludCAoX19jZGVjbCBDQ2RlY2xWdElkeFJldHJpZXZlcjo6KikoKSkgcEZ1bjsKICAgICAgICBjb25zdCBpbnQgaWR4ID0gKENDZGVjbFZ0SWR4UmV0cmlldmVyKCkuKnBWKSgpOwogICAgICAgICgoTU9DS19GVU4qKSBtX3BwVlQpW2lkeF0gPSBwU3Vic3Q7CiAgICB9CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgU1JDX0ZVTiwgdHlwZW5hbWUgTU9DS19GVU4+CiAgICB2b2lkIERvSW5zdGFudGlhdGVTdGRDYWxsKFNSQ19GVU4gcEZ1biwgTU9DS19GVU4gcFN1YnN0KQogICAgewogICAgICAgIGludCAoX19zdGRjYWxsIENTdGRDYWxsVnRJZHhSZXRyaWV2ZXI6OipwVikoKSA9IChpbnQgKF9fc3RkY2FsbCBDU3RkQ2FsbFZ0SWR4UmV0cmlldmVyOjoqKSgpKSBwRnVuOwogICAgICAgIGNvbnN0IGludCBpZHggPSAoQ1N0ZENhbGxWdElkeFJldHJpZXZlcigpLipwVikoKTsKICAgICAgICAoKE1PQ0tfRlVOKikgbV9wcFZUKVtpZHhdID0gcFN1YnN0OwogICAgfQogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFNSQ19GVU4sIHR5cGVuYW1lIE1PQ0tfRlVOPgogICAgdm9pZCBEb0luc3RhbnRpYXRlRmFzdENhbGwoU1JDX0ZVTiBwRnVuLCBNT0NLX0ZVTiBwU3Vic3QpCiAgICB7CiAgICAgICAgaW50IChfX2Zhc3RjYWxsIENGYXN0Q2FsbFZ0SWR4UmV0cmlldmVyOjoqcFYpKCkgPSAoaW50IChfX2Zhc3RjYWxsIENGYXN0Q2FsbFZ0SWR4UmV0cmlldmVyOjoqKSgpKSBwRnVuOwogICAgICAgIGNvbnN0IGludCBpZHggPSAoQ0Zhc3RDYWxsVnRJZHhSZXRyaWV2ZXIoKS4qcFYpKCk7CiAgICAgICAgKChNT0NLX0ZVTiopIG1fcHBWVClbaWR4XSA9IHBTdWJzdDsKICAgIH0KI2VuZGlmCgpwcm90ZWN0ZWQ6CgojZGVmaW5lIFBBUkFNU19NQUNST18xKG1hY3JvKSBtYWNybygxKQojZGVmaW5lIFBBUkFNU19NQUNST18yKG1hY3JvKSBQQVJBTVNfTUFDUk9fMShtYWNybyksIG1hY3JvKDIpCiNkZWZpbmUgUEFSQU1TX01BQ1JPXzMobWFjcm8pIFBBUkFNU19NQUNST18yKG1hY3JvKSwgbWFjcm8oMykKI2RlZmluZSBQQVJBTVNfTUFDUk9fNChtYWNybykgUEFSQU1TX01BQ1JPXzMobWFjcm8pLCBtYWNybyg0KQojZGVmaW5lIFBBUkFNU19NQUNST181KG1hY3JvKSBQQVJBTVNfTUFDUk9fNChtYWNybyksIG1hY3JvKDUpCiNkZWZpbmUgUEFSQU1TX01BQ1JPXzYobWFjcm8pIFBBUkFNU19NQUNST181KG1hY3JvKSwgbWFjcm8oNikKI2RlZmluZSBQQVJBTVNfTUFDUk9fNyhtYWNybykgUEFSQU1TX01BQ1JPXzYobWFjcm8pLCBtYWNybyg3KQojZGVmaW5lIFBBUkFNU19NQUNST184KG1hY3JvKSBQQVJBTVNfTUFDUk9fNyhtYWNybyksIG1hY3JvKDgpCiNkZWZpbmUgUEFSQU1TX01BQ1JPXzkobWFjcm8pIFBBUkFNU19NQUNST184KG1hY3JvKSwgbWFjcm8oOSkKCgojZGVmaW5lIEFSR1NfTUFDUk9fVEVNUEwodikgdHlwZW5hbWUgUCMjdgojZGVmaW5lIEFSR1NfTUFDUk9fREVDTCh2KSBQIyN2CgojZGVmaW5lIERPX0lOVk9LRV9QQVJBTVNfTUFDUk8obWFjcm8sIGNvbnZlbnRpb24sIG1vZGlmaWVyLCB2YXJhcmdzMCwgRG9JbnN0YW50aWF0ZSwgSW5zdGFudGlhdGUsIC4uLikgXAogICAgdGVtcGxhdGU8bWFjcm8oQVJHU19NQUNST19URU1QTCksIHR5cGVuYW1lIFIsIHR5cGVuYW1lIFNSQywgdHlwZW5hbWUgTU9DSz4gXAogICAgdm9pZCBJbnN0YW50aWF0ZShSIChjb252ZW50aW9uIFNSQzo6KnBGdW4pKG1hY3JvKEFSR1NfTUFDUk9fREVDTCkgX19WQV9BUkdTX18pIG1vZGlmaWVyIFwKICAgICAgICAsIFIgKGNvbnZlbnRpb24gTU9DSzo6KnBTdWJzdCkobWFjcm8oQVJHU19NQUNST19ERUNMKSBfX1ZBX0FSR1NfXykgbW9kaWZpZXIpIFwKICAgIHsgXAogICAgICAgIERvSW5zdGFudGlhdGUocEZ1biwgcFN1YnN0KTsgXAogICAgfQoKI2RlZmluZSBET19ERUNMX0lOU1RBTlRJQVRFX05PX1BBUkFNUyhjb252ZW50aW9uLCBtb2RpZmllciwgdmFyYXJnczAsIERvSW5zdGFudGlhdGUsIEluc3RhbnRpYXRlLCAuLi4pIFwKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFIsIHR5cGVuYW1lIFNSQywgdHlwZW5hbWUgTU9DSz4gXAogICAgdm9pZCBJbnN0YW50aWF0ZShSIChjb252ZW50aW9uIFNSQzo6KnBGdW4pKHZhcmFyZ3MwKSBtb2RpZmllciBcCiAgICAgICAgLCBSIChjb252ZW50aW9uIE1PQ0s6OipwU3Vic3QpKHZhcmFyZ3MwKSBtb2RpZmllcikgXAogICAgeyBcCiAgICAgICAgRG9JbnN0YW50aWF0ZShwRnVuLCBwU3Vic3QpOyBcCiAgICB9IAoKI2RlZmluZSBERUNMX0VNUFRZCiNkZWZpbmUgREVDTF9WQVJBUkdTXzAgLi4uCiNkZWZpbmUgREVDTF9WQVJBUkdTX1ggLCAuLi4KCiNkZWZpbmUgREVDTF9JTlNUQU5USUFURV9OT19QQVJBTVMoYXJncykgRE9fREVDTF9JTlNUQU5USUFURV9OT19QQVJBTVMgYXJncwojZGVmaW5lIElOVk9LRV9QQVJBTVNfTUFDUk8oYXJncykgRE9fSU5WT0tFX1BBUkFNU19NQUNSTyBhcmdzCgojZGVmaW5lIERFQ0xfSU5TVEFOVElBVEUoLi4uKSBcCiAgICBERUNMX0lOU1RBTlRJQVRFX05PX1BBUkFNUygoX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fMSwgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fMiwgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fMywgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fNCwgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fNSwgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fNiwgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fNywgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fOCwgX19WQV9BUkdTX18pKSBcCiAgICBJTlZPS0VfUEFSQU1TX01BQ1JPKChQQVJBTVNfTUFDUk9fOSwgX19WQV9BUkdTX18pKQoKI2RlZmluZSBERUNMX0lOU1RBTlRJQVRFX0NPTlZFTlRJT04oY29udmVudGlvbiwgQ3VzdG9tSW5zdGFudGlhdGUpIFwKICAgIERFQ0xfSU5TVEFOVElBVEUoREVDTF9FTVBUWSBjb252ZW50aW9uLCBERUNMX0VNUFRZLAlERUNMX0VNUFRZLAlDdXN0b21JbnN0YW50aWF0ZSwgSW5zdGFudGlhdGUsICAgIERFQ0xfRU1QVFkpIFwKICAgIERFQ0xfSU5TVEFOVElBVEUoREVDTF9FTVBUWSBjb252ZW50aW9uLCBjb25zdCwJCURFQ0xfRU1QVFksCUN1c3RvbUluc3RhbnRpYXRlLCBJbnN0YW50aWF0ZSwgICAgREVDTF9FTVBUWSkKCiAgICBERUNMX0lOU1RBTlRJQVRFX0NPTlZFTlRJT04oREVDTF9FTVBUWSwgRG9JbnN0YW50aWF0ZVRoaXNDYWxsKQojaWYgZGVmaW5lZChfV0lOMzIpICYmICFkZWZpbmVkKF9XSU42NCkKICAgIERFQ0xfSU5TVEFOVElBVEVfQ09OVkVOVElPTihfX2NkZWNsLCBEb0luc3RhbnRpYXRlQ2RlY2wpCiAgICBERUNMX0lOU1RBTlRJQVRFX0NPTlZFTlRJT04oX19zdGRjYWxsLCBEb0luc3RhbnRpYXRlU3RkQ2FsbCkKICAgIERFQ0xfSU5TVEFOVElBVEVfQ09OVkVOVElPTihfX2Zhc3RjYWxsLCBEb0luc3RhbnRpYXRlRmFzdENhbGwpCiNlbmRpZgoKI2lmIGRlZmluZWQoX1dJTjMyKSAmJiAhZGVmaW5lZChfV0lONjQpCiAgICBERUNMX0lOU1RBTlRJQVRFKF9fY2RlY2wsIERFQ0xfRU1QVFksCURFQ0xfVkFSQVJHU18wLCBEb0luc3RhbnRpYXRlQ2RlY2wsIEluc3RhbnRpYXRlVkEsIERFQ0xfVkFSQVJHU19YKQogICAgREVDTF9JTlNUQU5USUFURShfX2NkZWNsLCBjb25zdCwJCURFQ0xfVkFSQVJHU18wLCBEb0luc3RhbnRpYXRlQ2RlY2wsIEluc3RhbnRpYXRlVkEsIERFQ0xfVkFSQVJHU19YKQojZWxzZQogICAgREVDTF9JTlNUQU5USUFURShERUNMX0VNUFRZLCBERUNMX0VNUFRZLERFQ0xfVkFSQVJHU18wLCBEb0luc3RhbnRpYXRlVGhpc0NhbGwsIEluc3RhbnRpYXRlVkEsIERFQ0xfVkFSQVJHU19YKQogICAgREVDTF9JTlNUQU5USUFURShERUNMX0VNUFRZLCBjb25zdCwJCURFQ0xfVkFSQVJHU18wLCBEb0luc3RhbnRpYXRlVGhpc0NhbGwsIEluc3RhbnRpYXRlVkEsIERFQ0xfVkFSQVJHU19YKQojZW5kaWYKCiN1bmRlZiBJTlZPS0VfUEFSQU1TX01BQ1JPCgojdW5kZWYgQVJHU19NQUNST19URU1QTAojdW5kZWYgQVJHU19NQUNST19ERUNMCgojdW5kZWYgUEFSQU1TX01BQ1JPXzEKI3VuZGVmIFBBUkFNU19NQUNST18yCiN1bmRlZiBQQVJBTVNfTUFDUk9fMwojdW5kZWYgUEFSQU1TX01BQ1JPXzQKI3VuZGVmIFBBUkFNU19NQUNST181CiN1bmRlZiBQQVJBTVNfTUFDUk9fNgojdW5kZWYgUEFSQU1TX01BQ1JPXzcKI3VuZGVmIFBBUkFNU19NQUNST184CiN1bmRlZiBQQVJBTVNfTUFDUk9fOQoKCiN1bmRlZiBERUNMX0lOU1RBTlRJQVRFCiN1bmRlZiBERUNMX0VNUFRZCiN1bmRlZiBERUNMX1ZBUkFSR1NfMAojdW5kZWYgREVDTF9WQVJBUkdTX1gKCgogICAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgQz4gdm9pZCBFeGVjdXRlU3RydWN0b3IoVCBDOjoqciwgYm9vbCBjb25zdHJ1Y3QpCiAgICB7CiAgICAgICAgQyogb3RoZXIgPSAoQyopIHRoaXM7CgogICAgICAgIGlmIChjb25zdHJ1Y3QpCiAgICAgICAgewogICAgICAgICAgICA6Om5ldygmKCgqb3RoZXIpLipyKSkgVCgpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICAoKCpvdGhlcikuKnIpLn5UKCk7CiAgICAgICAgfQogICAgfQp9OwoKCgojZGVmaW5lIERFQ0xBUkVfTU9DS19NRU1CRVJTKHNyYywgbW9jaykJCQkJCQkJXApwdWJsaWM6CQkJCQkJCQkJCQlcCiAgICB0eXBlZGVmIHNyYyBUTW9ja09yaWdpbjsJCQkJCQkJCVwKICAgIGNoYXIgbV9tZW1iZXJzQWxsb2NCdWZmZXJbc2l6ZW9mKHNyYyldOwkJCQkJCVwKcHVibGljOgkJCQkJCQkJCQkJXAogICAgdm9pZCBFeGVjdXRlU3RydWN0b3JzKGJvb2wgY29uc3RydWN0KQkJCQkJCVwKICAgIHsJCQkJCQkJCQkJCVwKICAgICAgICBpbnQgaU1lbWJlckNvdW50TiA9IC0xOwkJCQkJCQkJXAogICAgICAgIEVudW1lcmF0ZVN0cnVjdG9ycyhpTWVtYmVyQ291bnROLCBjb25zdHJ1Y3QpOwkJCVwKICAgICAgICBpTWVtYmVyQ291bnROID0gfmlNZW1iZXJDb3VudE47CQkJCQkJCVwKICAgICAgICBpZiAoY29uc3RydWN0KQkJCQkJCQkJCVwKICAgICAgICB7CQkJCQkJCQkJCVwKICAgICAgICAgICAgaW50IGkgPSAwOwkJCQkJCQkJCVwKICAgICAgICAgICAgdHJ5CQkJCQkJCQkJCVwKICAgICAgICAgICAgewkJCQkJCQkJCQlcCiAgICAgICAgICAgICAgICBmb3IgKDsgaSA8IGlNZW1iZXJDb3VudE47ICsraSkJCQkJCVwKICAgICAgICAgICAgICAgIHsJCQkJCQkJCQlcCiAgICAgICAgICAgICAgICAgICAgRXhlY3V0ZU50aFN0cnVjdG9yKGksIGNvbnN0cnVjdCk7CQkJXAogICAgICAgICAgICAgICAgfQkJCQkJCQkJCVwKICAgICAgICAgICAgfQkJCQkJCQkJCQlcCiAgICAgICAgICAgIGNhdGNoICguLi4pCQkJCQkJCQkJXAogICAgICAgICAgICB7CQkJCQkJCQkJCVwKICAgICAgICAgICAgICAgIGZvciAoOyBpID49IDA7IC0taSkJCQkJCQkJXAogICAgICAgICAgICAgICAgewkJCQkJCQkJCVwKICAgICAgICAgICAgICAgICAgICBFeGVjdXRlTnRoU3RydWN0b3IoaSwgZmFsc2UpOwkJCQlcCiAgICAgICAgICAgICAgICB9CQkJCQkJCQkJXAogICAgICAgICAgICAgICAgdGhyb3c7CQkJCQkJCQkJXAogICAgICAgICAgICB9CQkJCQkJCQkJCVwKICAgICAgICB9CQkJCQkJCQkJCVwKICAgICAgICBlbHNlCQkJCQkJCQkJCVwKICAgICAgICAgICAgZm9yIChpbnQgaSA9IGlNZW1iZXJDb3VudE47IC0taSA+PSAwOyApCQkJCVwKICAgICAgICAgICAgewkJCQkJCQkJCQlcCiAgICAgICAgICAgICAgICBFeGVjdXRlTnRoU3RydWN0b3IoaSwgY29uc3RydWN0KTsJCQkJXAogICAgICAgICAgICB9CQkJCQkJCQkJCVwKICAgIH0JCQkJCQkJCQkJCVwKICAgIHZvaWQgRXhlY3V0ZU50aFN0cnVjdG9yKGludCBpTWVtYmVyVG9DYWxsLCBib29sIGNvbnN0cnVjdCkJXAogICAgewkJCQkJCQkJCQkJXAogICAgICAgIEVudW1lcmF0ZVN0cnVjdG9ycyhpTWVtYmVyVG9DYWxsLCBjb25zdHJ1Y3QpOwkJCVwKICAgICAgICBhc3NlcnQoMCA9PSBpTWVtYmVyVG9DYWxsKTsJCQkJCQkJXAogICAgfQkJCQkJCQkJCQkJXAogICAgdm9pZCBFbnVtZXJhdGVTdHJ1Y3RvcnMoaW50JiBpTWVtYmVyVG9DYWxsLCBib29sIGNvbnN0cnVjdCkKCgovLyBJdCBpcyBub3QgbmVjZXNzYXJ5IHRvIGRlY2xhcmUgUE9EIHR5cGVzCiNkZWZpbmUgREVDTEFSRV9NT0NLX01FTUJFUihtZW1iZXIpCQkJCQkJCVwKICAgICAgICBpZiAoMCA9PSBpTWVtYmVyVG9DYWxsKQkJCQkJCQkJXAogICAgICAgIHsJCQkJCQkJCQkJXAogICAgICAgICAgICBFeGVjdXRlU3RydWN0b3IoJlRNb2NrT3JpZ2luOjptZW1iZXIsIGNvbnN0cnVjdCk7CVwKICAgICAgICAgICAgcmV0dXJuOwkJCQkJCQkJCVwKICAgICAgICB9CQkJCQkJCQkJCVwKICAgICAgICAtLWlNZW1iZXJUb0NhbGw7CgovLyBUaGF0J3MgYW4gZXhhbXBsZSBvZiBpdHMgdXNhZ2U6Ci8vICNpbmNsdWRlICJNb2NrT2JqZWN0LmgiCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHNzdHJlYW0+Cgp1c2luZyBzdGQ6OnN0cmluZzsKdXNpbmcgc3RkOjpvc3RyaW5nc3RyZWFtOwp1c2luZyBzdGQ6OmNlcnI7CgpjbGFzcyBBCnsKcHVibGljOgogICAgdmlydHVhbCBzdHJpbmcgRHVtbXkwKGludCopOwoKICAgIHZpcnR1YWwgc3RyaW5nIER1bW15MChpbnQpIGNvbnN0OwoKICAgIHZpcnR1YWwgdm9pZCBEdW1teTIoY29uc3QgY2hhciopOwoKICAgIHZpcnR1YWwgaW50IER1bW15MygpOwogICAgdmlydHVhbCBpbnQgRHVtbXkzQ29uc3QoKSBjb25zdDsKCiAgICB2aXJ0dWFsIHN0cmluZyBTb21lT3RoZXJUZXN0KGludCBpLCBpbnQmIGopOwoKICAgIHZpcnR1YWwgaW50IFRha2VUaHJlZShpbnQgaSwgaW50IGosIGludCBrKTsKCiAgICB2aXJ0dWFsIGludCBUYWtlRm91cihpbnQgaSwgaW50IGosIGludCBrLCBpbnQgbCk7CgogICAgdmlydHVhbCBpbnQgVGFrZVRocmVlQ29uc3QoaW50IGksIGludCBqLCBpbnQgaykgY29uc3Q7CgogICAgdmlydHVhbCBpbnQgVGFrZUZvdXJDb25zdChpbnQgaSwgaW50IGosIGludCBrLCBpbnQgbCkgY29uc3Q7CgogICAgdmlydHVhbCBpbnQgVGFrZUZpdmUoaW50IGksIGludCBqLCBpbnQgaywgaW50IGwsIGludCBtKTsKICAgIHZpcnR1YWwgaW50IFRha2VGaXZlQ29uc3QoaW50IGksIGludCBqLCBpbnQgaywgaW50IGwsIGludCBtKSBjb25zdDsKCiAgICB2aXJ0dWFsIGRvdWJsZSBUYWtlRml2ZTIoaW50IGksIGludCBqLCBpbnQgaywgaW50IGwsIGludCBtKTsKCiAgICB2aXJ0dWFsIGRvdWJsZSBUZXN0MlRoaXNDYWxsKGludCBpLCBpbnQmIGopOwoKI2lmIGRlZmluZWQoX1dJTjMyKQogICAgdmlydHVhbCB2b2lkIF9fc3RkY2FsbCBTdGRDYWxsKGNoYXIqKTsKICAgIHZpcnR1YWwgZG91YmxlIF9fY2RlY2wgVGVzdDJDZGVjbChpbnQgaSwgaW50JiBqKTsKICAgIHZpcnR1YWwgZG91YmxlIF9fc3RkY2FsbCBUZXN0MlN0ZENhbGwoaW50IGksIGludCYgaik7CiAgICB2aXJ0dWFsIGRvdWJsZSBfX2Zhc3RjYWxsIFRlc3QyRmFzdENhbGwoaW50IGksIGludCYgaik7CiNlbmRpZgoKICAgIHZpcnR1YWwgZG91YmxlIFRlc3RWYXJBcmdzVGhpc0NhbGwoaW50IGksIC4uLik7CgogICAgdmlydHVhbCBkb3VibGUgVGVzdFZhckFyZ3MwVGhpc0NhbGwoLi4uKTsKCiAgICBpbnQgZHVtbXk7CgogICAgc3RyaW5nIGJ1ZmZlcjI7CgogICAgaW50IGR1bW15MjsKCiAgICBzdHJpbmcgYnVmZmVyOwp9OwoKY2xhc3MgQ1hUZXN0IDogcHVibGljIENNb2NrT2JqZWN0PENYVGVzdD4KewpwdWJsaWM6CgogICAgQ1hUZXN0KCkKICAgIHsKICAgICAgICBJbnN0YW50aWF0ZShzdGF0aWNfY2FzdDxzdHJpbmcgKEE6OiopKGludCkgY29uc3Q+KCZBOjpEdW1teTApLCAmQ1hUZXN0OjpEb1Rlc3QpOwogICAgICAgIEluc3RhbnRpYXRlKHN0YXRpY19jYXN0PHN0cmluZyAoQTo6KikoaW50Kik+KCZBOjpEdW1teTApLCAmQ1hUZXN0OjpEb0Fub3RoZXJUZXN0KTsKICAgICAgICBJbnN0YW50aWF0ZSgmQTo6RHVtbXkyLCAmQ1hUZXN0OjpZZXRBbm90aGVyVGVzdCk7CgogICAgICAgIEluc3RhbnRpYXRlKCZBOjpEdW1teTMsICZDWFRlc3Q6Ok5vUGFyYW1zVGVzdCk7CiAgICAgICAgSW5zdGFudGlhdGUoJkE6OkR1bW15M0NvbnN0LCAmQ1hUZXN0OjpOb1BhcmFtc1Rlc3RDb25zdCk7CiAgICAgICAgSW5zdGFudGlhdGUoJkE6OlRha2VUaHJlZSwgJkNYVGVzdDo6VGFrZVRocmVlKTsKICAgICAgICBJbnN0YW50aWF0ZSgmQTo6VGFrZUZvdXIsICZDWFRlc3Q6OlRha2VGb3VyKTsKICAgICAgICBJbnN0YW50aWF0ZSgmQTo6VGFrZVRocmVlQ29uc3QsICZDWFRlc3Q6OlRha2VUaHJlZUNvbnN0KTsKICAgICAgICBJbnN0YW50aWF0ZSgmQTo6VGFrZUZvdXJDb25zdCwgJkNYVGVzdDo6VGFrZUZvdXJDb25zdCk7CiAgICAgICAgSW5zdGFudGlhdGUoJkE6OlRha2VGaXZlLCAmQ1hUZXN0OjpUYWtlRml2ZSk7CiAgICAgICAgSW5zdGFudGlhdGUoJkE6OlRha2VGaXZlMiwgJkNYVGVzdDo6VGFrZUZpdmUyKTsKICAgICAgICBJbnN0YW50aWF0ZSgmQTo6VGFrZUZpdmVDb25zdCwgJkNYVGVzdDo6VGFrZUZpdmVDb25zdCk7CgogICAgICAgIEluc3RhbnRpYXRlKCZBOjpTb21lT3RoZXJUZXN0LCAmQ1hUZXN0OjpTb21lT3RoZXJUZXN0KTsKCiAgICAgICAgSW5zdGFudGlhdGUoJkE6OlRlc3QyVGhpc0NhbGwsICZDWFRlc3Q6OlRlc3QyVGhpc0NhbGwpOwojaWYgZGVmaW5lZChfV0lOMzIpCiAgICAgICAgSW5zdGFudGlhdGUoJkE6OlN0ZENhbGwsICZDWFRlc3Q6OlN0ZENhbGwpOwogICAgICAgIEluc3RhbnRpYXRlKCZBOjpUZXN0MkNkZWNsLCAmQ1hUZXN0OjpUZXN0MkNkZWNsKTsKICAgICAgICBJbnN0YW50aWF0ZSgmQTo6VGVzdDJTdGRDYWxsLCAmQ1hUZXN0OjpUZXN0MlN0ZENhbGwpOwogICAgICAgIEluc3RhbnRpYXRlKCZBOjpUZXN0MkZhc3RDYWxsLCAmQ1hUZXN0OjpUZXN0MkZhc3RDYWxsKTsKI2VuZGlmCgogICAgICAgIEluc3RhbnRpYXRlVkEoJkE6OlRlc3RWYXJBcmdzVGhpc0NhbGwsICZDWFRlc3Q6OlRlc3RWYXJBcmdzVGhpc0NhbGwpOwogICAgICAgIEluc3RhbnRpYXRlVkEoJkE6OlRlc3RWYXJBcmdzMFRoaXNDYWxsLCAmQ1hUZXN0OjpUZXN0VmFyQXJnczBUaGlzQ2FsbCk7CiAgICB9CgogICAgREVDTEFSRV9NT0NLX01FTUJFUlMoQSwgQ1hUZXN0KQogICAgewogICAgICAgIERFQ0xBUkVfTU9DS19NRU1CRVIoYnVmZmVyKQogICAgICAgIERFQ0xBUkVfTU9DS19NRU1CRVIoYnVmZmVyMikKICAgIH0KCiAgICBzdHJpbmcgRG9UZXN0KGludCBpKSBjb25zdAogICAgewogICAgICAgIG9zdHJpbmdzdHJlYW0gczsKICAgICAgICBzIDw8IGk7CiAgICAgICAgcmV0dXJuIHMuc3RyKCk7CiAgICB9CgogICAgc3RyaW5nIERvQW5vdGhlclRlc3QoaW50KiBpKQogICAgewogICAgICAgIG9zdHJpbmdzdHJlYW0gczsKICAgICAgICBzIDw8IC0qaTsKICAgICAgICByZXR1cm4gcy5zdHIoKTsKICAgIH0KCiAgICB2b2lkIFlldEFub3RoZXJUZXN0KGNvbnN0IGNoYXIqIHApCiAgICB7CiAgICAgICAgKChBKil0aGlzKS0+YnVmZmVyID0gcDsKICAgIH0KCiAgICBpbnQgTm9QYXJhbXNUZXN0KCkKICAgIHsKICAgICAgICByZXR1cm4gKChBKil0aGlzKS0+ZHVtbXk7CiAgICB9CiAgICBpbnQgTm9QYXJhbXNUZXN0Q29uc3QoKSBjb25zdAogICAgewogICAgICAgIHJldHVybiAoKEEqKXRoaXMpLT5kdW1teTsKICAgIH0KCiAgICBzdHJpbmcgU29tZU90aGVyVGVzdChpbnQgaSwgaW50JiBqKQogICAgewogICAgICAgIGogPSBpOwogICAgICAgIHJldHVybiAoKEEqKXRoaXMpLT5idWZmZXIyOwogICAgfQoKICAgIGludCBUYWtlVGhyZWUoaW50IGksIGludCBqLCBpbnQgaykKICAgIHsKICAgICAgICByZXR1cm4gaSArIGogKyBrOwogICAgfQoKICAgIGludCBUYWtlRm91cihpbnQgaSwgaW50IGosIGludCBrLCBpbnQgbCkKICAgIHsKICAgICAgICByZXR1cm4gaSArIGogKyBrICsgbDsKICAgIH0KCiAgICBpbnQgVGFrZVRocmVlQ29uc3QoaW50IGksIGludCBqLCBpbnQgaykgY29uc3QKICAgIHsKICAgICAgICByZXR1cm4gaSArIGogKyBrOwogICAgfQoKICAgIGludCBUYWtlRm91ckNvbnN0KGludCBpLCBpbnQgaiwgaW50IGssIGludCBsKSBjb25zdAogICAgewogICAgICAgIHJldHVybiBpICsgaiArIGsgKyBsOwogICAgfQoKICAgIGludCBUYWtlRml2ZShpbnQgaSwgaW50IGosIGludCBrLCBpbnQgbCwgaW50IG0pCiAgICB7CiAgICAgICAgcmV0dXJuIGkgKyBqICsgayArIGwgKyBtOwogICAgfQoKICAgIGRvdWJsZSBUYWtlRml2ZTIoaW50IGksIGludCBqLCBpbnQgaywgaW50IGwsIGludCBtKQogICAgewogICAgICAgIHJldHVybiBpICsgaiArIGsgKyBsICsgbTsKICAgIH0KCiAgICBpbnQgVGFrZUZpdmVDb25zdChpbnQgaSwgaW50IGosIGludCBrLCBpbnQgbCwgaW50IG0pIGNvbnN0CiAgICB7CiAgICAgICAgcmV0dXJuIGkgKyBqICsgayArIGwgKyBtOwogICAgfQoKICAgIGRvdWJsZSBUZXN0MlRoaXNDYWxsKGludCBpLCBpbnQmIGopCiAgICB7CiAgICAgICAgcmV0dXJuIDAuMTsKICAgIH0KCiNpZiBkZWZpbmVkKF9XSU4zMikKICAgIHZvaWQgX19zdGRjYWxsIFN0ZENhbGwoY2hhciogcCkKICAgIHsKICAgICAgICAoKEEqKXRoaXMpLT5idWZmZXIgPSBwOwogICAgfQogICAgZG91YmxlIF9fY2RlY2wgVGVzdDJDZGVjbChpbnQgaSwgaW50JiBqKQogICAgewogICAgICAgIHJldHVybiAwLjI7CiAgICB9CiAgICBkb3VibGUgX19zdGRjYWxsIFRlc3QyU3RkQ2FsbChpbnQgaSwgaW50JiBqKQogICAgewogICAgICAgIHJldHVybiAwLjM7CiAgICB9CiAgICBkb3VibGUgX19mYXN0Y2FsbCBUZXN0MkZhc3RDYWxsKGludCBpLCBpbnQmIGopCiAgICB7CiAgICAgICAgcmV0dXJuIDAuNDsKICAgIH0KI2VuZGlmCgogICAgZG91YmxlIFRlc3RWYXJBcmdzVGhpc0NhbGwoaW50IGksIC4uLikKICAgIHsKICAgICAgICByZXR1cm4gMTEuOwogICAgfQoKICAgIGRvdWJsZSBUZXN0VmFyQXJnczBUaGlzQ2FsbCguLi4pCiAgICB7CiAgICAgICAgcmV0dXJuIDIxLjsKICAgIH0KfTsKCiNkZWZpbmUgQ0hFQ0tfRVFVQUwoYSwgYikgXAogICAgaWYgKChhKSA9PSAoYikpOyBlbHNlIGNlcnIgPDwgIkNIRUNLX0VRVUFMIGZhaWxlZCBhdCAiIF9fRklMRV9fICIoIiA8PCBfX0xJTkVfXyA8PCAiKVxuIjsKCmludCBtYWluKCkKewogICAgQ1hUZXN0IHRlc3Q7CgogICAgQSogcEEgPSAoQSopICZ0ZXN0OwoKICAgIENIRUNLX0VRVUFMKCI3NzciLCBwQS0+RHVtbXkwKDc3NykpOwoKICAgIGludCBpID0gOTk5OwogICAgQ0hFQ0tfRVFVQUwoIi05OTkiLCBwQS0+RHVtbXkwKCZpKSk7CgogICAgcEEtPkR1bW15MigiWWV0QW5vdGhlclRlc3QiKTsKICAgIENIRUNLX0VRVUFMKCJZZXRBbm90aGVyVGVzdCIsIHBBLT5idWZmZXIpOwoKCiAgICBwQS0+ZHVtbXkgPSAzNDU2OwogICAgQ0hFQ0tfRVFVQUwoMzQ1NiwgcEEtPkR1bW15MygpKTsKICAgIENIRUNLX0VRVUFMKDM0NTYsIHBBLT5EdW1teTNDb25zdCgpKTsKCiAgICBpbnQgaiA9IDA7CiAgICBwQS0+YnVmZmVyMiA9ICJUaGlzIHdvdWxkIGJlIHRvIG1pc3MgYW4gb3Bwb3J0dW5pdHkuIjsKICAgIENIRUNLX0VRVUFMKCJUaGlzIHdvdWxkIGJlIHRvIG1pc3MgYW4gb3Bwb3J0dW5pdHkuIiwgcEEtPlNvbWVPdGhlclRlc3QoaSwgaikpOwogICAgQ0hFQ0tfRVFVQUwoaSwgaik7CgogICAgQ0hFQ0tfRVFVQUwoNiwgcEEtPlRha2VUaHJlZSgxLCAyLCAzKSk7CiAgICBDSEVDS19FUVVBTCgxMCwgcEEtPlRha2VGb3VyKDEsIDIsIDMsIDQpKTsKCiAgICBDSEVDS19FUVVBTCg2LCBwQS0+VGFrZVRocmVlQ29uc3QoMSwgMiwgMykpOwogICAgQ0hFQ0tfRVFVQUwoMTAsIHBBLT5UYWtlRm91ckNvbnN0KDEsIDIsIDMsIDQpKTsKCiAgICBDSEVDS19FUVVBTCgxNSwgcEEtPlRha2VGaXZlKDEsIDIsIDMsIDQsIDUpKTsKICAgIENIRUNLX0VRVUFMKDE1LCBwQS0+VGFrZUZpdmVDb25zdCgxLCAyLCAzLCA0LCA1KSk7CgogICAgQ0hFQ0tfRVFVQUwoMC4xLCBwQS0+VGVzdDJUaGlzQ2FsbCgxLCBqKSk7CiNpZiBkZWZpbmVkKF9XSU4zMikKICAgIHBBLT5TdGRDYWxsKCJTdGRDYWxsVGVzdCIpOwogICAgQ0hFQ0tfRVFVQUwoIlN0ZENhbGxUZXN0IiwgcEEtPmJ1ZmZlcik7CiAgICBDSEVDS19FUVVBTCgwLjIsIHBBLT5UZXN0MkNkZWNsKDEsIGopKTsKICAgIENIRUNLX0VRVUFMKDAuMywgcEEtPlRlc3QyU3RkQ2FsbCgxLCBqKSk7CiAgICBDSEVDS19FUVVBTCgwLjQsIHBBLT5UZXN0MkZhc3RDYWxsKDEsIGopKTsKI2VuZGlmCgogICAgQ0hFQ0tfRVFVQUwoMTEuLCBwQS0+VGVzdFZhckFyZ3NUaGlzQ2FsbCgxLCBqKSk7CiAgICBDSEVDS19FUVVBTCgyMS4sIHBBLT5UZXN0VmFyQXJnczBUaGlzQ2FsbCgxLCBqKSk7CgogICAgc3RkOjpjb3V0IDw8ICJvay5cbiI7Cn0K