Introduction

About PheWAS

In this Phenome-Wide Association Study, logistic regression is used to evaluate associations between single-nucleotide polymorphisms (SNPs) in the SPTLC3 gene and phenotypes derived from clinical ICD10 diagnosis billing codes. For each logistic regression model, we estimate whether the genotype is associated with a given diagnosis.

About Phecodes

Phecodes are standardized phenotype groupings that aggregate thousands of individual diagnosis codes from electronic health records into broader, clinically interpretable categories. For example, multiple ICD codes corresponding to related diabetes diagnoses can be collapsed into a single phecode category. This approach reduces sparsity and coding heterogeneity while improving the detection of clinically meaningful genotype–phenotype associations. Phecodes can be mapped back to ICD codes using the Phecode catalog.

About All of Us

All of Us (AoU) is a large-scale, longitudinal research program launched by the National Institutes of Health (NIH) in 2015. The initiative enrolled its first participants in 2017 and has since expanded to include more than 880,000 individuals across the United States. AoU is particularly valuable for genetic and phenomic research because it integrates multiple data modalities, including participant surveys, physical measurements, wearable device data, electronic health records (EHRs), and genomic sequencing data.

About SPTLC3

Sphingolipids are bioactive lipid molecules that serve as structural components of cell membranes and participate in cellular signaling pathways. Their de novo biosynthesis is initiated by serine palmitoyltransferase (SPT), an enzyme complex that catalyzes the first committed step in sphingolipid production. The composition of the SPT complex influences the sphingoid base products generated:

  • SPTLC1 + SPTLC2 produces typical 18-carbon sphingolipids.
  • SPTLC1 + SPTLC3 produces atypical 16-carbon sphingolipids.

These atypical sphingolipids are present in many tissues but their biological function is not fully understood. In 2024, two independent studies found that reducing SPTLC3 activity had a protective effect on liver and cardiac cells. In cardiac tissue, Kovilakath et al. reported that SPTLC3 contributes to ischemic cardiomyopathy by regulating mitochondrial complex I activity, with cardiomyocyte-specific SPTLC3 depletion showing protective effects after myocardial infarction (Kovilakath, 2024). In hepatic tissue, Montefusco et al. found that SPTLC3 regulates plasma membrane sphingolipid composition and supports hepatic gluconeogenesis through adenylate cyclase/cAMP signaling (Montefusco, 2024). Together, these findings suggest that genetic variation in SPTLC3 may have physiologically relevant consequences for metabolic and cardiovascular related phenotypes.


Methods

SNP Selection

Candidate variants were identified using the All of Us Data Browser. Variants in exonic regions that had an allele frequency greater than 0.015 were selected for analysis. Two additional intronic variants of interest, rs117004417 and rs77523068, were also included, resulting in a final set of eight SNPs.

  • Allele Count: The total number of times a specific allele (variant) is observed across all chromosomes in a dataset.
  • Allele Number: The total number of valid alleles sampled for a given variant, the combined pool of all tested chromosomes.
  • Allele Frequency: The proportion of all alleles in the population that are the specific variant. (AC/AN)
  • Homozygous Count: The total number of individuals who possess two identical copies of a specific variant.
variant_metadata |> 
  select(rsid, 
         exon,
         consequence,
         allele_count,
         allele_num,
         homozygous_count,
         aou_link
  ) |> 
  mutate(aou_link = paste0("<a target='_blank', href='", aou_link, "'>AoU</a>"),
         allele_count = scales::comma(allele_count),
         allele_num = scales::comma(allele_num),
         homozygous_count = scales::comma(homozygous_count)
  ) |> 
  datatable(escape = FALSE, 
            options = list(dom = "t")
  )

SNP Location

Scroll right on the image to see the full gene. Click the image to view an interactive version on NCBI.

Cohort Construction

A separate cohort was generated for each variant. Participants carrying at least one copy of the alternate allele were classified as carriers, whereas participants with no copies were classified as non-carriers.

Covariates were incorporated into the statistical model to account for participant-level factors that may confound genotype–phenotype associations. The adjusted covariates included current age, sex assigned at birth, electronic health record length, and the first 10 genetic principal components. Participants with missing covariate values were excluded prior to analysis.

After covariate filtering, each variant-specific cohort was stratified by genetic ancestry group. This produced up to six ancestry-specific subgroups per variant:

  • African (AFR)
  • Americas (AMR)
  • East Asian (EAS)
  • European (EUR)
  • Middle Eastern (MID)
  • South Asian (SAS)

PheWAS

Phenome-wide association analyses were performed using PheTK, an open-source toolkit developed for PheWAS workflows within the All of Us Researcher Workbench. Phecodes were generated from ICD diagnosis codes using Phecode X with U.S. ICD mappings. Diagnosis codes were mapped to phecodes and aggregated at the participant–phecode level.

For each SPTLC3 variant, participants were classified using a carrier-based dominant genotype model. Individuals with genotype 0/1 or 1/1 were classified as variant carriers, and individuals with genotype 0/0 were classified as non-carriers. Covariates were added to each variant-specific cohort, including current age, sex assigned at birth, EHR length, genetically inferred ancestry, and the first 10 genetic principal components. Genetic ancestry was used to stratify analyses, whereas current age, sex assigned at birth, EHR length, and the first 10 genetic principal components were included as regression covariates. Participants with missing covariate data were excluded.

Analyses were stratified by genetically inferred ancestry group. Within each variant–ancestry cohort, logistic regression was used to test the association between variant carrier status and each phecode-defined phenotype. Carrier status was specified as the independent variable of interest, and models were adjusted for available covariates. Phecodes were tested only if at least 50 cases were present in the cohort. Participants were classified as phecode cases only if they had at least two recorded instances of the corresponding diagnosis-derived phecode.


Results

This section summarizes ancestry-stratified PheWAS results for each variant. Model convergence is shown first as a quality-control metric. Results should be interpreted cautiously when model convergence is low or case counts are sparse. Manhattan plots show the strength of association between the variant and each tested phecode. Larger points are statistically significant.

rs243887

Convergence

eur

amr

afr

eas

sas

mid

rs243888

Convergence

eur

amr

afr

eas

sas

mid

rs117004417

Convergence

eur

amr

afr

eas

sas

mid

rs77523068

Convergence

eur

amr

afr

eas

No converged models for this ancestry.

sas

mid

No converged models for this ancestry.

rs6109692

Convergence

eur

amr

afr

eas

sas

mid

rs77696068

Convergence

eur

amr

afr

eas

sas

mid

rs6078938

Convergence

eur

amr

afr

eas

sas

mid

rs61738161

Convergence

eur

amr

afr

eas

sas

mid


Meta Analysis: Manhattan Plots

This section presents meta-analysis Manhattan plots combining PheWAS results across all ancestry groups for each variant. Pooled estimates were derived using a random-effects model (REML). Results with fewer contributing ancestry groups should be interpreted with additional caution.

rs243887

rs243888

rs117004417

rs77523068

rs6109692

rs77696068

rs6078938

rs61738161


Meta Analysis: Category Heatmap

This section displays meta-analysis results organized by phecode category, with one tab per category. Each cell represents a variant–phecode pair, colored by the pooled beta estimate (log odds ratio).

Blood/Immune

Cardiovascular

Congenital

Dermatological

Endocrine/Metab

Gastrointestinal

Genetic

Genitourinary

Infections

Mental

Muscloskeletal

Neoplasms

Neurological

Pregnancy

Respiratory

Sense organs

Symptoms


Meta Analysis: QC

QQ Plot

For each variant, we rank all phecode p-values from most to least significant and plot the observed -log10(p) against what we expect if every phecode were a true null (i.e., no association anywhere). The bulk of phecodes should fall along the diagonal because most phecodes shouldn’t associate with any variant. Departure above the line at the upper right suggests a signal (or inflation). Departure below the line means deflation.

qq_data <- meta_results |>
  filter(!is.na(pval)) |>
  group_by(rsid) |>
  arrange(pval, .by_group = TRUE) |>
  mutate(
    expected = -log10(seq_along(pval) / (n() + 1)),
    observed = -log10(pval),
    lambda = median(qchisq(1 - pval, df = 1), na.rm = TRUE) / qchisq(0.5, df = 1)
  ) |>
  ungroup()

# diagonal reference line spanning the full range
ref_max <- max(c(qq_data$expected, qq_data$observed), na.rm = TRUE)

plot_ly(qq_data,
        x = ~expected,
        y = ~observed,
        color = ~rsid,
        type  = "scatter",
        mode  = "markers",
        text  = ~paste0("<b>rsid</b>: ", rsid, "<br>",
                        "<b>Phecode</b>: ", phecode, "<br>",
                        "<b>Category</b>: ", phecode_category, "<br>",
                        "<b>Description</b>: ", phecode_string, "<br>",
                        "<b>Cases</b>: ", scales::comma(meta_total_cases), "<br>",
                        "<b>Controls</b>: ", scales::comma(meta_total_controls)),
        hoverinfo = "text"
  ) |>
  add_segments(
    x = 0, 
    xend = ref_max,
    y = 0, 
    yend = ref_max,
    line      = list(color = "firebrick", width = 1.5, dash = "dash"),
    inherit   = FALSE,
    showlegend = FALSE,
    hoverinfo  = "skip"
  ) |>
  layout(
    title  = "QQ Plot by Variant",
    xaxis  = list(title = "Expected -log10(p)"),
    yaxis  = list(title = "Observed -log10(p)"),
    legend = list(orientation = "h", x = 0.5, y = -0.2, xanchor = "center")
  )

Ancestries Per Meta-Analysis

In this plot, we show how often we actually had multi-ancestry data. For each variant, we counted how many phecode-variant pairs were meta-analyzed with ancestry groups (k).

Heterogeneity (I²)

I² shows the proportion of variance in the effect estimate attributable to true between-ancestry differences vs. sampling error. This shows the distribution of I² values for phecode-variant pairs with k > 2 (I² is unreliable at k=2 (wide CI, bimodal distribution near 0% or 100%).

  • High I² suggests ancestries are telling different stories.
  • Low I² (near 0) is what we expect in a trans-ancestry PheWAS because most phecodes should show no association in any ancestry.
plot_ly(
  meta_results |> filter(n_groups > 2),
  x     = ~i2,
  color = ~rsid,
  type  = "histogram",
  opacity   = 0.7,
  hoverinfo = "x+y"
) |>
  layout(
    barmode = "overlay",
    title   = "Heterogeneity Distribution by Variant",
    xaxis   = list(title = "I² (%)"),
    yaxis   = list(title = "Count"),
    legend = list(orientation = "h", x = 0.5, y = -0.2, xanchor = "center")
  )

REML Boundary

REML (Random Effects ) estimates τ² = 0 when the data doesn’t show between-ancestry variance. This plot shows the percentage of phecode-variant meta-analyses where the random effects model collapsed to a fixed-effects model after filtering out data where the number of ancestry groups is < 2.

  • High percentage indicate low heterogeneity (the ancestries are effectively agreeing).
  • Lower percentage indicates greater between-ancestry variation (the ancestries are effectively disagreeing).
boundary_df <- meta_results |>
  filter(n_groups > 2) |>
  group_by(rsid) |>
  summarise(
    n_total    = n(),
    n_boundary = sum(tau2_boundary, na.rm = TRUE),
    pct        = round(100 * n_boundary / n_total, 1),
    .groups    = "drop"
  )

plot_ly(
  boundary_df,
  x    = ~reorder(rsid, pct),
  y    = ~pct,
  type = "bar",
  text        = ~paste0(pct, "% (", n_boundary, "/", n_total, ")"),
  textposition = "none"
) |>
  layout(
    title  = list(text = "REML τ² = 0 Boundary Rate", 
                  y = .99),
    xaxis  = list(title = ""),
    yaxis  = list(title = "% of Meta-Analyses at Boundary", range = c(0, 100))
  )

LS0tCnRpdGxlOiAiUGhlbm9tZS1XaWRlIEFzc29jaWF0aW9uIFN0dWR5IG9mIFNQVExDMyIKYXV0aG9yOiAiTWFnZ2llIEtvaG4iCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIgogICAgdGhlbWU6CiAgICAgIGJhc2VfZm9udDoKICAgICAgICBnb29nbGU6ICJFQiBHYXJhbW9uZCIKICAgICAgY29kZV9mb250OgogICAgICAgIGdvb2dsZTogIkpldEJyYWlucyBNb25vIgotLS0KCmBgYHtyIHNldHVwLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKIyBMb2FkIExpYnJhcmllcwpsaWJyYXJ5KERUKQpsaWJyYXJ5KGhlYXRtYXBseSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KG1ldGFmb3IpCgojIExvYWQgZGF0YQp2YXJpYW50X21ldGFkYXRhICA8LSByZWFkX2NzdigiZGF0YS92YXJpYW50X21ldGFkYXRhLmNzdiIpCgpwaGV3YXNfcmVzdWx0cyAgICA8LSByZWFkX2NzdigiZGF0YS9zcHRsYzNfcmVzdWx0cy5jc3YiKSB8PgogIGxlZnRfam9pbigKICAgIGRpc3RpbmN0KHZhcmlhbnRfbWV0YWRhdGEsIGFvdV9pZCwgcnNpZCksIAogICAgYnkgPSBjKCJ2YXJpYW50X2lkIiA9ICJhb3VfaWQiKQogICkKCm1ldGFfcmVzdWx0cyAgICAgIDwtIHJlYWRfY3N2KCJkYXRhL3NwdGxjM19tZXRhX3Jlc3VsdHMuY3N2IikKCiMgQ29uc3RhbnRzCkFOQ0VTVFJJRVMgPC0gYygiZXVyIiwgImFtciIsICJhZnIiLCAiZWFzIiwgInNhcyIsICJyZW0iLCAibWlkIikKTl9QSEVDT0RFUyA8LSBuX2Rpc3RpbmN0KHBoZXdhc19yZXN1bHRzJHBoZWNvZGUpCk5fVkFSSUFOVFMgPC0gbl9kaXN0aW5jdChwaGV3YXNfcmVzdWx0cyRyc2lkKQoKb3JkZXJlZF9yc2lkcyA8LSB2YXJpYW50X21ldGFkYXRhIHw+IGFycmFuZ2UocG9zaXRpb24pIHw+IHB1bGwocnNpZCkKb3JkZXJlZF9hbmMgPC0gYygiZXVyIiwgImFtciIsICJhZnIiLCAiZWFzIiwgInNhcyIsICJtaWQiKQoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgSGVscGVyOiBwcmludCBhIHBsb3RseSB3aWRnZXQgaW5saW5lIGluIHJlc3VsdHM9J2FzaXMnIGNvbnRleHQKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCnByaW50X3Bsb3RseSA8LSBmdW5jdGlvbihwKSB7CiAgaHRtbHRvb2xzOjp0YWdMaXN0KHBsb3RseTo6cGFydGlhbF9idW5kbGUocCkpIHw+IHByaW50KCkKICBjYXQoIlxuXG4iKQp9CgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIEhlbHBlcjogZm9ybWF0IHAtdmFsdWVzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmZvcm1hdF9wIDwtIGZ1bmN0aW9uKHApIHsKICBjYXNlX3doZW4oCiAgICBpcy5uYShwKSAgICAgICAgfiBOQV9jaGFyYWN0ZXJfLAogICAgcCA+PSAwLjAwMSAgICAgIH4gZm9ybWF0KHJvdW5kKHAsIDQpLCBzY2llbnRpZmljID0gRkFMU0UpLAogICAgVFJVRSAgICAgICAgICAgIH4gZm9ybWF0QyhwLCBmb3JtYXQgPSAiZSIsIGRpZ2l0cyA9IDIpCiAgKQp9CgoKCmBgYAoKIyMgSW50cm9kdWN0aW9uIHsudGFic2V0IC50YWJzZXQtcGlsbHN9CgojIyMgQWJvdXQgUGhlV0FTCgpJbiB0aGlzIFsqKlBoZW5vbWUtV2lkZSBBc3NvY2lhdGlvbiBTdHVkeSoqXShodHRwczovL3BoZXdhc2NhdGFsb2cub3JnL3BoZXdhcy8jaG9tZSksIGxvZ2lzdGljIHJlZ3Jlc3Npb24gaXMgdXNlZCB0byBldmFsdWF0ZSBhc3NvY2lhdGlvbnMgYmV0d2VlbiBzaW5nbGUtbnVjbGVvdGlkZSBwb2x5bW9ycGhpc21zIChTTlBzKSBpbiB0aGUgU1BUTEMzIGdlbmUgYW5kIHBoZW5vdHlwZXMgZGVyaXZlZCBmcm9tIGNsaW5pY2FsIElDRDEwIGRpYWdub3NpcyBiaWxsaW5nIGNvZGVzLiBGb3IgZWFjaCBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsLCB3ZSBlc3RpbWF0ZSB3aGV0aGVyIHRoZSBnZW5vdHlwZSBpcyBhc3NvY2lhdGVkIHdpdGggYSBnaXZlbiBkaWFnbm9zaXMuCgohW10oaW1nL1BoZVdBUy5zdmcpCgojIyMgQWJvdXQgUGhlY29kZXMKClsqKlBoZWNvZGVzKipdKGh0dHBzOi8vYWNhZGVtaWMub3VwLmNvbS9iaW9pbmZvcm1hdGljcy9hcnRpY2xlLzM5LzExL2J0YWQ2NTUvNzMzNTgzOSkgYXJlIHN0YW5kYXJkaXplZCBwaGVub3R5cGUgZ3JvdXBpbmdzIHRoYXQgYWdncmVnYXRlIHRob3VzYW5kcyBvZiBpbmRpdmlkdWFsIGRpYWdub3NpcyBjb2RlcyBmcm9tIGVsZWN0cm9uaWMgaGVhbHRoIHJlY29yZHMgaW50byBicm9hZGVyLCBjbGluaWNhbGx5IGludGVycHJldGFibGUgY2F0ZWdvcmllcy4gRm9yIGV4YW1wbGUsIG11bHRpcGxlIElDRCBjb2RlcyBjb3JyZXNwb25kaW5nIHRvIHJlbGF0ZWQgZGlhYmV0ZXMgZGlhZ25vc2VzIGNhbiBiZSBjb2xsYXBzZWQgaW50byBhIHNpbmdsZSBwaGVjb2RlIGNhdGVnb3J5LiBUaGlzIGFwcHJvYWNoIHJlZHVjZXMgc3BhcnNpdHkgYW5kIGNvZGluZyBoZXRlcm9nZW5laXR5IHdoaWxlIGltcHJvdmluZyB0aGUgZGV0ZWN0aW9uIG9mIGNsaW5pY2FsbHkgbWVhbmluZ2Z1bCBnZW5vdHlwZeKAk3BoZW5vdHlwZSBhc3NvY2lhdGlvbnMuIFBoZWNvZGVzIGNhbiBiZSBtYXBwZWQgYmFjayB0byBJQ0QgY29kZXMgdXNpbmcgdGhlIFtQaGVjb2RlIGNhdGFsb2ddKGh0dHBzOi8vcGhld2FzY2F0YWxvZy5vcmcvcGhld2FzLyNwaGV4KS4gCgohW10oaW1nL3BoZWNvZGVzLnN2ZykKCiMjIyBBYm91dCBBbGwgb2YgVXMKCltBbGwgb2YgVXMgKEFvVSldKGh0dHBzOi8vYWxsb2Z1cy5uaWguZ292KSBpcyBhIGxhcmdlLXNjYWxlLCBsb25naXR1ZGluYWwgcmVzZWFyY2ggcHJvZ3JhbSBsYXVuY2hlZCBieSB0aGUgTmF0aW9uYWwgSW5zdGl0dXRlcyBvZiBIZWFsdGggKE5JSCkgaW4gMjAxNS4gVGhlIGluaXRpYXRpdmUgZW5yb2xsZWQgaXRzIGZpcnN0IHBhcnRpY2lwYW50cyBpbiAyMDE3IGFuZCBoYXMgc2luY2UgZXhwYW5kZWQgdG8gaW5jbHVkZSBtb3JlIHRoYW4gODgwLDAwMCBpbmRpdmlkdWFscyBhY3Jvc3MgdGhlIFVuaXRlZCBTdGF0ZXMuIEFvVSBpcyBwYXJ0aWN1bGFybHkgdmFsdWFibGUgZm9yIGdlbmV0aWMgYW5kIHBoZW5vbWljIHJlc2VhcmNoIGJlY2F1c2UgaXQgaW50ZWdyYXRlcyBtdWx0aXBsZSBkYXRhIG1vZGFsaXRpZXMsIGluY2x1ZGluZyBwYXJ0aWNpcGFudCBzdXJ2ZXlzLCBwaHlzaWNhbCBtZWFzdXJlbWVudHMsIHdlYXJhYmxlIGRldmljZSBkYXRhLCBlbGVjdHJvbmljIGhlYWx0aCByZWNvcmRzIChFSFJzKSwgYW5kIGdlbm9taWMgc2VxdWVuY2luZyBkYXRhLgoKLSBbQWJvdXQgdGhlIFJlc2VhcmNoZXIgSHViXShodHRwczovL3d3dy5yZXNlYXJjaGFsbG9mdXMub3JnL2Fib3V0LXRoZS1yZXNlYXJjaC1odWIvKQotIFtCcm93c2UgYWdncmVnYXRlLWxldmVsIGRhdGFdKGh0dHBzOi8vZGF0YWJyb3dzZXIucmVzZWFyY2hhbGxvZnVzLm9yZy9zbnZzaW5kZWxzL1NQVExDMykKCiMjIyBBYm91dCBTUFRMQzMKClNwaGluZ29saXBpZHMgYXJlIGJpb2FjdGl2ZSBsaXBpZCBtb2xlY3VsZXMgdGhhdCBzZXJ2ZSBhcyBzdHJ1Y3R1cmFsIGNvbXBvbmVudHMgb2YgY2VsbCBtZW1icmFuZXMgYW5kIHBhcnRpY2lwYXRlIGluIGNlbGx1bGFyIHNpZ25hbGluZyBwYXRod2F5cy4gVGhlaXIgZGUgbm92byBiaW9zeW50aGVzaXMgaXMgaW5pdGlhdGVkIGJ5IHNlcmluZSBwYWxtaXRveWx0cmFuc2ZlcmFzZSAoU1BUKSwgYW4gZW56eW1lIGNvbXBsZXggdGhhdCBjYXRhbHl6ZXMgdGhlIGZpcnN0IGNvbW1pdHRlZCBzdGVwIGluIHNwaGluZ29saXBpZCBwcm9kdWN0aW9uLiBUaGUgY29tcG9zaXRpb24gb2YgdGhlIFNQVCBjb21wbGV4IGluZmx1ZW5jZXMgdGhlIHNwaGluZ29pZCBiYXNlIHByb2R1Y3RzIGdlbmVyYXRlZDoKCi0gU1BUTEMxICsgU1BUTEMyIHByb2R1Y2VzIHR5cGljYWwgMTgtY2FyYm9uIHNwaGluZ29saXBpZHMuCi0gU1BUTEMxICsgKipTUFRMQzMqKiBwcm9kdWNlcyAqYXR5cGljYWwqIDE2LWNhcmJvbiBzcGhpbmdvbGlwaWRzLgoKVGhlc2UgYXR5cGljYWwgc3BoaW5nb2xpcGlkcyBhcmUgcHJlc2VudCBpbiBtYW55IHRpc3N1ZXMgYnV0IHRoZWlyIGJpb2xvZ2ljYWwgZnVuY3Rpb24gaXMgbm90IGZ1bGx5IHVuZGVyc3Rvb2QuIEluIDIwMjQsIHR3byBpbmRlcGVuZGVudCBzdHVkaWVzIGZvdW5kIHRoYXQgcmVkdWNpbmcgU1BUTEMzIGFjdGl2aXR5IGhhZCBhIHByb3RlY3RpdmUgZWZmZWN0IG9uIGxpdmVyIGFuZCBjYXJkaWFjIGNlbGxzLiBJbiBjYXJkaWFjIHRpc3N1ZSwgS292aWxha2F0aCBldCBhbC4gcmVwb3J0ZWQgdGhhdCBTUFRMQzMgY29udHJpYnV0ZXMgdG8gaXNjaGVtaWMgY2FyZGlvbXlvcGF0aHkgYnkgcmVndWxhdGluZyBtaXRvY2hvbmRyaWFsIGNvbXBsZXggSSBhY3Rpdml0eSwgd2l0aCBjYXJkaW9teW9jeXRlLXNwZWNpZmljIFNQVExDMyBkZXBsZXRpb24gc2hvd2luZyBwcm90ZWN0aXZlIGVmZmVjdHMgYWZ0ZXIgbXlvY2FyZGlhbCBpbmZhcmN0aW9uIChbS292aWxha2F0aCwgMjAyNF0oKSkuIEluIGhlcGF0aWMgdGlzc3VlLCBNb250ZWZ1c2NvIGV0IGFsLiBmb3VuZCB0aGF0IFNQVExDMyByZWd1bGF0ZXMgcGxhc21hIG1lbWJyYW5lIHNwaGluZ29saXBpZCBjb21wb3NpdGlvbiBhbmQgc3VwcG9ydHMgaGVwYXRpYyBnbHVjb25lb2dlbmVzaXMgdGhyb3VnaCBhZGVueWxhdGUgY3ljbGFzZS9jQU1QIHNpZ25hbGluZyAoW01vbnRlZnVzY28sIDIwMjRdKCkpLiBUb2dldGhlciwgdGhlc2UgZmluZGluZ3Mgc3VnZ2VzdCB0aGF0IGdlbmV0aWMgdmFyaWF0aW9uIGluIFNQVExDMyBtYXkgaGF2ZSBwaHlzaW9sb2dpY2FsbHkgcmVsZXZhbnQgY29uc2VxdWVuY2VzIGZvciBtZXRhYm9saWMgYW5kIGNhcmRpb3Zhc2N1bGFyIHJlbGF0ZWQgcGhlbm90eXBlcy4KCiMjIHstfQoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBNZXRob2RzIHsudGFic2V0IC50YWJzZXQtcGlsbHN9CgojIyMgU05QIFNlbGVjdGlvbgoKQ2FuZGlkYXRlIHZhcmlhbnRzIHdlcmUgaWRlbnRpZmllZCB1c2luZyB0aGUgW0FsbCBvZiBVcyBEYXRhIEJyb3dzZXJdKGh0dHBzOi8vZGF0YWJyb3dzZXIucmVzZWFyY2hhbGxvZnVzLm9yZy9zbnZzaW5kZWxzL1NQVExDMykuIFZhcmlhbnRzIGluIGV4b25pYyByZWdpb25zIHRoYXQgaGFkIGFuIGFsbGVsZSBmcmVxdWVuY3kgZ3JlYXRlciB0aGFuIDAuMDE1IHdlcmUgc2VsZWN0ZWQgZm9yIGFuYWx5c2lzLiBUd28gYWRkaXRpb25hbCBpbnRyb25pYyB2YXJpYW50cyBvZiBpbnRlcmVzdCwgKipyczExNzAwNDQxNyoqIGFuZCAqKnJzNzc1MjMwNjgqKiwgd2VyZSBhbHNvIGluY2x1ZGVkLCByZXN1bHRpbmcgaW4gYSBmaW5hbCBzZXQgb2YgZWlnaHQgU05Qcy4KCi0gKipBbGxlbGUgQ291bnQqKjogVGhlIHRvdGFsIG51bWJlciBvZiB0aW1lcyBhIHNwZWNpZmljIGFsbGVsZSAodmFyaWFudCkgaXMgb2JzZXJ2ZWQgYWNyb3NzIGFsbCBjaHJvbW9zb21lcyBpbiBhIGRhdGFzZXQuCi0gKipBbGxlbGUgTnVtYmVyKio6IFRoZSB0b3RhbCBudW1iZXIgb2YgdmFsaWQgYWxsZWxlcyBzYW1wbGVkIGZvciBhIGdpdmVuIHZhcmlhbnQsIHRoZSBjb21iaW5lZCBwb29sIG9mIGFsbCB0ZXN0ZWQgY2hyb21vc29tZXMuIAotICoqQWxsZWxlIEZyZXF1ZW5jeSoqOiBUaGUgcHJvcG9ydGlvbiBvZiBhbGwgYWxsZWxlcyBpbiB0aGUgcG9wdWxhdGlvbiB0aGF0IGFyZSB0aGUgc3BlY2lmaWMgdmFyaWFudC4gKEFDL0FOKQotICoqSG9tb3p5Z291cyBDb3VudCoqOiBUaGUgdG90YWwgbnVtYmVyIG9mIGluZGl2aWR1YWxzIHdobyBwb3NzZXNzIHR3byBpZGVudGljYWwgY29waWVzIG9mIGEgc3BlY2lmaWMgdmFyaWFudC4KCmBgYHtyIHZhcmlhbnRfc3VtbWFyeX0KCnZhcmlhbnRfbWV0YWRhdGEgfD4gCiAgc2VsZWN0KHJzaWQsIAogICAgICAgICBleG9uLAogICAgICAgICBjb25zZXF1ZW5jZSwKICAgICAgICAgYWxsZWxlX2NvdW50LAogICAgICAgICBhbGxlbGVfbnVtLAogICAgICAgICBob21venlnb3VzX2NvdW50LAogICAgICAgICBhb3VfbGluawogICkgfD4gCiAgbXV0YXRlKGFvdV9saW5rID0gcGFzdGUwKCI8YSB0YXJnZXQ9J19ibGFuaycsIGhyZWY9JyIsIGFvdV9saW5rLCAiJz5Bb1U8L2E+IiksCiAgICAgICAgIGFsbGVsZV9jb3VudCA9IHNjYWxlczo6Y29tbWEoYWxsZWxlX2NvdW50KSwKICAgICAgICAgYWxsZWxlX251bSA9IHNjYWxlczo6Y29tbWEoYWxsZWxlX251bSksCiAgICAgICAgIGhvbW96eWdvdXNfY291bnQgPSBzY2FsZXM6OmNvbW1hKGhvbW96eWdvdXNfY291bnQpCiAgKSB8PiAKICBkYXRhdGFibGUoZXNjYXBlID0gRkFMU0UsIAogICAgICAgICAgICBvcHRpb25zID0gbGlzdChkb20gPSAidCIpCiAgKQoKYGBgCgojIyMgU05QIExvY2F0aW9uCgo+IDxiPlNjcm9sbCByaWdodCBvbiB0aGUgaW1hZ2UgdG8gc2VlIHRoZSBmdWxsIGdlbmUuIENsaWNrIHRoZSBpbWFnZSB0byB2aWV3IGFuIGludGVyYWN0aXZlIHZlcnNpb24gb24gTkNCSS48L2I+Cgo6Ojoge3N0eWxlPSJvdmVyZmxvdy14OiBhdXRvOyB3aWR0aDogMTAwJTsgYm9yZGVyOiAxcHggc29saWQgIzExMTsgYm9yZGVyLXJhZGl1czogNHB4OyJ9CjxhIGhyZWY9Imh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHJvamVjdHMvc3ZpZXdlci8/aWQ9MjMwMjUxOTkzNyZ0cmFja3M9W2tleTpzZXF1ZW5jZV90cmFjayxuYW1lOlNlcXVlbmNlLGRpc3BsYXlfbmFtZTpTZXF1ZW5jZSxpZDpTVEQ2NDkyMjAyMzgsYW5ub3RzOlNlcXVlbmNlLFNob3dMYWJlbDp0cnVlLENvbG9yR2Fwczp0cnVlLHNob3duOnRydWUsb3JkZXI6MV1ba2V5OmdlbmVfbW9kZWxfdHJhY2ssbmFtZTpHZW5lcyxkaXNwbGF5X25hbWU6R2VuZXMsaWQ6U1REMzE5NDk4MjAwNSxhbm5vdHM6VW5uYW1lZCxPcHRpb25zOlNob3dBbGwsQ0RTUHJvZHVjdEZlYXRzOnRydWUsTnRSdWxlcjp0cnVlLEFhUnVsZXI6dHJ1ZSxIaWdobGlnaHRNb2RlOjIsU2hvd0xhYmVsOnRydWUsc2hvd246dHJ1ZSxvcmRlcjo0XSZtaz02ODQwMHxNaXNcOiUyMHJzMjQzODg3fGZmMDAwMHw5LDY4NDE3fFN5biUyMHJzMjQzODg4fDAwODAwMHwxLDg3MTk4fFN5biUyMHJzNjEwOTY5MnwzMzk5NjZ8MSwxNTAxNTF8U3luJTIwcnM2MDc4OTM4fDAwODAwMHwxLDg5NTA4fFNwbGljZSUyMHJzNzc2OTYwNjh8ODA4MDgwfDEsMTU2MTAzfE1pcyUyMHJzNjE3MzgxNjF8RkYwMDAwfDEsNzYwMTV8SW50cm9uJTIwcnMxMTcwMDQ0MTd8ODA4MDgwfDEsNzYwNDV8SW50cm9uJTIwcnM3NzUyMzA2OHw4MDgwODB8MSZ2PTE6MTY3MTMyJmM9ZmYwMDAwJnNlbGVjdD1udWxsJnNsaW09MCIKICAgICB0YXJnZXQ9Il9ibGFuayI+IDxpbWcgc3JjPSJpbWcvU1BUTEMzX1NOUHMuc3ZnIiBzdHlsZT0id2lkdGg6IDI1MDBweDsgbWF4LXdpZHRoOiBub25lOyIvPiA8L2E+Cjo6OgoKCiMjIyBDb2hvcnQgQ29uc3RydWN0aW9uCgpBIHNlcGFyYXRlIGNvaG9ydCB3YXMgZ2VuZXJhdGVkIGZvciBlYWNoIHZhcmlhbnQuIFBhcnRpY2lwYW50cyBjYXJyeWluZyBhdCBsZWFzdCBvbmUgY29weSBvZiB0aGUgYWx0ZXJuYXRlIGFsbGVsZSB3ZXJlIGNsYXNzaWZpZWQgYXMgY2FycmllcnMsIHdoZXJlYXMgcGFydGljaXBhbnRzIHdpdGggbm8gY29waWVzIHdlcmUgY2xhc3NpZmllZCBhcyBub24tY2FycmllcnMuCgoqKkNvdmFyaWF0ZXMqKiB3ZXJlIGluY29ycG9yYXRlZCBpbnRvIHRoZSBzdGF0aXN0aWNhbCBtb2RlbCB0byBhY2NvdW50IGZvciBwYXJ0aWNpcGFudC1sZXZlbCBmYWN0b3JzIHRoYXQgbWF5IGNvbmZvdW5kIGdlbm90eXBl4oCTcGhlbm90eXBlIGFzc29jaWF0aW9ucy4gVGhlIGFkanVzdGVkIGNvdmFyaWF0ZXMgaW5jbHVkZWQgY3VycmVudCBhZ2UsIHNleCBhc3NpZ25lZCBhdCBiaXJ0aCwgZWxlY3Ryb25pYyBoZWFsdGggcmVjb3JkIGxlbmd0aCwgYW5kIHRoZSBmaXJzdCAxMCBnZW5ldGljIHByaW5jaXBhbCBjb21wb25lbnRzLiBQYXJ0aWNpcGFudHMgd2l0aCBtaXNzaW5nIGNvdmFyaWF0ZSB2YWx1ZXMgd2VyZSBleGNsdWRlZCBwcmlvciB0byBhbmFseXNpcy4KCkFmdGVyIGNvdmFyaWF0ZSBmaWx0ZXJpbmcsIGVhY2ggdmFyaWFudC1zcGVjaWZpYyBjb2hvcnQgd2FzIHN0cmF0aWZpZWQgYnkgZ2VuZXRpYyBhbmNlc3RyeSBncm91cC4gVGhpcyBwcm9kdWNlZCB1cCB0byBzaXggYW5jZXN0cnktc3BlY2lmaWMgc3ViZ3JvdXBzIHBlciB2YXJpYW50OgoKLSBBZnJpY2FuIChBRlIpCi0gQW1lcmljYXMgKEFNUikKLSBFYXN0IEFzaWFuIChFQVMpCi0gRXVyb3BlYW4gKEVVUikKLSBNaWRkbGUgRWFzdGVybiAoTUlEKQotIFNvdXRoIEFzaWFuIChTQVMpCgojIyMgUGhlV0FTCgpQaGVub21lLXdpZGUgYXNzb2NpYXRpb24gYW5hbHlzZXMgd2VyZSBwZXJmb3JtZWQgdXNpbmcgW1BoZVRLXShodHRwczovL2FjYWRlbWljLm91cC5jb20vYmlvaW5mb3JtYXRpY3MvYXJ0aWNsZS80MS8xL2J0YWU3MTkvNzkxOTYwMD9sb2dpbj1mYWxzZSksIGFuIG9wZW4tc291cmNlIHRvb2xraXQgZGV2ZWxvcGVkIGZvciBQaGVXQVMgd29ya2Zsb3dzIHdpdGhpbiB0aGUgQWxsIG9mIFVzIFJlc2VhcmNoZXIgV29ya2JlbmNoLiBQaGVjb2RlcyB3ZXJlIGdlbmVyYXRlZCBmcm9tIElDRCBkaWFnbm9zaXMgY29kZXMgdXNpbmcgUGhlY29kZSBYIHdpdGggVS5TLiBJQ0QgbWFwcGluZ3MuIERpYWdub3NpcyBjb2RlcyB3ZXJlIG1hcHBlZCB0byBwaGVjb2RlcyBhbmQgYWdncmVnYXRlZCBhdCB0aGUgcGFydGljaXBhbnTigJNwaGVjb2RlIGxldmVsLiAKCkZvciBlYWNoIFNQVExDMyB2YXJpYW50LCBwYXJ0aWNpcGFudHMgd2VyZSBjbGFzc2lmaWVkIHVzaW5nIGEgY2Fycmllci1iYXNlZCBkb21pbmFudCBnZW5vdHlwZSBtb2RlbC4gSW5kaXZpZHVhbHMgd2l0aCBnZW5vdHlwZSAwLzEgb3IgMS8xIHdlcmUgY2xhc3NpZmllZCBhcyB2YXJpYW50IGNhcnJpZXJzLCBhbmQgaW5kaXZpZHVhbHMgd2l0aCBnZW5vdHlwZSAwLzAgd2VyZSBjbGFzc2lmaWVkIGFzIG5vbi1jYXJyaWVycy4gQ292YXJpYXRlcyB3ZXJlIGFkZGVkIHRvIGVhY2ggdmFyaWFudC1zcGVjaWZpYyBjb2hvcnQsIGluY2x1ZGluZyBjdXJyZW50IGFnZSwgc2V4IGFzc2lnbmVkIGF0IGJpcnRoLCBFSFIgbGVuZ3RoLCBnZW5ldGljYWxseSBpbmZlcnJlZCBhbmNlc3RyeSwgYW5kIHRoZSBmaXJzdCAxMCBnZW5ldGljIHByaW5jaXBhbCBjb21wb25lbnRzLiBHZW5ldGljIGFuY2VzdHJ5IHdhcyB1c2VkIHRvIHN0cmF0aWZ5IGFuYWx5c2VzLCB3aGVyZWFzIGN1cnJlbnQgYWdlLCBzZXggYXNzaWduZWQgYXQgYmlydGgsIEVIUiBsZW5ndGgsIGFuZCB0aGUgZmlyc3QgMTAgZ2VuZXRpYyBwcmluY2lwYWwgY29tcG9uZW50cyB3ZXJlIGluY2x1ZGVkIGFzIHJlZ3Jlc3Npb24gY292YXJpYXRlcy4gUGFydGljaXBhbnRzIHdpdGggbWlzc2luZyBjb3ZhcmlhdGUgZGF0YSB3ZXJlIGV4Y2x1ZGVkLgoKQW5hbHlzZXMgd2VyZSBzdHJhdGlmaWVkIGJ5IGdlbmV0aWNhbGx5IGluZmVycmVkIGFuY2VzdHJ5IGdyb3VwLiBXaXRoaW4gZWFjaCB2YXJpYW504oCTYW5jZXN0cnkgY29ob3J0LCBsb2dpc3RpYyByZWdyZXNzaW9uIHdhcyB1c2VkIHRvIHRlc3QgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gdmFyaWFudCBjYXJyaWVyIHN0YXR1cyBhbmQgZWFjaCBwaGVjb2RlLWRlZmluZWQgcGhlbm90eXBlLiBDYXJyaWVyIHN0YXR1cyB3YXMgc3BlY2lmaWVkIGFzIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBvZiBpbnRlcmVzdCwgYW5kIG1vZGVscyB3ZXJlIGFkanVzdGVkIGZvciBhdmFpbGFibGUgY292YXJpYXRlcy4gUGhlY29kZXMgd2VyZSB0ZXN0ZWQgb25seSBpZiBhdCBsZWFzdCA1MCBjYXNlcyB3ZXJlIHByZXNlbnQgaW4gdGhlIGNvaG9ydC4gUGFydGljaXBhbnRzIHdlcmUgY2xhc3NpZmllZCBhcyBwaGVjb2RlIGNhc2VzIG9ubHkgaWYgdGhleSBoYWQgYXQgbGVhc3QgdHdvIHJlY29yZGVkIGluc3RhbmNlcyBvZiB0aGUgY29ycmVzcG9uZGluZyBkaWFnbm9zaXMtZGVyaXZlZCBwaGVjb2RlLgoKIyMgey19CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIFJlc3VsdHMgey50YWJzZXQgLnRhYnNldC1waWxsc30KClRoaXMgc2VjdGlvbiBzdW1tYXJpemVzIGFuY2VzdHJ5LXN0cmF0aWZpZWQgUGhlV0FTIHJlc3VsdHMgZm9yIGVhY2ggdmFyaWFudC4gTW9kZWwgY29udmVyZ2VuY2UgaXMgc2hvd24gZmlyc3QgYXMgYSBxdWFsaXR5LWNvbnRyb2wgbWV0cmljLiBSZXN1bHRzIHNob3VsZCBiZSBpbnRlcnByZXRlZCBjYXV0aW91c2x5IHdoZW4gbW9kZWwgY29udmVyZ2VuY2UgaXMgbG93IG9yIGNhc2UgY291bnRzIGFyZSBzcGFyc2UuIE1hbmhhdHRhbiBwbG90cyBzaG93IHRoZSBzdHJlbmd0aCBvZiBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSB2YXJpYW50IGFuZCBlYWNoIHRlc3RlZCBwaGVjb2RlLiBMYXJnZXIgcG9pbnRzIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKYGBge3IgY29udmVyZ2VuY2VfaGVscGVyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBDb252ZXJnZW5jZSBiYXIgY2hhcnQKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKbWFrZV9jb252ZXJnZW5jZSA8LSBmdW5jdGlvbihkYXRhLCByc2lkKSB7CiAgCiAgY29udmVyZ2VuY2Vfc3VtbWFyeSA8LSBkYXRhIHw+CiAgICBmaWx0ZXIocnNpZCA9PSAhIXJzaWQpIHw+CiAgICBncm91cF9ieShhbmNlc3RyeV9ncm91cCkgfD4KICAgIHN1bW1hcmlzZSgKICAgICAgdG90YWwgICAgICAgICA9IG4oKSwKICAgICAgbl9jb252ZXJnZWQgICA9IHN1bShjb252ZXJnZWQsIG5hLnJtID0gVFJVRSksCiAgICAgIG5fZmFpbGVkICAgICAgPSBzdW0oIWNvbnZlcmdlZCwgbmEucm0gPSBUUlVFKSwKICAgICAgcGN0X2NvbnZlcmdlZCA9IHJvdW5kKDEwMCAqIG5fY29udmVyZ2VkIC8gdG90YWwsIDEpLAogICAgICAuZ3JvdXBzICAgICAgID0gImRyb3AiCiAgICApIHw+CiAgICBhcnJhbmdlKHBjdF9jb252ZXJnZWQpIHw+CiAgICBtdXRhdGUoCiAgICAgIGxhYmVsID0gcGFzdGUwKHBjdF9jb252ZXJnZWQsICIlIiksCiAgICAgIGhvdmVyID0gcGFzdGUwKAogICAgICAgICI8Yj4iLCByc2lkLCAiPC9iPjxicj4iLAogICAgICAgICJBbmNlc3RyeTogPGI+IiwgYW5jZXN0cnlfZ3JvdXAsICI8L2I+PGJyPiIsCiAgICAgICAgIkNvbnZlcmdlZDogIiwgc2NhbGVzOjpjb21tYShuX2NvbnZlcmdlZCksCiAgICAgICAgIiBvZiAiLCBzY2FsZXM6OmNvbW1hKHRvdGFsKSwgIiBtb2RlbHM8YnI+IiwKICAgICAgICAiRmFpbGVkOiAiLCBzY2FsZXM6OmNvbW1hKG5fZmFpbGVkKSwgIjxicj4iLAogICAgICAgICJSYXRlOiAiLCBwY3RfY29udmVyZ2VkLCAiJSIKICAgICAgKQogICAgKQogIAogIHBsb3RfbHkoCiAgICBkYXRhICAgICAgICAgPSBjb252ZXJnZW5jZV9zdW1tYXJ5LAogICAgeCAgICAgICAgICAgID0gfnBjdF9jb252ZXJnZWQsCiAgICB5ICAgICAgICAgICAgPSB+YW5jZXN0cnlfZ3JvdXAsCiAgICB0eXBlICAgICAgICAgPSAiYmFyIiwKICAgIG9yaWVudGF0aW9uICA9ICJoIiwKICAgIHRleHQgICAgICAgICA9IH5sYWJlbCwKICAgIHRleHRwb3NpdGlvbiA9ICJvdXRzaWRlIiwKICAgIGhvdmVyaW5mbyAgICA9ICJ0ZXh0IiwKICAgIGhvdmVydGV4dCAgICA9IH5ob3ZlcgogICkgfD4KICAgIGxheW91dCgKICAgICAgdGl0bGUgID0gbGlzdCh0ZXh0ID0gcGFzdGUwKHJzaWQsICIgTW9kZWwgQ29udmVyZ2VuY2UiKSwgeCA9IDAuNSksCiAgICAgIHhheGlzICA9IGxpc3QodGl0bGUgPSAiQ29udmVyZ2VkIG1vZGVscyAoJSkiLCAKICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGMoMCwgMTA1KSwgCiAgICAgICAgICAgICAgICAgICAgdGlja3N1ZmZpeCA9ICIlIiksCiAgICAgIHlheGlzICA9IGxpc3QodGl0bGUgPSAiIiwgCiAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnlvcmRlciA9ICJhcnJheSIsIAogICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5YXJyYXkgPSBjb252ZXJnZW5jZV9zdW1tYXJ5JGFuY2VzdHJ5X2dyb3VwKSwKICAgICAgbWFyZ2luID0gbGlzdChsID0gNjAsIHIgPSA0MCwgdCA9IDUwLCBiID0gNDApLAogICAgICBzaG93bGVnZW5kID0gRkFMU0UKICAgICkKfQoKIyBUT0RPOiBBZGQgYSBwbG90IHRvIHRoZSBsZWZ0IG9mIHRoZSBjb252ZXJnZW5jZSAKIyBBIHBsb3Qgc2hvd2luZyB0aGUgc2lnbmlmaWNhbnQgcGhlY29kZXMgYnkgY2F0ZWdvcnksIGhvdmVyaW5nIG92ZXIgdGhlIGNhdGVnb3J5IGJhciBzaG93cyB0ZXh0IHRoYXQgaGFzIHRoZSBsaXN0IG9mIHBoZWNvZGVzIGFuZCBwaGVjb2RlIHN0cmluZ3MKYGBgCgpgYGB7ciBtYW5oYXR0YW5faGVscGVyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBNYW5oYXR0YW4gcGxvdAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwptYWtlX21hbmhhdHRhbiA8LSBmdW5jdGlvbihwbG90X2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBib25mZXJyb25pX2FscGhhID0gMC4wNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmRyX2FscGhhID0gMC4wNSkgewogIAogIHBsb3RfZGF0YSA8LSBwbG90X2RhdGEgfD4KICAgIGFycmFuZ2UocGhlY29kZV9jYXRlZ29yeSwgcGhlY29kZSkgfD4KICAgIG11dGF0ZSgKICAgICAgeF9wb3MgPSByb3dfbnVtYmVyKCksCiAgICAgIGJvbmZlcnJvbmlfdGhyZXNob2xkID0gYm9uZmVycm9uaV9hbHBoYSAvIG5fZGlzdGluY3QocGhlY29kZSksCiAgICAgIGZkcl9hZGp1c3RlZCA9IHAuYWRqdXN0KHBfdmFsdWUsIG1ldGhvZCA9ICJCSCIpLAogICAgICBib25fc2lnID0gcF92YWx1ZSA8IGJvbmZlcnJvbmlfdGhyZXNob2xkLAogICAgICBmZHJfc2lnID0gZmRyX2FkanVzdGVkIDwgZmRyX2FscGhhLAogICAgICBwb2ludF9zaXplID0gaWZfZWxzZShib25fc2lnIHwgZmRyX3NpZywgMTAsIDQpLAogICAgICBzaWdfbGFiZWwgPSBjYXNlX3doZW4oCiAgICAgICAgYm9uX3NpZyAmIGZkcl9zaWcgfiAi4pyFIEJvbmZlcnJvbmkgc2lnbmlmaWNhbnQ8YnI+4pyFIEZEUiBzaWduaWZpY2FudCIsCiAgICAgICAgYm9uX3NpZyAgICAgICAgICAgfiAi4pyFIEJvbmZlcnJvbmkgc2lnbmlmaWNhbnQiLAogICAgICAgIGZkcl9zaWcgICAgICAgICAgIH4gIuKchSBGRFIgc2lnbmlmaWNhbnQiLAogICAgICAgIFRSVUUgICAgICAgICAgICAgIH4gIiIKICAgICAgKSwKICAgICAgaG92ZXIgPSBwYXN0ZTAoCiAgICAgICAgIjxiPiIsIHBoZWNvZGVfc3RyaW5nLCAiPC9iPjxicj4iLAogICAgICAgICI8Yj5DYXRlZ29yeTo8L2I+ICIsIHBoZWNvZGVfY2F0ZWdvcnksICI8YnI+IiwKICAgICAgICAiPGI+UGhlY29kZTo8L2I+ICIsIHBoZWNvZGUsICI8YnI+IiwKICAgICAgICAiPGI+cC12YWx1ZTo8L2I+ICIsIGZvcm1hdF9wKHBfdmFsdWUpLCAiPGJyPiIsCiAgICAgICAgaG92ZXJfZGV0YWlscywKICAgICAgICBpZl9lbHNlKHNpZ19sYWJlbCAhPSAiIiwgcGFzdGUwKCI8YnI+Iiwgc2lnX2xhYmVsKSwgIiIpCiAgICAgICkKICAgICkKICAKICBjYXRlZ29yeV90aWNrcyA8LSBwbG90X2RhdGEgfD4KICAgIGdyb3VwX2J5KHBoZWNvZGVfY2F0ZWdvcnkpIHw+CiAgICBzdW1tYXJpc2UobWlkID0gbWVhbih4X3BvcyksIC5ncm91cHMgPSAiZHJvcCIpCiAgCiAgYm9uZmVycm9uaV9saW5lIDwtIGxpc3QoCiAgICBsaXN0KAogICAgICB0eXBlICA9ICJsaW5lIiwKICAgICAgbGF5ZXIgPSAiYWJvdmUiLAogICAgICB4MCA9IDAsCiAgICAgIHgxID0gbWF4KHBsb3RfZGF0YSR4X3BvcyksCiAgICAgIHkwID0gLWxvZzEwKHVuaXF1ZShwbG90X2RhdGEkYm9uZmVycm9uaV90aHJlc2hvbGQpKSwKICAgICAgeTEgPSAtbG9nMTAodW5pcXVlKHBsb3RfZGF0YSRib25mZXJyb25pX3RocmVzaG9sZCkpLAogICAgICBsaW5lID0gbGlzdCgKICAgICAgICBjb2xvciA9ICJyZWQiLAogICAgICAgIHdpZHRoID0gMS41LAogICAgICAgIGRhc2ggPSAiZGFzaCIKICAgICAgKQogICAgKQogICkKICAKICBwbG90X2x5KAogICAgZGF0YSAgICAgID0gcGxvdF9kYXRhLAogICAgeCAgICAgICAgID0gfnhfcG9zLAogICAgeSAgICAgICAgID0gfm5lZ19sb2dfcF92YWx1ZSwKICAgIGNvbG9yICAgICA9IH5waGVjb2RlX2NhdGVnb3J5LAogICAgdHlwZSAgICAgID0gInNjYXR0ZXIiLAogICAgbW9kZSAgICAgID0gIm1hcmtlcnMiLAogICAgbWFya2VyICAgID0gbGlzdChzaXplID0gfnBvaW50X3NpemUsIG9wYWNpdHkgPSAxKSwKICAgIHRleHQgICAgICA9IH5ob3ZlciwKICAgIGhvdmVyaW5mbyA9ICJ0ZXh0IiwKICAgIHNob3dsZWdlbmQgPSBGQUxTRQogICkgfD4KICAgIGxheW91dCgKICAgICAgdGl0bGUgPSBsaXN0KHRleHQgPSB0aXRsZSwgeCA9IDAuNSksCiAgICAgIHhheGlzID0gbGlzdCgKICAgICAgICB0aXRsZSAgICAgPSAiIiwKICAgICAgICB0aWNrdmFscyAgPSBjYXRlZ29yeV90aWNrcyRtaWQsCiAgICAgICAgdGlja3RleHQgID0gY2F0ZWdvcnlfdGlja3MkcGhlY29kZV9jYXRlZ29yeSwKICAgICAgICB0aWNrYW5nbGUgPSAtOTAsCiAgICAgICAgcmFuZ2UgICAgID0gYygwLCBtYXgocGxvdF9kYXRhJHhfcG9zKSArIDEpCiAgICAgICksCiAgICAgIHlheGlzID0gbGlzdCgKICAgICAgICB0aXRsZSA9ICItbG9nMTAocC12YWx1ZSkiLAogICAgICAgIHJhbmdlbW9kZSA9ICJub25uZWdhdGl2ZSIKICAgICAgKSwKICAgICAgc2hhcGVzID0gYm9uZmVycm9uaV9saW5lLAogICAgICBob3ZlcmxhYmVsID0gbGlzdChhbGlnbiA9ICJsZWZ0IikKICAgICkKfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBQcmVwIHJlZ3VsYXIgYW5jZXN0cnktc3RyYXRpZmllZCBQaGVXQVMgcmVzdWx0cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpwcmVwX3BoZXdhc19tYW5oYXR0YW4gPC0gZnVuY3Rpb24oZGF0YSwgdmFyaWFudCwgYW5jZXN0cnkpIHsKICAKICBkYXRhIHw+CiAgICBmaWx0ZXIoCiAgICAgIHJzaWQgPT0gdmFyaWFudCwKICAgICAgYW5jZXN0cnlfZ3JvdXAgPT0gYW5jZXN0cnksCiAgICAgIGNvbnZlcmdlZCwKICAgICAgIWlzLm5hKHBfdmFsdWUpLAogICAgICBpcy5maW5pdGUocF92YWx1ZSksCiAgICAgIHBfdmFsdWUgPiAwCiAgICApIHw+CiAgICBtdXRhdGUoCiAgICAgIG5lZ19sb2dfcF92YWx1ZSA9IC1sb2cxMChwX3ZhbHVlKSwKICAgICAgaG92ZXJfZGV0YWlscyA9IHBhc3RlMCgKICAgICAgICAiPGI+T2RkcyBSYXRpbzo8L2I+ICIsIHJvdW5kKG9kZHNfcmF0aW8sIDMpLAogICAgICAgICIgWyIsIHJvdW5kKGNvbmZfaW50XzEsIDIpLCAiIC0gIiwgcm91bmQoY29uZl9pbnRfMiwgMiksICJdPGJyPiIsCiAgICAgICAgIjxiPkNhc2VzOjwvYj4gIiwgc2NhbGVzOjpjb21tYShjYXNlcyksICI8YnI+IiwKICAgICAgICAiPGI+Q29udHJvbHM6PC9iPiAiLCBzY2FsZXM6OmNvbW1hKGNvbnRyb2xzKQogICAgICApCiAgICApCn0KCgpgYGAKCmBgYHtyIHJlbmRlcl9wbG90cywgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFJlbmRlciBvbmUgYW5jZXN0cnkgc3ViLXRhYiAoIyMjIyBsZXZlbCkKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKcmVuZGVyX2FuY2VzdHJ5X3RhYiA8LSBmdW5jdGlvbihkYXRhLCB2YXJpYW50LCBhbmMpIHsKICAKICBjYXQoc3ByaW50ZigiXG5cbiMjIyMgJXNcblxuIiwgYW5jKSkKICAKICBwbG90X2RhdGEgPC0gcHJlcF9waGV3YXNfbWFuaGF0dGFuKAogICAgZGF0YSAgICAgPSBkYXRhLAogICAgdmFyaWFudCAgPSB2YXJpYW50LAogICAgYW5jZXN0cnkgPSBhbmMKICApCiAgCiAgaWYgKG5yb3cocGxvdF9kYXRhKSA9PSAwKSB7CiAgICBjYXQoIipObyBjb252ZXJnZWQgbW9kZWxzIGZvciB0aGlzIGFuY2VzdHJ5LipcblxuIikKICAgIHJldHVybihpbnZpc2libGUoTlVMTCkpCiAgfQogIAogIG1ha2VfbWFuaGF0dGFuKAogICAgcGxvdF9kYXRhID0gcGxvdF9kYXRhLAogICAgdGl0bGUgICAgID0gYW5jCiAgKSB8PgogICAgcHJpbnRfcGxvdGx5KCkKfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBSZW5kZXIgb25lIHZhcmlhbnQgdGFiICgjIyMgbGV2ZWwpIHdpdGggY29udmVyZ2VuY2UgKyBhbmNlc3RyeSBzdWItdGFicwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpyZW5kZXJfdmFyaWFudF90YWIgPC0gZnVuY3Rpb24oZGF0YSwgdmFyaWFudCwgYW5jZXN0cmllcykgewogIAogIGNhdChzcHJpbnRmKCJcblxuIyMjICVzIHsudGFic2V0IC50YWJzZXQtcGlsbHN9XG5cbiIsIHZhcmlhbnQpKQogIGNhdCgiIyMjIyBDb252ZXJnZW5jZVxuXG4iKQogIG1ha2VfY29udmVyZ2VuY2UoZGF0YSwgdmFyaWFudCkgfD4gcHJpbnRfcGxvdGx5KCkKICBwdXJycjo6d2FsayhhbmNlc3RyaWVzLCBcKGFuYykgcmVuZGVyX2FuY2VzdHJ5X3RhYihkYXRhLCB2YXJpYW50LCBhbmMpKQogIGNhdCgiXG5cbiMjIyB7LX1cblxuIikKfQoKcHVycnI6OndhbGsob3JkZXJlZF9yc2lkcywgXCh2KSByZW5kZXJfdmFyaWFudF90YWIocGhld2FzX3Jlc3VsdHMsIHYsIG9yZGVyZWRfYW5jKSkKCmBgYAoKIyMgey19CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIE1ldGEgQW5hbHlzaXM6IE1hbmhhdHRhbiBQbG90cyB7LnRhYnNldCAudGFic2V0LXBpbGxzfQoKVGhpcyBzZWN0aW9uIHByZXNlbnRzIG1ldGEtYW5hbHlzaXMgTWFuaGF0dGFuIHBsb3RzIGNvbWJpbmluZyBQaGVXQVMgcmVzdWx0cyBhY3Jvc3MgYWxsIGFuY2VzdHJ5IGdyb3VwcyBmb3IgZWFjaCB2YXJpYW50LiBQb29sZWQgZXN0aW1hdGVzIHdlcmUgZGVyaXZlZCB1c2luZyBhIHJhbmRvbS1lZmZlY3RzIG1vZGVsIChSRU1MKS4gUmVzdWx0cyB3aXRoIGZld2VyIGNvbnRyaWJ1dGluZyBhbmNlc3RyeSBncm91cHMgc2hvdWxkIGJlIGludGVycHJldGVkIHdpdGggYWRkaXRpb25hbCBjYXV0aW9uLiAKCmBgYHtyIG1ldGFfbWFuaGF0dGFuLCByZXN1bHRzPSdhc2lzJywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUHJlcCBtZXRhLWFuYWx5c2lzIFBoZVdBUyByZXN1bHRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnByZXBfbWV0YV9tYW5oYXR0YW4gPC0gZnVuY3Rpb24oZGF0YSwgdmFyaWFudCkgewogIAogIGRhdGEgfD4KICAgIGZpbHRlcigKICAgICAgcnNpZCA9PSB2YXJpYW50LAogICAgICAhaXMubmEocHZhbCksCiAgICAgIGlzLmZpbml0ZShwdmFsKSwKICAgICAgcHZhbCA+IDAKICAgICkgfD4KICAgIG11dGF0ZSgKICAgICAgcF92YWx1ZSA9IHB2YWwsCiAgICAgIG5lZ19sb2dfcF92YWx1ZSA9IC1sb2cxMChwdmFsKSwKICAgICAgb2Rkc19yYXRpbyA9IGV4cChlc3RpbWF0ZSksCiAgICAgIGNpX2xvdyA9IGV4cChjaV9sYiksCiAgICAgIGNpX2hpZ2ggPSBleHAoY2lfdWIpLAogICAgICBob3Zlcl9kZXRhaWxzID0gcGFzdGUwKAogICAgICAgICI8Yj5NZXRhLWFuYWx5c2lzIE9SOjwvYj4gIiwgcm91bmQob2Rkc19yYXRpbywgMyksCiAgICAgICAgIiBbIiwgcm91bmQoY2lfbG93LCAyKSwgIiAtICIsIHJvdW5kKGNpX2hpZ2gsIDIpLCAiXTxicj4iLAogICAgICAgICI8Yj5CZXRhOjwvYj4gIiwgcm91bmQoZXN0aW1hdGUsIDMpLCAiPGJyPiIsCiAgICAgICAgIjxiPlNFOjwvYj4gIiwgcm91bmQoc2UsIDMpLCAiPGJyPiIsCiAgICAgICAgIjxiPkFuY2VzdHJ5IGdyb3Vwczo8L2I+ICIsIG5fZ3JvdXBzLCAiPGJyPiIsCiAgICAgICAgIjxiPkNhc2VzOjwvYj4gIiwgc2NhbGVzOjpjb21tYShtZXRhX3RvdGFsX2Nhc2VzKSwgIjxicj4iLAogICAgICAgICI8Yj5Db250cm9sczo8L2I+ICIsIHNjYWxlczo6Y29tbWEobWV0YV90b3RhbF9jb250cm9scykKICAgICAgKQogICAgKQp9CgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFJlbmRlciBvbmUgbWV0YS1hbmFseXNpcyBNYW5oYXR0YW4gcGxvdCBwZXIgdmFyaWFudAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpyZW5kZXJfbWV0YV92YXJpYW50X3RhYiA8LSBmdW5jdGlvbihkYXRhLCB2YXJpYW50KSB7CiAgCiAgY2F0KHNwcmludGYoIlxuXG4jIyMgJXNcblxuIiwgdmFyaWFudCkpCiAgCiAgcGxvdF9kYXRhIDwtIHByZXBfbWV0YV9tYW5oYXR0YW4oCiAgICBkYXRhICAgID0gZGF0YSwKICAgIHZhcmlhbnQgPSB2YXJpYW50CiAgKQogIAogIG1ha2VfbWFuaGF0dGFuKAogICAgcGxvdF9kYXRhID0gcGxvdF9kYXRhLAogICAgdGl0bGUgICAgID0gcGFzdGUwKHZhcmlhbnQsICIgTWV0YS1BbmFseXNpcyBNYW5oYXR0YW4gUGxvdCIpCiAgKSB8PgogICAgcHJpbnRfcGxvdGx5KCkKfQoKcHVycnI6OndhbGsob3JkZXJlZF9yc2lkcywgXCh2KSByZW5kZXJfbWV0YV92YXJpYW50X3RhYihtZXRhX3Jlc3VsdHMsIHYpKQpgYGAKCiMjIHstfQoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBNZXRhIEFuYWx5c2lzOiBDYXRlZ29yeSBIZWF0bWFwIHsudGFic2V0IC50YWJzZXQtcGlsbHN9CgpUaGlzIHNlY3Rpb24gZGlzcGxheXMgbWV0YS1hbmFseXNpcyByZXN1bHRzIG9yZ2FuaXplZCBieSBwaGVjb2RlIGNhdGVnb3J5LCB3aXRoIG9uZSB0YWIgcGVyIGNhdGVnb3J5LiBFYWNoIGNlbGwgcmVwcmVzZW50cyBhIHZhcmlhbnTigJNwaGVjb2RlIHBhaXIsIGNvbG9yZWQgYnkgdGhlIHBvb2xlZCBiZXRhIGVzdGltYXRlIChsb2cgb2RkcyByYXRpbykuCgotIEJsdWUgaW5kaWNhdGVzIGEgbmVnYXRpdmUgYXNzb2NpYXRpb24gKGRlY3JlYXNlZCByaXNrKS4KLSBSZWQgaW5kaWNhdGVzIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gKGluY3JlYXNlZCByaXNrKS4KCmBgYHtyIGNhdGVnb3J5LWhlYXRtYXAsIHJlc3VsdHM9J2FzaXMnLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKaGVhdG1hcF9kYXRhIDwtIG1ldGFfcmVzdWx0cyB8PgogIGZpbHRlcighaXMubmEoZXN0aW1hdGUpKSB8PgogIGxlZnRfam9pbih2YXJpYW50X21ldGFkYXRhIHw+IHNlbGVjdChhb3VfaWQsIGFsbGVsZV9jb3VudCksCiAgICAgICAgICAgIGJ5ID0gYygidmFyaWFudF9pZCIgPSAiYW91X2lkIikKICApIHw+CiAgZmlsdGVyKCFpcy5uYShwdmFsKSkgfD4gCiAgbXV0YXRlKAogICAgdG9vbHRpcCA9IHBhc3RlMCgKICAgICAgIjxiPlBoZWNvZGUgQ2F0ZWdvcnk8L2I+OiAiLCBwaGVjb2RlX2NhdGVnb3J5LCAiPGJyPiIsCiAgICAgICI8Yj5QaGVjb2RlPC9iPjogIiwgcGhlY29kZSwgIjxicj4iLAogICAgICAiPGI+UGhlY29kZSBEZXNjcmlwdGlvbjwvYj46ICIsIHBoZWNvZGVfc3RyaW5nLCAiPGJyPiIsCiAgICAgICI8Yj5BbGxlbGUgY291bnQ8L2I+OiAiLCBzY2FsZXM6OmNvbW1hKGFsbGVsZV9jb3VudCksICI8YnI+IiwKICAgICAgIjxiPkJldGEgKGxvZy1PZGRzIFJhdGlvKTwvYj46ICIsIHJvdW5kKGVzdGltYXRlLCAzKSwgIjxicj4iLAogICAgICAiPGI+T2RkcyBSYXRpbzwvYj46ICIsIHJvdW5kKG9kZHNfcmF0aW8sIDMpLCAiPGJyPiIsCiAgICAgICI8Yj45NSUgQ29uZmlkZW5jZSBJbnRlcnZhbDwvYj46IFsiLCByb3VuZChvcl9jaV9sYiwgMyksICIsICIsIHJvdW5kKG9yX2NpX3ViLCAzKSwgIl08YnI+IiwKICAgICAgIjxiPlAtdmFsdWU8L2I+OiAiLCBmb3JtYXRDKHB2YWwsIGZvcm1hdCA9ICJlIiwgZGlnaXRzID0gMiksICI8YnI+IiwKICAgICAgIjxiPkZEUjwvYj46ICIsIGZvcm1hdEMoZmRyLCBmb3JtYXQgPSAiZSIsIGRpZ2l0cyA9IDIpLCAiPGJyPiIsCiAgICAgICI8Yj5BbmNlc3RyeSBHcm91cHM8L2I+OiAiLCBuX2dyb3VwcywgIjxicj4iLAogICAgICAiPGI+VG90YWwgQ2FzZXM8L2I+OiAiLCBzY2FsZXM6OmNvbW1hKG1ldGFfdG90YWxfY2FzZXMpLCAiPGJyPiIsCiAgICAgICI8Yj5Ub3RhbCBDb250cm9sczwvYj46ICIsIHNjYWxlczo6Y29tbWEobWV0YV90b3RhbF9jb250cm9scyksICI8YnI+IgogICAgKQogICkKCm1heF9iZXRhIDwtIG1heChhYnMoaGVhdG1hcF9kYXRhJGVzdGltYXRlKSwgbmEucm0gPSBUUlVFKQpjYXRlZ29yaWVzIDwtIHNvcnQodW5pcXVlKGhlYXRtYXBfZGF0YSRwaGVjb2RlX2NhdGVnb3J5KSkKCmZvciAoY2F0IGluIGNhdGVnb3JpZXMpIHsKICBjYXRfZGF0YSA8LSBoZWF0bWFwX2RhdGEgfD4gZmlsdGVyKHBoZWNvZGVfY2F0ZWdvcnkgPT0gY2F0KQogIAogICMgdGFiIGhlYWRlcgogIGNhdChzcHJpbnRmKCJcblxuIyMjICVzXG5cbiIsIGNhdCkpCiAgCiAgcCA8LSBwbG90X2x5KAogICAgZGF0YSAgICAgICA9IGNhdF9kYXRhLAogICAgeCAgICAgICAgICA9IH5yc2lkLAogICAgeSAgICAgICAgICA9IH5waGVjb2RlLAogICAgeiAgICAgICAgICA9IH5lc3RpbWF0ZSwKICAgIHRleHQgICAgICAgPSB+dG9vbHRpcCwKICAgIGhvdmVyaW5mbyAgPSAidGV4dCIsCiAgICB0eXBlICAgICAgID0gImhlYXRtYXAiLAogICAgY29sb3JzY2FsZSA9IGxpc3QoCiAgICAgIGMoMCwgICAiIzIxNjZhYyIpLAogICAgICBjKDAuNSwgIiNmZmZmZmYiKSwKICAgICAgYygxLCAgICIjYjIxODJiIikKICAgICksCiAgICB6bWluICAgICAgPSAtbWF4X2JldGEsCiAgICB6bWF4ICAgICAgPSAgbWF4X2JldGEsCiAgICBzaG93c2NhbGUgPSBGQUxTRQogICkgfD4KICAgIGxheW91dCgKICAgICAgdGl0bGUgID0gbGlzdCh0ZXh0ID0gY2F0LCB4ID0gMC41KSwKICAgICAgeGF4aXMgID0gbGlzdCh0aXRsZSA9ICIiLCAKICAgICAgICAgICAgICAgICAgICBjYXRlZ29yeW9yZGVyID0gImFycmF5IiwgCiAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnlhcnJheSA9IG9yZGVyZWRfcnNpZHMpLAogICAgICB5YXhpcyAgPSBsaXN0KHRpdGxlID0gIiIsIGF1dG9yYW5nZSA9ICJyZXZlcnNlZCIpCiAgICApCiAgCiAgcHJpbnRfcGxvdGx5KHApCn0KCmBgYAoKIyMgey19CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIE1ldGEgQW5hbHlzaXM6IFFDIHsudGFic2V0IC50YWJzZXQtcGlsbHN9CgojIyMgUVEgUGxvdAoKRm9yIGVhY2ggdmFyaWFudCwgd2UgcmFuayBhbGwgcGhlY29kZSBwLXZhbHVlcyBmcm9tIG1vc3QgdG8gbGVhc3Qgc2lnbmlmaWNhbnQgYW5kIHBsb3QgdGhlIG9ic2VydmVkIC1sb2cxMChwKSBhZ2FpbnN0IHdoYXQgd2UgZXhwZWN0IGlmIGV2ZXJ5IHBoZWNvZGUgd2VyZSBhIHRydWUgbnVsbCAoaS5lLiwgbm8gYXNzb2NpYXRpb24gYW55d2hlcmUpLiBUaGUgYnVsayBvZiBwaGVjb2RlcyBzaG91bGQgZmFsbCBhbG9uZyB0aGUgZGlhZ29uYWwgYmVjYXVzZSBtb3N0IHBoZWNvZGVzIHNob3VsZG4ndCBhc3NvY2lhdGUgd2l0aCBhbnkgdmFyaWFudC4gRGVwYXJ0dXJlIGFib3ZlIHRoZSBsaW5lIGF0IHRoZSB1cHBlciByaWdodCBzdWdnZXN0cyBhIHNpZ25hbCAob3IgaW5mbGF0aW9uKS4gRGVwYXJ0dXJlIGJlbG93IHRoZSBsaW5lIG1lYW5zIGRlZmxhdGlvbi4gCgpgYGB7ciBxcV9wbG90fQogIApxcV9kYXRhIDwtIG1ldGFfcmVzdWx0cyB8PgogIGZpbHRlcighaXMubmEocHZhbCkpIHw+CiAgZ3JvdXBfYnkocnNpZCkgfD4KICBhcnJhbmdlKHB2YWwsIC5ieV9ncm91cCA9IFRSVUUpIHw+CiAgbXV0YXRlKAogICAgZXhwZWN0ZWQgPSAtbG9nMTAoc2VxX2Fsb25nKHB2YWwpIC8gKG4oKSArIDEpKSwKICAgIG9ic2VydmVkID0gLWxvZzEwKHB2YWwpLAogICAgbGFtYmRhID0gbWVkaWFuKHFjaGlzcSgxIC0gcHZhbCwgZGYgPSAxKSwgbmEucm0gPSBUUlVFKSAvIHFjaGlzcSgwLjUsIGRmID0gMSkKICApIHw+CiAgdW5ncm91cCgpCgojIGRpYWdvbmFsIHJlZmVyZW5jZSBsaW5lIHNwYW5uaW5nIHRoZSBmdWxsIHJhbmdlCnJlZl9tYXggPC0gbWF4KGMocXFfZGF0YSRleHBlY3RlZCwgcXFfZGF0YSRvYnNlcnZlZCksIG5hLnJtID0gVFJVRSkKCnBsb3RfbHkocXFfZGF0YSwKICAgICAgICB4ID0gfmV4cGVjdGVkLAogICAgICAgIHkgPSB+b2JzZXJ2ZWQsCiAgICAgICAgY29sb3IgPSB+cnNpZCwKICAgICAgICB0eXBlICA9ICJzY2F0dGVyIiwKICAgICAgICBtb2RlICA9ICJtYXJrZXJzIiwKICAgICAgICB0ZXh0ICA9IH5wYXN0ZTAoIjxiPnJzaWQ8L2I+OiAiLCByc2lkLCAiPGJyPiIsCiAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5QaGVjb2RlPC9iPjogIiwgcGhlY29kZSwgIjxicj4iLAogICAgICAgICAgICAgICAgICAgICAgICAiPGI+Q2F0ZWdvcnk8L2I+OiAiLCBwaGVjb2RlX2NhdGVnb3J5LCAiPGJyPiIsCiAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5EZXNjcmlwdGlvbjwvYj46ICIsIHBoZWNvZGVfc3RyaW5nLCAiPGJyPiIsCiAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5DYXNlczwvYj46ICIsIHNjYWxlczo6Y29tbWEobWV0YV90b3RhbF9jYXNlcyksICI8YnI+IiwKICAgICAgICAgICAgICAgICAgICAgICAgIjxiPkNvbnRyb2xzPC9iPjogIiwgc2NhbGVzOjpjb21tYShtZXRhX3RvdGFsX2NvbnRyb2xzKSksCiAgICAgICAgaG92ZXJpbmZvID0gInRleHQiCiAgKSB8PgogIGFkZF9zZWdtZW50cygKICAgIHggPSAwLCAKICAgIHhlbmQgPSByZWZfbWF4LAogICAgeSA9IDAsIAogICAgeWVuZCA9IHJlZl9tYXgsCiAgICBsaW5lICAgICAgPSBsaXN0KGNvbG9yID0gImZpcmVicmljayIsIHdpZHRoID0gMS41LCBkYXNoID0gImRhc2giKSwKICAgIGluaGVyaXQgICA9IEZBTFNFLAogICAgc2hvd2xlZ2VuZCA9IEZBTFNFLAogICAgaG92ZXJpbmZvICA9ICJza2lwIgogICkgfD4KICBsYXlvdXQoCiAgICB0aXRsZSAgPSAiUVEgUGxvdCBieSBWYXJpYW50IiwKICAgIHhheGlzICA9IGxpc3QodGl0bGUgPSAiRXhwZWN0ZWQgLWxvZzEwKHApIiksCiAgICB5YXhpcyAgPSBsaXN0KHRpdGxlID0gIk9ic2VydmVkIC1sb2cxMChwKSIpLAogICAgbGVnZW5kID0gbGlzdChvcmllbnRhdGlvbiA9ICJoIiwgeCA9IDAuNSwgeSA9IC0wLjIsIHhhbmNob3IgPSAiY2VudGVyIikKICApCmBgYAoKIyMjIEFuY2VzdHJpZXMgUGVyIE1ldGEtQW5hbHlzaXMKCkluIHRoaXMgcGxvdCwgd2Ugc2hvdyBob3cgb2Z0ZW4gd2UgYWN0dWFsbHkgaGFkIG11bHRpLWFuY2VzdHJ5IGRhdGEuIEZvciBlYWNoIHZhcmlhbnQsIHdlIGNvdW50ZWQgaG93IG1hbnkgcGhlY29kZS12YXJpYW50IHBhaXJzIHdlcmUgbWV0YS1hbmFseXplZCB3aXRoIGFuY2VzdHJ5IGdyb3VwcyAoaykuIAoKYGBge3IgYW5jZXN0cmllc19tZXRhLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKYW5jZXN0cmllc19kYXRhIDwtIG1ldGFfcmVzdWx0cyB8PgogIGdyb3VwX2J5KHJzaWQsIG5fZ3JvdXBzKSB8PgogIHN1bW1hcmlzZShuID0gbigpLAogICAgICAgICAgICBhbmNlc3RyeV9ncm91cHMgPSBwYXN0ZSh1bmlxdWUodW5saXN0KGFuY2VzdHJ5X2dyb3VwcykpLCBjb2xsYXBzZSA9ICI8YnI+IiksCiAgICAgICAgICAgIC5ncm91cHMgICAgICAgICA9ICJkcm9wIgogICkgCgpwbG90X2x5KGFuY2VzdHJpZXNfZGF0YSwKICAgICAgICB4ICAgICA9IH5mYWN0b3Iobl9ncm91cHMpLAogICAgICAgIHkgICAgID0gfm4sCiAgICAgICAgY29sb3IgPSB+cnNpZCwKICAgICAgICB0eXBlICA9ICJiYXIiLAogICAgICAgIHRleHQgID0gfnBhc3RlMCgiPGI+cnNpZDwvYj46ICIsIHJzaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+PGI+UGhlY29kZXM8L2I+OiAiLCBuLAogICAgICAgICAgICAgICAgICAgICAgICAiPGJyPjxiPkFuY2VzdHJ5IEdyb3VwczwvYj48YnI+IiwgYW5jZXN0cnlfZ3JvdXBzKSwKICAgICAgICB0ZXh0cG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgaG92ZXJpbmZvID0gInRleHQiCiAgKSB8PgogIGxheW91dCgKICAgIGJhcm1vZGUgPSAiZ3JvdXAiLAogICAgdGl0bGUgICA9ICJBbmNlc3RyeSBHcm91cCBDb3ZlcmFnZSBwZXIgVmFyaWFudCIsCiAgICB4YXhpcyAgID0gbGlzdCh0aXRsZSA9ICJOdW1iZXIgb2YgQW5jZXN0cnkgR3JvdXBzIChrKSIpLAogICAgeWF4aXMgICA9IGxpc3QodGl0bGUgPSAiTnVtYmVyIG9mIFBoZWNvZGVzIiksCiAgICBsZWdlbmQgPSBsaXN0KG9yaWVudGF0aW9uID0gImgiLCB4ID0gMC41LCB5ID0gLTAuMiwgeGFuY2hvciA9ICJjZW50ZXIiKQogICkKCmBgYAoKCiMjIyBIZXRlcm9nZW5laXR5IChJwrIpCgpJwrIgc2hvd3MgdGhlIHByb3BvcnRpb24gb2YgdmFyaWFuY2UgaW4gdGhlIGVmZmVjdCBlc3RpbWF0ZSBhdHRyaWJ1dGFibGUgdG8gdHJ1ZSBiZXR3ZWVuLWFuY2VzdHJ5IGRpZmZlcmVuY2VzIHZzLiBzYW1wbGluZyBlcnJvci4gVGhpcyBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIEnCsiB2YWx1ZXMgZm9yIHBoZWNvZGUtdmFyaWFudCBwYWlycyB3aXRoIGsgPiAyIChJwrIgaXMgdW5yZWxpYWJsZSBhdCBrPTIgKHdpZGUgQ0ksIGJpbW9kYWwgZGlzdHJpYnV0aW9uIG5lYXIgMCUgb3IgMTAwJSkuCgotIEhpZ2ggScKyIHN1Z2dlc3RzIGFuY2VzdHJpZXMgYXJlIHRlbGxpbmcgZGlmZmVyZW50IHN0b3JpZXMuCi0gTG93IEnCsiAobmVhciAwKSBpcyB3aGF0IHdlIGV4cGVjdCBpbiBhIHRyYW5zLWFuY2VzdHJ5IFBoZVdBUyBiZWNhdXNlIG1vc3QgcGhlY29kZXMgc2hvdWxkIHNob3cgbm8gYXNzb2NpYXRpb24gaW4gYW55IGFuY2VzdHJ5LgoKYGBge3IgaTJfcGxvdH0KCnBsb3RfbHkoCiAgbWV0YV9yZXN1bHRzIHw+IGZpbHRlcihuX2dyb3VwcyA+IDIpLAogIHggICAgID0gfmkyLAogIGNvbG9yID0gfnJzaWQsCiAgdHlwZSAgPSAiaGlzdG9ncmFtIiwKICBvcGFjaXR5ICAgPSAwLjcsCiAgaG92ZXJpbmZvID0gIngreSIKKSB8PgogIGxheW91dCgKICAgIGJhcm1vZGUgPSAib3ZlcmxheSIsCiAgICB0aXRsZSAgID0gIkhldGVyb2dlbmVpdHkgRGlzdHJpYnV0aW9uIGJ5IFZhcmlhbnQiLAogICAgeGF4aXMgICA9IGxpc3QodGl0bGUgPSAiScKyICglKSIpLAogICAgeWF4aXMgICA9IGxpc3QodGl0bGUgPSAiQ291bnQiKSwKICAgIGxlZ2VuZCA9IGxpc3Qob3JpZW50YXRpb24gPSAiaCIsIHggPSAwLjUsIHkgPSAtMC4yLCB4YW5jaG9yID0gImNlbnRlciIpCiAgKQpgYGAKCiMjIyBSRU1MIEJvdW5kYXJ5CgpSRU1MIChSYW5kb20gRWZmZWN0cyApIGVzdGltYXRlcyDPhMKyID0gMCB3aGVuIHRoZSBkYXRhIGRvZXNuJ3Qgc2hvdyBiZXR3ZWVuLWFuY2VzdHJ5IHZhcmlhbmNlLiBUaGlzIHBsb3Qgc2hvd3MgdGhlIHBlcmNlbnRhZ2Ugb2YgcGhlY29kZS12YXJpYW50IG1ldGEtYW5hbHlzZXMgd2hlcmUgdGhlIHJhbmRvbSBlZmZlY3RzIG1vZGVsIGNvbGxhcHNlZCB0byBhIGZpeGVkLWVmZmVjdHMgbW9kZWwgYWZ0ZXIgZmlsdGVyaW5nIG91dCBkYXRhIHdoZXJlIHRoZSBudW1iZXIgb2YgYW5jZXN0cnkgZ3JvdXBzIGlzIDwgMi4gCgotIEhpZ2ggcGVyY2VudGFnZSBpbmRpY2F0ZSBsb3cgaGV0ZXJvZ2VuZWl0eSAodGhlIGFuY2VzdHJpZXMgYXJlIGVmZmVjdGl2ZWx5IGFncmVlaW5nKS4gCi0gTG93ZXIgcGVyY2VudGFnZSBpbmRpY2F0ZXMgZ3JlYXRlciBiZXR3ZWVuLWFuY2VzdHJ5IHZhcmlhdGlvbiAgKHRoZSBhbmNlc3RyaWVzIGFyZSBlZmZlY3RpdmVseSBkaXNhZ3JlZWluZykuICAKCmBgYHtyIHJlbWxfcGxvdH0KYm91bmRhcnlfZGYgPC0gbWV0YV9yZXN1bHRzIHw+CiAgZmlsdGVyKG5fZ3JvdXBzID4gMikgfD4KICBncm91cF9ieShyc2lkKSB8PgogIHN1bW1hcmlzZSgKICAgIG5fdG90YWwgICAgPSBuKCksCiAgICBuX2JvdW5kYXJ5ID0gc3VtKHRhdTJfYm91bmRhcnksIG5hLnJtID0gVFJVRSksCiAgICBwY3QgICAgICAgID0gcm91bmQoMTAwICogbl9ib3VuZGFyeSAvIG5fdG90YWwsIDEpLAogICAgLmdyb3VwcyAgICA9ICJkcm9wIgogICkKCnBsb3RfbHkoCiAgYm91bmRhcnlfZGYsCiAgeCAgICA9IH5yZW9yZGVyKHJzaWQsIHBjdCksCiAgeSAgICA9IH5wY3QsCiAgdHlwZSA9ICJiYXIiLAogIHRleHQgICAgICAgID0gfnBhc3RlMChwY3QsICIlICgiLCBuX2JvdW5kYXJ5LCAiLyIsIG5fdG90YWwsICIpIiksCiAgdGV4dHBvc2l0aW9uID0gIm5vbmUiCikgfD4KICBsYXlvdXQoCiAgICB0aXRsZSAgPSBsaXN0KHRleHQgPSAiUkVNTCDPhMKyID0gMCBCb3VuZGFyeSBSYXRlIiwgCiAgICAgICAgICAgICAgICAgIHkgPSAuOTkpLAogICAgeGF4aXMgID0gbGlzdCh0aXRsZSA9ICIiKSwKICAgIHlheGlzICA9IGxpc3QodGl0bGUgPSAiJSBvZiBNZXRhLUFuYWx5c2VzIGF0IEJvdW5kYXJ5IiwgcmFuZ2UgPSBjKDAsIDEwMCkpCiAgKQpgYGAKCiMjIHstfQoK