1 Overview

In Q. Wang et al. (2023), we developed an end-to-end pipeline to demonstrate the role of epistasis in the genetic control of cardiac hypertrophy. This pipeline consisted of four major phases: (1) the derivation of estimates of left ventricular mass via deep learning, (2) the computational prioritization of epistatic drivers based on data from the UK Biobank (Bycroft et al. 2018), (3) functional interpretation of the hypothesized epistatic genetic loci, and (4) experimental confirmation of epistasis in cardiac transcriptome and cardiac cellular morphology.

Here, we expand upon the computational prioritization of epistatic drivers phase. In this phase, we leveraged large-scale genetic and cardiac MRI data from the UK Biobank and developed the low-signal signed iterative random forest (lo-siRF) to prioritize genetic loci and interactions between loci for downstream investigations. As lo-siRF is heavily rooted in the Predictability, Computability, and Stability (PCS) framework for veridical (trustworthy) data science (Yu and Kumbier 2020), we conducted extensive stability analyses to help minimize the impact of human judgment calls and modeling decisions on our scientific conclusions. In this supplementary PCS documentation, we will:

  1. Transparently document and justify the many human judgment calls and modeling decisions that were inevitably made throughout our statistical analysis.
  2. Provide additional exploration and insight into the main results presented in Q. Wang et al. (2023) alongside the stability analyses.

In what follows, we organize this documentation by step in the lo-siRF pipeline (see Q. Wang et al. (2023)), beginning with the choice of phenotypic data, followed by the dimension reduction step, binarization step, prediction step, and concluding with the prioritization step. We then investigate the possibility of pleiotropy between LV mass and blood pressure, conducting a stability analysis where we examine the impact of excluding hypertensive individuals from the lo-siRF analysis. Lastly, we compare the lo-siRF prioritized loci and interactions between loci with those identified using existing methods and conclude with final remarks.

Origins and intended usage of lo-siRF: As discussed in Q. Wang et al. (2023), lo-siRF was originally developed as a first-stage recommendation (or hypothesis generation) tool to prioritize genetic loci and interactions between loci for downstream analyses and experimental validation. Importantly, the output of lo-siRF is a prioritization or ranking order of loci and interactions between loci, not a measure of statistical significance. We emphasize that recommendations or prioritizations from lo-siRF should not be interpreted as causal findings without further investigation. Given the numerous challenges inherent to epistasis discovery (e.g., high heterogeneity, small effect sizes, and unmeasured confounding factors, discussed further in Q. Wang et al. (2023)), assessing causality solely from data is incredibly complex and difficult to do reliably. Lo-siRF was thus designed and intended to be used as a single step within a larger scientific discovery pipeline. In Q. Wang et al. (2023), we relied on extensive follow-up investigations to validate the lo-siRF-prioritized genetic loci and interactions between loci, and we encourage practitioners to do the same.

2 Choice of Phenotypic Data

In the first step of lo-siRF, we began with a careful choice of phenotypic data. This first, but often overlooked, choice is critical to the reliability and interpretation of results. If the data quality is poor, conclusions may be unreliable. If the data is far-removed from the domain problem of interest, conclusions may not be relevant. Given the importance of this choice of phenotypic data, we conducted extensive data explorations for different phenotypes in addition obtaining clinician input regarding its clinical relevance.

Initial choice of phenotype: Our overarching goal was to study the role of epistasis in cardiac hypertrophy. One important disease that is closely related to cardiac hypertrophy is hypertrophic cardiomyopathy (HCM). HCM is a common heart disease, impacting around 1 in 500 people, where the heart muscle becomes enlarged or thickened. Given the high prevalence and possible life-threatening consequences of this disease, we first set out to explore this HCM phenotype, defined as a 0-1 indicator variable of whether or not the individual was diagnosed with HCM (i.e., any ICD10 code of I42.1 or I42.2 in the UK Biobank). However, when fitting various machine learning prediction models, including L1 or L2-regularized logistic regression, random forest (RF), iterative RF (iRF), and support vector machines, using single-nucleotide variant (SNV) data from the UK Biobank (details in Q. Wang et al. (2023)) to predict HCM diagnosis, the balanced classification accuracy on the held-out validation data did not consistently exceed 50% when trained on different bootstrapped training samples. In other words, the fitted prediction models were no better than random guessing. This made us wary of any interpretations extracted from these prediction models since it is unclear whether these models are capturing any relevant phenotypic signal or simply noise. Given this incredibly weak prediction signal, we deemed that these models did not pass the prediction check (the “P” in PCS) (Yu and Kumbier 2020). For this reason, we chose not to proceed further with the HCM phenotype and did not conduct any analysis with respect to interpreting the aforementioned models for HCM.

Pivoting to a cardiac MRI-derived phenotype: We instead pivoted to an alternative phenotype for cardiac hypertrophy based upon deep-learning-enabled left ventricular (LV) structural analysis using cardiac MRIs. This choice was heavily motivated by our struggles with HCM. Specifically, when looking back at the HCM diagnosis data, we noticed that the number of HCM cases in the UK Biobank data (only 236 HCM cases out of 337,535 unrelated White British individuals) was much lower than the 1 in 500 ratio that is expected. Although the UK Biobank population is known to be healthier than the general population (Fry et al. 2017), the observed discrepancy is large, leading us to speculate about potential under-diagnosis issues with the HCM phenotype. Consequently, rather than relying on a clinician’s diagnosis which may suffer from issues such as under-diagnosis, we chose to build upon recent advances in deep-learning-enabled phenotyping (Bai et al. 2018). Doing so enables us to extract a measure of left ventricular hypertrophy, specifically, the left ventricular mass (LVM), from anyone with a cardiac MRI.

Arriving at LVMi: However, LVM is known to be heavily influenced by body weight, height, and gender (Engel, Schwartz, and Homma 2016; Mizukoshi et al. 2016). Thus, if we were to proceed solely with LVM in our analysis, we risk identifying genetic loci and interactions between loci that are primarily associated with body weight, height, and gender, rather than left ventricular hypertrophy. Indeed, if we visualize the relationship between LVM, height, and weight within each gender group (Figure 2.1), we see strong positive correlations.

This motivates the need to adjust for height and weight in order to help decouple the effects of height/weight and LVM. As done in Khurshid et al. (2023), one common way to address this is by analyzing LVM indexed by body surface area (LVMi), defined as:

\[\begin{align*} \text{LVMi} = \text{LVM } / \text{ Body surface area}, \end{align*}\] where body surface area is calculated based on height and body weight via the Du Bois formula (Du Bois and Du Bois 1916).

After normalizing by body surface area (and hence, height and weight), the associations between LVMi and height/weight are much weaker within each gender group, exhibiting correlations closer to 0 (Figure 2.1). Thus, by focusing our statistical analysis on LVMi, we lessen the possibility that the identified genetic loci and interactions between loci are only selected because of their association with body height and/or weight. Still, there are differences in LVMi between males and females, with males tending to have higher LVMi measurements. As seen later, we will account for this in the modeling stage by using gender-specific binarization thresholds to binarize the LVMi responses into the high and low LVMi groups.

Study Cohort: Before proceeding, we note that another important human judgment call within our pipeline is the choice of study cohort. Specifically, we restricted our analysis to the unrelated White British individual population with both SNV and cardiac MRI data in the UK Biobank, resulting in a cohort of 29,661 individuals. We chose to focus this analysis on the unrelated White British population, anticipating the very low-signal problem under study (e.g., due to the generally small effect sizes of common genetic variants and the high phenotypic diversity of cardiac hypertrophy). By studying a more homogeneous cohort such as the unrelated White British population, we hope to first establish a proof-of-concept foothold on the role of epistasis in cardiac hypertrophy, and we view the study and generalization to the broader population as a very crucial next step.

Pair plot, illustrating the relationships between LVM, LVMi, height, and weight within each gender group (males in green and females in orange). Density distributions are shown along the diagonal.

Figure 2.1: Pair plot, illustrating the relationships between LVM, LVMi, height, and weight within each gender group (males in green and females in orange). Density distributions are shown along the diagonal.

3 Dimension Reduction Step

Overview

Having carefully chosen the phenotypic data (i.e., the cardiac MRI-derived LVMi) under study, the next step in lo-siRF is to do dimension reduction to reduce the number of SNVs under consideration using a genome-wide association study (GWAS). This dimension reduction step is necessary to mitigate the computational and statistical challenges of searching across millions of possible SNVs (which in the case of searching for epistasis results in an even larger combinatorial explosion of possibilities).

Why GWAS? We chose to do dimension reduction by running a GWAS as it (1) has been shown to be an incredibly useful tool for better understanding the genetic basis of numerous diseases in this field (Visscher et al. 2017; Pirruccello et al. 2020; Meyer et al. 2020; Harper et al. 2021; Khurshid et al. 2023), (2) is one of the few methods that can handle an input of millions of SNVs in a computationally-tractable manner, and (3) is a common, widely-accepted preprocessing step in other related statistical genomics tasks such as fine-mapping (Schaid, Chen, and Larson 2018).

Limitations: We acknowledge, however, that using a GWAS to reduce the number of SNVs under consideration has limitations. Because a GWAS prioritizes SNVs that have strong marginal associations with the phenotype under study, we may be removing SNVs that are associated with LVMi through an epistatic interaction but not through a marginal association. Alleviating this limitation is certainly interesting and an important direction to pursue in future work. Regardless, in this current work, we use lo-siRF primarily as a way to generate recommendations for experimental validation of epistasis. We thus are most interested in generating reliable recommendations for a limited number of experiments, rather than attempting to find all possible interactions that drive the disease. Given our particular use-case for lo-siRF, we accept the limitations of using a GWAS for dimension reduction and again view this work as a reliable first step (and certainly not the last) for better understanding the role of epistasis in cardiac hypertrophy.

How was the dimension reduction performed? We performed a GWAS on the training data for the rank-based inverse normal-transformed LVMi using two algorithms, PLINK (Purcell et al. 2007) and BOLT-LMM (Loh et al. 2015). For each of the two GWAS runs, we ranked the SNVs by significance (i.e., the GWAS p-value). We then took the union of the top 1000 SNVs (without clumping) from each of the two GWAS runs and proceeded with this resulting set of 1405 SNVs for the remainder of the lo-siRF pipeline. We refer to Q. Wang et al. (2023) for the details on the PLINK and BOLT-LMM implementations and use this document instead to justify several of our human judgment calls in this dimension reduction step.

  • Why PLINK and BOLT-LMM? Since BOLT-LMM and PLINK rely on different statistical models and it is unclear a priori which model is better suited for our problem, we employed both software packages to mitigate the dependence of downstream conclusions on this arbitrary choice of model.
  • Why the rank-based inverse normal-transformed LVMi? Because the distribution of LVMi measurements is right skewed (see Figure 2.1), and the p-value computation in PLINK and BOLT-LMM rely on normality assumptions, the rank-based inverse normal-transform was taken as in Khurshid et al. (2023).
  • Why was the union taken? As mentioned previously, relying on a GWAS to do dimension reduction can be limiting since it is primarily assessing marginal associations between the SNVs and the phenotype. There are also other restrictive modeling assumptions (e.g., linearity) that may add to these limitations. Due to this concern that we may be imposing too many unnecessary restrictions in order for SNVs to pass the GWAS filter, we chose to take the union of the top SNVs from BOLT-LMM and from PLINK, rather than taking the intersection which would have made it more difficult or restrictive for SNVs to pass the GWAS filter.
  • How was the threshold chosen? We chose the threshold of 1000 SNVs per GWAS method (without clumping) as it (1) struck a balance between the amount of information loss and the computational cost of our downstream modeling and (2) yielded the highest validation prediction accuracy compared to choosing other possible thresholds (500 and 2000) with and without clumping in the prediction modeling stage. We note that this choice of the top 1000 SNVs includes all SNVs that passed the genome-wide significance level (p-value = 5E-8) as well as additional SNVs that did not pass the genome-wide significance level. In particular, taking the top 1000 SNVs corresponds to using the p-value threshold of 1.7E-5 and 6.7E-6 for PLINK and BOLT-LMM, respectively.

Remark: We note that alternative dimension reduction strategies may be used in replacement of our proposed procedure. For example, one may consider using a different GWAS software (e.g., REGENIE (Mbatchou et al. 2021)), a different phenotype transformation, or perhaps a more sophisticated approach tailored for interactions and epistasis detection (e.g., MAPIT (Crawford et al. 2017)).

Organization: Under the GWAS Results Summary tab, we provide an investigation into the BOLT-LMM and PLINK GWAS results for LVM and LVMi. Under the GWAS-filtered SNVs, we explore the selected 1405 SNVs that passed the GWAS filter for the LVMi phenotype.

GWAS Results Summary

Below, we provide an overview of the genome-wide association study (GWAS) results for both the LVM and LVMi phenotypes. While LVMi is the primary phenotype of interest, we provide the LVM GWAS results for completeness. We further investigate the similarities in findings between the LVM and LVMi GWAS analyses via a stability analysis.

  • Under the BOLT-LMM and PLINK tabs:
    • We provide a brief look into the GWAS results, including the Manhattan plots for each phenotype (LVMi and LVM).
    • We also provide a table of the genomic risk loci, lead SNVs, and independent significant SNVs from each GWAS, determined using FUMA (Watanabe et al. 2017) with the default settings (i.e., maximum p-value of lead SNVs = 5E-8, maximum p-value cutoff = 0.05, \(r^2\) threshold to define independent significant SNVs = 0.6, 2nd \(r^2\) threshold to define lead SNVs = 0.1, minimum minor allele frequency = 0, maximum distance between LD blocks to merge into a locus = 250kb, using the UKB release2b 10k White British reference panel population).
    • Furthermore, we used FUMA to map SNVs to genes based on position, again with the default settings (maximum distance = 10kb), and provide this table of mapped genes below.
  • Lastly, under the Stability Analysis tab, we investigated the similarities and differences between the BOLT-LMM and PLINK results as well as between the LVM and LVMi results.

BOLT-LMM

LVMi

GWAS Manhattan plot for the LVMi phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Figure 3.1: GWAS Manhattan plot for the LVMi phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Genomic Risk Loci

Figure 3.2: List of genomic risk loci from FUMA for the LVMi BOLT-LMM GWAS. uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the top lead SNV for the given genomic locus. chr = Chromosome of top lead SNV. pos = Position of top lead SNV on hg19. p = P-value of top lead SNV. start = Start position of the locus. end = End position of the locus. nGWASSNVs = Number of the GWAS-tagged candidate SNVs within the genomic locus. nIndSigSNVs = Number of the independent significant SNVs in the genomic locus. IndSigSNVs = rsID of independent significant SNVs in the genomic locus. nLeadSNVs = The number of lead SNVs in the genomic locus. LeadSNVs = rsID of lead SNVs in the genomic locus.

Lead SNVs

Figure 3.3: List of lead SNVs from FUMA for the LVMi BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nIndSigSNVs = Number of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1. IndSigSNVs = rsID of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1.

Independent Significant SNVs

Figure 3.4: List of independent significant SNVs from FUMA for the LVMi BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nGWASSNVs = Number of GWAS-tagged SNVs which are in LD of the independent significant SNV given \(r^2\) = 0.6.

Mapped Genes

Figure 3.5: List of mapped genes (via positional mapping) from FUMA for the LVMi BOLT-LMM GWAS. ensg = ENSG ID. symbol = Gene Symbol. chr = Chromosome. start = Starting position of the gene. end = Ending position of the gene. strand = Strand of the gene. type = Gene biotype from Ensembl. entrezID = entrez ID (if available). HUGO = HUGO (HGNC) gene symbol. pLI = pLI score (the probability of being loss-of-function intolerant) from ExAC database; the higher the score is, the more intolerant to loss-of-function mutations the gene is. ncRVIS = Non-coding residual variation intolerance score; the higher the score is, the more intolerant to non-coding variation the gene is. posMapSNVs = Number of SNVs mapped to gene based on positional mapping. posMapMaxCADD = The maximum CADD score of mapped SNVs by positional mapping. minGwasP = The minimum P-value of mapped SNVs. IndSigSNVs = rsID of the independent significant SNVs that are in LD with the mapped SNVs. GenomicLocus = Index of genomic loci where mapped SNVs are from.

LVM

GWAS Manhattan plot for the LVM phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Figure 3.6: GWAS Manhattan plot for the LVM phenotype using BOLT-LMM. Red dashed line indicates the genome-wide significance level (p = 5E-8).

Genomic Risk Loci

Figure 3.7: List of genomic risk loci from FUMA for the LVM BOLT-LMM GWAS. uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the top lead SNV for the given genomic locus. chr = Chromosome of top lead SNV. pos = Position of top lead SNV on hg19. p = P-value of top lead SNV. start = Start position of the locus. end = End position of the locus. nGWASSNVs = Number of the GWAS-tagged candidate SNVs within the genomic locus. nIndSigSNVs = Number of the independent significant SNVs in the genomic locus. IndSigSNVs = rsID of independent significant SNVs in the genomic locus. nLeadSNVs = The number of lead SNVs in the genomic locus. LeadSNVs = rsID of lead SNVs in the genomic locus.

Lead SNVs

Figure 3.8: List of lead SNVs from FUMA for the LVM BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nIndSigSNVs = Number of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1. IndSigSNVs = rsID of independent significant SNVs which are in LD of the lead SNV at \(r^2\) = 0.1.

Independent Significant SNVs

Figure 3.9: List of independent significant SNVs from FUMA for the LVM BOLT-LMM GWAS. GenomicLocus = Index of assigned genomic locus (note: multiple independent lead SNVs can be assigned to the same genomic locus). uniqID = Unique ID of SNVs consists of chr:position:allele1:allele2 where alleles are alphabetically ordered. rsID = rsID of the SNV. chr = Chromosome. pos = Position on hg19. p = P-value from GWAS. nGWASSNVs = Number of GWAS-tagged SNVs which are in LD of the independent significant SNV given \(r^2\) = 0.6.

Mapped Genes

Figure 3.10: List of mapped genes (via positional mapping) from FUMA for the LVM BOLT-LMM GWAS. ensg = ENSG ID. symbol = Gene Symbol. chr = Chromosome. start = Starting position of the gene. end = Ending position of the gene. strand = Strand of the gene. type = Gene biotype from Ensembl. entrezID = entrez ID (if available). HUGO = HUGO (HGNC) gene symbol. pLI = pLI score (the probability of being loss-of-function intolerant) from ExAC database; the higher the score is, the more intolerant to loss-of-function mutations the gene is. ncRVIS = Non-coding residual variation intolerance score; the higher the score is, the more intolerant to non-coding variation the gene is. posMapSNVs = Number of SNVs mapped to gene based on positional mapping. posMapMaxCADD = The maximum CADD score of mapped SNVs by positional mapping. minGwasP = The minimum P-value of mapped SNVs. IndSigSNVs = rsID of the independent significant SNVs that are in LD with the mapped SNVs. GenomicLocus = Index of genomic loci where mapped SNVs are from.

Stability Analysis

To further investigate the choice of GWAS method and phenotype, we conducted a deeper exploration into the similarities and differences between the BOLT-LMM and PLINK results as well as between the LVM and LVMi results in the stability analysis below. The primary goal of this stability analysis is to answer the following two questions:

  1. Are there large differences between the GWAS p-values from BOLT-LMM and PLINK?
  • Figure 3.21: For each SNV, we plot the p-value (log-transformed) obtained via BOLT-LMM (x-axis) and PLINK (y-axis) for each of the LVM (left) and LVMi (right) phenotypes. We see that the most significant GWAS hits tend to be stable, no matter the choice of algorithm, but as the strength of the association decreases, there is greater variation in the p-value between BOLT-LMM and PLINK. This is to say that there is more stability around the SNVs with the strongest associations with LVMi and less stability around the SNVs with moderate or weak associations with LVMi. Another reason for taking the union of the top 1000 SNVs from each GWAS algorithm in the lo-siRF pipeline was to allow these moderate to weak association SNVs the chance of being identified in a multivariate model (i.e., via iterative random forest).
  1. What are the FUMA GWAS findings that are stable across GWAS methods (BOLT-LMM and PLINK) and choice of phenotype (LVM and LVMi)? As advocated by the stability principle (“S” in PCS) (Yu and Kumbier 2020; Yu 2013), we view stability across these arbitrary choices as a minimum requirement for making a scientific discovery.
  • In Figure 3.22, we summarize the SNVs, identified by FUMA, to be the top lead SNVs (per genomic risk locus), lead SNVs, and/or independent significant SNVs for each GWAS method (BOLT-LMM and PLINK) and choice of phenotype (LVM and LVMi). Some takeaways here:
    • rs3045696, an intronic TTN variant, is the only stable top lead SNV, identified across all four GWAS runs.
    • Besides rs3045696, rs1873164, an intronic CCDC141 variant, is the only stable lead SNV, identified by FUMA across all four GWAS runs.
    • rs7591091 (an intronic CCDC141 variant with the highest frequency of occurrence in lo-siRF, seen later), along with rs967507, rs12622500, and rs10178003, were stably identified as independent significant SNVs by FUMA across all four GWAS runs.
    • Two other SNVs (rs62178977, rs73973171) were also identified as independent significant SNVs by FUMA using both BOLT-LMM and PLINK for the LVMi phenotype.
  • In Figure 3.23, we summarize the genes that were positionally-mapped and prioritized by FUMA across the different GWAS methods (BOLT-LMM and PLINK) and choice of phenotype (LVM and LVMi).
    • The genes that were stably mapped by FUMA across all four GWAS runs are PRKRA, DFNB59, FKBP7, PLEKHA3, TTN, and CCDC141. We note that all of these genes are located near each other on chromosome 2 within ~600kb. The start position of PRKRA is 179296141 while the end position of CCDC141 is 179914813, with all other aforementioned genes in between.
    • No other genes were identified when using both BOLT-LMM and PLINK for the LVMi phenotype.
Comparison of the BOLT-LMM and PLINK GWAS p-values for each phenotype (LVM left, LVMi right). Each point represents a SNV with its BOLT-LMM p-value on the x-axis and its PLINK p-value on the y-axis.

Figure 3.21: Comparison of the BOLT-LMM and PLINK GWAS p-values for each phenotype (LVM left, LVMi right). Each point represents a SNV with its BOLT-LMM p-value on the x-axis and its PLINK p-value on the y-axis.

Summary of annotated SNVs from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

Figure 3.22: Summary of annotated SNVs from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

Summary of mapped genes from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

Figure 3.23: Summary of mapped genes from FUMA across different GWAS methods (BOLT-LMM and PLINK) and across different choices of phenotype (LVMi and LVM).

GWAS-filtered SNVs

In this section, we briefly explore the selected 1405 SNVs that passed the GWAS filter for the LVMi phenotype. We make two observations that will impact how we interpret the lo-siRF fit downstream:

  • There are strong correlations within blocks of neighboring SNVs due to linkage disequilibrium (LD) (Figure 3.24). This is a large contributing factor for why we ultimately extracted feature importances from the lo-siRF fit at the level of genetic loci, rather than for each individual SNV.
  • There are large differences in the number of SNVs that passed the GWAS filter from each genetic loci (Figure 3.25). We hence must account for this in the lo-siRF locus-level importance score.

We will expand upon this locus-level importance score in a later section (see Prioritization Step).

Additional notes:

  • Given the interest in CCDC141 and TTN in our work and their close proximity to each other on chromosome 2, we point out a couple pairwise (Pearson) correlations of particular relevance:
    • \(| Cor(\text{rs7591091}, \text{ rs66733621}) | = 0.35\)
    • \(| Cor(\text{rs7591091}, \text{ rs3045696}) | = 0.34\)
    • rs7591091 is the top SNV from the CCDC141 locus in lo-siRF and is one of the top CCDC141 GWAS hits (in fact, is identified to be a stable independent significant SNV (see GWAS Results Summary tab)). rs3045696, an intronic TTN SNV, was stably identified to be a top lead SNV in the GWASes, and rs66733621 is the top SNV from the TTN locus in lo-siRF. This is to say that the correlation between the CCDC141 and TTN loci is moderate and may possibly suggest independent roles of CCDC141 and TTN in their detected interaction. A further discussion of this is provided in Q. Wang et al. (2023). [Note: we use the term top SNV from a genetic locus in lo-siRF to mean the SNV in the specified genetic locus with the highest frequency of occurrence across decision paths in the siRF fit.]

LVMi - Correlation Between GWAS-filtered SNVs

Correlation heatmap for the GWAS-filtered SNVs. We plot the magnitude of the Pearson correlation between all possible pairs of SNVs that passed the GWAS filter. Darker red indicates higher correlation between the two SNVs. SNVs along the axes are ordered according to genomic location. Loci with more than two constituent SNVs are labeled.

Figure 3.24: Correlation heatmap for the GWAS-filtered SNVs. We plot the magnitude of the Pearson correlation between all possible pairs of SNVs that passed the GWAS filter. Darker red indicates higher correlation between the two SNVs. SNVs along the axes are ordered according to genomic location. Loci with more than two constituent SNVs are labeled.

LVMi - Table of GWAS-filtered SNVs

Figure 3.25: Number of SNVs per genetic locus that passed the GWAS filter. Note: a semicolon is used to denote the intergenic region between two genes.

4 Binarization Step

Overview

In the next step of lo-siRF, we chose to binarize the (continuous) LVMi phenotype measurements into two categories: a low LVMi group and a high LVMi group before fitting the prediction models.

Why did we choose to binarize? One of our main motivating factors to pursue binarization revolved around the prediction check criteria in the PCS framework (Yu and Kumbier 2020). This predictability principle advocates for the use of prediction accuracy as a reality check. This is to say that at a minimum, models should fit the data well, as measured by prediction accuracy, before believing that the model is capturing something relevant to reality or the real-world phenomena under study. In particular, before we thought to binarize the phenotype, we first attempted to train prediction models using the GWAS-filtered SNVs to predict the original (continuous) LVMi phenotype measurements. While this seemed like the most natural next step, these prediction results illuminated an incredibly weak prediction signal, with validation \(R^2\) values hovering very close to 0 (see Figure 4.1 in the Prediction Results without Binarization tab). Given that an \(R^2\) value of 0 can be achieved by simply predicting the mean LVMi response, this raised the question of whether these prediction models are capturing any biologically-relevant signal in the data. Consequently, the interpretation of these models may not be an accurate representation of reality. Put differently, these models do not satisfy the prediction check criteria under the PCS framework.

Given these difficulties in accurately predicting LVMi, we drew inspiration from how scientists often reduce complex problems into simplified versions. Here, the complex version of our problem aims to understand how SNVs are predictive of one’s precise (continuous-valued) LVMi measurement. This is challenging, as demonstrated by the poor prediction accuracy discussed previously. On the other hand, arguably the most simplified version of this problem is to understand how SNVs are predictive of whether one has an extremely high or extremely low LVMi measurement. Intuitively, if there are in fact genetic differences between these two LV chamber states, then differentiating between the two groups — those with extremely high LVMi and those with extremely low LVMi — should be easier than the original regression problem (i.e., predicting the raw continuous-valued LVMi response). Indeed, we will see this to be the case, observing that the resulting classification models consistently performed better than random guessing unlike the original regression models. More specifically, we observed balanced classification accuracies \(>55\%\), area under the receiver operator characteristic (AUROC) \(>0.58\), and area under the precision-recall curve (AUPRC) \(>0.55\) for the constructed binary classification task (see the Prediction Step tab). This prediction performance instills greater trustworthiness that the interpretation of these models after binarization are more relevant to the biological phenomena than the case without binarization.

How is the binarization done? We transformed the original regression problem of predicting the raw continuous-valued LVMi response into a binary classification problem as follows. For particular choice of threshold \(x\), we partitioned the raw continuous-valued LVMi phenotype into a low, middle, and high LVMi group corresponding to the \([0, x]\), \((x, 1-x)\), and \([1-x, 1]\) quantile ranges, respectively. We then omitted the individuals in the middle quantile range and trained the prediction models to differentiate between the low and high LVMi individuals. However, due to the gender-specific biological variation of LVMi shown earlier in the exploratory data analysis (see Choice of Phenotypic Data), we performed this binarization procedure for males and females separately. That is, we computed the quantiles for males and females separately. Finally, given that this threshold is artificially introduced, we run the remainder of the lo-siRF pipeline using three different reasonable binarization thresholds (15%, 20%, 25%) that balance the improvement in prediction signal and amount of data lost. In particular, we note that if we had chosen a binarization threshold of 50% so that no data is thrown out, then the balanced classification accuracy of the best-performing prediction model (signed iterative random forest) falls to \(51%\), which is very similar to random guessing. In the end, we will consolidate the results that were stable across all three binarization thresholds (15%, 20%, 25%), described later.

Limitations of binarization: We recognize that this binarization procedure has limitations and that these limitations should be carefully considered in context of the problem under study. For instance, the utility of this binarization is highly dependent on whether understanding the differences between the low and high quantiles is relevant to the study aims. In our case, we believe that the connection between cardiac hypertrophy and those with high LVMi helps to justify the use of binarizing based on the low and high quantiles. If one does not expect a monotonic relationship between the genetic features and the phenotype, then binarization may not be appropriate. In addition, binarization also requires the choice of binarization threshold. This choice is almost certainly a subjective choice and thus necessitates a stability analysis, that is, analyzing the stability of findings across different choices of binarization thresholds. In our case, we only prioritize loci/interactions that were stably important across three different choices of binarization threshold (15%, 20%, and 25%). Finally, binarization also reduces the sample size and systematically omits individuals who are not in the tails of the phenotype distribution. As a result, there may be additional interactions that are missed in lo-siRF. While we do not view this as a major concern if the goal is to recommend a small set of reliable experimental targets, this limitation may certainly impact studies with different end goals.

We expand on the prediction modeling with the binarized LVMi phenotype in the next section (see Prediction Step).

Prediction Results without Binarization

Here, we present a summary of the prediction modeling results, where we use the GWAS-filtered SNVs to predict the raw LVMi phenotype measurements (i.e., without any binarization). Specifically, we measure the validation set prediction accuracy from several popular machine learning regression algorithms (kernel ridge regression, Lasso regression, ridge regression, random forest (RF), and signed iterative random forest (siRF)) across four different prediction performance metrics - the Pearson correlation, mean absolute error (MAE), R-squared, and root-mean-squared error (RMSE) between the observed LVMi response and the predicted LVMi response. We also visualize how the predicted responses differ across the different prediction models in the provided pair plots. Though RF appears to yield the best prediction performance relative to the other methods under consideration, the RF prediction performance is still very poor as both the correlation and R-squared metrics are very close to 0.

Prediction Accuracies

Figure 4.1: Summary of prediction performance on the validation set for the LVMi phenotype (without binarization) across various prediction methods and evaluation metrics.

Prediction Pair Plot

Pair plot of the predicted LVMi responses from various prediction models. Each point represents an individual in the validation set, and the coordinates represent the predicted LVMi response from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted LVMi responses are shown along the diagonal.

Figure 4.2: Pair plot of the predicted LVMi responses from various prediction models. Each point represents an individual in the validation set, and the coordinates represent the predicted LVMi response from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted LVMi responses are shown along the diagonal.

5 Prediction Step

After choosing to binarize the LVMi phenotype, we next fit various prediction models using the GWAS-filtered SNVs to predict the binarized LVMi phenotype and assess their validation prediction accuracy.

Which models were chosen and why? While there are many methods, each with their unique advantages and disadvantages, for detecting epistasis from data (e.g., see Niel et al. 2015 and references therein), we chose to focus on siRF (Kumbier et al. 2023) as our primary interaction search engine for various reasons.

  1. Unlike many methods that make linear assumptions or require pre-specification of interaction order (i.e., the number of features involved in an interaction), siRF can identify higher-order, nonlinear Boolean interactions in a computationally-tractable manner without the need to specify the interaction order of interest.
  2. Another advantage of siRF for detecting interactions is the resemblance between the localized thresholding behavior of its decision trees and the threshold (or on-off switch-like) behavior frequently observed in biomolecular interactions (Nelson, Lehninger, and Cox 2008). In other words, the form of the siRF model appears to be well-suited for the biological phenomena under study.
  3. Furthermore, the prediction accuracy of the siRF model fit can be easily assessed. siRF also exhibited higher prediction accuracy than other commonly used prediction methods across almost all evaluation metrics examined and binarization thresholds (Figure 5.1). As discussed previously, prediction accuracy can serve as an indicator of whether or not the model is an accurate representation of reality. This prediction check is a necessary pre-requisite for interpreting the prediction model and is especially important in low-signal regimes such as this study.
  4. siRF and its predecessor iRF have demonstrated great success in detecting reliable interactions in previous real-world studies, such as in epistasis-controlled hair color (Behr et al. 2020), obesity (Allen et al. 2022), schizophrenia (De Rosa et al. 2022), and predictive gene expression networks (Cliff et al. 2019; Walker et al. 2022).
  5. Finally, due to the weak phenotypic signal and the strong correlations between neighboring SNVs due to linkage disequilibrium (Figure 3.24), we believed it was most appropriate to recommend interactions between genetic loci, rather than interactions betweeen individual SNVs. While it is not always clear how to perform this locus-level interaction search when the data is given at the SNV-level, we can build upon the siRF structure to aggregate feature importances across multiple SNVs using our new locus-level importance score, described in Q. Wang et al. (2023).

Though we are most interested in interpreting the siRF prediction model to identify candidate epistatic interactions, we also fit several other popular prediction models, including RF, L1-regularized logistic regression (Lasso), L2-regularized logistic regression (ridge), support vector machines (SVM), multilayer perceptron, AutoGluon TabularPredictor, and a polygenic risk score. These prediction models serve as baselines to ensure that siRF indeed fits the data well, relative to these other popular prediction models, and that siRF passes the prediction check in accordance with the PCS framework (Yu and Kumbier 2020).

Summary of prediction results: For all of the classification algorithms under investigation, we see that the validation prediction accuracy metrics, measured via classification accuracy, area under the receiver operator characteristic curve (AUROC), and area under the precision-recall curve (AUPRC), are all comfortably above the random-guessing baseline of 0.5 across three different binarization thresholds. This suggests that the prediction models are able to ascertain some phenotypic signal from the SNVs under study. That is, the SNVs used in the prediction models have some predictive power in differentiating those with high LVMi versus those with low LVMi. Moreover, siRF consistently yielded the highest predictive power across the various binarization thresholds and prediction metrics (with one exception being the classification accuracy for the 15% binarization threshold, where ridge is slightly better than siRF). From this, we conclude that siRF passed the prediction check and will proceed to interpret the siRF fit to recommend and prioritize interactions between genetic loci for downstream analyses and experiments.

Beyond the validation prediction accuracies, we also provide the confusion matrices, ROC and precision-recall curves, and pair plots comparing the predicted responses across methods for additional post-hoc exploration.

Prediction Accuracy Summary

Figure 5.1: Summary of prediction performance on the validation set for the binarized LVMi phenotype across various prediction methods, binarization thresholds, and evaluation metrics. Abbreviations: siRF, signed iterative random forest; RF, random forest; Lasso, L1-regularized logistic regression; Ridge, L2-regularized logistic regression; SVM, support vector machine; MLP, multilayer perceptron; Autogluon (medium/good), Autogluon TabularPredictor fitted with the medium/good quality preset; PGS, polygenic risk score.

Binarization Threshold = 0.15

Confusion Tables

Figure 5.2: Confusion matrix from various prediction models for predicting the binarized LVMi phenotype (binarization threshold = 0.15).

ROC/PR Curves

Figure 5.3: ROC curve for predicting the binarized LVMi (threshold = 0.15) across various prediction methods. TPR = true positive rate; FPR = false positive rate.

Figure 5.4: Precision-recall curve for predicting the binarized LVMi (threshold = 0.15) across various prediction methods.

Prediction Pair Plot

Pair plots of the predicted binarized LVMi responses (threshold = 0.15) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Figure 5.5: Pair plots of the predicted binarized LVMi responses (threshold = 0.15) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Binarization Threshold = 0.2

Confusion Tables

Figure 5.6: Confusion matrix from various prediction models for predicting the binarized LVMi phenotype (binarization threshold = 0.2).

ROC/PR Curves

Figure 5.7: ROC curve for predicting the binarized LVMi (threshold = 0.2) across various prediction methods. TPR = true positive rate; FPR = false positive rate.

Figure 5.8: Precision-recall curve for predicting the binarized LVMi (threshold = 0.2) across various prediction methods.

Prediction Pair Plot

Pair plots of the predicted binarized LVMi responses (threshold = 0.2) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Figure 5.9: Pair plots of the predicted binarized LVMi responses (threshold = 0.2) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Binarization Threshold = 0.25

Confusion Tables

Figure 5.10: Confusion matrix from various prediction models for predicting the binarized LVMi phenotype (binarization threshold = 0.25).

ROC/PR Curves

Figure 5.11: ROC curve for predicting the binarized LVMi (threshold = 0.25) across various prediction methods. TPR = true positive rate; FPR = false positive rate.

Figure 5.12: Precision-recall curve for predicting the binarized LVMi (threshold = 0.25) across various prediction methods.

Prediction Pair Plot

Pair plots of the predicted binarized LVMi responses (threshold = 0.25) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

Figure 5.13: Pair plots of the predicted binarized LVMi responses (threshold = 0.25) across various prediction methods. Each point represents an individual in the validation set, and the coordinates represent the predicted probability of having high LVMi from two different prediction methods, which are specified by the x and y-axes labels in each subplot. Density distributions of the predicted probabilities are shown along the diagonal.

6 Prioritization Step

Overview

Having passed the prediction check, we finally proceed to interpret the siRF fit in the last step of lo-siRF. In this step, we developed a novel stability-driven feature importance score to prioritize both genetic loci and interactions between genetic loci from siRF. We refer to Q. Wang et al. (2023) for the detailed description of this new importance score and here provide brief insights into the motivation and intuition behind this method.

Main idea: At a high-level, this new importance score (1) aggregates weak, unstable SNV-level importances from siRF into stronger, more stable locus-level importances and (2) can be leveraged to evaluate both the marginal importance of a genetic locus in siRF as well as the importance of higher-order interactions between genetic loci in siRF. The need for this locus-level feature importance score stems from two main reasons: the high correlation between SNVs and the weak phenotypic signal. Though the prediction models (including siRF) are all trained using SNV data, it is often very challenging to interpret the importance of an individual SNV from these models due to the high correlation between SNVs (Toloşi and Lengauer 2011; Hooker, Mentch, and Zhou 2021), which we observed in our previous exploratory data analysis (see Choice of Phenotypic Data tab). To further complicate matters, the weak phenotypic signal increases the instability of existing feature importance methods in that we see the feature rankings change drastically when using different bootstrap training samples. Given these challenges with SNV-level feature importances, it is then no surprise that siRF, out-of-the-box, does not find any stable interactions between SNVs (i.e., the siRF stability score is around 0 for all interactions between SNVs). To address these challenges, our new feature importance score leverages the correlation structure between SNVs, groups SNVs into genetic loci, and aggregates weak, unstable SNV-level importances from siRF into stronger, more stable locus-level importances.

Motivation behind new feature importance score: To better understand the motivation and construction of our new locus-level feature importance score, it can be helpful to first review the original importance score used in siRF (Kumbier et al. 2023). Briefly, in the original version of siRF, the importance of a signed interaction is based upon how stable or frequently it occurs in decisions paths across the random forest – that is, based upon the number of decision paths for which every signed feature in the signed interaction was used in at least one decision split (see Kumbier et al. (2023) for details). Following a similar logic, one natural path forward to calculate a locus-level importance from a forest that was fit on SNV data is as follows:

  1. Take the fitted forest, where each decision split used some SNV to make the split.
  2. Map each SNV used in a decision split to its corresponding genetic loci (e.g., using annotation software like ANNOVAR (K. Wang, Li, and Hakonarson 2010)).
  3. Compute the importance of a signed locus-level interaction based upon the frequency of occurrence of the interaction as before, but using the mapped genetic loci in lieu of the SNVs. That is, compute the number of decision paths for which every signed locus in the signed locus-level interaction was used in at least one decision split.

However, this frequency of occurrence measure is heavily tied to the number of SNVs that belong to each genetic locus. A genetic locus that consists of more SNVs will naturally have a higher frequency of occurrence than a genetic locus with only a few SNVs even though both genetic loci may be equally important (or unimportant). In other words, the original siRF importance score, measuring the frequency of occurrence, is not comparable across genetic loci. This bias is problematic given that we have previously seen some genetic loci may consist of only 1 SNV while other genetic loci have >50 SNVs (see GWAS-filtered SNVs tab in the Dimension Reduction Step).

Intuition behind new feature importance score: To alleviate this bias, we leverage the idea of a local feature importance score, where we compute a per-individual score that measures the importance of a locus/interaction for making the prediction of each individual. This is in contrast to a global feature importance score, which is a measure of importance for the entire group of individuals under study. While a global feature importance score gives rise to a single score for the entire population under study, we can compute a local feature importance score for each individual in the population. By computing a local feature importance score for each individual (i.e., this is the local stability importance (LSI) score from Q. Wang et al. (2023)), we can compare the importance of the locus/interaction across individuals and avoid the across-loci comparison that was problematic in the aforementioned discussion. This comparison is done via a permutation test in Q. Wang et al. (2023). Moreover, since we are comparing the local feature importances between individuals within or per loci/interaction in this permutation test, the local feature importances are all measured on the same scale and comparable, thereby mitigating the bias towards genetic loci with more SNVs.

How to aggregate SNVs: We mapped each SNV to its corresponding genetic locus using ANNOVAR (K. Wang, Li, and Hakonarson 2010) according to the hg19 refSeq Gene annotations. Given our ultimate goal of recommending/prioritizing genetic loci and interactions between loci for downstream analyses and experimental validation, we believe this choice provides an appropriate starting point to obtain actionable recommendations. However, we note that there are many alternative ways of aggregating SNVs. For example, it is possible to aggregate SNVs according to LD/haplotype blocks or to include additional gene-based or functional annotations in the aggregation scheme.

Organization: Under the SNV-level Importances tab, we provide the SNV-level feature importances from the fitted prediction algorithms (described in the Prediction Step section) for completeness. These SNV-level feature importances are very unstable across methods and across bootstrap perturbations for the reasons discussed above. We then summarize the results from the lo-siRF pipeline including the rankings of genetic loci and interaction between genetic loci using our new locus-level importance score under the Summary of lo-siRF Results tab. A final technical note on the advantages of incorporating signed information from siRF in this feature importance computation is provided under the Advantages of Signed Information tab.

SNV-level Feature Importances

Having observed that the aforementioned classification algorithms do have some predictive power to predict those with high versus low LVMi, a natural next step is to investigate which SNVs were used in these prediction models. Below, we highlight the top 100 SNVs, ranked by importance in each of the prediction models. For completeness, we provide the SNV importances for the unbinarized LVMi (regression) problem as well as the binarized LVMi (classification) problem across the three different binarization thresholds.

How is importance defined?

  • For ridge and Lasso, the importance of an SNV is defined as the magnitude of its coefficient in the prediction model.
  • For RF, the importance of an SNV is determined by the mean decrease in impurity (MDI) score.
  • For siRF, the importance of an SNV is determined by the MDI from the forest in the final iteration.
  • Due to the computational complexity, we did not compute the SNV importances from the SVM fit as there is no built-in model-based feature importance method (in R), and any permutation-based approach would be computationally expensive.

A word of caution: When interpreting these SNV importances, it is crucial to keep in mind that there are very large, strongly correlated blocks of SNVs within this data, which often renders the feature rankings unmeaningful and unstable (Toloşi and Lengauer 2011; Hooker, Mentch, and Zhou 2021). In particular, it is well-known that the MDI variable importance metric used in RF/iRF/siRF is biased against correlated features (Hooker, Mentch, and Zhou 2021). In other words, SNVs within large LD blocks tend to have artificially low MDI values. Given these idiosyncrasies, it is unsurprising that SNVs from TTN and CCDC141 – two genetic loci with many SNVs under LD – do not have high importances according to MDI. We provide these SNV importance tables only for completeness and to partially motivate the need to aggregate SNV-level importances into locus-level importances in lo-siRF.

Unbinarized (Regression)

Lasso

Figure 6.1: Lasso - Top 100 SNVs, ranked by importance, for predicting LVMi.

Ridge

Figure 6.2: Ridge - Top 100 SNVs, ranked by importance, for predicting LVMi.

RF

Figure 6.3: RF - Top 100 SNVs, ranked by importance, for predicting LVMi.

siRF

Figure 6.4: siRF - Top 100 SNVs, ranked by importance, for predicting LVMi.

Binarization Threshold = 0.15

Lasso

Figure 6.5: Lasso - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

Ridge

Figure 6.6: Ridge - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

RF

Figure 6.7: RF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

siRF

Figure 6.8: siRF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.15).

Binarization Threshold = 0.2

Lasso

Figure 6.9: Lasso - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

Ridge

Figure 6.10: Ridge - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

RF

Figure 6.11: RF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

siRF

Figure 6.12: siRF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.2).

Binarization Threshold = 0.25

Lasso

Figure 6.13: Lasso - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

Ridge

Figure 6.14: Ridge - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

RF

Figure 6.15: RF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

siRF

Figure 6.16: siRF - Top 100 SNVs, ranked by importance, for predicting the binarized LVMi (threshold = 0.25).

Summary of lo-siRF Results

Finally, we summarize the prioritization results from the lo-siRF pipeline using our new importance score to rank genetic loci and interactions between genetic loci. In this new importance score, we (1) computed a local (i.e., on a per-individual basis) stability importance score that aggregates weak SNV-level importances into stronger locus-level importances using the siRF fit and (2) conducted a permutation test to assess whether the local stability importance scores for a given locus/interaction are different between individuals with high and low LVMi (conditioned on the rest of the fitted forest). The larger the difference in local stability importance scores between those with high versus low LVMi, the greater the importance of the locus/interaction for predicting LVMi. For details on the new importance score, we refer to Q. Wang et al. (2023).

Below, we recap the siRF prediction accuracy for predicting the binarized LVMi across the three binarization thresholds (15%, 20%, 25%) (Figure 6.17). Then, in Figure 6.18, we summarize the prioritization rankings of genetic loci and interaction between loci according to the new importance score. We provide the nominal permutation p-values along with the permutation test statistic, that is, the difference in local feature stability scores between the high and low LVMi groups, with the standard deviation of this permutation distribution in parentheses.

Note that the permutation test was not performed for all loci/interactions (details in Q. Wang et al. (2023)). Given our primary aim of generating reliable hypotheses for follow-up experimental validation, we chose to only test loci/interactions that were predictive and stable in the siRF fit, following the PCS framework for veridical data science (Yu and Kumbier 2020). Specifically, for each binarization threshold, we only tested:

  • the top 25 loci with the highest average local stability importance scores, or in other words, those that occurred most stably/frequently (and thus likely predictive) in the siRF fit, and
  • the interactions between loci that were identified by siRF and achieved a stability score > 0.5, stability score for mean increase in precision > 0, and stability score for feature selection dependence > 0. We note that in addition to the explicit stability checks here, the requirement on the mean increase in precision serves as a predictability check, and the requirement on the feature selection dependence serves to differentiate marginal additive effects from non-additive interaction effects (see Kumbier et al. (2023) for details).

By implementing this additional predictability and stability check, we are requiring that the prioritized loci/interactions meet a higher standard, with the hope that this ultimately generates more reliable (albeit more conservative) experimental recommendations.

In addition to the provided summary of results,

  • Under the siRF Interaction Table tab, we provide the full siRF locus-level interaction table output for each binarization threshold (Figures 6.19, 6.21, and 6.23). This table includes several metrics for evaluating the stability and strength of the interaction. For details on these metrics, we refer to Kumbier et al. (2023).
    • For comparison, we also provide the analogous siRF output for interactions at the SNV level (Figures 6.20, 6.22, and 6.24). Here, we see that if we do not perform the SNV-to-locus aggregation, the stability scores for the SNV-level interactions are very close to 0. This means that the siRF-identified SNV-level interactions rarely appear when siRF is refitted using different bootstrapped training samples. As discussed previously, this instability is partially due to the correlation among SNVs and the weak phenotypic signal. This high instability also motivates the need for an alternative approach via our new importance score.
  • Under the Local Stability Importance Plots - Interactions and Local Stability Importance Plots - Loci, we provide visualizations of the density distribution of local stability importance scores between the low and high LVMi groups as well as the frequency distribution of SNVs used in the siRF fit (i.e., which SNVs occurred most frequently in the decision paths across the siRF fit).
    • In the density distribution of local stability importance scores, observable differences between the low and high LVMi groups are evidence that the genetic locus or interaction between loci is important for differentiating between individuals with high versus low LVMi. The larger the difference, the greater the importance of the locus or interaction between loci.
    • In the SNV frequency distributions, we show the frequency of occurrence for each SNV or SNV pair in the siRF fit. This is the number of decision paths for which the SNV or SNV pair appeared in the siRF fit. SNVs or SNV pairs with the highest number of occurrences in the RF decision paths (y-axis) contributed the most to the overall locus/interaction’s importance in the siRF fit.

Summary

Figure 6.17: Summary of the validation prediction performance from siRF across various LVMi binarization thresholds.

Figure 6.18: Summary of the lo-siRF permutation test results across various LVMi binarization thresholds including the test statistic (i.e., difference in local feature stability scores between the high and the low LVMi groups (SD in parentheses) and the resulting nominal p-values. Blank cells indicate that the locus/interaction was not selected for testing for the given binarization threshold. Loci/interactions are ranked according to the mean nominal p-value across all three binarization thresholds. Interactions between genetic loci are highlighted in blue.

siRF Interaction Table

0.15

Figure 6.19: Summary of the siRF locus-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.15). For all metrics excluding the nominal lo-siRF p-value, higher values indicate a stronger interaction. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Figure 6.20: Summary of the siRF SNV-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.15). Stability scores for all interactions are close to 0, suggesting unreliable SNV-level interactions. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

0.2

Figure 6.21: Summary of the siRF locus-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.2). For all metrics excluding the nominal lo-siRF p-value, higher values indicate a stronger interaction. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Figure 6.22: Summary of the siRF SNV-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.2). Stability scores for all interactions are close to 0, suggesting unreliable SNV-level interactions. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

0.25

Figure 6.23: Summary of the siRF locus-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.25). For all metrics excluding the nominal lo-siRF p-value, higher values indicate a stronger interaction. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Figure 6.24: Summary of the siRF SNV-level interaction table output for the binarized LVMi phenotype (binarization threshold = 0.25). Stability scores for all interactions are close to 0, suggesting unreliable SNV-level interactions. Details regarding these metrics in the siRF interaction table output can be found in Kumbier et al. (2018).

Local Stability Importance Plots - Interactions

0.15

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.25: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.26: Frequency of occurrence of SNV-SNV combinations in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.15). SNV-SNV combinations with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level interaction importance in the siRF fit.

0.2

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.27: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.28: Frequency of occurrence of SNV-SNV combinations in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.2). SNV-SNV combinations with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level interaction importance in the siRF fit.

0.25

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.29: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed interaction between loci (specified by subplot) that passed the siRF stability filter. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.30: Frequency of occurrence of SNV-SNV combinations in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.25). SNV-SNV combinations with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level interaction importance in the siRF fit.

Local Stability Importance Plots - Loci

0.15

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.31: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.15) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.32: Frequency of occurrence of SNVs in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.15). SNVs with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level importance in the siRF fit. SNVs are ordered on the x-axis by genomic location.

0.2

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.33: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.2) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.34: Frequency of occurrence of SNVs in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.2). SNVs with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level importance in the siRF fit. SNVs are ordered on the x-axis by genomic location.

0.25

Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.35: Distribution of local stability importance scores between the high and low LVMi groups (binarization threshold = 0.25) for each signed locus (specified by subplot). Here, we show only the top 25 signed loci, ranked by their average local stability importance scores. The nominal p-value from the permutation test, assessing distributional differences between the high and low LVMi groups, is provided in the top right corner of each subplot.

Figure 6.36: Frequency of occurrence of SNVs in the siRF fit for the binarized LVMi phenotype (binarization threshold = 0.25). SNVs with the highest number of occurrences in the siRF decision paths contribute the most to the overall locus-level importance in the siRF fit. SNVs are ordered on the x-axis by genomic location.

Advantages of Signed Information

Though the signed information is not pertinent to our goal of prioritizing/recommending candidate markers for experiments, the signed information from siRF provides more granular information that can improve our interpretation of the fit. To see this, suppose that we did not keep track of the sign of the feature when splitting (i.e., that we do not keep track of whether we split on low or high values of the feature). Suppose also that we would like to measure the importance of feature \(X_1\), which was used as the first (root) split in tree \(T\). In the first step in our new importance score computation, we compute the local stability importance (LSI) score of \(X_1\) for each individual \(i\). If we do not keep track of the sign of the \(X_1\) split, then \(X_1\) appears on every individual’s decision path so that \(LSI_T(X_1, i) = 1\) for every individual \(i\). In the next step of our new importance score computation, we perform a permutation test to assess whether there is a difference in the LSI scores for individuals with high LVMi and those with low LVMi. Since \(LSI_T(X_1, i) = 1\) for every \(i\), this permutation test will return a nominal p-value of 1. This suggests that \(X_1\) is an unimportant feature in this model. However, this is counterintuitive given that \(X_1\) was split on first in the tree and should be considered one of the most important features in this tree. By keeping track of the signed information of the splits as done in siRF, we can utilize this more granular information to mitigate the issue discussed above and improve our interpretation of the siRF fit.

Moreover, to facilitate the interpretation of this signed information, it can be beneficial to aggregate SNV features that are positively correlated (as opposed to negatively correlated) into a single locus (or group). Since the encoding of SNVs as a value taking on 0, 1, or 2 is rather arbitrary (e.g., a value of 0 can be re-encoded to take on the value of 2 by changing the reference allele), we can choose the encoding of the SNV to try to avoid strong negative correlations within a locus. More specifically, for each genetic locus which consists of SNVs \(X_1, \ldots, X_g\), we choose to “flip” the encoding of the SNV \(X_j\) (\(j = 2, \ldots, g\)) if the Pearson correlation between the observed values of \(X_j\) and \(X_1\) is below -0.15. Here, we use the term “flip” to mean the application of the function that maps 0 to 2, 1 to 1, and 2 to 0. This correlation threshold of -0.15 was chosen by visually inspecting the resulting pairwise correlations between \(X_i\) and \(X_j\) for all \(i, j = 1, \ldots, g\) and checking that these pairwise correlations are not strongly negative. However, while we focus on the lo-siRF prioritization results using this correlation threshold of -0.15, the results appear to be robust to other reasonable correlation threshold choices (e.g., -0.05, -0.25). Further analysis and improvements to this procedure are very interesting for future work.

7 Non-hypertensive Analysis

Overview

The lo-siRF analysis thus far has not accounted for the possibility of pleiotropy, particular between LV mass and blood pressure given the known connections between LV hypertrophy and hypertension (Yildiz et al. 2020). To evaluate this possibility of pleiotropic effects of the identified variants on both LV mass and blood pressure, we conducted two analyses.

  1. We assessed the marginal association between each of the lo-siRF-prioritized variants and hypertension (see Association between SNVs and Hypertension tab).
  2. We repeated the lo-siRF analysis using only the subset of UK Biobank individuals who were not reported to have hypertension (see Lo-siRF Results Summary tab).

Here, we define hypertensive diseases as anyone with self-reported hypertension, high blood pressure as diagnosed by a doctor, or any ICD10 billing code diagnosis in I10-I16. Out of the 29,661 UK Biobank participants in the original lo-siRF analysis, 7,371 individuals had hypertension, leaving 22,290 individuals for the non-hypertensive analysis.

Association between SNVs and Hypertension

To assess their marginal association with hypertension, we fit a separate logistic regression model for each of the 1405 GWAS-filtered SNVs, regressing hypertension (i.e., a binary indicator of whether or not one has hypertension) on the genotype of the SNV, while adjusting for the first five principal components of ancestry, sex, age, height, and body weight.

Overall, we found that none of the 1405 SNVs met the genome-wide (p < 5E-8) nor the suggestive (p < 1E-5) significance level (Figure 7.1 and Figure 7.2). Given our interest in the lo-siRF-prioritized interactions, which involve the TTN, CCDC141, IGF1R, and LOC157273;TNKS loci, we highlight the SNVs in each locus with the smallest p-values:

  • TTN: rs35112591 (p = 0.0328)
  • CCDC141: rs6725028 (p = 0.0403)
  • IGF1R: rs62024491 (p = 0.376)
  • LOC157273;TNKS: rs73185221 (0.0491)

The top lo-siRF-prioritized variants in each loci (see Figure 2f in Q. Wang et al. (2023)) exhibited even weaker marginal associations with hypertension;

  • TTN: rs66733621 (p = 0.776)
  • CCDC141: rs7591091 (p = 0.446)
  • IGF1R: rs62024491 (p = 0.376)
  • LOC157273;TNKS: rs6999852 (0.304)

We note however that the MIR588;RSPO3 locus with lead SNV rs2022479 gave the smallest p-value of 5E-5. This, in combination with the findings in the non-hypertension lo-siRF analysis next, may suggest a possible contribution of the MIR588;RSPO3 locus on mediating LV hypertrophy through regulating blood pressure.

Manhattan plot for the association between the 1405 GWAS-filtered SNVs used in the original lo-siRF analysis and hypertension.

Figure 7.1: Manhattan plot for the association between the 1405 GWAS-filtered SNVs used in the original lo-siRF analysis and hypertension.

Figure 7.2: List of top 100 SNVs (out of the 1405 GWAS-filtered SNVs used in the original lo-siRF analysis) with the highest association with hypertension. rsID = rsID of the SNV. Chr = Chromosome. Pos = Position on hg19. Lo-siRF Locus = assigned locus of the variant in the original lo-siRF analysis. p = P-value measuring the association between the SNV and hypertension.

Non-hypertensive Lo-siRF Results Summary

Using the same set of 1405 GWAS-filtered SNVs as in the original lo-siRF analysis, we repeated steps 2-4 of the lo-siRF analysis using only the non-hypertension UK Biobank cohort.

  • In Figure 7.3, we confirm that the siRF fit on the non-hypertensive cohort performs better than random guessing and satisfies the prediction check according to the PCS framework (Yu and Kumbier 2020). We thus choose to proceed with interpreting the siRF fit.
  • Overall, we found that the top 3 interactions between loci from our original lo-siRF analysis — namely, CCDC141-IGF1R, CCDC141-TTN, and CCDC141-LOC157273;TNKS — were again prioritized by lo-siRF when excluding the hypertensive individuals. That is, each of the aforementioned interactions yielded a nominal lo-siRF p-value less than our pre-specified threshold of 0.1 (in fact, all were < 0.01) for each of the three binarization thresholds (see Figure 7.4 below). This is to say that the top lo-siRF-prioritized interactions are stable with respect to the inclusion or exclusion of hypertensive individuals and provides evidence that these interactions are not solely mediating LV hypertrophy through the regulation of blood pressure.
  • All of the previously prioritized loci, with the exception of the MIR588;RSPO3 locus, were also prioritized in this non-hypertensive analysis. While the nominal lo-siRF p-value for the MIR588;RSPO3 locus was 0.019 and 0.007 for the 20% and 25% binarization thresholds, the nominal lo-siRF p-value was 0.187 (> 0.1 threshold) for the 15% binarization threshold and thus deemed not stable and was not prioritized in the non-hypertensive lo-siRF analysis. Though the MIR588;RSPO3 locus almost met the prioritization criteria here, this result, combined with the suspect marginal association results, suggests a possibility of pleiotropic locus contributing to variations of both blood pressure and LV mass.
  • We provide the full list of loci and interactions between loci from the non-hypertensive lo-siRF analysis in Figure 7.5. This list includes many loci and interactions that were not stable in the original lo-siRF analysis.

Figure 7.3: Summary of the validation prediction performance from siRF on the non-hypertensive cohort across various LVMi binarization thresholds.

Figure 7.4: Summary of the non-hypertensive lo-siRF permutation test results across various LVMi binarization thresholds including the test statistic (i.e., difference in local feature stability scores between the high and the low LVMi groups (SD in parentheses) and the resulting nominal p-values. Results are shown for the loci/interactions that were previously prioritized in the original lo-siRF analysis (including both hypertensive and non-hypertensive individuals). Loci/interactions are ranked according to the mean nominal p-value across all three binarization thresholds. Interactions between genetic loci are highlighted in blue. This table is a subset of the table below.

Figure 7.5: Summary of the non-hypertensive lo-siRF permutation test results across various LVMi binarization thresholds including the test statistic (i.e., difference in local feature stability scores between the high and the low LVMi groups (SD in parentheses) and the resulting nominal p-values. Blank cells indicate that the locus/interaction was not selected for testing for the given binarization threshold. Loci/interactions are ranked according to the mean nominal p-value across all three binarization thresholds. Interactions between genetic loci are highlighted in blue.

8 Comparison to Existing Methods

Epistasis Detection Methods

In this section, we compare the lo-siRF-prioritized interactions between loci to those interactions prioritized by other existing epistasis detection methods, namely, an exhaustive pairwise interaction search via linear (or logistic) regression, MAPIT (Crawford et al. 2017), and a locus-level version of MAPIT where we combined MAPIT and gene set enrichment analysis (GSEA) (Subramanian et al. 2005; Mootha et al. 2003).

Regression-based pairwise interaction scan

Below, we present the results from conducting an exhaustive pairwise interaction scan using linear (or logistic) regression over all GWAS-filtered SNVs with a minor allele frequency > 0.05. In this exhaustive interaction search, there are four different transformations of the LVMi response/phenotype that are of interest — namely, the rank-based inverse normal-transformed (RINT) LVMi (fitted using linear regression) and the binarized LVMi at three different thresholds (0.15, 0.2, and 0.25) (fitted using logistic regression). Details regarding the methodology can be found in Q. Wang et al. (2023).

  • In Figure 8.1, we examined the stability of the top ranked SNV-SNV interactions (i.e., those with the smallest p-values for the interaction term) across the different choices of LVMi response (i.e., RINT or one of the binarized versions). While there is some positive correlation across the different binarization runs, we found that there is very little correlation between the prioritized interactions when using the RINT-transformed LVMi versus the binarized LVMi as the response.
    • We note that the exhaustive interaction search was also conducted using all 1405 GWAS-filtered SNVs without the minor allele frequency filter. However, this led to even greater instability. We hence omit these results and focus on the results after restricting to SNVs with a minor allele frequency > 0.05.
  • In Figure 8.2, we provide a table of the SNV-SNV interactions and their corresponding interaction term p-values for each choice of LVMi response. We show only those SNV-SNV interactions with a p-value < 0.01 for at least one of the LVMi responses.
    • We note that none of the SNV-SNV interactions met the \(\alpha = 0.05\) significance threshold after performing a Bonferroni multiple testing adjustment.
    • Still, one could in theory use the p-values for ranking SNV-SNV interactions. For the unbinarized RINT-transformed LVMi response, the top interaction was between rs10227393 (chromosome 7; TPK1;CNTNAP2 locus) and rs8076248 (chromosome 17; CFAP52 locus). For the binarized LVMi response using both the 15% and 25% thresholds, the top interaction was between rs3176323 (chromosome 6; CDKN1A locus) and rs12795076 (chromosome 11; KIRREL3 locus). To our knowledge, these loci are not known to be closely related to hypertrophy. Only for the binarized LVMi response with the 20% threshold do we obtain a top interaction involving one of the lo-siRF-prioritized loci. Here, the top interaction is between rs12618871 (chromosome 2; CCDC141 locus) and rs9267356 (chromosome 6; MICB locus).

These differences in the top interactions across the different LVMi responses further highlight the instability of the regression-based pairwise interaction scan. This instability poses issues in interpreting results, as it can be unclear which results to trust. We suspect that at least part of the instability is a result of the low signal-to-noise ratio in this problem and highlights the need for more robust and stability-driven methods, such as lo-siRF, for detecting epistasis in low signal-to-noise regimes.

**Pair plot of the LVMi interaction effect p-values from an exhaustive regression-based SNVxSNV interaction scan using different transformations of the LVMi phenotype.** The transformations of interest include the rank-based inverse normal-transformed LVMi and the binarized LVMi using three different binarization thresholds (15%, 20%, 25%). The x- and y-axes show the interaction effect p-values after a -log10 transformation. Each point represents an SNV-SNV pair. We observe that the interaction effect p-values are generally unstable and depend on the choice of transformation of the phenotype (or response).

Figure 8.1: Pair plot of the LVMi interaction effect p-values from an exhaustive regression-based SNVxSNV interaction scan using different transformations of the LVMi phenotype. The transformations of interest include the rank-based inverse normal-transformed LVMi and the binarized LVMi using three different binarization thresholds (15%, 20%, 25%). The x- and y-axes show the interaction effect p-values after a -log10 transformation. Each point represents an SNV-SNV pair. We observe that the interaction effect p-values are generally unstable and depend on the choice of transformation of the phenotype (or response).

Figure 8.2: List of SNV-SNV interactions from an exhaustive regression-based SNVxSNV interaction scan using different transformations of the LVMi phenotype. The transformations of interest include the rank-based inverse normal-transformed LVMi and the binarized LVMi using three different binarization thresholds (15%, 20%, 25%). The table sorts the SNV-SNV interactions based on the mean p-value across the different transformations of the LVMi phenotype. To sort the SNV-SNV interactions based upon their p-value from a particular transformation, please use the toggles next to the column names. Only interactions that yielded a p-value < 0.01 for at least one transformation of the LVMi phenotype are shown for brevity.

MAPIT

Given the instabilities observed in the exhaustive regression-based interaction search, we applied MAPIT (Crawford et al. 2017) to our dataset as an additional comparison method. At a high-level, MAPIT aims to identify variants with non-zero marginal epistatic effects, defined as the total pairwise interaction effect between the given variant and all other variants in the data.

Similar to before, we used the GWAS-filtered SNVs with minor allele frequency > 0.05 as input to MAPIT. For the response, we used the rank-based inverse normal-transformed LVMi only since the MAPIT extension to binary traits has not yet been implemented. Details regarding the methodology can be found in Q. Wang et al. (2023).

  • Note: we also tried applying MAPIT to the full set of 1405 GWAS-filtered SNVs (without the additional minor allele frequency filter). However, the resulting top SNVs were predominantly those with the smallest minor allele frequencies, and we omit these results.

The top 5 SNVs from MAPIT with the smallest p-values were located in the MAT2B;LINC02143, MICB, BRMS1L;LINC00609, and CDKN1A loci (Figure 8.3). Interestingly, the highest-ranked SNVs from the CCDC141, TTN, and IGF1R loci were ranked 109 (p = 0.028), 75 (p = 0.003), and 87 (p = 0.011), respectively (compared to p < 8E-5 for the top 5 SNVs), according to MAPIT.

As is, the results from MAPIT and lo-siRF are not directly comparable since they are operating at different biological scales (i.e., MAPIT aims to identify epistatic variants while lo-siRF aims to identify epistatic loci). Variant-level approaches are known to be under-powered in traits where the effect of each variant is very small and/or noisy while group-level (or locus-level) approaches aggregate these signals across a collection of variants in hope of detecting more stable and biologically-relevant loci. In addition to this difference, there are a number of other potential reasons why MAPIT and lo-siRF may yield different, but non-contradictory results. For example, MAPIT and lo-siRF assume different underlying model assumptions and may capture different forms of interactions. In short, MAPIT encodes interactions as pairwise multiplicative effects (more typical in the statistical epistasis literature) whereas lo-siRF takes a more machine learning approach, encoding pairwise and higher-order interactions through decision paths (or boolean thresholding operations) in a decision tree. Other potential differences may stem from the different handling of variants with minor allele frequencies below 0.05 or the slightly different phenotypes used (i.e., lo-siRF used the binarized LVMi phenotype while MAPIT unfortunately requires a continuous phenotype and thus used the rank-based inverse normal-transformed LVMi).

Figure 8.3: Top epistatic variants from MAPIT, ranked by p-value. We show only the epistatic variants with p-value < 0.05. rsID = rsID of the variant. Chr = Chromosome. Pos = Position on hg19. Lo-siRF Locus = assigned locus of the variant in the lo-siRF analysis. P-value = p-value from MAPIT.

MAPIT+GSEA

Since the results of MAPIT and lo-siRF are on different biological scales (i.e., SNVs versus loci), we also conducted a locus-level analysis using MAPIT (Crawford et al. 2017) in conjunction with gene set enrichment analysis (GSEA) (Subramanian et al. 2005; Mootha et al. 2003). In this pipeline, we took the union of the top 10,000 GWAS hits from PLINK and BOLT-LMM, ran MAPIT on these SNVs to obtain a ranked list of SNVs according to their MAPIT p-values, and then ran GSEA on this ranked list to identify loci that are enriched at the top of this ranked list. The results of this MAPIT+GSEA analysis are provided below. We highlight three notable findings from this analysis: When ranking the loci by their normalized enrichment score,

  • The top-ranked locus (by MAPIT+GSEA) was the intergenic region between IGFBP3 and LOC730338 (denoted as IGFBP3;LOC730338). IGFBP3 encodes an insulin-like growth factor (IGF) binding protein, which is known to interact closely with IGF1R (Baxter 2023).
  • The three interacting loci, prioritized by lo-siRF, were all ranked within the top 30 by the MAPIT+GSEA analysis (LOC157273;TNKS: rank 2; IGF1R: rank 7; TTN: rank 23; CCDC141: rank 28 out of 863 total loci). Their corresponding nominal p-value, FDR q-value, and FWER p-value were 0 (or < 1e-3 given that we used 1000 permutations). We note however that the magnitudes of these p-values are not directly comparable to those from lo-siRF given the different modeling assumptions.
  • Aside from IGFBP3;LOC730338, LOC157273;TNKS, IGF1R, and ADAMTS16, other loci ranked in the top 10 by MAPIT+GSEA do not appear to be closely related to cardiac hypertrophy or cardiovascular diseases in the current literature. Moreover, except for IGFBP3;LOC730338, LOC157273;TNKS, IGF1R, ADAMTS16, and FBXL17, the remaining 5 loci in the top 10 were not among the top 1000 GWAS-filtered SNVs used in the original lo-siRF analysis. In other words, half of the top 10 loci identified by MAPIT+GSEA did not show strong marginal associations with LVMi. There is no expectation that variants involved in epistasis also have large marginal effects, so the lack of marginal associations alone is not particularly concerning. However, combined with the observation that the primary biological functions of these loci are not directly related to the heart, we are uncertain whether these epistatic findings would be validated in wet lab experiments.

Overall, in comparing lo-siRF with MAPIT+GSEA, we are encouraged to see that both methods identified loci like LOC157273;TNKS, IGF1R, TTN, and CCDC141. On the other hand, MAPIT+GSEA also identified loci deprioritized by lo-siRF, which turn out to lack biological relevance to cardiac diseases. These discrepancies may arise from the fundamental differences between the computational frameworks of lo-siRF and MAPIT+GSEA, which make direct comparisons challenging. First, MAPIT (or MAPIT+GSEA) outputs single SNVs or loci with marginal epistatic effects while lo-siRF directly identifies specific interactions between genetic loci. Secondly, lo-siRF and MAPIT are based on different modeling assumptions, so their definitions of epistasis are not directly comparable. Lastly, since performing GSEA after MAPIT has not been extensively studied, it is unclear whether the observed strengths and weaknesses of MAPIT+GSEA arise from MAPIT, GSEA, or their combination. It also remains uncertain whether using alternative SNV-to-locus grouping methods (in place of GSEA) would improve upon the epistatic loci rankings.

Figure 8.4: Top epistatic loci from MAPIT+GSEA, ranked by normalized enrichment score. We show only the epistatic loci with nominal p-value < 0.05.

Marginal Gene-based Methods

In this section, we compare the lo-siRF-prioritized loci to those loci prioritized by other existing marginal set-based methods, such as MAGMA (Leeuw et al. 2015) (Figures 8.5-8.6) and SKAT-O (Lee et al. 2012) (Figure 8.7). Details regarding the methodology can be found in Q. Wang et al. (2023).

Notably, we found that while lo-siRF prioritized IGF1R as one of its top recommended loci, SKAT-O and MAGMA did not rank IGF1R very highly. According to SKAT-O, IGF1R yielded a p-value of 1.0E-5 and was the 45th ranked locus, and using MAGMA, IGF1R yielded a p-value of 0.002 and was the 146th ranked locus. Given our extensive validation efforts demonstrating the importance of IGF1R for left ventricular hypertrophy, we view this as an interesting example where lo-siRF is able to identify important loci that are not necessarily prioritized by other methods, even for marginal effects.

Manhattan plot of the gene-based test as computed by MAGMA. The genome-wide significance level is shown by the red dotted line.

Figure 8.5: Manhattan plot of the gene-based test as computed by MAGMA. The genome-wide significance level is shown by the red dotted line.

Figure 8.6: Top genes from MAGMA, ranked by p-value. We show only the top 200 genes. Locus = Gene symbol. Chr = Chromosome. Start = Start position on hg19. Stop = Stop position on hg19. Z = Z-statistic from MAGMA. P-value = p-value from MAGMA.

Figure 8.7: Top genes from SKAT-O, ranked by p-value. Locus = Name of locus from lo-siRF analysis. Chr = Chromosome. P-value = p-value from SKAT-O.

9 Lo-siRF Permutation Test Simulations

In this section, we conduct several simulations to investigate the performance and demonstrate the validity of the permutation p-values from lo-siRF.

P-value Calibration Simulations

Calibration of p-values under null model: In the first set of simulations, we aimed to assess whether the permutation p-values are calibrated under the null model where no epistasis is present. To this end, we simulated binary responses \(y\) from a null, purely-noise model, where \(y \sim Bernoulli(1/2)\). Under this null simulation setup, we generated covariates \(X\) from three different data-generating processes:

  1. Independent normal: \(X_{ij} \stackrel{iid}{\sim} N(0, 1)\) for \(i = 1, \ldots, n\) and \(j = 1, \ldots, p\).
  2. Independent SNPs: \(X_{ij}\) iid from \(\{0, 1, 2\}\) with uniform probabilities for \(i = 1, \ldots, n\) and \(j = 1, \ldots, p\).
  3. Real-world SNPs: The \(n \times p\) matrix \(X\) is taken to be the GWAS-filtered SNV matrix used in lo-siRF. In this case, we we randomly subsampled the features and the columns to meet the desired dimensions of \(n\) and \(p\).

Under each of these three settings, we ran the simulated data through a simplified lo-siRF pipeline, where we:

  1. Split the data into two partition (2/3 training and 1/3 validation).
  2. Fit siRF on the training data to obtain a list of candidate interactions.
  3. For each of the interactions from step 2, evaluate the local stability importance scores and compute the associated permutation p-value using the validation data.

In simulations (A) and (B), we searched for interactions at the level of individual features (or SNVs), rather than a group of features (or genes). This was done to simplify the simulation setup and interpretation of results, given that the features were simulated independently. For simulation setup (C), we leveraged the same SNV-to-gene mapping used previously in lo-siRF and searched for interactions at the gene level.

We also note that the simplified lo-siRF pipeline omits the interaction filtering step based upon their siRF stability scores. This was done because the interaction filtering step excludes almost all non-relevant candidate interactions under the simulation setup. In particular, under the null simulation model, the interaction filtering (using the recommended thresholds from the original siRF paper (Kumbier et al. 2023)) removed all but 2 interactions across 200 simulated data replicates. Given our goal of assessing whether the permutation p-values are calibrated, we will focus our evaluation on the permutation p-values from all candidate interactions in this setting regardless of whether the interactions passed the stability filtering.

Results: In Figure 9.1 below, we plot the proportion of rejected null hypotheses across different significance levels \(\alpha\) under the aforementioned null simulation setup. We found that the observed type I error of our permutation test closely aligns with the significance level \(\alpha\), thereby confirming that the p-values are calibrated. Moreover, these results hold across different sample sizes, number of features, and all three data-generating processes for X.

Proportion of rejected null hypotheses across varying significance levels under the null simulation response model are represented by the solid black line. Dotted line represents a perfectly calibrated hypothesis test (i.e., the y = x line). Each row corresponds to a different data-generating process for X, and each column corresponds to a different choice of number of samples. Results are aggregated across 200 simulation replicates.

Figure 9.1: Proportion of rejected null hypotheses across varying significance levels under the null simulation response model are represented by the solid black line. Dotted line represents a perfectly calibrated hypothesis test (i.e., the y = x line). Each row corresponds to a different data-generating process for X, and each column corresponds to a different choice of number of samples. Results are aggregated across 200 simulation replicates.

Marginal and Interaction Effect Simulations

Marginal and Interaction Effect Simulations: Moving beyond this basic calibration investigation and the null, purely-noise model, we were more interested in studying the broader performance of lo-siRF and the permutation test. To this end, we conducted two additional simulations using boolean-type rules. We note that the boolean-type rules were chosen as they have been extensively studied in previous RF-based work and are thought to closely resemble the switch-like and stereospecific nature of interactions among biomolecules (Nelson, Lehninger, and Cox 2008; Kumbier et al. 2023; Behr et al. 2020). Specifically, we first simulated the \(X\) data from independent SNVs, where \(X_{ij}\) is simulated iid from \(\{0, 1, 2\}\) with uniform probabilities. Next, we simulated binary responses \(y \mid X \sim Bernoulli(p(X))\) via:

  1. Marginal effect model: \(p(X) = 0.4 \cdot \mathbf{1}\{X_1 > 0\} + 0.4 \cdot \mathbf{1}\{X_2 > 0\}\)
    • In this model, there are no true interactions.
  2. Interaction effect model: \(p(X) = 0.4 \cdot \mathbf{1}\{X_1 > 0\} \mathbf{1}\{X_2 > 0\} + 0.4 \cdot \mathbf{1}\{X_3 > 0\} \mathbf{1}\{X_4 > 0\}\)
    • In this model, the true interactions are \(X_1:X_2\) and \(X_3:X_4\).

We set the number of features to 100 and varied the number of samples across n = 1000, 1500, 2000. For each simulation model and choice of sample size, we ran 200 simulation replicates.

Results: The simulation results are summarized in Table 9.2 below. In what follows, we define “partial interaction” as a candidate interaction that involves at least one true signal feature from an interaction that appeared in the simulation model — specifically, at least one of \(X_1\) or \(X_2\) in the marginal effect simulation (D), or at least one of \(X_1\), \(X_2\), \(X_3\), or \(X_4\) in the interaction effect simulation (E). We define “true interaction” as a candidate interaction that involves both \(X_1\) and \(X_2\) or both \(X_3\) and \(X_4\) in the interaction effect simulation.

The main takeaways from these simulations are:

  1. Under both the marginal effect and interaction effect scenarios, the candidate interactions from siRF almost always include at least one true signal feature (and equivalently, is a partial interaction).

    • Specifically, under both the marginal effect (D) and interaction effect (E) scenarios, over 99% of the candidate interactions identified by siRF were found to be “partial interactions” (the 5th column in Table 9.2). Moreover, under the interaction effect (E) simulation, over 38% of the candidate interactions identified by siRF were “true interactions” (the 4th column in Table 9.2).
  2. The interaction filtering step within siRF, where we filter out candidate interactions that do not meet the siRF stability thresholds, is both necessary and effective at distinguishing between interactions and marginal effects.

    • First, the siRF interaction filtering is necessary to differentiate between interactions and marginal effects since the permutation test itself is not designed to distinguish between “true interactions” and “partial interactions.”

      • Because the permutation test within lo-siRF formally assesses whether the local stability importance of an interaction differs between the high and low LVMi groups, any candidate interaction involving at least one true signal feature (i.e., any partial interaction) is expected to show a difference between the two groups and result in a significant p-value. Our results support this expectation. In both the interaction and marginal simulation models, an overwhelming majority (>99%) of the permutation tests led to a significant p-value (p < 0.05) (the last column in Table 9.2). This is expected since each of these tested interactions was a partial interaction and involved at least one true signal feature (the 8th column in Table 9.2).
      • We thus relied on the siRF interaction filtering step to distinguish between marginal and true interaction effects. This siRF interaction filtering step is detailed in the Methods section Lo-siRF step 4.3: Permutation test for difference in local stability importance scores in Q. Wang et al. (2023). Specifically, the feature selection dependence threshold (discussed in greater detail in the original siRF paper (Kumbier et al. 2023)) was originally designed to differentiate between additive (e.g., marginal) and non-additive (e.g., interaction) effects. This metric showed strong performance in empirical simulations from the original siRF paper.
    • As in the original siRF paper, the siRF interaction filtering demonstrated similarly strong effectiveness for distinguishing between true interactions and true marginal effects under our simulation setup.

      • In particular, under the interaction simulation model, the siRF interaction filtering step reduced the number of interactions from over 3000 candidates (the 3rd column in Table 9.2), of which \(\sim\) 40% were true interactions (4th column), to ~1300 candidates (6th column). Of these remaining \(\sim\) 1300 candidates, 87%, 99%, and 100% were true interactions in the n = 1000, 1500, and 2000 simulations, respectively (the 7th column).
      • Furthermore, under the marginal simulation model, the siRF interaction filtering step reduced the number of interactions from over 4400 candidates (the 3rd column in Table 9.2) to fewer than 100 candidates (4th column). That is, less than 2% of the candidate interactions remain after the siRF interaction filtering step in the marginal effect simulation setting.
    • Thus, even though the permutation test rejects most tests involving partial interactions, in lo-siRF, the permutation test occurs after the siRF interaction filtering, which we have shown to effectively eliminate the vast majority of non-signal or partial interactions.

Figure 9.2: Summary of marginal and interaction effect simulations. # Candidate Interactions from siRF: The total number of interactions identified by siRF before applying the stability filtering step. Prop. (Num.) of True Interactions in Candidate Set: The proportion (or number) of true interactions out of the total number of candidate interactions from siRF. Prop. (Num.) of Partial Interactions in Candidate Set: The proportion (or number) of partial interactions out of the total number of candidate interactions from siRF. Prop. (Num.) of Stable Interactions in Candidate Set: The proportion (or number) of interactions that passed the stability filter step out of the total number of candidate interactions from siRF. Prop. (Num.) of True Interactions in Stable Set: The proportion (or number) of true interactions out of the total number of interactions that passed the stability filter. Prop. (Num.) of Partial Interactions in Stable Set: The proportion (or number) of partial interactions out of the total number of interactions that passed the stability filter. # Interactions Rejected (p < 0.05): The number of stable (or tested) interactions with a permutation test p-value below 0.05.

10 Final Remarks

We reiterate that lo-siRF was originally developed as a first-stage recommendation (or hypothesis generation) tool within a broader pipeline in order to prioritize genetic loci and interactions between loci for downstream analyses and experimental validation. Importantly, the output of lo-siRF is a prioritization/ranking order, not a proper statistical test of significance. We rely on follow-up investigations and in this study rigorous gene-silencing experiments in order to validate the prioritized genetic loci and interaction between loci. With that, many of the modeling decisions and human judgment calls were made with this original use case in mind. For other use cases or problems, it is highly likely that different choices may be better suited. We also acknowledge that though many stability checks were conducted to help ensure that our conclusions are stable across different reasonable data and/or modeling perturbations, these stability checks are inevitably constrained by computational limitations, and additional stability analyses can be conducted. We hope that by documenting our modeling choices, stability analyses, and providing insights into our motivations/reasons, this may help to both clarify the limitations of our current work and to facilitate the trustworthy (veridical) use of lo-siRF (and variants thereof) in other scientific problems.

11 Bibliography

Allen, Ben, Morgan Lane, Elizabeth Anderson Steeves, and Hollie Raynor. 2022. “Using Explainable Artificial Intelligence to Discover Interactions in an Ecological Model for Obesity.” International Journal of Environmental Research and Public Health 19 (15): 9447.
Bai, Wenjia, Matthew Sinclair, Giacomo Tarroni, Ozan Oktay, Martin Rajchl, Ghislain Vaillant, Aaron M Lee, et al. 2018. “Automated Cardiovascular Magnetic Resonance Image Analysis with Fully Convolutional Networks.” Journal of Cardiovascular Magnetic Resonance 20 (1): 1–12.
Baxter, Robert C. 2023. “Signaling Pathways of the Insulin-Like Growth Factor Binding Proteins.” Endocrine Reviews 44 (5): 753–78.
Behr, Merle, Karl Kumbier, Aldo Cordova-Palomera, Matthew Aguirre, Euan Ashley, Atul J Butte, Rima Arnaout, Ben Brown, James Priest, and Bin Yu. 2020. “Learning Epistatic Polygenic Phenotypes with Boolean Interactions.” bioRxiv, 2020–11.
Bycroft, Clare, Colin Freeman, Desislava Petkova, Gavin Band, Lloyd T Elliott, Kevin Sharp, Allan Motyer, et al. 2018. “The UK Biobank Resource with Deep Phenotyping and Genomic Data.” Nature 562 (7726): 203–9.
Cliff, Ashley, Jonathon Romero, David Kainer, Angelica Walker, Anna Furches, and Daniel Jacobson. 2019. “A High-Performance Computing Implementation of Iterative Random Forest for the Creation of Predictive Expression Networks.” Genes 10 (12): 996.
Crawford, Lorin, Ping Zeng, Sayan Mukherjee, and Xiang Zhou. 2017. “Detecting Epistasis with the Marginal Epistasis Test in Genetic Mapping Studies of Quantitative Traits.” PLoS Genetics 13 (7): e1006869.
De Rosa, Arianna, Andrea Fontana, Tommaso Nuzzo, Martina Garofalo, Anna Di Maio, Daniela Punzo, Massimiliano Copetti, et al. 2022. “Machine Learning Algorithm Unveils Glutamatergic Alterations in the Post-Mortem Schizophrenia Brain.” Schizophrenia 8 (1): 8.
Du Bois, Delafield, and Eugene F Du Bois. 1916. “Clinical Calorimetry: Tenth Paper a Formula to Estimate the Approximate Surface Area If Height and Weight Be Known.” Archives of Internal Medicine 17 (6_2): 863–71.
Engel, David J, Allan Schwartz, and Shunichi Homma. 2016. “Athletic Cardiac Remodeling in US Professional Basketball Players.” JAMA Cardiology 1 (1): 80–87.
Fry, Anna, Thomas J Littlejohns, Cathie Sudlow, Nicola Doherty, Ligia Adamska, Tim Sprosen, Rory Collins, and Naomi E Allen. 2017. “Comparison of Sociodemographic and Health-Related Characteristics of UK Biobank Participants with Those of the General Population.” American Journal of Epidemiology 186 (9): 1026–34.
Harper, Andrew R, Anuj Goel, Christopher Grace, Kate L Thomson, Steffen E Petersen, Xiao Xu, Adam Waring, et al. 2021. “Common Genetic Variants and Modifiable Risk Factors Underpin Hypertrophic Cardiomyopathy Susceptibility and Expressivity.” Nature Genetics 53 (2): 135–42.
Hooker, Giles, Lucas Mentch, and Siyu Zhou. 2021. “Unrestricted Permutation Forces Extrapolation: Variable Importance Requires at Least One More Model, or There Is No Free Variable Importance.” Statistics and Computing 31: 1–16.
Khurshid, Shaan, Julieta Lazarte, James P Pirruccello, Lu-Chen Weng, Seung Hoan Choi, Amelia W Hall, Xin Wang, et al. 2023. “Clinical and Genetic Associations of Deep Learning-Derived Cardiac Magnetic Resonance-Based Left Ventricular Mass.” Nature Communications 14 (1): 1558.
Kumbier, Karl, Sumanta Basu, Erwin Frise, James B Brown, Susan Celniker, and Bin Yu. 2023. “Signed Iterative Random Forests to Identify Enhancer-Associated Transcription Factor Binding.” arXiv Preprint arXiv:1810.07287.
Lee, Seunggeun, Mary J Emond, Michael J Bamshad, Kathleen C Barnes, Mark J Rieder, Deborah A Nickerson, David C Christiani, Mark M Wurfel, and Xihong Lin. 2012. “Optimal Unified Approach for Rare-Variant Association Testing with Application to Small-Sample Case-Control Whole-Exome Sequencing Studies.” The American Journal of Human Genetics 91 (2): 224–37.
Leeuw, Christiaan A de, Joris M Mooij, Tom Heskes, and Danielle Posthuma. 2015. “MAGMA: Generalized Gene-Set Analysis of GWAS Data.” PLoS Computational Biology 11 (4): e1004219.
Loh, Po-Ru, George Tucker, Brendan K Bulik-Sullivan, Bjarni J Vilhjalmsson, Hilary K Finucane, Rany M Salem, Daniel I Chasman, et al. 2015. “Efficient Bayesian Mixed-Model Analysis Increases Association Power in Large Cohorts.” Nature Genetics 47 (3): 284–90.
Mbatchou, Joelle, Leland Barnard, Joshua Backman, Anthony Marcketta, Jack A Kosmicki, Andrey Ziyatdinov, Christian Benner, et al. 2021. “Computationally Efficient Whole-Genome Regression for Quantitative and Binary Traits.” Nature Genetics 53 (7): 1097–1103.
Meyer, Hannah V, Timothy JW Dawes, Marta Serrani, Wenjia Bai, Paweł Tokarczuk, Jiashen Cai, Antonio de Marvao, et al. 2020. “Genetic and Functional Insights into the Fractal Structure of the Heart.” Nature 584 (7822): 589–94.
Mizukoshi, Kei, Masaaki Takeuchi, Yasufumi Nagata, Karima Addetia, Roberto M Lang, Yoshihiro J Akashi, and Yutaka Otsuji. 2016. “Normal Values of Left Ventricular Mass Index Assessed by Transthoracic Three-Dimensional Echocardiography.” Journal of the American Society of Echocardiography 29 (1): 51–61.
Mootha, Vamsi K, Cecilia M Lindgren, Karl-Fredrik Eriksson, Aravind Subramanian, Smita Sihag, Joseph Lehar, Pere Puigserver, et al. 2003. “PGC-1\(\alpha\)-Responsive Genes Involved in Oxidative Phosphorylation Are Coordinately Downregulated in Human Diabetes.” Nature Genetics 34 (3): 267–73.
Nelson, David L, Albert L Lehninger, and Michael M Cox. 2008. Lehninger Principles of Biochemistry. Macmillan.
Niel, Clément, Christine Sinoquet, Christian Dina, and Ghislain Rocheleau. 2015. “A Survey about Methods Dedicated to Epistasis Detection.” Frontiers in Genetics 6: 285.
Pirruccello, James P, Alexander Bick, Minxian Wang, Mark Chaffin, Samuel Friedman, Jie Yao, Xiuqing Guo, et al. 2020. “Analysis of Cardiac Magnetic Resonance Imaging in 36,000 Individuals Yields Genetic Insights into Dilated Cardiomyopathy.” Nature Communications 11 (1): 2254.
Purcell, Shaun, Benjamin Neale, Kathe Todd-Brown, Lori Thomas, Manuel AR Ferreira, David Bender, Julian Maller, et al. 2007. “PLINK: A Tool Set for Whole-Genome Association and Population-Based Linkage Analyses.” The American Journal of Human Genetics 81 (3): 559–75.
Schaid, Daniel J, Wenan Chen, and Nicholas B Larson. 2018. “From Genome-Wide Associations to Candidate Causal Variants by Statistical Fine-Mapping.” Nature Reviews Genetics 19 (8): 491–504.
Subramanian, Aravind, Pablo Tamayo, Vamsi K Mootha, Sayan Mukherjee, Benjamin L Ebert, Michael A Gillette, Amanda Paulovich, et al. 2005. “Gene Set Enrichment Analysis: A Knowledge-Based Approach for Interpreting Genome-Wide Expression Profiles.” Proceedings of the National Academy of Sciences 102 (43): 15545–50.
Toloşi, Laura, and Thomas Lengauer. 2011. “Classification with Correlated Features: Unreliability of Feature Ranking and Solutions.” Bioinformatics 27 (14): 1986–94.
Visscher, Peter M, Naomi R Wray, Qian Zhang, Pamela Sklar, Mark I McCarthy, Matthew A Brown, and Jian Yang. 2017. “10 Years of GWAS Discovery: Biology, Function, and Translation.” The American Journal of Human Genetics 101 (1): 5–22.
Walker, Angelica M, Ashley Cliff, Jonathon Romero, Manesh B Shah, Piet Jones, Joao Gabriel Felipe Machado Gazolla, Daniel A Jacobson, and David Kainer. 2022. “Evaluating the Performance of Random Forest and Iterative Random Forest Based Methods When Applied to Gene Expression Data.” Computational and Structural Biotechnology Journal 20: 3372–86.
Wang, Kai, Mingyao Li, and Hakon Hakonarson. 2010. “ANNOVAR: Functional Annotation of Genetic Variants from High-Throughput Sequencing Data.” Nucleic Acids Research 38 (16): e164–64.
Wang, Qianru, Tiffany M Tang, Nathan Youlton, Chad S Weldy, Ana M Kenney, Omer Ronen, J Weston Hughes, et al. 2023. “Epistasis Regulates Genetic Control of Cardiac Hypertrophy.”
Watanabe, Kyoko, Erdogan Taskesen, Arjen Van Bochoven, and Danielle Posthuma. 2017. “Functional Mapping and Annotation of Genetic Associations with FUMA.” Nature Communications 8 (1): 1826.
Yildiz, Mehmet, Ahmet Afşin Oktay, Merrill H Stewart, Richard V Milani, Hector O Ventura, and Carl J Lavie. 2020. “Left Ventricular Hypertrophy and Hypertension.” Progress in Cardiovascular Diseases 63 (1): 10–21.
Yu, Bin. 2013. “Stability.”
Yu, Bin, and Karl Kumbier. 2020. “Veridical Data Science.” Proceedings of the National Academy of Sciences 117 (8): 3920–29. https://doi.org/10.1073/pnas.1901326117.
LS0tCnRpdGxlOiAiUENTIGRvY3VtZW50YXRpb24gZm9yIGxvdy1zaWduYWwgc2lnbmVkIGl0ZXJhdGl2ZSByYW5kb20gZm9yZXN0cyAobG8tc2lSRikiCiMgYXV0aG9yOiAiVGlmZmFueSBNLiBUYW5nIgpkYXRlOiAiU2VwdGVtYmVyIDI3LCAyMDI0IgpiaWJsaW9ncmFwaHk6IGJpYmxpb2dyYXBoeS5iaWIKaGVhZGVyLWluY2x1ZGVzOgogICAgLSBcdXNlcGFja2FnZXtmbG9hdH0KICAgIC0gXHVzZXBhY2thZ2V7YW1zbWF0aH0KICAgIC0gXHVzZXBhY2thZ2V7Z2Vuc3ltYn0Kb3V0cHV0OgogIHZ0aGVtZXM6OnZtb2Rlcm46CiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKcGFyYW1zOgogIGV2YWw6IGZhbHNlCi0tLQoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpvcHRpb25zKHdpZHRoID0gMTAwMDApCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gRkFMU0UsCiAgd2FybmluZyA9IEZBTFNFLAogIG1lc3NhZ2UgPSBGQUxTRSwKICBjYWNoZSA9IEZBTFNFLAogICMgZXZhbCA9IEZBTFNFLAogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLAogIGZpZy5wb3MgPSAiSCIsCiAgIyBmaWcuc2hvdyA9ICJob2xkIiwKICBmaWcuaGVpZ2h0ID0gMTIsCiAgZmlnLndpZHRoID0gMTAKKQoKbGlicmFyeShrbml0cikKbGlicmFyeShmb250YXdlc29tZSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkodnRoZW1lcykKbGlicmFyeSh2ZG9jcykKCnNvdXJjZShmaWxlLnBhdGgoIi4uIiwgImZ1bmN0aW9ucyIsICJwbG90LWZ1bmN0aW9ucy5SIiksIGNoZGlyID0gVCkKc291cmNlKGZpbGUucGF0aCgiLi4iLCAiZnVuY3Rpb25zIiwgImxvYWQtZnVuY3Rpb25zLlIiKSwgY2hkaXIgPSBUKQpzb3VyY2UoZmlsZS5wYXRoKCIuLiIsICJmdW5jdGlvbnMiLCAiZXZhbC1mdW5jdGlvbnMuUiIpLCBjaGRpciA9IFQpCgpvcHRpb25zKAogIGtuaXRyLmthYmxlLk5BID0gIk5BIiwKICBkcGx5ci5zdW1tYXJpc2UuaW5mb3JtID0gRkFMU0UKKQoKIyBzY3JvbGxhYmxlIHRleHQgb3V0cHV0CmxvY2FsKHsKICBob29rX291dHB1dCA8LSBrbml0cjo6a25pdF9ob29rcyRnZXQoIm91dHB1dCIpCiAga25pdHI6OmtuaXRfaG9va3Mkc2V0KG91dHB1dCA9IGZ1bmN0aW9uKHgsIG9wdGlvbnMpIHsKICAgIGlmICghaXMubnVsbChvcHRpb25zJG1heC5oZWlnaHQpKSB7CiAgICAgIG9wdGlvbnMkYXR0ci5vdXRwdXQgPC0gYygKICAgICAgICBvcHRpb25zJGF0dHIub3V0cHV0LAogICAgICAgIHNwcmludGYoJ3N0eWxlPSJtYXgtaGVpZ2h0OiAlczsiJywgb3B0aW9ucyRtYXguaGVpZ2h0KQogICAgICApCiAgICB9CiAgICBob29rX291dHB1dCh4LCBvcHRpb25zKQogIH0pCn0pCgpkaXNwbGF5X2ltYWdlIDwtIGZ1bmN0aW9uKGZuYW1lLCBjaHVua19pZHgsIGNhcHRpb24gPSAiJyciKSB7CiAgc3ViY2h1bmtpZnkoCiAgICBnID0ga25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoZm5hbWUpLCBpID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9IGNhcHRpb24sCiAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IiksCiAgICBvdGhlcl9hcmdzID0gIm91dC53aWR0aD0nMTAwJSciCiAgKQogIGNodW5rX2lkeCA8PC0gY2h1bmtfaWR4ICsgMQp9CgpzdWJjaHVua2lmeSA8LSBmdW5jdGlvbiguLi4pIHsKICB2dGhlbWVzOjpzdWJjaHVua2lmeSguLi4pCiAgY2F0KCJcblxuIikKfQoKY2h1bmtfaWR4IDwtIDEKZGF0YV9kaXIgPC0gZmlsZS5wYXRoKCIuLiIsICJkYXRhIikKcmVzX2RpciA8LSBmaWxlLnBhdGgoIi4uIiwgInJlc3VsdHMiKQp0YWJfcmVzX2RpciA8LSBmaWxlLnBhdGgocmVzX2RpciwgInRhYmxlcyIpCmZpZ19yZXNfZGlyIDwtIGZpbGUucGF0aChyZXNfZGlyLCAiZmlndXJlcyIpCnBoZW5vdHlwZXMgPC0gYygiTFZNaSIgPSAiaUxWTSIpCnBoZW5vdHlwZXNfYWxsIDwtIGMoIkxWTWkiID0gImlMVk0iLCAiTFZNIiA9ICJMVk0iKQpgYGAKCmBgYHtjc3MsIGVjaG89RkFMU0V9Ci5idG4tdG9vbGJhciB7CiAgZGlzcGxheTogbm9uZTsKfQoKLmZpZ3VyZSBwLmNhcHRpb24gewogIGZvbnQtc2l6ZTogOTAlOwogIHBhZGRpbmc6IDhweDsKfQoKLmZpZ3VyZSB7CiAgZGlzcGxheTogaW5oZXJpdDsKfQoKLnRoLWdyb3VwLWhlYWRlciB7CiAgcGFkZGluZzogNXB4ICFpbXBvcnRhbnQ7CiAgYm9yZGVyOiBub25lICFpbXBvcnRhbnQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgoudGgtZ3JvdXAtaGVhZGVyOmFmdGVyIHsKICBjb250ZW50OiAiIjsgLyogVGhpcyBpcyBuZWNlc3NhcnkgZm9yIHRoZSBwc2V1ZG8gZWxlbWVudCB0byB3b3JrLiAqLyAKICBkaXNwbGF5OiBibG9jazsgLyogVGhpcyB3aWxsIHB1dCB0aGUgcHNldWRvIGVsZW1lbnQgb24gaXRzIG93biBsaW5lLiAqLwogIG1hcmdpbjogMCBhdXRvOyAvKiBUaGlzIHdpbGwgY2VudGVyIHRoZSBib3JkZXIuICovCiAgd2lkdGg6IDk1JTsgLyogQ2hhbmdlIHRoaXMgdG8gd2hhdGV2ZXIgd2lkdGggeW91IHdhbnQuICovCiAgcGFkZGluZy10b3A6IDE0cHg7IC8qIFRoaXMgY3JlYXRlcyBzb21lIHNwYWNlIGJldHdlZW4gdGhlIGVsZW1lbnQgYW5kIHRoZSBib3JkZXIuICovCiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIGJsYWNrOyAvKiBUaGlzIGNyZWF0ZXMgdGhlIGJvcmRlci4gUmVwbGFjZSBibGFjayB3aXRoIHdoYXRldmVyIGNvbG9yIHlvdSB3YW50LiAqLwp9CgoudGgtZ3JvdXAtc3ViaGVhZGVyIHsKICBib3JkZXItdG9wOiBub25lICFpbXBvcnRhbnQ7Cn0KCi5jaXRhdGlvbiB7CiAgY29sb3I6ICMwMDk2ODg7Cn0KCi5jc2wtZW50cnkgewogIG1hcmdpbi1ib3R0b206IDAuNWVtOwp9CmBgYAoKCiMgT3ZlcnZpZXcgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtdm1vZGVybn0KCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KSW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSksIHdlIGRldmVsb3BlZCBhbiBlbmQtdG8tZW5kIHBpcGVsaW5lIHRvIGRlbW9uc3RyYXRlIHRoZSByb2xlIG9mIGVwaXN0YXNpcyBpbiB0aGUgZ2VuZXRpYyBjb250cm9sIG9mIGNhcmRpYWMgaHlwZXJ0cm9waHkuIApUaGlzIHBpcGVsaW5lIGNvbnNpc3RlZCBvZiBmb3VyIG1ham9yIHBoYXNlczogCigxKSB0aGUgZGVyaXZhdGlvbiBvZiBlc3RpbWF0ZXMgb2YgbGVmdCB2ZW50cmljdWxhciBtYXNzIHZpYSBkZWVwIGxlYXJuaW5nLAooMikgdGhlIGNvbXB1dGF0aW9uYWwgcHJpb3JpdGl6YXRpb24gb2YgZXBpc3RhdGljIGRyaXZlcnMgYmFzZWQgb24gZGF0YSBmcm9tIHRoZSBVSyBCaW9iYW5rIFtAYnljcm9mdDIwMTh1a10sIAooMykgZnVuY3Rpb25hbCBpbnRlcnByZXRhdGlvbiBvZiB0aGUgaHlwb3RoZXNpemVkIGVwaXN0YXRpYyBnZW5ldGljIGxvY2ksIGFuZCAKKDQpIGV4cGVyaW1lbnRhbCBjb25maXJtYXRpb24gb2YgZXBpc3Rhc2lzIGluIGNhcmRpYWMgdHJhbnNjcmlwdG9tZSBhbmQgY2FyZGlhYyBjZWxsdWxhciBtb3JwaG9sb2d5LgoKSGVyZSwgd2UgZXhwYW5kIHVwb24gdGhlIGNvbXB1dGF0aW9uYWwgcHJpb3JpdGl6YXRpb24gb2YgZXBpc3RhdGljIGRyaXZlcnMgcGhhc2UuIApJbiB0aGlzIHBoYXNlLCB3ZSBsZXZlcmFnZWQgbGFyZ2Utc2NhbGUgZ2VuZXRpYyBhbmQgY2FyZGlhYyBNUkkgZGF0YSBmcm9tIHRoZSBVSyBCaW9iYW5rIGFuZCBkZXZlbG9wZWQgdGhlIGxvdy1zaWduYWwgc2lnbmVkIGl0ZXJhdGl2ZSByYW5kb20gZm9yZXN0IChsby1zaVJGKSB0byBwcmlvcml0aXplIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSBmb3IgZG93bnN0cmVhbSBpbnZlc3RpZ2F0aW9ucy4gCkFzIGxvLXNpUkYgaXMgaGVhdmlseSByb290ZWQgaW4gdGhlIFByZWRpY3RhYmlsaXR5LCBDb21wdXRhYmlsaXR5LCBhbmQgU3RhYmlsaXR5IChQQ1MpIGZyYW1ld29yayBmb3IgdmVyaWRpY2FsICh0cnVzdHdvcnRoeSkgZGF0YSBzY2llbmNlIFtAeXUyMDIwdmVyaWRpY2FsXSwgd2UgY29uZHVjdGVkIGV4dGVuc2l2ZSBzdGFiaWxpdHkgYW5hbHlzZXMgdG8gaGVscCBtaW5pbWl6ZSB0aGUgaW1wYWN0IG9mIGh1bWFuIGp1ZGdtZW50IGNhbGxzIGFuZCBtb2RlbGluZyBkZWNpc2lvbnMgb24gb3VyIHNjaWVudGlmaWMgY29uY2x1c2lvbnMuIApJbiB0aGlzIHN1cHBsZW1lbnRhcnkgUENTIGRvY3VtZW50YXRpb24sIHdlIHdpbGw6CgoxLiBUcmFuc3BhcmVudGx5IGRvY3VtZW50IGFuZCBqdXN0aWZ5IHRoZSBtYW55IGh1bWFuIGp1ZGdtZW50IGNhbGxzIGFuZCBtb2RlbGluZyBkZWNpc2lvbnMgdGhhdCB3ZXJlIGluZXZpdGFibHkgbWFkZSB0aHJvdWdob3V0IG91ciBzdGF0aXN0aWNhbCBhbmFseXNpcy4KMi4gUHJvdmlkZSBhZGRpdGlvbmFsIGV4cGxvcmF0aW9uIGFuZCBpbnNpZ2h0IGludG8gdGhlIG1haW4gcmVzdWx0cyBwcmVzZW50ZWQgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkgYWxvbmdzaWRlIHRoZSBzdGFiaWxpdHkgYW5hbHlzZXMuCgpJbiB3aGF0IGZvbGxvd3MsIHdlIG9yZ2FuaXplIHRoaXMgZG9jdW1lbnRhdGlvbiBieSBzdGVwIGluIHRoZSBsby1zaVJGIHBpcGVsaW5lIChzZWUgW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkpLCBiZWdpbm5pbmcgd2l0aCB0aGUgY2hvaWNlIG9mIHBoZW5vdHlwaWMgZGF0YSwgZm9sbG93ZWQgYnkgdGhlIGRpbWVuc2lvbiByZWR1Y3Rpb24gc3RlcCwgYmluYXJpemF0aW9uIHN0ZXAsIHByZWRpY3Rpb24gc3RlcCwgYW5kIGNvbmNsdWRpbmcgd2l0aCB0aGUgcHJpb3JpdGl6YXRpb24gc3RlcC4gCldlIHRoZW4gaW52ZXN0aWdhdGUgdGhlIHBvc3NpYmlsaXR5IG9mIHBsZWlvdHJvcHkgYmV0d2VlbiBMViBtYXNzIGFuZCBibG9vZCBwcmVzc3VyZSwgY29uZHVjdGluZyBhIHN0YWJpbGl0eSBhbmFseXNpcyB3aGVyZSB3ZSBleGFtaW5lIHRoZSBpbXBhY3Qgb2YgZXhjbHVkaW5nIGh5cGVydGVuc2l2ZSBpbmRpdmlkdWFscyBmcm9tIHRoZSBsby1zaVJGIGFuYWx5c2lzLiAKTGFzdGx5LCB3ZSBjb21wYXJlIHRoZSBsby1zaVJGIHByaW9yaXRpemVkIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgd2l0aCB0aG9zZSBpZGVudGlmaWVkIHVzaW5nIGV4aXN0aW5nIG1ldGhvZHMgYW5kIGNvbmNsdWRlIHdpdGggZmluYWwgcmVtYXJrcy4KCjwvZGl2PgoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgomIzk4ODg7CioqT3JpZ2lucyBhbmQgaW50ZW5kZWQgdXNhZ2Ugb2YgbG8tc2lSRjoqKiAKQXMgZGlzY3Vzc2VkIGluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKGh0dHBzOi8vd3d3Lm1lZHJ4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS8yMDIzLjExLjA2LjIzMjk3ODU4djEpLCBsby1zaVJGIHdhcyBvcmlnaW5hbGx5IGRldmVsb3BlZCBhcyBhIGZpcnN0LXN0YWdlIHJlY29tbWVuZGF0aW9uIChvciBoeXBvdGhlc2lzIGdlbmVyYXRpb24pIHRvb2wgdG8gcHJpb3JpdGl6ZSBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgZm9yIGRvd25zdHJlYW0gYW5hbHlzZXMgYW5kIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uLiAKSW1wb3J0YW50bHksIHRoZSBvdXRwdXQgb2YgbG8tc2lSRiBpcyBhIHByaW9yaXRpemF0aW9uIG9yIHJhbmtpbmcgb3JkZXIgb2YgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSwgbm90IGEgbWVhc3VyZSBvZiBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuIApXZSBlbXBoYXNpemUgdGhhdCByZWNvbW1lbmRhdGlvbnMgb3IgcHJpb3JpdGl6YXRpb25zIGZyb20gbG8tc2lSRiBzaG91bGQgbm90IGJlIGludGVycHJldGVkIGFzIGNhdXNhbCBmaW5kaW5ncyB3aXRob3V0IGZ1cnRoZXIgaW52ZXN0aWdhdGlvbi4gCkdpdmVuIHRoZSBudW1lcm91cyBjaGFsbGVuZ2VzIGluaGVyZW50IHRvIGVwaXN0YXNpcyBkaXNjb3ZlcnkgKGUuZy4sIGhpZ2ggaGV0ZXJvZ2VuZWl0eSwgc21hbGwgZWZmZWN0IHNpemVzLCBhbmQgdW5tZWFzdXJlZCBjb25mb3VuZGluZyBmYWN0b3JzLCBkaXNjdXNzZWQgZnVydGhlciBpbiBbQHdhbmcyMDIzZXBpc3Rhc2lzXShodHRwczovL3d3dy5tZWRyeGl2Lm9yZy9jb250ZW50LzEwLjExMDEvMjAyMy4xMS4wNi4yMzI5Nzg1OHYxKSksIGFzc2Vzc2luZyBjYXVzYWxpdHkgc29sZWx5IGZyb20gZGF0YSBpcyBpbmNyZWRpYmx5IGNvbXBsZXggYW5kIGRpZmZpY3VsdCB0byBkbyAqcmVsaWFibHkqLiAKTG8tc2lSRiB3YXMgdGh1cyBkZXNpZ25lZCBhbmQgaW50ZW5kZWQgdG8gYmUgdXNlZCBhcyBhIHNpbmdsZSBzdGVwIHdpdGhpbiBhIGxhcmdlciBzY2llbnRpZmljIGRpc2NvdmVyeSBwaXBlbGluZS4gCkluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKGh0dHBzOi8vd3d3Lm1lZHJ4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS8yMDIzLjExLjA2LjIzMjk3ODU4djEpLCB3ZSByZWxpZWQgb24gZXh0ZW5zaXZlIGZvbGxvdy11cCBpbnZlc3RpZ2F0aW9ucyB0byB2YWxpZGF0ZSB0aGUgbG8tc2lSRi1wcmlvcml0aXplZCBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2ksIGFuZCB3ZSBlbmNvdXJhZ2UgcHJhY3RpdGlvbmVycyB0byBkbyB0aGUgc2FtZS4KPC9kaXY+CgojIENob2ljZSBvZiBQaGVub3R5cGljIERhdGEgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtdm1vZGVybn0KCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KSW4gdGhlIGZpcnN0IHN0ZXAgb2YgbG8tc2lSRiwgd2UgYmVnYW4gd2l0aCBhIGNhcmVmdWwgY2hvaWNlIG9mIHBoZW5vdHlwaWMgZGF0YS4gClRoaXMgZmlyc3QsIGJ1dCBvZnRlbiBvdmVybG9va2VkLCBjaG9pY2UgaXMgY3JpdGljYWwgdG8gdGhlIHJlbGlhYmlsaXR5IGFuZCBpbnRlcnByZXRhdGlvbiBvZiByZXN1bHRzLgpJZiB0aGUgZGF0YSBxdWFsaXR5IGlzIHBvb3IsIGNvbmNsdXNpb25zIG1heSBiZSB1bnJlbGlhYmxlLiAKSWYgdGhlIGRhdGEgaXMgZmFyLXJlbW92ZWQgZnJvbSB0aGUgZG9tYWluIHByb2JsZW0gb2YgaW50ZXJlc3QsIGNvbmNsdXNpb25zIG1heSBub3QgYmUgcmVsZXZhbnQuIApHaXZlbiB0aGUgaW1wb3J0YW5jZSBvZiB0aGlzIGNob2ljZSBvZiBwaGVub3R5cGljIGRhdGEsIHdlIGNvbmR1Y3RlZCBleHRlbnNpdmUgZGF0YSBleHBsb3JhdGlvbnMgZm9yIGRpZmZlcmVudCBwaGVub3R5cGVzIGluIGFkZGl0aW9uIG9idGFpbmluZyBjbGluaWNpYW4gaW5wdXQgcmVnYXJkaW5nIGl0cyBjbGluaWNhbCByZWxldmFuY2UuCgoqKkluaXRpYWwgY2hvaWNlIG9mIHBoZW5vdHlwZToqKiAKT3VyIG92ZXJhcmNoaW5nIGdvYWwgd2FzIHRvIHN0dWR5IHRoZSByb2xlIG9mIGVwaXN0YXNpcyBpbiBjYXJkaWFjIGh5cGVydHJvcGh5LiAKT25lIGltcG9ydGFudCBkaXNlYXNlIHRoYXQgaXMgY2xvc2VseSByZWxhdGVkIHRvIGNhcmRpYWMgaHlwZXJ0cm9waHkgaXMgaHlwZXJ0cm9waGljIGNhcmRpb215b3BhdGh5IChIQ00pLiAKSENNIGlzIGEgY29tbW9uIGhlYXJ0IGRpc2Vhc2UsIGltcGFjdGluZyBhcm91bmQgMSBpbiA1MDAgcGVvcGxlLCB3aGVyZSB0aGUgaGVhcnQgbXVzY2xlIGJlY29tZXMgZW5sYXJnZWQgb3IgdGhpY2tlbmVkLiAKR2l2ZW4gdGhlIGhpZ2ggcHJldmFsZW5jZSBhbmQgcG9zc2libGUgbGlmZS10aHJlYXRlbmluZyBjb25zZXF1ZW5jZXMgb2YgdGhpcyBkaXNlYXNlLCB3ZSBmaXJzdCBzZXQgb3V0IHRvIGV4cGxvcmUgdGhpcyBIQ00gcGhlbm90eXBlLCBkZWZpbmVkIGFzIGEgMC0xIGluZGljYXRvciB2YXJpYWJsZSBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgaW5kaXZpZHVhbCB3YXMgZGlhZ25vc2VkIHdpdGggSENNIChpLmUuLCBhbnkgSUNEMTAgY29kZSBvZiBJNDIuMSBvciBJNDIuMiBpbiB0aGUgVUsgQmlvYmFuaykuIApIb3dldmVyLCB3aGVuIGZpdHRpbmcgdmFyaW91cyBtYWNoaW5lIGxlYXJuaW5nIHByZWRpY3Rpb24gbW9kZWxzLCBpbmNsdWRpbmcgTDEgb3IgTDItcmVndWxhcml6ZWQgbG9naXN0aWMgcmVncmVzc2lvbiwgcmFuZG9tIGZvcmVzdCAoUkYpLCBpdGVyYXRpdmUgUkYgKGlSRiksIGFuZCBzdXBwb3J0IHZlY3RvciBtYWNoaW5lcywgdXNpbmcgc2luZ2xlLW51Y2xlb3RpZGUgdmFyaWFudCAoU05WKSBkYXRhIGZyb20gdGhlIFVLIEJpb2JhbmsgKGRldGFpbHMgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkpIHRvIHByZWRpY3QgSENNIGRpYWdub3NpcywgdGhlIGJhbGFuY2VkIGNsYXNzaWZpY2F0aW9uIGFjY3VyYWN5IG9uIHRoZSBoZWxkLW91dCB2YWxpZGF0aW9uIGRhdGEgZGlkIG5vdCBjb25zaXN0ZW50bHkgZXhjZWVkIDUwXCUgd2hlbiB0cmFpbmVkIG9uIGRpZmZlcmVudCBib290c3RyYXBwZWQgdHJhaW5pbmcgc2FtcGxlcy4gCkluIG90aGVyIHdvcmRzLCB0aGUgZml0dGVkIHByZWRpY3Rpb24gbW9kZWxzIHdlcmUgbm8gYmV0dGVyIHRoYW4gcmFuZG9tIGd1ZXNzaW5nLiAKVGhpcyBtYWRlIHVzIHdhcnkgb2YgYW55IGludGVycHJldGF0aW9ucyBleHRyYWN0ZWQgZnJvbSB0aGVzZSBwcmVkaWN0aW9uIG1vZGVscyBzaW5jZSBpdCBpcyB1bmNsZWFyIHdoZXRoZXIgdGhlc2UgbW9kZWxzIGFyZSBjYXB0dXJpbmcgYW55IHJlbGV2YW50IHBoZW5vdHlwaWMgc2lnbmFsIG9yIHNpbXBseSBub2lzZS4gCkdpdmVuIHRoaXMgaW5jcmVkaWJseSB3ZWFrIHByZWRpY3Rpb24gc2lnbmFsLCB3ZSBkZWVtZWQgdGhhdCB0aGVzZSBtb2RlbHMgZGlkIG5vdCBwYXNzIHRoZSBwcmVkaWN0aW9uIGNoZWNrICh0aGUgIlAiIGluIFBDUykgW0B5dTIwMjB2ZXJpZGljYWxdLiAKRm9yIHRoaXMgcmVhc29uLCB3ZSBjaG9zZSBub3QgdG8gcHJvY2VlZCBmdXJ0aGVyIHdpdGggdGhlIEhDTSBwaGVub3R5cGUgYW5kIGRpZCBub3QgY29uZHVjdCBhbnkgYW5hbHlzaXMgd2l0aCByZXNwZWN0IHRvIGludGVycHJldGluZyB0aGUgYWZvcmVtZW50aW9uZWQgbW9kZWxzIGZvciBIQ00uCgoqKlBpdm90aW5nIHRvIGEgY2FyZGlhYyBNUkktZGVyaXZlZCBwaGVub3R5cGU6KiogCldlIGluc3RlYWQgcGl2b3RlZCB0byBhbiBhbHRlcm5hdGl2ZSBwaGVub3R5cGUgZm9yIGNhcmRpYWMgaHlwZXJ0cm9waHkgYmFzZWQgdXBvbiBkZWVwLWxlYXJuaW5nLWVuYWJsZWQgbGVmdCB2ZW50cmljdWxhciAoTFYpIHN0cnVjdHVyYWwgYW5hbHlzaXMgdXNpbmcgY2FyZGlhYyBNUklzLiAKVGhpcyBjaG9pY2Ugd2FzIGhlYXZpbHkgbW90aXZhdGVkIGJ5IG91ciBzdHJ1Z2dsZXMgd2l0aCBIQ00uIApTcGVjaWZpY2FsbHksIHdoZW4gbG9va2luZyBiYWNrIGF0IHRoZSBIQ00gZGlhZ25vc2lzIGRhdGEsIHdlIG5vdGljZWQgdGhhdCB0aGUgbnVtYmVyIG9mIEhDTSBjYXNlcyBpbiB0aGUgVUsgQmlvYmFuayBkYXRhIChvbmx5IDIzNiBIQ00gY2FzZXMgb3V0IG9mIDMzNyw1MzUgdW5yZWxhdGVkIFdoaXRlIEJyaXRpc2ggaW5kaXZpZHVhbHMpIHdhcyBtdWNoIGxvd2VyIHRoYW4gdGhlIDEgaW4gNTAwIHJhdGlvIHRoYXQgaXMgZXhwZWN0ZWQuIApBbHRob3VnaCB0aGUgVUsgQmlvYmFuayBwb3B1bGF0aW9uIGlzIGtub3duIHRvIGJlIGhlYWx0aGllciB0aGFuIHRoZSBnZW5lcmFsIHBvcHVsYXRpb24gW0BmcnkyMDE3Y29tcGFyaXNvbl0sIHRoZSBvYnNlcnZlZCBkaXNjcmVwYW5jeSBpcyBsYXJnZSwgbGVhZGluZyB1cyB0byBzcGVjdWxhdGUgYWJvdXQgcG90ZW50aWFsIHVuZGVyLWRpYWdub3NpcyBpc3N1ZXMgd2l0aCB0aGUgSENNIHBoZW5vdHlwZS4gCkNvbnNlcXVlbnRseSwgcmF0aGVyIHRoYW4gcmVseWluZyBvbiBhIGNsaW5pY2lhbidzIGRpYWdub3NpcyB3aGljaCBtYXkgc3VmZmVyIGZyb20gaXNzdWVzIHN1Y2ggYXMgdW5kZXItZGlhZ25vc2lzLCB3ZSBjaG9zZSB0byBidWlsZCB1cG9uIHJlY2VudCBhZHZhbmNlcyBpbiBkZWVwLWxlYXJuaW5nLWVuYWJsZWQgcGhlbm90eXBpbmcgW0BiYWkyMDE4YXV0b21hdGVkXS4gCkRvaW5nIHNvIGVuYWJsZXMgdXMgdG8gZXh0cmFjdCBhIG1lYXN1cmUgb2YgbGVmdCB2ZW50cmljdWxhciBoeXBlcnRyb3BoeSwgc3BlY2lmaWNhbGx5LCB0aGUgbGVmdCB2ZW50cmljdWxhciBtYXNzIChMVk0pLCBmcm9tIGFueW9uZSB3aXRoIGEgY2FyZGlhYyBNUkkuIAoKKipBcnJpdmluZyBhdCBMVk1pOioqCkhvd2V2ZXIsIExWTSBpcyBrbm93biB0byBiZSBoZWF2aWx5IGluZmx1ZW5jZWQgYnkgYm9keSB3ZWlnaHQsIGhlaWdodCwgYW5kIGdlbmRlciBbQGVuZ2VsMjAxNmF0aGxldGljOyBAbWl6dWtvc2hpMjAxNm5vcm1hbF0uIApUaHVzLCBpZiB3ZSB3ZXJlIHRvIHByb2NlZWQgc29sZWx5IHdpdGggTFZNIGluIG91ciBhbmFseXNpcywgd2UgcmlzayBpZGVudGlmeWluZyBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgdGhhdCBhcmUgcHJpbWFyaWx5IGFzc29jaWF0ZWQgd2l0aCBib2R5IHdlaWdodCwgaGVpZ2h0LCBhbmQgZ2VuZGVyLCByYXRoZXIgdGhhbiBsZWZ0IHZlbnRyaWN1bGFyIGh5cGVydHJvcGh5LiAKSW5kZWVkLCBpZiB3ZSB2aXN1YWxpemUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIExWTSwgaGVpZ2h0LCBhbmQgd2VpZ2h0IHdpdGhpbiBlYWNoIGdlbmRlciBncm91cCAoRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0xKSksIHdlIHNlZSBzdHJvbmcgcG9zaXRpdmUgY29ycmVsYXRpb25zLiAKClRoaXMgbW90aXZhdGVzIHRoZSBuZWVkIHRvIGFkanVzdCBmb3IgaGVpZ2h0IGFuZCB3ZWlnaHQgaW4gb3JkZXIgdG8gaGVscCBkZWNvdXBsZSB0aGUgZWZmZWN0cyBvZiBoZWlnaHQvd2VpZ2h0IGFuZCBMVk0uIApBcyBkb25lIGluIEBraHVyc2hpZDIwMjNjbGluaWNhbCwgb25lIGNvbW1vbiB3YXkgdG8gYWRkcmVzcyB0aGlzIGlzIGJ5IGFuYWx5emluZyBMVk0gaW5kZXhlZCBieSBib2R5IHN1cmZhY2UgYXJlYSAoTFZNaSksIGRlZmluZWQgYXM6CgpcYmVnaW57YWxpZ24qfQpcdGV4dHtMVk1pfSA9IFx0ZXh0e0xWTSB9IC8gXHRleHR7IEJvZHkgc3VyZmFjZSBhcmVhfSwKXGVuZHthbGlnbip9CndoZXJlIGJvZHkgc3VyZmFjZSBhcmVhIGlzIGNhbGN1bGF0ZWQgYmFzZWQgb24gaGVpZ2h0IGFuZCBib2R5IHdlaWdodCB2aWEgdGhlIER1IEJvaXMgZm9ybXVsYSBbQGR1MTkxNmNsaW5pY2FsXS4KCkFmdGVyIG5vcm1hbGl6aW5nIGJ5IGJvZHkgc3VyZmFjZSBhcmVhIChhbmQgaGVuY2UsIGhlaWdodCBhbmQgd2VpZ2h0KSwgdGhlIGFzc29jaWF0aW9ucyBiZXR3ZWVuIExWTWkgYW5kIGhlaWdodC93ZWlnaHQgYXJlIG11Y2ggd2Vha2VyIHdpdGhpbiBlYWNoIGdlbmRlciBncm91cCwgZXhoaWJpdGluZyBjb3JyZWxhdGlvbnMgY2xvc2VyIHRvIDAgKEZpZ3VyZSBcQHJlZihmaWc6c3ViY2h1bmstMSkpLiAKVGh1cywgYnkgZm9jdXNpbmcgb3VyIHN0YXRpc3RpY2FsIGFuYWx5c2lzIG9uIExWTWksIHdlIGxlc3NlbiB0aGUgcG9zc2liaWxpdHkgdGhhdCB0aGUgaWRlbnRpZmllZCBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgYXJlIG9ubHkgc2VsZWN0ZWQgYmVjYXVzZSBvZiB0aGVpciBhc3NvY2lhdGlvbiB3aXRoIGJvZHkgaGVpZ2h0IGFuZC9vciB3ZWlnaHQuIApTdGlsbCwgdGhlcmUgYXJlIGRpZmZlcmVuY2VzIGluIExWTWkgYmV0d2VlbiBtYWxlcyBhbmQgZmVtYWxlcywgd2l0aCBtYWxlcyB0ZW5kaW5nIHRvIGhhdmUgaGlnaGVyIExWTWkgbWVhc3VyZW1lbnRzLiAKQXMgc2VlbiBsYXRlciwgd2Ugd2lsbCBhY2NvdW50IGZvciB0aGlzIGluIHRoZSBtb2RlbGluZyBzdGFnZSBieSB1c2luZyBnZW5kZXItc3BlY2lmaWMgYmluYXJpemF0aW9uIHRocmVzaG9sZHMgdG8gYmluYXJpemUgdGhlIExWTWkgcmVzcG9uc2VzIGludG8gdGhlIGhpZ2ggYW5kIGxvdyBMVk1pIGdyb3Vwcy4gCgoqKlN0dWR5IENvaG9ydDoqKiAKQmVmb3JlIHByb2NlZWRpbmcsIHdlIG5vdGUgdGhhdCBhbm90aGVyIGltcG9ydGFudCBodW1hbiBqdWRnbWVudCBjYWxsIHdpdGhpbiBvdXIgcGlwZWxpbmUgaXMgdGhlIGNob2ljZSBvZiBzdHVkeSBjb2hvcnQuIApTcGVjaWZpY2FsbHksIHdlIHJlc3RyaWN0ZWQgb3VyIGFuYWx5c2lzIHRvIHRoZSB1bnJlbGF0ZWQgV2hpdGUgQnJpdGlzaCBpbmRpdmlkdWFsIHBvcHVsYXRpb24gd2l0aCBib3RoIFNOViBhbmQgY2FyZGlhYyBNUkkgZGF0YSBpbiB0aGUgVUsgQmlvYmFuaywgcmVzdWx0aW5nIGluIGEgY29ob3J0IG9mIDI5LDY2MSBpbmRpdmlkdWFscy4gCldlIGNob3NlIHRvIGZvY3VzIHRoaXMgYW5hbHlzaXMgb24gdGhlIHVucmVsYXRlZCBXaGl0ZSBCcml0aXNoIHBvcHVsYXRpb24sIGFudGljaXBhdGluZyB0aGUgdmVyeSBsb3ctc2lnbmFsIHByb2JsZW0gdW5kZXIgc3R1ZHkgKGUuZy4sIGR1ZSB0byB0aGUgZ2VuZXJhbGx5IHNtYWxsIGVmZmVjdCBzaXplcyBvZiBjb21tb24gZ2VuZXRpYyB2YXJpYW50cyBhbmQgdGhlIGhpZ2ggcGhlbm90eXBpYyBkaXZlcnNpdHkgb2YgY2FyZGlhYyBoeXBlcnRyb3BoeSkuIApCeSBzdHVkeWluZyBhIG1vcmUgaG9tb2dlbmVvdXMgY29ob3J0IHN1Y2ggYXMgdGhlIHVucmVsYXRlZCBXaGl0ZSBCcml0aXNoIHBvcHVsYXRpb24sIHdlIGhvcGUgdG8gZmlyc3QgZXN0YWJsaXNoIGEgcHJvb2Ytb2YtY29uY2VwdCBmb290aG9sZCBvbiB0aGUgcm9sZSBvZiBlcGlzdGFzaXMgaW4gY2FyZGlhYyBoeXBlcnRyb3BoeSwgYW5kIHdlIHZpZXcgdGhlIHN0dWR5IGFuZCBnZW5lcmFsaXphdGlvbiB0byB0aGUgYnJvYWRlciBwb3B1bGF0aW9uIGFzIGEgdmVyeSBjcnVjaWFsIG5leHQgc3RlcC4KPC9kaXY+CgpgYGB7ciBsdm0tZWRhLCByZXN1bHRzID0gImFzaXMifQppZiAocGFyYW1zJGV2YWwpIHsKICBwaGVub19kYXRhIDwtIGZyZWFkKCIvb2FrL3N0YW5mb3JkL3Byb2plY3RzL3VrYmIvaW1hZ2luZ19hc2hsZXkvMjAyMDkvcmVzdWx0cy90YWJsZV92ZW50cmljdWxhcl92b2x1bWVfd2l0aF9pbmRleGluZy5jc3YiKQogIG1lcmdlX2RmIDwtIGZyZWFkKCIvb2FrL3N0YW5mb3JkL3Byb2plY3RzL3VrYmIvZ2VuZXRpY19kYXRhX2FzaGxleS92Mi9icmlkZ2luZ19maWxlXzIyMjhfdG9fMTM3MjEuY3N2IikKICBwaGVub19kYXRhIDwtIGxlZnRfam9pbigKICAgIHggPSBwaGVub19kYXRhLCB5ID0gbWVyZ2VfZGYsCiAgICBieSA9IGMoIlYxIiA9ICJhcHAyMjI4MiIpCiAgKSAlPiUKICAgIGZpbHRlcighaXMubmEoYXBwMTM3MjEpKSAlPiUKICAgIG11dGF0ZShHZW5kZXIgPSBpZmVsc2UobG9hZERlbW9ncmFwaGljcyhhcHAxMzcyMSlbLCAiZ2VuZGVyIl0gPT0gMSwKICAgICAgIk1hbGUiLCAiRmVtYWxlIgogICAgKSAlPiUgYXMuZmFjdG9yKCkpICU+JQogICAgYXMuZGF0YS5mcmFtZSgpICU+JQogICAgcmVuYW1lKAogICAgICAiTFZNaSAoZy9tXjIpIiA9ICJpTFZNIChnL20yKSIsCiAgICAgICJXZWlnaHQgKGtnKSIgPSAid2VpZ2h0IChrZykiLAogICAgICAiSGVpZ2h0IChjbSkiID0gImhlaWdodCAoY20pIgogICAgKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKEdlbmRlcikpCgogIGtlZXBfY29scyA8LSBjKCJMVk0gKGcpIiwgIkxWTWkgKGcvbV4yKSIsICJXZWlnaHQgKGtnKSIsICJIZWlnaHQgKGNtKSIpCiAgcGx0IDwtIHBoZW5vX2RhdGEgJT4lCiAgICBkcGx5cjo6c2VsZWN0KHRpZHlzZWxlY3Q6OmFsbF9vZihrZWVwX2NvbHMpLCBHZW5kZXIpICU+JQogICAgdmRvY3M6OnBsb3RfcGFpcnMoY29sdW1ucyA9IGtlZXBfY29scywgY29sb3IgPSAuJEdlbmRlciwgcG9pbnRfc2l6ZSA9IDAuMSkKICAjIHNhdmVSRFMocGx0LCBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJwaGVub3R5cGVfY29ycmVsYXRpb25faGVhdG1hcC5yZHMiKSkKICAjIGdnc2F2ZShwbHQsCiAgIyAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAicGhlbm90eXBlX2NvcnJlbGF0aW9uX2hlYXRtYXAucG5nIiksCiAgIyAgIHdpZHRoID0gOCwgaGVpZ2h0ID0gNgogICMgKQp9IGVsc2UgewogIGRpc3BsYXlfaW1hZ2UoCiAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJwaGVub3R5cGVfY29ycmVsYXRpb25faGVhdG1hcC5wbmciKSwKICAgIGNodW5rX2lkeCA9IGNodW5rX2lkeCwKICAgIGNhcHRpb24gPSAiJ1BhaXIgcGxvdCwgaWxsdXN0cmF0aW5nIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gTFZNLCBMVk1pLCBoZWlnaHQsIGFuZCB3ZWlnaHQgd2l0aGluIGVhY2ggZ2VuZGVyIGdyb3VwIChtYWxlcyBpbiBncmVlbiBhbmQgZmVtYWxlcyBpbiBvcmFuZ2UpLiBEZW5zaXR5IGRpc3RyaWJ1dGlvbnMgYXJlIHNob3duIGFsb25nIHRoZSBkaWFnb25hbC4nIgogICkKfQpgYGAKCgojIERpbWVuc2lvbiBSZWR1Y3Rpb24gU3RlcCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC12bW9kZXJufQoKIyMgT3ZlcnZpZXcgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CkhhdmluZyBjYXJlZnVsbHkgY2hvc2VuIHRoZSBwaGVub3R5cGljIGRhdGEgKGkuZS4sIHRoZSBjYXJkaWFjIE1SSS1kZXJpdmVkIExWTWkpIHVuZGVyIHN0dWR5LCB0aGUgbmV4dCBzdGVwIGluIGxvLXNpUkYgaXMgdG8gZG8gZGltZW5zaW9uIHJlZHVjdGlvbiB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBTTlZzIHVuZGVyIGNvbnNpZGVyYXRpb24gdXNpbmcgYSBnZW5vbWUtd2lkZSBhc3NvY2lhdGlvbiBzdHVkeSAoR1dBUykuIApUaGlzIGRpbWVuc2lvbiByZWR1Y3Rpb24gc3RlcCBpcyBuZWNlc3NhcnkgdG8gbWl0aWdhdGUgdGhlIGNvbXB1dGF0aW9uYWwgYW5kIHN0YXRpc3RpY2FsIGNoYWxsZW5nZXMgb2Ygc2VhcmNoaW5nIGFjcm9zcyBtaWxsaW9ucyBvZiBwb3NzaWJsZSBTTlZzICh3aGljaCBpbiB0aGUgY2FzZSBvZiBzZWFyY2hpbmcgZm9yIGVwaXN0YXNpcyByZXN1bHRzIGluIGFuIGV2ZW4gbGFyZ2VyIGNvbWJpbmF0b3JpYWwgZXhwbG9zaW9uIG9mIHBvc3NpYmlsaXRpZXMpLgoKKipXaHkgR1dBUz8qKiAKV2UgY2hvc2UgdG8gZG8gZGltZW5zaW9uIHJlZHVjdGlvbiBieSBydW5uaW5nIGEgR1dBUyBhcyBpdCAKKDEpIGhhcyBiZWVuIHNob3duIHRvIGJlIGFuIGluY3JlZGlibHkgdXNlZnVsIHRvb2wgZm9yIGJldHRlciB1bmRlcnN0YW5kaW5nIHRoZSBnZW5ldGljIGJhc2lzIG9mIG51bWVyb3VzIGRpc2Vhc2VzIGluIHRoaXMgZmllbGQgW0B2aXNzY2hlcjIwMTcxMDsgQHBpcnJ1Y2NlbGxvMjAyMGFuYWx5c2lzOyBAbWV5ZXIyMDIwZ2VuZXRpYzsgQGhhcnBlcjIwMjFjb21tb247IEBraHVyc2hpZDIwMjNjbGluaWNhbF0sIAooMikgaXMgb25lIG9mIHRoZSBmZXcgbWV0aG9kcyB0aGF0IGNhbiBoYW5kbGUgYW4gaW5wdXQgb2YgbWlsbGlvbnMgb2YgU05WcyBpbiBhIGNvbXB1dGF0aW9uYWxseS10cmFjdGFibGUgbWFubmVyLCBhbmQgCigzKSBpcyBhIGNvbW1vbiwgd2lkZWx5LWFjY2VwdGVkIHByZXByb2Nlc3Npbmcgc3RlcCBpbiBvdGhlciByZWxhdGVkIHN0YXRpc3RpY2FsIGdlbm9taWNzIHRhc2tzIHN1Y2ggYXMgZmluZS1tYXBwaW5nIFtAc2NoYWlkMjAxOGdlbm9tZV0uCgoqKkxpbWl0YXRpb25zOioqIApXZSBhY2tub3dsZWRnZSwgaG93ZXZlciwgdGhhdCB1c2luZyBhIEdXQVMgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgU05WcyB1bmRlciBjb25zaWRlcmF0aW9uIGhhcyBsaW1pdGF0aW9ucy4gCkJlY2F1c2UgYSBHV0FTIHByaW9yaXRpemVzIFNOVnMgdGhhdCBoYXZlIHN0cm9uZyBtYXJnaW5hbCBhc3NvY2lhdGlvbnMgd2l0aCB0aGUgcGhlbm90eXBlIHVuZGVyIHN0dWR5LCB3ZSBtYXkgYmUgcmVtb3ZpbmcgU05WcyB0aGF0IGFyZSBhc3NvY2lhdGVkIHdpdGggTFZNaSB0aHJvdWdoIGFuIGVwaXN0YXRpYyBpbnRlcmFjdGlvbiBidXQgbm90IHRocm91Z2ggYSBtYXJnaW5hbCBhc3NvY2lhdGlvbi4gCkFsbGV2aWF0aW5nIHRoaXMgbGltaXRhdGlvbiBpcyBjZXJ0YWlubHkgaW50ZXJlc3RpbmcgYW5kIGFuIGltcG9ydGFudCBkaXJlY3Rpb24gdG8gcHVyc3VlIGluIGZ1dHVyZSB3b3JrLiAKUmVnYXJkbGVzcywgaW4gdGhpcyBjdXJyZW50IHdvcmssIHdlIHVzZSBsby1zaVJGIHByaW1hcmlseSBhcyBhIHdheSB0byBnZW5lcmF0ZSByZWNvbW1lbmRhdGlvbnMgZm9yIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uIG9mIGVwaXN0YXNpcy4gCldlIHRodXMgYXJlIG1vc3QgaW50ZXJlc3RlZCBpbiBnZW5lcmF0aW5nICpyZWxpYWJsZSogcmVjb21tZW5kYXRpb25zIGZvciBhIGxpbWl0ZWQgbnVtYmVyIG9mIGV4cGVyaW1lbnRzLCByYXRoZXIgdGhhbiBhdHRlbXB0aW5nIHRvIGZpbmQgYWxsIHBvc3NpYmxlIGludGVyYWN0aW9ucyB0aGF0IGRyaXZlIHRoZSBkaXNlYXNlLiAKR2l2ZW4gb3VyIHBhcnRpY3VsYXIgdXNlLWNhc2UgZm9yIGxvLXNpUkYsIHdlIGFjY2VwdCB0aGUgbGltaXRhdGlvbnMgb2YgdXNpbmcgYSBHV0FTIGZvciBkaW1lbnNpb24gcmVkdWN0aW9uIGFuZCBhZ2FpbiB2aWV3IHRoaXMgd29yayBhcyBhIHJlbGlhYmxlICpmaXJzdCogc3RlcCAoYW5kIGNlcnRhaW5seSBub3QgdGhlIGxhc3QpIGZvciBiZXR0ZXIgdW5kZXJzdGFuZGluZyB0aGUgcm9sZSBvZiBlcGlzdGFzaXMgaW4gY2FyZGlhYyBoeXBlcnRyb3BoeS4KCioqSG93IHdhcyB0aGUgZGltZW5zaW9uIHJlZHVjdGlvbiBwZXJmb3JtZWQ/KiogCldlIHBlcmZvcm1lZCBhIEdXQVMgb24gdGhlIHRyYWluaW5nIGRhdGEgZm9yIHRoZSByYW5rLWJhc2VkIGludmVyc2Ugbm9ybWFsLXRyYW5zZm9ybWVkIExWTWkgdXNpbmcgdHdvIGFsZ29yaXRobXMsIFBMSU5LIFtAcHVyY2VsbDIwMDdwbGlua10gYW5kIEJPTFQtTE1NIFtAbG9oMjAxNWVmZmljaWVudF0uIApGb3IgZWFjaCBvZiB0aGUgdHdvIEdXQVMgcnVucywgd2UgcmFua2VkIHRoZSBTTlZzIGJ5IHNpZ25pZmljYW5jZSAoaS5lLiwgdGhlIEdXQVMgcC12YWx1ZSkuIApXZSB0aGVuIHRvb2sgdGhlIHVuaW9uIG9mIHRoZSB0b3AgMTAwMCBTTlZzICh3aXRob3V0IGNsdW1waW5nKSBmcm9tIGVhY2ggb2YgdGhlIHR3byBHV0FTIHJ1bnMgYW5kIHByb2NlZWRlZCB3aXRoIHRoaXMgcmVzdWx0aW5nIHNldCBvZiAxNDA1IFNOVnMgZm9yIHRoZSByZW1haW5kZXIgb2YgdGhlIGxvLXNpUkYgcGlwZWxpbmUuIApXZSByZWZlciB0byBbQHdhbmcyMDIzZXBpc3Rhc2lzXShodHRwczovL3d3dy5tZWRyeGl2Lm9yZy9jb250ZW50LzEwLjExMDEvMjAyMy4xMS4wNi4yMzI5Nzg1OHYxKSBmb3IgdGhlIGRldGFpbHMgb24gdGhlIFBMSU5LIGFuZCBCT0xULUxNTSBpbXBsZW1lbnRhdGlvbnMgYW5kIHVzZSB0aGlzIGRvY3VtZW50IGluc3RlYWQgdG8ganVzdGlmeSBzZXZlcmFsIG9mIG91ciBodW1hbiBqdWRnbWVudCBjYWxscyBpbiB0aGlzIGRpbWVuc2lvbiByZWR1Y3Rpb24gc3RlcC4KCi0gKipXaHkgUExJTksgYW5kIEJPTFQtTE1NPyoqIFNpbmNlIEJPTFQtTE1NIGFuZCBQTElOSyByZWx5IG9uIGRpZmZlcmVudCBzdGF0aXN0aWNhbCBtb2RlbHMgYW5kIGl0IGlzIHVuY2xlYXIgYSBwcmlvcmkgd2hpY2ggbW9kZWwgaXMgYmV0dGVyIHN1aXRlZCBmb3Igb3VyIHByb2JsZW0sIHdlIGVtcGxveWVkIGJvdGggc29mdHdhcmUgcGFja2FnZXMgdG8gbWl0aWdhdGUgdGhlIGRlcGVuZGVuY2Ugb2YgZG93bnN0cmVhbSBjb25jbHVzaW9ucyBvbiB0aGlzIGFyYml0cmFyeSBjaG9pY2Ugb2YgbW9kZWwuCi0gKipXaHkgdGhlIHJhbmstYmFzZWQgaW52ZXJzZSBub3JtYWwtdHJhbnNmb3JtZWQgTFZNaT8qKiBCZWNhdXNlIHRoZSBkaXN0cmlidXRpb24gb2YgTFZNaSBtZWFzdXJlbWVudHMgaXMgcmlnaHQgc2tld2VkIChzZWUgRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0xKSksIGFuZCB0aGUgcC12YWx1ZSBjb21wdXRhdGlvbiBpbiBQTElOSyBhbmQgQk9MVC1MTU0gcmVseSBvbiBub3JtYWxpdHkgYXNzdW1wdGlvbnMsIHRoZSByYW5rLWJhc2VkIGludmVyc2Ugbm9ybWFsLXRyYW5zZm9ybSB3YXMgdGFrZW4gYXMgaW4gQGtodXJzaGlkMjAyM2NsaW5pY2FsLgotICoqV2h5IHdhcyB0aGUgdW5pb24gdGFrZW4/KiogQXMgbWVudGlvbmVkIHByZXZpb3VzbHksIHJlbHlpbmcgb24gYSBHV0FTIHRvIGRvIGRpbWVuc2lvbiByZWR1Y3Rpb24gY2FuIGJlIGxpbWl0aW5nIHNpbmNlIGl0IGlzIHByaW1hcmlseSBhc3Nlc3NpbmcgbWFyZ2luYWwgYXNzb2NpYXRpb25zIGJldHdlZW4gdGhlIFNOVnMgYW5kIHRoZSBwaGVub3R5cGUuIFRoZXJlIGFyZSBhbHNvIG90aGVyIHJlc3RyaWN0aXZlIG1vZGVsaW5nIGFzc3VtcHRpb25zIChlLmcuLCBsaW5lYXJpdHkpIHRoYXQgbWF5IGFkZCB0byB0aGVzZSBsaW1pdGF0aW9ucy4gRHVlIHRvIHRoaXMgY29uY2VybiB0aGF0IHdlIG1heSBiZSBpbXBvc2luZyB0b28gbWFueSB1bm5lY2Vzc2FyeSByZXN0cmljdGlvbnMgaW4gb3JkZXIgZm9yIFNOVnMgdG8gcGFzcyB0aGUgR1dBUyBmaWx0ZXIsIHdlIGNob3NlIHRvIHRha2UgdGhlIHVuaW9uIG9mIHRoZSB0b3AgU05WcyBmcm9tIEJPTFQtTE1NIGFuZCBmcm9tIFBMSU5LLCByYXRoZXIgdGhhbiB0YWtpbmcgdGhlIGludGVyc2VjdGlvbiB3aGljaCB3b3VsZCBoYXZlIG1hZGUgaXQgbW9yZSBkaWZmaWN1bHQgb3IgcmVzdHJpY3RpdmUgZm9yIFNOVnMgdG8gcGFzcyB0aGUgR1dBUyBmaWx0ZXIuCi0gKipIb3cgd2FzIHRoZSB0aHJlc2hvbGQgY2hvc2VuPyoqIFdlIGNob3NlIHRoZSB0aHJlc2hvbGQgb2YgMTAwMCBTTlZzIHBlciBHV0FTIG1ldGhvZCAod2l0aG91dCBjbHVtcGluZykgYXMgaXQgKDEpIHN0cnVjayBhIGJhbGFuY2UgYmV0d2VlbiB0aGUgYW1vdW50IG9mIGluZm9ybWF0aW9uIGxvc3MgYW5kIHRoZSBjb21wdXRhdGlvbmFsIGNvc3Qgb2Ygb3VyIGRvd25zdHJlYW0gbW9kZWxpbmcgYW5kICgyKSB5aWVsZGVkIHRoZSBoaWdoZXN0IHZhbGlkYXRpb24gcHJlZGljdGlvbiBhY2N1cmFjeSBjb21wYXJlZCB0byBjaG9vc2luZyBvdGhlciBwb3NzaWJsZSB0aHJlc2hvbGRzICg1MDAgYW5kIDIwMDApIHdpdGggYW5kIHdpdGhvdXQgY2x1bXBpbmcgaW4gdGhlIHByZWRpY3Rpb24gbW9kZWxpbmcgc3RhZ2UuIFdlIG5vdGUgdGhhdCB0aGlzIGNob2ljZSBvZiB0aGUgdG9wIDEwMDAgU05WcyBpbmNsdWRlcyBhbGwgU05WcyB0aGF0IHBhc3NlZCB0aGUgZ2Vub21lLXdpZGUgc2lnbmlmaWNhbmNlIGxldmVsIChwLXZhbHVlID0gNUUtOCkgYXMgd2VsbCBhcyBhZGRpdGlvbmFsIFNOVnMgdGhhdCBkaWQgbm90IHBhc3MgdGhlIGdlbm9tZS13aWRlIHNpZ25pZmljYW5jZSBsZXZlbC4gSW4gcGFydGljdWxhciwgdGFraW5nIHRoZSB0b3AgMTAwMCBTTlZzIGNvcnJlc3BvbmRzIHRvIHVzaW5nIHRoZSBwLXZhbHVlIHRocmVzaG9sZCBvZiAxLjdFLTUgYW5kIDYuN0UtNiBmb3IgUExJTksgYW5kIEJPTFQtTE1NLCByZXNwZWN0aXZlbHkuCgoqKlJlbWFyazoqKiBXZSBub3RlIHRoYXQgYWx0ZXJuYXRpdmUgZGltZW5zaW9uIHJlZHVjdGlvbiBzdHJhdGVnaWVzIG1heSBiZSB1c2VkIGluIHJlcGxhY2VtZW50IG9mIG91ciBwcm9wb3NlZCBwcm9jZWR1cmUuIEZvciBleGFtcGxlLCBvbmUgbWF5IGNvbnNpZGVyIHVzaW5nIGEgZGlmZmVyZW50IEdXQVMgc29mdHdhcmUgKGUuZy4sIFJFR0VOSUUgW0BtYmF0Y2hvdTIwMjFjb21wdXRhdGlvbmFsbHldKSwgYSBkaWZmZXJlbnQgcGhlbm90eXBlIHRyYW5zZm9ybWF0aW9uLCBvciBwZXJoYXBzIGEgbW9yZSBzb3BoaXN0aWNhdGVkIGFwcHJvYWNoIHRhaWxvcmVkIGZvciBpbnRlcmFjdGlvbnMgYW5kIGVwaXN0YXNpcyBkZXRlY3Rpb24gKGUuZy4sIE1BUElUIFtAY3Jhd2ZvcmQyMDE3ZGV0ZWN0aW5nXSkuCgoqKk9yZ2FuaXphdGlvbjoqKiBVbmRlciB0aGUgYEdXQVMgUmVzdWx0cyBTdW1tYXJ5YCB0YWIsIHdlIHByb3ZpZGUgYW4gaW52ZXN0aWdhdGlvbiBpbnRvIHRoZSBCT0xULUxNTSBhbmQgUExJTksgR1dBUyByZXN1bHRzIGZvciBMVk0gYW5kIExWTWkuIFVuZGVyIHRoZSBgR1dBUy1maWx0ZXJlZCBTTlZzYCwgd2UgZXhwbG9yZSB0aGUgc2VsZWN0ZWQgMTQwNSBTTlZzIHRoYXQgcGFzc2VkIHRoZSBHV0FTIGZpbHRlciBmb3IgdGhlIExWTWkgcGhlbm90eXBlLgo8L2Rpdj4KCiMjIEdXQVMgUmVzdWx0cyBTdW1tYXJ5IHsudW5udW1iZXJlZCAudGFic2V0fQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpCZWxvdywgd2UgcHJvdmlkZSBhbiBvdmVydmlldyBvZiB0aGUgZ2Vub21lLXdpZGUgYXNzb2NpYXRpb24gc3R1ZHkgKEdXQVMpIHJlc3VsdHMgZm9yIGJvdGggdGhlIExWTSBhbmQgTFZNaSBwaGVub3R5cGVzLiBXaGlsZSBMVk1pIGlzIHRoZSBwcmltYXJ5IHBoZW5vdHlwZSBvZiBpbnRlcmVzdCwgd2UgcHJvdmlkZSB0aGUgTFZNIEdXQVMgcmVzdWx0cyBmb3IgY29tcGxldGVuZXNzLiBXZSBmdXJ0aGVyIGludmVzdGlnYXRlIHRoZSBzaW1pbGFyaXRpZXMgaW4gZmluZGluZ3MgYmV0d2VlbiB0aGUgTFZNIGFuZCBMVk1pIEdXQVMgYW5hbHlzZXMgdmlhIGEgc3RhYmlsaXR5IGFuYWx5c2lzLiAKCi0gVW5kZXIgdGhlIGBCT0xULUxNTWAgYW5kIGBQTElOS2AgdGFiczoKICAtIFdlIHByb3ZpZGUgYSBicmllZiBsb29rIGludG8gdGhlIEdXQVMgcmVzdWx0cywgaW5jbHVkaW5nIHRoZSBNYW5oYXR0YW4gcGxvdHMgZm9yIGVhY2ggcGhlbm90eXBlIChMVk1pIGFuZCBMVk0pLiAKICAtIFdlIGFsc28gcHJvdmlkZSBhIHRhYmxlIG9mIHRoZSBnZW5vbWljIHJpc2sgbG9jaSwgbGVhZCBTTlZzLCBhbmQgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBmcm9tIGVhY2ggR1dBUywgZGV0ZXJtaW5lZCB1c2luZyBGVU1BIFtAd2F0YW5hYmUyMDE3ZnVuY3Rpb25hbF0gd2l0aCB0aGUgZGVmYXVsdCBzZXR0aW5ncyAoaS5lLiwgbWF4aW11bSBwLXZhbHVlIG9mIGxlYWQgU05WcyA9IDVFLTgsIG1heGltdW0gcC12YWx1ZSBjdXRvZmYgPSAwLjA1LCAkcl4yJCB0aHJlc2hvbGQgdG8gZGVmaW5lIGluZGVwZW5kZW50IHNpZ25pZmljYW50IFNOVnMgPSAwLjYsIDJuZCAkcl4yJCB0aHJlc2hvbGQgdG8gZGVmaW5lIGxlYWQgU05WcyA9IDAuMSwgbWluaW11bSBtaW5vciBhbGxlbGUgZnJlcXVlbmN5ID0gMCwgbWF4aW11bSBkaXN0YW5jZSBiZXR3ZWVuIExEIGJsb2NrcyB0byBtZXJnZSBpbnRvIGEgbG9jdXMgPSAyNTBrYiwgdXNpbmcgdGhlIFVLQiByZWxlYXNlMmIgMTBrIFdoaXRlIEJyaXRpc2ggcmVmZXJlbmNlIHBhbmVsIHBvcHVsYXRpb24pLgogIC0gRnVydGhlcm1vcmUsIHdlIHVzZWQgRlVNQSB0byBtYXAgU05WcyB0byBnZW5lcyBiYXNlZCBvbiBwb3NpdGlvbiwgYWdhaW4gd2l0aCB0aGUgZGVmYXVsdCBzZXR0aW5ncyAobWF4aW11bSBkaXN0YW5jZSA9IDEwa2IpLCBhbmQgcHJvdmlkZSB0aGlzIHRhYmxlIG9mIG1hcHBlZCBnZW5lcyBiZWxvdy4gCi0gTGFzdGx5LCB1bmRlciB0aGUgYFN0YWJpbGl0eSBBbmFseXNpc2AgdGFiLCB3ZSBpbnZlc3RpZ2F0ZWQgdGhlIHNpbWlsYXJpdGllcyBhbmQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgQk9MVC1MTU0gYW5kIFBMSU5LIHJlc3VsdHMgYXMgd2VsbCBhcyBiZXR3ZWVuIHRoZSBMVk0gYW5kIExWTWkgcmVzdWx0cy4gCjwvZGl2PgoKYGBge3IgZ3dhcy1tYW5oYXR0YW4sIHJlc3VsdHMgPSAiYXNpcyJ9Cmd3YXNfbWV0aG9kcyA8LSBjKCJCT0xULUxNTSIsICJQbGluayIpCgpnd2FzX2hlYWRlciA8LSAiXG5cbiMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LXNxdWFyZX0gXG5cbiIKcGhlbm90eXBlX2hlYWRlciA8LSAiXG5cbiMjIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9XG5cbiIKZnVtYV9oZWFkZXIgPC0gIlxuXG4jIyMjIyAlcyB7LnVubnVtYmVyZWR9XG5cbiIKClBWQUxfVEhSIDwtIDQKCiMgcGxvdCBnd2FzIHN1bW1hcnkgcmVzdWx0cwppZiAocGFyYW1zJGV2YWwpIHsKICBnd2FzX2xzIDwtIGxpc3QoKQogIHNucHNfdGFiX2xzIDwtIGxpc3QoKQogIGdlbmVzX3RhYl9scyA8LSBsaXN0KCkKICBmb3IgKGd3YXNfbWV0aG9kIGluIGd3YXNfbWV0aG9kcykgewogICAgZ3dhc19sc1tbZ3dhc19tZXRob2RdXSA8LSBsaXN0KCkKICAgIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXNfYWxsKSB7CiAgICAgICMgcmV0cmlldmUgZ3dhcyByZXN1bHRzCiAgICAgIGd3YXNfZGlyIDwtIHBhc3RlMCgiZ3dhc18iLCBzdHJfcmVwbGFjZSh0b2xvd2VyKGd3YXNfbWV0aG9kKSwgIi0iLCAiXyIpKQogICAgICBmbmFtZSA8LSBwYXN0ZTAocGhlbm90eXBlLCAiX25vcm1fYXBwMTM3MjEuc3RhdHNfYW5ub3QiKQogICAgICAjIGd3YXNfbHNbW2d3YXNfbWV0aG9kXV1bW3BoZW5vdHlwZV1dIDwtIGZyZWFkKGZpbGUucGF0aChyZXNfZGlyLCBnd2FzX2RpciwgZm5hbWUpKQoKICAgICAgIyByZXRyaWV2ZSBhbm5vdGF0ZWQgZnVtYSBnd2FzIHJlc3VsdHMKICAgICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlc19hbGwpW3BoZW5vdHlwZXNfYWxsID09IHBoZW5vdHlwZV0KICAgICAgZ3dhc19tZXRob2RfZnN0ciA8LSBzdHJpbmdyOjpzdHJfcmVwbGFjZSh0b2xvd2VyKGd3YXNfbWV0aG9kKSwgIi0iLCAiXyIpCiAgICAgIHBoZW5vdHlwZV9mc3RyIDwtIHN0cmluZ3I6OnN0cl9yZXBsYWNlKHRvbG93ZXIocGhlbm90eXBlKSwgImlsdm0iLCAibHZtaSIpCiAgICAgIGZ1bWFfZnBhdGggPC0gZmlsZS5wYXRoKAogICAgICAgIHJlc19kaXIsICJnd2FzX2Z1bWEiLCBzcHJpbnRmKCIlc18lc19nd2FzIiwgZ3dhc19tZXRob2RfZnN0ciwgcGhlbm90eXBlX2ZzdHIpCiAgICAgICkKICAgICAgbG9jaV90YWIgPC0gZnJlYWQoZmlsZS5wYXRoKGZ1bWFfZnBhdGgsICJHZW5vbWljUmlza0xvY2kudHh0IikpICU+JQogICAgICAgIHRpYmJsZTo6YXNfdGliYmxlKCkKICAgICAgbGVhZHNucHNfdGFiIDwtIGZyZWFkKGZpbGUucGF0aChmdW1hX2ZwYXRoLCAibGVhZFNOUHMudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLU5vKSAlPiUKICAgICAgICB0aWJibGU6OmFzX3RpYmJsZSgpCiAgICAgIGluZHNpZ3NucHNfdGFiIDwtIGZyZWFkKGZpbGUucGF0aChmdW1hX2ZwYXRoLCAiSW5kU2lnU05Qcy50eHQiKSkgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdCgtTm8pICU+JQogICAgICAgIHRpYmJsZTo6YXNfdGliYmxlKCkKICAgICAgZ2VuZXNfdGFiIDwtIGZyZWFkKGZpbGUucGF0aChmdW1hX2ZwYXRoLCAiZ2VuZXMudHh0IikpICU+JQogICAgICAgIHRpYmJsZTo6YXNfdGliYmxlKCkgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgIGBHV0FTIE1ldGhvZGAgPSAhIWd3YXNfbWV0aG9kLAogICAgICAgICAgYFBoZW5vdHlwZWAgPSAhIXBoZW5vdHlwZV9uYW1lCiAgICAgICAgKQogICAgICBzbnBzX3RhYiA8LSBpbmRzaWdzbnBzX3RhYiAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KEdlbm9taWNMb2N1czpwb3MpICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBgVG9wIExlYWQgU05QYCA9IHB1cnJyOjptYXBfbGdsKHVuaXFJRCwgfiAueCAlaW4lIGxvY2lfdGFiJHVuaXFJRCksCiAgICAgICAgICBgTGVhZCBTTlBgID0gcHVycnI6Om1hcF9sZ2wodW5pcUlELCB+IC54ICVpbiUgbGVhZHNucHNfdGFiJHVuaXFJRCksCiAgICAgICAgICBgSW5kLiBTaWcuIFNOUGAgPSBwdXJycjo6bWFwX2xnbCh1bmlxSUQsIH4gLnggJWluJSBpbmRzaWdzbnBzX3RhYiR1bmlxSUQpLAogICAgICAgICAgYEdXQVMgTWV0aG9kYCA9ICEhZ3dhc19tZXRob2QsCiAgICAgICAgICBgUGhlbm90eXBlYCA9ICEhcGhlbm90eXBlX25hbWUKICAgICAgICApCiAgICAgIHNucHNfdGFiX2xzIDwtIGMoc25wc190YWJfbHMsIGxpc3Qoc25wc190YWIpKQogICAgICBnZW5lc190YWJfbHMgPC0gYyhnZW5lc190YWJfbHMsIGxpc3QoZ2VuZXNfdGFiKSkKICAgIH0KICB9CgogICMgY29tcGFyZSBib2x0LWxtbSB2cyBwbGluayByZXN1bHRzCiAgcGx0X2RmIDwtIG1hcDJfZGZyKGd3YXNfbHNbWyJCT0xULUxNTSJdXSwgZ3dhc19sc1tbIlBsaW5rIl1dLAogICAgZnVuY3Rpb24oYm9sdCwgcGxpbmspIHsKICAgICAgaW5uZXJfam9pbigKICAgICAgICB4ID0gYm9sdCAlPiUKICAgICAgICAgIHNlbGVjdChTTlAsIGBCT0xULUxNTWAgPSBQX0JPTFRfTE1NX0lORikgJT4lCiAgICAgICAgICAjIGZpbHRlcigtbG9nMTAoYEJPTFQtTE1NYCkgPiBQVkFMX1RIUikgJT4lCiAgICAgICAgICBtdXRhdGUoYEJPTFQtTE1NYCA9IC1sb2cxMChgQk9MVC1MTU1gKSksCiAgICAgICAgeSA9IHBsaW5rICU+JQogICAgICAgICAgc2VsZWN0KFNOUCwgUGxpbmsgPSBQX0dMTSkgJT4lCiAgICAgICAgICAjIGZpbHRlcigtbG9nMTAoUGxpbmspID4gUFZBTF9USFIpICU+JQogICAgICAgICAgbXV0YXRlKFBsaW5rID0gLWxvZzEwKFBsaW5rKSksCiAgICAgICAgYnkgPSAiU05QIgogICAgICApCiAgICB9LAogICAgLmlkID0gIlBoZW5vdHlwZSIKICApICU+JQogICAgZHBseXI6Om11dGF0ZSggIyBrZWVwID0gKGBCT0xULUxNTWAgPiBQVkFMX1RIUikgfCAoUGxpbmsgPiBQVkFMX1RIUiksCiAgICAgIFBoZW5vdHlwZSA9IGlmZWxzZShQaGVub3R5cGUgPT0gImlMVk0iLCAiTFZNaSIsIFBoZW5vdHlwZSkKICAgICkKICBwbHQgPC0gdmRvY3M6OnBsb3RfcG9pbnQoCiAgICBwbHRfZGYsICMgJT4lIGRwbHlyOjpmaWx0ZXIoa2VlcCksCiAgICB4X3N0ciA9ICJCT0xULUxNTSIsIHlfc3RyID0gIlBsaW5rIiwgc2l6ZSA9IC4xCiAgKSArCiAgICBmYWNldF9ncmlkKH5QaGVub3R5cGUpICsKICAgIGxhYnMoeCA9ICItbG9nMTAoQk9MVC1MTU0gUC12YWx1ZSkiLCB5ID0gIi1sb2cxMChQTElOSyBQLXZhbHVlKSIpCiAgIyBzYXZlUkRTKHBsdCwgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAiZ3dhc19wdmFsdWVzX2NvbXBhcmUucmRzIikpCiAgIyBnZ3NhdmUocGx0LAogICMgICBmaWxlbmFtZSA9IGZpbGUucGF0aChmaWdfcmVzX2RpciwgImd3YXNfcHZhbHVlc19jb21wYXJlLnBuZyIpLAogICMgICB3aWR0aCA9IDYsIGhlaWdodCA9IDMuNQogICMgKQoKICAjIHN1bW1hcml6ZSBmdW1hIGd3YXMgU05QIHJlc3VsdHMgdXNpbmcgc3RhYmlsaXR5IGFjcm9zcyBnd2FzIHJ1bnMKICBzbnBzX3RhYiA8LSBkcGx5cjo6YmluZF9yb3dzKHNucHNfdGFiX2xzKSAlPiUKICAgIHRpZHlyOjpwaXZvdF93aWRlcigKICAgICAgaWRfY29scyA9IGModW5pcUlEOnBvcyksCiAgICAgIG5hbWVzX2Zyb20gPSBjKGBHV0FTIE1ldGhvZGAsIGBQaGVub3R5cGVgKSwKICAgICAgdmFsdWVzX2Zyb20gPSBjKGBUb3AgTGVhZCBTTlBgLCBgTGVhZCBTTlBgLCBgSW5kLiBTaWcuIFNOUGApLAogICAgICBuYW1lc19zZXAgPSAiICIsCiAgICAgIG5hbWVzX3ByZWZpeCA9ICItICIsCiAgICAgIHZhbHVlc19maWxsID0gRkFMU0UKICAgICkgJT4lCiAgICBkcGx5cjo6cm93d2lzZSgpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbl9jb3VudHMgPSBzdW0oZHBseXI6OmNfYWNyb3NzKHdoZXJlKGlzLmxvZ2ljYWwpKSkKICAgICkgJT4lCiAgICBkcGx5cjo6bGVmdF9qb2luKAogICAgICBnd2FzX2xzW1siQk9MVC1MTU0iXV1bWyJpTFZNIl1dICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QocnNJRCA9IFNOUCwgYEJPTFQtTE1NIExWTWkgcC12YWx1ZWAgPSBQX0JPTFRfTE1NX0lORiksCiAgICAgIGJ5ID0gInJzSUQiCiAgICApICU+JQogICAgZHBseXI6OmxlZnRfam9pbigKICAgICAgZ3dhc19sc1tbIkJPTFQtTE1NIl1dW1siTFZNIl1dICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QocnNJRCA9IFNOUCwgYEJPTFQtTE1NIExWTSBwLXZhbHVlYCA9IFBfQk9MVF9MTU1fSU5GKSwKICAgICAgYnkgPSAicnNJRCIKICAgICkgJT4lCiAgICBkcGx5cjo6bGVmdF9qb2luKAogICAgICBnd2FzX2xzW1siUGxpbmsiXV1bWyJpTFZNIl1dICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QocnNJRCA9IFNOUCwgYFBsaW5rIExWTWkgcC12YWx1ZWAgPSBQX0dMTSksCiAgICAgIGJ5ID0gInJzSUQiCiAgICApICU+JQogICAgZHBseXI6OmxlZnRfam9pbigKICAgICAgZ3dhc19sc1tbIlBsaW5rIl1dW1siTFZNIl1dICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QocnNJRCA9IFNOUCwgYFBsaW5rIExWTSBwLXZhbHVlYCA9IFBfR0xNKSwKICAgICAgYnkgPSAicnNJRCIKICAgICkgJT4lCiAgICBkcGx5cjo6cm93d2lzZSgpICU+JQogICAgZHBseXI6Om11dGF0ZSgKICAgICAgbl9wID0gc3VtKCFpcy5uYShkcGx5cjo6Y19hY3Jvc3ModGlkeXNlbGVjdDo6Y29udGFpbnMoInAtdmFsdWUiKSkpKSwKICAgICAgYXZnX3AgPSBtZWFuKGRwbHlyOjpjX2Fjcm9zcyh0aWR5c2VsZWN0Ojpjb250YWlucygicC12YWx1ZSIpKSwgbmEucm0gPSBUUlVFKQogICAgKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKC1uX2NvdW50cywgLW5fcCwgYXZnX3ApCgogIHNucHNfdGFiX2xvbmcgPC0gc25wc190YWIgJT4lCiAgICBkcGx5cjo6c2VsZWN0KAogICAgICAtdW5pcUlELCAtY2hyLCAtcG9zLCAtbl9jb3VudHMsIC1uX3AsIC1hdmdfcCwKICAgICAgLXRpZHlzZWxlY3Q6OmNvbnRhaW5zKCJwLXZhbHVlIikKICAgICkgJT4lCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKAogICAgICBjb2xzID0gYygKICAgICAgICB0aWR5c2VsZWN0OjpzdGFydHNfd2l0aCgiVG9wIiksCiAgICAgICAgdGlkeXNlbGVjdDo6c3RhcnRzX3dpdGgoIkxlYWQiKSwKICAgICAgICB0aWR5c2VsZWN0OjpzdGFydHNfd2l0aCgiSW5kIikKICAgICAgKQogICAgKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIE1ldGhvZCA9IHN0cmluZ3I6OnN0cl90cmltKHN0cmluZ3I6OnN0cl9leHRyYWN0KG5hbWUsICIoPzw9LSlcXHMqLioiKSksCiAgICAgIEdyb3VwID0gZmFjdG9yKAogICAgICAgIHN0cmluZ3I6OnN0cl90cmltKHN0cmluZ3I6OnN0cl9leHRyYWN0KG5hbWUsICJeW14tXSsiKSkgJT4lCiAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZSgiU05QIiwgIlNOViIpLAogICAgICAgIGxldmVscyA9IGMoIlRvcCBMZWFkIFNOViIsICJMZWFkIFNOViIsICJJbmQuIFNpZy4gU05WIikKICAgICAgKSwKICAgICAgcnNJRCA9IGZhY3Rvcihyc0lELCBsZXZlbHMgPSByZXYoc25wc190YWIkcnNJRCkpLAogICAgICB2YWx1ZSA9IGZhY3RvcigKICAgICAgICBpZmVsc2UodmFsdWUsICJUcnVlIiwgIkZhbHNlIiksCiAgICAgICAgbGV2ZWxzID0gYygiVHJ1ZSIsICJGYWxzZSIpCiAgICAgICkKICAgICkKCiAgcGx0IDwtIGdncGxvdDI6OmdncGxvdChzbnBzX3RhYl9sb25nKSArCiAgICBnZ3Bsb3QyOjphZXMoeCA9IE1ldGhvZCwgeSA9IHJzSUQsIGZpbGwgPSB2YWx1ZSkgKwogICAgZ2dwbG90Mjo6ZmFjZXRfZ3JpZCh+R3JvdXApICsKICAgIGdncGxvdDI6Omdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsKICAgIGdncGxvdDI6OnNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMzMzdhYjciLCAiZ3JleTgwIiksIG5hLnZhbHVlID0gImdyZXk4MCIpICsKICAgIGdncGxvdDI6OmxhYnMoeCA9ICIiLCBmaWxsID0gIiIpICsKICAgIHZ0aGVtZXM6OnRoZW1lX3Ztb2Rlcm4oCiAgICAgIHhfdGV4dF9hbmdsZSA9IFRSVUUsIGJnX2NvbG9yID0gIndoaXRlIiwgZ3JpZF9jb2xvciA9ICJ3aGl0ZSIKICAgICkKICAjIHNhdmVSRFMocGx0LCBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsICJnd2FzX2Z1bWFfc25wc19zdGFiaWxpdHlfcGxvdC5yZHMiKSkKICAjIGdnc2F2ZShwbHQsCiAgIyAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAiZ3dhc19mdW1hX3NucHNfc3RhYmlsaXR5X3Bsb3QucG5nIiksCiAgIyAgIHdpZHRoID0gOCwgaGVpZ2h0ID0gNgogICMgKQoKICBkdCA8LSBzbnBzX3RhYiAlPiUKICAgIGRwbHlyOjpzZWxlY3QodW5pcUlEOnBvcykgJT4lCiAgICBwcmV0dHlfRFQocm93bmFtZXMgPSBGQUxTRSkKICAjIHNhdmVSRFMoZHQsIGZpbGUucGF0aCh0YWJfcmVzX2RpciwgImd3YXNfZnVtYV9zbnBzX3N0YWJpbGl0eV90YWJsZS5yZHMiKSkKCiAgIyBzdW1tYXJpemUgZnVtYSBnd2FzIG1hcHBlZCBnZW5lIHJlc3VsdHMgdXNpbmcgc3RhYmlsaXR5IGFjcm9zcyBnd2FzIHJ1bnMKICBnZW5lc190YWIgPC0gZHBseXI6OmJpbmRfcm93cyhnZW5lc190YWJfbHMpICU+JQogICAgZHBseXI6Om11dGF0ZSh2YWx1ZSA9IFRSVUUpICU+JQogICAgdGlkeXI6OnBpdm90X3dpZGVyKAogICAgICBpZF9jb2xzID0gYyhlbnNnLCBzeW1ib2wsIGNociwgc3RhcnQsIGVuZCksCiAgICAgIG5hbWVzX2Zyb20gPSBjKGBHV0FTIE1ldGhvZGAsIGBQaGVub3R5cGVgKSwKICAgICAgdmFsdWVzX2Zyb20gPSB2YWx1ZSwKICAgICAgbmFtZXNfc2VwID0gIiAiLAogICAgICB2YWx1ZXNfZmlsbCA9IEZBTFNFCiAgICApICU+JQogICAgZHBseXI6OnJvd3dpc2UoKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIG5fY291bnRzID0gc3VtKGRwbHlyOjpjX2Fjcm9zcyh3aGVyZShpcy5sb2dpY2FsKSkpCiAgICApICU+JQogICAgZHBseXI6OmFycmFuZ2UoLW5fY291bnRzKQoKICBnZW5lc190YWJfbG9uZyA8LSBnZW5lc190YWIgJT4lCiAgICBkcGx5cjo6c2VsZWN0KC1lbnNnLCAtY2hyLCAtc3RhcnQsIC1lbmQsIC1uX2NvdW50cykgJT4lCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbHMgPSAtc3ltYm9sKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIHN5bWJvbCA9IGZhY3RvcihzeW1ib2wsIGxldmVscyA9IHJldihnZW5lc190YWIkc3ltYm9sKSksCiAgICAgIHZhbHVlID0gZmFjdG9yKAogICAgICAgIGlmZWxzZSh2YWx1ZSwgIk1hcHBlZCIsICJOb3QgTWFwcGVkIiksCiAgICAgICAgbGV2ZWxzID0gYygiTWFwcGVkIiwgIk5vdCBNYXBwZWQiKQogICAgICApCiAgICApCgogIHBsdCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QoZ2VuZXNfdGFiX2xvbmcpICsKICAgIGdncGxvdDI6OmFlcyh4ID0gbmFtZSwgeSA9IHN5bWJvbCwgZmlsbCA9IHZhbHVlKSArCiAgICBnZ3Bsb3QyOjpnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgICBnZ3Bsb3QyOjpzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMzM3YWI3IiwgImdyZXk4MCIpLCBuYS52YWx1ZSA9ICJncmV5ODAiKSArCiAgICBnZ3Bsb3QyOjpsYWJzKHggPSAiIiwgZmlsbCA9ICIiLCB5ID0gIkdlbmUgU3ltYm9sIikgKwogICAgdnRoZW1lczo6dGhlbWVfdm1vZGVybigKICAgICAgeF90ZXh0X2FuZ2xlID0gVFJVRSwgYmdfY29sb3IgPSAid2hpdGUiLCBncmlkX2NvbG9yID0gIndoaXRlIgogICAgKQogICMgc2F2ZVJEUyhwbHQsIGZpbGUucGF0aChmaWdfcmVzX2RpciwgImd3YXNfZnVtYV9nZW5lc19zdGFiaWxpdHlfcGxvdC5yZHMiKSkKICAjIGdnc2F2ZShwbHQsCiAgIyAgIGZpbGVuYW1lID0gZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAiZ3dhc19mdW1hX2dlbmVzX3N0YWJpbGl0eV9wbG90LnBuZyIpLAogICMgICB3aWR0aCA9IDYsIGhlaWdodCA9IDUKICAjICkKCiAgZHQgPC0gZ2VuZXNfdGFiICU+JQogICAgZHBseXI6OnNlbGVjdChlbnNnOmVuZCkgJT4lCiAgICBwcmV0dHlfRFQocm93bmFtZXMgPSBGQUxTRSkKICAjIHNhdmVSRFMoZHQsIGZpbGUucGF0aCh0YWJfcmVzX2RpciwgImd3YXNfZnVtYV9nZW5lc19zdGFiaWxpdHlfdGFibGUucmRzIikpCn0gZWxzZSB7CiAgZm9yIChnd2FzX21ldGhvZCBpbiBnd2FzX21ldGhvZHMpIHsKICAgIGNhdChzcHJpbnRmKGd3YXNfaGVhZGVyLCB0b3VwcGVyKGd3YXNfbWV0aG9kKSkpCiAgICBmb3IgKHBoZW5vdHlwZSBpbiBwaGVub3R5cGVzX2FsbCkgewogICAgICBwaGVub3R5cGVfbmFtZSA8LSBuYW1lcyhwaGVub3R5cGVzX2FsbClbcGhlbm90eXBlc19hbGwgPT0gcGhlbm90eXBlXQogICAgICBnd2FzX21ldGhvZF9mc3RyIDwtIHN0cmluZ3I6OnN0cl9yZXBsYWNlKHRvbG93ZXIoZ3dhc19tZXRob2QpLCAiLSIsICJfIikKICAgICAgcGhlbm90eXBlX2ZzdHIgPC0gc3RyaW5ncjo6c3RyX3JlcGxhY2UodG9sb3dlcihwaGVub3R5cGUpLCAiaWx2bSIsICJsdm1pIikKICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKAogICAgICAgIHJlc19kaXIsICJnd2FzX2Z1bWEiLCBzcHJpbnRmKCIlc18lc19nd2FzIiwgZ3dhc19tZXRob2RfZnN0ciwgcGhlbm90eXBlX2ZzdHIpCiAgICAgICkKICAgICAgY2F0KHNwcmludGYocGhlbm90eXBlX2hlYWRlciwgcGhlbm90eXBlX25hbWUpKQogICAgICBkaXNwbGF5X2ltYWdlKGZpbGUucGF0aChyZXNfZGlyLCAiZ3dhc19mdW1hIiwgc3ByaW50ZigibWFuaGF0dGFuXyVzXyVzLnBuZyIsIGd3YXNfbWV0aG9kX2ZzdHIsIHBoZW5vdHlwZV9mc3RyKSksCiAgICAgICAgY2h1bmtfaWR4ID0gY2h1bmtfaWR4LAogICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInR1dBUyBNYW5oYXR0YW4gcGxvdCBmb3IgdGhlICVzIHBoZW5vdHlwZSB1c2luZyAlcy4gUmVkIGRhc2hlZCBsaW5lIGluZGljYXRlcyB0aGUgZ2Vub21lLXdpZGUgc2lnbmlmaWNhbmNlIGxldmVsIChwID0gNUUtOCkuJyIsIHBoZW5vdHlwZV9uYW1lLCBnd2FzX21ldGhvZCkKICAgICAgKQoKICAgICAgY2F0KHNwcmludGYoZnVtYV9oZWFkZXIsICJHZW5vbWljIFJpc2sgTG9jaSIpKQogICAgICBkdCA8LSBmcmVhZChmaWxlLnBhdGgoZnBhdGgsICJHZW5vbWljUmlza0xvY2kudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLW5TTlBzKSAlPiUKICAgICAgICBkcGx5cjo6cmVuYW1lKAogICAgICAgICAgbkdXQVNTTlZzID0gbkdXQVNTTlBzLAogICAgICAgICAgbkluZFNpZ1NOVnMgPSBuSW5kU2lnU05QcywKICAgICAgICAgIEluZFNpZ1NOVnMgPSBJbmRTaWdTTlBzLAogICAgICAgICAgbkxlYWRTTlZzID0gbkxlYWRTTlBzLAogICAgICAgICAgTGVhZFNOVnMgPSBMZWFkU05QcwogICAgICAgICkgJT4lCiAgICAgICAgcHJldHR5X0RUKHJvd25hbWVzID0gRkFMU0UpCiAgICAgIHN1YmNodW5raWZ5KGR0LAogICAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIicqKkxpc3Qgb2YgZ2Vub21pYyByaXNrIGxvY2kgZnJvbSBGVU1BIGZvciB0aGUgJXMgJXMgR1dBUy4qKiB1bmlxSUQgPSBVbmlxdWUgSUQgb2YgU05WcyBjb25zaXN0cyBvZiBjaHI6cG9zaXRpb246YWxsZWxlMTphbGxlbGUyIHdoZXJlIGFsbGVsZXMgYXJlIGFscGhhYmV0aWNhbGx5IG9yZGVyZWQuIHJzSUQgPSByc0lEIG9mIHRoZSB0b3AgbGVhZCBTTlYgZm9yIHRoZSBnaXZlbiBnZW5vbWljIGxvY3VzLiBjaHIgPSBDaHJvbW9zb21lIG9mIHRvcCBsZWFkIFNOVi4gcG9zID0gUG9zaXRpb24gb2YgdG9wIGxlYWQgU05WIG9uIGhnMTkuIHAgPSBQLXZhbHVlIG9mIHRvcCBsZWFkIFNOVi4gc3RhcnQgPSBTdGFydCBwb3NpdGlvbiBvZiB0aGUgbG9jdXMuIGVuZCA9IEVuZCBwb3NpdGlvbiBvZiB0aGUgbG9jdXMuIG5HV0FTU05WcyA9IE51bWJlciBvZiB0aGUgR1dBUy10YWdnZWQgY2FuZGlkYXRlIFNOVnMgd2l0aGluIHRoZSBnZW5vbWljIGxvY3VzLiBuSW5kU2lnU05WcyA9IE51bWJlciBvZiB0aGUgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBpbiB0aGUgZ2Vub21pYyBsb2N1cy4gSW5kU2lnU05WcyA9IHJzSUQgb2YgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBpbiB0aGUgZ2Vub21pYyBsb2N1cy4gbkxlYWRTTlZzID0gVGhlIG51bWJlciBvZiBsZWFkIFNOVnMgaW4gdGhlIGdlbm9taWMgbG9jdXMuIExlYWRTTlZzID0gcnNJRCBvZiBsZWFkIFNOVnMgaW4gdGhlIGdlbm9taWMgbG9jdXMuJyIsIHBoZW5vdHlwZV9uYW1lLCBnd2FzX21ldGhvZCkKICAgICAgKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgICAgY2F0KHNwcmludGYoZnVtYV9oZWFkZXIsICJMZWFkIFNOVnMiKSkKICAgICAgZHQgPC0gZnJlYWQoZmlsZS5wYXRoKGZwYXRoLCAibGVhZFNOUHMudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLU5vKSAlPiUKICAgICAgICBkcGx5cjo6cmVuYW1lKAogICAgICAgICAgbkluZFNpZ1NOVnMgPSBuSW5kU2lnU05QcywKICAgICAgICAgIEluZFNpZ1NOVnMgPSBJbmRTaWdTTlBzCiAgICAgICAgKSAlPiUKICAgICAgICBwcmV0dHlfRFQocm93bmFtZXMgPSBGQUxTRSkKICAgICAgc3ViY2h1bmtpZnkoZHQsCiAgICAgICAgaSA9IGNodW5rX2lkeCwKICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJyoqTGlzdCBvZiBsZWFkIFNOVnMgZnJvbSBGVU1BIGZvciB0aGUgJXMgJXMgR1dBUy4qKiBHZW5vbWljTG9jdXMgPSBJbmRleCBvZiBhc3NpZ25lZCBnZW5vbWljIGxvY3VzIChub3RlOiBtdWx0aXBsZSBpbmRlcGVuZGVudCBsZWFkIFNOVnMgY2FuIGJlIGFzc2lnbmVkIHRvIHRoZSBzYW1lIGdlbm9taWMgbG9jdXMpLiB1bmlxSUQgPSBVbmlxdWUgSUQgb2YgU05WcyBjb25zaXN0cyBvZiBjaHI6cG9zaXRpb246YWxsZWxlMTphbGxlbGUyIHdoZXJlIGFsbGVsZXMgYXJlIGFscGhhYmV0aWNhbGx5IG9yZGVyZWQuIHJzSUQgPSByc0lEIG9mIHRoZSBTTlYuIGNociA9IENocm9tb3NvbWUuIHBvcyA9IFBvc2l0aW9uIG9uIGhnMTkuIHAgPSBQLXZhbHVlIGZyb20gR1dBUy4gbkluZFNpZ1NOVnMgPSBOdW1iZXIgb2YgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyB3aGljaCBhcmUgaW4gTEQgb2YgdGhlIGxlYWQgU05WIGF0ICRyXjIkID0gMC4xLiBJbmRTaWdTTlZzID0gcnNJRCBvZiBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlZzIHdoaWNoIGFyZSBpbiBMRCBvZiB0aGUgbGVhZCBTTlYgYXQgJHJeMiQgPSAwLjEuJyIsIHBoZW5vdHlwZV9uYW1lLCBnd2FzX21ldGhvZCkKICAgICAgKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgICAgY2F0KHNwcmludGYoZnVtYV9oZWFkZXIsICJJbmRlcGVuZGVudCBTaWduaWZpY2FudCBTTlZzIikpCiAgICAgIGR0IDwtIGZyZWFkKGZpbGUucGF0aChmcGF0aCwgIkluZFNpZ1NOUHMudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLU5vLCAtblNOUHMpICU+JQogICAgICAgIGRwbHlyOjpyZW5hbWUoCiAgICAgICAgICBuR1dBU1NOVnMgPSBuR1dBU1NOUHMKICAgICAgICApICU+JQogICAgICAgIHByZXR0eV9EVChyb3duYW1lcyA9IEZBTFNFKQogICAgICBzdWJjaHVua2lmeShkdCwKICAgICAgICBpID0gY2h1bmtfaWR4LAogICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInKipMaXN0IG9mIGluZGVwZW5kZW50IHNpZ25pZmljYW50IFNOVnMgZnJvbSBGVU1BIGZvciB0aGUgJXMgJXMgR1dBUy4qKiBHZW5vbWljTG9jdXMgPSBJbmRleCBvZiBhc3NpZ25lZCBnZW5vbWljIGxvY3VzIChub3RlOiBtdWx0aXBsZSBpbmRlcGVuZGVudCBsZWFkIFNOVnMgY2FuIGJlIGFzc2lnbmVkIHRvIHRoZSBzYW1lIGdlbm9taWMgbG9jdXMpLiB1bmlxSUQgPSBVbmlxdWUgSUQgb2YgU05WcyBjb25zaXN0cyBvZiBjaHI6cG9zaXRpb246YWxsZWxlMTphbGxlbGUyIHdoZXJlIGFsbGVsZXMgYXJlIGFscGhhYmV0aWNhbGx5IG9yZGVyZWQuIHJzSUQgPSByc0lEIG9mIHRoZSBTTlYuIGNociA9IENocm9tb3NvbWUuIHBvcyA9IFBvc2l0aW9uIG9uIGhnMTkuIHAgPSBQLXZhbHVlIGZyb20gR1dBUy4gbkdXQVNTTlZzID0gTnVtYmVyIG9mIEdXQVMtdGFnZ2VkIFNOVnMgd2hpY2ggYXJlIGluIExEIG9mIHRoZSBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlYgZ2l2ZW4gJHJeMiQgPSAwLjYuJyIsIHBoZW5vdHlwZV9uYW1lLCBnd2FzX21ldGhvZCkKICAgICAgKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgICAgY2F0KHNwcmludGYoZnVtYV9oZWFkZXIsICJNYXBwZWQgR2VuZXMiKSkKICAgICAgZHQgPC0gZnJlYWQoZmlsZS5wYXRoKGZwYXRoLCAiZ2VuZXMudHh0IikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLXRpZHlzZWxlY3Q6OmFueV9vZihjKCJjaU1hcCIsICJjaU1hcHRzIikpKSAlPiUKICAgICAgICBkcGx5cjo6cmVuYW1lKAogICAgICAgICAgcG9zTWFwU05WcyA9IHBvc01hcFNOUHMsCiAgICAgICAgICBJbmRTaWdTTlZzID0gSW5kU2lnU05QcwogICAgICAgICkgJT4lCiAgICAgICAgcHJldHR5X0RUKHJvd25hbWVzID0gRkFMU0UpCiAgICAgIHN1YmNodW5raWZ5KGR0LAogICAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIicqKkxpc3Qgb2YgbWFwcGVkIGdlbmVzICh2aWEgcG9zaXRpb25hbCBtYXBwaW5nKSBmcm9tIEZVTUEgZm9yIHRoZSAlcyAlcyBHV0FTLioqIGVuc2cgPSBFTlNHIElELiBzeW1ib2wgPSBHZW5lIFN5bWJvbC4gY2hyID0gQ2hyb21vc29tZS4gc3RhcnQgPSBTdGFydGluZyBwb3NpdGlvbiBvZiB0aGUgZ2VuZS4gZW5kID0gRW5kaW5nIHBvc2l0aW9uIG9mIHRoZSBnZW5lLiBzdHJhbmQgPSBTdHJhbmQgb2YgdGhlIGdlbmUuIHR5cGUgPSBHZW5lIGJpb3R5cGUgZnJvbSBFbnNlbWJsLiBlbnRyZXpJRCA9IGVudHJleiBJRCAoaWYgYXZhaWxhYmxlKS4gSFVHTyA9IEhVR08gKEhHTkMpIGdlbmUgc3ltYm9sLiBwTEkgPSBwTEkgc2NvcmUgKHRoZSBwcm9iYWJpbGl0eSBvZiBiZWluZyBsb3NzLW9mLWZ1bmN0aW9uIGludG9sZXJhbnQpIGZyb20gRXhBQyBkYXRhYmFzZTsgdGhlIGhpZ2hlciB0aGUgc2NvcmUgaXMsIHRoZSBtb3JlIGludG9sZXJhbnQgdG8gbG9zcy1vZi1mdW5jdGlvbiBtdXRhdGlvbnMgdGhlIGdlbmUgaXMuIG5jUlZJUyA9IE5vbi1jb2RpbmcgcmVzaWR1YWwgdmFyaWF0aW9uIGludG9sZXJhbmNlIHNjb3JlOyB0aGUgaGlnaGVyIHRoZSBzY29yZSBpcywgdGhlIG1vcmUgaW50b2xlcmFudCB0byBub24tY29kaW5nIHZhcmlhdGlvbiB0aGUgZ2VuZSBpcy4gcG9zTWFwU05WcyA9IE51bWJlciBvZiBTTlZzIG1hcHBlZCB0byBnZW5lIGJhc2VkIG9uIHBvc2l0aW9uYWwgbWFwcGluZy4gcG9zTWFwTWF4Q0FERCA9IFRoZSBtYXhpbXVtIENBREQgc2NvcmUgb2YgbWFwcGVkIFNOVnMgYnkgcG9zaXRpb25hbCBtYXBwaW5nLiBtaW5Hd2FzUCA9IFRoZSBtaW5pbXVtIFAtdmFsdWUgb2YgbWFwcGVkIFNOVnMuIEluZFNpZ1NOVnMgPSByc0lEIG9mIHRoZSBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlZzIHRoYXQgYXJlIGluIExEIHdpdGggdGhlIG1hcHBlZCBTTlZzLiBHZW5vbWljTG9jdXMgPSBJbmRleCBvZiBnZW5vbWljIGxvY2kgd2hlcmUgbWFwcGVkIFNOVnMgYXJlIGZyb20uJyIsIHBoZW5vdHlwZV9uYW1lLCBnd2FzX21ldGhvZCkKICAgICAgKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgfQogIH0KfQpgYGAKCgoKIyMjIFN0YWJpbGl0eSBBbmFseXNpcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LWNpcmNsZX0KCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KVG8gZnVydGhlciBpbnZlc3RpZ2F0ZSB0aGUgY2hvaWNlIG9mIEdXQVMgbWV0aG9kIGFuZCBwaGVub3R5cGUsIHdlIGNvbmR1Y3RlZCBhIGRlZXBlciBleHBsb3JhdGlvbiBpbnRvIHRoZSBzaW1pbGFyaXRpZXMgYW5kIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIEJPTFQtTE1NIGFuZCBQTElOSyByZXN1bHRzIGFzIHdlbGwgYXMgYmV0d2VlbiB0aGUgTFZNIGFuZCBMVk1pIHJlc3VsdHMgaW4gdGhlIHN0YWJpbGl0eSBhbmFseXNpcyBiZWxvdy4gVGhlIHByaW1hcnkgZ29hbCBvZiB0aGlzIHN0YWJpbGl0eSBhbmFseXNpcyBpcyB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZyB0d28gcXVlc3Rpb25zOgoKMS4gKipBcmUgdGhlcmUgbGFyZ2UgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgR1dBUyBwLXZhbHVlcyBmcm9tIEJPTFQtTE1NIGFuZCBQTElOSz8qKgogIC0gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0yMik6IEZvciBlYWNoIFNOViwgd2UgcGxvdCB0aGUgcC12YWx1ZSAobG9nLXRyYW5zZm9ybWVkKSBvYnRhaW5lZCB2aWEgQk9MVC1MTU0gKHgtYXhpcykgYW5kIFBMSU5LICh5LWF4aXMpIGZvciBlYWNoIG9mIHRoZSBMVk0gKGxlZnQpIGFuZCBMVk1pIChyaWdodCkgcGhlbm90eXBlcy4gV2Ugc2VlIHRoYXQgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgR1dBUyBoaXRzIHRlbmQgdG8gYmUgc3RhYmxlLCBubyBtYXR0ZXIgdGhlIGNob2ljZSBvZiBhbGdvcml0aG0sIGJ1dCBhcyB0aGUgc3RyZW5ndGggb2YgdGhlIGFzc29jaWF0aW9uIGRlY3JlYXNlcywgdGhlcmUgaXMgZ3JlYXRlciB2YXJpYXRpb24gaW4gdGhlIHAtdmFsdWUgYmV0d2VlbiBCT0xULUxNTSBhbmQgUExJTksuIFRoaXMgaXMgdG8gc2F5IHRoYXQgdGhlcmUgaXMgbW9yZSBzdGFiaWxpdHkgYXJvdW5kIHRoZSBTTlZzIHdpdGggdGhlIHN0cm9uZ2VzdCBhc3NvY2lhdGlvbnMgd2l0aCBMVk1pIGFuZCBsZXNzIHN0YWJpbGl0eSBhcm91bmQgdGhlIFNOVnMgd2l0aCBtb2RlcmF0ZSBvciB3ZWFrIGFzc29jaWF0aW9ucyB3aXRoIExWTWkuIEFub3RoZXIgcmVhc29uIGZvciB0YWtpbmcgdGhlIHVuaW9uIG9mIHRoZSB0b3AgMTAwMCBTTlZzIGZyb20gZWFjaCBHV0FTIGFsZ29yaXRobSBpbiB0aGUgbG8tc2lSRiBwaXBlbGluZSB3YXMgdG8gYWxsb3cgdGhlc2UgbW9kZXJhdGUgdG8gd2VhayBhc3NvY2lhdGlvbiBTTlZzIHRoZSBjaGFuY2Ugb2YgYmVpbmcgaWRlbnRpZmllZCBpbiBhIG11bHRpdmFyaWF0ZSBtb2RlbCAoaS5lLiwgdmlhIGl0ZXJhdGl2ZSByYW5kb20gZm9yZXN0KS4KCjIuICoqV2hhdCBhcmUgdGhlIEZVTUEgR1dBUyBmaW5kaW5ncyB0aGF0IGFyZSBzdGFibGUgYWNyb3NzIEdXQVMgbWV0aG9kcyAoQk9MVC1MTU0gYW5kIFBMSU5LKSBhbmQgY2hvaWNlIG9mIHBoZW5vdHlwZSAoTFZNIGFuZCBMVk1pKT8qKiBBcyBhZHZvY2F0ZWQgYnkgdGhlIHN0YWJpbGl0eSBwcmluY2lwbGUgKCJTIiBpbiBQQ1MpIFtAeXUyMDIwdmVyaWRpY2FsOyBAeXUyMDEzc3RhYmlsaXR5XSwgd2UgdmlldyBzdGFiaWxpdHkgYWNyb3NzIHRoZXNlIGFyYml0cmFyeSBjaG9pY2VzIGFzIGEgbWluaW11bSByZXF1aXJlbWVudCBmb3IgbWFraW5nIGEgc2NpZW50aWZpYyBkaXNjb3ZlcnkuCiAgLSBJbiBGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTIzKSwgd2Ugc3VtbWFyaXplIHRoZSBTTlZzLCBpZGVudGlmaWVkIGJ5IEZVTUEsIHRvIGJlIHRoZSB0b3AgbGVhZCBTTlZzIChwZXIgZ2Vub21pYyByaXNrIGxvY3VzKSwgbGVhZCBTTlZzLCBhbmQvb3IgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBmb3IgZWFjaCBHV0FTIG1ldGhvZCAoQk9MVC1MTU0gYW5kIFBMSU5LKSBhbmQgY2hvaWNlIG9mIHBoZW5vdHlwZSAoTFZNIGFuZCBMVk1pKS4gU29tZSB0YWtlYXdheXMgaGVyZToKICAgIC0gcnMzMDQ1Njk2LCBhbiBpbnRyb25pYyAqVFROKiB2YXJpYW50LCBpcyB0aGUgb25seSBzdGFibGUgdG9wIGxlYWQgU05WLCBpZGVudGlmaWVkIGFjcm9zcyBhbGwgZm91ciBHV0FTIHJ1bnMuCiAgICAtIEJlc2lkZXMgcnMzMDQ1Njk2LCByczE4NzMxNjQsIGFuIGludHJvbmljICpDQ0RDMTQxKiB2YXJpYW50LCBpcyB0aGUgb25seSBzdGFibGUgbGVhZCBTTlYsIGlkZW50aWZpZWQgYnkgRlVNQSBhY3Jvc3MgYWxsIGZvdXIgR1dBUyBydW5zLgogICAgLSByczc1OTEwOTEgKGFuIGludHJvbmljICpDQ0RDMTQxKiB2YXJpYW50IHdpdGggdGhlIGhpZ2hlc3QgZnJlcXVlbmN5IG9mIG9jY3VycmVuY2UgaW4gbG8tc2lSRiwgc2VlbiBsYXRlciksIGFsb25nIHdpdGggcnM5Njc1MDcsIHJzMTI2MjI1MDAsIGFuZCByczEwMTc4MDAzLCB3ZXJlIHN0YWJseSBpZGVudGlmaWVkIGFzIGluZGVwZW5kZW50IHNpZ25pZmljYW50IFNOVnMgYnkgRlVNQSBhY3Jvc3MgYWxsIGZvdXIgR1dBUyBydW5zLgogICAgLSBUd28gb3RoZXIgU05WcyAocnM2MjE3ODk3NywgcnM3Mzk3MzE3MSkgd2VyZSBhbHNvIGlkZW50aWZpZWQgYXMgaW5kZXBlbmRlbnQgc2lnbmlmaWNhbnQgU05WcyBieSBGVU1BIHVzaW5nIGJvdGggQk9MVC1MTU0gYW5kIFBMSU5LIGZvciB0aGUgTFZNaSBwaGVub3R5cGUuCiAgLSBJbiBGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTI0KSwgd2Ugc3VtbWFyaXplIHRoZSBnZW5lcyB0aGF0IHdlcmUgcG9zaXRpb25hbGx5LW1hcHBlZCBhbmQgcHJpb3JpdGl6ZWQgYnkgRlVNQSBhY3Jvc3MgdGhlIGRpZmZlcmVudCBHV0FTIG1ldGhvZHMgKEJPTFQtTE1NIGFuZCBQTElOSykgYW5kIGNob2ljZSBvZiBwaGVub3R5cGUgKExWTSBhbmQgTFZNaSkuCiAgICAtIFRoZSBnZW5lcyB0aGF0IHdlcmUgc3RhYmx5IG1hcHBlZCBieSBGVU1BIGFjcm9zcyBhbGwgZm91ciBHV0FTIHJ1bnMgYXJlICpQUktSQSosICpERk5CNTkqLCAqRktCUDcqLCAqUExFS0hBMyosICpUVE4qLCBhbmQgKkNDREMxNDEqLiBXZSBub3RlIHRoYXQgYWxsIG9mIHRoZXNlIGdlbmVzIGFyZSBsb2NhdGVkIG5lYXIgZWFjaCBvdGhlciBvbiBjaHJvbW9zb21lIDIgd2l0aGluIH42MDBrYi4gVGhlIHN0YXJ0IHBvc2l0aW9uIG9mIFBSS1JBIGlzIDE3OTI5NjE0MSB3aGlsZSB0aGUgZW5kIHBvc2l0aW9uIG9mIENDREMxNDEgaXMgMTc5OTE0ODEzLCB3aXRoIGFsbCBvdGhlciBhZm9yZW1lbnRpb25lZCBnZW5lcyBpbiBiZXR3ZWVuLgogICAgLSBObyBvdGhlciBnZW5lcyB3ZXJlIGlkZW50aWZpZWQgd2hlbiB1c2luZyBib3RoIEJPTFQtTE1NIGFuZCBQTElOSyBmb3IgdGhlIExWTWkgcGhlbm90eXBlLgo8L2Rpdj4KCmBgYHtyIGd3YXMtc3RhYmlsaXR5LCByZXN1bHRzID0gImFzaXMifQpQVkFMX1RIUiA8LSA0CgojIHBsb3Qgc3VtbWFyeSByZXN1bHRzCmlmICghcGFyYW1zJGV2YWwpIHsKICBkaXNwbGF5X2ltYWdlKGZpbGUucGF0aChmaWdfcmVzX2RpciwgImd3YXNfcHZhbHVlc19jb21wYXJlLnBuZyIpLAogICAgY2h1bmtfaWR4ID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9ICInQ29tcGFyaXNvbiBvZiB0aGUgQk9MVC1MTU0gYW5kIFBMSU5LIEdXQVMgcC12YWx1ZXMgZm9yIGVhY2ggcGhlbm90eXBlIChMVk0gbGVmdCwgTFZNaSByaWdodCkuIEVhY2ggcG9pbnQgcmVwcmVzZW50cyBhIFNOViB3aXRoIGl0cyBCT0xULUxNTSBwLXZhbHVlIG9uIHRoZSB4LWF4aXMgYW5kIGl0cyBQTElOSyBwLXZhbHVlIG9uIHRoZSB5LWF4aXMuJyIKICApCgogIGRpc3BsYXlfaW1hZ2UoZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAiZ3dhc19mdW1hX3NucHNfc3RhYmlsaXR5X3Bsb3QucG5nIiksCiAgICBjaHVua19pZHggPSBjaHVua19pZHgsCiAgICBjYXB0aW9uID0gIidTdW1tYXJ5IG9mIGFubm90YXRlZCBTTlZzIGZyb20gRlVNQSBhY3Jvc3MgZGlmZmVyZW50IEdXQVMgbWV0aG9kcyAoQk9MVC1MTU0gYW5kIFBMSU5LKSBhbmQgYWNyb3NzIGRpZmZlcmVudCBjaG9pY2VzIG9mIHBoZW5vdHlwZSAoTFZNaSBhbmQgTFZNKS4nIgogICkKCiAgIyBkdCA8LSByZWFkUkRTKGZpbGUucGF0aCh0YWJfcmVzX2RpciwgImd3YXNfZnVtYV9zbnBzX3N0YWJpbGl0eV90YWJsZS5yZHMiKSkKICAjIHN1YmNodW5raWZ5KGR0LCBpID0gY2h1bmtfaWR4LCBjYXB0aW9uID0gIidMaXN0IG9mIGFubm90YXRlZCBTTlZzIGZyb20gRlVNQS4nIikKICAjIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogIGRpc3BsYXlfaW1hZ2UoZmlsZS5wYXRoKGZpZ19yZXNfZGlyLCAiZ3dhc19mdW1hX2dlbmVzX3N0YWJpbGl0eV9wbG90LnBuZyIpLAogICAgY2h1bmtfaWR4ID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9ICInU3VtbWFyeSBvZiBtYXBwZWQgZ2VuZXMgZnJvbSBGVU1BIGFjcm9zcyBkaWZmZXJlbnQgR1dBUyBtZXRob2RzIChCT0xULUxNTSBhbmQgUExJTkspIGFuZCBhY3Jvc3MgZGlmZmVyZW50IGNob2ljZXMgb2YgcGhlbm90eXBlIChMVk1pIGFuZCBMVk0pLiciCiAgKQoKICAjIGR0IDwtIHJlYWRSRFMoZmlsZS5wYXRoKHRhYl9yZXNfZGlyLCAiZ3dhc19mdW1hX2dlbmVzX3N0YWJpbGl0eV90YWJsZS5yZHMiKSkKICAjIHN1YmNodW5raWZ5KGR0LCBpID0gY2h1bmtfaWR4LCBjYXB0aW9uID0gIidMaXN0IG9mIG1hcHBlZCBnZW5lcyBmcm9tIEZVTUEuJyIpCiAgIyBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQp9CmBgYAoKIyMgR1dBUy1maWx0ZXJlZCBTTlZzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpJbiB0aGlzIHNlY3Rpb24sIHdlIGJyaWVmbHkgZXhwbG9yZSB0aGUgc2VsZWN0ZWQgMTQwNSBTTlZzIHRoYXQgcGFzc2VkIHRoZSBHV0FTIGZpbHRlciBmb3IgdGhlIExWTWkgcGhlbm90eXBlLiBXZSBtYWtlIHR3byBvYnNlcnZhdGlvbnMgdGhhdCB3aWxsIGltcGFjdCBob3cgd2UgaW50ZXJwcmV0IHRoZSBsby1zaVJGIGZpdCBkb3duc3RyZWFtOgoKLSBUaGVyZSBhcmUgc3Ryb25nIGNvcnJlbGF0aW9ucyB3aXRoaW4gYmxvY2tzIG9mIG5laWdoYm9yaW5nIFNOVnMgZHVlIHRvIGxpbmthZ2UgZGlzZXF1aWxpYnJpdW0gKExEKSAoRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0yNSkpLiBUaGlzIGlzIGEgbGFyZ2UgY29udHJpYnV0aW5nIGZhY3RvciBmb3Igd2h5IHdlIHVsdGltYXRlbHkgZXh0cmFjdGVkIGZlYXR1cmUgaW1wb3J0YW5jZXMgZnJvbSB0aGUgbG8tc2lSRiBmaXQgYXQgdGhlIGxldmVsIG9mIGdlbmV0aWMgbG9jaSwgcmF0aGVyIHRoYW4gZm9yIGVhY2ggaW5kaXZpZHVhbCBTTlYuCi0gVGhlcmUgYXJlIGxhcmdlIGRpZmZlcmVuY2VzIGluIHRoZSBudW1iZXIgb2YgU05WcyB0aGF0IHBhc3NlZCB0aGUgR1dBUyBmaWx0ZXIgZnJvbSBlYWNoIGdlbmV0aWMgbG9jaSAoRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0yNikpLiBXZSBoZW5jZSBtdXN0IGFjY291bnQgZm9yIHRoaXMgaW4gdGhlIGxvLXNpUkYgbG9jdXMtbGV2ZWwgaW1wb3J0YW5jZSBzY29yZS4gCgpXZSB3aWxsIGV4cGFuZCB1cG9uIHRoaXMgbG9jdXMtbGV2ZWwgaW1wb3J0YW5jZSBzY29yZSBpbiBhIGxhdGVyIHNlY3Rpb24gKHNlZSBgUHJpb3JpdGl6YXRpb24gU3RlcGApLgoKQWRkaXRpb25hbCBub3RlczoKCi0gR2l2ZW4gdGhlIGludGVyZXN0IGluICpDQ0RDMTQxKiBhbmQgKlRUTiogaW4gb3VyIHdvcmsgYW5kIHRoZWlyIGNsb3NlIHByb3hpbWl0eSB0byBlYWNoIG90aGVyIG9uIGNocm9tb3NvbWUgMiwgd2UgcG9pbnQgb3V0IGEgY291cGxlIHBhaXJ3aXNlIChQZWFyc29uKSBjb3JyZWxhdGlvbnMgb2YgcGFydGljdWxhciByZWxldmFuY2U6CiAgLSAkfCBDb3IoXHRleHR7cnM3NTkxMDkxfSwgXHRleHR7IHJzNjY3MzM2MjF9KSB8ID0gMC4zNSQKICAtICR8IENvcihcdGV4dHtyczc1OTEwOTF9LCBcdGV4dHsgcnMzMDQ1Njk2fSkgfCA9IDAuMzQkCiAgLSByczc1OTEwOTEgaXMgdGhlIHRvcCBTTlYgZnJvbSB0aGUgQ0NEQzE0MSBsb2N1cyBpbiBsby1zaVJGIGFuZCBpcyBvbmUgb2YgdGhlIHRvcCBDQ0RDMTQxIEdXQVMgaGl0cyAoaW4gZmFjdCwgaXMgaWRlbnRpZmllZCB0byBiZSBhIHN0YWJsZSBpbmRlcGVuZGVudCBzaWduaWZpY2FudCBTTlYgKHNlZSBgR1dBUyBSZXN1bHRzIFN1bW1hcnlgIHRhYikpLiByczMwNDU2OTYsIGFuIGludHJvbmljICpUVE4qIFNOViwgd2FzIHN0YWJseSBpZGVudGlmaWVkIHRvIGJlIGEgdG9wIGxlYWQgU05WIGluIHRoZSBHV0FTZXMsIGFuZCByczY2NzMzNjIxIGlzIHRoZSB0b3AgU05WIGZyb20gdGhlIFRUTiBsb2N1cyBpbiBsby1zaVJGLiBUaGlzIGlzIHRvIHNheSB0aGF0IHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBDQ0RDMTQxIGFuZCBUVE4gbG9jaSBpcyBtb2RlcmF0ZSBhbmQgbWF5IHBvc3NpYmx5IHN1Z2dlc3QgaW5kZXBlbmRlbnQgcm9sZXMgb2YgQ0NEQzE0MSBhbmQgVFROIGluIHRoZWlyIGRldGVjdGVkIGludGVyYWN0aW9uLiBBIGZ1cnRoZXIgZGlzY3Vzc2lvbiBvZiB0aGlzIGlzIHByb3ZpZGVkIGluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKGh0dHBzOi8vd3d3Lm1lZHJ4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS8yMDIzLjExLjA2LjIzMjk3ODU4djEpLiBbTm90ZTogd2UgdXNlIHRoZSB0ZXJtICp0b3AgU05WIGZyb20gYSBnZW5ldGljIGxvY3VzIGluIGxvLXNpUkYqIHRvIG1lYW4gdGhlIFNOViBpbiB0aGUgc3BlY2lmaWVkIGdlbmV0aWMgbG9jdXMgd2l0aCB0aGUgaGlnaGVzdCBmcmVxdWVuY3kgb2Ygb2NjdXJyZW5jZSBhY3Jvc3MgZGVjaXNpb24gcGF0aHMgaW4gdGhlIHNpUkYgZml0Ll0KCjwvZGl2PgoKYGBge3IgZWRhLXRvcC1zbnBzLCByZXN1bHRzID0gImFzaXMifQpIRUFUTUFQX0hFSUdIVCA8LSA4CgpwaGVub3R5cGVfaGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgpzdWJzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyMgJXMgey51bm51bWJlcmVkfVxuXG4iCnBoZW5vdHlwZSA8LSAiaUxWTSIKcGhlbm90eXBlX25hbWUgPC0gIkxWTWkiCgppZiAocGFyYW1zJGV2YWwpIHsKICAjIGxvYWQgaW4gZGF0YQogIG5zbnBzIDwtIDEwMDAKICBzbnBsaXN0IDwtICJhcHAxMzcyMSIKICBib2x0X2RpciA8LSBmaWxlLnBhdGgoIi4uIiwgInJlc3VsdHMiLCAiZ3dhc19ib2x0X2xtbSIpCiAgcGxpbmtfZGlyIDwtIGZpbGUucGF0aCgiLi4iLCAicmVzdWx0cyIsICJnd2FzX3BsaW5rIikKICBrZWVwX3NucHMgPC0gbWFwKAogICAgYyhib2x0X2RpciwgcGxpbmtfZGlyKSwKICAgIGZ1bmN0aW9uKGZkaXIpIHsKICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKAogICAgICAgIGZkaXIsCiAgICAgICAgcGFzdGUwKAogICAgICAgICAgcGhlbm90eXBlLCAiX25vcm1fIiwgc25wbGlzdCwKICAgICAgICAgICIuc3RhdHNfYW5ub3QiCiAgICAgICAgKQogICAgICApCiAgICAgIHNucHMgPC0gZnJlYWQoZnBhdGgpICU+JQogICAgICAgIHNsaWNlKDE6bnNucHMpICU+JQogICAgICAgIHB1bGwoU05QKQogICAgfQogICkgJT4lCiAgICBwdXJycjo6cmVkdWNlKGMpICU+JQogICAgdW5pcXVlKCkKICBzbnBfZGYgPC0gbG9hZFNOUEluZm8oa2VlcF9zbnBzLCBieSA9ICJyc0lEIikKICAjIHdyaXRlLmNzdigKICAjICAgc25wX2RmICU+JQogICMgICAgIGRwbHlyOjpzZWxlY3QoLU5hbWUpLAogICMgICAiLi4vcmVzdWx0cy9nd2FzX2ZpbHRlcmVkX3NucHMuY3N2IiwKICAjICAgcXVvdGUgPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UKICAjICkKCiAgIyBmcmVxdWVuY3kgdGFibGUgb2Ygc25wcyBpbiBlYWNoIGxvY2kKICB0YWJfb3V0IDwtIHNucF9kZiAlPiUKICAgIGdyb3VwX2J5KENociwgR2VuZSkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIGBTdGFydCBQb3MuYCA9IG1pbihQb3MpLAogICAgICBgRW5kIFBvcy5gID0gbWF4KFBvcyksCiAgICAgIGAjIFNOUHNgID0gbigpLAogICAgICBgR2VuZSBGdW5jdGlvbmAgPSBkYXRhLmZyYW1lKHRhYmxlKGBHZW5lIEZ1bmN0aW9uYCkpICU+JQogICAgICAgIG11dGF0ZShzdHIgPSBwYXN0ZTAoR2VuZS5GdW5jdGlvbiwgIjogIiwgRnJlcSkpICU+JQogICAgICAgIHB1bGwoc3RyKSAlPiUKICAgICAgICBwYXN0ZShjb2xsYXBzZSA9ICI7ICIpCiAgICApICU+JQogICAgYXJyYW5nZShDaHIsIGBTdGFydCBQb3MuYCkgJT4lCiAgICByZW5hbWUoIkxvY3VzIiA9ICJHZW5lIiwgIkZ1bmN0aW9uIiA9ICJHZW5lIEZ1bmN0aW9uIikKICAjIHNhdmVSRFMoCiAgIyAgIHRhYl9vdXQsCiAgIyAgIGZpbGUucGF0aCgKICAjICAgICB0YWJfcmVzX2RpciwKICAjICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2d3YXNfc25wc19mcmVxdWVuY3lfYnlfZ2VuZS5yZHMiKQogICMgICApCiAgIyApCiAgIyB3cml0ZS5jc3YodGFiX291dCwgIi4uL3Jlc3VsdHMvZ3dhc19maWx0ZXJlZF9zbnBzX2J5X2xvY2kuY3N2IiwgcXVvdGUgPSBGQUxTRSwgcm93Lm5hbWVzID0gRkFMU0UpCgogICMgZ2V0IGRhdGEgdG8gbWFrZSBjb3JyZWxhdGlvbiBoZWF0bWFwCiAgaW52aXNpYmxlKGNhcHR1cmUub3V0cHV0KAogICAgdHJhaW5fZGF0YSA8LSBsb2FkRGF0YSgKICAgICAgcGhlbm9fbmFtZSA9IHBoZW5vdHlwZSwgcGhlbm9fYmluYXJ5ID0gRiwKICAgICAgbiA9IDE1MDAwLCBuX3Rlc3QgPSAwLCBpbmNsdWRlX2RlbXMgPSBGLAogICAgICBzbnBsaXN0ID0gc25wbGlzdCwga2VlcF9zbnBzID0ga2VlcF9zbnBzCiAgICApCiAgKSkKCiAgIyBzbnAgY29ycmVsYXRpb24gaGVhdG1hcAogIGduYW1lcyA8LSBzbnBfZGYgJT4lCiAgICBncm91cF9ieShHZW5lKSAlPiUKICAgIG11dGF0ZShHZW5lTmFtZSA9IHBhc3RlKEdlbmUsIHJzSUQsIHNlcCA9ICIsICIpKSAlPiUKICAgIHB1bGwoR2VuZU5hbWUpCiAgcGx0X2RmIDwtIHRyYWluX2RhdGEkZ2Vub190cmFpbgogIGNvbG5hbWVzKHBsdF9kZikgPC0gZ25hbWVzCiAgcGx0IDwtIHZkb2NzOjpwbG90X2Nvcl9oZWF0bWFwKFggPSBwbHRfZGYsIGFic29sdXRlX3ZhbHVlID0gVFJVRSwgY2x1c3QgPSBGQUxTRSkgKwogICAgbGFicyh4ID0gIlNOViIsIHkgPSAiU05WIiwgZmlsbCA9ICJ8Q29ycmVsYXRpb258IikgKwogICAgZ2dwbG90Mjo6c2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAid2hpdGUiLCBoaWdoID0gInJlZCIpCiAgIyBjbGVhbiB1cCBheGVzIGxhYmVscyAtIG9ubHkgc2hvdyBnZW5lcyB3aXRoID4gMiBzbnBzCiAgZGF0YV9sb25nIDwtIHBsdCRkYXRhICU+JQogICAgbXV0YXRlKAogICAgICBHZW5lX3kgPSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwdXJycjo6bWFwX2NocihzdHJpbmdyOjpzdHJfc3BsaXQoeSwgIiwgIiksIH4gLnhbWzFdXSkpLAogICAgICBHZW5lX3ggPSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwdXJycjo6bWFwX2NocihzdHJpbmdyOjpzdHJfc3BsaXQoeCwgIiwgIiksIH4gLnhbWzFdXSkpCiAgICApCiAgZ2VuZV9mcmVxIDwtIHRhYmxlKGRhdGFfbG9uZyRHZW5lX3gpIC8gbWluKHRhYmxlKGRhdGFfbG9uZyRHZW5lX3gpKQogIGludmlzaWJsZV9nZW5lcyA8LSBuYW1lcyhnZW5lX2ZyZXFbZ2VuZV9mcmVxIDw9IDJdKQogIHBsdF9icmVha3MgPC0gZGF0YV9sb25nICU+JQogICAgZHBseXI6Omdyb3VwX2J5KEdlbmVfeCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBvcmRlciA9IDE6ZHBseXI6Om4oKSAtIHJvdW5kKGRwbHlyOjpuKCkgLyAyKSwKICAgICAgR2VuZV94ID0gaWZlbHNlKEdlbmVfeCAlaW4lIGludmlzaWJsZV9nZW5lcywgIiIsIGFzLmNoYXJhY3RlcihHZW5lX3gpKQogICAgKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIob3JkZXIgPT0gMCkgJT4lCiAgICBkcGx5cjo6dW5ncm91cCgpCiAgcGx0X2JyZWFrcyA8LSBkcGx5cjo6YmluZF9yb3dzKAogICAgcGx0X2JyZWFrcywKICAgIGRhdGEuZnJhbWUoR2VuZV94ID0gIlRUTiwgcnM2NjczMzYyMSIsIHggPSAiVFROLCByczY2NzMzNjIxIiwgb3JkZXIgPSAxKSwKICAgIGRhdGEuZnJhbWUoR2VuZV94ID0gIlRUTiwgcnMzMDQ1Njk2IiwgeCA9ICJUVE4sIHJzMzA0NTY5NiIsIG9yZGVyID0gMSksCiAgICBkYXRhLmZyYW1lKEdlbmVfeCA9ICJDQ0RDMTQxLCByczc1OTEwOTEiLCB4ID0gIkNDREMxNDEsIHJzNzU5MTA5MSIsIG9yZGVyID0gMSkKICApCiAgcGx0IDwtIHBsdCArCiAgICBnZ3Bsb3QyOjpzY2FsZV94X2Rpc2NyZXRlKAogICAgICBicmVha3MgPSBwbHRfYnJlYWtzJHgsIGxhYmVscyA9IHBsdF9icmVha3MkR2VuZV94CiAgICApICsKICAgIGdncGxvdDI6OnNjYWxlX3lfZGlzY3JldGUoCiAgICAgIGJyZWFrcyA9IHBsdF9icmVha3MkeCwgbGFiZWxzID0gcGx0X2JyZWFrcyRHZW5lX3gKICAgICkgKwogICAgZ2dwbG90Mjo6dGhlbWUoCiAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KAogICAgICAgIGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUsCiAgICAgICAgY29sb3IgPSBpZmVsc2UocGx0X2JyZWFrcyRvcmRlciwgImNvcm5mbG93ZXJibHVlIiwgImJsYWNrIikKICAgICAgKSwKICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoY29sb3IgPSBpZmVsc2UocGx0X2JyZWFrcyRvcmRlciwgImNvcm5mbG93ZXJibHVlIiwgImJsYWNrIikpCiAgICApCiAgIyBzYXZlUkRTKAogICMgICBwbHQsCiAgIyAgIGZpbGUucGF0aCgKICAjICAgICBmaWdfcmVzX2RpciwKICAjICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2d3YXNfc25wc19jb3JfaGVhdG1hcF9ieV9wb3MucmRzIikKICAjICAgKQogICMgKQogICMgZ2dzYXZlKHBsdCwKICAjICAgZmlsZW5hbWUgPSBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfZ3dhc19zbnBzX2Nvcl9oZWF0bWFwX2J5X3Bvcy5wbmciKSksCiAgIyAgIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwCiAgIyApCn0gZWxzZSB7CiAgY2F0KHNwcmludGYocGhlbm90eXBlX2hlYWRlciwgc3ByaW50ZigiJXMgLSBDb3JyZWxhdGlvbiBCZXR3ZWVuIEdXQVMtZmlsdGVyZWQgU05WcyIsIHBoZW5vdHlwZV9uYW1lKSkpCiAgZGlzcGxheV9pbWFnZShmaWxlLnBhdGgoZmlnX3Jlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfZ3dhc19zbnBzX2Nvcl9oZWF0bWFwX2J5X3Bvcy5wbmciKSksCiAgICBjaHVua19pZHggPSBjaHVua19pZHgsCiAgICBjYXB0aW9uID0gIidDb3JyZWxhdGlvbiBoZWF0bWFwIGZvciB0aGUgR1dBUy1maWx0ZXJlZCBTTlZzLiBXZSBwbG90IHRoZSBtYWduaXR1ZGUgb2YgdGhlIFBlYXJzb24gY29ycmVsYXRpb24gYmV0d2VlbiBhbGwgcG9zc2libGUgcGFpcnMgb2YgU05WcyB0aGF0IHBhc3NlZCB0aGUgR1dBUyBmaWx0ZXIuIERhcmtlciByZWQgaW5kaWNhdGVzIGhpZ2hlciBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0d28gU05Wcy4gU05WcyBhbG9uZyB0aGUgYXhlcyBhcmUgb3JkZXJlZCBhY2NvcmRpbmcgdG8gZ2Vub21pYyBsb2NhdGlvbi4gTG9jaSB3aXRoIG1vcmUgdGhhbiB0d28gY29uc3RpdHVlbnQgU05WcyBhcmUgbGFiZWxlZC4nIgogICkKCiAgY2F0KHNwcmludGYocGhlbm90eXBlX2hlYWRlciwgc3ByaW50ZigiJXMgLSBUYWJsZSBvZiBHV0FTLWZpbHRlcmVkIFNOVnMiLCBwaGVub3R5cGVfbmFtZSkpKQogIHRhYiA8LSByZWFkUkRTKAogICAgZmlsZS5wYXRoKAogICAgICB0YWJfcmVzX2RpciwKICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9nd2FzX3NucHNfZnJlcXVlbmN5X2J5X2dlbmUucmRzIikKICAgICkKICApICU+JQogICAgZHBseXI6OnNlbGVjdCgtYFN0YXJ0IFBvcy5gLCAtYEVuZCBQb3MuYCkgJT4lCiAgICBkcGx5cjo6cmVuYW1lKCJMb2N1cyIgPSAiR2VuZSIsICIjIFNOVnMiID0gIiMgU05QcyIsICJGdW5jdGlvbiIgPSAiR2VuZSBGdW5jdGlvbiIpICU+JQogICAgcHJldHR5X0RUKHJvd25hbWVzID0gRkFMU0UpCiAgc3ViY2h1bmtpZnkodGFiLAogICAgaSA9IGNodW5rX2lkeCwgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgIGNhcHRpb24gPSAiJ051bWJlciBvZiBTTlZzIHBlciBnZW5ldGljIGxvY3VzIHRoYXQgcGFzc2VkIHRoZSBHV0FTIGZpbHRlci4gTm90ZTogYSBzZW1pY29sb24gaXMgdXNlZCB0byBkZW5vdGUgdGhlIGludGVyZ2VuaWMgcmVnaW9uIGJldHdlZW4gdHdvIGdlbmVzLiciCiAgKQogIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCn0KYGBgCgoKIyBCaW5hcml6YXRpb24gU3RlcCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC12bW9kZXJufQoKIyMgT3ZlcnZpZXcgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CgpJbiB0aGUgbmV4dCBzdGVwIG9mIGxvLXNpUkYsIHdlIGNob3NlIHRvIGJpbmFyaXplIHRoZSAoY29udGludW91cykgTFZNaSBwaGVub3R5cGUgbWVhc3VyZW1lbnRzIGludG8gdHdvIGNhdGVnb3JpZXM6IGEgbG93IExWTWkgZ3JvdXAgYW5kIGEgaGlnaCBMVk1pIGdyb3VwIGJlZm9yZSBmaXR0aW5nIHRoZSBwcmVkaWN0aW9uIG1vZGVscy4KCioqV2h5IGRpZCB3ZSBjaG9vc2UgdG8gYmluYXJpemU/KiogT25lIG9mIG91ciBtYWluIG1vdGl2YXRpbmcgZmFjdG9ycyB0byBwdXJzdWUgYmluYXJpemF0aW9uIHJldm9sdmVkIGFyb3VuZCB0aGUgcHJlZGljdGlvbiBjaGVjayBjcml0ZXJpYSBpbiB0aGUgUENTIGZyYW1ld29yayBbQHl1MjAyMHZlcmlkaWNhbF0uIFRoaXMgcHJlZGljdGFiaWxpdHkgcHJpbmNpcGxlIGFkdm9jYXRlcyBmb3IgdGhlIHVzZSBvZiBwcmVkaWN0aW9uIGFjY3VyYWN5IGFzIGEgcmVhbGl0eSBjaGVjay4gVGhpcyBpcyB0byBzYXkgdGhhdCBhdCBhIG1pbmltdW0sIG1vZGVscyBzaG91bGQgZml0IHRoZSBkYXRhIHdlbGwsIGFzIG1lYXN1cmVkIGJ5IHByZWRpY3Rpb24gYWNjdXJhY3ksIGJlZm9yZSBiZWxpZXZpbmcgdGhhdCB0aGUgbW9kZWwgaXMgY2FwdHVyaW5nIHNvbWV0aGluZyByZWxldmFudCB0byByZWFsaXR5IG9yIHRoZSByZWFsLXdvcmxkIHBoZW5vbWVuYSB1bmRlciBzdHVkeS4gSW4gcGFydGljdWxhciwgYmVmb3JlIHdlIHRob3VnaHQgdG8gYmluYXJpemUgdGhlIHBoZW5vdHlwZSwgd2UgZmlyc3QgYXR0ZW1wdGVkIHRvIHRyYWluIHByZWRpY3Rpb24gbW9kZWxzIHVzaW5nIHRoZSBHV0FTLWZpbHRlcmVkIFNOVnMgdG8gcHJlZGljdCB0aGUgb3JpZ2luYWwgKGNvbnRpbnVvdXMpIExWTWkgcGhlbm90eXBlIG1lYXN1cmVtZW50cy4gV2hpbGUgdGhpcyBzZWVtZWQgbGlrZSB0aGUgbW9zdCBuYXR1cmFsIG5leHQgc3RlcCwgdGhlc2UgcHJlZGljdGlvbiByZXN1bHRzIGlsbHVtaW5hdGVkIGFuIGluY3JlZGlibHkgd2VhayBwcmVkaWN0aW9uIHNpZ25hbCwgd2l0aCB2YWxpZGF0aW9uICRSXjIkIHZhbHVlcyBob3ZlcmluZyB2ZXJ5IGNsb3NlIHRvIDAgKHNlZSBGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTI3KSBpbiB0aGUgYFByZWRpY3Rpb24gUmVzdWx0cyB3aXRob3V0IEJpbmFyaXphdGlvbmAgdGFiKS4gR2l2ZW4gdGhhdCBhbiAkUl4yJCB2YWx1ZSBvZiAwIGNhbiBiZSBhY2hpZXZlZCBieSBzaW1wbHkgcHJlZGljdGluZyB0aGUgbWVhbiBMVk1pIHJlc3BvbnNlLCB0aGlzIHJhaXNlZCB0aGUgcXVlc3Rpb24gb2Ygd2hldGhlciB0aGVzZSBwcmVkaWN0aW9uIG1vZGVscyBhcmUgY2FwdHVyaW5nIGFueSBiaW9sb2dpY2FsbHktcmVsZXZhbnQgc2lnbmFsIGluIHRoZSBkYXRhLiBDb25zZXF1ZW50bHksIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGVzZSBtb2RlbHMgbWF5IG5vdCBiZSBhbiBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbiBvZiByZWFsaXR5LiBQdXQgZGlmZmVyZW50bHksIHRoZXNlIG1vZGVscyBkbyBub3Qgc2F0aXNmeSB0aGUgcHJlZGljdGlvbiBjaGVjayBjcml0ZXJpYSB1bmRlciB0aGUgUENTIGZyYW1ld29yay4KCkdpdmVuIHRoZXNlIGRpZmZpY3VsdGllcyBpbiBhY2N1cmF0ZWx5IHByZWRpY3RpbmcgTFZNaSwgd2UgZHJldyBpbnNwaXJhdGlvbiBmcm9tIGhvdyBzY2llbnRpc3RzIG9mdGVuIHJlZHVjZSBjb21wbGV4IHByb2JsZW1zIGludG8gc2ltcGxpZmllZCB2ZXJzaW9ucy4gSGVyZSwgdGhlIGNvbXBsZXggdmVyc2lvbiBvZiBvdXIgcHJvYmxlbSBhaW1zIHRvIHVuZGVyc3RhbmQgaG93IFNOVnMgYXJlIHByZWRpY3RpdmUgb2Ygb25lJ3MgcHJlY2lzZSAoY29udGludW91cy12YWx1ZWQpIExWTWkgbWVhc3VyZW1lbnQuIFRoaXMgaXMgY2hhbGxlbmdpbmcsIGFzIGRlbW9uc3RyYXRlZCBieSB0aGUgcG9vciBwcmVkaWN0aW9uIGFjY3VyYWN5IGRpc2N1c3NlZCBwcmV2aW91c2x5LiBPbiB0aGUgb3RoZXIgaGFuZCwgYXJndWFibHkgdGhlIG1vc3Qgc2ltcGxpZmllZCB2ZXJzaW9uIG9mIHRoaXMgcHJvYmxlbSBpcyB0byB1bmRlcnN0YW5kIGhvdyBTTlZzIGFyZSBwcmVkaWN0aXZlIG9mIHdoZXRoZXIgb25lIGhhcyBhbiBleHRyZW1lbHkgaGlnaCBvciBleHRyZW1lbHkgbG93IExWTWkgbWVhc3VyZW1lbnQuIEludHVpdGl2ZWx5LCBpZiB0aGVyZSBhcmUgaW4gZmFjdCBnZW5ldGljIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlc2UgdHdvIExWIGNoYW1iZXIgc3RhdGVzLCB0aGVuIGRpZmZlcmVudGlhdGluZyBiZXR3ZWVuIHRoZSB0d28gZ3JvdXBzIC0tLSB0aG9zZSB3aXRoIGV4dHJlbWVseSBoaWdoIExWTWkgYW5kIHRob3NlIHdpdGggZXh0cmVtZWx5IGxvdyBMVk1pIC0tLSBzaG91bGQgYmUgZWFzaWVyIHRoYW4gdGhlIG9yaWdpbmFsIHJlZ3Jlc3Npb24gcHJvYmxlbSAoaS5lLiwgcHJlZGljdGluZyB0aGUgcmF3IGNvbnRpbnVvdXMtdmFsdWVkIExWTWkgcmVzcG9uc2UpLiBJbmRlZWQsIHdlIHdpbGwgc2VlIHRoaXMgdG8gYmUgdGhlIGNhc2UsIG9ic2VydmluZyB0aGF0IHRoZSByZXN1bHRpbmcgY2xhc3NpZmljYXRpb24gbW9kZWxzIGNvbnNpc3RlbnRseSBwZXJmb3JtZWQgYmV0dGVyIHRoYW4gcmFuZG9tIGd1ZXNzaW5nIHVubGlrZSB0aGUgb3JpZ2luYWwgcmVncmVzc2lvbiBtb2RlbHMuIE1vcmUgc3BlY2lmaWNhbGx5LCB3ZSBvYnNlcnZlZCBiYWxhbmNlZCBjbGFzc2lmaWNhdGlvbiBhY2N1cmFjaWVzICQ+NTVcJSQsIGFyZWEgdW5kZXIgdGhlIHJlY2VpdmVyIG9wZXJhdG9yIGNoYXJhY3RlcmlzdGljIChBVVJPQykgJD4wLjU4JCwgYW5kIGFyZWEgdW5kZXIgdGhlIHByZWNpc2lvbi1yZWNhbGwgY3VydmUgKEFVUFJDKSAkPjAuNTUkIGZvciB0aGUgY29uc3RydWN0ZWQgYmluYXJ5IGNsYXNzaWZpY2F0aW9uIHRhc2sgKHNlZSB0aGUgYFByZWRpY3Rpb24gU3RlcGAgdGFiKS4gVGhpcyBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIGluc3RpbGxzIGdyZWF0ZXIgdHJ1c3R3b3J0aGluZXNzIHRoYXQgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZXNlIG1vZGVscyBhZnRlciBiaW5hcml6YXRpb24gYXJlIG1vcmUgcmVsZXZhbnQgdG8gdGhlIGJpb2xvZ2ljYWwgcGhlbm9tZW5hIHRoYW4gdGhlIGNhc2Ugd2l0aG91dCBiaW5hcml6YXRpb24uCgoqKkhvdyBpcyB0aGUgYmluYXJpemF0aW9uIGRvbmU/KiogV2UgdHJhbnNmb3JtZWQgdGhlIG9yaWdpbmFsIHJlZ3Jlc3Npb24gcHJvYmxlbSBvZiBwcmVkaWN0aW5nIHRoZSByYXcgY29udGludW91cy12YWx1ZWQgTFZNaSByZXNwb25zZSBpbnRvIGEgYmluYXJ5IGNsYXNzaWZpY2F0aW9uIHByb2JsZW0gYXMgZm9sbG93cy4gRm9yIHBhcnRpY3VsYXIgY2hvaWNlIG9mIHRocmVzaG9sZCAkeCQsIHdlIHBhcnRpdGlvbmVkIHRoZSByYXcgY29udGludW91cy12YWx1ZWQgTFZNaSBwaGVub3R5cGUgaW50byBhIGxvdywgbWlkZGxlLCBhbmQgaGlnaCBMVk1pIGdyb3VwIGNvcnJlc3BvbmRpbmcgdG8gdGhlICRbMCwgeF0kLCAkKHgsIDEteCkkLCBhbmQgJFsxLXgsIDFdJCBxdWFudGlsZSByYW5nZXMsIHJlc3BlY3RpdmVseS4gV2UgdGhlbiBvbWl0dGVkIHRoZSBpbmRpdmlkdWFscyBpbiB0aGUgbWlkZGxlIHF1YW50aWxlIHJhbmdlIGFuZCB0cmFpbmVkIHRoZSBwcmVkaWN0aW9uIG1vZGVscyB0byBkaWZmZXJlbnRpYXRlIGJldHdlZW4gdGhlIGxvdyBhbmQgaGlnaCBMVk1pIGluZGl2aWR1YWxzLiBIb3dldmVyLCBkdWUgdG8gdGhlIGdlbmRlci1zcGVjaWZpYyBiaW9sb2dpY2FsIHZhcmlhdGlvbiBvZiBMVk1pIHNob3duIGVhcmxpZXIgaW4gdGhlIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgKHNlZSBgQ2hvaWNlIG9mIFBoZW5vdHlwaWMgRGF0YWApLCB3ZSBwZXJmb3JtZWQgdGhpcyBiaW5hcml6YXRpb24gcHJvY2VkdXJlIGZvciBtYWxlcyBhbmQgZmVtYWxlcyBzZXBhcmF0ZWx5LiBUaGF0IGlzLCB3ZSBjb21wdXRlZCB0aGUgcXVhbnRpbGVzIGZvciBtYWxlcyBhbmQgZmVtYWxlcyBzZXBhcmF0ZWx5LiBGaW5hbGx5LCBnaXZlbiB0aGF0IHRoaXMgdGhyZXNob2xkIGlzIGFydGlmaWNpYWxseSBpbnRyb2R1Y2VkLCB3ZSBydW4gdGhlIHJlbWFpbmRlciBvZiB0aGUgbG8tc2lSRiBwaXBlbGluZSB1c2luZyB0aHJlZSBkaWZmZXJlbnQgcmVhc29uYWJsZSBiaW5hcml6YXRpb24gdGhyZXNob2xkcyAoMTVcJSwgMjBcJSwgMjVcJSkgdGhhdCBiYWxhbmNlIHRoZSBpbXByb3ZlbWVudCBpbiBwcmVkaWN0aW9uIHNpZ25hbCBhbmQgYW1vdW50IG9mIGRhdGEgbG9zdC4gSW4gcGFydGljdWxhciwgd2Ugbm90ZSB0aGF0IGlmIHdlIGhhZCBjaG9zZW4gYSBiaW5hcml6YXRpb24gdGhyZXNob2xkIG9mIDUwXCUgc28gdGhhdCBubyBkYXRhIGlzIHRocm93biBvdXQsIHRoZW4gdGhlIGJhbGFuY2VkIGNsYXNzaWZpY2F0aW9uIGFjY3VyYWN5IG9mIHRoZSBiZXN0LXBlcmZvcm1pbmcgcHJlZGljdGlvbiBtb2RlbCAoc2lnbmVkIGl0ZXJhdGl2ZSByYW5kb20gZm9yZXN0KSBmYWxscyB0byAkNTElJCwgd2hpY2ggaXMgdmVyeSBzaW1pbGFyIHRvIHJhbmRvbSBndWVzc2luZy4gSW4gdGhlIGVuZCwgd2Ugd2lsbCBjb25zb2xpZGF0ZSB0aGUgcmVzdWx0cyB0aGF0IHdlcmUgc3RhYmxlIGFjcm9zcyBhbGwgdGhyZWUgYmluYXJpemF0aW9uIHRocmVzaG9sZHMgKDE1XCUsIDIwXCUsIDI1XCUpLCBkZXNjcmliZWQgbGF0ZXIuCgoqKkxpbWl0YXRpb25zIG9mIGJpbmFyaXphdGlvbjoqKiBXZSByZWNvZ25pemUgdGhhdCB0aGlzIGJpbmFyaXphdGlvbiBwcm9jZWR1cmUgaGFzIGxpbWl0YXRpb25zIGFuZCB0aGF0IHRoZXNlIGxpbWl0YXRpb25zIHNob3VsZCBiZSBjYXJlZnVsbHkgY29uc2lkZXJlZCBpbiBjb250ZXh0IG9mIHRoZSBwcm9ibGVtIHVuZGVyIHN0dWR5LiBGb3IgaW5zdGFuY2UsIHRoZSB1dGlsaXR5IG9mIHRoaXMgYmluYXJpemF0aW9uIGlzIGhpZ2hseSBkZXBlbmRlbnQgb24gd2hldGhlciB1bmRlcnN0YW5kaW5nIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBsb3cgYW5kIGhpZ2ggcXVhbnRpbGVzIGlzIHJlbGV2YW50IHRvIHRoZSBzdHVkeSBhaW1zLiBJbiBvdXIgY2FzZSwgd2UgYmVsaWV2ZSB0aGF0IHRoZSBjb25uZWN0aW9uIGJldHdlZW4gY2FyZGlhYyBoeXBlcnRyb3BoeSBhbmQgdGhvc2Ugd2l0aCBoaWdoIExWTWkgaGVscHMgdG8ganVzdGlmeSB0aGUgdXNlIG9mIGJpbmFyaXppbmcgYmFzZWQgb24gdGhlIGxvdyBhbmQgaGlnaCBxdWFudGlsZXMuIElmIG9uZSBkb2VzIG5vdCBleHBlY3QgYSBtb25vdG9uaWMgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGdlbmV0aWMgZmVhdHVyZXMgYW5kIHRoZSBwaGVub3R5cGUsIHRoZW4gYmluYXJpemF0aW9uIG1heSBub3QgYmUgYXBwcm9wcmlhdGUuIEluIGFkZGl0aW9uLCBiaW5hcml6YXRpb24gYWxzbyByZXF1aXJlcyB0aGUgY2hvaWNlIG9mIGJpbmFyaXphdGlvbiB0aHJlc2hvbGQuIFRoaXMgY2hvaWNlIGlzIGFsbW9zdCBjZXJ0YWlubHkgYSBzdWJqZWN0aXZlIGNob2ljZSBhbmQgdGh1cyBuZWNlc3NpdGF0ZXMgYSBzdGFiaWxpdHkgYW5hbHlzaXMsIHRoYXQgaXMsIGFuYWx5emluZyB0aGUgc3RhYmlsaXR5IG9mIGZpbmRpbmdzIGFjcm9zcyBkaWZmZXJlbnQgY2hvaWNlcyBvZiBiaW5hcml6YXRpb24gdGhyZXNob2xkcy4gSW4gb3VyIGNhc2UsIHdlIG9ubHkgcHJpb3JpdGl6ZSBsb2NpL2ludGVyYWN0aW9ucyB0aGF0IHdlcmUgc3RhYmx5IGltcG9ydGFudCBhY3Jvc3MgdGhyZWUgZGlmZmVyZW50IGNob2ljZXMgb2YgYmluYXJpemF0aW9uIHRocmVzaG9sZCAoMTUlLCAyMCUsIGFuZCAyNSUpLiBGaW5hbGx5LCBiaW5hcml6YXRpb24gYWxzbyByZWR1Y2VzIHRoZSBzYW1wbGUgc2l6ZSBhbmQgc3lzdGVtYXRpY2FsbHkgb21pdHMgaW5kaXZpZHVhbHMgd2hvIGFyZSBub3QgaW4gdGhlIHRhaWxzIG9mIHRoZSBwaGVub3R5cGUgZGlzdHJpYnV0aW9uLiBBcyBhIHJlc3VsdCwgdGhlcmUgbWF5IGJlIGFkZGl0aW9uYWwgaW50ZXJhY3Rpb25zIHRoYXQgYXJlIG1pc3NlZCBpbiBsby1zaVJGLiBXaGlsZSB3ZSBkbyBub3QgdmlldyB0aGlzIGFzIGEgbWFqb3IgY29uY2VybiBpZiB0aGUgZ29hbCBpcyB0byByZWNvbW1lbmQgYSBzbWFsbCBzZXQgb2YgcmVsaWFibGUgZXhwZXJpbWVudGFsIHRhcmdldHMsIHRoaXMgbGltaXRhdGlvbiBtYXkgY2VydGFpbmx5IGltcGFjdCBzdHVkaWVzIHdpdGggZGlmZmVyZW50IGVuZCBnb2Fscy4KCldlIGV4cGFuZCBvbiB0aGUgcHJlZGljdGlvbiBtb2RlbGluZyB3aXRoIHRoZSBiaW5hcml6ZWQgTFZNaSBwaGVub3R5cGUgaW4gdGhlIG5leHQgc2VjdGlvbiAoc2VlIGBQcmVkaWN0aW9uIFN0ZXBgKS4KCjwvZGl2PgoKCiMjIFByZWRpY3Rpb24gUmVzdWx0cyB3aXRob3V0IEJpbmFyaXphdGlvbiB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LXNxdWFyZX0KCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KCkhlcmUsIHdlIHByZXNlbnQgYSBzdW1tYXJ5IG9mIHRoZSBwcmVkaWN0aW9uIG1vZGVsaW5nIHJlc3VsdHMsIHdoZXJlIHdlIHVzZSB0aGUgR1dBUy1maWx0ZXJlZCBTTlZzIHRvIHByZWRpY3QgdGhlIHJhdyBMVk1pIHBoZW5vdHlwZSBtZWFzdXJlbWVudHMgKGkuZS4sIHdpdGhvdXQgYW55IGJpbmFyaXphdGlvbikuIFNwZWNpZmljYWxseSwgd2UgbWVhc3VyZSB0aGUgdmFsaWRhdGlvbiBzZXQgcHJlZGljdGlvbiBhY2N1cmFjeSBmcm9tIHNldmVyYWwgcG9wdWxhciBtYWNoaW5lIGxlYXJuaW5nIHJlZ3Jlc3Npb24gYWxnb3JpdGhtcyAoa2VybmVsIHJpZGdlIHJlZ3Jlc3Npb24sIExhc3NvIHJlZ3Jlc3Npb24sIHJpZGdlIHJlZ3Jlc3Npb24sIHJhbmRvbSBmb3Jlc3QgKFJGKSwgYW5kIHNpZ25lZCBpdGVyYXRpdmUgcmFuZG9tIGZvcmVzdCAoc2lSRikpIGFjcm9zcyBmb3VyIGRpZmZlcmVudCBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIG1ldHJpY3MgLSB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiwgbWVhbiBhYnNvbHV0ZSBlcnJvciAoTUFFKSwgUi1zcXVhcmVkLCBhbmQgcm9vdC1tZWFuLXNxdWFyZWQgZXJyb3IgKFJNU0UpIGJldHdlZW4gdGhlIG9ic2VydmVkIExWTWkgcmVzcG9uc2UgYW5kIHRoZSBwcmVkaWN0ZWQgTFZNaSByZXNwb25zZS4gV2UgYWxzbyB2aXN1YWxpemUgaG93IHRoZSBwcmVkaWN0ZWQgcmVzcG9uc2VzIGRpZmZlciBhY3Jvc3MgdGhlIGRpZmZlcmVudCBwcmVkaWN0aW9uIG1vZGVscyBpbiB0aGUgcHJvdmlkZWQgcGFpciBwbG90cy4gVGhvdWdoIFJGIGFwcGVhcnMgdG8geWllbGQgdGhlIGJlc3QgcHJlZGljdGlvbiBwZXJmb3JtYW5jZSByZWxhdGl2ZSB0byB0aGUgb3RoZXIgbWV0aG9kcyB1bmRlciBjb25zaWRlcmF0aW9uLCB0aGUgUkYgcHJlZGljdGlvbiBwZXJmb3JtYW5jZSBpcyBzdGlsbCB2ZXJ5IHBvb3IgYXMgYm90aCB0aGUgY29ycmVsYXRpb24gYW5kIFItc3F1YXJlZCBtZXRyaWNzIGFyZSB2ZXJ5IGNsb3NlIHRvIDAuIAoKPC9kaXY+CgpgYGB7ciBwcmVkLXJlc3VsdHMtY3RzLCByZXN1bHRzID0gImFzaXMifQojIHBoZW5vdHlwZV9oZWFkZXIgPC0gIlxuXG4jIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9IFxuXG4iCnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgpzdWJzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyMjICVzIHsudW5udW1iZXJlZH0gXG5cbiIKCm1ldGhvZHMgPC0gYygiTGFzc28iID0gImxhc3NvIiwgIlJpZGdlIiA9ICJyaWRnZSIsICJSRiIgPSAicmYiLCAic2lSRiIgPSAiaXJmIiwgIktlcm5lbCBSaWRnZSIgPSAia2VybmVsX3JpZGdlIikKCmlmIChwYXJhbXMkZXZhbCkgewogIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXMpIHsKICAgIGZwYXRoIDwtIGZpbGUucGF0aChyZXNfZGlyLCBwYXN0ZTAocGhlbm90eXBlLCAiX2d3YXNfZmlsdGVyZWRfbnNucHMxMDAwIikpCgogICAgIyByZWFkIGluIHByZWRpY3Rpb24gcmVzdWx0cyB3aXRoIGRlbW9ncmFwaGljcwogICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJ2YWxpZGF0aW9uX3BoZW5vLlJkYXRhIikpICMgPiBwaGVubwogICAgcHJlZHNfZGF0YSA8LSBsaXN0KAogICAgICB5aGF0ID0gYygKICAgICAgICByZWFkUkRTKGZpbGUucGF0aChmcGF0aCwgInlwcmVkLnJkcyIpKSwKICAgICAgICBmcmVhZChmaWxlLnBhdGgoZnBhdGgsICJ5cHJlZC5jc3YiKSkKICAgICAgKSwKICAgICAgeSA9IHBoZW5vLAogICAgICBnZW5kZXIgPSBpZmVsc2UobG9hZERlbW9ncmFwaGljcyhuYW1lcyhwaGVubykpWywgImdlbmRlciJdID09IDEsCiAgICAgICAgIk1hbGUiLCAiRmVtYWxlIgogICAgICApICU+JQogICAgICAgIGFzLmZhY3RvcigpCiAgICApCgogICAgcHJlZHNfZGF0YSR5aGF0IDwtIHByZWRzX2RhdGEkeWhhdFttZXRob2RzXQogICAgbmFtZXMocHJlZHNfZGF0YSR5aGF0KSA8LSBuYW1lcyhtZXRob2RzKQoKICAgICMgcHJlZGljdGlvbiBhY2N1cmFjeSB0YWJsZQogICAgbWV0cmljcyA8LSBjKCJSTVNFIiwgIlIyIiwgIk1BRSIsICJDb3JyZWxhdGlvbiIpCiAgICBldmFsX291dCA8LSBtYXBfZGZyKHByZWRzX2RhdGEkeWhhdCwKICAgICAgfiBldmFsUHJlZHMoCiAgICAgICAgeSA9IHByZWRzX2RhdGEkeSwgeWhhdCA9IGMoLngpLAogICAgICAgIG1ldHJpYyA9IG1ldHJpY3MKICAgICAgKSwKICAgICAgLmlkID0gIk1ldGhvZCIKICAgICkgJT4lCiAgICAgIHNwcmVhZChrZXkgPSAiTWV0cmljIiwgdmFsdWUgPSAiVmFsdWUiKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICBkcGx5cjo6YWNyb3NzKAogICAgICAgICAgYyhDb3JyZWxhdGlvbiwgUjIpLAogICAgICAgICAgfiBpZmVsc2UoLnggPT0gbWF4KC54KSwKICAgICAgICAgICAga2FibGVFeHRyYTo6Y2VsbF9zcGVjKGZvcm1hdEMoLngsIGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJnIiwgZmxhZyA9ICIjIiksIGJvbGQgPSBUUlVFKSwKICAgICAgICAgICAgZm9ybWF0QygueCwgZGlnaXRzID0gMywgZm9ybWF0ID0gImciLCBmbGFnID0gIiMiKQogICAgICAgICAgKQogICAgICAgICksCiAgICAgICAgZHBseXI6OmFjcm9zcygKICAgICAgICAgIGMoTUFFLCBSTVNFKSwKICAgICAgICAgIH4gaWZlbHNlKC54ID09IG1pbigueCksCiAgICAgICAgICAgIGthYmxlRXh0cmE6OmNlbGxfc3BlYyhmb3JtYXRDKC54LCBkaWdpdHMgPSA0LCBmb3JtYXQgPSAiZyIsIGZsYWcgPSAiIyIpLCBib2xkID0gVFJVRSksCiAgICAgICAgICAgIGZvcm1hdEMoLngsIGRpZ2l0cyA9IDQsIGZvcm1hdCA9ICJnIiwgZmxhZyA9ICIjIikKICAgICAgICAgICkKICAgICAgICApCiAgICAgICkKICAgIHRhYiA8LSBwcmV0dHlfRFQoZXZhbF9vdXQsCiAgICAgIGRpZ2l0cyA9IDQsIHNpZ2ZpZyA9IFRSVUUsIHJvd25hbWVzID0gRkFMU0UsCiAgICAgIG5hX2Rpc3AgPSAiLS0iLAogICAgICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gbnJvdyhldmFsX291dCksIGRvbSA9ICJ0IikKICAgICkKICAgICMgc2F2ZVJEUygKICAgICMgICB0YWIsCiAgICAjICAgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLCBwYXN0ZTAocGhlbm90eXBlLCAiX3ByZWRfYWNjdXJhY3kucmRzIikpCiAgICAjICkKCiAgICAjIHByZWRpY3Rpb24gcGFpciBwbG90cwogICAgcGx0X2RmIDwtIG1hcF9kZmMocHJlZHNfZGF0YSR5aGF0LCB+IGMoLngpKQogICAgcGx0IDwtIHBsb3RfcGFpcnMoCiAgICAgIGRhdGEgPSBwbHRfZGYsIGNvbHVtbnMgPSAxOm5jb2wocGx0X2RmKSwKICAgICAgY29sb3IgPSBwcmVkc19kYXRhJGdlbmRlcgogICAgKQogICAgIyBzYXZlUkRTKAogICAgIyAgIHBsdCwKICAgICMgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfcHJlZF9wYWlyX3Bsb3QucmRzIikpCiAgICAjICkKICB9Cn0gZWxzZSB7CiAgZm9yIChwaGVub3R5cGUgaW4gcGhlbm90eXBlcykgewogICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlcylbcGhlbm90eXBlcyA9PSBwaGVub3R5cGVdCiAgICAjIGNhdChzcHJpbnRmKHBoZW5vdHlwZV9oZWFkZXIsIHBoZW5vdHlwZV9uYW1lKSkKCiAgICAjIHByZWRpY3Rpb24gYWNjdXJhY3kgdGFibGUKICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiUHJlZGljdGlvbiBBY2N1cmFjaWVzIikpCiAgICB0YWIgPC0gcmVhZFJEUygKICAgICAgZmlsZS5wYXRoKHRhYl9yZXNfZGlyLCBwYXN0ZTAocGhlbm90eXBlLCAiX3ByZWRfYWNjdXJhY3kucmRzIikpCiAgICApCiAgICBzdWJjaHVua2lmeSh0YWIsCiAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIG9uIHRoZSB2YWxpZGF0aW9uIHNldCBmb3IgdGhlICVzIHBoZW5vdHlwZSAod2l0aG91dCBiaW5hcml6YXRpb24pIGFjcm9zcyB2YXJpb3VzIHByZWRpY3Rpb24gbWV0aG9kcyBhbmQgZXZhbHVhdGlvbiBtZXRyaWNzLiciLCBwaGVub3R5cGVfbmFtZSkKICAgICkKICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogICAgIyBwcmVkaWN0aW9uIHBhaXIgcGxvdHMKICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiUHJlZGljdGlvbiBQYWlyIFBsb3QiKSkKICAgIHBsdCA8LSByZWFkUkRTKAogICAgICBmaWxlLnBhdGgoCiAgICAgICAgZmlnX3Jlc19kaXIsCiAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9wcmVkX3BhaXJfcGxvdC5yZHMiKQogICAgICApCiAgICApCiAgICBzdWJjaHVua2lmeShwbHQsCiAgICAgIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBwbHQkbmNvbCAqIDEuNSwKICAgICAgYWRkX2NsYXNzID0gYygicGFuZWwgcGFuZWwtZGVmYXVsdCIpLAogICAgICBvdGhlcl9hcmdzID0gIm91dC53aWR0aD0nMTAwJSciLAogICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1BhaXIgcGxvdCBvZiB0aGUgcHJlZGljdGVkICVzIHJlc3BvbnNlcyBmcm9tIHZhcmlvdXMgcHJlZGljdGlvbiBtb2RlbHMuIEVhY2ggcG9pbnQgcmVwcmVzZW50cyBhbiBpbmRpdmlkdWFsIGluIHRoZSB2YWxpZGF0aW9uIHNldCwgYW5kIHRoZSBjb29yZGluYXRlcyByZXByZXNlbnQgdGhlIHByZWRpY3RlZCAlcyByZXNwb25zZSBmcm9tIHR3byBkaWZmZXJlbnQgcHJlZGljdGlvbiBtZXRob2RzLCB3aGljaCBhcmUgc3BlY2lmaWVkIGJ5IHRoZSB4IGFuZCB5LWF4ZXMgbGFiZWxzIGluIGVhY2ggc3VicGxvdC4gRGVuc2l0eSBkaXN0cmlidXRpb25zIG9mIHRoZSBwcmVkaWN0ZWQgJXMgcmVzcG9uc2VzIGFyZSBzaG93biBhbG9uZyB0aGUgZGlhZ29uYWwuJyIsIHBoZW5vdHlwZV9uYW1lLCBwaGVub3R5cGVfbmFtZSwgcGhlbm90eXBlX25hbWUpCiAgICApCiAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogIH0KfQpgYGAKCiMgUHJlZGljdGlvbiBTdGVwIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXZtb2Rlcm59Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CgpBZnRlciBjaG9vc2luZyB0byBiaW5hcml6ZSB0aGUgTFZNaSBwaGVub3R5cGUsIHdlIG5leHQgZml0IHZhcmlvdXMgcHJlZGljdGlvbiBtb2RlbHMgdXNpbmcgdGhlIEdXQVMtZmlsdGVyZWQgU05WcyB0byBwcmVkaWN0IHRoZSBiaW5hcml6ZWQgTFZNaSBwaGVub3R5cGUgYW5kIGFzc2VzcyB0aGVpciB2YWxpZGF0aW9uIHByZWRpY3Rpb24gYWNjdXJhY3kuIAoKKipXaGljaCBtb2RlbHMgd2VyZSBjaG9zZW4gYW5kIHdoeT8qKiBXaGlsZSB0aGVyZSBhcmUgbWFueSBtZXRob2RzLCBlYWNoIHdpdGggdGhlaXIgdW5pcXVlIGFkdmFudGFnZXMgYW5kIGRpc2FkdmFudGFnZXMsIGZvciBkZXRlY3RpbmcgZXBpc3Rhc2lzIGZyb20gZGF0YSBbZS5nLiwgc2VlIEBuaWVsMjAxNXN1cnZleSBhbmQgcmVmZXJlbmNlcyB0aGVyZWluXSwgd2UgY2hvc2UgdG8gZm9jdXMgb24gc2lSRiBbQGt1bWJpZXIyMDE4cmVmaW5pbmddIGFzIG91ciBwcmltYXJ5IGludGVyYWN0aW9uIHNlYXJjaCBlbmdpbmUgZm9yIHZhcmlvdXMgcmVhc29ucy4gCgoxLiBVbmxpa2UgbWFueSBtZXRob2RzIHRoYXQgbWFrZSBsaW5lYXIgYXNzdW1wdGlvbnMgb3IgcmVxdWlyZSBwcmUtc3BlY2lmaWNhdGlvbiBvZiBpbnRlcmFjdGlvbiBvcmRlciAoaS5lLiwgdGhlIG51bWJlciBvZiBmZWF0dXJlcyBpbnZvbHZlZCBpbiBhbiBpbnRlcmFjdGlvbiksIHNpUkYgY2FuIGlkZW50aWZ5ICpoaWdoZXItb3JkZXIqLCAqbm9ubGluZWFyKiBCb29sZWFuIGludGVyYWN0aW9ucyBpbiBhIGNvbXB1dGF0aW9uYWxseS10cmFjdGFibGUgbWFubmVyIHdpdGhvdXQgdGhlIG5lZWQgdG8gc3BlY2lmeSB0aGUgaW50ZXJhY3Rpb24gb3JkZXIgb2YgaW50ZXJlc3QuIAoyLiBBbm90aGVyIGFkdmFudGFnZSBvZiBzaVJGIGZvciBkZXRlY3RpbmcgaW50ZXJhY3Rpb25zIGlzIHRoZSByZXNlbWJsYW5jZSBiZXR3ZWVuIHRoZSBsb2NhbGl6ZWQgdGhyZXNob2xkaW5nIGJlaGF2aW9yIG9mIGl0cyBkZWNpc2lvbiB0cmVlcyBhbmQgdGhlIHRocmVzaG9sZCAob3Igb24tb2ZmIHN3aXRjaC1saWtlKSBiZWhhdmlvciBmcmVxdWVudGx5IG9ic2VydmVkIGluIGJpb21vbGVjdWxhciBpbnRlcmFjdGlvbnMgW0BuZWxzb24yMDA4bGVobmluZ2VyXS4gSW4gb3RoZXIgd29yZHMsIHRoZSBmb3JtIG9mIHRoZSBzaVJGIG1vZGVsIGFwcGVhcnMgdG8gYmUgd2VsbC1zdWl0ZWQgZm9yIHRoZSBiaW9sb2dpY2FsIHBoZW5vbWVuYSB1bmRlciBzdHVkeS4KMy4gRnVydGhlcm1vcmUsIHRoZSBwcmVkaWN0aW9uIGFjY3VyYWN5IG9mIHRoZSBzaVJGIG1vZGVsIGZpdCBjYW4gYmUgZWFzaWx5IGFzc2Vzc2VkLiBzaVJGIGFsc28gZXhoaWJpdGVkIGhpZ2hlciBwcmVkaWN0aW9uIGFjY3VyYWN5IHRoYW4gb3RoZXIgY29tbW9ubHkgdXNlZCBwcmVkaWN0aW9uIG1ldGhvZHMgYWNyb3NzIGFsbW9zdCBhbGwgZXZhbHVhdGlvbiBtZXRyaWNzIGV4YW1pbmVkIGFuZCBiaW5hcml6YXRpb24gdGhyZXNob2xkcyAoRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay0yOSkpLiBBcyBkaXNjdXNzZWQgcHJldmlvdXNseSwgcHJlZGljdGlvbiBhY2N1cmFjeSBjYW4gc2VydmUgYXMgYW4gaW5kaWNhdG9yIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBtb2RlbCBpcyBhbiBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbiBvZiByZWFsaXR5LiBUaGlzIHByZWRpY3Rpb24gY2hlY2sgaXMgYSBuZWNlc3NhcnkgcHJlLXJlcXVpc2l0ZSBmb3IgaW50ZXJwcmV0aW5nIHRoZSBwcmVkaWN0aW9uIG1vZGVsIGFuZCBpcyBlc3BlY2lhbGx5IGltcG9ydGFudCBpbiBsb3ctc2lnbmFsIHJlZ2ltZXMgc3VjaCBhcyB0aGlzIHN0dWR5Lgo0LiBzaVJGIGFuZCBpdHMgcHJlZGVjZXNzb3IgaVJGIGhhdmUgZGVtb25zdHJhdGVkIGdyZWF0IHN1Y2Nlc3MgaW4gZGV0ZWN0aW5nIHJlbGlhYmxlIGludGVyYWN0aW9ucyBpbiBwcmV2aW91cyByZWFsLXdvcmxkIHN0dWRpZXMsIHN1Y2ggYXMgaW4gZXBpc3Rhc2lzLWNvbnRyb2xsZWQgaGFpciBjb2xvciBbQGJlaHIyMDIwbGVhcm5pbmddLCBvYmVzaXR5IFtAYWxsZW4yMDIydXNpbmddLCBzY2hpem9waHJlbmlhIFtAZGUyMDIybWFjaGluZV0sIGFuZCBwcmVkaWN0aXZlIGdlbmUgZXhwcmVzc2lvbiBuZXR3b3JrcyBbQGNsaWZmMjAxOWhpZ2g7IEB3YWxrZXIyMDIyZXZhbHVhdGluZ10uCjUuIEZpbmFsbHksIGR1ZSB0byB0aGUgd2VhayBwaGVub3R5cGljIHNpZ25hbCBhbmQgdGhlIHN0cm9uZyBjb3JyZWxhdGlvbnMgYmV0d2VlbiBuZWlnaGJvcmluZyBTTlZzIGR1ZSB0byBsaW5rYWdlIGRpc2VxdWlsaWJyaXVtIChGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTI1KSksIHdlIGJlbGlldmVkIGl0IHdhcyBtb3N0IGFwcHJvcHJpYXRlIHRvIHJlY29tbWVuZCBpbnRlcmFjdGlvbnMgYmV0d2VlbiBnZW5ldGljIGxvY2ksIHJhdGhlciB0aGFuIGludGVyYWN0aW9ucyBiZXR3ZWVlbiBpbmRpdmlkdWFsIFNOVnMuIFdoaWxlIGl0IGlzIG5vdCBhbHdheXMgY2xlYXIgaG93IHRvIHBlcmZvcm0gdGhpcyBsb2N1cy1sZXZlbCBpbnRlcmFjdGlvbiBzZWFyY2ggd2hlbiB0aGUgZGF0YSBpcyBnaXZlbiBhdCB0aGUgU05WLWxldmVsLCB3ZSBjYW4gYnVpbGQgdXBvbiB0aGUgc2lSRiBzdHJ1Y3R1cmUgdG8gYWdncmVnYXRlIGZlYXR1cmUgaW1wb3J0YW5jZXMgYWNyb3NzIG11bHRpcGxlIFNOVnMgdXNpbmcgb3VyIG5ldyBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlIHNjb3JlLCBkZXNjcmliZWQgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkuCgpUaG91Z2ggd2UgYXJlIG1vc3QgaW50ZXJlc3RlZCBpbiBpbnRlcnByZXRpbmcgdGhlIHNpUkYgcHJlZGljdGlvbiBtb2RlbCB0byBpZGVudGlmeSBjYW5kaWRhdGUgZXBpc3RhdGljIGludGVyYWN0aW9ucywgd2UgYWxzbyBmaXQgc2V2ZXJhbCBvdGhlciBwb3B1bGFyIHByZWRpY3Rpb24gbW9kZWxzLCBpbmNsdWRpbmcgUkYsIEwxLXJlZ3VsYXJpemVkIGxvZ2lzdGljIHJlZ3Jlc3Npb24gKExhc3NvKSwgTDItcmVndWxhcml6ZWQgbG9naXN0aWMgcmVncmVzc2lvbiAocmlkZ2UpLCBzdXBwb3J0IHZlY3RvciBtYWNoaW5lcyAoU1ZNKSwgbXVsdGlsYXllciBwZXJjZXB0cm9uLCBBdXRvR2x1b24gVGFidWxhclByZWRpY3RvciwgYW5kIGEgcG9seWdlbmljIHJpc2sgc2NvcmUuIFRoZXNlIHByZWRpY3Rpb24gbW9kZWxzIHNlcnZlIGFzIGJhc2VsaW5lcyB0byBlbnN1cmUgdGhhdCBzaVJGIGluZGVlZCBmaXRzIHRoZSBkYXRhIHdlbGwsIHJlbGF0aXZlIHRvIHRoZXNlIG90aGVyIHBvcHVsYXIgcHJlZGljdGlvbiBtb2RlbHMsIGFuZCB0aGF0IHNpUkYgcGFzc2VzIHRoZSBwcmVkaWN0aW9uIGNoZWNrIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgUENTIGZyYW1ld29yayBbQHl1MjAyMHZlcmlkaWNhbF0uCgoqKlN1bW1hcnkgb2YgcHJlZGljdGlvbiByZXN1bHRzOioqIEZvciBhbGwgb2YgdGhlIGNsYXNzaWZpY2F0aW9uIGFsZ29yaXRobXMgdW5kZXIgaW52ZXN0aWdhdGlvbiwgd2Ugc2VlIHRoYXQgdGhlIHZhbGlkYXRpb24gcHJlZGljdGlvbiBhY2N1cmFjeSBtZXRyaWNzLCBtZWFzdXJlZCB2aWEgY2xhc3NpZmljYXRpb24gYWNjdXJhY3ksIGFyZWEgdW5kZXIgdGhlIHJlY2VpdmVyIG9wZXJhdG9yIGNoYXJhY3RlcmlzdGljIGN1cnZlIChBVVJPQyksIGFuZCBhcmVhIHVuZGVyIHRoZSBwcmVjaXNpb24tcmVjYWxsIGN1cnZlIChBVVBSQyksIGFyZSBhbGwgY29tZm9ydGFibHkgYWJvdmUgdGhlIHJhbmRvbS1ndWVzc2luZyBiYXNlbGluZSBvZiAwLjUgYWNyb3NzIHRocmVlIGRpZmZlcmVudCBiaW5hcml6YXRpb24gdGhyZXNob2xkcy4gVGhpcyBzdWdnZXN0cyB0aGF0IHRoZSBwcmVkaWN0aW9uIG1vZGVscyBhcmUgYWJsZSB0byBhc2NlcnRhaW4gc29tZSBwaGVub3R5cGljIHNpZ25hbCBmcm9tIHRoZSBTTlZzIHVuZGVyIHN0dWR5LiBUaGF0IGlzLCB0aGUgU05WcyB1c2VkIGluIHRoZSBwcmVkaWN0aW9uIG1vZGVscyBoYXZlIHNvbWUgcHJlZGljdGl2ZSBwb3dlciBpbiBkaWZmZXJlbnRpYXRpbmcgdGhvc2Ugd2l0aCBoaWdoIExWTWkgdmVyc3VzIHRob3NlIHdpdGggbG93IExWTWkuIE1vcmVvdmVyLCBzaVJGIGNvbnNpc3RlbnRseSB5aWVsZGVkIHRoZSBoaWdoZXN0IHByZWRpY3RpdmUgcG93ZXIgYWNyb3NzIHRoZSB2YXJpb3VzIGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzIGFuZCBwcmVkaWN0aW9uIG1ldHJpY3MgKHdpdGggb25lIGV4Y2VwdGlvbiBiZWluZyB0aGUgY2xhc3NpZmljYXRpb24gYWNjdXJhY3kgZm9yIHRoZSAxNVwlIGJpbmFyaXphdGlvbiB0aHJlc2hvbGQsIHdoZXJlIHJpZGdlIGlzIHNsaWdodGx5IGJldHRlciB0aGFuIHNpUkYpLiBGcm9tIHRoaXMsIHdlIGNvbmNsdWRlIHRoYXQgc2lSRiBwYXNzZWQgdGhlIHByZWRpY3Rpb24gY2hlY2sgYW5kIHdpbGwgcHJvY2VlZCB0byBpbnRlcnByZXQgdGhlIHNpUkYgZml0IHRvIHJlY29tbWVuZCBhbmQgcHJpb3JpdGl6ZSBpbnRlcmFjdGlvbnMgYmV0d2VlbiBnZW5ldGljIGxvY2kgZm9yIGRvd25zdHJlYW0gYW5hbHlzZXMgYW5kIGV4cGVyaW1lbnRzLgoKQmV5b25kIHRoZSB2YWxpZGF0aW9uIHByZWRpY3Rpb24gYWNjdXJhY2llcywgd2UgYWxzbyBwcm92aWRlIHRoZSBjb25mdXNpb24gbWF0cmljZXMsIFJPQyBhbmQgcHJlY2lzaW9uLXJlY2FsbCBjdXJ2ZXMsIGFuZCBwYWlyIHBsb3RzIGNvbXBhcmluZyB0aGUgcHJlZGljdGVkIHJlc3BvbnNlcyBhY3Jvc3MgbWV0aG9kcyBmb3IgYWRkaXRpb25hbCBwb3N0LWhvYyBleHBsb3JhdGlvbi4KCjwvZGl2PgoKYGBge3IgcHJlZC1yZXN1bHRzLWJpbmFyeSwgcmVzdWx0cyA9ICJhc2lzIn0KIyBwaGVub3R5cGVfaGVhZGVyIDwtICJcblxuIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9IFxuXG4iCnN1bW1hcnlfaGVhZGVyIDwtICJcblxuIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9XG5cbiIKdGhyX2hlYWRlciA8LSAiXG5cbiMjIEJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LXNxdWFyZX1cblxuIgpzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LWNpcmNsZX0gXG5cbiIKc3Vic2VjdGlvbl9oZWFkZXIgPC0gIlxuXG4jIyMjICVzIHsudW5udW1iZXJlZH0gXG5cbiIKCm1ldGhvZHMgPC0gYygic2lSRiIgPSAiaXJmIiwgIlJGIiA9ICJyZiIsICJMYXNzbyIgPSAibGFzc28iLCAiUmlkZ2UiID0gInJpZGdlIiwgIlNWTSIgPSAic3ZtIiwgIk1MUCIgPSAibWxwIiwgIkF1dG9nbHVvbiAobWVkaXVtKSIgPSAiYXV0b2dsdW9uX21lZGl1bSIsICJBdXRvZ2x1b24gKGdvb2QpIiA9ICJhdXRvZ2x1b25fZ29vZCIsICJQUlMiID0gInBycyIpCgpBVUNfSEVJR0hUIDwtIDUKCmlmIChwYXJhbXMkZXZhbCkgewogIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXMpIHsKICAgIGV2YWxfbHMgPC0gbGlzdCgpCiAgICBwaGVub3R5cGVfbmFtZSA8LSBuYW1lcyhwaGVub3R5cGVzKVtwaGVub3R5cGVzID09IHBoZW5vdHlwZV0KICAgIGZvciAodGhyIGluIGMoMC4xNSwgMC4yLCAwLjI1KSkgewogICAgICBmcGF0aCA8LSBmaWxlLnBhdGgocmVzX2RpciwgcGFzdGUwKAogICAgICAgIHBoZW5vdHlwZSwgIl9iaW5hcnlfdGhyIiwgdGhyLAogICAgICAgICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiCiAgICAgICkpCiAgICAgICMgcmVhZCBpbiBwcmVkaWN0aW9uIHJlc3VsdHMKICAgICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJ2YWxpZGF0aW9uX3BoZW5vLlJkYXRhIikpICMgPiBwaGVubwogICAgICBwcmVkc19kYXRhIDwtIGxpc3QoCiAgICAgICAgeWhhdCA9IGMoCiAgICAgICAgICByZWFkUkRTKGZpbGUucGF0aChmcGF0aCwgInlwcmVkLnJkcyIpKSwKICAgICAgICAgIGZyZWFkKGZpbGUucGF0aChmcGF0aCwgInlwcmVkLmNzdiIpKSwKICAgICAgICAgIHBycyA9IHJlYWRSRFMoZmlsZS5wYXRoKHJlc19kaXIsICJwcnMiLCAicHJzX3ByZWQucmRzIikpW2FzLmNoYXJhY3Rlcih0aHIpXSAlPiUKICAgICAgICAgICAgdW5uYW1lKCkKICAgICAgICApLAogICAgICAgIHkgPSBwaGVubwogICAgICApCgogICAgICBwcmVkc19kYXRhJHloYXQgPC0gcHJlZHNfZGF0YSR5aGF0W21ldGhvZHNdCiAgICAgIG5hbWVzKHByZWRzX2RhdGEkeWhhdCkgPC0gbmFtZXMobWV0aG9kcykKCiAgICAgICMgcHJlZGljdGlvbiBhY2N1cmFjeSB0YWJsZQogICAgICBtZXRyaWNzIDwtIGMoIkNsYXNzIiwgIkFVQyIsICJQUiIpCiAgICAgIGV2YWxfb3V0IDwtIG1hcF9kZnIocHJlZHNfZGF0YSR5aGF0LAogICAgICAgIH4gYmluZF9yb3dzKAogICAgICAgICAgZXZhbFByZWRzKAogICAgICAgICAgICB5ID0gcHJlZHNfZGF0YSR5LCB5aGF0ID0gYygueCksCiAgICAgICAgICAgIG1ldHJpYyA9IGMoIkFVQyIsICJQUiIpCiAgICAgICAgICApLAogICAgICAgICAgZXZhbFByZWRzKAogICAgICAgICAgICB5ID0gcHJlZHNfZGF0YSR5LAogICAgICAgICAgICB5aGF0ID0gcm91bmQoYygueCkpLAogICAgICAgICAgICBtZXRyaWMgPSBjKCJCYWxhbmNlZENsYXNzIiwgIkNsYXNzIikKICAgICAgICAgICkKICAgICAgICApLAogICAgICAgIC5pZCA9ICJNZXRob2QiCiAgICAgICkgJT4lCiAgICAgICAgc3ByZWFkKGtleSA9ICJNZXRyaWMiLCB2YWx1ZSA9ICJWYWx1ZSIpCiAgICAgIGV2YWxfbHNbW2FzLmNoYXJhY3Rlcih0aHIpXV0gPC0gZXZhbF9vdXQKCiAgICAgICMgY29uZnVzaW9uIG1hdHJpeAogICAgICBjb25mX2FsbCA8LSBtYXAoCiAgICAgICAgcHJlZHNfZGF0YSR5aGF0LAogICAgICAgIH4gZXZhbENvbmZ1c2lvbih5ID0gcHJlZHNfZGF0YSR5LCB5aGF0ID0gLngpCiAgICAgICkgJT4lCiAgICAgICAgcHVycnI6OnJlZHVjZSguLCBjYmluZCkKICAgICAgY29uZl9uYW1lcyA8LSBjb2xuYW1lcyhjb25mX2FsbCkgJT4lCiAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2UoIjAiLCAiTG93IikgJT4lCiAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2UoIjEiLCAiSGlnaCIpCiAgICAgIGNvbG5hbWVzKGNvbmZfYWxsKSA8LSBwYXN0ZShjb25mX25hbWVzLCAxOm5jb2woY29uZl9hbGwpKQogICAgICByb3duYW1lcyhjb25mX2FsbCkgPC0gcm93bmFtZXMoY29uZl9hbGwpICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlKCIwIiwgIkxvdyIpICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlKCIxIiwgIkhpZ2giKQogICAgICBjb25mX2hlYWRlciA8LSBjKDEsIHJlcCgyLCBsZW5ndGgocHJlZHNfZGF0YSR5aGF0KSkpICU+JQogICAgICAgIHNldE5hbWVzKGMoIiAiLCBuYW1lcyhwcmVkc19kYXRhJHloYXQpKSkKICAgICAgdGFiIDwtIHByZXR0eV9EVChjb25mX2FsbCwKICAgICAgICByb3duYW1lcyA9IFRSVUUsCiAgICAgICAgZ3JvdXBlZF9oZWFkZXIgPSBjb25mX2hlYWRlciwKICAgICAgICBncm91cGVkX3N1YmhlYWRlciA9IGMoIiAiLCBjb25mX25hbWVzKSwKICAgICAgICBvcHRpb25zID0gbGlzdChkb20gPSAidCIsIG9yZGVyaW5nID0gRkFMU0UpCiAgICAgICkKICAgICAgIyBzYXZlUkRTKAogICAgICAjICAgdGFiLAogICAgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgICB0YWJfcmVzX2RpciwKICAgICAgIyAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsICJfY29uZnVzaW9uX21hdHJpeC5yZHMiKQogICAgICAjICAgKQogICAgICAjICkKCiAgICAgICMgYXVjL3ByIHBsb3RzCiAgICAgIHJvY19scyA8LSBtYXAoCiAgICAgICAgcHJlZHNfZGF0YSR5aGF0LAogICAgICAgIH4gZXZhbEFVQyh5ID0gcHJlZHNfZGF0YSR5LCB5aGF0ID0gLngsIG1ldHJpYyA9ICJyb2MiKQogICAgICApCiAgICAgIHByX2xzIDwtIG1hcCgKICAgICAgICBwcmVkc19kYXRhJHloYXQsCiAgICAgICAgfiBldmFsQVVDKHkgPSBwcmVkc19kYXRhJHksIHloYXQgPSAueCwgbWV0cmljID0gInByIikKICAgICAgKQoKICAgICAgIyBkcm9wIG1vZGVscyB3aXRoIGNvbnN0YW50IHByZWRpY3Rpb25zCiAgICAgIHJvY19scyA8LSByb2NfbHNbIXNhcHBseShyb2NfbHMsIGlzLm51bGwpXQogICAgICBwcl9scyA8LSBwcl9sc1shc2FwcGx5KHByX2xzLCBpcy5udWxsKV0KCiAgICAgICMgZ2V0IGN1cnZlcwogICAgICByb2NfZGYgPC0gbWFwX2Rmcihyb2NfbHMsCiAgICAgICAgfiBkYXRhLmZyYW1lKC54JGN1cnZlKSAlPiUKICAgICAgICAgIG11dGF0ZShBVUMgPSByb3VuZCgueCRhdWMsIDMpKSwKICAgICAgICAuaWQgPSAiTWV0aG9kIgogICAgICApICU+JQogICAgICAgIG11dGF0ZShNZXRob2QgPSBhcy5mYWN0b3IocGFzdGUoTWV0aG9kLCAiICgiLCBBVUMsICIpIiwgc2VwID0gIiIpKSkKICAgICAgcHJfZGYgPC0gbWFwX2Rmcihwcl9scywKICAgICAgICB+IGRhdGEuZnJhbWUoLngkY3VydmUpICU+JQogICAgICAgICAgbXV0YXRlKEFVQyA9IHJvdW5kKC54JGF1Yy5pbnRlZ3JhbCwgMykpLAogICAgICAgIC5pZCA9ICJNZXRob2QiCiAgICAgICkgJT4lCiAgICAgICAgbXV0YXRlKE1ldGhvZCA9IGFzLmZhY3RvcihwYXN0ZShNZXRob2QsICIgKCIsIEFVQywgIikiLCBzZXAgPSAiIikpKQoKICAgICAgIyBtYWtlIHBsb3RzCiAgICAgIHJvY19wbHQgPC0gZ2dwbG90KHJvY19kZikgKwogICAgICAgIGFlcyh4ID0gWDEsIHkgPSBYMiwgY29sb3IgPSBNZXRob2QpICsKICAgICAgICBnZW9tX2xpbmUoKSArCiAgICAgICAgbGFicyh4ID0gIkZQUiIsIHkgPSAiVFBSIikgKwogICAgICAgIHZ0aGVtZXM6OnRoZW1lX3Ztb2Rlcm4oKSArCiAgICAgICAgdnRoZW1lczo6c2NhbGVfY29sb3Jfdm1vZGVybihkaXNjcmV0ZSA9IFRSVUUpCiAgICAgICMgc2F2ZVJEUygKICAgICAgIyAgIHJvY19wbHQsCiAgICAgICMgICBmaWxlLnBhdGgoCiAgICAgICMgICAgIGZpZ19yZXNfZGlyLAogICAgICAjICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgIl9yb2MucmRzIikKICAgICAgIyAgICkKICAgICAgIyApCgogICAgICBwcl9wbHQgPC0gZ2dwbG90KHByX2RmKSArCiAgICAgICAgYWVzKHggPSBYMSwgeSA9IFgyLCBjb2xvciA9IE1ldGhvZCkgKwogICAgICAgIGdlb21fbGluZSgpICsKICAgICAgICBsYWJzKHggPSAiUmVjYWxsIiwgeSA9ICJQcmVjaXNpb24iKSArCiAgICAgICAgdnRoZW1lczo6dGhlbWVfdm1vZGVybigpICsKICAgICAgICB2dGhlbWVzOjpzY2FsZV9jb2xvcl92bW9kZXJuKGRpc2NyZXRlID0gVFJVRSkKICAgICAgIyBzYXZlUkRTKAogICAgICAjICAgcHJfcGx0LAogICAgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgICBmaWdfcmVzX2RpciwKICAgICAgIyAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsICJfcHIucmRzIikKICAgICAgIyAgICkKICAgICAgIyApCgogICAgICAjIHByZWRpY3Rpb24gcGFpciBwbG90cwogICAgICBwbHRfZGYgPC0gbWFwX2RmYyhwcmVkc19kYXRhJHloYXQsIH4gYygueCkpCiAgICAgIHBsdCA8LSBwbG90X3BhaXJzKGRhdGEgPSBwbHRfZGYsIGNvbHVtbnMgPSAxOm5jb2wocGx0X2RmKSwgcG9pbnRfc2l6ZSA9IDAuMSkKICAgICAgIyBzYXZlUkRTKAogICAgICAjICAgcGx0LAogICAgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgICBmaWdfcmVzX2RpciwKICAgICAgIyAgICAgcGFzdGUwKAogICAgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICMgICAgICAgIl9wcmVkX3BhaXJfcGxvdC5yZHMiCiAgICAgICMgICAgICkKICAgICAgIyAgICkKICAgICAgIyApCiAgICB9CgogICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlcylbcGhlbm90eXBlcyA9PSBwaGVub3R5cGVdCiAgICB0YWIgPC0gZHBseXI6OmJpbmRfcm93cyhldmFsX2xzLCAuaWQgPSAiVGhyZXNob2xkIikgJT4lCiAgICAgIGRwbHlyOjpyZW5hbWUoIkFjY3VyYWN5IiA9ICJDbGFzcyIsICJBVVJPQyIgPSAiQVVDIiwgIkFVUFJDIiA9ICJQUiIpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKFRocmVzaG9sZCA9IHBhc3RlMCgiQmluYXJpemF0aW9uIFRocmVzaG9sZCA9ICIsIFRocmVzaG9sZCkpICU+JQogICAgICBkcGx5cjo6c2VsZWN0KFRocmVzaG9sZCwgTWV0aG9kLCBBY2N1cmFjeSwgQVVST0MsIEFVUFJDKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICBNZXRob2QgPSBmYWN0b3IoTWV0aG9kLCBsZXZlbHMgPSBuYW1lcyhtZXRob2RzKSkKICAgICAgKSAlPiUKICAgICAgZHBseXI6OmFycmFuZ2UoTWV0aG9kKSAlPiUKICAgICAgZHBseXI6Omdyb3VwX2J5KFRocmVzaG9sZCkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoZHBseXI6OmFjcm9zcygKICAgICAgICBjKEFjY3VyYWN5LCBBVVJPQywgQVVQUkMpLAogICAgICAgIH4gaWZlbHNlKC54ID09IG1heCgueCksCiAgICAgICAgICBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoCiAgICAgICAgICAgIGZvcm1hdEMoLngsCiAgICAgICAgICAgICAgZGlnaXRzID0gMywKICAgICAgICAgICAgICBmb3JtYXQgPSAiZyIsIGZsYWcgPSAiIyIKICAgICAgICAgICAgKSwKICAgICAgICAgICAgYm9sZCA9IFRSVUUKICAgICAgICAgICksCiAgICAgICAgICBmb3JtYXRDKC54LAogICAgICAgICAgICBkaWdpdHMgPSAzLAogICAgICAgICAgICBmb3JtYXQgPSAiZyIsIGZsYWcgPSAiIyIKICAgICAgICAgICkKICAgICAgICApCiAgICAgICkpICU+JQogICAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbHMgPSBjKEFjY3VyYWN5LCBBVVJPQywgQVVQUkMpLCBuYW1lc190byA9ICJNZXRyaWMiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKSAlPiUKICAgICAgdGlkeXI6OnBpdm90X3dpZGVyKGlkX2NvbHMgPSBNZXRob2QsIG5hbWVzX2Zyb20gPSBjKFRocmVzaG9sZCwgTWV0cmljKSwgdmFsdWVzX2Zyb20gPSBWYWx1ZSkgJT4lCiAgICAgIHZ0aGVtZXM6OnByZXR0eV9EVCgKICAgICAgICBkaWdpdHMgPSAzLCBzaWdmaWcgPSBGQUxTRSwgcm93bmFtZXMgPSBGQUxTRSwgbmFfZGlzcCA9ICItLSIsCiAgICAgICAgZ3JvdXBlZF9oZWFkZXIgPSBjKAogICAgICAgICAgIiAiID0gMSwKICAgICAgICAgICJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gMC4xNSIgPSAzLAogICAgICAgICAgIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAwLjIwIiA9IDMsCiAgICAgICAgICAiQmluYXJpemF0aW9uIFRocmVzaG9sZCA9IDAuMjUiID0gMwogICAgICAgICksCiAgICAgICAgZ3JvdXBlZF9zdWJoZWFkZXIgPSBjKCJNZXRob2QiLCByZXAoYygiQWNjdXJhY3kiLCAiQVVST0MiLCAiQVVQUkMiKSwgdGltZXMgPSAzKSksCiAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gInQiKQogICAgICApCiAgICAjIHNhdmVSRFMoCiAgICAjICAgdGFiLAogICAgIyAgIGZpbGUucGF0aCh0YWJfcmVzX2RpciwgcGFzdGUwKHBoZW5vdHlwZSwgIl9iaW5hcnlfcHJlZF9hY2N1cmFjeS5yZHMiKSkKICAgICMgKQogIH0KfSBlbHNlIHsKICBmb3IgKHBoZW5vdHlwZSBpbiBwaGVub3R5cGVzKSB7CiAgICBwaGVub3R5cGVfbmFtZSA8LSBuYW1lcyhwaGVub3R5cGVzKVtwaGVub3R5cGVzID09IHBoZW5vdHlwZV0KICAgICMgY2F0KHNwcmludGYocGhlbm90eXBlX2hlYWRlciwgcGhlbm90eXBlX25hbWUpKQoKICAgICMgc3VtbWFyeSB0YWJsZSBvZiBwcmVkaWN0aW9uIGFjY3VyYWNpZXMKICAgIGNhdChzcHJpbnRmKHN1bW1hcnlfaGVhZGVyLCAiUHJlZGljdGlvbiBBY2N1cmFjeSBTdW1tYXJ5IikpCiAgICB0YWIgPC0gcmVhZFJEUyhmaWxlLnBhdGgodGFiX3Jlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfYmluYXJ5X3ByZWRfYWNjdXJhY3kucmRzIikpKQogICAgc3ViY2h1bmtpZnkodGFiLAogICAgICBpID0gY2h1bmtfaWR4LAogICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1N1bW1hcnkgb2YgcHJlZGljdGlvbiBwZXJmb3JtYW5jZSBvbiB0aGUgdmFsaWRhdGlvbiBzZXQgZm9yIHRoZSBiaW5hcml6ZWQgJXMgcGhlbm90eXBlIGFjcm9zcyB2YXJpb3VzIHByZWRpY3Rpb24gbWV0aG9kcywgYmluYXJpemF0aW9uIHRocmVzaG9sZHMsIGFuZCBldmFsdWF0aW9uIG1ldHJpY3MuIEFiYnJldmlhdGlvbnM6IHNpUkYsIHNpZ25lZCBpdGVyYXRpdmUgcmFuZG9tIGZvcmVzdDsgUkYsIHJhbmRvbSBmb3Jlc3Q7IExhc3NvLCBMMS1yZWd1bGFyaXplZCBsb2dpc3RpYyByZWdyZXNzaW9uOyBSaWRnZSwgTDItcmVndWxhcml6ZWQgbG9naXN0aWMgcmVncmVzc2lvbjsgU1ZNLCBzdXBwb3J0IHZlY3RvciBtYWNoaW5lOyBNTFAsIG11bHRpbGF5ZXIgcGVyY2VwdHJvbjsgQXV0b2dsdW9uIChtZWRpdW0vZ29vZCksIEF1dG9nbHVvbiBUYWJ1bGFyUHJlZGljdG9yIGZpdHRlZCB3aXRoIHRoZSBtZWRpdW0vZ29vZCBxdWFsaXR5IHByZXNldDsgUEdTLCBwb2x5Z2VuaWMgcmlzayBzY29yZS4nIiwgcGhlbm90eXBlX25hbWUpCiAgICApCiAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgIGZvciAodGhyIGluIGMoMC4xNSwgMC4yLCAwLjI1KSkgewogICAgICBjYXQoc3ByaW50Zih0aHJfaGVhZGVyLCB0aHIpKQoKICAgICAgIyBjb25mdXNpb24gbWF0cml4CiAgICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiQ29uZnVzaW9uIFRhYmxlcyIpKQogICAgICB0YWIgPC0gcmVhZFJEUyhmaWxlLnBhdGgoCiAgICAgICAgdGFiX3Jlc19kaXIsCiAgICAgICAgcGFzdGUwKAogICAgICAgICAgcGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICJfY29uZnVzaW9uX21hdHJpeC5yZHMiCiAgICAgICAgKQogICAgICApKQogICAgICBzdWJjaHVua2lmeSh0YWIsCiAgICAgICAgaSA9IGNodW5rX2lkeCwKICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ0NvbmZ1c2lvbiBtYXRyaXggZnJvbSB2YXJpb3VzIHByZWRpY3Rpb24gbW9kZWxzIGZvciBwcmVkaWN0aW5nIHRoZSBiaW5hcml6ZWQgJXMgcGhlbm90eXBlIChiaW5hcml6YXRpb24gdGhyZXNob2xkID0gJXMpLiciLCBwaGVub3R5cGVfbmFtZSwgdGhyKQogICAgICApCiAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogICAgICAjIGF1Yy9wciBwbG90cwogICAgICBjYXQoc3ByaW50ZihzZWN0aW9uX2hlYWRlciwgIlJPQy9QUiBDdXJ2ZXMiKSkKICAgICAgcGx0IDwtIHJlYWRSRFMoZmlsZS5wYXRoKAogICAgICAgIGZpZ19yZXNfZGlyLAogICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfdGhyIiwgdGhyLCAiX3JvYy5yZHMiKQogICAgICApKQogICAgICBzdWJjaHVua2lmeShnZ3Bsb3RseShwbHQpLAogICAgICAgIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBBVUNfSEVJR0hULAogICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIiksCiAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1JPQyBjdXJ2ZSBmb3IgcHJlZGljdGluZyB0aGUgYmluYXJpemVkICVzICh0aHJlc2hvbGQgPSAlcykgYWNyb3NzIHZhcmlvdXMgcHJlZGljdGlvbiBtZXRob2RzLiBUUFIgPSB0cnVlIHBvc2l0aXZlIHJhdGU7IEZQUiA9IGZhbHNlIHBvc2l0aXZlIHJhdGUuJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIpCiAgICAgICkKICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKCiAgICAgIHBsdCA8LSByZWFkUkRTKGZpbGUucGF0aCgKICAgICAgICBmaWdfcmVzX2RpciwKICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwgIl9wci5yZHMiKQogICAgICApKQogICAgICBzdWJjaHVua2lmeShnZ3Bsb3RseShwbHQpLAogICAgICAgIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBBVUNfSEVJR0hULAogICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIiksCiAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1ByZWNpc2lvbi1yZWNhbGwgY3VydmUgZm9yIHByZWRpY3RpbmcgdGhlIGJpbmFyaXplZCAlcyAodGhyZXNob2xkID0gJXMpIGFjcm9zcyB2YXJpb3VzIHByZWRpY3Rpb24gbWV0aG9kcy4nIiwgcGhlbm90eXBlX25hbWUsIHRocikKICAgICAgKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgICAgIyBwcmVkaWN0aW9uIHBhaXIgcGxvdHMKICAgICAgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJQcmVkaWN0aW9uIFBhaXIgUGxvdCIpKQogICAgICBwbHQgPC0gcmVhZFJEUyhmaWxlLnBhdGgoCiAgICAgICAgZmlnX3Jlc19kaXIsCiAgICAgICAgcGFzdGUwKAogICAgICAgICAgcGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICJfcHJlZF9wYWlyX3Bsb3QucmRzIgogICAgICAgICkKICAgICAgKSkKICAgICAgc3ViY2h1bmtpZnkocGx0LAogICAgICAgIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBwbHQkbmNvbCAqIDEuNSwKICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IiksCiAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1BhaXIgcGxvdHMgb2YgdGhlIHByZWRpY3RlZCBiaW5hcml6ZWQgJXMgcmVzcG9uc2VzICh0aHJlc2hvbGQgPSAlcykgYWNyb3NzIHZhcmlvdXMgcHJlZGljdGlvbiBtZXRob2RzLiBFYWNoIHBvaW50IHJlcHJlc2VudHMgYW4gaW5kaXZpZHVhbCBpbiB0aGUgdmFsaWRhdGlvbiBzZXQsIGFuZCB0aGUgY29vcmRpbmF0ZXMgcmVwcmVzZW50IHRoZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdHkgb2YgaGF2aW5nIGhpZ2ggJXMgZnJvbSB0d28gZGlmZmVyZW50IHByZWRpY3Rpb24gbWV0aG9kcywgd2hpY2ggYXJlIHNwZWNpZmllZCBieSB0aGUgeCBhbmQgeS1heGVzIGxhYmVscyBpbiBlYWNoIHN1YnBsb3QuIERlbnNpdHkgZGlzdHJpYnV0aW9ucyBvZiB0aGUgcHJlZGljdGVkIHByb2JhYmlsaXRpZXMgYXJlIHNob3duIGFsb25nIHRoZSBkaWFnb25hbC4nIiwgcGhlbm90eXBlX25hbWUsIHRociwgcGhlbm90eXBlX25hbWUpCiAgICAgICkKICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgIH0KICB9Cn0KYGBgCgojIFByaW9yaXRpemF0aW9uIFN0ZXAgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtdm1vZGVybn0KCiMjIE92ZXJ2aWV3IHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpIYXZpbmcgcGFzc2VkIHRoZSBwcmVkaWN0aW9uIGNoZWNrLCB3ZSBmaW5hbGx5IHByb2NlZWQgdG8gaW50ZXJwcmV0IHRoZSBzaVJGIGZpdCBpbiB0aGUgbGFzdCBzdGVwIG9mIGxvLXNpUkYuIEluIHRoaXMgc3RlcCwgd2UgZGV2ZWxvcGVkIGEgbm92ZWwgc3RhYmlsaXR5LWRyaXZlbiBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUgdG8gcHJpb3JpdGl6ZSBib3RoIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpIGZyb20gc2lSRi4gV2UgcmVmZXIgdG8gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkgZm9yIHRoZSBkZXRhaWxlZCBkZXNjcmlwdGlvbiBvZiB0aGlzIG5ldyBpbXBvcnRhbmNlIHNjb3JlIGFuZCBoZXJlIHByb3ZpZGUgYnJpZWYgaW5zaWdodHMgaW50byB0aGUgbW90aXZhdGlvbiBhbmQgaW50dWl0aW9uIGJlaGluZCB0aGlzIG1ldGhvZC4KCioqTWFpbiBpZGVhOioqIEF0IGEgaGlnaC1sZXZlbCwgdGhpcyBuZXcgaW1wb3J0YW5jZSBzY29yZSAoMSkgYWdncmVnYXRlcyB3ZWFrLCB1bnN0YWJsZSBTTlYtbGV2ZWwgaW1wb3J0YW5jZXMgZnJvbSBzaVJGIGludG8gc3Ryb25nZXIsIG1vcmUgc3RhYmxlIGxvY3VzLWxldmVsIGltcG9ydGFuY2VzIGFuZCAoMikgY2FuIGJlIGxldmVyYWdlZCB0byBldmFsdWF0ZSBib3RoIHRoZSBtYXJnaW5hbCBpbXBvcnRhbmNlIG9mIGEgZ2VuZXRpYyBsb2N1cyBpbiBzaVJGIGFzIHdlbGwgYXMgdGhlIGltcG9ydGFuY2Ugb2YgaGlnaGVyLW9yZGVyIGludGVyYWN0aW9ucyBiZXR3ZWVuIGdlbmV0aWMgbG9jaSBpbiBzaVJGLiBUaGUgbmVlZCBmb3IgdGhpcyBsb2N1cy1sZXZlbCBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUgc3RlbXMgZnJvbSB0d28gbWFpbiByZWFzb25zOiB0aGUgaGlnaCBjb3JyZWxhdGlvbiBiZXR3ZWVuIFNOVnMgYW5kIHRoZSB3ZWFrIHBoZW5vdHlwaWMgc2lnbmFsLiBUaG91Z2ggdGhlIHByZWRpY3Rpb24gbW9kZWxzIChpbmNsdWRpbmcgc2lSRikgYXJlIGFsbCB0cmFpbmVkIHVzaW5nIFNOViBkYXRhLCBpdCBpcyBvZnRlbiB2ZXJ5IGNoYWxsZW5naW5nIHRvIGludGVycHJldCB0aGUgaW1wb3J0YW5jZSBvZiBhbiBpbmRpdmlkdWFsIFNOViBmcm9tIHRoZXNlIG1vZGVscyBkdWUgdG8gdGhlIGhpZ2ggY29ycmVsYXRpb24gYmV0d2VlbiBTTlZzIFtAdG9sb2NzaTIwMTFjbGFzc2lmaWNhdGlvbjsgQGhvb2tlcjIwMjF1bnJlc3RyaWN0ZWRdLCB3aGljaCB3ZSBvYnNlcnZlZCBpbiBvdXIgcHJldmlvdXMgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyAoc2VlIGBDaG9pY2Ugb2YgUGhlbm90eXBpYyBEYXRhYCB0YWIpLiBUbyBmdXJ0aGVyIGNvbXBsaWNhdGUgbWF0dGVycywgdGhlIHdlYWsgcGhlbm90eXBpYyBzaWduYWwgaW5jcmVhc2VzIHRoZSBpbnN0YWJpbGl0eSBvZiBleGlzdGluZyBmZWF0dXJlIGltcG9ydGFuY2UgbWV0aG9kcyBpbiB0aGF0IHdlIHNlZSB0aGUgZmVhdHVyZSByYW5raW5ncyBjaGFuZ2UgZHJhc3RpY2FsbHkgd2hlbiB1c2luZyBkaWZmZXJlbnQgYm9vdHN0cmFwIHRyYWluaW5nIHNhbXBsZXMuIEdpdmVuIHRoZXNlIGNoYWxsZW5nZXMgd2l0aCBTTlYtbGV2ZWwgZmVhdHVyZSBpbXBvcnRhbmNlcywgaXQgaXMgdGhlbiBubyBzdXJwcmlzZSB0aGF0IHNpUkYsIG91dC1vZi10aGUtYm94LCBkb2VzIG5vdCBmaW5kIGFueSBzdGFibGUgaW50ZXJhY3Rpb25zIGJldHdlZW4gU05WcyAoaS5lLiwgdGhlIHNpUkYgc3RhYmlsaXR5IHNjb3JlIGlzIGFyb3VuZCAwIGZvciBhbGwgaW50ZXJhY3Rpb25zIGJldHdlZW4gU05WcykuIFRvIGFkZHJlc3MgdGhlc2UgY2hhbGxlbmdlcywgb3VyIG5ldyBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUgbGV2ZXJhZ2VzIHRoZSBjb3JyZWxhdGlvbiBzdHJ1Y3R1cmUgYmV0d2VlbiBTTlZzLCBncm91cHMgU05WcyBpbnRvIGdlbmV0aWMgbG9jaSwgYW5kIGFnZ3JlZ2F0ZXMgd2VhaywgdW5zdGFibGUgU05WLWxldmVsIGltcG9ydGFuY2VzIGZyb20gc2lSRiBpbnRvIHN0cm9uZ2VyLCBtb3JlIHN0YWJsZSBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlcy4KCioqTW90aXZhdGlvbiBiZWhpbmQgbmV3IGZlYXR1cmUgaW1wb3J0YW5jZSBzY29yZToqKiBUbyBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgbW90aXZhdGlvbiBhbmQgY29uc3RydWN0aW9uIG9mIG91ciBuZXcgbG9jdXMtbGV2ZWwgZmVhdHVyZSBpbXBvcnRhbmNlIHNjb3JlLCBpdCBjYW4gYmUgaGVscGZ1bCB0byBmaXJzdCByZXZpZXcgdGhlIG9yaWdpbmFsIGltcG9ydGFuY2Ugc2NvcmUgdXNlZCBpbiBzaVJGIFtAa3VtYmllcjIwMThyZWZpbmluZ10uIEJyaWVmbHksIGluIHRoZSBvcmlnaW5hbCB2ZXJzaW9uIG9mIHNpUkYsIHRoZSBpbXBvcnRhbmNlIG9mIGEgc2lnbmVkIGludGVyYWN0aW9uIGlzIGJhc2VkIHVwb24gKmhvdyBzdGFibGUgb3IgZnJlcXVlbnRseSBpdCBvY2N1cnMqIGluIGRlY2lzaW9ucyBwYXRocyBhY3Jvc3MgdGhlIHJhbmRvbSBmb3Jlc3QgLS0gdGhhdCBpcywgYmFzZWQgdXBvbiB0aGUgbnVtYmVyIG9mIGRlY2lzaW9uIHBhdGhzIGZvciB3aGljaCBldmVyeSBzaWduZWQgZmVhdHVyZSBpbiB0aGUgc2lnbmVkIGludGVyYWN0aW9uIHdhcyB1c2VkIGluIGF0IGxlYXN0IG9uZSBkZWNpc2lvbiBzcGxpdCAoc2VlIEBrdW1iaWVyMjAxOHJlZmluaW5nIGZvciBkZXRhaWxzKS4gRm9sbG93aW5nIGEgc2ltaWxhciBsb2dpYywgb25lIG5hdHVyYWwgcGF0aCBmb3J3YXJkIHRvIGNhbGN1bGF0ZSBhIGxvY3VzLWxldmVsIGltcG9ydGFuY2UgZnJvbSBhIGZvcmVzdCB0aGF0IHdhcyBmaXQgb24gU05WIGRhdGEgaXMgYXMgZm9sbG93czoKCjEuIFRha2UgdGhlIGZpdHRlZCBmb3Jlc3QsIHdoZXJlIGVhY2ggZGVjaXNpb24gc3BsaXQgdXNlZCBzb21lIFNOViB0byBtYWtlIHRoZSBzcGxpdC4KMi4gTWFwIGVhY2ggU05WIHVzZWQgaW4gYSBkZWNpc2lvbiBzcGxpdCB0byBpdHMgY29ycmVzcG9uZGluZyBnZW5ldGljIGxvY2kgKGUuZy4sIHVzaW5nIGFubm90YXRpb24gc29mdHdhcmUgbGlrZSBBTk5PVkFSIFtAd2FuZzIwMTBhbm5vdmFyXSkuCjMuIENvbXB1dGUgdGhlIGltcG9ydGFuY2Ugb2YgYSBzaWduZWQgbG9jdXMtbGV2ZWwgaW50ZXJhY3Rpb24gYmFzZWQgdXBvbiB0aGUgZnJlcXVlbmN5IG9mIG9jY3VycmVuY2Ugb2YgdGhlIGludGVyYWN0aW9uIGFzIGJlZm9yZSwgYnV0IHVzaW5nIHRoZSBtYXBwZWQgZ2VuZXRpYyBsb2NpIGluIGxpZXUgb2YgdGhlIFNOVnMuIFRoYXQgaXMsIGNvbXB1dGUgdGhlIG51bWJlciBvZiBkZWNpc2lvbiBwYXRocyBmb3Igd2hpY2ggZXZlcnkgc2lnbmVkIGxvY3VzIGluIHRoZSBzaWduZWQgbG9jdXMtbGV2ZWwgaW50ZXJhY3Rpb24gd2FzIHVzZWQgaW4gYXQgbGVhc3Qgb25lIGRlY2lzaW9uIHNwbGl0LiAKCkhvd2V2ZXIsIHRoaXMgKmZyZXF1ZW5jeSBvZiBvY2N1cnJlbmNlKiBtZWFzdXJlIGlzIGhlYXZpbHkgdGllZCB0byB0aGUgbnVtYmVyIG9mIFNOVnMgdGhhdCBiZWxvbmcgdG8gZWFjaCBnZW5ldGljIGxvY3VzLiBBIGdlbmV0aWMgbG9jdXMgdGhhdCBjb25zaXN0cyBvZiBtb3JlIFNOVnMgd2lsbCBuYXR1cmFsbHkgaGF2ZSBhIGhpZ2hlciBmcmVxdWVuY3kgb2Ygb2NjdXJyZW5jZSB0aGFuIGEgZ2VuZXRpYyBsb2N1cyB3aXRoIG9ubHkgYSBmZXcgU05WcyBldmVuIHRob3VnaCBib3RoIGdlbmV0aWMgbG9jaSBtYXkgYmUgZXF1YWxseSBpbXBvcnRhbnQgKG9yIHVuaW1wb3J0YW50KS4gSW4gb3RoZXIgd29yZHMsIHRoZSBvcmlnaW5hbCBzaVJGIGltcG9ydGFuY2Ugc2NvcmUsIG1lYXN1cmluZyB0aGUgZnJlcXVlbmN5IG9mIG9jY3VycmVuY2UsIGlzIG5vdCBjb21wYXJhYmxlIGFjcm9zcyBnZW5ldGljIGxvY2kuIFRoaXMgYmlhcyBpcyBwcm9ibGVtYXRpYyBnaXZlbiB0aGF0IHdlIGhhdmUgcHJldmlvdXNseSBzZWVuIHNvbWUgZ2VuZXRpYyBsb2NpIG1heSBjb25zaXN0IG9mIG9ubHkgMSBTTlYgd2hpbGUgb3RoZXIgZ2VuZXRpYyBsb2NpIGhhdmUgPjUwIFNOVnMgKHNlZSBgR1dBUy1maWx0ZXJlZCBTTlZzYCB0YWIgaW4gdGhlIERpbWVuc2lvbiBSZWR1Y3Rpb24gU3RlcCkuIAoKKipJbnR1aXRpb24gYmVoaW5kIG5ldyBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmU6KiogVG8gYWxsZXZpYXRlIHRoaXMgYmlhcywgd2UgbGV2ZXJhZ2UgdGhlIGlkZWEgb2YgYSAqbG9jYWwqIGZlYXR1cmUgaW1wb3J0YW5jZSBzY29yZSwgd2hlcmUgd2UgY29tcHV0ZSBhICpwZXItaW5kaXZpZHVhbCogc2NvcmUgdGhhdCBtZWFzdXJlcyB0aGUgaW1wb3J0YW5jZSBvZiBhIGxvY3VzL2ludGVyYWN0aW9uIGZvciBtYWtpbmcgdGhlIHByZWRpY3Rpb24gb2YgKmVhY2gqIGluZGl2aWR1YWwuIFRoaXMgaXMgaW4gY29udHJhc3QgdG8gYSAqZ2xvYmFsKiBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUsIHdoaWNoIGlzIGEgbWVhc3VyZSBvZiBpbXBvcnRhbmNlIGZvciB0aGUgZW50aXJlIGdyb3VwIG9mIGluZGl2aWR1YWxzIHVuZGVyIHN0dWR5LiBXaGlsZSBhIGdsb2JhbCBmZWF0dXJlIGltcG9ydGFuY2Ugc2NvcmUgZ2l2ZXMgcmlzZSB0byBhICpzaW5nbGUqIHNjb3JlIGZvciB0aGUgZW50aXJlIHBvcHVsYXRpb24gdW5kZXIgc3R1ZHksIHdlIGNhbiBjb21wdXRlIGEgbG9jYWwgZmVhdHVyZSBpbXBvcnRhbmNlIHNjb3JlIGZvciAqZWFjaCogaW5kaXZpZHVhbCBpbiB0aGUgcG9wdWxhdGlvbi4gQnkgY29tcHV0aW5nIGEgbG9jYWwgZmVhdHVyZSBpbXBvcnRhbmNlIHNjb3JlIGZvciBlYWNoIGluZGl2aWR1YWwgKGkuZS4sIHRoaXMgaXMgdGhlIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIChMU0kpIHNjb3JlIGZyb20gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkpLCB3ZSBjYW4gY29tcGFyZSB0aGUgaW1wb3J0YW5jZSBvZiB0aGUgbG9jdXMvaW50ZXJhY3Rpb24gYWNyb3NzICppbmRpdmlkdWFscyogYW5kIGF2b2lkIHRoZSBhY3Jvc3MtKmxvY2kqIGNvbXBhcmlzb24gdGhhdCB3YXMgcHJvYmxlbWF0aWMgaW4gdGhlIGFmb3JlbWVudGlvbmVkIGRpc2N1c3Npb24uIFRoaXMgY29tcGFyaXNvbiBpcyBkb25lIHZpYSBhIHBlcm11dGF0aW9uIHRlc3QgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkuIE1vcmVvdmVyLCBzaW5jZSB3ZSBhcmUgY29tcGFyaW5nIHRoZSBsb2NhbCBmZWF0dXJlIGltcG9ydGFuY2VzIGJldHdlZW4gaW5kaXZpZHVhbHMgKndpdGhpbiogb3IgKnBlciogbG9jaS9pbnRlcmFjdGlvbiBpbiB0aGlzIHBlcm11dGF0aW9uIHRlc3QsIHRoZSBsb2NhbCBmZWF0dXJlIGltcG9ydGFuY2VzIGFyZSBhbGwgbWVhc3VyZWQgb24gdGhlIHNhbWUgc2NhbGUgYW5kIGNvbXBhcmFibGUsIHRoZXJlYnkgbWl0aWdhdGluZyB0aGUgYmlhcyB0b3dhcmRzIGdlbmV0aWMgbG9jaSB3aXRoIG1vcmUgU05Wcy4KCioqSG93IHRvIGFnZ3JlZ2F0ZSBTTlZzOioqIFdlIG1hcHBlZCBlYWNoIFNOViB0byBpdHMgY29ycmVzcG9uZGluZyBnZW5ldGljIGxvY3VzIHVzaW5nIEFOTk9WQVIgW0B3YW5nMjAxMGFubm92YXJdIGFjY29yZGluZyB0byB0aGUgaGcxOSByZWZTZXEgR2VuZSBhbm5vdGF0aW9ucy4gR2l2ZW4gb3VyIHVsdGltYXRlIGdvYWwgb2YgcmVjb21tZW5kaW5nL3ByaW9yaXRpemluZyBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgZm9yIGRvd25zdHJlYW0gYW5hbHlzZXMgYW5kIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uLCB3ZSBiZWxpZXZlIHRoaXMgY2hvaWNlIHByb3ZpZGVzIGFuIGFwcHJvcHJpYXRlIHN0YXJ0aW5nIHBvaW50IHRvIG9idGFpbiBhY3Rpb25hYmxlIHJlY29tbWVuZGF0aW9ucy4gSG93ZXZlciwgd2Ugbm90ZSB0aGF0IHRoZXJlIGFyZSBtYW55IGFsdGVybmF0aXZlIHdheXMgb2YgYWdncmVnYXRpbmcgU05Wcy4gRm9yIGV4YW1wbGUsIGl0IGlzIHBvc3NpYmxlIHRvIGFnZ3JlZ2F0ZSBTTlZzIGFjY29yZGluZyB0byBMRC9oYXBsb3R5cGUgYmxvY2tzIG9yIHRvIGluY2x1ZGUgYWRkaXRpb25hbCBnZW5lLWJhc2VkIG9yIGZ1bmN0aW9uYWwgYW5ub3RhdGlvbnMgaW4gdGhlIGFnZ3JlZ2F0aW9uIHNjaGVtZS4KCioqT3JnYW5pemF0aW9uOioqIFVuZGVyIHRoZSBgU05WLWxldmVsIEltcG9ydGFuY2VzYCB0YWIsIHdlIHByb3ZpZGUgdGhlIFNOVi1sZXZlbCBmZWF0dXJlIGltcG9ydGFuY2VzIGZyb20gdGhlIGZpdHRlZCBwcmVkaWN0aW9uIGFsZ29yaXRobXMgKGRlc2NyaWJlZCBpbiB0aGUgYFByZWRpY3Rpb24gU3RlcGAgc2VjdGlvbikgZm9yIGNvbXBsZXRlbmVzcy4gVGhlc2UgU05WLWxldmVsIGZlYXR1cmUgaW1wb3J0YW5jZXMgYXJlIHZlcnkgdW5zdGFibGUgYWNyb3NzIG1ldGhvZHMgYW5kIGFjcm9zcyBib290c3RyYXAgcGVydHVyYmF0aW9ucyBmb3IgdGhlIHJlYXNvbnMgZGlzY3Vzc2VkIGFib3ZlLiBXZSB0aGVuIHN1bW1hcml6ZSB0aGUgcmVzdWx0cyBmcm9tIHRoZSBsby1zaVJGIHBpcGVsaW5lIGluY2x1ZGluZyB0aGUgcmFua2luZ3Mgb2YgZ2VuZXRpYyBsb2NpIGFuZCBpbnRlcmFjdGlvbiBiZXR3ZWVuIGdlbmV0aWMgbG9jaSB1c2luZyBvdXIgbmV3IGxvY3VzLWxldmVsIGltcG9ydGFuY2Ugc2NvcmUgdW5kZXIgdGhlIGBTdW1tYXJ5IG9mIGxvLXNpUkYgUmVzdWx0c2AgdGFiLiBBIGZpbmFsIHRlY2huaWNhbCBub3RlIG9uIHRoZSBhZHZhbnRhZ2VzIG9mIGluY29ycG9yYXRpbmcgc2lnbmVkIGluZm9ybWF0aW9uIGZyb20gc2lSRiBpbiB0aGlzIGZlYXR1cmUgaW1wb3J0YW5jZSBjb21wdXRhdGlvbiBpcyBwcm92aWRlZCB1bmRlciB0aGUgYEFkdmFudGFnZXMgb2YgU2lnbmVkIEluZm9ybWF0aW9uYCB0YWIuCgo8L2Rpdj4KCiMjIFNOVi1sZXZlbCBGZWF0dXJlIEltcG9ydGFuY2VzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpIYXZpbmcgb2JzZXJ2ZWQgdGhhdCB0aGUgYWZvcmVtZW50aW9uZWQgY2xhc3NpZmljYXRpb24gYWxnb3JpdGhtcyBkbyBoYXZlIHNvbWUgcHJlZGljdGl2ZSBwb3dlciB0byBwcmVkaWN0IHRob3NlIHdpdGggaGlnaCB2ZXJzdXMgbG93IExWTWksIGEgbmF0dXJhbCBuZXh0IHN0ZXAgaXMgdG8gaW52ZXN0aWdhdGUgd2hpY2ggU05WcyB3ZXJlIHVzZWQgaW4gdGhlc2UgcHJlZGljdGlvbiBtb2RlbHMuIEJlbG93LCB3ZSBoaWdobGlnaHQgdGhlIHRvcCAxMDAgU05WcywgcmFua2VkIGJ5IGltcG9ydGFuY2UgaW4gZWFjaCBvZiB0aGUgcHJlZGljdGlvbiBtb2RlbHMuIEZvciBjb21wbGV0ZW5lc3MsIHdlIHByb3ZpZGUgdGhlIFNOViBpbXBvcnRhbmNlcyBmb3IgdGhlIHVuYmluYXJpemVkIExWTWkgKHJlZ3Jlc3Npb24pIHByb2JsZW0gYXMgd2VsbCBhcyB0aGUgYmluYXJpemVkIExWTWkgKGNsYXNzaWZpY2F0aW9uKSBwcm9ibGVtIGFjcm9zcyB0aGUgdGhyZWUgZGlmZmVyZW50IGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzLgoKKipIb3cgaXMgaW1wb3J0YW5jZSBkZWZpbmVkPyoqCgotIEZvciByaWRnZSBhbmQgTGFzc28sIHRoZSBpbXBvcnRhbmNlIG9mIGFuIFNOViBpcyBkZWZpbmVkIGFzIHRoZSBtYWduaXR1ZGUgb2YgaXRzIGNvZWZmaWNpZW50IGluIHRoZSBwcmVkaWN0aW9uIG1vZGVsLgotIEZvciBSRiwgdGhlIGltcG9ydGFuY2Ugb2YgYW4gU05WIGlzIGRldGVybWluZWQgYnkgdGhlIG1lYW4gZGVjcmVhc2UgaW4gaW1wdXJpdHkgKE1ESSkgc2NvcmUuCi0gRm9yIHNpUkYsIHRoZSBpbXBvcnRhbmNlIG9mIGFuIFNOViBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBNREkgZnJvbSB0aGUgZm9yZXN0IGluIHRoZSBmaW5hbCBpdGVyYXRpb24uCi0gRHVlIHRvIHRoZSBjb21wdXRhdGlvbmFsIGNvbXBsZXhpdHksIHdlIGRpZCBub3QgY29tcHV0ZSB0aGUgU05WIGltcG9ydGFuY2VzIGZyb20gdGhlIFNWTSBmaXQgYXMgdGhlcmUgaXMgbm8gYnVpbHQtaW4gbW9kZWwtYmFzZWQgZmVhdHVyZSBpbXBvcnRhbmNlIG1ldGhvZCAoaW4gUiksIGFuZCBhbnkgcGVybXV0YXRpb24tYmFzZWQgYXBwcm9hY2ggd291bGQgYmUgY29tcHV0YXRpb25hbGx5IGV4cGVuc2l2ZS4KCioqQSB3b3JkIG9mIGNhdXRpb246KiogV2hlbiBpbnRlcnByZXRpbmcgdGhlc2UgU05WIGltcG9ydGFuY2VzLCBpdCBpcyBjcnVjaWFsIHRvIGtlZXAgaW4gbWluZCB0aGF0IHRoZXJlIGFyZSB2ZXJ5IGxhcmdlLCBzdHJvbmdseSBjb3JyZWxhdGVkIGJsb2NrcyBvZiBTTlZzIHdpdGhpbiB0aGlzIGRhdGEsIHdoaWNoIG9mdGVuIHJlbmRlcnMgdGhlIGZlYXR1cmUgcmFua2luZ3MgdW5tZWFuaW5nZnVsIGFuZCB1bnN0YWJsZSBbQHRvbG9jc2kyMDExY2xhc3NpZmljYXRpb247IEBob29rZXIyMDIxdW5yZXN0cmljdGVkXS4gSW4gcGFydGljdWxhciwgaXQgaXMgd2VsbC1rbm93biB0aGF0IHRoZSBNREkgdmFyaWFibGUgaW1wb3J0YW5jZSBtZXRyaWMgdXNlZCBpbiBSRi9pUkYvc2lSRiBpcyBiaWFzZWQgYWdhaW5zdCBjb3JyZWxhdGVkIGZlYXR1cmVzIFtAaG9va2VyMjAyMXVucmVzdHJpY3RlZF0uIEluIG90aGVyIHdvcmRzLCBTTlZzIHdpdGhpbiBsYXJnZSBMRCBibG9ja3MgdGVuZCB0byBoYXZlIGFydGlmaWNpYWxseSBsb3cgTURJIHZhbHVlcy4gR2l2ZW4gdGhlc2UgaWRpb3N5bmNyYXNpZXMsIGl0IGlzIHVuc3VycHJpc2luZyB0aGF0IFNOVnMgZnJvbSBUVE4gYW5kIENDREMxNDEgLS0gdHdvIGdlbmV0aWMgbG9jaSB3aXRoIG1hbnkgU05WcyB1bmRlciBMRCAtLSBkbyBub3QgaGF2ZSBoaWdoIGltcG9ydGFuY2VzIGFjY29yZGluZyB0byBNREkuIFdlIHByb3ZpZGUgdGhlc2UgU05WIGltcG9ydGFuY2UgdGFibGVzIG9ubHkgZm9yIGNvbXBsZXRlbmVzcyBhbmQgdG8gcGFydGlhbGx5IG1vdGl2YXRlIHRoZSBuZWVkIHRvIGFnZ3JlZ2F0ZSBTTlYtbGV2ZWwgaW1wb3J0YW5jZXMgaW50byBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlcyBpbiBsby1zaVJGLgoKPC9kaXY+CgoKYGBge3IgdmltcCwgcmVzdWx0cyA9ICJhc2lzIn0KIyBwaGVub3R5cGVfaGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgp0aHJfaGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSIKbWV0aG9kX2hlYWRlciA8LSAiXG5cbiMjIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9IFxuXG4iCnN1YnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjIyMgJXMgey51bm51bWJlcmVkfVxuXG4iCgptZXRob2RzIDwtIGMoIkxhc3NvIiA9ICJsYXNzbyIsICJSaWRnZSIgPSAicmlkZ2UiLCAiUkYiID0gInJmIiwgInNpUkYiID0gImlyZiIpCgppZiAocGFyYW1zJGV2YWwpIHsKICBzbnBzX2RmIDwtIGZyZWFkKGZpbGUucGF0aChyZXNfZGlyLCAiYW5ub3ZhciIsICJzbnAyZ2VuZV9kZi5jc3YiKSkKICBmb3IgKHBoZW5vdHlwZSBpbiBwaGVub3R5cGVzKSB7CiAgICBwaGVub3R5cGVfbmFtZSA8LSBuYW1lcyhwaGVub3R5cGVzKVtwaGVub3R5cGVzID09IHBoZW5vdHlwZV0KICAgIGZvciAodGhyIGluIGMoTkEsIDAuMTUsIDAuMiwgMC4yNSkpIHsKICAgICAgaWYgKGlzLm5hKHRocikpIHsKICAgICAgICBmcGF0aCA8LSBmaWxlLnBhdGgocmVzX2RpciwgcGFzdGUwKHBoZW5vdHlwZSwgIl9nd2FzX2ZpbHRlcmVkX25zbnBzMTAwMCIpKQogICAgICB9IGVsc2UgewogICAgICAgIGZwYXRoIDwtIGZpbGUucGF0aChyZXNfZGlyLCBwYXN0ZTAoCiAgICAgICAgICBwaGVub3R5cGUsICJfYmluYXJ5X3RociIsIHRociwKICAgICAgICAgICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiCiAgICAgICAgKSkKICAgICAgfQogICAgICBmb3IgKG1ldGhvZCBpbiBtZXRob2RzKSB7CiAgICAgICAgdmltcF9vdXQgPC0gZXZhbFZpbXAocmVzX2RpciA9IGZwYXRoLCBtZXRob2QgPSBtZXRob2QsIHNucHNfZGYgPSBzbnBzX2RmKSAlPiUKICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoIXN0cmluZ3I6OnN0cl9kZXRlY3QoR2VuZSwgIlBDWzAtOV0qJCIpKSAlPiUKICAgICAgICAgIGRwbHlyOjpzbGljZSgxOjEwMCkgJT4lCiAgICAgICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgICAgICBBbGxlbGVzID0gcHVycnI6Om1hcDIoUmVmLCBBbHQsIH4gc29ydChjKC54LCAueSkpKSwKICAgICAgICAgICAgQWxsZWxlMSA9IHB1cnJyOjptYXBfY2hyKEFsbGVsZXMsIH4gLnhbWzFdXSksCiAgICAgICAgICAgIEFsbGVsZTIgPSBwdXJycjo6bWFwX2NocihBbGxlbGVzLCB+IC54W1syXV0pLAogICAgICAgICAgICB1bmlxSUQgPSBwYXN0ZShDaHIsIFBvcywgQWxsZWxlMSwgQWxsZWxlMiwgc2VwID0gIjoiKQogICAgICAgICAgKSAlPiUKICAgICAgICAgIGRwbHlyOjpzZWxlY3QoCiAgICAgICAgICAgIENociwgcnNJRCwgUG9zLCB1bmlxSUQsCiAgICAgICAgICAgIExvY3VzID0gR2VuZSwgRnVuY3Rpb24gPSBgR2VuZSBGdW5jdGlvbmAsCiAgICAgICAgICAgIGBFeG9uaWMgRnVuY3Rpb25gLCBJbXBvcnRhbmNlCiAgICAgICAgICApCiAgICAgICAgaWYgKCFpcy5udWxsKHZpbXBfb3V0KSkgewogICAgICAgICAgdGFiIDwtIHByZXR0eV9EVCh2aW1wX291dCwgZGlnaXRzID0gMywgc2lnZmlnID0gVCwgbmFfZGlzcCA9ICItLSIpCiAgICAgICAgICAjIHNhdmVSRFMoCiAgICAgICAgICAjICAgdGFiLAogICAgICAgICAgIyAgIGZpbGUucGF0aCgKICAgICAgICAgICMgICAgIHRhYl9yZXNfZGlyLAogICAgICAgICAgIyAgICAgcGFzdGUwKAogICAgICAgICAgIyAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLCAiXyIsIG1ldGhvZCwKICAgICAgICAgICMgICAgICAgIl92aW1wLnJkcyIKICAgICAgICAgICMgICAgICkKICAgICAgICAgICMgICApCiAgICAgICAgICAjICkKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9Cn0gZWxzZSB7CiAgZm9yIChwaGVub3R5cGUgaW4gcGhlbm90eXBlcykgewogICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlcylbcGhlbm90eXBlcyA9PSBwaGVub3R5cGVdCiAgICAjIGNhdChzcHJpbnRmKHBoZW5vdHlwZV9oZWFkZXIsIHBoZW5vdHlwZV9uYW1lKSkKICAgIGZvciAodGhyIGluIGMoTkEsIDAuMTUsIDAuMiwgMC4yNSkpIHsKICAgICAgaWYgKGlzLm5hKHRocikpIHsKICAgICAgICBjYXQoc3ByaW50Zih0aHJfaGVhZGVyLCAiVW5iaW5hcml6ZWQgKFJlZ3Jlc3Npb24pIikpCiAgICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMChwaGVub3R5cGUsICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiKSkKICAgICAgICBwaGVub3R5cGVfc3RyIDwtIHNwcmludGYoIiVzIiwgcGhlbm90eXBlX25hbWUpCiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2F0KHNwcmludGYodGhyX2hlYWRlciwgcGFzdGUwKCJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gIiwgdGhyKSkpCiAgICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMCgKICAgICAgICAgIHBoZW5vdHlwZSwgIl9iaW5hcnlfdGhyIiwgdGhyLAogICAgICAgICAgIl9nd2FzX2ZpbHRlcmVkX25zbnBzMTAwMCIKICAgICAgICApKQogICAgICAgIHBoZW5vdHlwZV9zdHIgPC0gc3ByaW50ZigidGhlIGJpbmFyaXplZCAlcyAodGhyZXNob2xkID0gJXMpIiwgcGhlbm90eXBlX25hbWUsIHRocikKICAgICAgfQogICAgICBmb3IgKGkgaW4gMTpsZW5ndGgobWV0aG9kcykpIHsKICAgICAgICBtZXRob2QgPC0gbWV0aG9kc1tbaV1dCiAgICAgICAgbWV0aG9kX25hbWUgPC0gbmFtZXMobWV0aG9kcylbaV0KICAgICAgICBjYXQoc3ByaW50ZihtZXRob2RfaGVhZGVyLCBtZXRob2RfbmFtZSkpCiAgICAgICAgdG1wX2ZpbGUgPC0gZmlsZS5wYXRoKAogICAgICAgICAgdGFiX3Jlc19kaXIsCiAgICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsICJfIiwgbWV0aG9kLAogICAgICAgICAgICAiX3ZpbXAucmRzIgogICAgICAgICAgKQogICAgICAgICkKICAgICAgICBpZiAoZmlsZS5leGlzdHModG1wX2ZpbGUpKSB7CiAgICAgICAgICB0YWIgPC0gcmVhZFJEUyh0bXBfZmlsZSkKICAgICAgICAgIHN1YmNodW5raWZ5KHRhYiwKICAgICAgICAgICAgaSA9IGNodW5rX2lkeCwKICAgICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIiclcyAtIFRvcCAxMDAgU05WcywgcmFua2VkIGJ5IGltcG9ydGFuY2UsIGZvciBwcmVkaWN0aW5nICVzLiciLCBtZXRob2RfbmFtZSwgcGhlbm90eXBlX3N0cikKICAgICAgICAgICkKICAgICAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQp9CmBgYAoKIyMgU3VtbWFyeSBvZiBsby1zaVJGIFJlc3VsdHMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CkZpbmFsbHksIHdlIHN1bW1hcml6ZSB0aGUgcHJpb3JpdGl6YXRpb24gcmVzdWx0cyBmcm9tIHRoZSBsby1zaVJGIHBpcGVsaW5lIHVzaW5nIG91ciBuZXcgaW1wb3J0YW5jZSBzY29yZSB0byByYW5rIGdlbmV0aWMgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpLiBJbiB0aGlzIG5ldyBpbXBvcnRhbmNlIHNjb3JlLCB3ZSAoMSkgY29tcHV0ZWQgYSBsb2NhbCAoaS5lLiwgb24gYSBwZXItaW5kaXZpZHVhbCBiYXNpcykgc3RhYmlsaXR5IGltcG9ydGFuY2Ugc2NvcmUgdGhhdCBhZ2dyZWdhdGVzIHdlYWsgU05WLWxldmVsIGltcG9ydGFuY2VzIGludG8gc3Ryb25nZXIgbG9jdXMtbGV2ZWwgaW1wb3J0YW5jZXMgdXNpbmcgdGhlIHNpUkYgZml0IGFuZCAoMikgY29uZHVjdGVkIGEgcGVybXV0YXRpb24gdGVzdCB0byBhc3Nlc3Mgd2hldGhlciB0aGUgbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2Ugc2NvcmVzIGZvciBhIGdpdmVuIGxvY3VzL2ludGVyYWN0aW9uIGFyZSBkaWZmZXJlbnQgYmV0d2VlbiBpbmRpdmlkdWFscyB3aXRoIGhpZ2ggYW5kIGxvdyBMVk1pIChjb25kaXRpb25lZCBvbiB0aGUgcmVzdCBvZiB0aGUgZml0dGVkIGZvcmVzdCkuIFRoZSBsYXJnZXIgdGhlIGRpZmZlcmVuY2UgaW4gbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2Ugc2NvcmVzIGJldHdlZW4gdGhvc2Ugd2l0aCBoaWdoIHZlcnN1cyBsb3cgTFZNaSwgdGhlIGdyZWF0ZXIgdGhlIGltcG9ydGFuY2Ugb2YgdGhlIGxvY3VzL2ludGVyYWN0aW9uIGZvciBwcmVkaWN0aW5nIExWTWkuIEZvciBkZXRhaWxzIG9uIHRoZSBuZXcgaW1wb3J0YW5jZSBzY29yZSwgd2UgcmVmZXIgdG8gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkuCgpCZWxvdywgd2UgcmVjYXAgdGhlIHNpUkYgcHJlZGljdGlvbiBhY2N1cmFjeSBmb3IgcHJlZGljdGluZyB0aGUgYmluYXJpemVkIExWTWkgYWNyb3NzIHRoZSB0aHJlZSBiaW5hcml6YXRpb24gdGhyZXNob2xkcyAoMTVcJSwgMjBcJSwgMjVcJSkgKEZpZ3VyZSBcQHJlZihmaWc6c3ViY2h1bmstNTgpKS4gVGhlbiwgaW4gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay01OSksIHdlIHN1bW1hcml6ZSB0aGUgcHJpb3JpdGl6YXRpb24gcmFua2luZ3Mgb2YgZ2VuZXRpYyBsb2NpIGFuZCBpbnRlcmFjdGlvbiBiZXR3ZWVuIGxvY2kgYWNjb3JkaW5nIHRvIHRoZSBuZXcgaW1wb3J0YW5jZSBzY29yZS4gV2UgcHJvdmlkZSB0aGUgbm9taW5hbCBwZXJtdXRhdGlvbiBwLXZhbHVlcyBhbG9uZyB3aXRoIHRoZSBwZXJtdXRhdGlvbiB0ZXN0IHN0YXRpc3RpYywgdGhhdCBpcywgdGhlIGRpZmZlcmVuY2UgaW4gbG9jYWwgZmVhdHVyZSBzdGFiaWxpdHkgc2NvcmVzIGJldHdlZW4gdGhlIGhpZ2ggYW5kIGxvdyBMVk1pIGdyb3Vwcywgd2l0aCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoaXMgcGVybXV0YXRpb24gZGlzdHJpYnV0aW9uIGluIHBhcmVudGhlc2VzLiAKCk5vdGUgdGhhdCB0aGUgcGVybXV0YXRpb24gdGVzdCB3YXMgbm90IHBlcmZvcm1lZCBmb3IgYWxsIGxvY2kvaW50ZXJhY3Rpb25zIChkZXRhaWxzIGluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKGh0dHBzOi8vd3d3Lm1lZHJ4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS8yMDIzLjExLjA2LjIzMjk3ODU4djEpKS4gR2l2ZW4gb3VyIHByaW1hcnkgYWltIG9mIGdlbmVyYXRpbmcgcmVsaWFibGUgaHlwb3RoZXNlcyBmb3IgZm9sbG93LXVwIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uLCB3ZSBjaG9zZSB0byBvbmx5IHRlc3QgbG9jaS9pbnRlcmFjdGlvbnMgdGhhdCB3ZXJlICpwcmVkaWN0aXZlKiBhbmQgKnN0YWJsZSogaW4gdGhlIHNpUkYgZml0LCBmb2xsb3dpbmcgdGhlIFBDUyBmcmFtZXdvcmsgZm9yIHZlcmlkaWNhbCBkYXRhIHNjaWVuY2UgW0B5dTIwMjB2ZXJpZGljYWxdLiBTcGVjaWZpY2FsbHksIGZvciBlYWNoIGJpbmFyaXphdGlvbiB0aHJlc2hvbGQsIHdlIG9ubHkgdGVzdGVkOgoKLSB0aGUgdG9wIDI1IGxvY2kgd2l0aCB0aGUgaGlnaGVzdCBhdmVyYWdlIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3Jlcywgb3IgaW4gb3RoZXIgd29yZHMsIHRob3NlIHRoYXQgb2NjdXJyZWQgbW9zdCBzdGFibHkvZnJlcXVlbnRseSAoYW5kIHRodXMgbGlrZWx5IHByZWRpY3RpdmUpIGluIHRoZSBzaVJGIGZpdCwgYW5kCi0gdGhlIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgdGhhdCB3ZXJlIGlkZW50aWZpZWQgYnkgc2lSRiBhbmQgYWNoaWV2ZWQgYSBzdGFiaWxpdHkgc2NvcmUgPiAwLjUsIHN0YWJpbGl0eSBzY29yZSBmb3IgbWVhbiBpbmNyZWFzZSBpbiBwcmVjaXNpb24gPiAwLCBhbmQgc3RhYmlsaXR5IHNjb3JlIGZvciBmZWF0dXJlIHNlbGVjdGlvbiBkZXBlbmRlbmNlID4gMC4gV2Ugbm90ZSB0aGF0IGluIGFkZGl0aW9uIHRvIHRoZSBleHBsaWNpdCBzdGFiaWxpdHkgY2hlY2tzIGhlcmUsIHRoZSByZXF1aXJlbWVudCBvbiB0aGUgbWVhbiBpbmNyZWFzZSBpbiBwcmVjaXNpb24gc2VydmVzIGFzIGEgcHJlZGljdGFiaWxpdHkgY2hlY2ssIGFuZCB0aGUgcmVxdWlyZW1lbnQgb24gdGhlIGZlYXR1cmUgc2VsZWN0aW9uIGRlcGVuZGVuY2Ugc2VydmVzIHRvIGRpZmZlcmVudGlhdGUgbWFyZ2luYWwgYWRkaXRpdmUgZWZmZWN0cyBmcm9tIG5vbi1hZGRpdGl2ZSBpbnRlcmFjdGlvbiBlZmZlY3RzIChzZWUgQGt1bWJpZXIyMDE4cmVmaW5pbmcgZm9yIGRldGFpbHMpLgoKQnkgaW1wbGVtZW50aW5nIHRoaXMgYWRkaXRpb25hbCBwcmVkaWN0YWJpbGl0eSBhbmQgc3RhYmlsaXR5IGNoZWNrLCB3ZSBhcmUgcmVxdWlyaW5nIHRoYXQgdGhlIHByaW9yaXRpemVkIGxvY2kvaW50ZXJhY3Rpb25zIG1lZXQgYSBoaWdoZXIgc3RhbmRhcmQsIHdpdGggdGhlIGhvcGUgdGhhdCB0aGlzIHVsdGltYXRlbHkgZ2VuZXJhdGVzIG1vcmUgcmVsaWFibGUgKGFsYmVpdCBtb3JlIGNvbnNlcnZhdGl2ZSkgZXhwZXJpbWVudGFsIHJlY29tbWVuZGF0aW9ucy4KCkluIGFkZGl0aW9uIHRvIHRoZSBwcm92aWRlZCBzdW1tYXJ5IG9mIHJlc3VsdHMsCgotIFVuZGVyIHRoZSBgc2lSRiBJbnRlcmFjdGlvbiBUYWJsZWAgdGFiLCB3ZSBwcm92aWRlIHRoZSBmdWxsIHNpUkYgbG9jdXMtbGV2ZWwgaW50ZXJhY3Rpb24gdGFibGUgb3V0cHV0IGZvciBlYWNoIGJpbmFyaXphdGlvbiB0aHJlc2hvbGQgKEZpZ3VyZXMgXEByZWYoZmlnOnN1YmNodW5rLTYwKSwgXEByZWYoZmlnOnN1YmNodW5rLTYyKSwgYW5kIFxAcmVmKGZpZzpzdWJjaHVuay02NCkpLiBUaGlzIHRhYmxlIGluY2x1ZGVzIHNldmVyYWwgbWV0cmljcyBmb3IgZXZhbHVhdGluZyB0aGUgc3RhYmlsaXR5IGFuZCBzdHJlbmd0aCBvZiB0aGUgaW50ZXJhY3Rpb24uIEZvciBkZXRhaWxzIG9uIHRoZXNlIG1ldHJpY3MsIHdlIHJlZmVyIHRvIEBrdW1iaWVyMjAxOHJlZmluaW5nLgogIC0gRm9yIGNvbXBhcmlzb24sIHdlIGFsc28gcHJvdmlkZSB0aGUgYW5hbG9nb3VzIHNpUkYgb3V0cHV0IGZvciBpbnRlcmFjdGlvbnMgYXQgdGhlIFNOViBsZXZlbCAoRmlndXJlcyBcQHJlZihmaWc6c3ViY2h1bmstNjEpLCBcQHJlZihmaWc6c3ViY2h1bmstNjMpLCBhbmQgXEByZWYoZmlnOnN1YmNodW5rLTY1KSkuIEhlcmUsIHdlIHNlZSB0aGF0IGlmIHdlIGRvIG5vdCBwZXJmb3JtIHRoZSBTTlYtdG8tbG9jdXMgYWdncmVnYXRpb24sIHRoZSBzdGFiaWxpdHkgc2NvcmVzIGZvciB0aGUgU05WLWxldmVsIGludGVyYWN0aW9ucyBhcmUgdmVyeSBjbG9zZSB0byAwLiBUaGlzIG1lYW5zIHRoYXQgdGhlIHNpUkYtaWRlbnRpZmllZCBTTlYtbGV2ZWwgaW50ZXJhY3Rpb25zIHJhcmVseSBhcHBlYXIgd2hlbiBzaVJGIGlzIHJlZml0dGVkIHVzaW5nIGRpZmZlcmVudCBib290c3RyYXBwZWQgdHJhaW5pbmcgc2FtcGxlcy4gQXMgZGlzY3Vzc2VkIHByZXZpb3VzbHksIHRoaXMgaW5zdGFiaWxpdHkgaXMgcGFydGlhbGx5IGR1ZSB0byB0aGUgY29ycmVsYXRpb24gYW1vbmcgU05WcyBhbmQgdGhlIHdlYWsgcGhlbm90eXBpYyBzaWduYWwuIFRoaXMgaGlnaCBpbnN0YWJpbGl0eSBhbHNvIG1vdGl2YXRlcyB0aGUgbmVlZCBmb3IgYW4gYWx0ZXJuYXRpdmUgYXBwcm9hY2ggdmlhIG91ciBuZXcgaW1wb3J0YW5jZSBzY29yZS4KLSBVbmRlciB0aGUgYExvY2FsIFN0YWJpbGl0eSBJbXBvcnRhbmNlIFBsb3RzIC0gSW50ZXJhY3Rpb25zYCBhbmQgYExvY2FsIFN0YWJpbGl0eSBJbXBvcnRhbmNlIFBsb3RzIC0gTG9jaWAsIHdlIHByb3ZpZGUgdmlzdWFsaXphdGlvbnMgb2YgdGhlIGRlbnNpdHkgZGlzdHJpYnV0aW9uIG9mIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3JlcyBiZXR3ZWVuIHRoZSBsb3cgYW5kIGhpZ2ggTFZNaSBncm91cHMgYXMgd2VsbCBhcyB0aGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBvZiBTTlZzIHVzZWQgaW4gdGhlIHNpUkYgZml0IChpLmUuLCB3aGljaCBTTlZzIG9jY3VycmVkIG1vc3QgZnJlcXVlbnRseSBpbiB0aGUgZGVjaXNpb24gcGF0aHMgYWNyb3NzIHRoZSBzaVJGIGZpdCkuCiAgLSBJbiB0aGUgZGVuc2l0eSBkaXN0cmlidXRpb24gb2YgbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2Ugc2NvcmVzLCBvYnNlcnZhYmxlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGxvdyBhbmQgaGlnaCBMVk1pIGdyb3VwcyBhcmUgZXZpZGVuY2UgdGhhdCB0aGUgZ2VuZXRpYyBsb2N1cyBvciBpbnRlcmFjdGlvbiBiZXR3ZWVuIGxvY2kgaXMgaW1wb3J0YW50IGZvciBkaWZmZXJlbnRpYXRpbmcgYmV0d2VlbiBpbmRpdmlkdWFscyB3aXRoIGhpZ2ggdmVyc3VzIGxvdyBMVk1pLiBUaGUgbGFyZ2VyIHRoZSBkaWZmZXJlbmNlLCB0aGUgZ3JlYXRlciB0aGUgaW1wb3J0YW5jZSBvZiB0aGUgbG9jdXMgb3IgaW50ZXJhY3Rpb24gYmV0d2VlbiBsb2NpLgogIC0gSW4gdGhlIFNOViBmcmVxdWVuY3kgZGlzdHJpYnV0aW9ucywgd2Ugc2hvdyB0aGUgZnJlcXVlbmN5IG9mIG9jY3VycmVuY2UgZm9yIGVhY2ggU05WIG9yIFNOViBwYWlyIGluIHRoZSBzaVJGIGZpdC4gVGhpcyBpcyB0aGUgbnVtYmVyIG9mIGRlY2lzaW9uIHBhdGhzIGZvciB3aGljaCB0aGUgU05WIG9yIFNOViBwYWlyIGFwcGVhcmVkIGluIHRoZSBzaVJGIGZpdC4gU05WcyBvciBTTlYgcGFpcnMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgaW4gdGhlIFJGIGRlY2lzaW9uIHBhdGhzICh5LWF4aXMpIGNvbnRyaWJ1dGVkIHRoZSBtb3N0IHRvIHRoZSBvdmVyYWxsIGxvY3VzL2ludGVyYWN0aW9uJ3MgaW1wb3J0YW5jZSBpbiB0aGUgc2lSRiBmaXQuCgo8L2Rpdj4KCgpgYGB7ciBpcmYtcmVzdWx0cywgcmVzdWx0cyA9ICJhc2lzIn0KIyBwaGVub3R5cGVfaGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgpzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LWNpcmNsZX0gXG5cbiIKdGhyX2hlYWRlciA8LSAiXG5cbiMjIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGV9IFxuXG4iCiMgc3Vic2VjdGlvbl9oZWFkZXIgPC0gIlxuXG4jIyMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZSAudGFic2V0LWNpcmNsZX0gXG5cbiIKIyBzdWJzdWJzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyMjIyMgJXMgey51bm51bWJlcmVkfSBcblxuIgoKRElTVF9IRUlHSFQgPC0gOApIRUFUTUFQX0hFSUdIVCA8LSA4CkVQSV9IRUlHSFQgPC0gOApJVEVSIDwtIDMKTEVGVF9NQVJHSU4gPC0gNQoKaWYgKHBhcmFtcyRldmFsKSB7CiAgZm9yIChwaGVub3R5cGUgaW4gcGhlbm90eXBlcykgewogICAgcHJpbnQocGhlbm90eXBlKQogICAgZXZhbF9scyA8LSBsaXN0KCkKICAgIGludF9yZXN1bHRzX2xzIDwtIGxpc3QoKQogICAgZ2VuZV9yZXN1bHRzX2xzIDwtIGxpc3QoKQogICAgZm9yICh0aHIgaW4gYygwLjE1LCAwLjIsIDAuMjUpKSB7CiAgICAgIHByaW50KHRocikKICAgICAgZnBhdGggPC0gZmlsZS5wYXRoKHJlc19kaXIsIHBhc3RlMCgKICAgICAgICBwaGVub3R5cGUsICJfYmluYXJ5X3RociIsIHRociwKICAgICAgICAiX2d3YXNfZmlsdGVyZWRfbnNucHMxMDAwIgogICAgICApKQogICAgICAjID4gb3V0LCB5aGF0X3RyMiwgeWhhdF92YSwgaXJmX2dlbmVfb3V0LCBzbnBzLmRmLCBpcmZfc252X2ludF9vdXQKICAgICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJpcmZfaW50ZXJhY3Rpb25fZml0LlJkYXRhIikpCiAgICAgIHlfdGVzdCA8LSBpZmVsc2Uob3V0JHBoZW5vX3Rlc3QgPT0gMCwgIkxvdyBMVk1pIiwgIkhpZ2ggTFZNaSIpCgogICAgICAjICMgcHJlZGljdGlvbiByZXN1bHRzCiAgICAgICMgZXZhbF9vdXQgPC0gYmluZF9yb3dzKAogICAgICAjICAgZXZhbFByZWRzKHkgPSBvdXQkcGhlbm9fdGVzdCwgeWhhdCA9IHloYXRfdmEsIG1ldHJpYyA9IGMoIkFVQyIsICJQUiIpKSwKICAgICAgIyAgIGV2YWxQcmVkcyh5ID0gb3V0JHBoZW5vX3Rlc3QsIHloYXQgPSByb3VuZCh5aGF0X3ZhKSwgbWV0cmljID0gYygiQ2xhc3MiKSkKICAgICAgIyApICU+JQogICAgICAjICAgc3ByZWFkKGtleSA9ICJNZXRyaWMiLCB2YWx1ZSA9ICJWYWx1ZSIpCiAgICAgICMgZXZhbF9sc1tbYXMuY2hhcmFjdGVyKHRocildXSA8LSBldmFsX291dAoKICAgICAgIyBsb2NhbCBpbnRlcmFjdGlvbiBzdGFiaWxpdHkgcmVzdWx0cwogICAgICBsb2FkKGZpbGUucGF0aChmcGF0aCwgImxvY2FsX2ludGVyYWN0aW9uX3N0YWJpbGl0eV9yZXN1bHRzLlJkYXRhIikpCiAgICAgIGludF9vdXQgPC0gbGlzdCgKICAgICAgICBzdGFiX3RyMl9scyA9IGludF9zdGFiX3RyMl9scywKICAgICAgICBzdGFiX3ZhX2xzID0gaW50X3N0YWJfdmFfbHMsCiAgICAgICAgdGVzdF9pbnRzX2xzID0gdGVzdF9pbnRzX2xzLAogICAgICAgIHBlcm1fb3V0X2xzID0gaW50X3Blcm1fb3V0X2xzCiAgICAgICkKICAgICAgaW50X3Jlc3VsdHNfbHNbW2FzLmNoYXJhY3Rlcih0aHIpXV0gPC0gaW50X3Blcm1fb3V0X2xzCgogICAgICBpbnRfYWxsX291dCA8LSBsaXN0KGBVc2luZyBhbGwgc3BsaXRzYCA9IGludF9vdXQpCgogICAgICBwdmFsX2ludCA8LSBtYXBfZGZyKGludF9vdXQkcGVybV9vdXRfbHNbW0lURVJdXSwKICAgICAgICBmdW5jdGlvbih4KSB7CiAgICAgICAgICBkYXRhLmZyYW1lKAogICAgICAgICAgICBwdmFsID0geCRwdmFsLAogICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFCiAgICAgICAgICApCiAgICAgICAgfSwKICAgICAgICAuaWQgPSAiaW50IgogICAgICApICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBwdmFsX3N0ciA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgIHB2YWwgPCAxZS00IH4gIjwgMTA8c3VwPi00PC9zdXA+IiwKICAgICAgICAgICAgcHZhbCA8IDFlLTMgfiAiPCAxMDxzdXA+LTM8L3N1cD4iLAogICAgICAgICAgICBUUlVFIH4gc3ByaW50ZigiJXMiLCBmb3JtYXRDKHB2YWwsIGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJmIikpCiAgICAgICAgICApCiAgICAgICAgKQoKICAgICAgc3R5bGVfbmFtZXNfYmFzaWMgPC0gZnVuY3Rpb24oeCwgaXRhbGljID0gVFJVRSkgewogICAgICAgIHggPC0geCAlPiUKICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLV8iLCAiPHN1cD4mIzgyMTE7PC9zdXA+JiM4MjExOyIpICU+JQogICAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCJcXCtfIiwgIjxzdXA+Kzwvc3VwPiYjODIxMTsiKSAlPiUKICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLSQiLCAiPHN1cD4mIzgyMTE7PC9zdXA+IikgJT4lCiAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoIlxcKyQiLCAiPHN1cD4rPC9zdXA+IikgJT4lCiAgICAgICAgICBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoZXNjYXBlID0gRkFMU0UsIGl0YWxpYyA9IGl0YWxpYykKICAgICAgICByZXR1cm4oeCkKICAgICAgfQoKICAgICAgIyBpUkYgcmVzdWx0cwogICAgICB0YWJfb3V0IDwtIGlyZl9nZW5lX291dCRpbnRlcmFjdGlvbltbSVRFUl1dICU+JQogICAgICAgIGxlZnRfam9pbih5ID0gcHZhbF9pbnQsIGJ5ID0gImludCIpICU+JQogICAgICAgIGRwbHlyOjphcnJhbmdlKHB2YWwpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLXB2YWwpICU+JQogICAgICAgIGRwbHlyOjpyZW5hbWUoCiAgICAgICAgICAiSW50ZXJhY3Rpb24iID0gImludCIsCiAgICAgICAgICAiUHJldmFsZW5jZSIgPSAicHJldmFsZW5jZSIsCiAgICAgICAgICAiUHJlY2lzaW9uIiA9ICJwcmVjaXNpb24iLAogICAgICAgICAgIkNsYXNzIERpZmZlcmVuY2UgaW4gUHJldmFsZW5jZSIgPSAiY3BlIiwKICAgICAgICAgICJTdGFiaWxpdHkgb2YgQ2xhc3MgRGlmZmVyZW5jZSBpbiBQcmV2YWxlbmNlIiA9ICJzdGEuY3BlIiwKICAgICAgICAgICJGZWF0dXJlIFNlbGVjdGlvbiBEZXBlbmRlbmNlIiA9ICJmc2QiLAogICAgICAgICAgIlN0YWJpbGl0eSBvZiBGZWF0dXJlIFNlbGVjdGlvbiBEZXBlbmRlbmNlIiA9ICJzdGEuZnNkIiwKICAgICAgICAgICJJbmNyZWFzZSBpbiBQcmVjaXNpb24iID0gIm1pcCIsCiAgICAgICAgICAiU3RhYmlsaXR5IG9mIEluY3JlYXNlIGluIFByZWNpc2lvbiIgPSAic3RhLm1pcCIsCiAgICAgICAgICAiU3RhYmlsaXR5IiA9ICJzdGFiaWxpdHkiLAogICAgICAgICAgImxvLXNpUkYgTWVhbiBQZXJtdXRhdGlvbiBwLXZhbHVlIiA9ICJwdmFsX3N0ciIKICAgICAgICApICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoSW50ZXJhY3Rpb24gPSBzdHlsZV9uYW1lc19iYXNpYyhJbnRlcmFjdGlvbikpCiAgICAgIHRhYiA8LSBwcmV0dHlfRFQodGFiX291dCwKICAgICAgICBkaWdpdHMgPSAzLCBzaWdmaWcgPSBUUlVFLCByb3duYW1lcyA9IEZBTFNFLAogICAgICAgIG5hX2Rpc3AgPSAiLS0iCiAgICAgICkKICAgICAgIyBzYXZlUkRTKAogICAgICAjICAgdGFiLAogICAgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgICB0YWJfcmVzX2RpciwKICAgICAgIyAgICAgcGFzdGUwKAogICAgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICMgICAgICAgIl9pcmZfaW50ZXJhY3Rpb25fcmVzdWx0cy5yZHMiCiAgICAgICMgICAgICkKICAgICAgIyAgICkKICAgICAgIyApCgogICAgICAjIGlSRiByZXN1bHRzIC0gU05WIGxldmVsCiAgICAgIHRhYl9vdXQgPC0gaXJmX3Nudl9pbnRfb3V0ICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoaW50ID0gc3RyaW5ncjo6c3RyX3JlbW92ZV9hbGwoaW50LCAiWzAtOV0qY2giKSkgJT4lCiAgICAgICAgZHBseXI6OmFycmFuZ2UoLXN0YWJpbGl0eSkgJT4lCiAgICAgICAgZHBseXI6OnJlbmFtZSgKICAgICAgICAgICJJbnRlcmFjdGlvbiIgPSAiaW50IiwKICAgICAgICAgICJQcmV2YWxlbmNlIiA9ICJwcmV2YWxlbmNlIiwKICAgICAgICAgICJQcmVjaXNpb24iID0gInByZWNpc2lvbiIsCiAgICAgICAgICAiQ2xhc3MgRGlmZmVyZW5jZSBpbiBQcmV2YWxlbmNlIiA9ICJjcGUiLAogICAgICAgICAgIlN0YWJpbGl0eSBvZiBDbGFzcyBEaWZmZXJlbmNlIGluIFByZXZhbGVuY2UiID0gInN0YS5jcGUiLAogICAgICAgICAgIkZlYXR1cmUgU2VsZWN0aW9uIERlcGVuZGVuY2UiID0gImZzZCIsCiAgICAgICAgICAiU3RhYmlsaXR5IG9mIEZlYXR1cmUgU2VsZWN0aW9uIERlcGVuZGVuY2UiID0gInN0YS5mc2QiLAogICAgICAgICAgIkluY3JlYXNlIGluIFByZWNpc2lvbiIgPSAibWlwIiwKICAgICAgICAgICJTdGFiaWxpdHkgb2YgSW5jcmVhc2UgaW4gUHJlY2lzaW9uIiA9ICJzdGEubWlwIiwKICAgICAgICAgICJTdGFiaWxpdHkiID0gInN0YWJpbGl0eSIKICAgICAgICApICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBJbnRlcmFjdGlvbiA9IHN0eWxlX25hbWVzX2Jhc2ljKEludGVyYWN0aW9uLCBpdGFsaWMgPSBGQUxTRSkKICAgICAgICApCiAgICAgIHRhYiA8LSBwcmV0dHlfRFQodGFiX291dCwgZGlnaXRzID0gMywgc2lnZmlnID0gVFJVRSwgcm93bmFtZXMgPSBGQUxTRSkKICAgICAgIyBzYXZlUkRTKAogICAgICAjICAgdGFiLAogICAgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgICB0YWJfcmVzX2RpciwKICAgICAgIyAgICAgcGFzdGUwKAogICAgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICMgICAgICAgIl9pcmZfc252X2ludGVyYWN0aW9uX3Jlc3VsdHMucmRzIgogICAgICAjICAgICApCiAgICAgICMgICApCiAgICAgICMgKQoKICAgICAgIyBmb3IgKHR5cGUgaW4gbmFtZXMoaW50X2FsbF9vdXQpKSB7CiAgICAgICMgICBwcmludCh0eXBlKQogICAgICAjICAgIyBoZWF0bWFwCiAgICAgICMgICBwbHQgPC0gcGxvdF9oY2x1c3RfaGVhdG1hcChpbnRfYWxsX291dFtbdHlwZV1dJHN0YWJfdmFfbHNbW0lURVJdXSwKICAgICAgIyAgICAgeV9ncm91cHMgPSB5X3Rlc3QsCiAgICAgICMgICAgIGNsdXN0X3lfd2lfZ3JvdXAgPSBGQUxTRQogICAgICAjICAgKSArCiAgICAgICMgICAgIGxhYnMoCiAgICAgICMgICAgICAgeCA9ICJJbnRlcmFjdGlvbiIsIHkgPSAiUGF0aWVudHMiLAogICAgICAjICAgICAgIGZpbGwgPSAiTG9jYWxcblN0YWJpbGl0eVxuU2NvcmUiCiAgICAgICMgICAgICkgKwogICAgICAjICAgICB2dGhlbWVzOjp0aGVtZV92bW9kZXJuKHNpemVfcHJlc2V0ID0gIm1lZGl1bSIpICsKICAgICAgIyAgICAgdGhlbWUoCiAgICAgICMgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICMgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAjICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLjUpCiAgICAgICMgICAgICkKICAgICAgIyAgICMgc2F2ZVJEUygKICAgICAgIyAgICMgICBwbHQsCiAgICAgICMgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgIyAgICAgZmlnX3Jlc19kaXIsCiAgICAgICMgICAjICAgICBwYXN0ZTAoCiAgICAgICMgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICMgICAjICAgICAgICJfaW50X2xvY2FsX3N0YWJpbGl0eV9oZWF0bWFwXyIsIHR5cGUsICIucmRzIgogICAgICAjICAgIyAgICAgKQogICAgICAjICAgIyAgICkKICAgICAgIyAgICMgKQogICAgICAjIAogICAgICAjICAgIyBkaXN0cmlidXRpb24gcGxvdHMKICAgICAgIyAgIGludF9wdmFscyA8LSBtYXBfZGZyKGludF9hbGxfb3V0W1t0eXBlXV0kcGVybV9vdXRfbHNbW0lURVJdXSwKICAgICAgIyAgICAgfiBkYXRhLmZyYW1lKHB2YWwgPSAueCRwdmFsKSwKICAgICAgIyAgICAgLmlkID0gImludCIKICAgICAgIyAgICkgJT4lCiAgICAgICMgICAgIGFycmFuZ2UocHZhbCkgJT4lCiAgICAgICMgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICMgICAgICAgcHZhbF9zdHIgPSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICAjICAgICAgICAgcHZhbCA8IDFlLTQgfiAicCA8IDEwXi00IiwKICAgICAgIyAgICAgICAgIHB2YWwgPCAxZS0zIH4gInAgPCAxMF4tMyIsCiAgICAgICMgICAgICAgICAjIHB2YWwgPCAxZS00IH4gInAgPCAxMDxzdXA+LTQ8L3N1cD4iLAogICAgICAjICAgICAgICAgIyBwdmFsIDwgMWUtMyB+ICJwIDwgMTA8c3VwPi0zPC9zdXA+IiwKICAgICAgIyAgICAgICAgIFRSVUUgfiBzcHJpbnRmKCJwfmA9YH4lcyIsIGZvcm1hdEMocHZhbCwgZGlnaXRzID0gMywgZm9ybWF0ID0gImYiKSkKICAgICAgIyAgICAgICApCiAgICAgICMgICAgICkgJT4lCiAgICAgICMgICAgIG11dGF0ZShpbnRfcHZhbCA9IHNwcmludGYoIiVzICglcykiLCBpbnQsIHB2YWxfc3RyKSkKICAgICAgIyAgIHBsdF9kZiA8LSBpbnRfYWxsX291dFtbdHlwZV1dJHN0YWJfdmFfbHNbW0lURVJdXSAlPiUKICAgICAgIyAgICAgYmluZF9jb2xzKHkgPSB5X3Rlc3QpICU+JQogICAgICAjICAgICBnYXRoZXIoa2V5ID0gImludCIsIHZhbHVlID0gIlN0YWJpbGl0eSIsIC15KSAlPiUKICAgICAgIyAgICAgbGVmdF9qb2luKHkgPSBpbnRfcHZhbHMsIGJ5ID0gImludCIpICU+JQogICAgICAjICAgICAjIG11dGF0ZShpbnQgPSBwYXN0ZTAoaW50LCAiIChwID0gIiwgZm9ybWF0QyhwdmFsLCAzLCBmb3JtYXQgPSAiZyIpLCAiKSIpKSAlPiUKICAgICAgIyAgICAgbXV0YXRlKGludCA9IGZhY3RvcihpbnQsIGxldmVscyA9IGludF9wdmFscyRpbnQpKQogICAgICAjICAgcGx0IDwtIHBsb3RfZGVuc2l0eShkYXRhID0gcGx0X2RmLCB4X3N0ciA9ICJTdGFiaWxpdHkiLCBmaWxsX3N0ciA9ICJ5IikgKwogICAgICAjICAgICBmYWNldF93cmFwKH5pbnQsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDMpICsKICAgICAgIyAgICAgZ2dwbG90Mjo6bGFicyh4ID0gIkxvY2FsIFN0YWJpbGl0eSBJbXBvcnRhbmNlIFNjb3JlIiwgZmlsbCA9ICIiKSArCiAgICAgICMgICAgIGdncGxvdDI6Omdlb21fdGV4dCgKICAgICAgIyAgICAgICBnZ3Bsb3QyOjphZXMoeCA9IEluZiwgeSA9IEluZiwgaGp1c3QgPSAxLjEsIHZqdXN0ID0gMS41LCBsYWJlbCA9IHB2YWxfc3RyKSwKICAgICAgIyAgICAgICBkYXRhID0gcGx0X2RmICU+JSBkcGx5cjo6ZGlzdGluY3QoaW50LCAua2VlcF9hbGwgPSBUUlVFKSwKICAgICAgIyAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgIyAgICAgKSArCiAgICAgICMgICAgIGdncGxvdDI6OnRoZW1lKGF4aXMudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkKICAgICAgIyAgICMgc2F2ZVJEUygKICAgICAgIyAgICMgICBwbHQsCiAgICAgICMgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgIyAgICAgZmlnX3Jlc19kaXIsCiAgICAgICMgICAjICAgICBwYXN0ZTAoCiAgICAgICMgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICMgICAjICAgICAgICJfaW50X2xvY2FsX3N0YWJpbGl0eV9kaXN0XyIsIHR5cGUsICIucmRzIgogICAgICAjICAgIyAgICAgKQogICAgICAjICAgIyAgICkKICAgICAgIyAgICMgKQogICAgICAjIAogICAgICAjICAgIyBpbmRpdmlkdWFsIHNucCBwbG90cwogICAgICAjICAgcGx0IDwtIHBsb3RSRlNucEludERpc3QoCiAgICAgICMgICAgIGlyZl9nZW5lX291dCRyZi5saXN0W1tJVEVSXV0sIHNucHMuZGYsIGludF9wdmFscyRpbnQsCiAgICAgICMgICAgIHByb3AgPSBUUlVFCiAgICAgICMgICApICsKICAgICAgIyAgICAgZ2dwbG90Mjo6bGFicyh4ID0gIlNOVi1TTlYgUGFpciIpCiAgICAgICMgICAjIHNhdmVSRFMoCiAgICAgICMgICAjICAgcGx0LAogICAgICAjICAgIyAgIGZpbGUucGF0aCgKICAgICAgIyAgICMgICAgIGZpZ19yZXNfZGlyLAogICAgICAjICAgIyAgICAgcGFzdGUwKAogICAgICAjICAgIyAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAjICAgIyAgICAgICAiX2ludF9sb2NhbF9zdGFiaWxpdHlfc25wX2Rpc3RfIiwgdHlwZSwgIi5yZHMiCiAgICAgICMgICAjICAgICApCiAgICAgICMgICAjICAgKQogICAgICAjICAgIyApCiAgICAgICMgfQoKICAgICAgIyBsb2NhbCBmZWF0dXJlIHN0YWJpbGl0eSByZXN1bHRzCiAgICAgIGxvYWQoZmlsZS5wYXRoKGZwYXRoLCAibG9jYWxfZmVhdHVyZV9zdGFiaWxpdHlfcmVzdWx0cy5SZGF0YSIpKQogICAgICBzdGFiX291dCA8LSBsaXN0KAogICAgICAgIHN0YWJfdHIyX2xzID0gc3RhYl90cjJfbHMsCiAgICAgICAgc3RhYl92YV9scyA9IHN0YWJfdmFfbHMsCiAgICAgICAgdGVzdF9nZW5lc19scyA9IHRlc3RfZ2VuZXNfbHMsCiAgICAgICAgcGVybV9vdXRfbHMgPSBwZXJtX291dF9scwogICAgICApCiAgICAgIGdlbmVfcmVzdWx0c19sc1tbYXMuY2hhcmFjdGVyKHRocildXSA8LSBwZXJtX291dF9scwoKICAgICAgc3RhYl9hbGxfb3V0IDwtIGxpc3QoYFVzaW5nIGFsbCBzcGxpdHNgID0gc3RhYl9vdXQpCgogICAgICAjIGZvciAodHlwZSBpbiBuYW1lcyhpbnRfYWxsX291dCkpIHsKICAgICAgIyAgIHByaW50KHR5cGUpCiAgICAgICMgICBzdGFiX2RmIDwtIHN0YWJfYWxsX291dFtbdHlwZV1dJHN0YWJfdmFfbHNbW0lURVJdXSAlPiUKICAgICAgIyAgICAgc2VsZWN0KGFsbF9vZihzdGFiX2FsbF9vdXRbW3R5cGVdXSR0ZXN0X2dlbmVzX2xzW1tJVEVSXV0pKQogICAgICAjIAogICAgICAjICAgIyBoZWF0bWFwCiAgICAgICMgICBwbHQgPC0gcGxvdF9oY2x1c3RfaGVhdG1hcChzdGFiX2RmLAogICAgICAjICAgICB5X2dyb3VwcyA9IHlfdGVzdCwKICAgICAgIyAgICAgY2x1c3RfeV93aV9ncm91cCA9IEZBTFNFCiAgICAgICMgICApICsKICAgICAgIyAgICAgbGFicygKICAgICAgIyAgICAgICB4ID0gIkZlYXR1cmUiLCB5ID0gIlBhdGllbnRzIiwKICAgICAgIyAgICAgICBmaWxsID0gIkxvY2FsXG5TdGFiaWxpdHlcblNjb3JlIgogICAgICAjICAgICApICsKICAgICAgIyAgICAgdnRoZW1lczo6dGhlbWVfdm1vZGVybihzaXplX3ByZXNldCA9ICJtZWRpdW0iKSArCiAgICAgICMgICAgIHRoZW1lKAogICAgICAjICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAjICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgIyAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEsIHZqdXN0ID0gMC41KQogICAgICAjICAgICApCiAgICAgICMgICAjIHNhdmVSRFMoCiAgICAgICMgICAjICAgcGx0LAogICAgICAjICAgIyAgIGZpbGUucGF0aCgKICAgICAgIyAgICMgICAgIGZpZ19yZXNfZGlyLAogICAgICAjICAgIyAgICAgcGFzdGUwKAogICAgICAjICAgIyAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAjICAgIyAgICAgICAiX2xvY2FsX3N0YWJpbGl0eV9oZWF0bWFwXyIsIHR5cGUsICIucmRzIgogICAgICAjICAgIyAgICAgKQogICAgICAjICAgIyAgICkKICAgICAgIyAgICMgKQogICAgICAjIAogICAgICAjICAgIyBkaXN0cmlidXRpb24gcGxvdHMKICAgICAgIyAgIGZ0X3B2YWxzIDwtIG1hcF9kZnIoc3RhYl9hbGxfb3V0W1t0eXBlXV0kcGVybV9vdXRfbHNbW0lURVJdXSwKICAgICAgIyAgICAgfiBkYXRhLmZyYW1lKHB2YWwgPSAueCRwdmFsKSwKICAgICAgIyAgICAgLmlkID0gImZlYXR1cmUiCiAgICAgICMgICApICU+JQogICAgICAjICAgICBhcnJhbmdlKHB2YWwpICU+JQogICAgICAjICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAjICAgICAgIHB2YWxfc3RyID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgIyAgICAgICAgIHB2YWwgPCAxZS00IH4gInAgPCAxMF4tNCIsCiAgICAgICMgICAgICAgICBwdmFsIDwgMWUtMyB+ICJwIDwgMTBeLTMiLAogICAgICAjICAgICAgICAgIyBwdmFsIDwgMWUtNCB+ICJwIDwgMTA8c3VwPi00PC9zdXA+IiwKICAgICAgIyAgICAgICAgICMgcHZhbCA8IDFlLTMgfiAicCA8IDEwPHN1cD4tMzwvc3VwPiIsCiAgICAgICMgICAgICAgICBUUlVFIH4gc3ByaW50ZigicH5gPWB+JXMiLCBmb3JtYXRDKHB2YWwsIGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJmIikpCiAgICAgICMgICAgICAgKQogICAgICAjICAgICApICU+JQogICAgICAjICAgICBtdXRhdGUoZnRfcHZhbCA9IHBhc3RlMChmZWF0dXJlLCAiIChwID0gIiwgZm9ybWF0QyhwdmFsLCAzLCBmb3JtYXQgPSAiZyIpLCAiKSIpKQogICAgICAjICAgcGx0X2RmIDwtIHN0YWJfZGYgJT4lCiAgICAgICMgICAgIGJpbmRfY29scyh5ID0geV90ZXN0KSAlPiUKICAgICAgIyAgICAgZ2F0aGVyKGtleSA9ICJmZWF0dXJlIiwgdmFsdWUgPSAiU3RhYmlsaXR5IiwgLXkpICU+JQogICAgICAjICAgICBsZWZ0X2pvaW4oeSA9IGZ0X3B2YWxzLCBieSA9ICJmZWF0dXJlIikgJT4lCiAgICAgICMgICAgICMgbXV0YXRlKGZlYXR1cmUgPSBwYXN0ZTAoZmVhdHVyZSwgIiAocCA9ICIsIGZvcm1hdEMocHZhbCwgMywgZm9ybWF0ID0gImciKSwgIikiKSkgJT4lCiAgICAgICMgICAgIG11dGF0ZShmZWF0dXJlID0gZmFjdG9yKGZlYXR1cmUsIGxldmVscyA9IGZ0X3B2YWxzJGZlYXR1cmUpKQogICAgICAjICAgcGx0IDwtIHBsb3RfZGVuc2l0eShkYXRhID0gcGx0X2RmLCB4X3N0ciA9ICJTdGFiaWxpdHkiLCBmaWxsX3N0ciA9ICJ5IikgKwogICAgICAjICAgICBmYWNldF93cmFwKH5mZWF0dXJlLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSA0KSArCiAgICAgICMgICAgIGdncGxvdDI6OmxhYnMoeCA9ICJMb2NhbCBTdGFiaWxpdHkgSW1wb3J0YW5jZSBTY29yZSIsIGZpbGwgPSAiIikgKwogICAgICAjICAgICBnZ3Bsb3QyOjpnZW9tX3RleHQoCiAgICAgICMgICAgICAgZ2dwbG90Mjo6YWVzKHggPSBJbmYsIHkgPSBJbmYsIGhqdXN0ID0gMS4xLCB2anVzdCA9IDEuNSwgbGFiZWwgPSBwdmFsX3N0ciksCiAgICAgICMgICAgICAgZGF0YSA9IHBsdF9kZiAlPiUgZHBseXI6OmRpc3RpbmN0KGZlYXR1cmUsIC5rZWVwX2FsbCA9IFRSVUUpLAogICAgICAjICAgICAgIHBhcnNlID0gVFJVRQogICAgICAjICAgICApICsKICAgICAgIyAgICAgZ2dwbG90Mjo6dGhlbWUoYXhpcy50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTQpKQogICAgICAjICAgIyBzYXZlUkRTKAogICAgICAjICAgIyAgIHBsdCwKICAgICAgIyAgICMgICBmaWxlLnBhdGgoCiAgICAgICMgICAjICAgICBmaWdfcmVzX2RpciwKICAgICAgIyAgICMgICAgIHBhc3RlMCgKICAgICAgIyAgICMgICAgICAgcGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgIyAgICMgICAgICAgIl9sb2NhbF9zdGFiaWxpdHlfZGlzdF8iLCB0eXBlLCAiLnJkcyIKICAgICAgIyAgICMgICAgICkKICAgICAgIyAgICMgICApCiAgICAgICMgICAjICkKICAgICAgIyAKICAgICAgIyAgICMgaW5kaXZpZHVhbCBzbnAgcGxvdHMKICAgICAgIyAgIHBsdCA8LSBwbG90UkZTbnBEaXN0KAogICAgICAjICAgICBpcmZfZ2VuZV9vdXQkcmYubGlzdFtbSVRFUl1dLCBzbnBzLmRmLCBmdF9wdmFscyRmZWF0dXJlLAogICAgICAjICAgICBwcm9wID0gVFJVRQogICAgICAjICAgKSArCiAgICAgICMgICAgIGdncGxvdDI6OmxhYnMoeCA9ICJTTlYgKE9yZGVyZWQgYnkgUG9zaXRpb24pIikKICAgICAgIyAgICMgc2F2ZVJEUygKICAgICAgIyAgICMgICBwbHQsCiAgICAgICMgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgIyAgICAgZmlnX3Jlc19kaXIsCiAgICAgICMgICAjICAgICBwYXN0ZTAoCiAgICAgICMgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICMgICAjICAgICAgICJfbG9jYWxfc3RhYmlsaXR5X3NucF9kaXN0XyIsIHR5cGUsICIucmRzIgogICAgICAjICAgIyAgICAgKQogICAgICAjICAgIyAgICkKICAgICAgIyAgICMgKQogICAgICAjIH0KICAgIH0KCiAgICB0YWIgPC0gZHBseXI6OmJpbmRfcm93cyhldmFsX2xzLCAuaWQgPSAiQmluYXJpemF0aW9uIFRocmVzaG9sZCIpICU+JQogICAgICBkcGx5cjo6cmVuYW1lKCJBY2N1cmFjeSIgPSAiQ2xhc3MiLCAiQVVST0MiID0gIkFVQyIsICJBVVBSQyIgPSAiUFIiKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChgQmluYXJpemF0aW9uIFRocmVzaG9sZGAsIEFjY3VyYWN5LCBBVVJPQywgQVVQUkMpICU+JQogICAgICBwcmV0dHlfRFQoCiAgICAgICAgZGlnaXRzID0gMywgc2lnZmlnID0gRkFMU0UsIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gInQiLCBvcmRlcmluZyA9IEZBTFNFKQogICAgICApCiAgICAjIHNhdmVSRFMoCiAgICAjICAgdGFiLAogICAgIyAgIGZpbGUucGF0aCgKICAgICMgICAgIHRhYl9yZXNfZGlyLAogICAgIyAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9pcmZfcHJlZGljdGlvbl9yZXN1bHRzLnJkcyIpCiAgICAjICAgKQogICAgIyApCiAgICAKICAgIGdlbmVfcmVzdWx0c19kZiA8LSBwdXJycjo6bWFwX2RmcigKICAgICAgZ2VuZV9yZXN1bHRzX2xzLAogICAgICBmdW5jdGlvbihnZW5lX3Jlc3VsdHMpIHsKICAgICAgICBwdXJycjo6bWFwX2RmcigKICAgICAgICAgIGdlbmVfcmVzdWx0c1tbSVRFUl1dLAogICAgICAgICAgfiBkYXRhLmZyYW1lKAogICAgICAgICAgICBgU0RgID0gc2QoLngkcGVybV9kaXN0KSwKICAgICAgICAgICAgcCA9IC54JHB2YWwsCiAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRkFMU0UKICAgICAgICAgICksCiAgICAgICAgICAuaWQgPSAiTG9jdXMgLyBJbnRlcmFjdGlvbiIKICAgICAgICApCiAgICAgIH0sCiAgICAgIC5pZCA9ICJCaW5hcml6YXRpb24gVGhyZXNob2xkIgogICAgKQoKICAgICMgZ2V0IHN1bW1hcnkgcmVzdWx0cyB0YWJsZSAod2l0aG91dCBzdHlsaW5nIGZvciBEVCkKICAgIGludF9yZXN1bHRzX2RmIDwtIHB1cnJyOjptYXBfZGZyKAogICAgICBpbnRfcmVzdWx0c19scywKICAgICAgZnVuY3Rpb24oaW50X3Jlc3VsdHMpIHsKICAgICAgICBwdXJycjo6bWFwX2RmcigKICAgICAgICAgIGludF9yZXN1bHRzW1tJVEVSXV0sCiAgICAgICAgICB+IGRhdGEuZnJhbWUoCiAgICAgICAgICAgIGBTRGAgPSBzZCgueCRwZXJtX2Rpc3QpLAogICAgICAgICAgICBwID0gLngkcHZhbCwKICAgICAgICAgICAgY2hlY2submFtZXMgPSBGQUxTRQogICAgICAgICAgKSwKICAgICAgICAgIC5pZCA9ICJMb2N1cyAvIEludGVyYWN0aW9uIgogICAgICAgICkKICAgICAgfSwKICAgICAgLmlkID0gIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQiCiAgICApCiAgICBmZWF0dXJlX29yZGVyIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZ2VuZV9yZXN1bHRzX2RmLCBpbnRfcmVzdWx0c19kZikgJT4lCiAgICAgIGRwbHlyOjpncm91cF9ieShgTG9jdXMgLyBJbnRlcmFjdGlvbmApICU+JQogICAgICBkcGx5cjo6c3VtbWFyaXNlKAogICAgICAgIG4gPSBkcGx5cjo6bigpLAogICAgICAgIG1lYW4gPSBtZWFuKHApCiAgICAgICkgJT4lCiAgICAgIGRwbHlyOjphcnJhbmdlKC1uLCBtZWFuKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChgTG9jdXMgLyBJbnRlcmFjdGlvbmApCiAgICByZXN1bHRzX2RmIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZ2VuZV9yZXN1bHRzX2RmLCBpbnRfcmVzdWx0c19kZikgJT4lCiAgICAgIHRpZHlyOjpwaXZvdF93aWRlcigKICAgICAgICBpZF9jb2xzID0gYExvY3VzIC8gSW50ZXJhY3Rpb25gLAogICAgICAgIG5hbWVzX2Zyb20gPSBgQmluYXJpemF0aW9uIFRocmVzaG9sZGAsCiAgICAgICAgdmFsdWVzX2Zyb20gPSBwLAogICAgICAgIG5hbWVzX3ZhcnkgPSAic2xvd2VzdCIKICAgICAgKSAlPiUKICAgICAgZHBseXI6OmxlZnRfam9pbih4ID0gZmVhdHVyZV9vcmRlciwgeSA9IC4sIGJ5ID0gIkxvY3VzIC8gSW50ZXJhY3Rpb24iKQogICAgIyBzYXZlUkRTKAogICAgIyAgIHJlc3VsdHNfZGYsCiAgICAjICAgZmlsZS5wYXRoKAogICAgIyAgICAgdGFiX3Jlc19kaXIsCiAgICAjICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2lyZl9wdmFsdWVzX3N1bW1hcnlfdGFibGUucmRzIikKICAgICMgICApCiAgICAjICkKICAgICMgd3JpdGUuY3N2KAogICAgIyAgIHJlc3VsdHNfZGYsCiAgICAjICAgZmlsZS5wYXRoKAogICAgIyAgICAgdGFiX3Jlc19kaXIsCiAgICAjICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2lyZl9wdmFsdWVzX3N1bW1hcnlfdGFibGUuY3N2IikKICAgICMgICApCiAgICAjICkKCiAgICBnZW5lX3Jlc3VsdHNfZGYgPC0gcHVycnI6Om1hcF9kZnIoCiAgICAgIGdlbmVfcmVzdWx0c19scywKICAgICAgZnVuY3Rpb24oZ2VuZV9yZXN1bHRzKSB7CiAgICAgICAgcHVycnI6Om1hcF9kZnIoCiAgICAgICAgICBnZW5lX3Jlc3VsdHNbW0lURVJdXSwKICAgICAgICAgIH4gZGF0YS5mcmFtZSgKICAgICAgICAgICAgYE1lYW4gRGlmZmVyZW5jZSAoSGlnaCAtIExvdylgID0gZm9ybWF0QygueCRUX29icywgZGlnaXRzID0gMiwgZm9ybWF0ID0gImciKSwKICAgICAgICAgICAgYFNEYCA9IGZvcm1hdEMoc2QoLngkcGVybV9kaXN0KSwgZGlnaXRzID0gMiwgZm9ybWF0ID0gImciKSwKICAgICAgICAgICAgYHAtdmFsdWVgID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICAgICAgICAueCRwdmFsIDwgMWUtNCB+ICI8IDEwPHN1cD4tNDwvc3VwPiIsCiAgICAgICAgICAgICAgLngkcHZhbCA8IDFlLTMgfiAiPCAxMDxzdXA+LTM8L3N1cD4iLAogICAgICAgICAgICAgIFRSVUUgfiBmb3JtYXRDKC54JHB2YWwsIGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJmIikKICAgICAgICAgICAgKSwKICAgICAgICAgICAgcCA9IC54JHB2YWwsCiAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRkFMU0UKICAgICAgICAgICksCiAgICAgICAgICAuaWQgPSAiTG9jdXMgLyBJbnRlcmFjdGlvbiIKICAgICAgICApCiAgICAgIH0sCiAgICAgIC5pZCA9ICJCaW5hcml6YXRpb24gVGhyZXNob2xkIgogICAgKQoKICAgIGludF9yZXN1bHRzX2RmIDwtIHB1cnJyOjptYXBfZGZyKAogICAgICBpbnRfcmVzdWx0c19scywKICAgICAgZnVuY3Rpb24oaW50X3Jlc3VsdHMpIHsKICAgICAgICBwdXJycjo6bWFwX2RmcigKICAgICAgICAgIGludF9yZXN1bHRzW1tJVEVSXV0sCiAgICAgICAgICB+IGRhdGEuZnJhbWUoCiAgICAgICAgICAgIGBNZWFuIERpZmZlcmVuY2UgKEhpZ2ggLSBMb3cpYCA9IGZvcm1hdEMoLngkVF9vYnMsIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJnIiksCiAgICAgICAgICAgIGBTRGAgPSBmb3JtYXRDKHNkKC54JHBlcm1fZGlzdCksIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJnIiksCiAgICAgICAgICAgIGBwLXZhbHVlYCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgLngkcHZhbCA8IDFlLTQgfiAiPCAxMDxzdXA+LTQ8L3N1cD4iLAogICAgICAgICAgICAgIC54JHB2YWwgPCAxZS0zIH4gIjwgMTA8c3VwPi0zPC9zdXA+IiwKICAgICAgICAgICAgICBUUlVFIH4gZm9ybWF0QygueCRwdmFsLCBkaWdpdHMgPSAzLCBmb3JtYXQgPSAiZiIpCiAgICAgICAgICAgICksCiAgICAgICAgICAgIHAgPSAueCRwdmFsLAogICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFCiAgICAgICAgICApLAogICAgICAgICAgLmlkID0gIkxvY3VzIC8gSW50ZXJhY3Rpb24iCiAgICAgICAgKQogICAgICB9LAogICAgICAuaWQgPSAiQmluYXJpemF0aW9uIFRocmVzaG9sZCIKICAgICkKCiAgICBzdHlsZV9uYW1lcyA8LSBmdW5jdGlvbih4KSB7CiAgICAgIGNvbG9yX3ZlYyA8LSBzdHJpbmdyOjpzdHJfZGV0ZWN0KHgsICJfIikKICAgICAgeCA8LSB4ICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLV8iLCAiPHN1cD4mIzgyMTE7PC9zdXA+JiM4MjExOyIpICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLSQiLCAiPHN1cD4mIzgyMTE7PC9zdXA+IikgJT4lCiAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCJcXCsiLCAiPHN1cD4rPC9zdXA+IikKICAgICAgeCA8LSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICAgIGNvbG9yX3ZlYyB+IGthYmxlRXh0cmE6OmNlbGxfc3BlYygKICAgICAgICAgIHgsCiAgICAgICAgICBjb2xvciA9ICJjb3JuZmxvd2VyYmx1ZSIsIGVzY2FwZSA9IEZBTFNFLCBpdGFsaWMgPSBUUlVFCiAgICAgICAgKSwKICAgICAgICBUUlVFIH4ga2FibGVFeHRyYTo6Y2VsbF9zcGVjKHgsIGVzY2FwZSA9IEZBTFNFLCBpdGFsaWMgPSBUUlVFKQogICAgICApCiAgICAgIHJldHVybih4KQogICAgfQoKICAgIGZlYXR1cmVfb3JkZXIgPC0gZHBseXI6OmJpbmRfcm93cyhnZW5lX3Jlc3VsdHNfZGYsIGludF9yZXN1bHRzX2RmKSAlPiUKICAgICAgZHBseXI6Omdyb3VwX2J5KGBMb2N1cyAvIEludGVyYWN0aW9uYCkgJT4lCiAgICAgIGRwbHlyOjpzdW1tYXJpc2UoCiAgICAgICAgbiA9IGRwbHlyOjpuKCksCiAgICAgICAgbWVhbiA9IG1lYW4ocCkKICAgICAgKSAlPiUKICAgICAgZHBseXI6OmFycmFuZ2UoLW4sIG1lYW4pICU+JQogICAgICBkcGx5cjo6c2VsZWN0KGBMb2N1cyAvIEludGVyYWN0aW9uYCkKCiAgICBjb2xvcl92ZWMgPC0gc3RyaW5ncjo6c3RyX2RldGVjdChmZWF0dXJlX29yZGVyJGBMb2N1cyAvIEludGVyYWN0aW9uYCwgIl8iKQoKICAgIHJlc3VsdHNfZGYgPC0gZHBseXI6OmJpbmRfcm93cyhnZW5lX3Jlc3VsdHNfZGYsIGludF9yZXN1bHRzX2RmKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICBgRGlmZmVyZW5jZSBpbiBMb2NhbCBGZWF0dXJlIFN0YWJpbGl0eSAoSGlnaCAtIExvdylgID0gc3ByaW50ZigiJXMgKCVzKSIsIGBNZWFuIERpZmZlcmVuY2UgKEhpZ2ggLSBMb3cpYCwgU0QpCiAgICAgICkgJT4lCiAgICAgIHRpZHlyOjpwaXZvdF93aWRlcigKICAgICAgICBpZF9jb2xzID0gYExvY3VzIC8gSW50ZXJhY3Rpb25gLAogICAgICAgIG5hbWVzX2Zyb20gPSBgQmluYXJpemF0aW9uIFRocmVzaG9sZGAsCiAgICAgICAgdmFsdWVzX2Zyb20gPSBjKGBEaWZmZXJlbmNlIGluIExvY2FsIEZlYXR1cmUgU3RhYmlsaXR5IChIaWdoIC0gTG93KWAsIGBwLXZhbHVlYCksCiAgICAgICAgbmFtZXNfdmFyeSA9ICJzbG93ZXN0IgogICAgICApICU+JQogICAgICBkcGx5cjo6bGVmdF9qb2luKHggPSBmZWF0dXJlX29yZGVyLCB5ID0gLiwgYnkgPSAiTG9jdXMgLyBJbnRlcmFjdGlvbiIpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgIGBMb2N1cyAvIEludGVyYWN0aW9uYCA9IHN0eWxlX25hbWVzKGBMb2N1cyAvIEludGVyYWN0aW9uYCkKICAgICAgKQogICAgcmVzdWx0c190YWIgPC0gcHJldHR5X0RUKAogICAgICByZXN1bHRzX2RmLAogICAgICBuYV9kaXNwID0gIi0tIiwgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgZ3JvdXBlZF9oZWFkZXIgPSBjKAogICAgICAgICIgIiA9IDEsICJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gMC4xNSIgPSAyLAogICAgICAgICJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gMC4yMCIgPSAyLAogICAgICAgICJCaW5hcml6YXRpb24gVGhyZXNob2xkID0gMC4yNSIgPSAyCiAgICAgICksCiAgICAgIGdyb3VwZWRfc3ViaGVhZGVyID0gc3RyaW5ncjo6c3RyX3JlbW92ZShjb2xuYW1lcyhyZXN1bHRzX2RmKSwgIlxcX1suMC05XSsiKQogICAgKQogICAgIyBzYXZlUkRTKAogICAgIyAgIHJlc3VsdHNfdGFiLAogICAgIyAgIGZpbGUucGF0aCgKICAgICMgICAgIHRhYl9yZXNfZGlyLAogICAgIyAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9pcmZfcHZhbHVlc19zdW1tYXJ5LnJkcyIpCiAgICAjICAgKQogICAgIyApCiAgfQp9IGVsc2UgewogIG1ldGhvZF90eXBlcyA8LSBjKCJVc2luZyBhbGwgc3BsaXRzIikKICB0aHJzIDwtIGMoMC4xNSwgMC4yLCAwLjI1KQogIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXMpIHsKICAgIHBoZW5vdHlwZV9uYW1lIDwtIG5hbWVzKHBoZW5vdHlwZXMpW3BoZW5vdHlwZXMgPT0gcGhlbm90eXBlXQogICAgIyBjYXQoc3ByaW50ZihwaGVub3R5cGVfaGVhZGVyLCBwaGVub3R5cGVfbmFtZSkpCgogICAgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJTdW1tYXJ5IikpCiAgICB0YWIgPC0gcmVhZFJEUyhmaWxlLnBhdGgoCiAgICAgIHRhYl9yZXNfZGlyLAogICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2lyZl9wcmVkaWN0aW9uX3Jlc3VsdHMucmRzIikKICAgICkpCiAgICBzdWJjaHVua2lmeSh0YWIsCiAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiB0aGUgdmFsaWRhdGlvbiBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIGZyb20gc2lSRiBhY3Jvc3MgdmFyaW91cyAlcyBiaW5hcml6YXRpb24gdGhyZXNob2xkcy4nIiwgcGhlbm90eXBlX25hbWUpCiAgICApCiAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgIHRhYiA8LSByZWFkUkRTKGZpbGUucGF0aCgKICAgICAgdGFiX3Jlc19kaXIsCiAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfaXJmX3B2YWx1ZXNfc3VtbWFyeS5yZHMiKQogICAgKSkKICAgIHRhYiR4JGNvbnRhaW5lciA8LSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoCiAgICAgIHRhYiR4JGNvbnRhaW5lciwgInAtdmFsdWUiLCAiTm9taW5hbCBwLXZhbHVlIgogICAgKQogICAgc3ViY2h1bmtpZnkodGFiLAogICAgICBpID0gY2h1bmtfaWR4LAogICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1N1bW1hcnkgb2YgdGhlIGxvLXNpUkYgcGVybXV0YXRpb24gdGVzdCByZXN1bHRzIGFjcm9zcyB2YXJpb3VzICVzIGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzIGluY2x1ZGluZyB0aGUgdGVzdCBzdGF0aXN0aWMgKGkuZS4sIGRpZmZlcmVuY2UgaW4gbG9jYWwgZmVhdHVyZSBzdGFiaWxpdHkgc2NvcmVzIGJldHdlZW4gdGhlIGhpZ2ggYW5kIHRoZSBsb3cgJXMgZ3JvdXBzIChTRCBpbiBwYXJlbnRoZXNlcykgYW5kIHRoZSByZXN1bHRpbmcgbm9taW5hbCBwLXZhbHVlcy4gQmxhbmsgY2VsbHMgaW5kaWNhdGUgdGhhdCB0aGUgbG9jdXMvaW50ZXJhY3Rpb24gd2FzIG5vdCBzZWxlY3RlZCBmb3IgdGVzdGluZyBmb3IgdGhlIGdpdmVuIGJpbmFyaXphdGlvbiB0aHJlc2hvbGQuIExvY2kvaW50ZXJhY3Rpb25zIGFyZSByYW5rZWQgYWNjb3JkaW5nIHRvIHRoZSBtZWFuIG5vbWluYWwgcC12YWx1ZSBhY3Jvc3MgYWxsIHRocmVlIGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzLiBJbnRlcmFjdGlvbnMgYmV0d2VlbiBnZW5ldGljIGxvY2kgYXJlIGhpZ2hsaWdodGVkIGluIGJsdWUuJyIsIHBoZW5vdHlwZV9uYW1lLCBwaGVub3R5cGVfbmFtZSkKICAgICkKICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogICAgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJzaVJGIEludGVyYWN0aW9uIFRhYmxlIikpCiAgICBmb3IgKHRociBpbiB0aHJzKSB7CiAgICAgIGNhdChzcHJpbnRmKHRocl9oZWFkZXIsIHRocikpCiAgICAgIHRhYiA8LSByZWFkUkRTKGZpbGUucGF0aCgKICAgICAgICB0YWJfcmVzX2RpciwKICAgICAgICBwYXN0ZTAoCiAgICAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICAgIl9pcmZfaW50ZXJhY3Rpb25fcmVzdWx0cy5yZHMiCiAgICAgICAgKQogICAgICApKQogICAgICB0YWIkeCRjb250YWluZXIgPC0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAogICAgICAgIHRhYiR4JGNvbnRhaW5lciwgCiAgICAgICAgImxvLXNpUkYgTWVhbiBQZXJtdXRhdGlvbiBwLXZhbHVlIiwKICAgICAgICAiTm9taW5hbCBsby1zaVJGIHAtdmFsdWUiCiAgICAgICkKICAgICAgc3ViY2h1bmtpZnkodGFiLAogICAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidTdW1tYXJ5IG9mIHRoZSBzaVJGIGxvY3VzLWxldmVsIGludGVyYWN0aW9uIHRhYmxlIG91dHB1dCBmb3IgdGhlIGJpbmFyaXplZCAlcyBwaGVub3R5cGUgKGJpbmFyaXphdGlvbiB0aHJlc2hvbGQgPSAlcykuIEZvciBhbGwgbWV0cmljcyBleGNsdWRpbmcgdGhlIG5vbWluYWwgbG8tc2lSRiBwLXZhbHVlLCBoaWdoZXIgdmFsdWVzIGluZGljYXRlIGEgc3Ryb25nZXIgaW50ZXJhY3Rpb24uIERldGFpbHMgcmVnYXJkaW5nIHRoZXNlIG1ldHJpY3MgaW4gdGhlIHNpUkYgaW50ZXJhY3Rpb24gdGFibGUgb3V0cHV0IGNhbiBiZSBmb3VuZCBpbiBLdW1iaWVyIGV0IGFsLiAoMjAxOCkuJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIpCiAgICAgICkKICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICAgY2F0KCJcblxuIikKCiAgICAgIHRhYiA8LSByZWFkUkRTKGZpbGUucGF0aCgKICAgICAgICB0YWJfcmVzX2RpciwKICAgICAgICBwYXN0ZTAoCiAgICAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICAgIl9pcmZfc252X2ludGVyYWN0aW9uX3Jlc3VsdHMucmRzIgogICAgICAgICkKICAgICAgKSkKICAgICAgc3ViY2h1bmtpZnkodGFiLAogICAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidTdW1tYXJ5IG9mIHRoZSBzaVJGIFNOVi1sZXZlbCBpbnRlcmFjdGlvbiB0YWJsZSBvdXRwdXQgZm9yIHRoZSBiaW5hcml6ZWQgJXMgcGhlbm90eXBlIChiaW5hcml6YXRpb24gdGhyZXNob2xkID0gJXMpLiBTdGFiaWxpdHkgc2NvcmVzIGZvciBhbGwgaW50ZXJhY3Rpb25zIGFyZSBjbG9zZSB0byAwLCBzdWdnZXN0aW5nIHVucmVsaWFibGUgU05WLWxldmVsIGludGVyYWN0aW9ucy4gRGV0YWlscyByZWdhcmRpbmcgdGhlc2UgbWV0cmljcyBpbiB0aGUgc2lSRiBpbnRlcmFjdGlvbiB0YWJsZSBvdXRwdXQgY2FuIGJlIGZvdW5kIGluIEt1bWJpZXIgZXQgYWwuICgyMDE4KS4nIiwgcGhlbm90eXBlX25hbWUsIHRocikKICAgICAgKQogICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICBjYXQoIlxuXG4iKQogICAgfQoKICAgIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiTG9jYWwgU3RhYmlsaXR5IEltcG9ydGFuY2UgUGxvdHMgLSBJbnRlcmFjdGlvbnMiKSkKICAgIGZvciAodGhyIGluIHRocnMpIHsKICAgICAgY2F0KHNwcmludGYodGhyX2hlYWRlciwgdGhyKSkKICAgICAgZm9yICh0eXBlIGluIG1ldGhvZF90eXBlcykgewogICAgICAgICMgZGlzdHJpYnV0aW9uIHBsb3RzCiAgICAgICAgcGx0IDwtIHJlYWRSRFMoCiAgICAgICAgICBmaWxlLnBhdGgoCiAgICAgICAgICAgIGZpZ19yZXNfZGlyLAogICAgICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAgICAgcGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAiX2ludF9sb2NhbF9zdGFiaWxpdHlfZGlzdF8iLCB0eXBlLCAiLnJkcyIKICAgICAgICAgICAgKQogICAgICAgICAgKQogICAgICAgICkKICAgICAgICBucm93cyA8LSBjZWlsaW5nKG5sZXZlbHMocGx0JGRhdGEkaW50KSAvIDMpCiAgICAgICAgc3ViY2h1bmtpZnkocGx0LAogICAgICAgICAgaSA9IGNodW5rX2lkeCwgZmlnX2hlaWdodCA9IERJU1RfSEVJR0hUIC8gNCAqIG5yb3dzLAogICAgICAgICAgYWRkX2NsYXNzID0gYygicGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiKSwKICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ0Rpc3RyaWJ1dGlvbiBvZiBsb2NhbCBzdGFiaWxpdHkgaW1wb3J0YW5jZSBzY29yZXMgYmV0d2VlbiB0aGUgaGlnaCBhbmQgbG93ICVzIGdyb3VwcyAoYmluYXJpemF0aW9uIHRocmVzaG9sZCA9ICVzKSBmb3IgZWFjaCBzaWduZWQgaW50ZXJhY3Rpb24gYmV0d2VlbiBsb2NpIChzcGVjaWZpZWQgYnkgc3VicGxvdCkgdGhhdCBwYXNzZWQgdGhlIHNpUkYgc3RhYmlsaXR5IGZpbHRlci4gVGhlIG5vbWluYWwgcC12YWx1ZSBmcm9tIHRoZSBwZXJtdXRhdGlvbiB0ZXN0LCBhc3Nlc3NpbmcgZGlzdHJpYnV0aW9uYWwgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgaGlnaCBhbmQgbG93ICVzIGdyb3VwcywgaXMgcHJvdmlkZWQgaW4gdGhlIHRvcCByaWdodCBjb3JuZXIgb2YgZWFjaCBzdWJwbG90LiciLCBwaGVub3R5cGVfbmFtZSwgdGhyLCBwaGVub3R5cGVfbmFtZSkKICAgICAgICApCiAgICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICAgICBjYXQoIlxuXG4iKQoKICAgICAgICAjIGluZGl2aWR1YWwgc25wIHBsb3RzCiAgICAgICAgcGx0IDwtIHJlYWRSRFMoCiAgICAgICAgICBmaWxlLnBhdGgoCiAgICAgICAgICAgIGZpZ19yZXNfZGlyLAogICAgICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAgICAgcGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAiX2ludF9sb2NhbF9zdGFiaWxpdHlfc25wX2Rpc3RfIiwgdHlwZSwgIi5yZHMiCiAgICAgICAgICAgICkKICAgICAgICAgICkKICAgICAgICApCiAgICAgICAgbnJvd3MgPC0gY2VpbGluZyhsZW5ndGgodW5pcXVlKHBsdCRkYXRhJEdlbmVzKSkgLyAzKQogICAgICAgIHN1YmNodW5raWZ5KGdncGxvdGx5KHBsdCksCiAgICAgICAgICBpID0gY2h1bmtfaWR4LCBmaWdfaGVpZ2h0ID0gRElTVF9IRUlHSFQgLyA0ICogbnJvd3MsCiAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCIpLAogICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInRnJlcXVlbmN5IG9mIG9jY3VycmVuY2Ugb2YgU05WLVNOViBjb21iaW5hdGlvbnMgaW4gdGhlIHNpUkYgZml0IGZvciB0aGUgYmluYXJpemVkICVzIHBoZW5vdHlwZSAoYmluYXJpemF0aW9uIHRocmVzaG9sZCA9ICVzKS4gU05WLVNOViBjb21iaW5hdGlvbnMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgaW4gdGhlIHNpUkYgZGVjaXNpb24gcGF0aHMgY29udHJpYnV0ZSB0aGUgbW9zdCB0byB0aGUgb3ZlcmFsbCBsb2N1cy1sZXZlbCBpbnRlcmFjdGlvbiBpbXBvcnRhbmNlIGluIHRoZSBzaVJGIGZpdC4nIiwgcGhlbm90eXBlX25hbWUsIHRocikKICAgICAgICApCiAgICAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICAgICBjYXQoIlxuXG4iKQoKICAgICAgICAjICMgaGVhdG1hcAogICAgICAgICMgcGx0IDwtIHJlYWRSRFMoCiAgICAgICAgIyAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwKICAgICAgICAjICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICMgICAgICAgICAgICAgICAgICAgICJfaW50X2xvY2FsX3N0YWJpbGl0eV9oZWF0bWFwXyIsIHR5cGUsICIucmRzIikpCiAgICAgICAgIyApCiAgICAgICAgIyBzdWJjaHVua2lmeShwbHQsIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBIRUFUTUFQX0hFSUdIVCwKICAgICAgICAjICAgICAgICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQiKSwKICAgICAgICAjICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIpCiAgICAgICAgIyBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICB9CiAgICB9CgogICAgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJMb2NhbCBTdGFiaWxpdHkgSW1wb3J0YW5jZSBQbG90cyAtIExvY2kiKSkKICAgIGZvciAodGhyIGluIHRocnMpIHsKICAgICAgY2F0KHNwcmludGYodGhyX2hlYWRlciwgdGhyKSkKICAgICAgZm9yICh0eXBlIGluIG1ldGhvZF90eXBlcykgewogICAgICAgICMgZGlzdHJpYnV0aW9uIHBsb3RzCiAgICAgICAgcGx0IDwtIHJlYWRSRFMoCiAgICAgICAgICBmaWxlLnBhdGgoCiAgICAgICAgICAgIGZpZ19yZXNfZGlyLAogICAgICAgICAgICBwYXN0ZTAoCiAgICAgICAgICAgICAgcGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAgICAgICAiX2xvY2FsX3N0YWJpbGl0eV9kaXN0XyIsIHR5cGUsICIucmRzIgogICAgICAgICAgICApCiAgICAgICAgICApCiAgICAgICAgKQogICAgICAgIG5yb3dzIDwtIGNlaWxpbmcobmxldmVscyhwbHQkZGF0YSRmZWF0dXJlKSAvIDQpCiAgICAgICAgc3ViY2h1bmtpZnkocGx0LAogICAgICAgICAgaSA9IGNodW5rX2lkeCwgZmlnX2hlaWdodCA9IERJU1RfSEVJR0hUIC8gNCAqIG5yb3dzLAogICAgICAgICAgYWRkX2NsYXNzID0gYygicGFuZWwgcGFuZWwtZGVmYXVsdCIpLAogICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInRGlzdHJpYnV0aW9uIG9mIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3JlcyBiZXR3ZWVuIHRoZSBoaWdoIGFuZCBsb3cgJXMgZ3JvdXBzIChiaW5hcml6YXRpb24gdGhyZXNob2xkID0gJXMpIGZvciBlYWNoIHNpZ25lZCBsb2N1cyAoc3BlY2lmaWVkIGJ5IHN1YnBsb3QpLiBIZXJlLCB3ZSBzaG93IG9ubHkgdGhlIHRvcCAyNSBzaWduZWQgbG9jaSwgcmFua2VkIGJ5IHRoZWlyIGF2ZXJhZ2UgbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2Ugc2NvcmVzLiBUaGUgbm9taW5hbCBwLXZhbHVlIGZyb20gdGhlIHBlcm11dGF0aW9uIHRlc3QsIGFzc2Vzc2luZyBkaXN0cmlidXRpb25hbCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBoaWdoIGFuZCBsb3cgJXMgZ3JvdXBzLCBpcyBwcm92aWRlZCBpbiB0aGUgdG9wIHJpZ2h0IGNvcm5lciBvZiBlYWNoIHN1YnBsb3QuJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIsIHBoZW5vdHlwZV9uYW1lKQogICAgICAgICkKICAgICAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICAgIGNhdCgiXG5cbiIpCgogICAgICAgICMgaW5kaXZpZHVhbCBzbnAgcGxvdHMKICAgICAgICBwbHQgPC0gcmVhZFJEUygKICAgICAgICAgIGZpbGUucGF0aCgKICAgICAgICAgICAgZmlnX3Jlc19kaXIsCiAgICAgICAgICAgIHBhc3RlMCgKICAgICAgICAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICAgICAgICJfbG9jYWxfc3RhYmlsaXR5X3NucF9kaXN0XyIsIHR5cGUsICIucmRzIgogICAgICAgICAgICApCiAgICAgICAgICApCiAgICAgICAgKQogICAgICAgIG5yb3dzIDwtIGNlaWxpbmcobGVuZ3RoKHVuaXF1ZShwbHQkZGF0YSRHZW5lKSkgLyAzKQogICAgICAgIHN1YmNodW5raWZ5KGdncGxvdGx5KHBsdCwgdG9vbHRpcCA9IGMoInkiLCAidGV4dCIpKSwKICAgICAgICAgIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBESVNUX0hFSUdIVCAvIDQgKiBucm93cywKICAgICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIiksCiAgICAgICAgICBvdGhlcl9hcmdzID0gIm91dC53aWR0aD0nMTAwJSciLAogICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidGcmVxdWVuY3kgb2Ygb2NjdXJyZW5jZSBvZiBTTlZzIGluIHRoZSBzaVJGIGZpdCBmb3IgdGhlIGJpbmFyaXplZCAlcyBwaGVub3R5cGUgKGJpbmFyaXphdGlvbiB0aHJlc2hvbGQgPSAlcykuIFNOVnMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgaW4gdGhlIHNpUkYgZGVjaXNpb24gcGF0aHMgY29udHJpYnV0ZSB0aGUgbW9zdCB0byB0aGUgb3ZlcmFsbCBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlIGluIHRoZSBzaVJGIGZpdC4gU05WcyBhcmUgb3JkZXJlZCBvbiB0aGUgeC1heGlzIGJ5IGdlbm9taWMgbG9jYXRpb24uJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIpCiAgICAgICAgKQogICAgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAgICAgY2F0KCJcblxuIikKCiAgICAgICAgIyAjIGhlYXRtYXAKICAgICAgICAjIHBsdCA8LSByZWFkUkRTKAogICAgICAgICMgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAgICAgIyAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAjICAgICAgICAgICAgICAgICAgICAiX2xvY2FsX3N0YWJpbGl0eV9oZWF0bWFwXyIsIHR5cGUsICIucmRzIikpCiAgICAgICAgIyApCiAgICAgICAgIyBzdWJjaHVua2lmeShwbHQsIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBIRUFUTUFQX0hFSUdIVCwKICAgICAgICAjICAgICAgICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQiKSwKICAgICAgICAjICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIpCiAgICAgICAgIyBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQogICAgICB9CiAgICB9CiAgfQp9CmBgYAoKCiMjIEFkdmFudGFnZXMgb2YgU2lnbmVkIEluZm9ybWF0aW9uIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpUaG91Z2ggdGhlIHNpZ25lZCBpbmZvcm1hdGlvbiBpcyBub3QgcGVydGluZW50IHRvIG91ciBnb2FsIG9mIHByaW9yaXRpemluZy9yZWNvbW1lbmRpbmcgY2FuZGlkYXRlIG1hcmtlcnMgZm9yIGV4cGVyaW1lbnRzLCB0aGUgc2lnbmVkIGluZm9ybWF0aW9uIGZyb20gc2lSRiBwcm92aWRlcyBtb3JlIGdyYW51bGFyIGluZm9ybWF0aW9uIHRoYXQgY2FuIGltcHJvdmUgb3VyIGludGVycHJldGF0aW9uIG9mIHRoZSBmaXQuIFRvIHNlZSB0aGlzLCBzdXBwb3NlIHRoYXQgd2UgZGlkIG5vdCBrZWVwIHRyYWNrIG9mIHRoZSBzaWduIG9mIHRoZSBmZWF0dXJlIHdoZW4gc3BsaXR0aW5nIChpLmUuLCB0aGF0IHdlIGRvIG5vdCBrZWVwIHRyYWNrIG9mIHdoZXRoZXIgd2Ugc3BsaXQgb24gbG93IG9yIGhpZ2ggdmFsdWVzIG9mIHRoZSBmZWF0dXJlKS4gU3VwcG9zZSBhbHNvIHRoYXQgd2Ugd291bGQgbGlrZSB0byBtZWFzdXJlIHRoZSBpbXBvcnRhbmNlIG9mIGZlYXR1cmUgJFhfMSQsIHdoaWNoIHdhcyB1c2VkIGFzIHRoZSBmaXJzdCAocm9vdCkgc3BsaXQgaW4gdHJlZSAkVCQuIEluIHRoZSBmaXJzdCBzdGVwIGluIG91ciBuZXcgaW1wb3J0YW5jZSBzY29yZSBjb21wdXRhdGlvbiwgd2UgY29tcHV0ZSB0aGUgbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2UgKExTSSkgc2NvcmUgb2YgJFhfMSQgZm9yIGVhY2ggaW5kaXZpZHVhbCAkaSQuIElmIHdlIGRvIG5vdCBrZWVwIHRyYWNrIG9mIHRoZSBzaWduIG9mIHRoZSAkWF8xJCBzcGxpdCwgdGhlbiAkWF8xJCBhcHBlYXJzIG9uIGV2ZXJ5IGluZGl2aWR1YWwncyBkZWNpc2lvbiBwYXRoIHNvIHRoYXQgJExTSV9UKFhfMSwgaSkgPSAxJCBmb3IgZXZlcnkgaW5kaXZpZHVhbCAkaSQuIEluIHRoZSBuZXh0IHN0ZXAgb2Ygb3VyIG5ldyBpbXBvcnRhbmNlIHNjb3JlIGNvbXB1dGF0aW9uLCB3ZSBwZXJmb3JtIGEgcGVybXV0YXRpb24gdGVzdCB0byBhc3Nlc3Mgd2hldGhlciB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gdGhlIExTSSBzY29yZXMgZm9yIGluZGl2aWR1YWxzIHdpdGggaGlnaCBMVk1pIGFuZCB0aG9zZSB3aXRoIGxvdyBMVk1pLiBTaW5jZSAkTFNJX1QoWF8xLCBpKSA9IDEkIGZvciBldmVyeSAkaSQsIHRoaXMgcGVybXV0YXRpb24gdGVzdCB3aWxsIHJldHVybiBhIG5vbWluYWwgcC12YWx1ZSBvZiAxLiBUaGlzIHN1Z2dlc3RzIHRoYXQgJFhfMSQgaXMgYW4gdW5pbXBvcnRhbnQgZmVhdHVyZSBpbiB0aGlzIG1vZGVsLiBIb3dldmVyLCB0aGlzIGlzIGNvdW50ZXJpbnR1aXRpdmUgZ2l2ZW4gdGhhdCAkWF8xJCB3YXMgc3BsaXQgb24gZmlyc3QgaW4gdGhlIHRyZWUgYW5kIHNob3VsZCBiZSBjb25zaWRlcmVkIG9uZSBvZiB0aGUgbW9zdCBpbXBvcnRhbnQgZmVhdHVyZXMgaW4gdGhpcyB0cmVlLiBCeSBrZWVwaW5nIHRyYWNrIG9mIHRoZSBzaWduZWQgaW5mb3JtYXRpb24gb2YgdGhlIHNwbGl0cyBhcyBkb25lIGluIHNpUkYsIHdlIGNhbiB1dGlsaXplIHRoaXMgbW9yZSBncmFudWxhciBpbmZvcm1hdGlvbiB0byBtaXRpZ2F0ZSB0aGUgaXNzdWUgZGlzY3Vzc2VkIGFib3ZlIGFuZCBpbXByb3ZlIG91ciBpbnRlcnByZXRhdGlvbiBvZiB0aGUgc2lSRiBmaXQuCgpNb3Jlb3ZlciwgdG8gZmFjaWxpdGF0ZSB0aGUgaW50ZXJwcmV0YXRpb24gb2YgdGhpcyBzaWduZWQgaW5mb3JtYXRpb24sIGl0IGNhbiBiZSBiZW5lZmljaWFsIHRvIGFnZ3JlZ2F0ZSBTTlYgZmVhdHVyZXMgdGhhdCBhcmUgKnBvc2l0aXZlbHkqIGNvcnJlbGF0ZWQgKGFzIG9wcG9zZWQgdG8gbmVnYXRpdmVseSBjb3JyZWxhdGVkKSBpbnRvIGEgc2luZ2xlIGxvY3VzIChvciBncm91cCkuIFNpbmNlIHRoZSBlbmNvZGluZyBvZiBTTlZzIGFzIGEgdmFsdWUgdGFraW5nIG9uIDAsIDEsIG9yIDIgaXMgcmF0aGVyIGFyYml0cmFyeSAoZS5nLiwgYSB2YWx1ZSBvZiAwIGNhbiBiZSByZS1lbmNvZGVkIHRvIHRha2Ugb24gdGhlIHZhbHVlIG9mIDIgYnkgY2hhbmdpbmcgdGhlIHJlZmVyZW5jZSBhbGxlbGUpLCB3ZSBjYW4gY2hvb3NlIHRoZSBlbmNvZGluZyBvZiB0aGUgU05WIHRvIHRyeSB0byBhdm9pZCBzdHJvbmcgbmVnYXRpdmUgY29ycmVsYXRpb25zIHdpdGhpbiBhIGxvY3VzLiBNb3JlIHNwZWNpZmljYWxseSwgZm9yIGVhY2ggZ2VuZXRpYyBsb2N1cyB3aGljaCBjb25zaXN0cyBvZiBTTlZzICRYXzEsIFxsZG90cywgWF9nJCwgd2UgY2hvb3NlIHRvICJmbGlwIiB0aGUgZW5jb2Rpbmcgb2YgdGhlIFNOViAkWF9qJCAoJGogPSAyLCBcbGRvdHMsIGckKSBpZiB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBvYnNlcnZlZCB2YWx1ZXMgb2YgJFhfaiQgYW5kICRYXzEkIGlzIGJlbG93IC0wLjE1LiBIZXJlLCB3ZSB1c2UgdGhlIHRlcm0gImZsaXAiIHRvIG1lYW4gdGhlIGFwcGxpY2F0aW9uIG9mIHRoZSBmdW5jdGlvbiB0aGF0IG1hcHMgMCB0byAyLCAxIHRvIDEsIGFuZCAyIHRvIDAuIFRoaXMgY29ycmVsYXRpb24gdGhyZXNob2xkIG9mIC0wLjE1IHdhcyBjaG9zZW4gYnkgdmlzdWFsbHkgaW5zcGVjdGluZyB0aGUgcmVzdWx0aW5nIHBhaXJ3aXNlIGNvcnJlbGF0aW9ucyBiZXR3ZWVuICRYX2kkIGFuZCAkWF9qJCBmb3IgYWxsICRpLCBqID0gMSwgXGxkb3RzLCBnJCBhbmQgY2hlY2tpbmcgdGhhdCB0aGVzZSBwYWlyd2lzZSBjb3JyZWxhdGlvbnMgYXJlIG5vdCBzdHJvbmdseSBuZWdhdGl2ZS4gSG93ZXZlciwgd2hpbGUgd2UgZm9jdXMgb24gdGhlIGxvLXNpUkYgcHJpb3JpdGl6YXRpb24gcmVzdWx0cyB1c2luZyB0aGlzIGNvcnJlbGF0aW9uIHRocmVzaG9sZCBvZiAtMC4xNSwgdGhlIHJlc3VsdHMgYXBwZWFyIHRvIGJlIHJvYnVzdCB0byBvdGhlciByZWFzb25hYmxlIGNvcnJlbGF0aW9uIHRocmVzaG9sZCBjaG9pY2VzIChlLmcuLCAtMC4wNSwgLTAuMjUpLiBGdXJ0aGVyIGFuYWx5c2lzIGFuZCBpbXByb3ZlbWVudHMgdG8gdGhpcyBwcm9jZWR1cmUgYXJlIHZlcnkgaW50ZXJlc3RpbmcgZm9yIGZ1dHVyZSB3b3JrLgo8L2Rpdj4KCgojIE5vbi1oeXBlcnRlbnNpdmUgQW5hbHlzaXMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtdm1vZGVybn0KCiMjIE92ZXJ2aWV3IHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+ClRoZSBsby1zaVJGIGFuYWx5c2lzIHRodXMgZmFyIGhhcyBub3QgYWNjb3VudGVkIGZvciB0aGUgcG9zc2liaWxpdHkgb2YgcGxlaW90cm9weSwgcGFydGljdWxhciBiZXR3ZWVuIExWIG1hc3MgYW5kIGJsb29kIHByZXNzdXJlIGdpdmVuIHRoZSBrbm93biBjb25uZWN0aW9ucyBiZXR3ZWVuIExWIGh5cGVydHJvcGh5IGFuZCBoeXBlcnRlbnNpb24gW0B5aWxkaXoyMDIwbGVmdF0uIFRvIGV2YWx1YXRlIHRoaXMgcG9zc2liaWxpdHkgb2YgcGxlaW90cm9waWMgZWZmZWN0cyBvZiB0aGUgaWRlbnRpZmllZCB2YXJpYW50cyBvbiBib3RoIExWIG1hc3MgYW5kIGJsb29kIHByZXNzdXJlLCB3ZSBjb25kdWN0ZWQgdHdvIGFuYWx5c2VzLgoKMS4gV2UgYXNzZXNzZWQgdGhlIG1hcmdpbmFsIGFzc29jaWF0aW9uIGJldHdlZW4gZWFjaCBvZiB0aGUgbG8tc2lSRi1wcmlvcml0aXplZCB2YXJpYW50cyBhbmQgaHlwZXJ0ZW5zaW9uIChzZWUgYEFzc29jaWF0aW9uIGJldHdlZW4gU05WcyBhbmQgSHlwZXJ0ZW5zaW9uYCB0YWIpLgoyLiBXZSByZXBlYXRlZCB0aGUgbG8tc2lSRiBhbmFseXNpcyB1c2luZyBvbmx5IHRoZSBzdWJzZXQgb2YgVUsgQmlvYmFuayBpbmRpdmlkdWFscyB3aG8gd2VyZSBub3QgcmVwb3J0ZWQgdG8gaGF2ZSBoeXBlcnRlbnNpb24gKHNlZSBgTG8tc2lSRiBSZXN1bHRzIFN1bW1hcnlgIHRhYikuCgpIZXJlLCB3ZSBkZWZpbmUgaHlwZXJ0ZW5zaXZlIGRpc2Vhc2VzIGFzIGFueW9uZSB3aXRoIHNlbGYtcmVwb3J0ZWQgaHlwZXJ0ZW5zaW9uLCBoaWdoIGJsb29kIHByZXNzdXJlIGFzIGRpYWdub3NlZCBieSBhIGRvY3Rvciwgb3IgYW55IElDRDEwIGJpbGxpbmcgY29kZSBkaWFnbm9zaXMgaW4gSTEwLUkxNi4gT3V0IG9mIHRoZSAyOSw2NjEgVUsgQmlvYmFuayBwYXJ0aWNpcGFudHMgaW4gdGhlIG9yaWdpbmFsIGxvLXNpUkYgYW5hbHlzaXMsIDcsMzcxIGluZGl2aWR1YWxzIGhhZCBoeXBlcnRlbnNpb24sIGxlYXZpbmcgMjIsMjkwIGluZGl2aWR1YWxzIGZvciB0aGUgbm9uLWh5cGVydGVuc2l2ZSBhbmFseXNpcy4gCgo8L2Rpdj4KCiMjIEFzc29jaWF0aW9uIGJldHdlZW4gU05WcyBhbmQgSHlwZXJ0ZW5zaW9uIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+ClRvIGFzc2VzcyB0aGVpciBtYXJnaW5hbCBhc3NvY2lhdGlvbiB3aXRoIGh5cGVydGVuc2lvbiwgd2UgZml0IGEgc2VwYXJhdGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCBmb3IgZWFjaCBvZiB0aGUgMTQwNSBHV0FTLWZpbHRlcmVkIFNOVnMsIHJlZ3Jlc3NpbmcgaHlwZXJ0ZW5zaW9uIChpLmUuLCBhIGJpbmFyeSBpbmRpY2F0b3Igb2Ygd2hldGhlciBvciBub3Qgb25lIGhhcyBoeXBlcnRlbnNpb24pIG9uIHRoZSBnZW5vdHlwZSBvZiB0aGUgU05WLCB3aGlsZSBhZGp1c3RpbmcgZm9yIHRoZSBmaXJzdCBmaXZlIHByaW5jaXBhbCBjb21wb25lbnRzIG9mIGFuY2VzdHJ5LCBzZXgsIGFnZSwgaGVpZ2h0LCBhbmQgYm9keSB3ZWlnaHQuCgpPdmVyYWxsLCB3ZSBmb3VuZCB0aGF0IG5vbmUgb2YgdGhlIDE0MDUgU05WcyBtZXQgdGhlIGdlbm9tZS13aWRlIChwIDwgNUUtOCkgbm9yIHRoZSBzdWdnZXN0aXZlIChwIDwgMUUtNSkgc2lnbmlmaWNhbmNlIGxldmVsIChGaWd1cmUgXEByZWYoZmlnOnN1YmNodW5rLTc4KSBhbmQgRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay04MCkpLiBHaXZlbiBvdXIgaW50ZXJlc3QgaW4gdGhlIGxvLXNpUkYtcHJpb3JpdGl6ZWQgaW50ZXJhY3Rpb25zLCB3aGljaCBpbnZvbHZlIHRoZSAqVFROKiwgKkNDREMxNDEqLCAqSUdGMVIqLCBhbmQgKkxPQzE1NzI3MztUTktTKiBsb2NpLCB3ZSBoaWdobGlnaHQgdGhlIFNOVnMgaW4gZWFjaCBsb2N1cyB3aXRoIHRoZSBzbWFsbGVzdCBwLXZhbHVlczoKCi0gKlRUTio6IHJzMzUxMTI1OTEgKHAgPSAwLjAzMjgpCi0gKkNDREMxNDEqOiByczY3MjUwMjggKHAgPSAwLjA0MDMpCi0gKklHRjFSKjogcnM2MjAyNDQ5MSAocCA9IDAuMzc2KQotICpMT0MxNTcyNzM7VE5LUyo6IHJzNzMxODUyMjEgKDAuMDQ5MSkKClRoZSB0b3AgbG8tc2lSRi1wcmlvcml0aXplZCB2YXJpYW50cyBpbiBlYWNoIGxvY2kgKHNlZSBGaWd1cmUgMmYgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkpIGV4aGliaXRlZCBldmVuIHdlYWtlciBtYXJnaW5hbCBhc3NvY2lhdGlvbnMgd2l0aCBoeXBlcnRlbnNpb247CgotICpUVE4qOiByczY2NzMzNjIxIChwID0gMC43NzYpCi0gKkNDREMxNDEqOiByczc1OTEwOTEgKHAgPSAwLjQ0NikKLSAqSUdGMVIqOiByczYyMDI0NDkxIChwID0gMC4zNzYpCi0gKkxPQzE1NzI3MztUTktTKjogcnM2OTk5ODUyICgwLjMwNCkKCldlIG5vdGUgaG93ZXZlciB0aGF0IHRoZSAqTUlSNTg4O1JTUE8zKiBsb2N1cyB3aXRoIGxlYWQgU05WIHJzMjAyMjQ3OSBnYXZlIHRoZSBzbWFsbGVzdCBwLXZhbHVlIG9mIDVFLTUuIFRoaXMsIGluIGNvbWJpbmF0aW9uIHdpdGggdGhlIGZpbmRpbmdzIGluIHRoZSBub24taHlwZXJ0ZW5zaW9uIGxvLXNpUkYgYW5hbHlzaXMgbmV4dCwgbWF5IHN1Z2dlc3QgYSBwb3NzaWJsZSBjb250cmlidXRpb24gb2YgdGhlIE1JUjU4ODtSU1BPMyBsb2N1cyBvbiBtZWRpYXRpbmcgTFYgaHlwZXJ0cm9waHkgdGhyb3VnaCByZWd1bGF0aW5nIGJsb29kIHByZXNzdXJlLgo8L2Rpdj4KCmBgYHtyIGh0bi1nd2FzLCByZXN1bHRzID0gImFzaXMifQppZiAoIXBhcmFtcyRldmFsKSB7CiAgZGlzcGxheV9pbWFnZSgKICAgIGZpbGUucGF0aChyZXNfZGlyLCAibm9fSFROIiwgImZ1bWFfZ3dhcyIsICJtYW5oYXR0YW5fRlVNQV9qb2JzNDUzNTk0X2VkaXRlZC5wbmciKSwKICAgIGNodW5rX2lkeCA9IGNodW5rX2lkeCwKICAgIGNhcHRpb24gPSAiJ01hbmhhdHRhbiBwbG90IGZvciB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgMTQwNSBHV0FTLWZpbHRlcmVkIFNOVnMgdXNlZCBpbiB0aGUgb3JpZ2luYWwgbG8tc2lSRiBhbmFseXNpcyBhbmQgaHlwZXJ0ZW5zaW9uLiciCiAgKQogIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogIGh0bl9nd2FzX3Jlc3VsdHMgPC0gZGF0YS50YWJsZTo6ZnJlYWQoCiAgICBmaWxlLnBhdGgocmVzX2RpciwgIm5vX0hUTiIsICJodG5fZ3dhc19yZXN1bHRzX2Z1bGwuY3N2IikKICApCiAgdGFiIDwtIGh0bl9nd2FzX3Jlc3VsdHMgJT4lCiAgICBkcGx5cjo6c2VsZWN0KHJzSUQsIENociwgUG9zID0gYGhnMTkgUG9zYCwgYExvLXNpUkYgTG9jdXNgID0gR2VuZSwgcCA9IHAudmFsdWUpICU+JQogICAgZHBseXI6OmFycmFuZ2UocCkgJT4lCiAgICBkcGx5cjo6c2xpY2UoMToxMDApICU+JQogICAgdnRoZW1lczo6cHJldHR5X0RUKHJvd25hbWVzID0gRkFMU0UpCiAgc3ViY2h1bmtpZnkoCiAgICB0YWIsCiAgICBpID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9ICInKipMaXN0IG9mIHRvcCAxMDAgU05WcyAob3V0IG9mIHRoZSAxNDA1IEdXQVMtZmlsdGVyZWQgU05WcyB1c2VkIGluIHRoZSBvcmlnaW5hbCBsby1zaVJGIGFuYWx5c2lzKSB3aXRoIHRoZSBoaWdoZXN0IGFzc29jaWF0aW9uIHdpdGggaHlwZXJ0ZW5zaW9uLioqIHJzSUQgPSByc0lEIG9mIHRoZSBTTlYuIENociA9IENocm9tb3NvbWUuIFBvcyA9IFBvc2l0aW9uIG9uIGhnMTkuIExvLXNpUkYgTG9jdXMgPSBhc3NpZ25lZCBsb2N1cyBvZiB0aGUgdmFyaWFudCBpbiB0aGUgb3JpZ2luYWwgbG8tc2lSRiBhbmFseXNpcy4gcCA9IFAtdmFsdWUgbWVhc3VyaW5nIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBTTlYgYW5kIGh5cGVydGVuc2lvbi4nIgogICkKICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQp9CmBgYAoKIyMgTm9uLWh5cGVydGVuc2l2ZSBMby1zaVJGIFJlc3VsdHMgU3VtbWFyeSB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpVc2luZyB0aGUgc2FtZSBzZXQgb2YgMTQwNSBHV0FTLWZpbHRlcmVkIFNOVnMgYXMgaW4gdGhlIG9yaWdpbmFsIGxvLXNpUkYgYW5hbHlzaXMsIHdlIHJlcGVhdGVkIHN0ZXBzIDItNCBvZiB0aGUgbG8tc2lSRiBhbmFseXNpcyB1c2luZyBvbmx5IHRoZSBub24taHlwZXJ0ZW5zaW9uIFVLIEJpb2JhbmsgY29ob3J0LiAKCi0gSW4gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay04MSksIHdlIGNvbmZpcm0gdGhhdCB0aGUgc2lSRiBmaXQgb24gdGhlIG5vbi1oeXBlcnRlbnNpdmUgY29ob3J0IHBlcmZvcm1zIGJldHRlciB0aGFuIHJhbmRvbSBndWVzc2luZyBhbmQgc2F0aXNmaWVzIHRoZSBwcmVkaWN0aW9uIGNoZWNrIGFjY29yZGluZyB0byB0aGUgUENTIGZyYW1ld29yayBbQHl1MjAyMHZlcmlkaWNhbF0uIFdlIHRodXMgY2hvb3NlIHRvIHByb2NlZWQgd2l0aCBpbnRlcnByZXRpbmcgdGhlIHNpUkYgZml0LgotIE92ZXJhbGwsIHdlIGZvdW5kIHRoYXQgdGhlIHRvcCAzIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgZnJvbSBvdXIgb3JpZ2luYWwgbG8tc2lSRiBhbmFseXNpcyAtLS0gbmFtZWx5LCAqQ0NEQzE0MS1JR0YxUiosICpDQ0RDMTQxLVRUTiosIGFuZCAqQ0NEQzE0MS1MT0MxNTcyNzM7VE5LUyogLS0tIHdlcmUgYWdhaW4gcHJpb3JpdGl6ZWQgYnkgbG8tc2lSRiB3aGVuIGV4Y2x1ZGluZyB0aGUgaHlwZXJ0ZW5zaXZlIGluZGl2aWR1YWxzLiBUaGF0IGlzLCBlYWNoIG9mIHRoZSBhZm9yZW1lbnRpb25lZCBpbnRlcmFjdGlvbnMgeWllbGRlZCBhIG5vbWluYWwgbG8tc2lSRiBwLXZhbHVlIGxlc3MgdGhhbiBvdXIgcHJlLXNwZWNpZmllZCB0aHJlc2hvbGQgb2YgMC4xIChpbiBmYWN0LCBhbGwgd2VyZSA8IDAuMDEpIGZvciBlYWNoIG9mIHRoZSB0aHJlZSBiaW5hcml6YXRpb24gdGhyZXNob2xkcyAoc2VlIEZpZ3VyZSBcQHJlZihmaWc6c3ViY2h1bmstODIpIGJlbG93KS4gVGhpcyBpcyB0byBzYXkgdGhhdCB0aGUgdG9wIGxvLXNpUkYtcHJpb3JpdGl6ZWQgaW50ZXJhY3Rpb25zIGFyZSBzdGFibGUgd2l0aCByZXNwZWN0IHRvIHRoZSBpbmNsdXNpb24gb3IgZXhjbHVzaW9uIG9mIGh5cGVydGVuc2l2ZSBpbmRpdmlkdWFscyBhbmQgcHJvdmlkZXMgZXZpZGVuY2UgdGhhdCB0aGVzZSBpbnRlcmFjdGlvbnMgYXJlIG5vdCBzb2xlbHkgbWVkaWF0aW5nIExWIGh5cGVydHJvcGh5IHRocm91Z2ggdGhlIHJlZ3VsYXRpb24gb2YgYmxvb2QgcHJlc3N1cmUuIAotIEFsbCBvZiB0aGUgcHJldmlvdXNseSBwcmlvcml0aXplZCBsb2NpLCB3aXRoIHRoZSBleGNlcHRpb24gb2YgdGhlICpNSVI1ODg7UlNQTzMqIGxvY3VzLCB3ZXJlIGFsc28gcHJpb3JpdGl6ZWQgaW4gdGhpcyBub24taHlwZXJ0ZW5zaXZlIGFuYWx5c2lzLiBXaGlsZSB0aGUgbm9taW5hbCBsby1zaVJGIHAtdmFsdWUgZm9yIHRoZSAqTUlSNTg4O1JTUE8zKiBsb2N1cyB3YXMgMC4wMTkgYW5kIDAuMDA3IGZvciB0aGUgMjBcJSBhbmQgMjVcJSBiaW5hcml6YXRpb24gdGhyZXNob2xkcywgdGhlIG5vbWluYWwgbG8tc2lSRiBwLXZhbHVlIHdhcyAwLjE4NyAoPiAwLjEgdGhyZXNob2xkKSBmb3IgdGhlIDE1XCUgYmluYXJpemF0aW9uIHRocmVzaG9sZCBhbmQgdGh1cyBkZWVtZWQgbm90IHN0YWJsZSBhbmQgd2FzIG5vdCBwcmlvcml0aXplZCBpbiB0aGUgbm9uLWh5cGVydGVuc2l2ZSBsby1zaVJGIGFuYWx5c2lzLiBUaG91Z2ggdGhlICpNSVI1ODg7UlNQTzMqIGxvY3VzIGFsbW9zdCBtZXQgdGhlIHByaW9yaXRpemF0aW9uIGNyaXRlcmlhIGhlcmUsIHRoaXMgcmVzdWx0LCBjb21iaW5lZCB3aXRoIHRoZSBzdXNwZWN0IG1hcmdpbmFsIGFzc29jaWF0aW9uIHJlc3VsdHMsIHN1Z2dlc3RzIGEgcG9zc2liaWxpdHkgb2YgcGxlaW90cm9waWMgbG9jdXMgY29udHJpYnV0aW5nIHRvIHZhcmlhdGlvbnMgb2YgYm90aCBibG9vZCBwcmVzc3VyZSBhbmQgTFYgbWFzcy4KLSBXZSBwcm92aWRlIHRoZSBmdWxsIGxpc3Qgb2YgbG9jaSBhbmQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSBmcm9tIHRoZSBub24taHlwZXJ0ZW5zaXZlIGxvLXNpUkYgYW5hbHlzaXMgaW4gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay04MykuIFRoaXMgbGlzdCBpbmNsdWRlcyBtYW55IGxvY2kgYW5kIGludGVyYWN0aW9ucyB0aGF0IHdlcmUgbm90IHN0YWJsZSBpbiB0aGUgb3JpZ2luYWwgbG8tc2lSRiBhbmFseXNpcy4KPC9kaXY+CgpgYGB7ciBub2h0bi1wcmVkLXJlc3VsdHMtYmluYXJ5LCByZXN1bHRzID0gImFzaXMifQojIHBoZW5vdHlwZV9oZWFkZXIgPC0gIlxuXG4jIyMgJXMgey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWZhZGUgLnRhYnNldC1jaXJjbGV9IFxuXG4iCnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgp0aHJfaGVhZGVyIDwtICJcblxuIyMjIyAlcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtZmFkZX0gXG5cbiIKIyBzdWJzZWN0aW9uX2hlYWRlciA8LSAiXG5cbiMjIyMjICVzIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1mYWRlIC50YWJzZXQtY2lyY2xlfSBcblxuIgojIHN1YnN1YnNlY3Rpb25faGVhZGVyIDwtICJcblxuIyMjIyMjIyAlcyB7LnVubnVtYmVyZWR9IFxuXG4iCgprZWVwX2ludHMgPC0gYygiQ0NEQzE0MS1fVFROLSIsICJDQ0RDMTQxLV9JR0YxUi0iLCAiQ0NEQzE0MS1fTE9DMTU3MjczO1ROS1MtIikKa2VlcF9mZWF0dXJlcyA8LSBjKCJJR0YxUiIsICJNSVI1ODg7UlNQTzMiLCAiVFROIiwgIkNDREMxNDEiLCAiTFNQMSIpCmtlZXBfZmVhdHVyZXMgPC0gYygKICBwYXN0ZTAoa2VlcF9mZWF0dXJlcywgIisiKSwgcGFzdGUwKGtlZXBfZmVhdHVyZXMsICItIikKKQoKRElTVF9IRUlHSFQgPC0gMTIKSEVBVE1BUF9IRUlHSFQgPC0gOApFUElfSEVJR0hUIDwtIDgKSVRFUiA8LSAzCkxFRlRfTUFSR0lOIDwtIDUKCmlmIChwYXJhbXMkZXZhbCkgewogIGZvciAocGhlbm90eXBlIGluIHBoZW5vdHlwZXMpIHsKICAgIHByaW50KHBoZW5vdHlwZSkKICAgIGV2YWxfbHMgPC0gbGlzdCgpCiAgICBpbnRfcmVzdWx0c19scyA8LSBsaXN0KCkKICAgIGdlbmVfcmVzdWx0c19scyA8LSBsaXN0KCkKICAgIGZvciAodGhyIGluIGMoMC4xNSwgMC4yLCAwLjI1KSkgewogICAgICBwcmludCh0aHIpCiAgICAgIGZwYXRoIDwtIGZpbGUucGF0aCgKICAgICAgICByZXNfZGlyLCAibm9faHRuIiwKICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2JpbmFyeV90aHIiLCB0aHIsICJfZ3dhc19maWx0ZXJlZF9uc25wczEwMDAiKQogICAgICApCiAgICAgICMgPiBvdXQsIHloYXRfdHIyLCB5aGF0X3ZhLCBpcmZfZ2VuZV9vdXQsIHNucHMuZGYsIGlyZl9zbnZfaW50X291dAogICAgICBsb2FkKGZpbGUucGF0aChmcGF0aCwgImlyZl9pbnRlcmFjdGlvbl9maXQuUmRhdGEiKSkKICAgICAgeV90ZXN0IDwtIGlmZWxzZShvdXQkcGhlbm9fdGVzdCA9PSAwLCAiTG93IExWTWkiLCAiSGlnaCBMVk1pIikKCiAgICAgICMgcHJlZGljdGlvbiByZXN1bHRzCiAgICAgIGV2YWxfb3V0IDwtIGJpbmRfcm93cygKICAgICAgICBldmFsUHJlZHMoeSA9IG91dCRwaGVub190ZXN0LCB5aGF0ID0geWhhdF92YSwgbWV0cmljID0gYygiQVVDIiwgIlBSIikpLAogICAgICAgIGV2YWxQcmVkcyh5ID0gb3V0JHBoZW5vX3Rlc3QsIHloYXQgPSByb3VuZCh5aGF0X3ZhKSwgbWV0cmljID0gYygiQ2xhc3MiKSkKICAgICAgKSAlPiUKICAgICAgICBzcHJlYWQoa2V5ID0gIk1ldHJpYyIsIHZhbHVlID0gIlZhbHVlIikKICAgICAgZXZhbF9sc1tbYXMuY2hhcmFjdGVyKHRocildXSA8LSBldmFsX291dAoKICAgICAgIyBsb2NhbCBpbnRlcmFjdGlvbiBzdGFiaWxpdHkgcmVzdWx0cwogICAgICBsb2FkKGZpbGUucGF0aChmcGF0aCwgImxvY2FsX2ludGVyYWN0aW9uX3N0YWJpbGl0eV9yZXN1bHRzLlJkYXRhIikpCiAgICAgIGludF9vdXQgPC0gbGlzdCgKICAgICAgICBzdGFiX3RyMl9scyA9IGludF9zdGFiX3RyMl9scywKICAgICAgICBzdGFiX3ZhX2xzID0gaW50X3N0YWJfdmFfbHMsCiAgICAgICAgdGVzdF9pbnRzX2xzID0gdGVzdF9pbnRzX2xzLAogICAgICAgIHBlcm1fb3V0X2xzID0gaW50X3Blcm1fb3V0X2xzCiAgICAgICkKICAgICAgaW50X3Jlc3VsdHNfbHNbW2FzLmNoYXJhY3Rlcih0aHIpXV0gPC0gaW50X3Blcm1fb3V0X2xzCgogICAgICBpbnRfYWxsX291dCA8LSBsaXN0KGBVc2luZyBhbGwgc3BsaXRzYCA9IGludF9vdXQpCgogICAgICBwdmFsX2ludCA8LSBtYXBfZGZyKGludF9vdXQkcGVybV9vdXRfbHNbW0lURVJdXSwKICAgICAgICBmdW5jdGlvbih4KSB7CiAgICAgICAgICBkYXRhLmZyYW1lKAogICAgICAgICAgICBwdmFsID0geCRwdmFsLAogICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFCiAgICAgICAgICApCiAgICAgICAgfSwKICAgICAgICAuaWQgPSAiaW50IgogICAgICApICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICBwdmFsX3N0ciA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgIHB2YWwgPCAxZS00IH4gIjwgMTA8c3VwPi00PC9zdXA+IiwKICAgICAgICAgICAgcHZhbCA8IDFlLTMgfiAiPCAxMDxzdXA+LTM8L3N1cD4iLAogICAgICAgICAgICBUUlVFIH4gc3ByaW50ZigiJXMiLCBmb3JtYXRDKHB2YWwsIGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJmIikpCiAgICAgICAgICApCiAgICAgICAgKQoKICAgICAgc3R5bGVfbmFtZXNfYmFzaWMgPC0gZnVuY3Rpb24oeCwgaXRhbGljID0gVFJVRSkgewogICAgICAgIHggPC0geCAlPiUKICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLV8iLCAiPHN1cD4mIzgyMTE7PC9zdXA+JiM4MjExOyIpICU+JQogICAgICAgICAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCJcXCtfIiwgIjxzdXA+Kzwvc3VwPiYjODIxMTsiKSAlPiUKICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiLSQiLCAiPHN1cD4mIzgyMTE7PC9zdXA+IikgJT4lCiAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoIlxcKyQiLCAiPHN1cD4rPC9zdXA+IikgJT4lCiAgICAgICAgICBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoZXNjYXBlID0gRkFMU0UsIGl0YWxpYyA9IGl0YWxpYykKICAgICAgICByZXR1cm4oeCkKICAgICAgfQoKICAgICAgIyBpUkYgcmVzdWx0cwogICAgICB0YWJfb3V0IDwtIGlyZl9nZW5lX291dCRpbnRlcmFjdGlvbltbSVRFUl1dICU+JQogICAgICAgIGxlZnRfam9pbih5ID0gcHZhbF9pbnQsIGJ5ID0gImludCIpICU+JQogICAgICAgIGRwbHlyOjphcnJhbmdlKHB2YWwpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoLXB2YWwpICU+JQogICAgICAgIGRwbHlyOjpyZW5hbWUoCiAgICAgICAgICAiSW50ZXJhY3Rpb24iID0gImludCIsCiAgICAgICAgICAiUHJldmFsZW5jZSIgPSAicHJldmFsZW5jZSIsCiAgICAgICAgICAiUHJlY2lzaW9uIiA9ICJwcmVjaXNpb24iLAogICAgICAgICAgIkNsYXNzIERpZmZlcmVuY2UgaW4gUHJldmFsZW5jZSIgPSAiY3BlIiwKICAgICAgICAgICJTdGFiaWxpdHkgb2YgQ2xhc3MgRGlmZmVyZW5jZSBpbiBQcmV2YWxlbmNlIiA9ICJzdGEuY3BlIiwKICAgICAgICAgICJGZWF0dXJlIFNlbGVjdGlvbiBEZXBlbmRlbmNlIiA9ICJmc2QiLAogICAgICAgICAgIlN0YWJpbGl0eSBvZiBGZWF0dXJlIFNlbGVjdGlvbiBEZXBlbmRlbmNlIiA9ICJzdGEuZnNkIiwKICAgICAgICAgICJJbmNyZWFzZSBpbiBQcmVjaXNpb24iID0gIm1pcCIsCiAgICAgICAgICAiU3RhYmlsaXR5IG9mIEluY3JlYXNlIGluIFByZWNpc2lvbiIgPSAic3RhLm1pcCIsCiAgICAgICAgICAiU3RhYmlsaXR5IiA9ICJzdGFiaWxpdHkiLAogICAgICAgICAgImxvLXNpUkYgTWVhbiBQZXJtdXRhdGlvbiBwLXZhbHVlIiA9ICJwdmFsX3N0ciIKICAgICAgICApICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoSW50ZXJhY3Rpb24gPSBzdHlsZV9uYW1lc19iYXNpYyhJbnRlcmFjdGlvbikpCiAgICAgIHRhYiA8LSBwcmV0dHlfRFQodGFiX291dCwKICAgICAgICBkaWdpdHMgPSAzLCBzaWdmaWcgPSBUUlVFLCByb3duYW1lcyA9IEZBTFNFLAogICAgICAgIG5hX2Rpc3AgPSAiLS0iCiAgICAgICkKICAgICAgIyBzYXZlUkRTKAogICAgICAjICAgdGFiLAogICAgICAjICAgZmlsZS5wYXRoKAogICAgICAjICAgICB0YWJfcmVzX2RpciwKICAgICAgIyAgICAgcGFzdGUwKAogICAgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICMgICAgICAgIl9pcmZfaW50ZXJhY3Rpb25fbm9odG5fcmVzdWx0cy5yZHMiCiAgICAgICMgICAgICkKICAgICAgIyAgICkKICAgICAgIyApCgogICAgICBmb3IgKHR5cGUgaW4gbmFtZXMoaW50X2FsbF9vdXQpKSB7CiAgICAgICAgcHJpbnQodHlwZSkKICAgICAgICAjIGRpc3RyaWJ1dGlvbiBwbG90cwogICAgICAgIGludF9wdmFscyA8LSBtYXBfZGZyKGludF9hbGxfb3V0W1t0eXBlXV0kcGVybV9vdXRfbHNbW0lURVJdXSwKICAgICAgICAgIH4gZGF0YS5mcmFtZShwdmFsID0gLngkcHZhbCksCiAgICAgICAgICAuaWQgPSAiaW50IgogICAgICAgICkgJT4lCiAgICAgICAgICBhcnJhbmdlKHB2YWwpICU+JQogICAgICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICAgICAgcHZhbF9zdHIgPSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICAgICAgICAgIHB2YWwgPCAxZS00IH4gInAgPCAxMF4tNCIsCiAgICAgICAgICAgICAgcHZhbCA8IDFlLTMgfiAicCA8IDEwXi0zIiwKICAgICAgICAgICAgICAjIHB2YWwgPCAxZS00IH4gInAgPCAxMDxzdXA+LTQ8L3N1cD4iLAogICAgICAgICAgICAgICMgcHZhbCA8IDFlLTMgfiAicCA8IDEwPHN1cD4tMzwvc3VwPiIsCiAgICAgICAgICAgICAgVFJVRSB+IHNwcmludGYoInB+YD1gfiVzIiwgZm9ybWF0QyhwdmFsLCBkaWdpdHMgPSAzLCBmb3JtYXQgPSAiZiIpKQogICAgICAgICAgICApCiAgICAgICAgICApICU+JQogICAgICAgICAgbXV0YXRlKGludF9wdmFsID0gc3ByaW50ZigiJXMgKCVzKSIsIGludCwgcHZhbF9zdHIpKQogICAgICAgIHBsdF9kZiA8LSBpbnRfYWxsX291dFtbdHlwZV1dJHN0YWJfdmFfbHNbW0lURVJdXSAlPiUKICAgICAgICAgIGJpbmRfY29scyh5ID0geV90ZXN0KSAlPiUKICAgICAgICAgIGdhdGhlcihrZXkgPSAiaW50IiwgdmFsdWUgPSAiU3RhYmlsaXR5IiwgLXkpICU+JQogICAgICAgICAgbGVmdF9qb2luKHkgPSBpbnRfcHZhbHMsIGJ5ID0gImludCIpICU+JQogICAgICAgICAgIyBtdXRhdGUoaW50ID0gcGFzdGUwKGludCwgIiAocCA9ICIsIGZvcm1hdEMocHZhbCwgMywgZm9ybWF0ID0gImciKSwgIikiKSkgJT4lCiAgICAgICAgICBmaWx0ZXIoaW50ICVpbiUgISFrZWVwX2ludHMpICU+JQogICAgICAgICAgbXV0YXRlKAogICAgICAgICAgICBpbnQgPSBmYWN0b3IoaW50LCBsZXZlbHMgPSBpbnRfcHZhbHMkaW50W2ludF9wdmFscyRpbnQgJWluJSBrZWVwX2ludHNdKQogICAgICAgICAgKQogICAgICAgIHBsdCA8LSBwbG90X2RlbnNpdHkoZGF0YSA9IHBsdF9kZiwgeF9zdHIgPSAiU3RhYmlsaXR5IiwgZmlsbF9zdHIgPSAieSIpICsKICAgICAgICAgIGZhY2V0X3dyYXAofmludCwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMykgKwogICAgICAgICAgZ2dwbG90Mjo6bGFicyh4ID0gIkxvY2FsIFN0YWJpbGl0eSBJbXBvcnRhbmNlIFNjb3JlIiwgZmlsbCA9ICIiKSArCiAgICAgICAgICBnZ3Bsb3QyOjpnZW9tX3RleHQoCiAgICAgICAgICAgIGdncGxvdDI6OmFlcyh4ID0gSW5mLCB5ID0gSW5mLCBoanVzdCA9IDEuMSwgdmp1c3QgPSAxLjUsIGxhYmVsID0gcHZhbF9zdHIpLAogICAgICAgICAgICBkYXRhID0gcGx0X2RmICU+JSBkcGx5cjo6ZGlzdGluY3QoaW50LCAua2VlcF9hbGwgPSBUUlVFKSwKICAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICAgICAgICAgIGdncGxvdDI6OnRoZW1lKGF4aXMudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkKICAgICAgICAjIHNhdmVSRFMoCiAgICAgICAgIyAgIHBsdCwKICAgICAgICAjICAgZmlsZS5wYXRoKAogICAgICAgICMgICAgIGZpZ19yZXNfZGlyLAogICAgICAgICMgICAgIHBhc3RlMCgKICAgICAgICAjICAgICAgIHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAgICAgIyAgICAgICAiX2ludF9sb2NhbF9zdGFiaWxpdHlfZGlzdF8iLCB0eXBlLCAiX25vaHRuLnJkcyIKICAgICAgICAjICAgICApCiAgICAgICAgIyAgICkKICAgICAgICAjICkKCiAgICAgICAgIyBpbmRpdmlkdWFsIHNucCBwbG90cwogICAgICAgIHBsdCA8LSBwbG90UkZTbnBJbnREaXN0KAogICAgICAgICAgaXJmX2dlbmVfb3V0JHJmLmxpc3RbW0lURVJdXSwgc25wcy5kZiwKICAgICAgICAgIGludF9wdmFscyRpbnRbaW50X3B2YWxzJGludCAlaW4lIGtlZXBfaW50c10sCiAgICAgICAgICBwcm9wID0gVFJVRQogICAgICAgICkgKwogICAgICAgICAgZ2dwbG90Mjo6bGFicyh4ID0gIlNOVi1TTlYgUGFpciIpCiAgICAgICAgIyBzYXZlUkRTKAogICAgICAgICMgICBwbHQsCiAgICAgICAgIyAgIGZpbGUucGF0aCgKICAgICAgICAjICAgICBmaWdfcmVzX2RpciwKICAgICAgICAjICAgICBwYXN0ZTAoCiAgICAgICAgIyAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICMgICAgICAgIl9pbnRfbG9jYWxfc3RhYmlsaXR5X3NucF9kaXN0XyIsIHR5cGUsICJfbm9odG4ucmRzIgogICAgICAgICMgICAgICkKICAgICAgICAjICAgKQogICAgICAgICMgKQogICAgICB9CgogICAgICAjIGxvY2FsIGZlYXR1cmUgc3RhYmlsaXR5IHJlc3VsdHMKICAgICAgbG9hZChmaWxlLnBhdGgoZnBhdGgsICJsb2NhbF9mZWF0dXJlX3N0YWJpbGl0eV9yZXN1bHRzLlJkYXRhIikpCiAgICAgIHN0YWJfb3V0IDwtIGxpc3QoCiAgICAgICAgc3RhYl90cjJfbHMgPSBzdGFiX3RyMl9scywKICAgICAgICBzdGFiX3ZhX2xzID0gc3RhYl92YV9scywKICAgICAgICB0ZXN0X2dlbmVzX2xzID0gdGVzdF9nZW5lc19scywKICAgICAgICBwZXJtX291dF9scyA9IHBlcm1fb3V0X2xzCiAgICAgICkKICAgICAgZ2VuZV9yZXN1bHRzX2xzW1thcy5jaGFyYWN0ZXIodGhyKV1dIDwtIHBlcm1fb3V0X2xzCgogICAgICBzdGFiX2FsbF9vdXQgPC0gbGlzdChgVXNpbmcgYWxsIHNwbGl0c2AgPSBzdGFiX291dCkKCiAgICAgIGZvciAodHlwZSBpbiBuYW1lcyhpbnRfYWxsX291dCkpIHsKICAgICAgICBwcmludCh0eXBlKQogICAgICAgIHN0YWJfZGYgPC0gc3RhYl9hbGxfb3V0W1t0eXBlXV0kc3RhYl92YV9sc1tbSVRFUl1dICU+JQogICAgICAgICAgc2VsZWN0KGFsbF9vZihzdGFiX2FsbF9vdXRbW3R5cGVdXSR0ZXN0X2dlbmVzX2xzW1tJVEVSXV0pKQoKICAgICAgICAjIGRpc3RyaWJ1dGlvbiBwbG90cwogICAgICAgIGZ0X3B2YWxzIDwtIG1hcF9kZnIoc3RhYl9hbGxfb3V0W1t0eXBlXV0kcGVybV9vdXRfbHNbW0lURVJdXSwKICAgICAgICAgIH4gZGF0YS5mcmFtZShwdmFsID0gLngkcHZhbCksCiAgICAgICAgICAuaWQgPSAiZmVhdHVyZSIKICAgICAgICApICU+JQogICAgICAgICAgYXJyYW5nZShwdmFsKSAlPiUKICAgICAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgICAgIHB2YWxfc3RyID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICAgICAgICBwdmFsIDwgMWUtNCB+ICJwIDwgMTBeLTQiLAogICAgICAgICAgICAgIHB2YWwgPCAxZS0zIH4gInAgPCAxMF4tMyIsCiAgICAgICAgICAgICAgIyBwdmFsIDwgMWUtNCB+ICJwIDwgMTA8c3VwPi00PC9zdXA+IiwKICAgICAgICAgICAgICAjIHB2YWwgPCAxZS0zIH4gInAgPCAxMDxzdXA+LTM8L3N1cD4iLAogICAgICAgICAgICAgIFRSVUUgfiBzcHJpbnRmKCJwfmA9YH4lcyIsIGZvcm1hdEMocHZhbCwgZGlnaXRzID0gMywgZm9ybWF0ID0gImYiKSkKICAgICAgICAgICAgKQogICAgICAgICAgKSAlPiUKICAgICAgICAgIG11dGF0ZShmdF9wdmFsID0gcGFzdGUwKGZlYXR1cmUsICIgKHAgPSAiLCBmb3JtYXRDKHB2YWwsIDMsIGZvcm1hdCA9ICJnIiksICIpIikpCiAgICAgICAgcGx0X2RmIDwtIHN0YWJfZGYgJT4lCiAgICAgICAgICBiaW5kX2NvbHMoeSA9IHlfdGVzdCkgJT4lCiAgICAgICAgICBnYXRoZXIoa2V5ID0gImZlYXR1cmUiLCB2YWx1ZSA9ICJTdGFiaWxpdHkiLCAteSkgJT4lCiAgICAgICAgICBsZWZ0X2pvaW4oeSA9IGZ0X3B2YWxzLCBieSA9ICJmZWF0dXJlIikgJT4lCiAgICAgICAgICAjIG11dGF0ZShmZWF0dXJlID0gcGFzdGUwKGZlYXR1cmUsICIgKHAgPSAiLCBmb3JtYXRDKHB2YWwsIDMsIGZvcm1hdCA9ICJnIiksICIpIikpICU+JQogICAgICAgICAgZmlsdGVyKGZlYXR1cmUgJWluJSAhIWtlZXBfZmVhdHVyZXMpICU+JQogICAgICAgICAgbXV0YXRlKAogICAgICAgICAgICBmZWF0dXJlID0gZmFjdG9yKAogICAgICAgICAgICAgIGZlYXR1cmUsCiAgICAgICAgICAgICAgbGV2ZWxzID0gZnRfcHZhbHMkZmVhdHVyZVtmdF9wdmFscyRmZWF0dXJlICVpbiUga2VlcF9mZWF0dXJlc10KICAgICAgICAgICAgKQogICAgICAgICAgKQogICAgICAgIHBsdCA8LSBwbG90X2RlbnNpdHkoZGF0YSA9IHBsdF9kZiwgeF9zdHIgPSAiU3RhYmlsaXR5IiwgZmlsbF9zdHIgPSAieSIpICsKICAgICAgICAgIGZhY2V0X3dyYXAofmZlYXR1cmUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDQpICsKICAgICAgICAgIGdncGxvdDI6OmxhYnMoeCA9ICJMb2NhbCBTdGFiaWxpdHkgSW1wb3J0YW5jZSBTY29yZSIsIGZpbGwgPSAiIikgKwogICAgICAgICAgZ2dwbG90Mjo6Z2VvbV90ZXh0KAogICAgICAgICAgICBnZ3Bsb3QyOjphZXMoeCA9IEluZiwgeSA9IEluZiwgaGp1c3QgPSAxLjEsIHZqdXN0ID0gMS41LCBsYWJlbCA9IHB2YWxfc3RyKSwKICAgICAgICAgICAgZGF0YSA9IHBsdF9kZiAlPiUgZHBseXI6OmRpc3RpbmN0KGZlYXR1cmUsIC5rZWVwX2FsbCA9IFRSVUUpLAogICAgICAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgICAgICkgKwogICAgICAgICAgZ2dwbG90Mjo6dGhlbWUoYXhpcy50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTQpKQogICAgICAgICMgc2F2ZVJEUygKICAgICAgICAjICAgcGx0LAogICAgICAgICMgICBmaWxlLnBhdGgoCiAgICAgICAgIyAgICAgZmlnX3Jlc19kaXIsCiAgICAgICAgIyAgICAgcGFzdGUwKAogICAgICAgICMgICAgICAgcGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICAgICAjICAgICAgICJfbG9jYWxfc3RhYmlsaXR5X2Rpc3RfIiwgdHlwZSwgIl9ub2h0bi5yZHMiCiAgICAgICAgIyAgICAgKQogICAgICAgICMgICApCiAgICAgICAgIyApCgogICAgICAgICMgaW5kaXZpZHVhbCBzbnAgcGxvdHMKICAgICAgICBwbHQgPC0gcGxvdFJGU25wRGlzdCgKICAgICAgICAgIGlyZl9nZW5lX291dCRyZi5saXN0W1tJVEVSXV0sIHNucHMuZGYsCiAgICAgICAgICBmdF9wdmFscyRmZWF0dXJlW2Z0X3B2YWxzJGZlYXR1cmUgJWluJSBrZWVwX2ZlYXR1cmVzXSwKICAgICAgICAgIHByb3AgPSBUUlVFCiAgICAgICAgKSArCiAgICAgICAgICBnZ3Bsb3QyOjpsYWJzKHggPSAiU05WIChPcmRlcmVkIGJ5IFBvc2l0aW9uKSIpCiAgICAgICAgIyBzYXZlUkRTKAogICAgICAgICMgICBwbHQsCiAgICAgICAgIyAgIGZpbGUucGF0aCgKICAgICAgICAjICAgICBmaWdfcmVzX2RpciwKICAgICAgICAjICAgICBwYXN0ZTAoCiAgICAgICAgIyAgICAgICBwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgICAgICMgICAgICAgIl9sb2NhbF9zdGFiaWxpdHlfc25wX2Rpc3RfIiwgdHlwZSwgIl9ub2h0bi5yZHMiCiAgICAgICAgIyAgICAgKQogICAgICAgICMgICApCiAgICAgICAgIyApCiAgICAgIH0KICAgIH0KCiAgICB0YWIgPC0gZHBseXI6OmJpbmRfcm93cyhldmFsX2xzLCAuaWQgPSAiQmluYXJpemF0aW9uIFRocmVzaG9sZCIpICU+JQogICAgICBkcGx5cjo6cmVuYW1lKCJBY2N1cmFjeSIgPSAiQ2xhc3MiLCAiQVVST0MiID0gIkFVQyIsICJBVVBSQyIgPSAiUFIiKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChgQmluYXJpemF0aW9uIFRocmVzaG9sZGAsIEFjY3VyYWN5LCBBVVJPQywgQVVQUkMpICU+JQogICAgICBwcmV0dHlfRFQoCiAgICAgICAgZGlnaXRzID0gMywgc2lnZmlnID0gRkFMU0UsIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gInQiLCBvcmRlcmluZyA9IEZBTFNFKQogICAgICApCiAgICAjIHNhdmVSRFMoCiAgICAjICAgdGFiLAogICAgIyAgIGZpbGUucGF0aCgKICAgICMgICAgIHRhYl9yZXNfZGlyLAogICAgIyAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9pcmZfcHJlZGljdGlvbl9ub2h0bl9yZXN1bHRzLnJkcyIpCiAgICAjICAgKQogICAgIyApCgogICAgZ2VuZV9yZXN1bHRzX2RmIDwtIHB1cnJyOjptYXBfZGZyKAogICAgICBnZW5lX3Jlc3VsdHNfbHMsCiAgICAgIGZ1bmN0aW9uKGdlbmVfcmVzdWx0cykgewogICAgICAgIHB1cnJyOjptYXBfZGZyKAogICAgICAgICAgZ2VuZV9yZXN1bHRzW1tJVEVSXV0sCiAgICAgICAgICB+IGRhdGEuZnJhbWUoCiAgICAgICAgICAgIGBNZWFuIERpZmZlcmVuY2UgKEhpZ2ggLSBMb3cpYCA9IGZvcm1hdEMoLngkVF9vYnMsIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJnIiksCiAgICAgICAgICAgIGBTRGAgPSBmb3JtYXRDKHNkKC54JHBlcm1fZGlzdCksIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICJnIiksCiAgICAgICAgICAgIGBwLXZhbHVlYCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgLngkcHZhbCA8IDFlLTQgfiAiPCAxMDxzdXA+LTQ8L3N1cD4iLAogICAgICAgICAgICAgIC54JHB2YWwgPCAxZS0zIH4gIjwgMTA8c3VwPi0zPC9zdXA+IiwKICAgICAgICAgICAgICBUUlVFIH4gZm9ybWF0QygueCRwdmFsLCBkaWdpdHMgPSAzLCBmb3JtYXQgPSAiZiIpCiAgICAgICAgICAgICksCiAgICAgICAgICAgIHAgPSAueCRwdmFsLAogICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFCiAgICAgICAgICApLAogICAgICAgICAgLmlkID0gIkxvY3VzIC8gSW50ZXJhY3Rpb24iCiAgICAgICAgKQogICAgICB9LAogICAgICAuaWQgPSAiQmluYXJpemF0aW9uIFRocmVzaG9sZCIKICAgICkKCiAgICBpbnRfcmVzdWx0c19kZiA8LSBwdXJycjo6bWFwX2RmcigKICAgICAgaW50X3Jlc3VsdHNfbHMsCiAgICAgIGZ1bmN0aW9uKGludF9yZXN1bHRzKSB7CiAgICAgICAgcHVycnI6Om1hcF9kZnIoCiAgICAgICAgICBpbnRfcmVzdWx0c1tbSVRFUl1dLAogICAgICAgICAgfiBkYXRhLmZyYW1lKAogICAgICAgICAgICBgTWVhbiBEaWZmZXJlbmNlIChIaWdoIC0gTG93KWAgPSBmb3JtYXRDKC54JFRfb2JzLCBkaWdpdHMgPSAyLCBmb3JtYXQgPSAiZyIpLAogICAgICAgICAgICBgU0RgID0gZm9ybWF0QyhzZCgueCRwZXJtX2Rpc3QpLCBkaWdpdHMgPSAyLCBmb3JtYXQgPSAiZyIpLAogICAgICAgICAgICBgcC12YWx1ZWAgPSBkcGx5cjo6Y2FzZV93aGVuKAogICAgICAgICAgICAgIC54JHB2YWwgPCAxZS00IH4gIjwgMTA8c3VwPi00PC9zdXA+IiwKICAgICAgICAgICAgICAueCRwdmFsIDwgMWUtMyB+ICI8IDEwPHN1cD4tMzwvc3VwPiIsCiAgICAgICAgICAgICAgVFJVRSB+IGZvcm1hdEMoLngkcHZhbCwgZGlnaXRzID0gMywgZm9ybWF0ID0gImYiKQogICAgICAgICAgICApLAogICAgICAgICAgICBwID0gLngkcHZhbCwKICAgICAgICAgICAgY2hlY2submFtZXMgPSBGQUxTRQogICAgICAgICAgKSwKICAgICAgICAgIC5pZCA9ICJMb2N1cyAvIEludGVyYWN0aW9uIgogICAgICAgICkKICAgICAgfSwKICAgICAgLmlkID0gIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQiCiAgICApCgogICAgc3R5bGVfbmFtZXMgPC0gZnVuY3Rpb24oeCkgewogICAgICBjb2xvcl92ZWMgPC0gc3RyaW5ncjo6c3RyX2RldGVjdCh4LCAiXyIpCiAgICAgIHggPC0geCAlPiUKICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoIi1fIiwgIjxzdXA+JiM4MjExOzwvc3VwPiYjODIxMTsiKSAlPiUKICAgICAgICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoIi0kIiwgIjxzdXA+JiM4MjExOzwvc3VwPiIpICU+JQogICAgICAgIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiXFwrIiwgIjxzdXA+Kzwvc3VwPiIpCiAgICAgIHggPC0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICBjb2xvcl92ZWMgfiBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoCiAgICAgICAgICB4LAogICAgICAgICAgY29sb3IgPSAiY29ybmZsb3dlcmJsdWUiLCBlc2NhcGUgPSBGQUxTRSwgaXRhbGljID0gVFJVRQogICAgICAgICksCiAgICAgICAgVFJVRSB+IGthYmxlRXh0cmE6OmNlbGxfc3BlYyh4LCBlc2NhcGUgPSBGQUxTRSwgaXRhbGljID0gVFJVRSkKICAgICAgKQogICAgICByZXR1cm4oeCkKICAgIH0KCiAgICBmZWF0dXJlX29yZGVyIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZ2VuZV9yZXN1bHRzX2RmLCBpbnRfcmVzdWx0c19kZikgJT4lCiAgICAgIGRwbHlyOjpncm91cF9ieShgTG9jdXMgLyBJbnRlcmFjdGlvbmApICU+JQogICAgICBkcGx5cjo6c3VtbWFyaXNlKAogICAgICAgIG4gPSBkcGx5cjo6bigpLAogICAgICAgIG1lYW4gPSBtZWFuKHApCiAgICAgICkgJT4lCiAgICAgIGRwbHlyOjphcnJhbmdlKC1uLCBtZWFuKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChgTG9jdXMgLyBJbnRlcmFjdGlvbmApCgogICAgY29sb3JfdmVjIDwtIHN0cmluZ3I6OnN0cl9kZXRlY3QoZmVhdHVyZV9vcmRlciRgTG9jdXMgLyBJbnRlcmFjdGlvbmAsICJfIikKCiAgICByZXN1bHRzX2RmIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZ2VuZV9yZXN1bHRzX2RmLCBpbnRfcmVzdWx0c19kZikgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgYERpZmZlcmVuY2UgaW4gTG9jYWwgRmVhdHVyZSBTdGFiaWxpdHkgKEhpZ2ggLSBMb3cpYCA9IHNwcmludGYoIiVzICglcykiLCBgTWVhbiBEaWZmZXJlbmNlIChIaWdoIC0gTG93KWAsIFNEKQogICAgICApICU+JQogICAgICB0aWR5cjo6cGl2b3Rfd2lkZXIoCiAgICAgICAgaWRfY29scyA9IGBMb2N1cyAvIEludGVyYWN0aW9uYCwKICAgICAgICBuYW1lc19mcm9tID0gYEJpbmFyaXphdGlvbiBUaHJlc2hvbGRgLAogICAgICAgIHZhbHVlc19mcm9tID0gYyhgRGlmZmVyZW5jZSBpbiBMb2NhbCBGZWF0dXJlIFN0YWJpbGl0eSAoSGlnaCAtIExvdylgLCBgcC12YWx1ZWApLAogICAgICAgIG5hbWVzX3ZhcnkgPSAic2xvd2VzdCIKICAgICAgKSAlPiUKICAgICAgZHBseXI6OmxlZnRfam9pbih4ID0gZmVhdHVyZV9vcmRlciwgeSA9IC4sIGJ5ID0gIkxvY3VzIC8gSW50ZXJhY3Rpb24iKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZSgKICAgICAgICBgTG9jdXMgLyBJbnRlcmFjdGlvbmAgPSBzdHlsZV9uYW1lcyhgTG9jdXMgLyBJbnRlcmFjdGlvbmApCiAgICAgICkKICAgIHJlc3VsdHNfdGFiIDwtIHByZXR0eV9EVCgKICAgICAgcmVzdWx0c19kZiwKICAgICAgbmFfZGlzcCA9ICItLSIsIHJvd25hbWVzID0gRkFMU0UsCiAgICAgIGdyb3VwZWRfaGVhZGVyID0gYygKICAgICAgICAiICIgPSAxLCAiQmluYXJpemF0aW9uIFRocmVzaG9sZCA9IDAuMTUiID0gMiwKICAgICAgICAiQmluYXJpemF0aW9uIFRocmVzaG9sZCA9IDAuMjAiID0gMiwKICAgICAgICAiQmluYXJpemF0aW9uIFRocmVzaG9sZCA9IDAuMjUiID0gMgogICAgICApLAogICAgICBncm91cGVkX3N1YmhlYWRlciA9IHN0cmluZ3I6OnN0cl9yZW1vdmUoY29sbmFtZXMocmVzdWx0c19kZiksICJcXF9bLjAtOV0rIikKICAgICkKICAgICMgc2F2ZVJEUygKICAgICMgICByZXN1bHRzX3RhYiwKICAgICMgICBmaWxlLnBhdGgoCiAgICAjICAgICB0YWJfcmVzX2RpciwKICAgICMgICAgIHBhc3RlMChwaGVub3R5cGUsICJfaXJmX3B2YWx1ZXNfc3VtbWFyeV9mdWxsX25vaHRuLnJkcyIpCiAgICAjICAgKQogICAgIyApCgogICAgcmVzdWx0c19kZiA8LSBkcGx5cjo6YmluZF9yb3dzKGdlbmVfcmVzdWx0c19kZiwgaW50X3Jlc3VsdHNfZGYpICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKGBMb2N1cyAvIEludGVyYWN0aW9uYCAlaW4lIGMoa2VlcF9pbnRzLCBrZWVwX2ZlYXR1cmVzKSkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgYERpZmZlcmVuY2UgaW4gTG9jYWwgRmVhdHVyZSBTdGFiaWxpdHkgKEhpZ2ggLSBMb3cpYCA9IHNwcmludGYoIiVzICglcykiLCBgTWVhbiBEaWZmZXJlbmNlIChIaWdoIC0gTG93KWAsIFNEKQogICAgICApICU+JQogICAgICB0aWR5cjo6cGl2b3Rfd2lkZXIoCiAgICAgICAgaWRfY29scyA9IGBMb2N1cyAvIEludGVyYWN0aW9uYCwKICAgICAgICBuYW1lc19mcm9tID0gYEJpbmFyaXphdGlvbiBUaHJlc2hvbGRgLAogICAgICAgIHZhbHVlc19mcm9tID0gYyhgRGlmZmVyZW5jZSBpbiBMb2NhbCBGZWF0dXJlIFN0YWJpbGl0eSAoSGlnaCAtIExvdylgLCBgcC12YWx1ZWApLAogICAgICAgIG5hbWVzX3ZhcnkgPSAic2xvd2VzdCIKICAgICAgKSAlPiUKICAgICAgZHBseXI6OmlubmVyX2pvaW4oeCA9IGZlYXR1cmVfb3JkZXIsIHkgPSAuLCBieSA9ICJMb2N1cyAvIEludGVyYWN0aW9uIikgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICAgYExvY3VzIC8gSW50ZXJhY3Rpb25gID0gc3R5bGVfbmFtZXMoYExvY3VzIC8gSW50ZXJhY3Rpb25gKQogICAgICApCiAgICByZXN1bHRzX3RhYiA8LSBwcmV0dHlfRFQoCiAgICAgIHJlc3VsdHNfZGYsCiAgICAgIG5hX2Rpc3AgPSAiLS0iLCByb3duYW1lcyA9IEZBTFNFLAogICAgICBncm91cGVkX2hlYWRlciA9IGMoCiAgICAgICAgIiAiID0gMSwgIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAwLjE1IiA9IDIsCiAgICAgICAgIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAwLjIwIiA9IDIsCiAgICAgICAgIkJpbmFyaXphdGlvbiBUaHJlc2hvbGQgPSAwLjI1IiA9IDIKICAgICAgKSwKICAgICAgZ3JvdXBlZF9zdWJoZWFkZXIgPSBzdHJpbmdyOjpzdHJfcmVtb3ZlKGNvbG5hbWVzKHJlc3VsdHNfZGYpLCAiXFxfWy4wLTldKyIpLAogICAgICBvcHRpb25zID0gbGlzdChkb20gPSAidCIpCiAgICApCiAgICAjIHNhdmVSRFMoCiAgICAjICAgcmVzdWx0c190YWIsCiAgICAjICAgZmlsZS5wYXRoKAogICAgIyAgICAgdGFiX3Jlc19kaXIsCiAgICAjICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX2lyZl9wdmFsdWVzX3N1bW1hcnlfbm9odG4ucmRzIikKICAgICMgICApCiAgICAjICkKICB9Cn0gZWxzZSB7CiAgbWV0aG9kX3R5cGVzIDwtIGMoIlVzaW5nIGFsbCBzcGxpdHMiKQogIHRocnMgPC0gYygwLjE1LCAwLjIsIDAuMjUpCiAgZm9yIChwaGVub3R5cGUgaW4gcGhlbm90eXBlcykgewogICAgcGhlbm90eXBlX25hbWUgPC0gbmFtZXMocGhlbm90eXBlcylbcGhlbm90eXBlcyA9PSBwaGVub3R5cGVdCiAgICAjIGNhdChzcHJpbnRmKHBoZW5vdHlwZV9oZWFkZXIsIHBoZW5vdHlwZV9uYW1lKSkKCiAgICAjIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiU3VtbWFyeSIpKQogICAgdGFiIDwtIHJlYWRSRFMoZmlsZS5wYXRoKAogICAgICB0YWJfcmVzX2RpciwKICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9pcmZfcHJlZGljdGlvbl9ub2h0bl9yZXN1bHRzLnJkcyIpCiAgICApKQogICAgc3ViY2h1bmtpZnkodGFiLAogICAgICBpID0gY2h1bmtfaWR4LAogICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ1N1bW1hcnkgb2YgdGhlIHZhbGlkYXRpb24gcHJlZGljdGlvbiBwZXJmb3JtYW5jZSBmcm9tIHNpUkYgb24gdGhlIG5vbi1oeXBlcnRlbnNpdmUgY29ob3J0IGFjcm9zcyB2YXJpb3VzICVzIGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzLiciLCBwaGVub3R5cGVfbmFtZSkKICAgICkKICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogICAgdGFiIDwtIHJlYWRSRFMoZmlsZS5wYXRoKAogICAgICB0YWJfcmVzX2RpciwKICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl9pcmZfcHZhbHVlc19zdW1tYXJ5X25vaHRuLnJkcyIpCiAgICApKQogICAgdGFiJHgkY29udGFpbmVyIDwtIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKICAgICAgdGFiJHgkY29udGFpbmVyLCAicC12YWx1ZSIsICJOb21pbmFsIHAtdmFsdWUiCiAgICApCiAgICBzdWJjaHVua2lmeSh0YWIsCiAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiB0aGUgbm9uLWh5cGVydGVuc2l2ZSBsby1zaVJGIHBlcm11dGF0aW9uIHRlc3QgcmVzdWx0cyBhY3Jvc3MgdmFyaW91cyAlcyBiaW5hcml6YXRpb24gdGhyZXNob2xkcyBpbmNsdWRpbmcgdGhlIHRlc3Qgc3RhdGlzdGljIChpLmUuLCBkaWZmZXJlbmNlIGluIGxvY2FsIGZlYXR1cmUgc3RhYmlsaXR5IHNjb3JlcyBiZXR3ZWVuIHRoZSBoaWdoIGFuZCB0aGUgbG93ICVzIGdyb3VwcyAoU0QgaW4gcGFyZW50aGVzZXMpIGFuZCB0aGUgcmVzdWx0aW5nIG5vbWluYWwgcC12YWx1ZXMuIFJlc3VsdHMgYXJlIHNob3duIGZvciB0aGUgbG9jaS9pbnRlcmFjdGlvbnMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgcHJpb3JpdGl6ZWQgaW4gdGhlIG9yaWdpbmFsIGxvLXNpUkYgYW5hbHlzaXMgKGluY2x1ZGluZyBib3RoIGh5cGVydGVuc2l2ZSBhbmQgbm9uLWh5cGVydGVuc2l2ZSBpbmRpdmlkdWFscykuIExvY2kvaW50ZXJhY3Rpb25zIGFyZSByYW5rZWQgYWNjb3JkaW5nIHRvIHRoZSBtZWFuIG5vbWluYWwgcC12YWx1ZSBhY3Jvc3MgYWxsIHRocmVlIGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzLiBJbnRlcmFjdGlvbnMgYmV0d2VlbiBnZW5ldGljIGxvY2kgYXJlIGhpZ2hsaWdodGVkIGluIGJsdWUuIFRoaXMgdGFibGUgaXMgYSBzdWJzZXQgb2YgdGhlIHRhYmxlIGJlbG93LiciLCBwaGVub3R5cGVfbmFtZSwgcGhlbm90eXBlX25hbWUpCiAgICApCiAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgIHRhYiA8LSByZWFkUkRTKGZpbGUucGF0aCgKICAgICAgdGFiX3Jlc19kaXIsCiAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfaXJmX3B2YWx1ZXNfc3VtbWFyeV9mdWxsX25vaHRuLnJkcyIpCiAgICApKQogICAgdGFiJHgkY29udGFpbmVyIDwtIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKICAgICAgdGFiJHgkY29udGFpbmVyLCAicC12YWx1ZSIsICJOb21pbmFsIHAtdmFsdWUiCiAgICApCiAgICBzdWJjaHVua2lmeSh0YWIsCiAgICAgIGkgPSBjaHVua19pZHgsCiAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInU3VtbWFyeSBvZiB0aGUgbm9uLWh5cGVydGVuc2l2ZSBsby1zaVJGIHBlcm11dGF0aW9uIHRlc3QgcmVzdWx0cyBhY3Jvc3MgdmFyaW91cyAlcyBiaW5hcml6YXRpb24gdGhyZXNob2xkcyBpbmNsdWRpbmcgdGhlIHRlc3Qgc3RhdGlzdGljIChpLmUuLCBkaWZmZXJlbmNlIGluIGxvY2FsIGZlYXR1cmUgc3RhYmlsaXR5IHNjb3JlcyBiZXR3ZWVuIHRoZSBoaWdoIGFuZCB0aGUgbG93ICVzIGdyb3VwcyAoU0QgaW4gcGFyZW50aGVzZXMpIGFuZCB0aGUgcmVzdWx0aW5nIG5vbWluYWwgcC12YWx1ZXMuIEJsYW5rIGNlbGxzIGluZGljYXRlIHRoYXQgdGhlIGxvY3VzL2ludGVyYWN0aW9uIHdhcyBub3Qgc2VsZWN0ZWQgZm9yIHRlc3RpbmcgZm9yIHRoZSBnaXZlbiBiaW5hcml6YXRpb24gdGhyZXNob2xkLiBMb2NpL2ludGVyYWN0aW9ucyBhcmUgcmFua2VkIGFjY29yZGluZyB0byB0aGUgbWVhbiBub21pbmFsIHAtdmFsdWUgYWNyb3NzIGFsbCB0aHJlZSBiaW5hcml6YXRpb24gdGhyZXNob2xkcy4gSW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpIGFyZSBoaWdobGlnaHRlZCBpbiBibHVlLiciLCBwaGVub3R5cGVfbmFtZSwgcGhlbm90eXBlX25hbWUpCiAgICApCiAgICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQoKICAgICMgY2F0KHNwcmludGYoc2VjdGlvbl9oZWFkZXIsICJzaVJGIEludGVyYWN0aW9uIFRhYmxlIikpCiAgICAjIGZvciAodGhyIGluIHRocnMpIHsKICAgICMgICBjYXQoc3ByaW50Zih0aHJfaGVhZGVyLCB0aHIpKQogICAgIyAgIHRhYiA8LSByZWFkUkRTKGZpbGUucGF0aCh0YWJfcmVzX2RpciwKICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiX2lyZl9pbnRlcmFjdGlvbl9ub2h0bl9yZXN1bHRzLnJkcyIpKSkKICAgICMgICBzdWJjaHVua2lmeSh0YWIsIGkgPSBjaHVua19pZHgsCiAgICAjICAgICAgICAgICAgICAgY2FwdGlvbiA9IHNwcmludGYoIidTdW1tYXJ5IG9mIHRoZSBzaVJGIGxvY3VzLWxldmVsIGludGVyYWN0aW9uIHRhYmxlIG91dHB1dCBmb3IgdGhlIGJpbmFyaXplZCAlcyBwaGVub3R5cGUgKGJpbmFyaXphdGlvbiB0aHJlc2hvbGQgPSAlcykgaW4gdGhlIG5vbi1oeXBlcnRlbnNpdmUgbG8tc2lSRiBhbmFseXNpcy4gRm9yIGFsbCBtZXRyaWNzIGV4Y2x1ZGluZyB0aGUgbG8tc2lSRiBtZWFuIHBlcm11dGF0aW9uIHAtdmFsdWUsIGhpZ2hlciB2YWx1ZXMgaW5kaWNhdGUgYSBzdHJvbmdlciBpbnRlcmFjdGlvbi4gRGV0YWlscyByZWdhcmRpbmcgdGhlc2UgbWV0cmljcyBpbiB0aGUgc2lSRiBpbnRlcmFjdGlvbiB0YWJsZSBvdXRwdXQgY2FuIGJlIGZvdW5kIGluIEt1bWJpZXIgZXQgYWwuICgyMDE4KS4nIiwgcGhlbm90eXBlX25hbWUsIHRocikpCiAgICAjICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICMgICBjYXQoIlxuXG4iKQogICAgIyB9CiAgICAjCiAgICAjIGNhdChzcHJpbnRmKHNlY3Rpb25faGVhZGVyLCAiTG9jYWwgU3RhYmlsaXR5IEltcG9ydGFuY2UgUGxvdHMgLSBJbnRlcmFjdGlvbnMiKSkKICAgICMgZm9yICh0aHIgaW4gdGhycykgewogICAgIyAgIGNhdChzcHJpbnRmKHRocl9oZWFkZXIsIHRocikpCiAgICAjICAgZm9yICh0eXBlIGluIG1ldGhvZF90eXBlcykgewogICAgIyAgICAgIyBkaXN0cmlidXRpb24gcGxvdHMKICAgICMgICAgIHBsdCA8LSByZWFkUkRTKAogICAgIyAgICAgICBmaWxlLnBhdGgoZmlnX3Jlc19kaXIsCiAgICAjICAgICAgICAgICAgICAgICBwYXN0ZTAocGhlbm90eXBlLCAiX3RociIsIHRociwKICAgICMgICAgICAgICAgICAgICAgICAgICAgICAiX2ludF9sb2NhbF9zdGFiaWxpdHlfZGlzdF8iLCB0eXBlLCAiX25vaHRuLnJkcyIpKQogICAgIyAgICAgKQogICAgIyAgICAgbnJvd3MgPC0gY2VpbGluZyhubGV2ZWxzKHBsdCRkYXRhJGludCkgLyAzKQogICAgIyAgICAgc3ViY2h1bmtpZnkocGx0LCBpID0gY2h1bmtfaWR4LCBmaWdfaGVpZ2h0ID0gRElTVF9IRUlHSFQgLyA0ICogbnJvd3MsCiAgICAjICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCIpLAogICAgIyAgICAgICAgICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICMgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInRGlzdHJpYnV0aW9uIG9mIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIHNjb3JlcyBiZXR3ZWVuIHRoZSBoaWdoIGFuZCBsb3cgJXMgZ3JvdXBzIChiaW5hcml6YXRpb24gdGhyZXNob2xkID0gJXMpIGluIHRoZSBub24taHlwZXJ0ZW5zaXZlIGxvLXNpUkYgYW5hbHlzaXMuIFJlc3VsdHMgYXJlIHNob3duIGZvciBlYWNoIHNpZ25lZCBpbnRlcmFjdGlvbiBiZXR3ZWVuIGxvY2kgKHNwZWNpZmllZCBieSBzdWJwbG90KSB0aGF0IHdhcyBwcmlvcml0aXplZCBpbiB0aGUgb3JpZ2luYWwgbG8tc2lSRiBhbmFseXNpcy4gVGhlIHBlcm11dGF0aW9uIHRlc3QgcC12YWx1ZSwgYXNzZXNzaW5nIGRpc3RyaWJ1dGlvbmFsIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGhpZ2ggYW5kIGxvdyAlcyBncm91cHMsIGlzIHByb3ZpZGVkIGluIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIGVhY2ggc3VicGxvdC4nIiwgcGhlbm90eXBlX25hbWUsIHRociwgcGhlbm90eXBlX25hbWUpKQogICAgIyAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICMgICAgIGNhdCgiXG5cbiIpCiAgICAjCiAgICAjICAgICAjIGluZGl2aWR1YWwgc25wIHBsb3RzCiAgICAjICAgICBwbHQgPC0gcmVhZFJEUygKICAgICMgICAgICAgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLAogICAgIyAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAjICAgICAgICAgICAgICAgICAgICAgICAgIl9pbnRfbG9jYWxfc3RhYmlsaXR5X3NucF9kaXN0XyIsIHR5cGUsICJfbm9odG4ucmRzIikpCiAgICAjICAgICApCiAgICAjICAgICBucm93cyA8LSBjZWlsaW5nKGxlbmd0aCh1bmlxdWUocGx0JGRhdGEkR2VuZXMpKSAvIDMpCiAgICAjICAgICBzdWJjaHVua2lmeShnZ3Bsb3RseShwbHQpLCBpID0gY2h1bmtfaWR4LCBmaWdfaGVpZ2h0ID0gRElTVF9IRUlHSFQgLyA0ICogbnJvd3MsCiAgICAjICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCIpLAogICAgIyAgICAgICAgICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICMgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInRnJlcXVlbmN5IG9mIG9jY3VycmVuY2Ugb2YgU05WLVNOViBjb21iaW5hdGlvbnMgaW4gdGhlIHNpUkYgZml0IGZvciB0aGUgYmluYXJpemVkICVzIHBoZW5vdHlwZSAoYmluYXJpemF0aW9uIHRocmVzaG9sZCA9ICVzKSBpbiB0aGUgbm9uLWh5cGVydGVuc2l2ZSBsby1zaVJGIGFuYWx5c2lzLiBTTlYtU05WIGNvbWJpbmF0aW9ucyB3aXRoIHRoZSBoaWdoZXN0IG51bWJlciBvZiBvY2N1cnJlbmNlcyBpbiB0aGUgc2lSRiBkZWNpc2lvbiBwYXRocyBjb250cmlidXRlIHRoZSBtb3N0IHRvIHRoZSBvdmVyYWxsIGxvY3VzLWxldmVsIGludGVyYWN0aW9uIGltcG9ydGFuY2UgaW4gdGhlIHNpUkYgZml0LiciLCBwaGVub3R5cGVfbmFtZSwgdGhyKSkKICAgICMgICAgIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCiAgICAjICAgICBjYXQoIlxuXG4iKQogICAgIyAgIH0KICAgICMgfQogICAgIwogICAgIyBjYXQoc3ByaW50ZihzZWN0aW9uX2hlYWRlciwgIkxvY2FsIFN0YWJpbGl0eSBJbXBvcnRhbmNlIFBsb3RzIC0gTG9jaSIpKQogICAgIyBmb3IgKHRociBpbiB0aHJzKSB7CiAgICAjICAgY2F0KHNwcmludGYodGhyX2hlYWRlciwgdGhyKSkKICAgICMgICBmb3IgKHR5cGUgaW4gbWV0aG9kX3R5cGVzKSB7CiAgICAjICAgICAjIGRpc3RyaWJ1dGlvbiBwbG90cwogICAgIyAgICAgcGx0IDwtIHJlYWRSRFMoCiAgICAjICAgICAgIGZpbGUucGF0aChmaWdfcmVzX2RpciwKICAgICMgICAgICAgICAgICAgICAgIHBhc3RlMChwaGVub3R5cGUsICJfdGhyIiwgdGhyLAogICAgIyAgICAgICAgICAgICAgICAgICAgICAgICJfbG9jYWxfc3RhYmlsaXR5X2Rpc3RfIiwgdHlwZSwgIl9ub2h0bi5yZHMiKSkKICAgICMgICAgICkKICAgICMgICAgIG5yb3dzIDwtIGNlaWxpbmcobmxldmVscyhwbHQkZGF0YSRmZWF0dXJlKSAvIDQpCiAgICAjICAgICBzdWJjaHVua2lmeShwbHQsIGkgPSBjaHVua19pZHgsIGZpZ19oZWlnaHQgPSBESVNUX0hFSUdIVCAvIDQgKiBucm93cywKICAgICMgICAgICAgICAgICAgICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQiKSwKICAgICMgICAgICAgICAgICAgICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICAjICAgICAgICAgICAgICAgICBjYXB0aW9uID0gc3ByaW50ZigiJ0Rpc3RyaWJ1dGlvbiBvZiBsb2NhbCBzdGFiaWxpdHkgaW1wb3J0YW5jZSBzY29yZXMgYmV0d2VlbiB0aGUgaGlnaCBhbmQgbG93ICVzIGdyb3VwcyAoYmluYXJpemF0aW9uIHRocmVzaG9sZCA9ICVzKSBpbiB0aGUgbm9uLWh5cGVydGVuc2l2ZSBsby1zaVJGIGFuYWx5c2lzLiBSZXN1bHRzIGFyZSBzaG93biBmb3IgZWFjaCBzaWduZWQgbG9jdXMgKHNwZWNpZmllZCBieSBzdWJwbG90KSB0aGF0IHdhcyBwcmlvcml0aXplZCBpbiB0aGUgb3JpZ2luYWwgbG8tc2lSRiBhbmFseXNpcy4gVGhlIHBlcm11dGF0aW9uIHRlc3QgcC12YWx1ZSwgYXNzZXNzaW5nIGRpc3RyaWJ1dGlvbmFsIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGhpZ2ggYW5kIGxvdyAlcyBncm91cHMsIGlzIHByb3ZpZGVkIGluIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIGVhY2ggc3VicGxvdC4nIiwgcGhlbm90eXBlX25hbWUsIHRociwgcGhlbm90eXBlX25hbWUpKQogICAgIyAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICMgICAgIGNhdCgiXG5cbiIpCiAgICAjCiAgICAjICAgICAjIGluZGl2aWR1YWwgc25wIHBsb3RzCiAgICAjICAgICBwbHQgPC0gcmVhZFJEUygKICAgICMgICAgICAgZmlsZS5wYXRoKGZpZ19yZXNfZGlyLAogICAgIyAgICAgICAgICAgICAgICAgcGFzdGUwKHBoZW5vdHlwZSwgIl90aHIiLCB0aHIsCiAgICAjICAgICAgICAgICAgICAgICAgICAgICAgIl9sb2NhbF9zdGFiaWxpdHlfc25wX2Rpc3RfIiwgdHlwZSwgIl9ub2h0bi5yZHMiKSkKICAgICMgICAgICkKICAgICMgICAgIG5yb3dzIDwtIGNlaWxpbmcobGVuZ3RoKHVuaXF1ZShwbHQkZGF0YSRHZW5lKSkgLyAzKQogICAgIyAgICAgc3ViY2h1bmtpZnkoZ2dwbG90bHkocGx0LCB0b29sdGlwID0gYygieSIsICJ0ZXh0IikpLCBpID0gY2h1bmtfaWR4LCBmaWdfaGVpZ2h0ID0gRElTVF9IRUlHSFQgLyA0ICogbnJvd3MsCiAgICAjICAgICAgICAgICAgICAgICBhZGRfY2xhc3MgPSBjKCJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCIpLAogICAgIyAgICAgICAgICAgICAgICAgb3RoZXJfYXJncyA9ICJvdXQud2lkdGg9JzEwMCUnIiwKICAgICMgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBzcHJpbnRmKCInRnJlcXVlbmN5IG9mIG9jY3VycmVuY2Ugb2YgU05WcyBpbiB0aGUgc2lSRiBmaXQgZm9yIHRoZSBiaW5hcml6ZWQgJXMgcGhlbm90eXBlIChiaW5hcml6YXRpb24gdGhyZXNob2xkID0gJXMpIGluIHRoZSBub24taHlwZXJ0ZW5zaXZlIGxvLXNpUkYgYW5hbHlzaXMuIFNOVnMgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgaW4gdGhlIHNpUkYgZGVjaXNpb24gcGF0aHMgY29udHJpYnV0ZSB0aGUgbW9zdCB0byB0aGUgb3ZlcmFsbCBsb2N1cy1sZXZlbCBpbXBvcnRhbmNlIGluIHRoZSBzaVJGIGZpdC4gU05WcyBhcmUgb3JkZXJlZCBvbiB0aGUgeC1heGlzIGJ5IGdlbm9taWMgbG9jYXRpb24uJyIsIHBoZW5vdHlwZV9uYW1lLCB0aHIpKQogICAgIyAgICAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKICAgICMgICAgIGNhdCgiXG5cbiIpCiAgICAjICAgfQogICAgIyB9CiAgfQp9CmBgYAoKIyBDb21wYXJpc29uIHRvIEV4aXN0aW5nIE1ldGhvZHMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtdm1vZGVybn0KCiMjIEVwaXN0YXNpcyBEZXRlY3Rpb24gTWV0aG9kcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpJbiB0aGlzIHNlY3Rpb24sIHdlIGNvbXBhcmUgdGhlIGxvLXNpUkYtcHJpb3JpdGl6ZWQgaW50ZXJhY3Rpb25zIGJldHdlZW4gbG9jaSB0byB0aG9zZSBpbnRlcmFjdGlvbnMgcHJpb3JpdGl6ZWQgYnkgb3RoZXIgZXhpc3RpbmcgZXBpc3Rhc2lzIGRldGVjdGlvbiBtZXRob2RzLCBuYW1lbHksIGFuIGV4aGF1c3RpdmUgcGFpcndpc2UgaW50ZXJhY3Rpb24gc2VhcmNoIHZpYSBsaW5lYXIgKG9yIGxvZ2lzdGljKSByZWdyZXNzaW9uLCBNQVBJVCBbQGNyYXdmb3JkMjAxN2RldGVjdGluZ10sIGFuZCBhIGxvY3VzLWxldmVsIHZlcnNpb24gb2YgTUFQSVQgd2hlcmUgd2UgY29tYmluZWQgTUFQSVQgYW5kIGdlbmUgc2V0IGVucmljaG1lbnQgYW5hbHlzaXMgKEdTRUEpIFtAc3VicmFtYW5pYW4yMDA1Z2VuZTsgQG1vb3RoYTIwMDNwZ2NdLgo8L2Rpdj4KCiMjIyBSZWdyZXNzaW9uLWJhc2VkIHBhaXJ3aXNlIGludGVyYWN0aW9uIHNjYW4gey51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1waWxscyAudGFic2V0LWNpcmNsZX0KCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KQmVsb3csIHdlIHByZXNlbnQgdGhlIHJlc3VsdHMgZnJvbSBjb25kdWN0aW5nIGFuIGV4aGF1c3RpdmUgcGFpcndpc2UgaW50ZXJhY3Rpb24gc2NhbiB1c2luZyBsaW5lYXIgKG9yIGxvZ2lzdGljKSByZWdyZXNzaW9uIG92ZXIgYWxsIEdXQVMtZmlsdGVyZWQgU05WcyB3aXRoIGEgbWlub3IgYWxsZWxlIGZyZXF1ZW5jeSA+IDAuMDUuIApJbiB0aGlzIGV4aGF1c3RpdmUgaW50ZXJhY3Rpb24gc2VhcmNoLCB0aGVyZSBhcmUgZm91ciBkaWZmZXJlbnQgdHJhbnNmb3JtYXRpb25zIG9mIHRoZSBMVk1pIHJlc3BvbnNlL3BoZW5vdHlwZSB0aGF0IGFyZSBvZiBpbnRlcmVzdCAtLS0gbmFtZWx5LCB0aGUgcmFuay1iYXNlZCBpbnZlcnNlIG5vcm1hbC10cmFuc2Zvcm1lZCAoUklOVCkgTFZNaSAoZml0dGVkIHVzaW5nIGxpbmVhciByZWdyZXNzaW9uKSBhbmQgdGhlIGJpbmFyaXplZCBMVk1pIGF0IHRocmVlIGRpZmZlcmVudCB0aHJlc2hvbGRzICgwLjE1LCAwLjIsIGFuZCAwLjI1KSAoZml0dGVkIHVzaW5nIGxvZ2lzdGljIHJlZ3Jlc3Npb24pLiAKRGV0YWlscyByZWdhcmRpbmcgdGhlIG1ldGhvZG9sb2d5IGNhbiBiZSBmb3VuZCBpbiBbQHdhbmcyMDIzZXBpc3Rhc2lzXShodHRwczovL3d3dy5tZWRyeGl2Lm9yZy9jb250ZW50LzEwLjExMDEvMjAyMy4xMS4wNi4yMzI5Nzg1OHYxKS4KCi0gSW4gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay04NCksIHdlIGV4YW1pbmVkIHRoZSBzdGFiaWxpdHkgb2YgdGhlIHRvcCByYW5rZWQgU05WLVNOViBpbnRlcmFjdGlvbnMgKGkuZS4sIHRob3NlIHdpdGggdGhlIHNtYWxsZXN0IHAtdmFsdWVzIGZvciB0aGUgaW50ZXJhY3Rpb24gdGVybSkgYWNyb3NzIHRoZSBkaWZmZXJlbnQgY2hvaWNlcyBvZiBMVk1pIHJlc3BvbnNlIChpLmUuLCBSSU5UIG9yIG9uZSBvZiB0aGUgYmluYXJpemVkIHZlcnNpb25zKS4gV2hpbGUgdGhlcmUgaXMgc29tZSBwb3NpdGl2ZSBjb3JyZWxhdGlvbiBhY3Jvc3MgdGhlIGRpZmZlcmVudCBiaW5hcml6YXRpb24gcnVucywgd2UgZm91bmQgdGhhdCB0aGVyZSBpcyB2ZXJ5IGxpdHRsZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBwcmlvcml0aXplZCBpbnRlcmFjdGlvbnMgd2hlbiB1c2luZyB0aGUgUklOVC10cmFuc2Zvcm1lZCBMVk1pIHZlcnN1cyB0aGUgYmluYXJpemVkIExWTWkgYXMgdGhlIHJlc3BvbnNlLgogIC0gV2Ugbm90ZSB0aGF0IHRoZSBleGhhdXN0aXZlIGludGVyYWN0aW9uIHNlYXJjaCB3YXMgYWxzbyBjb25kdWN0ZWQgdXNpbmcgYWxsIDE0MDUgR1dBUy1maWx0ZXJlZCBTTlZzIHdpdGhvdXQgdGhlIG1pbm9yIGFsbGVsZSBmcmVxdWVuY3kgZmlsdGVyLiBIb3dldmVyLCB0aGlzIGxlZCB0byBldmVuIGdyZWF0ZXIgaW5zdGFiaWxpdHkuIFdlIGhlbmNlIG9taXQgdGhlc2UgcmVzdWx0cyBhbmQgZm9jdXMgb24gdGhlIHJlc3VsdHMgYWZ0ZXIgcmVzdHJpY3RpbmcgdG8gU05WcyB3aXRoIGEgbWlub3IgYWxsZWxlIGZyZXF1ZW5jeSA+IDAuMDUuCi0gSW4gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay04NSksIHdlIHByb3ZpZGUgYSB0YWJsZSBvZiB0aGUgU05WLVNOViBpbnRlcmFjdGlvbnMgYW5kIHRoZWlyIGNvcnJlc3BvbmRpbmcgaW50ZXJhY3Rpb24gdGVybSBwLXZhbHVlcyBmb3IgZWFjaCBjaG9pY2Ugb2YgTFZNaSByZXNwb25zZS4gV2Ugc2hvdyBvbmx5IHRob3NlIFNOVi1TTlYgaW50ZXJhY3Rpb25zIHdpdGggYSBwLXZhbHVlIDwgMC4wMSBmb3IgYXQgbGVhc3Qgb25lIG9mIHRoZSBMVk1pIHJlc3BvbnNlcy4KICAtIFdlIG5vdGUgdGhhdCBub25lIG9mIHRoZSBTTlYtU05WIGludGVyYWN0aW9ucyBtZXQgdGhlICRcYWxwaGEgPSAwLjA1JCBzaWduaWZpY2FuY2UgdGhyZXNob2xkIGFmdGVyIHBlcmZvcm1pbmcgYSBCb25mZXJyb25pIG11bHRpcGxlIHRlc3RpbmcgYWRqdXN0bWVudC4gCiAgLSBTdGlsbCwgb25lIGNvdWxkIGluIHRoZW9yeSB1c2UgdGhlIHAtdmFsdWVzIGZvciByYW5raW5nIFNOVi1TTlYgaW50ZXJhY3Rpb25zLiBGb3IgdGhlIHVuYmluYXJpemVkIFJJTlQtdHJhbnNmb3JtZWQgTFZNaSByZXNwb25zZSwgdGhlIHRvcCBpbnRlcmFjdGlvbiB3YXMgYmV0d2VlbiByczEwMjI3MzkzIChjaHJvbW9zb21lIDc7ICpUUEsxO0NOVE5BUDIqIGxvY3VzKSBhbmQgcnM4MDc2MjQ4IChjaHJvbW9zb21lIDE3OyAqQ0ZBUDUyKiBsb2N1cykuIEZvciB0aGUgYmluYXJpemVkIExWTWkgcmVzcG9uc2UgdXNpbmcgYm90aCB0aGUgMTUlIGFuZCAyNSUgdGhyZXNob2xkcywgdGhlIHRvcCBpbnRlcmFjdGlvbiB3YXMgYmV0d2VlbiByczMxNzYzMjMgKGNocm9tb3NvbWUgNjsgKkNES04xQSogbG9jdXMpIGFuZCByczEyNzk1MDc2IChjaHJvbW9zb21lIDExOyAqS0lSUkVMMyogbG9jdXMpLiBUbyBvdXIga25vd2xlZGdlLCB0aGVzZSBsb2NpIGFyZSBub3Qga25vd24gdG8gYmUgY2xvc2VseSByZWxhdGVkIHRvIGh5cGVydHJvcGh5LiBPbmx5IGZvciB0aGUgYmluYXJpemVkIExWTWkgcmVzcG9uc2Ugd2l0aCB0aGUgMjAlIHRocmVzaG9sZCBkbyB3ZSBvYnRhaW4gYSB0b3AgaW50ZXJhY3Rpb24gaW52b2x2aW5nIG9uZSBvZiB0aGUgbG8tc2lSRi1wcmlvcml0aXplZCBsb2NpLiBIZXJlLCB0aGUgdG9wIGludGVyYWN0aW9uIGlzIGJldHdlZW4gcnMxMjYxODg3MSAoY2hyb21vc29tZSAyOyAqQ0NEQzE0MSogbG9jdXMpIGFuZCByczkyNjczNTYgKGNocm9tb3NvbWUgNjsgKk1JQ0IqIGxvY3VzKS4gCgpUaGVzZSBkaWZmZXJlbmNlcyBpbiB0aGUgdG9wIGludGVyYWN0aW9ucyBhY3Jvc3MgdGhlIGRpZmZlcmVudCBMVk1pIHJlc3BvbnNlcyBmdXJ0aGVyIGhpZ2hsaWdodCB0aGUgaW5zdGFiaWxpdHkgb2YgdGhlIHJlZ3Jlc3Npb24tYmFzZWQgcGFpcndpc2UgaW50ZXJhY3Rpb24gc2Nhbi4gVGhpcyBpbnN0YWJpbGl0eSBwb3NlcyBpc3N1ZXMgaW4gaW50ZXJwcmV0aW5nIHJlc3VsdHMsIGFzIGl0IGNhbiBiZSB1bmNsZWFyIHdoaWNoIHJlc3VsdHMgdG8gdHJ1c3QuIFdlIHN1c3BlY3QgdGhhdCBhdCBsZWFzdCBwYXJ0IG9mIHRoZSBpbnN0YWJpbGl0eSBpcyBhIHJlc3VsdCBvZiB0aGUgbG93IHNpZ25hbC10by1ub2lzZSByYXRpbyBpbiB0aGlzIHByb2JsZW0gYW5kIGhpZ2hsaWdodHMgdGhlIG5lZWQgZm9yIG1vcmUgcm9idXN0IGFuZCBzdGFiaWxpdHktZHJpdmVuIG1ldGhvZHMsIHN1Y2ggYXMgbG8tc2lSRiwgZm9yIGRldGVjdGluZyBlcGlzdGFzaXMgaW4gbG93IHNpZ25hbC10by1ub2lzZSByZWdpbWVzLgogIAo8L2Rpdj4KCmBgYHtyIHBhaXJ3aXNlLWludGVyYWN0aW9uLXNjYW4sIHJlc3VsdHMgPSAiYXNpcyJ9CnRocl9oZWFkZXIgPC0gIlxuXG4jIyMjICVzXG5cbiIKCnBoZW5vX25hbWVzIDwtIGMoCiAgImlMVk1fbm9ybSIsCiAgImlMVk1fYmluYXJ5X3RocjAuMTUiLAogICJpTFZNX2JpbmFyeV90aHIwLjIiLAogICJpTFZNX2JpbmFyeV90aHIwLjI1IgopCgppZiAocGFyYW1zJGV2YWwpIHsKICBtYWZfZGYgPC0gZGF0YS50YWJsZTo6ZnJlYWQoCiAgICBmaWxlLnBhdGgoZGF0YV9kaXIsICJwbGlua19kYXRhIiwgIkhUTl90cmFpbmluZy5mcnEiKQogICkgJT4lCiAgICB0aWJibGU6OmFzX3RpYmJsZSgpCiAgcm1fc25wcyA8LSBtYWZfZGYgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKE1BRiA8IDAuMDUpICU+JQogICAgZHBseXI6OmxlZnRfam9pbihzbnBzX2RmLCBieSA9IGMoIlNOUCIgPSAicnNJRCIpKSAlPiUKICAgIGRwbHlyOjpwdWxsKE5hbWUpCgogIHJlc3VsdHNfbHMgPC0gbGlzdCgpCiAgZm9yIChwaGVub19uYW1lIGluIHBoZW5vX25hbWVzKSB7CiAgICByZXN1bHRzIDwtIHJlYWRSRFMoCiAgICAgIGZpbGUucGF0aCgKICAgICAgICByZXNfZGlyLCAiZXBpc3Rhc2lzX2NvbXBhcmlzb25zIiwgIm1hbnVhbCIsCiAgICAgICAgc3ByaW50ZigiJXNfc25weHNucF9zY2FuLnJkcyIsIHBoZW5vX25hbWUpCiAgICAgICkKICAgICkgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgIShzbnAxX25hbWUgJWluJSBybV9zbnBzKSwgIShzbnAyX25hbWUgJWluJSBybV9zbnBzKQogICAgICApCiAgICBzbnBzX2RmMSA8LSBsb2FkU05QSW5mbyh1bmlxdWUocmVzdWx0cyRzbnAxX25hbWUpKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChOYW1lLCByc0lEMSA9IHJzSUQpCiAgICBzbnBzX2RmMiA8LSBsb2FkU05QSW5mbyh1bmlxdWUocmVzdWx0cyRzbnAyX25hbWUpKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChOYW1lLCByc0lEMiA9IHJzSUQpCiAgICByZXN1bHRzIDwtIHJlc3VsdHMgJT4lCiAgICAgIGRwbHlyOjpsZWZ0X2pvaW4oc25wc19kZjEsIGJ5ID0gYygic25wMV9uYW1lIiA9ICJOYW1lIikpICU+JQogICAgICBkcGx5cjo6bGVmdF9qb2luKHNucHNfZGYyLCBieSA9IGMoInNucDJfbmFtZSIgPSAiTmFtZSIpKQoKICAgIHJlc3VsdHNfbHNbW3BoZW5vX25hbWVdXSA8LSByZXN1bHRzICU+JQogICAgICBkcGx5cjo6c2VsZWN0KAogICAgICAgIGBTTlAxIHJzSURgID0gcnNJRDEsIGBTTlAxIENocmAsIGBTTlAxIExvY3VzYCA9IGBTTlAxIEdlbmVgLAogICAgICAgIGBTTlAyIHJzSURgID0gcnNJRDIsIGBTTlAyIENocmAsIGBTTlAyIExvY3VzYCA9IGBTTlAyIEdlbmVgLAogICAgICAgIGBTTlAxeFNOUDIgSW50ZXJhY3Rpb24gcC12YWx1ZWAgPSBgc25wMTpzbnAyYAogICAgICApCiAgfQoKICBhZ2dfcmVzdWx0c19scyA8LSBwdXJycjo6aW1hcCgKICAgIHJlc3VsdHNfbHMsCiAgICB+IC54ICU+JQogICAgICBkcGx5cjo6bXV0YXRlKAogICAgICAgIG9yZGVyID0gcHVycnI6Om1hcDIoCiAgICAgICAgICBgU05QMSBMb2N1c2AsIGBTTlAyIExvY3VzYCwKICAgICAgICAgIH4gcmFuayhjKC54LCAueSkpCiAgICAgICAgKSwKICAgICAgICByc0lEID0gcHVycnI6OnBtYXBfY2hyKAogICAgICAgICAgbGlzdChzbnAxID0gYFNOUDEgcnNJRGAsIHNucDIgPSBgU05QMiByc0lEYCwgb3JkZXIgPSBvcmRlciksCiAgICAgICAgICBmdW5jdGlvbihzbnAxLCBzbnAyLCBvcmRlcikgewogICAgICAgICAgICBwYXN0ZShjKHNucDEsIHNucDIpW29yZGVyXSwgY29sbGFwc2UgPSAiLSIpCiAgICAgICAgICB9CiAgICAgICAgKSwKICAgICAgICBMb2N1cyA9IHB1cnJyOjpwbWFwX2NocigKICAgICAgICAgIGxpc3Qoc25wMSA9IGBTTlAxIExvY3VzYCwgc25wMiA9IGBTTlAyIExvY3VzYCwgb3JkZXIgPSBvcmRlciksCiAgICAgICAgICBmdW5jdGlvbihzbnAxLCBzbnAyLCBvcmRlcikgewogICAgICAgICAgICBwYXN0ZShjKHNucDEsIHNucDIpW29yZGVyXSwgY29sbGFwc2UgPSAiLSIpCiAgICAgICAgICB9CiAgICAgICAgKSwKICAgICAgICBDaHIgPSBwdXJycjo6cG1hcF9jaHIoCiAgICAgICAgICBsaXN0KHNucDEgPSBgU05QMSBDaHJgLCBzbnAyID0gYFNOUDIgQ2hyYCwgb3JkZXIgPSBvcmRlciksCiAgICAgICAgICBmdW5jdGlvbihzbnAxLCBzbnAyLCBvcmRlcikgewogICAgICAgICAgICBwYXN0ZShjKHNucDEsIHNucDIpW29yZGVyXSwgY29sbGFwc2UgPSAiLSIpCiAgICAgICAgICB9CiAgICAgICAgKQogICAgICApICU+JQogICAgICBkcGx5cjo6c2VsZWN0KHJzSUQsIExvY3VzLCBDaHIsIGBTTlAxeFNOUDIgSW50ZXJhY3Rpb24gcC12YWx1ZWApICU+JQogICAgICBkcGx5cjo6YXJyYW5nZShgU05QMXhTTlAyIEludGVyYWN0aW9uIHAtdmFsdWVgKSAlPiUKICAgICAgZHBseXI6OnJlbmFtZSgKICAgICAgICB7eyAueSB9fSA6PSBgU05QMXhTTlAyIEludGVyYWN0aW9uIHAtdmFsdWVgCiAgICAgICkgJT4lCiAgICAgIGRwbHlyOjpkaXN0aW5jdChyc0lELCAua2VlcF9hbGwgPSBUUlVFKQogICkKCiAgcmVzdWx0c19kZiA8LSBwdXJycjo6cmVkdWNlKAogICAgYWdnX3Jlc3VsdHNfbHMsIGRwbHlyOjpmdWxsX2pvaW4sCiAgICBieSA9IGMoInJzSUQiLCAiTG9jdXMiLCAiQ2hyIikKICApICU+JQogICAgZHBseXI6OnJvd3dpc2UoKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIG1lYW5fcCA9IG1lYW4oZHBseXI6OmNfYWNyb3NzKGBpTFZNX25vcm1gOmBpTFZNX2JpbmFyeV90aHIwLjI1YCkpCiAgICApICU+JQogICAgZHBseXI6OnVuZ3JvdXAoKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKG1lYW5fcCkgJT4lCiAgICBuYS5vbWl0KCkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKAogICAgICBpTFZNX25vcm0gPCAwLjAxIHwKICAgICAgICBpTFZNX2JpbmFyeV90aHIwLjE1IDwgMC4wMSB8CiAgICAgICAgaUxWTV9iaW5hcnlfdGhyMC4yIDwgMC4wMSB8CiAgICAgICAgaUxWTV9iaW5hcnlfdGhyMC4yNSA8IDAuMDEKICAgICkKCiAgIyBzYXZlUkRTKAogICMgICByZXN1bHRzX2RmLAogICMgICBmaWxlID0gZmlsZS5wYXRoKHJlc19kaXIsICJlcGlzdGFzaXNfY29tcGFyaXNvbnMiLCAibWFudWFsIiwgImlMVk1fc25weHNucF9zY2FuX3Jlc3VsdHMucmRzIikKICAjICkKfSBlbHNlIHsKICByZXN1bHRzX2RmIDwtIHJlYWRSRFMoCiAgICBmaWxlLnBhdGgocmVzX2RpciwgImVwaXN0YXNpc19jb21wYXJpc29ucyIsICJtYW51YWwiLCAiaUxWTV9zbnB4c25wX3NjYW5fcmVzdWx0cy5yZHMiKQogICkgJT4lCiAgICBkcGx5cjo6cmVuYW1lKAogICAgICBgTFZNaSAoUklOVClgID0gaUxWTV9ub3JtLAogICAgICBgTFZNaSAoQmluYXJpemF0aW9uID0gMC4xNSlgID0gaUxWTV9iaW5hcnlfdGhyMC4xNSwKICAgICAgYExWTWkgKEJpbmFyaXphdGlvbiA9IDAuMilgID0gaUxWTV9iaW5hcnlfdGhyMC4yLAogICAgICBgTFZNaSAoQmluYXJpemF0aW9uID0gMC4yNSlgID0gaUxWTV9iaW5hcnlfdGhyMC4yNSwKICAgICAgYE1lYW4gcC12YWx1ZWAgPSBtZWFuX3AKICAgICkKICBwbHQgPC0gcmVzdWx0c19kZiAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIGRwbHlyOjphY3Jvc3ModGlkeXNlbGVjdDo6c3RhcnRzX3dpdGgoIkxWTWkiKSwgfiAtbG9nMTAoLngpKQogICAgKSAlPiUKICAgIHZkb2NzOjpwbG90X3BhaXJzKAogICAgICBjb2x1bW5zID0gY29sbmFtZXMocmVzdWx0c19kZilbCiAgICAgICAgc3RyaW5ncjo6c3RyX3N0YXJ0cyhjb2xuYW1lcyhyZXN1bHRzX2RmKSwgIkxWTWkiKQogICAgICBdCiAgICApCiAgc3ViY2h1bmtpZnkoCiAgICBwbHQsCiAgICBpID0gY2h1bmtfaWR4LCBmaWdfaGVpZ2h0ID0gOCwKICAgIGFkZF9jbGFzcyA9IGMoInBhbmVsIHBhbmVsLWRlZmF1bHQiKSwKICAgIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgICBjYXB0aW9uID0gIicqKlBhaXIgcGxvdCBvZiB0aGUgTFZNaSBpbnRlcmFjdGlvbiBlZmZlY3QgcC12YWx1ZXMgZnJvbSBhbiBleGhhdXN0aXZlIHJlZ3Jlc3Npb24tYmFzZWQgU05WeFNOViBpbnRlcmFjdGlvbiBzY2FuIHVzaW5nIGRpZmZlcmVudCB0cmFuc2Zvcm1hdGlvbnMgb2YgdGhlIExWTWkgcGhlbm90eXBlLioqIFRoZSB0cmFuc2Zvcm1hdGlvbnMgb2YgaW50ZXJlc3QgaW5jbHVkZSB0aGUgcmFuay1iYXNlZCBpbnZlcnNlIG5vcm1hbC10cmFuc2Zvcm1lZCBMVk1pIGFuZCB0aGUgYmluYXJpemVkIExWTWkgdXNpbmcgdGhyZWUgZGlmZmVyZW50IGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzICgxNSUsIDIwJSwgMjUlKS4gVGhlIHgtIGFuZCB5LWF4ZXMgc2hvdyB0aGUgaW50ZXJhY3Rpb24gZWZmZWN0IHAtdmFsdWVzIGFmdGVyIGEgLWxvZzEwIHRyYW5zZm9ybWF0aW9uLiBFYWNoIHBvaW50IHJlcHJlc2VudHMgYW4gU05WLVNOViBwYWlyLiBXZSBvYnNlcnZlIHRoYXQgdGhlIGludGVyYWN0aW9uIGVmZmVjdCBwLXZhbHVlcyBhcmUgZ2VuZXJhbGx5IHVuc3RhYmxlIGFuZCBkZXBlbmQgb24gdGhlIGNob2ljZSBvZiB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgcGhlbm90eXBlIChvciByZXNwb25zZSkuJyIKICApCiAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKCiAgdGFiIDwtIHByZXR0eV9EVChyZXN1bHRzX2RmKQogIHN1YmNodW5raWZ5KHRhYiwKICAgIGkgPSBjaHVua19pZHgsCiAgICBjYXB0aW9uID0gIicqKkxpc3Qgb2YgU05WLVNOViBpbnRlcmFjdGlvbnMgZnJvbSBhbiBleGhhdXN0aXZlIHJlZ3Jlc3Npb24tYmFzZWQgU05WeFNOViBpbnRlcmFjdGlvbiBzY2FuIHVzaW5nIGRpZmZlcmVudCB0cmFuc2Zvcm1hdGlvbnMgb2YgdGhlIExWTWkgcGhlbm90eXBlLioqIFRoZSB0cmFuc2Zvcm1hdGlvbnMgb2YgaW50ZXJlc3QgaW5jbHVkZSB0aGUgcmFuay1iYXNlZCBpbnZlcnNlIG5vcm1hbC10cmFuc2Zvcm1lZCBMVk1pIGFuZCB0aGUgYmluYXJpemVkIExWTWkgdXNpbmcgdGhyZWUgZGlmZmVyZW50IGJpbmFyaXphdGlvbiB0aHJlc2hvbGRzICgxNSUsIDIwJSwgMjUlKS4gVGhlIHRhYmxlIHNvcnRzIHRoZSBTTlYtU05WIGludGVyYWN0aW9ucyBiYXNlZCBvbiB0aGUgbWVhbiBwLXZhbHVlIGFjcm9zcyB0aGUgZGlmZmVyZW50IHRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgTFZNaSBwaGVub3R5cGUuIFRvIHNvcnQgdGhlIFNOVi1TTlYgaW50ZXJhY3Rpb25zIGJhc2VkIHVwb24gdGhlaXIgcC12YWx1ZSBmcm9tIGEgcGFydGljdWxhciB0cmFuc2Zvcm1hdGlvbiwgcGxlYXNlIHVzZSB0aGUgdG9nZ2xlcyBuZXh0IHRvIHRoZSBjb2x1bW4gbmFtZXMuIE9ubHkgaW50ZXJhY3Rpb25zIHRoYXQgeWllbGRlZCBhIHAtdmFsdWUgPCAwLjAxIGZvciBhdCBsZWFzdCBvbmUgdHJhbnNmb3JtYXRpb24gb2YgdGhlIExWTWkgcGhlbm90eXBlIGFyZSBzaG93biBmb3IgYnJldml0eS4nIgogICkKICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQp9CmBgYAoKIyMjIE1BUElUIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1jaXJjbGV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CkdpdmVuIHRoZSBpbnN0YWJpbGl0aWVzIG9ic2VydmVkIGluIHRoZSBleGhhdXN0aXZlIHJlZ3Jlc3Npb24tYmFzZWQgaW50ZXJhY3Rpb24gc2VhcmNoLCB3ZSBhcHBsaWVkIE1BUElUIFtAY3Jhd2ZvcmQyMDE3ZGV0ZWN0aW5nXSB0byBvdXIgZGF0YXNldCBhcyBhbiBhZGRpdGlvbmFsIGNvbXBhcmlzb24gbWV0aG9kLiBBdCBhIGhpZ2gtbGV2ZWwsIE1BUElUIGFpbXMgdG8gaWRlbnRpZnkgdmFyaWFudHMgd2l0aCBub24temVybyBtYXJnaW5hbCBlcGlzdGF0aWMgZWZmZWN0cywgZGVmaW5lZCBhcyB0aGUgdG90YWwgcGFpcndpc2UgaW50ZXJhY3Rpb24gZWZmZWN0IGJldHdlZW4gdGhlIGdpdmVuIHZhcmlhbnQgYW5kIGFsbCBvdGhlciB2YXJpYW50cyBpbiB0aGUgZGF0YS4KClNpbWlsYXIgdG8gYmVmb3JlLCB3ZSB1c2VkIHRoZSBHV0FTLWZpbHRlcmVkIFNOVnMgd2l0aCBtaW5vciBhbGxlbGUgZnJlcXVlbmN5ID4gMC4wNSBhcyBpbnB1dCB0byBNQVBJVC4gRm9yIHRoZSByZXNwb25zZSwgd2UgdXNlZCB0aGUgcmFuay1iYXNlZCBpbnZlcnNlIG5vcm1hbC10cmFuc2Zvcm1lZCBMVk1pIG9ubHkgc2luY2UgdGhlIE1BUElUIGV4dGVuc2lvbiB0byBiaW5hcnkgdHJhaXRzIGhhcyBub3QgeWV0IGJlZW4gaW1wbGVtZW50ZWQuIERldGFpbHMgcmVnYXJkaW5nIHRoZSBtZXRob2RvbG9neSBjYW4gYmUgZm91bmQgaW4gW0B3YW5nMjAyM2VwaXN0YXNpc10oaHR0cHM6Ly93d3cubWVkcnhpdi5vcmcvY29udGVudC8xMC4xMTAxLzIwMjMuMTEuMDYuMjMyOTc4NTh2MSkuCgogIC0gTm90ZTogd2UgYWxzbyB0cmllZCBhcHBseWluZyBNQVBJVCB0byB0aGUgZnVsbCBzZXQgb2YgMTQwNSBHV0FTLWZpbHRlcmVkIFNOVnMgKHdpdGhvdXQgdGhlIGFkZGl0aW9uYWwgbWlub3IgYWxsZWxlIGZyZXF1ZW5jeSBmaWx0ZXIpLiBIb3dldmVyLCB0aGUgcmVzdWx0aW5nIHRvcCBTTlZzIHdlcmUgcHJlZG9taW5hbnRseSB0aG9zZSB3aXRoIHRoZSBzbWFsbGVzdCBtaW5vciBhbGxlbGUgZnJlcXVlbmNpZXMsIGFuZCB3ZSBvbWl0IHRoZXNlIHJlc3VsdHMuCgpUaGUgdG9wIDUgU05WcyBmcm9tIE1BUElUIHdpdGggdGhlIHNtYWxsZXN0IHAtdmFsdWVzIHdlcmUgbG9jYXRlZCBpbiB0aGUgKk1BVDJCO0xJTkMwMjE0MyosICpNSUNCKiwgKkJSTVMxTDtMSU5DMDA2MDkqLCBhbmQgKkNES04xQSogbG9jaSAoRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay04NikpLiBJbnRlcmVzdGluZ2x5LCB0aGUgaGlnaGVzdC1yYW5rZWQgU05WcyBmcm9tIHRoZSAqQ0NEQzE0MSosICpUVE4qLCBhbmQgKklHRjFSKiBsb2NpIHdlcmUgcmFua2VkIDEwOSAocCA9IDAuMDI4KSwgNzUgKHAgPSAwLjAwMyksIGFuZCA4NyAocCA9IDAuMDExKSwgcmVzcGVjdGl2ZWx5IChjb21wYXJlZCB0byBwIDwgOEUtNSBmb3IgdGhlIHRvcCA1IFNOVnMpLCBhY2NvcmRpbmcgdG8gTUFQSVQuIAoKQXMgaXMsIHRoZSByZXN1bHRzIGZyb20gTUFQSVQgYW5kIGxvLXNpUkYgYXJlIG5vdCBkaXJlY3RseSBjb21wYXJhYmxlIHNpbmNlIHRoZXkgYXJlIG9wZXJhdGluZyBhdCBkaWZmZXJlbnQgYmlvbG9naWNhbCBzY2FsZXMgKGkuZS4sIE1BUElUIGFpbXMgdG8gaWRlbnRpZnkgZXBpc3RhdGljIHZhcmlhbnRzIHdoaWxlIGxvLXNpUkYgYWltcyB0byBpZGVudGlmeSBlcGlzdGF0aWMgbG9jaSkuIFZhcmlhbnQtbGV2ZWwgYXBwcm9hY2hlcyBhcmUga25vd24gdG8gYmUgdW5kZXItcG93ZXJlZCBpbiB0cmFpdHMgd2hlcmUgdGhlIGVmZmVjdCBvZiBlYWNoIHZhcmlhbnQgaXMgdmVyeSBzbWFsbCBhbmQvb3Igbm9pc3kgd2hpbGUgZ3JvdXAtbGV2ZWwgKG9yIGxvY3VzLWxldmVsKSBhcHByb2FjaGVzIGFnZ3JlZ2F0ZSB0aGVzZSBzaWduYWxzIGFjcm9zcyBhIGNvbGxlY3Rpb24gb2YgdmFyaWFudHMgaW4gaG9wZSBvZiBkZXRlY3RpbmcgbW9yZSBzdGFibGUgYW5kIGJpb2xvZ2ljYWxseS1yZWxldmFudCBsb2NpLiBJbiBhZGRpdGlvbiB0byB0aGlzIGRpZmZlcmVuY2UsIHRoZXJlIGFyZSBhIG51bWJlciBvZiBvdGhlciBwb3RlbnRpYWwgcmVhc29ucyB3aHkgTUFQSVQgYW5kIGxvLXNpUkYgbWF5IHlpZWxkIGRpZmZlcmVudCwgYnV0IG5vbi1jb250cmFkaWN0b3J5IHJlc3VsdHMuIEZvciBleGFtcGxlLCBNQVBJVCBhbmQgbG8tc2lSRiBhc3N1bWUgZGlmZmVyZW50IHVuZGVybHlpbmcgbW9kZWwgYXNzdW1wdGlvbnMgYW5kIG1heSBjYXB0dXJlIGRpZmZlcmVudCBmb3JtcyBvZiBpbnRlcmFjdGlvbnMuIEluIHNob3J0LCBNQVBJVCBlbmNvZGVzIGludGVyYWN0aW9ucyBhcyBwYWlyd2lzZSBtdWx0aXBsaWNhdGl2ZSBlZmZlY3RzIChtb3JlIHR5cGljYWwgaW4gdGhlIHN0YXRpc3RpY2FsIGVwaXN0YXNpcyBsaXRlcmF0dXJlKSB3aGVyZWFzIGxvLXNpUkYgdGFrZXMgYSBtb3JlIG1hY2hpbmUgbGVhcm5pbmcgYXBwcm9hY2gsIGVuY29kaW5nIHBhaXJ3aXNlIGFuZCBoaWdoZXItb3JkZXIgaW50ZXJhY3Rpb25zIHRocm91Z2ggZGVjaXNpb24gcGF0aHMgKG9yIGJvb2xlYW4gdGhyZXNob2xkaW5nIG9wZXJhdGlvbnMpIGluIGEgZGVjaXNpb24gdHJlZS4gT3RoZXIgcG90ZW50aWFsIGRpZmZlcmVuY2VzIG1heSBzdGVtIGZyb20gdGhlIGRpZmZlcmVudCBoYW5kbGluZyBvZiB2YXJpYW50cyB3aXRoIG1pbm9yIGFsbGVsZSBmcmVxdWVuY2llcyBiZWxvdyAwLjA1IG9yIHRoZSBzbGlnaHRseSBkaWZmZXJlbnQgcGhlbm90eXBlcyB1c2VkIChpLmUuLCBsby1zaVJGIHVzZWQgdGhlIGJpbmFyaXplZCBMVk1pIHBoZW5vdHlwZSB3aGlsZSBNQVBJVCB1bmZvcnR1bmF0ZWx5IHJlcXVpcmVzIGEgY29udGludW91cyBwaGVub3R5cGUgYW5kIHRodXMgdXNlZCB0aGUgcmFuay1iYXNlZCBpbnZlcnNlIG5vcm1hbC10cmFuc2Zvcm1lZCBMVk1pKS4gCjwvZGl2PgoKYGBge3IgbWFwaXQsIHJlc3VsdHMgPSAiYXNpcyJ9CmlmICghcGFyYW1zJGV2YWwpIHsKICBtYXBpdF9kZiA8LSByZWFkUkRTKAogICAgZmlsZS5wYXRoKHJlc19kaXIsICJlcGlzdGFzaXNfY29tcGFyaXNvbnMiLCAibWFwaXQiLCAibXZtYXBpdF9ub3JtYWxfbWFmMC4wNV9yYW5rbm9ybS5yZHMiKQogICkkcHZhbHVlcwogIHNucHNfZGYgPC0gbG9hZFNOUEluZm8obWFwaXRfZGYkaWQpCiAgbWFwaXRfZGYgPC0gbWFwaXRfZGYgJT4lCiAgICBkcGx5cjo6bGVmdF9qb2luKHNucHNfZGYsIGJ5ID0gYygiaWQiID0gIk5hbWUiKSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKFJhbmsgPSBhcy5pbnRlZ2VyKHJhbmsocCkpKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKHApICU+JQogICAgZHBseXI6OnNlbGVjdCgKICAgICAgUmFuaywgcnNJRCwgQ2hyLAogICAgICBQb3MgPSBgaGcxOSBQb3NgLCBgTG8tc2lSRiBMb2N1c2AgPSBHZW5lLCBwCiAgICApICU+JQogICAgZHBseXI6OmZpbHRlcihwIDwgMC4wNSkKICAjIHdyaXRlLmNzdihtYXBpdF9kZiwgZmlsZS5wYXRoKHJlc19kaXIsICJlcGlzdGFzaXNfY29tcGFyaXNvbnMiLCAibWFwaXQiLCAibWFwaXRfcmVzdWx0cy5jc3YiKSwgcm93Lm5hbWVzID0gRkFMU0UpCiAgdGFiIDwtIHZ0aGVtZXM6OnByZXR0eV9EVChtYXBpdF9kZiwgcm93bmFtZXMgPSBGQUxTRSkKCiAgdnRoZW1lczo6c3ViY2h1bmtpZnkoCiAgICB0YWIsCiAgICBpID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9ICInKipUb3AgZXBpc3RhdGljIHZhcmlhbnRzIGZyb20gTUFQSVQsIHJhbmtlZCBieSBwLXZhbHVlLioqIFdlIHNob3cgb25seSB0aGUgZXBpc3RhdGljIHZhcmlhbnRzIHdpdGggcC12YWx1ZSA8IDAuMDUuIHJzSUQgPSByc0lEIG9mIHRoZSB2YXJpYW50LiBDaHIgPSBDaHJvbW9zb21lLiBQb3MgPSBQb3NpdGlvbiBvbiBoZzE5LiBMby1zaVJGIExvY3VzID0gYXNzaWduZWQgbG9jdXMgb2YgdGhlIHZhcmlhbnQgaW4gdGhlIGxvLXNpUkYgYW5hbHlzaXMuIFAtdmFsdWUgPSBwLXZhbHVlIGZyb20gTUFQSVQuJyIKICApCiAgY2h1bmtfaWR4IDwtIGNodW5rX2lkeCArIDEKfQpgYGAKCiMjIyBNQVBJVCtHU0VBIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1jaXJjbGV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+ClNpbmNlIHRoZSByZXN1bHRzIG9mIE1BUElUIGFuZCBsby1zaVJGIGFyZSBvbiBkaWZmZXJlbnQgYmlvbG9naWNhbCBzY2FsZXMgKGkuZS4sIFNOVnMgdmVyc3VzIGxvY2kpLCB3ZSBhbHNvIGNvbmR1Y3RlZCBhIGxvY3VzLWxldmVsIGFuYWx5c2lzIHVzaW5nIE1BUElUIFtAY3Jhd2ZvcmQyMDE3ZGV0ZWN0aW5nXSBpbiBjb25qdW5jdGlvbiB3aXRoIGdlbmUgc2V0IGVucmljaG1lbnQgYW5hbHlzaXMgKEdTRUEpIFtAc3VicmFtYW5pYW4yMDA1Z2VuZTsgQG1vb3RoYTIwMDNwZ2NdLiBJbiB0aGlzIHBpcGVsaW5lLCB3ZSB0b29rIHRoZSB1bmlvbiBvZiB0aGUgdG9wIDEwLDAwMCBHV0FTIGhpdHMgZnJvbSBQTElOSyBhbmQgQk9MVC1MTU0sIHJhbiBNQVBJVCBvbiB0aGVzZSBTTlZzIHRvIG9idGFpbiBhIHJhbmtlZCBsaXN0IG9mIFNOVnMgYWNjb3JkaW5nIHRvIHRoZWlyIE1BUElUIHAtdmFsdWVzLCBhbmQgdGhlbiByYW4gR1NFQSBvbiB0aGlzIHJhbmtlZCBsaXN0IHRvIGlkZW50aWZ5IGxvY2kgdGhhdCBhcmUgZW5yaWNoZWQgYXQgdGhlIHRvcCBvZiB0aGlzIHJhbmtlZCBsaXN0LiBUaGUgcmVzdWx0cyBvZiB0aGlzIE1BUElUK0dTRUEgYW5hbHlzaXMgYXJlIHByb3ZpZGVkIGJlbG93LiBXZSBoaWdobGlnaHQgdGhyZWUgbm90YWJsZSBmaW5kaW5ncyBmcm9tIHRoaXMgYW5hbHlzaXM6IFdoZW4gcmFua2luZyB0aGUgbG9jaSBieSB0aGVpciBub3JtYWxpemVkIGVucmljaG1lbnQgc2NvcmUsCgotIFRoZSB0b3AtcmFua2VkIGxvY3VzIChieSBNQVBJVCtHU0VBKSB3YXMgdGhlIGludGVyZ2VuaWMgcmVnaW9uIGJldHdlZW4gKklHRkJQMyogYW5kICpMT0M3MzAzMzgqIChkZW5vdGVkIGFzICpJR0ZCUDM7TE9DNzMwMzM4KikuICpJR0ZCUDMqIGVuY29kZXMgYW4gaW5zdWxpbi1saWtlIGdyb3d0aCBmYWN0b3IgKElHRikgYmluZGluZyBwcm90ZWluLCB3aGljaCBpcyBrbm93biB0byBpbnRlcmFjdCBjbG9zZWx5IHdpdGggKklHRjFSKiBbQGJheHRlcjIwMjNzaWduYWxpbmddLgotIFRoZSB0aHJlZSBpbnRlcmFjdGluZyBsb2NpLCBwcmlvcml0aXplZCBieSBsby1zaVJGLCB3ZXJlIGFsbCByYW5rZWQgd2l0aGluIHRoZSB0b3AgMzAgYnkgdGhlIE1BUElUK0dTRUEgYW5hbHlzaXMgKCpMT0MxNTcyNzM7VE5LUyo6IHJhbmsgMjsgKklHRjFSKjogcmFuayA3OyAqVFROKjogcmFuayAyMzsgKkNDREMxNDEqOiByYW5rIDI4IG91dCBvZiA4NjMgdG90YWwgbG9jaSkuIFRoZWlyIGNvcnJlc3BvbmRpbmcgbm9taW5hbCBwLXZhbHVlLCBGRFIgcS12YWx1ZSwgYW5kIEZXRVIgcC12YWx1ZSB3ZXJlIDAgKG9yIDwgMWUtMyBnaXZlbiB0aGF0IHdlIHVzZWQgMTAwMCBwZXJtdXRhdGlvbnMpLiBXZSBub3RlIGhvd2V2ZXIgdGhhdCB0aGUgbWFnbml0dWRlcyBvZiB0aGVzZSBwLXZhbHVlcyBhcmUgbm90IGRpcmVjdGx5IGNvbXBhcmFibGUgdG8gdGhvc2UgZnJvbSBsby1zaVJGIGdpdmVuIHRoZSBkaWZmZXJlbnQgbW9kZWxpbmcgYXNzdW1wdGlvbnMuCi0gQXNpZGUgZnJvbSAqSUdGQlAzO0xPQzczMDMzOCosICpMT0MxNTcyNzM7VE5LUyosICpJR0YxUiosIGFuZCAqQURBTVRTMTYqLCBvdGhlciBsb2NpIHJhbmtlZCBpbiB0aGUgdG9wIDEwIGJ5IE1BUElUK0dTRUEgZG8gbm90IGFwcGVhciB0byBiZSBjbG9zZWx5IHJlbGF0ZWQgdG8gY2FyZGlhYyBoeXBlcnRyb3BoeSBvciBjYXJkaW92YXNjdWxhciBkaXNlYXNlcyBpbiB0aGUgY3VycmVudCBsaXRlcmF0dXJlLiBNb3Jlb3ZlciwgZXhjZXB0IGZvciAqSUdGQlAzO0xPQzczMDMzOCosICpMT0MxNTcyNzM7VE5LUyosICpJR0YxUiosICpBREFNVFMxNiosIGFuZCAqRkJYTDE3KiwgdGhlIHJlbWFpbmluZyA1IGxvY2kgaW4gdGhlIHRvcCAxMCB3ZXJlIG5vdCBhbW9uZyB0aGUgdG9wIDEwMDAgR1dBUy1maWx0ZXJlZCBTTlZzIHVzZWQgaW4gdGhlIG9yaWdpbmFsIGxvLXNpUkYgYW5hbHlzaXMuIEluIG90aGVyIHdvcmRzLCBoYWxmIG9mIHRoZSB0b3AgMTAgbG9jaSBpZGVudGlmaWVkIGJ5IE1BUElUK0dTRUEgZGlkIG5vdCBzaG93IHN0cm9uZyBtYXJnaW5hbCBhc3NvY2lhdGlvbnMgd2l0aCBMVk1pLiBUaGVyZSBpcyBubyBleHBlY3RhdGlvbiB0aGF0IHZhcmlhbnRzIGludm9sdmVkIGluIGVwaXN0YXNpcyBhbHNvIGhhdmUgbGFyZ2UgbWFyZ2luYWwgZWZmZWN0cywgc28gdGhlIGxhY2sgb2YgbWFyZ2luYWwgYXNzb2NpYXRpb25zIGFsb25lIGlzIG5vdCBwYXJ0aWN1bGFybHkgY29uY2VybmluZy4gSG93ZXZlciwgY29tYmluZWQgd2l0aCB0aGUgb2JzZXJ2YXRpb24gdGhhdCB0aGUgcHJpbWFyeSBiaW9sb2dpY2FsIGZ1bmN0aW9ucyBvZiB0aGVzZSBsb2NpIGFyZSBub3QgZGlyZWN0bHkgcmVsYXRlZCB0byB0aGUgaGVhcnQsIHdlIGFyZSB1bmNlcnRhaW4gd2hldGhlciB0aGVzZSBlcGlzdGF0aWMgZmluZGluZ3Mgd291bGQgYmUgdmFsaWRhdGVkIGluIHdldCBsYWIgZXhwZXJpbWVudHMuCgpPdmVyYWxsLCBpbiBjb21wYXJpbmcgbG8tc2lSRiB3aXRoIE1BUElUK0dTRUEsIHdlIGFyZSBlbmNvdXJhZ2VkIHRvIHNlZSB0aGF0IGJvdGggbWV0aG9kcyBpZGVudGlmaWVkIGxvY2kgbGlrZSAqTE9DMTU3MjczO1ROS1MqLCAqSUdGMVIqLCAqVFROKiwgYW5kICpDQ0RDMTQxKi4gT24gdGhlIG90aGVyIGhhbmQsIE1BUElUK0dTRUEgYWxzbyBpZGVudGlmaWVkIGxvY2kgZGVwcmlvcml0aXplZCBieSBsby1zaVJGLCB3aGljaCB0dXJuIG91dCB0byBsYWNrIGJpb2xvZ2ljYWwgcmVsZXZhbmNlIHRvIGNhcmRpYWMgZGlzZWFzZXMuIFRoZXNlIGRpc2NyZXBhbmNpZXMgbWF5IGFyaXNlIGZyb20gdGhlIGZ1bmRhbWVudGFsIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGNvbXB1dGF0aW9uYWwgZnJhbWV3b3JrcyBvZiBsby1zaVJGIGFuZCBNQVBJVCtHU0VBLCB3aGljaCBtYWtlIGRpcmVjdCBjb21wYXJpc29ucyBjaGFsbGVuZ2luZy4gRmlyc3QsIE1BUElUIChvciBNQVBJVCtHU0VBKSBvdXRwdXRzIHNpbmdsZSBTTlZzIG9yIGxvY2kgd2l0aCBtYXJnaW5hbCBlcGlzdGF0aWMgZWZmZWN0cyB3aGlsZSBsby1zaVJGIGRpcmVjdGx5IGlkZW50aWZpZXMgc3BlY2lmaWMgaW50ZXJhY3Rpb25zIGJldHdlZW4gZ2VuZXRpYyBsb2NpLiBTZWNvbmRseSwgbG8tc2lSRiBhbmQgTUFQSVQgYXJlIGJhc2VkIG9uIGRpZmZlcmVudCBtb2RlbGluZyBhc3N1bXB0aW9ucywgc28gdGhlaXIgZGVmaW5pdGlvbnMgb2YgZXBpc3Rhc2lzIGFyZSBub3QgZGlyZWN0bHkgY29tcGFyYWJsZS4gTGFzdGx5LCBzaW5jZSBwZXJmb3JtaW5nIEdTRUEgYWZ0ZXIgTUFQSVQgaGFzIG5vdCBiZWVuIGV4dGVuc2l2ZWx5IHN0dWRpZWQsIGl0IGlzIHVuY2xlYXIgd2hldGhlciB0aGUgb2JzZXJ2ZWQgc3RyZW5ndGhzIGFuZCB3ZWFrbmVzc2VzIG9mIE1BUElUK0dTRUEgYXJpc2UgZnJvbSBNQVBJVCwgR1NFQSwgb3IgdGhlaXIgY29tYmluYXRpb24uIEl0IGFsc28gcmVtYWlucyB1bmNlcnRhaW4gd2hldGhlciB1c2luZyBhbHRlcm5hdGl2ZSBTTlYtdG8tbG9jdXMgZ3JvdXBpbmcgbWV0aG9kcyAoaW4gcGxhY2Ugb2YgR1NFQSkgd291bGQgaW1wcm92ZSB1cG9uIHRoZSBlcGlzdGF0aWMgbG9jaSByYW5raW5ncy4gCjwvZGl2PgoKYGBge3IgbWFwaXQtZ2VuZXMsIHJlc3VsdHMgPSAiYXNpcyJ9CmlmICghcGFyYW1zJGV2YWwpIHsKICB0YWIgPC0gZGF0YS50YWJsZTo6ZnJlYWQoCiAgICBmaWxlLnBhdGgoCiAgICAgIHJlc19kaXIsIAogICAgICAibWFwaXRfZ2VuZXMiLAogICAgICAibWFwaXRfZ2VuZV9nc2VhX2NsYXNzaWMuR3NlYVByZXJhbmtlZC4xNzI2ODQzNTU2OTU0IiwKICAgICAgImdzZWFfcmVwb3J0X2Zvcl9uYV9wb3NfMTcyNjg0MzU1Njk1NC50c3YiCiAgICApCiAgKSB8PgogIHRpYmJsZTo6YXNfdGliYmxlKCkgfD4KICBkcGx5cjo6bXV0YXRlKAogICAgUmFuayA9IDE6ZHBseXI6Om4oKQogICkgfD4KICBkcGx5cjo6c2VsZWN0KAogICAgUmFuaywKICAgIE5hbWUgPSBOQU1FLAogICAgYCMgU05Qc2AgPSBTSVpFLAogICAgYEVucmljaG1lbnQgU2NvcmVgID0gRVMsCiAgICBgTm9ybWFsaXplZCBFbnJpY2htZW50IFNjb3JlYCA9IE5FUywKICAgIGBOb21pbmFsIHAtdmFsdWVgID0gYE5PTSBwLXZhbGAsCiAgICBgRkRSIHEtdmFsdWVgID0gYEZEUiBxLXZhbGAsCiAgICBgRldFUiBwLXZhbHVlYCA9IGBGV0VSIHAtdmFsYAogICkgfD4KICBkcGx5cjo6ZmlsdGVyKAogICAgYE5vbWluYWwgcC12YWx1ZWAgPCAwLjA1CiAgKSB8PgogIHZ0aGVtZXM6OnByZXR0eV9EVCgKICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTUsIG9yZGVyaW5nID0gRkFMU0UpCiAgKQogIHZ0aGVtZXM6OnN1YmNodW5raWZ5KAogICAgdGFiLAogICAgaSA9IGNodW5rX2lkeCwKICAgIGNhcHRpb24gPSAiJyoqVG9wIGVwaXN0YXRpYyBsb2NpIGZyb20gTUFQSVQrR1NFQSwgcmFua2VkIGJ5IG5vcm1hbGl6ZWQgZW5yaWNobWVudCBzY29yZS4qKiBXZSBzaG93IG9ubHkgdGhlIGVwaXN0YXRpYyBsb2NpIHdpdGggbm9taW5hbCBwLXZhbHVlIDwgMC4wNS4nIgogICkKICBjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQp9CmBgYAoKCiMjIE1hcmdpbmFsIEdlbmUtYmFzZWQgTWV0aG9kcyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpJbiB0aGlzIHNlY3Rpb24sIHdlIGNvbXBhcmUgdGhlIGxvLXNpUkYtcHJpb3JpdGl6ZWQgbG9jaSB0byB0aG9zZSBsb2NpIHByaW9yaXRpemVkIGJ5IG90aGVyIGV4aXN0aW5nIG1hcmdpbmFsIHNldC1iYXNlZCBtZXRob2RzLCBzdWNoIGFzIE1BR01BIFtAZGUyMDE1bWFnbWFdIChGaWd1cmVzIFxAcmVmKGZpZzpzdWJjaHVuay04OCktXEByZWYoZmlnOnN1YmNodW5rLTkwKSkgYW5kIFNLQVQtTyBbQGxlZTIwMTJvcHRpbWFsXSAoRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay05MSkpLiBEZXRhaWxzIHJlZ2FyZGluZyB0aGUgbWV0aG9kb2xvZ3kgY2FuIGJlIGZvdW5kIGluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKGh0dHBzOi8vd3d3Lm1lZHJ4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS8yMDIzLjExLjA2LjIzMjk3ODU4djEpLiAKCk5vdGFibHksIHdlIGZvdW5kIHRoYXQgd2hpbGUgbG8tc2lSRiBwcmlvcml0aXplZCAqSUdGMVIqIGFzIG9uZSBvZiBpdHMgdG9wIHJlY29tbWVuZGVkIGxvY2ksIFNLQVQtTyBhbmQgTUFHTUEgZGlkIG5vdCByYW5rICpJR0YxUiogdmVyeSBoaWdobHkuIEFjY29yZGluZyB0byBTS0FULU8sICpJR0YxUiogeWllbGRlZCBhIHAtdmFsdWUgb2YgMS4wRS01IGFuZCB3YXMgdGhlIDQ1dGggcmFua2VkIGxvY3VzLCBhbmQgdXNpbmcgTUFHTUEsICpJR0YxUiogeWllbGRlZCBhIHAtdmFsdWUgb2YgMC4wMDIgYW5kIHdhcyB0aGUgMTQ2dGggcmFua2VkIGxvY3VzLiBHaXZlbiBvdXIgZXh0ZW5zaXZlIHZhbGlkYXRpb24gZWZmb3J0cyBkZW1vbnN0cmF0aW5nIHRoZSBpbXBvcnRhbmNlIG9mICpJR0YxUiogZm9yIGxlZnQgdmVudHJpY3VsYXIgaHlwZXJ0cm9waHksIHdlIHZpZXcgdGhpcyBhcyBhbiBpbnRlcmVzdGluZyBleGFtcGxlIHdoZXJlIGxvLXNpUkYgaXMgYWJsZSB0byBpZGVudGlmeSBpbXBvcnRhbnQgbG9jaSB0aGF0IGFyZSBub3QgbmVjZXNzYXJpbHkgcHJpb3JpdGl6ZWQgYnkgb3RoZXIgbWV0aG9kcywgZXZlbiBmb3IgbWFyZ2luYWwgZWZmZWN0cy4KPC9kaXY+CgpgYGB7ciBzZXQtdGVzdHMsIHJlc3VsdHMgPSAiYXNpcyJ9CmlmICghcGFyYW1zJGV2YWwpIHsKICAjIyBNQUdNQQogIG1hZ21hX2RmIDwtIGRhdGEudGFibGU6OmZyZWFkKAogICAgZmlsZS5wYXRoKHJlc19kaXIsICJnd2FzX2Z1bWEiLCAibWFnbWEiLCAibWFnbWEuZ2VuZXMub3V0IikKICApICU+JQogICAgZHBseXI6OnNlbGVjdCgKICAgICAgTG9jdXMgPSBTWU1CT0wsIENociA9IENIUiwgU3RhcnQgPSBTVEFSVCwgU3RvcCA9IFNUT1AsIFogPSBaU1RBVCwgcCA9IFAKICAgICkgJT4lCiAgICBkcGx5cjo6YXJyYW5nZShwKSAlPiUKICAgIGRwbHlyOjpzbGljZSgxOjIwMCkKCiAgZGlzcGxheV9pbWFnZSgKICAgIGZpbGUucGF0aChyZXNfZGlyLCAiZ3dhc19mdW1hIiwgIm1hZ21hIiwgImdlbmVNYW5oYXR0YW5fRlVNQV9qb2JzNDU3NjAyLnBuZyIpLAogICAgY2h1bmtfaWR4ID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9ICInTWFuaGF0dGFuIHBsb3Qgb2YgdGhlIGdlbmUtYmFzZWQgdGVzdCBhcyBjb21wdXRlZCBieSBNQUdNQS4gVGhlIGdlbm9tZS13aWRlIHNpZ25pZmljYW5jZSBsZXZlbCBpcyBzaG93biBieSB0aGUgcmVkIGRvdHRlZCBsaW5lLiciCiAgKQogIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogIHRhYiA8LSB2dGhlbWVzOjpwcmV0dHlfRFQobWFnbWFfZGYpCiAgdnRoZW1lczo6c3ViY2h1bmtpZnkoCiAgICB0YWIsCiAgICBpID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9ICInKipUb3AgZ2VuZXMgZnJvbSBNQUdNQSwgcmFua2VkIGJ5IHAtdmFsdWUuKiogV2Ugc2hvdyBvbmx5IHRoZSB0b3AgMjAwIGdlbmVzLiBMb2N1cyA9IEdlbmUgc3ltYm9sLiBDaHIgPSBDaHJvbW9zb21lLiBTdGFydCA9IFN0YXJ0IHBvc2l0aW9uIG9uIGhnMTkuIFN0b3AgPSBTdG9wIHBvc2l0aW9uIG9uIGhnMTkuIFogPSBaLXN0YXRpc3RpYyBmcm9tIE1BR01BLiBQLXZhbHVlID0gcC12YWx1ZSBmcm9tIE1BR01BLiciCiAgKQogIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCgogICMjIFNLQVQKICBsb2FkKAogICAgZmlsZS5wYXRoKHJlc19kaXIsICJza2F0IiwgInNrYXRfcmFua25vcm1fcmVzdWx0c19tYWYwLjA1LlJkYXRhIikKICApCiAgdGFiIDwtIHNrYXRfZGYgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1vZGUgPT0gIlNLQVRPIikgJT4lCiAgICBkcGx5cjo6YXJyYW5nZShwdmFsKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoCiAgICAgIExvY3VzID0gR2VuZSwgQ2hyLCBwID0gcHZhbAogICAgKSAlPiUKICAgIHZ0aGVtZXM6OnByZXR0eV9EVCgpCiAgdnRoZW1lczo6c3ViY2h1bmtpZnkoCiAgICB0YWIsCiAgICBpID0gY2h1bmtfaWR4LAogICAgY2FwdGlvbiA9ICInKipUb3AgZ2VuZXMgZnJvbSBTS0FULU8sIHJhbmtlZCBieSBwLXZhbHVlLioqIExvY3VzID0gTmFtZSBvZiBsb2N1cyBmcm9tIGxvLXNpUkYgYW5hbHlzaXMuIENociA9IENocm9tb3NvbWUuIFAtdmFsdWUgPSBwLXZhbHVlIGZyb20gU0tBVC1PLiciCiAgKQogIGNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCn0KYGBgCgoKCgojIExvLXNpUkYgUGVybXV0YXRpb24gVGVzdCBTaW11bGF0aW9ucyB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC12bW9kZXJufQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgpJbiB0aGlzIHNlY3Rpb24sIHdlIGNvbmR1Y3Qgc2V2ZXJhbCBzaW11bGF0aW9ucyB0byBpbnZlc3RpZ2F0ZSB0aGUgcGVyZm9ybWFuY2UgYW5kIGRlbW9uc3RyYXRlIHRoZSB2YWxpZGl0eSBvZiB0aGUgcGVybXV0YXRpb24gcC12YWx1ZXMgZnJvbSBsby1zaVJGLiAKPC9kaXY+CgojIyBQLXZhbHVlIENhbGlicmF0aW9uIFNpbXVsYXRpb25zIHsudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtcGlsbHMgLnRhYnNldC1zcXVhcmV9Cgo8ZGl2IGNsYXNzPSJwYW5lbCBwYW5lbC1kZWZhdWx0IHBhZGRlZC1wYW5lbCI+CioqQ2FsaWJyYXRpb24gb2YgcC12YWx1ZXMgdW5kZXIgbnVsbCBtb2RlbCoqOiBJbiB0aGUgZmlyc3Qgc2V0IG9mIHNpbXVsYXRpb25zLCB3ZSBhaW1lZCB0byBhc3Nlc3Mgd2hldGhlciB0aGUgcGVybXV0YXRpb24gcC12YWx1ZXMgYXJlIGNhbGlicmF0ZWQgdW5kZXIgdGhlIG51bGwgbW9kZWwgd2hlcmUgbm8gZXBpc3Rhc2lzIGlzIHByZXNlbnQuIFRvIHRoaXMgZW5kLCB3ZSBzaW11bGF0ZWQgYmluYXJ5IHJlc3BvbnNlcyAkeSQgZnJvbSBhIG51bGwsIHB1cmVseS1ub2lzZSBtb2RlbCwgd2hlcmUgJHkgXHNpbSBCZXJub3VsbGkoMS8yKSQuIFVuZGVyIHRoaXMgbnVsbCBzaW11bGF0aW9uIHNldHVwLCB3ZSBnZW5lcmF0ZWQgY292YXJpYXRlcyAkWCQgZnJvbSB0aHJlZSBkaWZmZXJlbnQgZGF0YS1nZW5lcmF0aW5nIHByb2Nlc3NlczoKCjxvbCB0eXBlPSJBIj4KPGxpPkluZGVwZW5kZW50IG5vcm1hbDogJFhfe2lqfSBcc3RhY2tyZWx7aWlkfXtcc2ltfSBOKDAsIDEpJCBmb3IgJGkgPSAxLCBcbGRvdHMsIG4kIGFuZCAkaiA9IDEsIFxsZG90cywgcCQuPC9saT4KPGxpPkluZGVwZW5kZW50IFNOUHM6ICRYX3tpan0kIGlpZCBmcm9tICRcezAsIDEsIDJcfSQgd2l0aCB1bmlmb3JtIHByb2JhYmlsaXRpZXMgZm9yICRpID0gMSwgXGxkb3RzLCBuJCBhbmQgJGogPSAxLCBcbGRvdHMsIHAkLjwvbGk+CjxsaT5SZWFsLXdvcmxkIFNOUHM6IFRoZSAkbiBcdGltZXMgcCQgbWF0cml4ICRYJCBpcyB0YWtlbiB0byBiZSB0aGUgR1dBUy1maWx0ZXJlZCBTTlYgbWF0cml4IHVzZWQgaW4gbG8tc2lSRi4gSW4gdGhpcyBjYXNlLCB3ZSB3ZSByYW5kb21seSBzdWJzYW1wbGVkIHRoZSBmZWF0dXJlcyBhbmQgdGhlIGNvbHVtbnMgdG8gbWVldCB0aGUgZGVzaXJlZCBkaW1lbnNpb25zIG9mICRuJCBhbmQgJHAkLjwvbGk+Cjwvb2w+CgpVbmRlciBlYWNoIG9mIHRoZXNlIHRocmVlIHNldHRpbmdzLCB3ZSByYW4gdGhlIHNpbXVsYXRlZCBkYXRhIHRocm91Z2ggYSBzaW1wbGlmaWVkIGxvLXNpUkYgcGlwZWxpbmUsIHdoZXJlIHdlOgoKMS4gU3BsaXQgdGhlIGRhdGEgaW50byB0d28gcGFydGl0aW9uICgyLzMgdHJhaW5pbmcgYW5kIDEvMyB2YWxpZGF0aW9uKS4KMi4gRml0IHNpUkYgb24gdGhlIHRyYWluaW5nIGRhdGEgdG8gb2J0YWluIGEgbGlzdCBvZiBjYW5kaWRhdGUgaW50ZXJhY3Rpb25zLgozLiBGb3IgZWFjaCBvZiB0aGUgaW50ZXJhY3Rpb25zIGZyb20gc3RlcCAyLCBldmFsdWF0ZSB0aGUgbG9jYWwgc3RhYmlsaXR5IGltcG9ydGFuY2Ugc2NvcmVzIGFuZCBjb21wdXRlIHRoZSBhc3NvY2lhdGVkIHBlcm11dGF0aW9uIHAtdmFsdWUgdXNpbmcgdGhlIHZhbGlkYXRpb24gZGF0YS4KCkluIHNpbXVsYXRpb25zIChBKSBhbmQgKEIpLCB3ZSBzZWFyY2hlZCBmb3IgaW50ZXJhY3Rpb25zIGF0IHRoZSBsZXZlbCBvZiBpbmRpdmlkdWFsIGZlYXR1cmVzIChvciBTTlZzKSwgcmF0aGVyIHRoYW4gYSBncm91cCBvZiBmZWF0dXJlcyAob3IgZ2VuZXMpLiBUaGlzIHdhcyBkb25lIHRvIHNpbXBsaWZ5IHRoZSBzaW11bGF0aW9uIHNldHVwIGFuZCBpbnRlcnByZXRhdGlvbiBvZiByZXN1bHRzLCBnaXZlbiB0aGF0IHRoZSBmZWF0dXJlcyB3ZXJlIHNpbXVsYXRlZCBpbmRlcGVuZGVudGx5LiBGb3Igc2ltdWxhdGlvbiBzZXR1cCAoQyksIHdlIGxldmVyYWdlZCB0aGUgc2FtZSBTTlYtdG8tZ2VuZSBtYXBwaW5nIHVzZWQgcHJldmlvdXNseSBpbiBsby1zaVJGIGFuZCBzZWFyY2hlZCBmb3IgaW50ZXJhY3Rpb25zIGF0IHRoZSBnZW5lIGxldmVsLgoKV2UgYWxzbyBub3RlIHRoYXQgdGhlIHNpbXBsaWZpZWQgbG8tc2lSRiBwaXBlbGluZSBvbWl0cyB0aGUgaW50ZXJhY3Rpb24gZmlsdGVyaW5nIHN0ZXAgYmFzZWQgdXBvbiB0aGVpciBzaVJGIHN0YWJpbGl0eSBzY29yZXMuIFRoaXMgd2FzIGRvbmUgYmVjYXVzZSB0aGUgaW50ZXJhY3Rpb24gZmlsdGVyaW5nIHN0ZXAgZXhjbHVkZXMgYWxtb3N0IGFsbCBub24tcmVsZXZhbnQgY2FuZGlkYXRlIGludGVyYWN0aW9ucyB1bmRlciB0aGUgc2ltdWxhdGlvbiBzZXR1cC4gSW4gcGFydGljdWxhciwgdW5kZXIgdGhlIG51bGwgc2ltdWxhdGlvbiBtb2RlbCwgdGhlIGludGVyYWN0aW9uIGZpbHRlcmluZyAodXNpbmcgdGhlIHJlY29tbWVuZGVkIHRocmVzaG9sZHMgZnJvbSB0aGUgb3JpZ2luYWwgc2lSRiBwYXBlciBbQGt1bWJpZXIyMDE4cmVmaW5pbmddKSByZW1vdmVkIGFsbCBidXQgMiBpbnRlcmFjdGlvbnMgYWNyb3NzIDIwMCBzaW11bGF0ZWQgZGF0YSByZXBsaWNhdGVzLiBHaXZlbiBvdXIgZ29hbCBvZiBhc3Nlc3Npbmcgd2hldGhlciB0aGUgcGVybXV0YXRpb24gcC12YWx1ZXMgYXJlIGNhbGlicmF0ZWQsIHdlIHdpbGwgZm9jdXMgb3VyIGV2YWx1YXRpb24gb24gdGhlIHBlcm11dGF0aW9uIHAtdmFsdWVzIGZyb20gYWxsIGNhbmRpZGF0ZSBpbnRlcmFjdGlvbnMgaW4gdGhpcyBzZXR0aW5nIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUgaW50ZXJhY3Rpb25zIHBhc3NlZCB0aGUgc3RhYmlsaXR5IGZpbHRlcmluZy4gCgoqKlJlc3VsdHMqKjogSW4gRmlndXJlIFxAcmVmKGZpZzpzdWJjaHVuay05MikgYmVsb3csIHdlIHBsb3QgdGhlIHByb3BvcnRpb24gb2YgcmVqZWN0ZWQgbnVsbCBoeXBvdGhlc2VzIGFjcm9zcyBkaWZmZXJlbnQgc2lnbmlmaWNhbmNlIGxldmVscyAkXGFscGhhJCB1bmRlciB0aGUgYWZvcmVtZW50aW9uZWQgbnVsbCBzaW11bGF0aW9uIHNldHVwLiBXZSBmb3VuZCB0aGF0IHRoZSBvYnNlcnZlZCB0eXBlIEkgZXJyb3Igb2Ygb3VyIHBlcm11dGF0aW9uIHRlc3QgY2xvc2VseSBhbGlnbnMgd2l0aCB0aGUgc2lnbmlmaWNhbmNlIGxldmVsICRcYWxwaGEkLCB0aGVyZWJ5IGNvbmZpcm1pbmcgdGhhdCB0aGUgcC12YWx1ZXMgYXJlIGNhbGlicmF0ZWQuIE1vcmVvdmVyLCB0aGVzZSByZXN1bHRzIGhvbGQgYWNyb3NzIGRpZmZlcmVudCBzYW1wbGUgc2l6ZXMsIG51bWJlciBvZiBmZWF0dXJlcywgYW5kIGFsbCB0aHJlZSBkYXRhLWdlbmVyYXRpbmcgcHJvY2Vzc2VzIGZvciBYLgo8L2Rpdj4KCmBgYHtyIHBlcm0tdGVzdC1zaW11bGF0aW9ucywgcmVzdWx0cyA9ICJhc2lzIn0KZGdwX25hbWVzIDwtIGMoCiAgIkdhdXNzaWFuIFgiLAogICJSZWFsIFNOUCBYIiwKICAiU05QIFgiLAogICJTTlAgWCAob3JkZXIgMSkiLAogICJTTlAgWCAob3JkZXIgMikiCikKbnVsbF9kZ3BfbmFtZXMgPC0gYygKICAiR2F1c3NpYW4gWCIsCiAgIlNOUCBYIiwKICAiUmVhbCBTTlAgWCIKKQpmaXRfcmVzdWx0c19scyA8LSBsaXN0KCkKZm9yIChkZ3BfbmFtZSBpbiBkZ3BfbmFtZXMpIHsKICBudW1fZmVhdHVyZXMgPC0gZHBseXI6OmNhc2Vfd2hlbigKICAgIGRncF9uYW1lID09ICJSZWFsIFNOUCBYIiB+IDUwMCwKICAgIFRSVUUgfiAxMDAKICApCiAgZml0X3Jlc3VsdHNfbHNbW2RncF9uYW1lXV0gPC0gcmVhZFJEUygKICAgIGZpbGUucGF0aCgKICAgICAgcmVzX2RpciwgIlBlcm11dGF0aW9uIFZhbGlkaXR5IiwgZGdwX25hbWUsICJWYXJ5aW5nIG4iLCAiZml0X3Jlc3VsdHMucmRzIgogICAgKQogICkgfD4gCiAgICBkcGx5cjo6bXV0YXRlKHAgPSBudW1fZmVhdHVyZXMpCn0KCiMgY2FsaWJyYXRpb24gcGxvdAphbHBoYXMgPC0gc2VxKDAsIDEsIGJ5ID0gMC4wMSkKcGx0X2RmIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZml0X3Jlc3VsdHNfbHMsIC5pZCA9ICJkZ3BfbmFtZSIpIHw+CiAgdGlkeXI6OnVubmVzdChyZXN1bHQpIHw+IAogIGRwbHlyOjpncm91cF9ieShkZ3BfbmFtZSwgbiwgcCkgfD4KICBkcGx5cjo6c3VtbWFyaXNlKAogICAgYWxwaGEgPSB0aWJibGU6OnRpYmJsZSgKICAgICAgYWxwaGEgPSBhbHBoYXMsCiAgICAgIHJlamVjdF9wcm9iID0gcHVycnI6Om1hcF9kYmwoYWxwaGFzLCB+IG1lYW4ocHZhbCA8IC54KSkKICAgICkgfD4KICAgICAgbGlzdCgpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgfD4KICB0aWR5cjo6dW5uZXN0KGFscGhhKSB8PgogIGRwbHlyOjptdXRhdGUoCiAgICBzZXR0aW5nID0gc3ByaW50ZigiTnVtLiBTYW1wbGVzID0gJXNcbk51bS4gRmVhdHVyZXMgPSAlcyIsIG4sIHApCiAgKQpwbHRfbHMgPC0gbGlzdCgpCmZvciAoZGdwX25hbWUgaW4gbnVsbF9kZ3BfbmFtZXMpIHsKICBwbHRfbHNbW2RncF9uYW1lXV0gPC0gcGx0X2RmIHw+CiAgICBkcGx5cjo6ZmlsdGVyKAogICAgICBkZ3BfbmFtZSA9PSAhIWRncF9uYW1lCiAgICApIHw+IAogICAgZHBseXI6Om11dGF0ZSgKICAgICAgZGdwX25hbWUgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZShkZ3BfbmFtZSwgIlNOUCIsICJTTlYiKQogICAgKSB8PiAKICAgIGdncGxvdDI6OmdncGxvdCgpICsKICAgIGdncGxvdDI6OmFlcygKICAgICAgeCA9IGFscGhhLCB5ID0gcmVqZWN0X3Byb2IKICAgICkgKwogICAgZ2dwbG90Mjo6Z2VvbV9saW5lKCkgKwogICAgZ2dwbG90Mjo6Z2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICBnZ3Bsb3QyOjpmYWNldF9ncmlkKGRncF9uYW1lIH4gc2V0dGluZykgKwogICAgZ2dwbG90Mjo6bGFicygKICAgICAgeCA9ICJTaWduaWZpY2FuY2UgTGV2ZWwgKGFscGhhKSIsCiAgICAgIHkgPSAiUHJvcG9ydGlvbiBvZiBSZWplY3RlZCBOdWxsIEh5cG90aGVzZXMiLAogICAgKSArCiAgICB2dGhlbWVzOjp0aGVtZV92bW9kZXJuKCkKfQpwbHQgPC0gcGF0Y2h3b3JrOjp3cmFwX3Bsb3RzKHBsdF9scywgbmNvbCA9IDEpICsKICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KGF4ZXMgPSAiY29sbGVjdCIpCnN1YmNodW5raWZ5KAogIHBsdCwKICBpID0gY2h1bmtfaWR4LCAKICBmaWdfaGVpZ2h0ID0gNi41LAogIGZpZ193aWR0aCA9IDgsCiAgYWRkX2NsYXNzID0gYygicGFuZWwgcGFuZWwtZGVmYXVsdCIpLAogIG90aGVyX2FyZ3MgPSAib3V0LndpZHRoPScxMDAlJyIsCiAgY2FwdGlvbiA9ICInUHJvcG9ydGlvbiBvZiByZWplY3RlZCBudWxsIGh5cG90aGVzZXMgYWNyb3NzIHZhcnlpbmcgc2lnbmlmaWNhbmNlIGxldmVscyB1bmRlciB0aGUgbnVsbCBzaW11bGF0aW9uIHJlc3BvbnNlIG1vZGVsIGFyZSByZXByZXNlbnRlZCBieSB0aGUgc29saWQgYmxhY2sgbGluZS4gRG90dGVkIGxpbmUgcmVwcmVzZW50cyBhIHBlcmZlY3RseSBjYWxpYnJhdGVkIGh5cG90aGVzaXMgdGVzdCAoaS5lLiwgdGhlIHkgPSB4IGxpbmUpLiBFYWNoIHJvdyBjb3JyZXNwb25kcyB0byBhIGRpZmZlcmVudCBkYXRhLWdlbmVyYXRpbmcgcHJvY2VzcyBmb3IgWCwgYW5kIGVhY2ggY29sdW1uIGNvcnJlc3BvbmRzIHRvIGEgZGlmZmVyZW50IGNob2ljZSBvZiBudW1iZXIgb2Ygc2FtcGxlcy4gUmVzdWx0cyBhcmUgYWdncmVnYXRlZCBhY3Jvc3MgMjAwIHNpbXVsYXRpb24gcmVwbGljYXRlcy4nIgopCmNodW5rX2lkeCA8LSBjaHVua19pZHggKyAxCmNhdCgiXG5cbiIpCmBgYAoKIyMgTWFyZ2luYWwgYW5kIEludGVyYWN0aW9uIEVmZmVjdCBTaW11bGF0aW9ucyB7LnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LXBpbGxzIC50YWJzZXQtc3F1YXJlfQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgoqKk1hcmdpbmFsIGFuZCBJbnRlcmFjdGlvbiBFZmZlY3QgU2ltdWxhdGlvbnMqKjogTW92aW5nIGJleW9uZCB0aGlzIGJhc2ljIGNhbGlicmF0aW9uIGludmVzdGlnYXRpb24gYW5kIHRoZSBudWxsLCBwdXJlbHktbm9pc2UgbW9kZWwsIHdlIHdlcmUgbW9yZSBpbnRlcmVzdGVkIGluIHN0dWR5aW5nIHRoZSBicm9hZGVyIHBlcmZvcm1hbmNlIG9mIGxvLXNpUkYgYW5kIHRoZSBwZXJtdXRhdGlvbiB0ZXN0LiBUbyB0aGlzIGVuZCwgd2UgY29uZHVjdGVkIHR3byBhZGRpdGlvbmFsIHNpbXVsYXRpb25zIHVzaW5nIGJvb2xlYW4tdHlwZSBydWxlcy4gV2Ugbm90ZSB0aGF0IHRoZSBib29sZWFuLXR5cGUgcnVsZXMgd2VyZSBjaG9zZW4gYXMgdGhleSBoYXZlIGJlZW4gZXh0ZW5zaXZlbHkgc3R1ZGllZCBpbiBwcmV2aW91cyBSRi1iYXNlZCB3b3JrIGFuZCBhcmUgdGhvdWdodCB0byBjbG9zZWx5IHJlc2VtYmxlIHRoZSBzd2l0Y2gtbGlrZSBhbmQgc3RlcmVvc3BlY2lmaWMgbmF0dXJlIG9mIGludGVyYWN0aW9ucyBhbW9uZyBiaW9tb2xlY3VsZXMgW0BuZWxzb24yMDA4bGVobmluZ2VyOyBAa3VtYmllcjIwMThyZWZpbmluZzsgQGJlaHIyMDIwbGVhcm5pbmddLiBTcGVjaWZpY2FsbHksIHdlIGZpcnN0IHNpbXVsYXRlZCB0aGUgJFgkIGRhdGEgZnJvbSBpbmRlcGVuZGVudCBTTlZzLCB3aGVyZSAkWF97aWp9JCBpcyBzaW11bGF0ZWQgaWlkIGZyb20gJFx7MCwgMSwgMlx9JCB3aXRoIHVuaWZvcm0gcHJvYmFiaWxpdGllcy4gTmV4dCwgd2Ugc2ltdWxhdGVkIGJpbmFyeSByZXNwb25zZXMgJHkgXG1pZCBYIFxzaW0gQmVybm91bGxpKHAoWCkpJCB2aWE6Cgo8b2wgdHlwZT0iQSIgc3RhcnQ9IjQiPgo8bGk+TWFyZ2luYWwgZWZmZWN0IG1vZGVsOiAkcChYKSA9IDAuNCBcY2RvdCBcbWF0aGJmezF9XHtYXzEgPiAwXH0gKyAwLjQgXGNkb3QgXG1hdGhiZnsxfVx7WF8yID4gMFx9JDwvbGk+Cjx1bD4KPGxpPiBJbiB0aGlzIG1vZGVsLCB0aGVyZSBhcmUgbm8gdHJ1ZSBpbnRlcmFjdGlvbnMuPC9saT4KPC91bD4KPGxpPkludGVyYWN0aW9uIGVmZmVjdCBtb2RlbDogJHAoWCkgPSAwLjQgXGNkb3QgXG1hdGhiZnsxfVx7WF8xID4gMFx9IFxtYXRoYmZ7MX1ce1hfMiA+IDBcfSArIDAuNCBcY2RvdCBcbWF0aGJmezF9XHtYXzMgPiAwXH0gXG1hdGhiZnsxfVx7WF80ID4gMFx9JDwvbGk+Cjx1bD4KPGxpPiBJbiB0aGlzIG1vZGVsLCB0aGUgdHJ1ZSBpbnRlcmFjdGlvbnMgYXJlICRYXzE6WF8yJCBhbmQgJFhfMzpYXzQkLjwvbGk+CjwvdWw+Cjwvb2w+CgpXZSBzZXQgdGhlIG51bWJlciBvZiBmZWF0dXJlcyB0byAxMDAgYW5kIHZhcmllZCB0aGUgbnVtYmVyIG9mIHNhbXBsZXMgYWNyb3NzIG4gPSAxMDAwLCAxNTAwLCAyMDAwLiBGb3IgZWFjaCBzaW11bGF0aW9uIG1vZGVsIGFuZCBjaG9pY2Ugb2Ygc2FtcGxlIHNpemUsIHdlIHJhbiAyMDAgc2ltdWxhdGlvbiByZXBsaWNhdGVzLgoKKipSZXN1bHRzKio6IFRoZSBzaW11bGF0aW9uIHJlc3VsdHMgYXJlIHN1bW1hcml6ZWQgaW4gVGFibGUgXEByZWYoZmlnOnN1YmNodW5rLTkzKSBiZWxvdy4gSW4gd2hhdCBmb2xsb3dzLCB3ZSBkZWZpbmUgInBhcnRpYWwgaW50ZXJhY3Rpb24iIGFzIGEgY2FuZGlkYXRlIGludGVyYWN0aW9uIHRoYXQgaW52b2x2ZXMgYXQgbGVhc3Qgb25lIHRydWUgc2lnbmFsIGZlYXR1cmUgZnJvbSBhbiBpbnRlcmFjdGlvbiB0aGF0IGFwcGVhcmVkIGluIHRoZSBzaW11bGF0aW9uIG1vZGVsIC0tLSBzcGVjaWZpY2FsbHksIGF0IGxlYXN0IG9uZSBvZiAkWF8xJCBvciAkWF8yJCBpbiB0aGUgbWFyZ2luYWwgZWZmZWN0IHNpbXVsYXRpb24gKEQpLCBvciBhdCBsZWFzdCBvbmUgb2YgJFhfMSQsICRYXzIkLCAkWF8zJCwgb3IgJFhfNCQgaW4gdGhlIGludGVyYWN0aW9uIGVmZmVjdCBzaW11bGF0aW9uIChFKS4gV2UgZGVmaW5lICJ0cnVlIGludGVyYWN0aW9uIiBhcyBhIGNhbmRpZGF0ZSBpbnRlcmFjdGlvbiB0aGF0IGludm9sdmVzIGJvdGggJFhfMSQgYW5kICRYXzIkIG9yIGJvdGggJFhfMyQgYW5kICRYXzQkIGluIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3Qgc2ltdWxhdGlvbi4gCgpUaGUgbWFpbiB0YWtlYXdheXMgZnJvbSB0aGVzZSBzaW11bGF0aW9ucyBhcmU6CgoxLiBVbmRlciBib3RoIHRoZSBtYXJnaW5hbCBlZmZlY3QgYW5kIGludGVyYWN0aW9uIGVmZmVjdCBzY2VuYXJpb3MsIHRoZSBjYW5kaWRhdGUgaW50ZXJhY3Rpb25zIGZyb20gc2lSRiBhbG1vc3QgYWx3YXlzIGluY2x1ZGUgYXQgbGVhc3Qgb25lIHRydWUgc2lnbmFsIGZlYXR1cmUgKGFuZCBlcXVpdmFsZW50bHksIGlzIGEgcGFydGlhbCBpbnRlcmFjdGlvbikuCgogICAgLSBTcGVjaWZpY2FsbHksIHVuZGVyIGJvdGggdGhlIG1hcmdpbmFsIGVmZmVjdCAoRCkgYW5kIGludGVyYWN0aW9uIGVmZmVjdCAoRSkgc2NlbmFyaW9zLCBvdmVyIDk5JSBvZiB0aGUgY2FuZGlkYXRlIGludGVyYWN0aW9ucyBpZGVudGlmaWVkIGJ5IHNpUkYgd2VyZSBmb3VuZCB0byBiZSAicGFydGlhbCBpbnRlcmFjdGlvbnMiICh0aGUgNXRoIGNvbHVtbiBpbiBUYWJsZSBcQHJlZihmaWc6c3ViY2h1bmstOTMpKS4gTW9yZW92ZXIsIHVuZGVyIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3QgKEUpIHNpbXVsYXRpb24sIG92ZXIgMzglIG9mIHRoZSBjYW5kaWRhdGUgaW50ZXJhY3Rpb25zIGlkZW50aWZpZWQgYnkgc2lSRiB3ZXJlICJ0cnVlIGludGVyYWN0aW9ucyIgKHRoZSA0dGggY29sdW1uIGluIFRhYmxlIFxAcmVmKGZpZzpzdWJjaHVuay05MykpLiAKCjIuIFRoZSBpbnRlcmFjdGlvbiBmaWx0ZXJpbmcgc3RlcCB3aXRoaW4gc2lSRiwgd2hlcmUgd2UgZmlsdGVyIG91dCBjYW5kaWRhdGUgaW50ZXJhY3Rpb25zIHRoYXQgZG8gbm90IG1lZXQgdGhlIHNpUkYgc3RhYmlsaXR5IHRocmVzaG9sZHMsIGlzIGJvdGggbmVjZXNzYXJ5IGFuZCBlZmZlY3RpdmUgYXQgZGlzdGluZ3Vpc2hpbmcgYmV0d2VlbiBpbnRlcmFjdGlvbnMgYW5kIG1hcmdpbmFsIGVmZmVjdHMuCgogICAgLSBGaXJzdCwgdGhlIHNpUkYgaW50ZXJhY3Rpb24gZmlsdGVyaW5nIGlzIG5lY2Vzc2FyeSB0byBkaWZmZXJlbnRpYXRlIGJldHdlZW4gaW50ZXJhY3Rpb25zIGFuZCBtYXJnaW5hbCBlZmZlY3RzIHNpbmNlIHRoZSBwZXJtdXRhdGlvbiB0ZXN0IGl0c2VsZiBpcyBub3QgZGVzaWduZWQgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiAidHJ1ZSBpbnRlcmFjdGlvbnMiIGFuZCAicGFydGlhbCBpbnRlcmFjdGlvbnMuIgogICAgCiAgICAgICAgLSBCZWNhdXNlIHRoZSBwZXJtdXRhdGlvbiB0ZXN0IHdpdGhpbiBsby1zaVJGIGZvcm1hbGx5IGFzc2Vzc2VzIHdoZXRoZXIgdGhlIGxvY2FsIHN0YWJpbGl0eSBpbXBvcnRhbmNlIG9mIGFuIGludGVyYWN0aW9uIGRpZmZlcnMgYmV0d2VlbiB0aGUgaGlnaCBhbmQgbG93IExWTWkgZ3JvdXBzLCBhbnkgY2FuZGlkYXRlIGludGVyYWN0aW9uIGludm9sdmluZyBhdCBsZWFzdCBvbmUgdHJ1ZSBzaWduYWwgZmVhdHVyZSAoaS5lLiwgYW55IHBhcnRpYWwgaW50ZXJhY3Rpb24pIGlzIGV4cGVjdGVkIHRvIHNob3cgYSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBncm91cHMgYW5kIHJlc3VsdCBpbiBhIHNpZ25pZmljYW50IHAtdmFsdWUuIE91ciByZXN1bHRzIHN1cHBvcnQgdGhpcyBleHBlY3RhdGlvbi4gSW4gYm90aCB0aGUgaW50ZXJhY3Rpb24gYW5kIG1hcmdpbmFsIHNpbXVsYXRpb24gbW9kZWxzLCBhbiBvdmVyd2hlbG1pbmcgbWFqb3JpdHkgKD45OSUpIG9mIHRoZSBwZXJtdXRhdGlvbiB0ZXN0cyBsZWQgdG8gYSBzaWduaWZpY2FudCBwLXZhbHVlIChwIDwgMC4wNSkgKHRoZSBsYXN0IGNvbHVtbiBpbiBUYWJsZSBcQHJlZihmaWc6c3ViY2h1bmstOTMpKS4gVGhpcyBpcyBleHBlY3RlZCBzaW5jZSBlYWNoIG9mIHRoZXNlIHRlc3RlZCBpbnRlcmFjdGlvbnMgd2FzIGEgcGFydGlhbCBpbnRlcmFjdGlvbiBhbmQgaW52b2x2ZWQgYXQgbGVhc3Qgb25lIHRydWUgc2lnbmFsIGZlYXR1cmUgKHRoZSA4dGggY29sdW1uIGluIFRhYmxlIFxAcmVmKGZpZzpzdWJjaHVuay05MykpLgogICAgICAgIC0gV2UgdGh1cyByZWxpZWQgb24gdGhlIHNpUkYgaW50ZXJhY3Rpb24gZmlsdGVyaW5nIHN0ZXAgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBtYXJnaW5hbCBhbmQgdHJ1ZSBpbnRlcmFjdGlvbiBlZmZlY3RzLiBUaGlzIHNpUkYgaW50ZXJhY3Rpb24gZmlsdGVyaW5nIHN0ZXAgaXMgZGV0YWlsZWQgaW4gdGhlIE1ldGhvZHMgc2VjdGlvbiAqTG8tc2lSRiBzdGVwIDQuMzogUGVybXV0YXRpb24gdGVzdCBmb3IgZGlmZmVyZW5jZSBpbiBsb2NhbCBzdGFiaWxpdHkgaW1wb3J0YW5jZSBzY29yZXMqIGluIFtAd2FuZzIwMjNlcGlzdGFzaXNdKGh0dHBzOi8vd3d3Lm1lZHJ4aXYub3JnL2NvbnRlbnQvMTAuMTEwMS8yMDIzLjExLjA2LjIzMjk3ODU4djEpLiBTcGVjaWZpY2FsbHksIHRoZSBmZWF0dXJlIHNlbGVjdGlvbiBkZXBlbmRlbmNlIHRocmVzaG9sZCAoZGlzY3Vzc2VkIGluIGdyZWF0ZXIgZGV0YWlsIGluIHRoZSBvcmlnaW5hbCBzaVJGIHBhcGVyIFtAa3VtYmllcjIwMThyZWZpbmluZ10pIHdhcyBvcmlnaW5hbGx5IGRlc2lnbmVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBhZGRpdGl2ZSAoZS5nLiwgbWFyZ2luYWwpIGFuZCBub24tYWRkaXRpdmUgKGUuZy4sIGludGVyYWN0aW9uKSBlZmZlY3RzLiBUaGlzIG1ldHJpYyBzaG93ZWQgc3Ryb25nIHBlcmZvcm1hbmNlIGluIGVtcGlyaWNhbCBzaW11bGF0aW9ucyBmcm9tIHRoZSBvcmlnaW5hbCBzaVJGIHBhcGVyLgogICAgICAgIAogICAgLSBBcyBpbiB0aGUgb3JpZ2luYWwgc2lSRiBwYXBlciwgdGhlIHNpUkYgaW50ZXJhY3Rpb24gZmlsdGVyaW5nIGRlbW9uc3RyYXRlZCBzaW1pbGFybHkgc3Ryb25nIGVmZmVjdGl2ZW5lc3MgZm9yIGRpc3Rpbmd1aXNoaW5nIGJldHdlZW4gdHJ1ZSBpbnRlcmFjdGlvbnMgYW5kIHRydWUgbWFyZ2luYWwgZWZmZWN0cyB1bmRlciBvdXIgc2ltdWxhdGlvbiBzZXR1cC4KICAgIAogICAgICAgIC0gSW4gcGFydGljdWxhciwgdW5kZXIgdGhlIGludGVyYWN0aW9uIHNpbXVsYXRpb24gbW9kZWwsIHRoZSBzaVJGIGludGVyYWN0aW9uIGZpbHRlcmluZyBzdGVwIHJlZHVjZWQgdGhlIG51bWJlciBvZiBpbnRlcmFjdGlvbnMgZnJvbSBvdmVyIDMwMDAgY2FuZGlkYXRlcyAodGhlIDNyZCBjb2x1bW4gaW4gVGFibGUgXEByZWYoZmlnOnN1YmNodW5rLTkzKSksIG9mIHdoaWNoICRcc2ltJCA0MCUgd2VyZSB0cnVlIGludGVyYWN0aW9ucyAoNHRoIGNvbHVtbiksIHRvIH4xMzAwIGNhbmRpZGF0ZXMgKDZ0aCBjb2x1bW4pLiBPZiB0aGVzZSByZW1haW5pbmcgJFxzaW0kIDEzMDAgY2FuZGlkYXRlcywgODclLCA5OSUsIGFuZCAxMDAlIHdlcmUgdHJ1ZSBpbnRlcmFjdGlvbnMgaW4gdGhlIG4gPSAxMDAwLCAxNTAwLCBhbmQgMjAwMCBzaW11bGF0aW9ucywgcmVzcGVjdGl2ZWx5ICh0aGUgN3RoIGNvbHVtbikuIAogICAgICAgIC0gRnVydGhlcm1vcmUsIHVuZGVyIHRoZSBtYXJnaW5hbCBzaW11bGF0aW9uIG1vZGVsLCB0aGUgc2lSRiBpbnRlcmFjdGlvbiBmaWx0ZXJpbmcgc3RlcCByZWR1Y2VkIHRoZSBudW1iZXIgb2YgaW50ZXJhY3Rpb25zIGZyb20gb3ZlciA0NDAwIGNhbmRpZGF0ZXMgKHRoZSAzcmQgY29sdW1uIGluIFRhYmxlIFxAcmVmKGZpZzpzdWJjaHVuay05MykpIHRvIGZld2VyIHRoYW4gMTAwIGNhbmRpZGF0ZXMgKDR0aCBjb2x1bW4pLiBUaGF0IGlzLCBsZXNzIHRoYW4gMiUgb2YgdGhlIGNhbmRpZGF0ZSBpbnRlcmFjdGlvbnMgcmVtYWluIGFmdGVyIHRoZSBzaVJGIGludGVyYWN0aW9uIGZpbHRlcmluZyBzdGVwIGluIHRoZSBtYXJnaW5hbCBlZmZlY3Qgc2ltdWxhdGlvbiBzZXR0aW5nLgogICAgICAgIAogICAgLSBUaHVzLCBldmVuIHRob3VnaCB0aGUgcGVybXV0YXRpb24gdGVzdCByZWplY3RzIG1vc3QgdGVzdHMgaW52b2x2aW5nIHBhcnRpYWwgaW50ZXJhY3Rpb25zLCBpbiBsby1zaVJGLCB0aGUgcGVybXV0YXRpb24gdGVzdCBvY2N1cnMgYWZ0ZXIgdGhlIHNpUkYgaW50ZXJhY3Rpb24gZmlsdGVyaW5nLCB3aGljaCB3ZSBoYXZlIHNob3duIHRvIGVmZmVjdGl2ZWx5IGVsaW1pbmF0ZSB0aGUgdmFzdCBtYWpvcml0eSBvZiBub24tc2lnbmFsIG9yIHBhcnRpYWwgaW50ZXJhY3Rpb25zLgo8L2Rpdj4KCmBgYHtyIHBlcm0tdGVzdC1zaW11bGF0aW9ucy0yLCByZXN1bHRzID0gImFzaXMifQojIG1hcmdpbmFsIGFuZCBpbnRlcmFjdGlvbiBzaW11bGF0aW9ucwpsZWZ0X2pvaW5fd2l0aF9uYSA8LSBmdW5jdGlvbih4LCB5LCBieSkgewogIGlmICghaXMubnVsbCh4KSAmJiAhaXMubnVsbCh5KSkgewogICAgZHBseXI6OmxlZnRfam9pbih4LCB5LCBieSA9IGJ5KQogIH0gZWxzZSBpZiAoIWlzLm51bGwoeCkpIHsKICAgIHgKICB9IGVsc2UgewogICAgTlVMTAogIH0KfQoKdGFiIDwtIGRwbHlyOjpiaW5kX3Jvd3MoZml0X3Jlc3VsdHNfbHMsIC5pZCA9ICJkZ3BfbmFtZSIpIHw+CiAgZHBseXI6OmZpbHRlcigKICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoLmRncF9uYW1lLCAib3JkZXIiKQogICkgfD4gCiAgZHBseXI6OnJvd3dpc2UoKSB8PiAKICBkcGx5cjo6bXV0YXRlKAogICAgcmVzdWx0ID0gbGlzdChsZWZ0X2pvaW5fd2l0aF9uYShpbnRfZGYsIHJlc3VsdCwgYnkgPSAiaW50IikpCiAgKSB8PiAKICBkcGx5cjo6dW5ncm91cCgpIHw+IAogIHRpZHlyOjp1bm5lc3QocmVzdWx0KSB8PiAKICBkcGx5cjo6bXV0YXRlKAogICAgaW50X3ZlYyA9IHN0cmluZ3I6OnN0cl9yZW1vdmVfYWxsKGludCwgIltbKy8tXV0iKSB8PiAKICAgICAgc3RyaW5ncjo6c3RyX3NwbGl0KCJfIiksCiAgICB0cnVlX2ZlYXQgPSBwdXJycjo6bWFwMl9sZ2woCiAgICAgIGludF92ZWMsIC5kZ3BfbmFtZSwKICAgICAgZnVuY3Rpb24oLngsIC55KSB7CiAgICAgICAgaWYgKC55ID09ICJTTlAgWCAob3JkZXIgMikiKSB7CiAgICAgICAgICAoIlgxIiAlaW4lIC54KSB8fCAoIlgyIiAlaW4lIC54KSB8fCAoIlgzIiAlaW4lIC54KSB8fCAoIlg0IiAlaW4lIC54KQogICAgICAgIH0gZWxzZSBpZiAoLnkgPT0gIlNOUCBYIChvcmRlciAxKSIpIHsKICAgICAgICAgICgiWDEiICVpbiUgLngpIHx8ICgiWDIiICVpbiUgLngpCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIEZBTFNFCiAgICAgICAgfQogICAgICB9CiAgICApLAogICAgdHJ1ZV9pbnQgPSBwdXJycjo6bWFwMl9sZ2woCiAgICAgIGludF92ZWMsIC5kZ3BfbmFtZSwKICAgICAgZnVuY3Rpb24oLngsIC55KSB7CiAgICAgICAgaWYgKC55ID09ICJTTlAgWCAob3JkZXIgMikiKSB7CiAgICAgICAgICAoKCJYMSIgJWluJSAueCkgJiYgKCJYMiIgJWluJSAueCkpIHx8CiAgICAgICAgICAgICgoIlgzIiAlaW4lIC54KSAmJiAoIlg0IiAlaW4lIC54KSkKICAgICAgICB9IGVsc2UgewogICAgICAgICAgRkFMU0UKICAgICAgICB9CiAgICAgIH0KICAgICksCiAgICB0ZXN0ZWRfaW50ID0gIWlzLm5hKHB2YWwpCiAgKSB8PiAKICBkcGx5cjo6Z3JvdXBfYnkoCiAgICBkZ3BfbmFtZSwgbiwgcAogICkgfD4KICBkcGx5cjo6c3VtbWFyaXNlKAogICAgYCMgQ2FuZGlkYXRlIEludGVyYWN0aW9ucyBmcm9tIHNpUkZgID0gZHBseXI6Om4oKSwKICAgIGBQcm9wLiAoTnVtLikgb2YgVHJ1ZSBJbnRlcmFjdGlvbnMgaW4gQ2FuZGlkYXRlIFNldGAgPSAKICAgICAgc3ByaW50ZigiJS4zZiAoJXMpIiwgc3VtKHRydWVfaW50KSAvIGRwbHlyOjpuKCksIHN1bSh0cnVlX2ludCkpLAogICAgYFByb3AuIChOdW0uKSBvZiBQYXJ0aWFsIEludGVyYWN0aW9ucyBpbiBDYW5kaWRhdGUgU2V0YCA9IAogICAgICBzcHJpbnRmKCIlLjNmICglcykiLCBzdW0odHJ1ZV9mZWF0KSAvIGRwbHlyOjpuKCksIHN1bSh0cnVlX2ZlYXQpKSwKICAgIGBQcm9wLiAoTnVtLikgb2YgU3RhYmxlIEludGVyYWN0aW9ucyBpbiBDYW5kaWRhdGUgU2V0YCA9IAogICAgICBzcHJpbnRmKCIlLjNmICglcykiLCBzdW0odGVzdGVkX2ludCkgLyBkcGx5cjo6bigpLCBzdW0odGVzdGVkX2ludCkpLAogICAgYFByb3AuIChOdW0uKSBvZiBUcnVlIEludGVyYWN0aW9ucyBpbiBTdGFibGUgU2V0YCA9IAogICAgICBzcHJpbnRmKAogICAgICAgICIlLjJmICglcykiLCAKICAgICAgICBzdW0odHJ1ZV9pbnQgJiB0ZXN0ZWRfaW50KSAvIHN1bSh0ZXN0ZWRfaW50KSwKICAgICAgICBzdW0odHJ1ZV9pbnQgJiB0ZXN0ZWRfaW50KQogICAgICApLAogICAgYFByb3AuIChOdW0uKSBvZiBQYXJ0aWFsIEludGVyYWN0aW9ucyBpbiBTdGFibGUgU2V0YCA9IAogICAgICBzcHJpbnRmKAogICAgICAgICIlLjJmICglcykiLCAKICAgICAgICBzdW0odHJ1ZV9mZWF0ICYgdGVzdGVkX2ludCkgLyBzdW0odGVzdGVkX2ludCksCiAgICAgICAgc3VtKHRydWVfZmVhdCAmIHRlc3RlZF9pbnQpCiAgICAgICksCiAgICBgIyBJbnRlcmFjdGlvbnMgUmVqZWN0ZWQgKHAgPCAwLjA1KWAgPSAKICAgICAgc3ByaW50ZigKICAgICAgICAiJXMgKG91dCBvZiAlcyB0ZXN0cykiLCAKICAgICAgICBzdW0ocHZhbCA8PSAwLjA1LCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICBzdW0oIWlzLm5hKHB2YWwpKQogICAgICApLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgfD4gCiAgZHBseXI6Om11dGF0ZSgKICAgIGRncF9uYW1lID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgZGdwX25hbWUgPT0gIlNOUCBYIChvcmRlciAxKSIgfiAiTWFyZ2luYWwgTW9kZWwiLAogICAgICBkZ3BfbmFtZSA9PSAiU05QIFggKG9yZGVyIDIpIiB+ICJJbnRlcmFjdGlvbiBNb2RlbCIKICAgICkgfD4gCiAgICAgIGZhY3RvcihsZXZlbHMgPSBjKCJJbnRlcmFjdGlvbiBNb2RlbCIsICJNYXJnaW5hbCBNb2RlbCIpKQogICkgfD4gCiAgZHBseXI6OmFycmFuZ2UoZGdwX25hbWUpIHw+IAogIGRwbHlyOjpyZW5hbWUoCiAgICAiU2ltdWxhdGlvbiBOYW1lIiA9IGRncF9uYW1lLAogICAgYE51bS4gU2FtcGxlc2AgPSBuCiAgKSB8PiAKICBkcGx5cjo6c2VsZWN0KC1wKQpzdWJjaHVua2lmeSgKICB2dGhlbWVzOjpwcmV0dHlfRFQoCiAgICB0YWIsIHJvd25hbWVzID0gRkFMU0UsIG9wdGlvbnMgPSBsaXN0KGRvbSA9ICJ0Iiwgb3JkZXJpbmcgPSBGQUxTRSkKICApLCAKICBpID0gY2h1bmtfaWR4LAogIGNhcHRpb24gPSAiJ1N1bW1hcnkgb2YgbWFyZ2luYWwgYW5kIGludGVyYWN0aW9uIGVmZmVjdCBzaW11bGF0aW9ucy4gIyBDYW5kaWRhdGUgSW50ZXJhY3Rpb25zIGZyb20gc2lSRjogVGhlIHRvdGFsIG51bWJlciBvZiBpbnRlcmFjdGlvbnMgaWRlbnRpZmllZCBieSBzaVJGIGJlZm9yZSBhcHBseWluZyB0aGUgc3RhYmlsaXR5IGZpbHRlcmluZyBzdGVwLiBQcm9wLiAoTnVtLikgb2YgVHJ1ZSBJbnRlcmFjdGlvbnMgaW4gQ2FuZGlkYXRlIFNldDogVGhlIHByb3BvcnRpb24gKG9yIG51bWJlcikgb2YgdHJ1ZSBpbnRlcmFjdGlvbnMgb3V0IG9mIHRoZSB0b3RhbCBudW1iZXIgb2YgY2FuZGlkYXRlIGludGVyYWN0aW9ucyBmcm9tIHNpUkYuIFByb3AuIChOdW0uKSBvZiBQYXJ0aWFsIEludGVyYWN0aW9ucyBpbiBDYW5kaWRhdGUgU2V0OiBUaGUgcHJvcG9ydGlvbiAob3IgbnVtYmVyKSBvZiBwYXJ0aWFsIGludGVyYWN0aW9ucyBvdXQgb2YgdGhlIHRvdGFsIG51bWJlciBvZiBjYW5kaWRhdGUgaW50ZXJhY3Rpb25zIGZyb20gc2lSRi4gUHJvcC4gKE51bS4pIG9mIFN0YWJsZSBJbnRlcmFjdGlvbnMgaW4gQ2FuZGlkYXRlIFNldDogVGhlIHByb3BvcnRpb24gKG9yIG51bWJlcikgb2YgaW50ZXJhY3Rpb25zIHRoYXQgcGFzc2VkIHRoZSBzdGFiaWxpdHkgZmlsdGVyIHN0ZXAgb3V0IG9mIHRoZSB0b3RhbCBudW1iZXIgb2YgY2FuZGlkYXRlIGludGVyYWN0aW9ucyBmcm9tIHNpUkYuIFByb3AuIChOdW0uKSBvZiBUcnVlIEludGVyYWN0aW9ucyBpbiBTdGFibGUgU2V0OiBUaGUgcHJvcG9ydGlvbiAob3IgbnVtYmVyKSBvZiB0cnVlIGludGVyYWN0aW9ucyBvdXQgb2YgdGhlIHRvdGFsIG51bWJlciBvZiBpbnRlcmFjdGlvbnMgdGhhdCBwYXNzZWQgdGhlIHN0YWJpbGl0eSBmaWx0ZXIuIFByb3AuIChOdW0uKSBvZiBQYXJ0aWFsIEludGVyYWN0aW9ucyBpbiBTdGFibGUgU2V0OiBUaGUgcHJvcG9ydGlvbiAob3IgbnVtYmVyKSBvZiBwYXJ0aWFsIGludGVyYWN0aW9ucyBvdXQgb2YgdGhlIHRvdGFsIG51bWJlciBvZiBpbnRlcmFjdGlvbnMgdGhhdCBwYXNzZWQgdGhlIHN0YWJpbGl0eSBmaWx0ZXIuICMgSW50ZXJhY3Rpb25zIFJlamVjdGVkIChwIDwgMC4wNSk6IFRoZSBudW1iZXIgb2Ygc3RhYmxlIChvciB0ZXN0ZWQpIGludGVyYWN0aW9ucyB3aXRoIGEgcGVybXV0YXRpb24gdGVzdCBwLXZhbHVlIGJlbG93IDAuMDUuJyIKKQpjaHVua19pZHggPC0gY2h1bmtfaWR4ICsgMQpjYXQoIlxuXG4iKQpgYGAKCgojIEZpbmFsIFJlbWFya3MKCjxkaXYgY2xhc3M9InBhbmVsIHBhbmVsLWRlZmF1bHQgcGFkZGVkLXBhbmVsIj4KV2UgcmVpdGVyYXRlIHRoYXQgbG8tc2lSRiB3YXMgb3JpZ2luYWxseSBkZXZlbG9wZWQgYXMgYSBmaXJzdC1zdGFnZSByZWNvbW1lbmRhdGlvbiAob3IgaHlwb3RoZXNpcyBnZW5lcmF0aW9uKSB0b29sIHdpdGhpbiBhIGJyb2FkZXIgcGlwZWxpbmUgaW4gb3JkZXIgdG8gcHJpb3JpdGl6ZSBnZW5ldGljIGxvY2kgYW5kIGludGVyYWN0aW9ucyBiZXR3ZWVuIGxvY2kgZm9yIGRvd25zdHJlYW0gYW5hbHlzZXMgYW5kIGV4cGVyaW1lbnRhbCB2YWxpZGF0aW9uLiBJbXBvcnRhbnRseSwgdGhlIG91dHB1dCBvZiBsby1zaVJGIGlzIGEgcHJpb3JpdGl6YXRpb24vcmFua2luZyBvcmRlciwgbm90IGEgcHJvcGVyIHN0YXRpc3RpY2FsIHRlc3Qgb2Ygc2lnbmlmaWNhbmNlLiBXZSByZWx5IG9uIGZvbGxvdy11cCBpbnZlc3RpZ2F0aW9ucyBhbmQgaW4gdGhpcyBzdHVkeSByaWdvcm91cyBnZW5lLXNpbGVuY2luZyBleHBlcmltZW50cyBpbiBvcmRlciB0byB2YWxpZGF0ZSB0aGUgcHJpb3JpdGl6ZWQgZ2VuZXRpYyBsb2NpIGFuZCBpbnRlcmFjdGlvbiBiZXR3ZWVuIGxvY2kuIFdpdGggdGhhdCwgbWFueSBvZiB0aGUgbW9kZWxpbmcgZGVjaXNpb25zIGFuZCBodW1hbiBqdWRnbWVudCBjYWxscyB3ZXJlIG1hZGUgd2l0aCB0aGlzIG9yaWdpbmFsIHVzZSBjYXNlIGluIG1pbmQuIEZvciBvdGhlciB1c2UgY2FzZXMgb3IgcHJvYmxlbXMsIGl0IGlzIGhpZ2hseSBsaWtlbHkgdGhhdCBkaWZmZXJlbnQgY2hvaWNlcyBtYXkgYmUgYmV0dGVyIHN1aXRlZC4gV2UgYWxzbyBhY2tub3dsZWRnZSB0aGF0IHRob3VnaCBtYW55IHN0YWJpbGl0eSBjaGVja3Mgd2VyZSBjb25kdWN0ZWQgdG8gaGVscCBlbnN1cmUgdGhhdCBvdXIgY29uY2x1c2lvbnMgYXJlIHN0YWJsZSBhY3Jvc3MgZGlmZmVyZW50IHJlYXNvbmFibGUgZGF0YSBhbmQvb3IgbW9kZWxpbmcgcGVydHVyYmF0aW9ucywgdGhlc2Ugc3RhYmlsaXR5IGNoZWNrcyBhcmUgaW5ldml0YWJseSBjb25zdHJhaW5lZCBieSBjb21wdXRhdGlvbmFsIGxpbWl0YXRpb25zLCBhbmQgYWRkaXRpb25hbCBzdGFiaWxpdHkgYW5hbHlzZXMgY2FuIGJlIGNvbmR1Y3RlZC4gV2UgaG9wZSB0aGF0IGJ5IGRvY3VtZW50aW5nIG91ciBtb2RlbGluZyBjaG9pY2VzLCBzdGFiaWxpdHkgYW5hbHlzZXMsIGFuZCBwcm92aWRpbmcgaW5zaWdodHMgaW50byBvdXIgbW90aXZhdGlvbnMvcmVhc29ucywgdGhpcyBtYXkgaGVscCB0byBib3RoIGNsYXJpZnkgdGhlIGxpbWl0YXRpb25zIG9mIG91ciBjdXJyZW50IHdvcmsgYW5kIHRvIGZhY2lsaXRhdGUgdGhlIHRydXN0d29ydGh5ICh2ZXJpZGljYWwpIHVzZSBvZiBsby1zaVJGIChhbmQgdmFyaWFudHMgdGhlcmVvZikgaW4gb3RoZXIgc2NpZW50aWZpYyBwcm9ibGVtcy4KPC9kaXY+CgojIEJpYmxpb2dyYXBoeQoKPGRpdiBjbGFzcz0icGFuZWwgcGFuZWwtZGVmYXVsdCBwYWRkZWQtcGFuZWwiPgo8ZGl2IGlkPSJyZWZzIj48L2Rpdj4KPC9kaXY+Cg==