#include <iostream>
#include <cassert>
class stackelement {
stackelement* caller;
stackelement* callee;
static stackelement* & frameptr( )
{
static stackelement* frameptr= NULL ;
return frameptr;
}
protected :
virtual const char * get_name( ) const = 0 ;
virtual void printparams( std:: ostream & out,
const char * before_params,
const char * between_params,
const char * after_params) const = 0 ;
public :
stackelement( )
: caller( frameptr( ) ) , callee( NULL )
{ frameptr( ) = this ; }
stackelement( const stackelement& r)
: caller( r.caller ) , callee( r.callee )
{
assert ( frameptr( ) == & r) ;
frameptr( ) = this ;
}
stackelement& operator= ( const stackelement& r) {
assert ( frameptr( ) == & r) ;
caller = r.caller ;
callee = r.callee ;
frameptr( ) = this ;
return * this ;
}
virtual ~stackelement( ) {
if ( caller)
caller- > callee = NULL ;
frameptr( ) = caller;
}
static void print( std:: ostream & out,
const char * begin_line= "" ,
const char * before_params= " with " ,
const char * between_params= ", " ,
const char * after_params= "." ,
const char * end_line= "\n " ) {
stackelement* self = frameptr( ) ;
do {
out << begin_line << self- > get_name( ) ;
self- > printparams( out, before_params, between_params, after_params) ;
out << end_line;
self = self- > caller;
} while ( self) ;
}
} ;
template < class P0, class P1, class P2, class P3, class P4>
struct stackinstance : stackelement {
protected :
const char * name;
P0& p0;
P1& p1;
P2& p2;
P3& p3;
P4& p4;
public :
template < int N>
stackinstance( const char ( & name_) [ N] , P0& p0_, P1& p1_, P2& p2_, P3& p3_, P4& p4_)
: name( name_) , p0( p0_) , p1( p1_) , p2( p2_) , p3( p3_) , p4( p4_) { }
protected :
virtual const char * get_name( ) const { return name; }
virtual void printparams( std:: ostream & out,
const char * before_params,
const char * between_params,
const char * after_params) const
{ out << before_params << p0
<< between_params << p1
<< between_params << p2
<< between_params << p3
<< between_params << p4
<< after_params; }
} ;
template < class P0, class P1, class P2, class P3>
struct stackinstance< P0, P1, P2, P3, void > : stackelement {
protected :
const char * name;
P0& p0;
P1& p1;
P2& p2;
P3& p3;
public :
template < int N>
stackinstance( const char ( & name_) [ N] , P0& p0_, P1& p1_, P2& p2_, P3& p3_)
: name( name_) , p0( p0_) , p1( p1_) , p2( p2_) , p3( p3_) { }
protected :
virtual const char * get_name( ) const { return name; }
virtual void printparams( std:: ostream & out,
const char * before_params,
const char * between_params,
const char * after_params) const
{ out << before_params << p0
<< between_params << p1
<< between_params << p2
<< between_params << p3
<< after_params; }
} ;
template < class P0, class P1, class P2>
struct stackinstance< P0, P1, P2, void , void > : stackelement {
protected :
const char * name;
P0& p0;
P1& p1;
P2& p2;
public :
template < int N>
stackinstance( const char ( & name_) [ N] , P0& p0_, P1& p1_, P2& p2_)
: name( name_) , p0( p0_) , p1( p1_) , p2( p2_) { }
protected :
virtual const char * get_name( ) const { return name; }
virtual void printparams( std:: ostream & out,
const char * before_params,
const char * between_params,
const char * after_params) const
{ out << before_params << p0
<< between_params << p1
<< between_params << p2
<< after_params; }
} ;
template < class P0, class P1>
struct stackinstance< P0, P1, void , void , void > : stackelement {
protected :
const char * name;
P0& p0;
P1& p1;
public :
template < int N>
stackinstance( const char ( & name_) [ N] , P0& p0_, P1& p1_)
: name( name_) , p0( p0_) , p1( p1_) { }
protected :
virtual const char * get_name( ) const { return name; }
virtual void printparams( std:: ostream & out,
const char * before_params,
const char * between_params,
const char * after_params) const
{ out << before_params << p0
<< between_params << p1
<< after_params; }
} ;
template < class P0>
struct stackinstance< P0, void , void , void , void > : stackelement {
protected :
const char * name;
P0& p0;
public :
template < int N>
stackinstance( const char ( & name_) [ N] , P0& p0_)
: name( name_) , p0( p0_) { }
protected :
virtual const char * get_name( ) const { return name; }
virtual void printparams( std:: ostream & out,
const char * before_params,
const char * between_params,
const char * after_params) const
{ out << before_params << p0
<< after_params; }
} ;
template <>
struct stackinstance< void , void , void , void , void > : stackelement {
protected :
const char * name;
public :
template < int N>
stackinstance( const char ( & name_) [ N] )
: name( name_) { }
protected :
virtual const char * get_name( ) const { return name; }
virtual void printparams( std:: ostream & ,
const char * ,
const char * ,
const char * ) const
{ }
} ;
template < int N, class P0, class P1, class P2, class P3, class P4>
stackinstance< P0, P1, P2, P3, P4> StackTrace( const char ( & name_) [ N] , P0& p0_, P1& p1_, P2& p2_, P3& p3_, P4& p4_)
{ return stackinstance< P0, P1, P2, P3, P4> ( name_, p0_, p1_, p2_, p3_, p4_) ; }
template < int N, class P0, class P1, class P2, class P3>
stackinstance< P0, P1, P2, P3, void > StackTrace( const char ( & name_) [ N] , P0& p0_, P1& p1_, P2& p2_, P3& p3_)
{ return stackinstance< P0, P1, P2, P3, void > ( name_, p0_, p1_, p2_, p3_) ; }
template < int N, class P0, class P1, class P2>
stackinstance< P0, P1, P2, void , void > StackTrace( const char ( & name_) [ N] , P0& p0_, P1& p1_, P2& p2_)
{ return stackinstance< P0, P1, P2, void , void > ( name_, p0_, p1_, p2_) ; }
template < int N, class P0, class P1>
stackinstance< P0, P1, void , void , void > StackTrace( const char ( & name_) [ N] , P0& p0_, P1& p1_)
{ return stackinstance< P0, P1, void , void , void > ( name_, p0_, p1_) ; }
template < int N, class P0>
stackinstance< P0, void , void , void , void > StackTrace( const char ( & name_) [ N] , P0& p0_)
{ return stackinstance< P0, void , void , void , void > ( name_, p0_) ; }
template < int N>
stackinstance< void , void , void , void , void > StackTrace( const char ( & name_) [ N] )
{ return stackinstance< void , void , void , void , void > ( name_) ; }
#ifdef __GNUC__
#define __FUNCSIG__ __PRETTY_FUNCTION__
#endif
#include <iostream>
#include <sstream>
#include <exception>
#include <stdexcept>
class stack_aware_exception : public std:: runtime_error {
std:: string get_stack( ) {
std:: stringstream stacktrace;
stackelement:: print ( stacktrace) ;
return stacktrace.str ( ) ;
}
public :
stack_aware_exception( ) : std:: runtime_error ( get_stack( ) ) { }
} ;
unsigned thing( unsigned i) {
auto trace = StackTrace( __FUNCSIG__, i) ;
if ( i== 10 )
throw stack_aware_exception( ) ;
else if ( i== 0 )
return i;
return thing( i- 1 ) ;
}
int Foo( ) {
auto trace = StackTrace( __FUNCSIG__) ;
return thing( 7 ) + thing( 0 ) + thing( 17 ) ;
}
int main( int argc, char ** argv) {
auto trace = StackTrace( __FUNCSIG__, argc, argv) ;
try {
Foo( ) ;
} catch ( const stack_aware_exception& exc) {
std:: cout << exc.what ( ) ;
}
return 0 ;
}
CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGNhc3NlcnQ+CgpjbGFzcyBzdGFja2VsZW1lbnQgewoJc3RhY2tlbGVtZW50KiBjYWxsZXI7CglzdGFja2VsZW1lbnQqIGNhbGxlZTsKCXN0YXRpYyBzdGFja2VsZW1lbnQqJiBmcmFtZXB0cigpIAoJewoJCXN0YXRpYyBzdGFja2VsZW1lbnQqIGZyYW1lcHRyPU5VTEw7CgkJcmV0dXJuIGZyYW1lcHRyOwoJfQpwcm90ZWN0ZWQ6Cgl2aXJ0dWFsIGNvbnN0IGNoYXIqIGdldF9uYW1lKCkgY29uc3QgPTA7Cgl2aXJ0dWFsIHZvaWQgcHJpbnRwYXJhbXMoc3RkOjpvc3RyZWFtJiBvdXQsCgkJCQkJCQkJCSAgY29uc3QgY2hhciogYmVmb3JlX3BhcmFtcywKCQkJCQkJCQkJICBjb25zdCBjaGFyKiBiZXR3ZWVuX3BhcmFtcywKCQkJCQkJCQkJICBjb25zdCBjaGFyKiBhZnRlcl9wYXJhbXMpIGNvbnN0ID0wOwpwdWJsaWM6CglzdGFja2VsZW1lbnQoKSAKCQk6IGNhbGxlcihmcmFtZXB0cigpKSwgY2FsbGVlKE5VTEwpCgl7IGZyYW1lcHRyKCkgPSB0aGlzO30KCXN0YWNrZWxlbWVudChjb25zdCBzdGFja2VsZW1lbnQmIHIpIAoJCTogY2FsbGVyKHIuY2FsbGVyKSwgY2FsbGVlKHIuY2FsbGVlKSAKCXsKCQlhc3NlcnQoZnJhbWVwdHIoKSA9PSAmcik7CgkJZnJhbWVwdHIoKSA9IHRoaXM7Cgl9CglzdGFja2VsZW1lbnQmIG9wZXJhdG9yPShjb25zdCBzdGFja2VsZW1lbnQmIHIpICB7CgkJYXNzZXJ0KGZyYW1lcHRyKCkgPT0gJnIpOwoJCWNhbGxlciA9IHIuY2FsbGVyOwoJCWNhbGxlZSA9IHIuY2FsbGVlOwoJCWZyYW1lcHRyKCkgPSB0aGlzOwoJCXJldHVybiAqdGhpczsKCX0KCXZpcnR1YWwgfnN0YWNrZWxlbWVudCgpIHsKCQlpZiAoY2FsbGVyKQoJCQljYWxsZXItPmNhbGxlZSA9IE5VTEw7CgkJZnJhbWVwdHIoKSA9IGNhbGxlcjsKCX0KCXN0YXRpYyB2b2lkIHByaW50KHN0ZDo6b3N0cmVhbSYgb3V0LCAKCQkJCQkJY29uc3QgY2hhciogYmVnaW5fbGluZT0iIiwgCgkJCQkJCWNvbnN0IGNoYXIqIGJlZm9yZV9wYXJhbXM9IiB3aXRoICIsIAoJCQkJCQljb25zdCBjaGFyKiBiZXR3ZWVuX3BhcmFtcz0iLCAiLAoJCQkJCQljb25zdCBjaGFyKiBhZnRlcl9wYXJhbXM9Ii4iLAoJCQkJCQljb25zdCBjaGFyKiBlbmRfbGluZT0iXG4iKSB7CgkJc3RhY2tlbGVtZW50KiBzZWxmID0gZnJhbWVwdHIoKTsKCQlkbyB7CgkJCW91dCA8PCBiZWdpbl9saW5lIDw8IHNlbGYtPmdldF9uYW1lKCk7CgkJCXNlbGYtPnByaW50cGFyYW1zKG91dCwgYmVmb3JlX3BhcmFtcywgYmV0d2Vlbl9wYXJhbXMsIGFmdGVyX3BhcmFtcyk7CgkJCW91dCA8PCBlbmRfbGluZTsKCQkJc2VsZiA9IHNlbGYtPmNhbGxlcjsKCQl9IHdoaWxlKHNlbGYpOwoJfQp9OwoKdGVtcGxhdGU8Y2xhc3MgUDAsIGNsYXNzIFAxLCBjbGFzcyBQMiwgY2xhc3MgUDMsIGNsYXNzIFA0PgpzdHJ1Y3Qgc3RhY2tpbnN0YW5jZSA6IHN0YWNrZWxlbWVudCB7CnByb3RlY3RlZDoKCWNvbnN0IGNoYXIqIG5hbWU7CglQMCYgcDA7CglQMSYgcDE7CglQMiYgcDI7CglQMyYgcDM7CglQNCYgcDQ7CnB1YmxpYzoKCXRlbXBsYXRlPGludCBOPgoJc3RhY2tpbnN0YW5jZShjb25zdCBjaGFyKCZuYW1lXylbTl0sIFAwJiBwMF8sIFAxJiBwMV8sIFAyJiBwMl8sIFAzJiBwM18sIFA0JiBwNF8pCgkJOm5hbWUobmFtZV8pLCBwMChwMF8pLCBwMShwMV8pLCBwMihwMl8pLCBwMyhwM18pLCBwNChwNF8pIHt9CnByb3RlY3RlZDoKCXZpcnR1YWwgY29uc3QgY2hhciogZ2V0X25hbWUoKSBjb25zdCAge3JldHVybiBuYW1lO30KCXZpcnR1YWwgdm9pZCBwcmludHBhcmFtcyhzdGQ6Om9zdHJlYW0mIG91dCwKCQkJCQkJCQkJICBjb25zdCBjaGFyKiBiZWZvcmVfcGFyYW1zLAoJCQkJCQkJCQkgIGNvbnN0IGNoYXIqIGJldHdlZW5fcGFyYW1zLAoJCQkJCQkJCQkgIGNvbnN0IGNoYXIqIGFmdGVyX3BhcmFtcykgY29uc3QgCgl7b3V0IDw8IGJlZm9yZV9wYXJhbXMgPDwgcDAKCQkJCTw8IGJldHdlZW5fcGFyYW1zIDw8IHAxCgkJCQk8PCBiZXR3ZWVuX3BhcmFtcyA8PCBwMgoJCQkJPDwgYmV0d2Vlbl9wYXJhbXMgPDwgcDMKCQkJCTw8IGJldHdlZW5fcGFyYW1zIDw8IHA0CgkJCQk8PCBhZnRlcl9wYXJhbXM7IH0KfTsKCnRlbXBsYXRlPGNsYXNzIFAwLCBjbGFzcyBQMSwgY2xhc3MgUDIsIGNsYXNzIFAzPgpzdHJ1Y3Qgc3RhY2tpbnN0YW5jZTxQMCwgUDEsIFAyLCBQMywgdm9pZD4gOiBzdGFja2VsZW1lbnQgewpwcm90ZWN0ZWQ6Cgljb25zdCBjaGFyKiBuYW1lOwoJUDAmIHAwOwoJUDEmIHAxOwoJUDImIHAyOwoJUDMmIHAzOwpwdWJsaWM6Cgl0ZW1wbGF0ZTxpbnQgTj4KCXN0YWNraW5zdGFuY2UoY29uc3QgY2hhcigmbmFtZV8pW05dLCBQMCYgcDBfLCBQMSYgcDFfLCBQMiYgcDJfLCBQMyYgcDNfKQoJCTpuYW1lKG5hbWVfKSwgcDAocDBfKSwgcDEocDFfKSwgcDIocDJfKSwgcDMocDNfKSB7fQpwcm90ZWN0ZWQ6Cgl2aXJ0dWFsIGNvbnN0IGNoYXIqIGdldF9uYW1lKCkgY29uc3QgIHtyZXR1cm4gbmFtZTt9Cgl2aXJ0dWFsIHZvaWQgcHJpbnRwYXJhbXMoc3RkOjpvc3RyZWFtJiBvdXQsCgkJCQkJCQkJCSAgY29uc3QgY2hhciogYmVmb3JlX3BhcmFtcywKCQkJCQkJCQkJICBjb25zdCBjaGFyKiBiZXR3ZWVuX3BhcmFtcywKCQkJCQkJCQkJICBjb25zdCBjaGFyKiBhZnRlcl9wYXJhbXMpIGNvbnN0IAoJe291dCA8PCBiZWZvcmVfcGFyYW1zIDw8IHAwCgkJCQk8PCBiZXR3ZWVuX3BhcmFtcyA8PCBwMQoJCQkJPDwgYmV0d2Vlbl9wYXJhbXMgPDwgcDIKCQkJCTw8IGJldHdlZW5fcGFyYW1zIDw8IHAzCgkJCQk8PCBhZnRlcl9wYXJhbXM7IH0KfTsKCnRlbXBsYXRlPGNsYXNzIFAwLCBjbGFzcyBQMSwgY2xhc3MgUDI+CnN0cnVjdCBzdGFja2luc3RhbmNlPFAwLCBQMSwgUDIsIHZvaWQsIHZvaWQ+IDogc3RhY2tlbGVtZW50IHsKcHJvdGVjdGVkOgoJY29uc3QgY2hhciogbmFtZTsKCVAwJiBwMDsKCVAxJiBwMTsKCVAyJiBwMjsKcHVibGljOgoJdGVtcGxhdGU8aW50IE4+CglzdGFja2luc3RhbmNlKGNvbnN0IGNoYXIoJm5hbWVfKVtOXSwgUDAmIHAwXywgUDEmIHAxXywgUDImIHAyXykKCQk6bmFtZShuYW1lXyksIHAwKHAwXyksIHAxKHAxXyksIHAyKHAyXykge30KcHJvdGVjdGVkOgoJdmlydHVhbCBjb25zdCBjaGFyKiBnZXRfbmFtZSgpIGNvbnN0ICB7cmV0dXJuIG5hbWU7fQoJdmlydHVhbCB2b2lkIHByaW50cGFyYW1zKHN0ZDo6b3N0cmVhbSYgb3V0LAoJCQkJCQkJCQkgIGNvbnN0IGNoYXIqIGJlZm9yZV9wYXJhbXMsCgkJCQkJCQkJCSAgY29uc3QgY2hhciogYmV0d2Vlbl9wYXJhbXMsCgkJCQkJCQkJCSAgY29uc3QgY2hhciogYWZ0ZXJfcGFyYW1zKSBjb25zdCAKCXtvdXQgPDwgYmVmb3JlX3BhcmFtcyA8PCBwMAoJCQkJPDwgYmV0d2Vlbl9wYXJhbXMgPDwgcDEKCQkJCTw8IGJldHdlZW5fcGFyYW1zIDw8IHAyCgkJCQk8PCBhZnRlcl9wYXJhbXM7IH0KfTsKCnRlbXBsYXRlPGNsYXNzIFAwLCBjbGFzcyBQMT4Kc3RydWN0IHN0YWNraW5zdGFuY2U8UDAsIFAxLCB2b2lkLCB2b2lkLCB2b2lkPiA6IHN0YWNrZWxlbWVudCB7CnByb3RlY3RlZDoKCWNvbnN0IGNoYXIqIG5hbWU7CglQMCYgcDA7CglQMSYgcDE7CnB1YmxpYzoKCXRlbXBsYXRlPGludCBOPgoJc3RhY2tpbnN0YW5jZShjb25zdCBjaGFyKCZuYW1lXylbTl0sIFAwJiBwMF8sIFAxJiBwMV8pCgkJOm5hbWUobmFtZV8pLCBwMChwMF8pLCBwMShwMV8pIHt9CnByb3RlY3RlZDoKCXZpcnR1YWwgY29uc3QgY2hhciogZ2V0X25hbWUoKSBjb25zdCAge3JldHVybiBuYW1lO30KCXZpcnR1YWwgdm9pZCBwcmludHBhcmFtcyhzdGQ6Om9zdHJlYW0mIG91dCwKCQkJCQkJCQkJICBjb25zdCBjaGFyKiBiZWZvcmVfcGFyYW1zLAoJCQkJCQkJCQkgIGNvbnN0IGNoYXIqIGJldHdlZW5fcGFyYW1zLAoJCQkJCQkJCQkgIGNvbnN0IGNoYXIqIGFmdGVyX3BhcmFtcykgY29uc3QgCgl7b3V0IDw8IGJlZm9yZV9wYXJhbXMgPDwgcDAgCgkJCQk8PCBiZXR3ZWVuX3BhcmFtcyA8PCBwMQoJCQkJPDwgYWZ0ZXJfcGFyYW1zOyB9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBQMD4Kc3RydWN0IHN0YWNraW5zdGFuY2U8UDAsIHZvaWQsIHZvaWQsIHZvaWQsIHZvaWQ+IDogc3RhY2tlbGVtZW50IHsKcHJvdGVjdGVkOgoJY29uc3QgY2hhciogbmFtZTsKCVAwJiBwMDsKcHVibGljOgoJdGVtcGxhdGU8aW50IE4+CglzdGFja2luc3RhbmNlKGNvbnN0IGNoYXIoJm5hbWVfKVtOXSwgUDAmIHAwXykKCQk6bmFtZShuYW1lXyksIHAwKHAwXykge30KcHJvdGVjdGVkOgoJdmlydHVhbCBjb25zdCBjaGFyKiBnZXRfbmFtZSgpIGNvbnN0ICB7cmV0dXJuIG5hbWU7fQoJdmlydHVhbCB2b2lkIHByaW50cGFyYW1zKHN0ZDo6b3N0cmVhbSYgb3V0LAoJCQkJCQkJCQkgIGNvbnN0IGNoYXIqIGJlZm9yZV9wYXJhbXMsCgkJCQkJCQkJCSAgY29uc3QgY2hhciogYmV0d2Vlbl9wYXJhbXMsCgkJCQkJCQkJCSAgY29uc3QgY2hhciogYWZ0ZXJfcGFyYW1zKSBjb25zdCAKCXtvdXQgPDwgYmVmb3JlX3BhcmFtcyA8PCBwMAoJCQkJPDwgYWZ0ZXJfcGFyYW1zOyB9Cn07Cgp0ZW1wbGF0ZTw+CnN0cnVjdCBzdGFja2luc3RhbmNlPHZvaWQsIHZvaWQsIHZvaWQsIHZvaWQsIHZvaWQ+IDogc3RhY2tlbGVtZW50IHsKcHJvdGVjdGVkOgoJY29uc3QgY2hhciogbmFtZTsKcHVibGljOgoJdGVtcGxhdGU8aW50IE4+CglzdGFja2luc3RhbmNlKGNvbnN0IGNoYXIoJm5hbWVfKVtOXSkKCQk6bmFtZShuYW1lXykge30KcHJvdGVjdGVkOgoJdmlydHVhbCBjb25zdCBjaGFyKiBnZXRfbmFtZSgpIGNvbnN0IHtyZXR1cm4gbmFtZTt9Cgl2aXJ0dWFsIHZvaWQgcHJpbnRwYXJhbXMoc3RkOjpvc3RyZWFtJiwKCQkJCQkJCQkJICBjb25zdCBjaGFyKiwKCQkJCQkJCQkJICBjb25zdCBjaGFyKiwKCQkJCQkJCQkJICBjb25zdCBjaGFyKikgY29uc3QgCgl7fQp9OwoKdGVtcGxhdGU8aW50IE4sIGNsYXNzIFAwLCBjbGFzcyBQMSwgY2xhc3MgUDIsIGNsYXNzIFAzLCBjbGFzcyBQND4Kc3RhY2tpbnN0YW5jZTxQMCwgUDEsIFAyLCBQMywgUDQ+IFN0YWNrVHJhY2UoY29uc3QgY2hhcigmbmFtZV8pW05dLCBQMCYgcDBfLCBQMSYgcDFfLCBQMiYgcDJfLCBQMyYgcDNfLCBQNCYgcDRfKQp7cmV0dXJuIHN0YWNraW5zdGFuY2U8UDAsIFAxLCBQMiwgUDMsIFA0PihuYW1lXywgcDBfLCBwMV8sIHAyXywgcDNfLCBwNF8pO30KCnRlbXBsYXRlPGludCBOLCBjbGFzcyBQMCwgY2xhc3MgUDEsIGNsYXNzIFAyLCBjbGFzcyBQMz4Kc3RhY2tpbnN0YW5jZTxQMCwgUDEsIFAyLCBQMywgdm9pZD4gU3RhY2tUcmFjZShjb25zdCBjaGFyKCZuYW1lXylbTl0sIFAwJiBwMF8sIFAxJiBwMV8sIFAyJiBwMl8sIFAzJiBwM18pCntyZXR1cm4gc3RhY2tpbnN0YW5jZTxQMCwgUDEsIFAyLCBQMywgdm9pZD4obmFtZV8sIHAwXywgcDFfLCBwMl8sIHAzXyk7fQoKdGVtcGxhdGU8aW50IE4sIGNsYXNzIFAwLCBjbGFzcyBQMSwgY2xhc3MgUDI+CnN0YWNraW5zdGFuY2U8UDAsIFAxLCBQMiwgdm9pZCwgdm9pZD4gU3RhY2tUcmFjZShjb25zdCBjaGFyKCZuYW1lXylbTl0sIFAwJiBwMF8sIFAxJiBwMV8sIFAyJiBwMl8pCntyZXR1cm4gc3RhY2tpbnN0YW5jZTxQMCwgUDEsIFAyLCB2b2lkLCB2b2lkPihuYW1lXywgcDBfLCBwMV8sIHAyXyk7fQoKdGVtcGxhdGU8aW50IE4sIGNsYXNzIFAwLCBjbGFzcyBQMT4Kc3RhY2tpbnN0YW5jZTxQMCwgUDEsIHZvaWQsIHZvaWQsIHZvaWQ+IFN0YWNrVHJhY2UoY29uc3QgY2hhcigmbmFtZV8pW05dLCBQMCYgcDBfLCBQMSYgcDFfKQp7cmV0dXJuIHN0YWNraW5zdGFuY2U8UDAsIFAxLCB2b2lkLCB2b2lkLCB2b2lkPihuYW1lXywgcDBfLCBwMV8pO30KCnRlbXBsYXRlPGludCBOLCBjbGFzcyBQMD4Kc3RhY2tpbnN0YW5jZTxQMCwgdm9pZCwgdm9pZCwgdm9pZCwgdm9pZD4gU3RhY2tUcmFjZShjb25zdCBjaGFyKCZuYW1lXylbTl0sIFAwJiBwMF8pCntyZXR1cm4gc3RhY2tpbnN0YW5jZTxQMCwgdm9pZCwgdm9pZCwgdm9pZCwgdm9pZD4obmFtZV8sIHAwXyk7fQoKdGVtcGxhdGU8aW50IE4+CnN0YWNraW5zdGFuY2U8dm9pZCwgdm9pZCwgdm9pZCwgdm9pZCwgdm9pZD4gU3RhY2tUcmFjZShjb25zdCBjaGFyKCZuYW1lXylbTl0pCntyZXR1cm4gc3RhY2tpbnN0YW5jZTx2b2lkLCB2b2lkLCB2b2lkLCB2b2lkLCB2b2lkPihuYW1lXyk7fQoKI2lmZGVmIF9fR05VQ19fCiNkZWZpbmUgX19GVU5DU0lHX18gX19QUkVUVFlfRlVOQ1RJT05fXwojZW5kaWYKCgoKCgoKCgoKCgoKCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHNzdHJlYW0+CiNpbmNsdWRlIDxleGNlcHRpb24+CiNpbmNsdWRlIDxzdGRleGNlcHQ+CgpjbGFzcyBzdGFja19hd2FyZV9leGNlcHRpb24gOiBwdWJsaWMgc3RkOjpydW50aW1lX2Vycm9yIHsKCXN0ZDo6c3RyaW5nIGdldF9zdGFjaygpIHsKCQlzdGQ6OnN0cmluZ3N0cmVhbSBzdGFja3RyYWNlOwoJCXN0YWNrZWxlbWVudDo6cHJpbnQoc3RhY2t0cmFjZSk7CgkJcmV0dXJuIHN0YWNrdHJhY2Uuc3RyKCk7Cgl9CnB1YmxpYzoKCXN0YWNrX2F3YXJlX2V4Y2VwdGlvbigpIDpzdGQ6OnJ1bnRpbWVfZXJyb3IoZ2V0X3N0YWNrKCkpIHt9Cn07Cgp1bnNpZ25lZCB0aGluZyh1bnNpZ25lZCBpKSB7CglhdXRvIHRyYWNlID0gU3RhY2tUcmFjZShfX0ZVTkNTSUdfXywgaSk7CglpZiAoaT09MTApCgkJdGhyb3cgc3RhY2tfYXdhcmVfZXhjZXB0aW9uKCk7CgllbHNlIGlmIChpPT0wKQoJCXJldHVybiBpOwoJcmV0dXJuIHRoaW5nKGktMSk7Cn0KCmludCBGb28oKSB7CglhdXRvIHRyYWNlID0gU3RhY2tUcmFjZShfX0ZVTkNTSUdfXyk7CglyZXR1cm4gdGhpbmcoNykgKyB0aGluZygwKSArIHRoaW5nKDE3KTsKfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqKiBhcmd2KSB7CglhdXRvIHRyYWNlID0gU3RhY2tUcmFjZShfX0ZVTkNTSUdfXywgYXJnYywgYXJndik7Cgl0cnkgewoJCUZvbygpOwoJfSBjYXRjaChjb25zdCBzdGFja19hd2FyZV9leGNlcHRpb24mIGV4YykgewoJCXN0ZDo6Y291dCA8PCBleGMud2hhdCgpOwoJfQoJcmV0dXJuIDA7Cn0=