The Haunted DAG & The Causal Terror
Key Idea: Selection Processes Can Create Correlations
- Observation: The most newsworthy studies often
appear to be the least trustworthy.
- Hypothesis: This pattern arises not because of a
true relationship, but due to the act of
selection.
Example: Grant Review and Selection Bias
- Suppose:
- 200 grant proposals are evaluated.
- Two criteria are assessed: Newsworthiness (nw) and
Trustworthiness (tw).
- Both criteria are uncorrelated in the
population.
- The top 10% of combined scores (\(nw +
tw\)) are selected for funding.
Question:
- After selection, are nw and tw
still uncorrelated?
Simulation: How Selection Creates Correlation

Results:
Before Selection:
- No correlation between nw and tw.
- Regression line is flat.
After Selection:
- Correlation appears among selected proposals.
- Selection favors high combined scores (\(nw + tw\)).
Distortion:
- The selection process creates an artificial correlation.
Why Does This Happen?
This phenomenon, known as Berkson’s Paradox or the
Selection-Distortion Effect, occurs because: -
Selection conditions on the sum (\(nw +
tw\)), introducing dependence between nw and
tw.
Broader Implications:
- Everywhere in Life: Restaurants with bad food in
good locations (and vice versa) are examples of
selection-distortion.
- In Regression Models: Adding predictors can induce
statistical selection, a form of collider bias. This bias can mislead us
into believing relationships exist where they do not.
Key Takeaways:
- Selection Can Create Illusory Correlations: Simply
combining unrelated factors can produce spurious relationships.
- Regression Models Are Susceptible: Adding
predictors can induce collider bias, especially when conditioning on a
variable.
This example highlights why understanding causal structures and
conditioning effects is critical for responsible regression
modeling.
Multicollinearity
Key Idea: Challenges of Multiple Predictors
- Context: Many potential predictor variables may be
available, e.g., 7 predictors in the primate milk data.
- Problem: Including all predictors may lead to
issues like multicollinearity.
- Multicollinearity:
- A strong association between two or more predictors (conditional on
other variables).
- Leads to uncertainty in parameter estimates, even if all predictors
are strongly associated with the outcome.
- Not a problem for prediction but can hinder interpretability.
Example: Predicting Height Using Leg Length
Simulation: Height vs. Left and Right Leg Length
# Simulated data
N <- 100 # number of individuals
set.seed(909)
height <- rnorm(N,10,2) # sim total height of each
leg_prop <- runif(N,0.4,0.5) # leg as proportion of height
leg_left <- leg_prop*height + rnorm( N , 0 , 0.02 ) # left leg + error
leg_right <- leg_prop*height + rnorm( N , 0 , 0.02 ) # right leg + error
# Combine into data frame
d <- data.frame(height, leg_left, leg_right)
Model: Using Both Legs as Predictors
plot(precis(m6.1))

Observations
- Both legs have almost identical lengths and are strongly associated
with height.
Key Question:
- What is the value of knowing one leg’s length after knowing the
other leg’s length?
Result:
- The posterior distribution for coefficients \(\beta_l\) (left leg) and \(\beta_r\) (right leg) shows:
- A high correlation between \(\beta_l\) and \(\beta_r\), forming a narrow ridge of
plausible values.
- The model cannot disentangle the contributions of each leg.
Visualizing the Posterior
# Sample from the posterior
post <- extract.samples(m6.1)
# Add transparency and color
rangi2 <- rgb(0.2, 0.4, 0.8, alpha = 1) # Blue color
col_alpha <- function(color, alpha) adjustcolor(color, alpha.f = alpha)
# Set up side-by-side plots
par(mfrow = c(1, 2)) # 1 row, 2 columns
# Left Panel: Scatter plot of bl vs br
plot(post$bl, post$br, col = col_alpha(rangi2, 0.5), pch = 16,
xlab = "Left leg coefficient (bl)",
ylab = "Right leg coefficient (br)",
main = "Scatter: bl vs br")
# Right Panel: Density plot of bl + br
bl_br_sum <- post$bl + post$br
plot(density(bl_br_sum), col = "blue", lwd = 2,
main = "Density: bl + br",
xlab = "Sum of bl and br",
ylab = "Density",
type = "l") # Only line plot

- The left plot shows the narrow ridge of plausible values for \(\beta_l\) and \(\beta_r\).
- The right plot shows the posterior distribution for their sum (\(\beta_l + \beta_r\)), which the model
reliably estimates.
What has happened here is that since both leg variables contain
almost exactly the same information, if you insist on including both in
a model, then there will be a practically infinite number of
combinations of bl and br that produce the same predictions.
One way to think of this phenomenon is that you have approximated
this model:
\[y_i \sim
\mathcal{N}(\mu_i,\,\sigma)\] \[\mu_i
= \alpha + \beta_1 \times \text{Leg Length}_i + \beta_2 \times \text{Leg
Length}_i\] \[\mu_i = \alpha +
(\beta_1 + \beta_2) \times \text{Leg Length}_i\]
The parameters β1 and β2 cannot be pulled apart, because they never
separately influence the mean µ. Only their sum, β1+β2,influences µ. So
this means the posterior distribution ends up reporting the very large
range of combinations of β1 and β2 that make their sum close to the
actual association of x with y.
And the posterior distribution in this simulated example has done
exactly that: It has produced a good estimate of the sum of bl and br.
But it has done so at the expense of producing a very wide range of
plausible values for bl and br separately. This is the essence of
multicollinearity. It is not a problem with the model. It is a problem
with the question. The model is answering the question you asked, but
the question is not what you thought it was.
Simpler Model: One Leg as Predictor
m6.2 <- quap(
alist(
height ~ dnorm( mu , sigma ) ,
mu <- a + bl*leg_left,
a ~ dnorm( 10 , 100 ) ,
bl ~ dnorm( 2 , 10 ) ,
sigma ~ dexp( 1 )
) ,
data=d )
precis(m6.2)
- Using only one leg results in stable posterior estimates, avoiding
multicollinearity.
Multicollinearity in Primate Milk Data: Standardizing Variables
Key Points:
- Multicollinearity: Occurs when predictors in a
regression model are highly correlated, impacting the reliability of the
model.
- Standardizing Variables: A common technique to
address multicollinearity by transforming variables to have a mean of
zero and a standard deviation of one.
Why It Matters:
- Multicollinearity can obscure the true relationships between
variables, leading to misleading conclusions.
- Standardizing variables helps to mitigate the effects of
multicollinearity, making the model more reliable and
interpretable.
Example:
- In the context of primate milk data, standardizing variables can
help to better understand the relationships between different predictors
and the outcome variable.
Steps to Standardize Variables:
- Calculate the Mean and Standard Deviation: For each
predictor variable.
- Transform the Variables: Subtract the mean and
divide by the standard deviation for each value in the predictor
variable.
data(milk)
d <- milk
d$K <- standardize( d$kcal.per.g )
d$F <- standardize( d$perc.fat )
d$L <- standardize( d$perc.lactose )
Models: Using One Predictor
#kcal.per.g regressedonperc.fat
m6.3<-quap(
alist(
K~dnorm(mu,sigma),
mu<-a+bF*F,
a~dnorm(0,0.2),
bF~ dnorm(0,0.5),
sigma~dexp(1)
),
data=d)
#kcal.per.g regressedonperc.lactose
m6.4<-quap(
alist(
K~dnorm(mu,sigma),
mu<-a+bL*L,
a~dnorm(0,0.2),
bL~ dnorm(0,0.5),
sigma~dexp(1)
),data=d)
precis(m6.3)
precis(m6.4)
- Both predictors are strongly associated with energy content in
separate models.
- The posterior distributions for bF and bL are essentially mirror
images of one another.
- Given the strong association of each predictor with outcome, we
might conclude that both are important. The more fat the more calorie
content, and the more lactose the less calorie content.
What happens when we fit a model with both predictors?
Model: Using Both Predictors
#kcal.per.g regressedonperc.fatandperc.lactose
m6.5<-quap(
alist(
K~dnorm(mu,sigma),
mu<-a+bF*F+bL*L,
a~dnorm(0,0.2),
bF~ dnorm(0,0.5),
bL~ dnorm(0,0.5),
sigma~dexp(1)
),data=d)
precis(m6.5)
- Including both predictors increases the posterior uncertainty for
\(\beta_F\) and \(\beta_L\), as the two variables are highly
collinear.
- The ridge-like posterior distribution indicates that the model
cannot disentangle the effects of fat and lactose on energy content. The
easiest way to see this is to use a pairs plot.
Diagnosing Multicollinearity
pairs( ~ kcal.per.g + perc.fat + perc.lactose , data=d , col=rangi2 )

- Scatterplots reveal \(\text{perc.fat}\) and \(\text{perc.lactose}\) are highly correlated
and nearly redundant.
- The strong association between predictors leads to
multicollinearity, hindering the model’s interpretability.
Dodgy Procedures for Multicollinearity
- In some fields, a common but flawed approach to handling
multicollinearity involves:
- Inspecting pairwise correlations between
predictors.
- Dropping highly correlated variables before modeling.
- Why is this a mistake?
- Pairwise correlations are not the issue; conditional
associations within the model are what matter.
- The right approach depends on the cause of the collinearity, which
requires a causal perspective.
- Example of dodginess:
- Imagine analyzing human health data and finding that “exercise” and
“calorie intake” are highly correlated.
- Dropping one might ignore important causal relationships—exercise
and calorie intake both influence weight but in different ways.
Core Tradeoff in Milk Composition
In the milk example, a natural tradeoff likely explains the
collinearity between fat and lactose:
- Frequent nursing:
- Milk tends to be watery and low in energy.
- High in sugar (lactose) to provide quick
energy.
- Infrequent nursing:
- Milk needs to be more energy-dense.
- High in fat to sustain the infant for longer
periods between feedings.
- This tradeoff suggests a causal model: nursing
frequency drives milk composition. High lactose and high fat are
inversely related because they serve different energetic
strategies.
# Define the DAG with D as latent
dag <- dagitty( "dag{
L -> K <- F
L <- D -> F
D [unobserved]
}" )
# Define coordinates for visualization
coordinates(dag) <- list(
x = c(L = 0, K = 1, D = 1, F = 2),
y = c(L = 0.5, K = 1, D = 0.5, F = 0.5)
)
plot( dag )
circle_points(c("D"), dag)

Key Takeaways
- Multicollinearity is a problem of interpretation, not
prediction.
- When predictors are highly correlated, the model struggles to
allocate effects to each predictor.
Avoid Pairwise Correlation Tests:
- It’s conditional associations, not pairwise correlations, that
matter.
Understand the Causal Model:
- Collinearity often arises from underlying causal processes.
- In the milk example, fat and lactose are linked by nursing
frequency, a latent variable.
Post-treatment Bias
Key Idea: Mistakes From Including Variables
- It’s common to worry about omitting predictor variables
(omitted variable bias).
- Less attention is given to mistakes from including
variables (included variable bias):
- Adding variables without considering causality can ruin randomized
experiments.
- Example: Post-treatment bias occurs when a
predictor is influenced by the treatment or outcome.
Example: Plant Growth Experiment
- Scenario:
- Goal: Measure the causal effect of soil treatment
on plant growth.
- Variables:
- Initial height (\(H_0\)):
Pre-treatment height.
- Final height (\(H_1\)):
Post-treatment height.
- Treatment (\(T\)): Soil
treatment.
- Fungus (\(F\)): Fungus
presence.
- Problem: Including \(F\) (fungus) induces bias because \(T \to F \to H_1\):
- Treatment influences fungus.
- Fungus influences growth (\(H_1\)).
- Controlling for \(F\) blocks the
causal path \(T \to H_1\).
Simulated Data
set.seed(1914)
N <- 100
h0 <- rnorm(N, 10, 2)
treatment <- rep(0:1, each = N/2)
fungus <- rbinom(N, size = 1, prob = 0.5 - treatment * 0.4)
h1 <- h0 + rnorm(N, 5 - 3 * fungus)
d <- data.frame(h0 = h0, h1 = h1, treatment = treatment, fungus = fungus)
precis(d)
'data.frame': 100 obs. of 4 variables:
Initial Growth Model Without Predictors
Model Definition
Goal: Model proportional growth (\(p = \frac{H_1}{H_0}\)).
Model:
- \(h_{1,i} \sim N(\mu_i,
\sigma)\)
- \(\mu_i = h_{0,i} \times p\)
- \(p \sim \text{LogNormal}(0,
0.25)\): Prior centered around no growth (\(p = 1\)).
Simulation and Fitting
# Simulate prior from model
sim_p <- rlnorm( 1e4 , 0 , 0.25 )
precis( data.frame(sim_p) )
'data.frame': 10000 obs. of 1 variables:
hist(sim_p)

So this prior expects anything from 40% shrinkage up to 50% growth.
Let’s fit this model, so you can see how it just measures the average
growth in the experiment.
# Fit the model
m6.6 <- quap(
alist(
h1 ~ dnorm( h0 * p , sigma ),
mu <- h0 * p,
p ~ dlnorm( 0 , 0.25 ),
sigma ~ dexp( 1 )
),
data = d
)
precis(m6.6)
NA
Output:
- Posterior mean for \(p\): Approximately 1.4, suggesting
40% average growth.
- Prior: Allows for 40% shrinkage to 50% growth.
Adding Treatment and Fungus
Model Definition
Extend \(p\) to depend on treatment
and fungus: - \(h_{1,i} \sim N(\mu_i,
\sigma)\) - \(\mu_i = h_{0,i} \times
p\) - \(p = a + b_t \times T_i + b_f
\times F_i\)
Priors:
- \(a \sim \text{LogNormal}(0,
0.2)\)
- \(b_t, b_f \sim N(0, 0.5)\)
- \(\sigma \sim
\text{Exponential}(1)\)
Model Fitting
The proportion of growth p is now a function of the predictor
variables. It looks like any other linear model. The priors on the
slopes are almost certainly too flat. They place 95% of the prior mass
between −1 (100% reduction) and +1 (100% increase) and two-thirds of the
prior mass between −0.5 and +0.5.
# Fit the model
m6.7<-quap(
alist(
h1~ dnorm(mu,sigma),
mu<-h0*p,
p<- a+bt*treatment+bf*fungus,
a~dlnorm(0,0.2),
bt~ dnorm(0,0.5),
bf~ dnorm(0,0.5),
sigma~dexp(1)
), data=d
)
precis(m6.7)
Output:
- Treatment effect (\(b_t\)): Close to zero, suggesting
no effect.
- Fungus effect (\(b_f\)): Negative, indicating
reduced growth due to fungus.
Why?
- Fungus is a post-treatment variable. Controlling for it blocks the
causal path \(T \rightarrow H_1\).
Blocked by consequence. The problem is that fungus
is mostly a consequence of treatment. This is to say that fungus is a
post-treatment variable. So when we control for fungus, the model is
implicitly answering the question: Once we already know whether or not a
plant developed fungus, does soil treatment matter? The answer is “no,”
because soil treatment has its effects on growth through reducing
fungus. But we actually want to know, based on the design of the
experiment, is the impact of treatment on growth. To measure this
properly, we should omit the post-treatment variable fungus. Here’s what
the inference looks like in that case.
Correct Inference: Excluding Fungus
Adjusted Model
Exclude \(F\) to correctly measure
the treatment effect: - \(p = a + b_t \times
T_i\)
Model Fitting
# Fit the model
m6.8<-quap(
alist(
h1~ dnorm(mu,sigma),
mu<-h0*p,
p<- a+bt*treatment,
a~dlnorm(0,0.2),
bt~ dnorm(0,0.5),
sigma~dexp(1)
), data=d
)
precis(m6.8)
Output:
- Treatment effect (\(b_t\)): Positive, as
expected.
- Excluding fungus reveals the true effect of treatment on
growth.
Now the impact of treatment is clearly positive, as it should be. It
makes sense to control for pre-treatment differences, like the initial
height h0, that might mask the causal influence of treatment. But
including post-treatment variables can actually mask the treatment
itself. This doesn’t mean you don’t want the model that includes both
treatment and fungus. The fact that including fungus zeros the
coefficient for treatment suggests that the treatment works for
exactly the anticipated reasons. It tells us about the mechanism. But a
correct inference about the treatment still depends upon omitting the
post-treatment variable.
Visualizing With a DAG
Fungus and d-separation. It helps to look at this problem in terms of
a DAG. In this case, I’ll show you how to draw it using the dagitty R
package, because we are going to use that package now to do some graph
analysis.
Causal Diagram
Graph: - \(T \rightarrow F \rightarrow
H_1\) - \(H_0 \rightarrow
H_1\)
The causal diagram for this scenario is shown below:
# Define the DAG with D as latent
plant_dag <- dagitty( "dag {
H_0-> H_1
F-> H_1
T-> F
}")
coordinates( plant_dag ) <- list( x=c(H_0=0,T=2,F=1.5,H_1=1) ,
y=c(H_0=0,T=0,F=0,H_1=0)
)
drawdag( plant_dag )

NA
Key Insight:
- Conditioning on \(F\) (fungus)
blocks the path \(T \rightarrow H_1\),
making \(T\) and \(H_1\) independent.
Key Takeaways
- Post-treatment bias:
- Including variables affected by treatment can mask the treatment
effect.
- DAGs help clarify causality:
- Use causal diagrams to identify variables that should or should not
be included.
- Correct inference:
- Exclude post-treatment variables to measure causal effects
accurately.
Collider Bias
Key Idea: Selection and Collider Bias
- Selection processes can create misleading associations in
statistical models, known as collider bias.
- Collider: A variable influenced by two or more
other variables (e.g., trustworthiness and newsworthiness both affect
selection).
Example: Selection in Grant Proposals
Causal Diagram
- Trustworthiness (\(T\)) and
Newsworthiness (\(N\)) both influence
Selection (\(S\)).
- Selection (\(S\)) is a
collider.
grant_dag <- dagitty("dag {
T -> S
N -> S
}")
coordinates(grant_dag) <- list(
x = c(T = 0, N = 2, S = 1),
y = c(T = 0, N = 0, S = 0)
)
drawdag(grant_dag)

Explanation
- Conditioning on \(S\) creates a
statistical association between \(T\)
and \(N\):
- If a selected proposal has low \(T\), it must have high \(N\) to be selected (and vice versa).
- This creates a negative association between \(T\) and \(N\), even if they are uncorrelated in the
population.
Example: Aging, Happiness, and Marriage
Causal Diagram
- Happiness (\(H\)) and Age (\(A\)) both influence Marriage (\(M\)).
- \(M\) is a collider.
# Create the DAG mentioned in the paragraph above
happiness_dag <- dagitty( "dag {
A -> M
H -> M
}")
coordinates( happiness_dag ) <- list( x=c(A=0, H=2, M=1) ,
y=c(A=0, H=0, M=0)
)
drawdag( happiness_dag )

Explanation
- Conditioning on \(M\) induces a
spurious association between \(A\) and
\(H\), even if happiness is constant
across ages.
- This collider bias arises from conditioning on a
variable influenced by two other variables.
- Happiness (H) and age (A) both cause marriage (M). Marriage is
therefore a collider.
Simulating the Data
Simulation Design
- Each year, 20 individuals are born with uniformly distributed
happiness.
- Individuals age and may get married:
- Happiness does not change with age.
- Probability of marriage increases with happiness and age.
- Married individuals remain married. Individuals over 65 are removed
(They move to Spain.)
# Simulate data
d <- sim_happiness( seed=1977 , N_years=1000 )
precis(d)
'data.frame': 1300 obs. of 3 variables:
Plotting the Data
# Plot happiness vs. age, colored by marriage status
plot( d$age , d$happiness , col=d$married+1 , pch=16 ,
xlab="Age" , ylab="Happiness" )
legend( "topleft" , legend=c("Not Married","Married") , pch=16 , col=1:2 )

Observation
- Happiness is uncorrelated with age.
- Marriage is associated with both age and happiness, creating the
appearance of a relationship.
Multiple Regression: Conditioning on Marriage
Model Definition
Linear model: - \(\mu_i =
\alpha_{MID[i]} + \beta_A \times A_i\) - \(MID[i]\): Marriage status index.
Rescale age (\(A\)) for
adults (18–65): - \(A =
\frac{\text{age} - 18}{65 - 18}\)
# Rescale age
d2 <- d[ d$age>17 , ] # only adults
d2$A <- ( d2$age- 18 ) / ( 65- 18 )
Model Fitting
# Create marriage status index variable
d2$MID <- d2$married + 1
# Fit the model
m6.9 <- quap(
alist(
happiness ~ dnorm( mu , sigma ) ,
mu <- a[MID] + bA * A ,
a[MID] ~ dnorm( 0 , 1 ) ,
bA ~ dnorm( 0 , 2 ) ,
sigma ~ dexp( 1 )
) ,
data=d2
)
precis(m6.9, depth=2)
Output:
- The model suggests a negative association between age and happiness,
which is spurious due to collider bias.
- Conditioning on marriage status induces a statistical relationship
between age and happiness.
Regression Without Conditioning on Marriage
# Fit the model without marriage status
m6.10 <- quap(
alist(
happiness ~ dnorm( mu , sigma ) ,
mu <- a + bA * A ,
a ~ dnorm( 0 , 1 ) ,
bA ~ dnorm( 0 , 2 ) ,
sigma ~ dexp( 1 )
) ,
data=d2
)
precis(m6.10, depth=1)
Output:
- Without conditioning on \(M\), the
model finds no association between age and happiness, reflecting the
true causal model.
It’s easy to plead with this example. Shouldn’t marriage also
influence happiness? What if happiness does change with age? But this
misses the point. If you don’t have a causal model, you can’t make
inferences from a multiple regression. And the regression itself does
not provide the evidence you need to justify a causal model. Instead,
you need some science.
Key Takeaways
- Collider Bias:
- Conditioning on a collider creates misleading associations between
its causes.
- In the marriage example, conditioning on \(M\) induces a spurious relationship between
\(A\) and \(H\).
- DAGs Clarify Causal Relationships:
- DAGs help identify colliders and prevent incorrect variable
selection.
- Causal Inference Requires a Model:
- Without a causal model, multiple regression cannot justify
inferences.
- Practical Advice:
- Avoid conditioning on colliders to prevent spurious
associations.
Take-Home Messages
Key Lessons:
- Causal Understanding is Crucial:
- Statistical models cannot replace a thoughtful causal
framework.
- DAGs provide a way to structure and communicate assumptions.
- Selection and Collider Bias:
- Conditioning on colliders creates misleading associations.
- Examples like marriage in the happiness study or fungus in the plant
growth example demonstrate this.
- Avoid Over-Conditioning:
- Adding variables without a causal perspective can mask or distort
true relationships.
- Multicollinearity:
- Predictors with shared information can lead to wide posterior
distributions.
- Interpretability suffers, even if prediction is still
effective.
- Think Causally, Not Just Statistically:
- Regression models answer the questions you ask—ensure your question
reflects your research goals.
LS0tDQp0aXRsZTogIlN0YXRpc3RpY2FsIFJldGhpbmtpbmcgLSBDaGFwdGVyIDYiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyLCBlY2hvPUZhbHNlLCBtZXNzYWdlPUZhbHNlLCB3YXJuaW5nPVRSVUV9DQojIEltcG9ydCB0aGUgbmVjZXNzYXJ5IGxpYnJhcmllcyBmb3IgdGhlIGFuYWx5c2lzLg0KDQojIENoZWNrIGFuZCBpbnN0YWxsIG1pc3NpbmcgcGFja2FnZXMNCnJlcXVpcmVkX3BhY2thZ2VzIDwtIGMoImdncGxvdDIiLCAiZHBseXIiLCAicmV0aGlua2luZyIsICJkYWdpdHR5IikNCmZvciAocGtnIGluIHJlcXVpcmVkX3BhY2thZ2VzKSB7DQogIGlmICghcmVxdWlyZU5hbWVzcGFjZShwa2csIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcyhwa2cpDQp9DQoNCg0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMNCmxpYnJhcnkocmV0aGlua2luZykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZGFnaXR0eSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQoNCmxpYnJhcnkoaHRtbHRvb2xzKQ0KDQpgYGANCg0KDQojIyBUaGUgSGF1bnRlZCBEQUcgJiBUaGUgQ2F1c2FsIFRlcnJvcg0KDQojIyMgS2V5IElkZWE6IFNlbGVjdGlvbiBQcm9jZXNzZXMgQ2FuIENyZWF0ZSBDb3JyZWxhdGlvbnMNCi0gKipPYnNlcnZhdGlvbioqOiBUaGUgbW9zdCBuZXdzd29ydGh5IHN0dWRpZXMgb2Z0ZW4gYXBwZWFyIHRvIGJlIHRoZSBsZWFzdCB0cnVzdHdvcnRoeS4NCi0gKipIeXBvdGhlc2lzKio6IFRoaXMgcGF0dGVybiBhcmlzZXMgbm90IGJlY2F1c2Ugb2YgYSB0cnVlIHJlbGF0aW9uc2hpcCwgYnV0IGR1ZSB0byB0aGUgYWN0IG9mICoqc2VsZWN0aW9uKiouDQoNCi0tLQ0KDQojIyMgRXhhbXBsZTogR3JhbnQgUmV2aWV3IGFuZCBTZWxlY3Rpb24gQmlhcw0KLSBTdXBwb3NlOg0KICAtIDIwMCBncmFudCBwcm9wb3NhbHMgYXJlIGV2YWx1YXRlZC4NCiAgLSBUd28gY3JpdGVyaWEgYXJlIGFzc2Vzc2VkOiAqKk5ld3N3b3J0aGluZXNzIChudykqKiBhbmQgKipUcnVzdHdvcnRoaW5lc3MgKHR3KSoqLg0KICAtIEJvdGggY3JpdGVyaWEgYXJlICoqdW5jb3JyZWxhdGVkKiogaW4gdGhlIHBvcHVsYXRpb24uDQogIC0gVGhlIHRvcCAxMCUgb2YgY29tYmluZWQgc2NvcmVzIChcKG53ICsgdHdcKSkgYXJlIHNlbGVjdGVkIGZvciBmdW5kaW5nLg0KICANCiMjIyMgUXVlc3Rpb246DQotIEFmdGVyIHNlbGVjdGlvbiwgYXJlICoqbncqKiBhbmQgKip0dyoqIHN0aWxsIHVuY29ycmVsYXRlZD8NCg0KLS0tDQoNCiMjIyBTaW11bGF0aW9uOiBIb3cgU2VsZWN0aW9uIENyZWF0ZXMgQ29ycmVsYXRpb24NCg0KYGBge3IsIGVjaG89RmFsc2V9DQojIFNpbXVsYXRlZCBkYXRhDQpzZXQuc2VlZCgxOTE0KQ0KTiA8LSAyMDAgIyBOdW1iZXIgb2YgZ3JhbnQgcHJvcG9zYWxzDQpwIDwtIDAuMSAjIFByb3BvcnRpb24gdG8gc2VsZWN0DQoNCiMgVW5jb3JyZWxhdGVkIG5ld3N3b3J0aGluZXNzIGFuZCB0cnVzdHdvcnRoaW5lc3MNCm53IDwtIHJub3JtKE4pDQp0dyA8LSBybm9ybShOKQ0KDQojIFNlbGVjdCB0b3AgMTAlIG9mIGNvbWJpbmVkIHNjb3Jlcw0KcyA8LSBudyArIHR3ICMgVG90YWwgc2NvcmUNCnEgPC0gcXVhbnRpbGUocywgMSAtIHApICMgVG9wIDEwJSB0aHJlc2hvbGQNCnNlbGVjdGVkIDwtIGlmZWxzZShzID49IHEsIFRSVUUsIEZBTFNFKQ0KDQojIFNldCB1cCBzaWRlLWJ5LXNpZGUgcGxvdHMNCnBhcihtZnJvdyA9IGMoMSwgMikpICMgQXJyYW5nZSBwbG90cyBpbiAxIHJvdyBhbmQgMiBjb2x1bW5zDQoNCiMgTGVmdCBQbG90OiBBbGwgcG9pbnRzIHdpdGggcmVncmVzc2lvbiBsaW5lDQpwbG90KG53LCB0dywgY29sID0gImJsYWNrIiwgcGNoID0gMTksDQogICAgIHhsYWIgPSAiTmV3c3dvcnRoaW5lc3MgKG53KSIsIA0KICAgICB5bGFiID0gIlRydXN0d29ydGhpbmVzcyAodHcpIiwgDQogICAgIG1haW4gPSAiQWxsIFBvaW50cyIpDQpmaXRfYWxsIDwtIGxtKHR3IH4gbncpDQphYmxpbmUoZml0X2FsbCwgY29sID0gInJlZCIsIGx3ZCA9IDIpICMgUmVncmVzc2lvbiBsaW5lIGZvciBhbGwgcG9pbnRzDQoNCiMgUmlnaHQgUGxvdDogSGlnaGxpZ2h0IHNlbGVjdGVkIHBvaW50cw0KcGxvdChudywgdHcsIGNvbCA9IGlmZWxzZShzZWxlY3RlZCwgImJsdWUiLCAiYmxhY2siKSwgDQogICAgIHBjaCA9IGlmZWxzZShzZWxlY3RlZCwgMTksIDEpLCAjIEZpbGxlZCBmb3Igc2VsZWN0ZWQsIHVuZmlsbGVkIGZvciBvdGhlcnMNCiAgICAgeGxhYiA9ICJOZXdzd29ydGhpbmVzcyAobncpIiwgDQogICAgIHlsYWIgPSAiVHJ1c3R3b3J0aGluZXNzICh0dykiLCANCiAgICAgbWFpbiA9ICJTZWxlY3RlZCBQb2ludHMiKQ0KaWYgKGFueShzZWxlY3RlZCkpIHsNCiAgZml0X3NlbGVjdGVkIDwtIGxtKHR3W3NlbGVjdGVkXSB+IG53W3NlbGVjdGVkXSkNCiAgYWJsaW5lKGZpdF9zZWxlY3RlZCwgY29sID0gImJsdWUiLCBsd2QgPSAyKSAjIFJlZ3Jlc3Npb24gbGluZSBmb3Igc2VsZWN0ZWQgcG9pbnRzDQp9DQoNCiMgRGlzcGxheSBjb3JyZWxhdGlvbiBvbiB0aGUgcmlnaHQgcGxvdA0KY29ycmVsYXRpb24gPC0gY29yKHR3W3NlbGVjdGVkXSwgbndbc2VsZWN0ZWRdKQ0KbXRleHQocGFzdGUoIkNvcnJlbGF0aW9uIChzZWxlY3RlZCk6Iiwgcm91bmQoY29ycmVsYXRpb24sIDIpKSwgc2lkZSA9IDMsIGxpbmUgPSAtMS41LCBhdCA9IG1heChudykgKiAwLjkpDQoNCmBgYA0KDQojIyBSZXN1bHRzOg0KDQojIyMgQmVmb3JlIFNlbGVjdGlvbjoNCi0gTm8gY29ycmVsYXRpb24gYmV0d2VlbiBudyBhbmQgdHcuDQotIFJlZ3Jlc3Npb24gbGluZSBpcyBmbGF0Lg0KDQojIyMgQWZ0ZXIgU2VsZWN0aW9uOg0KLSBDb3JyZWxhdGlvbiBhcHBlYXJzIGFtb25nIHNlbGVjdGVkIHByb3Bvc2Fscy4NCi0gU2VsZWN0aW9uIGZhdm9ycyBoaWdoIGNvbWJpbmVkIHNjb3JlcyAoXChudyArIHR3XCkpLg0KDQojIyMgRGlzdG9ydGlvbjoNCi0gVGhlIHNlbGVjdGlvbiBwcm9jZXNzIGNyZWF0ZXMgYW4gYXJ0aWZpY2lhbCBjb3JyZWxhdGlvbi4NCg0KIyMjIFdoeSBEb2VzIFRoaXMgSGFwcGVuPw0KVGhpcyBwaGVub21lbm9uLCBrbm93biBhcyAqKkJlcmtzb27igJlzIFBhcmFkb3gqKiBvciB0aGUgKipTZWxlY3Rpb24tRGlzdG9ydGlvbiBFZmZlY3QqKiwgb2NjdXJzIGJlY2F1c2U6DQotIFNlbGVjdGlvbiBjb25kaXRpb25zIG9uIHRoZSBzdW0gKFwobncgKyB0d1wpKSwgaW50cm9kdWNpbmcgZGVwZW5kZW5jZSBiZXR3ZWVuICoqbncqKiBhbmQgKip0dyoqLg0KDQojIyMgQnJvYWRlciBJbXBsaWNhdGlvbnM6DQotICoqRXZlcnl3aGVyZSBpbiBMaWZlKio6IFJlc3RhdXJhbnRzIHdpdGggYmFkIGZvb2QgaW4gZ29vZCBsb2NhdGlvbnMgKGFuZCB2aWNlIHZlcnNhKSBhcmUgZXhhbXBsZXMgb2Ygc2VsZWN0aW9uLWRpc3RvcnRpb24uDQotICoqSW4gUmVncmVzc2lvbiBNb2RlbHMqKjogQWRkaW5nIHByZWRpY3RvcnMgY2FuIGluZHVjZSBzdGF0aXN0aWNhbCBzZWxlY3Rpb24sIGEgZm9ybSBvZiBjb2xsaWRlciBiaWFzLiBUaGlzIGJpYXMgY2FuIG1pc2xlYWQgdXMgaW50byBiZWxpZXZpbmcgcmVsYXRpb25zaGlwcyBleGlzdCB3aGVyZSB0aGV5IGRvIG5vdC4NCg0KIyMjIEtleSBUYWtlYXdheXM6DQotICoqU2VsZWN0aW9uIENhbiBDcmVhdGUgSWxsdXNvcnkgQ29ycmVsYXRpb25zKio6IFNpbXBseSBjb21iaW5pbmcgdW5yZWxhdGVkIGZhY3RvcnMgY2FuIHByb2R1Y2Ugc3B1cmlvdXMgcmVsYXRpb25zaGlwcy4NCi0gKipSZWdyZXNzaW9uIE1vZGVscyBBcmUgU3VzY2VwdGlibGUqKjogQWRkaW5nIHByZWRpY3RvcnMgY2FuIGluZHVjZSBjb2xsaWRlciBiaWFzLCBlc3BlY2lhbGx5IHdoZW4gY29uZGl0aW9uaW5nIG9uIGEgdmFyaWFibGUuDQoNClRoaXMgZXhhbXBsZSBoaWdobGlnaHRzIHdoeSB1bmRlcnN0YW5kaW5nIGNhdXNhbCBzdHJ1Y3R1cmVzIGFuZCBjb25kaXRpb25pbmcgZWZmZWN0cyBpcyBjcml0aWNhbCBmb3IgcmVzcG9uc2libGUgcmVncmVzc2lvbiBtb2RlbGluZy4NCg0KDQoNCiMjIE11bHRpY29sbGluZWFyaXR5DQoNCiMjIyBLZXkgSWRlYTogQ2hhbGxlbmdlcyBvZiBNdWx0aXBsZSBQcmVkaWN0b3JzDQotICoqQ29udGV4dCoqOiBNYW55IHBvdGVudGlhbCBwcmVkaWN0b3IgdmFyaWFibGVzIG1heSBiZSBhdmFpbGFibGUsIGUuZy4sIDcgcHJlZGljdG9ycyBpbiB0aGUgcHJpbWF0ZSBtaWxrIGRhdGEuDQotICoqUHJvYmxlbSoqOiBJbmNsdWRpbmcgYWxsIHByZWRpY3RvcnMgbWF5IGxlYWQgdG8gaXNzdWVzIGxpa2UgbXVsdGljb2xsaW5lYXJpdHkuDQotICoqTXVsdGljb2xsaW5lYXJpdHkqKjoNCiAgLSBBIHN0cm9uZyBhc3NvY2lhdGlvbiBiZXR3ZWVuIHR3byBvciBtb3JlIHByZWRpY3RvcnMgKGNvbmRpdGlvbmFsIG9uIG90aGVyIHZhcmlhYmxlcykuDQogIC0gTGVhZHMgdG8gdW5jZXJ0YWludHkgaW4gcGFyYW1ldGVyIGVzdGltYXRlcywgZXZlbiBpZiBhbGwgcHJlZGljdG9ycyBhcmUgc3Ryb25nbHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBvdXRjb21lLg0KICAtIE5vdCBhIHByb2JsZW0gZm9yIHByZWRpY3Rpb24gYnV0IGNhbiBoaW5kZXIgaW50ZXJwcmV0YWJpbGl0eS4NCg0KLS0tDQoNCiMjIyBFeGFtcGxlOiBQcmVkaWN0aW5nIEhlaWdodCBVc2luZyBMZWcgTGVuZ3RoDQoNCiMjIyMgU2ltdWxhdGlvbjogSGVpZ2h0IHZzLiBMZWZ0IGFuZCBSaWdodCBMZWcgTGVuZ3RoDQpgYGB7cn0NCiMgU2ltdWxhdGVkIGRhdGENCk4gPC0gMTAwICAjIG51bWJlciBvZiBpbmRpdmlkdWFscw0Kc2V0LnNlZWQoOTA5KQ0KaGVpZ2h0IDwtIHJub3JtKE4sMTAsMikgICMgc2ltIHRvdGFsIGhlaWdodCBvZiBlYWNoDQpsZWdfcHJvcCA8LSBydW5pZihOLDAuNCwwLjUpICAjIGxlZyBhcyBwcm9wb3J0aW9uIG9mIGhlaWdodA0KbGVnX2xlZnQgPC0gbGVnX3Byb3AqaGVpZ2h0ICsgcm5vcm0oIE4gLCAwICwgMC4wMiApICAjIGxlZnQgbGVnICsgZXJyb3INCmxlZ19yaWdodCA8LSBsZWdfcHJvcCpoZWlnaHQgKyBybm9ybSggTiAsIDAgLCAwLjAyICkgICMgcmlnaHQgbGVnICsgZXJyb3INCg0KIyBDb21iaW5lIGludG8gZGF0YSBmcmFtZQ0KZCA8LSBkYXRhLmZyYW1lKGhlaWdodCwgbGVnX2xlZnQsIGxlZ19yaWdodCkNCmBgYA0KDQoNCioqTW9kZWw6IFVzaW5nIEJvdGggTGVncyBhcyBQcmVkaWN0b3JzKioNCg0KYGBge3IsIGVjaG89RmFsc2V9DQptNi4xIDwtIHF1YXAoDQogIGFsaXN0KA0KICBoZWlnaHQgfiBkbm9ybSggbXUgLCBzaWdtYSApICwNCiAgbXUgPC0gYSArIGJsKmxlZ19sZWZ0ICsgYnIqbGVnX3JpZ2h0ICwNCiAgYSB+IGRub3JtKCAxMCAsIDEwMCApICwNCiAgYmwgfiBkbm9ybSggMiAsIDEwICkgLA0KICBiciB+IGRub3JtKCAyICwgMTAgKSAsDQogIHNpZ21hIH4gZGV4cCggMSApDQogICksDQogIGRhdGE9ZA0KICApDQpwcmVjaXMobTYuMSkNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCnBsb3QocHJlY2lzKG02LjEpKQ0KYGBgDQojIyBPYnNlcnZhdGlvbnMNCi0gQm90aCBsZWdzIGhhdmUgYWxtb3N0IGlkZW50aWNhbCBsZW5ndGhzIGFuZCBhcmUgc3Ryb25nbHkgYXNzb2NpYXRlZCB3aXRoIGhlaWdodC4NCg0KIyMjIEtleSBRdWVzdGlvbjoNCi0gV2hhdCBpcyB0aGUgdmFsdWUgb2Yga25vd2luZyBvbmUgbGVnJ3MgbGVuZ3RoIGFmdGVyIGtub3dpbmcgdGhlIG90aGVyIGxlZ+KAmXMgbGVuZ3RoPw0KDQojIyMgUmVzdWx0Og0KLSBUaGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBmb3IgY29lZmZpY2llbnRzIFwoIFxiZXRhX2wgXCkgKGxlZnQgbGVnKSBhbmQgXCggXGJldGFfciBcKSAocmlnaHQgbGVnKSBzaG93czoNCiAgLSBBIGhpZ2ggY29ycmVsYXRpb24gYmV0d2VlbiBcKCBcYmV0YV9sIFwpIGFuZCBcKCBcYmV0YV9yIFwpLCBmb3JtaW5nIGEgbmFycm93IHJpZGdlIG9mIHBsYXVzaWJsZSB2YWx1ZXMuDQogIC0gVGhlIG1vZGVsIGNhbm5vdCBkaXNlbnRhbmdsZSB0aGUgY29udHJpYnV0aW9ucyBvZiBlYWNoIGxlZy4NCg0KDQojIyBWaXN1YWxpemluZyB0aGUgUG9zdGVyaW9yDQoNCiANCmBgYHtyfSANCiMgU2FtcGxlIGZyb20gdGhlIHBvc3Rlcmlvcg0KcG9zdCA8LSBleHRyYWN0LnNhbXBsZXMobTYuMSkNCg0KDQojIEFkZCB0cmFuc3BhcmVuY3kgYW5kIGNvbG9yDQpyYW5naTIgPC0gcmdiKDAuMiwgMC40LCAwLjgsIGFscGhhID0gMSkgIyBCbHVlIGNvbG9yDQpjb2xfYWxwaGEgPC0gZnVuY3Rpb24oY29sb3IsIGFscGhhKSBhZGp1c3Rjb2xvcihjb2xvciwgYWxwaGEuZiA9IGFscGhhKQ0KDQojIFNldCB1cCBzaWRlLWJ5LXNpZGUgcGxvdHMNCnBhcihtZnJvdyA9IGMoMSwgMikpICMgMSByb3csIDIgY29sdW1ucw0KDQojIExlZnQgUGFuZWw6IFNjYXR0ZXIgcGxvdCBvZiBibCB2cyBicg0KcGxvdChwb3N0JGJsLCBwb3N0JGJyLCBjb2wgPSBjb2xfYWxwaGEocmFuZ2kyLCAwLjUpLCBwY2ggPSAxNiwNCiAgICAgeGxhYiA9ICJMZWZ0IGxlZyBjb2VmZmljaWVudCAoYmwpIiwgDQogICAgIHlsYWIgPSAiUmlnaHQgbGVnIGNvZWZmaWNpZW50IChicikiLA0KICAgICBtYWluID0gIlNjYXR0ZXI6IGJsIHZzIGJyIikNCg0KIyBSaWdodCBQYW5lbDogRGVuc2l0eSBwbG90IG9mIGJsICsgYnINCmJsX2JyX3N1bSA8LSBwb3N0JGJsICsgcG9zdCRicg0KcGxvdChkZW5zaXR5KGJsX2JyX3N1bSksIGNvbCA9ICJibHVlIiwgbHdkID0gMiwNCiAgICAgbWFpbiA9ICJEZW5zaXR5OiBibCArIGJyIiwNCiAgICAgeGxhYiA9ICJTdW0gb2YgYmwgYW5kIGJyIiwgDQogICAgIHlsYWIgPSAiRGVuc2l0eSIsDQogICAgIHR5cGUgPSAibCIpICMgT25seSBsaW5lIHBsb3QNCmBgYA0KLSBUaGUgbGVmdCBwbG90IHNob3dzIHRoZSBuYXJyb3cgcmlkZ2Ugb2YgcGxhdXNpYmxlIHZhbHVlcyBmb3IgXChcYmV0YV9sXCkgYW5kIFwoXGJldGFfclwpLg0KLSBUaGUgcmlnaHQgcGxvdCBzaG93cyB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBmb3IgdGhlaXIgc3VtIChcKFxiZXRhX2wgKyBcYmV0YV9yXCkpLCB3aGljaCB0aGUgbW9kZWwgcmVsaWFibHkgZXN0aW1hdGVzLg0KDQpXaGF0IGhhcyBoYXBwZW5lZCBoZXJlIGlzIHRoYXQgc2luY2UgYm90aCBsZWcgdmFyaWFibGVzIGNvbnRhaW4gYWxtb3N0IGV4YWN0bHkgdGhlIHNhbWUgaW5mb3JtYXRpb24sIGlmIHlvdSBpbnNpc3Qgb24gaW5jbHVkaW5nIGJvdGggaW4gYSBtb2RlbCwgdGhlbiB0aGVyZSB3aWxsIGJlIGEgcHJhY3RpY2FsbHkgaW5maW5pdGUgbnVtYmVyIG9mIGNvbWJpbmF0aW9ucyBvZiBibCBhbmQgYnIgdGhhdCBwcm9kdWNlIHRoZSBzYW1lIHByZWRpY3Rpb25zLg0KIA0KT25lIHdheSB0byB0aGluayBvZiB0aGlzIHBoZW5vbWVub24gaXMgdGhhdCB5b3UgaGF2ZSBhcHByb3hpbWF0ZWQgdGhpcyBtb2RlbDoNCg0KJCR5X2kgXHNpbSBcbWF0aGNhbHtOfShcbXVfaSxcLFxzaWdtYSkkJA0KJCRcbXVfaSA9IFxhbHBoYSArIFxiZXRhXzEgXHRpbWVzIFx0ZXh0e0xlZyBMZW5ndGh9X2kgKyBcYmV0YV8yIFx0aW1lcyBcdGV4dHtMZWcgTGVuZ3RofV9pJCQNCiQkXG11X2kgPSBcYWxwaGEgKyAoXGJldGFfMSArIFxiZXRhXzIpIFx0aW1lcyBcdGV4dHtMZWcgTGVuZ3RofV9pJCQNCg0KVGhlIHBhcmFtZXRlcnMgzrIxIGFuZCDOsjIgY2Fubm90IGJlIHB1bGxlZCBhcGFydCwgYmVjYXVzZSB0aGV5IG5ldmVyIHNlcGFyYXRlbHkgaW5mbHVlbmNlIHRoZSBtZWFuIMK1LiBPbmx5IHRoZWlyIHN1bSwgzrIxK86yMixpbmZsdWVuY2VzIMK1LiBTbyB0aGlzIG1lYW5zIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIGVuZHMgdXAgcmVwb3J0aW5nIHRoZSB2ZXJ5IGxhcmdlIHJhbmdlIG9mIGNvbWJpbmF0aW9ucyBvZiDOsjEgYW5kIM6yMiB0aGF0IG1ha2UgdGhlaXIgc3VtIGNsb3NlIHRvIHRoZSBhY3R1YWwgYXNzb2NpYXRpb24gb2YgeCB3aXRoIHkuDQoNCkFuZCB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBpbiB0aGlzIHNpbXVsYXRlZCBleGFtcGxlIGhhcyBkb25lIGV4YWN0bHkgdGhhdDogSXQgaGFzIHByb2R1Y2VkIGEgZ29vZCBlc3RpbWF0ZSBvZiB0aGUgc3VtIG9mIGJsIGFuZCBici4gQnV0IGl0IGhhcyBkb25lIHNvIGF0IHRoZSBleHBlbnNlIG9mIHByb2R1Y2luZyBhIHZlcnkgd2lkZSByYW5nZSBvZiBwbGF1c2libGUgdmFsdWVzIGZvciBibCBhbmQgYnIgc2VwYXJhdGVseS4gVGhpcyBpcyB0aGUgZXNzZW5jZSBvZiBtdWx0aWNvbGxpbmVhcml0eS4gSXQgaXMgbm90IGEgcHJvYmxlbSB3aXRoIHRoZSBtb2RlbC4gSXQgaXMgYSBwcm9ibGVtIHdpdGggdGhlIHF1ZXN0aW9uLiBUaGUgbW9kZWwgaXMgYW5zd2VyaW5nIHRoZSBxdWVzdGlvbiB5b3UgYXNrZWQsIGJ1dCB0aGUgcXVlc3Rpb24gaXMgbm90IHdoYXQgeW91IHRob3VnaHQgaXQgd2FzLg0KDQojIyBTaW1wbGVyIE1vZGVsOiBPbmUgTGVnIGFzIFByZWRpY3Rvcg0KDQoNCmBgYHtyfQ0KbTYuMiA8LSBxdWFwKA0KICBhbGlzdCgNCiAgICBoZWlnaHQgfiBkbm9ybSggbXUgLCBzaWdtYSApICwNCiAgICBtdSA8LSBhICsgYmwqbGVnX2xlZnQsDQogICAgYSB+IGRub3JtKCAxMCAsIDEwMCApICwNCiAgICBibCB+IGRub3JtKCAyICwgMTAgKSAsDQogICAgc2lnbWEgfiBkZXhwKCAxICkNCiAgKSAsDQogIGRhdGE9ZCApDQoNCnByZWNpcyhtNi4yKQ0KYGBgDQoNCi0gVXNpbmcgb25seSBvbmUgbGVnIHJlc3VsdHMgaW4gc3RhYmxlIHBvc3RlcmlvciBlc3RpbWF0ZXMsIGF2b2lkaW5nIG11bHRpY29sbGluZWFyaXR5Lg0KDQoNCiMjIE11bHRpY29sbGluZWFyaXR5IGluIFByaW1hdGUgTWlsayBEYXRhOiBTdGFuZGFyZGl6aW5nIFZhcmlhYmxlcw0KDQojIyMgS2V5IFBvaW50czoNCi0gKipNdWx0aWNvbGxpbmVhcml0eSoqOiBPY2N1cnMgd2hlbiBwcmVkaWN0b3JzIGluIGEgcmVncmVzc2lvbiBtb2RlbCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQsIGltcGFjdGluZyB0aGUgcmVsaWFiaWxpdHkgb2YgdGhlIG1vZGVsLg0KLSAqKlN0YW5kYXJkaXppbmcgVmFyaWFibGVzKio6IEEgY29tbW9uIHRlY2huaXF1ZSB0byBhZGRyZXNzIG11bHRpY29sbGluZWFyaXR5IGJ5IHRyYW5zZm9ybWluZyB2YXJpYWJsZXMgdG8gaGF2ZSBhIG1lYW4gb2YgemVybyBhbmQgYSBzdGFuZGFyZCBkZXZpYXRpb24gb2Ygb25lLg0KDQojIyMgV2h5IEl0IE1hdHRlcnM6DQotIE11bHRpY29sbGluZWFyaXR5IGNhbiBvYnNjdXJlIHRoZSB0cnVlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB2YXJpYWJsZXMsIGxlYWRpbmcgdG8gbWlzbGVhZGluZyBjb25jbHVzaW9ucy4NCi0gU3RhbmRhcmRpemluZyB2YXJpYWJsZXMgaGVscHMgdG8gbWl0aWdhdGUgdGhlIGVmZmVjdHMgb2YgbXVsdGljb2xsaW5lYXJpdHksIG1ha2luZyB0aGUgbW9kZWwgbW9yZSByZWxpYWJsZSBhbmQgaW50ZXJwcmV0YWJsZS4NCg0KIyMjIEV4YW1wbGU6DQotIEluIHRoZSBjb250ZXh0IG9mIHByaW1hdGUgbWlsayBkYXRhLCBzdGFuZGFyZGl6aW5nIHZhcmlhYmxlcyBjYW4gaGVscCB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIGRpZmZlcmVudCBwcmVkaWN0b3JzIGFuZCB0aGUgb3V0Y29tZSB2YXJpYWJsZS4NCg0KIyMjIFN0ZXBzIHRvIFN0YW5kYXJkaXplIFZhcmlhYmxlczoNCjEuICoqQ2FsY3VsYXRlIHRoZSBNZWFuIGFuZCBTdGFuZGFyZCBEZXZpYXRpb24qKjogRm9yIGVhY2ggcHJlZGljdG9yIHZhcmlhYmxlLg0KMi4gKipUcmFuc2Zvcm0gdGhlIFZhcmlhYmxlcyoqOiBTdWJ0cmFjdCB0aGUgbWVhbiBhbmQgZGl2aWRlIGJ5IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIGVhY2ggdmFsdWUgaW4gdGhlIHByZWRpY3RvciB2YXJpYWJsZS4NCg0KYGBge3J9ICANCmRhdGEobWlsaykNCmQgPC0gbWlsaw0KZCRLIDwtIHN0YW5kYXJkaXplKCBkJGtjYWwucGVyLmcgKQ0KZCRGIDwtIHN0YW5kYXJkaXplKCBkJHBlcmMuZmF0ICkNCmQkTCA8LSBzdGFuZGFyZGl6ZSggZCRwZXJjLmxhY3Rvc2UgKQ0KYGBgDQoNCiMjIE1vZGVsczogVXNpbmcgT25lIFByZWRpY3Rvcg0KDQoNCmBgYHtyfQ0KI2tjYWwucGVyLmcgcmVncmVzc2Vkb25wZXJjLmZhdA0KIG02LjM8LXF1YXAoDQogICBhbGlzdCgNCiAgICAgS35kbm9ybShtdSxzaWdtYSksDQogICAgIG11PC1hK2JGKkYsDQogICAgIGF+ZG5vcm0oMCwwLjIpLA0KICAgICBiRn4gZG5vcm0oMCwwLjUpLA0KICAgICBzaWdtYX5kZXhwKDEpDQogICApLA0KICAgZGF0YT1kKQ0KIA0KDQoja2NhbC5wZXIuZyByZWdyZXNzZWRvbnBlcmMubGFjdG9zZQ0KIG02LjQ8LXF1YXAoDQogICBhbGlzdCgNCiAgICAgS35kbm9ybShtdSxzaWdtYSksDQogICAgIG11PC1hK2JMKkwsDQogICAgIGF+ZG5vcm0oMCwwLjIpLA0KICAgICBiTH4gZG5vcm0oMCwwLjUpLA0KICAgICBzaWdtYX5kZXhwKDEpDQogICksZGF0YT1kKQ0KIA0KIHByZWNpcyhtNi4zKQ0KIA0KIHByZWNpcyhtNi40KQ0KYGBgDQoNCi0gQm90aCBwcmVkaWN0b3JzIGFyZSBzdHJvbmdseSBhc3NvY2lhdGVkIHdpdGggZW5lcmd5IGNvbnRlbnQgaW4gc2VwYXJhdGUgbW9kZWxzLg0KLSBUaGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMgZm9yIGJGIGFuZCBiTCBhcmUgZXNzZW50aWFsbHkgbWlycm9yIGltYWdlcyBvZiBvbmUgYW5vdGhlci4gDQotIEdpdmVuIHRoZSBzdHJvbmcgYXNzb2NpYXRpb24gb2YgZWFjaCBwcmVkaWN0b3Igd2l0aCBvdXRjb21lLCB3ZSBtaWdodCBjb25jbHVkZSB0aGF0IGJvdGggYXJlIGltcG9ydGFudC4gVGhlIG1vcmUgZmF0IHRoZSBtb3JlIGNhbG9yaWUgY29udGVudCwgYW5kIHRoZSBtb3JlIGxhY3Rvc2UgdGhlIGxlc3MgY2Fsb3JpZSBjb250ZW50LiANCg0KV2hhdCBoYXBwZW5zIHdoZW4gd2UgZml0IGEgbW9kZWwgd2l0aCBib3RoIHByZWRpY3RvcnM/DQoNCiMjIE1vZGVsOiBVc2luZyBCb3RoIFByZWRpY3RvcnMNCg0KDQpgYGB7cn0NCg0KI2tjYWwucGVyLmcgcmVncmVzc2Vkb25wZXJjLmZhdGFuZHBlcmMubGFjdG9zZQ0KIG02LjU8LXF1YXAoDQogICBhbGlzdCgNCiAgICAgS35kbm9ybShtdSxzaWdtYSksDQogICAgIG11PC1hK2JGKkYrYkwqTCwNCiAgICAgYX5kbm9ybSgwLDAuMiksDQogICAgIGJGfiBkbm9ybSgwLDAuNSksDQogICAgIGJMfiBkbm9ybSgwLDAuNSksDQogICAgIHNpZ21hfmRleHAoMSkNCiAgKSxkYXRhPWQpDQogDQogcHJlY2lzKG02LjUpDQpgYGANCg0KLSBJbmNsdWRpbmcgYm90aCBwcmVkaWN0b3JzIGluY3JlYXNlcyB0aGUgcG9zdGVyaW9yIHVuY2VydGFpbnR5IGZvciBcKFxiZXRhX0ZcKSBhbmQgXChcYmV0YV9MXCksIGFzIHRoZSB0d28gdmFyaWFibGVzIGFyZSBoaWdobHkgY29sbGluZWFyLg0KLSBUaGUgcmlkZ2UtbGlrZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBjYW5ub3QgZGlzZW50YW5nbGUgdGhlIGVmZmVjdHMgb2YgZmF0IGFuZCBsYWN0b3NlIG9uIGVuZXJneSBjb250ZW50LiBUaGUgZWFzaWVzdCB3YXkgdG8gc2VlIHRoaXMgaXMgdG8gdXNlIGEgcGFpcnMgcGxvdC4NCg0KIyMgRGlhZ25vc2luZyBNdWx0aWNvbGxpbmVhcml0eQ0KDQoNCmBgYHtyfQ0KcGFpcnMoIH4ga2NhbC5wZXIuZyArIHBlcmMuZmF0ICsgcGVyYy5sYWN0b3NlICwgZGF0YT1kICwgY29sPXJhbmdpMiApDQoNCmBgYA0KDQotIFNjYXR0ZXJwbG90cyByZXZlYWwgXChcdGV4dHtwZXJjLmZhdH1cKSBhbmQgXChcdGV4dHtwZXJjLmxhY3Rvc2V9XCkgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIGFuZCBuZWFybHkgcmVkdW5kYW50Lg0KLSBUaGUgc3Ryb25nIGFzc29jaWF0aW9uIGJldHdlZW4gcHJlZGljdG9ycyBsZWFkcyB0byBtdWx0aWNvbGxpbmVhcml0eSwgaGluZGVyaW5nIHRoZSBtb2RlbCdzIGludGVycHJldGFiaWxpdHkuDQoNCiMjIyBEb2RneSBQcm9jZWR1cmVzIGZvciBNdWx0aWNvbGxpbmVhcml0eQ0KDQotIEluIHNvbWUgZmllbGRzLCBhIGNvbW1vbiBidXQgZmxhd2VkIGFwcHJvYWNoIHRvIGhhbmRsaW5nIG11bHRpY29sbGluZWFyaXR5IGludm9sdmVzOg0KICAxLiBJbnNwZWN0aW5nICoqcGFpcndpc2UgY29ycmVsYXRpb25zKiogYmV0d2VlbiBwcmVkaWN0b3JzLg0KICAyLiBEcm9wcGluZyBoaWdobHkgY29ycmVsYXRlZCB2YXJpYWJsZXMgYmVmb3JlIG1vZGVsaW5nLg0KICANCi0gKipXaHkgaXMgdGhpcyBhIG1pc3Rha2U/KioNCiAgLSBQYWlyd2lzZSBjb3JyZWxhdGlvbnMgYXJlIG5vdCB0aGUgaXNzdWU7ICoqY29uZGl0aW9uYWwgYXNzb2NpYXRpb25zKiogd2l0aGluIHRoZSBtb2RlbCBhcmUgd2hhdCBtYXR0ZXIuDQogIC0gVGhlIHJpZ2h0IGFwcHJvYWNoIGRlcGVuZHMgb24gdGhlIGNhdXNlIG9mIHRoZSBjb2xsaW5lYXJpdHksIHdoaWNoIHJlcXVpcmVzIGEgKipjYXVzYWwgcGVyc3BlY3RpdmUqKi4NCiAgDQotICoqRXhhbXBsZSBvZiBkb2RnaW5lc3MqKjoNCiAgLSBJbWFnaW5lIGFuYWx5emluZyBodW1hbiBoZWFsdGggZGF0YSBhbmQgZmluZGluZyB0aGF0ICJleGVyY2lzZSIgYW5kICJjYWxvcmllIGludGFrZSIgYXJlIGhpZ2hseSBjb3JyZWxhdGVkLiANCiAgLSBEcm9wcGluZyBvbmUgbWlnaHQgaWdub3JlIGltcG9ydGFudCBjYXVzYWwgcmVsYXRpb25zaGlwc+KAlGV4ZXJjaXNlIGFuZCBjYWxvcmllIGludGFrZSBib3RoIGluZmx1ZW5jZSB3ZWlnaHQgYnV0IGluIGRpZmZlcmVudCB3YXlzLg0KDQotLS0NCg0KIyMjIENvcmUgVHJhZGVvZmYgaW4gTWlsayBDb21wb3NpdGlvbg0KDQpJbiB0aGUgbWlsayBleGFtcGxlLCBhIG5hdHVyYWwgdHJhZGVvZmYgbGlrZWx5IGV4cGxhaW5zIHRoZSBjb2xsaW5lYXJpdHkgYmV0d2VlbiBmYXQgYW5kIGxhY3Rvc2U6DQoNCi0gKipGcmVxdWVudCBudXJzaW5nKio6DQogIC0gTWlsayB0ZW5kcyB0byBiZSB3YXRlcnkgYW5kIGxvdyBpbiBlbmVyZ3kuDQogIC0gSGlnaCBpbiBzdWdhciAoKipsYWN0b3NlKiopIHRvIHByb3ZpZGUgcXVpY2sgZW5lcmd5Lg0KDQotICoqSW5mcmVxdWVudCBudXJzaW5nKio6DQogIC0gTWlsayBuZWVkcyB0byBiZSBtb3JlIGVuZXJneS1kZW5zZS4NCiAgLSBIaWdoIGluICoqZmF0KiogdG8gc3VzdGFpbiB0aGUgaW5mYW50IGZvciBsb25nZXIgcGVyaW9kcyBiZXR3ZWVuIGZlZWRpbmdzLg0KDQotIFRoaXMgdHJhZGVvZmYgc3VnZ2VzdHMgYSAqKmNhdXNhbCBtb2RlbCoqOiBudXJzaW5nIGZyZXF1ZW5jeSBkcml2ZXMgbWlsayBjb21wb3NpdGlvbi4gSGlnaCBsYWN0b3NlIGFuZCBoaWdoIGZhdCBhcmUgaW52ZXJzZWx5IHJlbGF0ZWQgYmVjYXVzZSB0aGV5IHNlcnZlIGRpZmZlcmVudCBlbmVyZ2V0aWMgc3RyYXRlZ2llcy4NCg0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KY2lyY2xlX3BvaW50cyA8LSBmdW5jdGlvbihwb2ludHNfdG9fY2lyY2xlLCBnKSB7DQogICAgI2ZldyByZWdleHMgdG8gZXh0cmFjdCB0aGUgcG9pbnRzIGFuZCB0aGUgcG9zaXRpb25zIGZyb20gImciDQogICAgI2NhbiBzdXJlbHkgYmUgb3B0aW1pemVkLCBtYWRlIG5pY2VyIGFuZCBtb3JlIHJvYnVzdCBidXQgaXQgd29ya3MgZm9yIG5vdw0KICAgIGZzcGxpdCA8LSBzdHJzcGxpdChnWzFdLCAiXFxdIilbWzFdXQ0KICAgIGZzcGxpdCA8LSBmc3BsaXRbLWxlbmd0aChmc3BsaXQpXQ0KICAgIGZzcGxpdCA8LSBzdWJzdHIoZnNwbGl0LCAxLCBuY2hhcihmc3BsaXQpLTEpDQogICAgZnNwbGl0WzFdIDwtIHN1YnN0cihmc3BsaXRbMV0sIDYsIG5jaGFyKGZzcGxpdCkpDQogICAgdmFycyA8LSBzYXBwbHkocmVnbWF0Y2hlcyhmc3BsaXQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdleGVjKCJcXFxuKC4qPylcXHMqXFxbIiwgZnNwbGl0KSksICJbIiwgMikNCiAgICBwb3MgPC0gc3ViKCIuKnBvcz1cXFwiIiwgIiIsIGZzcGxpdCkNCiAgICANCiAgICAjYnVpbGQgZGF0YWZyYW1lIHdpdGggZXh0cmFjdGVkIGluZm9ybWF0aW9uDQogICAgcmVzX2RmIDwtIGRhdGEuZnJhbWUodmFycyA9IHZhcnMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3ggPSBzYXBwbHkoc3Ryc3BsaXQocG9zLCAiLCIpLCAiWyIsMSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3kgPSBzYXBwbHkoc3Ryc3BsaXQocG9zLCAiLCIpLCAiWyIsMikpDQogICAgZGZfdG9fY2lyY2xlIDwtIHJlc19kZltyZXNfZGYkdmFycyAlaW4lIHBvaW50c190b19jaXJjbGUsXQ0KICAgIA0KICAgICN5LXBvc2l0aW9uIHNlZW1zIHRvIGJlIGludmVydGVkIGFuZCBoYXMgdG8gYmUgbXVsdGlwbGllZCBieSAtMQ0KICAgIHBvaW50cyhjKGFzLm51bWVyaWMoZGZfdG9fY2lyY2xlJHBvc3gpKSwgDQogICAgICAgICAgIGMoYXMubnVtZXJpYyhkZl90b19jaXJjbGUkcG9zeSkgKiAtMSksIA0KICAgICAgICAgICBjZXggPSA0KQ0KfQ0KDQpgYGANCg0KYGBge3J9DQoNCiMgRGVmaW5lIHRoZSBEQUcgd2l0aCBEIGFzIGxhdGVudA0KZGFnIDwtIGRhZ2l0dHkoICJkYWd7DQogIEwgLT4gSyA8LSBGDQogIEwgPC0gRCAtPiBGDQogIEQgW3Vub2JzZXJ2ZWRdDQp9IiApDQoNCiMgRGVmaW5lIGNvb3JkaW5hdGVzIGZvciB2aXN1YWxpemF0aW9uDQpjb29yZGluYXRlcyhkYWcpIDwtIGxpc3QoDQogIHggPSBjKEwgPSAwLCBLID0gMSwgRCA9IDEsIEYgPSAyKSwNCiAgeSA9IGMoTCA9IDAuNSwgSyA9IDEsIEQgPSAwLjUsIEYgPSAwLjUpDQopDQoNCnBsb3QoIGRhZyApDQoNCmNpcmNsZV9wb2ludHMoYygiRCIpLCBkYWcpDQpgYGANCg0KIyMgS2V5IFRha2Vhd2F5cw0KLSAqKk11bHRpY29sbGluZWFyaXR5IGlzIGEgcHJvYmxlbSBvZiBpbnRlcnByZXRhdGlvbiwgbm90IHByZWRpY3Rpb24qKi4NCi0gV2hlbiBwcmVkaWN0b3JzIGFyZSBoaWdobHkgY29ycmVsYXRlZCwgdGhlIG1vZGVsIHN0cnVnZ2xlcyB0byBhbGxvY2F0ZSBlZmZlY3RzIHRvIGVhY2ggcHJlZGljdG9yLg0KDQojIyMgQXZvaWQgUGFpcndpc2UgQ29ycmVsYXRpb24gVGVzdHM6DQotIEl04oCZcyBjb25kaXRpb25hbCBhc3NvY2lhdGlvbnMsIG5vdCBwYWlyd2lzZSBjb3JyZWxhdGlvbnMsIHRoYXQgbWF0dGVyLg0KDQojIyMgVW5kZXJzdGFuZCB0aGUgQ2F1c2FsIE1vZGVsOg0KLSBDb2xsaW5lYXJpdHkgb2Z0ZW4gYXJpc2VzIGZyb20gdW5kZXJseWluZyBjYXVzYWwgcHJvY2Vzc2VzLg0KLSBJbiB0aGUgbWlsayBleGFtcGxlLCBmYXQgYW5kIGxhY3Rvc2UgYXJlIGxpbmtlZCBieSBudXJzaW5nIGZyZXF1ZW5jeSwgYSBsYXRlbnQgdmFyaWFibGUuDQoNCg0KIyMgUG9zdC10cmVhdG1lbnQgQmlhcw0KDQojIyMgS2V5IElkZWE6IE1pc3Rha2VzIEZyb20gSW5jbHVkaW5nIFZhcmlhYmxlcw0KLSBJdOKAmXMgY29tbW9uIHRvIHdvcnJ5IGFib3V0IG9taXR0aW5nIHByZWRpY3RvciB2YXJpYWJsZXMgKCoqb21pdHRlZCB2YXJpYWJsZSBiaWFzKiopLg0KLSBMZXNzIGF0dGVudGlvbiBpcyBnaXZlbiB0byBtaXN0YWtlcyBmcm9tICoqaW5jbHVkaW5nIHZhcmlhYmxlcyoqICgqKmluY2x1ZGVkIHZhcmlhYmxlIGJpYXMqKik6DQogIC0gQWRkaW5nIHZhcmlhYmxlcyB3aXRob3V0IGNvbnNpZGVyaW5nIGNhdXNhbGl0eSBjYW4gcnVpbiByYW5kb21pemVkIGV4cGVyaW1lbnRzLg0KICAtIEV4YW1wbGU6ICoqUG9zdC10cmVhdG1lbnQgYmlhcyoqIG9jY3VycyB3aGVuIGEgcHJlZGljdG9yIGlzIGluZmx1ZW5jZWQgYnkgdGhlIHRyZWF0bWVudCBvciBvdXRjb21lLg0KDQotLS0NCg0KIyMjIEV4YW1wbGU6IFBsYW50IEdyb3d0aCBFeHBlcmltZW50DQotIFNjZW5hcmlvOg0KICAtICoqR29hbCoqOiBNZWFzdXJlIHRoZSBjYXVzYWwgZWZmZWN0IG9mIHNvaWwgdHJlYXRtZW50IG9uIHBsYW50IGdyb3d0aC4NCiAgLSBWYXJpYWJsZXM6DQogICAgMS4gSW5pdGlhbCBoZWlnaHQgKFwoSF8wXCkpOiBQcmUtdHJlYXRtZW50IGhlaWdodC4NCiAgICAyLiBGaW5hbCBoZWlnaHQgKFwoSF8xXCkpOiBQb3N0LXRyZWF0bWVudCBoZWlnaHQuDQogICAgMy4gVHJlYXRtZW50IChcKFRcKSk6IFNvaWwgdHJlYXRtZW50Lg0KICAgIDQuIEZ1bmd1cyAoXChGXCkpOiBGdW5ndXMgcHJlc2VuY2UuDQotICoqUHJvYmxlbSoqOiBJbmNsdWRpbmcgXChGXCkgKGZ1bmd1cykgaW5kdWNlcyBiaWFzIGJlY2F1c2UgXChUIFx0byBGIFx0byBIXzFcKToNCiAgLSBUcmVhdG1lbnQgaW5mbHVlbmNlcyBmdW5ndXMuDQogIC0gRnVuZ3VzIGluZmx1ZW5jZXMgZ3Jvd3RoIChcKEhfMVwpKS4NCiAgLSBDb250cm9sbGluZyBmb3IgXChGXCkgYmxvY2tzIHRoZSBjYXVzYWwgcGF0aCBcKFQgXHRvIEhfMVwpLg0KDQotLS0NCg0KIyMjIFNpbXVsYXRlZCBEYXRhDQpgYGB7cn0NCnNldC5zZWVkKDE5MTQpDQpOIDwtIDEwMA0KaDAgPC0gcm5vcm0oTiwgMTAsIDIpDQp0cmVhdG1lbnQgPC0gcmVwKDA6MSwgZWFjaCA9IE4vMikNCmZ1bmd1cyA8LSByYmlub20oTiwgc2l6ZSA9IDEsIHByb2IgPSAwLjUgLSB0cmVhdG1lbnQgKiAwLjQpDQpoMSA8LSBoMCArIHJub3JtKE4sIDUgLSAzICogZnVuZ3VzKQ0KZCA8LSBkYXRhLmZyYW1lKGgwID0gaDAsIGgxID0gaDEsIHRyZWF0bWVudCA9IHRyZWF0bWVudCwgZnVuZ3VzID0gZnVuZ3VzKQ0KcHJlY2lzKGQpDQpgYGANCg0KIyMgSW5pdGlhbCBHcm93dGggTW9kZWwgV2l0aG91dCBQcmVkaWN0b3JzDQoNCiMjIyBNb2RlbCBEZWZpbml0aW9uDQoqKkdvYWwqKjogTW9kZWwgcHJvcG9ydGlvbmFsIGdyb3d0aCAoXCggcCA9IFxmcmFje0hfMX17SF8wfSBcKSkuDQoNCiMjIyBNb2RlbDoNCi0gXCggaF97MSxpfSBcc2ltIE4oXG11X2ksIFxzaWdtYSkgXCkNCi0gXCggXG11X2kgPSBoX3swLGl9IFx0aW1lcyBwIFwpDQotIFwoIHAgXHNpbSBcdGV4dHtMb2dOb3JtYWx9KDAsIDAuMjUpIFwpOiBQcmlvciBjZW50ZXJlZCBhcm91bmQgbm8gZ3Jvd3RoIChcKCBwID0gMSBcKSkuDQoNCiMjIyBTaW11bGF0aW9uIGFuZCBGaXR0aW5nDQoNCg0KYGBge3J9DQoNCiMgU2ltdWxhdGUgcHJpb3IgZnJvbSBtb2RlbA0Kc2ltX3AgPC0gcmxub3JtKCAxZTQgLCAwICwgMC4yNSApDQoNCnByZWNpcyggZGF0YS5mcmFtZShzaW1fcCkgKQ0KDQpoaXN0KHNpbV9wKQ0KDQpgYGANClNvIHRoaXMgcHJpb3IgZXhwZWN0cyBhbnl0aGluZyBmcm9tIDQwJSBzaHJpbmthZ2UgdXAgdG8gNTAlIGdyb3d0aC4gTGV04oCZcyBmaXQgdGhpcyBtb2RlbCwgc28geW91IGNhbiBzZWUgaG93IGl0IGp1c3QgbWVhc3VyZXMgdGhlIGF2ZXJhZ2UgZ3Jvd3RoIGluIHRoZSBleHBlcmltZW50LiANCg0KYGBge3J9DQojIEZpdCB0aGUgbW9kZWwNCm02LjYgPC0gcXVhcCgNCiAgYWxpc3QoDQogICAgaDEgfiBkbm9ybSggaDAgKiBwICwgc2lnbWEgKSwNCiAgICBtdSA8LSBoMCAqIHAsDQogICAgcCB+IGRsbm9ybSggMCAsIDAuMjUgKSwNCiAgICBzaWdtYSB+IGRleHAoIDEgKQ0KICApLA0KICBkYXRhID0gZA0KKQ0KDQpwcmVjaXMobTYuNikNCg0KYGBgDQojIyBPdXRwdXQ6DQotICoqUG9zdGVyaW9yIG1lYW4gZm9yIFwoIHAgXCkqKjogQXBwcm94aW1hdGVseSAxLjQsIHN1Z2dlc3RpbmcgNDAlIGF2ZXJhZ2UgZ3Jvd3RoLg0KLSAqKlByaW9yKio6IEFsbG93cyBmb3IgNDAlIHNocmlua2FnZSB0byA1MCUgZ3Jvd3RoLg0KDQojIyBBZGRpbmcgVHJlYXRtZW50IGFuZCBGdW5ndXMNCg0KIyMjIE1vZGVsIERlZmluaXRpb24NCkV4dGVuZCBcKCBwIFwpIHRvIGRlcGVuZCBvbiB0cmVhdG1lbnQgYW5kIGZ1bmd1czoNCi0gXCggaF97MSxpfSBcc2ltIE4oXG11X2ksIFxzaWdtYSkgXCkNCi0gXCggXG11X2kgPSBoX3swLGl9IFx0aW1lcyBwIFwpDQotIFwoIHAgPSBhICsgYl90IFx0aW1lcyBUX2kgKyBiX2YgXHRpbWVzIEZfaSBcKQ0KDQojIyMgUHJpb3JzOg0KLSBcKCBhIFxzaW0gXHRleHR7TG9nTm9ybWFsfSgwLCAwLjIpIFwpDQotIFwoIGJfdCwgYl9mIFxzaW0gTigwLCAwLjUpIFwpDQotIFwoIFxzaWdtYSBcc2ltIFx0ZXh0e0V4cG9uZW50aWFsfSgxKSBcKQ0KDQojIyMgTW9kZWwgRml0dGluZw0KDQpUaGUgcHJvcG9ydGlvbiBvZiBncm93dGggcCBpcyBub3cgYSBmdW5jdGlvbiBvZiB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcy4gSXQgbG9va3MgbGlrZSBhbnkgIG90aGVyIGxpbmVhciBtb2RlbC4gVGhlIHByaW9ycyBvbiB0aGUgc2xvcGVzIGFyZSBhbG1vc3QgY2VydGFpbmx5IHRvbyBmbGF0LiBUaGV5IHBsYWNlIDk1JSBvZiB0aGUgcHJpb3IgbWFzcyBiZXR3ZWVuIOKIkjEgKDEwMCUgcmVkdWN0aW9uKSBhbmQgKzEgKDEwMCUgaW5jcmVhc2UpIGFuZCB0d28tdGhpcmRzIG9mIHRoZSBwcmlvciBtYXNzIGJldHdlZW4g4oiSMC41IGFuZCArMC41LiAgDQoNCg0KDQpgYGB7cn0NCiMgRml0IHRoZSBtb2RlbA0KIG02Ljc8LXF1YXAoDQogICBhbGlzdCgNCiAgICAgaDF+IGRub3JtKG11LHNpZ21hKSwNCiAgICAgbXU8LWgwKnAsDQogICAgIHA8LSBhK2J0KnRyZWF0bWVudCtiZipmdW5ndXMsDQogICAgIGF+ZGxub3JtKDAsMC4yKSwNCiAgICAgYnR+IGRub3JtKDAsMC41KSwNCiAgICAgYmZ+IGRub3JtKDAsMC41KSwNCiAgICAgc2lnbWF+ZGV4cCgxKQ0KICAgICANCiAgICApLCBkYXRhPWQNCiAgIA0KICAgKQ0KDQpwcmVjaXMobTYuNykNCmBgYA0KDQojIyBPdXRwdXQ6DQotICoqVHJlYXRtZW50IGVmZmVjdCAoXCggYl90IFwpKSoqOiBDbG9zZSB0byB6ZXJvLCBzdWdnZXN0aW5nIG5vIGVmZmVjdC4NCi0gKipGdW5ndXMgZWZmZWN0IChcKCBiX2YgXCkpKio6IE5lZ2F0aXZlLCBpbmRpY2F0aW5nIHJlZHVjZWQgZ3Jvd3RoIGR1ZSB0byBmdW5ndXMuDQoNCiMjIyBXaHk/DQotIEZ1bmd1cyBpcyBhIHBvc3QtdHJlYXRtZW50IHZhcmlhYmxlLiBDb250cm9sbGluZyBmb3IgaXQgYmxvY2tzIHRoZSBjYXVzYWwgcGF0aCBcKCBUIFxyaWdodGFycm93IEhfMSBcKS4NCg0KDQoNCioqQmxvY2tlZCBieSBjb25zZXF1ZW5jZSoqLiBUaGUgcHJvYmxlbSBpcyB0aGF0IGZ1bmd1cyBpcyBtb3N0bHkgYSBjb25zZXF1ZW5jZSBvZiB0cmVhdG1lbnQuIFRoaXMgaXMgdG8gc2F5IHRoYXQgZnVuZ3VzIGlzIGEgcG9zdC10cmVhdG1lbnQgdmFyaWFibGUuIFNvIHdoZW4gd2UgY29udHJvbCBmb3IgZnVuZ3VzLCB0aGUgbW9kZWwgaXMgaW1wbGljaXRseSBhbnN3ZXJpbmcgdGhlIHF1ZXN0aW9uOiBPbmNlIHdlIGFscmVhZHkga25vdyB3aGV0aGVyIG9yIG5vdCBhIHBsYW50IGRldmVsb3BlZCBmdW5ndXMsIGRvZXMgc29pbCB0cmVhdG1lbnQgbWF0dGVyPyBUaGUgYW5zd2VyIGlzIOKAnG5vLOKAnSBiZWNhdXNlIHNvaWwgdHJlYXRtZW50IGhhcyBpdHMgZWZmZWN0cyBvbiBncm93dGggdGhyb3VnaCByZWR1Y2luZyBmdW5ndXMuIEJ1dCB3ZSBhY3R1YWxseSB3YW50IHRvIGtub3csIGJhc2VkIG9uIHRoZSBkZXNpZ24gb2YgdGhlIGV4cGVyaW1lbnQsIGlzIHRoZSBpbXBhY3Qgb2YgdHJlYXRtZW50IG9uIGdyb3d0aC4gVG8gbWVhc3VyZSB0aGlzIHByb3Blcmx5LCB3ZSBzaG91bGQgb21pdCB0aGUgcG9zdC10cmVhdG1lbnQgdmFyaWFibGUgZnVuZ3VzLiBIZXJl4oCZcyB3aGF0IHRoZSBpbmZlcmVuY2UgbG9va3MgbGlrZSBpbiB0aGF0IGNhc2UuDQoNCiMjIENvcnJlY3QgSW5mZXJlbmNlOiBFeGNsdWRpbmcgRnVuZ3VzDQoNCiMjIyBBZGp1c3RlZCBNb2RlbA0KRXhjbHVkZSBcKCBGIFwpIHRvIGNvcnJlY3RseSBtZWFzdXJlIHRoZSB0cmVhdG1lbnQgZWZmZWN0Og0KLSBcKCBwID0gYSArIGJfdCBcdGltZXMgVF9pIFwpDQoNCiMjIyBNb2RlbCBGaXR0aW5nDQoNCg0KYGBge3J9DQojIEZpdCB0aGUgbW9kZWwNCiBtNi44PC1xdWFwKA0KICAgYWxpc3QoDQogICAgIGgxfiBkbm9ybShtdSxzaWdtYSksDQogICAgIG11PC1oMCpwLA0KICAgICBwPC0gYStidCp0cmVhdG1lbnQsDQogICAgIGF+ZGxub3JtKDAsMC4yKSwNCiAgICAgYnR+IGRub3JtKDAsMC41KSwNCiAgICAgc2lnbWF+ZGV4cCgxKQ0KICAgICANCiAgICApLCBkYXRhPWQNCiAgIA0KICAgKQ0KDQpwcmVjaXMobTYuOCkNCmBgYA0KDQojIyBPdXRwdXQ6DQotICoqVHJlYXRtZW50IGVmZmVjdCAoXCggYl90IFwpKSoqOiBQb3NpdGl2ZSwgYXMgZXhwZWN0ZWQuDQotIEV4Y2x1ZGluZyBmdW5ndXMgcmV2ZWFscyB0aGUgdHJ1ZSBlZmZlY3Qgb2YgdHJlYXRtZW50IG9uIGdyb3d0aC4NCg0KDQpOb3cgdGhlIGltcGFjdCBvZiB0cmVhdG1lbnQgaXMgY2xlYXJseSBwb3NpdGl2ZSwgYXMgaXQgc2hvdWxkIGJlLiBJdCBtYWtlcyBzZW5zZSB0byBjb250cm9sIGZvciBwcmUtdHJlYXRtZW50IGRpZmZlcmVuY2VzLCBsaWtlIHRoZSBpbml0aWFsIGhlaWdodCBoMCwgdGhhdCBtaWdodCBtYXNrIHRoZSBjYXVzYWwgaW5mbHVlbmNlIG9mIHRyZWF0bWVudC4gQnV0IGluY2x1ZGluZyBwb3N0LXRyZWF0bWVudCB2YXJpYWJsZXMgY2FuIGFjdHVhbGx5IG1hc2sgdGhlIHRyZWF0bWVudCBpdHNlbGYuIFRoaXMgZG9lc27igJl0IG1lYW4geW91IGRvbuKAmXQgd2FudCB0aGUgbW9kZWwgdGhhdCBpbmNsdWRlcyBib3RoIHRyZWF0bWVudCBhbmQgZnVuZ3VzLiBUaGUgZmFjdCB0aGF0IGluY2x1ZGluZyAqZnVuZ3VzKiB6ZXJvcyB0aGUgY29lZmZpY2llbnQgZm9yICp0cmVhdG1lbnQqIHN1Z2dlc3RzIHRoYXQgdGhlIHRyZWF0bWVudCB3b3JrcyBmb3IgZXhhY3RseSB0aGUgYW50aWNpcGF0ZWQgcmVhc29ucy4gSXQgdGVsbHMgdXMgYWJvdXQgdGhlIG1lY2hhbmlzbS4gQnV0IGEgY29ycmVjdCBpbmZlcmVuY2UgYWJvdXQgdGhlIHRyZWF0bWVudCBzdGlsbCBkZXBlbmRzIHVwb24gb21pdHRpbmcgdGhlIHBvc3QtdHJlYXRtZW50IHZhcmlhYmxlLg0KDQojIyBWaXN1YWxpemluZyBXaXRoIGEgREFHDQpGdW5ndXMgYW5kIGQtc2VwYXJhdGlvbi4gSXQgaGVscHMgdG8gbG9vayBhdCB0aGlzIHByb2JsZW0gaW4gdGVybXMgb2YgYSBEQUcuIEluIHRoaXMgY2FzZSwgSeKAmWxsIHNob3cgeW91IGhvdyB0byBkcmF3IGl0IHVzaW5nIHRoZSBkYWdpdHR5IFIgcGFja2FnZSwgYmVjYXVzZSB3ZSBhcmUgZ29pbmcgdG8gdXNlIHRoYXQgcGFja2FnZSBub3cgdG8gZG8gc29tZSBncmFwaCBhbmFseXNpcy4NCg0KDQojIyMgQ2F1c2FsIERpYWdyYW0NCkdyYXBoOg0KLSBcKCBUIFxyaWdodGFycm93IEYgXHJpZ2h0YXJyb3cgSF8xIFwpDQotIFwoIEhfMCBccmlnaHRhcnJvdyBIXzEgXCkNCg0KDQpUaGUgY2F1c2FsIGRpYWdyYW0gZm9yIHRoaXMgc2NlbmFyaW8gaXMgc2hvd24gYmVsb3c6DQoNCmBgYHtyfQ0KIyBEZWZpbmUgdGhlIERBRyB3aXRoIEQgYXMgbGF0ZW50DQpwbGFudF9kYWcgPC0gZGFnaXR0eSggImRhZyB7DQogICAgSF8wLT4gSF8xDQogICAgRi0+IEhfMQ0KICAgIFQtPiBGDQogfSIpDQoNCg0KIGNvb3JkaW5hdGVzKCBwbGFudF9kYWcgKSA8LSBsaXN0KCB4PWMoSF8wPTAsVD0yLEY9MS41LEhfMT0xKSAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9YyhIXzA9MCxUPTAsRj0wLEhfMT0wKSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCiBkcmF3ZGFnKCBwbGFudF9kYWcgKQ0KIA0KYGBgDQojIyBLZXkgSW5zaWdodDoNCi0gQ29uZGl0aW9uaW5nIG9uIFwoIEYgXCkgKGZ1bmd1cykgYmxvY2tzIHRoZSBwYXRoIFwoIFQgXHJpZ2h0YXJyb3cgSF8xIFwpLCBtYWtpbmcgXCggVCBcKSBhbmQgXCggSF8xIFwpIGluZGVwZW5kZW50Lg0KDQojIyBLZXkgVGFrZWF3YXlzDQotICoqUG9zdC10cmVhdG1lbnQgYmlhcyoqOg0KICAtIEluY2x1ZGluZyB2YXJpYWJsZXMgYWZmZWN0ZWQgYnkgdHJlYXRtZW50IGNhbiBtYXNrIHRoZSB0cmVhdG1lbnQgZWZmZWN0Lg0KLSAqKkRBR3MgaGVscCBjbGFyaWZ5IGNhdXNhbGl0eSoqOg0KICAtIFVzZSBjYXVzYWwgZGlhZ3JhbXMgdG8gaWRlbnRpZnkgdmFyaWFibGVzIHRoYXQgc2hvdWxkIG9yIHNob3VsZCBub3QgYmUgaW5jbHVkZWQuDQotICoqQ29ycmVjdCBpbmZlcmVuY2UqKjoNCiAgLSBFeGNsdWRlIHBvc3QtdHJlYXRtZW50IHZhcmlhYmxlcyB0byBtZWFzdXJlIGNhdXNhbCBlZmZlY3RzIGFjY3VyYXRlbHkuDQoNCg0KIyMgQ29sbGlkZXIgQmlhcw0KDQojIyMgS2V5IElkZWE6IFNlbGVjdGlvbiBhbmQgQ29sbGlkZXIgQmlhcw0KLSBTZWxlY3Rpb24gcHJvY2Vzc2VzIGNhbiBjcmVhdGUgbWlzbGVhZGluZyBhc3NvY2lhdGlvbnMgaW4gc3RhdGlzdGljYWwgbW9kZWxzLCBrbm93biBhcyAqKmNvbGxpZGVyIGJpYXMqKi4NCi0gKipDb2xsaWRlcioqOiBBIHZhcmlhYmxlIGluZmx1ZW5jZWQgYnkgdHdvIG9yIG1vcmUgb3RoZXIgdmFyaWFibGVzIChlLmcuLCB0cnVzdHdvcnRoaW5lc3MgYW5kIG5ld3N3b3J0aGluZXNzIGJvdGggYWZmZWN0IHNlbGVjdGlvbikuDQoNCi0tLQ0KDQojIyMgRXhhbXBsZTogU2VsZWN0aW9uIGluIEdyYW50IFByb3Bvc2Fscw0KDQojIyMjIENhdXNhbCBEaWFncmFtDQotIFRydXN0d29ydGhpbmVzcyAoXChUXCkpIGFuZCBOZXdzd29ydGhpbmVzcyAoXChOXCkpIGJvdGggaW5mbHVlbmNlIFNlbGVjdGlvbiAoXChTXCkpLg0KLSBTZWxlY3Rpb24gKFwoU1wpKSBpcyBhICoqY29sbGlkZXIqKi4NCg0KYGBge3J9DQpncmFudF9kYWcgPC0gZGFnaXR0eSgiZGFnIHsNCiAgICBUIC0+IFMNCiAgICBOIC0+IFMNCn0iKQ0KY29vcmRpbmF0ZXMoZ3JhbnRfZGFnKSA8LSBsaXN0KA0KICB4ID0gYyhUID0gMCwgTiA9IDIsIFMgPSAxKSwNCiAgeSA9IGMoVCA9IDAsIE4gPSAwLCBTID0gMCkNCikNCmRyYXdkYWcoZ3JhbnRfZGFnKQ0KDQpgYGANCg0KIyMgRXhwbGFuYXRpb24NCi0gQ29uZGl0aW9uaW5nIG9uIFwoIFMgXCkgY3JlYXRlcyBhIHN0YXRpc3RpY2FsIGFzc29jaWF0aW9uIGJldHdlZW4gXCggVCBcKSBhbmQgXCggTiBcKToNCiAgLSBJZiBhIHNlbGVjdGVkIHByb3Bvc2FsIGhhcyBsb3cgXCggVCBcKSwgaXQgbXVzdCBoYXZlIGhpZ2ggXCggTiBcKSB0byBiZSBzZWxlY3RlZCAoYW5kIHZpY2UgdmVyc2EpLg0KICAtIFRoaXMgY3JlYXRlcyBhIG5lZ2F0aXZlIGFzc29jaWF0aW9uIGJldHdlZW4gXCggVCBcKSBhbmQgXCggTiBcKSwgZXZlbiBpZiB0aGV5IGFyZSB1bmNvcnJlbGF0ZWQgaW4gdGhlIHBvcHVsYXRpb24uDQoNCg0KIyMgRXhhbXBsZTogQWdpbmcsIEhhcHBpbmVzcywgYW5kIE1hcnJpYWdlDQoNCiMjIyBDYXVzYWwgRGlhZ3JhbQ0KLSBIYXBwaW5lc3MgKFwoIEggXCkpIGFuZCBBZ2UgKFwoIEEgXCkpIGJvdGggaW5mbHVlbmNlIE1hcnJpYWdlIChcKCBNIFwpKS4NCi0gXCggTSBcKSBpcyBhIGNvbGxpZGVyLg0KDQoNCmBgYHtyfQ0KIyBDcmVhdGUgdGhlIERBRyBtZW50aW9uZWQgaW4gdGhlIHBhcmFncmFwaCBhYm92ZQ0KaGFwcGluZXNzX2RhZyA8LSBkYWdpdHR5KCAiZGFnIHsNCiAgICBBIC0+IE0NCiAgICBIIC0+IE0NCiB9IikNCg0KY29vcmRpbmF0ZXMoIGhhcHBpbmVzc19kYWcgKSA8LSBsaXN0KCB4PWMoQT0wLCBIPTIsIE09MSkgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PWMoQT0wLCBIPTAsIE09MCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCg0KZHJhd2RhZyggaGFwcGluZXNzX2RhZyApDQpgYGANCg0KIyMgRXhwbGFuYXRpb24NCi0gQ29uZGl0aW9uaW5nIG9uIFwoIE0gXCkgaW5kdWNlcyBhIHNwdXJpb3VzIGFzc29jaWF0aW9uIGJldHdlZW4gXCggQSBcKSBhbmQgXCggSCBcKSwgZXZlbiBpZiBoYXBwaW5lc3MgaXMgY29uc3RhbnQgYWNyb3NzIGFnZXMuDQotIFRoaXMgKipjb2xsaWRlciBiaWFzKiogYXJpc2VzIGZyb20gY29uZGl0aW9uaW5nIG9uIGEgdmFyaWFibGUgaW5mbHVlbmNlZCBieSB0d28gb3RoZXIgdmFyaWFibGVzLg0KLSBIYXBwaW5lc3MgKEgpIGFuZCBhZ2UgKEEpIGJvdGggY2F1c2UgbWFycmlhZ2UgKE0pLiBNYXJyaWFnZSBpcyB0aGVyZWZvcmUgYSBjb2xsaWRlci4gDQoNCg0KDQojIyBTaW11bGF0aW5nIHRoZSBEYXRhDQoNCiMjIyBTaW11bGF0aW9uIERlc2lnbg0KLSBFYWNoIHllYXIsIDIwIGluZGl2aWR1YWxzIGFyZSBib3JuIHdpdGggdW5pZm9ybWx5IGRpc3RyaWJ1dGVkIGhhcHBpbmVzcy4NCi0gSW5kaXZpZHVhbHMgYWdlIGFuZCBtYXkgZ2V0IG1hcnJpZWQ6DQogIC0gSGFwcGluZXNzIGRvZXMgbm90IGNoYW5nZSB3aXRoIGFnZS4NCiAgLSBQcm9iYWJpbGl0eSBvZiBtYXJyaWFnZSBpbmNyZWFzZXMgd2l0aCBoYXBwaW5lc3MgYW5kIGFnZS4NCi0gTWFycmllZCBpbmRpdmlkdWFscyByZW1haW4gbWFycmllZC4gSW5kaXZpZHVhbHMgb3ZlciA2NSBhcmUgcmVtb3ZlZCAoVGhleSBtb3ZlIHRvIFNwYWluLikNCg0KYGBge3J9DQojIFNpbXVsYXRlIGRhdGENCmQgPC0gc2ltX2hhcHBpbmVzcyggc2VlZD0xOTc3ICwgTl95ZWFycz0xMDAwICkNCg0KcHJlY2lzKGQpDQpgYGANCg0KIyMgUGxvdHRpbmcgdGhlIERhdGENCg0KYGBge3J9DQojIFBsb3QgaGFwcGluZXNzIHZzLiBhZ2UsIGNvbG9yZWQgYnkgbWFycmlhZ2Ugc3RhdHVzDQpwbG90KCBkJGFnZSAsIGQkaGFwcGluZXNzICwgY29sPWQkbWFycmllZCsxICwgcGNoPTE2ICwNCiAgICAgIHhsYWI9IkFnZSIgLCB5bGFiPSJIYXBwaW5lc3MiICkNCmxlZ2VuZCggInRvcGxlZnQiICwgbGVnZW5kPWMoIk5vdCBNYXJyaWVkIiwiTWFycmllZCIpICwgcGNoPTE2ICwgY29sPTE6MiApDQpgYGANCiMjIE9ic2VydmF0aW9uDQotIEhhcHBpbmVzcyBpcyB1bmNvcnJlbGF0ZWQgd2l0aCBhZ2UuDQotIE1hcnJpYWdlIGlzIGFzc29jaWF0ZWQgd2l0aCBib3RoIGFnZSBhbmQgaGFwcGluZXNzLCBjcmVhdGluZyB0aGUgYXBwZWFyYW5jZSBvZiBhIHJlbGF0aW9uc2hpcC4NCg0KIyMgTXVsdGlwbGUgUmVncmVzc2lvbjogQ29uZGl0aW9uaW5nIG9uIE1hcnJpYWdlDQoNCiMjIyBNb2RlbCBEZWZpbml0aW9uDQoqKkxpbmVhciBtb2RlbCoqOg0KLSBcKCBcbXVfaSA9IFxhbHBoYV97TUlEW2ldfSArIFxiZXRhX0EgXHRpbWVzIEFfaSBcKQ0KLSBcKCBNSURbaV0gXCk6IE1hcnJpYWdlIHN0YXR1cyBpbmRleC4NCg0KKipSZXNjYWxlIGFnZSAoXCggQSBcKSkgZm9yIGFkdWx0cyAoMTjigJM2NSkqKjoNCi0gXCggQSA9IFxmcmFje1x0ZXh0e2FnZX0gLSAxOH17NjUgLSAxOH0gXCkNCg0KDQpgYGB7cn0NCiMgUmVzY2FsZSBhZ2UNCmQyIDwtIGRbIGQkYWdlPjE3ICwgXSAjIG9ubHkgYWR1bHRzDQoNCmQyJEEgPC0gKCBkMiRhZ2UtIDE4ICkgLyAoIDY1LSAxOCApDQoNCmBgYA0KDQojIyBNb2RlbCBGaXR0aW5nDQoNCmBgYHtyfQ0KIyBDcmVhdGUgbWFycmlhZ2Ugc3RhdHVzIGluZGV4IHZhcmlhYmxlDQpkMiRNSUQgPC0gZDIkbWFycmllZCArIDENCg0KIyBGaXQgdGhlIG1vZGVsDQptNi45IDwtIHF1YXAoDQogIGFsaXN0KA0KICAgIGhhcHBpbmVzcyB+IGRub3JtKCBtdSAsIHNpZ21hICkgLA0KICAgIG11IDwtIGFbTUlEXSArIGJBICogQSAsDQogICAgYVtNSURdIH4gZG5vcm0oIDAgLCAxICkgLA0KICAgIGJBIH4gZG5vcm0oIDAgLCAyICkgLA0KICAgIHNpZ21hIH4gZGV4cCggMSApDQogICkgLA0KICBkYXRhPWQyDQopDQoNCnByZWNpcyhtNi45LCBkZXB0aD0yKQ0KYGBgDQoNCiMjIE91dHB1dDoNCi0gVGhlIG1vZGVsIHN1Z2dlc3RzIGEgbmVnYXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiBhZ2UgYW5kIGhhcHBpbmVzcywgd2hpY2ggaXMgc3B1cmlvdXMgZHVlIHRvIGNvbGxpZGVyIGJpYXMuDQotIENvbmRpdGlvbmluZyBvbiBtYXJyaWFnZSBzdGF0dXMgaW5kdWNlcyBhIHN0YXRpc3RpY2FsIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgaGFwcGluZXNzLg0KDQoNCiMjIFJlZ3Jlc3Npb24gV2l0aG91dCBDb25kaXRpb25pbmcgb24gTWFycmlhZ2UNCg0KYGBge3J9DQojIEZpdCB0aGUgbW9kZWwgd2l0aG91dCBtYXJyaWFnZSBzdGF0dXMNCm02LjEwIDwtIHF1YXAoDQogIGFsaXN0KA0KICAgIGhhcHBpbmVzcyB+IGRub3JtKCBtdSAsIHNpZ21hICkgLA0KICAgIG11IDwtIGEgKyBiQSAqIEEgLA0KICAgIGEgfiBkbm9ybSggMCAsIDEgKSAsDQogICAgYkEgfiBkbm9ybSggMCAsIDIgKSAsDQogICAgc2lnbWEgfiBkZXhwKCAxICkNCiAgKSAsDQogIGRhdGE9ZDINCikNCg0KcHJlY2lzKG02LjEwLCBkZXB0aD0xKQ0KYGBgDQoNCiMjIE91dHB1dDoNCi0gV2l0aG91dCBjb25kaXRpb25pbmcgb24gXCggTSBcKSwgdGhlIG1vZGVsIGZpbmRzIG5vIGFzc29jaWF0aW9uIGJldHdlZW4gYWdlIGFuZCBoYXBwaW5lc3MsIHJlZmxlY3RpbmcgdGhlIHRydWUgY2F1c2FsIG1vZGVsLg0KDQoNCkl04oCZcyBlYXN5IHRvIHBsZWFkIHdpdGggdGhpcyBleGFtcGxlLiBTaG91bGRu4oCZdCBtYXJyaWFnZSBhbHNvIGluZmx1ZW5jZSBoYXBwaW5lc3M/IFdoYXQgaWYgaGFwcGluZXNzIGRvZXMgY2hhbmdlIHdpdGggYWdlPyBCdXQgdGhpcyBtaXNzZXMgdGhlIHBvaW50LiBJZiB5b3UgZG9u4oCZdCBoYXZlIGEgY2F1c2FsIG1vZGVsLCB5b3UgY2Fu4oCZdCBtYWtlIGluZmVyZW5jZXMgZnJvbSBhIG11bHRpcGxlIHJlZ3Jlc3Npb24uIEFuZCB0aGUgcmVncmVzc2lvbiBpdHNlbGYgZG9lcyBub3QgcHJvdmlkZSB0aGUgZXZpZGVuY2UgeW91IG5lZWQgdG8ganVzdGlmeSBhIGNhdXNhbCBtb2RlbC4gSW5zdGVhZCwgeW91IG5lZWQgc29tZSBzY2llbmNlLg0KDQojIyBLZXkgVGFrZWF3YXlzDQotICoqQ29sbGlkZXIgQmlhcyoqOg0KICAtIENvbmRpdGlvbmluZyBvbiBhIGNvbGxpZGVyIGNyZWF0ZXMgbWlzbGVhZGluZyBhc3NvY2lhdGlvbnMgYmV0d2VlbiBpdHMgY2F1c2VzLg0KICAtIEluIHRoZSBtYXJyaWFnZSBleGFtcGxlLCBjb25kaXRpb25pbmcgb24gXCggTSBcKSBpbmR1Y2VzIGEgc3B1cmlvdXMgcmVsYXRpb25zaGlwIGJldHdlZW4gXCggQSBcKSBhbmQgXCggSCBcKS4NCg0KLSAqKkRBR3MgQ2xhcmlmeSBDYXVzYWwgUmVsYXRpb25zaGlwcyoqOg0KICAtIERBR3MgaGVscCBpZGVudGlmeSBjb2xsaWRlcnMgYW5kIHByZXZlbnQgaW5jb3JyZWN0IHZhcmlhYmxlIHNlbGVjdGlvbi4NCg0KLSAqKkNhdXNhbCBJbmZlcmVuY2UgUmVxdWlyZXMgYSBNb2RlbCoqOg0KICAtIFdpdGhvdXQgYSBjYXVzYWwgbW9kZWwsIG11bHRpcGxlIHJlZ3Jlc3Npb24gY2Fubm90IGp1c3RpZnkgaW5mZXJlbmNlcy4NCg0KLSAqKlByYWN0aWNhbCBBZHZpY2UqKjoNCiAgLSBBdm9pZCBjb25kaXRpb25pbmcgb24gY29sbGlkZXJzIHRvIHByZXZlbnQgc3B1cmlvdXMgYXNzb2NpYXRpb25zLg0KDQojIyBUYWtlLUhvbWUgTWVzc2FnZXMNCg0KIyMjIEtleSBMZXNzb25zOg0KLSAqKkNhdXNhbCBVbmRlcnN0YW5kaW5nIGlzIENydWNpYWwqKjoNCiAgLSBTdGF0aXN0aWNhbCBtb2RlbHMgY2Fubm90IHJlcGxhY2UgYSB0aG91Z2h0ZnVsIGNhdXNhbCBmcmFtZXdvcmsuDQogIC0gREFHcyBwcm92aWRlIGEgd2F5IHRvIHN0cnVjdHVyZSBhbmQgY29tbXVuaWNhdGUgYXNzdW1wdGlvbnMuDQoNCi0gKipTZWxlY3Rpb24gYW5kIENvbGxpZGVyIEJpYXMqKjoNCiAgLSBDb25kaXRpb25pbmcgb24gY29sbGlkZXJzIGNyZWF0ZXMgbWlzbGVhZGluZyBhc3NvY2lhdGlvbnMuDQogIC0gRXhhbXBsZXMgbGlrZSBtYXJyaWFnZSBpbiB0aGUgaGFwcGluZXNzIHN0dWR5IG9yIGZ1bmd1cyBpbiB0aGUgcGxhbnQgZ3Jvd3RoIGV4YW1wbGUgZGVtb25zdHJhdGUgdGhpcy4NCg0KLSAqKkF2b2lkIE92ZXItQ29uZGl0aW9uaW5nKio6DQogIC0gQWRkaW5nIHZhcmlhYmxlcyB3aXRob3V0IGEgY2F1c2FsIHBlcnNwZWN0aXZlIGNhbiBtYXNrIG9yIGRpc3RvcnQgdHJ1ZSByZWxhdGlvbnNoaXBzLg0KDQotICoqTXVsdGljb2xsaW5lYXJpdHkqKjoNCiAgLSBQcmVkaWN0b3JzIHdpdGggc2hhcmVkIGluZm9ybWF0aW9uIGNhbiBsZWFkIHRvIHdpZGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMuDQogIC0gSW50ZXJwcmV0YWJpbGl0eSBzdWZmZXJzLCBldmVuIGlmIHByZWRpY3Rpb24gaXMgc3RpbGwgZWZmZWN0aXZlLg0KDQotICoqVGhpbmsgQ2F1c2FsbHksIE5vdCBKdXN0IFN0YXRpc3RpY2FsbHkqKjoNCiAgLSBSZWdyZXNzaW9uIG1vZGVscyBhbnN3ZXIgdGhlIHF1ZXN0aW9ucyB5b3UgYXNr4oCUZW5zdXJlIHlvdXIgcXVlc3Rpb24gcmVmbGVjdHMgeW91ciByZXNlYXJjaCBnb2Fscy4NCg0K