R Packages for
Imputation
Several R packages have functions to perform imputation for missing
values. This section lists a few commonly used R libraries. We only
explain the concepts with no coding.
MICE Package
MICE (Multivariate Imputation via Chained Equations) is one of the
commonly used packages by R users. Creating multiple imputations as
compared to a single imputation (such as the mean) takes care of
uncertainty in missing values.
MICE assumes that the missing data are Missing at Random (MAR), which
means that the probability that a value is missing depends only on the
observed value and can be predicted using them. It imputes data on a
variable-by-variable basis by specifying an imputation model per
variable.
As an example, we consider a data set with variables \(X_1, X_2, \cdots, X_k\). If \(X_1\) has missing values, then it will be
regressed on other variables \(X_2\) to
\(X_k\). The missing values in \(X_1\) will be then replaced by predictive
values obtained. Similarly, if \(X_2\)
has missing values, then \(X_1\), \(X_3\) to \(X_k\) variables will be used in the
prediction model as independent variables. Later, missing values will be
replaced with predicted values.
By default, linear regression is used to predict continuous missing
values. Logistic regression is used for categorical missing values. Once
this cycle is complete, multiple data sets are generated. These data
sets differ only in imputed missing values. Generally, it’s considered
to be a good practice to build models on these data sets separately and
combine their results.
Precisely, the methods used by this package can be found in the
document of the package at https://cran.r-project.org/web/packages/mice/mice.pdf.
Hmisc Package
Hmisc is a multiple-purpose package useful for data analysis,
high–level graphics, imputing missing values, advanced table making,
model fitting & diagnostics (linear regression, logistic regression
& cox regression), etc. Amidst, the wide range of functions
contained in this package, it offers 2 powerful functions for imputing
missing values. These are impute() and aregImpute(). Though it also has
transcan() function, aregImpute() is better to use.
impute() function simply imputes missing values using a user-defined
statistical method (mean, max, mean). Its default is median. On the
other hand, aregImpute() allows the mean imputation using additive
regression, bootstrapping, and predictive mean matching.
In bootstrapping, different bootstrap resamples are used for each of
the multiple imputations. Then, a flexible additive model
(non-parametric regression method) is fitted on samples taken with
replacements from original data, and missing values (acts as dependent
variable) are predicted using non-missing values (independent
variable).
Then, it uses predictive mean matching (default) to impute missing
values. Predictive mean matching works well for continuous and
categorical (binary & multi-level) without the need for computing
residuals and maximum likelihood fit.
More functions and updates in Hmisc package can be found at https://cran.r-project.org/web/packages/Hmisc/Hmisc.pdf
The MICE Algorithm
The MICE process follows a systematic approach to iteratively impute
missing data. It involves creating multiple versions of the data set
with plausible estimates for missing values while preserving the
relationships among variables.
In the R library mice()
, argument maxit = m
indicates the number of cycles (iterations) of the iterative imputing
process. To illustrate this iterative imputation process, we use the
following toy data to show the logical process.
include_graphics("img/MI-Iterative-Imputed-Process.jpg")
Below is an algorithm that summarizes the above MICE process.
MICE Algorithm
Step 1: Initialize imputed values
1.1. For each variable with missing values, impute initial values using
a simple imputation method (e.g., mean, median, mode imputation,
or regression).
1.2. These initial imputations will be used as starting values in the
iterative process.
Step 2: Set up the imputation model for each variable
2.1. Define the imputation model for each variable with missing data.
The model can be different for each variable and can be based on a
regression model (e.g., linear regression, logistic regression) or
other models depending on the nature of the data.
2.2. The variable to be imputed (dependent variable) will be regressed
on other variables in the dataset (predictor variables).
Step 3: Iterative imputation process
3.1. For each iteration t, repeat the following process for each variable
with missing values:
3.1.1. For each variable Vi with missing data, use the current values
of the other variables (including previously imputed values)
to predict the missing values for Vi.
3.1.2. The model for imputation of Vi is fitted to the complete data
(where no missing values exist for Vi).
3.1.3. Impute missing values for Vi based on the model fit in step
3.1.2, replacing the missing values with predicted values
(this imputation is stochastic, introducing random variability
to account for uncertainty).
3.2. Repeat this process for all variables with missing data.
Step 4: Perform multiple imputations
4.1. Repeat Step 3 m times (with m being the number of imputations) to
create m different imputed datasets. Each dataset will contain
imputed values for the missing data based on different imputations,
reflecting the uncertainty in the imputation process.
Step 5: Analyze each imputed dataset
5.1. Perform the desired analysis (e.g., regression, hypothesis testing)
on each of the m imputed datasets, yielding m sets of results.
Step 6: Pool the results using Rubin's Rules
6.1. Combine the results from the m datasets using Rubin’s rules:
6.1.1. Combine the parameter estimates (e.g., regression coefficients)
by averaging them across the m datasets.
6.1.2. Combine the variance estimates, accounting for both the
within-imputed dataset variance and the between-imputed
dataset variance.
6.1.3. Calculate the overall standard errors, confidence intervals,
and p-values based on the combined estimates.
Step 7: Report on the combined results
7.1. Present the final, pooled results, including the combined estimates,
standard errors, and confidence intervals.
The R mice library
has several functions listed below to
extract relevant information in the above algorithm.
mice()
Impute the missing data m times
with()
Analyze completed data sets.
pool()
Combine parameter estimates.
complete()
Export imputed data.
ampute()
Generate missing data.
Numerical
Example
For ease of illustration, we use the built-in airquality
data in the subsequent examples. The first few records in the data are
given below.
library(mice)
data <- airquality # Example dataset with missing values
data[1:10,]
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 NA NA 14.3 56 5 5
6 28 NA 14.9 66 5 6
7 23 299 8.6 65 5 7
8 19 99 13.8 59 5 8
9 8 19 20.1 61 5 9
10 NA 194 8.6 69 5 10
1. Initialization
The process begins by assigning initial values to all missing entries
in the data set. These initial values are often derived using simple
imputation techniques, such as:
This step provides a starting point for the iterative process.
init <- mice(data, maxit = 0) # Check initial imputation setup
init$method # View default imputation methods
Ozone Solar.R Wind Temp Month Day
"pmm" "pmm" "" "" "" ""
2. Imputation Models
Each variable with missing data is assigned a specific imputation
model tailored to its data type. Some commonly used models are listed
below.
- Predictive Mean Matching (pmm): For continuous
variables.
- Logistic Regression (logreg): For binary
variables.
- Polytomous Regression (polyreg): For categorical
variables.
- Proportional Odds Model (polr): For ordinal
variables.
These models predict missing values based on other observed variables
in the data set. As an example, we impute only one data (under the
iterative imputing process illustrated earlier).
library(mice)
dat <- airquality # Example data set with missing values
## individual variable
imp <- mice(dat, method = c("pmm","pmm", "pmm", "pmm", "", ""),
maxit = 10, # iterating 10 cycles to complete each imputed data set
m = 1, # generate 1 imputed data set
print=F) # suppress printouts
## we use complete() tp view the complete data set.
complete(imp, action = 1L)[1:10,] # The default *action = 1L* returns the first
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 19 150 14.3 56 5 5
6 28 254 14.9 66 5 6
7 23 299 8.6 65 5 7
8 19 99 13.8 59 5 8
9 8 19 20.1 61 5 9
10 30 194 8.6 69 5 10
# imputed (complete) data set.
3. Iterative Imputation
The core of the MICE process is its iterative nature:
Each variable with missing data is treated as a dependent
variable, while all other variables act as predictors.
Missing values for the target variable are imputed using the
assigned model.
This process cycles through all variables with missing data,
iteratively refining the imputations.
The iterations continue until the imputed values stabilize,
indicating convergence.
data <- airquality # Example data set with missing values
imp <- mice(data, method = "pmm", # using predictive mean matching (ppm)
maxit = 10, # pre-specified cycles in the iterative process
m = 2, # generate 2 imputed data sets
seed = 123, # setting seed to keep reproducibility of the process
print=F) # suppress printouts
complete(imp, action = "broad")[1:10,] # *action = "broad"* combines the two imputed
Ozone.1 Solar.R.1 Wind.1 Temp.1 Month.1 Day.1 Ozone.2 Solar.R.2 Wind.2
1 41 190 7.4 67 5 1 41 190 7.4
2 36 118 8.0 72 5 2 36 118 8.0
3 12 149 12.6 74 5 3 12 149 12.6
4 18 313 11.5 62 5 4 18 313 11.5
5 6 273 14.3 56 5 5 8 47 14.3
6 28 186 14.9 66 5 6 28 192 14.9
7 23 299 8.6 65 5 7 23 299 8.6
8 19 99 13.8 59 5 8 19 99 13.8
9 8 19 20.1 61 5 9 8 19 20.1
10 16 194 8.6 69 5 10 24 194 8.6
Temp.2 Month.2 Day.2
1 67 5 1
2 72 5 2
3 74 5 3
4 62 5 4
5 56 5 5
6 66 5 6
7 65 5 7
8 59 5 8
9 61 5 9
10 69 5 10
# data sets in a wide table. There are other
# options to lay out the imputed data sets.
3. Multiple Imputations
Multiple imputed data sets are created to capture the variability
introduced by missing data.
imp5 <- mice(data, method = "pmm", m = 5, maxit = 10, seed = 123, print=F)
plot(imp5)
Here, m = 5 specifies the number of imputations, and maxit = 10
defines the number of iterations.
4. Analysis and Pooling
Each imputed data set is analyzed independently, and the results are
combined using Rubin’s Rules to produce final estimates and standard
errors.
model5 <- with(imp5, lm(Ozone ~ Wind + Temp)) # The statistical model to assess
# the relationship between *Ozone*
# and *Wind* and *Temp*.
summary.stats = summary(model5) # display the regression results of
# individual imputed data set.
summary.stats
# A tibble: 15 × 6
term estimate std.error statistic p.value nobs
<chr> <dbl> <dbl> <dbl> <dbl> <int>
1 (Intercept) -63.4 19.3 -3.28 1.29e- 3 153
2 Wind -3.19 0.554 -5.75 4.74e- 8 153
3 Temp 1.77 0.206 8.57 1.17e-14 153
4 (Intercept) -53.3 20.5 -2.60 1.03e- 2 153
5 Wind -3.32 0.588 -5.64 8.15e- 8 153
6 Temp 1.64 0.219 7.51 5.00e-12 153
7 (Intercept) -75.4 19.4 -3.89 1.48e- 4 153
8 Wind -2.67 0.556 -4.81 3.69e- 6 153
9 Temp 1.84 0.207 8.90 1.72e-15 153
10 (Intercept) -84.4 19.8 -4.27 3.46e- 5 153
11 Wind -2.38 0.567 -4.19 4.75e- 5 153
12 Temp 1.94 0.211 9.19 3.12e-16 153
13 (Intercept) -66.5 19.8 -3.35 1.01e- 3 153
14 Wind -2.82 0.569 -4.95 1.98e- 6 153
15 Temp 1.75 0.212 8.24 7.86e-14 153
To combine the results, we simply take the average of the
corresponding estimated regression coefficients.
summary(pool(model5))
term estimate std.error statistic df p.value
1 (Intercept) -68.572693 23.6337059 -2.901479 30.90197 6.788592e-03
2 Wind -2.874688 0.7062186 -4.070535 23.79733 4.468363e-04
3 Temp 1.787463 0.2431392 7.351602 41.42155 4.972123e-09
The above-pooled results are calculated based on the formulas on
\(Q, U, B\), and \(T\). The following code illustrates the
calculation of the pooled standard error of the intercept.
beta = summary.stats$estimate[seq(1,15,by=3)] # explicit vector: c(1,4,7,10,13)
beta.var = (summary.stats$std.error[seq(1,15,by=3)])^2
Q = mean(beta)
U = mean(beta.var)
B = var(beta)
T = U + (6/5)*B
pool.se = sqrt(T)
cbind(pool.se.intercept = pool.se)
pool.se.intercept
[1,] 23.63371
Advantages of
MICE
MICE offers several benefits:
- Flexibility: It handles mixed data types
(continuous, binary, categorical).
- Preservation of Relationships: Imputation respects
the relationships between variables.
- Uncertainty Representation: Multiple imputations
account for variability in missing data.
In R, the mice package simplifies MICE implementation, allowing users
to customize imputation methods for each variable. The main function
mice()
can detect the missingness of individual variables.
If a variable has no missing values, the imputing model will be
automatically set to ""
.
imp6 <- mice(data, method = c("pmm", "pmm", "pmm", "pmm", "", ""),
maxit = 5,
print=F,
seed = 123)
imp6$method
Ozone Solar.R Wind Temp Month Day
"pmm" "pmm" "" "" "" ""
## without mno specified imputing model
init <- mice(data,
maxit = 5,
print=F,
seed = 123)
init$method
Ozone Solar.R Wind Temp Month Day
"pmm" "pmm" "" "" "" ""
In this example, predictive mean matching (pmm
) is used
for continuous variables. If there is a binary categorical variable with
missing values, logistic regression (logreg
) will be used
as the imputed model.
Challenges of
MICE
Despite its advantages, MICE comes with challenges:
- Computational Intensity: Large datasets and high
missingness can increase computation time.
- Model Specification: Poorly chosen imputation
models may lead to inaccurate results.
- Dependence on Data Quality: Errors in observed data
can propagate through imputations.
In R, proper pre-processing, including outlier handling and
transformation, can mitigate some challenges.
Practical
Applications of MICE
MICE is widely used in various fields, including healthcare, social
sciences, and survey research. For instance:
In clinical trials, MICE imputes missing patient data to preserve the
study’s integrity.
In surveys, it handles incomplete responses while maintaining
representativeness.
# Imputation for a survey dataset
survey_data <- data.frame(
Age = c(25, 30, NA, 35, 40),
Gender = c("Male", "Female", "Male", NA, "Female"),
Income = c(50000, NA, 60000, 65000, 70000)
)
imp <- mice(survey_data, method = c("pmm", "logreg", "pmm"), maxit = 5,
print=F, seed = 123)
Warning: Number of logged events: 1
complete_data <- complete(imp)
print(complete_data)
Age Gender Income
1 25 Male 50000
2 30 Female 70000
3 25 Male 60000
4 35 <NA> 65000
5 40 Female 70000
Here, polyreg is used for categorical variables, showcasing MICE’s
versatility.
Conclusion
MICE is a powerful and flexible tool for handling missing data,
ensuring robust and unbiased statistical analyses. Its iterative
process, reliance on tailored imputation models, and ability to account
for uncertainty make it a cornerstone of modern data science. With tools
like the mice package in R, implementing MICE has become more
accessible, enabling analysts to address missing data challenges
effectively. While it requires careful implementation, the benefits of
using MICE far outweigh its challenges, making it an essential technique
for high-quality data analysis.
LS0tDQp0aXRsZTogIkhhbmRsaW5nIE1pc3NpbmcgRGF0YSBpbiBTdXJ2ZXkiDQphdXRob3I6ICJDaGVuZyBQZW5nIg0KZGF0ZTogIiAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCiAgcGRmX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAga2VlcF90ZXg6IGZhbHNlDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiA1DQogICAgZmlnX2hlaWdodDogNA0KLS0tDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpkaXYjVE9DIGxpIHsNCiAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjBweDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgxIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIycHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDIgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNXB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCjwvc3R5bGU+DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoIndlYnNob3QiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygid2Vic2hvdCIpDQogICBsaWJyYXJ5KHdlYnNob3QpDQp9DQppZiAoIXJlcXVpcmUoInBzeWNoIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCiAgIGxpYnJhcnkocHN5Y2gpDQp9DQppZiAoIXJlcXVpcmUoImNvY3JvbiIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJjb2Nyb24iKQ0KICAgbGlicmFyeShjb2Nyb24pDQp9DQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQoNCg0KIyBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICJDOi9Vc2Vycy83NUNQRU5HL09uZURyaXZlIC0gV2VzdCBDaGVzdGVyIFVuaXZlcnNpdHkgb2YgUEEvRG9jdW1lbnRzIikNCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiQzpcXFNUQTQ5MFxcdzA1IikNCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5ncyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduPSdjZW50ZXInLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWcucG9zID0gJ2h0JykNCmBgYA0KDQoNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KTWlzc2luZyBkYXRhIGFyZSBxdWVzdGlvbnMgd2l0aG91dCBhbnN3ZXJzIG9yIHZhcmlhYmxlcyB3aXRob3V0IG9ic2VydmF0aW9ucy4gVGhleSBhcmUgYSBjb21tb24gYW5kIHNpZ25pZmljYW50IGNoYWxsZW5nZSBpbiB0aGUgc3VydmV5LiBUaGV5IG9mdGVuIGluZmx1ZW5jZSB0aGUgc2VsZWN0aW9uIG9mIGEgc3RhdGlzdGljYWwgbWV0aG9kIG9mIGFuYWx5c2lzLCBhbmQsIGRlcGVuZGluZyBvbiB0aGVpciBzZXZlcml0eSwgY2FuIHVuZGVybWluZSB0aGUgY29uZmlkZW5jZSBvZiBhbmFseXNpcywgb3IgZXZlbiByZXN1bHQgaW4gd3JvbmcgY29uY2x1c2lvbnMuDQoNCiMgU291cmNlcyBvZiBNaXNzaW5nIERhdGENCg0KTWlzc2luZyBkYXRhIG9jY3VyIGluIHN1cnZleSByZXNlYXJjaCBkdWUgdG8gdmFyaW91cyByZWFzb25zLg0KDQoqICoqVG90YWwgTm9uLXJlc3BvbnNlKio6IGEgc2FtcGxlZCBzdWJqZWN0IGRvZXMgbm90IHBhcnRpY2lwYXRlIGluIHRoZSBzdXJ2ZXkuIFRvdGFsIG5vbi1yZXNwb25zZSByZXN1bHRzIGZyb20gcmVmdXNhbHMgdG8gcGFydGljaXBhdGUgaW4gdGhlIHN1cnZleSwgbm9uLWNvbnRhY3RzIChub3QtYXQtaG9tZXMpLCBhbmQgb3RoZXIgcmVhc29ucyBzdWNoIGFzIGEgbGFuZ3VhZ2UgYmFycmllciwgZGVhZm5lc3MsIG9yIGJlaW5nIHRvbyBpbGwgdG8gcGFydGljaXBhdGUuIA0KDQoqICoqTm9uLWNvdmVyYWdlKio6IGEgc3ViamVjdCBpbiB0aGUgdGFyZ2V0IHBvcHVsYXRpb24gaXMgbm90IGluY2x1ZGVkIGluIHRoZSBzdXJ2ZXnigJlzIHNhbXBsaW5nIGZyYW1lLiBJdCBvY2N1cnMgd2hlbiBzb21lIHN1YmplY3RzIGluIHRoZSBwb3B1bGF0aW9uIG9mIGluZmVyZW5jZSBmb3IgdGhlIHN1cnZleSBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSBzdXJ2ZXnigJlzIHNhbXBsaW5nIGZyYW1lLiBUaGVzZSBtaXNzaW5nIHN1YmplY3RzIGhhdmUgbm8gY2hhbmNlIG9mIHNlbGVjdGlvbiBmb3IgdGhlIHNhbXBsZSBhbmQgaGVuY2UgZ28gdW5yZXByZXNlbnRlZC4gDQoNCiogKipJdGVtIE5vbi1yZXNwb25zZSoqOiBhIHJlc3BvbmRpbmcgc2FtcGxlZCBzdWJqZWN0IGZhaWxzIHRvIHByb3ZpZGUgYWNjZXB0YWJsZSByZXNwb25zZXMgdG8gb25lIG9yIG1vcmUgb2YgdGhlIHN1cnZleSBpdGVtcy4gIEl0ZW0gbm9uLXJlc3BvbnNlIG1heSBhcmlzZSBiZWNhdXNlIA0KICAtIGEgcmVzcG9uZGVudCByZWZ1c2VzIHRvIGFuc3dlciBhbiBpdGVtIGJlY2F1c2UgaXQgaXMgdG9vIHNlbnNpdGl2ZSwgZG9lcyBub3Qga25vdyB0aGUgYW5zd2VyIHRvIHRoZSBpdGVtLCBnaXZlcyBhbiBhbnN3ZXIgdGhhdCBpcyBpbmNvbnNpc3RlbnQgd2l0aCBhbnN3ZXJzIHRvIG90aGVyIGl0ZW1zIGFuZCBoZW5jZSBpcyBkZWxldGVkIGluIGVkaXRpbmc7DQogIC0gdGhlIGludGVydmlld2VyIGZhaWxzIHRvIGFzayB0aGUgcXVlc3Rpb24gb3IgcmVjb3JkIHRoZSBhbnN3ZXIuIA0KDQoqICoqUGFydGlhbCBOb24tcmVzcG9uc2UqKjogUGFydGlhbCBub24tcmVzcG9uc2UgZmFsbHMgYmV0d2VlbiB0b3RhbCBhbmQgaXRlbSBub24tcmVzcG9uc2UuIFdoZXJlYXMgdG90YWwgbm9uLXJlc3BvbnNlIHJlbGF0ZXMgdG8gYSBmYWlsdXJlIHRvIG9idGFpbiBhbnkgcmVzcG9uc2VzIGZyb20gYSBzYW1wbGVkIHN1YmplY3QgYW5kIGl0ZW0gbm9uLXJlc3BvbnNlIHVzdWFsbHkgaW1wbGllcyB0aGUgZmFpbHVyZSB0byBvYnRhaW4gcmVzcG9uc2VzIGZvciBvbmx5IGEgc21hbGwgbnVtYmVyIG9mIHN1cnZleSBpdGVtcy4gUGFydGlhbCBub24tcmVzcG9uc2UgaW52b2x2ZXMgYSBzdWJzdGFudGlhbCBudW1iZXIgb2YgaXRlbSBub24tcmVzcG9uc2VzLiBJdCBjYW4gb2NjdXIsIGZvciBpbnN0YW5jZSwNCiAgLSB3aGVuIGEgcmVzcG9uZGVudCBjdXRzIG9mZiB0aGUgaW50ZXJ2aWV3IGluIHRoZSBtaWRkbGUsIA0KICAtIHdoZW4gYSByZXNwb25kZW50IGluIGEgcGFuZWwgc3VydmV5IGZhaWxzIHRvIHByb3ZpZGUgZGF0YSBmb3Igb25lIG9yIG1vcmUgb2YgdGhlIHdhdmVzIG9mIHRoZSBwYW5lbCwgb3IgDQogIC0gd2hlbiBhIHJlc3BvbmRlbnQgaW4gYSBtdWx0aS1waGFzZSBzdXJ2ZXkgcHJvdmlkZXMgZGF0YSBmb3Igc29tZSBidXQgbm90IGFsbCBwaGFzZXMgb2YgZGF0YSBjb2xsZWN0aW9uLiANCg0KDQojIFBhdHRlcm5zIGFuZCBNZWNoYW5pc21zIG9mIE1pc3NpbmcgRGF0YQ0KDQpCZWZvcmUgY2hvb3NpbmcgYXBwcm9wcmlhdGUgbWV0aG9kcyB0byBoYW5kbGUgbWlzc2luZyBkYXRhLCB3ZSBuZWVkIHRvIGtub3cgdGhlIHBhdHRlcm5zIGFuZCBtZWNoYW5pc21zIG9mIG1pc3NpbmcgZGF0YS4NCg0KIyMgTWlzc2luZyBEYXRhIFBhdHRlcm5zDQoNCk1pc3NpbmcgZGF0YSBjYW4gYmUgZ3JvdXBlZCBhY2NvcmRpbmcgdG8gdGhlIG1pc3NpbmcgZGF0YSBwYXR0ZXJuLCB3aGljaCBkZXNjcmliZXMgd2hpY2ggdmFsdWVzIGFyZSBvYnNlcnZlZCBhbmQgd2hpY2ggdmFsdWVzIGFyZSBtaXNzaW5nIGluIHRoZSBkYXRhIG1hdHJpeC4gSW4gZ2VuZXJhbCwgbWlzc2luZyBkYXRhIHBhdHRlcm5zIGNhbiBiZSByb3VnaGx5IGNsYXNzaWZpZWQgaW50byBhIHZhcmlldHkgb2YgZ3JvdXBzLCBzdWNoIGFzIHVuaXZhcmlhdGUsIG11bHRpdmFyaWF0ZSwgbW9ub3RvbmUsIG5vbi1tb25vdG9uZSwgYW5kIGZpbGUgbWF0Y2hpbmcgKExpdHRsZSBhbmQgUnViaW4sIDIwMDIpLg0KDQpBIHVuaXZhcmlhdGUgbWlzc2luZyBwYXR0ZXJuIGluZGljYXRlcyBhIHNpdHVhdGlvbiB3aGVyZSBtaXNzaW5nIGRhdGEgb2NjdXIgb25seSBpbiBhIHNpbmdsZSB2YXJpYWJsZS4gQXMgYW4gZXh0ZW5zaW9uIG9mIHRoZSB1bml2YXJpYXRlIGNhc2UsIHRoZSBtdWx0aXZhcmlhdGUgbWlzc2luZyBwYXR0ZXJuIHJlZmVycyB0byBtaXNzaW5nIGRhdGEgaW4gYSBzZXQgb2YgdmFyaWFibGVzLCBlaXRoZXIgZm9yIHRoZSBlbnRpcmUgdW5pdCBvciBmb3IgcGFydGljdWxhciBpdGVtcyBpbiBhIHF1ZXN0aW9ubmFpcmUuIA0KDQoqIElmIGEgdmFyaWFibGUgaXMgbWlzc2luZyBmb3IgYSBwYXJ0aWN1bGFyIHN1YmplY3Qgbm90IG9ubHkgYXQgYSBzcGVjaWZpYyB0aW1lIHBvaW50IGJ1dCBhbHNvIGF0IGFsbCBzdWJzZXF1ZW50IHRpbWUgb2NjYXNpb25zLCB0aGUgbWlzc2luZyBkYXRhIHBhdHRlcm4gZm9yIHRoaXMgaW5kaXZpZHVhbCBpcyBzYWlkIHRvIGJlIGEgbW9ub3RvbmUgbWlzc2luZyBwYXR0ZXJuLiANCg0KKiBJZiBhIGNhc2UgaXMgbWlzc2luZyBhdCBhIGdpdmVuIHRpbWUgcG9pbnQgYW5kIHRoZW4gcmV0dXJucyBhdCBhIGxhdGVyIGZvbGxvdy11cCBpbnZlc3RpZ2F0aW9uLCB0aGVuIHRoZSBtaXNzaW5nIGRhdGEgcGF0dGVybiBmb3IgdGhpcyBzdWJqZWN0IGlzIHJlZmVycmVkIHRvIGFzIHRoZSBub24tbW9ub3RvbmUgbWlzc2luZyBkYXRhLiANCg0KSW4gbG9uZ2l0dWRpbmFsIGRhdGEgYW5hbHlzaXMsIHRoZSBub24tbW9ub3RvbmUgbWlzc2luZyBwYXR0ZXJuIGNhbiBjYXVzZSBtb3JlIHByb2JsZW1zIHRoYW4gdGhlIG1vbm90b25lIHBhdHRlcm4gYW5kIHRodXMgZGVzZXJ2ZXMgY2xvc2UgYXR0ZW50aW9uLiBUaGVyZSBhcmUgbW9yZSBtaXNzaW5nIGRhdGEgcGF0dGVybnMgc3VjaCBhcyB0aGUgbGF0ZW50LWZhY3RvciBwYXR0ZXJucyB3aXRoIHZhcmlhYmxlcyB0aGF0IGFyZSBuZXZlciBvYnNlcnZlZC4gRm9yIGVhY2ggbWlzc2luZyBkYXRhIHBhdHRlcm4sIHRoZXJlIGFyZSBjb3JyZXNwb25kaW5nIHN0YXRpc3RpY2FsIHRlY2huaXF1ZXMgdG8gaGFuZGxlIGl0cyBpbXBhY3Qgb24gdGhlIHF1YWxpdHkgb2YgZGF0YSBhbmFseXNpcy4NCg0KIyMgVHlwZXMgb2YgTWlzc2luZyBEYXRhIE1lY2hhbmlzbXMNCg0KTWlzc2luZyBkYXRhIG1lY2hhbmlzbXMgY29uY2VybiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbWlzc2luZyBkYXRhIGFuZCB0aGUgdmFsdWVzIG9mIHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBtYXRyaXguIEdpdmVuIHRoaXMgZm9jdXMsIG1pc3NpbmcgZGF0YSBtZWNoYW5pc21zIGNhbiBiZSBjYXRlZ29yaXplZCBpbnRvIHRocmVlIGNsYXNzZXM6IG1pc3NpbmcgY29tcGxldGVseSBhdCByYW5kb20gKE1DQVIpLCBtaXNzaW5nIGF0IHJhbmRvbSAoTUFSKSwgYW5kIG1pc3Npbmcgbm90IGF0IHJhbmRvbSAoTU5BUikuIA0KDQoqICoqTWlzc2luZyBDb21wbGV0ZWx5IGF0IFJhbmRvbSAoTUNBUikqKjogSWYgbWlzc2luZyBkYXRhIGFyZSB1bnJlbGF0ZWQgdG8gYm90aCB0aGUgbWlzc2luZyByZXNwb25zZXMgYW5kIHRoZSBzZXQgb2Ygb2JzZXJ2ZWQgcmVzcG9uc2VzLCB0aGUgb2JzZXJ2ZWQgdmFsdWVzIGFyZSByZXByZXNlbnRhdGl2ZSBvZiB0aGUgZW50aXJlIHNhbXBsZSB3aXRob3V0IG1pc3NpbmcgdmFsdWVzLiBUaGlzIG1pc3NpbmcgZGF0YSBtZWNoYW5pc20gaXMgcmVmZXJyZWQgdG8gYXMgTUNBUi4gVGhpcyBpcyB0aGUgYmVzdCB3ZSBjYW4gaG9wZSBmb3Igc2luY2Ugd2UgY2FuIHNpbXBseSBpZ25vcmUgdGhlIHJlY29yZHMgd2l0aCBtaXNzaW5nIGNvbXBvbmVudHMgKGxpc3Qtd2lzZSBkZWxldGlvbikgd2l0aG91dCBpbnRyb2R1Y2luZyBiaWFzIHRvIHRoZSBkYXRhLg0KDQoNCiogKipNaXNzaW5nIGF0IFJhbmRvbSAoTUFSKSoqOiBJZiBtaXNzaW5nIGRhdGEgZGVwZW5kIG9uIHRoZSBzZXQgb2Ygb2JzZXJ2ZWQgcmVzcG9uc2VzIGJ1dCBhcmUgdW5yZWxhdGVkIHRvIHRoZSBtaXNzaW5nIHZhbHVlcywgdGhlIG1pc3NpbmcgZGF0YSBhcmUgc2FpZCB0byBiZSBNQVIuIEZvciBleGFtcGxlLCBhIHJlZ2lzdHJ5IGV4YW1pbmluZyBkZXByZXNzaW9uIG1heSBlbmNvdW50ZXIgZGF0YSB0aGF0IGFyZSBNQVIgaWYgbWFsZSBwYXJ0aWNpcGFudHMgYXJlIGxlc3MgbGlrZWx5IHRvIGNvbXBsZXRlIGEgc3VydmV5IGFib3V0IGRlcHJlc3Npb24gc2V2ZXJpdHkgdGhhbiBmZW1hbGUgcGFydGljaXBhbnRzLiBUaGF0IGlzLCBpZiB0aGUgcHJvYmFiaWxpdHkgb2YgY29tcGxldGlvbiBvZiB0aGUgc3VydmV5IGlzIHJlbGF0ZWQgdG8gdGhlaXIgc2V4ICh3aGljaCBpcyBmdWxseSBvYnNlcnZlZCkgYnV0IG5vdCB0aGUgc2V2ZXJpdHkgb2YgdGhlaXIgZGVwcmVzc2lvbiwgdGhlbiB0aGUgZGF0YSBtYXkgYmUgcmVnYXJkZWQgYXMgTUFSLiAgU2luY2UgdGhlcmUgaXMgYSBzeXN0ZW1hdGljIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwcm9wZW5zaXR5IG9mIG1pc3NpbmcgdmFsdWVzIGFuZCB0aGUgb2JzZXJ2ZWQgZGF0YSwgYnV0IG5vdCB0aGUgbWlzc2luZyBkYXRhLiBXaGF0IGl0IG1lYW5zLCBpcyB0aGF0IHRoZSBtaXNzaW5nIGRhdGEgY2FuIGJlIHByZWRpY3RlZCBieSBvdGhlciB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgc2V0LiANCg0KDQoqICoqTWlzc2luZyBOb3QgYXQgUmFuZG9tIChNTkFSKSoqOiBUaGVyZSBpcyBhIHBhdHRlcm4gaW4gdGhlIG1pc3NpbmcgZGF0YSB0aGF0IGFmZmVjdHMgdGhlIHByaW1hcnkgZGVwZW5kZW50IHZhcmlhYmxlcy4gV2UgY2FuIGV4dGVuZCB0aGUgYWJvdmUgImRlcHJlc3Npb24iIGV4YW1wbGUgaWYgcGFydGljaXBhbnRzIHdpdGggc2V2ZXJlIGRlcHJlc3Npb24gYXJlIG1vcmUgbGlrZWx5IHRvIHJlZnVzZSB0byBjb21wbGV0ZSB0aGUgc3VydmV5IGFib3V0IGRlcHJlc3Npb24gc2V2ZXJpdHkuIFNpbmNlIHRoZSBzb3VyY2VzIG9mIG1pc3NpbmcgZGF0YSBhcmUgdGhlbXNlbHZlcyB1bm1lYXN1cmVkIG1lYW5zIHRoYXQgKGluIGdlbmVyYWwpIHRoaXMgaXNzdWUgY2Fubm90IGJlIGFkZHJlc3NlZCBpbiBhbmFseXNpcywgYW5kIHRoZSBlc3RpbWF0ZSBvZiBlZmZlY3Qgd2lsbCBsaWtlbHkgYmUgYmlhc2VkLiBNaXNzaW5nIG5vdCBhdCByYW5kb20gaXMgdGhlIHdvcnN0LWNhc2Ugc2NlbmFyaW8uIFdlIHNob3VsZCB1c2UgTU5BUiBkYXRhIHdpdGggY2F1dGlvbiBzaW5jZSB0aGVzZSBtaXNzaW5nIGRhdGEgY2Fubm90IGJlICJyZWNvdmVyZWQiLg0KDQoNCiMgTWV0aG9kcyBvZiBIYW5kbGluZyBNaXNzaW5nIERhdGENCg0KTWV0aG9kcyBvZiBoYW5kbGluZyBtaXNzaW5nIGRhdGEgYXJlIGRlcGVuZGVudCBvbiB0aGUgbWlzc2luZyBkYXRhIG1lY2hhbmlzbXMuICBXZSBoYXZlIGJyaWVmbHkgZGlzY3Vzc2VkIHRocmVlIG1ham9yIHR5cGVzIG9mIG1pc3NpbmcgbWVjaGFuaXNtcyBpbiB0aGUgcHJldmlvdXMgc2VjdGlvbnMuIEhlcmUgaXMgYSBzdW1tYXJ5IG9mIHRoZXNlIG1lY2hhbmlzbXMuDQoNCiogSW4gKipNQ0FSKiosIHRoZSBtaXNzaW5nIG1lY2hhbmlzbSBpcyBpbmRlcGVuZGVudCBvZiBjaGFyYWN0ZXJpc3RpY3Mgb2YgZWl0aGVyIHRoZSBvYnNlcnZlZCBkYXRhIG9yIHRoZSB1bm9ic2VydmVkIHZhbHVlcyBpbiB0aGUgZGF0YSBzZXQuDQoNCiogSW4gKipNQVIqKiwgdGhlIG1pc3NpbmcgbWVjaGFuaXNtIGlzIGVudGlyZWx5IGV4cGxhaW5lZCBieSB0aGUgb2JzZXJ2ZWQgZGF0YSwgdGhhdCBpcywgYWZ0ZXIgb2JzZXJ2ZWQgdmFsdWVzIGFyZSBhY2NvdW50ZWQgZm9yLCBtaXNzaW5nbmVzcyBpcyByYW5kb21seSBkaXN0cmlidXRlZC4NCg0KKiBJbiAqKk1OQVIqKiwgbWlzc2luZyBvYnNlcnZhdGlvbnMgYXJlIGRlcGVuZGVudCB1cG9uIHVub2JzZXJ2ZWQgdmFsdWVzOyBtaXNzaW5nbmVzcyBjYW5ub3QgYmUgYWNjb3VudGVkIGZvciBieSBjb250cm9sbGluZyBmb3Igb2JzZXJ2ZWQgZGF0YS4NCg0KDQpJbiB0aGUgc3Vic2VxdWVudCBzdWItc2VjdGlvbnMsIHdlIHdpbGwgb3V0bGluZSB0aGUgbWFqb3IgbWV0aG9kcyB1c2VkIHRvIGhhbmRsZSBtaXNzaW5nIGRhdGEgd2l0aCBkaWZmZXJlbnQgdHlwZXMgb2YgbWlzc2luZyBtZWNoYW5pc21zLg0KDQojIyBMaXN0d2lzZSBEZWxldGlvbg0KDQpEZWxldGUgYWxsIGRhdGEgZnJvbSBhbnkgcGFydGljaXBhbnQgd2l0aCBtaXNzaW5nIHZhbHVlcy4gSWYgdGhlIHNhbXBsZSBpcyBsYXJnZSBlbm91Z2gsIHdlIGxpa2VseSBjYW4gZHJvcCBkYXRhIHdpdGhvdXQgc3Vic3RhbnRpYWwgbG9zcyBvZiBzdGF0aXN0aWNhbCBwb3dlci4gQmUgc3VyZSB0aGF0IHRoZSB2YWx1ZXMgYXJlIG1pc3NpbmcgYXQgcmFuZG9tIGFuZCB0aGF0IHlvdSBhcmUgbm90IGluYWR2ZXJ0ZW50bHkgcmVtb3ZpbmcgYSBjbGFzcyBvZiBwYXJ0aWNpcGFudHMuDQoNClRoaXMgbWV0aG9kIGlzIHVzZWQgZm9yIE1DQVIgYW5kLCBvY2Nhc2lvbmFsbHksIE1BUi4gSXQgaXMgdGhlIGVhc2llc3QgYW5kIHNpbXBsZXN0IG1ldGhvZCBhbW9uZyBhbGwgb3RoZXIgYXZhaWxhYmxlIG1ldGhvZHMuDQoNClRoZSBkaXNhZHZhbnRhZ2VzIGFyZQ0KDQoqIGxvc3Mgb2YgdmFsdWFibGUgaW5mb3JtYXRpb247DQoqIHBvdGVudGlhbCBjb250cmlidXRpb24gdG8gYmlhczsNCiogbG9zcyBvZiBzdGF0aXN0aWNhbCBwb3dlcjsNCg0KIyMgTWVhbiBSZXBsYWNlbWVudCANCg0KRm9yIHZhcmlhYmxlIOKAnFjigJ0gd2l0aCBtaXNzaW5nIHZhbHVlcywgdGFrZSB0aGUgbWVhbiBvZiBhbGwgaW5jbHVkZWQgb2JzZXJ2YXRpb25zLiBTdWJzdGl0dXRlIHRoZSBtZWFuIG9mIOKAnFjigJ0gZm9yIG1pc3NpbmcgdmFsdWVzIG9mIOKAnFjigJ0uIFRoaXMgaXMgYSB0eXBlIG9mIHNpbXBsZSBpbXB1dGF0aW9uIG1ldGhvZC4gDQoNCkl0IGlzIHZhbGlkIGZvciBNQ0FSLiBUaGUgYWR2YW50YWdlcyBhcmUNCg0KKiBwcmVzZXJ2aW5nIHRoZSBtZWFuIG9mIHRoZSBkYXRhIHNldDsgDQoqIHNpbXBsZTsNCiogYWxsb3dpbmcgdXNlIG9mIGFsbCBvYnNlcnZhdGlvbnMNCg0KVGhlIGRpc2FkdmFudGFnZXMgYXJlDQoNCiogYXJ0aWZpY2lhbGx5IHJlZHVjaW5nIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGRhdGEgc2V0LCANCiogZGlzdG9ydGluZyByZWxhdGlvbnNoaXBzIGJldHdlZW4gdmFyaWFibGVzOw0KKiB5aWVsZGluZyBwb3RlbnRpYWxseSBiaWFzZWQgZXN0aW1hdGVzOw0KKiBwcm9kdWNpbmcgcmVzdWx0cyB0aGF0IGFyZSBoaWdobHkgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgYnV0IGluYWNjdXJhdGU7DQoNCg0KIyMgUmVncmVzc2lvbiBSZXBsYWNlbWVudA0KDQpUaGlzIGlzIGFub3RoZXIgbWV0aG9kIG9mIHNpbmdsZSBpbXB1dGF0aW9uLiBJdCBlc3RpbWF0ZXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgbWlzc2luZyB2YXJpYWJsZShzKSwgZ2l2ZW4gY292YXJpYXRlcywgdGFrZXMgYSByYW5kb20gZHJhdyBmcm9tIHRoaXMgZGlzdHJpYnV0aW9uIGZvciBlYWNoIHZhbHVlIHRoZW4gcGVyZm9ybXMgYW5hbHlzaXMgYXMgdXN1YWwuDQoNClRoZSByZWdyZXNzaW9uIHJlcGxhY2VtZW50IGlzIHZhbGlkIGZvciBib3RoIE1DQVIgYW5kIE1BUi4gVGhlIGFkdmFudGFnZXMgYXJlIA0KKiBhdm9pZGFuY2Ugb2YgIGJpYXMgaW4gZXN0aW1hdGluZzsNCiogc2ltcGxlciB0aGFuIG11bHRpcGxlIGltcHV0YXRpb25zOw0KDQoNClRoZSBkaXNhZHZhbnRhZ2VzIGFyZQ0KDQoqIG1pc3JlcHJlc2VudGluZyB1bmNlcnRhaW50eSBvZiBlc3RpbWF0ZXM7IA0KKiBtb3JlIGNvbXBsaWNhdGVkIHRoYW4gbGlzdC13aXNlIGRlbGV0aW9uIG9yIG1lYW4gcmVwbGFjZW1lbnQNCiogcmVkdWNpbmcgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgZXN0aW1hdGVzIGFsdGhvdWdoIHRoZW9yZXRpY2FsbHkgdW5iaWFzZWQuIA0KDQoNCiMjIE11bHRpcGxlIEltcHV0YXRpb24NCg0KTXVsdGlwbGUgSW1wdXRhdGlvbiBpcyB0aGUgbW9zdCBzb3BoaXN0aWNhdGVkIGFuZCwgY3VycmVudGx5LCBtb3N0IHBvcHVsYXIgYXBwcm9hY2ggdG8gdGFrZSB0aGUgcmVncmVzc2lvbiBpZGVhIGZ1cnRoZXIgYW5kIHRha2UgYWR2YW50YWdlIG9mIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHJlc3BvbnNlcy4gDQoNCkl0IGVzdGltYXRlcyB0aGUgZGlzdHJpYnV0aW9uIChCYXllc2lhbiBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uKSBvZiB0aGUgbWlzc2luZyB2YXJpYWJsZSwgZ2l2ZW4gY292YXJpYXRlczsgdGFrZXMgcmFuZG9tIGRyYXdzIGZyb20gdGhpcyBkaXN0cmlidXRpb24gdG8gcHJvZHVjZSBtdWx0aXBsZSB2ZXJzaW9ucyAodXN1YWxseSAz4oCTMTApIG9mIGFuIGltcHV0ZWQgZGF0YSBzZXQ7IHBlcmZvcm1zIGFuYWx5c2lzIG9uIGVhY2ggaW1wdXRlZCBkYXRhIHNldCBhbmQgcG9vbHMgdGhlIHJlc3VsdHMuIEl0IGlzIGEgc2ltdWxhdGlvbi1iYXNlZCBCYXllc2lhbiBtZXRob2QuIE1vc3Qgc3RhdGlzdGljYWwgY29tcHV0ZXIgcHJvZ3JhbXMgY2FuIGRvIG11bHRpcGxlIGltcHV0YXRpb25zLg0KDQpJdCBpcyB2YWxpZCBmb3IgTUNBUiBvciBNQVIuIFRoZSBhZHZhbnRhZ2VzIGFyZQ0KDQoqIGFjY291bnRpbmcgZm9yIHRoZSBleHRyYSB1bmNlcnRhaW50eSBwcm9kdWNlZCBieSBpbXB1dGluZyBkYXRhOw0KKiBwcm9kdWNpbmcgYmV0dGVyIGVzdGltYXRlcyBvZiBtaXNzaW5nIHZhbHVlcy4NCg0KVGhlIGRpc2FkdmFudGFnZXMgYXJlDQoNCiogcmVxdWlyaW5nIGNvbXBsaWNhdGVkIHN0YXRpc3RpY2FsIG1ldGhvZHMgb3IgY29tcGxpY2F0ZWQgc29mdHdhcmU7DQoqIGhhcmRlciB0byB1bmRlcnN0YW5kOyANCiogdGFraW5nIGV4dHJhIHN0ZXBzOw0KKiBiZWNhdXNlIHRoZSBtZXRob2QgYWNjb3VudHMgZm9yIGV4dHJhIHVuY2VydGFpbnR5LCByZXN1bHRzIGNhbiBiZSBpbnRlcnByZXRlZCBhcyBpZiBkYXRhIHdlcmUgbm90IG1pc3NpbmcuDQoNCiMgUiBQYWNrYWdlcyBmb3IgSW1wdXRhdGlvbg0KDQpTZXZlcmFsIFIgcGFja2FnZXMgaGF2ZSBmdW5jdGlvbnMgdG8gcGVyZm9ybSBpbXB1dGF0aW9uIGZvciBtaXNzaW5nIHZhbHVlcy4gVGhpcyBzZWN0aW9uIGxpc3RzIGEgZmV3IGNvbW1vbmx5IHVzZWQgUiBsaWJyYXJpZXMuIFdlIG9ubHkgZXhwbGFpbiB0aGUgY29uY2VwdHMgd2l0aCBubyBjb2RpbmcuDQoNCiMjIE1JQ0UgUGFja2FnZQ0KDQpNSUNFIChNdWx0aXZhcmlhdGUgSW1wdXRhdGlvbiB2aWEgQ2hhaW5lZCBFcXVhdGlvbnMpIGlzIG9uZSBvZiB0aGUgY29tbW9ubHkgdXNlZCBwYWNrYWdlcyBieSBSIHVzZXJzLiBDcmVhdGluZyBtdWx0aXBsZSBpbXB1dGF0aW9ucyBhcyBjb21wYXJlZCB0byBhIHNpbmdsZSBpbXB1dGF0aW9uIChzdWNoIGFzIHRoZSBtZWFuKSB0YWtlcyBjYXJlIG9mIHVuY2VydGFpbnR5IGluIG1pc3NpbmcgdmFsdWVzLg0KDQpNSUNFIGFzc3VtZXMgdGhhdCB0aGUgbWlzc2luZyBkYXRhIGFyZSBNaXNzaW5nIGF0IFJhbmRvbSAoTUFSKSwgd2hpY2ggbWVhbnMgdGhhdCB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIHZhbHVlIGlzIG1pc3NpbmcgZGVwZW5kcyBvbmx5IG9uIHRoZSBvYnNlcnZlZCB2YWx1ZSBhbmQgY2FuIGJlIHByZWRpY3RlZCB1c2luZyB0aGVtLiBJdCBpbXB1dGVzIGRhdGEgb24gYSB2YXJpYWJsZS1ieS12YXJpYWJsZSBiYXNpcyBieSBzcGVjaWZ5aW5nIGFuIGltcHV0YXRpb24gbW9kZWwgcGVyIHZhcmlhYmxlLg0KDQpBcyBhbiBleGFtcGxlLCB3ZSBjb25zaWRlciBhIGRhdGEgc2V0IHdpdGggdmFyaWFibGVzICRYXzEsIFhfMiwgXGNkb3RzLCBYX2skLiBJZiAkWF8xJCBoYXMgbWlzc2luZyB2YWx1ZXMsIHRoZW4gaXQgd2lsbCBiZSByZWdyZXNzZWQgb24gb3RoZXIgdmFyaWFibGVzICRYXzIkIHRvICRYX2skLiBUaGUgbWlzc2luZyB2YWx1ZXMgaW4gJFhfMSQgd2lsbCBiZSB0aGVuIHJlcGxhY2VkIGJ5IHByZWRpY3RpdmUgdmFsdWVzIG9idGFpbmVkLiBTaW1pbGFybHksIGlmICRYXzIkIGhhcyBtaXNzaW5nIHZhbHVlcywgdGhlbiAkWF8xJCwgJFhfMyQgdG8gJFhfayQgdmFyaWFibGVzIHdpbGwgYmUgdXNlZCBpbiB0aGUgcHJlZGljdGlvbiBtb2RlbCBhcyBpbmRlcGVuZGVudCB2YXJpYWJsZXMuIExhdGVyLCBtaXNzaW5nIHZhbHVlcyB3aWxsIGJlIHJlcGxhY2VkIHdpdGggcHJlZGljdGVkIHZhbHVlcy4NCg0KQnkgZGVmYXVsdCwgbGluZWFyIHJlZ3Jlc3Npb24gaXMgdXNlZCB0byBwcmVkaWN0IGNvbnRpbnVvdXMgbWlzc2luZyB2YWx1ZXMuIExvZ2lzdGljIHJlZ3Jlc3Npb24gaXMgdXNlZCBmb3IgY2F0ZWdvcmljYWwgbWlzc2luZyB2YWx1ZXMuIE9uY2UgdGhpcyBjeWNsZSBpcyBjb21wbGV0ZSwgbXVsdGlwbGUgZGF0YSBzZXRzIGFyZSBnZW5lcmF0ZWQuIFRoZXNlIGRhdGEgc2V0cyBkaWZmZXIgb25seSBpbiBpbXB1dGVkIG1pc3NpbmcgdmFsdWVzLiBHZW5lcmFsbHksIGl04oCZcyBjb25zaWRlcmVkIHRvIGJlIGEgZ29vZCBwcmFjdGljZSB0byBidWlsZCBtb2RlbHMgb24gdGhlc2UgZGF0YSBzZXRzIHNlcGFyYXRlbHkgYW5kIGNvbWJpbmUgdGhlaXIgcmVzdWx0cy4NCg0KUHJlY2lzZWx5LCB0aGUgbWV0aG9kcyB1c2VkIGJ5IHRoaXMgcGFja2FnZSBjYW4gYmUgZm91bmQgaW4gdGhlIGRvY3VtZW50IG9mIHRoZSBwYWNrYWdlIGF0IDxodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWljZS9taWNlLnBkZj4uDQoNCiMjIEhtaXNjIFBhY2thZ2UNCg0KSG1pc2MgaXMgYSBtdWx0aXBsZS1wdXJwb3NlIHBhY2thZ2UgdXNlZnVsIGZvciBkYXRhIGFuYWx5c2lzLCBoaWdo4oCTbGV2ZWwgZ3JhcGhpY3MsIGltcHV0aW5nIG1pc3NpbmcgdmFsdWVzLCBhZHZhbmNlZCB0YWJsZSBtYWtpbmcsIG1vZGVsIGZpdHRpbmcgJiBkaWFnbm9zdGljcyAobGluZWFyIHJlZ3Jlc3Npb24sIGxvZ2lzdGljIHJlZ3Jlc3Npb24gJiBjb3ggcmVncmVzc2lvbiksIGV0Yy4gQW1pZHN0LCB0aGUgd2lkZSByYW5nZSBvZiBmdW5jdGlvbnMgY29udGFpbmVkIGluIHRoaXMgcGFja2FnZSwgaXQgb2ZmZXJzIDIgcG93ZXJmdWwgZnVuY3Rpb25zIGZvciBpbXB1dGluZyBtaXNzaW5nIHZhbHVlcy4gVGhlc2UgYXJlIGltcHV0ZSgpIGFuZCBhcmVnSW1wdXRlKCkuIFRob3VnaCBpdCBhbHNvIGhhcyB0cmFuc2NhbigpIGZ1bmN0aW9uLCBhcmVnSW1wdXRlKCkgaXMgYmV0dGVyIHRvIHVzZS4NCg0KaW1wdXRlKCkgZnVuY3Rpb24gc2ltcGx5IGltcHV0ZXMgbWlzc2luZyB2YWx1ZXMgdXNpbmcgYSB1c2VyLWRlZmluZWQgc3RhdGlzdGljYWwgbWV0aG9kIChtZWFuLCBtYXgsIG1lYW4pLiBJdHMgZGVmYXVsdCBpcyBtZWRpYW4uIE9uIHRoZSBvdGhlciBoYW5kLCBhcmVnSW1wdXRlKCkgYWxsb3dzIHRoZSBtZWFuIGltcHV0YXRpb24gdXNpbmcgYWRkaXRpdmUgcmVncmVzc2lvbiwgYm9vdHN0cmFwcGluZywgYW5kIHByZWRpY3RpdmUgbWVhbiBtYXRjaGluZy4NCg0KSW4gYm9vdHN0cmFwcGluZywgZGlmZmVyZW50IGJvb3RzdHJhcCByZXNhbXBsZXMgYXJlIHVzZWQgZm9yIGVhY2ggb2YgdGhlIG11bHRpcGxlIGltcHV0YXRpb25zLiBUaGVuLCBhIGZsZXhpYmxlIGFkZGl0aXZlIG1vZGVsIChub24tcGFyYW1ldHJpYyByZWdyZXNzaW9uIG1ldGhvZCkgaXMgZml0dGVkIG9uIHNhbXBsZXMgdGFrZW4gd2l0aCByZXBsYWNlbWVudHMgZnJvbSBvcmlnaW5hbCBkYXRhLCBhbmQgbWlzc2luZyB2YWx1ZXMgKGFjdHMgYXMgZGVwZW5kZW50IHZhcmlhYmxlKSBhcmUgcHJlZGljdGVkIHVzaW5nIG5vbi1taXNzaW5nIHZhbHVlcyAoaW5kZXBlbmRlbnQgdmFyaWFibGUpLg0KDQpUaGVuLCBpdCB1c2VzIHByZWRpY3RpdmUgbWVhbiBtYXRjaGluZyAoZGVmYXVsdCkgdG8gaW1wdXRlIG1pc3NpbmcgdmFsdWVzLiBQcmVkaWN0aXZlIG1lYW4gbWF0Y2hpbmcgd29ya3Mgd2VsbCBmb3IgY29udGludW91cyBhbmQgY2F0ZWdvcmljYWwgKGJpbmFyeSAmIG11bHRpLWxldmVsKSB3aXRob3V0IHRoZSBuZWVkIGZvciBjb21wdXRpbmcgcmVzaWR1YWxzIGFuZCBtYXhpbXVtIGxpa2VsaWhvb2QgZml0Lg0KDQpNb3JlIGZ1bmN0aW9ucyBhbmQgdXBkYXRlcyBpbiBIbWlzYyBwYWNrYWdlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0htaXNjL0htaXNjLnBkZj4gDQoNCg0KDQojIFRoZSBNSUNFIEFsZ29yaXRobQ0KDQpUaGUgTUlDRSBwcm9jZXNzIGZvbGxvd3MgYSBzeXN0ZW1hdGljIGFwcHJvYWNoIHRvIGl0ZXJhdGl2ZWx5IGltcHV0ZSBtaXNzaW5nIGRhdGEuIEl0IGludm9sdmVzIGNyZWF0aW5nIG11bHRpcGxlIHZlcnNpb25zIG9mIHRoZSBkYXRhIHNldCB3aXRoIHBsYXVzaWJsZSBlc3RpbWF0ZXMgZm9yIG1pc3NpbmcgdmFsdWVzIHdoaWxlIHByZXNlcnZpbmcgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgdmFyaWFibGVzLiANCg0KSW4gdGhlIFIgbGlicmFyeSBgbWljZSgpYCwgYXJndW1lbnQgYG1heGl0ID0gbWAgaW5kaWNhdGVzIHRoZSBudW1iZXIgb2YgY3ljbGVzIChpdGVyYXRpb25zKSBvZiB0aGUgaXRlcmF0aXZlIGltcHV0aW5nIHByb2Nlc3MuIFRvIGlsbHVzdHJhdGUgdGhpcyBpdGVyYXRpdmUgaW1wdXRhdGlvbiBwcm9jZXNzLCB3ZSB1c2UgdGhlIGZvbGxvd2luZyB0b3kgZGF0YSB0byBzaG93IHRoZSBsb2dpY2FsIHByb2Nlc3MuDQoNCg0KYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjgwJSIsIGZpZy5jYXA9Ikl0ZXJhdGl2ZSBpbXB1dGF0aW9uIHByb2Nlc3MgaW4gTUkuIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImltZy9NSS1JdGVyYXRpdmUtSW1wdXRlZC1Qcm9jZXNzLmpwZyIpDQpgYGANCg0KDQpCZWxvdyBpcyBhbiBhbGdvcml0aG0gdGhhdCBzdW1tYXJpemVzIHRoZSBhYm92ZSBNSUNFIHByb2Nlc3MuDQoNCg0KKipNSUNFIEFsZ29yaXRobSoqDQoNCmBgYA0KU3RlcCAxOiBJbml0aWFsaXplIGltcHV0ZWQgdmFsdWVzDQogICAgICAgIDEuMS4gRm9yIGVhY2ggdmFyaWFibGUgd2l0aCBtaXNzaW5nIHZhbHVlcywgaW1wdXRlIGluaXRpYWwgdmFsdWVzIHVzaW5nIA0KICAgICAgICAgICAgIGEgc2ltcGxlIGltcHV0YXRpb24gbWV0aG9kIChlLmcuLCBtZWFuLCBtZWRpYW4sIG1vZGUgaW1wdXRhdGlvbiwgDQogICAgICAgICAgICAgb3IgcmVncmVzc2lvbikuDQogICAgICAgIDEuMi4gVGhlc2UgaW5pdGlhbCBpbXB1dGF0aW9ucyB3aWxsIGJlIHVzZWQgYXMgc3RhcnRpbmcgdmFsdWVzIGluIHRoZSANCiAgICAgICAgICAgICBpdGVyYXRpdmUgcHJvY2Vzcy4NClN0ZXAgMjogU2V0IHVwIHRoZSBpbXB1dGF0aW9uIG1vZGVsIGZvciBlYWNoIHZhcmlhYmxlDQogICAgICAgIDIuMS4gRGVmaW5lIHRoZSBpbXB1dGF0aW9uIG1vZGVsIGZvciBlYWNoIHZhcmlhYmxlIHdpdGggbWlzc2luZyBkYXRhLiANCiAgICAgICAgICAgICBUaGUgbW9kZWwgY2FuIGJlIGRpZmZlcmVudCBmb3IgZWFjaCB2YXJpYWJsZSBhbmQgY2FuIGJlIGJhc2VkIG9uIGEgDQogICAgICAgICAgICAgcmVncmVzc2lvbiBtb2RlbCAoZS5nLiwgbGluZWFyIHJlZ3Jlc3Npb24sIGxvZ2lzdGljIHJlZ3Jlc3Npb24pIG9yIA0KICAgICAgICAgICAgIG90aGVyIG1vZGVscyBkZXBlbmRpbmcgb24gdGhlIG5hdHVyZSBvZiB0aGUgZGF0YS4NCiAgICAgICAgMi4yLiBUaGUgdmFyaWFibGUgdG8gYmUgaW1wdXRlZCAoZGVwZW5kZW50IHZhcmlhYmxlKSB3aWxsIGJlIHJlZ3Jlc3NlZCANCiAgICAgICAgICAgICBvbiBvdGhlciB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQgKHByZWRpY3RvciB2YXJpYWJsZXMpLg0KU3RlcCAzOiBJdGVyYXRpdmUgaW1wdXRhdGlvbiBwcm9jZXNzDQogICAgICAgIDMuMS4gRm9yIGVhY2ggaXRlcmF0aW9uIHQsIHJlcGVhdCB0aGUgZm9sbG93aW5nIHByb2Nlc3MgZm9yIGVhY2ggdmFyaWFibGUgDQogICAgICAgICAgICAgd2l0aCBtaXNzaW5nIHZhbHVlczoNCiAgICAgICAgICAgICAzLjEuMS4gRm9yIGVhY2ggdmFyaWFibGUgVmkgd2l0aCBtaXNzaW5nIGRhdGEsIHVzZSB0aGUgY3VycmVudCB2YWx1ZXMgDQogICAgICAgICAgICAgICAgICAgIG9mIHRoZSBvdGhlciB2YXJpYWJsZXMgKGluY2x1ZGluZyBwcmV2aW91c2x5IGltcHV0ZWQgdmFsdWVzKSANCiAgICAgICAgICAgICAgICAgICAgdG8gcHJlZGljdCB0aGUgbWlzc2luZyB2YWx1ZXMgZm9yIFZpLg0KICAgICAgICAgICAgIDMuMS4yLiBUaGUgbW9kZWwgZm9yIGltcHV0YXRpb24gb2YgVmkgaXMgZml0dGVkIHRvIHRoZSBjb21wbGV0ZSBkYXRhIA0KICAgICAgICAgICAgICAgICAgICAod2hlcmUgbm8gbWlzc2luZyB2YWx1ZXMgZXhpc3QgZm9yIFZpKS4NCiAgICAgICAgICAgICAzLjEuMy4gSW1wdXRlIG1pc3NpbmcgdmFsdWVzIGZvciBWaSBiYXNlZCBvbiB0aGUgbW9kZWwgZml0IGluIHN0ZXAgDQogICAgICAgICAgICAgICAgICAgIDMuMS4yLCByZXBsYWNpbmcgdGhlIG1pc3NpbmcgdmFsdWVzIHdpdGggcHJlZGljdGVkIHZhbHVlcyANCiAgICAgICAgICAgICAgICAgICAgKHRoaXMgaW1wdXRhdGlvbiBpcyBzdG9jaGFzdGljLCBpbnRyb2R1Y2luZyByYW5kb20gdmFyaWFiaWxpdHkgDQogICAgICAgICAgICAgICAgICAgIHRvIGFjY291bnQgZm9yIHVuY2VydGFpbnR5KS4NCiAgICAgICAgMy4yLiBSZXBlYXQgdGhpcyBwcm9jZXNzIGZvciBhbGwgdmFyaWFibGVzIHdpdGggbWlzc2luZyBkYXRhLg0KU3RlcCA0OiBQZXJmb3JtIG11bHRpcGxlIGltcHV0YXRpb25zDQogICAgICAgIDQuMS4gUmVwZWF0IFN0ZXAgMyBtIHRpbWVzICh3aXRoIG0gYmVpbmcgdGhlIG51bWJlciBvZiBpbXB1dGF0aW9ucykgdG8gDQogICAgICAgICAgICAgY3JlYXRlIG0gZGlmZmVyZW50IGltcHV0ZWQgZGF0YXNldHMuIEVhY2ggZGF0YXNldCB3aWxsIGNvbnRhaW4gDQogICAgICAgICAgICAgaW1wdXRlZCB2YWx1ZXMgZm9yIHRoZSBtaXNzaW5nIGRhdGEgYmFzZWQgb24gZGlmZmVyZW50IGltcHV0YXRpb25zLCANCiAgICAgICAgICAgICByZWZsZWN0aW5nIHRoZSB1bmNlcnRhaW50eSBpbiB0aGUgaW1wdXRhdGlvbiBwcm9jZXNzLg0KU3RlcCA1OiBBbmFseXplIGVhY2ggaW1wdXRlZCBkYXRhc2V0DQogICAgICAgICA1LjEuIFBlcmZvcm0gdGhlIGRlc2lyZWQgYW5hbHlzaXMgKGUuZy4sIHJlZ3Jlc3Npb24sIGh5cG90aGVzaXMgdGVzdGluZykgDQogICAgICAgICAgICAgIG9uIGVhY2ggb2YgdGhlIG0gaW1wdXRlZCBkYXRhc2V0cywgeWllbGRpbmcgbSBzZXRzIG9mIHJlc3VsdHMuDQpTdGVwIDY6IFBvb2wgdGhlIHJlc3VsdHMgdXNpbmcgUnViaW4ncyBSdWxlcw0KICAgICAgICAgNi4xLiBDb21iaW5lIHRoZSByZXN1bHRzIGZyb20gdGhlIG0gZGF0YXNldHMgdXNpbmcgUnViaW7igJlzIHJ1bGVzOg0KICAgICAgICAgICAgICA2LjEuMS4gQ29tYmluZSB0aGUgcGFyYW1ldGVyIGVzdGltYXRlcyAoZS5nLiwgcmVncmVzc2lvbiBjb2VmZmljaWVudHMpIA0KICAgICAgICAgICAgICAgICAgICAgYnkgYXZlcmFnaW5nIHRoZW0gYWNyb3NzIHRoZSBtIGRhdGFzZXRzLg0KICAgICAgICAgICAgICA2LjEuMi4gQ29tYmluZSB0aGUgdmFyaWFuY2UgZXN0aW1hdGVzLCBhY2NvdW50aW5nIGZvciBib3RoIHRoZSANCiAgICAgICAgICAgICAgICAgICAgIHdpdGhpbi1pbXB1dGVkIGRhdGFzZXQgdmFyaWFuY2UgYW5kIHRoZSBiZXR3ZWVuLWltcHV0ZWQgDQogICAgICAgICAgICAgICAgICAgICBkYXRhc2V0IHZhcmlhbmNlLg0KICAgICAgICAgICAgICA2LjEuMy4gQ2FsY3VsYXRlIHRoZSBvdmVyYWxsIHN0YW5kYXJkIGVycm9ycywgY29uZmlkZW5jZSBpbnRlcnZhbHMsIA0KICAgICAgICAgICAgICAgICAgICAgYW5kIHAtdmFsdWVzIGJhc2VkIG9uIHRoZSBjb21iaW5lZCBlc3RpbWF0ZXMuDQpTdGVwIDc6IFJlcG9ydCBvbiB0aGUgY29tYmluZWQgcmVzdWx0cw0KICAgICAgICA3LjEuIFByZXNlbnQgdGhlIGZpbmFsLCBwb29sZWQgcmVzdWx0cywgaW5jbHVkaW5nIHRoZSBjb21iaW5lZCBlc3RpbWF0ZXMsIA0KICAgICAgICAgICAgIHN0YW5kYXJkIGVycm9ycywgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLg0KYGBgDQoNClRoZSBSIGBtaWNlIGxpYnJhcnlgIGhhcyBzZXZlcmFsIGZ1bmN0aW9ucyBsaXN0ZWQgYmVsb3cgdG8gZXh0cmFjdCByZWxldmFudCBpbmZvcm1hdGlvbiBpbiB0aGUgYWJvdmUgYWxnb3JpdGhtLiANCg0KDQpgbWljZSgpYAlJbXB1dGUgdGhlIG1pc3NpbmcgZGF0YSAqbSogdGltZXMNCg0KYHdpdGgoKWAJQW5hbHl6ZSBjb21wbGV0ZWQgZGF0YSBzZXRzLg0KDQpgcG9vbCgpYAlDb21iaW5lIHBhcmFtZXRlciBlc3RpbWF0ZXMuDQoNCmBjb21wbGV0ZSgpYAlFeHBvcnQgaW1wdXRlZCBkYXRhLg0KDQpgYW1wdXRlKClgCUdlbmVyYXRlIG1pc3NpbmcgZGF0YS4NCg0KDQoNCiMjIE51bWVyaWNhbCBFeGFtcGxlDQoNCkZvciBlYXNlIG9mIGlsbHVzdHJhdGlvbiwgd2UgdXNlIHRoZSBidWlsdC1pbiBgYWlycXVhbGl0eWAgZGF0YSBpbiB0aGUgc3Vic2VxdWVudCBleGFtcGxlcy4gIFRoZSBmaXJzdCBmZXcgcmVjb3JkcyBpbiB0aGUgZGF0YSBhcmUgZ2l2ZW4gYmVsb3cuDQoNCg0KYGBge3J9DQpsaWJyYXJ5KG1pY2UpDQpkYXRhIDwtIGFpcnF1YWxpdHkgICMgRXhhbXBsZSBkYXRhc2V0IHdpdGggbWlzc2luZyB2YWx1ZXMNCmRhdGFbMToxMCxdDQpgYGANCg0KDQoqKjEuIEluaXRpYWxpemF0aW9uKioNCg0KVGhlIHByb2Nlc3MgYmVnaW5zIGJ5IGFzc2lnbmluZyBpbml0aWFsIHZhbHVlcyB0byBhbGwgbWlzc2luZyBlbnRyaWVzIGluIHRoZSBkYXRhIHNldC4gVGhlc2UgaW5pdGlhbCB2YWx1ZXMgYXJlIG9mdGVuIGRlcml2ZWQgdXNpbmcgc2ltcGxlIGltcHV0YXRpb24gdGVjaG5pcXVlcywgc3VjaCBhczoNCg0KKiBSZXBsYWNpbmcgbWlzc2luZyBudW1lcmljIHZhbHVlcyB3aXRoIHRoZSBtZWFuIG9yIG1lZGlhbi4NCg0KKiBGaWxsaW5nIG1pc3NpbmcgY2F0ZWdvcmljYWwgdmFsdWVzIHdpdGggdGhlIG1vZGUuDQoNClRoaXMgc3RlcCBwcm92aWRlcyBhIHN0YXJ0aW5nIHBvaW50IGZvciB0aGUgaXRlcmF0aXZlIHByb2Nlc3MuDQoNCg0KYGBge3J9DQppbml0IDwtIG1pY2UoZGF0YSwgbWF4aXQgPSAwKSAgIyBDaGVjayBpbml0aWFsIGltcHV0YXRpb24gc2V0dXANCmluaXQkbWV0aG9kICAgICAgICAgICAgICAgICAgICAjIFZpZXcgZGVmYXVsdCBpbXB1dGF0aW9uIG1ldGhvZHMNCmBgYA0KDQoqKjIuIEltcHV0YXRpb24gTW9kZWxzKioNCg0KRWFjaCB2YXJpYWJsZSB3aXRoIG1pc3NpbmcgZGF0YSBpcyBhc3NpZ25lZCBhIHNwZWNpZmljIGltcHV0YXRpb24gbW9kZWwgdGFpbG9yZWQgdG8gaXRzIGRhdGEgdHlwZS4gU29tZSBjb21tb25seSB1c2VkIG1vZGVscyBhcmUgbGlzdGVkIGJlbG93Lg0KDQoqICoqUHJlZGljdGl2ZSBNZWFuIE1hdGNoaW5nIChwbW0pKio6IEZvciBjb250aW51b3VzIHZhcmlhYmxlcy4NCiogKipMb2dpc3RpYyBSZWdyZXNzaW9uIChsb2dyZWcpKio6IEZvciBiaW5hcnkgdmFyaWFibGVzLg0KKiAqKlBvbHl0b21vdXMgUmVncmVzc2lvbiAocG9seXJlZykqKjogRm9yIGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4NCiogKipQcm9wb3J0aW9uYWwgT2RkcyBNb2RlbCAocG9scikqKjogRm9yIG9yZGluYWwgdmFyaWFibGVzLg0KDQpUaGVzZSBtb2RlbHMgcHJlZGljdCBtaXNzaW5nIHZhbHVlcyBiYXNlZCBvbiBvdGhlciBvYnNlcnZlZCB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgc2V0LiBBcyBhbiBleGFtcGxlLCB3ZSBpbXB1dGUgb25seSBvbmUgZGF0YSAodW5kZXIgdGhlIGl0ZXJhdGl2ZSBpbXB1dGluZyBwcm9jZXNzIGlsbHVzdHJhdGVkIGVhcmxpZXIpLg0KDQpgYGB7cn0NCmxpYnJhcnkobWljZSkNCmRhdCA8LSBhaXJxdWFsaXR5ICAjIEV4YW1wbGUgZGF0YSBzZXQgd2l0aCBtaXNzaW5nIHZhbHVlcw0KIyMgaW5kaXZpZHVhbCB2YXJpYWJsZSANCmltcCA8LSBtaWNlKGRhdCwgbWV0aG9kID0gYygicG1tIiwicG1tIiwgInBtbSIsICJwbW0iLCAgIiIsICIiKSwgDQogICAgICAgICAgICAgICAgIG1heGl0ID0gMTAsICAjIGl0ZXJhdGluZyAxMCBjeWNsZXMgdG8gY29tcGxldGUgZWFjaCBpbXB1dGVkIGRhdGEgc2V0DQogICAgICAgICAgICAgICAgIG0gPSAxLCAgICAgICAjIGdlbmVyYXRlIDEgaW1wdXRlZCBkYXRhIHNldA0KICAgICAgICAgICAgICAgICBwcmludD1GKSAgICAgIyBzdXBwcmVzcyBwcmludG91dHMNCiMjIHdlIHVzZSBjb21wbGV0ZSgpIHRwIHZpZXcgdGhlIGNvbXBsZXRlIGRhdGEgc2V0Lg0KY29tcGxldGUoaW1wLCBhY3Rpb24gPSAxTClbMToxMCxdICAjIFRoZSBkZWZhdWx0ICphY3Rpb24gPSAxTCogcmV0dXJucyB0aGUgZmlyc3QNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbXB1dGVkIChjb21wbGV0ZSkgZGF0YSBzZXQuDQpgYGANCg0KKiozLiBJdGVyYXRpdmUgSW1wdXRhdGlvbioqDQoNClRoZSBjb3JlIG9mIHRoZSBNSUNFIHByb2Nlc3MgaXMgaXRzIGl0ZXJhdGl2ZSBuYXR1cmU6DQoNCiogRWFjaCB2YXJpYWJsZSB3aXRoIG1pc3NpbmcgZGF0YSBpcyB0cmVhdGVkIGFzIGEgZGVwZW5kZW50IHZhcmlhYmxlLCB3aGlsZSBhbGwgb3RoZXIgdmFyaWFibGVzIGFjdCBhcyBwcmVkaWN0b3JzLg0KDQoqIE1pc3NpbmcgdmFsdWVzIGZvciB0aGUgdGFyZ2V0IHZhcmlhYmxlIGFyZSBpbXB1dGVkIHVzaW5nIHRoZSBhc3NpZ25lZCBtb2RlbC4NCg0KKiBUaGlzIHByb2Nlc3MgY3ljbGVzIHRocm91Z2ggYWxsIHZhcmlhYmxlcyB3aXRoIG1pc3NpbmcgZGF0YSwgaXRlcmF0aXZlbHkgcmVmaW5pbmcgdGhlIGltcHV0YXRpb25zLg0KDQpUaGUgaXRlcmF0aW9ucyBjb250aW51ZSB1bnRpbCB0aGUgaW1wdXRlZCB2YWx1ZXMgc3RhYmlsaXplLCBpbmRpY2F0aW5nIGNvbnZlcmdlbmNlLg0KDQoNCmBgYHtyfQ0KZGF0YSA8LSBhaXJxdWFsaXR5ICAjIEV4YW1wbGUgZGF0YSBzZXQgd2l0aCBtaXNzaW5nIHZhbHVlcw0KaW1wIDwtIG1pY2UoZGF0YSwgbWV0aG9kID0gInBtbSIsICMgdXNpbmcgcHJlZGljdGl2ZSBtZWFuIG1hdGNoaW5nIChwcG0pDQogICAgICAgICAgICAgICAgICBtYXhpdCA9IDEwLCAgIyBwcmUtc3BlY2lmaWVkIGN5Y2xlcyBpbiB0aGUgaXRlcmF0aXZlIHByb2Nlc3MNCiAgICAgICAgICAgICAgICAgIG0gPSAyLCAgICAgICAjIGdlbmVyYXRlIDIgaW1wdXRlZCBkYXRhIHNldHMNCiAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMsICAjIHNldHRpbmcgc2VlZCB0byBrZWVwIHJlcHJvZHVjaWJpbGl0eSBvZiB0aGUgcHJvY2Vzcw0KICAgICAgICAgICAgICAgICAgcHJpbnQ9RikgICAgICMgc3VwcHJlc3MgcHJpbnRvdXRzDQpjb21wbGV0ZShpbXAsIGFjdGlvbiA9ICJicm9hZCIpWzE6MTAsXSAjICphY3Rpb24gPSAiYnJvYWQiKiBjb21iaW5lcyB0aGUgdHdvIGltcHV0ZWQgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZGF0YSBzZXRzIGluIGEgd2lkZSB0YWJsZS4gVGhlcmUgYXJlIG90aGVyIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG9wdGlvbnMgdG8gbGF5IG91dCB0aGUgaW1wdXRlZCBkYXRhIHNldHMuDQpgYGANCg0KKiozLiBNdWx0aXBsZSBJbXB1dGF0aW9ucyoqDQoNCk11bHRpcGxlIGltcHV0ZWQgZGF0YSBzZXRzIGFyZSBjcmVhdGVkIHRvIGNhcHR1cmUgdGhlIHZhcmlhYmlsaXR5IGludHJvZHVjZWQgYnkgbWlzc2luZyBkYXRhLg0KDQpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTUsIGZpZy5jYXA9IkxpbmUgcGxvdHMgb2YgbWVhbnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbnMgb2YgdGhlIHR3byBudW1lcmljYWwgdmFyaWFibGVzIHdpdGggbWlzc2luZyB2YWx1ZXMgaW4gZWFjaCBpbXB1dGVkIGRhdGEgc2V0cy4ifQ0KaW1wNSA8LSBtaWNlKGRhdGEsIG1ldGhvZCA9ICJwbW0iLCBtID0gNSwgbWF4aXQgPSAxMCwgc2VlZCA9IDEyMywgcHJpbnQ9RikNCnBsb3QoaW1wNSkNCmBgYA0KDQpIZXJlLCBtID0gNSBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiBpbXB1dGF0aW9ucywgYW5kIG1heGl0ID0gMTAgZGVmaW5lcyB0aGUgbnVtYmVyIG9mIGl0ZXJhdGlvbnMuDQoNCg0KKio0LiBBbmFseXNpcyBhbmQgUG9vbGluZyoqDQoNCkVhY2ggaW1wdXRlZCBkYXRhIHNldCBpcyBhbmFseXplZCBpbmRlcGVuZGVudGx5LCBhbmQgdGhlIHJlc3VsdHMgYXJlIGNvbWJpbmVkIHVzaW5nIFJ1Ymlu4oCZcyBSdWxlcyB0byBwcm9kdWNlIGZpbmFsIGVzdGltYXRlcyBhbmQgc3RhbmRhcmQgZXJyb3JzLg0KDQoNCmBgYHtyfQ0KbW9kZWw1IDwtIHdpdGgoaW1wNSwgbG0oT3pvbmUgfiBXaW5kICsgVGVtcCkpICAjIFRoZSBzdGF0aXN0aWNhbCBtb2RlbCB0byBhc3Nlc3MNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKk96b25lKg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGFuZCAqV2luZCogYW5kICpUZW1wKi4NCnN1bW1hcnkuc3RhdHMgPSBzdW1tYXJ5KG1vZGVsNSkgICAgICAgICAgICAgICAgIyBkaXNwbGF5IHRoZSByZWdyZXNzaW9uIHJlc3VsdHMgb2YgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW5kaXZpZHVhbCBpbXB1dGVkIGRhdGEgc2V0Lg0Kc3VtbWFyeS5zdGF0cyANCmBgYA0KDQpUbyBjb21iaW5lIHRoZSByZXN1bHRzLCB3ZSBzaW1wbHkgdGFrZSB0aGUgYXZlcmFnZSBvZiB0aGUgY29ycmVzcG9uZGluZyBlc3RpbWF0ZWQgcmVncmVzc2lvbiBjb2VmZmljaWVudHMuDQoNCmBgYHtyfQ0Kc3VtbWFyeShwb29sKG1vZGVsNSkpDQpgYGANCg0KVGhlIGFib3ZlLXBvb2xlZCByZXN1bHRzIGFyZSBjYWxjdWxhdGVkIGJhc2VkIG9uIHRoZSBmb3JtdWxhcyBvbiAkUSwgVSwgQiQsIGFuZCAkVCQuIFRoZSBmb2xsb3dpbmcgY29kZSBpbGx1c3RyYXRlcyB0aGUgY2FsY3VsYXRpb24gb2YgdGhlIHBvb2xlZCBzdGFuZGFyZCBlcnJvciBvZiB0aGUgaW50ZXJjZXB0Lg0KDQpgYGB7cn0NCmJldGEgPSBzdW1tYXJ5LnN0YXRzJGVzdGltYXRlW3NlcSgxLDE1LGJ5PTMpXSAgIyBleHBsaWNpdCB2ZWN0b3I6IGMoMSw0LDcsMTAsMTMpDQpiZXRhLnZhciA9IChzdW1tYXJ5LnN0YXRzJHN0ZC5lcnJvcltzZXEoMSwxNSxieT0zKV0pXjIgDQpRID0gbWVhbihiZXRhKQ0KVSA9IG1lYW4oYmV0YS52YXIpDQpCID0gdmFyKGJldGEpDQpUID0gVSArICg2LzUpKkINCnBvb2wuc2UgPSBzcXJ0KFQpDQpjYmluZChwb29sLnNlLmludGVyY2VwdCA9IHBvb2wuc2UpDQpgYGANCg0KIyMgQWR2YW50YWdlcyBvZiBNSUNFDQoNCk1JQ0Ugb2ZmZXJzIHNldmVyYWwgYmVuZWZpdHM6DQoNCiogKipGbGV4aWJpbGl0eSoqOiBJdCBoYW5kbGVzIG1peGVkIGRhdGEgdHlwZXMgKGNvbnRpbnVvdXMsIGJpbmFyeSwgY2F0ZWdvcmljYWwpLg0KKiAqKlByZXNlcnZhdGlvbiBvZiBSZWxhdGlvbnNoaXBzKio6IEltcHV0YXRpb24gcmVzcGVjdHMgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB2YXJpYWJsZXMuDQoqICoqVW5jZXJ0YWludHkgUmVwcmVzZW50YXRpb24qKjogTXVsdGlwbGUgaW1wdXRhdGlvbnMgYWNjb3VudCBmb3IgdmFyaWFiaWxpdHkgaW4gbWlzc2luZyBkYXRhLg0KDQpJbiBSLCB0aGUgbWljZSBwYWNrYWdlIHNpbXBsaWZpZXMgTUlDRSBpbXBsZW1lbnRhdGlvbiwgYWxsb3dpbmcgdXNlcnMgdG8gY3VzdG9taXplIGltcHV0YXRpb24gbWV0aG9kcyBmb3IgZWFjaCB2YXJpYWJsZS4gVGhlIG1haW4gZnVuY3Rpb24gYG1pY2UoKWAgY2FuIGRldGVjdCB0aGUgbWlzc2luZ25lc3Mgb2YgaW5kaXZpZHVhbCB2YXJpYWJsZXMuIElmIGEgdmFyaWFibGUgaGFzIG5vIG1pc3NpbmcgdmFsdWVzLCB0aGUgaW1wdXRpbmcgbW9kZWwgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHNldCB0byBgIiJgLiAgDQoNCg0KYGBge3J9DQppbXA2IDwtIG1pY2UoZGF0YSwgbWV0aG9kID0gYygicG1tIiwgInBtbSIsICJwbW0iLCAicG1tIiwgIiIsICIiKSwgDQogICAgICAgICAgICBtYXhpdCA9IDUsDQogICAgICAgICAgICBwcmludD1GLCANCiAgICAgICAgICAgIHNlZWQgPSAxMjMpDQppbXA2JG1ldGhvZCAgDQojIyB3aXRob3V0IG1ubyBzcGVjaWZpZWQgaW1wdXRpbmcgbW9kZWwNCmluaXQgPC0gbWljZShkYXRhLCAgIA0KICAgICAgICAgICAgbWF4aXQgPSA1LA0KICAgICAgICAgICAgcHJpbnQ9RiwgDQogICAgICAgICAgICBzZWVkID0gMTIzKQ0KaW5pdCRtZXRob2QNCmBgYA0KDQoNCkluIHRoaXMgZXhhbXBsZSwgcHJlZGljdGl2ZSBtZWFuIG1hdGNoaW5nIChgcG1tYCkgaXMgdXNlZCBmb3IgY29udGludW91cyB2YXJpYWJsZXMuIElmIHRoZXJlIGlzIGEgYmluYXJ5IGNhdGVnb3JpY2FsIHZhcmlhYmxlIHdpdGggbWlzc2luZyB2YWx1ZXMsIGxvZ2lzdGljIHJlZ3Jlc3Npb24gKGBsb2dyZWdgKSB3aWxsIGJlIHVzZWQgYXMgdGhlIGltcHV0ZWQgbW9kZWwuDQoNCg0KIyMgQ2hhbGxlbmdlcyBvZiBNSUNFDQoNCkRlc3BpdGUgaXRzIGFkdmFudGFnZXMsIE1JQ0UgY29tZXMgd2l0aCBjaGFsbGVuZ2VzOg0KDQoqICoqQ29tcHV0YXRpb25hbCBJbnRlbnNpdHkqKjogTGFyZ2UgZGF0YXNldHMgYW5kIGhpZ2ggbWlzc2luZ25lc3MgY2FuIGluY3JlYXNlIGNvbXB1dGF0aW9uIHRpbWUuDQoqICoqTW9kZWwgU3BlY2lmaWNhdGlvbioqOiBQb29ybHkgY2hvc2VuIGltcHV0YXRpb24gbW9kZWxzIG1heSBsZWFkIHRvIGluYWNjdXJhdGUgcmVzdWx0cy4NCiogKipEZXBlbmRlbmNlIG9uIERhdGEgUXVhbGl0eSoqOiBFcnJvcnMgaW4gb2JzZXJ2ZWQgZGF0YSBjYW4gcHJvcGFnYXRlIHRocm91Z2ggaW1wdXRhdGlvbnMuDQoNCkluIFIsIHByb3BlciBwcmUtcHJvY2Vzc2luZywgaW5jbHVkaW5nIG91dGxpZXIgaGFuZGxpbmcgYW5kIHRyYW5zZm9ybWF0aW9uLCBjYW4gbWl0aWdhdGUgc29tZSBjaGFsbGVuZ2VzLg0KDQoNCiMjIFByYWN0aWNhbCBBcHBsaWNhdGlvbnMgb2YgTUlDRQ0KDQpNSUNFIGlzIHdpZGVseSB1c2VkIGluIHZhcmlvdXMgZmllbGRzLCBpbmNsdWRpbmcgaGVhbHRoY2FyZSwgc29jaWFsIHNjaWVuY2VzLCBhbmQgc3VydmV5IHJlc2VhcmNoLiBGb3IgaW5zdGFuY2U6DQoNCkluIGNsaW5pY2FsIHRyaWFscywgTUlDRSBpbXB1dGVzIG1pc3NpbmcgcGF0aWVudCBkYXRhIHRvIHByZXNlcnZlIHRoZSBzdHVkeeKAmXMgaW50ZWdyaXR5Lg0KDQpJbiBzdXJ2ZXlzLCBpdCBoYW5kbGVzIGluY29tcGxldGUgcmVzcG9uc2VzIHdoaWxlIG1haW50YWluaW5nIHJlcHJlc2VudGF0aXZlbmVzcy4NCg0KDQpgYGB7cn0NCiMgSW1wdXRhdGlvbiBmb3IgYSBzdXJ2ZXkgZGF0YXNldA0Kc3VydmV5X2RhdGEgPC0gZGF0YS5mcmFtZSgNCiAgQWdlID0gYygyNSwgMzAsIE5BLCAzNSwgNDApLA0KICBHZW5kZXIgPSBjKCJNYWxlIiwgIkZlbWFsZSIsICJNYWxlIiwgTkEsICJGZW1hbGUiKSwNCiAgSW5jb21lID0gYyg1MDAwMCwgTkEsIDYwMDAwLCA2NTAwMCwgNzAwMDApDQopDQppbXAgPC0gbWljZShzdXJ2ZXlfZGF0YSwgbWV0aG9kID0gYygicG1tIiwgImxvZ3JlZyIsICJwbW0iKSwgbWF4aXQgPSA1LCANCiAgICAgICAgICAgIHByaW50PUYsIHNlZWQgPSAxMjMpDQpjb21wbGV0ZV9kYXRhIDwtIGNvbXBsZXRlKGltcCkNCnByaW50KGNvbXBsZXRlX2RhdGEpDQpgYGANCg0KSGVyZSwgcG9seXJlZyBpcyB1c2VkIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIHNob3djYXNpbmcgTUlDRSdzIHZlcnNhdGlsaXR5Lg0KDQoNCiMjIENvbmNsdXNpb24NCg0KTUlDRSBpcyBhIHBvd2VyZnVsIGFuZCBmbGV4aWJsZSB0b29sIGZvciBoYW5kbGluZyBtaXNzaW5nIGRhdGEsIGVuc3VyaW5nIHJvYnVzdCBhbmQgdW5iaWFzZWQgc3RhdGlzdGljYWwgYW5hbHlzZXMuIEl0cyBpdGVyYXRpdmUgcHJvY2VzcywgcmVsaWFuY2Ugb24gdGFpbG9yZWQgaW1wdXRhdGlvbiBtb2RlbHMsIGFuZCBhYmlsaXR5IHRvIGFjY291bnQgZm9yIHVuY2VydGFpbnR5IG1ha2UgaXQgYSBjb3JuZXJzdG9uZSBvZiBtb2Rlcm4gZGF0YSBzY2llbmNlLiBXaXRoIHRvb2xzIGxpa2UgdGhlIG1pY2UgcGFja2FnZSBpbiBSLCBpbXBsZW1lbnRpbmcgTUlDRSBoYXMgYmVjb21lIG1vcmUgYWNjZXNzaWJsZSwgZW5hYmxpbmcgYW5hbHlzdHMgdG8gYWRkcmVzcyBtaXNzaW5nIGRhdGEgY2hhbGxlbmdlcyBlZmZlY3RpdmVseS4gV2hpbGUgaXQgcmVxdWlyZXMgY2FyZWZ1bCBpbXBsZW1lbnRhdGlvbiwgdGhlIGJlbmVmaXRzIG9mIHVzaW5nIE1JQ0UgZmFyIG91dHdlaWdoIGl0cyBjaGFsbGVuZ2VzLCBtYWtpbmcgaXQgYW4gZXNzZW50aWFsIHRlY2huaXF1ZSBmb3IgaGlnaC1xdWFsaXR5IGRhdGEgYW5hbHlzaXMuDQoNCg0KDQoNCg==