Introduction to Low Default Portfolios (LDPs)

The Basel Accord provides no formal definition of a low default portfolio (LDP). The Bank of England earlier suggested 20 as the minimum number of required defaults to begin modeling (Prudential Regulation Authority 2013). Hence, if you have fewer than 20 defaults, you definitely have a low default portfolio. The definition of a low default portfolio strongly depends not only on the quality, but also on the ratio between default cases and nondefault ones.

For example, suppose you have two classes: A (for example, Nondefaulter) and B (Default). Class A is 90% of your data-set and class B is the other 10%, but you are most interested in identifying instances of class B. You can reach an accuracy of 90% by simply predicting class A every time, but this provides a useless classifier for your intended use case. Instead, a properly calibrated method may achieve a lower accuracy, but would have a substantially higher true positive rate (or recall), which is really the metric you should have been optimizing for. These scenarios often occur in the context of detection, such as for abusive content online, or disease markers in medical data.

The situation described above is also called “imbalance problem” or “imbalanced data” or low default portfolio in context of credit scoring and classification of loan applications. The problem of imbalanced data is recognized as one of the major problems in the field of data analysis, data mining and machine learning as most statistical models as well as machine learning algorithms assume that data is equally distributed (or unskewed data). In the case of imbalanced data, majority classes dominate over minority classes, causing the machine learning classifiers to be more biased towards majority classes. This causes poor classification of minority classes. Classifiers may even predict all the test data as majority classes. Here are a few practical settings where class imbalance often occurs:

  • Online advertising: An advertisement is presented to a viewer which creates an impression. The click through rate is the number of times an ad was clicked on divided by the total number of impressions and tends to be very low (Richardson et al. 2007 cite a rate less than 2.4%).

  • Pharmaceutical research: High-throughput screening is an experimental technique where large numbers of molecules (10000s) are rapidly evaluated for biological activity. Usually only a few molecules show high activity; therefore, the frequency of interesting compounds is low.

  • Insurance Sector: Artis et al. (2002) investigated auto insurance damage claims in Spain between the years of 1993 and 1996. Of claims undergoing auditing, the rate of fraud was estimated to be approximately 22 %.

Difficulties When Handling With Low Default Portfolios

Low default portfolios are quite common in a financial setting. A popular example is exposures to sovereigns; very few countries have gone into default in the past. Other examples are exposures to banks, insurance companies, and project finance, which is finance for large projects such as building highways or nuclear reactors. Exposures to large corporations and/or specialized lending are additional examples. When you bring new products to the market, it will also take some time before you have the necessary number of defaults to estimate standard credit risk models.

For low default portfolios, typically you have a lack of modeling data, especially default data, which makes it very difficult to apply the advanced internal ratings based (IRB) approach, in which case you need to estimate the prob- ability of default (PD), the LGD, and the EAD. Historical average default rates are not appropriate since they have been calculated on only a few observations. Because of data scarcity, the credit risk can thus be substantially underestimated or overesti- mated. This is a significant problem, especially given the fact that a substantial portion of a bank’s assets might consist of low default portfolios.

Here you can see some statements made by the Basel Committee Accord Implementation Group’s Validation Subgroup on the issue of low default portfolios (Basel Committee on Banking Supervision 2005) in context of modelling scorecard and loan application classification:

  • “LDPs should not, by their very nature, automatically be excluded from IRB treatment.”

  • “…an additional set of rules or principles specifically applying to LDPs is neither necessary nor desirable.”

  • “…relatively sparse data might require increased reliance on alternative data sources and data enhancing tools for quantification and alternative techniques for validation.”

  • “…LDPs should not be considered or treated as conceptually different from other portfolios.”

The Financial Services Authority (FSA), which was the predecessor of the Prudential Regulation Authority (PRA) in the United Kingdom, earlier also explicitly confirmed that it should be possible to include a firm’s LDPs in the IRB approach (see Financial Services Authority 2006a, Section 7).

In case of rare diseases classification, a machine learning or statistical model may suffer from accuracy paradox, which makes it difficult to control false positives (or Type I Error) and false negatives (or Type II Error). This means that the patient may suffer from a rare disease but the machine learning model will not predict so since the majority of the data will be from patients without the disease. In the example of loan classification, the goal is to identify whether the loan application is default or not. Because most cases are nondefault, this causes the model to predict the default applications as valid.

Select the Right Evaluation Metrics

For imbalaned data sets, ppplying inappropriate evaluation metrics for evaluating model can be dangerous. Imagine our training data is the one illustrated in graph above. If accuracy is used to measure the goodness of a model, a model which classifies all testing samples into “0” will have an excellent accuracy (99.8%), but obviously, this model won’t provide any valuable information for us. In this case, other alternative evaluation metrics can be applied such as:

  • AUC: relation between true-positive rate and false positive rate.

  • Precision/Specificity: how many selected instances are relevant.

  • Recall/Sensitivity: how many relevant instances are selected.

  • F1 score: harmonic mean of precision and recall.

Remedies for Low Default Portfolios

Default risk data sets often have a very skewed target class distribution where typi- cally only about 1 percent or even less of the transactions are defaulters. Obviously, this creates problems for the analytical techniques discussed earlier since they are being flooded by all the nondefault observations and will thus tend toward classi- fying every observation as nondefault. Think about decision trees, for example: If they start from a data set with 99 percent/1 percent nondefault/default observations, then the entropy is already very low and hence it is very likely that the decision tree does not find any useful split and classifies all observations as nondefault, thereby achieving a classification accuracy of 99 percent, but essentially detecting none of the defaulters. It is thus recommended to increase the number of default observations or their weight, such that the analytical techniques can pay better attention to them. Various remedies are possible to do this and will be outlined in what follows.

Solution 1: Approach Based on Sampling Technique

When there is a priori knowledge of a class imbalance, one straightforward method to reduce its impact on model training is to select a training set sample to have roughly equal event rates during the initial data collection (see, e.g., Artis et al. 2002). Basically, instead of having the model deal with the imbalance, we can attempt to balance the class frequencies. Taking this approach eliminates the fundamental imbalance issue that plagues model training. However, if the training set is sampled to be balanced, the test set should be sampled to be more consistent with the state of nature and should reflect the imbalance so that honest estimates of future performance can be computed.

Two general post hoc approaches are under-sampling (or downsampling) and up-sampling (or oversampling) the data. Up-sampling is any technique that simulates or imputes additional data points to improve balance across classes, while down-sampling refers to any technique that reduces the number of samples to improve the balance across classes.

More specially, the first way to increase the number of defaulters is by increasing the weight of the defaulters is by either oversampling (or up-sampling) them or by undersampling the nondefaulters. Here, the idea is to replicate the defaulters two or more times so as to make the distribution less skewed. Ling and Li (1998) provide one approach to up-sampling in which cases from the minority classes are sampled with replacement until each class has approximately the same number. For the insurance data, the training set contained 6466 non-policy and 411 insured customers. If we keep the original minority class data, adding 6055 random samples (with replacement) would bring the minority class equal to the majority. In doing this, some minority class samples may show up in the training set with a fairly high frequency while each sample in the majority class has a single realization in the data. This is very similar to the case weight approach shown in an earlier section, with varying weights per case.

On the contrary, undersampling (or Down-sampling) balances the dataset by reducing the size of the abundant class. This method is used when quantity of data is sufficient. By keeping all samples in the rare class and randomly selecting an equal number of samples in the abundant class, a balanced new dataset can be retrieved for further modelling. Down-sampling selects data points from the majority class so that the ma- jority class is roughly the same size as the minority class(es). There are several approaches to down-sampling. First, a basic approach is to randomly sample the majority classes so that all classes have approximately the same size. Another approach would be to take a bootstrap sample across all cases such that the classes are balanced in the bootstrap set. The advantage of this approach is that the bootstrap selection can be run many times so that the estimate of variation can be obtained about the down-sampling. One implementation of random forests can inherently down-sample by controlling the bootstrap sampling process within a stratification variable. If class is used as the stratification variable, then bootstrap samples will be created that are roughly the same size per class. These internally down-sampled versions of the training set are then used to construct trees in the ensemble.

The third approach is a “mixed combination” of the two methods descibed above. The synthetic minority over-sampling technique (SMOTE), proposed by Chawla et al. (2002), is a data sampling procedure that uses both up-sampling and down-sampling, depending on the class, and has three operational parameters: the amount of up-sampling, the amount of down-sampling, and the number of neighbors that are used to impute new cases. To up-sample for the minority class, SMOTE synthesizes new cases. To do this, a data point is randomly selected from the minority class and its K-nearest neighbors (KNNs) are determined. Chawla et al. (2002) used five neighbors in their analyses, but different values can be used depending on the data. The new synthetic data point is a random combination of the predictors of the randomly selected data point and its neighbors. While the SMOTE algorithm adds new samples to the minority class via up-sampling, it also can down-sample cases from the majority class via random sampling in order to help balance the training set.

Solution 2: Model Tuning

The simplest approach to counteracting the negative effects of class imbalance is to tune the model to maximize the accuracy of the minority class(es). For default loan prediction, tuning the model to maximize the sensitivity may help desensitize the training process to the high percentage of nondefault cases in the training set.

Solution 3: Search Optimal Threshold

When there are two possible outcome categories (such as in case of default loan prediction), another method for increasing the prediction accuracy of the minority class samples is to determine alternative cutoffs for the predicted probabilities which effectively changes the definition of a predicted event. The most straightforward approach is to use the ROC curve since it calculates the sensitivity and specificity across a continuum of cutoffs. Using this curve, an appropriate balance between sensitivity and specificity can be determined.

Solution 3: Adjusting Prior Probabilities

Several techniques exist for determining a new cutoff. First, if there is a particular target that must be met for the sensitivity or specificity, this point can be found on the ROC curve and the corresponding cutoff can be determined. Another approach is to find the point on the ROC curve that is closest (i.e., the shortest distance) to the perfect model (with 100 % sensitivity and 100 % specificity), which is associated with the upper left corner of the plot.

Another approach for determining the cutoff uses Youden’s J index, which measures the proportion of correctly predicted samples for both the event and nonevent groups. This index can be computed for each cutoff that is used to create the ROC curve. The cutoff associated with the largest value of the Youden index may also show superior performance relative to the default 50 % value.

Some models use prior probabilities, such as naı̈ve Bayes and discriminant analysis classifiers. Unless specified manually, these models typically derive the value of the priors from the training data. Weiss and Provost (2001a) suggest that priors that reflect the natural class imbalance will materially bias predictions to the majority class. Using more balanced priors or a balanced training set may help deal with a class imbalance.

Solution 4: Cost-Sensitive Training

Instead of optimizing the typical performance measure, such as accuracy or impurity, some models can alternatively optimize a cost or loss function that differentially weights specific types of errors. For example, it may be appropriate to believe that misclassifying true events (false negatives) is X times as costly as incorrectly predicting nonevents (false positives). Incorporation of specific costs during model training may bias the model towards less frequent classes. Unlike using alternative cutoffs, unequal costs can affect the model parameters and thus have the potential to make true improvements to the classifier.

A Real-world Application: Predicting Defaulters from Mortgage Applications

In this post I will only present the method of using the oversampling technique for dealing with imbalanced data in practice. Data used is Caravan which contains 5822 real customer records. ach record consists of 86 variables, containing sociodemographic data (variables 1-43) and product ownership (variables 44-86). The sociodemographic data is derived from zip codes. All customers living in areas with the same zip code have the same sociodemographic attributes. Variable 86 (Purchase) indicates whether the customer purchased a caravan insurance policy. Further information on the individual variables can be obtained at http://www.liacs.nl/~putten/library/cc2000/data.html.

For this data set, there are two technical aspects must be considered: (1) Between-Predictor Correlations, (2) Zero- and Near Zero-Variance Predictors.

Between-Predictor Correlations

Collinearity is the technical term for the situation where a pair of predictor variables have a substantial correlation with each other. It is also possible to have relationships between multiple predictors at once (called multicollinearity).

In general, there are good reasons to avoid data with highly correlated predictors. First, redundant predictors frequently add more complexity to the model than information they provide to the model. In situations where obtaining the predictor data is costly (either in time or money), fewer variables is obviously better. While this argument is mostly philosophical, there are mathematical disadvantages to having correlated predictor data. Using highly correlated predictors in techniques like linear regression can result in highly unstable models, numerical errors, and degraded predictive performance.

Since collinear predictors can impact the variance of parameter estimates in this model, a statistic called the variance inflation factor (VIF) can be used to identify predictors that are impacted (Myers, 1994). Beyond linear regression, this method may be inadequate for several reasons: it was developed for linear models, it requires more samples than predictor variables, and, while it does identify collinear predictors, it does not determine which should be removed to resolve the problem.

A less theoretical, more heuristic approach to dealing with this issue is to remove the minimum number of predictors to ensure that all pairwise correlations are below a certain threshold. While this method only identify collinearities in two dimensions, it can have a significantly positive effect on the performance of some models.

The algorithm is as follows:

  1. Calculate the correlation matrix of the predictors.

  2. Determine the two predictors associated with the largest absolute pairwise correlation (call them predictors A and B).

  3. Determine the average correlation between A and the other variables. Do the same for predictor B.

  4. If A has a larger average correlation, remove it; otherwise, remove predictor B.

  5. Repeat Steps 2–4 until no absolute correlations are above the threshold.

The idea is to first remove the predictors that have the most correlated relationships.

For example, Suppose we wanted to use a model that is particularly sensitive to between-predictor correlations, we might apply a threshold of 0.75. This means that we want to eliminate the minimum number of predictors to achieve all pairwise correlations less than 0.75.

Zero- and Near Zero-Variance Predictors

There are potential advantages to removing predictors prior to modeling. First, fewer predictors means decreased computational time and complexity. Second, if two predictors are highly correlated, this implies that they are measuring the same underlying information. Removing one should not compromise the performance of the model and might lead to a more parsimoniousand interpretable model. Third, some models can be crippled by predictors with degenerate distributions. In these cases, there can be a significant improvement in model performance and/or stability without the problematic variables.

Consider a predictor variable that has a single unique value; we refer to this type of data as a zero variance predictor. For some models, such an uninformative variable may have little effect on the calculations. For example, a tree-based model is impervious to this type of predictor since it would never be used in a split. However, a model such as linear regression would find these data problematic and is likely to cause an error in the computations. In either case, these data have no information and can easily be discarded.

Similarly, some predictors might have only a handful of unique values that occur with very low frequencies. These “near-zero variance predictors” may have a single value for the vast majority of the samples.

How can the user diagnose this mode of problematic data? A rule of thumb for detecting near-zero variance predictors is:

  • The fraction of unique values over the sample size is low (say 10 %).

  • The ratio of the frequency of the most prevalent value to the frequency of the second most prevalent value is large (say around 20).

If both of these criteria are true and the model in question is susceptible to this type of predictor, it may be advantageous to remove the variable from the model.

R Codes

In this section I will present R codes for oversampling and undersampling technique.

The first stage is to determine the optimal ratio between majority and minority class. This process is done as follows. In the first step, an analytical model is built on the original data set with the skew class distribution (for example, 95 percent/5 percent nondefaulters/ defaulters). The area under the curve (AUC) of this model is recorded (possibly on an independent validation data set). In a next step, over- or undersampling is used to change the class distribution by 5 percent (for example, 90 percent/10 percent). Again, the AUC of the model is recorded. Subsequent models are built on samples of 85 percent/ 15 percent, 80 percent/20 percent, 75 percent/25 percent, and so on, each time recording their AUCs. Once the AUC starts to stagnate (or drop), the procedure stops and the optimal odds ratio has been found.

The second stage is compare model results based on some valuation criteria.

R Codes for conducting over- and under-sampling techniques:

# Split data: 
set.seed(1)
id <- createDataPartition(y = remaining_df_after_zero$Purchase, p = 0.5, list = FALSE)
df_train <- remaining_df_after_zero[id, ] # For training
df_test <- remaining_df_after_zero[-id, ] # For testing


#-----------------------------------------------------------------------------
#  A function for calculating AUC / ROC based on 10 samples with given rate 
#  of minority class as described by oversampling technique 
#-----------------------------------------------------------------------------

library(ROSE)
library(pROC)

# Set conditions for training: 
  
set.seed(19950917)
ctrl <- trainControl(method = "repeatedcv",
                     number = 3,
                     repeats = 1,
                     summaryFunction = multiClassSummary, 
                     allowParallel = TRUE,
                     classProbs = TRUE)
  

my_auc_over <- function(minority_rate) {
  
  p <- minority_rate
  df_com <- data_frame()
  for (j in 1:10) {
    
    # Use oversampling for training logistic model: 
    set.seed(j)
    data_balanced_over <- ovun.sample(Purchase ~., data = df_train, p = p, method = "over")$data
    
    # Train logistic model: 
    my_logistic <- train(Purchase ~., method = "glm", trControl = ctrl, data = data_balanced_over)
    
    # Calculate some model performance metrics: 
    
    test_pred <- predict(my_logistic, df_test)
    cm <- confusionMatrix(df_test$Purchase, test_pred)
    
    bg_gg <- cm$table %>% 
      as.vector() %>% 
      matrix(ncol = 4) %>% 
      as.data.frame()
    
    names(bg_gg) <- c("BB", "GB", "BG", "GG")
    kq <- c(cm$overall, cm$byClass) 
    
    ten <- kq %>% 
      as.data.frame() %>% 
      row.names()
    
    kq %>% 
      as.vector() %>% 
      matrix(ncol = 18) %>% 
      as.data.frame() -> all_df
    
    names(all_df) <- ten
    all_df <- bind_cols(all_df, bg_gg)
    
    # Calculate AUC: 
    pred <- predict(my_logistic, df_test, type = "prob") %>% pull(Yes)
    auc <- roc(df_test$Purchase, pred)$auc

    # Add AUC: 
    all_df %<>% mutate(AUC = auc %>% as.vector(), Minority_Rate = p)
    df_com <- bind_rows(df_com, all_df)

  }
  return(df_com)

}

# Minorrity rate from original data: 
Caravan$Purchase %>% table() / nrow(Caravan)
## .
##         No        Yes 
## 0.94022673 0.05977327
##    user  system elapsed 
##  101.25    3.19  104.80
## # A tibble: 9 x 2
##   Minority_Rate avg_auc
##           <dbl>   <dbl>
## 1          0.1    0.683
## 2          0.15   0.683
## 3          0.2    0.687
## 4          0.25   0.687
## 5          0.3    0.687
## 6          0.35   0.687
## 7          0.4    0.689
## 8          0.45   0.687
## 9          0.5    0.685
## # A tibble: 9 x 2
##   Minority_Rate avg_acc
##           <dbl>   <dbl>
## 1          0.1    0.935
## 2          0.15   0.923
## 3          0.2    0.907
## 4          0.25   0.885
## 5          0.3    0.857
## 6          0.35   0.820
## 7          0.4    0.777
## 8          0.45   0.728
## 9          0.5    0.680

##    user  system elapsed 
##   65.15    0.25   65.78
## # A tibble: 9 x 2
##   Majority_Rate avg_auc
##           <dbl>   <dbl>
## 1          0.5    0.665
## 2          0.55   0.652
## 3          0.6    0.655
## 4          0.65   0.646
## 5          0.7    0.636
## 6          0.75   0.646
## 7          0.8    0.609
## 8          0.85   0.589
## 9          0.9    0.562
## # A tibble: 9 x 2
##   Majority_Rate avg_acc
##           <dbl>   <dbl>
## 1          0.5    0.625
## 2          0.55   0.557
## 3          0.6    0.507
## 4          0.65   0.461
## 5          0.7    0.419
## 6          0.75   0.368
## 7          0.8    0.315
## 8          0.85   0.267
## 9          0.9    0.244

Some Key Conclusions

From empirical evidences based on Caravan data set, we can conclude that:

  1. Oversampling technique has a negligible impact on AUC and Accuracy.

  2. Undersampling technique has an adverse impact on AUC and Accuracy.

The same conclusions are found from a post by Nina Zumel and John Mount: http://www.win-vector.com/blog/2015/02/does-balancing-classes-improve-classifier-performance/.

References

  1. Basel Committee on Banking Supervision. 2005. “Validation of Low-Default Portfolios in the Basel II Framework.” Basel Committee Newsletter no. 6, September.

  2. Artis M, Ayuso M, Guillen M (2002). “Detection of Automobile Insurance Fraud with Discrete Choice Models and Misclassified Claims.” The Journal of Risk and Insurance, 69(3), 325–340.

  3. Richardson M, Dominowska E, Ragno R (2007). “Predicting Clicks: Estimating the Click–Through Rate for New Ads.” In “Proceedings of the 16 th International Conference on the World Wide Web,” pp. 521–530.

  4. Visa, S., & Ralescu, A. (2005, April). Issues in mining imbalanced data sets - a review paper. In Proceedings of the sixteen midwest artificial intelligence and cognitive science conference (Vol. 2005, pp. 67-73).

  5. Kotsiantis, S., Kanellopoulos, D., & Pintelas, P. (2006). Handling imbalanced datasets: A review. GESTS International Transactions on Computer Science and Engineering, 30(1), 25-36.

  6. Maloof, M. A. (2003, August). Learning when data sets are imbalanced and when costs are unequal and unknown. In ICML-2003 workshop on learning from imbalanced data sets II (Vol. 2, pp. 2-1).

  7. Japkowicz, N. (2003, August). Class imbalances: are we focusing on the right issue. In Workshop on Learning from Imbalanced Data Sets II (Vol. 1723, p. 63).

  8. Chawla, N. V., Bowyer, K. W., Hall, L. O., & Kegelmeyer, W. P. (2002). SMOTE: synthetic minority over-sampling technique. Journal of artificial intelligence research, 16, 321-357.

  9. Myers R (1994). Classical and Modern Regression with Applications. PWS-KENT Publishing Company, Boston, MA, second edition.

LS0tDQp0aXRsZTogIlByb2JsZW0gb2YgTG93IERlZmF1bHQgUG9ydGZvbGlvcyAoTERQcykgaW4gQ3JlZGl0IFNjb3JpbmcgYW5kIE1vZGVsbGluZyBTY29yZWNhcmQiIA0KIyBzdWJ0aXRsZTogIlRoZSBTZXJpb3VzIFByb2JsZW0gTXVzdCBCZSBIYW5kbGVkIg0KYXV0aG9yOiAiTmd1eWVuIENoaSBEdW5nIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgIyBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzDQogICAgIyBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiAiZmxhdGx5Ig0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KLS0tDQoNCmBgYHtyIHNldHVwLGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCiMjIyBJbnRyb2R1Y3Rpb24gdG8gTG93IERlZmF1bHQgUG9ydGZvbGlvcyAoTERQcykNCg0KVGhlIEJhc2VsIEFjY29yZCBwcm92aWRlcyBubyBmb3JtYWwgZGVmaW5pdGlvbiBvZiBhIGxvdyBkZWZhdWx0IHBvcnRmb2xpbyAoTERQKS4gVGhlIEJhbmsNCm9mIEVuZ2xhbmQgZWFybGllciBzdWdnZXN0ZWQgMjAgYXMgdGhlIG1pbmltdW0gbnVtYmVyIG9mIHJlcXVpcmVkIGRlZmF1bHRzIHRvIGJlZ2luDQptb2RlbGluZyAoUHJ1ZGVudGlhbCBSZWd1bGF0aW9uIEF1dGhvcml0eSAyMDEzKS4gSGVuY2UsIGlmIHlvdSBoYXZlIGZld2VyIHRoYW4gMjANCmRlZmF1bHRzLCB5b3UgZGVmaW5pdGVseSBoYXZlIGEgbG93IGRlZmF1bHQgcG9ydGZvbGlvLiBUaGUgZGVmaW5pdGlvbiBvZiBhIGxvdyBkZWZhdWx0DQpwb3J0Zm9saW8gc3Ryb25nbHkgZGVwZW5kcyBub3Qgb25seSBvbiB0aGUgcXVhbGl0eSwgYnV0IGFsc28gb24gdGhlIHJhdGlvIGJldHdlZW4gZGVmYXVsdCBjYXNlcyBhbmQgbm9uZGVmYXVsdCBvbmVzLiANCg0KRm9yIGV4YW1wbGUsIHN1cHBvc2UgeW91IGhhdmUgdHdvIGNsYXNzZXM6IEEgKGZvciBleGFtcGxlLCBOb25kZWZhdWx0ZXIpIGFuZCBCIChEZWZhdWx0KS4gQ2xhc3MgQSBpcyA5MCUgb2YgeW91ciBkYXRhLXNldCBhbmQgY2xhc3MgQiBpcyB0aGUgb3RoZXIgMTAlLCBidXQgeW91IGFyZSBtb3N0IGludGVyZXN0ZWQgaW4gaWRlbnRpZnlpbmcgaW5zdGFuY2VzIG9mIGNsYXNzIEIuIFlvdSBjYW4gcmVhY2ggYW4gYWNjdXJhY3kgb2YgOTAlIGJ5IHNpbXBseSBwcmVkaWN0aW5nIGNsYXNzIEEgZXZlcnkgdGltZSwgYnV0IHRoaXMgcHJvdmlkZXMgYSB1c2VsZXNzIGNsYXNzaWZpZXIgZm9yIHlvdXIgaW50ZW5kZWQgdXNlIGNhc2UuIEluc3RlYWQsIGEgcHJvcGVybHkgY2FsaWJyYXRlZCBtZXRob2QgbWF5IGFjaGlldmUgYSBsb3dlciBhY2N1cmFjeSwgYnV0IHdvdWxkIGhhdmUgYSBzdWJzdGFudGlhbGx5IGhpZ2hlciB0cnVlIHBvc2l0aXZlIHJhdGUgKG9yIHJlY2FsbCksIHdoaWNoIGlzIHJlYWxseSB0aGUgbWV0cmljIHlvdSBzaG91bGQgaGF2ZSBiZWVuIG9wdGltaXppbmcgZm9yLiBUaGVzZSBzY2VuYXJpb3Mgb2Z0ZW4gb2NjdXIgaW4gdGhlIGNvbnRleHQgb2YgZGV0ZWN0aW9uLCBzdWNoIGFzIGZvciBhYnVzaXZlIGNvbnRlbnQgb25saW5lLCBvciBkaXNlYXNlIG1hcmtlcnMgaW4gbWVkaWNhbCBkYXRhLg0KDQpUaGUgc2l0dWF0aW9uIGRlc2NyaWJlZCBhYm92ZSBpcyBhbHNvIGNhbGxlZCAiaW1iYWxhbmNlIHByb2JsZW0iIG9yICJpbWJhbGFuY2VkIGRhdGEiIG9yIGxvdyBkZWZhdWx0IHBvcnRmb2xpbyBpbiBjb250ZXh0IG9mIGNyZWRpdCBzY29yaW5nIGFuZCBjbGFzc2lmaWNhdGlvbiBvZiBsb2FuIGFwcGxpY2F0aW9ucy4gVGhlIHByb2JsZW0gb2YgaW1iYWxhbmNlZCBkYXRhIGlzIHJlY29nbml6ZWQgYXMgb25lIG9mIHRoZSBtYWpvciBwcm9ibGVtcyBpbiB0aGUgZmllbGQgb2YgZGF0YSBhbmFseXNpcywgZGF0YSBtaW5pbmcgYW5kIG1hY2hpbmUgbGVhcm5pbmcgYXMgbW9zdCBzdGF0aXN0aWNhbCBtb2RlbHMgYXMgd2VsbCBhcyAgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG1zIGFzc3VtZSB0aGF0IGRhdGEgaXMgZXF1YWxseSBkaXN0cmlidXRlZCAob3IgdW5za2V3ZWQgZGF0YSkuIEluIHRoZSBjYXNlIG9mIGltYmFsYW5jZWQgZGF0YSwgbWFqb3JpdHkgY2xhc3NlcyBkb21pbmF0ZSBvdmVyIG1pbm9yaXR5IGNsYXNzZXMsIGNhdXNpbmcgdGhlIG1hY2hpbmUgbGVhcm5pbmcgY2xhc3NpZmllcnMgdG8gYmUgbW9yZSBiaWFzZWQgdG93YXJkcyBtYWpvcml0eSBjbGFzc2VzLiBUaGlzIGNhdXNlcyBwb29yIGNsYXNzaWZpY2F0aW9uIG9mIG1pbm9yaXR5IGNsYXNzZXMuIENsYXNzaWZpZXJzIG1heSBldmVuIHByZWRpY3QgYWxsIHRoZSB0ZXN0IGRhdGEgYXMgbWFqb3JpdHkgY2xhc3Nlcy4gSGVyZSBhcmUgYSBmZXcgcHJhY3RpY2FsIHNldHRpbmdzIHdoZXJlIGNsYXNzIGltYmFsYW5jZSBvZnRlbiBvY2N1cnM6DQoNCg0KLSBPbmxpbmUgYWR2ZXJ0aXNpbmc6IEFuIGFkdmVydGlzZW1lbnQgaXMgcHJlc2VudGVkIHRvIGEgdmlld2VyIHdoaWNoIGNyZWF0ZXMNCmFuIGltcHJlc3Npb24uIFRoZSBjbGljayB0aHJvdWdoIHJhdGUgaXMgdGhlIG51bWJlciBvZiB0aW1lcyBhbiBhZCB3YXMNCmNsaWNrZWQgb24gZGl2aWRlZCBieSB0aGUgdG90YWwgbnVtYmVyIG9mIGltcHJlc3Npb25zIGFuZCB0ZW5kcyB0byBiZSB2ZXJ5DQpsb3cgKFJpY2hhcmRzb24gZXQgYWwuIDIwMDcgY2l0ZSBhIHJhdGUgbGVzcyB0aGFuIDIuNCUpLg0KDQotIFBoYXJtYWNldXRpY2FsIHJlc2VhcmNoOiBIaWdoLXRocm91Z2hwdXQgc2NyZWVuaW5nIGlzIGFuIGV4cGVyaW1lbnRhbA0KdGVjaG5pcXVlIHdoZXJlIGxhcmdlIG51bWJlcnMgb2YgbW9sZWN1bGVzICgxMDAwMHMpIGFyZSByYXBpZGx5IGV2YWx1YXRlZA0KZm9yIGJpb2xvZ2ljYWwgYWN0aXZpdHkuIFVzdWFsbHkgb25seSBhIGZldyBtb2xlY3VsZXMgc2hvdyBoaWdoIGFjdGl2aXR5Ow0KdGhlcmVmb3JlLCB0aGUgZnJlcXVlbmN5IG9mIGludGVyZXN0aW5nIGNvbXBvdW5kcyBpcyBsb3cuDQoNCi0gSW5zdXJhbmNlIFNlY3RvcjogQXJ0aXMgZXQgYWwuICgyMDAyKSBpbnZlc3RpZ2F0ZWQgYXV0byBpbnN1cmFuY2UgZGFtYWdlDQpjbGFpbXMgaW4gU3BhaW4gYmV0d2VlbiB0aGUgeWVhcnMgb2YgMTk5MyBhbmQgMTk5Ni4gT2YgY2xhaW1zIHVuZGVyZ29pbmcNCmF1ZGl0aW5nLCB0aGUgcmF0ZSBvZiBmcmF1ZCB3YXMgZXN0aW1hdGVkIHRvIGJlIGFwcHJveGltYXRlbHkgMjIgJS4NCg0KDQojIyMgRGlmZmljdWx0aWVzIFdoZW4gSGFuZGxpbmcgV2l0aCBMb3cgRGVmYXVsdCBQb3J0Zm9saW9zDQoNCkxvdyBkZWZhdWx0IHBvcnRmb2xpb3MgYXJlIHF1aXRlIGNvbW1vbiBpbiBhIGZpbmFuY2lhbCBzZXR0aW5nLiBBIHBvcHVsYXIgZXhhbXBsZQ0KaXMgZXhwb3N1cmVzIHRvIHNvdmVyZWlnbnM7IHZlcnkgZmV3IGNvdW50cmllcyBoYXZlIGdvbmUgaW50byBkZWZhdWx0IGluIHRoZSBwYXN0Lg0KT3RoZXIgZXhhbXBsZXMgYXJlIGV4cG9zdXJlcyB0byBiYW5rcywgaW5zdXJhbmNlIGNvbXBhbmllcywgYW5kIHByb2plY3QgZmluYW5jZSwNCndoaWNoIGlzIGZpbmFuY2UgZm9yIGxhcmdlIHByb2plY3RzIHN1Y2ggYXMgYnVpbGRpbmcgaGlnaHdheXMgb3IgbnVjbGVhciByZWFjdG9ycy4NCkV4cG9zdXJlcyB0byBsYXJnZSBjb3Jwb3JhdGlvbnMgYW5kL29yIHNwZWNpYWxpemVkIGxlbmRpbmcgYXJlIGFkZGl0aW9uYWwgZXhhbXBsZXMuDQpXaGVuIHlvdSBicmluZyBuZXcgcHJvZHVjdHMgdG8gdGhlIG1hcmtldCwgaXQgd2lsbCBhbHNvIHRha2Ugc29tZSB0aW1lIGJlZm9yZSB5b3UNCmhhdmUgdGhlIG5lY2Vzc2FyeSBudW1iZXIgb2YgZGVmYXVsdHMgdG8gZXN0aW1hdGUgc3RhbmRhcmQgY3JlZGl0IHJpc2sgbW9kZWxzLg0KDQpGb3IgbG93IGRlZmF1bHQgcG9ydGZvbGlvcywgdHlwaWNhbGx5IHlvdSBoYXZlIGEgbGFjayBvZiBtb2RlbGluZyBkYXRhLCBlc3BlY2lhbGx5IGRlZmF1bHQgZGF0YSwgd2hpY2ggbWFrZXMgaXQgdmVyeSBkaWZmaWN1bHQgdG8gYXBwbHkgdGhlIGFkdmFuY2VkDQppbnRlcm5hbCByYXRpbmdzIGJhc2VkIChJUkIpIGFwcHJvYWNoLCBpbiB3aGljaCBjYXNlIHlvdSBuZWVkIHRvIGVzdGltYXRlIHRoZSBwcm9iLQ0KYWJpbGl0eSBvZiBkZWZhdWx0IChQRCksIHRoZSBMR0QsIGFuZCB0aGUgRUFELiBIaXN0b3JpY2FsIGF2ZXJhZ2UgZGVmYXVsdCByYXRlcyBhcmUNCm5vdCBhcHByb3ByaWF0ZSBzaW5jZSB0aGV5IGhhdmUgYmVlbiBjYWxjdWxhdGVkIG9uIG9ubHkgYSBmZXcgb2JzZXJ2YXRpb25zLiBCZWNhdXNlDQpvZiBkYXRhIHNjYXJjaXR5LCB0aGUgY3JlZGl0IHJpc2sgY2FuIHRodXMgYmUgc3Vic3RhbnRpYWxseSB1bmRlcmVzdGltYXRlZCBvciBvdmVyZXN0aS0NCm1hdGVkLiBUaGlzIGlzIGEgc2lnbmlmaWNhbnQgcHJvYmxlbSwgZXNwZWNpYWxseSBnaXZlbiB0aGUgZmFjdCB0aGF0IGEgc3Vic3RhbnRpYWwgcG9ydGlvbg0Kb2YgYSBiYW5r4oCZcyBhc3NldHMgbWlnaHQgY29uc2lzdCBvZiBsb3cgZGVmYXVsdCBwb3J0Zm9saW9zLg0KDQpIZXJlIHlvdSBjYW4gc2VlIHNvbWUgc3RhdGVtZW50cyBtYWRlIGJ5IHRoZSBCYXNlbCBDb21taXR0ZWUgQWNjb3JkIEltcGxlbWVudGF0aW9uIEdyb3Vw4oCZcyBWYWxpZGF0aW9uIFN1Ymdyb3VwIG9uIHRoZSBpc3N1ZSBvZiBsb3cgZGVmYXVsdCBwb3J0Zm9saW9zIChCYXNlbA0KQ29tbWl0dGVlIG9uIEJhbmtpbmcgU3VwZXJ2aXNpb24gMjAwNSkgaW4gY29udGV4dCBvZiBtb2RlbGxpbmcgc2NvcmVjYXJkIGFuZCBsb2FuIGFwcGxpY2F0aW9uIGNsYXNzaWZpY2F0aW9uOiANCg0KLSDigJxMRFBzIHNob3VsZCBub3QsIGJ5IHRoZWlyIHZlcnkgbmF0dXJlLCBhdXRvbWF0aWNhbGx5IGJlIGV4Y2x1ZGVkIGZyb20gSVJCIHRyZWF0bWVudC7igJ0NCg0KLSDigJwuLi5hbiBhZGRpdGlvbmFsIHNldCBvZiBydWxlcyBvciBwcmluY2lwbGVzIHNwZWNpZmljYWxseSBhcHBseWluZyB0byBMRFBzIGlzIG5laXRoZXIgbmVjZXNzYXJ5IG5vciBkZXNpcmFibGUu4oCdDQoNCi0g4oCcLi4ucmVsYXRpdmVseSBzcGFyc2UgZGF0YSBtaWdodCByZXF1aXJlIGluY3JlYXNlZCByZWxpYW5jZSBvbiBhbHRlcm5hdGl2ZSBkYXRhIHNvdXJjZXMgYW5kIGRhdGEgZW5oYW5jaW5nIHRvb2xzIGZvciBxdWFudGlmaWNhdGlvbiBhbmQgYWx0ZXJuYXRpdmUgdGVjaG5pcXVlcyBmb3IgdmFsaWRhdGlvbi7igJ0NCg0KLSDigJwuLi5MRFBzIHNob3VsZCBub3QgYmUgY29uc2lkZXJlZCBvciB0cmVhdGVkIGFzIGNvbmNlcHR1YWxseSBkaWZmZXJlbnQgZnJvbSBvdGhlciBwb3J0Zm9saW9zLuKAnQ0KDQpUaGUgRmluYW5jaWFsIFNlcnZpY2VzIEF1dGhvcml0eSAoRlNBKSwgd2hpY2ggd2FzIHRoZSBwcmVkZWNlc3NvciBvZiB0aGUgUHJ1ZGVudGlhbCBSZWd1bGF0aW9uIEF1dGhvcml0eSAoUFJBKSBpbiB0aGUgVW5pdGVkIEtpbmdkb20sIGVhcmxpZXIgYWxzbyBleHBsaWNpdGx5DQpjb25maXJtZWQgdGhhdCBpdCBzaG91bGQgYmUgcG9zc2libGUgdG8gaW5jbHVkZSBhIGZpcm3igJlzIExEUHMgaW4gdGhlIElSQiBhcHByb2FjaCAoc2VlIEZpbmFuY2lhbCBTZXJ2aWNlcyBBdXRob3JpdHkgMjAwNmEsIFNlY3Rpb24gNykuDQoNCkluIGNhc2Ugb2YgcmFyZSBkaXNlYXNlcyBjbGFzc2lmaWNhdGlvbiwgYSBtYWNoaW5lIGxlYXJuaW5nIG9yIHN0YXRpc3RpY2FsIG1vZGVsIG1heSBzdWZmZXIgZnJvbSBhY2N1cmFjeSBwYXJhZG94LCB3aGljaCBtYWtlcyBpdCBkaWZmaWN1bHQgdG8gY29udHJvbCBmYWxzZSBwb3NpdGl2ZXMgKG9yIFR5cGUgSSBFcnJvcikgYW5kIGZhbHNlIG5lZ2F0aXZlcyAob3IgVHlwZSBJSSBFcnJvcikuIFRoaXMgbWVhbnMgdGhhdCB0aGUgcGF0aWVudCBtYXkgc3VmZmVyIGZyb20gYSByYXJlIGRpc2Vhc2UgYnV0IHRoZSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHdpbGwgbm90IHByZWRpY3Qgc28gc2luY2UgdGhlIG1ham9yaXR5IG9mIHRoZSBkYXRhIHdpbGwgYmUgZnJvbSBwYXRpZW50cyB3aXRob3V0IHRoZSBkaXNlYXNlLiBJbiB0aGUgZXhhbXBsZSBvZiBsb2FuIGNsYXNzaWZpY2F0aW9uLCB0aGUgZ29hbCBpcyB0byBpZGVudGlmeSB3aGV0aGVyIHRoZSBsb2FuIGFwcGxpY2F0aW9uIGlzIGRlZmF1bHQgb3Igbm90LiBCZWNhdXNlIG1vc3QgY2FzZXMgYXJlIG5vbmRlZmF1bHQsIHRoaXMgY2F1c2VzIHRoZSBtb2RlbCB0byBwcmVkaWN0IHRoZSBkZWZhdWx0IGFwcGxpY2F0aW9ucyBhcyB2YWxpZC4gDQoNCg0KIyMjIFNlbGVjdCB0aGUgUmlnaHQgRXZhbHVhdGlvbiBNZXRyaWNzDQoNCkZvciBpbWJhbGFuZWQgZGF0YSBzZXRzLCBwcHBseWluZyBpbmFwcHJvcHJpYXRlIGV2YWx1YXRpb24gbWV0cmljcyBmb3IgZXZhbHVhdGluZyBtb2RlbCBjYW4gYmUgZGFuZ2Vyb3VzLiBJbWFnaW5lIG91ciB0cmFpbmluZyBkYXRhIGlzIHRoZSBvbmUgaWxsdXN0cmF0ZWQgaW4gZ3JhcGggYWJvdmUuIElmIGFjY3VyYWN5IGlzIHVzZWQgdG8gbWVhc3VyZSB0aGUgZ29vZG5lc3Mgb2YgYSBtb2RlbCwgYSBtb2RlbCB3aGljaCBjbGFzc2lmaWVzIGFsbCB0ZXN0aW5nIHNhbXBsZXMgaW50byDigJww4oCdIHdpbGwgaGF2ZSBhbiBleGNlbGxlbnQgYWNjdXJhY3kgKDk5LjglKSwgYnV0IG9idmlvdXNseSwgdGhpcyBtb2RlbCB3b27igJl0IHByb3ZpZGUgYW55IHZhbHVhYmxlIGluZm9ybWF0aW9uIGZvciB1cy4gSW4gdGhpcyBjYXNlLCBvdGhlciBhbHRlcm5hdGl2ZSBldmFsdWF0aW9uIG1ldHJpY3MgY2FuIGJlIGFwcGxpZWQgc3VjaCBhczoNCg0KLSAqKkFVQyoqOiByZWxhdGlvbiBiZXR3ZWVuIHRydWUtcG9zaXRpdmUgcmF0ZSBhbmQgZmFsc2UgcG9zaXRpdmUgcmF0ZS4NCg0KLSAqKlByZWNpc2lvbi9TcGVjaWZpY2l0eSoqOiBob3cgbWFueSBzZWxlY3RlZCBpbnN0YW5jZXMgYXJlIHJlbGV2YW50Lg0KDQotICoqUmVjYWxsL1NlbnNpdGl2aXR5Kio6IGhvdyBtYW55IHJlbGV2YW50IGluc3RhbmNlcyBhcmUgc2VsZWN0ZWQuDQoNCi0gKipGMSBzY29yZSoqOiBoYXJtb25pYyBtZWFuIG9mIHByZWNpc2lvbiBhbmQgcmVjYWxsLg0KDQojIyMgUmVtZWRpZXMgZm9yIExvdyBEZWZhdWx0IFBvcnRmb2xpb3MNCg0KRGVmYXVsdCByaXNrIGRhdGEgc2V0cyBvZnRlbiBoYXZlIGEgdmVyeSBza2V3ZWQgdGFyZ2V0IGNsYXNzIGRpc3RyaWJ1dGlvbiB3aGVyZSB0eXBpLQ0KY2FsbHkgb25seSBhYm91dCAxIHBlcmNlbnQgb3IgZXZlbiBsZXNzIG9mIHRoZSB0cmFuc2FjdGlvbnMgYXJlIGRlZmF1bHRlcnMuIE9idmlvdXNseSwgDQp0aGlzIGNyZWF0ZXMgcHJvYmxlbXMgZm9yIHRoZSBhbmFseXRpY2FsIHRlY2huaXF1ZXMgZGlzY3Vzc2VkIGVhcmxpZXIgc2luY2UgdGhleSBhcmUNCmJlaW5nIGZsb29kZWQgYnkgYWxsIHRoZSBub25kZWZhdWx0IG9ic2VydmF0aW9ucyBhbmQgd2lsbCB0aHVzIHRlbmQgdG93YXJkIGNsYXNzaS0NCmZ5aW5nIGV2ZXJ5IG9ic2VydmF0aW9uIGFzIG5vbmRlZmF1bHQuIFRoaW5rIGFib3V0IGRlY2lzaW9uIHRyZWVzLCBmb3IgZXhhbXBsZTogSWYNCnRoZXkgc3RhcnQgZnJvbSBhIGRhdGEgc2V0IHdpdGggOTkgcGVyY2VudC8xIHBlcmNlbnQgbm9uZGVmYXVsdC9kZWZhdWx0IG9ic2VydmF0aW9ucywNCnRoZW4gdGhlIGVudHJvcHkgaXMgYWxyZWFkeSB2ZXJ5IGxvdyBhbmQgaGVuY2UgaXQgaXMgdmVyeSBsaWtlbHkgdGhhdCB0aGUgZGVjaXNpb24gdHJlZQ0KZG9lcyBub3QgZmluZCBhbnkgdXNlZnVsIHNwbGl0IGFuZCBjbGFzc2lmaWVzIGFsbCBvYnNlcnZhdGlvbnMgYXMgbm9uZGVmYXVsdCwgdGhlcmVieQ0KYWNoaWV2aW5nIGEgY2xhc3NpZmljYXRpb24gYWNjdXJhY3kgb2YgOTkgcGVyY2VudCwgYnV0IGVzc2VudGlhbGx5IGRldGVjdGluZyBub25lIG9mDQp0aGUgZGVmYXVsdGVycy4gSXQgaXMgdGh1cyByZWNvbW1lbmRlZCB0byBpbmNyZWFzZSB0aGUgbnVtYmVyIG9mIGRlZmF1bHQgb2JzZXJ2YXRpb25zIG9yIHRoZWlyIHdlaWdodCwgc3VjaCB0aGF0IHRoZSBhbmFseXRpY2FsIHRlY2huaXF1ZXMgY2FuIHBheSBiZXR0ZXIgYXR0ZW50aW9uIHRvDQp0aGVtLiBWYXJpb3VzIHJlbWVkaWVzIGFyZSBwb3NzaWJsZSB0byBkbyB0aGlzIGFuZCB3aWxsIGJlIG91dGxpbmVkIGluIHdoYXQgZm9sbG93cy4NCg0KIyMjIFNvbHV0aW9uIDE6IEFwcHJvYWNoIEJhc2VkIG9uIFNhbXBsaW5nIFRlY2huaXF1ZQ0KDQpXaGVuIHRoZXJlIGlzIGEgcHJpb3JpIGtub3dsZWRnZSBvZiBhIGNsYXNzIGltYmFsYW5jZSwgb25lIHN0cmFpZ2h0Zm9yd2FyZA0KbWV0aG9kIHRvIHJlZHVjZSBpdHMgaW1wYWN0IG9uIG1vZGVsIHRyYWluaW5nIGlzIHRvIHNlbGVjdCBhIHRyYWluaW5nIHNldA0Kc2FtcGxlIHRvIGhhdmUgcm91Z2hseSBlcXVhbCBldmVudCByYXRlcyBkdXJpbmcgdGhlIGluaXRpYWwgZGF0YSBjb2xsZWN0aW9uDQooc2VlLCBlLmcuLCBBcnRpcyBldCBhbC4gMjAwMikuIEJhc2ljYWxseSwgaW5zdGVhZCBvZiBoYXZpbmcgdGhlIG1vZGVsIGRlYWwgd2l0aA0KdGhlIGltYmFsYW5jZSwgd2UgY2FuIGF0dGVtcHQgdG8gYmFsYW5jZSB0aGUgY2xhc3MgZnJlcXVlbmNpZXMuIFRha2luZyB0aGlzDQphcHByb2FjaCBlbGltaW5hdGVzIHRoZSBmdW5kYW1lbnRhbCBpbWJhbGFuY2UgaXNzdWUgdGhhdCBwbGFndWVzIG1vZGVsDQp0cmFpbmluZy4gSG93ZXZlciwgaWYgdGhlIHRyYWluaW5nIHNldCBpcyBzYW1wbGVkIHRvIGJlIGJhbGFuY2VkLCB0aGUgdGVzdCBzZXQNCnNob3VsZCBiZSBzYW1wbGVkIHRvIGJlIG1vcmUgY29uc2lzdGVudCB3aXRoIHRoZSBzdGF0ZSBvZiBuYXR1cmUgYW5kIHNob3VsZA0KcmVmbGVjdCB0aGUgaW1iYWxhbmNlIHNvIHRoYXQgaG9uZXN0IGVzdGltYXRlcyBvZiBmdXR1cmUgcGVyZm9ybWFuY2UgY2FuIGJlDQpjb21wdXRlZC4NCg0KDQpUd28gZ2VuZXJhbCBwb3N0IGhvYyBhcHByb2FjaGVzIGFyZSAqKnVuZGVyLXNhbXBsaW5nKiogKG9yIGRvd25zYW1wbGluZykgYW5kICoqdXAtc2FtcGxpbmcqKiAob3Igb3ZlcnNhbXBsaW5nKSB0aGUgZGF0YS4gVXAtc2FtcGxpbmcgaXMgYW55IHRlY2huaXF1ZSB0aGF0IHNpbXVsYXRlcyBvciBpbXB1dGVzIGFkZGl0aW9uYWwgZGF0YSBwb2ludHMgdG8gaW1wcm92ZSBiYWxhbmNlIGFjcm9zcyBjbGFzc2VzLCB3aGlsZSBkb3duLXNhbXBsaW5nIHJlZmVycyB0byBhbnkgdGVjaG5pcXVlIHRoYXQgcmVkdWNlcyB0aGUgbnVtYmVyIG9mIHNhbXBsZXMgdG8gaW1wcm92ZSB0aGUNCmJhbGFuY2UgYWNyb3NzIGNsYXNzZXMuDQoNCg0KTW9yZSBzcGVjaWFsbHksIHRoZSBmaXJzdCB3YXkgdG8gaW5jcmVhc2UgdGhlIG51bWJlciBvZiBkZWZhdWx0ZXJzIGlzIGJ5IGluY3JlYXNpbmcgdGhlIHdlaWdodCBvZiB0aGUgZGVmYXVsdGVycyBpcyBieSBlaXRoZXIgb3ZlcnNhbXBsaW5nIChvciB1cC1zYW1wbGluZykgdGhlbQ0Kb3IgYnkgdW5kZXJzYW1wbGluZyB0aGUgbm9uZGVmYXVsdGVycy4gSGVyZSwgdGhlIGlkZWEgaXMgdG8gcmVwbGljYXRlIHRoZSBkZWZhdWx0ZXJzIHR3byBvciBtb3JlIHRpbWVzIHNvIGFzIHRvIG1ha2UgdGhlDQpkaXN0cmlidXRpb24gbGVzcyBza2V3ZWQuIExpbmcgYW5kIExpICgxOTk4KSBwcm92aWRlIG9uZSBhcHByb2FjaCB0byB1cC1zYW1wbGluZyBpbiB3aGljaCBjYXNlcw0KZnJvbSB0aGUgbWlub3JpdHkgY2xhc3NlcyBhcmUgc2FtcGxlZCB3aXRoIHJlcGxhY2VtZW50IHVudGlsIGVhY2ggY2xhc3MgaGFzDQphcHByb3hpbWF0ZWx5IHRoZSBzYW1lIG51bWJlci4gRm9yIHRoZSBpbnN1cmFuY2UgZGF0YSwgdGhlIHRyYWluaW5nIHNldA0KY29udGFpbmVkIDY0NjYgbm9uLXBvbGljeSBhbmQgNDExIGluc3VyZWQgY3VzdG9tZXJzLiBJZiB3ZSBrZWVwIHRoZSBvcmlnaW5hbA0KbWlub3JpdHkgY2xhc3MgZGF0YSwgYWRkaW5nIDYwNTUgcmFuZG9tIHNhbXBsZXMgKHdpdGggcmVwbGFjZW1lbnQpIHdvdWxkDQpicmluZyB0aGUgbWlub3JpdHkgY2xhc3MgZXF1YWwgdG8gdGhlIG1ham9yaXR5LiBJbiBkb2luZyB0aGlzLCBzb21lIG1pbm9yaXR5DQpjbGFzcyBzYW1wbGVzIG1heSBzaG93IHVwIGluIHRoZSB0cmFpbmluZyBzZXQgd2l0aCBhIGZhaXJseSBoaWdoIGZyZXF1ZW5jeQ0Kd2hpbGUgZWFjaCBzYW1wbGUgaW4gdGhlIG1ham9yaXR5IGNsYXNzIGhhcyBhIHNpbmdsZSByZWFsaXphdGlvbiBpbiB0aGUgZGF0YS4NClRoaXMgaXMgdmVyeSBzaW1pbGFyIHRvIHRoZSBjYXNlIHdlaWdodCBhcHByb2FjaCBzaG93biBpbiBhbiBlYXJsaWVyIHNlY3Rpb24sDQp3aXRoIHZhcnlpbmcgd2VpZ2h0cyBwZXIgY2FzZS4NCg0KDQpPbiB0aGUgY29udHJhcnksIHVuZGVyc2FtcGxpbmcgKG9yIERvd24tc2FtcGxpbmcpIGJhbGFuY2VzIHRoZSBkYXRhc2V0IGJ5IHJlZHVjaW5nIHRoZSBzaXplIG9mIHRoZSBhYnVuZGFudCBjbGFzcy4gVGhpcyBtZXRob2QgaXMgdXNlZCB3aGVuIHF1YW50aXR5IG9mIGRhdGEgaXMgc3VmZmljaWVudC4gQnkga2VlcGluZyBhbGwgc2FtcGxlcyBpbiB0aGUgcmFyZSBjbGFzcyBhbmQgcmFuZG9tbHkgc2VsZWN0aW5nIGFuIGVxdWFsIG51bWJlciBvZiBzYW1wbGVzIGluIHRoZSBhYnVuZGFudCBjbGFzcywgYSBiYWxhbmNlZCBuZXcgZGF0YXNldCBjYW4gYmUgcmV0cmlldmVkIGZvciBmdXJ0aGVyIG1vZGVsbGluZy4gRG93bi1zYW1wbGluZyBzZWxlY3RzIGRhdGEgcG9pbnRzIGZyb20gdGhlIG1ham9yaXR5IGNsYXNzIHNvIHRoYXQgdGhlIG1hLQ0Kam9yaXR5IGNsYXNzIGlzIHJvdWdobHkgdGhlIHNhbWUgc2l6ZSBhcyB0aGUgbWlub3JpdHkgY2xhc3MoZXMpLiBUaGVyZSBhcmUgc2V2ZXJhbA0KYXBwcm9hY2hlcyB0byBkb3duLXNhbXBsaW5nLiBGaXJzdCwgYSBiYXNpYyBhcHByb2FjaCBpcyB0byByYW5kb21seSBzYW1wbGUNCnRoZSBtYWpvcml0eSBjbGFzc2VzIHNvIHRoYXQgYWxsIGNsYXNzZXMgaGF2ZSBhcHByb3hpbWF0ZWx5IHRoZSBzYW1lIHNpemUuIEFub3RoZXIgYXBwcm9hY2ggd291bGQgYmUgdG8gdGFrZSBhIGJvb3RzdHJhcCBzYW1wbGUgYWNyb3NzIGFsbCBjYXNlcyBzdWNoIHRoYXQNCnRoZSBjbGFzc2VzIGFyZSBiYWxhbmNlZCBpbiB0aGUgYm9vdHN0cmFwIHNldC4gVGhlIGFkdmFudGFnZSBvZiB0aGlzIGFwcHJvYWNoDQppcyB0aGF0IHRoZSBib290c3RyYXAgc2VsZWN0aW9uIGNhbiBiZSBydW4gbWFueSB0aW1lcyBzbyB0aGF0IHRoZSBlc3RpbWF0ZSBvZiB2YXJpYXRpb24gY2FuIGJlIG9idGFpbmVkIGFib3V0IHRoZSBkb3duLXNhbXBsaW5nLiBPbmUgaW1wbGVtZW50YXRpb24NCm9mIHJhbmRvbSBmb3Jlc3RzIGNhbiBpbmhlcmVudGx5IGRvd24tc2FtcGxlIGJ5IGNvbnRyb2xsaW5nIHRoZSBib290c3RyYXANCnNhbXBsaW5nIHByb2Nlc3Mgd2l0aGluIGEgc3RyYXRpZmljYXRpb24gdmFyaWFibGUuIElmIGNsYXNzIGlzIHVzZWQgYXMgdGhlIHN0cmF0aWZpY2F0aW9uIHZhcmlhYmxlLCB0aGVuIGJvb3RzdHJhcCBzYW1wbGVzIHdpbGwgYmUgY3JlYXRlZCB0aGF0IGFyZSByb3VnaGx5IHRoZQ0Kc2FtZSBzaXplIHBlciBjbGFzcy4gVGhlc2UgaW50ZXJuYWxseSBkb3duLXNhbXBsZWQgdmVyc2lvbnMgb2YgdGhlIHRyYWluaW5nDQpzZXQgYXJlIHRoZW4gdXNlZCB0byBjb25zdHJ1Y3QgdHJlZXMgaW4gdGhlIGVuc2VtYmxlLg0KDQoNClRoZSB0aGlyZCBhcHByb2FjaCBpcyBhICJtaXhlZCBjb21iaW5hdGlvbiIgb2YgdGhlIHR3byBtZXRob2RzIGRlc2NpYmVkIGFib3ZlLiAqKlRoZSBzeW50aGV0aWMgbWlub3JpdHkgb3Zlci1zYW1wbGluZyB0ZWNobmlxdWUgKFNNT1RFKSoqLCBwcm9wb3NlZCBieQ0KQ2hhd2xhIGV0IGFsLiAoMjAwMiksIGlzIGEgZGF0YSBzYW1wbGluZyBwcm9jZWR1cmUgdGhhdCB1c2VzIGJvdGggdXAtc2FtcGxpbmcNCmFuZCBkb3duLXNhbXBsaW5nLCBkZXBlbmRpbmcgb24gdGhlIGNsYXNzLCBhbmQgaGFzIHRocmVlIG9wZXJhdGlvbmFsIHBhcmFtZXRlcnM6IHRoZSBhbW91bnQgb2YgdXAtc2FtcGxpbmcsIHRoZSBhbW91bnQgb2YgZG93bi1zYW1wbGluZywgYW5kIHRoZQ0KbnVtYmVyIG9mIG5laWdoYm9ycyB0aGF0IGFyZSB1c2VkIHRvIGltcHV0ZSBuZXcgY2FzZXMuIFRvIHVwLXNhbXBsZSBmb3IgdGhlDQptaW5vcml0eSBjbGFzcywgU01PVEUgc3ludGhlc2l6ZXMgbmV3IGNhc2VzLiBUbyBkbyB0aGlzLCBhIGRhdGEgcG9pbnQgaXMgcmFuZG9tbHkgc2VsZWN0ZWQgZnJvbSB0aGUgbWlub3JpdHkgY2xhc3MgYW5kIGl0cyBLLW5lYXJlc3QgbmVpZ2hib3JzIChLTk5zKQ0KYXJlIGRldGVybWluZWQuIENoYXdsYSBldCBhbC4gKDIwMDIpIHVzZWQgZml2ZSBuZWlnaGJvcnMgaW4gdGhlaXIgYW5hbHlzZXMsDQpidXQgZGlmZmVyZW50IHZhbHVlcyBjYW4gYmUgdXNlZCBkZXBlbmRpbmcgb24gdGhlIGRhdGEuIFRoZSBuZXcgc3ludGhldGljDQpkYXRhIHBvaW50IGlzIGEgcmFuZG9tIGNvbWJpbmF0aW9uIG9mIHRoZSBwcmVkaWN0b3JzIG9mIHRoZSByYW5kb21seSBzZWxlY3RlZCBkYXRhIHBvaW50IGFuZCBpdHMgbmVpZ2hib3JzLiBXaGlsZSB0aGUgU01PVEUgYWxnb3JpdGhtIGFkZHMgbmV3DQpzYW1wbGVzIHRvIHRoZSBtaW5vcml0eSBjbGFzcyB2aWEgdXAtc2FtcGxpbmcsIGl0IGFsc28gY2FuIGRvd24tc2FtcGxlIGNhc2VzDQpmcm9tIHRoZSBtYWpvcml0eSBjbGFzcyB2aWEgcmFuZG9tIHNhbXBsaW5nIGluIG9yZGVyIHRvIGhlbHAgYmFsYW5jZSB0aGUNCnRyYWluaW5nIHNldC4NCg0KDQojIyMgU29sdXRpb24gMjogTW9kZWwgVHVuaW5nDQoNClRoZSBzaW1wbGVzdCBhcHByb2FjaCB0byBjb3VudGVyYWN0aW5nIHRoZSBuZWdhdGl2ZSBlZmZlY3RzIG9mIGNsYXNzIGltYmFsYW5jZQ0KaXMgdG8gdHVuZSB0aGUgbW9kZWwgdG8gbWF4aW1pemUgdGhlIGFjY3VyYWN5IG9mIHRoZSBtaW5vcml0eSBjbGFzcyhlcykuDQpGb3IgZGVmYXVsdCBsb2FuIHByZWRpY3Rpb24sIHR1bmluZyB0aGUgbW9kZWwgdG8gbWF4aW1pemUgdGhlIHNlbnNpdGl2aXR5IG1heQ0KaGVscCBkZXNlbnNpdGl6ZSB0aGUgdHJhaW5pbmcgcHJvY2VzcyB0byB0aGUgaGlnaCBwZXJjZW50YWdlIG9mIG5vbmRlZmF1bHQgY2FzZXMgaW4gdGhlIHRyYWluaW5nIHNldC4gDQoNCiMjIyBTb2x1dGlvbiAzOiBTZWFyY2ggT3B0aW1hbCBUaHJlc2hvbGQNCg0KV2hlbiB0aGVyZSBhcmUgdHdvIHBvc3NpYmxlIG91dGNvbWUgY2F0ZWdvcmllcyAoc3VjaCBhcyBpbiBjYXNlIG9mIGRlZmF1bHQgbG9hbiBwcmVkaWN0aW9uKSwgYW5vdGhlciBtZXRob2QgZm9yIGluY3JlYXNpbmcgdGhlIHByZWRpY3Rpb24gYWNjdXJhY3kgb2YgdGhlIG1pbm9yaXR5IGNsYXNzIHNhbXBsZXMgaXMgdG8gZGV0ZXJtaW5lIGFsdGVybmF0aXZlIGN1dG9mZnMgZm9yIHRoZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdGllcyB3aGljaCBlZmZlY3RpdmVseSBjaGFuZ2VzDQp0aGUgZGVmaW5pdGlvbiBvZiBhIHByZWRpY3RlZCBldmVudC4gVGhlIG1vc3Qgc3RyYWlnaHRmb3J3YXJkIGFwcHJvYWNoIGlzIHRvDQp1c2UgdGhlIFJPQyBjdXJ2ZSBzaW5jZSBpdCBjYWxjdWxhdGVzIHRoZSBzZW5zaXRpdml0eSBhbmQgc3BlY2lmaWNpdHkgYWNyb3NzDQphIGNvbnRpbnV1bSBvZiBjdXRvZmZzLiBVc2luZyB0aGlzIGN1cnZlLCBhbiBhcHByb3ByaWF0ZSBiYWxhbmNlIGJldHdlZW4NCnNlbnNpdGl2aXR5IGFuZCBzcGVjaWZpY2l0eSBjYW4gYmUgZGV0ZXJtaW5lZC4NCg0KIyMjIFNvbHV0aW9uIDM6IEFkanVzdGluZyBQcmlvciBQcm9iYWJpbGl0aWVzDQoNClNldmVyYWwgdGVjaG5pcXVlcyBleGlzdCBmb3IgZGV0ZXJtaW5pbmcgYSBuZXcgY3V0b2ZmLiBGaXJzdCwgaWYgdGhlcmUgaXMNCmEgcGFydGljdWxhciB0YXJnZXQgdGhhdCBtdXN0IGJlIG1ldCBmb3IgdGhlIHNlbnNpdGl2aXR5IG9yIHNwZWNpZmljaXR5LCB0aGlzDQpwb2ludCBjYW4gYmUgZm91bmQgb24gdGhlIFJPQyBjdXJ2ZSBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgY3V0b2ZmIGNhbiBiZQ0KZGV0ZXJtaW5lZC4gQW5vdGhlciBhcHByb2FjaCBpcyB0byBmaW5kIHRoZSBwb2ludCBvbiB0aGUgUk9DIGN1cnZlIHRoYXQgaXMNCmNsb3Nlc3QgKGkuZS4sIHRoZSBzaG9ydGVzdCBkaXN0YW5jZSkgdG8gdGhlIHBlcmZlY3QgbW9kZWwgKHdpdGggMTAwICUgc2Vuc2l0aXZpdHkNCmFuZCAxMDAgJSBzcGVjaWZpY2l0eSksIHdoaWNoIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgdXBwZXIgbGVmdCBjb3JuZXIgb2YgdGhlDQpwbG90LiANCg0KQW5vdGhlciBhcHByb2FjaCBmb3IgZGV0ZXJtaW5pbmcgdGhlIGN1dG9mZiB1c2VzIFlvdWRlbuKAmXMgSiBpbmRleCwgd2hpY2ggbWVhc3VyZXMgdGhlIHByb3BvcnRpb24gb2YgY29ycmVjdGx5IHByZWRpY3RlZCBzYW1wbGVzDQpmb3IgYm90aCB0aGUgZXZlbnQgYW5kIG5vbmV2ZW50IGdyb3Vwcy4gVGhpcyBpbmRleCBjYW4gYmUgY29tcHV0ZWQgZm9yIGVhY2gNCmN1dG9mZiB0aGF0IGlzIHVzZWQgdG8gY3JlYXRlIHRoZSBST0MgY3VydmUuIFRoZSBjdXRvZmYgYXNzb2NpYXRlZCB3aXRoIHRoZQ0KbGFyZ2VzdCB2YWx1ZSBvZiB0aGUgWW91ZGVuIGluZGV4IG1heSBhbHNvIHNob3cgc3VwZXJpb3IgcGVyZm9ybWFuY2UgcmVsYXRpdmUgdG8gdGhlIGRlZmF1bHQgNTAgJSB2YWx1ZS4NCg0KU29tZSBtb2RlbHMgdXNlIHByaW9yIHByb2JhYmlsaXRpZXMsIHN1Y2ggYXMgbmHEscyIdmUgQmF5ZXMgYW5kIGRpc2NyaW1pbmFudA0KYW5hbHlzaXMgY2xhc3NpZmllcnMuIFVubGVzcyBzcGVjaWZpZWQgbWFudWFsbHksIHRoZXNlIG1vZGVscyB0eXBpY2FsbHkgZGVyaXZlDQp0aGUgdmFsdWUgb2YgdGhlIHByaW9ycyBmcm9tIHRoZSB0cmFpbmluZyBkYXRhLiBXZWlzcyBhbmQgUHJvdm9zdCAoMjAwMWEpDQpzdWdnZXN0IHRoYXQgcHJpb3JzIHRoYXQgcmVmbGVjdCB0aGUgbmF0dXJhbCBjbGFzcyBpbWJhbGFuY2Ugd2lsbCBtYXRlcmlhbGx5IGJpYXMNCnByZWRpY3Rpb25zIHRvIHRoZSBtYWpvcml0eSBjbGFzcy4gVXNpbmcgbW9yZSBiYWxhbmNlZCBwcmlvcnMgb3IgYSBiYWxhbmNlZA0KdHJhaW5pbmcgc2V0IG1heSBoZWxwIGRlYWwgd2l0aCBhIGNsYXNzIGltYmFsYW5jZS4NCg0KIyMjIFNvbHV0aW9uIDQ6IENvc3QtU2Vuc2l0aXZlIFRyYWluaW5nDQoNCkluc3RlYWQgb2Ygb3B0aW1pemluZyB0aGUgdHlwaWNhbCBwZXJmb3JtYW5jZSBtZWFzdXJlLCBzdWNoIGFzIGFjY3VyYWN5IG9yDQppbXB1cml0eSwgc29tZSBtb2RlbHMgY2FuIGFsdGVybmF0aXZlbHkgb3B0aW1pemUgYSBjb3N0IG9yIGxvc3MgZnVuY3Rpb24NCnRoYXQgZGlmZmVyZW50aWFsbHkgd2VpZ2h0cyBzcGVjaWZpYyB0eXBlcyBvZiBlcnJvcnMuIEZvciBleGFtcGxlLCBpdCBtYXkgYmUgYXBwcm9wcmlhdGUgdG8gYmVsaWV2ZSB0aGF0IG1pc2NsYXNzaWZ5aW5nIHRydWUgZXZlbnRzIChmYWxzZSBuZWdhdGl2ZXMpIGlzIFgNCnRpbWVzIGFzIGNvc3RseSBhcyBpbmNvcnJlY3RseSBwcmVkaWN0aW5nIG5vbmV2ZW50cyAoZmFsc2UgcG9zaXRpdmVzKS4gSW5jb3Jwb3JhdGlvbiBvZiBzcGVjaWZpYyBjb3N0cyBkdXJpbmcgbW9kZWwgdHJhaW5pbmcgbWF5IGJpYXMgdGhlIG1vZGVsIHRvd2FyZHMgbGVzcyBmcmVxdWVudCBjbGFzc2VzLiBVbmxpa2UgdXNpbmcgYWx0ZXJuYXRpdmUgY3V0b2ZmcywgdW5lcXVhbCBjb3N0cyBjYW4gYWZmZWN0IHRoZSBtb2RlbCBwYXJhbWV0ZXJzIGFuZCB0aHVzIGhhdmUgdGhlIHBvdGVudGlhbCB0byBtYWtlIHRydWUgaW1wcm92ZW1lbnRzIHRvIHRoZSBjbGFzc2lmaWVyLg0KDQojIyMgQSBSZWFsLXdvcmxkIEFwcGxpY2F0aW9uOiBQcmVkaWN0aW5nIERlZmF1bHRlcnMgZnJvbSBNb3J0Z2FnZSBBcHBsaWNhdGlvbnMNCg0KSW4gdGhpcyBwb3N0IEkgd2lsbCBvbmx5IHByZXNlbnQgdGhlIG1ldGhvZCBvZiB1c2luZyB0aGUgb3ZlcnNhbXBsaW5nIHRlY2huaXF1ZSBmb3IgZGVhbGluZyB3aXRoIGltYmFsYW5jZWQgZGF0YSBpbiBwcmFjdGljZS4gRGF0YSB1c2VkIGlzIENhcmF2YW4gd2hpY2ggY29udGFpbnMgNTgyMiByZWFsIGN1c3RvbWVyIHJlY29yZHMuIGFjaCByZWNvcmQgY29uc2lzdHMgb2YgODYgdmFyaWFibGVzLCBjb250YWluaW5nIHNvY2lvZGVtb2dyYXBoaWMgZGF0YSAodmFyaWFibGVzIDEtNDMpIGFuZCBwcm9kdWN0IG93bmVyc2hpcCAodmFyaWFibGVzIDQ0LTg2KS4gVGhlIHNvY2lvZGVtb2dyYXBoaWMgZGF0YSBpcyBkZXJpdmVkIGZyb20gemlwIGNvZGVzLiBBbGwgY3VzdG9tZXJzIGxpdmluZyBpbiBhcmVhcyB3aXRoIHRoZSBzYW1lIHppcCBjb2RlIGhhdmUgdGhlIHNhbWUgc29jaW9kZW1vZ3JhcGhpYyBhdHRyaWJ1dGVzLiBWYXJpYWJsZSA4NiAoUHVyY2hhc2UpIGluZGljYXRlcyB3aGV0aGVyIHRoZSBjdXN0b21lciBwdXJjaGFzZWQgYSBjYXJhdmFuIGluc3VyYW5jZSBwb2xpY3kuIEZ1cnRoZXIgaW5mb3JtYXRpb24gb24gdGhlIGluZGl2aWR1YWwgdmFyaWFibGVzIGNhbiBiZSBvYnRhaW5lZCBhdCBodHRwOi8vd3d3LmxpYWNzLm5sL35wdXR0ZW4vbGlicmFyeS9jYzIwMDAvZGF0YS5odG1sLiANCg0KDQpGb3IgdGhpcyBkYXRhIHNldCwgdGhlcmUgYXJlIHR3byB0ZWNobmljYWwgYXNwZWN0cyBtdXN0IGJlIGNvbnNpZGVyZWQ6ICgxKSBCZXR3ZWVuLVByZWRpY3RvciBDb3JyZWxhdGlvbnMsICgyKSBaZXJvLSBhbmQgTmVhciBaZXJvLVZhcmlhbmNlIFByZWRpY3RvcnMuIA0KDQojIyMgQmV0d2Vlbi1QcmVkaWN0b3IgQ29ycmVsYXRpb25zDQoNCg0KQ29sbGluZWFyaXR5IGlzIHRoZSB0ZWNobmljYWwgdGVybSBmb3IgdGhlIHNpdHVhdGlvbiB3aGVyZSBhIHBhaXIgb2YgcHJlZGljdG9yIHZhcmlhYmxlcyBoYXZlIGEgc3Vic3RhbnRpYWwgY29ycmVsYXRpb24gd2l0aCBlYWNoIG90aGVyLiBJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIGhhdmUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIG11bHRpcGxlIHByZWRpY3RvcnMgYXQgb25jZSAoY2FsbGVkIG11bHRpY29sbGluZWFyaXR5KS4NCg0KSW4gZ2VuZXJhbCwgdGhlcmUgYXJlIGdvb2QgcmVhc29ucyB0byBhdm9pZCBkYXRhIHdpdGggaGlnaGx5IGNvcnJlbGF0ZWQNCnByZWRpY3RvcnMuIEZpcnN0LCByZWR1bmRhbnQgcHJlZGljdG9ycyBmcmVxdWVudGx5IGFkZCBtb3JlIGNvbXBsZXhpdHkgdG8gdGhlDQptb2RlbCB0aGFuIGluZm9ybWF0aW9uIHRoZXkgcHJvdmlkZSB0byB0aGUgbW9kZWwuIEluIHNpdHVhdGlvbnMgd2hlcmUgb2J0YWluaW5nIHRoZSBwcmVkaWN0b3IgZGF0YSBpcyBjb3N0bHkgKGVpdGhlciBpbiB0aW1lIG9yIG1vbmV5KSwgZmV3ZXIgdmFyaWFibGVzDQppcyBvYnZpb3VzbHkgYmV0dGVyLiBXaGlsZSB0aGlzIGFyZ3VtZW50IGlzIG1vc3RseSBwaGlsb3NvcGhpY2FsLCB0aGVyZSBhcmUNCm1hdGhlbWF0aWNhbCBkaXNhZHZhbnRhZ2VzIHRvIGhhdmluZyBjb3JyZWxhdGVkIHByZWRpY3RvciBkYXRhLiBVc2luZyBoaWdobHkNCmNvcnJlbGF0ZWQgcHJlZGljdG9ycyBpbiB0ZWNobmlxdWVzIGxpa2UgbGluZWFyIHJlZ3Jlc3Npb24gY2FuIHJlc3VsdCBpbiBoaWdobHkNCnVuc3RhYmxlIG1vZGVscywgbnVtZXJpY2FsIGVycm9ycywgYW5kIGRlZ3JhZGVkIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UuDQoNClNpbmNlIGNvbGxpbmVhciBwcmVkaWN0b3JzIGNhbiBpbXBhY3QgdGhlIHZhcmlhbmNlIG9mIHBhcmFtZXRlciBlc3RpbWF0ZXMgaW4gdGhpcyBtb2RlbCwgYSBzdGF0aXN0aWMgY2FsbGVkIHRoZSB2YXJpYW5jZSBpbmZsYXRpb24NCmZhY3RvciAoVklGKSBjYW4gYmUgdXNlZCB0byBpZGVudGlmeSBwcmVkaWN0b3JzIHRoYXQgYXJlIGltcGFjdGVkIChNeWVycywgMTk5NCkuIEJleW9uZCBsaW5lYXIgcmVncmVzc2lvbiwgdGhpcyBtZXRob2QgbWF5IGJlIGluYWRlcXVhdGUgZm9yIHNldmVyYWwNCnJlYXNvbnM6IGl0IHdhcyBkZXZlbG9wZWQgZm9yIGxpbmVhciBtb2RlbHMsIGl0IHJlcXVpcmVzIG1vcmUgc2FtcGxlcyB0aGFuIHByZWRpY3RvciB2YXJpYWJsZXMsIGFuZCwgd2hpbGUgaXQgZG9lcyBpZGVudGlmeSBjb2xsaW5lYXIgcHJlZGljdG9ycywgaXQgZG9lcw0Kbm90IGRldGVybWluZSB3aGljaCBzaG91bGQgYmUgcmVtb3ZlZCB0byByZXNvbHZlIHRoZSBwcm9ibGVtLg0KDQpBIGxlc3MgdGhlb3JldGljYWwsIG1vcmUgaGV1cmlzdGljIGFwcHJvYWNoIHRvIGRlYWxpbmcgd2l0aCB0aGlzIGlzc3VlIGlzIHRvIHJlbW92ZSB0aGUgbWluaW11bSBudW1iZXIgb2YgcHJlZGljdG9ycyB0byBlbnN1cmUgdGhhdCBhbGwgcGFpcndpc2UNCmNvcnJlbGF0aW9ucyBhcmUgYmVsb3cgYSBjZXJ0YWluIHRocmVzaG9sZC4gV2hpbGUgdGhpcyBtZXRob2Qgb25seSBpZGVudGlmeSBjb2xsaW5lYXJpdGllcyBpbiB0d28gZGltZW5zaW9ucywgaXQgY2FuIGhhdmUgYSBzaWduaWZpY2FudGx5IHBvc2l0aXZlIGVmZmVjdCBvbiB0aGUgcGVyZm9ybWFuY2Ugb2Ygc29tZSBtb2RlbHMuDQoNClRoZSBhbGdvcml0aG0gaXMgYXMgZm9sbG93czoNCg0KMS4gQ2FsY3VsYXRlIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggb2YgdGhlIHByZWRpY3RvcnMuDQoNCjIuIERldGVybWluZSB0aGUgdHdvIHByZWRpY3RvcnMgYXNzb2NpYXRlZCB3aXRoIHRoZSBsYXJnZXN0IGFic29sdXRlIHBhaXJ3aXNlDQpjb3JyZWxhdGlvbiAoY2FsbCB0aGVtIHByZWRpY3RvcnMgQSBhbmQgQikuDQoNCjMuIERldGVybWluZSB0aGUgYXZlcmFnZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIEEgYW5kIHRoZSBvdGhlciB2YXJpYWJsZXMuDQpEbyB0aGUgc2FtZSBmb3IgcHJlZGljdG9yIEIuDQoNCjQuIElmIEEgaGFzIGEgbGFyZ2VyIGF2ZXJhZ2UgY29ycmVsYXRpb24sIHJlbW92ZSBpdDsgb3RoZXJ3aXNlLCByZW1vdmUgcHJlZGljdG9yIEIuDQoNCjUuIFJlcGVhdCBTdGVwcyAy4oCTNCB1bnRpbCBubyBhYnNvbHV0ZSBjb3JyZWxhdGlvbnMgYXJlIGFib3ZlIHRoZSB0aHJlc2hvbGQuDQoNClRoZSBpZGVhIGlzIHRvIGZpcnN0IHJlbW92ZSB0aGUgcHJlZGljdG9ycyB0aGF0IGhhdmUgdGhlIG1vc3QgY29ycmVsYXRlZCByZWxhdGlvbnNoaXBzLg0KDQpGb3IgZXhhbXBsZSwgU3VwcG9zZSB3ZSB3YW50ZWQgdG8gdXNlIGEgbW9kZWwgdGhhdCBpcyBwYXJ0aWN1bGFybHkgc2Vuc2l0aXZlIHRvIGJldHdlZW4tcHJlZGljdG9yIGNvcnJlbGF0aW9ucywgd2UgbWlnaHQgYXBwbHkgYSB0aHJlc2hvbGQgb2YgMC43NS4gVGhpcyBtZWFucyB0aGF0IHdlDQp3YW50IHRvIGVsaW1pbmF0ZSB0aGUgbWluaW11bSBudW1iZXIgb2YgcHJlZGljdG9ycyB0byBhY2hpZXZlIGFsbCBwYWlyd2lzZSBjb3JyZWxhdGlvbnMgbGVzcyB0aGFuIDAuNzUuDQoNCiMjIyBaZXJvLSBhbmQgTmVhciBaZXJvLVZhcmlhbmNlIFByZWRpY3RvcnMNCg0KVGhlcmUgYXJlIHBvdGVudGlhbCBhZHZhbnRhZ2VzIHRvIHJlbW92aW5nIHByZWRpY3RvcnMgcHJpb3IgdG8gbW9kZWxpbmcuDQpGaXJzdCwgZmV3ZXIgcHJlZGljdG9ycyBtZWFucyBkZWNyZWFzZWQgY29tcHV0YXRpb25hbCB0aW1lIGFuZCBjb21wbGV4aXR5Lg0KU2Vjb25kLCBpZiB0d28gcHJlZGljdG9ycyBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQsIHRoaXMgaW1wbGllcyB0aGF0IHRoZXkgYXJlIG1lYXN1cmluZyB0aGUgc2FtZSB1bmRlcmx5aW5nIGluZm9ybWF0aW9uLiBSZW1vdmluZyBvbmUgc2hvdWxkIG5vdCBjb21wcm9taXNlIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgbW9kZWwgYW5kIG1pZ2h0IGxlYWQgdG8gYSBtb3JlIHBhcnNpbW9uaW91c2FuZCBpbnRlcnByZXRhYmxlIG1vZGVsLiBUaGlyZCwgc29tZSBtb2RlbHMgY2FuIGJlIGNyaXBwbGVkIGJ5IHByZWRpY3RvcnMNCndpdGggZGVnZW5lcmF0ZSBkaXN0cmlidXRpb25zLiBJbiB0aGVzZSBjYXNlcywgdGhlcmUgY2FuIGJlIGEgc2lnbmlmaWNhbnQgaW1wcm92ZW1lbnQgaW4gbW9kZWwgcGVyZm9ybWFuY2UgYW5kL29yIHN0YWJpbGl0eSB3aXRob3V0IHRoZSBwcm9ibGVtYXRpYyB2YXJpYWJsZXMuDQoNCkNvbnNpZGVyIGEgcHJlZGljdG9yIHZhcmlhYmxlIHRoYXQgaGFzIGEgc2luZ2xlIHVuaXF1ZSB2YWx1ZTsgd2UgcmVmZXIgdG8gdGhpcyB0eXBlIG9mIGRhdGEgYXMgKiphIHplcm8gdmFyaWFuY2UgcHJlZGljdG9yKiouIEZvciBzb21lIG1vZGVscywgc3VjaCBhbiB1bmluZm9ybWF0aXZlIHZhcmlhYmxlIG1heSBoYXZlIGxpdHRsZSBlZmZlY3Qgb24gdGhlIGNhbGN1bGF0aW9ucy4gRm9yIGV4YW1wbGUsIGEgdHJlZS1iYXNlZCBtb2RlbCBpcyBpbXBlcnZpb3VzIHRvIHRoaXMgdHlwZSBvZiBwcmVkaWN0b3Igc2luY2UgaXQNCndvdWxkIG5ldmVyIGJlIHVzZWQgaW4gYSBzcGxpdC4gSG93ZXZlciwgYSBtb2RlbCBzdWNoIGFzIGxpbmVhciByZWdyZXNzaW9uDQp3b3VsZCBmaW5kIHRoZXNlIGRhdGEgcHJvYmxlbWF0aWMgYW5kIGlzIGxpa2VseSB0byBjYXVzZSBhbiBlcnJvciBpbiB0aGUgY29tcHV0YXRpb25zLiBJbiBlaXRoZXIgY2FzZSwgdGhlc2UgZGF0YSBoYXZlIG5vIGluZm9ybWF0aW9uIGFuZCBjYW4gZWFzaWx5IGJlIGRpc2NhcmRlZC4NCg0KU2ltaWxhcmx5LCBzb21lIHByZWRpY3RvcnMgbWlnaHQgaGF2ZSBvbmx5IGEgaGFuZGZ1bCBvZiB1bmlxdWUgdmFsdWVzIHRoYXQgb2NjdXIgd2l0aCB2ZXJ5IGxvdyBmcmVxdWVuY2llcy4gVGhlc2Ug4oCcbmVhci16ZXJvIHZhcmlhbmNlIHByZWRpY3RvcnPigJ0gbWF5IGhhdmUgYSBzaW5nbGUgdmFsdWUgZm9yIHRoZSB2YXN0IG1ham9yaXR5IG9mIHRoZSBzYW1wbGVzLiANCg0KSG93IGNhbiB0aGUgdXNlciBkaWFnbm9zZSB0aGlzIG1vZGUgb2YgcHJvYmxlbWF0aWMgZGF0YT8gQSBydWxlIG9mIHRodW1iIGZvciBkZXRlY3RpbmcgbmVhci16ZXJvIHZhcmlhbmNlIHByZWRpY3RvcnMgaXM6IA0KDQotIFRoZSBmcmFjdGlvbiBvZiB1bmlxdWUgdmFsdWVzIG92ZXIgdGhlIHNhbXBsZSBzaXplIGlzIGxvdyAoc2F5IDEwICUpLg0KDQotIFRoZSByYXRpbyBvZiB0aGUgZnJlcXVlbmN5IG9mIHRoZSBtb3N0IHByZXZhbGVudCB2YWx1ZSB0byB0aGUgZnJlcXVlbmN5IG9mIHRoZSBzZWNvbmQgbW9zdCBwcmV2YWxlbnQgdmFsdWUgaXMgbGFyZ2UgKHNheSBhcm91bmQgMjApLg0KDQpJZiBib3RoIG9mIHRoZXNlIGNyaXRlcmlhIGFyZSB0cnVlIGFuZCB0aGUgbW9kZWwgaW4gcXVlc3Rpb24gaXMgc3VzY2VwdGlibGUgdG8gdGhpcyB0eXBlIG9mIHByZWRpY3RvciwgaXQgbWF5IGJlIGFkdmFudGFnZW91cyB0byByZW1vdmUgdGhlIHZhcmlhYmxlIGZyb20gdGhlIG1vZGVsLg0KDQojIyMgUiBDb2Rlcw0KDQpJbiB0aGlzIHNlY3Rpb24gSSB3aWxsIHByZXNlbnQgUiBjb2RlcyBmb3Igb3ZlcnNhbXBsaW5nIGFuZCB1bmRlcnNhbXBsaW5nIHRlY2huaXF1ZS4gDQoNClRoZSBmaXJzdCBzdGFnZSBpcyB0byBkZXRlcm1pbmUgdGhlIG9wdGltYWwgcmF0aW8gYmV0d2VlbiBtYWpvcml0eSBhbmQgbWlub3JpdHkgY2xhc3MuIFRoaXMgcHJvY2VzcyBpcyBkb25lIGFzIGZvbGxvd3MuIEluIHRoZSBmaXJzdCBzdGVwLCBhbiBhbmFseXRpY2FsIG1vZGVsIGlzIGJ1aWx0IG9uIHRoZSBvcmlnaW5hbCBkYXRhIHNldCB3aXRoIHRoZSBza2V3IGNsYXNzIGRpc3RyaWJ1dGlvbiAoZm9yIGV4YW1wbGUsIDk1IHBlcmNlbnQvNSBwZXJjZW50IG5vbmRlZmF1bHRlcnMvDQpkZWZhdWx0ZXJzKS4gVGhlIGFyZWEgdW5kZXIgdGhlIGN1cnZlIChBVUMpIG9mIHRoaXMgbW9kZWwgaXMgcmVjb3JkZWQgKHBvc3NpYmx5IG9uDQphbiBpbmRlcGVuZGVudCB2YWxpZGF0aW9uIGRhdGEgc2V0KS4gSW4gYSBuZXh0IHN0ZXAsIG92ZXItIG9yIHVuZGVyc2FtcGxpbmcgaXMgdXNlZA0KdG8gY2hhbmdlIHRoZSBjbGFzcyBkaXN0cmlidXRpb24gYnkgNSBwZXJjZW50IChmb3IgZXhhbXBsZSwgOTAgcGVyY2VudC8xMCBwZXJjZW50KS4gQWdhaW4sIHRoZQ0KQVVDIG9mIHRoZSBtb2RlbCBpcyByZWNvcmRlZC4gU3Vic2VxdWVudCBtb2RlbHMgYXJlIGJ1aWx0IG9uIHNhbXBsZXMgb2YgODUgcGVyY2VudC8NCjE1IHBlcmNlbnQsIDgwIHBlcmNlbnQvMjAgcGVyY2VudCwgNzUgcGVyY2VudC8yNSBwZXJjZW50LCBhbmQgc28gb24sIGVhY2ggdGltZQ0KcmVjb3JkaW5nIHRoZWlyIEFVQ3MuIE9uY2UgdGhlIEFVQyBzdGFydHMgdG8gc3RhZ25hdGUgKG9yIGRyb3ApLCB0aGUgcHJvY2VkdXJlIHN0b3BzDQphbmQgdGhlIG9wdGltYWwgb2RkcyByYXRpbyBoYXMgYmVlbiBmb3VuZC4NCg0KVGhlIHNlY29uZCBzdGFnZSBpcyBjb21wYXJlIG1vZGVsIHJlc3VsdHMgYmFzZWQgb24gc29tZSB2YWx1YXRpb24gY3JpdGVyaWEuIA0KDQoNCmBgYHtyLCBmaWcuZnVsbHdpZHRoID0gVFJVRSwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTEyfQ0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAgU3RhZ2UgMTogRGF0YSBQcmUtcHJvY2Vzc2luZw0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIENsZWFyIHdvcmtzcGFjZTogDQpybShsaXN0ID0gbHMoKSkNCg0KIyBMb2FkIHBhY2thZ2VzIGFuZCBkYXRhOiANCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkoSVNMUikNCmRhdGEoIkNhcmF2YW4iKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgUmVtb3ZlIGNvbGxpbmVhciBhbmQgbmVhci16ZXJvIHZhcmlhbmNlIHByZWRpY3RvcnMNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgQWxsIG9yaWdpbmFsIHByZWRpY3RvcnM6IA0KZGZfcHJlZGljdG9ycyA8LSBDYXJhdmFuICU+JSBzZWxlY3QoLVB1cmNoYXNlKQ0KDQojIENvbXB1dGUgYW5kIHBsb3QgYSBjb3JyZWxhdGlvbiBtYXRyaXg6ICANCmxpYnJhcnkoY29ycnBsb3QpDQoNCmRmX3ByZWRpY3RvcnMgJT4lDQogIGNvciguKSAtPiBjb3JyZWxhdGlvbnMgDQoNCmNvcnJlbGF0aW9ucyAlPiUNCiAgY29ycnBsb3QoLiwgb3JkZXIgPSAiaGNsdXN0IiwgdGwuY2V4ID0gLjM1KQ0KDQojIEZpbHRlciB2YXJpYWJsZXMgYmFzZWQgb24gdGhyZXNob2xkIG9mIDAuODogDQpsaWJyYXJ5KGNhcmV0KQ0KaGlnaENvcnIgPC0gZmluZENvcnJlbGF0aW9uKGNvcnJlbGF0aW9ucywgY3V0b2ZmID0gLjgpDQoNCiMgUmVtYWluaW5nIHByZWRpY3RvcnM6DQpyZW1haW5pbmdfZGYgPC0gZGZfcHJlZGljdG9ycyAlPiUgc2VsZWN0KC1oaWdoQ29ycikNCg0KIyBSZW1vdmUgbmVhci16ZXJvIHZhcmlhbmNlIHByZWRpY3RvcnM6IA0KcmVtYWluaW5nX2RmX2FmdGVyX3plcm8gPC0gcmVtYWluaW5nX2RmICU+JSBzZWxlY3QoLW5lYXJaZXJvVmFyKHJlbWFpbmluZ19kZikpDQoNCiMgQWRkIHRhcmdldCB2YXJpYWJsZTogDQpyZW1haW5pbmdfZGZfYWZ0ZXJfemVybyAlPD4lIG11dGF0ZShQdXJjaGFzZSA9IENhcmF2YW4kUHVyY2hhc2UpDQoNCmBgYA0KDQpSIENvZGVzIGZvciBjb25kdWN0aW5nIG92ZXItIGFuZCB1bmRlci1zYW1wbGluZyB0ZWNobmlxdWVzOiANCg0KYGBge3IsIGZpZy5mdWxsd2lkdGggPSBUUlVFLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9DQojIFNwbGl0IGRhdGE6IA0Kc2V0LnNlZWQoMSkNCmlkIDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24oeSA9IHJlbWFpbmluZ19kZl9hZnRlcl96ZXJvJFB1cmNoYXNlLCBwID0gMC41LCBsaXN0ID0gRkFMU0UpDQpkZl90cmFpbiA8LSByZW1haW5pbmdfZGZfYWZ0ZXJfemVyb1tpZCwgXSAjIEZvciB0cmFpbmluZw0KZGZfdGVzdCA8LSByZW1haW5pbmdfZGZfYWZ0ZXJfemVyb1staWQsIF0gIyBGb3IgdGVzdGluZw0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgQSBmdW5jdGlvbiBmb3IgY2FsY3VsYXRpbmcgQVVDIC8gUk9DIGJhc2VkIG9uIDEwIHNhbXBsZXMgd2l0aCBnaXZlbiByYXRlIA0KIyAgb2YgbWlub3JpdHkgY2xhc3MgYXMgZGVzY3JpYmVkIGJ5IG92ZXJzYW1wbGluZyB0ZWNobmlxdWUgDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KbGlicmFyeShST1NFKQ0KbGlicmFyeShwUk9DKQ0KDQojIFNldCBjb25kaXRpb25zIGZvciB0cmFpbmluZzogDQogIA0Kc2V0LnNlZWQoMTk5NTA5MTcpDQpjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAicmVwZWF0ZWRjdiIsDQogICAgICAgICAgICAgICAgICAgICBudW1iZXIgPSAzLA0KICAgICAgICAgICAgICAgICAgICAgcmVwZWF0cyA9IDEsDQogICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5RnVuY3Rpb24gPSBtdWx0aUNsYXNzU3VtbWFyeSwgDQogICAgICAgICAgICAgICAgICAgICBhbGxvd1BhcmFsbGVsID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgIGNsYXNzUHJvYnMgPSBUUlVFKQ0KICANCg0KbXlfYXVjX292ZXIgPC0gZnVuY3Rpb24obWlub3JpdHlfcmF0ZSkgew0KICANCiAgcCA8LSBtaW5vcml0eV9yYXRlDQogIGRmX2NvbSA8LSBkYXRhX2ZyYW1lKCkNCiAgZm9yIChqIGluIDE6MTApIHsNCiAgICANCiAgICAjIFVzZSBvdmVyc2FtcGxpbmcgZm9yIHRyYWluaW5nIGxvZ2lzdGljIG1vZGVsOiANCiAgICBzZXQuc2VlZChqKQ0KICAgIGRhdGFfYmFsYW5jZWRfb3ZlciA8LSBvdnVuLnNhbXBsZShQdXJjaGFzZSB+LiwgZGF0YSA9IGRmX3RyYWluLCBwID0gcCwgbWV0aG9kID0gIm92ZXIiKSRkYXRhDQogICAgDQogICAgIyBUcmFpbiBsb2dpc3RpYyBtb2RlbDogDQogICAgbXlfbG9naXN0aWMgPC0gdHJhaW4oUHVyY2hhc2Ugfi4sIG1ldGhvZCA9ICJnbG0iLCB0ckNvbnRyb2wgPSBjdHJsLCBkYXRhID0gZGF0YV9iYWxhbmNlZF9vdmVyKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHNvbWUgbW9kZWwgcGVyZm9ybWFuY2UgbWV0cmljczogDQogICAgDQogICAgdGVzdF9wcmVkIDwtIHByZWRpY3QobXlfbG9naXN0aWMsIGRmX3Rlc3QpDQogICAgY20gPC0gY29uZnVzaW9uTWF0cml4KGRmX3Rlc3QkUHVyY2hhc2UsIHRlc3RfcHJlZCkNCiAgICANCiAgICBiZ19nZyA8LSBjbSR0YWJsZSAlPiUgDQogICAgICBhcy52ZWN0b3IoKSAlPiUgDQogICAgICBtYXRyaXgobmNvbCA9IDQpICU+JSANCiAgICAgIGFzLmRhdGEuZnJhbWUoKQ0KICAgIA0KICAgIG5hbWVzKGJnX2dnKSA8LSBjKCJCQiIsICJHQiIsICJCRyIsICJHRyIpDQogICAga3EgPC0gYyhjbSRvdmVyYWxsLCBjbSRieUNsYXNzKSANCiAgICANCiAgICB0ZW4gPC0ga3EgJT4lIA0KICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgICAgIHJvdy5uYW1lcygpDQogICAgDQogICAga3EgJT4lIA0KICAgICAgYXMudmVjdG9yKCkgJT4lIA0KICAgICAgbWF0cml4KG5jb2wgPSAxOCkgJT4lIA0KICAgICAgYXMuZGF0YS5mcmFtZSgpIC0+IGFsbF9kZg0KICAgIA0KICAgIG5hbWVzKGFsbF9kZikgPC0gdGVuDQogICAgYWxsX2RmIDwtIGJpbmRfY29scyhhbGxfZGYsIGJnX2dnKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIEFVQzogDQogICAgcHJlZCA8LSBwcmVkaWN0KG15X2xvZ2lzdGljLCBkZl90ZXN0LCB0eXBlID0gInByb2IiKSAlPiUgcHVsbChZZXMpDQogICAgYXVjIDwtIHJvYyhkZl90ZXN0JFB1cmNoYXNlLCBwcmVkKSRhdWMNCg0KICAgICMgQWRkIEFVQzogDQogICAgYWxsX2RmICU8PiUgbXV0YXRlKEFVQyA9IGF1YyAlPiUgYXMudmVjdG9yKCksIE1pbm9yaXR5X1JhdGUgPSBwKQ0KICAgIGRmX2NvbSA8LSBiaW5kX3Jvd3MoZGZfY29tLCBhbGxfZGYpDQoNCiAgfQ0KICByZXR1cm4oZGZfY29tKQ0KDQp9DQoNCiMgTWlub3JyaXR5IHJhdGUgZnJvbSBvcmlnaW5hbCBkYXRhOiANCkNhcmF2YW4kUHVyY2hhc2UgJT4lIHRhYmxlKCkgLyBucm93KENhcmF2YW4pDQoNCiMgVXNlIHRoaXMgZnVuY3Rpb246IA0Kc3lzdGVtLnRpbWUob3B0aW1hbF9yYXRlIDwtIGxhcHBseShzZXEoMC4xLCAwLjUsIDAuMDUpLCBteV9hdWNfb3ZlcikpDQpvcHRpbWFsX3JhdGUgPC0gZG8uY2FsbCgiYmluZF9yb3dzIiwgb3B0aW1hbF9yYXRlKQ0KDQojIFNob3cgcmVzdWx0czogDQpvcHRpbWFsX3JhdGUgJT4lIA0KICBncm91cF9ieShNaW5vcml0eV9SYXRlKSAlPiUgDQogIHN1bW1hcmlzZShhdmdfYXVjID0gbWVhbihBVUMpKQ0KDQpvcHRpbWFsX3JhdGUgJT4lIA0KICBncm91cF9ieShNaW5vcml0eV9SYXRlKSAlPiUgDQogIHN1bW1hcmlzZShhdmdfYWNjID0gbWVhbihBY2N1cmFjeSkpDQoNCiMgTW9kZWwgUGVyZm9ybWFuY2UgYmFzZWQgb24gc29tZSBjcml0ZXJpYTogDQoNCnRoZW1lX3NldCh0aGVtZV9taW5pbWFsKCkpDQoNCm9wdGltYWxfcmF0ZSAlPiUgDQogIHNlbGVjdChBY2N1cmFjeSwgS2FwcGEsIFNlbnNpdGl2aXR5LCBTcGVjaWZpY2l0eSwgUHJlY2lzaW9uLCBSZWNhbGwsIEYxLCBQcmV2YWxlbmNlLCBBVUMsIE1pbm9yaXR5X1JhdGUpICU+JSANCiAgbXV0YXRlKE1pbm9yaXR5X1JhdGUgPSBmYWN0b3IoTWlub3JpdHlfUmF0ZSkpICU+JSANCiAgZ2F0aGVyKGEsIGIsIC1NaW5vcml0eV9SYXRlKSAlPiUgDQogIGdncGxvdChhZXMoTWlub3JpdHlfUmF0ZSwgYiwgZmlsbCA9IE1pbm9yaXR5X1JhdGUsIGNvbG9yID0gTWlub3JpdHlfUmF0ZSkpICsgDQogIGdlb21fYm94cGxvdChzaG93LmxlZ2VuZCA9IEZBTFNFLCBhbHBoYSA9IDAuMykgKyANCiAgZmFjZXRfd3JhcCh+IGEsIHNjYWxlcyA9ICJmcmVlIikgKyANCiAgY29vcmRfZmxpcCgpICsgDQogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDEsIDEsIDEsIDEpLCAiY20iKSkgKyANCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgDQogICAgICAgdGl0bGUgPSAiRmlndXJlIDE6IE1vZGVsIFBlcmZvcm1hbmNlIEJhc2VkIG9uIDkgQ3JpdGVyaWEgZm9yIEFsdGVybmF0aXZlIE1pbm9yaXR5IFJhdGVzIGJ5IFVwc2FtcGxpbmcgVGVjaG5pcXVlIiwgDQogICAgICAgc3VidGl0bGUgPSAiRGF0YSBVc2VkOiBDYXJhdmFuIikNCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgIEEgZnVuY3Rpb24gZm9yIGNhbGN1bGF0aW5nIEFVQyAvIFJPQyBiYXNlZCBvbiAzMCBzYW1wbGVzIHdpdGggZ2l2ZW4gcmF0ZSANCiMgIG9mIG1ham9yaXR5IGNsYXNzIGFzIGRlc2NyaWJlZCBieSB1bmRlcnNhbXBsaW5nIHRlY2huaXF1ZSANCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQpteV9hdWNfdW5kZXIgPC0gZnVuY3Rpb24obWFqb3JpdHlfcmF0ZSkgew0KICANCiAgcCA8LSBtYWpvcml0eV9yYXRlDQogIGRmX2NvbSA8LSBkYXRhX2ZyYW1lKCkNCiAgZm9yIChqIGluIDE6MTApIHsNCiAgICANCiAgICAjIFVzZSBvdmVyc2FtcGxpbmcgZm9yIHRyYWluaW5nIGxvZ2lzdGljIG1vZGVsOiANCiAgICBzZXQuc2VlZChqKQ0KICAgIGRhdGFfYmFsYW5jZWRfdW5kZXIgPC0gb3Z1bi5zYW1wbGUoUHVyY2hhc2Ugfi4sIGRhdGEgPSBkZl90cmFpbiwgcCA9IHAsIG1ldGhvZCA9ICJ1bmRlciIpJGRhdGENCiAgICANCiAgICAjIFRyYWluIGxvZ2lzdGljIG1vZGVsOiANCiAgICBteV9sb2dpc3RpYyA8LSB0cmFpbihQdXJjaGFzZSB+LiwgbWV0aG9kID0gImdsbSIsIHRyQ29udHJvbCA9IGN0cmwsIGRhdGEgPSBkYXRhX2JhbGFuY2VkX3VuZGVyKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHNvbWUgbW9kZWwgcGVyZm9ybWFuY2UgbWV0cmljczogDQogICAgDQogICAgdGVzdF9wcmVkIDwtIHByZWRpY3QobXlfbG9naXN0aWMsIGRmX3Rlc3QpDQogICAgY20gPC0gY29uZnVzaW9uTWF0cml4KGRmX3Rlc3QkUHVyY2hhc2UsIHRlc3RfcHJlZCkNCiAgICANCiAgICBiZ19nZyA8LSBjbSR0YWJsZSAlPiUgDQogICAgICBhcy52ZWN0b3IoKSAlPiUgDQogICAgICBtYXRyaXgobmNvbCA9IDQpICU+JSANCiAgICAgIGFzLmRhdGEuZnJhbWUoKQ0KICAgIA0KICAgIG5hbWVzKGJnX2dnKSA8LSBjKCJCQiIsICJHQiIsICJCRyIsICJHRyIpDQogICAga3EgPC0gYyhjbSRvdmVyYWxsLCBjbSRieUNsYXNzKSANCiAgICANCiAgICB0ZW4gPC0ga3EgJT4lIA0KICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgICAgIHJvdy5uYW1lcygpDQogICAgDQogICAga3EgJT4lIA0KICAgICAgYXMudmVjdG9yKCkgJT4lIA0KICAgICAgbWF0cml4KG5jb2wgPSAxOCkgJT4lIA0KICAgICAgYXMuZGF0YS5mcmFtZSgpIC0+IGFsbF9kZg0KICAgIA0KICAgIG5hbWVzKGFsbF9kZikgPC0gdGVuDQogICAgYWxsX2RmIDwtIGJpbmRfY29scyhhbGxfZGYsIGJnX2dnKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIEFVQzogDQogICAgcHJlZCA8LSBwcmVkaWN0KG15X2xvZ2lzdGljLCBkZl90ZXN0LCB0eXBlID0gInByb2IiKSAlPiUgcHVsbChZZXMpDQogICAgYXVjIDwtIHJvYyhkZl90ZXN0JFB1cmNoYXNlLCBwcmVkKSRhdWMNCg0KICAgICMgQWRkIEFVQzogDQogICAgYWxsX2RmICU8PiUgbXV0YXRlKEFVQyA9IGF1YyAlPiUgYXMudmVjdG9yKCksIE1ham9yaXR5X1JhdGUgPSBwKQ0KICAgIGRmX2NvbSA8LSBiaW5kX3Jvd3MoZGZfY29tLCBhbGxfZGYpDQoNCiAgfQ0KICANCiAgcmV0dXJuKGRmX2NvbSkNCg0KfQ0KDQoNCnN5c3RlbS50aW1lKG9wdGltYWxfcmF0ZV91bmRlciA8LSBsYXBwbHkoc2VxKDAuNSwgMC45LCAwLjA1KSwgbXlfYXVjX3VuZGVyKSkNCm9wdGltYWxfcmF0ZV91bmRlciA8LSBkby5jYWxsKCJiaW5kX3Jvd3MiLCBvcHRpbWFsX3JhdGVfdW5kZXIpDQoNCg0KIyBTaG93IHJlc3VsdHM6IA0Kb3B0aW1hbF9yYXRlX3VuZGVyICU+JSANCiAgZ3JvdXBfYnkoTWFqb3JpdHlfUmF0ZSkgJT4lIA0KICBzdW1tYXJpc2UoYXZnX2F1YyA9IG1lYW4oQVVDKSkNCg0Kb3B0aW1hbF9yYXRlX3VuZGVyICU+JSANCiAgZ3JvdXBfYnkoTWFqb3JpdHlfUmF0ZSkgJT4lIA0KICBzdW1tYXJpc2UoYXZnX2FjYyA9IG1lYW4oQWNjdXJhY3kpKQ0KDQpvcHRpbWFsX3JhdGVfdW5kZXIgJT4lIA0KICBzZWxlY3QoQWNjdXJhY3ksIEthcHBhLCBTZW5zaXRpdml0eSwgU3BlY2lmaWNpdHksIFByZWNpc2lvbiwgUmVjYWxsLCBGMSwgUHJldmFsZW5jZSwgQVVDLCBNYWpvcml0eV9SYXRlKSAlPiUgDQogIG11dGF0ZShNYWpvcml0eV9SYXRlID0gZmFjdG9yKE1ham9yaXR5X1JhdGUpKSAlPiUgDQogIGdhdGhlcihhLCBiLCAtTWFqb3JpdHlfUmF0ZSkgJT4lIA0KICBnZ3Bsb3QoYWVzKE1ham9yaXR5X1JhdGUsIGIsIGZpbGwgPSBNYWpvcml0eV9SYXRlLCBjb2xvciA9IE1ham9yaXR5X1JhdGUpKSArIA0KICBnZW9tX2JveHBsb3Qoc2hvdy5sZWdlbmQgPSBGQUxTRSwgYWxwaGEgPSAwLjMpICsgDQogIGZhY2V0X3dyYXAofiBhLCBzY2FsZXMgPSAiZnJlZSIpICsgDQogIGNvb3JkX2ZsaXAoKSArIA0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygxLCAxLCAxLCAxKSwgImNtIikpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyANCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIA0KICAgICAgIHRpdGxlID0gIkZpZ3VyZSAyOiBNb2RlbCBQZXJmb3JtYW5jZSBCYXNlZCBvbiA5IENyaXRlcmlhIGZvciBBbHRlcm5hdGl2ZSBNaW5vcml0eSBSYXRlcyBieSBEb3duc2FtcGxpbmcgVGVjaG5pcXVlIiwgDQogICAgICAgc3VidGl0bGUgPSAiRGF0YSBVc2VkOiBDYXJhdmFuIikNCg0KDQpgYGANCg0KIyMjIFNvbWUgS2V5IENvbmNsdXNpb25zDQoNCkZyb20gZW1waXJpY2FsIGV2aWRlbmNlcyBiYXNlZCBvbiBDYXJhdmFuIGRhdGEgc2V0LCB3ZSBjYW4gY29uY2x1ZGUgdGhhdDogDQoNCjEuIE92ZXJzYW1wbGluZyB0ZWNobmlxdWUgaGFzIGEgbmVnbGlnaWJsZSBpbXBhY3Qgb24gQVVDIGFuZCBBY2N1cmFjeS4gDQoNCjIuIFVuZGVyc2FtcGxpbmcgdGVjaG5pcXVlIGhhcyBhbiBhZHZlcnNlIGltcGFjdCBvbiBBVUMgYW5kIEFjY3VyYWN5Lg0KDQpUaGUgc2FtZSBjb25jbHVzaW9ucyBhcmUgZm91bmQgZnJvbSBhIHBvc3QgYnkgTmluYSBadW1lbCBhbmQgSm9obiBNb3VudDogDQpodHRwOi8vd3d3Lndpbi12ZWN0b3IuY29tL2Jsb2cvMjAxNS8wMi9kb2VzLWJhbGFuY2luZy1jbGFzc2VzLWltcHJvdmUtY2xhc3NpZmllci1wZXJmb3JtYW5jZS8uICANCg0KDQojIyMgUmVmZXJlbmNlcw0KDQoxLiBCYXNlbCBDb21taXR0ZWUgb24gQmFua2luZyBTdXBlcnZpc2lvbi4gMjAwNS4gIOKAnFZhbGlkYXRpb24gb2YgTG93LURlZmF1bHQgUG9ydGZvbGlvcyBpbiB0aGUgQmFzZWwgSUkgRnJhbWV3b3JrLuKAnSAgQmFzZWwgQ29tbWl0dGVlIE5ld3NsZXR0ZXIgbm8uIDYsICBTZXB0ZW1iZXIuDQoNCjIuIEFydGlzIE0sIEF5dXNvIE0sIEd1aWxsZW4gTSAoMjAwMikuIOKAnERldGVjdGlvbiBvZiBBdXRvbW9iaWxlIEluc3VyYW5jZSBGcmF1ZCB3aXRoIERpc2NyZXRlIENob2ljZSBNb2RlbHMgYW5kIE1pc2NsYXNzaWZpZWQgQ2xhaW1zLuKAnSBUaGUgSm91cm5hbCBvZiBSaXNrIGFuZCBJbnN1cmFuY2UsIDY5KDMpLCAzMjXigJMzNDAuDQoNCjMuIFJpY2hhcmRzb24gTSwgRG9taW5vd3NrYSBFLCBSYWdubyBSICgyMDA3KS4g4oCcUHJlZGljdGluZyBDbGlja3M6IEVzdGltYXRpbmcgdGhlIENsaWNr4oCTVGhyb3VnaCBSYXRlIGZvciBOZXcgQWRzLuKAnSBJbiDigJxQcm9jZWVkaW5ncyBvZiB0aGUgMTYgdGggSW50ZXJuYXRpb25hbCBDb25mZXJlbmNlIG9uIHRoZSBXb3JsZCBXaWRlIFdlYizigJ0gcHAuIDUyMeKAkzUzMC4NCg0KNC4gVmlzYSwgUy4sICYgUmFsZXNjdSwgQS4gKDIwMDUsIEFwcmlsKS4gSXNzdWVzIGluIG1pbmluZyBpbWJhbGFuY2VkIGRhdGEgc2V0cyAtIGEgcmV2aWV3IHBhcGVyLiBJbiBQcm9jZWVkaW5ncyBvZiB0aGUgc2l4dGVlbiBtaWR3ZXN0IGFydGlmaWNpYWwgaW50ZWxsaWdlbmNlIGFuZCBjb2duaXRpdmUgc2NpZW5jZSBjb25mZXJlbmNlIChWb2wuIDIwMDUsIHBwLiA2Ny03MykuDQoNCjUuIEtvdHNpYW50aXMsIFMuLCBLYW5lbGxvcG91bG9zLCBELiwgJiBQaW50ZWxhcywgUC4gKDIwMDYpLiBIYW5kbGluZyBpbWJhbGFuY2VkIGRhdGFzZXRzOiBBIHJldmlldy4gR0VTVFMgSW50ZXJuYXRpb25hbCBUcmFuc2FjdGlvbnMgb24gQ29tcHV0ZXIgU2NpZW5jZSBhbmQgRW5naW5lZXJpbmcsIDMwKDEpLCAyNS0zNi4NCg0KNi4gTWFsb29mLCBNLiBBLiAoMjAwMywgQXVndXN0KS4gTGVhcm5pbmcgd2hlbiBkYXRhIHNldHMgYXJlIGltYmFsYW5jZWQgYW5kIHdoZW4gY29zdHMgYXJlIHVuZXF1YWwgYW5kIHVua25vd24uIEluIElDTUwtMjAwMyB3b3Jrc2hvcCBvbiBsZWFybmluZyBmcm9tIGltYmFsYW5jZWQgZGF0YSBzZXRzIElJIChWb2wuIDIsIHBwLiAyLTEpLg0KDQo3LiBKYXBrb3dpY3osIE4uICgyMDAzLCBBdWd1c3QpLiBDbGFzcyBpbWJhbGFuY2VzOiBhcmUgd2UgZm9jdXNpbmcgb24gdGhlIHJpZ2h0IGlzc3VlLiBJbiBXb3Jrc2hvcCBvbiBMZWFybmluZyBmcm9tIEltYmFsYW5jZWQgRGF0YSBTZXRzIElJIChWb2wuIDE3MjMsIHAuIDYzKS4NCg0KOC4gQ2hhd2xhLCBOLiBWLiwgQm93eWVyLCBLLiBXLiwgSGFsbCwgTC4gTy4sICYgS2VnZWxtZXllciwgVy4gUC4gKDIwMDIpLiBTTU9URTogc3ludGhldGljIG1pbm9yaXR5IG92ZXItc2FtcGxpbmcgdGVjaG5pcXVlLiBKb3VybmFsIG9mIGFydGlmaWNpYWwgaW50ZWxsaWdlbmNlIHJlc2VhcmNoLCAxNiwgMzIxLTM1Ny4gDQoNCjkuIE15ZXJzIFIgKDE5OTQpLiBDbGFzc2ljYWwgYW5kIE1vZGVybiBSZWdyZXNzaW9uIHdpdGggQXBwbGljYXRpb25zLiBQV1MtS0VOVCBQdWJsaXNoaW5nIENvbXBhbnksIEJvc3RvbiwgTUEsIHNlY29uZCBlZGl0aW9uLg0KDQoNCg0K