#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX_SOURCE 5000
#define MAX_TOKENS 500
#define MAX_TEXT 50
#define MAX_SYMBOLS 100
#define MAX_ERRORS 100
#define MAX_TAC 500
#define TOKEN_INT 1
#define TOKEN_IDENTIFIER 2
#define TOKEN_NUMBER 3
#define TOKEN_IF 4
#define TOKEN_ELSE 5
#define TOKEN_WHILE 6
#define TOKEN_OPERATOR 7
#define TOKEN_SYMBOL 8
#define TOKEN_UNKNOWN 9
char source[ MAX_SOURCE] ;
int sourceLength = 0 ;
char tokenText[ MAX_TOKENS] [ MAX_TEXT] ;
int tokenType[ MAX_TOKENS] ;
int tokenLine[ MAX_TOKENS] ;
int tokenCount = 0 ;
char symbolName[ MAX_SYMBOLS] [ MAX_TEXT] ;
char symbolType[ MAX_SYMBOLS] [ 20 ] ;
int symbolValue[ MAX_SYMBOLS] ;
int symbolCount = 0 ;
char semanticErrors[ MAX_ERRORS] [ 100 ] ;
int semanticErrorCount = 0 ;
char tac[ MAX_TAC] [ 100 ] ;
int tacCount = 0 ;
int currentToken = 0 ;
int syntaxError = 0 ;
char syntaxErrorMessage[ 120 ] ;
int tempCount = 1 ;
int labelCount = 1 ;
int assignmentAffectsSymbol = 1 ;
char lastIdentifier[ MAX_TEXT] ;
char lastExpressionText[ 100 ] ;
char lastExprLeft[ MAX_TEXT] ;
char lastExprOp[ MAX_TEXT] ;
char lastExprRight[ MAX_TEXT] ;
int lastExprHasOperator = 0 ;
int lastExprValue = 0 ;
int lastExprValueKnown = 0 ;
int lastExprSemanticOk = 1 ;
char conditionLeft[ MAX_TEXT] ;
char conditionOp[ MAX_TEXT] ;
char conditionRight[ MAX_TEXT] ;
char tempLine[ 150 ] ;
void readSource( ) ;
void tokenize( ) ;
void printSource( ) ;
void printTokens( ) ;
void parseProgram( ) ;
void parseDeclaration( ) ;
void parseAssignment( ) ;
void parseIfStatement( ) ;
void parseWhileStatement( ) ;
void parseCondition( ) ;
void parseExpression( ) ;
void readOperand( char outputText[ ] ) ;
int findSymbolIndex( char name[ ] ) ;
void addSymbol( char name[ ] ) ;
void updateSymbolValue( char name[ ] , int value) ;
void addSemanticError( char message[ ] ) ;
void addTAC( char line[ ] ) ;
void printSyntaxResult( ) ;
void printSymbolTable( ) ;
void printSemanticErrors( ) ;
void printTAC( ) ;
void addToken( char text[ ] , int type, int line) ;
int isOperatorToken( char text[ ] ) ;
int isSymbolToken( char text[ ] ) ;
int tokenIs( char text[ ] ) ;
int tokenKindIs( int type) ;
void setSyntaxError( char message[ ] ) ;
void expectText( char text[ ] ) ;
void copyCurrentToken( char outputText[ ] ) ;
int operandValue( char text[ ] , int ok) ;
int newLabel( ) ;
int main( )
{
readSource( ) ;
tokenize( ) ;
printf ( "========== Source Program ==========\n " ) ; printSource( ) ;
printf ( "\n ========== 1. Tokens ==========\n " ) ; printTokens( ) ;
parseProgram( ) ;
printf ( "\n ========== 2. Syntax Analysis Output ==========\n " ) ; printSyntaxResult( ) ;
printf ( "\n ========== 3. Symbol Table ==========\n " ) ; printSymbolTable( ) ;
printf ( "\n ========== 4. Semantic Analysis Output ==========\n " ) ; printSemanticErrors( ) ;
printf ( "\n ========== 5. Three Address Code ==========\n " ) ; printTAC( ) ;
return 0 ;
}
void readSource( )
{
int ch;
int i;
i = 0 ;
if ( freopen ( "input.txt" , "r" , stdin
) == NULL
) {
printf ( "Error: input.txt file not found.\n " ) ; source[ 0 ] = '\0 ' ;
sourceLength = 0 ;
return ;
}
while ( ( ch
= getchar ( ) ) != EOF
&& i
< MAX_SOURCE
- 1 ) {
source[ i] = ch;
i++;
}
source[ i] = '\0 ' ;
sourceLength = i;
}
void printSource( )
{
if ( sourceLength == 0 )
{
printf ( "No source code loaded.\n " ) ; }
else
{
if ( source[ sourceLength - 1 ] != '\n ' )
{
}
}
}
void addToken( char text[ ] , int type, int line)
{
if ( tokenCount >= MAX_TOKENS)
{
return ;
}
strcpy ( tokenText
[ tokenCount
] , text
) ; tokenType[ tokenCount] = type;
tokenLine[ tokenCount] = line;
tokenCount++;
}
int isOperatorToken( char text[ ] )
{
{
return 1 ;
}
{
return 1 ;
}
{
return 1 ;
}
{
return 1 ;
}
{
return 1 ;
}
return 0 ;
}
int isSymbolToken( char text[ ] )
{
{
return 1 ;
}
{
return 1 ;
}
{
return 1 ;
}
return 0 ;
}
void tokenize( )
{
int i;
int j;
int line;
char word[ MAX_TEXT] ;
char single[ 2 ] ;
i = 0 ;
line = 1 ;
while ( source[ i] != '\0 ' )
{
if ( source[ i] == '\n ' )
{
line++;
i++;
}
{
i++;
}
else if ( isalpha ( source
[ i
] ) || source
[ i
] == '_' ) {
j = 0 ;
while ( ( isalnum ( source
[ i
] ) || source
[ i
] == '_' ) && j
< MAX_TEXT
- 1 ) {
word[ j] = source[ i] ;
j++;
i++;
}
word[ j] = '\0 ' ;
{
addToken( word, TOKEN_INT, line) ;
}
else if ( strcmp ( word
, "if" ) == 0 ) {
addToken( word, TOKEN_IF, line) ;
}
else if ( strcmp ( word
, "else" ) == 0 ) {
addToken( word, TOKEN_ELSE, line) ;
}
else if ( strcmp ( word
, "while" ) == 0 ) {
addToken( word, TOKEN_WHILE, line) ;
}
else
{
addToken( word, TOKEN_IDENTIFIER, line) ;
}
}
{
j = 0 ;
while ( isdigit ( source
[ i
] ) && j
< MAX_TEXT
- 1 ) {
word[ j] = source[ i] ;
j++;
i++;
}
word[ j] = '\0 ' ;
addToken( word, TOKEN_NUMBER, line) ;
}
else
{
single[ 0 ] = source[ i] ;
single[ 1 ] = '\0 ' ;
if ( isOperatorToken( single) )
{
addToken( single, TOKEN_OPERATOR, line) ;
}
else if ( isSymbolToken( single) )
{
addToken( single, TOKEN_SYMBOL, line) ;
}
else
{
addToken( single, TOKEN_UNKNOWN, line) ;
}
i++;
}
}
}
void printTokens( )
{
int i;
int previousLine;
previousLine = - 1 ;
for ( i = 0 ; i < tokenCount; i++ )
{
if ( previousLine != - 1 && tokenLine[ i] != previousLine)
{
}
if ( tokenType[ i] == TOKEN_INT)
{
}
else if ( tokenType[ i] == TOKEN_IDENTIFIER)
{
printf ( "IDENTIFIER(%s)" , tokenText
[ i
] ) ; }
else if ( tokenType[ i] == TOKEN_NUMBER)
{
printf ( "NUMBER(%s)" , tokenText
[ i
] ) ; }
else if ( tokenType[ i] == TOKEN_IF)
{
}
else if ( tokenType[ i] == TOKEN_ELSE)
{
}
else if ( tokenType[ i] == TOKEN_WHILE)
{
}
else
{
}
if ( i + 1 < tokenCount && tokenLine[ i + 1 ] == tokenLine[ i] )
{
}
previousLine = tokenLine[ i] ;
}
}
int tokenIs( char text[ ] )
{
if ( currentToken
< tokenCount
&& strcmp ( tokenText
[ currentToken
] , text
) == 0 ) {
return 1 ;
}
return 0 ;
}
int tokenKindIs( int type)
{
if ( currentToken < tokenCount && tokenType[ currentToken] == type)
{
return 1 ;
}
return 0 ;
}
void setSyntaxError( char message[ ] )
{
if ( syntaxError == 0 )
{
syntaxError = 1 ;
strcpy ( syntaxErrorMessage
, message
) ; }
}
void expectText( char text[ ] )
{
if ( syntaxError)
{
return ;
}
if ( tokenIs( text) )
{
currentToken++;
}
else
{
sprintf ( tempLine
, "Expected '%s'" , text
) ; setSyntaxError( tempLine) ;
}
}
void copyCurrentToken( char outputText[ ] )
{
if ( currentToken < tokenCount)
{
strcpy ( outputText
, tokenText
[ currentToken
] ) ; }
else
{
outputText[ 0 ] = '\0 ' ;
}
}
void parseProgram( )
{
currentToken = 0 ;
assignmentAffectsSymbol = 1 ;
while ( currentToken < tokenCount && syntaxError == 0 )
{
if ( tokenKindIs( TOKEN_INT) )
{
parseDeclaration( ) ;
}
else if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
assignmentAffectsSymbol = 1 ;
parseAssignment( ) ;
}
else if ( tokenKindIs( TOKEN_IF) )
{
parseIfStatement( ) ;
}
else if ( tokenKindIs( TOKEN_WHILE) )
{
parseWhileStatement( ) ;
}
else
{
sprintf ( tempLine
, "Unexpected token '%s'" , tokenText
[ currentToken
] ) ; setSyntaxError( tempLine) ;
}
}
}
void parseDeclaration( )
{
char name[ MAX_TEXT] ;
expectText( "int" ) ;
if ( syntaxError)
{
return ;
}
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
copyCurrentToken( name) ;
currentToken++;
}
else
{
setSyntaxError( "Expected identifier after int" ) ;
return ;
}
expectText( ";" ) ;
if ( syntaxError == 0 )
{
addSymbol( name) ;
}
}
void parseAssignment( )
{
char target[ MAX_TEXT] ;
int targetIndex;
int canUpdate;
canUpdate = 1 ;
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
copyCurrentToken( target) ;
strcpy ( lastIdentifier
, target
) ; currentToken++;
}
else
{
setSyntaxError( "Expected identifier at start of assignment" ) ;
return ;
}
targetIndex = findSymbolIndex( target) ;
if ( targetIndex == - 1 )
{
sprintf ( tempLine
, "Variable '%s' used without declaration" , target
) ; addSemanticError( tempLine) ;
canUpdate = 0 ;
}
expectText( "=" ) ;
parseExpression( ) ;
expectText( ";" ) ;
if ( syntaxError)
{
return ;
}
if ( lastExprSemanticOk == 0 )
{
canUpdate = 0 ;
}
if ( lastExprHasOperator)
{
sprintf ( tempLine
, "t%d = %s %s %s" , tempCount
, lastExprLeft
, lastExprOp
, lastExprRight
) ; addTAC( tempLine) ;
sprintf ( tempLine
, "%s = t%d" , target
, tempCount
) ; addTAC( tempLine) ;
tempCount++;
}
else
{
sprintf ( tempLine
, "%s = %s" , target
, lastExprLeft
) ; addTAC( tempLine) ;
}
if ( assignmentAffectsSymbol && canUpdate && lastExprValueKnown)
{
updateSymbolValue( target, lastExprValue) ;
}
}
void parseExpression( )
{
int leftOk;
int rightOk;
int leftValue;
int rightValue;
lastExprHasOperator = 0 ;
lastExprValueKnown = 0 ;
lastExprSemanticOk = 1 ;
lastExprLeft[ 0 ] = '\0 ' ;
lastExprOp[ 0 ] = '\0 ' ;
lastExprRight[ 0 ] = '\0 ' ;
lastExpressionText[ 0 ] = '\0 ' ;
readOperand( lastExprLeft) ;
if ( syntaxError)
{
return ;
}
leftOk = lastExprSemanticOk;
leftValue = operandValue( lastExprLeft, leftOk) ;
if ( tokenIs( "+" ) || tokenIs( "-" ) )
{
lastExprHasOperator = 1 ;
copyCurrentToken( lastExprOp) ;
currentToken++;
readOperand( lastExprRight) ;
if ( syntaxError)
{
return ;
}
rightOk = lastExprSemanticOk;
rightValue = operandValue( lastExprRight, rightOk) ;
sprintf ( lastExpressionText
, "%s %s %s" , lastExprLeft
, lastExprOp
, lastExprRight
) ;
if ( leftOk && rightOk)
{
lastExprValueKnown = 1 ;
if ( strcmp ( lastExprOp
, "+" ) == 0 ) {
lastExprValue = leftValue + rightValue;
}
else
{
lastExprValue = leftValue - rightValue;
}
}
}
else
{
strcpy ( lastExpressionText
, lastExprLeft
) ; if ( leftOk)
{
lastExprValueKnown = 1 ;
lastExprValue = leftValue;
}
}
}
void readOperand( char outputText[ ] )
{
int symbolIndex;
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
copyCurrentToken( outputText) ;
symbolIndex = findSymbolIndex( outputText) ;
if ( symbolIndex == - 1 )
{
sprintf ( tempLine
, "Variable '%s' used without declaration" , outputText
) ; addSemanticError( tempLine) ;
lastExprSemanticOk = 0 ;
}
currentToken++;
}
else if ( tokenKindIs( TOKEN_NUMBER) )
{
copyCurrentToken( outputText) ;
currentToken++;
}
else
{
setSyntaxError( "Expected identifier or number in expression" ) ;
}
}
int operandValue( char text[ ] , int ok)
{
int i;
if ( ok == 0 )
{
return 0 ;
}
{
}
i = findSymbolIndex( text) ;
if ( i != - 1 )
{
return symbolValue[ i] ;
}
return 0 ;
}
void parseIfStatement( )
{
int trueLabel;
int falseLabel;
int endLabel;
expectText( "if" ) ;
parseCondition( ) ;
if ( syntaxError)
{
return ;
}
trueLabel = newLabel( ) ;
falseLabel = newLabel( ) ;
endLabel = newLabel( ) ;
sprintf ( tempLine
, "if %s %s %s goto L%d" , conditionLeft
, conditionOp
, conditionRight
, trueLabel
) ; addTAC( tempLine) ;
sprintf ( tempLine
, "goto L%d" , falseLabel
) ; addTAC( tempLine) ;
sprintf ( tempLine
, "L%d:" , trueLabel
) ; addTAC( tempLine) ;
assignmentAffectsSymbol = 0 ;
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
parseAssignment( ) ;
}
else
{
setSyntaxError( "Expected assignment after if condition" ) ;
return ;
}
sprintf ( tempLine
, "goto L%d" , endLabel
) ; addTAC( tempLine) ;
sprintf ( tempLine
, "L%d:" , falseLabel
) ; addTAC( tempLine) ;
if ( tokenKindIs( TOKEN_ELSE) )
{
expectText( "else" ) ;
}
else
{
setSyntaxError( "Expected else after if statement" ) ;
return ;
}
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
parseAssignment( ) ;
}
else
{
setSyntaxError( "Expected assignment after else" ) ;
return ;
}
sprintf ( tempLine
, "L%d:" , endLabel
) ; addTAC( tempLine) ;
assignmentAffectsSymbol = 1 ;
}
void parseWhileStatement( )
{
int startLabel;
int bodyLabel;
int endLabel;
expectText( "while" ) ;
startLabel = newLabel( ) ;
bodyLabel = newLabel( ) ;
endLabel = newLabel( ) ;
sprintf ( tempLine
, "L%d:" , startLabel
) ; addTAC( tempLine) ;
parseCondition( ) ;
if ( syntaxError)
{
return ;
}
sprintf ( tempLine
, "if %s %s %s goto L%d" , conditionLeft
, conditionOp
, conditionRight
, bodyLabel
) ; addTAC( tempLine) ;
sprintf ( tempLine
, "goto L%d" , endLabel
) ; addTAC( tempLine) ;
sprintf ( tempLine
, "L%d:" , bodyLabel
) ; addTAC( tempLine) ;
assignmentAffectsSymbol = 0 ;
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
parseAssignment( ) ;
}
else
{
setSyntaxError( "Expected assignment after while condition" ) ;
return ;
}
sprintf ( tempLine
, "goto L%d" , startLabel
) ; addTAC( tempLine) ;
sprintf ( tempLine
, "L%d:" , endLabel
) ; addTAC( tempLine) ;
assignmentAffectsSymbol = 1 ;
}
void parseCondition( )
{
int symbolIndex;
expectText( "(" ) ;
if ( tokenKindIs( TOKEN_IDENTIFIER) || tokenKindIs( TOKEN_NUMBER) )
{
copyCurrentToken( conditionLeft) ;
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
symbolIndex = findSymbolIndex( conditionLeft) ;
if ( symbolIndex == - 1 )
{
sprintf ( tempLine
, "Variable '%s' used without declaration" , conditionLeft
) ; addSemanticError( tempLine) ;
}
}
currentToken++;
}
else
{
setSyntaxError( "Expected left operand in condition" ) ;
return ;
}
if ( tokenIs( "<" ) || tokenIs( ">" ) )
{
copyCurrentToken( conditionOp) ;
currentToken++;
}
else
{
setSyntaxError( "Expected relational operator in condition" ) ;
return ;
}
if ( tokenKindIs( TOKEN_IDENTIFIER) || tokenKindIs( TOKEN_NUMBER) )
{
copyCurrentToken( conditionRight) ;
if ( tokenKindIs( TOKEN_IDENTIFIER) )
{
symbolIndex = findSymbolIndex( conditionRight) ;
if ( symbolIndex == - 1 )
{
sprintf ( tempLine
, "Variable '%s' used without declaration" , conditionRight
) ; addSemanticError( tempLine) ;
}
}
currentToken++;
}
else
{
setSyntaxError( "Expected right operand in condition" ) ;
return ;
}
expectText( ")" ) ;
}
int findSymbolIndex( char name[ ] )
{
int i;
for ( i = 0 ; i < symbolCount; i++ )
{
if ( strcmp ( symbolName
[ i
] , name
) == 0 ) {
return i;
}
}
return - 1 ;
}
void addSymbol( char name[ ] )
{
if ( findSymbolIndex( name) != - 1 )
{
sprintf ( tempLine
, "Duplicate declaration of variable '%s'" , name
) ; addSemanticError( tempLine) ;
return ;
}
if ( symbolCount >= MAX_SYMBOLS)
{
addSemanticError( "Symbol table is full" ) ;
return ;
}
strcpy ( symbolName
[ symbolCount
] , name
) ; strcpy ( symbolType
[ symbolCount
] , "int" ) ; symbolValue[ symbolCount] = 0 ;
symbolCount++;
}
void updateSymbolValue( char name[ ] , int value)
{
int index;
index = findSymbolIndex( name) ;
if ( index != - 1 )
{
symbolValue[ index] = value;
}
}
void addSemanticError( char message[ ] )
{
if ( semanticErrorCount >= MAX_ERRORS)
{
return ;
}
strcpy ( semanticErrors
[ semanticErrorCount
] , message
) ; semanticErrorCount++;
}
void addTAC( char line[ ] )
{
if ( tacCount >= MAX_TAC)
{
return ;
}
tacCount++;
}
int newLabel( )
{
int label;
label = labelCount;
labelCount++;
return label;
}
void printSyntaxResult( )
{
if ( syntaxError)
{
printf ( "Syntax Error: %s\n " , syntaxErrorMessage
) ; }
else
{
printf ( "Parsing Successful\n " ) ; printf ( "No Syntax Error Found\n " ) ; }
}
void printSymbolTable( )
{
int i;
printf ( "Variable\t Type\t Value\n " ) ; printf ( "-----------------------------\n " ) ;
if ( symbolCount == 0 )
{
return ;
}
for ( i = 0 ; i < symbolCount; i++ )
{
printf ( "%s\t \t %s\t %d\n " , symbolName
[ i
] , symbolType
[ i
] , symbolValue
[ i
] ) ; }
}
void printSemanticErrors( )
{
int i;
if ( semanticErrorCount == 0 )
{
printf ( "No Semantic Error Found\n " ) ; return ;
}
for ( i = 0 ; i < semanticErrorCount; i++ )
{
printf ( "Semantic Error: %s\n " , semanticErrors
[ i
] ) ; }
}
void printTAC( )
{
int i;
if ( tacCount == 0 )
{
return ;
}
for ( i = 0 ; i < tacCount; i++ )
{
}
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGN0eXBlLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCiNkZWZpbmUgTUFYX1NPVVJDRSA1MDAwCiNkZWZpbmUgTUFYX1RPS0VOUyA1MDAKI2RlZmluZSBNQVhfVEVYVCA1MAojZGVmaW5lIE1BWF9TWU1CT0xTIDEwMAojZGVmaW5lIE1BWF9FUlJPUlMgMTAwCiNkZWZpbmUgTUFYX1RBQyA1MDAKCiNkZWZpbmUgVE9LRU5fSU5UIDEKI2RlZmluZSBUT0tFTl9JREVOVElGSUVSIDIKI2RlZmluZSBUT0tFTl9OVU1CRVIgMwojZGVmaW5lIFRPS0VOX0lGIDQKI2RlZmluZSBUT0tFTl9FTFNFIDUKI2RlZmluZSBUT0tFTl9XSElMRSA2CiNkZWZpbmUgVE9LRU5fT1BFUkFUT1IgNwojZGVmaW5lIFRPS0VOX1NZTUJPTCA4CiNkZWZpbmUgVE9LRU5fVU5LTk9XTiA5CgpjaGFyIHNvdXJjZVtNQVhfU09VUkNFXTsKaW50IHNvdXJjZUxlbmd0aCA9IDA7CgpjaGFyIHRva2VuVGV4dFtNQVhfVE9LRU5TXVtNQVhfVEVYVF07CmludCB0b2tlblR5cGVbTUFYX1RPS0VOU107CmludCB0b2tlbkxpbmVbTUFYX1RPS0VOU107CmludCB0b2tlbkNvdW50ID0gMDsKCmNoYXIgc3ltYm9sTmFtZVtNQVhfU1lNQk9MU11bTUFYX1RFWFRdOwpjaGFyIHN5bWJvbFR5cGVbTUFYX1NZTUJPTFNdWzIwXTsKaW50IHN5bWJvbFZhbHVlW01BWF9TWU1CT0xTXTsKaW50IHN5bWJvbENvdW50ID0gMDsKCmNoYXIgc2VtYW50aWNFcnJvcnNbTUFYX0VSUk9SU11bMTAwXTsKaW50IHNlbWFudGljRXJyb3JDb3VudCA9IDA7CgpjaGFyIHRhY1tNQVhfVEFDXVsxMDBdOwppbnQgdGFjQ291bnQgPSAwOwoKaW50IGN1cnJlbnRUb2tlbiA9IDA7CmludCBzeW50YXhFcnJvciA9IDA7CmNoYXIgc3ludGF4RXJyb3JNZXNzYWdlWzEyMF07CgppbnQgdGVtcENvdW50ID0gMTsKaW50IGxhYmVsQ291bnQgPSAxOwppbnQgYXNzaWdubWVudEFmZmVjdHNTeW1ib2wgPSAxOwoKY2hhciBsYXN0SWRlbnRpZmllcltNQVhfVEVYVF07CmNoYXIgbGFzdEV4cHJlc3Npb25UZXh0WzEwMF07CmNoYXIgbGFzdEV4cHJMZWZ0W01BWF9URVhUXTsKY2hhciBsYXN0RXhwck9wW01BWF9URVhUXTsKY2hhciBsYXN0RXhwclJpZ2h0W01BWF9URVhUXTsKaW50IGxhc3RFeHBySGFzT3BlcmF0b3IgPSAwOwppbnQgbGFzdEV4cHJWYWx1ZSA9IDA7CmludCBsYXN0RXhwclZhbHVlS25vd24gPSAwOwppbnQgbGFzdEV4cHJTZW1hbnRpY09rID0gMTsKCmNoYXIgY29uZGl0aW9uTGVmdFtNQVhfVEVYVF07CmNoYXIgY29uZGl0aW9uT3BbTUFYX1RFWFRdOwpjaGFyIGNvbmRpdGlvblJpZ2h0W01BWF9URVhUXTsKCmNoYXIgdGVtcExpbmVbMTUwXTsKCnZvaWQgcmVhZFNvdXJjZSgpOwp2b2lkIHRva2VuaXplKCk7CnZvaWQgcHJpbnRTb3VyY2UoKTsKdm9pZCBwcmludFRva2VucygpOwp2b2lkIHBhcnNlUHJvZ3JhbSgpOwp2b2lkIHBhcnNlRGVjbGFyYXRpb24oKTsKdm9pZCBwYXJzZUFzc2lnbm1lbnQoKTsKdm9pZCBwYXJzZUlmU3RhdGVtZW50KCk7CnZvaWQgcGFyc2VXaGlsZVN0YXRlbWVudCgpOwp2b2lkIHBhcnNlQ29uZGl0aW9uKCk7CnZvaWQgcGFyc2VFeHByZXNzaW9uKCk7CnZvaWQgcmVhZE9wZXJhbmQoY2hhciBvdXRwdXRUZXh0W10pOwppbnQgZmluZFN5bWJvbEluZGV4KGNoYXIgbmFtZVtdKTsKdm9pZCBhZGRTeW1ib2woY2hhciBuYW1lW10pOwp2b2lkIHVwZGF0ZVN5bWJvbFZhbHVlKGNoYXIgbmFtZVtdLCBpbnQgdmFsdWUpOwp2b2lkIGFkZFNlbWFudGljRXJyb3IoY2hhciBtZXNzYWdlW10pOwp2b2lkIGFkZFRBQyhjaGFyIGxpbmVbXSk7CnZvaWQgcHJpbnRTeW50YXhSZXN1bHQoKTsKdm9pZCBwcmludFN5bWJvbFRhYmxlKCk7CnZvaWQgcHJpbnRTZW1hbnRpY0Vycm9ycygpOwp2b2lkIHByaW50VEFDKCk7CnZvaWQgYWRkVG9rZW4oY2hhciB0ZXh0W10sIGludCB0eXBlLCBpbnQgbGluZSk7CmludCBpc09wZXJhdG9yVG9rZW4oY2hhciB0ZXh0W10pOwppbnQgaXNTeW1ib2xUb2tlbihjaGFyIHRleHRbXSk7CmludCB0b2tlbklzKGNoYXIgdGV4dFtdKTsKaW50IHRva2VuS2luZElzKGludCB0eXBlKTsKdm9pZCBzZXRTeW50YXhFcnJvcihjaGFyIG1lc3NhZ2VbXSk7CnZvaWQgZXhwZWN0VGV4dChjaGFyIHRleHRbXSk7CnZvaWQgY29weUN1cnJlbnRUb2tlbihjaGFyIG91dHB1dFRleHRbXSk7CmludCBvcGVyYW5kVmFsdWUoY2hhciB0ZXh0W10sIGludCBvayk7CmludCBuZXdMYWJlbCgpOwoKaW50IG1haW4oKQp7CiAgICByZWFkU291cmNlKCk7CiAgICB0b2tlbml6ZSgpOwoKICAgIHByaW50ZigiPT09PT09PT09PSBTb3VyY2UgUHJvZ3JhbSA9PT09PT09PT09XG4iKTsKICAgIHByaW50U291cmNlKCk7CgogICAgcHJpbnRmKCJcbj09PT09PT09PT0gMS4gVG9rZW5zID09PT09PT09PT1cbiIpOwogICAgcHJpbnRUb2tlbnMoKTsKCiAgICBwYXJzZVByb2dyYW0oKTsKCiAgICBwcmludGYoIlxuPT09PT09PT09PSAyLiBTeW50YXggQW5hbHlzaXMgT3V0cHV0ID09PT09PT09PT1cbiIpOwogICAgcHJpbnRTeW50YXhSZXN1bHQoKTsKCiAgICBwcmludGYoIlxuPT09PT09PT09PSAzLiBTeW1ib2wgVGFibGUgPT09PT09PT09PVxuIik7CiAgICBwcmludFN5bWJvbFRhYmxlKCk7CgogICAgcHJpbnRmKCJcbj09PT09PT09PT0gNC4gU2VtYW50aWMgQW5hbHlzaXMgT3V0cHV0ID09PT09PT09PT1cbiIpOwogICAgcHJpbnRTZW1hbnRpY0Vycm9ycygpOwoKICAgIHByaW50ZigiXG49PT09PT09PT09IDUuIFRocmVlIEFkZHJlc3MgQ29kZSA9PT09PT09PT09XG4iKTsKICAgIHByaW50VEFDKCk7CgogICAgcmV0dXJuIDA7Cn0KCnZvaWQgcmVhZFNvdXJjZSgpCnsKICAgIGludCBjaDsKICAgIGludCBpOwoKICAgIGkgPSAwOwoKICAgIGlmIChmcmVvcGVuKCJpbnB1dC50eHQiLCAiciIsIHN0ZGluKSA9PSBOVUxMKQogICAgewogICAgICAgIHByaW50ZigiRXJyb3I6IGlucHV0LnR4dCBmaWxlIG5vdCBmb3VuZC5cbiIpOwogICAgICAgIHNvdXJjZVswXSA9ICdcMCc7CiAgICAgICAgc291cmNlTGVuZ3RoID0gMDsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgd2hpbGUgKChjaCA9IGdldGNoYXIoKSkgIT0gRU9GICYmIGkgPCBNQVhfU09VUkNFIC0gMSkKICAgIHsKICAgICAgICBzb3VyY2VbaV0gPSBjaDsKICAgICAgICBpKys7CiAgICB9CgogICAgc291cmNlW2ldID0gJ1wwJzsKICAgIHNvdXJjZUxlbmd0aCA9IGk7Cn0KCnZvaWQgcHJpbnRTb3VyY2UoKQp7CiAgICBpZiAoc291cmNlTGVuZ3RoID09IDApCiAgICB7CiAgICAgICAgcHJpbnRmKCJObyBzb3VyY2UgY29kZSBsb2FkZWQuXG4iKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBwcmludGYoIiVzIiwgc291cmNlKTsKICAgICAgICBpZiAoc291cmNlW3NvdXJjZUxlbmd0aCAtIDFdICE9ICdcbicpCiAgICAgICAgewogICAgICAgICAgICBwcmludGYoIlxuIik7CiAgICAgICAgfQogICAgfQp9Cgp2b2lkIGFkZFRva2VuKGNoYXIgdGV4dFtdLCBpbnQgdHlwZSwgaW50IGxpbmUpCnsKICAgIGlmICh0b2tlbkNvdW50ID49IE1BWF9UT0tFTlMpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIHN0cmNweSh0b2tlblRleHRbdG9rZW5Db3VudF0sIHRleHQpOwogICAgdG9rZW5UeXBlW3Rva2VuQ291bnRdID0gdHlwZTsKICAgIHRva2VuTGluZVt0b2tlbkNvdW50XSA9IGxpbmU7CiAgICB0b2tlbkNvdW50Kys7Cn0KCmludCBpc09wZXJhdG9yVG9rZW4oY2hhciB0ZXh0W10pCnsKICAgIGlmIChzdHJjbXAodGV4dCwgIj0iKSA9PSAwKQogICAgewogICAgICAgIHJldHVybiAxOwogICAgfQogICAgaWYgKHN0cmNtcCh0ZXh0LCAiKyIpID09IDApCiAgICB7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICBpZiAoc3RyY21wKHRleHQsICItIikgPT0gMCkKICAgIHsKICAgICAgICByZXR1cm4gMTsKICAgIH0KICAgIGlmIChzdHJjbXAodGV4dCwgIjwiKSA9PSAwKQogICAgewogICAgICAgIHJldHVybiAxOwogICAgfQogICAgaWYgKHN0cmNtcCh0ZXh0LCAiPiIpID09IDApCiAgICB7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gMDsKfQoKaW50IGlzU3ltYm9sVG9rZW4oY2hhciB0ZXh0W10pCnsKICAgIGlmIChzdHJjbXAodGV4dCwgIjsiKSA9PSAwKQogICAgewogICAgICAgIHJldHVybiAxOwogICAgfQogICAgaWYgKHN0cmNtcCh0ZXh0LCAiKCIpID09IDApCiAgICB7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICBpZiAoc3RyY21wKHRleHQsICIpIikgPT0gMCkKICAgIHsKICAgICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiAwOwp9Cgp2b2lkIHRva2VuaXplKCkKewogICAgaW50IGk7CiAgICBpbnQgajsKICAgIGludCBsaW5lOwogICAgY2hhciB3b3JkW01BWF9URVhUXTsKICAgIGNoYXIgc2luZ2xlWzJdOwoKICAgIGkgPSAwOwogICAgbGluZSA9IDE7CgogICAgd2hpbGUgKHNvdXJjZVtpXSAhPSAnXDAnKQogICAgewogICAgICAgIGlmIChzb3VyY2VbaV0gPT0gJ1xuJykKICAgICAgICB7CiAgICAgICAgICAgIGxpbmUrKzsKICAgICAgICAgICAgaSsrOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChpc3NwYWNlKHNvdXJjZVtpXSkpCiAgICAgICAgewogICAgICAgICAgICBpKys7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGlzYWxwaGEoc291cmNlW2ldKSB8fCBzb3VyY2VbaV0gPT0gJ18nKQogICAgICAgIHsKICAgICAgICAgICAgaiA9IDA7CiAgICAgICAgICAgIHdoaWxlICgoaXNhbG51bShzb3VyY2VbaV0pIHx8IHNvdXJjZVtpXSA9PSAnXycpICYmIGogPCBNQVhfVEVYVCAtIDEpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHdvcmRbal0gPSBzb3VyY2VbaV07CiAgICAgICAgICAgICAgICBqKys7CiAgICAgICAgICAgICAgICBpKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd29yZFtqXSA9ICdcMCc7CgogICAgICAgICAgICBpZiAoc3RyY21wKHdvcmQsICJpbnQiKSA9PSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBhZGRUb2tlbih3b3JkLCBUT0tFTl9JTlQsIGxpbmUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYgKHN0cmNtcCh3b3JkLCAiaWYiKSA9PSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBhZGRUb2tlbih3b3JkLCBUT0tFTl9JRiwgbGluZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoc3RyY21wKHdvcmQsICJlbHNlIikgPT0gMCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYWRkVG9rZW4od29yZCwgVE9LRU5fRUxTRSwgbGluZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoc3RyY21wKHdvcmQsICJ3aGlsZSIpID09IDApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGFkZFRva2VuKHdvcmQsIFRPS0VOX1dISUxFLCBsaW5lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGFkZFRva2VuKHdvcmQsIFRPS0VOX0lERU5USUZJRVIsIGxpbmUpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGlzZGlnaXQoc291cmNlW2ldKSkKICAgICAgICB7CiAgICAgICAgICAgIGogPSAwOwogICAgICAgICAgICB3aGlsZSAoaXNkaWdpdChzb3VyY2VbaV0pICYmIGogPCBNQVhfVEVYVCAtIDEpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHdvcmRbal0gPSBzb3VyY2VbaV07CiAgICAgICAgICAgICAgICBqKys7CiAgICAgICAgICAgICAgICBpKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd29yZFtqXSA9ICdcMCc7CiAgICAgICAgICAgIGFkZFRva2VuKHdvcmQsIFRPS0VOX05VTUJFUiwgbGluZSk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIHNpbmdsZVswXSA9IHNvdXJjZVtpXTsKICAgICAgICAgICAgc2luZ2xlWzFdID0gJ1wwJzsKCiAgICAgICAgICAgIGlmIChpc09wZXJhdG9yVG9rZW4oc2luZ2xlKSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYWRkVG9rZW4oc2luZ2xlLCBUT0tFTl9PUEVSQVRPUiwgbGluZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZiAoaXNTeW1ib2xUb2tlbihzaW5nbGUpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBhZGRUb2tlbihzaW5nbGUsIFRPS0VOX1NZTUJPTCwgbGluZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBhZGRUb2tlbihzaW5nbGUsIFRPS0VOX1VOS05PV04sIGxpbmUpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpKys7CiAgICAgICAgfQogICAgfQp9Cgp2b2lkIHByaW50VG9rZW5zKCkKewogICAgaW50IGk7CiAgICBpbnQgcHJldmlvdXNMaW5lOwoKICAgIHByZXZpb3VzTGluZSA9IC0xOwoKICAgIGZvciAoaSA9IDA7IGkgPCB0b2tlbkNvdW50OyBpKyspCiAgICB7CiAgICAgICAgaWYgKHByZXZpb3VzTGluZSAhPSAtMSAmJiB0b2tlbkxpbmVbaV0gIT0gcHJldmlvdXNMaW5lKQogICAgICAgIHsKICAgICAgICAgICAgcHJpbnRmKCJcbiIpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHRva2VuVHlwZVtpXSA9PSBUT0tFTl9JTlQpCiAgICAgICAgewogICAgICAgICAgICBwcmludGYoIklOVCIpOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmICh0b2tlblR5cGVbaV0gPT0gVE9LRU5fSURFTlRJRklFUikKICAgICAgICB7CiAgICAgICAgICAgIHByaW50ZigiSURFTlRJRklFUiglcykiLCB0b2tlblRleHRbaV0pOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmICh0b2tlblR5cGVbaV0gPT0gVE9LRU5fTlVNQkVSKQogICAgICAgIHsKICAgICAgICAgICAgcHJpbnRmKCJOVU1CRVIoJXMpIiwgdG9rZW5UZXh0W2ldKTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAodG9rZW5UeXBlW2ldID09IFRPS0VOX0lGKQogICAgICAgIHsKICAgICAgICAgICAgcHJpbnRmKCJJRiIpOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmICh0b2tlblR5cGVbaV0gPT0gVE9LRU5fRUxTRSkKICAgICAgICB7CiAgICAgICAgICAgIHByaW50ZigiRUxTRSIpOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmICh0b2tlblR5cGVbaV0gPT0gVE9LRU5fV0hJTEUpCiAgICAgICAgewogICAgICAgICAgICBwcmludGYoIldISUxFIik7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIHByaW50ZigiJXMiLCB0b2tlblRleHRbaV0pOwogICAgICAgIH0KCiAgICAgICAgaWYgKGkgKyAxIDwgdG9rZW5Db3VudCAmJiB0b2tlbkxpbmVbaSArIDFdID09IHRva2VuTGluZVtpXSkKICAgICAgICB7CiAgICAgICAgICAgIHByaW50ZigiICIpOwogICAgICAgIH0KCiAgICAgICAgcHJldmlvdXNMaW5lID0gdG9rZW5MaW5lW2ldOwogICAgfQoKICAgIHByaW50ZigiXG4iKTsKfQoKaW50IHRva2VuSXMoY2hhciB0ZXh0W10pCnsKICAgIGlmIChjdXJyZW50VG9rZW4gPCB0b2tlbkNvdW50ICYmIHN0cmNtcCh0b2tlblRleHRbY3VycmVudFRva2VuXSwgdGV4dCkgPT0gMCkKICAgIHsKICAgICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiAwOwp9CgppbnQgdG9rZW5LaW5kSXMoaW50IHR5cGUpCnsKICAgIGlmIChjdXJyZW50VG9rZW4gPCB0b2tlbkNvdW50ICYmIHRva2VuVHlwZVtjdXJyZW50VG9rZW5dID09IHR5cGUpCiAgICB7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gMDsKfQoKdm9pZCBzZXRTeW50YXhFcnJvcihjaGFyIG1lc3NhZ2VbXSkKewogICAgaWYgKHN5bnRheEVycm9yID09IDApCiAgICB7CiAgICAgICAgc3ludGF4RXJyb3IgPSAxOwogICAgICAgIHN0cmNweShzeW50YXhFcnJvck1lc3NhZ2UsIG1lc3NhZ2UpOwogICAgfQp9Cgp2b2lkIGV4cGVjdFRleHQoY2hhciB0ZXh0W10pCnsKICAgIGlmIChzeW50YXhFcnJvcikKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHRva2VuSXModGV4dCkpCiAgICB7CiAgICAgICAgY3VycmVudFRva2VuKys7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgc3ByaW50Zih0ZW1wTGluZSwgIkV4cGVjdGVkICclcyciLCB0ZXh0KTsKICAgICAgICBzZXRTeW50YXhFcnJvcih0ZW1wTGluZSk7CiAgICB9Cn0KCnZvaWQgY29weUN1cnJlbnRUb2tlbihjaGFyIG91dHB1dFRleHRbXSkKewogICAgaWYgKGN1cnJlbnRUb2tlbiA8IHRva2VuQ291bnQpCiAgICB7CiAgICAgICAgc3RyY3B5KG91dHB1dFRleHQsIHRva2VuVGV4dFtjdXJyZW50VG9rZW5dKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBvdXRwdXRUZXh0WzBdID0gJ1wwJzsKICAgIH0KfQoKdm9pZCBwYXJzZVByb2dyYW0oKQp7CiAgICBjdXJyZW50VG9rZW4gPSAwOwogICAgYXNzaWdubWVudEFmZmVjdHNTeW1ib2wgPSAxOwoKICAgIHdoaWxlIChjdXJyZW50VG9rZW4gPCB0b2tlbkNvdW50ICYmIHN5bnRheEVycm9yID09IDApCiAgICB7CiAgICAgICAgaWYgKHRva2VuS2luZElzKFRPS0VOX0lOVCkpCiAgICAgICAgewogICAgICAgICAgICBwYXJzZURlY2xhcmF0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKHRva2VuS2luZElzKFRPS0VOX0lERU5USUZJRVIpKQogICAgICAgIHsKICAgICAgICAgICAgYXNzaWdubWVudEFmZmVjdHNTeW1ib2wgPSAxOwogICAgICAgICAgICBwYXJzZUFzc2lnbm1lbnQoKTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAodG9rZW5LaW5kSXMoVE9LRU5fSUYpKQogICAgICAgIHsKICAgICAgICAgICAgcGFyc2VJZlN0YXRlbWVudCgpOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmICh0b2tlbktpbmRJcyhUT0tFTl9XSElMRSkpCiAgICAgICAgewogICAgICAgICAgICBwYXJzZVdoaWxlU3RhdGVtZW50KCk7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIHNwcmludGYodGVtcExpbmUsICJVbmV4cGVjdGVkIHRva2VuICclcyciLCB0b2tlblRleHRbY3VycmVudFRva2VuXSk7CiAgICAgICAgICAgIHNldFN5bnRheEVycm9yKHRlbXBMaW5lKTsKICAgICAgICB9CiAgICB9Cn0KCnZvaWQgcGFyc2VEZWNsYXJhdGlvbigpCnsKICAgIGNoYXIgbmFtZVtNQVhfVEVYVF07CgogICAgZXhwZWN0VGV4dCgiaW50Iik7CgogICAgaWYgKHN5bnRheEVycm9yKQogICAgewogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAodG9rZW5LaW5kSXMoVE9LRU5fSURFTlRJRklFUikpCiAgICB7CiAgICAgICAgY29weUN1cnJlbnRUb2tlbihuYW1lKTsKICAgICAgICBjdXJyZW50VG9rZW4rKzsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBzZXRTeW50YXhFcnJvcigiRXhwZWN0ZWQgaWRlbnRpZmllciBhZnRlciBpbnQiKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgZXhwZWN0VGV4dCgiOyIpOwoKICAgIGlmIChzeW50YXhFcnJvciA9PSAwKQogICAgewogICAgICAgIGFkZFN5bWJvbChuYW1lKTsKICAgIH0KfQoKdm9pZCBwYXJzZUFzc2lnbm1lbnQoKQp7CiAgICBjaGFyIHRhcmdldFtNQVhfVEVYVF07CiAgICBpbnQgdGFyZ2V0SW5kZXg7CiAgICBpbnQgY2FuVXBkYXRlOwoKICAgIGNhblVwZGF0ZSA9IDE7CgogICAgaWYgKHRva2VuS2luZElzKFRPS0VOX0lERU5USUZJRVIpKQogICAgewogICAgICAgIGNvcHlDdXJyZW50VG9rZW4odGFyZ2V0KTsKICAgICAgICBzdHJjcHkobGFzdElkZW50aWZpZXIsIHRhcmdldCk7CiAgICAgICAgY3VycmVudFRva2VuKys7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgc2V0U3ludGF4RXJyb3IoIkV4cGVjdGVkIGlkZW50aWZpZXIgYXQgc3RhcnQgb2YgYXNzaWdubWVudCIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICB0YXJnZXRJbmRleCA9IGZpbmRTeW1ib2xJbmRleCh0YXJnZXQpOwogICAgaWYgKHRhcmdldEluZGV4ID09IC0xKQogICAgewogICAgICAgIHNwcmludGYodGVtcExpbmUsICJWYXJpYWJsZSAnJXMnIHVzZWQgd2l0aG91dCBkZWNsYXJhdGlvbiIsIHRhcmdldCk7CiAgICAgICAgYWRkU2VtYW50aWNFcnJvcih0ZW1wTGluZSk7CiAgICAgICAgY2FuVXBkYXRlID0gMDsKICAgIH0KCiAgICBleHBlY3RUZXh0KCI9Iik7CiAgICBwYXJzZUV4cHJlc3Npb24oKTsKICAgIGV4cGVjdFRleHQoIjsiKTsKCiAgICBpZiAoc3ludGF4RXJyb3IpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChsYXN0RXhwclNlbWFudGljT2sgPT0gMCkKICAgIHsKICAgICAgICBjYW5VcGRhdGUgPSAwOwogICAgfQoKICAgIGlmIChsYXN0RXhwckhhc09wZXJhdG9yKQogICAgewogICAgICAgIHNwcmludGYodGVtcExpbmUsICJ0JWQgPSAlcyAlcyAlcyIsIHRlbXBDb3VudCwgbGFzdEV4cHJMZWZ0LCBsYXN0RXhwck9wLCBsYXN0RXhwclJpZ2h0KTsKICAgICAgICBhZGRUQUModGVtcExpbmUpOwogICAgICAgIHNwcmludGYodGVtcExpbmUsICIlcyA9IHQlZCIsIHRhcmdldCwgdGVtcENvdW50KTsKICAgICAgICBhZGRUQUModGVtcExpbmUpOwogICAgICAgIHRlbXBDb3VudCsrOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHNwcmludGYodGVtcExpbmUsICIlcyA9ICVzIiwgdGFyZ2V0LCBsYXN0RXhwckxlZnQpOwogICAgICAgIGFkZFRBQyh0ZW1wTGluZSk7CiAgICB9CgogICAgaWYgKGFzc2lnbm1lbnRBZmZlY3RzU3ltYm9sICYmIGNhblVwZGF0ZSAmJiBsYXN0RXhwclZhbHVlS25vd24pCiAgICB7CiAgICAgICAgdXBkYXRlU3ltYm9sVmFsdWUodGFyZ2V0LCBsYXN0RXhwclZhbHVlKTsKICAgIH0KfQoKdm9pZCBwYXJzZUV4cHJlc3Npb24oKQp7CiAgICBpbnQgbGVmdE9rOwogICAgaW50IHJpZ2h0T2s7CiAgICBpbnQgbGVmdFZhbHVlOwogICAgaW50IHJpZ2h0VmFsdWU7CgogICAgbGFzdEV4cHJIYXNPcGVyYXRvciA9IDA7CiAgICBsYXN0RXhwclZhbHVlS25vd24gPSAwOwogICAgbGFzdEV4cHJTZW1hbnRpY09rID0gMTsKICAgIGxhc3RFeHByTGVmdFswXSA9ICdcMCc7CiAgICBsYXN0RXhwck9wWzBdID0gJ1wwJzsKICAgIGxhc3RFeHByUmlnaHRbMF0gPSAnXDAnOwogICAgbGFzdEV4cHJlc3Npb25UZXh0WzBdID0gJ1wwJzsKCiAgICByZWFkT3BlcmFuZChsYXN0RXhwckxlZnQpOwogICAgaWYgKHN5bnRheEVycm9yKQogICAgewogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBsZWZ0T2sgPSBsYXN0RXhwclNlbWFudGljT2s7CiAgICBsZWZ0VmFsdWUgPSBvcGVyYW5kVmFsdWUobGFzdEV4cHJMZWZ0LCBsZWZ0T2spOwoKICAgIGlmICh0b2tlbklzKCIrIikgfHwgdG9rZW5JcygiLSIpKQogICAgewogICAgICAgIGxhc3RFeHBySGFzT3BlcmF0b3IgPSAxOwogICAgICAgIGNvcHlDdXJyZW50VG9rZW4obGFzdEV4cHJPcCk7CiAgICAgICAgY3VycmVudFRva2VuKys7CgogICAgICAgIHJlYWRPcGVyYW5kKGxhc3RFeHByUmlnaHQpOwogICAgICAgIGlmIChzeW50YXhFcnJvcikKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHJpZ2h0T2sgPSBsYXN0RXhwclNlbWFudGljT2s7CiAgICAgICAgcmlnaHRWYWx1ZSA9IG9wZXJhbmRWYWx1ZShsYXN0RXhwclJpZ2h0LCByaWdodE9rKTsKCiAgICAgICAgc3ByaW50ZihsYXN0RXhwcmVzc2lvblRleHQsICIlcyAlcyAlcyIsIGxhc3RFeHByTGVmdCwgbGFzdEV4cHJPcCwgbGFzdEV4cHJSaWdodCk7CgogICAgICAgIGlmIChsZWZ0T2sgJiYgcmlnaHRPaykKICAgICAgICB7CiAgICAgICAgICAgIGxhc3RFeHByVmFsdWVLbm93biA9IDE7CiAgICAgICAgICAgIGlmIChzdHJjbXAobGFzdEV4cHJPcCwgIisiKSA9PSAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBsYXN0RXhwclZhbHVlID0gbGVmdFZhbHVlICsgcmlnaHRWYWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGxhc3RFeHByVmFsdWUgPSBsZWZ0VmFsdWUgLSByaWdodFZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHN0cmNweShsYXN0RXhwcmVzc2lvblRleHQsIGxhc3RFeHByTGVmdCk7CiAgICAgICAgaWYgKGxlZnRPaykKICAgICAgICB7CiAgICAgICAgICAgIGxhc3RFeHByVmFsdWVLbm93biA9IDE7CiAgICAgICAgICAgIGxhc3RFeHByVmFsdWUgPSBsZWZ0VmFsdWU7CiAgICAgICAgfQogICAgfQp9Cgp2b2lkIHJlYWRPcGVyYW5kKGNoYXIgb3V0cHV0VGV4dFtdKQp7CiAgICBpbnQgc3ltYm9sSW5kZXg7CgogICAgaWYgKHRva2VuS2luZElzKFRPS0VOX0lERU5USUZJRVIpKQogICAgewogICAgICAgIGNvcHlDdXJyZW50VG9rZW4ob3V0cHV0VGV4dCk7CiAgICAgICAgc3ltYm9sSW5kZXggPSBmaW5kU3ltYm9sSW5kZXgob3V0cHV0VGV4dCk7CgogICAgICAgIGlmIChzeW1ib2xJbmRleCA9PSAtMSkKICAgICAgICB7CiAgICAgICAgICAgIHNwcmludGYodGVtcExpbmUsICJWYXJpYWJsZSAnJXMnIHVzZWQgd2l0aG91dCBkZWNsYXJhdGlvbiIsIG91dHB1dFRleHQpOwogICAgICAgICAgICBhZGRTZW1hbnRpY0Vycm9yKHRlbXBMaW5lKTsKICAgICAgICAgICAgbGFzdEV4cHJTZW1hbnRpY09rID0gMDsKICAgICAgICB9CgogICAgICAgIGN1cnJlbnRUb2tlbisrOwogICAgfQogICAgZWxzZSBpZiAodG9rZW5LaW5kSXMoVE9LRU5fTlVNQkVSKSkKICAgIHsKICAgICAgICBjb3B5Q3VycmVudFRva2VuKG91dHB1dFRleHQpOwogICAgICAgIGN1cnJlbnRUb2tlbisrOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHNldFN5bnRheEVycm9yKCJFeHBlY3RlZCBpZGVudGlmaWVyIG9yIG51bWJlciBpbiBleHByZXNzaW9uIik7CiAgICB9Cn0KCmludCBvcGVyYW5kVmFsdWUoY2hhciB0ZXh0W10sIGludCBvaykKewogICAgaW50IGk7CgogICAgaWYgKG9rID09IDApCiAgICB7CiAgICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgaWYgKGlzZGlnaXQodGV4dFswXSkpCiAgICB7CiAgICAgICAgcmV0dXJuIGF0b2kodGV4dCk7CiAgICB9CgogICAgaSA9IGZpbmRTeW1ib2xJbmRleCh0ZXh0KTsKICAgIGlmIChpICE9IC0xKQogICAgewogICAgICAgIHJldHVybiBzeW1ib2xWYWx1ZVtpXTsKICAgIH0KCiAgICByZXR1cm4gMDsKfQoKdm9pZCBwYXJzZUlmU3RhdGVtZW50KCkKewogICAgaW50IHRydWVMYWJlbDsKICAgIGludCBmYWxzZUxhYmVsOwogICAgaW50IGVuZExhYmVsOwoKICAgIGV4cGVjdFRleHQoImlmIik7CiAgICBwYXJzZUNvbmRpdGlvbigpOwoKICAgIGlmIChzeW50YXhFcnJvcikKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgdHJ1ZUxhYmVsID0gbmV3TGFiZWwoKTsKICAgIGZhbHNlTGFiZWwgPSBuZXdMYWJlbCgpOwogICAgZW5kTGFiZWwgPSBuZXdMYWJlbCgpOwoKICAgIHNwcmludGYodGVtcExpbmUsICJpZiAlcyAlcyAlcyBnb3RvIEwlZCIsIGNvbmRpdGlvbkxlZnQsIGNvbmRpdGlvbk9wLCBjb25kaXRpb25SaWdodCwgdHJ1ZUxhYmVsKTsKICAgIGFkZFRBQyh0ZW1wTGluZSk7CiAgICBzcHJpbnRmKHRlbXBMaW5lLCAiZ290byBMJWQiLCBmYWxzZUxhYmVsKTsKICAgIGFkZFRBQyh0ZW1wTGluZSk7CiAgICBzcHJpbnRmKHRlbXBMaW5lLCAiTCVkOiIsIHRydWVMYWJlbCk7CiAgICBhZGRUQUModGVtcExpbmUpOwoKICAgIGFzc2lnbm1lbnRBZmZlY3RzU3ltYm9sID0gMDsKCiAgICBpZiAodG9rZW5LaW5kSXMoVE9LRU5fSURFTlRJRklFUikpCiAgICB7CiAgICAgICAgcGFyc2VBc3NpZ25tZW50KCk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgc2V0U3ludGF4RXJyb3IoIkV4cGVjdGVkIGFzc2lnbm1lbnQgYWZ0ZXIgaWYgY29uZGl0aW9uIik7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIHNwcmludGYodGVtcExpbmUsICJnb3RvIEwlZCIsIGVuZExhYmVsKTsKICAgIGFkZFRBQyh0ZW1wTGluZSk7CiAgICBzcHJpbnRmKHRlbXBMaW5lLCAiTCVkOiIsIGZhbHNlTGFiZWwpOwogICAgYWRkVEFDKHRlbXBMaW5lKTsKCiAgICBpZiAodG9rZW5LaW5kSXMoVE9LRU5fRUxTRSkpCiAgICB7CiAgICAgICAgZXhwZWN0VGV4dCgiZWxzZSIpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHNldFN5bnRheEVycm9yKCJFeHBlY3RlZCBlbHNlIGFmdGVyIGlmIHN0YXRlbWVudCIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAodG9rZW5LaW5kSXMoVE9LRU5fSURFTlRJRklFUikpCiAgICB7CiAgICAgICAgcGFyc2VBc3NpZ25tZW50KCk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgc2V0U3ludGF4RXJyb3IoIkV4cGVjdGVkIGFzc2lnbm1lbnQgYWZ0ZXIgZWxzZSIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBzcHJpbnRmKHRlbXBMaW5lLCAiTCVkOiIsIGVuZExhYmVsKTsKICAgIGFkZFRBQyh0ZW1wTGluZSk7CiAgICBhc3NpZ25tZW50QWZmZWN0c1N5bWJvbCA9IDE7Cn0KCnZvaWQgcGFyc2VXaGlsZVN0YXRlbWVudCgpCnsKICAgIGludCBzdGFydExhYmVsOwogICAgaW50IGJvZHlMYWJlbDsKICAgIGludCBlbmRMYWJlbDsKCiAgICBleHBlY3RUZXh0KCJ3aGlsZSIpOwoKICAgIHN0YXJ0TGFiZWwgPSBuZXdMYWJlbCgpOwogICAgYm9keUxhYmVsID0gbmV3TGFiZWwoKTsKICAgIGVuZExhYmVsID0gbmV3TGFiZWwoKTsKCiAgICBzcHJpbnRmKHRlbXBMaW5lLCAiTCVkOiIsIHN0YXJ0TGFiZWwpOwogICAgYWRkVEFDKHRlbXBMaW5lKTsKCiAgICBwYXJzZUNvbmRpdGlvbigpOwoKICAgIGlmIChzeW50YXhFcnJvcikKICAgIHsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgc3ByaW50Zih0ZW1wTGluZSwgImlmICVzICVzICVzIGdvdG8gTCVkIiwgY29uZGl0aW9uTGVmdCwgY29uZGl0aW9uT3AsIGNvbmRpdGlvblJpZ2h0LCBib2R5TGFiZWwpOwogICAgYWRkVEFDKHRlbXBMaW5lKTsKICAgIHNwcmludGYodGVtcExpbmUsICJnb3RvIEwlZCIsIGVuZExhYmVsKTsKICAgIGFkZFRBQyh0ZW1wTGluZSk7CiAgICBzcHJpbnRmKHRlbXBMaW5lLCAiTCVkOiIsIGJvZHlMYWJlbCk7CiAgICBhZGRUQUModGVtcExpbmUpOwoKICAgIGFzc2lnbm1lbnRBZmZlY3RzU3ltYm9sID0gMDsKCiAgICBpZiAodG9rZW5LaW5kSXMoVE9LRU5fSURFTlRJRklFUikpCiAgICB7CiAgICAgICAgcGFyc2VBc3NpZ25tZW50KCk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgc2V0U3ludGF4RXJyb3IoIkV4cGVjdGVkIGFzc2lnbm1lbnQgYWZ0ZXIgd2hpbGUgY29uZGl0aW9uIik7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIHNwcmludGYodGVtcExpbmUsICJnb3RvIEwlZCIsIHN0YXJ0TGFiZWwpOwogICAgYWRkVEFDKHRlbXBMaW5lKTsKICAgIHNwcmludGYodGVtcExpbmUsICJMJWQ6IiwgZW5kTGFiZWwpOwogICAgYWRkVEFDKHRlbXBMaW5lKTsKCiAgICBhc3NpZ25tZW50QWZmZWN0c1N5bWJvbCA9IDE7Cn0KCnZvaWQgcGFyc2VDb25kaXRpb24oKQp7CiAgICBpbnQgc3ltYm9sSW5kZXg7CgogICAgZXhwZWN0VGV4dCgiKCIpOwoKICAgIGlmICh0b2tlbktpbmRJcyhUT0tFTl9JREVOVElGSUVSKSB8fCB0b2tlbktpbmRJcyhUT0tFTl9OVU1CRVIpKQogICAgewogICAgICAgIGNvcHlDdXJyZW50VG9rZW4oY29uZGl0aW9uTGVmdCk7CgogICAgICAgIGlmICh0b2tlbktpbmRJcyhUT0tFTl9JREVOVElGSUVSKSkKICAgICAgICB7CiAgICAgICAgICAgIHN5bWJvbEluZGV4ID0gZmluZFN5bWJvbEluZGV4KGNvbmRpdGlvbkxlZnQpOwogICAgICAgICAgICBpZiAoc3ltYm9sSW5kZXggPT0gLTEpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHNwcmludGYodGVtcExpbmUsICJWYXJpYWJsZSAnJXMnIHVzZWQgd2l0aG91dCBkZWNsYXJhdGlvbiIsIGNvbmRpdGlvbkxlZnQpOwogICAgICAgICAgICAgICAgYWRkU2VtYW50aWNFcnJvcih0ZW1wTGluZSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGN1cnJlbnRUb2tlbisrOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHNldFN5bnRheEVycm9yKCJFeHBlY3RlZCBsZWZ0IG9wZXJhbmQgaW4gY29uZGl0aW9uIik7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmICh0b2tlbklzKCI8IikgfHwgdG9rZW5JcygiPiIpKQogICAgewogICAgICAgIGNvcHlDdXJyZW50VG9rZW4oY29uZGl0aW9uT3ApOwogICAgICAgIGN1cnJlbnRUb2tlbisrOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHNldFN5bnRheEVycm9yKCJFeHBlY3RlZCByZWxhdGlvbmFsIG9wZXJhdG9yIGluIGNvbmRpdGlvbiIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAodG9rZW5LaW5kSXMoVE9LRU5fSURFTlRJRklFUikgfHwgdG9rZW5LaW5kSXMoVE9LRU5fTlVNQkVSKSkKICAgIHsKICAgICAgICBjb3B5Q3VycmVudFRva2VuKGNvbmRpdGlvblJpZ2h0KTsKCiAgICAgICAgaWYgKHRva2VuS2luZElzKFRPS0VOX0lERU5USUZJRVIpKQogICAgICAgIHsKICAgICAgICAgICAgc3ltYm9sSW5kZXggPSBmaW5kU3ltYm9sSW5kZXgoY29uZGl0aW9uUmlnaHQpOwogICAgICAgICAgICBpZiAoc3ltYm9sSW5kZXggPT0gLTEpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHNwcmludGYodGVtcExpbmUsICJWYXJpYWJsZSAnJXMnIHVzZWQgd2l0aG91dCBkZWNsYXJhdGlvbiIsIGNvbmRpdGlvblJpZ2h0KTsKICAgICAgICAgICAgICAgIGFkZFNlbWFudGljRXJyb3IodGVtcExpbmUpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBjdXJyZW50VG9rZW4rKzsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBzZXRTeW50YXhFcnJvcigiRXhwZWN0ZWQgcmlnaHQgb3BlcmFuZCBpbiBjb25kaXRpb24iKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgZXhwZWN0VGV4dCgiKSIpOwp9CgppbnQgZmluZFN5bWJvbEluZGV4KGNoYXIgbmFtZVtdKQp7CiAgICBpbnQgaTsKCiAgICBmb3IgKGkgPSAwOyBpIDwgc3ltYm9sQ291bnQ7IGkrKykKICAgIHsKICAgICAgICBpZiAoc3RyY21wKHN5bWJvbE5hbWVbaV0sIG5hbWUpID09IDApCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gaTsKICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIC0xOwp9Cgp2b2lkIGFkZFN5bWJvbChjaGFyIG5hbWVbXSkKewogICAgaWYgKGZpbmRTeW1ib2xJbmRleChuYW1lKSAhPSAtMSkKICAgIHsKICAgICAgICBzcHJpbnRmKHRlbXBMaW5lLCAiRHVwbGljYXRlIGRlY2xhcmF0aW9uIG9mIHZhcmlhYmxlICclcyciLCBuYW1lKTsKICAgICAgICBhZGRTZW1hbnRpY0Vycm9yKHRlbXBMaW5lKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHN5bWJvbENvdW50ID49IE1BWF9TWU1CT0xTKQogICAgewogICAgICAgIGFkZFNlbWFudGljRXJyb3IoIlN5bWJvbCB0YWJsZSBpcyBmdWxsIik7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIHN0cmNweShzeW1ib2xOYW1lW3N5bWJvbENvdW50XSwgbmFtZSk7CiAgICBzdHJjcHkoc3ltYm9sVHlwZVtzeW1ib2xDb3VudF0sICJpbnQiKTsKICAgIHN5bWJvbFZhbHVlW3N5bWJvbENvdW50XSA9IDA7CiAgICBzeW1ib2xDb3VudCsrOwp9Cgp2b2lkIHVwZGF0ZVN5bWJvbFZhbHVlKGNoYXIgbmFtZVtdLCBpbnQgdmFsdWUpCnsKICAgIGludCBpbmRleDsKCiAgICBpbmRleCA9IGZpbmRTeW1ib2xJbmRleChuYW1lKTsKICAgIGlmIChpbmRleCAhPSAtMSkKICAgIHsKICAgICAgICBzeW1ib2xWYWx1ZVtpbmRleF0gPSB2YWx1ZTsKICAgIH0KfQoKdm9pZCBhZGRTZW1hbnRpY0Vycm9yKGNoYXIgbWVzc2FnZVtdKQp7CiAgICBpZiAoc2VtYW50aWNFcnJvckNvdW50ID49IE1BWF9FUlJPUlMpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIHN0cmNweShzZW1hbnRpY0Vycm9yc1tzZW1hbnRpY0Vycm9yQ291bnRdLCBtZXNzYWdlKTsKICAgIHNlbWFudGljRXJyb3JDb3VudCsrOwp9Cgp2b2lkIGFkZFRBQyhjaGFyIGxpbmVbXSkKewogICAgaWYgKHRhY0NvdW50ID49IE1BWF9UQUMpCiAgICB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIHN0cmNweSh0YWNbdGFjQ291bnRdLCBsaW5lKTsKICAgIHRhY0NvdW50Kys7Cn0KCmludCBuZXdMYWJlbCgpCnsKICAgIGludCBsYWJlbDsKCiAgICBsYWJlbCA9IGxhYmVsQ291bnQ7CiAgICBsYWJlbENvdW50Kys7CiAgICByZXR1cm4gbGFiZWw7Cn0KCnZvaWQgcHJpbnRTeW50YXhSZXN1bHQoKQp7CiAgICBpZiAoc3ludGF4RXJyb3IpCiAgICB7CiAgICAgICAgcHJpbnRmKCJQYXJzaW5nIEZhaWxlZFxuIik7CiAgICAgICAgcHJpbnRmKCJTeW50YXggRXJyb3I6ICVzXG4iLCBzeW50YXhFcnJvck1lc3NhZ2UpOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIHByaW50ZigiUGFyc2luZyBTdWNjZXNzZnVsXG4iKTsKICAgICAgICBwcmludGYoIk5vIFN5bnRheCBFcnJvciBGb3VuZFxuIik7CiAgICB9Cn0KCnZvaWQgcHJpbnRTeW1ib2xUYWJsZSgpCnsKICAgIGludCBpOwoKICAgIHByaW50ZigiVmFyaWFibGVcdFR5cGVcdFZhbHVlXG4iKTsKICAgIHByaW50ZigiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiIpOwoKICAgIGlmIChzeW1ib2xDb3VudCA9PSAwKQogICAgewogICAgICAgIHByaW50ZigiTm8gc3ltYm9scyBmb3VuZFxuIik7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGZvciAoaSA9IDA7IGkgPCBzeW1ib2xDb3VudDsgaSsrKQogICAgewogICAgICAgIHByaW50ZigiJXNcdFx0JXNcdCVkXG4iLCBzeW1ib2xOYW1lW2ldLCBzeW1ib2xUeXBlW2ldLCBzeW1ib2xWYWx1ZVtpXSk7CiAgICB9Cn0KCnZvaWQgcHJpbnRTZW1hbnRpY0Vycm9ycygpCnsKICAgIGludCBpOwoKICAgIGlmIChzZW1hbnRpY0Vycm9yQ291bnQgPT0gMCkKICAgIHsKICAgICAgICBwcmludGYoIk5vIFNlbWFudGljIEVycm9yIEZvdW5kXG4iKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgZm9yIChpID0gMDsgaSA8IHNlbWFudGljRXJyb3JDb3VudDsgaSsrKQogICAgewogICAgICAgIHByaW50ZigiU2VtYW50aWMgRXJyb3I6ICVzXG4iLCBzZW1hbnRpY0Vycm9yc1tpXSk7CiAgICB9Cn0KCnZvaWQgcHJpbnRUQUMoKQp7CiAgICBpbnQgaTsKCiAgICBpZiAodGFjQ291bnQgPT0gMCkKICAgIHsKICAgICAgICBwcmludGYoIk5vIFRBQyBnZW5lcmF0ZWRcbiIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBmb3IgKGkgPSAwOyBpIDwgdGFjQ291bnQ7IGkrKykKICAgIHsKICAgICAgICBwcmludGYoIiVzXG4iLCB0YWNbaV0pOwogICAgfQp9Cg==