#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAXYR 200
#define MAXEST 100
#define MSIZE (MAXEST * (MAXEST + 1) / 2)
#define MAXSIM 600000
#define MAXSTP 500
#define IN stdin
#define IOUT stdout
void PHOUT( double * CL, double RAWCL, int ILAST, int IY) ;
double CLIMIT( double * CATCH, double * SIGHT, double * FMATRX, int * ISYR, int * IZYR,
double * ZMULT, double * POP, double * G) ;
double CONTRL( double D, double Y, double PLEVEL, double PSLOPE) ;
void DEVIAN( double * SS0, double * SS1, double * SS2, double * SS3, double * SIGHT, double * FMATRX,
int * ISYR, int * IZYR, double * ZMULT, double * POP, double * G) ;
double STKSIM( double RK, double R, double * POP, double * CATCH) ;
void SORT( double * ARRAY, double * ARRAY2, int N) ;
int _getline( char * buff, size_t size, FILE * fp) ;
/* from Fortran COMMON VARIABLE */
struct MANPAR {
double PPROB; /* Probability level */
double PYMAX; /* Maximum value of the productivity parameter (Y) for integration */
double PNYSTP; /* Number of step in integration over Y */
double PKSTEP; /* Maximum relative step size in integration over K */
double PDSTEP; /* Target step size for integration over depletion */
double PNBSTP; /* Number of steps for integration over the bias parameter */
double PBMIN; /* Minimum multiplicative bias eg 0.5 means 50% downward bias */
double PBMAX; /* Maximum multiplicative bias eg 1.5 means 50% upward bias */
double PSCALE; /* Raw deviance scaling factor S = 1/PSCALE**2 */
double PHASET; /* Number of years without surveys before phaseout invoked */
double PHASEP; /* Phaseout: anual reduction proportion */
double PCYCLE; /* Maximum number of years before a new CLC=number of years a CLC is valid */
double PLEVEL; /* Internal protection level */
double PSLOPE; /* 'Slope' of catch control law */
} mp = {
0.4102 , 0.05 , 200.0 , 0.05 , 0.01 ,
100.0 , 0.0 , 1.6667 , 4.0 , 8.0 ,
0.2 , 5.0 , 0.54 , 3.0
} ;
/* All years are scaled so 0 = a year prior to the 1st input data */
struct MANDAT {
int ISTART; /* Year of first input data (catch or abundance data) */
int IYEAR; /* Year for which to set first catch limit */
int NS; /* Number of non-zero estimates */
int NZ; /* Number of zero estimates */
double RKLO; /* Lower bound used in integration over K */
double RKHI; /* Upper bound used in integration over K */
} md;
int main( void )
{
/* ***** LOCAL VARIABLES */
/*
CHARACTER STOCK*30, FORMT*50
INTEGER IY, INITYR, I, IS, IYRCL, ILAST, N, IN, IOUT
*/
double CATCH[ MAXYR + 1 ] , /* Catch array, indexed by year */
SIGHT[ MAXEST + 1 ] , /* Abundance estimate array, indexed by estimate number */
FMATRX[ MSIZE + 1 ] , /* Information matrix (H) of the log sightings estimates */
/* (excludeing zero estimates, stored as a lower triangle */
ZMULT[ MAXEST + 1 ] , /* Poisson multiplier for Nth zero estimate */
POP[ MAXYR + 1 ] , /* Modelled population size in year I (set in STKSIM) */
G[ MAXYR + 1 ] , /* set & used in DEVIAN */
RAWCL, /* Nominal catch limit i.e. output from the Catch Limit Algorithm */
CL; /* The catch limit for the area considerd */
int ISYR[ MAXEST + 1 ] , /* Year of Nth abundance estimate SIGHT(N). N=0, NS-1 */
IZYR[ MAXEST + 1 ] , /* Year of Nth zero estimate. N=0, NZ-1 */
POUT; /* Parameter determing whether phaseout may be applied if */
/* necessary. Test for phaseout if POUT=1. (Phaseout is not */
/* applied to Medium of Large area nominal catch limits) */
int INITYR, /* Year in which first premanagement catch taken */
ILAST, /* Year of the most recent abundance estimate */
IY, I, IS, IYRCL, N, J, N1;
double C, TOTALC;
int numlen, len, ret = 0 ;
char /* STOCK[30], FORMT[50],*/ buff[ 300 ] ;
/* ***** Read in the data required for application of the CLA */
_getline( buff, sizeof ( buff) , IN) ;
fprintf ( IOUT
, "%s by C\n \n " , buff
) ; _getline( buff, sizeof ( buff) , IN) ; /* Discard empty lines */
/* Read the year of the first catch, the first year for which catch */
/* limits are to be set & the phaseout option */
_getline( buff, sizeof ( buff) , IN) ;
numlen
= 4 ; len
= strlen ( buff
) ; INITYR
= atoi ( & buff
[ len
- numlen
] ) ;
fprintf ( IOUT
, "%.*s %4d\n " , len
- numlen
, buff
, INITYR
) ;
_getline( buff, sizeof ( buff) , IN) ;
numlen
= 4 ; len
= strlen ( buff
) ; IYRCL
= atoi ( & buff
[ len
- numlen
] ) ;
fprintf ( IOUT
, "%.*s %4d\n " , len
- numlen
, buff
, IYRCL
) ;
_getline( buff, sizeof ( buff) , IN) ;
numlen
= 4 ; len
= strlen ( buff
) ; POUT
= atoi ( & buff
[ len
- numlen
] ) ; if ( POUT == 1 ) {
fprintf ( IOUT
, "Apply phaseout if necessary YES\n " ) ; } else {
fprintf ( IOUT
, "Apply phaseout No\n " ) ; }
/* Re-scale IYRCL such that 0 is the year prior to the first input data */
md.ISTART = 0 ;
md.IYEAR = IYRCL - INITYR;
if ( ( md.IYEAR <= 0 ) || ( md.IYEAR > MAXYR) ) {
ret = 1 ;
}
/* Initialize the catch array */
for ( I = 0 ; I <= MAXYR; I++ ) {
CATCH[ I] = 0.0 ;
}
/* Read in the catch data, scaling each year to the initial year */
_getline( buff, sizeof ( buff) , IN) ; /* Discard empty lines */
_getline( buff, sizeof ( buff) , IN) ; /* Discard empty lines */
_getline( buff, sizeof ( buff) , IN) ; /* Discard empty lines */
fprintf ( IOUT
, "\n Historic catches:\n " ) ; TOTALC = 0 ;
for ( I = 0 ; I <= MAXYR; I++ ) {
_getline( buff, sizeof ( buff) , IN) ;
sscanf ( buff
, "%4d%7lf" , & IY
, & C
) ; if ( IY < 0 ) break ; /* EOD */
IY = IY - INITYR;
if ( IY < 0 || IY > md.IYEAR ) {
fprintf ( stderr
, " ERROR: IY is out of range(%d)\n " , IY
) ; ret = 1 ;
}
CATCH[ IY] = C;
TOTALC = TOTALC + C;
}
if ( TOTALC < 0 ) {
fprintf ( stderr
, " ERROR: No historic catch input\n " ) ; ret = 1 ;
}
/* Read in the non-zero sightings estimates and information matrix */
_getline( buff, sizeof ( buff) , IN) ; /* Discard empty lines */
_getline( buff, sizeof ( buff) , IN) ; /* Discard empty lines */
_getline( buff, sizeof ( buff) , IN) ;
numlen
= 4 ; len
= strlen ( buff
) ; md.
NS = atoi ( & buff
[ len
- numlen
] ) ;
fprintf ( IOUT
, "\n Abundance estimates:\n " ) ; if ( md.NS > MAXEST) {
fprintf ( stderr
, "ERROR: Abundance year out of range\n " ) ; ret = 1 ;
}
_getline( buff, sizeof ( buff) , IN) ;
for ( N = 0 ; N <= md.NS - 1 ; N++ ) {
N1 = ( N * ( N + 1 ) ) / 2 ;
_getline( buff, sizeof ( buff) , IN) ;
sscanf ( buff
, "%4d%10lf" , & ISYR
[ N
] , & SIGHT
[ N
] ) ; fprintf ( IOUT
, "%4d %8.f" , ISYR
[ N
] , SIGHT
[ N
] ) ; for ( J = 0 ; J < N + 1 ; J++ ) {
if ( len > J * 7 + 14 ) {
sscanf ( & buff
[ 0 ] + J
* 7 + 14 , "%7lf" , & FMATRX
[ N1
+ J
] ) ; } else {
FMATRX[ N1 + J] = 0.0 ;
}
fprintf ( IOUT
, "%7.f" , FMATRX
[ N1
+ J
] ) ; }
ISYR[ N] = ISYR[ N] - INITYR;
if ( ISYR[ N] < 0 || ISYR[ N] >= md.IYEAR ) {
fprintf ( stderr
, "ERROR: Sight year out of range\n " ) ; ret = 1 ;
}
if ( SIGHT[ N] <= 0.0 ) {
fprintf ( stderr
, "ERROR: Estimate not positive\n " ) ; ret = 1 ;
}
}
/* Read in the Poisson multipliers for any zero sightings estimates */
_getline( buff, sizeof ( buff) , IN) ;
_getline( buff, sizeof ( buff) , IN) ;
numlen
= 3 ; len
= strlen ( buff
) ; md.
NZ = atoi ( & buff
[ len
- numlen
] ) ; if ( md.NZ > 0 ) {
fprintf ( IOUT
, "\n Zero abundance estimates:\n " ) ; }
if ( md.NZ > MAXEST) {
fprintf ( stderr
, "ERROR: Zero estimate array too small\n " ) ; ret = 1 ;
}
_getline( buff, sizeof ( buff) , IN) ;
for ( N = 0 ; N <= md.NZ - 1 ; N++ ) {
N1 = ( N * ( N + 1 ) ) / 2 ;
_getline( buff, sizeof ( buff) , IN) ;
sscanf ( buff
, "%4d%10lf" , & IZYR
[ N
] , & ZMULT
[ N
] ) ; fprintf ( IOUT
, "%4d%7.f\n " , IZYR
[ N
] , ZMULT
[ N
] ) ; IZYR[ N] = IZYR[ N] - INITYR;
if ( IZYR[ N] < 0 || IZYR[ N] >= md.IYEAR ) {
fprintf ( stderr
, "Sight year out of range\n " ) ; ret = 1 ;
}
if ( ZMULT[ N] <= 0.0 ) {
fprintf ( stderr
, "ERROR: Multiplier not positive\n " ) ; ret = 1 ;
}
}
/* Bound the range for the integration over K */
md.RKHI = 1.0E7 ;
md.RKLO = 0.0 ;
IS = 0 ; /* orignal not initialized bug? */
/* ****** Run the CLA to obtain the nominal catch limit */
RAWCL = CLIMIT( CATCH, SIGHT, FMATRX, ISYR, IZYR, ZMULT, POP, G) ;
/* Set the catch limits for PCYCLE years. If the catch limit may be */
/* subject to phaseout, call POUT to apply the phaseout rule. */
/* First set ILAST = year of the most recent abundance estimate */
if ( md.NS > 0 ) ILAST = ISYR[ md.NS - 1 ] ;
if ( md.NZ > 0 ) ILAST = ( IS > IZYR[ md.NZ - 1 ] ) ? IS: IZYR[ md.NZ - 1 ] ;
for ( IY = md.IYEAR ; IY <= md.IYEAR + mp.PCYCLE - 1 ; IY++ ) {
if ( POUT == 1 ) {
PHOUT( & CL, RAWCL, ILAST, IY) ;
} else {
CL = RAWCL;
}
fprintf ( IOUT
, "Year: %4d Catch limit:%6d\n " , IY
+ INITYR
, ( int ) ( CL
+ 0.5 ) ) ;
}
return ret;
}
/*
C **************************************************************************************
C
C CLC version 6
C
C **************************************************************************************
C
C 31 January 1994
C
C **************************************************************************************
*/
/*
SUBROUTINE PHOUT (CL, RAWCL, ILAST, IY)
*/
void PHOUT( double * CL, double RAWCL, int ILAST, int IY)
{
/*
PHASET Number of years without surveys before phaseout invoked
PHASEP Phaseout annual reduction proportion
Phaseout: Reduce catch limit if there is no survey data in the
last PHASET years
*/
if ( IY >= ILAST + mp.PHASET ) {
* CL = RAWCL * ( 1.0 - mp.PHASEP * ( IY - ILAST - mp.PHASET ) ) ;
if ( * CL < 0.0 ) * CL = 0.0 ;
} else {
* CL = RAWCL;
}
/* RETURN
END */
}
/*
REAL FUNCTION CLIMIT (CATCH,SIGHT,FMATRX,ISYR,IZYR,ZMULT,POP,G)
Run the CLA to obtain to nominal catch limit
*/
double CLIMIT( double * CATCH, double * SIGHT, double * FMATRX, int * ISYR, int * IZYR, double * ZMULT, double * POP, double * G)
{
double SF, SS0, SS1, SS2, SS3;
double Y[ MAXSTP + 1 ] , B[ MAXSTP + 1 ] , RLGB[ MAXSTP + 1 ] ;
double * PRES = NULL, * QRES = NULL;
int NB, NR;
double BINC, YINC, DK, R, RK, D, DD, P, Q, PTOT;
int I, J, N, N2;
double _CLIMIT = 0.0 ;
if ( md.NS <= 0 ) return _CLIMIT;
PRES
= ( double * ) malloc ( sizeof ( double ) * ( MAXSIM
+ 1 ) ) ; if ( PRES == NULL) {
fprintf ( stderr
, "Can't Allocate memory (PRES)\n " ) ; goto err_exit;
}
memset ( PRES
, 0 , sizeof ( double ) * ( MAXSTP
+ 1 ) ) ;
QRES
= ( double * ) malloc ( sizeof ( double ) * ( MAXSIM
+ 1 ) ) ; if ( QRES == NULL) {
fprintf ( stderr
, "Can't Allocate memory (QRES)\n " ) ; goto err_exit;
}
memset ( QRES
, 0 , sizeof ( double ) * ( MAXSTP
+ 1 ) ) ;
SF = 0.5 / ( mp.PSCALE * mp.PSCALE ) ;
/* Check the sizes of the Y and B arrays are large enough */
if ( mp.PNBSTP > MAXSTP || mp.PNYSTP > MAXSTP) {
fprintf ( stderr
, "Y &/or b array sizes too small\n " ) ; goto err_exit;
}
/* Set sightings bias step sizes & their log values. BINC = Bias increment */
NB = ( int ) mp.PNBSTP ;
BINC = ( mp.PBMAX - mp.PBMIN ) / NB;
for ( I = 0 ; I <= NB - 1 ; I++ ) {
* ( B + I) = mp.PBMIN + ( I + 0.5 ) * BINC;
* ( RLGB
+ I
) = - log ( * ( B
+ I
) ) ; }
/* Set productivity parameter step sizes (midpoints) */
NR = ( int ) mp.PNYSTP ;
YINC = mp.PYMAX / NR;
for ( I = 0 ; I <= NR - 1 ; I++ ) {
* ( Y + I) = ( I + 0.5 ) * YINC;
}
PTOT = 0 ;
N = 0 ;
for ( I = 0 ; I <= NR - 1 ; I++ ) {
/* Set R from the productivity parameter, Y */
R = 1.4184 * * ( Y + I) ;
/* Step size for K */
DK = mp.PKSTEP ;
D = 1.0 ;
RK = md.RKHI ;
/* Use function STKSIM to set up the Nth population trajectory */
/* i.e. set up the pop array */
while ( 1 ) {
if ( ( RK <= md.RKLO ) || ( STKSIM( RK, R, POP, CATCH) <= 0.0 ) ) break ;
if ( N >= MAXSIM) {
fprintf ( stderr
, "ERROR: TOO MANY SIMULATIONS" ) ; goto err_exit;
}
/* How much depletion covered? */
DD = D - POP[ md.IYEAR ] / RK;
D = POP[ md.IYEAR ] / RK;
P = 0.0 ;
if ( DD > 0.0 ) {
/* Compute the internal catch limit corresponding to D and Y(I) */
QRES[ N] = CONTRL( D, Y[ I] , mp.PLEVEL , mp.PSLOPE ) * POP[ md.IYEAR ] ;
/* Calculate deviance */
DEVIAN( & SS0, & SS1, & SS2, & SS3, SIGHT, FMATRX, ISYR, IZYR, ZMULT, POP, G) ;
/* Scale likelihood and integrate over values for the bias parameter */
for ( J = 0 ; J <= NB - 1 ; J++ ) {
P
= P
+ exp ( - SF
* ( SS0
+ * ( RLGB
+ J
) * ( SS1
+ * ( RLGB
+ J
) * SS2
) + SS3
* * ( B
+ J
) ) ) ; }
/* Calculate the weight for this point (& total area under likelihood) */
PRES[ N] = P * DD;
PTOT = PTOT + PRES[ N] ;
/* Update counter */
N = N + 1 ;
/* Find the next K */
DK = DK * mp.PDSTEP / DD;
if ( DK > mp.PKSTEP ) DK = mp.PKSTEP ;
} else {
DK = mp.PKSTEP ;
}
/* Set the new value of K */
RK = RK / ( 1.0 + DK) ;
}
}
if ( PTOT < 0.0 ) {
fprintf ( stderr
, "ERROR: PROB INTEGRATES TO ZERO" ) ; goto err_exit;
}
/* Sort the QRES and PRES arrays in ascending order of QRES */
N2 = N;
SORT( QRES, PRES, N2) ;
/* Normalize the relative likelihoods */
for ( I = 0 ; I <= N - 1 ; I++ ) {
PRES[ I] = PRES[ I] / PTOT;
}
/* Extract the desired probability level: the nominal catch limit (NCL) */
/* is the lower PROB% of the distribution. */
/* First calculate PRES(I), the probability that the NCL is between */
/* QRES(I) & QRES(I + 1). */
P = 0 ;
for ( I = 0 ; I <= N - 1 ; I++ ) {
P = P + PRES[ I] ;
if ( P > mp.PPROB ) break ;
}
/* Interpolate to set the nominal catch limit */
if ( I >= N - 1 ) {
Q = QRES[ N - 1 ] ;
} else {
Q = ( QRES[ I + 1 ] * ( mp.PPROB - P + PRES[ I] ) + QRES[ I] * ( P - mp.PPROB ) ) / PRES[ I] ;
}
_CLIMIT = Q;
if ( QRES
!= NULL
) free ( QRES
) ; if ( PRES
!= NULL
) free ( PRES
) ; return _CLIMIT;
err_exit:
if ( QRES
!= NULL
) free ( QRES
) ; if ( PRES
!= NULL
) free ( PRES
) ; return 0.0 ; /* not reached */
}
/*
FUNCTION CONTRL (D, Y, PLEVEL, PSLOPE)
Catch control law
*/
double CONTRL( double D, double Y, double PLEVEL, double PSLOPE)
{
double ret;
if ( D < PLEVEL) {
ret = 0.0 ;
} else if ( D < 1.0 ) {
ret = PSLOPE * Y * ( D - PLEVEL) ;
} else {
ret = PSLOPE * Y * ( 1.0 - PLEVEL) ;
}
return ret;
/* END */
}
/*
SUBROUTINE DEVIAN (SS0, SS1, SS2, SS3, SIGHT, FMATRX, ISYR,
Calculate deviance (-2 log likelihood) in terms of coefficients for
the bias and log bias parameters
*/
void DEVIAN( double * SS0, double * SS1, double * SS2, double * SS3, double * SIGHT,
double * FMATRX, int * ISYR, int * IZYR, double * ZMULT, double * POP, double * G)
{
int N, J, K;
* SS0 = 0.0 ;
* SS1 = 0.0 ;
* SS2 = 0.0 ;
* SS3 = 0.0 ;
for ( N = 0 ; N <= md.NS - 1 ; N++ ) {
* ( G
+ N
) = log ( * ( SIGHT
+ N
) / * ( POP
+* ( ISYR
+ N
) ) ) ; K = N * ( N + 1 ) / 2 ;
for ( J = 0 ; J <= N - 1 ; J++ ) {
/*1st add non diagonal contributions (which are doubled up)*/
* SS0 = * SS0 + 2.0 * * ( G + J) * * ( G + N) * * ( FMATRX + K) ;
* SS1 = * SS1 + 2.0 * ( * ( G + J) + * ( G + N) ) * * ( FMATRX + K) ;
* SS2 = * SS2 + * ( FMATRX + K) + * ( FMATRX + K) ;
K = K + 1 ;
}
/* Now add diagnoal contribution */
* SS0 = * SS0 + * ( G + N) * * ( G + N) * * ( FMATRX + K) ;
* SS1 = * SS1 + 2.0 * * ( G + N) * * ( FMATRX + K) ;
* SS2 = * SS2 + * ( FMATRX + K) ;
}
/* Now do the zero estimates */
for ( N = 0 ; N <= md.NZ - 1 ; N++ ) {
* SS3 = * SS3 + 2.0 * * ( POP + * ( IZYR + N) ) / * ( ZMULT + N) ;
}
return ;
}
/*
FUNCTION STKSIM (RK, R, POP, CATCH)
Calculate the stock trajectory with parameter RK and R: return
the current stock size
RK = notional carrying capacity; R = productivity parameter * 1.4184
*/
double STKSIM( double RK, double R, double * POP, double * CATCH)
{
int I;
double D;
* ( POP+ md.ISTART ) = RK;
for ( I = md.ISTART + 1 ; I <= md.IYEAR ; I++ ) {
D = * ( POP + I - 1 ) / RK;
* ( POP + I) = * ( POP + I - 1 ) * ( 1.0 + R * ( 1.0 - D * D) ) - * ( CATCH + I - 1 ) ;
if ( * ( POP + I) <= 0 ) {
return 0.0 ;
}
}
return * ( POP + md.IYEAR ) ;
}
/*
SUBROUTINE SORT (ARRAY, ARRAY2, N)
SORT sorts a pair of arrays in ascending order of the first array
(using the heapsort algorithm)
*/
void SORT( double * ARRAY, double * ARRAY2, int N)
{
double /*ARRAY(0:*), ARRAY2(0:*),*/ TEMP, TEMP2;
int /*N,*/ K, IR, I, J;
if ( N < 2 ) return ;
K = N / 2 ;
IR = N - 1 ;
while ( 1 ) { /*10*/
if ( K != 0 ) {
K = K - 1 ;
TEMP = * ( ARRAY + K) ;
TEMP2 = * ( ARRAY2 + K) ;
} else {
TEMP = * ( ARRAY + IR) ;
TEMP2 = * ( ARRAY2 + IR) ;
* ( ARRAY + IR) = * ARRAY;
* ( ARRAY2 + IR) = * ARRAY2;
IR = IR - 1 ;
if ( IR == 0 ) {
* ARRAY = TEMP;
* ARRAY2 = TEMP2;
return ;
}
}
I = K;
J = K + K + 1 ;
while ( 1 ) { /*20*/
if ( J > IR) break ;
if ( ( J < IR) && ( * ( ARRAY + J) < * ( ARRAY+ J + 1 ) ) ) J = J + 1 ;
if ( TEMP < * ( ARRAY + J) ) {
* ( ARRAY + I) = * ( ARRAY + J) ;
* ( ARRAY2 + I) = * ( ARRAY2 + J) ;
I = J;
J = J + I + 1 ;
} else {
J = IR + 1 ;
}
} /*GOTO 20*/
* ( ARRAY + I) = TEMP;
* ( ARRAY2 + I) = TEMP2;
} /*GOTO 10*/
/*END*/
}
int _getline( char * buff, size_t size, FILE * fp) {
char * ret;
ret
= fgets ( buff
, size
, fp
) ; if ( ret != NULL) {
if ( buff
[ strlen ( buff
) - 1 ] == '\n ' ) if ( buff
[ strlen ( buff
) - 1 ] == '\r ' ) }
return ( ret != NULL) ;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8bWF0aC5oPgoKI2RlZmluZSBNQVhZUiAgMjAwCiNkZWZpbmUgTUFYRVNUIDEwMAojZGVmaW5lIE1TSVpFICAoTUFYRVNUICogKE1BWEVTVCArIDEpIC8gMikKCiNkZWZpbmUgTUFYU0lNICA2MDAwMDAKI2RlZmluZSBNQVhTVFAgIDUwMAoKI2RlZmluZSBJTiBzdGRpbgojZGVmaW5lIElPVVQgc3Rkb3V0Cgp2b2lkIFBIT1VUKGRvdWJsZSAqQ0wsIGRvdWJsZSBSQVdDTCwgaW50IElMQVNULCBpbnQgSVkpOwpkb3VibGUgQ0xJTUlUKGRvdWJsZSAqQ0FUQ0gsIGRvdWJsZSAqU0lHSFQsIGRvdWJsZSAqRk1BVFJYLCBpbnQgKklTWVIsIGludCAqSVpZUiwKICAgICAgICAgICAgICBkb3VibGUgKlpNVUxULGRvdWJsZSAqUE9QLCBkb3VibGUgKkcpOwpkb3VibGUgQ09OVFJMKGRvdWJsZSBELCBkb3VibGUgWSwgZG91YmxlIFBMRVZFTCwgZG91YmxlIFBTTE9QRSk7CnZvaWQgREVWSUFOKGRvdWJsZSAqU1MwLCBkb3VibGUgKlNTMSwgZG91YmxlICpTUzIsIGRvdWJsZSAqU1MzLCBkb3VibGUgKlNJR0hULCBkb3VibGUgKkZNQVRSWCwgCiAgICAgICAgICAgIGludCAqSVNZUiwgaW50ICpJWllSLCBkb3VibGUgKlpNVUxULCBkb3VibGUgKlBPUCwgZG91YmxlICpHKTsKZG91YmxlIFNUS1NJTShkb3VibGUgUkssIGRvdWJsZSBSLCBkb3VibGUgKlBPUCwgZG91YmxlICpDQVRDSCk7CnZvaWQgU09SVChkb3VibGUgKkFSUkFZLCBkb3VibGUgKkFSUkFZMiwgaW50IE4pOwppbnQgIF9nZXRsaW5lKGNoYXIgKmJ1ZmYsIHNpemVfdCBzaXplLCBGSUxFICpmcCk7CgovKiBmcm9tIEZvcnRyYW4gQ09NTU9OIFZBUklBQkxFICovCnN0cnVjdCBNQU5QQVIgewoJZG91YmxlIFBQUk9COyAgLyogUHJvYmFiaWxpdHkgbGV2ZWwgKi8KCWRvdWJsZSBQWU1BWDsgIC8qIE1heGltdW0gdmFsdWUgb2YgdGhlIHByb2R1Y3Rpdml0eSBwYXJhbWV0ZXIgKFkpIGZvciBpbnRlZ3JhdGlvbiAqLwoJZG91YmxlIFBOWVNUUDsgLyogTnVtYmVyIG9mIHN0ZXAgaW4gaW50ZWdyYXRpb24gb3ZlciBZICovCglkb3VibGUgUEtTVEVQOyAvKiBNYXhpbXVtIHJlbGF0aXZlIHN0ZXAgc2l6ZSBpbiBpbnRlZ3JhdGlvbiBvdmVyIEsgKi8KCWRvdWJsZSBQRFNURVA7IC8qIFRhcmdldCBzdGVwIHNpemUgZm9yIGludGVncmF0aW9uIG92ZXIgZGVwbGV0aW9uICovCglkb3VibGUgUE5CU1RQOyAvKiBOdW1iZXIgb2Ygc3RlcHMgZm9yIGludGVncmF0aW9uIG92ZXIgdGhlIGJpYXMgcGFyYW1ldGVyICovCglkb3VibGUgUEJNSU47ICAvKiBNaW5pbXVtIG11bHRpcGxpY2F0aXZlIGJpYXMgZWcgMC41IG1lYW5zIDUwJSBkb3dud2FyZCBiaWFzICovCglkb3VibGUgUEJNQVg7ICAvKiBNYXhpbXVtIG11bHRpcGxpY2F0aXZlIGJpYXMgZWcgMS41IG1lYW5zIDUwJSB1cHdhcmQgYmlhcyAqLwoJZG91YmxlIFBTQ0FMRTsgLyogUmF3IGRldmlhbmNlIHNjYWxpbmcgZmFjdG9yIFMgPSAxL1BTQ0FMRSoqMiAqLwoJZG91YmxlIFBIQVNFVDsgLyogTnVtYmVyIG9mIHllYXJzIHdpdGhvdXQgc3VydmV5cyBiZWZvcmUgcGhhc2VvdXQgaW52b2tlZCAqLwoJZG91YmxlIFBIQVNFUDsgLyogUGhhc2VvdXQ6IGFudWFsIHJlZHVjdGlvbiBwcm9wb3J0aW9uICovCglkb3VibGUgUENZQ0xFOyAvKiBNYXhpbXVtIG51bWJlciBvZiB5ZWFycyBiZWZvcmUgYSBuZXcgQ0xDPW51bWJlciBvZiB5ZWFycyBhIENMQyBpcyB2YWxpZCAqLwoJZG91YmxlIFBMRVZFTDsgLyogSW50ZXJuYWwgcHJvdGVjdGlvbiBsZXZlbCAqLwoJZG91YmxlIFBTTE9QRTsgLyogJ1Nsb3BlJyBvZiBjYXRjaCBjb250cm9sIGxhdyAqLwp9IG1wID0gewoJMC40MTAyLCAwLjA1LCAgMjAwLjAsICAwLjA1LCAgMC4wMSwKCTEwMC4wLCAgMC4wLCAgIDEuNjY2NywgNC4wLCAgIDguMCwKCTAuMiwgICAgNS4wLCAgIDAuNTQsICAgMy4wCn07Ci8qIEFsbCB5ZWFycyBhcmUgc2NhbGVkIHNvIDAgPSBhIHllYXIgcHJpb3IgdG8gdGhlIDFzdCBpbnB1dCBkYXRhICovCnN0cnVjdCBNQU5EQVQgewoJaW50IElTVEFSVDsgICAgLyogWWVhciBvZiBmaXJzdCBpbnB1dCBkYXRhIChjYXRjaCBvciBhYnVuZGFuY2UgZGF0YSkgKi8KCWludCBJWUVBUjsgICAgIC8qIFllYXIgZm9yIHdoaWNoIHRvIHNldCBmaXJzdCBjYXRjaCBsaW1pdCAqLwoJaW50IE5TOyAgICAgICAgLyogTnVtYmVyIG9mIG5vbi16ZXJvIGVzdGltYXRlcyAqLwoJaW50IE5aOyAgICAgICAgLyogTnVtYmVyIG9mIHplcm8gZXN0aW1hdGVzICovCglkb3VibGUgUktMTzsgICAvKiBMb3dlciBib3VuZCB1c2VkIGluIGludGVncmF0aW9uIG92ZXIgSyAqLwoJZG91YmxlIFJLSEk7ICAgLyogVXBwZXIgYm91bmQgdXNlZCBpbiBpbnRlZ3JhdGlvbiBvdmVyIEsgKi8KfSBtZDsKCmludCBtYWluKHZvaWQpCnsKLyogKioqKiogTE9DQUwgVkFSSUFCTEVTICovCi8qCglDSEFSQUNURVIgU1RPQ0sqMzAsIEZPUk1UKjUwCglJTlRFR0VSIElZLCBJTklUWVIsIEksIElTLCBJWVJDTCwgSUxBU1QsIE4sIElOLCBJT1VUCiovCglkb3VibGUJQ0FUQ0hbTUFYWVIgKyAxXSwgIC8qIENhdGNoIGFycmF5LCBpbmRleGVkIGJ5IHllYXIgKi8KCQkJU0lHSFRbTUFYRVNUICsgMV0sIC8qIEFidW5kYW5jZSBlc3RpbWF0ZSBhcnJheSwgaW5kZXhlZCBieSBlc3RpbWF0ZSBudW1iZXIgKi8KCQkJRk1BVFJYW01TSVpFICsgMV0sIC8qIEluZm9ybWF0aW9uIG1hdHJpeCAoSCkgb2YgdGhlIGxvZyBzaWdodGluZ3MgZXN0aW1hdGVzICovCgkJCQkJCQkgLyogKGV4Y2x1ZGVpbmcgemVybyBlc3RpbWF0ZXMsIHN0b3JlZCBhcyBhIGxvd2VyIHRyaWFuZ2xlICovCgkJCVpNVUxUW01BWEVTVCArIDFdLCAvKiBQb2lzc29uIG11bHRpcGxpZXIgZm9yIE50aCB6ZXJvIGVzdGltYXRlICovCgkJCVBPUFtNQVhZUiArIDFdLCAgICAvKiBNb2RlbGxlZCBwb3B1bGF0aW9uIHNpemUgaW4geWVhciBJIChzZXQgaW4gU1RLU0lNKSAqLwoJCQlHW01BWFlSICsgMV0sICAgICAgLyogc2V0ICYgdXNlZCBpbiBERVZJQU4gKi8KCQkJUkFXQ0wsICAgICAgICAgICAvKiBOb21pbmFsIGNhdGNoIGxpbWl0IGkuZS4gb3V0cHV0IGZyb20gdGhlIENhdGNoIExpbWl0IEFsZ29yaXRobSAqLwoJCQlDTDsgICAgICAgICAgICAgIC8qIFRoZSBjYXRjaCBsaW1pdCBmb3IgdGhlIGFyZWEgY29uc2lkZXJkICovCglpbnQgCUlTWVJbTUFYRVNUICsgMV0sICAvKiBZZWFyIG9mIE50aCBhYnVuZGFuY2UgZXN0aW1hdGUgU0lHSFQoTikuIE49MCwgTlMtMSAqLwoJCQlJWllSW01BWEVTVCArIDFdLCAgLyogWWVhciBvZiBOdGggemVybyBlc3RpbWF0ZS4gTj0wLCBOWi0xICovCgkJCVBPVVQ7ICAgICAgICAgICAgLyogUGFyYW1ldGVyIGRldGVybWluZyB3aGV0aGVyIHBoYXNlb3V0IG1heSBiZSBhcHBsaWVkIGlmICovCgkJCQkJCQkgLyogbmVjZXNzYXJ5LiBUZXN0IGZvciBwaGFzZW91dCBpZiBQT1VUPTEuIChQaGFzZW91dCBpcyBub3QgKi8KCQkJCQkJCSAvKiBhcHBsaWVkIHRvIE1lZGl1bSBvZiBMYXJnZSBhcmVhIG5vbWluYWwgY2F0Y2ggbGltaXRzKSAqLwoJaW50IAlJTklUWVIsCQkJIC8qIFllYXIgaW4gd2hpY2ggZmlyc3QgcHJlbWFuYWdlbWVudCBjYXRjaCB0YWtlbiAqLwoJCQlJTEFTVCwJCQkgLyogWWVhciBvZiB0aGUgbW9zdCByZWNlbnQgYWJ1bmRhbmNlIGVzdGltYXRlICovCgkJCUlZLCBJLCBJUywgSVlSQ0wsIE4sIEosIE4xOwoJZG91YmxlCUMsIFRPVEFMQzsKCWludAkJbnVtbGVuLCBsZW4sIHJldCA9IDA7CgljaGFyIC8qIFNUT0NLWzMwXSwgRk9STVRbNTBdLCovIGJ1ZmZbMzAwXTsKCi8qICoqKioqIFJlYWQgaW4gdGhlIGRhdGEgcmVxdWlyZWQgZm9yIGFwcGxpY2F0aW9uIG9mIHRoZSBDTEEgKi8KCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCWZwcmludGYoSU9VVCwgIiVzIGJ5IENcblxuIiwgYnVmZik7CglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsgLyogRGlzY2FyZCBlbXB0eSBsaW5lcyAqLwoKLyogCVJlYWQgdGhlIHllYXIgb2YgdGhlIGZpcnN0IGNhdGNoLCB0aGUgZmlyc3QgeWVhciBmb3Igd2hpY2ggY2F0Y2ggKi8KLyogbGltaXRzIGFyZSB0byBiZSBzZXQgJiB0aGUgcGhhc2VvdXQgb3B0aW9uICovCgoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7CgludW1sZW4gPSA0OyBsZW4gPSBzdHJsZW4oYnVmZik7CglJTklUWVIgPSBhdG9pKCZidWZmW2xlbi1udW1sZW5dKTsKCglmcHJpbnRmKElPVVQsICAgIiUuKnMgJTRkXG4iLCBsZW4gLSBudW1sZW4sIGJ1ZmYsIElOSVRZUik7CgoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7CgludW1sZW4gPSA0OyBsZW4gPSBzdHJsZW4oYnVmZik7CglJWVJDTCA9IGF0b2koJmJ1ZmZbbGVuLW51bWxlbl0pOwoKCWZwcmludGYoSU9VVCwgICAiJS4qcyAlNGRcbiIsIGxlbiAtIG51bWxlbiwgYnVmZiwgSVlSQ0wpOwoKCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOwoJbnVtbGVuID0gNDsgbGVuID0gc3RybGVuKGJ1ZmYpOwoJUE9VVCA9IGF0b2koJmJ1ZmZbbGVuLW51bWxlbl0pOwoJaWYgKFBPVVQgPT0gMSkgewoJCWZwcmludGYoSU9VVCwgICAiQXBwbHkgcGhhc2VvdXQgaWYgbmVjZXNzYXJ5ICAgIFlFU1xuIik7Cgl9IGVsc2UgewoJCWZwcmludGYoSU9VVCwgICAiQXBwbHkgcGhhc2VvdXQgICAgICAgICAgICAgICAgICBOb1xuIik7Cgl9CgovKiBSZS1zY2FsZSBJWVJDTCBzdWNoIHRoYXQgMCBpcyB0aGUgeWVhciBwcmlvciB0byB0aGUgZmlyc3QgaW5wdXQgZGF0YSAqLwoKCW1kLklTVEFSVCA9IDA7CgltZC5JWUVBUiA9IElZUkNMIC0gSU5JVFlSOwoJaWYgKChtZC5JWUVBUiA8PSAwKSB8fCAobWQuSVlFQVIgPiBNQVhZUikpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIklOVkFMSUQgWUVBUiIpOwoJCXJldCA9IDE7CgkJZ290byBleGl0OwoJfQoKLyogSW5pdGlhbGl6ZSB0aGUgY2F0Y2ggYXJyYXkgKi8KCglmb3IgKEkgPSAwOyBJIDw9IE1BWFlSOyBJKyspIHsKCQlDQVRDSFtJXSA9IDAuMDsKCX0KCi8qIFJlYWQgaW4gdGhlIGNhdGNoIGRhdGEsIHNjYWxpbmcgZWFjaCB5ZWFyIHRvIHRoZSBpbml0aWFsIHllYXIgKi8KCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOyAvKiBEaXNjYXJkIGVtcHR5IGxpbmVzICovCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsgLyogRGlzY2FyZCBlbXB0eSBsaW5lcyAqLwoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7IC8qIERpc2NhcmQgZW1wdHkgbGluZXMgKi8KCglmcHJpbnRmKElPVVQsICJcbkhpc3RvcmljIGNhdGNoZXM6XG4iKTsKCVRPVEFMQyA9IDA7Cglmb3IgKEkgPSAwOyBJIDw9IE1BWFlSOyBJKyspIHsKCQlfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCQlzc2NhbmYoYnVmZiwiJTRkJTdsZiIsICZJWSwgJkMpOwoJCWlmIChJWSA8IDApIGJyZWFrOyAvKiBFT0QgKi8KCgkJZnByaW50ZihJT1VULCAiJTRkJTYuZlxuIiwgSVksIEMpOwoJCUlZID0gSVkgLSBJTklUWVI7CgkJaWYgKElZIDwgMCB8fCBJWSA+IG1kLklZRUFSKSB7CgkJCWZwcmludGYoc3RkZXJyLCAiIEVSUk9SOiBJWSBpcyBvdXQgb2YgcmFuZ2UoJWQpXG4iLCBJWSk7CgkJCXJldCA9IDE7CgkJCWdvdG8gZXhpdDsKCQl9CgkJQ0FUQ0hbSVldID0gQzsKCQlUT1RBTEMgPSBUT1RBTEMgKyBDOwoJfQoKCWlmIChUT1RBTEMgPCAwKSB7CgkJZnByaW50ZihzdGRlcnIsICIgRVJST1I6IE5vIGhpc3RvcmljIGNhdGNoIGlucHV0XG4iKTsKCQlyZXQgPSAxOwoJCWdvdG8gZXhpdDsKCX0KCi8qIFJlYWQgaW4gdGhlIG5vbi16ZXJvIHNpZ2h0aW5ncyBlc3RpbWF0ZXMgYW5kIGluZm9ybWF0aW9uIG1hdHJpeCAqLwoKCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOyAvKiBEaXNjYXJkIGVtcHR5IGxpbmVzICovCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsgLyogRGlzY2FyZCBlbXB0eSBsaW5lcyAqLwoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7CgludW1sZW4gPSA0OyBsZW4gPSBzdHJsZW4oYnVmZik7CgltZC5OUyA9IGF0b2koJmJ1ZmZbbGVuLW51bWxlbl0pOwoKCWZwcmludGYoSU9VVCwgICAiXG5BYnVuZGFuY2UgZXN0aW1hdGVzOlxuIik7CglpZiAobWQuTlMgPiBNQVhFU1QpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIkVSUk9SOiBBYnVuZGFuY2UgeWVhciBvdXQgb2YgcmFuZ2VcbiIpOwoJCXJldCA9IDE7CgkJZ290byBleGl0OwoJfQoJX2dldGxpbmUoYnVmZiwgc2l6ZW9mKGJ1ZmYpLCBJTik7Cglmb3IgKE4gPSAwOyBOIDw9IG1kLk5TIC0gMTsgTisrKSB7CgkJTjEgPSAoTiAqIChOICsgMSkpIC8gMjsKCQlfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCQlzc2NhbmYoYnVmZiwgIiU0ZCUxMGxmIiwgJklTWVJbTl0sICZTSUdIVFtOXSk7CgkJZnByaW50ZihJT1VULCAgICIlNGQgJTguZiIsIElTWVJbTl0sIFNJR0hUW05dKTsKCQlsZW4gPSBzdHJsZW4oYnVmZik7CgkJZm9yIChKID0gMDsgSiA8IE4gKyAxOyBKKyspIHsKCQkJaWYgKGxlbiA+IEogKiA3ICsgMTQpIHsKCQkJCXNzY2FuZigmYnVmZlswXSArIEogKiA3ICsgMTQsIiU3bGYiLCAmRk1BVFJYW04xICsgSl0pOwoJCQl9IGVsc2UgewoJCQkJRk1BVFJYW04xICsgSl0gPSAwLjA7CgkJCX0KCQkJZnByaW50ZihJT1VULCAgICIlNy5mIiwgRk1BVFJYW04xICsgSl0pOwoJCX0KCQlmcHJpbnRmKElPVVQsICAgIlxuIik7CgkJSVNZUltOXSA9IElTWVJbTl0gLSBJTklUWVI7CgkJaWYgKElTWVJbTl0gPCAwIHx8IElTWVJbTl0gPj0gbWQuSVlFQVIpIHsKCQkJZnByaW50ZihzdGRlcnIsICJFUlJPUjogU2lnaHQgeWVhciBvdXQgb2YgcmFuZ2VcbiIpOwoJCQlyZXQgPSAxOwoJCQlnb3RvIGV4aXQ7CgkJfQoJCWlmIChTSUdIVFtOXSA8PSAwLjApIHsKCQkJZnByaW50ZihzdGRlcnIsICJFUlJPUjogRXN0aW1hdGUgbm90IHBvc2l0aXZlXG4iKTsKCQkJcmV0ID0gMTsKCQkJZ290byBleGl0OwoJCX0KCX0KCi8qIFJlYWQgaW4gdGhlIFBvaXNzb24gbXVsdGlwbGllcnMgZm9yIGFueSB6ZXJvIHNpZ2h0aW5ncyBlc3RpbWF0ZXMgKi8KCglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOwoJbnVtbGVuID0gMzsgbGVuID0gc3RybGVuKGJ1ZmYpOwoJbWQuTlogPSBhdG9pKCZidWZmW2xlbi1udW1sZW5dKTsKCWlmIChtZC5OWiA+IDApIHsKCQlmcHJpbnRmKElPVVQsICAgIlxuWmVybyBhYnVuZGFuY2UgZXN0aW1hdGVzOlxuIik7Cgl9CglpZiAobWQuTlogPiBNQVhFU1QpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIkVSUk9SOiBaZXJvIGVzdGltYXRlIGFycmF5IHRvbyBzbWFsbFxuIik7CgkJcmV0ID0gMTsKCQlnb3RvIGV4aXQ7Cgl9CglfZ2V0bGluZShidWZmLCBzaXplb2YoYnVmZiksIElOKTsKCWZvciAoTiA9IDA7IE4gPD0gbWQuTlogLSAxOyBOKyspIHsKCQlOMSA9IChOICogKE4gKyAxKSkgLyAyOwoJCV9nZXRsaW5lKGJ1ZmYsIHNpemVvZihidWZmKSwgSU4pOwoJCXNzY2FuZihidWZmLCAiJTRkJTEwbGYiLCAmSVpZUltOXSwgJlpNVUxUW05dKTsKCQlmcHJpbnRmKElPVVQsICAgIiU0ZCU3LmZcbiIsIElaWVJbTl0sIFpNVUxUW05dKTsKCQlJWllSW05dID0gSVpZUltOXSAtIElOSVRZUjsKCQlpZiAoSVpZUltOXSA8IDAgfHwgSVpZUltOXSA+PSBtZC5JWUVBUikgewoJCQlmcHJpbnRmKHN0ZGVyciwgIlNpZ2h0IHllYXIgb3V0IG9mIHJhbmdlXG4iKTsKCQkJcmV0ID0gMTsKCQkJZ290byBleGl0OwoJCX0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgkJaWYgKFpNVUxUW05dIDw9IDAuMCkgewoJCQlmcHJpbnRmKHN0ZGVyciwgIkVSUk9SOiBNdWx0aXBsaWVyIG5vdCBwb3NpdGl2ZVxuIik7CgkJCXJldCA9IDE7CgkJCWdvdG8gZXhpdDsKCQl9Cgl9CglmcHJpbnRmKElPVVQsIlxuIik7Ci8qIEJvdW5kIHRoZSByYW5nZSBmb3IgdGhlIGludGVncmF0aW9uIG92ZXIgSyAqLwoKCW1kLlJLSEkgPSAxLjBFNzsKCW1kLlJLTE8gPSAwLjA7CglJUyA9IDA7IC8qIG9yaWduYWwgbm90IGluaXRpYWxpemVkIGJ1Zz8gKi8KCi8qICoqKioqKiBSdW4gdGhlIENMQSB0byBvYnRhaW4gdGhlIG5vbWluYWwgY2F0Y2ggbGltaXQgKi8KCVJBV0NMID0gQ0xJTUlUKENBVENILCBTSUdIVCwgRk1BVFJYLCBJU1lSLCBJWllSLCBaTVVMVCwgUE9QLCBHKTsKLyogU2V0IHRoZSBjYXRjaCBsaW1pdHMgZm9yIFBDWUNMRSB5ZWFycy4gSWYgdGhlIGNhdGNoIGxpbWl0IG1heSBiZSAqLwovKiBzdWJqZWN0IHRvIHBoYXNlb3V0LCBjYWxsIFBPVVQgdG8gYXBwbHkgdGhlIHBoYXNlb3V0IHJ1bGUuICovCgovKiBGaXJzdCBzZXQgSUxBU1QgPSB5ZWFyIG9mIHRoZSBtb3N0IHJlY2VudCBhYnVuZGFuY2UgZXN0aW1hdGUgKi8KCglpZiAobWQuTlMgPiAwKSBJTEFTVCA9IElTWVJbbWQuTlMgLSAxXTsKCWlmIChtZC5OWiA+IDApIElMQVNUID0gKElTID4gSVpZUlttZC5OWiAtIDFdKT8gSVM6IElaWVJbbWQuTlogLSAxXTsKCglmb3IgKElZID0gbWQuSVlFQVI7IElZIDw9IG1kLklZRUFSICsgbXAuUENZQ0xFIC0gMTsgSVkrKykgewoJCWlmIChQT1VUID09IDEpIHsKCQkJUEhPVVQoJkNMLCBSQVdDTCwgSUxBU1QsIElZKTsKCQl9IGVsc2UgewoJCQlDTCA9IFJBV0NMOwoJCX0KCQlmcHJpbnRmKElPVVQsICAgIlllYXI6ICU0ZCAgICAgQ2F0Y2ggbGltaXQ6JTZkXG4iLCBJWSArIElOSVRZUiwgKGludCkoQ0wgKyAwLjUpKTsKCgl9CgpleGl0OgoJcmV0dXJuIHJldDsKfQoKLyoKQyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpDCkMJQ0xDIHZlcnNpb24gNgpDCkMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQwpDCTMxIEphbnVhcnkgMTk5NApDCkMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKKi8KLyoKCVNVQlJPVVRJTkUgUEhPVVQgKENMLCBSQVdDTCwgSUxBU1QsIElZKQoqLwp2b2lkIFBIT1VUKGRvdWJsZSAqQ0wsIGRvdWJsZSBSQVdDTCwgaW50IElMQVNULCBpbnQgSVkpCnsKLyoKCVBIQVNFVCBOdW1iZXIgb2YgeWVhcnMgd2l0aG91dCBzdXJ2ZXlzIGJlZm9yZSBwaGFzZW91dCBpbnZva2VkCglQSEFTRVAgUGhhc2VvdXQgYW5udWFsIHJlZHVjdGlvbiBwcm9wb3J0aW9uCglQaGFzZW91dDogUmVkdWNlIGNhdGNoIGxpbWl0IGlmIHRoZXJlIGlzIG5vIHN1cnZleSBkYXRhIGluIHRoZQoJbGFzdCBQSEFTRVQgeWVhcnMKKi8KCWlmIChJWSA+PSBJTEFTVCArIG1wLlBIQVNFVCkgewoJCSpDTCA9IFJBV0NMICogKDEuMCAtIG1wLlBIQVNFUCAqIChJWSAtIElMQVNUIC0gbXAuUEhBU0VUKSk7CgkJaWYgKCpDTCA8IDAuMCkgKkNMID0gMC4wOwoJfSBlbHNlIHsKCQkqQ0wgPSBSQVdDTDsKCX0KCS8qIFJFVFVSTgoJICAgRU5EICovCn0KCi8qCglSRUFMIEZVTkNUSU9OIENMSU1JVCAoQ0FUQ0gsU0lHSFQsRk1BVFJYLElTWVIsSVpZUixaTVVMVCxQT1AsRykKCVJ1biB0aGUgQ0xBIHRvIG9idGFpbiB0byBub21pbmFsIGNhdGNoIGxpbWl0CiovCmRvdWJsZSBDTElNSVQoZG91YmxlICpDQVRDSCwgZG91YmxlICpTSUdIVCwgZG91YmxlICpGTUFUUlgsIGludCAqSVNZUiwgaW50ICpJWllSLCBkb3VibGUgKlpNVUxULGRvdWJsZSAqUE9QLCBkb3VibGUgKkcpCnsKCWRvdWJsZSBTRiwgU1MwLCBTUzEsIFNTMiwgU1MzOwoJZG91YmxlIFlbTUFYU1RQICsgMV0sIEJbTUFYU1RQICsgMV0sIFJMR0JbTUFYU1RQICsgMV07Cglkb3VibGUgKlBSRVMgPSBOVUxMLCAqUVJFUyA9IE5VTEw7CgoJaW50IE5CLCBOUjsKCWRvdWJsZSBCSU5DLCBZSU5DLCBESywgUiwgUkssIEQsIERELCBQLCBRLCBQVE9UOwoJaW50IEksIEosIE4sIE4yOwoKCWRvdWJsZSBfQ0xJTUlUID0gMC4wOwoJaWYgKG1kLk5TIDw9IDApIHJldHVybiBfQ0xJTUlUOwoKCVBSRVMgPSAoZG91YmxlICopIG1hbGxvYyhzaXplb2YoZG91YmxlKSAqIChNQVhTSU0gKyAxKSk7CglpZiAoUFJFUyA9PSBOVUxMKSB7CgkJZnByaW50ZihzdGRlcnIsICJDYW4ndCBBbGxvY2F0ZSBtZW1vcnkgKFBSRVMpXG4iKTsKCQlnb3RvIGVycl9leGl0OwoJfQoJbWVtc2V0KFBSRVMsIDAsIHNpemVvZihkb3VibGUpICogKE1BWFNUUCArIDEpKTsKCglRUkVTID0gKGRvdWJsZSAqKSBtYWxsb2Moc2l6ZW9mKGRvdWJsZSkgKiAoTUFYU0lNICsgMSkpOwoJaWYgKFFSRVMgPT0gTlVMTCkgewoJCWZwcmludGYoc3RkZXJyLCAiQ2FuJ3QgQWxsb2NhdGUgbWVtb3J5IChRUkVTKVxuIik7CgkJZ290byBlcnJfZXhpdDsKCX0KCW1lbXNldChRUkVTLCAwLCBzaXplb2YoZG91YmxlKSAqIChNQVhTVFAgKyAxKSk7CgoJU0YgPSAwLjUgLyAobXAuUFNDQUxFICogbXAuUFNDQUxFKTsKCgkvKiBDaGVjayB0aGUgc2l6ZXMgb2YgdGhlIFkgYW5kIEIgYXJyYXlzIGFyZSBsYXJnZSBlbm91Z2ggKi8KCWlmIChtcC5QTkJTVFAgPiBNQVhTVFAgfHwgbXAuUE5ZU1RQID4gTUFYU1RQKSB7CgkJZnByaW50ZihzdGRlcnIsICJZICYvb3IgYiBhcnJheSBzaXplcyB0b28gc21hbGxcbiIpOwoJCWdvdG8gZXJyX2V4aXQ7Cgl9CgkvKiBTZXQgc2lnaHRpbmdzIGJpYXMgc3RlcCBzaXplcyAmIHRoZWlyIGxvZyB2YWx1ZXMuIEJJTkMgPSBCaWFzIGluY3JlbWVudCAqLwoJTkIgPSAoaW50KW1wLlBOQlNUUDsKCUJJTkMgPSAobXAuUEJNQVggLSBtcC5QQk1JTikgLyBOQjsKCWZvciAoSSA9IDA7IEkgPD0gTkIgLSAxOyBJKyspIHsKICAgICAgICAqKEIgKyBJKSA9IG1wLlBCTUlOICsgKEkgKyAwLjUpICogQklOQzsKICAgICAgICAqKFJMR0IgKyBJKSA9IC1sb2coKihCICsgSSkpOwoJfQoKCS8qIFNldCBwcm9kdWN0aXZpdHkgcGFyYW1ldGVyIHN0ZXAgc2l6ZXMgKG1pZHBvaW50cykgKi8KCU5SID0gKGludCltcC5QTllTVFA7CglZSU5DID0gbXAuUFlNQVggLyBOUjsKCWZvciAoSSA9IDA7IEkgPD0gTlIgLSAxOyBJKyspIHsKCQkqKFkgKyBJKSA9IChJICsgMC41KSAqIFlJTkM7Cgl9CgoJUFRPVCA9IDA7CglOID0gMDsKCWZvciAoSSA9IDA7IEkgPD0gTlIgLSAxOyBJKyspIHsKCQkvKiBTZXQgUiBmcm9tIHRoZSBwcm9kdWN0aXZpdHkgcGFyYW1ldGVyLCBZICovCgkJUiA9IDEuNDE4NCAqICooWSArIEkpOwoKCQkvKiBTdGVwIHNpemUgZm9yIEsgKi8KICAgICAgICBESyA9IG1wLlBLU1RFUDsKICAgICAgICBEID0gMS4wOwogICAgICAgIFJLID0gbWQuUktISTsKCgkJLyogVXNlIGZ1bmN0aW9uIFNUS1NJTSB0byBzZXQgdXAgdGhlIE50aCBwb3B1bGF0aW9uIHRyYWplY3RvcnkgKi8KCQkvKiBpLmUuIHNldCB1cCB0aGUgcG9wIGFycmF5ICovCgoJCXdoaWxlICgxKSB7CgkJCWlmICgoUksgPD0gbWQuUktMTykgfHwgKFNUS1NJTShSSywgUiwgUE9QLCBDQVRDSCkgPD0gMC4wKSkgYnJlYWs7CgkJCWlmIChOID49IE1BWFNJTSkgewoJCQkJZnByaW50ZihzdGRlcnIsICJFUlJPUjogVE9PIE1BTlkgU0lNVUxBVElPTlMiKTsKCQkJCWdvdG8gZXJyX2V4aXQ7CgkJCX0KCQkJLyogSG93IG11Y2ggZGVwbGV0aW9uIGNvdmVyZWQ/ICovCgkJCUREID0gRCAtIFBPUFttZC5JWUVBUl0gLyBSSzsKCQkJRCA9IFBPUFttZC5JWUVBUl0gLyBSSzsKCQkJUCA9IDAuMDsKCgkJCWlmIChERCA+IDAuMCkgewoJCQkJLyogQ29tcHV0ZSB0aGUgaW50ZXJuYWwgY2F0Y2ggbGltaXQgY29ycmVzcG9uZGluZyB0byBEIGFuZCBZKEkpICovCgkJCQlRUkVTW05dID0gQ09OVFJMKEQsIFlbSV0sIG1wLlBMRVZFTCwgbXAuUFNMT1BFKSAqIFBPUFttZC5JWUVBUl07CgoJCQkJLyogQ2FsY3VsYXRlIGRldmlhbmNlICovCiAgICAgICAgICAgIAlERVZJQU4oJlNTMCwgJlNTMSwgJlNTMiwgJlNTMywgU0lHSFQsIEZNQVRSWCwgSVNZUixJWllSLCBaTVVMVCwgUE9QLCBHKTsKCgkJCQkvKiBTY2FsZSBsaWtlbGlob29kIGFuZCBpbnRlZ3JhdGUgb3ZlciB2YWx1ZXMgZm9yIHRoZSBiaWFzIHBhcmFtZXRlciAqLwoJCQkJZm9yIChKID0gMDsgSiA8PSBOQiAtIDE7IEorKykgewoJCQkJCVAgPSBQICsgZXhwKC1TRiAqIChTUzAgKyAqKFJMR0IgKyBKKSAqIChTUzEgKyAqKFJMR0IgKyBKKSAqIFNTMikgKyBTUzMgKiAqKEIgKyBKKSkpOwoJCQkJfQoKCQkJCS8qIENhbGN1bGF0ZSB0aGUgd2VpZ2h0IGZvciB0aGlzIHBvaW50ICgmIHRvdGFsIGFyZWEgdW5kZXIgbGlrZWxpaG9vZCkgKi8KCQkJCVBSRVNbTl0gPSBQICogREQ7CgkJCQlQVE9UID0gUFRPVCArIFBSRVNbTl07CgoJCQkJLyogVXBkYXRlIGNvdW50ZXIgKi8KCQkJCU4gPSBOICsgMTsKCgkJCQkvKiBGaW5kIHRoZSBuZXh0IEsgKi8KCQkJCURLID0gREsgKiBtcC5QRFNURVAgLyBERDsKCQkJCWlmIChESyA+IG1wLlBLU1RFUCkgREsgPSBtcC5QS1NURVA7CgoJCQl9IGVsc2UgewoJCQkJREsgPSBtcC5QS1NURVA7CgkJCX0KCQkJLyogU2V0IHRoZSBuZXcgdmFsdWUgb2YgSyAqLwoJCQlSSyA9IFJLIC8gKDEuMCArIERLKTsKCQl9Cgl9CglpZiAoUFRPVCA8IDAuMCkgewoJCWZwcmludGYoc3RkZXJyLCJFUlJPUjogUFJPQiBJTlRFR1JBVEVTIFRPIFpFUk8iKTsKCQlnb3RvIGVycl9leGl0OwoJfQoKCS8qIFNvcnQgdGhlIFFSRVMgYW5kIFBSRVMgYXJyYXlzIGluIGFzY2VuZGluZyBvcmRlciBvZiBRUkVTICovCglOMiA9IE47CglTT1JUKFFSRVMsIFBSRVMsIE4yKTsKCgkvKiBOb3JtYWxpemUgdGhlIHJlbGF0aXZlIGxpa2VsaWhvb2RzICovCglmb3IgKEkgPSAwOyBJIDw9IE4gLSAxOyBJKyspIHsKCQlQUkVTW0ldID0gUFJFU1tJXSAvIFBUT1Q7Cgl9CgoJLyogRXh0cmFjdCB0aGUgZGVzaXJlZCBwcm9iYWJpbGl0eSBsZXZlbDogdGhlIG5vbWluYWwgY2F0Y2ggbGltaXQgKE5DTCkgKi8KCS8qIGlzIHRoZSBsb3dlciBQUk9CJSBvZiB0aGUgZGlzdHJpYnV0aW9uLiAqLwoJLyogRmlyc3QgY2FsY3VsYXRlIFBSRVMoSSksIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBOQ0wgaXMgYmV0d2VlbiAqLwoJLyogUVJFUyhJKSAmIFFSRVMoSSArIDEpLiAqLwoKCVAgPSAwOwoJZm9yIChJID0gMDsgSSA8PSBOIC0gMTsgSSsrKSB7CgkJUCA9IFAgKyBQUkVTW0ldOwoJCWlmIChQID4gbXAuUFBST0IpIGJyZWFrOwoJfQoKCS8qIEludGVycG9sYXRlIHRvIHNldCB0aGUgbm9taW5hbCBjYXRjaCBsaW1pdCAqLwoJaWYgIChJID49IE4gLSAxKSB7CiAgICAgICAgUSA9IFFSRVNbTiAtIDFdOwoJfSBlbHNlIHsKICAgICAgICBRID0gKFFSRVNbSSArIDFdICogKG1wLlBQUk9CIC0gUCArIFBSRVNbSV0pICsgUVJFU1tJXSAqIChQIC0gbXAuUFBST0IpKSAvIFBSRVNbSV07Cgl9CgoJX0NMSU1JVCA9IFE7CgoJaWYgKFFSRVMgIT0gTlVMTCkgZnJlZShRUkVTKTsKCWlmIChQUkVTICE9IE5VTEwpIGZyZWUoUFJFUyk7CglyZXR1cm4gX0NMSU1JVDsKCmVycl9leGl0OgoJaWYgKFFSRVMgIT0gTlVMTCkgZnJlZShRUkVTKTsKCWlmIChQUkVTICE9IE5VTEwpIGZyZWUoUFJFUyk7CglleGl0KDEpOwoJcmV0dXJuIDAuMDsgLyogbm90IHJlYWNoZWQgKi8KfQoKLyoKCUZVTkNUSU9OIENPTlRSTCAoRCwgWSwgUExFVkVMLCBQU0xPUEUpCglDYXRjaCBjb250cm9sIGxhdwoqLwpkb3VibGUgQ09OVFJMKGRvdWJsZSBELCBkb3VibGUgWSwgZG91YmxlIFBMRVZFTCwgZG91YmxlIFBTTE9QRSkKewoJZG91YmxlIHJldDsKCWlmIChEIDwgUExFVkVMKSB7CgkJcmV0ID0gMC4wOwoJfSBlbHNlIGlmIChEIDwgMS4wKSB7CgkJcmV0ID0gUFNMT1BFICogWSAqIChEIC0gUExFVkVMKTsKCX0gZWxzZSB7CgkJcmV0ID0gUFNMT1BFICogWSAqICgxLjAgLSBQTEVWRUwpOwoJfQoJcmV0dXJuIHJldDsKCS8qIEVORCAqLwp9CgovKgoJU1VCUk9VVElORSBERVZJQU4gKFNTMCwgU1MxLCBTUzIsIFNTMywgU0lHSFQsIEZNQVRSWCwgSVNZUiwKCUNhbGN1bGF0ZSBkZXZpYW5jZSAoLTIgbG9nIGxpa2VsaWhvb2QpIGluIHRlcm1zIG9mIGNvZWZmaWNpZW50cyBmb3IgCgl0aGUgYmlhcyBhbmQgbG9nIGJpYXMgcGFyYW1ldGVycwoqLwp2b2lkIERFVklBTihkb3VibGUgKlNTMCwgZG91YmxlICpTUzEsIGRvdWJsZSAqU1MyLCBkb3VibGUgKlNTMywgZG91YmxlICpTSUdIVCwKICAgICAgICAgICAgZG91YmxlICpGTUFUUlgsIGludCAqSVNZUiwgaW50ICpJWllSLCBkb3VibGUgKlpNVUxULCBkb3VibGUgKlBPUCwgZG91YmxlICpHKQp7CglpbnQgTiwgSiwgSzsKCgkqU1MwID0gMC4wOwoJKlNTMSA9IDAuMDsKCSpTUzIgPSAwLjA7CgkqU1MzID0gMC4wOwoKCWZvciAoTiA9IDA7IE4gPD0gbWQuTlMgLSAxOyBOKyspIHsgCgoJCSooRyArIE4pID0gbG9nKCooU0lHSFQgKyBOKSAvICooUE9QKyooSVNZUiArIE4pKSk7CgkJSyA9IE4gKiAoTiArIDEpIC8gMjsKCgkJZm9yIChKID0gMDsgSiA8PSBOIC0gMTsgSisrKSB7CgkJCS8qMXN0IGFkZCBub24gZGlhZ29uYWwgY29udHJpYnV0aW9ucyAod2hpY2ggYXJlIGRvdWJsZWQgdXApKi8KCQkJKlNTMCA9ICpTUzAgKyAyLjAgKiAqKEcgKyBKKSAqICooRyArIE4pICogKihGTUFUUlggKyBLKTsKCQkJKlNTMSA9ICpTUzEgKyAyLjAgKiAoKihHICsgSikgKyAqKEcgKyBOKSkgKiAqKEZNQVRSWCArIEspOwoJCQkqU1MyID0gKlNTMiArICooRk1BVFJYICsgSykgKyAqKEZNQVRSWCArIEspOwoJCQlLID0gSyArIDE7CgkJfQoKCQkvKiBOb3cgYWRkIGRpYWdub2FsIGNvbnRyaWJ1dGlvbiAqLwogICAgICAgICpTUzAgPSAqU1MwICsgKihHICsgTikgKiAqKEcgKyBOKSAqICooRk1BVFJYICsgSyk7CiAgICAgICAgKlNTMSA9ICpTUzEgKyAyLjAgKiAqKEcgKyBOKSAqICooRk1BVFJYICsgSyk7CiAgICAgICAgKlNTMiA9ICpTUzIgKyAqKEZNQVRSWCArIEspOwoKCX0KCgkvKiBOb3cgZG8gdGhlIHplcm8gZXN0aW1hdGVzICovCglmb3IgKE4gPTA7IE4gPD0gbWQuTlogLSAxOyBOKyspIHsKCQkqU1MzID0gKlNTMyArIDIuMCAqICooUE9QICsgKihJWllSICsgTikpIC8gKihaTVVMVCArIE4pOwogCX0KCglyZXR1cm47Cn0KLyoKCUZVTkNUSU9OIFNUS1NJTSAoUkssIFIsIFBPUCwgQ0FUQ0gpCglDYWxjdWxhdGUgdGhlIHN0b2NrIHRyYWplY3Rvcnkgd2l0aCBwYXJhbWV0ZXIgUksgYW5kIFI6IHJldHVybgoJdGhlIGN1cnJlbnQgc3RvY2sgc2l6ZQoJUksgPSBub3Rpb25hbCBjYXJyeWluZyBjYXBhY2l0eTsgUiA9IHByb2R1Y3Rpdml0eSBwYXJhbWV0ZXIgKiAxLjQxODQgCiovCmRvdWJsZSBTVEtTSU0oZG91YmxlIFJLLCBkb3VibGUgUiwgZG91YmxlICpQT1AsIGRvdWJsZSAqQ0FUQ0gpCnsKCWludCBJOwoJZG91YmxlIEQ7CgkqKFBPUCttZC5JU1RBUlQpID0gUks7Cglmb3IgKEkgPSBtZC5JU1RBUlQgKyAxOyBJIDw9IG1kLklZRUFSOyBJKyspIHsKCQlEID0gKihQT1AgKyBJIC0gMSkgLyBSSzsKCQkqKFBPUCArIEkpID0gKihQT1AgKyBJIC0gMSkgKiAoMS4wICsgUiAqICgxLjAgLSBEICogRCkpIC0gKihDQVRDSCArIEkgLTEpOwoJCWlmICgqKFBPUCArIEkpIDw9IDApIHsKCQkJcmV0dXJuIDAuMDsKCQl9Cgl9CgoJcmV0dXJuICooUE9QICsgbWQuSVlFQVIpOwp9Ci8qIAoJU1VCUk9VVElORSBTT1JUIChBUlJBWSwgQVJSQVkyLCBOKQoJU09SVCBzb3J0cyBhIHBhaXIgb2YgYXJyYXlzIGluIGFzY2VuZGluZyBvcmRlciBvZiB0aGUgZmlyc3QgYXJyYXkKICAgKHVzaW5nIHRoZSBoZWFwc29ydCBhbGdvcml0aG0pCiovCnZvaWQgU09SVChkb3VibGUgKkFSUkFZLCBkb3VibGUgKkFSUkFZMiwgaW50IE4pCnsKCWRvdWJsZSAvKkFSUkFZKDA6KiksIEFSUkFZMigwOiopLCovIFRFTVAsIFRFTVAyOwoJaW50ICAvKk4sKi8gSywgSVIsIEksIEo7CglpZiAoTiA8IDIpIHJldHVybjsKCUsgPSBOIC8gMjsKCUlSID0gTiAtIDE7Cgl3aGlsZSAoMSkgeyAvKjEwKi8KCQlpZiAoSyAhPSAwKSB7CgkJCUsgPSBLIC0gMTsKCQkJVEVNUCA9ICooQVJSQVkgKyBLKTsKCQkJVEVNUDIgPSAqKEFSUkFZMiArIEspOwoJCX0gZWxzZSB7CgkJCVRFTVAgPSAqKEFSUkFZICsgSVIpOwoJCQlURU1QMiA9ICooQVJSQVkyICsgSVIpOwoJCQkqKEFSUkFZICsgSVIpID0gKkFSUkFZOwoJCQkqKEFSUkFZMiArIElSKSA9ICpBUlJBWTI7CgkJCUlSID0gSVIgLSAxOwoJCQlpZiAoSVIgPT0gMCkgewoJCQkJKkFSUkFZID0gVEVNUDsKCQkJCSpBUlJBWTIgPSBURU1QMjsKCQkJCXJldHVybjsKCQkJfQoJCX0KCQlJID0gSzsKCQlKID0gSyArIEsgKyAxOwoJCXdoaWxlICgxKSB7LyoyMCovCgkJCWlmIChKID4gSVIpIGJyZWFrOwoJCQlpZiAoKEogPCBJUikgJiYgKCooQVJSQVkgKyBKKSA8ICooQVJSQVkrIEogKyAxKSkpIEogPSBKICsgMTsKCQkJaWYgKFRFTVAgPCAqKEFSUkFZICsgSikpIHsKCQkJCSooQVJSQVkgKyBJKSA9ICooQVJSQVkgKyBKKTsKCQkJCSooQVJSQVkyICsgSSkgPSAqKEFSUkFZMiArIEopOwoJCQkJSSA9IEo7CgkJCQlKID0gSiArIEkgKyAxOwoJCQl9IGVsc2UgewoJCQkJSiA9IElSICsgMTsKCQkJfQoJCX0gLypHT1RPIDIwKi8KCQkqKEFSUkFZICsgSSkgPSBURU1QOwoJCSooQVJSQVkyICsgSSkgPSBURU1QMjsKCX0vKkdPVE8gMTAqLwoJLypFTkQqLwp9CmludCBfZ2V0bGluZShjaGFyICpidWZmLCBzaXplX3Qgc2l6ZSwgRklMRSAqZnApewoJY2hhciAqcmV0OwoJcmV0ID0gZmdldHMoYnVmZiwgc2l6ZSwgZnApOwoJaWYgKHJldCAhPSBOVUxMKSB7CgkJaWYgKGJ1ZmZbc3RybGVuKGJ1ZmYpIC0gMV0gPT0gJ1xuJykKCQkJYnVmZltzdHJsZW4oYnVmZikgLSAxXSA9IDA7CgkJaWYgKGJ1ZmZbc3RybGVuKGJ1ZmYpIC0gMV0gPT0gJ1xyJykKCQkJYnVmZltzdHJsZW4oYnVmZikgLSAxXSA9IDA7Cgl9CglyZXR1cm4gKHJldCAhPSBOVUxMKTsKfQo=