Introduction

Overview & Purpose

This document is intended to give an intuitive sense of how PCA works, and why certain pre-processing steps are necessary. Many implementations of PCA provide options to perform these pre-processing steps.

All analysis here is performed in R, with the help of several packages.

The Data

I will be using the mtcars dataset built-in to R. For our purposes, we will only be looking at 3 variables: weight (wt), horsepower (hp), and fuel efficiency mpg. Here is what they look like.

Sample Plot

The Goal

Let’s assume that the goal of this is to create a model that predicts mpg based on weight and power.

Regressions

Multiple Linear Regressions

Keeping the goal in mind, one approach would be to create a simple linear regression.

\(y = mx + b\)

Where:

  • \(y\): mpg
  • \(m\): slope
  • \(b\): intercept
  • \(x\): independent variable (weight or power)

Since we have 2 predictors (weight and power), then we could make 2 separate linear regressions, and choose whichever one has a better fit to be our predictor.

Weight

Power

Between these two regressions (click the tabs), weight looks like it may be a better predictor than power based on \(r^2\).

Wouldn’t it be nice to have a model that creates a regression on both at the same time?


Multilinear Regression

Multilinear regression (MLR) does exactly this. The formula in our case would be: \(y=m_1x_1 + m_2x_2 + b\)

Where:

  • \(y\): mpg
  • \(x_1\): weight
  • \(m_1\): coefficient for weight
  • \(x_2\): power
  • \(m_2\): coefficient for power
  • \(b\): intercept

After performing this fit, here is the resulting MLR.

y =-3.59*weight + -0.03*hp + 36.59
r squared = 0.8

We can see that this is a better model than either of the individual linear regressions.

But imagine if you have a very large number of predictors. There would have to be a term for each one. This is one of many reasons why we may want to perform dimension reduction. This will reduce the number of predictors so that the regression model is simplified.


Takeaways

  • We can build linear regression models based on each predictor
  • A multilinear regression model based on all predictors seems to be a better fit
  • Multilinear regression has more terms than regular linear regression

Projections

Although our dataset already has very few predictors (2), it can be used to illustrate the logic of dimension reduction very well.

So, lets go about reducing the number of predictors from 2 to 1.


Correlated Predictors

Let’s go back to a plot of our 2 predictors.

It is quite apparent that these two predictors are correlated. As weight increases, power generally increases too.

Another way to put it is that if we know the weight, we know something about the power, and vice-versa. This can be referred to as redundancy (i.e. similar information is represented by multiple variables). Of course the relationship isn’t perfect – we cannot predict power with perfect accuracy based on weight.


Least Squares Regression

One way that we can see the correlation is with least-squares regression. This is what we generally mean when we say “linear regression”, and is the method that was used in the previous section on MLR.

Least-squares regression finds the line that minimizes the magnitude of the (squared) errors. But is it important to note that it is defining errors based only on the \(y\) values, i.e. the difference between the actual \(y\) values and the predicted \(y\) values. These errors can be visualized as vertical lines.

While the fact that least-squares regression is based on “vertical” errors may seem subtle, it can have certain implications, as we will see later.


Regression Line as a New Axis?

Getting back to the objective: reducing our 2 predictors to 1.

This may not be an immediately obvious choice, but what if we converted our 2 predictors into 1 by taking the regression line to be a new axis.

Each point could then be represented by a single number: how far along the regression line that point lies.

To see how far along the regression line a point lies, we can draw a line segment that is perpendicular to the regression line, connecting the point to the regression line.

Before we try this with our dataset, let me illustrate the idea with some made up data.

In this case, we could ignore our original 2 variables and instead use a simplified variable: the distance along the regression line where each point projects, as indicated by the blue lines. Since the original variables (\(x\) and \(y\)) were correlated, this new variable still captures the information pretty well.

One thing to note though is that not all information is preserved. For instance the points at \((1.28, 1.95)\) and \((1.63, 1.54)\) project to nearly the same point on the regression line. So with just this 1 dimension, the difference between these points is greatly reduced.


With this ideal example in mind, let’s do the same to our car data. Let’s add perpendicular lines connecting the regression line and the points to illustrate the new axis.

You may think, “Those are not perpendicular to the regression line!”. They actually are, but because the scale on the 2 axes are so different, they don’t look like it.


We can visualize the same plot with both axes to the same scale, but then we can’t even see the lines. The magnitude of our vertical axis is just too much greater than our horizontal axis.

The Problem of Scale

Looking at the last plot, we can see that if we use this technique, then when we project the points to the regression line, the variable with smaller magnitude doesn’t really seem to matter. Effectively, our new axis based on the regression line is pretty much the same as just using the power or \(y\) axis as our predictor.

The reality of this can be seen in this way. The regression line and vertical axis are pretty much parallel. So, when projecting to the regression line, it is about the same as projecting just to the vertical axis, and ignoring the other variable (weight).

So if we were to use this regression line as our new axis for dimension reduction, we would pretty much just be taking our new variable to be the power and ignore the weight variable.


Rescaling

While the above commentary may make it seem like this approach is doomed, it actually shows something very different. Yes, it is true that this method is sensitive to the scale of the predictors, but the scale is actually quite arbitrary.

Let’s look at the weight axis in the above plots. As noted, these are in units of 1000 lb. So a weight of 5 is actually 5000 lb, for example.

I can easily adjust my data so that the \(x\) axis is in units of lb, which is completely valid. But this certainly affects the scale of the axis, and also our perception of the projection to the regression line.

Normal axis scaling

Equal Axis Scales

Role Reversed

Now, instead of the lines that are perpendicular to the regression line looking horizontal, they look vertical. This is because the \(x\) axis now has greater magnitude.

Additionally, the regression line is more parallel to the \(x\) axis. So if we were to project onto this regression line, our new variable would mostly reflect the weight as a predictor.


Takeaways:

  • The scaling of the axes is arbitrary
  • Axis scales strongly affect how our predictor variables would be represented in a new variable based on projection to a regression line.

Rescaling

The reason that when the fake data were projected to the new axis (regression line) worked so well is that I intentionally gave each variable a similar scale (0 to 5).

So, in order to make this proposed method of dimension reduction work, we need to ensure that each variable is equally scaled.We can rest assured that this is okay, since we have already demonstrated that scale is arbitrary (\(1000\ lb\) vs \(lb\)).

We could, for instance, pick a value for each variable by which we would divide each value. By choosing the right number for each, they could have the same scale. But how would you choose this value? Trial and error? Spray and pray?

There is actually a more robust method of rescaling. We can divide the values of each variable by that variable’s standard deviation. If the values of each variable are at least kind of normally distributed, they will have similar scale. Let’s take a look at the results of this.


Replotting

Now that the data are rescaled, the projections to the regression line are looking good!

Going back to the overall goal: we are trying to create a regression model to predict mpg based on a single variable that captures the information of the 2 original variables weight and power.

To do this, I will create a new variable which I will call reg, which is the distance along the regression line where each point projects. This can be seen as the where the blue lines touch the regression line in the plot above.

For now, I am doing this based on geometry (thank you Pythagoras).

So now, each point is represented by the single variable reg. We can plot this variable against mpg since this is the variable we want to predict based on our new single predictor variable, reg.

We can now perform a linear regression on the above plot to see how well our new variable predicts fuel efficiency.

It is actually impressive! We have reduced the number of predictor variables, yet the correlation is the same as or stronger than:

  • Linear regression based on power (\(r^2=0.625\))
  • Linear regression based on weight (\(r^2=0.703\))
  • Multilinear regression based on both weight and hp (\(r^2=0.8\))

Of course, this is only a single observation, so we can’t be sure if the difference is significant. Still, it is interesting.


Takeaways

  • Each variable can be rescaled by dividing by its standard deviation
  • Once each variable is rescaled, they have equal magnitude
  • Each variable then contributes equally to the new axis
  • This new single variable effectively captures the information of both original variables leading to similar predictive strength

Orthogonal Regression

New Coordinate System

To review: our new variable reg is the projection of our data onto a linear regression line of the re-scaled weight and hp variables. This regression was performed using ordinary least-squares, which minimizes the errors in the \(y\) direction.

So far, we have only looked at the single new variable, represented by the projection. But even in this new coordinate system, we can look at it as having 2 dimensions:

  • \(x\): regression line axis
  • \(y\): axis perpendicular to regression line.

The new \(y\) axis coordinate can be seen as the distance a point is from the new \(x\) axis, the regression line. These distances are shown in blue here.

We can plot the same points in this new rotated coordinate system.

I will now refer to the regression axis as reg1 and the perpendicular axis as reg2.


Persistent Correlation

It may (or may not) seem odd that these new variables are still correlated!

The strangeness may be more apparent when you think about why we took this approach in the first place. We realized our variables were correlated, so a projection to a regression line summarized both variables pretty well.

Since they’re still correlated, we could do this same process again. And again..

Clearly, these variables are less correlated though than the original variables (weight and hp). We would expect this to be the case because the regression on the original variables should have had points distributed evenly above and below the regression line. After all, isn’t that the whole idea of regression?

So given that last fact, why are they still correlated?

It comes down to how we performed the regression. As mentioned, we used ordinary least-squares regression, which minimizes the vertical errors. By contrast, it did not minimize the real (perpendicular) distances from the regression line.

This is problematic in a few ways:

  • Firstly, it means that this method is dependent on which variable you put on which axis when performing regression. This is undesirable, because you have to be cautious and choosy to get the “best” results. Imagine brute-force comparing thousands of variable order combinations!
  • Second, it means that our new variables are still (potentially) correlated. This seems harmless, but it opens the idea of, why not do the method again. When do you decide to stop?

Orthogonal Regression

One way around this is to perform a different kind of linear regression. Orthogonal (a.k.a total least-square or Deming) regression minimizes the errors orthogonal (perpendicular) to the regression line.

Below, I have shown both types of regression. The errors which are minimized for each method are shown in blue. I have also performed the projection to the different regression lines, and plotted the data in the new coordinate system.

Regressions

It is apparent that the regression lines are very different in each case.

New Coordinates

We can see that the new coordinates based on orthogonal regression are uncorrelated as indicated by the horizontal regression line and \(r^2=0\). The variables based on ordinary regression are only weakly correlated, but the regression line is obviously not horizontal.


Checking Predictor

Now that we have been able to find a better regression model to project to, let’s see how this new variable predicts fuel efficiency. For the regressions shown below ordinary least squares regression is used at this point, since we are trying to predict fuel efficiency based on our new variable. ortho and ordinary in the titles indicate the regression method used for generating the independent variable.

The correlation seems to be about the same as the variable made from ordinary regression projection. While there is no obvious improvement, all the previous commentary on the benefit of orthogonal regression still holds.


Takeaways

  • Ordinary least-square regression is inappropriate as a new axis for a few reasons:
    • Minimizes vertical errors
    • Dependent on which variable is on which axis
    • New variables are still correlated
  • Orthogonal regression is advantageous:
    • Variable order does not matter
    • New variables are uncorrelated
  • Rescaling still matters

Eigenvectors

So far we have explored 2 methods of finding a new axis to which we can project:

  • Ordinary least-squares regression
  • Orthogonal least-squares regression

We began with regressions since these intuitively follow directions of variance. However, a more efficient method is to find the eigenvectors of the covariance matrix between the variables. These eigenvectors will serve as the new axes for data projection, similar to how the regression lines were used.

This process is effectively the same as the orthogonal regression projection, but is much simpler to perform, since matrix operations are more concise than performing regression and projection based on geometries.

Since it is pretty much the same process, we will still be computing on the scaled data, as this method is still sensitive to variable magnitude.


Calculating the Eigenvectors

Firstly, we compute the covariance matrix of our variables. For two variables, that is:

\[\begin{bmatrix}Cov(x,x) & Cov(x,y)\\ Cov(y,x) & Cov(y,y)\end{bmatrix}\]

The main diagonal contains the variances of the individual variables since \(Cov(a,a)=Var(a)\), while off-diagonal values are the covariances between variables. Notice that each individual variable has a variance of 1. This is because we have already divided by the standard deviation during rescaling.

        hp_norm wt_norm
hp_norm    1.00    0.66
wt_norm    0.66    1.00

Next, we calculate the eigen-decomposition of the covariance matrix. This gives two eigenvalues each associated with an eigenvector. The number of eigen values and eigenvectors is always equal to the number of input variables.

The largest eigenvalue represents the direction of maximum variance, which is analogous to our orthogonal regression line.

eigen() decomposition
$values
[1] 1.6647411 0.3352589

$vectors
          [,1]       [,2]
[1,] 0.7071068 -0.7071068
[2,] 0.7071068  0.7071068

Another great thing about this method over orthogonal regression projection is that we now have more information about our transformation. For instance, we can see the amount of variance explained by each of our new axes.

The total variance is given by the sum of the eigenvalues (\(\lambda\)): \[total\ variance\ = \sum_{i=1}^{N} \lambda_i\] So, the portion of the total variance “explained” by each of our new axes associated with each eigenvalue is given as \[portion\ of\ variance = \frac{\lambda}{total\ variance}\]


Projecting to the New Axes

Now that we have the eigen-decomposition, we can project to our new axes. This again is done with matrix operations as:

\[New\ data=Eigen\ vectors^T*Original\ data^T\]

I will call our new axes \(eig1\) and \(eig2\), not to be confused with the eigen values \(\lambda_1\) and \(\lambda_2\).


Notice how our new feature space created through eigenvector projection is qualitatively identical to the orthogonal regression projection. While the center and scale of the axes are not identical, we can see they are perfectly correlated.

This shows that performing projection to an orthogonal regression line is essentially the same as projecting to the eigenvectors. So while eigenvectors and matrix operations may sound confusing, as long as the orthogonal regression projection makes sense, you can think of the eigenvector projection as just another mathematical way to do the same thing.

New Axes

Correlation

Principal Component Analysis

Now, for the big reveal you have all been waiting for: What we just did is … drumroll please … principal component analysis!

Orthogonal regression line = dominant eigenvector direction = first principal axis

Orthogonal residual direction = secondary eigenvector direction = second principal axis

So, behind the scenes of these fancy principal component functions, they are really just projecting to the directions given by the eigenvectors, which is pretty much the same as our orthogonal regression projections.

So, let’s take a look at the similarities between our eigenvector projections and the principal components found using the R function, prcomp().

New Coordinates

Correlation

Something Isn’t Right

Uh-oh. Why are they not perfectly correlated?

So far, we have performed re-scaling as a pre-pocessing step, because we saw the undesirable effects that occur when our variables have different magnitudes.

Now we are seeing another effect that our variables are having on PCA.

To make the final steps work, we will explore how re-centering was not necessary for orthogonal regression projection, but is necessary for PCA.


Takeaways

  • The directions given by the eigenvectors of the covariance matrix are equivalent to the orthogonal regression projection axes
  • The eigenvalues associated with each eigenvector represent the amount of variance in that direction
  • The directions given by the eigenvectors are referred to as principal axes
  • PCA is sensitive the re-centering, which we will explore further

Recentering

Previously, our orthogonal regression line had a non-zero intercept. This meant that the regression performed well no matter “where” our rescaled data were. However, PCA builds the new axes through the origin by definition.

To illustrate the issue with this, we can build an orthogonal regression with the constraint that the intercept be zero (i.e. the regression line passes through the origin). This simulates how principal components are chosen.

Now, we can project to this new regression line. I will call our new axes that result from this projection ortho_no_1 and ortho_no_2.

Here is ortho_no_1 plotted against PC1.

Now we have perfectly recapitulated Principal Component Analysis by projecting to an orthogonal regression line.

However, by performing the orthogonal regression through the origin, we actually lose a lot of sensitivity to the data.


Loss of Sensitivity

When we force orthogonal regression to pass through the origin, the line is fully defined by just two points: the origin \((0,0)\) and the centroid of the data \((\bar{x}, \bar{y})\). This is not a very good representation of the data due to these restrictions.

To illustrate this, I can show what the first principal component (or orthogonal regression with fixed zero intercept) looks like on some fake data. As mentioned, the fit solely depends on the intercept and centroid, and ignoreS the actual slope of the data.


Recentering

With this in mind, we have to consider our constraints. As I stated, principal axes (via matrix operations) always pass through the origin. So, we cannot get around that aspect when moving from orthogonal regression to principal component analysis.

But recall how we rescaled our data to improve the regression performance?

Now, we can do something similar. It can be shown that orthogonal regression, as well as principal components always pass through the centroid, which is the mean of each variable \((\bar{x}, \bar{y})\).

So what if we performed some operation on our data such that the centroid is at the origin? Then we no longer need to limit the fit of the regression just to ensure that the line passes through the origin, as it will naturally do so.

We can do that by subtracting the mean of each variable from each point. Recall that our rescaling operation was dividing each point by the standard deviation of each variable. Now if we both rescale (divide by \(\sigma\)) and recenter (subtract \(\bar{x}\)) the equation for transforming each variable is:

\(X=\frac{x-\bar{x}}{\sigma}\)

But keep in mind that \(x\) is referring to any variable, not just the variable on the \(x\) axis.


Standardization

The above equation may look familiar. Indeed, it is the equation of a \(z\)-score to convert data to a standard normal distribution. In the standard normal distribution:

  • The standard deviation is 1, which for us means that each variable contributes equally to the regression for projection
  • The mean is 0, which means that the orthogonal regression can be optimal while passing through the origin as is necessary for PCA.

When the data are standardized, here is what they look like


Dimension Reduction of Standardized Variables

Using the standardized variables, we can compare (a) the projection to orthogonal regression and (b) PCA.

Projections

Correlation


Conclusion

When the data are standardized, then orthogonal regression projection is identical to PCA.


Takeaways

  • Principal components always pass through the origin, which limits their fit to uncentered data
  • We can center data by converting to \(z\)-score, which allows PCA to optimally fit the data
  • PCA is identical to projection to an orthogonal regression, once data have been standardized

Summary

We have taken a road trip to fundamentally understanding principal component analysis.

Motivation

There are a variety of reasons for performing dimension reduction, including simplifying the overall model by reducing the number of variables.

Some variables may be correlated, so there is a redundancy in their information. This makes itself apparent in that if you know the value of one correlated variable, you can predict the value of the other variable. Converting these correlated variables into a single new variable seems like a good choice for reducing the number of variables while retaining information.

Projection to Linear Regression

Since linear regressions follow the pattern of correlated variables, we could project to a linear regression as a single new variable representing the original correlated variables.

However, ordinary least-squares regression is dependent on variable order. You will get a different axis dependent on which variable is on each axis.

Orthogonal regression (a.k.a. Deming or Total Least Squares regression) is independent of variable order, and is a better choice.

Additionally, when projecting to ordinary least-squares regression, the resulting variables may still be correlated. The resultant variables from projection to orthogonal regression are not.

Since PCA is essentially the same as this approach, there is a catch. As mentioned, the new resulting axes are uncorrelated by definition. If all the original variables are correlated, then only the first principal axis has any meaning. For this reason, exploratory data analysis is crucial to see which original variables are correlated. If they all are, then PCA is not advisable beyond the first principal component.

Standardization

We need to standardize our variables for PCA for a few reasons.

  • When variables have different magnitudes, the larger magnitude variable(s) dominate the new axis.
  • When variables are uncentered, PCA is completely insensitive to slope, and is only defined by the centroid.

We can negate the above concerns by standardizing each variable by converting to a \(z\)-score.

\(z=\frac{x-\bar{x}}{\sigma}\).

It should be noted that this method works best for normally distributed variables. PCA performance can be improved by pre-processing data to become approximately normally distributed before standardization. For instance, if your data are log-normally distributed, you may want to first take the \(\log\) of your variable before calculating \(z\)-score.

Since standardization is so crucial, most functions that are implementations of PCA in various programming languages (R, Python, etc.) have an option to perform centering and rescaling automatically. However, these operations are generally optimal for normally distributed data but the functions do not check this assumption. For this reason it is best to check for normality (e.g. with a Q-Q plot), and if they are not normal, perform your own pre-processing.

Eigen Decomposition

The orthogonal regression follows the direction of maximum variance of the variables. This direction can be calculated by eigen decomposition. This yields:

  • Eigen vectors: which indicate the direction(s) of maximum variance
  • Eigen values: which indicate the amount of total variance represented by the corresponding eigen vector

PCA is performed using eigen decomposition. This gives more information than simply projecting to the orthogonal regression lines (e.g. amount of variance represented by the new axes).


Back to The Predictive Model

We started this journey by trying to predict vehicle fuel efficiency from weight and power. After doing some linear regressions on the variables independently, and then with multilinear regression, we decided to try dimension reduction to capture the effect of both weight and power in a single variable.

So to wrap it up, let’s take look at predicting fuel efficiency based on the first principal component

It seems that for this example case, mutlilinear regression is a better way of predicting fuel efficiency from the original two variables. And maybe that is the final lesson. This project showed us intuitively how PCA works. But in our case it was not necessary since we had so few variables, and actually made the performance worse. Sometimes “simpler” models like MLR are better!

Hopefully this has shown how PCA works. Now you may better understand how and why we preprocess data, what the variance measures indicate, and when PCA may actually be detrimental to model performance.

LS0tDQp0aXRsZTogIkV4cGxhaW5lZDogUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KYXV0aG9yOiBLZW5uZXRoIFNjaGFja2FydCAoc2NoYWNrYXJ0azFAZ21haWwuY29tKQ0KLS0tDQoNCiMgey50YWJzZXR9DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShicm9vbSkgICAgICAjIHRpZHkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShncmlkRXh0cmEpICAjIFNpZGUgYnkgc2lkZSBwbG90cw0KbGlicmFyeShodXJ3aXR6TGFiKSAjIENvbG9yIHBhbGV0dGVzDQpsaWJyYXJ5KE1ldGhDb21wKSAgICMgRGVtaW5nIHJlZ3Jlc3Npb24NCmxpYnJhcnkocGFyc25pcCkNCmxpYnJhcnkocHVycnIpICAgICAgI21hcA0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0aWJibGUpDQpsaWJyYXJ5KHRpZHlyKQ0KDQpzb3VyY2UoImhlbHBlcnMuUiIpDQoNCnRoZW1lX3NldCh0aGVtZV9saWdodCgpICsNCiAgICAgICAgICAgIHRoZW1lKA0KICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICAgICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkNCiAgICAgICAgICAgICkpDQpgYGANCg0KIyMgSW50cm9kdWN0aW9uDQoNCiMjIyBPdmVydmlldyAmIFB1cnBvc2UNCg0KVGhpcyBkb2N1bWVudCBpcyBpbnRlbmRlZCB0byBnaXZlIGFuIGludHVpdGl2ZSBzZW5zZSBvZiBob3cgUENBIHdvcmtzLCBhbmQgd2h5IGNlcnRhaW4gcHJlLXByb2Nlc3Npbmcgc3RlcHMgYXJlIG5lY2Vzc2FyeS4gTWFueSBpbXBsZW1lbnRhdGlvbnMgb2YgUENBIHByb3ZpZGUgb3B0aW9ucyB0byBwZXJmb3JtIHRoZXNlIHByZS1wcm9jZXNzaW5nIHN0ZXBzLg0KDQpBbGwgYW5hbHlzaXMgaGVyZSBpcyBwZXJmb3JtZWQgaW4gUiwgd2l0aCB0aGUgaGVscCBvZiBzZXZlcmFsIHBhY2thZ2VzLg0KDQojIyMgVGhlIERhdGENCg0KSSB3aWxsIGJlIHVzaW5nIHRoZSBtdGNhcnMgZGF0YXNldCBidWlsdC1pbiB0byBSLiBGb3Igb3VyIHB1cnBvc2VzLCB3ZSB3aWxsIG9ubHkNCmJlIGxvb2tpbmcgYXQgMyB2YXJpYWJsZXM6IHdlaWdodCAoYHd0YCksIGhvcnNlcG93ZXIgKGBocGApLCBhbmQgZnVlbCBlZmZpY2llbmN5IGBtcGdgLiAgSGVyZSBpcyB3aGF0IHRoZXkgbG9vayBsaWtlLg0KDQpgYGB7ciBkYXRhX3NlbGVjdCwgZWNobz1GQUxTRX0NCmRmIDwtIG10Y2FycyAlPiUgc2VsZWN0KG1wZywgd3QsIGhwKQ0KDQpzZXQuc2VlZCgzNDU2KQ0KdHJhaW5JbmRleCA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKGRmJG1wZywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwID0gLjgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVzID0gMSkNCnRyYWluIDwtIGRmW3RyYWluSW5kZXgsIF0NCnRlc3QgPC0gZGZbLXRyYWluSW5kZXgsIF0NCg0KdHJhaW4NCmBgYA0KDQojIyMgU2FtcGxlIFBsb3QNCg0KYGBge3IgcmF3X3Bsb3QsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQp0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gd3QsIHkgPSBocCwgY29sb3IgPSBtcGcpKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsDQogICAgICAgICAgICAgIHNlID0gRkFMU0UsDQogICAgICAgICAgICAgIGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJsaWdodF9ncmF5IikpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgc2NhbGVfY29sb3JfaHVyd2l0eihkaXNjcmV0ZSA9IEZBTFNFLCBwYWxldHRlID0gImNsYXNzaWMiKSArDQogIGxhYnMoDQogICAgeCA9ICJXZWlnaHQgKDEwMDAgbGIpIiwNCiAgICB5ID0gIlBvd2VyIChocCkiLA0KICAgIGNvbG9yID0gIkZ1ZWwgRWZmaWNpZW5jeSAobXBnKSIsDQogICAgdGl0bGUgPSAiU2NhdHRlcnBsb3Qgb2YgbXRjYXJzIg0KICApDQpgYGANCiMjIyBUaGUgR29hbA0KDQpMZXQncyBhc3N1bWUgdGhhdCB0aGUgZ29hbCBvZiB0aGlzIGlzIHRvIGNyZWF0ZSBhIG1vZGVsIHRoYXQgcHJlZGljdHMgYG1wZ2AgYmFzZWQNCm9uIGB3ZWlnaHRgIGFuZCBgcG93ZXJgLg0KDQoNCiMjIFJlZ3Jlc3Npb25zDQoNCiMjIyBNdWx0aXBsZSBMaW5lYXIgUmVncmVzc2lvbnMgey50YWJzZXR9DQoNCktlZXBpbmcgdGhlIGdvYWwgaW4gbWluZCwgb25lIGFwcHJvYWNoIHdvdWxkIGJlIHRvIGNyZWF0ZSBhIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbi4NCg0KJHkgPSBteCArIGIkDQoNCldoZXJlOg0KDQoqICR5JDogYG1wZ2ANCiogJG0kOiBzbG9wZQ0KKiAkYiQ6IGludGVyY2VwdA0KKiAkeCQ6IGluZGVwZW5kZW50IHZhcmlhYmxlIChgd2VpZ2h0YCBvciBgcG93ZXJgKQ0KDQpgYGB7ciBsbSwgZWNobz1GQUxTRX0NCmxtX21vZGVsIDwtIGxpbmVhcl9yZWcoKSAlPiUNCiAgc2V0X2VuZ2luZSgibG0iKSAlPiUNCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQ0KYGBgDQoNClNpbmNlIHdlIGhhdmUgMiBwcmVkaWN0b3JzIChgd2VpZ2h0YCBhbmQgYHBvd2VyYCksIHRoZW4gd2UgY291bGQgbWFrZSAyIHNlcGFyYXRlDQpsaW5lYXIgcmVncmVzc2lvbnMsIGFuZCBjaG9vc2Ugd2hpY2hldmVyIG9uZSBoYXMgYSBiZXR0ZXIgZml0IHRvIGJlIG91ciBwcmVkaWN0b3IuDQoNCmBgYHtyIG11bHRpcGxlX3JlZ3Jlc3Npb25zLCBlY2hvPUZBTFNFfQ0KcmVnIDwtIGxpc3QoKQ0KcGx0IDwtIGxpc3QoKQ0KDQpyZWckbXBnX3d0IDwtIGxtX21vZGVsICU+JSBmaXQobXBnIH4gd3QsIGRhdGEgPSB0cmFpbikNCg0KcmVnJG1wZ19ocCA8LSBsbV9tb2RlbCAlPiUgZml0KG1wZyB+IGhwLCBkYXRhID0gdHJhaW4pDQpgYGANCg0KIyMjIyBXZWlnaHQNCg0KYGBge3Igd3RfbW9kZWwsIGVjaG89RkFMU0V9DQp0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gd3QsIHkgPSBtcGcpKSArDQogIGdlb21fYWJsaW5lKA0KICAgIHNsb3BlID0gZ2V0X2NvZWYocmVnJG1wZ193dCwgInd0IiksDQogICAgaW50ZXJjZXB0ID0gZ2V0X2NvZWYocmVnJG1wZ193dCksDQogICAgY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoImxpZ2h0X2dyYXkiKSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJNUEcgdnMgV2VpZ2h0IiwNCiAgICBzdWJ0aXRsZSA9IHN0cl9nbHVlKCJyIHNxdWFyZWQgPSB7Z2V0X3JzcShyZWckbXBnX3d0LCAzKX0iKSwNCiAgICB4ID0gIldlaWdodCAoMTAwMCBsYikiLA0KICAgIHkgPSAiRnVlbCBFZmZpY2llbmN5IChtcGcpIg0KICApDQpgYGANCg0KIyMjIyBQb3dlcg0KDQpgYGB7ciBocF9tb2RlbCwgZWNobz1GQUxTRX0NCnRyYWluICU+JSBnZ3Bsb3QoYWVzKHggPSBocCwgeSA9IG1wZykpICsNCiAgZ2VvbV9hYmxpbmUoDQogICAgc2xvcGUgPSBnZXRfY29lZihyZWckbXBnX2hwLCAiaHAiKSwNCiAgICBpbnRlcmNlcHQgPSBnZXRfY29lZihyZWckbXBnX2hwKSwNCiAgICBjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygibGlnaHRfZ3JheSIpLA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk1QRyB2cyBQb3dlciIsDQogICAgc3VidGl0bGUgPSBzdHJfZ2x1ZSgiciBzcXVhcmVkID0ge2dldF9yc3EocmVnJG1wZ19ocCwgMyl9IiksDQogICAgeCA9ICJQb3dlciAoaHApIiwNCiAgICB5ID0gIkZ1ZWwgRWZmaWNpZW5jeSAobXBnKSINCiAgKQ0KYGBgDQoNCkJldHdlZW4gdGhlc2UgdHdvIHJlZ3Jlc3Npb25zIChjbGljayB0aGUgdGFicyksIHdlaWdodCBsb29rcyBsaWtlIGl0IG1heSBiZSBhIGJldHRlciBwcmVkaWN0b3IgdGhhbiBwb3dlciBiYXNlZCBvbiAkcl4yJC4NCg0KV291bGRuJ3QgaXQgYmUgbmljZSB0byBoYXZlIGEgbW9kZWwgdGhhdCBjcmVhdGVzIGEgcmVncmVzc2lvbiBvbiBib3RoIGF0IHRoZSBzYW1lIHRpbWU/DQoNCi0tLQ0KDQojIyMgTXVsdGlsaW5lYXIgUmVncmVzc2lvbg0KDQpNdWx0aWxpbmVhciByZWdyZXNzaW9uIChNTFIpIGRvZXMgZXhhY3RseSB0aGlzLiBUaGUgZm9ybXVsYSBpbiBvdXIgY2FzZSB3b3VsZCBiZToNCiR5PW1fMXhfMSArIG1fMnhfMiArIGIkDQoNCldoZXJlOg0KDQoqICR5JDogYG1wZ2ANCiogJHhfMSQ6IGB3ZWlnaHRgDQoqICRtXzEkOiBjb2VmZmljaWVudCBmb3IgYHdlaWdodGANCiogJHhfMiQ6IGBwb3dlcmANCiogJG1fMiQ6IGNvZWZmaWNpZW50IGZvciBgcG93ZXJgDQoqICRiJDogaW50ZXJjZXB0DQoNCkFmdGVyIHBlcmZvcm1pbmcgdGhpcyBmaXQsIGhlcmUgaXMgdGhlIHJlc3VsdGluZyBNTFIuIA0KDQpgYGB7ciByZWdyZXNzaW9uLCBlY2hvPUZBTFNFfQ0KcmVnJG1wZ19hbGwgPC0gIGxtX21vZGVsICU+JQ0KICBmaXQobXBnIH4gLiwgZGF0YSA9IHRyYWluKQ0KDQpwcmludCgNCiAgc3RyX2dsdWUoDQogICAgInkgPSIsDQogICAgIntyb3VuZChnZXRfY29lZihyZWckbXBnX2FsbCwgJ3d0JyksIDIpfSp3ZWlnaHQiLA0KICAgICIgKyAiLA0KICAgICJ7cm91bmQoZ2V0X2NvZWYocmVnJG1wZ19hbGwsICdocCcpLCAyKX0qaHAiLA0KICAgICIgKyAiLA0KICAgICJ7cm91bmQoZ2V0X2NvZWYocmVnJG1wZ19hbGwpLCAyKX0iDQogICkNCikNCnByaW50KHN0cl9nbHVlKCJyIHNxdWFyZWQgPSAiLA0KICAgICAgICAgICAgICAgIntnZXRfcnNxKHJlZyRtcGdfYWxsLCAzKX0iKSkNCmBgYA0KDQpXZSBjYW4gc2VlIHRoYXQgdGhpcyBpcyBhIGJldHRlciBtb2RlbCB0aGFuIGVpdGhlciBvZiB0aGUgaW5kaXZpZHVhbCBsaW5lYXIgcmVncmVzc2lvbnMuDQoNCkJ1dCBpbWFnaW5lIGlmIHlvdSBoYXZlIGEgdmVyeSBsYXJnZSBudW1iZXIgb2YgcHJlZGljdG9ycy4gVGhlcmUgd291bGQgaGF2ZSB0byBiZSBhIHRlcm0gZm9yIGVhY2ggb25lLiBUaGlzIGlzIG9uZSBvZiBtYW55IHJlYXNvbnMgd2h5IHdlIG1heSB3YW50IHRvIHBlcmZvcm0gZGltZW5zaW9uIHJlZHVjdGlvbi4gVGhpcyB3aWxsIHJlZHVjZSB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgc28gdGhhdCB0aGUgcmVncmVzc2lvbiBtb2RlbCBpcyBzaW1wbGlmaWVkLg0KDQotLS0NCg0KKlRha2Vhd2F5cyoNCg0KKiBXZSBjYW4gYnVpbGQgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWxzIGJhc2VkIG9uIGVhY2ggcHJlZGljdG9yDQoqIEEgbXVsdGlsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBiYXNlZCBvbiBhbGwgcHJlZGljdG9ycyBzZWVtcyB0byBiZSBhIGJldHRlciBmaXQNCiogTXVsdGlsaW5lYXIgcmVncmVzc2lvbiBoYXMgbW9yZSB0ZXJtcyB0aGFuIHJlZ3VsYXIgbGluZWFyIHJlZ3Jlc3Npb24NCg0KIyMgUHJvamVjdGlvbnMNCg0KQWx0aG91Z2ggb3VyIGRhdGFzZXQgYWxyZWFkeSBoYXMgdmVyeSBmZXcgcHJlZGljdG9ycyAoMiksIGl0IGNhbiBiZSB1c2VkIHRvIGlsbHVzdHJhdGUgdGhlIGxvZ2ljIG9mIGRpbWVuc2lvbiByZWR1Y3Rpb24gdmVyeSB3ZWxsLg0KDQpTbywgbGV0cyBnbyBhYm91dCByZWR1Y2luZyB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgZnJvbSAyIHRvIDEuDQoNCi0tLSANCg0KIyMjIENvcnJlbGF0ZWQgUHJlZGljdG9ycw0KDQpMZXQncyBnbyBiYWNrIHRvIGEgcGxvdCBvZiBvdXIgMiBwcmVkaWN0b3JzLg0KDQpgYGB7ciBjb3JyX3Bsb3QsIGVjaG89RkFMU0V9DQp0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gd3QsIHkgPSBocCkpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicyh4ID0gIldlaWdodCAoMTAwMCBsYikiLA0KICAgICAgIHkgPSAiUG93ZXIgKGhwKSIsDQogICAgICAgdGl0bGUgPSAiQ29ycmVsYXRlZCBQcmVkaWN0b3JzIikNCmBgYA0KDQpJdCBpcyBxdWl0ZSBhcHBhcmVudCB0aGF0IHRoZXNlIHR3byBwcmVkaWN0b3JzIGFyZSBjb3JyZWxhdGVkLiBBcyB3ZWlnaHQgaW5jcmVhc2VzLCBwb3dlciBnZW5lcmFsbHkgaW5jcmVhc2VzIHRvby4NCg0KQW5vdGhlciB3YXkgdG8gcHV0IGl0IGlzIHRoYXQgaWYgd2Uga25vdyB0aGUgd2VpZ2h0LCB3ZSBrbm93ICpzb21ldGhpbmcqIGFib3V0IHRoZSBwb3dlciwgYW5kIHZpY2UtdmVyc2EuIFRoaXMgY2FuIGJlIHJlZmVycmVkIHRvIGFzICpyZWR1bmRhbmN5KiAoKmkuZS4qIHNpbWlsYXIgaW5mb3JtYXRpb24gaXMgcmVwcmVzZW50ZWQgYnkgbXVsdGlwbGUgdmFyaWFibGVzKS4gT2YgY291cnNlIHRoZSByZWxhdGlvbnNoaXAgaXNuJ3QgcGVyZmVjdCAtLSB3ZSBjYW5ub3QgcHJlZGljdCBwb3dlciB3aXRoIHBlcmZlY3QgYWNjdXJhY3kgYmFzZWQgb24gd2VpZ2h0Lg0KDQotLS0NCg0KIyMjIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbg0KDQpPbmUgd2F5IHRoYXQgd2UgY2FuIHNlZSB0aGUgY29ycmVsYXRpb24gaXMgd2l0aCBsZWFzdC1zcXVhcmVzIHJlZ3Jlc3Npb24uIFRoaXMgaXMgd2hhdCB3ZSBnZW5lcmFsbHkgbWVhbiB3aGVuIHdlIHNheSAibGluZWFyIHJlZ3Jlc3Npb24iLCBhbmQgaXMgdGhlIG1ldGhvZCB0aGF0IHdhcyB1c2VkIGluIHRoZSBwcmV2aW91cyBzZWN0aW9uIG9uIE1MUi4NCg0KTGVhc3Qtc3F1YXJlcyByZWdyZXNzaW9uIGZpbmRzIHRoZSBsaW5lIHRoYXQgbWluaW1pemVzIHRoZSBtYWduaXR1ZGUgb2YgdGhlIChzcXVhcmVkKSBlcnJvcnMuIEJ1dCBpcyBpdCBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IGl0IGlzIGRlZmluaW5nIGVycm9ycyBiYXNlZCBvbmx5IG9uIHRoZSAkeSQgdmFsdWVzLCBpLmUuIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGFjdHVhbCAkeSQgdmFsdWVzIGFuZCB0aGUgcHJlZGljdGVkICR5JCB2YWx1ZXMuIFRoZXNlIGVycm9ycyBjYW4gYmUgdmlzdWFsaXplZCBhcyB2ZXJ0aWNhbCBsaW5lcy4NCg0KYGBge3IgcHJlZF9yZWcsIGVjaG89RkFMU0V9DQpyZWckaHBfd3QgPC0gbG1fbW9kZWwgJT4lIA0KICBmaXQoaHAgfiB3dCwgZGF0YT10cmFpbikNCmBgYA0KDQpgYGB7ciB2ZXJ0X2JhcnMsIGVjaG89RkFMU0V9DQp0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gd3QsIHkgPSBocCkpICsNCiAgZ2VvbV9zZWdtZW50KGFlcyh4ZW5kID0gd3QsIHllbmQgPSBocCAtIHJlZyRocF93dCRmaXQkcmVzaWR1YWxzKSwNCiAgICAgICAgICAgICAgIGNvbG91ciA9IGdldF9odXJ3aXR6X2NvbG9ycygidmlraW5nIikpICsNCiAgZ2VvbV9hYmxpbmUoDQogICAgc2xvcGUgPSBnZXRfY29lZihyZWckaHBfd3QsICJ3dCIpLA0KICAgIGludGVyY2VwdCA9IGdldF9jb2VmKHJlZyRocF93dCksDQogICAgY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoImxpZ2h0X2dyYXkiKSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicyh4ID0gIldlaWdodCAoMTAwMCBsYikiLA0KICAgICAgIHkgPSAiUG93ZXIgKGhwKSIsDQogICAgICAgdGl0bGUgPSAiTGVhc3QtU3F1YXJlcyBSZWdyZXNzaW9uIikNCmBgYA0KDQpXaGlsZSB0aGUgZmFjdCB0aGF0IGxlYXN0LXNxdWFyZXMgcmVncmVzc2lvbiBpcyBiYXNlZCBvbiAidmVydGljYWwiIGVycm9ycyBtYXkgc2VlbSBzdWJ0bGUsIGl0IGNhbiBoYXZlIGNlcnRhaW4gaW1wbGljYXRpb25zLCBhcyB3ZSB3aWxsIHNlZSBsYXRlci4NCg0KLS0tDQoNCiMjIyBSZWdyZXNzaW9uIExpbmUgYXMgYSBOZXcgQXhpcz8NCg0KR2V0dGluZyBiYWNrIHRvIHRoZSBvYmplY3RpdmU6IHJlZHVjaW5nIG91ciAyIHByZWRpY3RvcnMgdG8gMS4NCg0KVGhpcyBtYXkgbm90IGJlIGFuIGltbWVkaWF0ZWx5IG9idmlvdXMgY2hvaWNlLCBidXQgd2hhdCBpZiB3ZSBjb252ZXJ0ZWQgb3VyIDIgcHJlZGljdG9ycyBpbnRvIDEgYnkgdGFraW5nIHRoZSByZWdyZXNzaW9uIGxpbmUgdG8gYmUgYSBuZXcgYXhpcy4NCg0KRWFjaCBwb2ludCBjb3VsZCB0aGVuIGJlIHJlcHJlc2VudGVkIGJ5IGEgc2luZ2xlIG51bWJlcjogaG93IGZhciBhbG9uZyB0aGUgcmVncmVzc2lvbiBsaW5lIHRoYXQgcG9pbnQgbGllcy4NCg0KVG8gc2VlIGhvdyBmYXIgYWxvbmcgdGhlIHJlZ3Jlc3Npb24gbGluZSBhIHBvaW50IGxpZXMsIHdlIGNhbiBkcmF3IGEgbGluZSBzZWdtZW50IHRoYXQgaXMgcGVycGVuZGljdWxhciB0byB0aGUgcmVncmVzc2lvbiBsaW5lLCBjb25uZWN0aW5nIHRoZSBwb2ludCB0byB0aGUgcmVncmVzc2lvbiBsaW5lLg0KDQpCZWZvcmUgd2UgdHJ5IHRoaXMgd2l0aCBvdXIgZGF0YXNldCwgbGV0IG1lIGlsbHVzdHJhdGUgdGhlIGlkZWEgd2l0aCBzb21lIG1hZGUgdXAgZGF0YS4NCg0KYGBge3IgcGVycHMsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTV9DQpkZl9mYWtlIDwtIHRpYmJsZSgNCiAgeCA9IGMoDQogICAgMC4yMywNCiAgICAwLjcxLA0KICAgIDEuMDIsDQogICAgMS4yOCwNCiAgICAxLjYzLA0KICAgIDEuODcsDQogICAgMS45OCwNCiAgICAyLjM0LA0KICAgIDIuOCwNCiAgICAzLjIsDQogICAgMy41NiwNCiAgICAzLjksDQogICAgNC41LA0KICAgIDQuNjUNCiAgKSwNCiAgeSA9IGMoDQogICAgMC42MiwNCiAgICAwLjg5LA0KICAgIDAuOTksDQogICAgMS45NSwNCiAgICAxLjU0LA0KICAgIDIuMDcsDQogICAgMi4xMiwNCiAgICAyLjk1LA0KICAgIDIuMiwNCiAgICAzLjgsDQogICAgMy42LA0KICAgIDMuNDMsDQogICAgNC4xLA0KICAgIDQuOTQNCiAgKQ0KKQ0KDQpyZWckaWRlYWwgPC0gbG1fbW9kZWwgJT4lDQogIGZpdCh5IH4geCwgZGF0YSA9IGRmX2Zha2UpDQoNCnNlZ21lbnRzIDwtIHBlcnBfc2VnbWVudF9jb29yZChkZl9mYWtlJHgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZfZmFrZSR5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldF9jb2VmKHJlZyRpZGVhbCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0X2NvZWYocmVnJGlkZWFsLCAieCIpKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCmRmX2Zha2UgJT4lIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YSA9IHNlZ21lbnRzLA0KICAgICAgICAgICAgICAgYWVzKA0KICAgICAgICAgICAgICAgICB4ID0geDAsDQogICAgICAgICAgICAgICAgIHkgPSB5MCwNCiAgICAgICAgICAgICAgICAgeGVuZCA9IHgxLA0KICAgICAgICAgICAgICAgICB5ZW5kID0geTENCiAgICAgICAgICAgICAgICksDQogICAgICAgICAgICAgICBjb2xvdXIgPSBnZXRfaHVyd2l0el9jb2xvcnMoInZpa2luZyIpKSArDQogIGdlb21fYWJsaW5lKA0KICAgIHNsb3BlID0gZ2V0X2NvZWYocmVnJGlkZWFsLCAieCIpLA0KICAgIGludGVyY2VwdCA9IGdldF9jb2VmKHJlZyRpZGVhbCksDQogICAgY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoImxpZ2h0X2dyYXkiKSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgeGxpbShjKDAsIDUpKSArIHlsaW0oYygwLCA1KSkgKw0KICBsYWJzKHRpdGxlID0gIkZha2UgRGF0YSB3aXRoIFJlZ3Jlc3Npb24gTGluZSIsDQogICAgICAgc3VidGl0bGUgPSAiUGVycGVuZGljdWxhciBsaW5lcyBzaG93IHByb2plY3Rpb24gdG8gbmV3IGF4aXMiKQ0KDQpybShzZWdtZW50cykNCmBgYA0KDQpJbiB0aGlzIGNhc2UsIHdlIGNvdWxkIGlnbm9yZSBvdXIgb3JpZ2luYWwgMiB2YXJpYWJsZXMgYW5kIGluc3RlYWQgdXNlIGEgc2ltcGxpZmllZCB2YXJpYWJsZTogdGhlIGRpc3RhbmNlIGFsb25nIHRoZSByZWdyZXNzaW9uIGxpbmUgd2hlcmUgZWFjaCBwb2ludCBwcm9qZWN0cywgYXMgaW5kaWNhdGVkIGJ5IHRoZSBibHVlIGxpbmVzLiBTaW5jZSB0aGUgb3JpZ2luYWwgdmFyaWFibGVzICgkeCQgYW5kICR5JCkgd2VyZSBjb3JyZWxhdGVkLCB0aGlzIG5ldyB2YXJpYWJsZSBzdGlsbCBjYXB0dXJlcyB0aGUgaW5mb3JtYXRpb24gcHJldHR5IHdlbGwuDQoNCk9uZSB0aGluZyB0byBub3RlIHRob3VnaCBpcyB0aGF0IG5vdCBhbGwgaW5mb3JtYXRpb24gaXMgcHJlc2VydmVkLiBGb3IgaW5zdGFuY2UgdGhlIHBvaW50cyBhdCAkKDEuMjgsIDEuOTUpJCBhbmQgJCgxLjYzLCAxLjU0KSQgcHJvamVjdCB0byBuZWFybHkgdGhlIHNhbWUgcG9pbnQgb24gdGhlIHJlZ3Jlc3Npb24gbGluZS4gU28gd2l0aCBqdXN0IHRoaXMgMSBkaW1lbnNpb24sIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlc2UgcG9pbnRzIGlzIGdyZWF0bHkgcmVkdWNlZC4NCg0KLS0tDQoNCldpdGggdGhpcyBpZGVhbCBleGFtcGxlIGluIG1pbmQsIGxldCdzIGRvIHRoZSBzYW1lIHRvIG91ciBjYXIgZGF0YS4gTGV0J3MgYWRkIHBlcnBlbmRpY3VsYXIgbGluZXMgY29ubmVjdGluZyB0aGUgcmVncmVzc2lvbiBsaW5lIGFuZCB0aGUgcG9pbnRzIHRvIGlsbHVzdHJhdGUgdGhlIG5ldyBheGlzLg0KDQpgYGB7ciByZWdfYXhpcywgZWNobz1GQUxTRX0NCnBsdCRocF93dCA8LSB0cmFpbiAlPiUgcGxvdF9wZXJwKHggPSAid3QiLCB5ID0gImhwIikgKw0KICBsYWJzKHggPSAiV2VpZ2h0ICgxMDAwIGxiKSIsDQogICAgICAgeSA9ICJQb3dlciAoaHApIiwNCiAgICAgICB0aXRsZSA9ICJSZWdyZXNzaW9uIExpbmUgYXMgTmV3IEF4aXMiKQ0KDQpwbHQkaHBfd3QNCmBgYA0KDQpZb3UgbWF5IHRoaW5rLCAiVGhvc2UgYXJlIG5vdCBwZXJwZW5kaWN1bGFyIHRvIHRoZSByZWdyZXNzaW9uIGxpbmUhIi4gVGhleSBhY3R1YWxseSBhcmUsIGJ1dCBiZWNhdXNlIHRoZSBzY2FsZSBvbiB0aGUgMiBheGVzIGFyZSBzbyBkaWZmZXJlbnQsIHRoZXkgZG9uJ3QgbG9vayBsaWtlIGl0Lg0KDQotLS0NCg0KV2UgY2FuIHZpc3VhbGl6ZSB0aGUgc2FtZSBwbG90IHdpdGggYm90aCBheGVzIHRvIHRoZSBzYW1lIHNjYWxlLCBidXQgdGhlbiB3ZSBjYW4ndCBldmVuIHNlZSB0aGUgbGluZXMuIFRoZSBtYWduaXR1ZGUgb2Ygb3VyIHZlcnRpY2FsIGF4aXMgaXMganVzdCB0b28gbXVjaCBncmVhdGVyIHRoYW4gb3VyIGhvcml6b250YWwgYXhpcy4NCg0KYGBge3IgcmVzY2FsZWRfcmVnX2F4aXMsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTV9DQptYXhfc2NhbGUgPC0gMS4wNSAqIChtYXgodHJhaW4kaHAsIHRyYWluJHd0KSkNCg0KcGx0JGhwX3d0ICsNCiAgeGxpbShjKDAsIG1heF9zY2FsZSkpICsNCiAgeWxpbShjKDAsIG1heF9zY2FsZSkpICsNCiAgbGFicyh0aXRsZSA9ICJFcXVhbGx5IFNjYWxlZCBSZWdyZXNzaW9uIikNCg0Kcm0obWF4X3NjYWxlKQ0KYGBgDQoNCiMjIyBUaGUgUHJvYmxlbSBvZiBTY2FsZQ0KDQpMb29raW5nIGF0IHRoZSBsYXN0IHBsb3QsIHdlIGNhbiBzZWUgdGhhdCBpZiB3ZSB1c2UgdGhpcyB0ZWNobmlxdWUsIHRoZW4gd2hlbiB3ZSBwcm9qZWN0IHRoZSBwb2ludHMgdG8gdGhlIHJlZ3Jlc3Npb24gbGluZSwgdGhlIHZhcmlhYmxlIHdpdGggc21hbGxlciBtYWduaXR1ZGUgZG9lc24ndCByZWFsbHkgc2VlbSB0byBtYXR0ZXIuIEVmZmVjdGl2ZWx5LCBvdXIgbmV3IGF4aXMgYmFzZWQgb24gdGhlIHJlZ3Jlc3Npb24gbGluZSBpcyBwcmV0dHkgbXVjaCB0aGUgc2FtZSBhcyBqdXN0IHVzaW5nIHRoZSBgcG93ZXJgIG9yICR5JCBheGlzIGFzIG91ciBwcmVkaWN0b3IuDQoNClRoZSByZWFsaXR5IG9mIHRoaXMgY2FuIGJlIHNlZW4gaW4gdGhpcyB3YXkuIFRoZSByZWdyZXNzaW9uIGxpbmUgYW5kIHZlcnRpY2FsIGF4aXMgYXJlIHByZXR0eSBtdWNoIHBhcmFsbGVsLiBTbywgd2hlbiBwcm9qZWN0aW5nIHRvIHRoZSByZWdyZXNzaW9uIGxpbmUsIGl0IGlzIGFib3V0IHRoZSBzYW1lIGFzIHByb2plY3RpbmcganVzdCB0byB0aGUgdmVydGljYWwgYXhpcywgYW5kIGlnbm9yaW5nIHRoZSBvdGhlciB2YXJpYWJsZSAoYHdlaWdodGApLg0KDQpTbyBpZiB3ZSB3ZXJlIHRvIHVzZSB0aGlzIHJlZ3Jlc3Npb24gbGluZSBhcyBvdXIgbmV3IGF4aXMgZm9yIGRpbWVuc2lvbiByZWR1Y3Rpb24sIHdlIHdvdWxkIHByZXR0eSBtdWNoIGp1c3QgYmUgdGFraW5nIG91ciBuZXcgdmFyaWFibGUgdG8gYmUgdGhlIGBwb3dlcmAgYW5kIGlnbm9yZSB0aGUgYHdlaWdodGAgdmFyaWFibGUuDQoNCi0tLQ0KDQojIyMgUmVzY2FsaW5nIHsudGFic2V0fQ0KDQpXaGlsZSB0aGUgYWJvdmUgY29tbWVudGFyeSBtYXkgbWFrZSBpdCBzZWVtIGxpa2UgdGhpcyBhcHByb2FjaCBpcyBkb29tZWQsIGl0IGFjdHVhbGx5IHNob3dzIHNvbWV0aGluZyB2ZXJ5IGRpZmZlcmVudC4gWWVzLCBpdCBpcyB0cnVlIHRoYXQgdGhpcyBtZXRob2QgaXMgc2Vuc2l0aXZlIHRvIHRoZSBzY2FsZSBvZiB0aGUgcHJlZGljdG9ycywgYnV0IHRoZSBzY2FsZSBpcyBhY3R1YWxseSBxdWl0ZSBhcmJpdHJhcnkuDQoNCkxldCdzIGxvb2sgYXQgdGhlIGB3ZWlnaHRgIGF4aXMgaW4gdGhlIGFib3ZlIHBsb3RzLiBBcyBub3RlZCwgdGhlc2UgYXJlIGluIHVuaXRzIG9mIDEwMDAgbGIuIFNvIGEgd2VpZ2h0IG9mIDUgaXMgYWN0dWFsbHkgNTAwMCBsYiwgZm9yIGV4YW1wbGUuDQoNCkkgY2FuIGVhc2lseSBhZGp1c3QgbXkgZGF0YSBzbyB0aGF0IHRoZSAkeCQgYXhpcyBpcyBpbiB1bml0cyBvZiBsYiwgd2hpY2ggaXMgY29tcGxldGVseSB2YWxpZC4gQnV0IHRoaXMgY2VydGFpbmx5IGFmZmVjdHMgdGhlIHNjYWxlIG9mIHRoZSBheGlzLCBhbmQgYWxzbyBvdXIgcGVyY2VwdGlvbiBvZiB0aGUgcHJvamVjdGlvbiB0byB0aGUgcmVncmVzc2lvbiBsaW5lLg0KDQojIyMjIE5vcm1hbCBheGlzIHNjYWxpbmcNCg0KYGBge3IsIGVjaG89RkFMU0V9DQp0cmFpbiR3dF9sYiA8LSB0cmFpbiR3dCAqIDEwMDANCg0KcGx0JGhwX3d0X2xiIDwtIHRyYWluICU+JSBwbG90X3BlcnAoeCA9ICJ3dF9sYiIsIHkgPSAiaHAiKSArDQogIGxhYnMoDQogICAgeCA9ICJXZWlnaHQgKGxiKSIsDQogICAgeSA9ICJQb3dlciAoaHApIiwNCiAgICB0aXRsZSA9ICJSZWdyZXNzaW9uIExpbmUgYXMgTmV3IEF4aXMsIFJlc2NhbGVkIFdlaWdodCIsDQogICAgc3VidGl0bGUgPSAiTGluZXMgYXJlIHBlcnBpbmRpY3VsYXIgdG8gcmVncmVzc2lvbiBsaW5lIg0KICApDQoNCnBsdCRocF93dF9sYg0KYGBgDQojIyMjIEVxdWFsIEF4aXMgU2NhbGVzDQoNCmBgYHtyIGVxX2F4ZXMsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTV9DQptYXhfc2NhbGUgPC0gbWF4KHRyYWluJHd0X2xiLCB0cmFpbiRocCkNCg0KcGx0JGhwX3d0X2xiICsNCiAgeGxpbShjKDAsIG1heF9zY2FsZSkpICsNCiAgeWxpbShjKDAsIG1heF9zY2FsZSkpICsNCiAgbGFicyhzdWJ0aXRsZSA9ICIiLA0KICAgICAgIHRpdGxlID0gIlJlc2NhbGVkIFdlaWdodCwgQXhlcyBTY2FsZWQgRXF1YWxseSIpDQoNCnJtKG1heF9zY2FsZSkNCmBgYA0KDQojIyMgUm9sZSBSZXZlcnNlZA0KDQpOb3csIGluc3RlYWQgb2YgdGhlIGxpbmVzIHRoYXQgYXJlIHBlcnBlbmRpY3VsYXIgdG8gdGhlIHJlZ3Jlc3Npb24gbGluZSBsb29raW5nIGhvcml6b250YWwsIHRoZXkgbG9vayB2ZXJ0aWNhbC4gVGhpcyBpcyBiZWNhdXNlIHRoZSAkeCQgYXhpcyBub3cgaGFzIGdyZWF0ZXIgbWFnbml0dWRlLg0KDQpBZGRpdGlvbmFsbHksIHRoZSByZWdyZXNzaW9uIGxpbmUgaXMgbW9yZSBwYXJhbGxlbCB0byB0aGUgJHgkIGF4aXMuIFNvIGlmIHdlIHdlcmUgdG8gcHJvamVjdCBvbnRvIHRoaXMgcmVncmVzc2lvbiBsaW5lLCBvdXIgbmV3IHZhcmlhYmxlIHdvdWxkIG1vc3RseSByZWZsZWN0IHRoZSBgd2VpZ2h0YCBhcyBhIHByZWRpY3Rvci4NCg0KLS0tDQoNCipUYWtlYXdheXM6Kg0KDQoqIFRoZSBzY2FsaW5nIG9mIHRoZSBheGVzIGlzIGFyYml0cmFyeQ0KKiBBeGlzIHNjYWxlcyBzdHJvbmdseSBhZmZlY3QgaG93IG91ciBwcmVkaWN0b3IgdmFyaWFibGVzIHdvdWxkIGJlIHJlcHJlc2VudGVkIGluIGEgbmV3IHZhcmlhYmxlIGJhc2VkIG9uIHByb2plY3Rpb24gdG8gYSByZWdyZXNzaW9uIGxpbmUuDQoNCiMjIFJlc2NhbGluZw0KDQpUaGUgcmVhc29uIHRoYXQgd2hlbiB0aGUgZmFrZSBkYXRhIHdlcmUgcHJvamVjdGVkIHRvIHRoZSBuZXcgYXhpcyAocmVncmVzc2lvbiBsaW5lKSB3b3JrZWQgc28gd2VsbCBpcyB0aGF0IEkgaW50ZW50aW9uYWxseSBnYXZlIGVhY2ggdmFyaWFibGUgYSBzaW1pbGFyIHNjYWxlICgwIHRvIDUpLg0KDQpTbywgaW4gb3JkZXIgdG8gbWFrZSB0aGlzIHByb3Bvc2VkIG1ldGhvZCBvZiBkaW1lbnNpb24gcmVkdWN0aW9uIHdvcmssIHdlIG5lZWQgdG8gZW5zdXJlIHRoYXQgZWFjaCB2YXJpYWJsZSBpcyBlcXVhbGx5IHNjYWxlZC5XZSBjYW4gcmVzdCBhc3N1cmVkIHRoYXQgdGhpcyBpcyBva2F5LCBzaW5jZSB3ZSBoYXZlIGFscmVhZHkgZGVtb25zdHJhdGVkIHRoYXQgc2NhbGUgaXMgYXJiaXRyYXJ5ICgkMTAwMFwgbGIkIHZzICRsYiQpLg0KDQpXZSBjb3VsZCwgZm9yIGluc3RhbmNlLCBwaWNrIGEgdmFsdWUgZm9yIGVhY2ggdmFyaWFibGUgYnkgd2hpY2ggd2Ugd291bGQgZGl2aWRlIGVhY2ggdmFsdWUuIEJ5IGNob29zaW5nIHRoZSByaWdodCBudW1iZXIgZm9yIGVhY2gsIHRoZXkgY291bGQgaGF2ZSB0aGUgc2FtZSBzY2FsZS4gQnV0IGhvdyB3b3VsZCB5b3UgY2hvb3NlIHRoaXMgdmFsdWU/IFRyaWFsIGFuZCBlcnJvcj8gU3ByYXkgYW5kIHByYXk/DQoNClRoZXJlIGlzIGFjdHVhbGx5IGEgbW9yZSByb2J1c3QgbWV0aG9kIG9mIHJlc2NhbGluZy4gV2UgY2FuIGRpdmlkZSB0aGUgdmFsdWVzIG9mIGVhY2ggdmFyaWFibGUgYnkgdGhhdCB2YXJpYWJsZSdzIHN0YW5kYXJkIGRldmlhdGlvbi4gSWYgdGhlIHZhbHVlcyBvZiBlYWNoIHZhcmlhYmxlIGFyZSBhdCBsZWFzdCBraW5kIG9mIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB0aGV5IHdpbGwgaGF2ZSBzaW1pbGFyIHNjYWxlLiBMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgcmVzdWx0cyBvZiB0aGlzLg0KDQpgYGB7ciBub3JtLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD01fQ0KdHJhaW4kaHBfbm9ybSA8LSB0cmFpbiRocCAvIHNkKHRyYWluJGhwKQ0KdHJhaW4kd3Rfbm9ybSA8LSB0cmFpbiR3dCAvIHNkKHRyYWluJHd0KQ0KDQptYXhfc2NhbGUgPC0gdHJhaW4gJT4lIHNlbGVjdChocF9ub3JtLCB3dF9ub3JtKSAlPiUgbWF4KCkNCg0KcGx0JGhwX25vcm1fd3Rfbm9ybSA8LQ0KICB0cmFpbiAlPiUgcGxvdF9wZXJwKHggPSAid3Rfbm9ybSIsIHkgPSAiaHBfbm9ybSIpICsNCiAgbGFicygNCiAgICB4ID0gIlJlc2NhbGVkIFdlaWdodCIsDQogICAgeSA9ICJSZXNjYWxlZCBQb3dlciIsDQogICAgdGl0bGUgPSAiUmVzY2FsZWQgVmFyaWFibGVzIiwNCiAgICBzdWJ0aXRsZSA9ICJWYXJpYWJsZXMgZGl2aWRlZCBieSBpdHMgc3RhbmRhcmQgZGV2aWF0aW9uIg0KICApICsNCiAgbGltcyh4ID0gYygwLCBtYXhfc2NhbGUpLCB5ID0gYygwLCBtYXhfc2NhbGUpKQ0KDQpwbHQkaHBfbm9ybV93dF9ub3JtDQoNCnJtKG1heF9zY2FsZSkNCmBgYA0KDQotLS0NCg0KIyMjIFJlcGxvdHRpbmcNCg0KTm93IHRoYXQgdGhlIGRhdGEgYXJlIHJlc2NhbGVkLCB0aGUgcHJvamVjdGlvbnMgdG8gdGhlIHJlZ3Jlc3Npb24gbGluZSBhcmUgbG9va2luZyBnb29kIQ0KDQpHb2luZyBiYWNrIHRvIHRoZSBvdmVyYWxsIGdvYWw6IHdlIGFyZSB0cnlpbmcgdG8gY3JlYXRlIGEgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IGBtcGdgIGJhc2VkIG9uIGEgc2luZ2xlIHZhcmlhYmxlIHRoYXQgY2FwdHVyZXMgdGhlIGluZm9ybWF0aW9uIG9mIHRoZSAyIG9yaWdpbmFsIHZhcmlhYmxlcyBgd2VpZ2h0YCBhbmQgYHBvd2VyYC4NCg0KVG8gZG8gdGhpcywgSSB3aWxsIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSB3aGljaCBJIHdpbGwgY2FsbCBgcmVnYCwgd2hpY2ggaXMgdGhlIGRpc3RhbmNlIGFsb25nIHRoZSByZWdyZXNzaW9uIGxpbmUgd2hlcmUgZWFjaCBwb2ludCBwcm9qZWN0cy4gVGhpcyBjYW4gYmUgc2VlbiBhcyB0aGUgd2hlcmUgdGhlIGJsdWUgbGluZXMgdG91Y2ggdGhlIHJlZ3Jlc3Npb24gbGluZSBpbiB0aGUgcGxvdCBhYm92ZS4NCg0KRm9yIG5vdywgSSBhbSBkb2luZyB0aGlzIGJhc2VkIG9uIGdlb21ldHJ5ICgqdGhhbmsgeW91IFB5dGhhZ29yYXMqKS4NCg0KU28gbm93LCBlYWNoIHBvaW50IGlzIHJlcHJlc2VudGVkIGJ5IHRoZSBzaW5nbGUgdmFyaWFibGUgYHJlZ2AuIFdlIGNhbiBwbG90IHRoaXMgdmFyaWFibGUgYWdhaW5zdCBgbXBnYCBzaW5jZSB0aGlzIGlzIHRoZSB2YXJpYWJsZSB3ZSB3YW50IHRvIHByZWRpY3QgYmFzZWQgb24gb3VyIG5ldyBzaW5nbGUgcHJlZGljdG9yIHZhcmlhYmxlLCBgcmVnYC4NCg0KYGBge3Igcm90LCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KdHJhaW4gPC0gdHJhaW4gJT4lIHJlZ19jb29yZCh4ID0gInd0X25vcm0iLCB5ID0gImhwX25vcm0iKSAlPiUNCiAgbGVmdF9qb2luKHRyYWluKSAlPiUNCiAgcmVuYW1lKCJyZWcxIiA9IHgsICJyZWcyIiA9IHkpDQoNCnBsdCRtcGdfcmVnMSA8LSB0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gcmVnMSwgeSA9IG1wZykpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicyh4ID0gIk5ldyB2YXJpYWJsZSwgcmVnIiwNCiAgICAgICB5ID0gIkZ1ZWwgRWZmaWNpZW5jeSAobXBnKSIsDQogICAgICAgdGl0bGUgPSAiRnVlbCBFZmZpY2llbmN5IHZzIE5ldyBWYXJpYWJsZSIpDQoNCnBsdCRtcGdfcmVnMQ0KYGBgDQoNCldlIGNhbiBub3cgcGVyZm9ybSBhIGxpbmVhciByZWdyZXNzaW9uIG9uIHRoZSBhYm92ZSBwbG90IHRvIHNlZSBob3cgd2VsbCBvdXIgbmV3IHZhcmlhYmxlIHByZWRpY3RzIGBmdWVsIGVmZmljaWVuY3lgLg0KDQpJdCBpcyBhY3R1YWxseSBpbXByZXNzaXZlISBXZSBoYXZlIHJlZHVjZWQgdGhlIG51bWJlciBvZiBwcmVkaWN0b3IgdmFyaWFibGVzLCB5ZXQgdGhlIGNvcnJlbGF0aW9uIGlzIHRoZSBzYW1lIGFzIG9yIHN0cm9uZ2VyIHRoYW46DQoNCiogTGluZWFyIHJlZ3Jlc3Npb24gYmFzZWQgb24gYHBvd2VyYCAoJHJeMj0wLjYyNSQpDQoqIExpbmVhciByZWdyZXNzaW9uIGJhc2VkIG9uIGB3ZWlnaHRgICgkcl4yPTAuNzAzJCkNCiogTXVsdGlsaW5lYXIgcmVncmVzc2lvbiBiYXNlZCBvbiBib3RoIGB3ZWlnaHRgIGFuZCBgaHBgICgkcl4yPTAuOCQpDQoNCk9mIGNvdXJzZSwgdGhpcyBpcyBvbmx5IGEgc2luZ2xlIG9ic2VydmF0aW9uLCBzbyB3ZSBjYW4ndCBiZSBzdXJlIGlmIHRoZSBkaWZmZXJlbmNlIGlzIHNpZ25pZmljYW50LiBTdGlsbCwgaXQgaXMgaW50ZXJlc3RpbmcuDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KcmVnJG1wZ19yZWcxIDwtIGxtX21vZGVsICU+JQ0KICBmaXQobXBnIH4gcmVnMSwgZGF0YSA9IHRyYWluKQ0KDQpwbHQkbXBnX3JlZzFfZml0IDwtIHRyYWluICU+JSBnZ3Bsb3QoYWVzKHggPSByZWcxLCB5ID0gbXBnKSkgKw0KICBnZW9tX2FibGluZSgNCiAgICBzbG9wZSA9IGdldF9jb2VmKHJlZyRtcGdfcmVnMSwgInJlZzEiKSwNCiAgICBpbnRlcmNlcHQgPSBnZXRfY29lZihyZWckbXBnX3JlZzEpLA0KICAgIGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJsaWdodF9ncmF5IiksDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoInJlZCIpKSArDQogIGxhYnMoDQogICAgeCA9ICJOZXcgdmFyaWFibGUsIHJlZyIsDQogICAgeSA9ICJGdWVsIEVmZmljaWVuY3kgKG1wZykiLA0KICAgIHRpdGxlID0gIkZ1ZWwgRWZmaWNpZW5jeSB2cyBOZXcgVmFyaWFibGUiLA0KICAgIHN1YnRpdGxlID0gc3RyX2dsdWUoInIgc3F1YXJlZCA9ICIsDQogICAgICAgICAgICAgICAgICAgICAgICAie2dldF9yc3EocmVnJG1wZ19yZWcxLCAzKX0iKQ0KICApDQoNCnBsdCRtcGdfcmVnMV9maXQNCmBgYA0KDQotLS0NCg0KKlRha2Vhd2F5cyoNCg0KKiBFYWNoIHZhcmlhYmxlIGNhbiBiZSByZXNjYWxlZCBieSBkaXZpZGluZyBieSBpdHMgc3RhbmRhcmQgZGV2aWF0aW9uDQoqIE9uY2UgZWFjaCB2YXJpYWJsZSBpcyByZXNjYWxlZCwgdGhleSBoYXZlIGVxdWFsIG1hZ25pdHVkZQ0KKiBFYWNoIHZhcmlhYmxlIHRoZW4gY29udHJpYnV0ZXMgZXF1YWxseSB0byB0aGUgbmV3IGF4aXMNCiogVGhpcyBuZXcgc2luZ2xlIHZhcmlhYmxlIGVmZmVjdGl2ZWx5IGNhcHR1cmVzIHRoZSBpbmZvcm1hdGlvbiBvZiBib3RoIG9yaWdpbmFsIHZhcmlhYmxlcyBsZWFkaW5nIHRvIHNpbWlsYXIgcHJlZGljdGl2ZSBzdHJlbmd0aA0KDQoNCiMjIE9ydGhvZ29uYWwgUmVncmVzc2lvbg0KDQojIyMgTmV3IENvb3JkaW5hdGUgU3lzdGVtDQoNClRvIHJldmlldzogb3VyIG5ldyB2YXJpYWJsZSBgcmVnYCBpcyB0aGUgcHJvamVjdGlvbiBvZiBvdXIgZGF0YSBvbnRvIGEgbGluZWFyDQpyZWdyZXNzaW9uIGxpbmUgb2YgdGhlIHJlLXNjYWxlZCBgd2VpZ2h0YCBhbmQgYGhwYCB2YXJpYWJsZXMuIFRoaXMgcmVncmVzc2lvbg0Kd2FzIHBlcmZvcm1lZCB1c2luZyBvcmRpbmFyeSBsZWFzdC1zcXVhcmVzLCB3aGljaCBtaW5pbWl6ZXMgdGhlIGVycm9ycyBpbiB0aGUNCiR5JCBkaXJlY3Rpb24uDQoNClNvIGZhciwgd2UgaGF2ZSBvbmx5IGxvb2tlZCBhdCB0aGUgc2luZ2xlIG5ldyB2YXJpYWJsZSwgcmVwcmVzZW50ZWQgYnkgdGhlDQpwcm9qZWN0aW9uLiBCdXQgZXZlbiBpbiB0aGlzIG5ldyBjb29yZGluYXRlIHN5c3RlbSwgd2UgY2FuIGxvb2sgYXQgaXQgYXMNCmhhdmluZyAyIGRpbWVuc2lvbnM6DQoNCiogJHgkOiByZWdyZXNzaW9uIGxpbmUgYXhpcw0KKiAkeSQ6IGF4aXMgcGVycGVuZGljdWxhciB0byByZWdyZXNzaW9uIGxpbmUuDQoNClRoZSBuZXcgJHkkIGF4aXMgY29vcmRpbmF0ZSBjYW4gYmUgc2VlbiBhcyB0aGUgZGlzdGFuY2UgYSBwb2ludCBpcyBmcm9tIHRoZSBuZXcNCiR4JCBheGlzLCB0aGUgcmVncmVzc2lvbiBsaW5lLiBUaGVzZSBkaXN0YW5jZXMgYXJlIHNob3duIGluIGJsdWUgaGVyZS4NCg0KYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTV9DQpwbHQkaHBfbm9ybV93dF9ub3JtDQpgYGANCg0KV2UgY2FuIHBsb3QgdGhlIHNhbWUgcG9pbnRzIGluIHRoaXMgbmV3ICpyb3RhdGVkKiBjb29yZGluYXRlIHN5c3RlbS4NCg0KSSB3aWxsIG5vdyByZWZlciB0byB0aGUgcmVncmVzc2lvbiBheGlzIGFzIGByZWcxYCBhbmQgdGhlIHBlcnBlbmRpY3VsYXIgYXhpcw0KYXMgYHJlZzJgLg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnBsdCRyZWcyX3JlZzEgPC0gdHJhaW4gJT4lIGdncGxvdChhZXMoeCA9IHJlZzEsIHkgPSByZWcyKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLA0KICAgICAgICAgICAgIGNvbG9yID0gImxpZ2h0Z3JheSIsDQogICAgICAgICAgICAgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicyh0aXRsZSA9ICJSb3RhdGVkIENvb3JkaW5hdGUgU3lzdGVtIFBsb3QiKQ0KDQpwbHQkcmVnMl9yZWcxDQpgYGANCg0KLS0tDQoNCiMjIyBQZXJzaXN0ZW50IENvcnJlbGF0aW9uDQoNCkl0IG1heSAob3IgbWF5IG5vdCkgc2VlbSBvZGQgdGhhdCB0aGVzZSBuZXcgdmFyaWFibGVzIGFyZSBzdGlsbCBjb3JyZWxhdGVkIQ0KDQpUaGUgc3RyYW5nZW5lc3MgbWF5IGJlIG1vcmUgYXBwYXJlbnQgd2hlbiB5b3UgdGhpbmsgYWJvdXQgd2h5IHdlIHRvb2sgdGhpcw0KYXBwcm9hY2ggaW4gdGhlIGZpcnN0IHBsYWNlLiBXZSByZWFsaXplZCBvdXIgdmFyaWFibGVzIHdlcmUgY29ycmVsYXRlZCwNCnNvIGEgcHJvamVjdGlvbiB0byBhIHJlZ3Jlc3Npb24gbGluZSBzdW1tYXJpemVkIGJvdGggdmFyaWFibGVzIHByZXR0eSB3ZWxsLg0KDQpTaW5jZSB0aGV5J3JlIHN0aWxsIGNvcnJlbGF0ZWQsIHdlIGNvdWxkIGRvIHRoaXMgc2FtZSBwcm9jZXNzIGFnYWluLiBBbmQgYWdhaW4uLg0KDQpDbGVhcmx5LCB0aGVzZSB2YXJpYWJsZXMgYXJlIGxlc3MgY29ycmVsYXRlZCB0aG91Z2gNCnRoYW4gdGhlIG9yaWdpbmFsIHZhcmlhYmxlcyAoYHdlaWdodGAgYW5kIGBocGApLiBXZSB3b3VsZCBleHBlY3QgdGhpcyB0byBiZSB0aGUNCmNhc2UgYmVjYXVzZSAqdGhlIHJlZ3Jlc3Npb24gb24gdGhlIG9yaWdpbmFsIHZhcmlhYmxlcyBzaG91bGQgaGF2ZSBoYWQgcG9pbnRzDQpkaXN0cmlidXRlZCBldmVubHkgYWJvdmUgYW5kIGJlbG93IHRoZSByZWdyZXNzaW9uIGxpbmUuKiBBZnRlciBhbGwsIGlzbid0IHRoYXQNCnRoZSB3aG9sZSBpZGVhIG9mIHJlZ3Jlc3Npb24/DQoNClNvIGdpdmVuIHRoYXQgbGFzdCBmYWN0LCB3aHkgYXJlIHRoZXkgc3RpbGwgY29ycmVsYXRlZD8NCg0KSXQgY29tZXMgZG93biB0byBob3cgd2UgcGVyZm9ybWVkIHRoZSByZWdyZXNzaW9uLiBBcyBtZW50aW9uZWQsIHdlIHVzZWQNCm9yZGluYXJ5IGxlYXN0LXNxdWFyZXMgcmVncmVzc2lvbiwgd2hpY2ggbWluaW1pemVzIHRoZSB2ZXJ0aWNhbCBlcnJvcnMuIEJ5IA0KY29udHJhc3QsIGl0IGRpZCBub3QgbWluaW1pemUgdGhlIHJlYWwgKHBlcnBlbmRpY3VsYXIpIGRpc3RhbmNlcyBmcm9tIHRoZQ0KcmVncmVzc2lvbiBsaW5lLg0KDQpUaGlzIGlzIHByb2JsZW1hdGljIGluIGEgZmV3IHdheXM6IA0KDQoqIEZpcnN0bHksIGl0IG1lYW5zIHRoYXQgdGhpcyBtZXRob2QgaXMNCmRlcGVuZGVudCBvbiB3aGljaCB2YXJpYWJsZSB5b3UgcHV0IG9uIHdoaWNoIGF4aXMgd2hlbiBwZXJmb3JtaW5nIHJlZ3Jlc3Npb24uDQpUaGlzIGlzIHVuZGVzaXJhYmxlLCBiZWNhdXNlIHlvdSBoYXZlIHRvIGJlIGNhdXRpb3VzIGFuZCBjaG9vc3kgdG8gZ2V0IHRoZSAiYmVzdCINCnJlc3VsdHMuIEltYWdpbmUgYnJ1dGUtZm9yY2UgY29tcGFyaW5nIHRob3VzYW5kcyBvZiB2YXJpYWJsZSBvcmRlciBjb21iaW5hdGlvbnMhDQoqIFNlY29uZCwgaXQgbWVhbnMgdGhhdCBvdXIgbmV3IHZhcmlhYmxlcyBhcmUgc3RpbGwgKHBvdGVudGlhbGx5KQ0KY29ycmVsYXRlZC4gVGhpcyBzZWVtcyBoYXJtbGVzcywgYnV0IGl0IG9wZW5zIHRoZSBpZGVhIG9mLCB3aHkgbm90IGRvIHRoZSBtZXRob2QNCmFnYWluLiBXaGVuIGRvIHlvdSBkZWNpZGUgdG8gc3RvcD8NCg0KLS0tDQoNCiMjIyBPcnRob2dvbmFsIFJlZ3Jlc3Npb24gey50YWJzZXR9DQoNCk9uZSB3YXkgYXJvdW5kIHRoaXMgaXMgdG8gcGVyZm9ybSBhIGRpZmZlcmVudCBraW5kIG9mIGxpbmVhciByZWdyZXNzaW9uLg0KT3J0aG9nb25hbCAoKmEuay5hKiB0b3RhbCBsZWFzdC1zcXVhcmUgb3IgRGVtaW5nKSByZWdyZXNzaW9uIG1pbmltaXplcyB0aGUNCmVycm9ycyBvcnRob2dvbmFsIChwZXJwZW5kaWN1bGFyKSB0byB0aGUgcmVncmVzc2lvbiBsaW5lLg0KDQpCZWxvdywgSSBoYXZlIHNob3duIGJvdGggdHlwZXMgb2YgcmVncmVzc2lvbi4gVGhlIGVycm9ycyB3aGljaCBhcmUgbWluaW1pemVkIGZvcg0KZWFjaCBtZXRob2QgYXJlIHNob3duIGluIGJsdWUuIEkgaGF2ZSBhbHNvIHBlcmZvcm1lZCB0aGUgcHJvamVjdGlvbiB0byB0aGUNCmRpZmZlcmVudCByZWdyZXNzaW9uIGxpbmVzLCBhbmQgcGxvdHRlZCB0aGUgZGF0YSBpbiB0aGUgbmV3IGNvb3JkaW5hdGUgc3lzdGVtLg0KDQojIyMjIFJlZ3Jlc3Npb25zDQoNCkl0IGlzIGFwcGFyZW50IHRoYXQgdGhlIHJlZ3Jlc3Npb24gbGluZXMgYXJlIHZlcnkgZGlmZmVyZW50IGluIGVhY2ggY2FzZS4NCg0KYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00fQ0KcmVnJGRlbSA8LSBEZW1pbmcodHJhaW4kd3Rfbm9ybSwgdHJhaW4kaHBfbm9ybSkNCg0KcmVnJGhwX25vcm1fd3Rfbm9ybSA8LSBsbV9tb2RlbCAlPiUNCiAgZml0KGhwX25vcm0gfiB3dF9ub3JtLCBkYXRhID0gdHJhaW4pDQoNCmRlbWlfc2VnbWVudHMgPC0gcGVycF9zZWdtZW50X2Nvb3JkKHRyYWluJHd0X25vcm0sIHRyYWluJGhwX25vcm0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWckZGVtWyJJbnRlcmNlcHQiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZyRkZW1bIlNsb3BlIl0pICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KcGxvdCA8LSB0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gd3Rfbm9ybSwgeSA9IGhwX25vcm0pKSArDQogIGxhYnMoeCA9ICJSZXNjYWxlZCBXZWlnaHQiLA0KICAgICAgIHkgPSAiUmVzY2FsZWQgUG93ZXIiKQ0KDQpwbHQkaHBfbm9ybV93dF9ub3JtX3JlZyA8LSBwbG90ICsNCiAgZ2VvbV9hYmxpbmUoDQogICAgc2xvcGUgPSBnZXRfY29lZihyZWckaHBfbm9ybV93dF9ub3JtLCAid3Rfbm9ybSIpLA0KICAgIGludGVyY2VwdCA9IGdldF9jb2VmKHJlZyRocF9ub3JtX3d0X25vcm0pLA0KICAgIGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJsaWdodF9ncmF5IiksDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fc2VnbWVudCgNCiAgICBhZXMoDQogICAgICB4ZW5kID0gd3Rfbm9ybSwNCiAgICAgIHllbmQgPSBocF9ub3JtIC0gcmVnJGhwX25vcm1fd3Rfbm9ybSRmaXQkcmVzaWR1YWxzDQogICAgKSwNCiAgICBjb2xvdXIgPSBnZXRfaHVyd2l0el9jb2xvcnMoInZpa2luZyIpDQogICkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKHRpdGxlID0gIk9yZGluYXJ5IFJlZ3Jlc3Npb24iKQ0KDQpwbHQkaHBfbm9ybV93dF9ub3JtX2RlbSA8LSBwbG90ICsNCiAgZ2VvbV9hYmxpbmUoDQogICAgc2xvcGUgPSByZWckZGVtWyJTbG9wZSJdLA0KICAgIGludGVyY2VwdCA9IHJlZyRkZW1bIkludGVyY2VwdCJdLA0KICAgIGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJsaWdodF9ncmF5IiksDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fc2VnbWVudChkYXRhID0gZGVtaV9zZWdtZW50cywNCiAgICAgICAgICAgICAgIGFlcygNCiAgICAgICAgICAgICAgICAgeCA9IHgwLA0KICAgICAgICAgICAgICAgICB5ID0geTAsDQogICAgICAgICAgICAgICAgIHhlbmQgPSB4MSwNCiAgICAgICAgICAgICAgICAgeWVuZCA9IHkxDQogICAgICAgICAgICAgICApLA0KICAgICAgICAgICAgICAgY29sb3VyID0gZ2V0X2h1cndpdHpfY29sb3JzKCJ2aWtpbmciKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKHRpdGxlID0gIk9ydGhvZ29uYWwgUmVncmVzc2lvbiIsDQogICAgICAgeSA9ICIiKQ0KDQpncmlkLmFycmFuZ2UocGx0JGhwX25vcm1fd3Rfbm9ybV9yZWcsIHBsdCRocF9ub3JtX3d0X25vcm1fZGVtLCBuY29sID0gMikNCg0Kcm0ocGxvdCkNCg0KYGBgDQoNCiMjIyMgTmV3IENvb3JkaW5hdGVzDQoNCldlIGNhbiBzZWUgdGhhdCB0aGUgbmV3IGNvb3JkaW5hdGVzIGJhc2VkIG9uIG9ydGhvZ29uYWwgcmVncmVzc2lvbiBhcmUgDQp1bmNvcnJlbGF0ZWQgYXMgaW5kaWNhdGVkIGJ5IHRoZSBob3Jpem9udGFsIHJlZ3Jlc3Npb24gbGluZQ0KYW5kICRyXjI9MCQuIFRoZSB2YXJpYWJsZXMgYmFzZWQgb24gb3JkaW5hcnkgcmVncmVzc2lvbiBhcmUgb25seSB3ZWFrbHkgY29ycmVsYXRlZCwgYnV0IHRoZSByZWdyZXNzaW9uIGxpbmUgaXMgb2J2aW91c2x5IG5vdCBob3Jpem9udGFsLg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTR9DQpyZWckcmVnMl9yZWcxIDwtIGxtX21vZGVsICU+JQ0KICBmaXQocmVnMiB+IHJlZzEsIGRhdGEgPSB0cmFpbikNCg0KcGx0JHJlZzJfcmVnMV9maXQgPC0gdHJhaW4gJT4lIGdncGxvdChhZXMoeCA9IHJlZzEsIHkgPSByZWcyKSkgKw0KICBnZW9tX2FibGluZSgNCiAgICBzbG9wZSA9IGdldF9jb2VmKHJlZyRyZWcyX3JlZzEsICJyZWcxIiksDQogICAgaW50ZXJjZXB0ID0gZ2V0X2NvZWYocmVnJHJlZzJfcmVnMSksDQogICAgY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoImxpZ2h0X2dyYXkiKSwNCiAgICBzaXplID0gMSwNCiAgICBhbHBoYSA9IDAuNQ0KICApICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicyh0aXRsZSA9ICJSb3RhdGVkIE9yZGluYXJ5IFJlZ3Jlc3Npb24iLA0KICAgICAgIHN1YnRpdGxlID0gc3RyX2dsdWUoInIgc3F1YXJlID0ge2dldF9yc3EocmVnJHJlZzJfcmVnMSwgMyl9IikpDQoNCnRyYWluIDwtIHRyYWluICU+JSBhZGRfY29sdW1uKG9ydGhvMSA9IHNxcnQoKGRlbWlfc2VnbWVudHMkeDEpIF4gMiArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRlbWlfc2VnbWVudHMkeTEgLSByZWckZGVtWyJJbnRlcmNlcHQiXSkgXiAyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ydGhvMiA9IHNxcnQoDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkZW1pX3NlZ21lbnRzJHgxIC0gZGVtaV9zZWdtZW50cyR4MCkgXiAyICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGVtaV9zZWdtZW50cyR5MSAtIGRlbWlfc2VnbWVudHMkeTApIF4gMg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCg0KdHJhaW4gPC0gdHJhaW4gJT4lIG11dGF0ZShvcnRobzEgPSBjYXNlX3doZW4oZGVtaV9zZWdtZW50cyR4MSA8IDAgfiAtb3J0aG8xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVtaV9zZWdtZW50cyR4MSA+PSAwIH4gb3J0aG8xKSkgJT4lDQogIG11dGF0ZSgNCiAgICBvcnRobzIgPSBjYXNlX3doZW4oDQogICAgICBkZW1pX3NlZ21lbnRzJHkwIDwgZGVtaV9zZWdtZW50cyR5MSB+IC1vcnRobzIsDQogICAgICBkZW1pX3NlZ21lbnRzJHkwID49IGRlbWlfc2VnbWVudHMkeTEgfiBvcnRobzINCiAgICApDQogICkNCg0KcmVnJG9ydGhvMl9vcnRobzEgPC0gbG1fbW9kZWwgJT4lDQogIGZpdChvcnRobzIgfiBvcnRobzEsIGRhdGEgPSB0cmFpbikNCg0KcGx0JG9ydGhvMl9vcnRoMSA8LSB0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gb3J0aG8xLCB5ID0gb3J0aG8yKSkgKw0KICBnZW9tX2FibGluZSgNCiAgICBzbG9wZSA9IGdldF9jb2VmKHJlZyRvcnRobzJfb3J0aG8xLCAib3J0aG8xIiksDQogICAgaW50ZXJjZXB0ID0gZ2V0X2NvZWYocmVnJG9ydGhvMl9vcnRobzEpLA0KICAgIGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJsaWdodF9ncmF5IiksDQogICAgc2l6ZSA9IDEsDQogICAgYWxwaGEgPSAwLjUNCiAgKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoInJlZCIpKSArDQogIGxhYnModGl0bGUgPSAiUm90YXRlZCBPcnRob2dvbmFsIFJlZ3Jlc3Npb24iLA0KICAgICAgIHN1YnRpdGxlID0gc3RyX2dsdWUoInIgc3F1YXJlID0ge2dldF9yc3EocmVnJG9ydGhvMl9vcnRobzEsIDMpfSIpKQ0KDQpncmlkLmFycmFuZ2UocGx0JHJlZzJfcmVnMV9maXQsIHBsdCRvcnRobzJfb3J0aDEsIG5jb2wgPSAyKQ0KDQpybShkZW1pX3NlZ21lbnRzKQ0KYGBgDQoNCi0tLQ0KDQojIyMgQ2hlY2tpbmcgUHJlZGljdG9yDQoNCk5vdyB0aGF0IHdlIGhhdmUgYmVlbiBhYmxlIHRvIGZpbmQgYSBiZXR0ZXIgcmVncmVzc2lvbiBtb2RlbCB0byBwcm9qZWN0IHRvLCBsZXQncw0Kc2VlIGhvdyB0aGlzIG5ldyB2YXJpYWJsZSBwcmVkaWN0cyBmdWVsIGVmZmljaWVuY3kuIEZvciB0aGUgcmVncmVzc2lvbnMgc2hvd24gYmVsb3cgb3JkaW5hcnkgbGVhc3Qgc3F1YXJlcyByZWdyZXNzaW9uIGlzIHVzZWQgYXQgdGhpcyBwb2ludCwgc2luY2Ugd2UgYXJlIHRyeWluZyB0byBwcmVkaWN0IGZ1ZWwgZWZmaWNpZW5jeSBiYXNlZCBvbiBvdXIgbmV3IHZhcmlhYmxlLiAqb3J0aG8qIGFuZCAqb3JkaW5hcnkqIGluIHRoZSB0aXRsZXMgaW5kaWNhdGUgdGhlIHJlZ3Jlc3Npb24gbWV0aG9kIHVzZWQgZm9yIGdlbmVyYXRpbmcgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlLg0KDQpUaGUgY29ycmVsYXRpb24gc2VlbXMgdG8gYmUgYWJvdXQgdGhlIHNhbWUgYXMgdGhlIHZhcmlhYmxlIG1hZGUgZnJvbSBvcmRpbmFyeSByZWdyZXNzaW9uIHByb2plY3Rpb24uIFdoaWxlIHRoZXJlIGlzIG5vIG9idmlvdXMgaW1wcm92ZW1lbnQsIGFsbCB0aGUgcHJldmlvdXMgY29tbWVudGFyeSBvbiB0aGUgYmVuZWZpdCBvZiBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gc3RpbGwgaG9sZHMuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NH0NCnJlZyRtcGdfb3J0aG8xIDwtIGxtX21vZGVsICU+JQ0KICBmaXQobXBnIH4gb3J0aG8xLCBkYXRhID0gdHJhaW4pDQoNCnBsdCRtcGdfb3J0aG8xIDwtIHRyYWluICU+JSBnZ3Bsb3QoYWVzKHggPSBvcnRobzEsIHkgPSBtcGcpKSArDQogIGdlb21fYWJsaW5lKA0KICAgIHNsb3BlID0gZ2V0X2NvZWYocmVnJG1wZ19vcnRobzEsICJvcnRobzEiKSwNCiAgICBpbnRlcmNlcHQgPSBnZXRfY29lZihyZWckbXBnX29ydGhvMSksDQogICAgY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoImxpZ2h0X2dyYXkiKSwNCiAgICBzaXplID0gMQ0KICApICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicygNCiAgICB5ID0gIiIsDQogICAgdGl0bGUgPSAiT3J0aG8gUHJvamVjdGVkIFJlZ3Jlc3Npb24iLA0KICAgIHN1YnRpdGxlID0gc3RyX2dsdWUoInIgc3F1YXJlID0ge2dldF9yc3EocmVnJG1wZ19vcnRobzEsIDMpfSIpDQogICkNCg0KcGx0JG1wZ19yZWcxX2ZpdCA8LSBwbHQkbXBnX3JlZzFfZml0ICsNCiAgbGFicyh0aXRsZSA9ICJPcmRpbmFyeSBQcm9qZWN0ZWQgUmVncmVzc2lvbiIpDQoNCg0KZ3JpZC5hcnJhbmdlKHBsdCRtcGdfcmVnMV9maXQgKyBsYWJzKHggPSAicmVnMSIpLCBwbHQkbXBnX29ydGhvMSwgbmNvbCA9DQogICAgICAgICAgICAgICAyKQ0KYGBgDQoNCi0tLQ0KDQoqVGFrZWF3YXlzKg0KDQoqIE9yZGluYXJ5IGxlYXN0LXNxdWFyZSByZWdyZXNzaW9uIGlzIGluYXBwcm9wcmlhdGUgYXMgYSBuZXcgYXhpcyBmb3IgYSBmZXcgcmVhc29uczoNCiAgKiBNaW5pbWl6ZXMgKnZlcnRpY2FsKiBlcnJvcnMNCiAgKiBEZXBlbmRlbnQgb24gd2hpY2ggdmFyaWFibGUgaXMgb24gd2hpY2ggYXhpcw0KICAqIE5ldyB2YXJpYWJsZXMgYXJlIHN0aWxsIGNvcnJlbGF0ZWQNCiogT3J0aG9nb25hbCByZWdyZXNzaW9uIGlzIGFkdmFudGFnZW91czoNCiAgKiBWYXJpYWJsZSBvcmRlciBkb2VzIG5vdCBtYXR0ZXINCiAgKiBOZXcgdmFyaWFibGVzIGFyZSB1bmNvcnJlbGF0ZWQNCiogUmVzY2FsaW5nIHN0aWxsIG1hdHRlcnMNCg0KIyMgRWlnZW52ZWN0b3JzDQoNClNvIGZhciB3ZSBoYXZlIGV4cGxvcmVkIDIgbWV0aG9kcyBvZiBmaW5kaW5nIGEgbmV3IGF4aXMgdG8gd2hpY2ggd2UgY2FuIHByb2plY3Q6DQoNCiogT3JkaW5hcnkgbGVhc3Qtc3F1YXJlcyByZWdyZXNzaW9uDQoqIE9ydGhvZ29uYWwgbGVhc3Qtc3F1YXJlcyByZWdyZXNzaW9uDQoNCldlIGJlZ2FuIHdpdGggcmVncmVzc2lvbnMgc2luY2UgdGhlc2UgaW50dWl0aXZlbHkgZm9sbG93IGRpcmVjdGlvbnMgb2YgdmFyaWFuY2UuIEhvd2V2ZXIsIGEgbW9yZSBlZmZpY2llbnQgbWV0aG9kIGlzIHRvIGZpbmQgdGhlIGVpZ2VudmVjdG9ycyBvZiB0aGUgY292YXJpYW5jZSBtYXRyaXggYmV0d2VlbiB0aGUgdmFyaWFibGVzLiBUaGVzZSBlaWdlbnZlY3RvcnMgd2lsbCBzZXJ2ZSBhcyB0aGUgbmV3IGF4ZXMgZm9yIGRhdGEgcHJvamVjdGlvbiwgc2ltaWxhciB0byBob3cgdGhlIHJlZ3Jlc3Npb24gbGluZXMgd2VyZSB1c2VkLg0KDQpUaGlzIHByb2Nlc3MgaXMgZWZmZWN0aXZlbHkgdGhlIHNhbWUgYXMgdGhlIG9ydGhvZ29uYWwgcmVncmVzc2lvbiBwcm9qZWN0aW9uLCBidXQgaXMgbXVjaCBzaW1wbGVyIHRvIHBlcmZvcm0sIHNpbmNlIG1hdHJpeCBvcGVyYXRpb25zIGFyZSBtb3JlIGNvbmNpc2UgdGhhbiBwZXJmb3JtaW5nIHJlZ3Jlc3Npb24gYW5kIHByb2plY3Rpb24gYmFzZWQgb24gZ2VvbWV0cmllcy4NCg0KU2luY2UgaXQgaXMgcHJldHR5IG11Y2ggdGhlIHNhbWUgcHJvY2Vzcywgd2Ugd2lsbCBzdGlsbCBiZSBjb21wdXRpbmcgb24gdGhlIHNjYWxlZCBkYXRhLCBhcyB0aGlzIG1ldGhvZCBpcyBzdGlsbCBzZW5zaXRpdmUgdG8gdmFyaWFibGUgbWFnbml0dWRlLg0KDQotLS0NCg0KIyMjIENhbGN1bGF0aW5nIHRoZSBFaWdlbnZlY3RvcnMNCg0KRmlyc3RseSwgd2UgY29tcHV0ZSB0aGUgY292YXJpYW5jZSBtYXRyaXggb2Ygb3VyIHZhcmlhYmxlcy4gRm9yIHR3byB2YXJpYWJsZXMsIHRoYXQgaXM6DQoNClxbXGJlZ2lue2JtYXRyaXh9Q292KHgseCkgJiBDb3YoeCx5KVxcIA0KQ292KHkseCkgJiBDb3YoeSx5KVxlbmR7Ym1hdHJpeH1cXQ0KDQpUaGUgbWFpbiBkaWFnb25hbCBjb250YWlucyB0aGUgdmFyaWFuY2VzIG9mIHRoZSBpbmRpdmlkdWFsIHZhcmlhYmxlcyBzaW5jZSAkQ292KGEsYSk9VmFyKGEpJCwgd2hpbGUgb2ZmLWRpYWdvbmFsIHZhbHVlcyBhcmUgdGhlIGNvdmFyaWFuY2VzIGJldHdlZW4gdmFyaWFibGVzLiBOb3RpY2UgdGhhdCBlYWNoIGluZGl2aWR1YWwgdmFyaWFibGUgaGFzIGEgdmFyaWFuY2Ugb2YgMS4gVGhpcyBpcyBiZWNhdXNlIHdlIGhhdmUgYWxyZWFkeSBkaXZpZGVkIGJ5IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gZHVyaW5nIHJlc2NhbGluZy4NCg0KYGBge3IgY292LCBlY2hvPUZBTFNFfQ0KY292X2RmIDwtIGNvdih0cmFpbiAlPiUgc2VsZWN0KGhwX25vcm0sIHd0X25vcm0pKQ0KDQpyb3VuZChjb3ZfZGYsIDIpDQpgYGANCg0KTmV4dCwgd2UgY2FsY3VsYXRlIHRoZSBlaWdlbi1kZWNvbXBvc2l0aW9uIG9mIHRoZSBjb3ZhcmlhbmNlIG1hdHJpeC4gVGhpcyBnaXZlcyB0d28gZWlnZW52YWx1ZXMgZWFjaCBhc3NvY2lhdGVkIHdpdGggYW4gZWlnZW52ZWN0b3IuIFRoZSBudW1iZXIgb2YgZWlnZW4gdmFsdWVzIGFuZCBlaWdlbnZlY3RvcnMgaXMgYWx3YXlzIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgaW5wdXQgdmFyaWFibGVzLg0KDQpUaGUgbGFyZ2VzdCBlaWdlbnZhbHVlIHJlcHJlc2VudHMgdGhlIGRpcmVjdGlvbiBvZiBtYXhpbXVtIHZhcmlhbmNlLCB3aGljaCBpcyBhbmFsb2dvdXMgdG8gb3VyIG9ydGhvZ29uYWwgcmVncmVzc2lvbiBsaW5lLg0KDQpgYGB7ciBlaWdlbl9kZWNvbXAsIGVjaG89RkFMU0V9DQplaWdfZGYgPC0gZWlnZW4oY292X2RmKQ0KDQplaWdfZGYNCmBgYA0KDQpBbm90aGVyIGdyZWF0IHRoaW5nIGFib3V0IHRoaXMgbWV0aG9kIG92ZXIgb3J0aG9nb25hbCByZWdyZXNzaW9uIHByb2plY3Rpb24gaXMgdGhhdCB3ZSBub3cgaGF2ZSBtb3JlIGluZm9ybWF0aW9uIGFib3V0IG91ciB0cmFuc2Zvcm1hdGlvbi4gRm9yIGluc3RhbmNlLCB3ZSBjYW4gc2VlIHRoZSBhbW91bnQgb2YgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IGVhY2ggb2Ygb3VyIG5ldyBheGVzLg0KDQpUaGUgdG90YWwgdmFyaWFuY2UgaXMgZ2l2ZW4gYnkgdGhlIHN1bSBvZiB0aGUgZWlnZW52YWx1ZXMgKCRcbGFtYmRhJCk6DQpcW3RvdGFsXCB2YXJpYW5jZVwgPSBcc3VtX3tpPTF9XntOfSBcbGFtYmRhX2lcXQ0KU28sIHRoZSBwb3J0aW9uIG9mIHRoZSB0b3RhbCB2YXJpYW5jZSAiZXhwbGFpbmVkIiBieSBlYWNoIG9mIG91ciBuZXcgYXhlcyBhc3NvY2lhdGVkIHdpdGggZWFjaCBlaWdlbnZhbHVlIGlzIGdpdmVuIGFzIFxbcG9ydGlvblwgb2ZcIHZhcmlhbmNlID0gXGZyYWN7XGxhbWJkYX17dG90YWxcIHZhcmlhbmNlfVxdDQoNCi0tLQ0KDQojIyMgUHJvamVjdGluZyB0byB0aGUgTmV3IEF4ZXMgey50YWJzZXR9DQoNCk5vdyB0aGF0IHdlIGhhdmUgdGhlIGVpZ2VuLWRlY29tcG9zaXRpb24sIHdlIGNhbiBwcm9qZWN0IHRvIG91ciBuZXcgYXhlcy4gVGhpcyBhZ2FpbiBpcyBkb25lIHdpdGggbWF0cml4IG9wZXJhdGlvbnMgYXM6DQoNClxbTmV3XCBkYXRhPUVpZ2VuXCB2ZWN0b3JzXlQqT3JpZ2luYWxcIGRhdGFeVFxdDQoNCkkgd2lsbCBjYWxsIG91ciBuZXcgYXhlcyAkZWlnMSQgYW5kICRlaWcyJCwgbm90IHRvIGJlIGNvbmZ1c2VkIHdpdGggdGhlIGVpZ2VuIHZhbHVlcyAkXGxhbWJkYV8xJCBhbmQgJFxsYW1iZGFfMiQuDQoNCmBgYHtyIGVpZ19wcm9qZWN0LCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kbm9ybV9laWcgPC0NCiAgdChlaWdfZGYkdmVjdG9ycykgJSolIHQoc2VsZWN0KHRyYWluLCB3dF9ub3JtLCBocF9ub3JtKSkgJT4lDQogIHQoKSAlPiUgYXNfdGliYmxlKCkNCg0KdHJhaW4gPC0gdHJhaW4gJT4lIGFkZF9jb2x1bW4oImVpZzEiID0gbm9ybV9laWckVjEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZWlnMiIgPSBub3JtX2VpZyRWMikNCg0Kcm0oY292X2RmLCBlaWdfZGYsIG5vcm1fZWlnKQ0KYGBgDQoNCi0tLQ0KDQpOb3RpY2UgaG93IG91ciBuZXcgZmVhdHVyZSBzcGFjZSBjcmVhdGVkIHRocm91Z2ggZWlnZW52ZWN0b3IgcHJvamVjdGlvbiBpcyBxdWFsaXRhdGl2ZWx5IGlkZW50aWNhbCB0byB0aGUgb3J0aG9nb25hbCByZWdyZXNzaW9uIHByb2plY3Rpb24uIFdoaWxlIHRoZSBjZW50ZXIgYW5kIHNjYWxlIG9mIHRoZSBheGVzIGFyZSBub3QgaWRlbnRpY2FsLCB3ZSBjYW4gc2VlIHRoZXkgYXJlIHBlcmZlY3RseSBjb3JyZWxhdGVkLg0KDQpUaGlzIHNob3dzIHRoYXQgcGVyZm9ybWluZyBwcm9qZWN0aW9uIHRvIGFuIG9ydGhvZ29uYWwgcmVncmVzc2lvbiBsaW5lIGlzIGVzc2VudGlhbGx5IHRoZSBzYW1lIGFzIHByb2plY3RpbmcgdG8gdGhlIGVpZ2VudmVjdG9ycy4gU28gd2hpbGUgZWlnZW52ZWN0b3JzIGFuZCBtYXRyaXggb3BlcmF0aW9ucyBtYXkgc291bmQgY29uZnVzaW5nLCBhcyBsb25nIGFzIHRoZSBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gcHJvamVjdGlvbiBtYWtlcyBzZW5zZSwgeW91IGNhbiB0aGluayBvZiB0aGUgZWlnZW52ZWN0b3IgcHJvamVjdGlvbiBhcyBqdXN0IGFub3RoZXIgbWF0aGVtYXRpY2FsIHdheSB0byBkbyB0aGUgc2FtZSB0aGluZy4NCg0KIyMjIyBOZXcgQXhlcw0KDQpgYGB7ciBwbG90X2VpZywgZWNobz1GQUxTRSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTR9DQpwbHQkZWlnMl9laWcxIDwtIHRyYWluICU+JSBnZ3Bsb3QoYWVzKHggPSBlaWcxLCB5ID0gZWlnMikpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicyh0aXRsZSA9ICJFaWdlbiBQcm9qZWN0ZWQgRGF0YSIpDQoNCmdyaWQuYXJyYW5nZShwbHQkZWlnMl9laWcxLA0KICAgICAgICAgICAgIHBsdCRvcnRobzJfb3J0aDEgKyBsYWJzKHN1YnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSwNCiAgICAgICAgICAgICBuY29sID0gMikNCmBgYCANCg0KIyMjIyBDb3JyZWxhdGlvbg0KDQpgYGB7ciBlaWdfZGVtaV9jb3JyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcmVnJGVpZzFfb3J0aG8xIDwtIGxtX21vZGVsICU+JQ0KICBmaXQoZWlnMSB+IG9ydGhvMSwgZGF0YSA9IHRyYWluKQ0KDQpwbHQkZWlnMV9vcnRobzEgPC0gdHJhaW4gJT4lIGdncGxvdChhZXMoeCA9IG9ydGhvMSwgeSA9IGVpZzEpKSArDQogIGdlb21fYWJsaW5lKA0KICAgIHNsb3BlID0gZ2V0X2NvZWYocmVnJGVpZzFfb3J0aG8xLCAib3J0aG8xIiksDQogICAgaW50ZXJjZXB0ID0gZ2V0X2NvZWYocmVnJGVpZzFfb3J0aG8xKSwNCiAgICBjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygibGlnaHRfZ3JheSIpLA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkVpZ2VudmVjdG9yIFByb2plY3RlZCB2cw0KICAgICAgIE9ydGhvZ29uYWwgUmVncmVzc2lvbiBQcm9qZWN0ZWQgVmFyaWFibGVzIiwNCiAgICBzdWJ0aXRsZSA9IHN0cl9nbHVlKCJyIHNxdWFyZWQgPSB7Z2V0X3JzcShyZWckZWlnMV9vcnRobzEsIDMpfSIpDQogICkNCg0KcGx0JGVpZzFfb3J0aG8xDQpgYGANCg0KIyMjIFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgey50YWJzZXR9DQoNCk5vdywgZm9yIHRoZSBiaWcgcmV2ZWFsIHlvdSBoYXZlIGFsbCBiZWVuIHdhaXRpbmcgZm9yOiBXaGF0IHdlIGp1c3QgZGlkIGlzIC4uLiAqZHJ1bXJvbGwgcGxlYXNlKiAuLi4gcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcyENCg0KT3J0aG9nb25hbCByZWdyZXNzaW9uIGxpbmUgPSBkb21pbmFudCBlaWdlbnZlY3RvciBkaXJlY3Rpb24gPSBmaXJzdCBwcmluY2lwYWwgYXhpcw0KDQpPcnRob2dvbmFsIHJlc2lkdWFsIGRpcmVjdGlvbiA9IHNlY29uZGFyeSBlaWdlbnZlY3RvciBkaXJlY3Rpb24gPSBzZWNvbmQgcHJpbmNpcGFsIGF4aXMNCg0KU28sIGJlaGluZCB0aGUgc2NlbmVzIG9mIHRoZXNlIGZhbmN5IHByaW5jaXBhbCBjb21wb25lbnQgZnVuY3Rpb25zLCB0aGV5IGFyZSByZWFsbHkganVzdCBwcm9qZWN0aW5nIHRvIHRoZSBkaXJlY3Rpb25zIGdpdmVuIGJ5IHRoZSBlaWdlbnZlY3RvcnMsIHdoaWNoIGlzIHByZXR0eSBtdWNoIHRoZSBzYW1lIGFzIG91ciBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gcHJvamVjdGlvbnMuDQoNClNvLCBsZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgc2ltaWxhcml0aWVzIGJldHdlZW4gb3VyIGVpZ2VudmVjdG9yIHByb2plY3Rpb25zIGFuZCB0aGUgcHJpbmNpcGFsIGNvbXBvbmVudHMgZm91bmQgdXNpbmcgdGhlIFIgZnVuY3Rpb24sIGBwcmNvbXAoKWAuDQoNCiMjIyMgTmV3IENvb3JkaW5hdGVzDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NH0NCnBjYV9maXQgPC0gdHJhaW4gJT4lDQogIHNlbGVjdCh3dF9ub3JtLCBocF9ub3JtKSAlPiUNCiAgcHJjb21wKHNjYWxlID0gRkFMU0UsIGNlbnRlciA9IEZBTFNFKQ0KDQp0cmFpbiA8LSB0cmFpbiAlPiUgYWRkX2NvbHVtbihQQzEgPSBwY2FfZml0JHhbLCAxXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBDMiA9IHBjYV9maXQkeFssIDJdKQ0KDQpybShwY2FfZml0KQ0KDQpyZWckUEMxX2VpZzEgPC0gbG1fbW9kZWwgJT4lDQogIGZpdChQQzEgfiBlaWcxLCBkYXRhID0gdHJhaW4pDQoNCnBsdCRQQzJfUEMxIDwtIHRyYWluICU+JSBnZ3Bsb3QoYWVzKHggPSBQQzEsIHkgPSBQQzIpKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoInJlZCIpKSArDQogIGxhYnModGl0bGUgPSAiUENBIFByb2plY3RlZCBEYXRhIikNCg0KZ3JpZC5hcnJhbmdlKHBsdCRQQzJfUEMxLCBwbHQkZWlnMl9laWcxLCBuY29sID0gMikNCmBgYA0KDQojIyMjIENvcnJlbGF0aW9uDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KcGx0JFBDMV9laWcxIDwtIHRyYWluICU+JSBnZ3Bsb3QoYWVzKHggPSBlaWcxLCB5ID0gUEMxKSkgKw0KICBnZW9tX2FibGluZSgNCiAgICBzbG9wZSA9IGdldF9jb2VmKHJlZyRQQzFfZWlnMSwgImVpZzEiKSwNCiAgICBpbnRlcmNlcHQgPSBnZXRfY29lZihyZWckUEMxX2VpZzEpLA0KICAgIGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJsaWdodF9ncmF5IiksDQogICAgc2l6ZSA9IDENCiAgKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSBnZXRfaHVyd2l0el9jb2xvcnMoInJlZCIpKSArDQogIGxhYnModGl0bGUgPSAiUENBIHZzIEVpZ2VudmVjdG9yIFByb2plY3RlZCBWYXJpYWJsZXMiLA0KICAgICAgIHN1YnRpdGxlID0gc3RyX2dsdWUoInIgc3F1YXJlID0ge2dldF9yc3EocmVnJFBDMV9laWcxLCAzKX0iKSkNCg0KcGx0JFBDMV9laWcxDQpgYGANCg0KIyMjIFNvbWV0aGluZyBJc24ndCBSaWdodA0KDQpVaC1vaC4gV2h5IGFyZSB0aGV5IG5vdCBwZXJmZWN0bHkgY29ycmVsYXRlZD8NCg0KU28gZmFyLCB3ZSBoYXZlIHBlcmZvcm1lZCByZS1zY2FsaW5nIGFzIGEgcHJlLXBvY2Vzc2luZyBzdGVwLCBiZWNhdXNlIHdlIHNhdyB0aGUgdW5kZXNpcmFibGUgZWZmZWN0cyB0aGF0IG9jY3VyIHdoZW4gb3VyIHZhcmlhYmxlcyBoYXZlIGRpZmZlcmVudCBtYWduaXR1ZGVzLg0KDQpOb3cgd2UgYXJlIHNlZWluZyBhbm90aGVyIGVmZmVjdCB0aGF0IG91ciB2YXJpYWJsZXMgYXJlIGhhdmluZyBvbiBQQ0EuDQoNClRvIG1ha2UgdGhlIGZpbmFsIHN0ZXBzIHdvcmssIHdlIHdpbGwgZXhwbG9yZSBob3cgKnJlLWNlbnRlcmluZyogd2FzIG5vdCBuZWNlc3NhcnkgZm9yIG9ydGhvZ29uYWwgcmVncmVzc2lvbiBwcm9qZWN0aW9uLCBidXQgaXMgbmVjZXNzYXJ5IGZvciBQQ0EuDQoNCi0tLQ0KDQoqVGFrZWF3YXlzKg0KDQoqIFRoZSBkaXJlY3Rpb25zIGdpdmVuIGJ5IHRoZSBlaWdlbnZlY3RvcnMgb2YgdGhlIGNvdmFyaWFuY2UgbWF0cml4IGFyZSBlcXVpdmFsZW50IHRvIHRoZSBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gcHJvamVjdGlvbiBheGVzDQoqIFRoZSBlaWdlbnZhbHVlcyBhc3NvY2lhdGVkIHdpdGggZWFjaCBlaWdlbnZlY3RvciByZXByZXNlbnQgdGhlIGFtb3VudCBvZiB2YXJpYW5jZSBpbiB0aGF0IGRpcmVjdGlvbg0KKiBUaGUgZGlyZWN0aW9ucyBnaXZlbiBieSB0aGUgZWlnZW52ZWN0b3JzIGFyZSByZWZlcnJlZCB0byBhcyBwcmluY2lwYWwgYXhlcw0KKiBQQ0EgaXMgc2Vuc2l0aXZlIHRoZSAqcmUtY2VudGVyaW5nKiwgd2hpY2ggd2Ugd2lsbCBleHBsb3JlIGZ1cnRoZXINCg0KIyMgUmVjZW50ZXJpbmcNCg0KUHJldmlvdXNseSwgb3VyIG9ydGhvZ29uYWwgcmVncmVzc2lvbiBsaW5lIGhhZCBhIG5vbi16ZXJvIGludGVyY2VwdC4gVGhpcyBtZWFudCB0aGF0IHRoZSByZWdyZXNzaW9uIHBlcmZvcm1lZCB3ZWxsIG5vIG1hdHRlciAid2hlcmUiIG91ciByZXNjYWxlZCBkYXRhIHdlcmUuIEhvd2V2ZXIsIFBDQSBidWlsZHMgdGhlIG5ldyBheGVzICp0aHJvdWdoIHRoZSBvcmlnaW4qIGJ5IGRlZmluaXRpb24uDQoNClRvIGlsbHVzdHJhdGUgdGhlIGlzc3VlIHdpdGggdGhpcywgd2UgY2FuIGJ1aWxkIGFuIG9ydGhvZ29uYWwgcmVncmVzc2lvbiB3aXRoIHRoZSBjb25zdHJhaW50IHRoYXQgdGhlIGludGVyY2VwdCBiZSB6ZXJvICgqaS5lLiogdGhlIHJlZ3Jlc3Npb24gbGluZSBwYXNzZXMgdGhyb3VnaCB0aGUgb3JpZ2luKS4gVGhpcyBzaW11bGF0ZXMgaG93IHByaW5jaXBhbCBjb21wb25lbnRzIGFyZSBjaG9zZW4uDQoNCmBgYHtyLCBlY2hvID0gZmFsc2V9DQpyZWckZGVtX3plcm9faW50IDwtIGMoc2xvcGUgPSBtZWFuKHRyYWluJGhwX25vcm0pIC8gbWVhbih0cmFpbiR3dF9ub3JtKSwNCiAgICAgICAgICAgICAgICAgICAgICBpbnRlcmNlcHQgPSAwKQ0KDQp0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gd3Rfbm9ybSwgeSA9IGhwX25vcm0pKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fYWJsaW5lKHNsb3BlID0gcmVnJGRlbV96ZXJvX2ludFsic2xvcGUiXSwNCiAgICAgICAgICAgICAgaW50ZXJjZXB0ID0gcmVnJGRlbV96ZXJvX2ludFsiaW50ZXJjZXB0Il0pICsNCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSByZWckZGVtWyJTbG9wZSJdLA0KICAgICAgICAgICAgICBpbnRlcmNlcHQgPSByZWckZGVtWyJJbnRlcmNlcHQiXSwNCiAgICAgICAgICAgICAgY29sb3IgPSAiZ3JheSIpICsNCiAgbGltcyh4ID0gYygwLCA2KSwgeSA9IGMoMCwgNikpICsNCiAgbGFicygNCiAgICB4ID0gIlJlc2NhbGVkIFdlaWdodCIsDQogICAgeSA9ICJSZXNjYWxlZCBQb3dlciIsDQogICAgdGl0bGUgPSAiT3J0aG9nb25hbCBSZWdyZXNzaW9uIiwNCiAgICBzdWJ0aXRsZSA9ICJHcmF5OiBzdGFuZGFyZCBCbGFjazogdGhyb3VnaCBvcmlnaW4iDQogICkNCmBgYA0KTm93LCB3ZSBjYW4gcHJvamVjdCB0byB0aGlzIG5ldyByZWdyZXNzaW9uIGxpbmUuIEkgd2lsbCBjYWxsIG91ciBuZXcgYXhlcyB0aGF0IHJlc3VsdCBmcm9tIHRoaXMgcHJvamVjdGlvbiBgb3J0aG9fbm9fMWAgYW5kIGBvcnRob19ub18yYC4NCg0KSGVyZSBpcyBgb3J0aG9fbm9fMWAgcGxvdHRlZCBhZ2FpbnN0IGBQQzFgLg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCm9ydGhvX25vX3NlZ21lbnRzIDwtIHBlcnBfc2VnbWVudF9jb29yZCh0cmFpbiR3dF9ub3JtLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWluJGhwX25vcm0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnJGRlbV96ZXJvX2ludFsiaW50ZXJjZXB0Il0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnJGRlbV96ZXJvX2ludFsic2xvcGUiXSkgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQp0cmFpbiA8LSB0cmFpbiAlPiUgYWRkX2NvbHVtbihvcnRob19ub18xID0gc3FydCgob3J0aG9fbm9fc2VnbWVudHMkeDEpIF4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMiArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChvcnRob19ub19zZWdtZW50cyR5MSAtIHJlZyRkZW1femVyb19pbnRbImludGVyY2VwdCJdKSBeDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDINCiksDQpvcnRob19ub18yID0gc3FydCgNCiAgKG9ydGhvX25vX3NlZ21lbnRzJHgxIC0gb3J0aG9fbm9fc2VnbWVudHMkeDApIF4gMiArDQogICAgKG9ydGhvX25vX3NlZ21lbnRzJHkxIC0gb3J0aG9fbm9fc2VnbWVudHMkeTApIF4gMg0KKSkNCg0KdHJhaW4gPC0gdHJhaW4gJT4lIG11dGF0ZSgNCiAgb3J0aG9fbm9fMSA9IGNhc2Vfd2hlbigNCiAgICBvcnRob19ub19zZWdtZW50cyR4MSA8IDAgfiAtb3J0aG9fbm9fMSwNCiAgICBvcnRob19ub19zZWdtZW50cyR4MSA+PSAwIH4gb3J0aG9fbm9fMQ0KICApDQopICU+JQ0KICBtdXRhdGUoDQogICAgb3J0aG9fbm9fMiA9IGNhc2Vfd2hlbigNCiAgICAgIG9ydGhvX25vX3NlZ21lbnRzJHkwIDwgb3J0aG9fbm9fc2VnbWVudHMkeTEgfiAtb3J0aG9fbm9fMiwNCiAgICAgIG9ydGhvX25vX3NlZ21lbnRzJHkwID49IG9ydGhvX25vX3NlZ21lbnRzJHkxIH4gb3J0aG9fbm9fMg0KICAgICkNCiAgKQ0KDQpyZWckUEMxX29ydGhvX25vXzEgPC0gbG1fbW9kZWwgJT4lDQogIGZpdChQQzEgfiBvcnRob19ub18xLCBkYXRhID0gdHJhaW4pDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0V9DQp0cmFpbiAlPiUgZ2dwbG90KGFlcyh4ID0gb3J0aG9fbm9fMSwgeSA9IFBDMSkpICsNCiAgZ2VvbV9hYmxpbmUoDQogICAgc2xvcGUgPSBnZXRfY29lZihyZWckUEMxX29ydGhvX25vXzEsICJvcnRob19ub18xIiksDQogICAgaW50ZXJjZXB0ID0gZ2V0X2NvZWYocmVnJFBDMV9vcnRob19ub18xKSwNCiAgICBjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygibGlnaHRfZ3JheSIpLA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBDMSB2cy4gb3J0aG9fbm9fMSIsDQogICAgc3VidGl0bGUgPSBzdHJfZ2x1ZSgiciBzcXVhcmUgPSB7Z2V0X3JzcShyZWckUEMxX29ydGhvX25vXzEsMyl9IikNCiAgKQ0KYGBgDQoNCk5vdyB3ZSBoYXZlIHBlcmZlY3RseSByZWNhcGl0dWxhdGVkIFByaW5jaXBhbCBDb21wb25lbnQgQW5hbHlzaXMgYnkgcHJvamVjdGluZyB0byBhbiBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gbGluZS4NCg0KSG93ZXZlciwgYnkgcGVyZm9ybWluZyB0aGUgb3J0aG9nb25hbCByZWdyZXNzaW9uIHRocm91Z2ggdGhlIG9yaWdpbiwgd2UgYWN0dWFsbHkgbG9zZSBhIGxvdCBvZiBzZW5zaXRpdml0eSB0byB0aGUgZGF0YS4NCg0KLS0tDQoNCiMjIyMgTG9zcyBvZiBTZW5zaXRpdml0eQ0KDQpXaGVuIHdlIGZvcmNlIG9ydGhvZ29uYWwgcmVncmVzc2lvbiB0byBwYXNzIHRocm91Z2ggdGhlIG9yaWdpbiwgdGhlIGxpbmUgaXMgZnVsbHkgZGVmaW5lZCBieSBqdXN0IHR3byBwb2ludHM6IHRoZSBvcmlnaW4gJCgwLDApJCBhbmQgdGhlIGNlbnRyb2lkIG9mIHRoZSBkYXRhICQoXGJhcnt4fSwgXGJhcnt5fSkkLiBUaGlzIGlzIG5vdCBhIHZlcnkgZ29vZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgZGF0YSBkdWUgdG8gdGhlc2UgcmVzdHJpY3Rpb25zLg0KDQpUbyBpbGx1c3RyYXRlIHRoaXMsIEkgY2FuIHNob3cgd2hhdCB0aGUgZmlyc3QgcHJpbmNpcGFsIGNvbXBvbmVudCAob3Igb3J0aG9nb25hbCByZWdyZXNzaW9uIHdpdGggZml4ZWQgemVybyBpbnRlcmNlcHQpIGxvb2tzIGxpa2Ugb24gc29tZSBmYWtlIGRhdGEuIEFzIG1lbnRpb25lZCwgdGhlIGZpdCBzb2xlbHkgZGVwZW5kcyBvbiB0aGUgaW50ZXJjZXB0IGFuZCBjZW50cm9pZCwgYW5kIGlnbm9yZVMgdGhlIGFjdHVhbCBzbG9wZSBvZiB0aGUgZGF0YS4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpkZl9mYWtlJHhfMiA8LSBjKDAuMiwNCiAgICAgICAgICAgICAgICAgMC4yNywNCiAgICAgICAgICAgICAgICAgMC4zMiwNCiAgICAgICAgICAgICAgICAgMC4zOSwNCiAgICAgICAgICAgICAgICAgMC40NCwNCiAgICAgICAgICAgICAgICAgMC40NCwNCiAgICAgICAgICAgICAgICAgMC40OCwNCiAgICAgICAgICAgICAgICAgMC41MSwNCiAgICAgICAgICAgICAgICAgMC41OSwNCiAgICAgICAgICAgICAgICAgMC42OCwNCiAgICAgICAgICAgICAgICAgMC43MiwNCiAgICAgICAgICAgICAgICAgMC44MywNCiAgICAgICAgICAgICAgICAgMC45NSwNCiAgICAgICAgICAgICAgICAgMS4wKQ0KDQpkZl9mYWtlJHlfMiA8LSBjKDAuOTcsDQogICAgICAgICAgICAgICAgIDAuODYsDQogICAgICAgICAgICAgICAgIDAuODYsDQogICAgICAgICAgICAgICAgIDAuNzUsDQogICAgICAgICAgICAgICAgIDAuNywNCiAgICAgICAgICAgICAgICAgMC42NSwNCiAgICAgICAgICAgICAgICAgMC40OSwNCiAgICAgICAgICAgICAgICAgMC41MCwNCiAgICAgICAgICAgICAgICAgMC40MSwNCiAgICAgICAgICAgICAgICAgMC40NSwNCiAgICAgICAgICAgICAgICAgMC4zNywNCiAgICAgICAgICAgICAgICAgMC4yNiwNCiAgICAgICAgICAgICAgICAgMC4zMCwNCiAgICAgICAgICAgICAgICAgMC4xMSkNCg0KcGx0JHlfMl94XzIgPC0gZGZfZmFrZSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geF8yLCB5ID0geV8yKSkgKw0KICBnZW9tX2FibGluZSgNCiAgICBzbG9wZSA9IG1lYW4oZGZfZmFrZSR5XzIpIC8gbWVhbihkZl9mYWtlJHhfMiksDQogICAgaW50ZXJjZXB0ID0gYygwLCAwKSwNCiAgICBjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygibGlnaHRfZ3JheSIpLA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsaW1zKHggPSBjKDAsIDEpLCB5ID0gYygwLCAxKSkgKw0KICBsYWJzKA0KICAgIHggPSAiVmFyaWFibGUgMSIsDQogICAgeSA9ICJWYXJpYWJsZSAyIiwNCiAgICB0aXRsZSA9ICJGaXJzdCBQcmluY2lwYWwgQ29tcG9uZW50IG9mIFVuY2VudGVyZWQgRGF0YSIsDQogICAgc3VidGl0bGUgPSAiRXF1aXZhbGVudCB0byBPcnRob2dvbmFsIFJlZ3Jlc3Npb24sIDAgSW50ZXJjZXB0Ig0KICApDQoNCg0KcGx0JHlfMl94XzINCmBgYA0KDQotLS0NCg0KIyMjIFJlY2VudGVyaW5nDQoNCldpdGggdGhpcyBpbiBtaW5kLCB3ZSBoYXZlIHRvIGNvbnNpZGVyIG91ciBjb25zdHJhaW50cy4gQXMgSSBzdGF0ZWQsIHByaW5jaXBhbCBheGVzICh2aWEgbWF0cml4IG9wZXJhdGlvbnMpIGFsd2F5cyBwYXNzIHRocm91Z2ggdGhlIG9yaWdpbi4gU28sIHdlIGNhbm5vdCBnZXQgYXJvdW5kIHRoYXQgYXNwZWN0IHdoZW4gbW92aW5nIGZyb20gb3J0aG9nb25hbCByZWdyZXNzaW9uIHRvIHByaW5jaXBhbCBjb21wb25lbnQgYW5hbHlzaXMuDQoNCkJ1dCByZWNhbGwgaG93IHdlIHJlc2NhbGVkIG91ciBkYXRhIHRvIGltcHJvdmUgdGhlIHJlZ3Jlc3Npb24gcGVyZm9ybWFuY2U/DQoNCk5vdywgd2UgY2FuIGRvIHNvbWV0aGluZyBzaW1pbGFyLiBJdCBjYW4gYmUgc2hvd24gdGhhdCBvcnRob2dvbmFsIHJlZ3Jlc3Npb24sIGFzIHdlbGwgYXMgcHJpbmNpcGFsIGNvbXBvbmVudHMgYWx3YXlzIHBhc3MgdGhyb3VnaCB0aGUgY2VudHJvaWQsIHdoaWNoIGlzIHRoZSBtZWFuIG9mIGVhY2ggdmFyaWFibGUgJChcYmFye3h9LCBcYmFye3l9KSQuDQoNClNvIHdoYXQgaWYgd2UgcGVyZm9ybWVkIHNvbWUgb3BlcmF0aW9uIG9uIG91ciBkYXRhIHN1Y2ggdGhhdCB0aGUgY2VudHJvaWQgaXMgYXQgdGhlIG9yaWdpbj8gVGhlbiB3ZSBubyBsb25nZXIgbmVlZCB0byBsaW1pdCB0aGUgZml0IG9mIHRoZSByZWdyZXNzaW9uIGp1c3QgdG8gZW5zdXJlIHRoYXQgdGhlIGxpbmUgcGFzc2VzIHRocm91Z2ggdGhlIG9yaWdpbiwgYXMgaXQgd2lsbCBuYXR1cmFsbHkgZG8gc28uDQoNCldlIGNhbiBkbyB0aGF0IGJ5IHN1YnRyYWN0aW5nIHRoZSBtZWFuIG9mIGVhY2ggdmFyaWFibGUgZnJvbSBlYWNoIHBvaW50LiBSZWNhbGwgdGhhdCBvdXIgcmVzY2FsaW5nIG9wZXJhdGlvbiB3YXMgZGl2aWRpbmcgZWFjaCBwb2ludCBieSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGVhY2ggdmFyaWFibGUuIE5vdyBpZiB3ZSBib3RoIHJlc2NhbGUgKGRpdmlkZSBieSAkXHNpZ21hJCkgYW5kIHJlY2VudGVyIChzdWJ0cmFjdCAkXGJhcnt4fSQpIHRoZSBlcXVhdGlvbiBmb3IgdHJhbnNmb3JtaW5nIGVhY2ggdmFyaWFibGUgaXM6DQoNCiRYPVxmcmFje3gtXGJhcnt4fX17XHNpZ21hfSQNCg0KQnV0IGtlZXAgaW4gbWluZCB0aGF0ICR4JCBpcyByZWZlcnJpbmcgdG8gYW55IHZhcmlhYmxlLCBub3QganVzdCB0aGUgdmFyaWFibGUgb24gdGhlICR4JCBheGlzLg0KDQotLS0NCg0KIyMjIFN0YW5kYXJkaXphdGlvbg0KDQpUaGUgYWJvdmUgZXF1YXRpb24gbWF5IGxvb2sgZmFtaWxpYXIuIEluZGVlZCwgaXQgaXMgdGhlIGVxdWF0aW9uIG9mIGEgJHokLXNjb3JlIHRvIGNvbnZlcnQgZGF0YSB0byBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24uIEluIHRoZSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uOg0KDQoqIFRoZSBzdGFuZGFyZCBkZXZpYXRpb24gaXMgMSwgd2hpY2ggZm9yIHVzIG1lYW5zIHRoYXQgZWFjaCB2YXJpYWJsZSBjb250cmlidXRlcyBlcXVhbGx5IHRvIHRoZSByZWdyZXNzaW9uIGZvciBwcm9qZWN0aW9uDQoqIFRoZSBtZWFuIGlzIDAsIHdoaWNoIG1lYW5zIHRoYXQgdGhlIG9ydGhvZ29uYWwgcmVncmVzc2lvbiBjYW4gYmUgb3B0aW1hbCB3aGlsZSBwYXNzaW5nIHRocm91Z2ggdGhlIG9yaWdpbiBhcyBpcyBuZWNlc3NhcnkgZm9yIFBDQS4NCg0KV2hlbiB0aGUgZGF0YSBhcmUgc3RhbmRhcmRpemVkLCBoZXJlIGlzIHdoYXQgdGhleSBsb29rIGxpa2UNCg0KYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTV9DQp0cmFpbiA8LSB0cmFpbiAlPiUNCiAgbXV0YXRlKGhwX3ogPSAgKGhwIC0gbWVhbihocCkpIC8gc2QoaHApLA0KICAgICAgICAgd3RfeiA9ICAod3QgLSBtZWFuKHd0KSkgLyBzZCh3dCkpDQoNCm1heF9zY2FsZSA8LSBtYXgoYWJzKHRyYWluJGhwX3opLCBhYnModHJhaW4kd3RfeikpDQoNCnBsdCRocF96X3R3X3ogPC0gdHJhaW4gJT4lIGdncGxvdChhZXMoeCA9IHd0X3osIHkgPSBocF96KSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBnZW9tX3BvaW50KA0KICAgIHggPSBtZWFuKHRyYWluJHd0X3opLA0KICAgIHkgPSBtZWFuKHRyYWluJGhwX3opLA0KICAgIGNvbG9yID0gImRhcmtncmF5IiwNCiAgICBwY2ggPSAiKyIsDQogICAgc2l6ZSA9IDUNCiAgKSArDQogIGxpbXMoeCA9IGMoLW1heF9zY2FsZSwgbWF4X3NjYWxlKSwNCiAgICAgICB5ID0gYygtbWF4X3NjYWxlLCBtYXhfc2NhbGUpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU3RhbmRhcmRpemVkIFZhcmlhYmxlcyIsDQogICAgc3VidGl0bGUgPSAiQ2VudHJvaWQgbWFya2VkIHdpdGggKyIsDQogICAgeCA9ICJTdGFuZGFyZGl6ZWQgV2VpZ2h0IiwNCiAgICB5ID0gIlN0YW5kYXJkaXplZCBQb3dlciINCiAgKQ0KDQpwbHQkaHBfel90d196DQpgYGANCg0KLS0tDQoNCiMjIyBEaW1lbnNpb24gUmVkdWN0aW9uIG9mIFN0YW5kYXJkaXplZCBWYXJpYWJsZXMgey50YWJzZXR9DQoNClVzaW5nIHRoZSBzdGFuZGFyZGl6ZWQgdmFyaWFibGVzLCB3ZSBjYW4gY29tcGFyZSAoYSkgdGhlIHByb2plY3Rpb24gdG8gb3J0aG9nb25hbCByZWdyZXNzaW9uIGFuZCAoYikgUENBLg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnJlZyRocF96X3d0X3ogPC0gRGVtaW5nKHRyYWluJHd0X3osIHRyYWluJGhwX3opDQoNCmRlbWlfc2VnbWVudHMgPC0gcGVycF9zZWdtZW50X2Nvb3JkKHRyYWluJHd0X3osIHRyYWluJGhwX3osDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWckaHBfel93dF96WyJJbnRlcmNlcHQiXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZyRocF96X3d0X3pbIlNsb3BlIl0pICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KdHJhaW4gPC0gdHJhaW4gJT4lIG11dGF0ZShvcnRob196XzEgPSBzcXJ0KChkZW1pX3NlZ21lbnRzJHgxKSBeIDIgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRlbWlfc2VnbWVudHMkeTEgLQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnJGhwX3pfd3RfelsiSW50ZXJjZXB0Il0pIF4gMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgIG9ydGhvX3pfMiA9IHNxcnQoDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRlbWlfc2VnbWVudHMkeDEgLSBkZW1pX3NlZ21lbnRzJHgwKSBeIDIgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRlbWlfc2VnbWVudHMkeTEgLSBkZW1pX3NlZ21lbnRzJHkwKSBeIDINCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCg0KdHJhaW4gPC0gdHJhaW4gJT4lIG11dGF0ZShvcnRob196XzEgPSBjYXNlX3doZW4oDQogIGRlbWlfc2VnbWVudHMkeDEgPCAwIH4gLW9ydGhvX3pfMSwNCiAgZGVtaV9zZWdtZW50cyR4MSA+PSAwIH4gb3J0aG9fel8xDQopKSAlPiUNCiAgbXV0YXRlKA0KICAgIG9ydGhvX3pfMiA9IGNhc2Vfd2hlbigNCiAgICAgIGRlbWlfc2VnbWVudHMkeTAgPCBkZW1pX3NlZ21lbnRzJHkxIH4gLW9ydGhvX3pfMiwNCiAgICAgIGRlbWlfc2VnbWVudHMkeTAgPj0gZGVtaV9zZWdtZW50cyR5MSB+IG9ydGhvX3pfMg0KICAgICkNCiAgKQ0KDQpwY2Ffel9maXQgPC0gdHJhaW4gJT4lDQogIHNlbGVjdCh3dF96LCBocF96KSAlPiUNCiAgcHJjb21wKHNjYWxlID0gRkFMU0UsIGNlbnRlciA9IEZBTFNFKQ0KDQp0cmFpbiA8LSB0cmFpbiAlPiUgYWRkX2NvbHVtbihQQzFfeiA9IHBjYV96X2ZpdCR4WywgMV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQQzJfeiA9IHBjYV96X2ZpdCR4WywgMl0pDQoNCnJlbW92ZShwY2Ffel9maXQpDQoNCnJlZyRQQzFfel9vcnRob196XzEgPC0gbG1fbW9kZWwgJT4lDQogIGZpdChQQzFfeiB+IG9ydGhvX3pfMSwgZGF0YSA9IHRyYWluKQ0KYGBgDQoNCiMjIyMgUHJvamVjdGlvbnMNCg0KYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00fQ0KcGx0JG9ydGhvX3pfMl9vcnRob196XzEgPC0gdHJhaW4gJT4lDQogIGdncGxvdChhZXMoeCA9IG9ydGhvX3pfMSwgeSA9IG9ydGhvX3pfMikpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygicmVkIikpICsNCiAgbGFicyh0aXRsZSA9ICJPcnRob2dvbmFsIFJlZ3Jlc3Npb24gUHJvamVjdGlvbiIsDQogICAgICAgeCA9ICJvcnRob18xIG9mIHN0YW5kYXJkaXplZCB2YXJpYWJsZXMiLA0KICAgICAgIHkgPSAib3J0aG9fMiBvZiBzdGFuZGFyZGl6ZWQgdmFyaWFibGVzIikNCg0KcGx0JFBDMl96X1BDMV96IDwtIHRyYWluICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBQQzFfeiwgeSA9IFBDMl96KSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKHRpdGxlID0gIlByaW5jaXBhbCBDb21wb25lbnQgUHJvamVjdGlvbiIsDQogICAgICAgeCA9ICJQQzEgb2Ygc3RhbmRhcmRpemVkIHZhcmlhYmxlcyIsDQogICAgICAgeSA9ICJQQzIgb2Ygc3RhbmRhcmRpemVkIHZhcmlhYmxlcyIpDQoNCmdyaWQuYXJyYW5nZShwbHQkb3J0aG9fel8yX29ydGhvX3pfMSwNCiAgICAgICAgICAgICBwbHQkUEMyX3pfUEMxX3osDQogICAgICAgICAgICAgbmNvbCA9IDIpDQpgYGANCg0KIyMjIyBDb3JyZWxhdGlvbg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBsdCRQQzFfel9vcnRob196XzEgPC0gdHJhaW4gJT4lDQogIGdncGxvdChhZXMoeCA9IG9ydGhvX3pfMSwgeSA9IFBDMV96KSkgKw0KICBnZW9tX2FibGluZSgNCiAgICBzbG9wZSA9IGdldF9jb2VmKHJlZyRQQzFfel9vcnRob196XzEsICJvcnRob196XzEiKSwNCiAgICBpbnRlcmNlcHQgPSBnZXRfY29lZihyZWckUEMxX3pfb3J0aG9fel8xKSwNCiAgICBjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygibGlnaHRfZ3JheSIpLA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBDMSBhbmQgT3J0aG9nb25hbCBQcm9qZWN0aW9uIG9mIFN0YW5kYXJkaXplZCBWYXJpYWJsZXMiLA0KICAgIHggPSAib3J0aG9fMSBvZiBzdGFuZGFyZGl6ZWQgdmFyaWFibGVzIiwNCiAgICB5ID0gIlBDMSBvZiBzdGFuZGFyZGl6ZWQgdmFyaWFibGVzIiwNCiAgICBzdWJ0aXRsZSA9IHN0cl9nbHVlKCJyIHNxdWFyZSA9IHtnZXRfcnNxKHJlZyRQQzFfel9vcnRob196XzEsMyl9IikNCiAgKQ0KDQpwbHQkUEMxX3pfb3J0aG9fel8xDQpgYGANCg0KLS0tDQoNCiMjIyBDb25jbHVzaW9uDQoNCldoZW4gdGhlIGRhdGEgYXJlIHN0YW5kYXJkaXplZCwgdGhlbiBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gcHJvamVjdGlvbiBpcyBpZGVudGljYWwgdG8gUENBLg0KDQotLS0NCg0KKlRha2Vhd2F5cyoNCg0KKiBQcmluY2lwYWwgY29tcG9uZW50cyBhbHdheXMgcGFzcyB0aHJvdWdoIHRoZSBvcmlnaW4sIHdoaWNoIGxpbWl0cyB0aGVpciBmaXQgdG8gdW5jZW50ZXJlZCBkYXRhDQoqIFdlIGNhbiBjZW50ZXIgZGF0YSBieSBjb252ZXJ0aW5nIHRvICR6JC1zY29yZSwgd2hpY2ggYWxsb3dzIFBDQSB0byBvcHRpbWFsbHkgZml0IHRoZSBkYXRhDQoqIFBDQSBpcyBpZGVudGljYWwgdG8gcHJvamVjdGlvbiB0byBhbiBvcnRob2dvbmFsIHJlZ3Jlc3Npb24sIG9uY2UgZGF0YSBoYXZlIGJlZW4gc3RhbmRhcmRpemVkDQoNCiMjIFN1bW1hcnkNCg0KV2UgaGF2ZSB0YWtlbiBhIHJvYWQgdHJpcCB0byBmdW5kYW1lbnRhbGx5IHVuZGVyc3RhbmRpbmcgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcy4NCg0KIyMjIE1vdGl2YXRpb24NCg0KVGhlcmUgYXJlIGEgdmFyaWV0eSBvZiByZWFzb25zIGZvciBwZXJmb3JtaW5nIGRpbWVuc2lvbiByZWR1Y3Rpb24sIGluY2x1ZGluZyBzaW1wbGlmeWluZyB0aGUgb3ZlcmFsbCBtb2RlbCBieSByZWR1Y2luZyB0aGUgbnVtYmVyIG9mIHZhcmlhYmxlcy4NCg0KU29tZSB2YXJpYWJsZXMgbWF5IGJlIGNvcnJlbGF0ZWQsIHNvIHRoZXJlIGlzIGEgKnJlZHVuZGFuY3kqIGluIHRoZWlyIGluZm9ybWF0aW9uLiBUaGlzIG1ha2VzIGl0c2VsZiBhcHBhcmVudCBpbiB0aGF0IGlmIHlvdSBrbm93IHRoZSB2YWx1ZSBvZiBvbmUgY29ycmVsYXRlZCB2YXJpYWJsZSwgeW91IGNhbiBwcmVkaWN0IHRoZSB2YWx1ZSBvZiB0aGUgb3RoZXIgdmFyaWFibGUuIENvbnZlcnRpbmcgdGhlc2UgY29ycmVsYXRlZCB2YXJpYWJsZXMgaW50byBhIHNpbmdsZSBuZXcgdmFyaWFibGUgc2VlbXMgbGlrZSBhIGdvb2QgY2hvaWNlIGZvciByZWR1Y2luZyB0aGUgbnVtYmVyIG9mIHZhcmlhYmxlcyB3aGlsZSByZXRhaW5pbmcgaW5mb3JtYXRpb24uDQoNCiMjIyBQcm9qZWN0aW9uIHRvIExpbmVhciBSZWdyZXNzaW9uDQoNClNpbmNlIGxpbmVhciByZWdyZXNzaW9ucyBmb2xsb3cgdGhlIHBhdHRlcm4gb2YgY29ycmVsYXRlZCB2YXJpYWJsZXMsIHdlIGNvdWxkIHByb2plY3QgdG8gYSBsaW5lYXIgcmVncmVzc2lvbiBhcyBhIHNpbmdsZSBuZXcgdmFyaWFibGUgcmVwcmVzZW50aW5nIHRoZSBvcmlnaW5hbCBjb3JyZWxhdGVkIHZhcmlhYmxlcy4NCg0KSG93ZXZlciwgb3JkaW5hcnkgbGVhc3Qtc3F1YXJlcyByZWdyZXNzaW9uIGlzIGRlcGVuZGVudCBvbiB2YXJpYWJsZSBvcmRlci4gWW91IHdpbGwgZ2V0IGEgZGlmZmVyZW50IGF4aXMgZGVwZW5kZW50IG9uIHdoaWNoIHZhcmlhYmxlIGlzIG9uIGVhY2ggYXhpcy4NCg0KT3J0aG9nb25hbCByZWdyZXNzaW9uICgqYS5rLmEuKiBEZW1pbmcgb3IgVG90YWwgTGVhc3QgU3F1YXJlcyByZWdyZXNzaW9uKSBpcyBpbmRlcGVuZGVudCBvZiB2YXJpYWJsZSBvcmRlciwgYW5kIGlzIGEgYmV0dGVyIGNob2ljZS4gDQoNCkFkZGl0aW9uYWxseSwgd2hlbiBwcm9qZWN0aW5nIHRvIG9yZGluYXJ5IGxlYXN0LXNxdWFyZXMgcmVncmVzc2lvbiwgdGhlIHJlc3VsdGluZyB2YXJpYWJsZXMgbWF5IHN0aWxsIGJlIGNvcnJlbGF0ZWQuIFRoZSByZXN1bHRhbnQgdmFyaWFibGVzIGZyb20gcHJvamVjdGlvbiB0byBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gYXJlIG5vdC4NCg0KU2luY2UgUENBIGlzIGVzc2VudGlhbGx5IHRoZSBzYW1lIGFzIHRoaXMgYXBwcm9hY2gsIHRoZXJlIGlzIGEgY2F0Y2guIEFzIG1lbnRpb25lZCwgdGhlIG5ldyByZXN1bHRpbmcgYXhlcyBhcmUgdW5jb3JyZWxhdGVkIGJ5IGRlZmluaXRpb24uIElmIGFsbCB0aGUgb3JpZ2luYWwgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkLCB0aGVuIG9ubHkgdGhlIGZpcnN0IHByaW5jaXBhbCBheGlzIGhhcyBhbnkgbWVhbmluZy4gRm9yIHRoaXMgcmVhc29uLCBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIGlzIGNydWNpYWwgdG8gc2VlIHdoaWNoIG9yaWdpbmFsIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZC4gSWYgdGhleSBhbGwgYXJlLCB0aGVuIFBDQSBpcyBub3QgYWR2aXNhYmxlIGJleW9uZCB0aGUgZmlyc3QgcHJpbmNpcGFsIGNvbXBvbmVudC4NCg0KIyMjIFN0YW5kYXJkaXphdGlvbg0KDQpXZSBuZWVkIHRvIHN0YW5kYXJkaXplIG91ciB2YXJpYWJsZXMgZm9yIFBDQSBmb3IgYSBmZXcgcmVhc29ucy4NCg0KKiBXaGVuIHZhcmlhYmxlcyBoYXZlIGRpZmZlcmVudCBtYWduaXR1ZGVzLCB0aGUgbGFyZ2VyIG1hZ25pdHVkZSB2YXJpYWJsZShzKSBkb21pbmF0ZSB0aGUgbmV3IGF4aXMuDQoqIFdoZW4gdmFyaWFibGVzIGFyZSB1bmNlbnRlcmVkLCBQQ0EgaXMgY29tcGxldGVseSBpbnNlbnNpdGl2ZSB0byBzbG9wZSwgYW5kIGlzIG9ubHkgZGVmaW5lZCBieSB0aGUgY2VudHJvaWQuDQoNCldlIGNhbiBuZWdhdGUgdGhlIGFib3ZlIGNvbmNlcm5zIGJ5IHN0YW5kYXJkaXppbmcgZWFjaCB2YXJpYWJsZSBieSBjb252ZXJ0aW5nIHRvIGEgJHokLXNjb3JlLg0KDQokej1cZnJhY3t4LVxiYXJ7eH19e1xzaWdtYX0kLg0KDQpJdCBzaG91bGQgYmUgbm90ZWQgdGhhdCB0aGlzIG1ldGhvZCB3b3JrcyBiZXN0IGZvciBub3JtYWxseSBkaXN0cmlidXRlZCB2YXJpYWJsZXMuIFBDQSBwZXJmb3JtYW5jZSBjYW4gYmUgaW1wcm92ZWQgYnkgcHJlLXByb2Nlc3NpbmcgZGF0YSB0byBiZWNvbWUgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZCBiZWZvcmUgc3RhbmRhcmRpemF0aW9uLiBGb3IgaW5zdGFuY2UsIGlmIHlvdXIgZGF0YSBhcmUgbG9nLW5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB5b3UgbWF5IHdhbnQgdG8gZmlyc3QgdGFrZSB0aGUgJFxsb2ckIG9mIHlvdXIgdmFyaWFibGUgYmVmb3JlIGNhbGN1bGF0aW5nICR6JC1zY29yZS4NCg0KU2luY2Ugc3RhbmRhcmRpemF0aW9uIGlzIHNvIGNydWNpYWwsIG1vc3QgZnVuY3Rpb25zIHRoYXQgYXJlIGltcGxlbWVudGF0aW9ucyBvZiBQQ0EgaW4gdmFyaW91cyBwcm9ncmFtbWluZyBsYW5ndWFnZXMgKFIsIFB5dGhvbiwgZXRjLikgaGF2ZSBhbiBvcHRpb24gdG8gcGVyZm9ybSBjZW50ZXJpbmcgYW5kIHJlc2NhbGluZyBhdXRvbWF0aWNhbGx5LiBIb3dldmVyLCB0aGVzZSBvcGVyYXRpb25zIGFyZSBnZW5lcmFsbHkgb3B0aW1hbCBmb3Igbm9ybWFsbHkgZGlzdHJpYnV0ZWQgZGF0YSBidXQgdGhlIGZ1bmN0aW9ucyBkbyBub3QgY2hlY2sgdGhpcyBhc3N1bXB0aW9uLiBGb3IgdGhpcyByZWFzb24gaXQgaXMgYmVzdCB0byBjaGVjayBmb3Igbm9ybWFsaXR5ICgqZS5nLiogd2l0aCBhIFEtUSBwbG90KSwgYW5kIGlmIHRoZXkgYXJlIG5vdCBub3JtYWwsIHBlcmZvcm0geW91ciBvd24gcHJlLXByb2Nlc3NpbmcuDQoNCiMjIyBFaWdlbiBEZWNvbXBvc2l0aW9uDQoNClRoZSBvcnRob2dvbmFsIHJlZ3Jlc3Npb24gZm9sbG93cyB0aGUgZGlyZWN0aW9uIG9mIG1heGltdW0gdmFyaWFuY2Ugb2YgdGhlIHZhcmlhYmxlcy4gVGhpcyBkaXJlY3Rpb24gY2FuIGJlIGNhbGN1bGF0ZWQgYnkgZWlnZW4gZGVjb21wb3NpdGlvbi4gVGhpcyB5aWVsZHM6DQoNCiogRWlnZW4gdmVjdG9yczogd2hpY2ggaW5kaWNhdGUgdGhlIGRpcmVjdGlvbihzKSBvZiBtYXhpbXVtIHZhcmlhbmNlDQoqIEVpZ2VuIHZhbHVlczogd2hpY2ggaW5kaWNhdGUgdGhlIGFtb3VudCBvZiB0b3RhbCB2YXJpYW5jZSByZXByZXNlbnRlZCBieSB0aGUgY29ycmVzcG9uZGluZyBlaWdlbiB2ZWN0b3INCg0KUENBIGlzIHBlcmZvcm1lZCB1c2luZyBlaWdlbiBkZWNvbXBvc2l0aW9uLiBUaGlzIGdpdmVzIG1vcmUgaW5mb3JtYXRpb24gdGhhbiBzaW1wbHkgcHJvamVjdGluZyB0byB0aGUgb3J0aG9nb25hbCByZWdyZXNzaW9uIGxpbmVzICgqZS5nLiogYW1vdW50IG9mIHZhcmlhbmNlIHJlcHJlc2VudGVkIGJ5IHRoZSBuZXcgYXhlcykuDQoNCi0tLQ0KDQojIyMgQmFjayB0byBUaGUgUHJlZGljdGl2ZSBNb2RlbA0KDQpXZSBzdGFydGVkIHRoaXMgam91cm5leSBieSB0cnlpbmcgdG8gcHJlZGljdCB2ZWhpY2xlIGZ1ZWwgZWZmaWNpZW5jeSBmcm9tIHdlaWdodCBhbmQgcG93ZXIuIEFmdGVyIGRvaW5nIHNvbWUgbGluZWFyIHJlZ3Jlc3Npb25zIG9uIHRoZSB2YXJpYWJsZXMgaW5kZXBlbmRlbnRseSwgYW5kIHRoZW4gd2l0aCBtdWx0aWxpbmVhciByZWdyZXNzaW9uLCB3ZSBkZWNpZGVkIHRvIHRyeSBkaW1lbnNpb24gcmVkdWN0aW9uIHRvIGNhcHR1cmUgdGhlIGVmZmVjdCBvZiBib3RoIHdlaWdodCBhbmQgcG93ZXIgaW4gYSBzaW5nbGUgdmFyaWFibGUuDQoNClNvIHRvIHdyYXAgaXQgdXAsIGxldCdzIHRha2UgbG9vayBhdCBwcmVkaWN0aW5nIGZ1ZWwgZWZmaWNpZW5jeSBiYXNlZCBvbiB0aGUgZmlyc3QgcHJpbmNpcGFsIGNvbXBvbmVudA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnJlZyRtcGdfUEMxX3ogPC0gbG1fbW9kZWwgJT4lDQogIGZpdChtcGcgfiBQQzFfeiwgZGF0YSA9IHRyYWluKQ0KDQpwbHQkbXBnX1BDMV96IDwtIHRyYWluICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBQQzFfeiwgeSA9IG1wZykpICsNCiAgZ2VvbV9hYmxpbmUoDQogICAgc2xvcGUgPSBnZXRfY29lZihyZWckbXBnX1BDMV96LCAiUEMxX3oiKSwNCiAgICBpbnRlcmNlcHQgPSBnZXRfY29lZihyZWckbXBnX1BDMV96KSwNCiAgICBjb2xvciA9IGdldF9odXJ3aXR6X2NvbG9ycygibGlnaHRfZ3JheSIpLA0KICAgIHNpemUgPSAxDQogICkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gZ2V0X2h1cndpdHpfY29sb3JzKCJyZWQiKSkgKw0KICBsYWJzKA0KICAgIHggPSAiRmlyc3QgUHJpbmNpcGFsIENvbXBvbmVudCAoUEMxKSIsDQogICAgeSA9ICJGdWVsIEVmZmljaWVuY3kgKG1wZykiLA0KICAgIHRpdGxlID0gIkZ1ZWwgRWZmaWNpZW5jeSB2cyBGaXJzdCBQcmluY2lwYWwgQ29tcG9uZW50IiwNCiAgICBzdWJ0aXRsZSA9IHN0cl9nbHVlKCJyLXNxdWFyZSA9IHtnZXRfcnNxKHJlZyRtcGdfUEMxX3opfSIpDQogICkNCg0KcGx0JG1wZ19QQzFfeg0KYGBgDQoNCkl0IHNlZW1zIHRoYXQgZm9yIHRoaXMgZXhhbXBsZSBjYXNlLCBtdXRsaWxpbmVhciByZWdyZXNzaW9uIGlzIGEgYmV0dGVyIHdheSBvZiBwcmVkaWN0aW5nIGZ1ZWwgZWZmaWNpZW5jeSBmcm9tIHRoZSBvcmlnaW5hbCB0d28gdmFyaWFibGVzLiBBbmQgbWF5YmUgdGhhdCBpcyB0aGUgZmluYWwgbGVzc29uLiBUaGlzIHByb2plY3Qgc2hvd2VkIHVzIGludHVpdGl2ZWx5IGhvdyBQQ0Egd29ya3MuIEJ1dCBpbiBvdXIgY2FzZSBpdCB3YXMgbm90IG5lY2Vzc2FyeSBzaW5jZSB3ZSBoYWQgc28gZmV3IHZhcmlhYmxlcywgYW5kIGFjdHVhbGx5IG1hZGUgdGhlIHBlcmZvcm1hbmNlIHdvcnNlLiBTb21ldGltZXMgInNpbXBsZXIiIG1vZGVscyBsaWtlIE1MUiBhcmUgYmV0dGVyIQ0KDQpIb3BlZnVsbHkgdGhpcyBoYXMgc2hvd24gaG93IFBDQSB3b3Jrcy4gTm93IHlvdSBtYXkgYmV0dGVyIHVuZGVyc3RhbmQgaG93IGFuZCB3aHkgd2UgcHJlcHJvY2VzcyBkYXRhLCB3aGF0IHRoZSB2YXJpYW5jZSBtZWFzdXJlcyBpbmRpY2F0ZSwgYW5kIHdoZW4gUENBIG1heSBhY3R1YWxseSBiZSBkZXRyaW1lbnRhbCB0byBtb2RlbCBwZXJmb3JtYW5jZS4=