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

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

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)

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:

  1. Calculate the Mean and Standard Deviation: For each predictor variable.
  2. 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)

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)

Diagnosing Multicollinearity

pairs( ~ kcal.per.g + perc.fat + perc.lactose , data=d , col=rangi2 )

Dodgy Procedures for Multicollinearity

  • In some fields, a common but flawed approach to handling multicollinearity involves:
    1. Inspecting pairwise correlations between predictors.
    2. 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

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:
      1. Initial height (\(H_0\)): Pre-treatment height.
      2. Final height (\(H_1\)): Post-treatment height.
      3. Treatment (\(T\)): Soil treatment.
      4. 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:

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:

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:

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:

Key Takeaways

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

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

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

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:

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:

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

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