Exploring heterogeneity
Introduction to heterogeneity
One major goal of meta-analysis is to quantitatively summarize the effect sizes observed in multiple studies on the same topic. A second major goal is to explore whether these effect sizes (and the true effect sizes that they estimate with some error) are consistent across studies, and if not, to determine what factors lead to variation in the magnitudes of the true effects. In meta-analysis, this variation in the true effect sizes is known as heterogeneity. For example, it may be interesting to determine if the strength of an effect, such as the magnitude of a trophic cascade, is similar across studies conducted in different ecosystem types, or in studies with different experimental durations. To determine whether variation in the observed effect sizes is indicative of real differences in the true effect sizes, and to determine if there are moderating variables that explain the variation in true effect sizes, meta-analysts can conduct formal tests of heterogeneity.
Factors that can contribute to heterogeneity in (true) effect sizes:
- heterogeneity among studies
- heterogeneity among groups (e.g., studies conducted in different ecosystem types)
- covariates (e.g., treatment dose, experimental duration, or some other continuous predictor variable)
The basic concept behind heterogeneity tests is that the effect sizes observed in primary studies are estimates of true effects, and these estimates are measured with some error. Therefore, when we conduct heterogeneity tests we have to try to separate the variation in effect sizes due to measurement error from the variation due to real differences in the true effects.
Evaluating heterogeneity: (Q)
One common way of evaluating heterogeneity in classic meta-analysis is based on the (Q) statistic (also known as Cochran’s (Q)). The (Q) statistic partitions the total variation of the observed effect sizes ((Q_{total})) into two components: (Q_{model}) and (Q_{error}), e.g.: [Q_{total} = Q_{model} + Q_{error}]
(Q_{model}) is the amount of heterogeneity that is explained by the meta-analysis model, and is assumed to be due to real variation in the true effect sizes among studies, groups, and/or whatever moderating variables of interest are included in the model. If there is only one factor in the model (e.g., study), then (Q_{model}) would indicate the amount of heterogeneity in the true effect sizes among levels of that factor. If there are multiple variables in the model, then (Q_{model}) is a cumulative term. (Q_{error}) is due to random, unexplained variation (e.g., measurement error).
For a simple fixed effect model, total heterogeneity (Q_{total}) is calculated using the equation: [Q_{total} = sum_{(i=1)}^k w_i (e_i – bar{E})^2] Where:
- (bar{E}) is the overall mean effect size
- (e_i) is the effect size of the (ith) study
- (w_i) is the weight for the (ith) study
- (k) is the total number of studies in the meta-analysis
- and the degrees of freedom ((df)) associated with this term are (k-1)
In a random effects model the formula for (Q_{total}) would be the same, except the weights would be the random effects version that incorporate both within- and among-study variance.
*Note that (Q) requires estimates of within-study variance to be able to parse out “true” variation in the observed effect sizes from variation due to sampling error. Therefore, parametric (i.e., variance-based) weights are required for its calculation. Other methods must be used to evaluate heterogeneity in models incorporating non-parametric weights, such as model comparison (e.g., comparing a model including study ID as a predictor variable with a model that does not include study ID). See this page from the metafor
website for some examples.
Heterogeneity among studies
Generally, unless all the primary studies in your meta-analysis are conducted under a very narrow set of conditions and procedures, it is reasonable to expect some degree of variation in the observed effect sizes among studies, such as in Fig.1:
Fig. 1) Example of potential heterogeneity among studies in a meta-analysis. Blue circles represent the observed effect sizes, with bars representing their 95% CI.
A heterogeneity test is a way to determine whether these differences in the observed effect sizes are caused by differences in the true effect sizes among studies in the meta-analysis, or if they are instead due to sampling error within individual studies. If there are no groups or explanatory variables in your model, (e.g., when you are just exploring heterogeneity among the effect sizes, which you assume under the null hypothesis all come from the same population), then (Q_{model} = 0), because you assume the true effect is the same across all studies. When (Q_{model} = 0), then all heterogeneity in (Q_{total}) comes from (Q_{error}).
To determine if the amount of variation in the observed effect sizes is likely given the assumption that they all come from the same population, you can compare the (Q_{total}) to a (chi^2) distribution. If (Q_{total}) is larger than predicted for a given (alpha), (i.e. if your p-value is < .05), then this indicates that you have more unexplained variation than would be expected by chance if (Q_{model} = 0).(^{**}) In this case, you can infer that the true effect sizes differ among your studies, and thus using a fixed effect model is not appropriate for the data. Instead, you should use a random effects model.
However, as mentioned in the previous section on Statistical models, heterogeneity tests based on (Q) have low power when there are few studies in the meta-analysis, so a non-significant p-value does not necessarily mean that the true effect sizes are the same across studies; the test could simply not have enough power to detect significant differences. Similarly, (Q) tests can also have too much power if there are many studies in the meta-analysis, especially if some are very large (meaning the test finds significant differences when the true effect sizes are actually homogeneous) (Higgins et al. 2003).
Heterogeneity among groups
In addition to testing for among-study differences in effect sizes, sometimes there are groups within the data that could hypothetically explain some of the variation in effect sizes observed across studies. For example, in a meta-analysis on the effects of maternal temperature environment on the response of offspring to elevated temperature, there could be differences in the effect sizes of ectotherms vs. endotherms.
Fig. 2) Example of potential heterogeneity among groups in a meta-analysis. Blue circles represent the observed effect sizes, with bars representing their error. Studies 1-3 were conducted on ectotherms, while studies 4-5 were conducted on endotherms.
You can see in Fig. 2 that the effect sizes for the studies performed on ectotherms cluster above zero, while the effect sizes for the studies on endotherms cluster below zero. This pattern indicates that the groups ectotherm vs. endotherm might drive significant heterogeneity in the effect sizes. To test this, you could use thermo-regulatory type as a moderating variable in the meta-analysis model. Then, you could estimate the amount of variation explained by thermo-regulatory type using (Q_{model}), i.e., the amount of among-group variation, with (Q_{error}) representing leftover unexplained variation. Another way to think about this is to rewrite (Q_{model}) as (Q_{groups}).
[Q_{total} = Q_{groups} + Q_{error}]
Thus, (Q) operates similarly to ANOVA, where variation in the form of sums of squares (SS) are partitioned across groups (i.e. treatment levels) and error terms, e.g. (SS_{total} = SS_{groups} + SS_{error}). These SS terms are then compared to determine if the variance explained by the groups is greater than the unexplained error variance (this is also known as residual variance). (Q) is simply a weighted SS, and thus, as in ANOVA, you are testing whether heterogeneity is greater among the groups than it is within them. In ANOVA this would be done using the F-ratio, (which equals the variation among / variation within), which you then compare to a normal distribution to determine the p-value. In meta-analysis, this is done by comparing (Q_{groups}) to a (chi^2) distribution.
Thus, another way to think about this for groups is: [Q_{total} = Q_{among} + Q_{within}]
To calculate (Q_{groups}): for a fixed effect model: [Q_{groups} = sum_{(j=1)}^{m}sum_{(i=1)}^{n_j} w_{ij} (bar{E_j} – bar{E})^2] Where:
- (bar{E}) is the overall mean effect size (specifically its estimate based on observed effect sizes)
- (bar{E}_j) is the mean effect in group (j) (based on averaging (e_{ij})’s)
- (w_{ij}) is the weight for the (ith) study in group (j)
- (m) is the number of groups
- (n_j) is the number of studies in group (j)
- Total number of studies is: (k = sum_{j=1}^{m}n_j)
- (df = m – 1) for this term
If (Q_{groups}) is not significant, it indicates that this moderating variable does not explain any heterogeneity in effect sizes in the meta-analysis model. This result can be compared with (Q_{error}). If (Q_{error}) has a significant p-value, then the effect-sizes still have some significant unexplained heterogeneity (and therefore the meta-analyst might want to investigate some other moderating variables).
(Q_{error}), i.e. the residual heterogeneity, is calculated this way: [Q_{error} = sum_{(j=1)}^{m}sum_{(i=1)}^{n_j} w_{ij} (e_j – bar{E_j})^2]
- (df = k – m) for this term (i.e., the total number of studies minus the number of groups)
This approach of using (Q_{groups}) to evaluate the ability of categorical moderating variables to explain heterogeneity in the effect sizes can be expanded to models with multiple moderators, or hierarchical models, where you have one set of groups nested within another (e.g. sites nested in regions). It can also be extended to random effects models. However, although the hypothesis testing and interpretation of the different (Q)’s is still the same, the calculation of each (Q) becomes slighly more complex for these more complicated models. (See Koricheva, Gurevitch, and Mengersen 2013 for more details).
Evaluating heterogeneity due to continuous covariates
(Q) can also be applied to models with continuous variables (i.e., covariates), which may drive variation in the effects sizes observed across studies. This is analogous to a weighted regression analysis, and is known in meta-analysis as a meta-regression. For example, if experimental duration was related to the effect size observed in different studies:
Fig. 3 shows a meta-regression using the effect of experimental duration (x) on the log-risk ratio (y). Points represent effect sizes observed in primary studies. The size of each point indicates the relative weight of that effect size (larger = higher weight).
In this type of model, the mean effect size of each study (bar{E_i}) varies as the value of covariate (X_i) changes, with a slope (beta_{1}) , i.e.:
[bar{E_i} = beta_0 + beta_1X_i + varepsilon_i] Just like the formulation for a regression model, (beta_0) is the intercept of the line, and (varepsilon_i) represents residual error for study (i).
Significance for the different components of heterogeneity are determined the same way as with the categorical moderating variables, by comparing (Q) to a (chi^2) distribution with the corresponding degrees of freedom ((df)). The formula for (Q_{total}) is the same as before (Eqn. X). However, the calculations for (Q_{model}) and (Q_{error}) change.
(Q_{model}) changes to evaluate heterogeneity associated with the slope (beta_{1}): [Q_{model} = frac{beta^2_{1}}{s^2_{beta_{1}}}]
Where (s^2_{beta_{1}}) is the standard error of (beta_{1}), and the (df = 1). (See Koricheva, Gurevitch, and Mengersen 2013 Ch. 9) for the formula for (s_{beta_{1}}). Many statistical packages like metafor
will calculate it for you, and provide you with the correct (Q_{model}) output.
If there is no heterogeneity explained by the covariate, then (beta_{1}) should equal zero. To test the null hypothesis that (beta_{1} = 0), calculate (Q_{model}) and compare it to a (chi^2) distribution as before.
Alternatively, if you want to test whether (beta_{1}) or (beta_{0}) are significantly different from (0), then you can divide their estimate by their standard error ((beta_{} ~/~ s_{beta_{}})), and compare to a normal ((z)) distribution. (So there are two ways to test if (beta_{1} = 0), which yield equivalent results.)
(Q_{error}) has a very complicated formula, so it is easiest to calculate it as: [Q_{error} = Q_{total} – Q_{model}] With (df = k-2), and (k) = total number of studies
Heterogeneity tests in metafor
metafor
will calculate (Q) and conduct the appropriate significance test based on (df) for you.
We will go over how to do this in class.
Summary of (Q)
(Q) provides a formal way to test for heterogeneity in effect sizes, whether due to differences among studies, or due to other moderating variables (categorical or continuous). It relies on paritioning variance components, and thus it requires parametric (variance-based) weights. Additionally, (Q) is on a standarized scale, meaning it is not affected by the effect size metric. However, this scale-free nature means the amount of heterogeneity that it represents is harder to interpret, as it is not in the same units as the original data. Furthermore, (Q) is a sum, and therefore it cannot be compared across meta-analyses because its value depends on the number of studies in the meta-analysis. Finally, although (Q) allows the evaluation of whether or not there is significant among-study variation in effect sizes, due to frequent issues with power leading to the wrong conclusion, it is not recommended as a tool for deciding whether to use a fixed effect model or a random effects model.
Other measures of heterogeneity
In addition to (Q), other metrics have been developed for quantifying heterogeneity in a meta-analysis. The main ones include (T^2), (T), and (I^2). These metrics all have their benefits and limitations, which we will briefly discuss in the following sections.
(T^2)
(T^2), which we discussed in the Statistical models section, estimates the among-study variance, based on the observed effect sizes and their within-study variance. Thus, it is used to estimate variation in the true effect sizes, and provides an absolute value for this estimate. However, it does not quantify how much of the observed variation is real and how much is just sampling/measurement error. It is not sensitive to number of studies, but is sensitive to effect size metric because it is calculated on the same scale as the observed effect sizes. There are multiple ways to calculate (T^2). The DerSimonian and Laird method section, is one of the most common and simplest methods to calculate, however, it has some drawbacks in certain contexts [Future: add more here]. However, increases in computational efficiency have made other methods possible, including restricted maximum likelihood (REML). Due to the benefits of this approach [Future: add more here], many statistical programs are beginning to default to REML, including metafor
.
(T)
(T) is the square root of (T^2), and estimates the among-study standard deviation. Like (T^2), (T) estimates variation in true effect sizes, and is on the same scale as them, but has the added benefit of being in the same units as the original effect size measurements. Thus, it is easier to interpret how much variability there is around those effect sizes. However, due to the dependence of (T) and (T^2) on the scale of original effect size measurements (which depends on the effect size metric), it is difficult to compare (T) and (T^2) among meta-analyses using different effect size metrics.
(I^2)
One metric for estimating heterogeneity that removes the scaling issues associated with (T) and (T^2) is the (I^2) statistic. This statistic gives an estimate of heterogeneity on a relative scale, allowing comparisons of heterogeneity across meta-analyses. (I^2) estimates the percentage of total observed heterogeneity that is attributable to real differences in the true effect sizes, and not due to random error. Therefore, it can be used to indicate the percentage of total observed heterogeneity that is attributable to among-study variance, or to the variance among levels of a moderating variable of interest (Higgins et al. 2003). Thus, it can be thought of as: [I^2 = left( frac{V_{among}}{V_{total}} right) times 100] If (I^2) is zero, it means that all of the observed variation is due to random (e.g., measurement) error and not due to heterogeneity, i.e., variation in the true effect sizes. If it is close to 100%, it indicates that most of the observed variation is due to heterogeneity in effect sizes.
The formula for calculating (I^2) in a random effects model is: [I^2 = lgroup frac{Q_{}-df}{Q_{}} rgroup times 100] The (Q) in the numerator and denominator is (Q_{total}) if the goal is to explore among-study heterogeneity (meaning that (df = k -1), with (k =) the number of studies in the meta-analysis.
(I^2) is a useful statistic because it depends less on the number of studies in the meta-analysis than (Q), however it still can have low power when sample size is small (REF). Additionally, it does not give information on the absolute value of the heterogeneity in effect sizes, so if this information is useful for the interpretation of results, (T^2) or (T) would be important to report as well.
Summary
There are a variety of ways to evaluate variation in effect sizes in a meta-analysis. (Q) provides a formal statistical test to assess differences in the true effects among studies, or the importance of moderating variables (which can be continuous or categorical) for explaining variation in the observed effect sizes. (T^2), (T), and (I^2) are meant to describe variation in effect sizes, either on an absolute ((T^2), (T)) or relative ((I^2)) scale. These metrics have different benefits and drawbacks, and often reveal slightly different information which can be helpful in explaining the results of a meta-analysis.
After conducting heterogeneity tests, the only remaining steps in a meta-analysis are to plot and interpret the results, and evaluate publication bias. We will address these topics in the next modules. Go to [module 9] to learn more about how to visualize meta-analysis results, and [module 10] to learn how to test for publication bias.
Last updated: 2019, January 29 Author: Amy Briggs
References
- Higgins et al. 2003. Measuring inconsistency in meta-analyses. BMJ. 327. 557-560.
Koricheva, Julia, Jessica Gurevitch, and Kerrie Mengersen. 2013. Handbook of Meta-Analysis in Ecology and Evolution. Princeton University Press. https://muse.jhu.edu/book/41629.
LS0tCnRpdGxlOiAiRXhwbG9yaW5nIGhldGVyb2dlbmVpdHkiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdApoZWFkZXItaW5jbHVkZXM6IHwKICBcdXNlcGFja2FnZXtmYW5jeWhkcn0KICBccGFnZXN0eWxle2ZhbmN5fQpiaWJsaW9ncmFwaHk6IG1ldGEtYW5hbHlzaXMgdHV0b3JpYWwuYmliCi0tLQoKYGBge3IsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0V9CiMgbG9hZCBsaWJyYXJpZXMgYW5kIGRvIHN0dWZmIGZvciBkb2N1bWVudCBjcmVhdGlvbgpsaWJyYXJ5KFJlZk1hbmFnZVIpICMgcmVmZXJlbmNlIG1hbmFnZXIKbGlicmFyeShnZ3Bsb3QyKSAjIGdyYXBoaW5nCmBgYAoKIyMgSW50cm9kdWN0aW9uIHRvIGhldGVyb2dlbmVpdHkKCk9uZSBtYWpvciBnb2FsIG9mIG1ldGEtYW5hbHlzaXMgaXMgdG8gcXVhbnRpdGF0aXZlbHkgc3VtbWFyaXplIHRoZSBlZmZlY3Qgc2l6ZXMgb2JzZXJ2ZWQgaW4gbXVsdGlwbGUgc3R1ZGllcyBvbiB0aGUgc2FtZSB0b3BpYy4gIEEgc2Vjb25kIG1ham9yIGdvYWwgaXMgdG8gZXhwbG9yZSB3aGV0aGVyIHRoZXNlIGVmZmVjdCBzaXplcyAoYW5kIHRoZSB0cnVlIGVmZmVjdCBzaXplcyB0aGF0IHRoZXkgZXN0aW1hdGUgd2l0aCBzb21lIGVycm9yKSBhcmUgY29uc2lzdGVudCBhY3Jvc3Mgc3R1ZGllcywgYW5kIGlmIG5vdCwgdG8gZGV0ZXJtaW5lIHdoYXQgZmFjdG9ycyBsZWFkIHRvIHZhcmlhdGlvbiBpbiB0aGUgbWFnbml0dWRlcyBvZiB0aGUgKnRydWUqIGVmZmVjdHMuICBJbiBtZXRhLWFuYWx5c2lzLCB0aGlzIHZhcmlhdGlvbiBpbiB0aGUgdHJ1ZSBlZmZlY3Qgc2l6ZXMgaXMga25vd24gYXMgKipoZXRlcm9nZW5laXR5KiouICBGb3IgZXhhbXBsZSwgaXQgbWF5IGJlIGludGVyZXN0aW5nIHRvIGRldGVybWluZSBpZiB0aGUgc3RyZW5ndGggb2YgYW4gZWZmZWN0LCBzdWNoIGFzIHRoZSBtYWduaXR1ZGUgb2YgYSB0cm9waGljIGNhc2NhZGUsIGlzIHNpbWlsYXIgYWNyb3NzIHN0dWRpZXMgY29uZHVjdGVkIGluIGRpZmZlcmVudCBlY29zeXN0ZW0gdHlwZXMsIG9yIGluIHN0dWRpZXMgd2l0aCBkaWZmZXJlbnQgZXhwZXJpbWVudGFsIGR1cmF0aW9ucy4gICoqVG8gZGV0ZXJtaW5lIHdoZXRoZXIgdmFyaWF0aW9uIGluIHRoZSBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgaXMgaW5kaWNhdGl2ZSBvZiByZWFsIGRpZmZlcmVuY2VzIGluIHRoZSAqdHJ1ZSogZWZmZWN0IHNpemVzLCBhbmQgdG8gZGV0ZXJtaW5lIGlmIHRoZXJlIGFyZSBtb2RlcmF0aW5nIHZhcmlhYmxlcyB0aGF0IGV4cGxhaW4gdGhlIHZhcmlhdGlvbiBpbiB0cnVlIGVmZmVjdCBzaXplcywgbWV0YS1hbmFseXN0cyBjYW4gY29uZHVjdCBmb3JtYWwgdGVzdHMgb2YgaGV0ZXJvZ2VuZWl0eSoqLiAKCkZhY3RvcnMgdGhhdCBjYW4gY29udHJpYnV0ZSB0byBoZXRlcm9nZW5laXR5IGluICh0cnVlKSBlZmZlY3Qgc2l6ZXM6CgoqIGhldGVyb2dlbmVpdHkgYW1vbmcgc3R1ZGllcyAKKiBoZXRlcm9nZW5laXR5IGFtb25nIGdyb3VwcyAoZS5nLiwgc3R1ZGllcyBjb25kdWN0ZWQgaW4gZGlmZmVyZW50IGVjb3N5c3RlbSB0eXBlcykKKiBjb3ZhcmlhdGVzIChlLmcuLCB0cmVhdG1lbnQgZG9zZSwgZXhwZXJpbWVudGFsIGR1cmF0aW9uLCBvciBzb21lIG90aGVyIGNvbnRpbnVvdXMgcHJlZGljdG9yIHZhcmlhYmxlKQoKVGhlIGJhc2ljIGNvbmNlcHQgYmVoaW5kIGhldGVyb2dlbmVpdHkgdGVzdHMgaXMgdGhhdCB0aGUgZWZmZWN0IHNpemVzIG9ic2VydmVkIGluIHByaW1hcnkgc3R1ZGllcyBhcmUgZXN0aW1hdGVzIG9mIHRydWUgZWZmZWN0cywgYW5kIHRoZXNlIGVzdGltYXRlcyBhcmUgbWVhc3VyZWQgd2l0aCBzb21lIGVycm9yLiAgVGhlcmVmb3JlLCB3aGVuIHdlIGNvbmR1Y3QgaGV0ZXJvZ2VuZWl0eSB0ZXN0cyB3ZSBoYXZlIHRvIHRyeSB0byBzZXBhcmF0ZSB0aGUgdmFyaWF0aW9uIGluIGVmZmVjdCBzaXplcyBkdWUgdG8gbWVhc3VyZW1lbnQgZXJyb3IgZnJvbSB0aGUgdmFyaWF0aW9uIGR1ZSB0byByZWFsIGRpZmZlcmVuY2VzIGluIHRoZSB0cnVlIGVmZmVjdHMuCgombmJzcDsKCiMjIEV2YWx1YXRpbmcgaGV0ZXJvZ2VuZWl0eTogJFEkCgpPbmUgY29tbW9uIHdheSBvZiBldmFsdWF0aW5nIGhldGVyb2dlbmVpdHkgaW4gY2xhc3NpYyBtZXRhLWFuYWx5c2lzIGlzIGJhc2VkIG9uIHRoZSAkUSQgc3RhdGlzdGljIChhbHNvIGtub3duIGFzIENvY2hyYW4ncyAkUSQpLiBUaGUgJFEkIHN0YXRpc3RpYyBwYXJ0aXRpb25zIHRoZSB0b3RhbCB2YXJpYXRpb24gb2YgdGhlIG9ic2VydmVkIGVmZmVjdCBzaXplcyAoJFFfe3RvdGFsfSQpIGludG8gdHdvIGNvbXBvbmVudHM6ICRRX3ttb2RlbH0kIGFuZCAkUV97ZXJyb3J9JCwgZS5nLjoKJCRRX3t0b3RhbH0gPSBRX3ttb2RlbH0gKyBRX3tlcnJvcn0kJAoKJFFfe21vZGVsfSQgaXMgdGhlIGFtb3VudCBvZiBoZXRlcm9nZW5laXR5IHRoYXQgaXMgZXhwbGFpbmVkIGJ5IHRoZSBtZXRhLWFuYWx5c2lzIG1vZGVsLCBhbmQgaXMgYXNzdW1lZCB0byBiZSBkdWUgdG8gcmVhbCB2YXJpYXRpb24gaW4gdGhlIHRydWUgZWZmZWN0IHNpemVzIGFtb25nIHN0dWRpZXMsIGdyb3VwcywgYW5kL29yIHdoYXRldmVyIG1vZGVyYXRpbmcgdmFyaWFibGVzIG9mIGludGVyZXN0IGFyZSBpbmNsdWRlZCBpbiB0aGUgbW9kZWwuICBJZiB0aGVyZSBpcyBvbmx5IG9uZSBmYWN0b3IgaW4gdGhlIG1vZGVsIChlLmcuLCBzdHVkeSksIHRoZW4gJFFfe21vZGVsfSQgd291bGQgaW5kaWNhdGUgdGhlIGFtb3VudCBvZiBoZXRlcm9nZW5laXR5IGluIHRoZSB0cnVlIGVmZmVjdCBzaXplcyBhbW9uZyBsZXZlbHMgb2YgdGhhdCBmYWN0b3IuIElmIHRoZXJlIGFyZSBtdWx0aXBsZSB2YXJpYWJsZXMgaW4gdGhlIG1vZGVsLCB0aGVuICRRX3ttb2RlbH0kIGlzIGEgY3VtdWxhdGl2ZSB0ZXJtLiAgJFFfe2Vycm9yfSQgaXMgZHVlIHRvIHJhbmRvbSwgdW5leHBsYWluZWQgdmFyaWF0aW9uIChlLmcuLCBtZWFzdXJlbWVudCBlcnJvcikuICAKCkZvciBhIHNpbXBsZSAqZml4ZWQqIGVmZmVjdCBtb2RlbCwgdG90YWwgaGV0ZXJvZ2VuZWl0eSAkUV97dG90YWx9JCBpcyBjYWxjdWxhdGVkIHVzaW5nIHRoZSBlcXVhdGlvbjoKJCRRX3t0b3RhbH0gPSBcc3VtX3soaT0xKX1eayB3X2kgKGVfaSAtIFxiYXJ7RX0pXjIkJApXaGVyZToKCiogJFxiYXJ7RX0kIGlzIHRoZSBvdmVyYWxsIG1lYW4gZWZmZWN0IHNpemUgCiogJGVfaSQgaXMgdGhlIGVmZmVjdCBzaXplIG9mIHRoZSAkaXRoJCBzdHVkeQoqICR3X2kkIGlzIHRoZSB3ZWlnaHQgZm9yIHRoZSAkaXRoJCBzdHVkeQoqICRrJCBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIHN0dWRpZXMgaW4gdGhlIG1ldGEtYW5hbHlzaXMgCiogYW5kIHRoZSBkZWdyZWVzIG9mIGZyZWVkb20gKCRkZiQpIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRlcm0gYXJlICRrLTEkCgoqSW4gYSByYW5kb20gZWZmZWN0cyBtb2RlbCB0aGUgZm9ybXVsYSBmb3IgJFFfe3RvdGFsfSQgd291bGQgYmUgdGhlIHNhbWUsIGV4Y2VwdCB0aGUgd2VpZ2h0cyB3b3VsZCBiZSB0aGUgcmFuZG9tIGVmZmVjdHMgdmVyc2lvbiB0aGF0IGluY29ycG9yYXRlIGJvdGggd2l0aGluLSBhbmQgYW1vbmctc3R1ZHkgdmFyaWFuY2UuKgoKKk5vdGUgdGhhdCAkUSQgcmVxdWlyZXMgZXN0aW1hdGVzIG9mIHdpdGhpbi1zdHVkeSB2YXJpYW5jZSB0byBiZSBhYmxlIHRvIHBhcnNlIG91dCAidHJ1ZSIgdmFyaWF0aW9uIGluIHRoZSBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgZnJvbSB2YXJpYXRpb24gZHVlIHRvIHNhbXBsaW5nIGVycm9yLiAgVGhlcmVmb3JlLCBwYXJhbWV0cmljIChpLmUuLCB2YXJpYW5jZS1iYXNlZCkgd2VpZ2h0cyBhcmUgcmVxdWlyZWQgZm9yIGl0cyBjYWxjdWxhdGlvbi4gIE90aGVyIG1ldGhvZHMgbXVzdCBiZSB1c2VkIHRvIGV2YWx1YXRlIGhldGVyb2dlbmVpdHkgaW4gbW9kZWxzIGluY29ycG9yYXRpbmcgbm9uLXBhcmFtZXRyaWMgd2VpZ2h0cywgc3VjaCBhcyBtb2RlbCBjb21wYXJpc29uIChlLmcuLCBjb21wYXJpbmcgYSBtb2RlbCBpbmNsdWRpbmcgc3R1ZHkgSUQgYXMgYSBwcmVkaWN0b3IgdmFyaWFibGUgd2l0aCBhIG1vZGVsIHRoYXQgZG9lcyBub3QgaW5jbHVkZSBzdHVkeSBJRCkuICBTZWUgW3RoaXMgcGFnZSBmcm9tIHRoZSBgbWV0YWZvcmAgd2Vic2l0ZV0oaHR0cDovL3d3dy5tZXRhZm9yLXByb2plY3Qub3JnL2Rva3UucGhwL3RpcHM6bXVsdGlwbGVfZmFjdG9yc19pbnRlcmFjdGlvbnMpIGZvciBzb21lIGV4YW1wbGVzLgoKJm5ic3A7CgojIyMgSGV0ZXJvZ2VuZWl0eSBhbW9uZyBzdHVkaWVzCgpHZW5lcmFsbHksIHVubGVzcyBhbGwgdGhlIHByaW1hcnkgc3R1ZGllcyBpbiB5b3VyIG1ldGEtYW5hbHlzaXMgYXJlIGNvbmR1Y3RlZCB1bmRlciBhIHZlcnkgbmFycm93IHNldCBvZiBjb25kaXRpb25zIGFuZCBwcm9jZWR1cmVzLCBpdCBpcyByZWFzb25hYmxlIHRvIGV4cGVjdCBzb21lIGRlZ3JlZSBvZiB2YXJpYXRpb24gaW4gdGhlIG9ic2VydmVkIGVmZmVjdCBzaXplcyBhbW9uZyBzdHVkaWVzLCBzdWNoIGFzIGluICBGaWcuMToKCjxjZW50ZXI+CgohW0ZpZy4gMSkgRXhhbXBsZSBvZiBwb3RlbnRpYWwgaGV0ZXJvZ2VuZWl0eSBhbW9uZyBzdHVkaWVzIGluIGEgbWV0YS1hbmFseXNpcy4gIEJsdWUgY2lyY2xlcyByZXByZXNlbnQgdGhlIG9ic2VydmVkIGVmZmVjdCBzaXplcywgd2l0aCBiYXJzIHJlcHJlc2VudGluZyB0aGVpciA5NSUgQ0kuXSgvVXNlcnMvYW15LmJyaWdncy9Ecm9wYm94LzFfVUdBL1JBIHdvcmsvbWV0YS1hbmFseXNpcy9vbmxpbmUgY291cnNlIGRldmVsb3BtZW50L01BX29ubGluZSBjb3Vyc2UgZGV2ZWxvcG1lbnQvZmlndXJlcy9oZXRlcm9nZW5laXR5X3N0dWR5X3NtYWxsLnBuZykKCjwvY2VudGVyPgoKQSBoZXRlcm9nZW5laXR5IHRlc3QgaXMgYSB3YXkgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdGhlc2UgZGlmZmVyZW5jZXMgaW4gdGhlIG9ic2VydmVkIGVmZmVjdCBzaXplcyBhcmUgY2F1c2VkIGJ5IGRpZmZlcmVuY2VzIGluIHRoZSB0cnVlIGVmZmVjdCBzaXplcyBhbW9uZyBzdHVkaWVzIGluIHRoZSBtZXRhLWFuYWx5c2lzLCBvciBpZiB0aGV5IGFyZSBpbnN0ZWFkIGR1ZSB0byBzYW1wbGluZyBlcnJvciB3aXRoaW4gaW5kaXZpZHVhbCBzdHVkaWVzLiAgSWYgdGhlcmUgYXJlIG5vIGdyb3VwcyBvciBleHBsYW5hdG9yeSB2YXJpYWJsZXMgaW4geW91ciBtb2RlbCwgKGUuZy4sIHdoZW4geW91IGFyZSBqdXN0IGV4cGxvcmluZyBoZXRlcm9nZW5laXR5IGFtb25nIHRoZSBlZmZlY3Qgc2l6ZXMsIHdoaWNoIHlvdSBhc3N1bWUgdW5kZXIgdGhlIG51bGwgaHlwb3RoZXNpcyBhbGwgY29tZSBmcm9tIHRoZSBzYW1lIHBvcHVsYXRpb24pLCB0aGVuICRRX3ttb2RlbH0gPSAwJCwgYmVjYXVzZSB5b3UgYXNzdW1lIHRoZSB0cnVlIGVmZmVjdCBpcyB0aGUgc2FtZSBhY3Jvc3MgYWxsIHN0dWRpZXMuICBXaGVuICRRX3ttb2RlbH0gPSAwJCwgdGhlbiBhbGwgaGV0ZXJvZ2VuZWl0eSBpbiAkUV97dG90YWx9JCBjb21lcyBmcm9tICRRX3tlcnJvcn0kLiAgCgpUbyBkZXRlcm1pbmUgaWYgdGhlIGFtb3VudCBvZiB2YXJpYXRpb24gaW4gdGhlIG9ic2VydmVkIGVmZmVjdCBzaXplcyBpcyBsaWtlbHkgZ2l2ZW4gdGhlIGFzc3VtcHRpb24gdGhhdCB0aGV5IGFsbCBjb21lIGZyb20gdGhlIHNhbWUgcG9wdWxhdGlvbiwgeW91IGNhbiBjb21wYXJlIHRoZSAkUV97dG90YWx9JCB0byBhICRcY2hpXjIkIGRpc3RyaWJ1dGlvbi4gIElmICRRX3t0b3RhbH0kIGlzIGxhcmdlciB0aGFuIHByZWRpY3RlZCBmb3IgYSBnaXZlbiAkXGFscGhhJCwgKGkuZS4gaWYgeW91ciBwLXZhbHVlIGlzIDwgLjA1KSwgdGhlbiB0aGlzIGluZGljYXRlcyB0aGF0IHlvdSBoYXZlIG1vcmUgdW5leHBsYWluZWQgdmFyaWF0aW9uIHRoYW4gd291bGQgYmUgZXhwZWN0ZWQgYnkgY2hhbmNlIGlmICRRX3ttb2RlbH0gPSAwJC4kXnsqKn0kICBJbiB0aGlzIGNhc2UsIHlvdSBjYW4gaW5mZXIgdGhhdCB0aGUgdHJ1ZSBlZmZlY3Qgc2l6ZXMgZGlmZmVyIGFtb25nIHlvdXIgc3R1ZGllcywgYW5kIHRodXMgdXNpbmcgYSBmaXhlZCBlZmZlY3QgbW9kZWwgaXMgKm5vdCogYXBwcm9wcmlhdGUgZm9yIHRoZSBkYXRhLiBJbnN0ZWFkLCB5b3Ugc2hvdWxkIHVzZSBhIHJhbmRvbSBlZmZlY3RzIG1vZGVsLgoKSG93ZXZlciwgYXMgbWVudGlvbmVkIGluIHRoZSBwcmV2aW91cyBzZWN0aW9uIG9uIFsqU3RhdGlzdGljYWwgbW9kZWxzKl0oaHR0cDovL21ldGFhbmFseXNpcy5lY29sb2d5LnVnYS5lZHUvNi1zdGF0aXN0aWNhbC1tb2RlbHMvKSwgaGV0ZXJvZ2VuZWl0eSB0ZXN0cyBiYXNlZCBvbiAkUSQgaGF2ZSBsb3cgcG93ZXIgd2hlbiB0aGVyZSBhcmUgZmV3IHN0dWRpZXMgaW4gdGhlIG1ldGEtYW5hbHlzaXMsIHNvIGEgbm9uLXNpZ25pZmljYW50IHAtdmFsdWUgZG9lcyBub3QgbmVjZXNzYXJpbHkgbWVhbiB0aGF0IHRoZSB0cnVlIGVmZmVjdCBzaXplcyBhcmUgdGhlIHNhbWUgYWNyb3NzIHN0dWRpZXM7IHRoZSB0ZXN0IGNvdWxkIHNpbXBseSBub3QgaGF2ZSBlbm91Z2ggcG93ZXIgdG8gZGV0ZWN0IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzLiAgU2ltaWxhcmx5LCAkUSQgdGVzdHMgY2FuIGFsc28gaGF2ZSB0b28gbXVjaCBwb3dlciBpZiB0aGVyZSBhcmUgbWFueSBzdHVkaWVzIGluIHRoZSBtZXRhLWFuYWx5c2lzLCBlc3BlY2lhbGx5IGlmIHNvbWUgYXJlIHZlcnkgbGFyZ2UgKG1lYW5pbmcgdGhlIHRlc3QgZmluZHMgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgd2hlbiB0aGUgdHJ1ZSBlZmZlY3Qgc2l6ZXMgYXJlIGFjdHVhbGx5IGhvbW9nZW5lb3VzKSAoKkhpZ2dpbnMgZXQgYWwuIDIwMDMqKS4KCiZuYnNwOwoKIyMjIEhldGVyb2dlbmVpdHkgYW1vbmcgZ3JvdXBzCgpJbiBhZGRpdGlvbiB0byB0ZXN0aW5nIGZvciBhbW9uZy1zdHVkeSBkaWZmZXJlbmNlcyBpbiBlZmZlY3Qgc2l6ZXMsIHNvbWV0aW1lcyB0aGVyZSBhcmUgZ3JvdXBzIHdpdGhpbiB0aGUgZGF0YSB0aGF0IGNvdWxkIGh5cG90aGV0aWNhbGx5IGV4cGxhaW4gc29tZSBvZiB0aGUgdmFyaWF0aW9uIGluIGVmZmVjdCBzaXplcyBvYnNlcnZlZCBhY3Jvc3Mgc3R1ZGllcy4gIEZvciBleGFtcGxlLCBpbiBhIG1ldGEtYW5hbHlzaXMgb24gdGhlIGVmZmVjdHMgb2YgbWF0ZXJuYWwgdGVtcGVyYXR1cmUgZW52aXJvbm1lbnQgb24gdGhlIHJlc3BvbnNlIG9mIG9mZnNwcmluZyB0byBlbGV2YXRlZCB0ZW1wZXJhdHVyZSwgdGhlcmUgY291bGQgYmUgZGlmZmVyZW5jZXMgaW4gdGhlIGVmZmVjdCBzaXplcyBvZiBlY3RvdGhlcm1zIHZzLiBlbmRvdGhlcm1zLgoKPGNlbnRlcj4KCiFbRmlnLiAyKSBFeGFtcGxlIG9mIHBvdGVudGlhbCBoZXRlcm9nZW5laXR5IGFtb25nIGdyb3VwcyBpbiBhIG1ldGEtYW5hbHlzaXMuICBCbHVlIGNpcmNsZXMgcmVwcmVzZW50IHRoZSBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMsIHdpdGggYmFycyByZXByZXNlbnRpbmcgdGhlaXIgZXJyb3IuIFN0dWRpZXMgMS0zIHdlcmUgY29uZHVjdGVkIG9uIGVjdG90aGVybXMsIHdoaWxlIHN0dWRpZXMgNC01IHdlcmUgY29uZHVjdGVkIG9uIGVuZG90aGVybXMuIF0oL1VzZXJzL2FteS5icmlnZ3MvRHJvcGJveC8xX1VHQS9SQSB3b3JrL21ldGEtYW5hbHlzaXMvb25saW5lIGNvdXJzZSBkZXZlbG9wbWVudC9NQV9vbmxpbmUgY291cnNlIGRldmVsb3BtZW50L2ZpZ3VyZXMvaGV0ZXJvZ2VuZWl0eV9ncm91cF9zbWFsbC5wbmcpCgo8L2NlbnRlcj4KCllvdSBjYW4gc2VlIGluIEZpZy4gMiB0aGF0IHRoZSBlZmZlY3Qgc2l6ZXMgZm9yIHRoZSBzdHVkaWVzIHBlcmZvcm1lZCBvbiBlY3RvdGhlcm1zIGNsdXN0ZXIgYWJvdmUgemVybywgd2hpbGUgdGhlIGVmZmVjdCBzaXplcyBmb3IgdGhlIHN0dWRpZXMgb24gZW5kb3RoZXJtcyBjbHVzdGVyIGJlbG93IHplcm8uICBUaGlzIHBhdHRlcm4gaW5kaWNhdGVzIHRoYXQgdGhlIGdyb3VwcyBlY3RvdGhlcm0gdnMuIGVuZG90aGVybSBtaWdodCBkcml2ZSBzaWduaWZpY2FudCBoZXRlcm9nZW5laXR5IGluIHRoZSBlZmZlY3Qgc2l6ZXMuICBUbyB0ZXN0IHRoaXMsIHlvdSBjb3VsZCB1c2UgdGhlcm1vLXJlZ3VsYXRvcnkgdHlwZSBhcyBhIG1vZGVyYXRpbmcgdmFyaWFibGUgaW4gdGhlIG1ldGEtYW5hbHlzaXMgbW9kZWwuIFRoZW4sIHlvdSBjb3VsZCBlc3RpbWF0ZSB0aGUgYW1vdW50IG9mIHZhcmlhdGlvbiBleHBsYWluZWQgYnkgdGhlcm1vLXJlZ3VsYXRvcnkgdHlwZSB1c2luZyAkUV97bW9kZWx9JCwgaS5lLiwgdGhlIGFtb3VudCBvZiBhbW9uZy1ncm91cCB2YXJpYXRpb24sIHdpdGggJFFfe2Vycm9yfSQgcmVwcmVzZW50aW5nIGxlZnRvdmVyIHVuZXhwbGFpbmVkIHZhcmlhdGlvbi4gIEFub3RoZXIgd2F5IHRvIHRoaW5rIGFib3V0IHRoaXMgaXMgdG8gcmV3cml0ZSAkUV97bW9kZWx9JCBhcyAkUV97Z3JvdXBzfSQuCgokJFFfe3RvdGFsfSA9IFFfe2dyb3Vwc30gKyBRX3tlcnJvcn0kJAoKVGh1cywgJFEkIG9wZXJhdGVzIHNpbWlsYXJseSB0byBBTk9WQSwgd2hlcmUgdmFyaWF0aW9uIGluIHRoZSBmb3JtIG9mIHN1bXMgb2Ygc3F1YXJlcyAoU1MpIGFyZSBwYXJ0aXRpb25lZCBhY3Jvc3MgZ3JvdXBzIChpLmUuIHRyZWF0bWVudCBsZXZlbHMpIGFuZCBlcnJvciB0ZXJtcywgZS5nLiAkU1Nfe3RvdGFsfSA9ICBTU197Z3JvdXBzfSArIFNTX3tlcnJvcn0kLiAgVGhlc2UgU1MgdGVybXMgYXJlIHRoZW4gY29tcGFyZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIGdyb3VwcyBpcyBncmVhdGVyIHRoYW4gdGhlIHVuZXhwbGFpbmVkIGVycm9yIHZhcmlhbmNlICh0aGlzIGlzIGFsc28ga25vd24gYXMgcmVzaWR1YWwgdmFyaWFuY2UpLiAkUSQgaXMgc2ltcGx5IGEgd2VpZ2h0ZWQgU1MsIGFuZCB0aHVzLCBhcyBpbiBBTk9WQSwgeW91IGFyZSB0ZXN0aW5nIHdoZXRoZXIgaGV0ZXJvZ2VuZWl0eSBpcyBncmVhdGVyIGFtb25nIHRoZSBncm91cHMgdGhhbiBpdCBpcyB3aXRoaW4gdGhlbS4gIEluIEFOT1ZBIHRoaXMgd291bGQgYmUgZG9uZSB1c2luZyB0aGUgRi1yYXRpbywgKHdoaWNoIGVxdWFscyB0aGUgdmFyaWF0aW9uIGFtb25nIC8gdmFyaWF0aW9uIHdpdGhpbiksIHdoaWNoIHlvdSB0aGVuIGNvbXBhcmUgdG8gYSBub3JtYWwgZGlzdHJpYnV0aW9uIHRvIGRldGVybWluZSB0aGUgcC12YWx1ZS4gSW4gbWV0YS1hbmFseXNpcywgdGhpcyBpcyBkb25lIGJ5IGNvbXBhcmluZyAkUV97Z3JvdXBzfSQgdG8gYSAkXGNoaV4yJCBkaXN0cmlidXRpb24uICAKClRodXMsIGFub3RoZXIgd2F5IHRvIHRoaW5rIGFib3V0IHRoaXMgZm9yIGdyb3VwcyBpczoKJCRRX3t0b3RhbH0gPSBRX3thbW9uZ30gKyBRX3t3aXRoaW59JCQKClRvIGNhbGN1bGF0ZSAqKiRRX3tncm91cHN9JDoqKiBmb3IgYSAqZml4ZWQqIGVmZmVjdCBtb2RlbDoKJCRRX3tncm91cHN9ID0gXHN1bV97KGo9MSl9XnttfVxzdW1feyhpPTEpfV57bl9qfSB3X3tpan0gKFxiYXJ7RV9qfSAtIFxiYXJ7RX0pXjIkJApXaGVyZToKCiogJFxiYXJ7RX0kIGlzIHRoZSBvdmVyYWxsIG1lYW4gZWZmZWN0IHNpemUgKHNwZWNpZmljYWxseSBpdHMgZXN0aW1hdGUgYmFzZWQgb24gb2JzZXJ2ZWQgZWZmZWN0IHNpemVzKQoqICRcYmFye0V9X2okIGlzIHRoZSBtZWFuIGVmZmVjdCBpbiBncm91cCAkaiQgKGJhc2VkIG9uIGF2ZXJhZ2luZyAkZV97aWp9JCdzKQoqICR3X3tpan0kIGlzIHRoZSB3ZWlnaHQgZm9yIHRoZSAkaXRoJCBzdHVkeSBpbiBncm91cCAkaiQKKiAkbSQgaXMgdGhlIG51bWJlciBvZiBncm91cHMKKiAkbl9qJCBpcyB0aGUgbnVtYmVyIG9mIHN0dWRpZXMgaW4gZ3JvdXAgJGokCiogVG90YWwgbnVtYmVyIG9mIHN0dWRpZXMgaXM6ICRrID0gXHN1bV97aj0xfV57bX1uX2okIAoqICRkZiA9IG0gLSAxJCBmb3IgdGhpcyB0ZXJtCgpJZiAkUV97Z3JvdXBzfSQgaXMgbm90IHNpZ25pZmljYW50LCBpdCBpbmRpY2F0ZXMgdGhhdCB0aGlzIG1vZGVyYXRpbmcgdmFyaWFibGUgZG9lcyBub3QgZXhwbGFpbiBhbnkgaGV0ZXJvZ2VuZWl0eSBpbiBlZmZlY3Qgc2l6ZXMgaW4gdGhlIG1ldGEtYW5hbHlzaXMgbW9kZWwuICBUaGlzIHJlc3VsdCBjYW4gYmUgY29tcGFyZWQgd2l0aCAkUV97ZXJyb3J9JC4gIElmICRRX3tlcnJvcn0kIGhhcyBhIHNpZ25pZmljYW50IHAtdmFsdWUsIHRoZW4gdGhlIGVmZmVjdC1zaXplcyBzdGlsbCBoYXZlIHNvbWUgc2lnbmlmaWNhbnQgdW5leHBsYWluZWQgaGV0ZXJvZ2VuZWl0eSAoYW5kIHRoZXJlZm9yZSB0aGUgbWV0YS1hbmFseXN0IG1pZ2h0IHdhbnQgdG8gaW52ZXN0aWdhdGUgc29tZSBvdGhlciBtb2RlcmF0aW5nIHZhcmlhYmxlcykuCgoKJFFfe2Vycm9yfSQsIGkuZS4gdGhlICoqcmVzaWR1YWwgaGV0ZXJvZ2VuZWl0eSwqKiBpcyBjYWxjdWxhdGVkIHRoaXMgd2F5OgokJFFfe2Vycm9yfSA9IFxzdW1feyhqPTEpfV57bX1cc3VtX3soaT0xKX1ee25fan0gd197aWp9IChlX2ogLSBcYmFye0Vfan0pXjIkJAoKKiAkZGYgPSBrIC0gbSQgZm9yIHRoaXMgdGVybSAoaS5lLiwgdGhlIHRvdGFsIG51bWJlciBvZiBzdHVkaWVzIG1pbnVzIHRoZSBudW1iZXIgb2YgZ3JvdXBzKQoKJm5ic3A7CgpUaGlzIGFwcHJvYWNoIG9mIHVzaW5nICRRX3tncm91cHN9JCB0byBldmFsdWF0ZSB0aGUgYWJpbGl0eSBvZiBjYXRlZ29yaWNhbCBtb2RlcmF0aW5nIHZhcmlhYmxlcyB0byBleHBsYWluIGhldGVyb2dlbmVpdHkgaW4gdGhlIGVmZmVjdCBzaXplcyBjYW4gYmUgZXhwYW5kZWQgdG8gbW9kZWxzIHdpdGggbXVsdGlwbGUgbW9kZXJhdG9ycywgb3IgaGllcmFyY2hpY2FsIG1vZGVscywgd2hlcmUgeW91IGhhdmUgb25lIHNldCBvZiBncm91cHMgbmVzdGVkIHdpdGhpbiBhbm90aGVyIChlLmcuIHNpdGVzIG5lc3RlZCBpbiByZWdpb25zKS4gIEl0IGNhbiBhbHNvIGJlIGV4dGVuZGVkIHRvIHJhbmRvbSBlZmZlY3RzIG1vZGVscy4gSG93ZXZlciwgYWx0aG91Z2ggdGhlIGh5cG90aGVzaXMgdGVzdGluZyBhbmQgaW50ZXJwcmV0YXRpb24gb2YgdGhlIGRpZmZlcmVudCAkUSQncyBpcyBzdGlsbCB0aGUgc2FtZSwgdGhlIGNhbGN1bGF0aW9uIG9mIGVhY2ggJFEkIGJlY29tZXMgc2xpZ2hseSBtb3JlIGNvbXBsZXggZm9yIHRoZXNlIG1vcmUgY29tcGxpY2F0ZWQgbW9kZWxzLiAgW1NlZSBAa29yaWNoZXZhX2hhbmRib29rXzIwMTMgZm9yIG1vcmUgZGV0YWlsc10uCgombmJzcDsKCiMjIyBFdmFsdWF0aW5nIGhldGVyb2dlbmVpdHkgZHVlIHRvIGNvbnRpbnVvdXMgY292YXJpYXRlcyAKCiRRJCBjYW4gYWxzbyBiZSBhcHBsaWVkIHRvIG1vZGVscyB3aXRoICpjb250aW51b3VzIHZhcmlhYmxlcyAoaS5lLiwgY292YXJpYXRlcykqLCB3aGljaCBtYXkgZHJpdmUgdmFyaWF0aW9uIGluIHRoZSBlZmZlY3RzIHNpemVzIG9ic2VydmVkIGFjcm9zcyBzdHVkaWVzLiAgVGhpcyBpcyBhbmFsb2dvdXMgdG8gYSB3ZWlnaHRlZCByZWdyZXNzaW9uIGFuYWx5c2lzLCBhbmQgaXMga25vd24gaW4gbWV0YS1hbmFseXNpcyBhcyBhICoqbWV0YS1yZWdyZXNzaW9uKiouIEZvciBleGFtcGxlLCBpZiBleHBlcmltZW50YWwgZHVyYXRpb24gd2FzIHJlbGF0ZWQgdG8gdGhlIGVmZmVjdCBzaXplIG9ic2VydmVkIGluIGRpZmZlcmVudCBzdHVkaWVzOgoKPGNlbnRlcj4KCmBgYHtyIGZpZywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLndpZHRoPTUsZmlnLmhlaWdodD00LCBmaWcuY2FwPSJBIG1ldGEtcmVncmVzc2lvbiBzaG93aW5nIHRoZSBlZmZlY3Qgb2YgZXhwZXJpbWVudGFsIGR1cmF0aW9uICh4KSBvbiB0aGUgbG9nLXJpc2sgcmF0aW8gKHkpLiAgUG9pbnRzIHJlcHJlc2VudCBlZmZlY3Qgc2l6ZXMgb2JzZXJ2ZWQgaW4gcHJpbWFyeSBzdHVkaWVzLiAgVGhlIHNpemUgb2YgZWFjaCBwb2ludCBpbmRpY2F0ZXMgdGhlIHJlbGF0aXZlIHdlaWdodCBvZiB0aGF0IGVmZmVjdCBzaXplIChsYXJnZXIgPSBoaWdoZXIgd2VpZ2h0KS4ifQpsaWJyYXJ5KG1ldGFmb3IpCmxpYnJhcnkoTWF0cml4KQoKIyMjIGNhbGN1bGF0ZSAobG9nKSByaXNrIHJhdGlvcyBhbmQgY29ycmVzcG9uZGluZyBzYW1wbGluZyB2YXJpYW5jZXMKZGF0IDwtIGVzY2FsYyhtZWFzdXJlPSJSUiIsIGFpPXRwb3MsIGJpPXRuZWcsIGNpPWNwb3MsIGRpPWNuZWcsIGRhdGE9ZGF0LmJjZykKIAojIyMgZml0IG1peGVkLWVmZmVjdHMgbW9kZWwgd2l0aCBhYnNvbHV0ZSBsYXRpdHVkZSBhcyBwcmVkaWN0b3IKcmVzIDwtIHJtYSh5aSwgdmksIG1vZHMgPSB+IGFibGF0LCBkYXRhPWRhdCkKIAojIyMgY2FsY3VsYXRlIHByZWRpY3RlZCByaXNrIHJhdGlvcyBmb3IgMCB0byA2MCBkZWdyZWVzIGFic29sdXRlIGxhdGl0dWRlCnByZWRzIDwtIHByZWRpY3QocmVzLCBuZXdtb2RzPWMoMDo2MCksIHRyYW5zZj1leHApCiAKIyMjIGNhbGN1bGF0ZSBwb2ludCBzaXplcyBieSByZXNjYWxpbmcgdGhlIHN0YW5kYXJkIGVycm9ycwp3aSAgICA8LSAxL3NxcnQoZGF0JHZpKQpzaXplICA8LSAwLjUgKyAzLjAgKiAod2kgLSBtaW4od2kpKS8obWF4KHdpKSAtIG1pbih3aSkpCiAKIyMjIGFkanVzdCBtYXJnaW5zIHNvIHRoZSBzcGFjZSBpcyBiZXR0ZXIgdXNlZApwYXIobWFyPWMoNSw1LDEsMikpCgojIyMgcGxvdCB0aGUgcmlzayByYXRpb3MgYWdhaW5zdCBhYnNvbHV0ZSBsYXRpdHVkZQpwbG90KGRhdCRhYmxhdCwgZXhwKGRhdCR5aSksIHBjaD0xOSwgY2V4PXNpemUsIHhsaW09YygwLDYwKSwKICAgICB4bGFiPSJFeHBlcmltZW50YWwgZHVyYXRpb24gKGRheXMpIiwgeWxhYj0iRWZmZWN0IHNpemUgKGxvZyBSaXNrLXJhdGlvKSIsCiAgICAgbGFzPTEsIGJ0eT0ibCIsIGxvZz0ieSIpCiAKIyMjIGFkZCBwcmVkaWN0ZWQgdmFsdWVzIChhbmQgY29ycmVzcG9uZGluZyBDSSBib3VuZHMpCmxpbmVzKDA6NjAsIHByZWRzJHByZWQpCmxpbmVzKDA6NjAsIHByZWRzJGNpLmxiLCBsdHk9ImRhc2hlZCIpCmxpbmVzKDA6NjAsIHByZWRzJGNpLnViLCBsdHk9ImRhc2hlZCIpCiAKIyMjIGRvdHRlZCBsaW5lIGF0IFJSPTEgKG5vIGRpZmZlcmVuY2UgYmV0d2VlbiBncm91cHMpCmFibGluZShoPTEsIGx0eT0iZG90dGVkIikKYGBgCgo8L2NlbnRlcj4KCkZpZy4gMyBzaG93cyBhIG1ldGEtcmVncmVzc2lvbiB1c2luZyB0aGUgZWZmZWN0IG9mIGV4cGVyaW1lbnRhbCBkdXJhdGlvbiAoeCkgb24gdGhlIGxvZy1yaXNrIHJhdGlvICh5KS4gUG9pbnRzIHJlcHJlc2VudCBlZmZlY3Qgc2l6ZXMgb2JzZXJ2ZWQgaW4gcHJpbWFyeSBzdHVkaWVzLiBUaGUgc2l6ZSBvZiBlYWNoIHBvaW50IGluZGljYXRlcyB0aGUgcmVsYXRpdmUgd2VpZ2h0IG9mIHRoYXQgZWZmZWN0IHNpemUgKGxhcmdlciA9IGhpZ2hlciB3ZWlnaHQpLgoKJm5ic3A7CgpJbiB0aGlzIHR5cGUgb2YgbW9kZWwsIHRoZSBtZWFuIGVmZmVjdCBzaXplIG9mIGVhY2ggc3R1ZHkgJFxiYXJ7RV9pfSQgdmFyaWVzIGFzIHRoZSB2YWx1ZSBvZiBjb3ZhcmlhdGUgJFhfaSQgY2hhbmdlcywgd2l0aCBhIHNsb3BlICRcYmV0YV97MX0kICwgaS5lLjoKCiQkXGJhcntFX2l9ID0gXGJldGFfMCArIFxiZXRhXzFYX2kgKyBcdmFyZXBzaWxvbl9pJCQKSnVzdCBsaWtlIHRoZSBmb3JtdWxhdGlvbiBmb3IgYSByZWdyZXNzaW9uIG1vZGVsLCAkXGJldGFfMCQgaXMgdGhlIGludGVyY2VwdCBvZiB0aGUgbGluZSwgYW5kICRcdmFyZXBzaWxvbl9pJCByZXByZXNlbnRzIHJlc2lkdWFsIGVycm9yIGZvciBzdHVkeSAkaSQuCgombmJzcDsKClNpZ25pZmljYW5jZSBmb3IgdGhlIGRpZmZlcmVudCBjb21wb25lbnRzIG9mIGhldGVyb2dlbmVpdHkgYXJlIGRldGVybWluZWQgdGhlIHNhbWUgd2F5IGFzIHdpdGggdGhlIGNhdGVnb3JpY2FsIG1vZGVyYXRpbmcgdmFyaWFibGVzLCBieSBjb21wYXJpbmcgJFEkIHRvIGEgJFxjaGleMiQgZGlzdHJpYnV0aW9uIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgZGVncmVlcyBvZiBmcmVlZG9tICgkZGYkKS4gIFRoZSBmb3JtdWxhIGZvciAkUV97dG90YWx9JCBpcyB0aGUgc2FtZSBhcyBiZWZvcmUgKEVxbi4gKlgqKS4gIEhvd2V2ZXIsIHRoZSBjYWxjdWxhdGlvbnMgZm9yICRRX3ttb2RlbH0kIGFuZCAkUV97ZXJyb3J9JCBjaGFuZ2UuCgokUV97bW9kZWx9JCBjaGFuZ2VzIHRvIGV2YWx1YXRlIGhldGVyb2dlbmVpdHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBzbG9wZSAkXGJldGFfezF9JDoKJCRRX3ttb2RlbH0gPSBcZnJhY3tcYmV0YV4yX3sxfX17c14yX3tcYmV0YV97MX19fSQkIAoKCldoZXJlICRzXjJfe1xiZXRhX3sxfX0kIGlzIHRoZSBzdGFuZGFyZCBlcnJvciBvZiAkXGJldGFfezF9JCwgYW5kIHRoZSAkZGYgPSAxJC4gIFtTZWUgQGtvcmljaGV2YV9oYW5kYm9va18yMDEzIENoLiA5XSBmb3IgdGhlIGZvcm11bGEgZm9yICRzX3tcYmV0YV97MX19JC4gTWFueSBzdGF0aXN0aWNhbCBwYWNrYWdlcyBsaWtlIGBtZXRhZm9yYCB3aWxsIGNhbGN1bGF0ZSBpdCBmb3IgeW91LCBhbmQgcHJvdmlkZSB5b3Ugd2l0aCB0aGUgY29ycmVjdCAkUV97bW9kZWx9JCBvdXRwdXQuIAoKSWYgdGhlcmUgaXMgbm8gaGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgdGhlIGNvdmFyaWF0ZSwgdGhlbiAkXGJldGFfezF9JCBzaG91bGQgZXF1YWwgemVyby4gVG8gdGVzdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgJFxiZXRhX3sxfSA9IDAkLCBjYWxjdWxhdGUgJFFfe21vZGVsfSQgYW5kIGNvbXBhcmUgaXQgdG8gYSAkXGNoaV4yJCBkaXN0cmlidXRpb24gYXMgYmVmb3JlLiAgCgpBbHRlcm5hdGl2ZWx5LCBpZiB5b3Ugd2FudCB0byB0ZXN0IHdoZXRoZXIgJFxiZXRhX3sxfSQgb3IgJFxiZXRhX3swfSQgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gJDAkLCB0aGVuIHlvdSBjYW4gZGl2aWRlIHRoZWlyIGVzdGltYXRlIGJ5IHRoZWlyIHN0YW5kYXJkIGVycm9yICgkXGJldGFfe30gfi9+IHNfe1xiZXRhX3t9fSQpLCBhbmQgY29tcGFyZSB0byBhICpub3JtYWwqICgkeiQpIGRpc3RyaWJ1dGlvbi4gKFNvIHRoZXJlIGFyZSB0d28gd2F5cyB0byB0ZXN0IGlmICRcYmV0YV97MX0gPSAwJCwgd2hpY2ggeWllbGQgZXF1aXZhbGVudCByZXN1bHRzLikKCiZuYnNwOwoKJFFfe2Vycm9yfSQgaGFzIGEgdmVyeSBjb21wbGljYXRlZCBmb3JtdWxhLCBzbyBpdCBpcyBlYXNpZXN0IHRvIGNhbGN1bGF0ZSBpdCBhczogCiQkUV97ZXJyb3J9ID0gUV97dG90YWx9IC0gUV97bW9kZWx9JCQKV2l0aCAkZGYgPSBrLTIkLCBhbmQgJGskID0gdG90YWwgbnVtYmVyIG9mIHN0dWRpZXMKCiZuYnNwOwoKIyMjIEhldGVyb2dlbmVpdHkgdGVzdHMgaW4gYG1ldGFmb3JgCgpgbWV0YWZvcmAgd2lsbCBjYWxjdWxhdGUgJFEkIGFuZCBjb25kdWN0IHRoZSBhcHByb3ByaWF0ZSBzaWduaWZpY2FuY2UgdGVzdCBiYXNlZCBvbiAkZGYkIGZvciB5b3UuIAoKKldlIHdpbGwgZ28gb3ZlciBob3cgdG8gZG8gdGhpcyBpbiBjbGFzcy4qCgombmJzcDsKCiMjIyBTdW1tYXJ5IG9mICRRJCAKCiRRJCBwcm92aWRlcyBhIGZvcm1hbCB3YXkgdG8gdGVzdCBmb3IgaGV0ZXJvZ2VuZWl0eSBpbiBlZmZlY3Qgc2l6ZXMsIHdoZXRoZXIgZHVlIHRvIGRpZmZlcmVuY2VzIGFtb25nIHN0dWRpZXMsIG9yIGR1ZSB0byBvdGhlciBtb2RlcmF0aW5nIHZhcmlhYmxlcyAoY2F0ZWdvcmljYWwgb3IgY29udGludW91cykuICBJdCByZWxpZXMgb24gcGFyaXRpb25pbmcgdmFyaWFuY2UgY29tcG9uZW50cywgYW5kIHRodXMgaXQgcmVxdWlyZXMgcGFyYW1ldHJpYyAodmFyaWFuY2UtYmFzZWQpIHdlaWdodHMuICBBZGRpdGlvbmFsbHksICRRJCBpcyBvbiBhIHN0YW5kYXJpemVkIHNjYWxlLCBtZWFuaW5nIGl0IGlzIG5vdCBhZmZlY3RlZCBieSB0aGUgZWZmZWN0IHNpemUgbWV0cmljLiAgSG93ZXZlciwgdGhpcyBzY2FsZS1mcmVlIG5hdHVyZSBtZWFucyB0aGUgYW1vdW50IG9mIGhldGVyb2dlbmVpdHkgdGhhdCBpdCByZXByZXNlbnRzIGlzIGhhcmRlciB0byBpbnRlcnByZXQsIGFzIGl0IGlzIG5vdCBpbiB0aGUgc2FtZSB1bml0cyBhcyB0aGUgb3JpZ2luYWwgZGF0YS4gIEZ1cnRoZXJtb3JlLCAkUSQgaXMgYSBzdW0sIGFuZCB0aGVyZWZvcmUgaXQgY2Fubm90IGJlIGNvbXBhcmVkIGFjcm9zcyBtZXRhLWFuYWx5c2VzIGJlY2F1c2UgaXRzIHZhbHVlIGRlcGVuZHMgb24gdGhlIG51bWJlciBvZiBzdHVkaWVzIGluIHRoZSBtZXRhLWFuYWx5c2lzLiBGaW5hbGx5LCBhbHRob3VnaCAkUSQgYWxsb3dzIHRoZSBldmFsdWF0aW9uIG9mIHdoZXRoZXIgb3Igbm90IHRoZXJlIGlzIHNpZ25pZmljYW50IGFtb25nLXN0dWR5IHZhcmlhdGlvbiBpbiBlZmZlY3Qgc2l6ZXMsIGR1ZSB0byBmcmVxdWVudCBpc3N1ZXMgd2l0aCBwb3dlciBsZWFkaW5nIHRvIHRoZSB3cm9uZyBjb25jbHVzaW9uLCBpdCBpcyBub3QgcmVjb21tZW5kZWQgYXMgYSB0b29sIGZvciBkZWNpZGluZyB3aGV0aGVyIHRvIHVzZSBhIGZpeGVkIGVmZmVjdCBtb2RlbCBvciBhIHJhbmRvbSBlZmZlY3RzIG1vZGVsLiAgCgombmJzcDsKCiMjIE90aGVyIG1lYXN1cmVzIG9mIGhldGVyb2dlbmVpdHkgICAKCkluIGFkZGl0aW9uIHRvICRRJCwgb3RoZXIgbWV0cmljcyBoYXZlIGJlZW4gZGV2ZWxvcGVkIGZvciBxdWFudGlmeWluZyBoZXRlcm9nZW5laXR5IGluIGEgbWV0YS1hbmFseXNpcy4gVGhlIG1haW4gb25lcyBpbmNsdWRlICoqJFReMiQsICRUJCwgYW5kICRJXjIkKiouICBUaGVzZSBtZXRyaWNzIGFsbCBoYXZlIHRoZWlyIGJlbmVmaXRzIGFuZCBsaW1pdGF0aW9ucywgd2hpY2ggd2Ugd2lsbCBicmllZmx5IGRpc2N1c3MgaW4gdGhlIGZvbGxvd2luZyBzZWN0aW9ucy4KCiMjIyAkVF4yJAoKJFReMiQsIHdoaWNoIHdlIGRpc2N1c3NlZCBpbiB0aGUgWypTdGF0aXN0aWNhbCBtb2RlbHMqXShodHRwOi8vbWV0YWFuYWx5c2lzLmVjb2xvZ3kudWdhLmVkdS82LXN0YXRpc3RpY2FsLW1vZGVscy8pIHNlY3Rpb24sIGVzdGltYXRlcyB0aGUgIGFtb25nLXN0dWR5IHZhcmlhbmNlLCBiYXNlZCBvbiB0aGUgb2JzZXJ2ZWQgZWZmZWN0IHNpemVzIGFuZCB0aGVpciB3aXRoaW4tc3R1ZHkgdmFyaWFuY2UuICBUaHVzLCBpdCBpcyB1c2VkIHRvIGVzdGltYXRlIHZhcmlhdGlvbiBpbiB0aGUgKnRydWUqIGVmZmVjdCBzaXplcywgYW5kIHByb3ZpZGVzIGFuIGFic29sdXRlIHZhbHVlIGZvciB0aGlzIGVzdGltYXRlLiAgSG93ZXZlciwgaXQgZG9lcyBub3QgcXVhbnRpZnkgaG93IG11Y2ggb2YgdGhlIG9ic2VydmVkIHZhcmlhdGlvbiBpcyByZWFsIGFuZCBob3cgbXVjaCBpcyBqdXN0IHNhbXBsaW5nL21lYXN1cmVtZW50IGVycm9yLiAgSXQgaXMgbm90IHNlbnNpdGl2ZSB0byBudW1iZXIgb2Ygc3R1ZGllcywgYnV0IGlzIHNlbnNpdGl2ZSB0byBlZmZlY3Qgc2l6ZSBtZXRyaWMgYmVjYXVzZSBpdCBpcyBjYWxjdWxhdGVkIG9uIHRoZSBzYW1lIHNjYWxlIGFzIHRoZSBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMuICBUaGVyZSBhcmUgbXVsdGlwbGUgd2F5cyB0byBjYWxjdWxhdGUgJFReMiQuIFRoZSBbRGVyU2ltb25pYW4gYW5kIExhaXJkIG1ldGhvZF0oaHR0cDovL21ldGFhbmFseXNpcy5lY29sb2d5LnVnYS5lZHUvNi1zdGF0aXN0aWNhbC1tb2RlbHMvKSBzZWN0aW9uLCBpcyBvbmUgb2YgdGhlIG1vc3QgY29tbW9uIGFuZCBzaW1wbGVzdCBtZXRob2RzIHRvIGNhbGN1bGF0ZSwgaG93ZXZlciwgaXQgaGFzIHNvbWUgZHJhd2JhY2tzIGluIGNlcnRhaW4gY29udGV4dHMgWypGdXR1cmU6IGFkZCBtb3JlIGhlcmUqXS4gIEhvd2V2ZXIsIGluY3JlYXNlcyBpbiBjb21wdXRhdGlvbmFsIGVmZmljaWVuY3kgaGF2ZSBtYWRlIG90aGVyIG1ldGhvZHMgcG9zc2libGUsIGluY2x1ZGluZyAqKnJlc3RyaWN0ZWQgbWF4aW11bSBsaWtlbGlob29kIChSRU1MKSoqLiAgRHVlIHRvIHRoZSBiZW5lZml0cyBvZiB0aGlzIGFwcHJvYWNoIFsqRnV0dXJlOiBhZGQgbW9yZSBoZXJlKl0sIG1hbnkgc3RhdGlzdGljYWwgcHJvZ3JhbXMgYXJlIGJlZ2lubmluZyB0byBkZWZhdWx0IHRvIFJFTUwsIGluY2x1ZGluZyBgbWV0YWZvcmAuICAKCiZuYnNwOwoKIyMjICRUJAoKJFQkIGlzIHRoZSBzcXVhcmUgcm9vdCBvZiAkVF4yJCwgYW5kICoqZXN0aW1hdGVzIHRoZSBhbW9uZy1zdHVkeSBzdGFuZGFyZCBkZXZpYXRpb24qKi4gTGlrZSAkVF4yJCwgJFQkIGVzdGltYXRlcyB2YXJpYXRpb24gaW4gKnRydWUqIGVmZmVjdCBzaXplcywgYW5kIGlzIG9uIHRoZSBzYW1lIHNjYWxlIGFzIHRoZW0sIGJ1dCBoYXMgdGhlIGFkZGVkIGJlbmVmaXQgb2YgYmVpbmcgaW4gdGhlIHNhbWUgdW5pdHMgYXMgdGhlIG9yaWdpbmFsIGVmZmVjdCBzaXplIG1lYXN1cmVtZW50cy4gIFRodXMsIGl0IGlzIGVhc2llciB0byBpbnRlcnByZXQgaG93IG11Y2ggdmFyaWFiaWxpdHkgdGhlcmUgaXMgYXJvdW5kIHRob3NlIGVmZmVjdCBzaXplcy4gIEhvd2V2ZXIsIGR1ZSB0byB0aGUgZGVwZW5kZW5jZSBvZiAkVCQgYW5kICRUXjIkIG9uIHRoZSBzY2FsZSBvZiBvcmlnaW5hbCBlZmZlY3Qgc2l6ZSBtZWFzdXJlbWVudHMgKHdoaWNoIGRlcGVuZHMgb24gdGhlIGVmZmVjdCBzaXplIG1ldHJpYyksIGl0IGlzIGRpZmZpY3VsdCB0byBjb21wYXJlICRUJCBhbmQgJFReMiQgYW1vbmcgbWV0YS1hbmFseXNlcyB1c2luZyBkaWZmZXJlbnQgZWZmZWN0IHNpemUgbWV0cmljcy4KCiZuYnNwOwoKIyMjICRJXjIkCgpPbmUgbWV0cmljIGZvciBlc3RpbWF0aW5nIGhldGVyb2dlbmVpdHkgdGhhdCByZW1vdmVzIHRoZSBzY2FsaW5nIGlzc3VlcyBhc3NvY2lhdGVkIHdpdGggJFQkIGFuZCAkVF4yJCBpcyB0aGUgJEleMiQgc3RhdGlzdGljLiAgVGhpcyBzdGF0aXN0aWMgZ2l2ZXMgKmFuIGVzdGltYXRlIG9mIGhldGVyb2dlbmVpdHkgb24gYSByZWxhdGl2ZSBzY2FsZSosIGFsbG93aW5nIGNvbXBhcmlzb25zIG9mIGhldGVyb2dlbmVpdHkgYWNyb3NzIG1ldGEtYW5hbHlzZXMuICAqKiRJXjIkIGVzdGltYXRlcyB0aGUgcGVyY2VudGFnZSBvZiB0b3RhbCBvYnNlcnZlZCBoZXRlcm9nZW5laXR5IHRoYXQgaXMgYXR0cmlidXRhYmxlIHRvIHJlYWwgZGlmZmVyZW5jZXMgaW4gdGhlIHRydWUgZWZmZWN0IHNpemVzLCBhbmQgbm90IGR1ZSB0byByYW5kb20gZXJyb3IuKiogIFRoZXJlZm9yZSwgaXQgY2FuIGJlIHVzZWQgdG8gaW5kaWNhdGUgdGhlIHBlcmNlbnRhZ2Ugb2YgdG90YWwgb2JzZXJ2ZWQgaGV0ZXJvZ2VuZWl0eSB0aGF0IGlzIGF0dHJpYnV0YWJsZSB0byBhbW9uZy1zdHVkeSB2YXJpYW5jZSwgb3IgdG8gdGhlIHZhcmlhbmNlIGFtb25nIGxldmVscyBvZiBhIG1vZGVyYXRpbmcgdmFyaWFibGUgb2YgaW50ZXJlc3QgKEhpZ2dpbnMgZXQgYWwuIDIwMDMpLiAgVGh1cywgaXQgY2FuIGJlIHRob3VnaHQgb2YgYXM6CiQkSV4yID0gXGxlZnQoIFxmcmFje1Zfe2Ftb25nfX17Vl97dG90YWx9fSBccmlnaHQpIFx0aW1lcyAxMDAkJApJZiAkSV4yJCBpcyB6ZXJvLCBpdCBtZWFucyB0aGF0IGFsbCBvZiB0aGUgb2JzZXJ2ZWQgdmFyaWF0aW9uIGlzIGR1ZSB0byByYW5kb20gKGUuZy4sIG1lYXN1cmVtZW50KSBlcnJvciBhbmQgbm90IGR1ZSB0byBoZXRlcm9nZW5laXR5LCBpLmUuLCB2YXJpYXRpb24gaW4gdGhlIHRydWUgZWZmZWN0IHNpemVzLiAgSWYgaXQgaXMgY2xvc2UgdG8gMTAwJSwgaXQgaW5kaWNhdGVzIHRoYXQgbW9zdCBvZiB0aGUgb2JzZXJ2ZWQgdmFyaWF0aW9uIGlzIGR1ZSB0byBoZXRlcm9nZW5laXR5IGluIGVmZmVjdCBzaXplcy4gICAKClRoZSBmb3JtdWxhIGZvciBjYWxjdWxhdGluZyAkSV4yJCBpbiBhICpyYW5kb20qIGVmZmVjdHMgbW9kZWwgaXM6CiQkSV4yID0gXGxncm91cCBcZnJhY3tRX3t9LWRmfXtRX3t9fSBccmdyb3VwIFx0aW1lcyAxMDAkJApUaGUgJFEkIGluIHRoZSBudW1lcmF0b3IgYW5kIGRlbm9taW5hdG9yIGlzICRRX3t0b3RhbH0kIGlmIHRoZSBnb2FsIGlzIHRvIGV4cGxvcmUgYW1vbmctc3R1ZHkgaGV0ZXJvZ2VuZWl0eSAobWVhbmluZyB0aGF0ICRkZiA9IGsgLTEkLCB3aXRoICRrID0kIHRoZSBudW1iZXIgb2Ygc3R1ZGllcyBpbiB0aGUgbWV0YS1hbmFseXNpcy4gIAoKJm5ic3A7CgokSV4yJCBpcyBhIHVzZWZ1bCBzdGF0aXN0aWMgYmVjYXVzZSBpdCBkZXBlbmRzIGxlc3Mgb24gdGhlIG51bWJlciBvZiBzdHVkaWVzIGluIHRoZSBtZXRhLWFuYWx5c2lzIHRoYW4gJFEkLCBob3dldmVyIGl0IHN0aWxsIGNhbiBoYXZlIGxvdyBwb3dlciB3aGVuIHNhbXBsZSBzaXplIGlzIHNtYWxsICgqUkVGKikuICBBZGRpdGlvbmFsbHksIGl0IGRvZXMgbm90IGdpdmUgaW5mb3JtYXRpb24gb24gdGhlIGFic29sdXRlIHZhbHVlIG9mIHRoZSBoZXRlcm9nZW5laXR5IGluIGVmZmVjdCBzaXplcywgc28gaWYgdGhpcyBpbmZvcm1hdGlvbiBpcyB1c2VmdWwgZm9yIHRoZSBpbnRlcnByZXRhdGlvbiBvZiByZXN1bHRzLCAkVF4yJCBvciAkVCQgd291bGQgYmUgaW1wb3J0YW50IHRvIHJlcG9ydCBhcyB3ZWxsLiAKCiZuYnNwOwoKIyMgU3VtbWFyeQoKVGhlcmUgYXJlIGEgdmFyaWV0eSBvZiB3YXlzIHRvIGV2YWx1YXRlIHZhcmlhdGlvbiBpbiBlZmZlY3Qgc2l6ZXMgaW4gYSBtZXRhLWFuYWx5c2lzLiAgJFEkIHByb3ZpZGVzIGEgZm9ybWFsIHN0YXRpc3RpY2FsIHRlc3QgdG8gYXNzZXNzIGRpZmZlcmVuY2VzIGluIHRoZSB0cnVlIGVmZmVjdHMgYW1vbmcgc3R1ZGllcywgb3IgdGhlIGltcG9ydGFuY2Ugb2YgbW9kZXJhdGluZyB2YXJpYWJsZXMgKHdoaWNoIGNhbiBiZSBjb250aW51b3VzIG9yIGNhdGVnb3JpY2FsKSBmb3IgZXhwbGFpbmluZyB2YXJpYXRpb24gaW4gdGhlIG9ic2VydmVkIGVmZmVjdCBzaXplcy4gJFReMiQsICRUJCwgYW5kICRJXjIkIGFyZSBtZWFudCB0byBkZXNjcmliZSB2YXJpYXRpb24gaW4gZWZmZWN0IHNpemVzLCBlaXRoZXIgb24gYW4gYWJzb2x1dGUgKCRUXjIkLCAkVCQpIG9yIHJlbGF0aXZlICgkSV4yJCkgc2NhbGUuICBUaGVzZSBtZXRyaWNzIGhhdmUgZGlmZmVyZW50IGJlbmVmaXRzIGFuZCBkcmF3YmFja3MsIGFuZCBvZnRlbiByZXZlYWwgc2xpZ2h0bHkgZGlmZmVyZW50IGluZm9ybWF0aW9uIHdoaWNoIGNhbiBiZSBoZWxwZnVsIGluIGV4cGxhaW5pbmcgdGhlIHJlc3VsdHMgb2YgYSBtZXRhLWFuYWx5c2lzLiAKCiZuYnNwOwoKQWZ0ZXIgY29uZHVjdGluZyBoZXRlcm9nZW5laXR5IHRlc3RzLCB0aGUgb25seSByZW1haW5pbmcgc3RlcHMgaW4gYSBtZXRhLWFuYWx5c2lzIGFyZSB0byBwbG90IGFuZCBpbnRlcnByZXQgdGhlIHJlc3VsdHMsIGFuZCBldmFsdWF0ZSBwdWJsaWNhdGlvbiBiaWFzLiAgV2Ugd2lsbCBhZGRyZXNzIHRoZXNlIHRvcGljcyBpbiB0aGUgbmV4dCBtb2R1bGVzLiAgR28gdG8gWyptb2R1bGUgOSpdIHRvIGxlYXJuIG1vcmUgYWJvdXQgaG93IHRvIHZpc3VhbGl6ZSBtZXRhLWFuYWx5c2lzIHJlc3VsdHMsIGFuZCBbKm1vZHVsZSAxMCpdIHRvIGxlYXJuIGhvdyB0byB0ZXN0IGZvciBwdWJsaWNhdGlvbiBiaWFzLgoKJm5ic3A7CgoqKioKCipMYXN0IHVwZGF0ZWQ6ICBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVZLCAlQiAlZCcpYCoKQXV0aG9yOiBBbXkgQnJpZ2dzCgombmJzcDsKCiMgUmVmZXJlbmNlcwoKKiBIaWdnaW5zIGV0IGFsLiAyMDAzLiBNZWFzdXJpbmcgaW5jb25zaXN0ZW5jeSBpbiBtZXRhLWFuYWx5c2VzLiBCTUouIDMyNy4gNTU3LTU2MC4=