Summary

QC_Status PASS
Purity 0.43 (0.41-0.79)
Ploidy 2.911 (2.851-4.917)
Gender MALE
Top MutSigs Old: Sig3 (11082), Sig13 (6441) - New: SBS13 (6369), SBS39 (4511)
CNVs (Somatic) Min: -0.52; Max: 11.52; N: 1497
SVs (unmelted) Sum: 807, INS: 19, DUP: 205, DEL: 375, BND: 208
SVs (melted) Sum: 15879, INS: 21, DUP: 6788, DEL: 8819, BND: 251
Genome hg38
AF Summary Stats
set n mean median mode
Global 32264 0.28 0.24 0.25
Key genes CDS 67 0.32 0.25 0.25

Somatic Mutation Profiles

Allelic Frequencies

Summarised below are the allele frequencies (AFs) for somatic variants detected genome-wide (Global) vs. within the coding sequence of ~1,100 UMCCR cancer genes (Key Genes CDS). AFs range from 0 to 1, or 0%-100% (we filter out all novel variants with AF < 10%).

Details

Variants are typically called in bcbio by 3 different callers, with calls supported by at least 2 of them used (“ensemble” approach). In some cases only a single caller is used due to technical reasons (e.g. highly mutated FFPE sample).

The following post-processing steps occur:

  1. somatic_vcf_annotate: annotate VCF against databases of known hotspots, germline variants, low mappability regions, UMCCR panel of normals
  2. somatic_vcf_filter: filter VCF to remove germline variants and artefacts, but keep known hotspots
  3. As preparation for the allelic frequencies plots:
    • subset_to_giab: keep variants in ‘high confidence’ regions as determined by the Genome in a Bottle consortium
    • keep only variants with AF above 10%
  4. Allele frequencies for global and keygenes:
    • afs: grab only the INFO/TUMOR_AF field and output to final txt file
    • afs_keygenes: grab the CHROM, POS, ID, REF, ALT and INFO/TUMOR_AF for variants in the UMCCR cancer gene BED file, and output to final txt file

Mutational Signatures

Deciphering the mutational signature of a tumor sample can provide insight into the mutational processes involved in carcinogenesis and help in cancer treatment and prevention. The MutationalPatterns R package is used to generate a mutation signature for the sample. We use the final filtered somatic calls as input.

Context signature

Point mutation spectrum

Description

We can count the mutation type occurrences for the input VCF. For C>T mutations, a distinction is made between C>T at CpG sites and other sites, as deamination of methylated cytosine at CpG sites is a common mutational process. This is the reason the reference genome is needed.

A mutation spectrum shows the relative contribution of each mutation type in the base substitution catalogs. We can plot the mean relative contribution of each of the 6 base substitution types over all samples. Error bars indicate standard deviation over all samples. The total number of mutations is indicated. We can also distinguish between C>T at CpG sites and other sites.

Transcriptional strand bias

Description

We can determine if a gene mutation is on the transcribed or non-transcribed strand, which can be used to evaluate the involvement of transcription-coupled repair. By convention base substitutions are regarded as C>X or T>X, so we try to determine whether the C or T base is on the same strand as the gene definition. Base substitutions on the same strand as the gene definition are considered ‘untranscribed’, and on the opposite strand ‘transcribed’, since the gene definitions report the coding or sense strand, which is untranscribed. No strand information is reported for base substitutions that overlap with more than one gene on different strands.

Replicative strand bias

Description

The involvement of replication-associated mechanisms can be evaluated by testing for a mutational bias between the leading and lagging strand. The replication strand is dependent on the locations of replication origins from which DNA replication is fired. However, replication timing is dynamic and cell-type specific, which makes replication strand determination less straightforward than transcriptional strand bias analysis. Replication timing profiles can be generated with Repli-Seq experiments. Once the replication direction is defined, a strand asymmetry analysis can be performed similarly as the transcription strand bias analysis.

Signature Contribution

Description

The contribution of any set of signatures to the mutational profile of a sample can be quantified. This unique feature is specifically useful for mutational signature analyses of small cohorts or individual samples, but also to relate own findings to known signatures and published findings. The fit_to_signatures function finds the optimal linear combination of mutational signatures that most closely reconstructs the mutation matrix by solving a non-negative least-squares constraints problem.

Shown are signatures with positive Contribution values, along with summarised descriptions and reference signature plots from https://cancer.sanger.ac.uk/cosmic/signatures.

 

OLD

Rank Signature Contribution Description Plot
1 Sig3 11082 Breast, ovarian, pancreatic; germline + somatic BRCA1/BRCA2 mut; failure of DNA ds break-repair; many large indels.
2 Sig13 6441 In 22 cancers; mostly cervical, bladder, breast; AID/APOBEC; C>G mut; similar to sig2; maybe viral infection, retrotransposon jumping or tissue inflammation; kataegis.
3 Sig2 4072 In 22 cancers; mostly cervical + bladder; AID/APOBEC; similar to sig13; maybe viral infection, retrotransposon jumping or tissue inflammation; exon TSB.
4 Sig8 3270 Breast cancer, medulloblastoma; many CC>AA subs; weak strand bias for C>A subs.
5 Sig19 2220 Only in pilocytic astrocytoma.
6 Sig7 1985 Skin, lip, head, neck or oral squamous cancers; ultraviolet light exposure; many CC>TT subs; strong TSB with many C>T mut.
7 Sig16 1246 Liver; strong TSB for T>C at ATN context.
8 Sig12 1093 Liver; TSB for T>C.
9 Sig1 1082 All cancers; correlates with age of diagnosis; few small indels
10 Sig9 996 Chronic lymphocytic leukaemias, malignant B-cell lymphomas; mut pattern associated with polymerase H (implicated with AID during som hypermutation).
11 Sig11 644 Melanoma, glioblastoma; alkylating agents; TSB for C>T.
12 Sig27 66 Subset of kidney clear cell carcinomas; strong TSB for T>A; many small indels.
13 Sig28 38 Subset of stomach cancers.
14 Sig10 6 In 6 cancers; mostly colorectal and uterine; hypermutated samples due to altered POLE activity; TSB for C>A at TCT context, T>G at TTT context.

NEW

Rank Signature Contribution Description Plot
1 SBS13 6369 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS13.tt
2 SBS39 4511 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS39.tt
3 SBS2 3866 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS2.tt
4 SBS8 3412 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS8.tt
5 SBS3 2803 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS3.tt
6 SBS19 1922 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS19.tt
7 SBS5 1833 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS5.tt
8 SBS7a 1749 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS7a.tt
9 SBS41 1222 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS41.tt
10 SBS37 921 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS37.tt
11 SBS1 733 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS1.tt
12 SBS32 715 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS32.tt
13 SBS31 473 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS31.tt
14 SBS46 (SA) 468 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS46.tt
15 SBS58 (SA) 424 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS58.tt
16 SBS14 370 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS14.tt
17 SBS30 351 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS30.tt
18 SBS12 332 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS12.tt
19 SBS50 (SA) 284 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS50.tt
20 SBS10b 264 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS10b.tt
21 SBS7b 246 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS7b.tt
22 SBS7c 245 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS7c.tt
23 SBS54 (SA) 183 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS54.tt
24 SBS85 151 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS85.tt
25 SBS16 149 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS16.tt
26 SBS17b 125 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS17b.tt
27 SBS53 (SA) 105 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS53.tt
28 SBS43 (SA) 86 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS43.tt
29 SBS27 (SA) 74 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS27.tt
30 SBS55 (SA) 50 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS55.tt
31 SBS35 20 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS35.tt
32 SBS38 17 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS38.tt
32 SBS59 (SA) 17 https://cancer.sanger.ac.uk/cosmic/signatures/SBS/SBS59.tt

 

Rainfall Plot

Rainfall plots show the distribution of mutations along the genome, with mutation types indicated with different colors. The y-axis corresponds to the distance of a mutation from the previous mutation, and is log10 transformed. Drop-downs from the plots indicate clusters or “hotspots” of mutations.

Circos Plots

Circos plots are generated by PURPLE. The first BAF plot is based on PURPLE data and configuration files.

BAF, Total/Minor CN, SVs

Description

  • Track1: Chromosomes. Darker shaded areas: gaps in reference genome (centromeres, heterochromatin & missing short arms)
  • Track2: Beta Allele Frequency. Given that the BAF points correspond to allele frequencies of heterozygous SNPs that are common in germline samples, there shouldn’t be any in chromosome Y (and chromosome X when male).
  • Track3: Total copy number changes adjusted for tumor purity, including focal and chromosomal somatic events. Red = Loss; Green = Gain. Scaled from 0 (complete loss) to 6 (high level gains). If > 6, shown as 6 with a green dot on the outermost green gridline.
  • Track4: Minor allele copy numbers. Range from 0 to 3. Expected normal minor allele copy number is 1, and anything below 1 is shown as a loss (Orange), representing an LOH event. Minor allele copy numbers above 1 (Blue) indicate gains of both A and B alleles.
  • Track5 (Inner circle): Observed structural variants within or between the chromosomes.
    • Blue = Translocations
    • Red = Deletions
    • Yellow = Insertions
    • Green = Tandem duplications
    • Black = Inversions

SNVs/Indels, Total/Minor CN, SVs

Description

  • Track1: Chromosomes. Darker shaded areas: gaps in reference genome (centromeres, heterochromatin & missing short arms)
  • Track2: Somatic variants (incl. exon, intron and intergenic regions).
    • outer ring: SNP allele frequencies, corrected for tumor purity and scaled from 0 to 100%. Each dot represents a single somatic variant, coloured according to the type of base change (e.g. C>T/G>A in red).
    • inner ring: short insertion (yellow) and deletion (red) locations.
  • Track3: Observed total copy number changes adjusted for tumor purity, including focal and chromosomal somatic events. Red = Loss; Green = Gain. Scaled from 0 (complete loss) to 6 (high level gains). If > 6, shown as 6 with a green dot on the outermost green gridline.
  • Track4: Observed minor allele copy numbers. Range from 0 to 3. Expected normal minor allele copy number is 1, and anything below 1 is shown as a loss (Orange), representing an LOH event. Minor allele copy numbers above 1 (Blue) indicate gains of both A and B alleles.
  • Track5 (Inner circle): Observed structural variants within or between the chromosomes.
    • Blue = Translocations
    • Red = Deletions
    • Yellow = Insertions
    • Green = Tandem duplications
    • Black = Inversions

Allele Ratios, BAF

Description

  • Track1: Chromosomes. Darker shaded areas: gaps in reference genome (centromeres, heterochromatin & missing short arms)
  • Track2: Tumor and Normal Allele Ratios
  • Track3: Beta Allele Frequency Given that the BAF points correspond to allele frequencies of heterozygous SNPs that are common in germline samples, there shouldn’t be any in chromosome Y (and chromosome X when male).

Structural Variants

Structural variants are inferred with Manta, adjusted using PURPLE, and prioritised using simple_sv_annotation. Allele frequencies, copy number changes and ploidy are purity-adjusted.

Details

The input file corresponds to umccrised/<batch>/structural/<batch>-manta.tsv.

It’s generated through the following steps:

Step 1: Processing

  • Input: Manta structural variant calls from bcbio (final/<tumor-name>/<batch-name>-sv-prioritize-manta.vcf.gz (or <batch-name>-manta.vcf.gz if not prioritised))
  • Remove following annotations from Manta VCF: ‘INFO/SIMPLE_ANN’, ‘INFO/SV_HIGHEST_TIER’, ‘FILTER/Intergenic’, ‘FILTER/MissingAnn’, ‘FILTER/REJECT’
  • Prioritise variants with simple_sv_annotation`
  • Output: work/{batch}/structural/prioritize/{batch}-manta.vcf.gz
  • Keep PASS variants
  • If more than 100,000 variants, keep only variants where INFO/SV_TOP_TIER <= 3
  • Output: work/{batch}/structural/keep_pass/{batch}-manta.vcf
  • Deal with chromosome capitalisation occurring from SnpEff
  • Run BreakPointInspector (BPI) if it was disabled in bcbio
  • Output: work/{batch}/structural/maybe_bpi/{batch}-manta.vcf

Step 2: Filtering

  • Keep PASS variants (since BPI updates the FILTER column)
  • For BND variants require paired reads support (PR) to be higher than split read support (SR)
  • Keep all INFO/SV_TOP_TIER <= 2 variants
  • For INFO/SV_TOP_TIER > 2 variants require split or paired reads support of at least 5x
  • For INFO/SV_TOP_TIER > 2 variants with low allele frequency at any breakpoint (BPI_AF[0 or 1] < 0.1), require SR or PR support of at least 10x
  • Output: work/{batch}/structural/filt/{batch}-manta.vcf

Step 3: PURPLE and FFPE conditional

  • If the sample is not FFPE:
    • Feed above filtered SVs to PURPLE, which outputs purple.sv.vcf.gz that contains rescued SVs
    • Prioritise variants (again)
    • Remove ‘INFO/ANN’ annotation
    • Output: {batch}/structural/{batch}-manta.vcf.gz
  • If the sample is FFPE:
    • Just copy filtered variants and don’t do anything (i.e. we don’t want the rescued SVs from PURPLE since they’ll likely be heaps) (note that PURPLE will still get fed with the filtered SVs)
    • Output: {batch}/structural/{batch}-manta.vcf.gz

Step 4: TSV final output

  • Input: {batch}/structural/{batch}-manta.vcf.gz VCF
  • Output: {batch}/structural/{batch}-manta.tsv TSV
Description of Manta TSV columns
Column Description
AF_BPI INFO/BPI_AF: AF at each breakpoint (so AF_BPI1,AF_BPI2)
AF_PURPLE INFO/PURPLE_AF: AF at each breakend (purity adjusted) (so AF_PURPLE1,AF_PURPLE2)
annotation INFO/SIMPLE_ANN: Simplified structural variant annotation: ‘SVTYPE | EFFECT | GENE(s) | TRANSCRIPT | PRIORITY (1-4)’
caller Manta SV caller
chrom CHROM column in VCF
CN_change_PURPLE INFO/PURPLE_CN_CHANGE: change in CN at each breakend (purity adjusted) (so CN_change_PURPLE1,CN_change_PURPLE2)
CN_PURPLE INFO/PURPLE_CN: CN at each breakend (purity adjusted) (so CN_PURPLE1,CN_PURPLE2)
end INFO/END: End position of the variant described in this record
END_BPI INFO/BPI_END: BPI adjusted breakend location
ID ID column in VCF
MATEID INFO/MATEID: ID of mate breakend
paired_support_PE FORMAT/PE of tumor sample: ??
paired_support_PR FORMAT/PR of tumor sample: Spanning paired-read support for the ref and alt alleles in the order listed, for reads where P(allele|read)>0.999
Ploidy_PURPLE INFO/PURPLE_PLOIDY: Ploidy of variant (purity adjusted)
PURPLE_status INFERRED if FILTER=INFERRED, or RECOVERED if has INFO/RECOVERED, else blank. INFERRED: Breakend inferred from copy number transition
sample Tumor sample name
somaticscore INFO/SOMATICSCORE: Somatic variant quality score
split_read_support FORMAT/SR of tumor sample: Split reads for the ref and alt alleles in the order listed, for reads where P(allele|read)>0.999
start POS column in VCF
START_BPI INFO/BPI_START: BPI adjusted breakend location
svtype INFO/SVTYPE: Type of structural variant
tier INFO/SV_TOP_TIER (or 4 if missing): Highest priority tier for the effects of a variant entry

 

Prioritisation process

  1. Annotate with SnpEff based on Ensembl gene model
  2. Subset annotations to APPRIS principal transcripts
  3. Prioritize variants with simple_sv_annotation 1(high)-2(moderate)-3(low)-4(no interest):
  • exon loss

    • on prioritisation gene list (1)
    • other (2)
  • gene_fusion

    • paired (hits two genes)
      • on list of known pairs (1) (curated by HMF)
      • one gene is a known promiscuous fusion gene (1) (curated by HMF)
      • on list of FusionCatcher known pairs (2)
      • other:
        • one or two genes on prioritisation gene list (2)
        • neither gene on prioritisation gene list (3)
    • unpaired (hits one gene)
      • on prioritisation gene list (2)
      • others (3)
  • upstream or downstream

    • on prioritisation gene list genes (2) - e.g. one gene is got into control of another gene’s promoter and get overexpressed (oncogene) or underexpressed (tsgene)
  • LoF or HIGH impact in a tumor suppressor

    • on prioritisation gene list (2)
    • other TS gene (3)
  • other (4)

  • Use PURPLE copy number caller to infer more SV calls from copy number transitions (marked as ‘PURPLE Inferred’)

name abbreviation
3_prime_UTR_truncation 3UTRtrunc
3_prime_UTR_variant 3UTRvar
5_prime_UTR_truncation 5UTRtrunc
5_prime_UTR_variant 5UTRvar
bidirectional_gene_fusion BidFusG
chromosome_number_variation ChromNumV
conservative_inframe_deletion ConsInframeDel
feature_ablation DelG
transcript_ablation DelTx
downstream_gene_variant DnstreamGV
duplication Dup
exon_loss_variant ExonLossV
frameshift_variant FrameshiftV
feature_fusion Fus
gene_fusion FusG
intergenic_region IntergenReg
intragenic_variant IntragenV
intron_variant IntronV
no_func_effect NoFuncEff
non_coding_transcript_variant NoncodTxV
no_prio_effect NoPrioEff
splice_acceptor_variant SpliceAccV
splice_donor_variant SpliceDonV
splice_region_variant SpliceRegV
start_lost StartLoss
stop_gained StopGain
stop_lost StopLoss
TFBS_ablation TFBSDel
TF_binding_site_variant TFBSVar
upstream_gene_variant UpstreamGV

 

Summary

SV type by top tier before
breaking down by annotation
BND DEL DUP INS Sum
1 0 0 1 0 1
2 20 27 35 0 82
3 4 27 11 1 43
4 184 321 158 18 681
Sum 208 375 205 19 807
SV type by individual tier after
breaking down by annotation
BND DEL DUP INS Sum
1 0 0 1 0 1
2 26 117 43 0 186
3 6 257 222 1 486
4 219 8445 6522 20 15206
Sum 251 8819 6788 21 15879

Unmelted Variants

Description

Column Description
varnum Original event row number that connects variants to events
TierTop Top priority of the event (from ‘simple_sv_annotation’: 1 highest, 4 lowest)
Chr Chromosome
Start Start position as inferred by BPI (for PURPLE-inferred SVs we use POS)
End End position. For BNDs this has been assigned to the Chr:Start of the BND’s mate for convenience. Values are inferred by BPI (PURPLE-inferred SVs don’t have an End).
Type Type of structural variant
ID ID of BND from Manta (or PURPLE for PURPLE-inferred SVs))
MATEID ID of BND mate from Manta
BND_ID ID of BND pair simplified. BNDs with the same BND_ID belong to the same translocation event
BND_mate ‘A’ or ‘B’ depending on if it’s the first or second mate in the BND pair
SR_PR_alt Number of Split Reads and Paired Reads supporting the alt allele, for reads where P(allele|read)>0.999
SR_PR_ref Number of Split Reads and Paired Reads supporting the ref allele, for reads where P(allele|read)>0.999
Ploidy Ploidy of variant from PURPLE (purity adjusted)
AF_PURPLE PURPLE AF at each breakend preceded by their average
AF_BPI BPI AF at each breakend preceded by their average
CNC Copy Number Change at each breakend preceded by their average
CN Copy Number at each breakend preceded by their average
SScore Somatic variant quality score
nann Number of annotations for given event

Translocations (BNDs)

Main Columns

Description

Column Description
nrow Row number that connects variants between tables in same tab set
varnum Original event row number that connects variants to events
Tier Priority of the specific event (from ‘simple_sv_annotation’: 1 highest, 4 lowest)
Chr Chromosome
Start Start position as inferred by BPI (for PURPLE-inferred SVs we use POS)
End End position. For BNDs this has been assigned to the Chr:Start of the BND’s mate for convenience. Values are inferred by BPI (PURPLE-inferred SVs don’t have an End).
ID ID of BND from Manta (or PURPLE for PURPLE-inferred SVs))
BND_ID ID of BND pair simplified. BNDs with the same BND_ID belong to the same translocation event
BND_mate ‘A’ or ‘B’ depending on if it’s the first or second mate in the BND pair
Genes Genes involved in the event. DEL/DUP/INS events involving more than 2 genes are shown in separate table.
Effect SV effect (based on SnpEff Effect Sequence Ontology - abbreviations are shown under Details in the Effects table
Detail Prioritisation detail (from ‘simple_sv_annotation’)
SR_PR_alt Number of Split Reads and Paired Reads supporting the alt allele, for reads where P(allele|read)>0.999
Ploidy Ploidy of variant from PURPLE (purity adjusted)
AF_PURPLE PURPLE AF at each breakend preceded by their average

Other Columns

Description

Column Description
nrow Row number that connects variants between tables in same tab set
AF_BPI BPI AF at each breakend preceded by their average
CNC Copy Number Change at each breakend preceded by their average
CN Copy Number at each breakend preceded by their average
SR_PR_ref Number of Split Reads and Paired Reads supporting the ref allele, for reads where P(allele|read)>0.999
SScore Somatic variant quality score
ntrx Number of transcripts for given event
Transcript Transcripts involved in the event. DEL/DUP/INS events involving more than 2 transcripts are shown in separate table.

PURPLE Inferred

Description

Column Description
Tier Priority of the specific event (from ‘simple_sv_annotation’: 1 highest, 4 lowest)
Chr Chromosome
Start Start position as inferred by BPI (for PURPLE-inferred SVs we use POS)
Effect SV effect (based on SnpEff Effect Sequence Ontology - abbreviations are shown under Details in the Effects table
Detail Prioritisation detail (from ‘simple_sv_annotation’)
Ploidy Ploidy of variant from PURPLE (purity adjusted)
CN Copy Number at each breakend preceded by their average
CNC Copy Number Change at each breakend preceded by their average
ID ID of BND from Manta (or PURPLE for PURPLE-inferred SVs))

DEL/DUP/INS

Main Columns

Description

Column Description
nrow Row number that connects variants between tables in same tab set
varnum Original event row number that connects variants to events
TierTop Top priority of the event (from ‘simple_sv_annotation’: 1 highest, 4 lowest)
Tier Priority of the specific event (from ‘simple_sv_annotation’: 1 highest, 4 lowest)
Type Type of structural variant
Chr Chromosome
Start Start position as inferred by BPI (for PURPLE-inferred SVs we use POS)
End End position. For BNDs this has been assigned to the Chr:Start of the BND’s mate for convenience. Values are inferred by BPI (PURPLE-inferred SVs don’t have an End).
Effect SV effect (based on SnpEff Effect Sequence Ontology - abbreviations are shown under Details in the Effects table
Genes Genes involved in the event. DEL/DUP/INS events involving more than 2 genes are shown in separate table.
Transcript Transcripts involved in the event. DEL/DUP/INS events involving more than 2 transcripts are shown in separate table.
Detail Prioritisation detail (from ‘simple_sv_annotation’)
SR_PR_alt Number of Split Reads and Paired Reads supporting the alt allele, for reads where P(allele|read)>0.999
AF_PURPLE PURPLE AF at each breakend preceded by their average

Other Columns

Description

Column Description
varnum Original event row number that connects variants to events
Ploidy Ploidy of variant from PURPLE (purity adjusted)
AF_BPI BPI AF at each breakend preceded by their average
CNC Copy Number Change at each breakend preceded by their average
CN Copy Number at each breakend preceded by their average
SR_PR_ref Number of Split Reads and Paired Reads supporting the ref allele, for reads where P(allele|read)>0.999
SScore Somatic variant quality score

Many Genes

Description

Column Description
nrow Row number that connects variants between tables in same tab set
varnum Original event row number that connects variants to events
Tier Priority of the specific event (from ‘simple_sv_annotation’: 1 highest, 4 lowest)
Type Type of structural variant
Chr Chromosome
Start Start position as inferred by BPI (for PURPLE-inferred SVs we use POS)
End End position. For BNDs this has been assigned to the Chr:Start of the BND’s mate for convenience. Values are inferred by BPI (PURPLE-inferred SVs don’t have an End).
Effect SV effect (based on SnpEff Effect Sequence Ontology - abbreviations are shown under Details in the Effects table
ngen Number of genes for given event
Genes Genes involved in the event. DEL/DUP/INS events involving more than 2 genes are shown in separate table.

Many Transcripts

Description

Column Description
nrow Row number that connects variants between tables in same tab set
varnum Original event row number that connects variants to events
Tier Priority of the specific event (from ‘simple_sv_annotation’: 1 highest, 4 lowest)
Type Type of structural variant
Chr Chromosome
Start Start position as inferred by BPI (for PURPLE-inferred SVs we use POS)
End End position. For BNDs this has been assigned to the Chr:Start of the BND’s mate for convenience. Values are inferred by BPI (PURPLE-inferred SVs don’t have an End).
Effect SV effect (based on SnpEff Effect Sequence Ontology - abbreviations are shown under Details in the Effects table
ntrx Number of transcripts for given event
Transcript Transcripts involved in the event. DEL/DUP/INS events involving more than 2 transcripts are shown in separate table.

Copy Number Variants

The purity and ploidy estimator PURPLE is used to generate a copy number profile for the somatic sample.

QC, Purity and Ploidy Summary

PURPLE outputs a QC status along with a summary for the inferred purity and ploidy of the somatic sample. A failed QC status can be attributed to several factors (see Description below).

Description

QC Status

The QC Status field reflects how we have determined the purity of the sample:

  • NORMAL - PURPLE fit the purity using COBALT and AMBER output.
  • HIGHLY_DIPLOID - The fitted purity solution is highly diploid (> 95%) with a large range of potential solutions, but somatic variants are unable to help either because they were not supplied or because their implied purity was too low.
  • SOMATIC - Somatic variants have improved the otherwise highly diploid solution.
  • NO_TUMOR - PURPLE failed to find any aneuploidy and somatic variants were supplied but there were fewer than 300 with observed VAF > 0.1.

QC Failure

There are several reasons PURPLE may classify a sample as failed:

  • FAIL_SEGMENT: more than 220 copy number segments not supported at either end by SV breakpoints. Indicates samples with extreme GC bias, with differences in depth of >= 10x between high and low GC regions. GC normalisation is unreliable when the corrections are so extreme so it is recommended to fail the sample (concerns with miscalled deletions or amplifications or have poor sensitivity in high GC regions.
  • NO_TUMOR: no aneuploidy found and the number of somatic SNVs found is less than 1,000
  • MIN_PURITY: fitted purity < 20%
  • FAIL_DELETED_GENES: more than 280 deleted genes. This QC step was added after observing that in a handful of samples with high MB scale positive GC bias we sometimes systematically underestimate the copy number in high GC regions. This can lead us to incorrectly infer homozygous loss of entire chromosomes, particularly on chromosomes 17 and 19.
  • FAIL_GENDER: if the AMBER and COBALT inferred genders are inconsistent then the COBALT one is used but the sample is failed.

 

Variable value details
QC_Status PASS
Purity 0.43 (0.41-0.79) Purity of tumor in the sample (and min-max with score within 10% of best)
Ploidy 2.911 (2.851-4.917) Average ploidy of tumor sample after adjusting for purity (and min-max with score within 10% of best)
Gender MALE
WGD true Whole genome duplication
MSI (indels/Mb) MSS (0.135) MSI status (MSI, MSS or UNKNOWN if somatic variants not supplied) & MS Indels per Mb
Polyclonal Prop 0.287 Proportion of CN regions that are more than 0.25 from a whole copy number
Diploidy Prop 0.015 (0.001-0.015) Proportion of CN regions that have 1 (+- 0.2) minor and major allele
Segment_Pass TRUE Score: 15; Unsupported: 15
Gender_Pass TRUE Amber: MALE; Cobalt: MALE
DelGenes_Pass TRUE count: 77
TMB 12.714 (HIGH) Tumor mutational burden per mega base (Status: ‘HIGH’, ‘LOW’ or ‘UNKNOWN’ if somatic variants not supplied)
TML 0 (LOW) Tumor mutational load (Status: ‘HIGH’, ‘LOW’ or ‘UNKNOWN’ if somatic variants not supplied)

UMCCR Gene CNV Calls

Description

PURPLE copy number alterations in the UMCCR Cancer Gene panel (~1,200 genes) - description is from https://github.com/hartwigmedical/hmftools/blob/master/purity-ploidy-estimator/README.md#gene-copy-number-file

Column Description
gene Name of gene
minCN/maxCN Min/Max copy number found in gene exons
chrom/start/end Chromosome/start/end location of gene transcript
chrBand Chromosome band of the gene
onco_or_ts oncogene (‘oncogene’), tumor suppressor (‘tsgene’), or both (‘onco+ts’), as reported by Cancermine
transcriptID Ensembl transcript ID (dot version)
minMinorAllelePloidy Minimum allele ploidy found over the gene exons - useful for identifying LOH events
somReg (somaticRegions) Count of somatic copy number regions this gene spans
germDelReg (germlineHomDeletionRegions / germlineHetToHomDeletionRegions) Number of regions spanned by this gene that are (homozygously deleted in the germline / both heterozygously deleted in the germline and homozygously deleted in the tumor)
minReg (minRegions) Number of somatic regions inside the gene that share the min copy number
minRegStartEnd Start/End base of the copy number region overlapping the gene with the minimum copy number
minRegSupportStartEndMethod Start/end support of the CN region overlapping the gene with the min CN (plus determination method)

 

Genome-wide CNV Segments

Description

PURPLE outputs a file with the copy number profile of all contiguous segments of the tumor sample:

PURPLE copy number profile of all (contiguous) segments of the tumor sample - description is from https://github.com/hartwigmedical/hmftools/blob/master/purity-ploidy-estimator/README.md#copy-number-file

Column Description
Chr/Start/End Coordinates of copy number segment
CN Fitted absolute copy number of segment adjusted for purity and ploidy
Ploidy Min+Maj Ploidy of minor + major allele adjusted for purity
BAF Tumor BAF after adjusted for purity and ploidy
BafCount Count of AMBER baf points covered by this segment
Start/End SegSupport Type of SV support for the CN breakpoint at start/end of region. Allowed values: CENTROMERE, TELOMERE, INV, DEL, DUP, BND (translocation), SGL (single breakend SV support), NONE (no SV support for CN breakpoint), MULT (multiple SV support at exact breakpoint)
Method Method used to determine the CN of the region. Allowed values: BAF_WEIGHTED (avg of all depth windows for the region), STRUCTURAL_VARIANT (inferred using ploidy of flanking SVs), LONG_ARM (inferred from the long arm), GERMLINE_AMPLIFICATION (inferred using special logic to handle regions of germline amplification)
windowCount Count of COBALT windows covered by this segment
GC Proportion of segment that is G or C

 

PURPLE Charts

PURPLE generates charts for summarising tumor sample characteristics. Description is from the PURPLE docs.

Copy number / Minor allele ploidy

The following figures show the AMBER BAF count weighted distribution of copy number and minor allele ploidy throughout the fitted segments. Copy numbers are broken down by colour into their respective minor allele ploidy (MAP) while the minor allele ploidy figure is broken down by copy number.

Rainfall

If a somatic variant VCF has been supplied, a figure will be produced showing the somatic variant ploidy broken down by copy number as well as a rainfall plot with kataegis clusters highlighted in grey.

Purity/ploidy

The following ‘sunrise’ chart shows the range of scores of all examined solutions of purity and ploidy. Crosshairs identify the best purity / ploidy solution.

Clonality

The following diagram illustrates the clonality model of a typical sample.

The top figure shows the histogram of somatic ploidy for all SNVs and INDELs in blue. Superimposed are peaks in different colours fitted from the sample as described in the docs while the black line shows the overall fitted ploidy distribution. Red filled peaks are below the 0.85 subclonal threshold.

We can determine the likelihood of a variant being subclonal at any given ploidy as shown in the bottom half of the figure.

Segment

The contribution of each fitted segment to the final score of the best fit is shown in the following figure. Each segment is divided into its major and minor allele ploidy. The area of each circle shows the weight (AMBER baf count) of each segment.

Oncoviruses

Oncoviruses and their integration sites. Viral sequences are obtained from the GDC database. Host genes are reported if the integration site falls on a gene or at least before 100kbp of the gene start.

## No oncoviral content detected in this sample.

Addendum

Back to top

Conda Pkgs Main

name version build channel envs
umccrise 1.0.0 dev_0 <develop> NA
snakemake 5.17.0 dev_0 <develop> NA
reference-data 1.0.3 dev_0 <develop> NA
r-base 3.5.1 hc461eb7_1012 conda-forge _pcgr, _cancer_report
r-base 3.6.3 h316533a_2 conda-forge _hmf
python 3.7.3 h357f687_2 conda-forge NA, _pcgr, _hmf
python 3.8.2 he5300dc_7_cpython conda-forge _cancer_report
pcgr 0.8.4.10 py37r35_0 pcgr _pcgr
pandocfilters 1.4.2 py37_1 NA NA
pandoc 2.9.2.1 0 conda-forge NA, _pcgr, _hmf, _cancer_report
ngs-utils 2.6.2 dev_0 <develop> NA
ngs_utils 2.5.6 py37_0 vladsaveliev _pcgr
multiqc-bcbio 0.2.8 pypi_0 pypi NA
multiqc 1.9.dev0 dev_0 <develop> NA
htslib 1.10.2 h78d89cc_0 bioconda NA, _hmf
htslib 1.9 h244ad75_9 bioconda _pcgr
hmftools-sage 1.0 0 bioconda _hmf
hmftools-purple 2.40 0 bioconda _hmf
hmftools-linx 1.7 0 bioconda _hmf
hmftools-cobalt 1.8 0 bioconda _hmf
hmftools-amber 3.2 0 bioconda _hmf
gridss 2.8.3 0 bioconda _hmf
cpsr 0.5.2.6 0 pcgr _pcgr
conpair 0.2 pypi_0 pypi NA
cacao 0.2.1.2 0 pcgr _pcgr

Report Inputs

key value
title Cancer Report for Sample
tumor_name SEQC-II_Tumor_50pc
batch_name SEQC-II-50pc__SEQC-II_Tumor_50pc
genome_build hg38
key_genes /g/data/gx8/extras/vlad/synced/NGS_Utils/ngs_utils/reference_data/key_genes/umccr_cancer_genes.latest.tsv
af_global /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/rmd/afs/af_tumor.txt
af_keygenes /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/rmd/afs/af_tumor_keygenes.txt
somatic_snv /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/rmd/somatic-with_chr_prefix.vcf
somatic_sv /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/SEQC-II-50pc__SEQC-II_Tumor_50pc/structural/SEQC-II-50pc__SEQC-II_Tumor_50pc-manta.tsv
purple_gene_cnv /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/purple/SEQC-II-50pc__SEQC-II_Tumor_50pc.purple.cnv.gene.tsv
purple_cnv /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/purple/SEQC-II-50pc__SEQC-II_Tumor_50pc.purple.cnv.somatic.tsv
purple_purity /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/purple/SEQC-II-50pc__SEQC-II_Tumor_50pc.purple.purity.tsv
purple_qc /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/purple/SEQC-II-50pc__SEQC-II_Tumor_50pc.purple.qc
oncoviral_present_viruses /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/SEQC-II-50pc__SEQC-II_Tumor_50pc/oncoviruses/present_viruses.txt
oncoviral_breakpoints_tsv
conda_list /g/data/gx8/extras/vlad/umccrise_tests/Jun14_SEQC2/work/conda_pkg_list.txt

Conda Pkgs All

 

LS0tCmF1dGhvcjogIlVuaXZlcnNpdHkgb2YgTWVsYm91cm5lIENlbnRyZSBmb3IgQ2FuY2VyIFJlc2VhcmNoIgpkYXRlOiAiYHIgU3lzLnRpbWUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGNvc21vICMgZGFya2x5CiAgICBjc3M6IHN0eWxlLmNzcwogICAgdG9jOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIHJtZGZvcm1hdHM6Om1hdGVyaWFsOgogICAgaGlnaGxpZ2h0OiBrYXRlCnBhcmFtczoKICB0aXRsZTogIkNhbmNlciBSZXBvcnQgZm9yIFNhbXBsZSAiCiAgdHVtb3JfbmFtZTogJ3gnCiAgYmF0Y2hfbmFtZTogJ3gnCiAgZ2Vub21lX2J1aWxkOiAnaGczOCcgIyAnaGcxOScKICBrZXlfZ2VuZXM6ICd4JwogIGFmX2dsb2JhbDogJ3gnCiAgYWZfa2V5Z2VuZXM6ICd4JwogIHNvbWF0aWNfc252OiAneCcKICBzb21hdGljX3N2OiAneCcKICBwdXJwbGVfZ2VuZV9jbnY6ICd4JwogIHB1cnBsZV9jbnY6ICd4JwogIHB1cnBsZV9wdXJpdHk6ICd4JwogIHB1cnBsZV9xYzogJ3gnCiAgb25jb3ZpcmFsX3ByZXNlbnRfdmlydXNlczogJ3gnCiAgb25jb3ZpcmFsX2JyZWFrcG9pbnRzX3RzdjogJ3gnCiAgY29uZGFfbGlzdDogJ3gnCiAgIyBnZW5vbWVfYnVpbGQ6ICAgICAnaGczOCcKICAjIHR1bW9yX25hbWU6ICAgICAgICdUX1NSUjc4OTA5MDJfMjBwYycKICAjIGJhdGNoX25hbWU6ICAgICAgICdUX1NSUjc4OTA5MDJfMjBwYycKICAjIGtleV9nZW5lczogICAgICAgICd+L3Jqbi9leHRyYXMvdmxhZC9zeW5jZWQvTkdTX1V0aWxzL25nc191dGlscy9yZWZlcmVuY2VfZGF0YS9rZXlfZ2VuZXMvdW1jY3JfY2FuY2VyX2dlbmVzLmxhdGVzdC50c3YnCiAgIyBhZl9nbG9iYWw6ICAgICAgICAnfi9yam4vZXh0cmFzL3ZsYWQvc3luY2VkL3VtY2NyL3VtY2NyaXNlX3Rlc3RfZGF0YS9yZXN1bHRzL1RfU1JSNzg5MDkwMl8yMHBjL3dvcmsvVF9TUlI3ODkwOTAyXzIwcGMvcm1kL2Fmcy9hZl90dW1vci50eHQnCiAgIyBhZl9rZXlnZW5lczogICAgICAnfi9yam4vZXh0cmFzL3ZsYWQvc3luY2VkL3VtY2NyL3VtY2NyaXNlX3Rlc3RfZGF0YS9yZXN1bHRzL1RfU1JSNzg5MDkwMl8yMHBjL3dvcmsvVF9TUlI3ODkwOTAyXzIwcGMvcm1kL2Fmcy9hZl90dW1vcl9rZXlnZW5lcy50eHQnCiAgIyBzb21hdGljX3NudjogICAgICAnfi9yam4vZXh0cmFzL3ZsYWQvc3luY2VkL3VtY2NyL3VtY2NyaXNlX3Rlc3RfZGF0YS9yZXN1bHRzL1RfU1JSNzg5MDkwMl8yMHBjL3dvcmsvVF9TUlI3ODkwOTAyXzIwcGMvcm1kL2RyYWdlbi13aXRoX2Nocl9wcmVmaXgudmNmJwogICMgc29tYXRpY19zdjogICAgICAgJ34vcmpuL2V4dHJhcy92bGFkL3N5bmNlZC91bWNjci91bWNjcmlzZV90ZXN0X2RhdGEvcmVzdWx0cy9UX1NSUjc4OTA5MDJfMjBwYy9UX1NSUjc4OTA5MDJfMjBwYy9zdHJ1Y3R1cmFsL1RfU1JSNzg5MDkwMl8yMHBjLW1hbnRhLnRzdicKICAjIHB1cnBsZV9nZW5lX2NudjogICd+L3Jqbi9leHRyYXMvdmxhZC9zeW5jZWQvdW1jY3IvdW1jY3Jpc2VfdGVzdF9kYXRhL3Jlc3VsdHMvVF9TUlI3ODkwOTAyXzIwcGMvd29yay9UX1NSUjc4OTA5MDJfMjBwYy9wdXJwbGUvVF9TUlI3ODkwOTAyXzIwcGMucHVycGxlLmNudi5nZW5lLnRzdicKICAjIHB1cnBsZV9jbnY6ICAgICAgICd+L3Jqbi9leHRyYXMvdmxhZC9zeW5jZWQvdW1jY3IvdW1jY3Jpc2VfdGVzdF9kYXRhL3Jlc3VsdHMvVF9TUlI3ODkwOTAyXzIwcGMvd29yay9UX1NSUjc4OTA5MDJfMjBwYy9wdXJwbGUvVF9TUlI3ODkwOTAyXzIwcGMucHVycGxlLmNudi5zb21hdGljLnRzdicKICAjIHB1cnBsZV9wdXJpdHk6ICAgICd+L3Jqbi9leHRyYXMvdmxhZC9zeW5jZWQvdW1jY3IvdW1jY3Jpc2VfdGVzdF9kYXRhL3Jlc3VsdHMvVF9TUlI3ODkwOTAyXzIwcGMvd29yay9UX1NSUjc4OTA5MDJfMjBwYy9wdXJwbGUvVF9TUlI3ODkwOTAyXzIwcGMucHVycGxlLnB1cml0eS50c3YnCiAgIyBwdXJwbGVfcWM6ICAgICAgICAnfi9yam4vZXh0cmFzL3ZsYWQvc3luY2VkL3VtY2NyL3VtY2NyaXNlX3Rlc3RfZGF0YS9yZXN1bHRzL1RfU1JSNzg5MDkwMl8yMHBjL3dvcmsvVF9TUlI3ODkwOTAyXzIwcGMvcHVycGxlL1RfU1JSNzg5MDkwMl8yMHBjLnB1cnBsZS5xYycKICAjIGNvbmRhX2xpc3Q6ICAgICAgICd+L3Jqbi9leHRyYXMvdmxhZC9zeW5jZWQvdW1jY3IvdW1jY3Jpc2VfdGVzdF9kYXRhL3Jlc3VsdHMvVF9TUlI3ODkwOTAyXzIwcGMvd29yay9UX1NSUjc4OTA5MDJfMjBwYy9ybWQvY29uZGFfcGtnX2xpc3QudHh0JwpkZXNjcmlwdGlvbjogIkFuYWx5c2lzIG9mIHR1bW9yL25vcm1hbCBzYW1wbGVzIGF0IFVNQ0NSIgp0aXRsZTogImByIHBhc3RlKHBhcmFtcyR0aXRsZSwgcGFyYW1zJGJhdGNoX25hbWUpYCIKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTQwMHB4OwogIG1hcmdpbi1sZWZ0OiBhdXRvOwogIG1hcmdpbi1yaWdodDogYXV0bzsKfQo8L3N0eWxlPgoKYGBge3Iga25pdHJfb3B0cywgaW5jbHVkZT1GfQprbml0cjo6b3B0c19jaHVuayRzZXQoY29sbGFwc2UgPSBUUlVFLCBlY2hvID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKYGBgCgpgYGB7ciByZW5kZXJfcmVwb3J0X2ludGVyYWN0aXZlbHksIGV2YWw9RiwgZWNobz1GfQpiYXRjaF9uYW1lIDwtICJFbG9uIgojIHR1bW9yX25hbWUgPC0gc3Ryc3BsaXQoYmF0Y2hfbmFtZSwgIl9fIilbWzFdXVsyXQp0dW1vcl9uYW1lIDwtICJFbG9uX1QiCnNudl9jYWxsZXIgPC0gImVuc2VtYmxlIiAjIGVuc2VtYmxlCgpwYXJhbXNfdG1wIDwtIGxpc3QoCiAgc3BhcnRhbiA9IGxpc3QoCiAgICB0dW1vcl9uYW1lPScnLAogICAgYmF0Y2hfbmFtZT0nJywKICAgIGdlbm9tZV9idWlsZD0nJywKICAgIGtleV9nZW5lcz0nJywKICAgIGFmX2dsb2JhbD0nJywKICAgIGFmX2tleWdlbmVzPScnLAogICAgc29tYXRpY19zbnY9JycsCiAgICBzb21hdGljX3N2PScnLAogICAgcHVycGxlX2dlbmVfY252PScnLAogICAgcHVycGxlX2Nudj0nJywKICAgIHB1cnBsZV9wdXJpdHk9JycsCiAgICBwdXJwbGVfcWM9JycpLAogIHJhaWppbiA9IGxpc3QoCiAgICB0dW1vcl9uYW1lPScnLAogICAgYmF0Y2hfbmFtZT0nJywKICAgIGdlbm9tZV9idWlsZD0nJywKICAgIGtleV9nZW5lcz0nJywKICAgIGFmX2dsb2JhbD0nJywKICAgIGFmX2tleWdlbmVzPScnLAogICAgc29tYXRpY19zbnY9JycsCiAgICBzb21hdGljX3N2PScnLAogICAgcHVycGxlX2dlbmVfY252PScnLAogICAgcHVycGxlX2Nudj0nJywKICAgIHB1cnBsZV9wdXJpdHk9JycsCiAgICBwdXJwbGVfcWM9JycpLAogIGxvY2FsID0gbGlzdCgKICAgIGdlbm9tZV9idWlsZD0naGczOCcsCiAgICBrZXlfZ2VuZXM9J2RhdGEvcmVmL3VtY2NyX2NhbmNlcl9nZW5lcy5sYXRlc3QudHN2JywKICAgIGFmX2dsb2JhbD1nbHVlOjpnbHVlKCdkYXRhL3dvcmsve2JhdGNoX25hbWV9L3JtZC9hZnMvYWZfdHVtb3IudHh0JyksCiAgICBhZl9rZXlnZW5lcz1nbHVlOjpnbHVlKCdkYXRhL3dvcmsve2JhdGNoX25hbWV9L3JtZC9hZnMvYWZfdHVtb3Jfa2V5Z2VuZXMudHh0JyksCiAgICBzb21hdGljX3Nudj1nbHVlOjpnbHVlKCdkYXRhL3dvcmsve2JhdGNoX25hbWV9L3JtZC97c252X2NhbGxlcn0td2l0aF9jaHJfcHJlZml4LnZjZicpLAogICAgc29tYXRpY19zdj1nbHVlOjpnbHVlKCdkYXRhL3tiYXRjaF9uYW1lfS9zdHJ1Y3R1cmFsL3tiYXRjaF9uYW1lfS1tYW50YS50c3YnKSwKICAgIHB1cnBsZV9nZW5lX2Nudj1nbHVlOjpnbHVlKCdkYXRhL3dvcmsve2JhdGNoX25hbWV9L3B1cnBsZS97YmF0Y2hfbmFtZX0ucHVycGxlLmNudi5nZW5lLnRzdicpLAogICAgcHVycGxlX2Nudj1nbHVlOjpnbHVlKCdkYXRhL3dvcmsve2JhdGNoX25hbWV9L3B1cnBsZS97YmF0Y2hfbmFtZX0ucHVycGxlLmNudi5zb21hdGljLnRzdicpLAogICAgcHVycGxlX3B1cml0eT1nbHVlOjpnbHVlKCdkYXRhL3dvcmsve2JhdGNoX25hbWV9L3B1cnBsZS97YmF0Y2hfbmFtZX0ucHVycGxlLnB1cml0eS50c3YnKSwKICAgIHB1cnBsZV9xYz1nbHVlOjpnbHVlKCdkYXRhL3dvcmsve2JhdGNoX25hbWV9L3B1cnBsZS97YmF0Y2hfbmFtZX0ucHVycGxlLnFjJyksCiAgICBjb25kYV9saXN0PWdsdWU6OmdsdWUoJ2RhdGEvd29yay9jb25kYV9wa2dfbGlzdC50eHQnKQogICkKKQoKcGFyYW1zIDwtIHBhcmFtc190bXBbWyJsb2NhbCJdXQpwYXJhbXMkYmF0Y2hfbmFtZSA8LSBiYXRjaF9uYW1lCnBhcmFtcyR0dW1vcl9uYW1lIDwtIHR1bW9yX25hbWUKCnJlbmRlcl9tZSA8LSBmdW5jdGlvbigpIHsKICBybWFya2Rvd246OnJlbmRlcigKICAgICJjYW5jZXJfcmVwb3J0LlJtZCIsCiAgICBwYXJhbXMgPSBwYXJhbXMpCn0KcmVuZGVyX21lKCkKYGBgCgpgYGB7ciBsb2FkX3BrZ3N9CiMgQmlvY29uZHVjdG9yCmxpYnJhcnkoQlNnZW5vbWUpCmxpYnJhcnkoTXV0YXRpb25hbFBhdHRlcm5zKQpyZWZfZ2Vub21lIDwtIHBhc3RlMCgiQlNnZW5vbWUuSHNhcGllbnMuVUNTQy4iLCBwYXJhbXMkZ2Vub21lX2J1aWxkKQpsaWJyYXJ5KHJlZl9nZW5vbWUsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKdHhfcmVmX2dlbm9tZSA8LSBwYXN0ZTAoIlR4RGIuSHNhcGllbnMuVUNTQy4iLCBwYXJhbXMkZ2Vub21lX2J1aWxkLCAiLmtub3duR2VuZSIpCmxpYnJhcnkodHhfcmVmX2dlbm9tZSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQojIENSQU4KbGlicmFyeShkZXZ0b29scykKbGlicmFyeShEVCkKbGlicmFyeShkcGx5cikKbGlicmFyeShnbHVlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoaHRtbHRvb2xzKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkocm1hcmtkb3duKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkodGlkeXIpCmBgYAoKYGBge3IgZnVuY3N9CiMgZm9yIGNoZWNraW5nIGlmIHRoZSBjb2x1bW5zIGluIHRoZSBkdCBhcmUgYWxsIGRlc2NyaWJlZApjaGVja19jb2xzX2Rlc2NyaWJlZCA8LSBmdW5jdGlvbihjb2xzLCBkZXNjcikgewogIHN0b3BpZm5vdChpcy5jaGFyYWN0ZXIoY29scyksIGlzLmF0b21pYyhjb2xzKSkKICBzdG9waWZub3QoaXMuY2hhcmFjdGVyKGRlc2NyKSwgaXMuYXRvbWljKGRlc2NyKSkKICBmb3IgKGNvbCBpbiBjb2xzKSB7CiAgICBpZiAoIWNvbCAlaW4lIGRlc2NyKSB7CiAgICAgIHdhcm5pbmcoZ2x1ZTo6Z2x1ZSgie2NvbH0gaXMgbm90IGRlc2NyaWJlZCEiKSkKICAgIH0KICB9Cn0KCiMgZ2V0IGpzIGluZGljZXMgd2hlbiB1c2luZyBpbiBEVCBvcHRpb25zCmNvbF9pbmRfanMgPC0gZnVuY3Rpb24oZHQsIGNvbCkgewogIG50YWIgPC0gc2V0TmFtZXMoKDE6bmNvbChkdCkgLSAxKSwgbmFtZXMoZHQpKQogIHN0b3BpZm5vdChhbGwoY29sICVpbiUgbmFtZXMoZHQpKSkKICBzb3J0KHVubmFtZShudGFiW2NvbF0pKQp9CgojIHVzZWQgaW4gU1YgdGFibGUgRGV0YWlscwpzdl9kZXRhaWxfdGFibGUgPC0gZnVuY3Rpb24odGFiKSB7CiAgY2hlY2tfY29sc19kZXNjcmliZWQoY29sbmFtZXModGFiKSwgc3ZfY29sX2Rlc2NyJENvbHVtbikKICBsaXN0KENvbHVtbiA9IGNvbG5hbWVzKHRhYikpICU+JQogICAgdGliYmxlOjphc190aWJibGUoKSAlPiUKICAgIGRwbHlyOjpsZWZ0X2pvaW4oc3ZfY29sX2Rlc2NyLCBieSA9ICJDb2x1bW4iKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIENvbHVtbiA9IGthYmxlRXh0cmE6OmNlbGxfc3BlYyhDb2x1bW4sIGJvbGQgPSBUUlVFKSkgJT4lCiAgICBrbml0cjo6a2FibGUoZXNjYXBlID0gRkFMU0UpICU+JQogICAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICAgIGthYmxlRXh0cmE6OnNjcm9sbF9ib3goaGVpZ2h0ID0gIjIwMHB4IikKfQpgYGAKCmBgYHtyIGFsbGVsZV9mcmVxX3ByZXB9CiMtLS0tIEFsbGVsZSBGcmVxdWVuY2llcyAtLS0tIwpzZXQuc2VlZCg0MikKYWZfZ2xvYmFsIDwtCiAgcmVhZHI6OnJlYWRfdHN2KHBhcmFtcyRhZl9nbG9iYWwsIGNvbF90eXBlcyA9ICJkIikgJT4lCiAgZHBseXI6Om11dGF0ZShzZXQgPSAiR2xvYmFsIikKCmFmX2tleWdlbmVzIDwtCiAgcmVhZHI6OnJlYWRfdHN2KHBhcmFtcyRhZl9rZXlnZW5lcywgY29sX3R5cGVzID0gImNpY2NjZCIpICU+JQogIGRwbHlyOjpzZWxlY3QoYWYpICU+JQogIGRwbHlyOjptdXRhdGUoc2V0ID0gJ0tleSBnZW5lcyBDRFMnKQoKYWZfYm90aCA8LQogIGRwbHlyOjpiaW5kX3Jvd3MoYWZfZ2xvYmFsLCBhZl9rZXlnZW5lcykgJT4lCiAgZHBseXI6Om11dGF0ZShzZXQgPSBmYWN0b3Ioc2V0LCBsZXZlbHMgPSBjKCJHbG9iYWwiLCAiS2V5IGdlbmVzIENEUyIpKSkKCm1vZGUyIDwtIGZ1bmN0aW9uKHgpIHsKICB1eCA8LSB1bmlxdWUoeCkKICB1eFt3aGljaC5tYXgodGFidWxhdGUobWF0Y2goeCwgdXgpKSldCn0KCmFmX3N0YXRzIDwtIGFmX2JvdGggJT4lCiAgZHBseXI6Omdyb3VwX2J5KHNldCkgJT4lCiAgZHBseXI6OnN1bW1hcmlzZShuID0gbigpLAogICAgICAgICAgICAgICAgICAgbWVhbiA9IHJvdW5kKG1lYW4oYWYpLCAyKSwKICAgICAgICAgICAgICAgICAgIG1lZGlhbiA9IHJvdW5kKG1lZGlhbihhZiksIDIpLAogICAgICAgICAgICAgICAgICAgbW9kZSA9IHJvdW5kKG1vZGUyKGFmKSwgMikpICU+JQogIHRpZHlyOjpjb21wbGV0ZShzZXQsIGZpbGwgPSBsaXN0KG4gPSAwKSkKYGBgCgpgYGB7ciBtdXRhdGlvbmFsX3NpZ3NfcHJlcH0KIy0tLS0gTXV0YXRpb25hbCBTaWduYXR1cmVzIC0tLS0jCnNvbWF0aWNfc252IDwtIE11dGF0aW9uYWxQYXR0ZXJuczo6cmVhZF92Y2ZzX2FzX2dyYW5nZXMoCiAgdmNmX2ZpbGVzID0gcGFyYW1zJHNvbWF0aWNfc252LAogIHNhbXBsZV9uYW1lcyA9IHBhcmFtcyR0dW1vcl9uYW1lLAogIGdlbm9tZSA9IHJlZl9nZW5vbWUsCiAgZ3JvdXAgPSAiYXV0bytzZXgiKQoKbXV0X21hdCA8LSBNdXRhdGlvbmFsUGF0dGVybnM6Om11dF9tYXRyaXgodmNmX2xpc3QgPSBzb21hdGljX3NudiwgcmVmX2dlbm9tZSA9IHJlZl9nZW5vbWUpCgojIyMtLS0gT0xEIFNpZ3MgLS0tIyMjCiMgR2V0IFNhbmdlciBzaWdzIGZyb20gImh0dHA6Ly9jYW5jZXIuc2FuZ2VyLmFjLnVrL2NhbmNlcmdlbm9tZS9hc3NldHMvc2lnbmF0dXJlc19wcm9iYWJpbGl0aWVzLnR4dCIKc2lnX3Byb2JzIDwtIGZpbGUucGF0aCgibWlzYy9zaWcvdjJfbWFyMjAxNS9zaWduYXR1cmVzX3Byb2JhYmlsaXRpZXMudHh0IikKIyBiZXR0ZXIgYmUgZXhwbGljaXQgLSB0aGUgc2lnX3Byb2JzIGZpbGUgaGFzIDcgZXh0cmEgZW1wdHkgY29sdW1ucwpjb2xfdHlwZXMgPC0gcGFzdGUwKGMoImNjYyIsIHBhc3RlMChyZXAoImQiLCAzMCksIGNvbGxhcHNlID0gIiIpLCAiY2NjY2NjYyIpLCBjb2xsYXBzZSA9ICIiKQpjb2xfbmFtZXMgPC0gYygiU3Vic3RUeXBlIiwgIlRyaW51Y2xlb3RpZGUiLCAiU29tTXV0VHlwZSIsIHBhc3RlMCgiU2lnIiwgMTozMCksIHBhc3RlMCgiZm9vIiwgMTo3KSkKY2FuY2VyX3NpZ25hdHVyZXMgPC0KICByZWFkcjo6cmVhZF90c3Yoc2lnX3Byb2JzLCBjb2xfbmFtZXMgPSBjb2xfbmFtZXMsIGNvbF90eXBlcyA9IGNvbF90eXBlcywgc2tpcCA9IDEpICU+JQogIGRwbHlyOjphcnJhbmdlKFN1YnN0VHlwZSkKCiMgc2FuaXR5IGNoZWNrIC0gbmVlZCB0byBiZSBpbiBzYW1lIG9yZGVyCnN0b3BpZm5vdChhbGwoY2FuY2VyX3NpZ25hdHVyZXMkU29tTXV0VHlwZSA9PSByb3duYW1lcyhtdXRfbWF0KSkpCiMgc2VsZWN0IG9ubHkgMzAgc2lnIGNvbHVtbnMsIDk2IG11dCB0eXBlcwpjYW5jZXJfc2lnbmF0dXJlcyA8LSBjYW5jZXJfc2lnbmF0dXJlcyAlPiUKICBkcGx5cjo6c2VsZWN0KDQ6MzMpICU+JQogIGFzLm1hdHJpeCgpCgojIyMtLS0gTkVXIFNpZ3MgLS0tIyMjCnNpZ19wcm9iczIgPC0gZmlsZS5wYXRoKCJtaXNjL3NpZy92M19tYXkyMDE5L3NpZ1Byb2ZpbGVyX1NCU19zaWduYXR1cmVzXzIwMTlfMDVfMjIuY3N2IikKY2FuY2VyX3NpZ25hdHVyZXMyIDwtCiAgcmVhZHI6OnJlYWRfY3N2KHNpZ19wcm9iczIsIGNvbF90eXBlcyA9IGNvbHMoLmRlZmF1bHQgPSAiZCIsIFR5cGUgPSAiYyIsIFN1YlR5cGUgPSAiYyIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKFNvbU11dFR5cGUgPSBwYXN0ZTAoc3Vic3RyKFN1YlR5cGUsIDEsIDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWyIsIFR5cGUsICJdIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic3RyKFN1YlR5cGUsIDMsIDMpKSkgJT4lCiAgZHBseXI6OnNlbGVjdChTb21NdXRUeXBlLCBTQlMxOlNCUzg1KQoKIyBzYW5pdHkgY2hlY2sgLSBuZWVkIHRvIGJlIGluIHNhbWUgb3JkZXIKc3RvcGlmbm90KGFsbChjYW5jZXJfc2lnbmF0dXJlczIkU29tTXV0VHlwZSA9PSByb3duYW1lcyhtdXRfbWF0KSkpCiMgc2VsZWN0IG9ubHkgNjcgc2lnIGNvbHVtbnMsIDk2IG11dCB0eXBlcwpjYW5jZXJfc2lnbmF0dXJlczIgPC0gY2FuY2VyX3NpZ25hdHVyZXMyICU+JQogIGRwbHlyOjpzZWxlY3QoLTEpICU+JQogIGFzLm1hdHJpeCgpCgojIEZpdCBtdXRhdGlvbiBtYXRyaXggdG8gY2FuY2VyIHNpZ25hdHVyZXMKZml0X3JlcyA8LSBNdXRhdGlvbmFsUGF0dGVybnM6OmZpdF90b19zaWduYXR1cmVzKG11dF9tYXRyaXggPSBtdXRfbWF0LCBzaWduYXR1cmVzID0gY2FuY2VyX3NpZ25hdHVyZXMpCmZpdF9yZXMyIDwtIE11dGF0aW9uYWxQYXR0ZXJuczo6Zml0X3RvX3NpZ25hdHVyZXMobXV0X21hdHJpeCA9IG11dF9tYXQsIHNpZ25hdHVyZXMgPSBjYW5jZXJfc2lnbmF0dXJlczIpCgojIENvbnZlcnQgdG8gdGliYmxlcyBmb3IgbW9yZSBidWxsZXQtcHJvb2Ygc3Vic2V0dGluZwpmaXRfcmVzIDwtIHRpYmJsZTo6dGliYmxlKAogIHNpZyA9IHJvd25hbWVzKGZpdF9yZXMkY29udHJpYnV0aW9uKSwgIyBtYXRyaXggcm93bmFtZXMKICBjb250ciA9IHVubmFtZShmaXRfcmVzJGNvbnRyaWJ1dGlvblssIDFdKSkgIyBtYXRyaXggc2luZ2xlIGNvbHVtbiAtPiB2ZWN0b3IKCmZpdF9yZXMyIDwtIHRpYmJsZTo6dGliYmxlKAogIHNpZyA9IHJvd25hbWVzKGZpdF9yZXMyJGNvbnRyaWJ1dGlvbiksCiAgY29udHIgPSB1bm5hbWUoZml0X3JlczIkY29udHJpYnV0aW9uWywgMV0pKQoKIyBTZWxlY3Qgc2lnbmF0dXJlcyB3aXRoIHNvbWUgY29udHJpYnV0aW9uCmZpdF9yZXNfY29udHIgPC0gZHBseXI6OmZpbHRlcihmaXRfcmVzLCBjb250ciA+IDApCmZpdF9yZXNfY29udHIyIDwtIGRwbHlyOjpmaWx0ZXIoZml0X3JlczIsIGNvbnRyID4gMCkKCiMgSWYgdGhlcmUgYXJlIG5vIHNpZ25hdHVyZXMsIHJldHVybiBhIGR1bW15IHRpYmJsZQppZiAobnJvdyhmaXRfcmVzX2NvbnRyKSA9PSAwKSB7CiAgZml0X3Jlc19jb250ciA8LSB0aWJibGU6OnRpYmJsZSgKICAgIHNpZyA9ICJOT1NJR1MiLAogICAgY29udHIgPSAwCiAgKQp9CgppZiAobnJvdyhmaXRfcmVzX2NvbnRyMikgPT0gMCkgewogIGZpdF9yZXNfY29udHIyIDwtIHRpYmJsZTo6dGliYmxlKAogICAgc2lnID0gIk5PU0lHUyIsCiAgICBjb250ciA9IDAKICApCn0KCm11dF9zaWdfY29udHIgPC0KICBmaXRfcmVzX2NvbnRyICU+JQogIGRwbHlyOjptdXRhdGUoY29udHIgPSByb3VuZChjb250ciwgMCksCiAgICAgICAgICAgICAgICBSYW5rID0gYXMuaW50ZWdlcihiYXNlOjpyYW5rKC1jb250cikpKSAlPiUKICBkcGx5cjo6c2VsZWN0KFJhbmssIFNpZ25hdHVyZSA9IHNpZywgQ29udHJpYnV0aW9uID0gY29udHIpICU+JQogIGRwbHlyOjphcnJhbmdlKFJhbmspCm11dF9zaWdfY29udHIyIDwtCiAgZml0X3Jlc19jb250cjIgJT4lCiAgZHBseXI6Om11dGF0ZShjb250ciA9IHJvdW5kKGNvbnRyLCAwKSwKICAgICAgICAgICAgICAgIFJhbmsgPSBhcy5pbnRlZ2VyKGJhc2U6OnJhbmsoLWNvbnRyKSkpICU+JQogIGRwbHlyOjpzZWxlY3QoUmFuaywgU2lnbmF0dXJlID0gc2lnLCBDb250cmlidXRpb24gPSBjb250cikgJT4lCiAgZHBseXI6OmFycmFuZ2UoUmFuaykKYGBgCgpgYGB7ciBzdl9wcmlvcml0aXplX3ByZXB9CiMtLS0tIFN0cnVjdHVyYWwgVmFyaWFudHMgLS0tLSMKc3BsaXRfc3ZfZmllbGQgPC0gZnVuY3Rpb24oLmRhdGEsIGZpZWxkLCBpc19wY3QgPSBGQUxTRSkgewogICMgLSBzZXBhcmF0ZSBmaWVsZCBpbnRvIHR3byBwYXJ0cwogICMgLSBtdXRhdGUgdG8gcGN0IGFjY29yZGluZ2x5CiAgIyAtIG9yaWdpbmFsIGZpZWxkIGlzIG1lYW4gb2YgdHdvIHBhcnRzCiAgZl9xIDwtIHJsYW5nOjplbnF1byhmaWVsZCkKICBmX3N0ciA8LSBybGFuZzo6cXVvX25hbWUoZl9xKQogIGYxX3N0ciA8LSBzdHJfYyhmX3N0ciwgJzEnKQogIGYyX3N0ciA8LSBzdHJfYyhmX3N0ciwgJzInKQogIGYxX3EgPC0gc3ltKGYxX3N0cikKICBmMl9xIDwtIHN5bShmMl9zdHIpCiAgLmRhdGEgJT4lCiAgICB0aWR5cjo6c2VwYXJhdGUoISFmX3EsIGMoZjFfc3RyLCBmMl9zdHIpLCBzZXAgPSAiLCIsIGZpbGwgPSAicmlnaHQiKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgICEhZjFfcSA6PSByb3VuZChhcy5kb3VibGUoISFmMV9xKSAqIGlmZWxzZShpc19wY3QsIDEwMCwgMSksIDEpLAogICAgICAhIWYyX3EgOj0gcm91bmQoYXMuZG91YmxlKCEhZjJfcSkgKiBpZmVsc2UoaXNfcGN0LCAxMDAsIDEpLCAxKSwKICAgICAgISFmX3EgIDo9IHJvdW5kKCgoISFmMV9xICsgaWZlbHNlKGlzLm5hKCEhZjJfcSksICEhZjFfcSwgISFmMl9xKSkgLyAyKSwgMSkKICAgICkKfQoKY291bnRfcGllY2VzIDwtIGZ1bmN0aW9uKHgsIHNlcCkgewogIGlmZWxzZShuY2hhcih4KSA9PSAwLCAwLCBzdHJpbmdyOjpzdHJfY291bnQoeCwgc2VwKSArIDEpCn0KCmVmZmVjdF9hYmJyZXZpYXRpb25zIDwtIGMoCiAgIjNfcHJpbWVfVVRSX3RydW5jYXRpb24iID0gIjNVVFJ0cnVuYyIsICIzX3ByaW1lX1VUUl92YXJpYW50IiA9ICIzVVRSdmFyIiwKICAiNV9wcmltZV9VVFJfdHJ1bmNhdGlvbiIgPSAiNVVUUnRydW5jIiwgICI1X3ByaW1lX1VUUl92YXJpYW50IiA9ICI1VVRSdmFyIiwKICAiZmVhdHVyZV9mdXNpb24iID0gIkZ1cyIsICJiaWRpcmVjdGlvbmFsX2dlbmVfZnVzaW9uIiA9ICJCaWRGdXNHIiwgImdlbmVfZnVzaW9uIiA9ICJGdXNHIiwKICAiY2hyb21vc29tZV9udW1iZXJfdmFyaWF0aW9uIiA9ICJDaHJvbU51bVYiLCAiY29uc2VydmF0aXZlX2luZnJhbWVfZGVsZXRpb24iID0gIkNvbnNJbmZyYW1lRGVsIiwKICAiZG93bnN0cmVhbV9nZW5lX3ZhcmlhbnQiID0gIkRuc3RyZWFtR1YiLCAidXBzdHJlYW1fZ2VuZV92YXJpYW50IiA9ICJVcHN0cmVhbUdWIiwKICAiZHVwbGljYXRpb24iID0gIkR1cCIsICJleG9uX2xvc3NfdmFyaWFudCIgPSAiRXhvbkxvc3NWIiwKICAiZmVhdHVyZV9hYmxhdGlvbiIgPSAiRGVsRyIsICJ0cmFuc2NyaXB0X2FibGF0aW9uIiA9ICJEZWxUeCIsCiAgImZyYW1lc2hpZnRfdmFyaWFudCIgPSAiRnJhbWVzaGlmdFYiLCAiaW50ZXJnZW5pY19yZWdpb24iID0gIkludGVyZ2VuUmVnIiwgImludHJhZ2VuaWNfdmFyaWFudCIgPSAiSW50cmFnZW5WIiwKICAiaW50cm9uX3ZhcmlhbnQiID0gIkludHJvblYiLCAgIm5vX2Z1bmNfZWZmZWN0IiA9ICJOb0Z1bmNFZmYiLCAibm9fcHJpb19lZmZlY3QiID0gIk5vUHJpb0VmZiIsCiAgIm5vbl9jb2RpbmdfdHJhbnNjcmlwdF92YXJpYW50IiA9ICJOb25jb2RUeFYiLAogICJzcGxpY2VfYWNjZXB0b3JfdmFyaWFudCIgPSAiU3BsaWNlQWNjViIsCiAgInNwbGljZV9kb25vcl92YXJpYW50IiA9ICJTcGxpY2VEb25WIiwgInNwbGljZV9yZWdpb25fdmFyaWFudCIgPSAiU3BsaWNlUmVnViIsCiAgInN0YXJ0X2xvc3QiID0gIlN0YXJ0TG9zcyIsICJzdG9wX2dhaW5lZCIgPSAiU3RvcEdhaW4iLCAic3RvcF9sb3N0IiA9ICJTdG9wTG9zcyIsCiAgIlRGX2JpbmRpbmdfc2l0ZV92YXJpYW50IiA9ICJURkJTVmFyIiwgICJURkJTX2FibGF0aW9uIiA9ICJURkJTRGVsIikKZWZmZWN0X2FiYnJldl9ubXMgPC0gbmFtZXMoZWZmZWN0X2FiYnJldmlhdGlvbnMpCgphYmJyZXZpYXRlX2VmZmVjdCA8LSBmdW5jdGlvbihlZmZlY3RzKSB7CiAgIyB0YWtlIHN0cmluZyBhcyB4JnkmegogICMgc3BsaXQgYnkgJgogICMgYWJicmV2aWF0ZSBlYWNoIHBpZWNlIGFuZCBnbHVlIGJhY2sgd2l0aCBjb21tYQoKICAuYWJicmV2aWF0ZV9lZmZlY3QgPC0gZnVuY3Rpb24oZWZmZWN0KSB7CiAgICBpZmVsc2UoZWZmZWN0ICVpbiUgZWZmZWN0X2FiYnJldl9ubXMsIGVmZmVjdF9hYmJyZXZpYXRpb25zW2VmZmVjdF0sIGVmZmVjdCkKICB9CgogIHN0cnNwbGl0KGVmZmVjdHMsICImIilbWzFdXSAlPiUKICAgIHB1cnJyOjptYXBfY2hyKC5hYmJyZXZpYXRlX2VmZmVjdCkgJT4lCiAgICBwYXN0ZShjb2xsYXBzZSA9ICIsICIpCn0KYWJicmV2aWF0ZV9lZmZlY3R2IDwtIFZlY3Rvcml6ZShhYmJyZXZpYXRlX2VmZmVjdCkKCnN2X3BhdGggPC0gcGFyYW1zJHNvbWF0aWNfc3YKc3ZfdW5tZWx0ZWQgPC0gTlVMTApzdl9hbGwgPC0gTlVMTAoKc29tYXRpY19zdl90c3YgPC0gcmVhZHI6OnJlYWRfdHN2KHN2X3BhdGgsIGNvbF9uYW1lcyA9IFRSVUUsIGNvbF90eXBlcyA9ICJjY2NpaWNjY2NjaWNjY2NjZGNpaWNjIikKbm9fc3ZfZm91bmQgPSBsZW5ndGgocmVhZExpbmVzKGNvbiA9IHN2X3BhdGgsIG4gPSAyKSkgPCAyICAjIG9ubHkgaGVhZGVyIGluIHRoZSBmaWxlCgppZiAoIW5vX3N2X2ZvdW5kKSB7CiAgc3ZfdW5tZWx0ZWQgPC0gc29tYXRpY19zdl90c3YgJT4lCiAgICBkcGx5cjo6c2VsZWN0KC1jYWxsZXIsIC1zYW1wbGUpICU+JQogICAgc3BsaXRfc3ZfZmllbGQoQUZfQlBJKSAlPiUKICAgIHNwbGl0X3N2X2ZpZWxkKEFGX1BVUlBMRSkgJT4lCiAgICBzcGxpdF9zdl9maWVsZChDTl9QVVJQTEUpICU+JQogICAgc3BsaXRfc3ZfZmllbGQoQ05fY2hhbmdlX1BVUlBMRSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBBRl9CUEkgPSBpZmVsc2UoaXMubmEoQUZfQlBJKSwgTkEsIHBhc3RlMChBRl9CUEksICIgKCIsIEFGX0JQSTEsICIsIiwgQUZfQlBJMiwgIikiKSksCiAgICAgIEFGX1BVUlBMRSA9IGlmZWxzZShpcy5uYShBRl9QVVJQTEUpLCBOQSwgcGFzdGUwKEFGX1BVUlBMRSwgIiAoIiwgQUZfUFVSUExFMSwgIiwgIiwgQUZfUFVSUExFMiwgIikiKSksCiAgICAgIENOX1BVUlBMRSA9IGlmZWxzZShpcy5uYShDTl9QVVJQTEUpLCBOQSwgcGFzdGUwKENOX1BVUlBMRSwgIiAoIiwgQ05fUFVSUExFMSwgIiwgIiwgQ05fUFVSUExFMiwgIikiKSksCiAgICAgIENOX2NoYW5nZV9QVVJQTEUgPSBpZmVsc2UoaXMubmEoQ05fY2hhbmdlX1BVUlBMRSksIE5BLCBwYXN0ZTAoQ05fY2hhbmdlX1BVUlBMRSwgIiAoIiwgQ05fY2hhbmdlX1BVUlBMRTEsICIsICIsIENOX2NoYW5nZV9QVVJQTEUyLCAiKSIpKQogICAgKSAlPiUKICAgIHRpZHlyOjpzZXBhcmF0ZShzcGxpdF9yZWFkX3N1cHBvcnQsIGMoIlNSX3JlZiIsICJTUl9hbHQiKSwgIiwiLCBjb252ZXJ0ID0gVFJVRSkgJT4lCiAgICB0aWR5cjo6c2VwYXJhdGUocGFpcmVkX3N1cHBvcnRfUFIsIGMoIlBSX3JlZiIsICJQUl9hbHQiKSwgIiwiLCBjb252ZXJ0ID0gVFJVRSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBTUl9QUl9hbHQgPSBwYXN0ZTAoU1JfYWx0LCAiLCIsIFBSX2FsdCksCiAgICAgIFNSX1BSX3JlZiA9IHBhc3RlMChTUl9yZWYsICIsIiwgUFJfcmVmKSwKICAgICAgUGxvaWR5ID0gcm91bmQoYXMuZG91YmxlKFBsb2lkeV9QVVJQTEUpLCAyKSwKICAgICAgY2hyb20gPSBzdWIoImNociIsICIiLCBjaHJvbSksCiAgICAgIGNocm9tID0gYXMuZmFjdG9yKGNocm9tKSwgIyBmb3IgYmV0dGVyIERUIGZpbHRlcmluZwogICAgICBzdnR5cGUgPSBpZmVsc2UoaXMubmEoUFVSUExFX3N0YXR1cyksIHN2dHlwZSwgIlBVUlBMRV9pbmYiKSwKICAgICAgU3RhcnQgPSBpZmVsc2UoaXMubmEoUFVSUExFX3N0YXR1cyksIFNUQVJUX0JQSSwgc3RhcnQpLAogICAgICBuYW5uID0gY291bnRfcGllY2VzKGFubm90YXRpb24sICIsIiksCiAgICAgIHZhcm51bSA9IGRwbHlyOjpyb3dfbnVtYmVyKCksCiAgICAgIHZhcm51bSA9IHNwcmludGYoZ2x1ZTo6Z2x1ZSgiJTB7bmNoYXIobnJvdyguKSl9ZCIpLCB2YXJudW0pKQoKICAjIEZpeCBCTkQgSURzCiAgc3ZfdW5tZWx0ZWRfYm5kIDwtIHN2X3VubWVsdGVkICU+JQogICAgZHBseXI6OmZpbHRlcihzdnR5cGUgPT0gIkJORCIpICU+JQogICAgdGlkeXI6OnNlcGFyYXRlKElELCBpbnRvID0gYygiQk5EX2dyb3VwIiwgIkJORF9tYXRlIiksIHNlcCA9IC0xLCBjb252ZXJ0ID0gVFJVRSwgcmVtb3ZlID0gRkFMU0UpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KEJORF9ncm91cCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBCTkRfSUQgPSBkcGx5cjo6Z3JvdXBfaW5kaWNlcygpLAogICAgICBCTkRfSUQgPSBzcHJpbnRmKGdsdWU6OmdsdWUoIiUwe25jaGFyKG5yb3coLikpfWQiKSwgQk5EX0lEKSwKICAgICAgQk5EX21hdGUgPSBpZmVsc2UoQk5EX21hdGUgPT0gMCwgIkEiLCAiQiIpKSAlPiUKICAgIGRwbHlyOjp1bmdyb3VwKCkgJT4lCiAgICBkcGx5cjo6YmluZF9jb2xzKC4sIC5bbWF0Y2goLiRJRCwgLiRNQVRFSUQpLCAiY2hyb20iXSkgJT4lCiAgICBkcGx5cjo6cmVuYW1lKEJORF9tYXRlX2Nocm9tID0gY2hyb20xKQoKICBzdl91bm1lbHRlZF9vdGhlciA8LSBzdl91bm1lbHRlZCAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoc3Z0eXBlICE9ICJCTkQiKQoKICBzdl91bm1lbHRlZCA8LQogICAgZHBseXI6OmJpbmRfcm93cyhzdl91bm1lbHRlZF9ibmQsCiAgICAgICAgICAgICAgICAgICAgIHN2X3VubWVsdGVkX290aGVyKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIEVORF9CUEkgPSBiYXNlOjpmb3JtYXQoRU5EX0JQSSwgYmlnLm1hcmsgPSAiLCIsIHRyaW0gPSBUUlVFKSwKICAgICAgRW5kID0gaWZlbHNlKHN2dHlwZSA9PSAiQk5EIiwgcGFzdGUwKEJORF9tYXRlX2Nocm9tLCAiOiIsIEVORF9CUEkpLCBFTkRfQlBJKSkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KHZhcm51bSwgVGllclRvcCA9IHRpZXIsCiAgICAgICAgICAgICAgICAgIENociA9IGNocm9tLCBTdGFydCwgRW5kLAogICAgICAgICAgICAgICAgICBUeXBlID0gc3Z0eXBlLAogICAgICAgICAgICAgICAgICBJRCwgTUFURUlELCBCTkRfSUQsIEJORF9tYXRlLAogICAgICAgICAgICAgICAgICBTUl9QUl9hbHQsIFNSX1BSX3JlZiwgUGxvaWR5LAogICAgICAgICAgICAgICAgICBBRl9QVVJQTEUsIEFGX0JQSSwKICAgICAgICAgICAgICAgICAgQ05DID0gQ05fY2hhbmdlX1BVUlBMRSwgQ04gPSBDTl9QVVJQTEUsCiAgICAgICAgICAgICAgICAgIFNTY29yZSA9IHNvbWF0aWNzY29yZSwgbmFubiwgYW5ub3RhdGlvbikKCiAgc3ZfYWxsIDwtIHN2X3VubWVsdGVkICU+JQogICAgZHBseXI6Om11dGF0ZShhbm5vdGF0aW9uID0gc3Ryc3BsaXQoYW5ub3RhdGlvbiwgJywnKSkgJT4lCiAgICB0aWR5cjo6dW5uZXN0KGFubm90YXRpb24pICU+JQogICAgdGlkeXI6OnNlcGFyYXRlKAogICAgICBhbm5vdGF0aW9uLCBjKCdFdmVudCcsICdFZmZlY3QnLCAnR2VuZXMnLCAnVHJhbnNjcmlwdCcsICdEZXRhaWwnLCAnVGllcicpLAogICAgICBzZXAgPSAnXFx8JywgY29udmVydCA9IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIG50cnggPSBjb3VudF9waWVjZXMoVHJhbnNjcmlwdCwgIiYiKSwKICAgICAgbmdlbiA9IGNvdW50X3BpZWNlcyhHZW5lcywgIiYiKSwKICAgICAgbmVmZiA9IGNvdW50X3BpZWNlcyhFZmZlY3QsICImIiksCiAgICAgIFRyYW5zY3JpcHQgPSBUcmFuc2NyaXB0ICU+JSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoJyYnLCAnLCAnKSwKICAgICAgR2VuZXMgPSBHZW5lcyAlPiUgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCcmJywgJywgJyksCiAgICAgIEVmZmVjdCA9IGFiYnJldmlhdGVfZWZmZWN0dihFZmZlY3QpKSAlPiUKICAgIGRwbHlyOjpkaXN0aW5jdCgpICU+JQogICAgZHBseXI6OmFycmFuZ2UoVGllciwgR2VuZXMsIEVmZmVjdCkKfSBlbHNlIHsKICBzdl91bm1lbHRlZCA8LSB0aWJibGUoV0FSTklORyA9ICJUSEVSRSBXRVJFIDAgU1ZzIFBSSU9SSVRJU0VEISEiKQogIHN2X2FsbCA8LSB0aWJibGUoV0FSTklORyA9ICJUSEVSRSBXRVJFIDAgU1ZzIFBSSU9SSVRJU0VEISEiKQp9CmBgYAoKYGBge3IgcHVycGxlX3FjX3ByZXB9CiMtLS0tIFBVUlBMRSBRQyAtLS0tIwojIHJlYWQgYm90aCBkYXRhc2V0cwpxY19wYXRoIDwtIHBhcmFtcyRwdXJwbGVfcWMKcHVyaXR5X3BhdGggPC0gcGFyYW1zJHB1cnBsZV9wdXJpdHkKCnB1cnBsZV9xYyA8LQogIGZpbGUucGF0aChxY19wYXRoKSAlPiUKICByZWFkcjo6cmVhZF90c3YoY29sX25hbWVzID0gYygia2V5IiwgInZhbHVlIiksIGNvbF90eXBlcyA9ICJjYyIpICU+JQogIGRwbHlyOjptdXRhdGUodmFsdWUgPSB0b3VwcGVyKHZhbHVlKSkKIyB0dXJuIGludG8gbmFtZWQgdmVjdG9yCnB1cnBsZV9xYyA8LSBzdHJ1Y3R1cmUocHVycGxlX3FjJHZhbHVlLCBuYW1lcyA9IHB1cnBsZV9xYyRrZXkpCgpwdXJwbGVfcHVyaXR5IDwtCiAgZmlsZS5wYXRoKHB1cml0eV9wYXRoKSAlPiUKICByZWFkcjo6cmVhZF90c3YoY29sX3R5cGVzID0gY29scyguZGVmYXVsdCA9IGNvbF9kb3VibGUoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5kZXIgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdob2xlR2Vub21lRHVwbGljYXRpb24gPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNTdGF0dXMgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1sU3RhdHVzID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtYlN0YXR1cyA9IGNvbF9jaGFyYWN0ZXIoKQogICkpICU+JQogIGRwbHlyOjptdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIDMpICU+JQogIHVubGlzdCgpCgojIHNhbml0eSBjaGVja3MgaW4gY2FzZSBzb21ldGhpbmcgY2hhbmdlcyBiZXR3ZWVuIHZlcnNpb25zIChQVVJQTEUgdjIuMzQgYXMgb2YgMjAxOS0wOS0yOSkKbm1zX3B1cnBsZV9xYyA8LSBjKCJRQ1N0YXR1cyIsICJTZWdtZW50UGFzcyIsICJHZW5kZXJQYXNzIiwgIkRlbGV0ZWRHZW5lc1Bhc3MiLAogICAgICAgICAgICAgICAgICAgIlNlZ21lbnRTY29yZSIsICJVbnN1cHBvcnRlZFNlZ21lbnRzIiwgIlBsb2lkeSIsCiAgICAgICAgICAgICAgICAgICAiQW1iZXJHZW5kZXIiLCAiQ29iYWx0R2VuZGVyIiwgIkRlbGV0ZWRHZW5lcyIpCgpubXNfcHVycGxlX3B1cml0eSA8LSBjKCJwdXJpdHkiLCAibm9ybUZhY3RvciIsICJzY29yZSIsICJkaXBsb2lkUHJvcG9ydGlvbiIsICJwbG9pZHkiLAogICAgICAgICAgICAgICAgICAgICAgICJnZW5kZXIiLCAic3RhdHVzIiwgInBvbHljbG9uYWxQcm9wb3J0aW9uIiwgIm1pblB1cml0eSIsICJtYXhQdXJpdHkiLAogICAgICAgICAgICAgICAgICAgICAgICJtaW5QbG9pZHkiLCAibWF4UGxvaWR5IiwgIm1pbkRpcGxvaWRQcm9wb3J0aW9uIiwgIm1heERpcGxvaWRQcm9wb3J0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAidmVyc2lvbiIsICJzb21hdGljUGVuYWx0eSIsICJ3aG9sZUdlbm9tZUR1cGxpY2F0aW9uIiwgIm1zSW5kZWxzUGVyTWIiLCAibXNTdGF0dXMiLAogICAgICAgICAgICAgICAgICAgICAgICJ0bWwiLCAidG1sU3RhdHVzIiwgInRtYlBlck1iIiwgInRtYlN0YXR1cyIpCgoKIyBmb3Igc2hvcnRlciByZWZlcmVuY2UgaW4gZ2x1ZQpwIDwtIHB1cnBsZV9wdXJpdHkKcSA8LSBwdXJwbGVfcWMKcHVycGxlX3FjX3N1bW1hcnkgPC0gZHBseXI6OnRyaWJibGUoCiAgflZhcmlhYmxlICAgICAgICAsIH52YWx1ZSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+ZGV0YWlscywKICAnUUNfU3RhdHVzJyAgICAgICwgZ2x1ZSgne3FbIlFDU3RhdHVzIl19JykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAiIiwKICAnUHVyaXR5JyAgICAgICAgICwgZ2x1ZSgne3BbInB1cml0eSJdfSAoe3BbIm1pblB1cml0eSJdfS17cFsibWF4UHVyaXR5Il19KScpLCAiUHVyaXR5IG9mIHR1bW9yIGluIHRoZSBzYW1wbGUgKGFuZCBtaW4tbWF4IHdpdGggc2NvcmUgd2l0aGluIDEwJSBvZiBiZXN0KSIsCiAgJ1Bsb2lkeScgICAgICAgICAsIGdsdWUoJ3twWyJwbG9pZHkiXX0gKHtwWyJtaW5QbG9pZHkiXX0te3BbIm1heFBsb2lkeSJdfSknKSwgIkF2ZXJhZ2UgcGxvaWR5IG9mIHR1bW9yIHNhbXBsZSBhZnRlciBhZGp1c3RpbmcgZm9yIHB1cml0eSAoYW5kIG1pbi1tYXggd2l0aCBzY29yZSB3aXRoaW4gMTAlIG9mIGJlc3QpIiwKICAnR2VuZGVyJyAgICAgICAgICwgZ2x1ZSgne3BbImdlbmRlciJdfScpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAiIiwKICAnV0dEJyAgICAgICAgICAgICwgZ2x1ZSgne3BbIndob2xlR2Vub21lRHVwbGljYXRpb24iXX0nKSAgICAgICAgICAgICAgICAgICAgLCAiV2hvbGUgZ2Vub21lIGR1cGxpY2F0aW9uIiwKICAnTVNJIChpbmRlbHMvTWIpJywgZ2x1ZSgne3BbIm1zU3RhdHVzIl19ICh7cFsibXNJbmRlbHNQZXJNYiJdfSknKSAgICAgICAgICAgLCAiTVNJIHN0YXR1cyAoTVNJLCBNU1Mgb3IgVU5LTk9XTiBpZiBzb21hdGljIHZhcmlhbnRzIG5vdCBzdXBwbGllZCkgJiBNUyBJbmRlbHMgcGVyIE1iIiwKICAnUG9seWNsb25hbCBQcm9wJywgZ2x1ZSgne3BbInBvbHljbG9uYWxQcm9wb3J0aW9uIl19JykgICAgICAgICAgICAgICAgICAgICAgLCAiUHJvcG9ydGlvbiBvZiBDTiByZWdpb25zIHRoYXQgYXJlIG1vcmUgdGhhbiAwLjI1IGZyb20gYSB3aG9sZSBjb3B5IG51bWJlciIsCiAgJ0RpcGxvaWR5IFByb3AnICAsIGdsdWUoJ3twWyJkaXBsb2lkUHJvcG9ydGlvbiJdfSAoe3BbIm1pbkRpcGxvaWRQcm9wb3J0aW9uIl19LXtwWyJtYXhEaXBsb2lkUHJvcG9ydGlvbiJdfSknKSwgZ2x1ZSgnUHJvcG9ydGlvbiBvZiBDTiByZWdpb25zIHRoYXQgaGF2ZSAxICgrLSAwLjIpIG1pbm9yIGFuZCBtYWpvciBhbGxlbGUnKSwKICAnU2VnbWVudF9QYXNzJyAgICwgZ2x1ZSgne3FbIlNlZ21lbnRQYXNzIl19JykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBnbHVlKCdTY29yZToge3FbIlNlZ21lbnRTY29yZSJdfTsgVW5zdXBwb3J0ZWQ6IHtxWyJVbnN1cHBvcnRlZFNlZ21lbnRzIl19JyksCiAgJ0dlbmRlcl9QYXNzJyAgICAsIGdsdWUoJ3txWyJHZW5kZXJQYXNzIl19JykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgZ2x1ZSgnQW1iZXI6IHtxWyJBbWJlckdlbmRlciJdfTsgQ29iYWx0OiB7cVsiQ29iYWx0R2VuZGVyIl19JyksCiAgJ0RlbEdlbmVzX1Bhc3MnICAsIGdsdWUoJ3txWyJEZWxldGVkR2VuZXNQYXNzIl19JykgICAgICAgICAgICAgICAgICAgICAgICAgICwgZ2x1ZSgnY291bnQ6IHtxWyJEZWxldGVkR2VuZXMiXX0nKSwKICAnVE1CJyAgICAgICAgICAgICwgZ2x1ZSgne3BbInRtYlBlck1iIl19ICh7cFsidG1iU3RhdHVzIl19KScpICAgICAgICAgICAgICAgLCAiVHVtb3IgbXV0YXRpb25hbCBidXJkZW4gcGVyIG1lZ2EgYmFzZSAoU3RhdHVzOiAnSElHSCcsICdMT1cnIG9yICdVTktOT1dOJyBpZiBzb21hdGljIHZhcmlhbnRzIG5vdCBzdXBwbGllZCkiLAogICdUTUwnICAgICAgICAgICAgLCBnbHVlKCd7cFsidG1sIl19ICh7cFsidG1sU3RhdHVzIl19KScpICAgICAgICAgICAgICAgICAgICAsICJUdW1vciBtdXRhdGlvbmFsIGxvYWQgKFN0YXR1czogJ0hJR0gnLCAnTE9XJyBvciAnVU5LTk9XTicgaWYgc29tYXRpYyB2YXJpYW50cyBub3Qgc3VwcGxpZWQpIgopCmBgYAoKYGBge3IgcHVycGxlX2dlbmVfY252X3ByZXB9CiMtLS0tIFBVUlBMRSBHZW5lIENOViBUYWJsZSAtLS0tIwprZXlfZ2VuZXMgPC0KICByZWFkcjo6cmVhZF90c3YocGFyYW1zJGtleV9nZW5lcywgY29sX3R5cGVzID0gY29scyhvbmNvZ2VuZSA9ICJsIiwgdHVtb3JzdXBwcmVzc29yID0gImwiKSkgJT4lCiAgZHBseXI6OnNlbGVjdChzeW1ib2wsIG9uY29nZW5lLCB0dW1vcnN1cHByZXNzb3IpCgpvbmNvZ2VuZXMgPC0ga2V5X2dlbmVzICU+JSBkcGx5cjo6ZmlsdGVyKG9uY29nZW5lKSAlPiUgZHBseXI6OnB1bGwoc3ltYm9sKQp0c2dlbmVzIDwtIGtleV9nZW5lcyAlPiUgZHBseXI6OmZpbHRlcih0dW1vcnN1cHByZXNzb3IpICU+JSBkcGx5cjo6cHVsbChzeW1ib2wpCgpwdXJwbGVfZ2VuZV9jbnYgPC0gcmVhZHI6OnJlYWRfdHN2KHBhcmFtcyRwdXJwbGVfZ2VuZV9jbnYsIGNvbF90eXBlcyA9ICJjaWljZGRjZGRkY2NjZGlpY2NjZCIpCgojIHNhbml0eSBjaGVja3MgaW4gY2FzZSBzb21ldGhpbmcgY2hhbmdlcyBiZXR3ZWVuIHZlcnNpb25zIChQVVJQTEUgdjIuMzQgYXMgb2YgMjAxOS0wOS0yOSkKbm1zX2dlbmVfY252IDwtIGMoImNocm9tb3NvbWUiLCAic3RhcnQiLCAiZW5kIiwgImdlbmUiLCAibWluQ29weU51bWJlciIsICJtYXhDb3B5TnVtYmVyIiwKICAgICAgICAgICAgICAgICAgInVudXNlZCIsICJzb21hdGljUmVnaW9ucyIsICJnZXJtbGluZUhvbURlbGV0aW9uUmVnaW9ucyIsICJnZXJtbGluZUhldFRvSG9tRGVsZXRpb25SZWdpb25zIiwKICAgICAgICAgICAgICAgICAgInRyYW5zY3JpcHRJZCIsICJ0cmFuc2NyaXB0VmVyc2lvbiIsICJjaHJvbW9zb21lQmFuZCIsICJtaW5SZWdpb25zIiwKICAgICAgICAgICAgICAgICAgIm1pblJlZ2lvblN0YXJ0IiwgIm1pblJlZ2lvbkVuZCIsICJtaW5SZWdpb25TdGFydFN1cHBvcnQiLCAibWluUmVnaW9uRW5kU3VwcG9ydCIsCiAgICAgICAgICAgICAgICAgICJtaW5SZWdpb25NZXRob2QiLCAibWluTWlub3JBbGxlbGVQbG9pZHkiKQpzdG9waWZub3QoYWxsKGNvbG5hbWVzKHB1cnBsZV9nZW5lX2NudikgPT0gbm1zX2dlbmVfY252KSkKCnB1cnBsZV9nZW5lX2NudiA8LSBwdXJwbGVfZ2VuZV9jbnYgJT4lCiAgZHBseXI6OmZpbHRlcihnZW5lICVpbiUga2V5X2dlbmVzJHN5bWJvbCkgJT4lCiAgZHBseXI6Om11dGF0ZShjaHJvbW9zb21lID0gYXMuZmFjdG9yKGNocm9tb3NvbWUpLAogICAgICAgICAgICAgICAgdHJhbnNjcmlwdElEID0gcGFzdGUwKHRyYW5zY3JpcHRJZCwgIi4iLCB0cmFuc2NyaXB0VmVyc2lvbiksCiAgICAgICAgICAgICAgICBtaW5SZWdTdGFydEVuZCA9IHBhc3RlMChtaW5SZWdpb25TdGFydCwgIi0iLCBtaW5SZWdpb25FbmQpLAogICAgICAgICAgICAgICAgbWluUmVnU3VwcG9ydFN0YXJ0RW5kTWV0aG9kID0gcGFzdGUwKG1pblJlZ2lvblN0YXJ0U3VwcG9ydCwgIi0iLCBtaW5SZWdpb25FbmRTdXBwb3J0LCAiICgiLCBtaW5SZWdpb25NZXRob2QsICIpIiksCiAgICAgICAgICAgICAgICBnZXJtRGVsUmVnID0gcGFzdGUwKGdlcm1saW5lSG9tRGVsZXRpb25SZWdpb25zLCAiLyIsIGdlcm1saW5lSGV0VG9Ib21EZWxldGlvblJlZ2lvbnMpLAogICAgICAgICAgICAgICAgb25jb2dlbmUgPSBnZW5lICVpbiUgb25jb2dlbmVzLAogICAgICAgICAgICAgICAgdHNnZW5lID0gZ2VuZSAlaW4lIHRzZ2VuZXMsCiAgICAgICAgICAgICAgICBvbmNvX29yX3RzID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgb25jb2dlbmUgJiB0c2dlbmUgfiAib25jbyt0cyIsCiAgICAgICAgICAgICAgICAgIG9uY29nZW5lIH4gIm9uY29nZW5lIiwKICAgICAgICAgICAgICAgICAgdHNnZW5lIH4gInRzZ2VuZSIsCiAgICAgICAgICAgICAgICAgIFRSVUUgfiAiIikpICU+JQogIGRwbHlyOjpzZWxlY3QoZ2VuZSwgbWluQ04gPSBtaW5Db3B5TnVtYmVyLCBtYXhDTiA9IG1heENvcHlOdW1iZXIsCiAgICAgICAgICAgICAgICBjaHJvbSA9IGNocm9tb3NvbWUsIHN0YXJ0LCBlbmQsCiAgICAgICAgICAgICAgICBjaHJCYW5kID0gY2hyb21vc29tZUJhbmQsIG9uY29fb3JfdHMsIHRyYW5zY3JpcHRJRCwgbWluTWlub3JBbGxlbGVQbG9pZHksCiAgICAgICAgICAgICAgICBzb21SZWcgPSBzb21hdGljUmVnaW9ucywgZ2VybURlbFJlZywgbWluUmVnID0gbWluUmVnaW9ucywKICAgICAgICAgICAgICAgIG1pblJlZ1N0YXJ0RW5kLCBtaW5SZWdTdXBwb3J0U3RhcnRFbmRNZXRob2QpCmBgYAoKYGBge3IgcHVycGxlX2dsb2JhbF9jbnZfcHJlcH0KIy0tLS0gUFVSUExFIEdsb2JhbCBDTlYgVGFibGUgLS0tLSMKcHVycGxlX2dsb2JhbF9jbnYgPC0gZmlsZS5wYXRoKHBhcmFtcyRwdXJwbGVfY252KSAlPiUKICByZWFkcjo6cmVhZF90c3YoY29sX3R5cGVzID0gImNpaWRpZGRjY2NkZGRkZGQiKQoKbm1zX3B1cnBsZV9jbnYgPC0gYygiY2hyb21vc29tZSIsICJzdGFydCIsICJlbmQiLCAiY29weU51bWJlciIsICJiYWZDb3VudCIsICJvYnNlcnZlZEJBRiIsCiAgICAgICAgICAgICAgICAgICAgImJhZiIsICJzZWdtZW50U3RhcnRTdXBwb3J0IiwgInNlZ21lbnRFbmRTdXBwb3J0IiwgIm1ldGhvZCIsCiAgICAgICAgICAgICAgICAgICAgImRlcHRoV2luZG93Q291bnQiLCAiZ2NDb250ZW50IiwgIm1pblN0YXJ0IiwgIm1heFN0YXJ0IiwgIm1pbm9yQWxsZWxlUGxvaWR5IiwKICAgICAgICAgICAgICAgICAgICAibWFqb3JBbGxlbGVQbG9pZHkiKQoKIyBzYW5pdHkgY2hlY2tzIGluIGNhc2Ugc29tZXRoaW5nIGNoYW5nZXMgYmV0d2VlbiB2ZXJzaW9ucyAoUFVSUExFIHYyLjM0IGFzIG9mIDIwMTktMDktMjkpCnN0b3BpZm5vdChhbGwobmFtZXMocHVycGxlX2dsb2JhbF9jbnYpID09IG5tc19wdXJwbGVfY252KSkKYGBgCgojIyBTdW1tYXJ5CgpgYGB7ciBzdW1tYXJ5X3RhYmxlc30Kc3VtbWFyaXNlX3NpZ3MgPC0gZnVuY3Rpb24obXV0X3NpZ19jb250cikgewogIG11dF9zaWdfY29udHIgJT4lCiAgICBoZWFkKDIpICU+JQogICAgZHBseXI6Om11dGF0ZShzdHJpbmcgPSBwYXN0ZTAoU2lnbmF0dXJlLCAiICgiLCBDb250cmlidXRpb24sICIpIikpICU+JQogICAgZHBseXI6OnB1bGwoc3RyaW5nKSAlPiUKICAgIHBhc3RlKGNvbGxhcHNlID0gIiwgIikKfQoKYWZfc3VtbWFyeSA8LSBhZl9zdGF0cyAlPiUKICBrbml0cjo6a2FibGUoZm9ybWF0ID0gImh0bWwiLCBjYXB0aW9uID0gIkFGIFN1bW1hcnkgU3RhdHMiKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIGthYmxlRXh0cmE6OmNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFKQoKY252X3N1bW1hcnkgPC0gcHVycGxlX2dsb2JhbF9jbnYgJT4lCiAgZHBseXI6OnJlbmFtZShjbiA9IGNvcHlOdW1iZXIpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoTWluID0gcm91bmQobWluKGNuKSwgMiksCiAgICAgICAgICAgICAgICAgICBNYXggPSByb3VuZChtYXgoY24pLCAyKSwKICAgICAgICAgICAgICAgICAgIE4gPSBuKCkpICU+JSB1bmxpc3QoKQoKaWYgKG5vX3N2X2ZvdW5kKSB7CiAgc3Zfc3VtbWFyeSA8LSB0aWJibGUodW5tZWx0ZWQgPSBjKDApLCBtZWx0ZWQgPSBjKDApKQp9IGVsc2UgewogIHN2X3N1bW1hcnkgPC0KICAgIGxpc3QodW5tZWx0ZWQgPSBzdl91bm1lbHRlZCAlPiUgZHBseXI6OnNlbGVjdChUeXBlKSwKICAgICAgICAgbWVsdGVkID0gc3ZfYWxsICU+JSBkcGx5cjo6c2VsZWN0KFR5cGUpKSAlPiUKICAgIHB1cnJyOjptYXAoZnVuY3Rpb24oeCkgYWRkbWFyZ2lucyh0YWJsZSh4LCB1c2VOQSA9ICdpZmFueScpKSkgJT4lCiAgICBkby5jYWxsKCJyYmluZCIsIC4pICU+JQogICAgYXMuZGF0YS5mcmFtZSgpICU+JQogICAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4odmFyID0gImdyb3VwIikgJT4lCiAgICB0aWR5cjo6cGl2b3RfbG9uZ2VyKC1ncm91cCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKHZhbHVlID0gcGFzdGUwKG5hbWUsICI6ICIsIHZhbHVlKSkgJT4lCiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGdyb3VwLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QodW5tZWx0ZWQsIG1lbHRlZCkKfQoKcWNfc3VtbWFyeV9hbGwgPC0gcHVycGxlX3FjX3N1bW1hcnkgJT4lCiAgZHBseXI6OmZpbHRlcihWYXJpYWJsZSAlaW4lIGMoIlFDX1N0YXR1cyIsICJHZW5kZXIiLCAiUHVyaXR5IiwgIlBsb2lkeSIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KFZhcmlhYmxlLCB2YWx1ZSkgJT4lCiAgZHBseXI6OmJpbmRfcm93cygKICAgIGRwbHlyOjp0cmliYmxlKAogICAgICB+VmFyaWFibGUsIH52YWx1ZSwKICAgICAgIlRvcCBNdXRTaWdzIiwgZ2x1ZTo6Z2x1ZSgie2h0bWx0b29sczo6c3Ryb25nKCdPbGQ6Jyl9IHtzdW1tYXJpc2Vfc2lncyhtdXRfc2lnX2NvbnRyKX0gIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLSB7aHRtbHRvb2xzOjpzdHJvbmcoJ05ldzonKX0ge3N1bW1hcmlzZV9zaWdzKG11dF9zaWdfY29udHIyKX0iKSwKICAgICAgIkNOVnMgKFNvbWF0aWMpIiwgZ2x1ZTo6Z2x1ZSgie2h0bWx0b29sczo6c3Ryb25nKCdNaW46ICcpfXtjbnZfc3VtbWFyeVsnTWluJ119OyAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ7aHRtbHRvb2xzOjpzdHJvbmcoJ01heDogJyl9e2Nudl9zdW1tYXJ5WydNYXgnXX07ICIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIntodG1sdG9vbHM6OnN0cm9uZygnTjogJyl9e2Nudl9zdW1tYXJ5WydOJ119ICIpLAogICAgICAiU1ZzICh1bm1lbHRlZCkiLCBwYXN0ZShyZXYoc3Zfc3VtbWFyeSR1bm1lbHRlZCksIGNvbGxhcHNlID0gIiwgIiksCiAgICAgICJTVnMgKG1lbHRlZCkiLCBwYXN0ZShyZXYoc3Zfc3VtbWFyeSRtZWx0ZWQpLCBjb2xsYXBzZSA9ICIsICIpLAogICAgICAiR2Vub21lIiwgcGFyYW1zJGdlbm9tZV9idWlsZAogICAgKQogICkgJT4lCiAgZHBseXI6Om11dGF0ZShWYXJpYWJsZSA9IGthYmxlRXh0cmE6OmNlbGxfc3BlYyhWYXJpYWJsZSwgYm9sZCA9IFRSVUUpKSAlPiUKICBrbml0cjo6a2FibGUoZXNjYXBlID0gRkFMU0UsIGNvbC5uYW1lcyA9IE5VTEwpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJsZWZ0IikKCnFjX3N1bW1hcnlfYWxsCmFmX3N1bW1hcnkKYGBgCgojIyBTb21hdGljIE11dGF0aW9uIFByb2ZpbGVzCgojIyMgQWxsZWxpYyBGcmVxdWVuY2llcyB7I2FsbGVsaWMtZnJlcXN9ClN1bW1hcmlzZWQgYmVsb3cgYXJlIHRoZSBhbGxlbGUgZnJlcXVlbmNpZXMgKEFGcykgZm9yIHNvbWF0aWMgdmFyaWFudHMgZGV0ZWN0ZWQKZ2Vub21lLXdpZGUgKF9fR2xvYmFsX18pIHZzLiB3aXRoaW4gdGhlIGNvZGluZyBzZXF1ZW5jZSBvZiB+MSwxMDAgVU1DQ1IKY2FuY2VyIGdlbmVzIChfX0tleSBHZW5lcyBDRFNfXykuCkFGcyByYW5nZSBmcm9tIDAgdG8gMSwgb3IgMCUtMTAwJSAod2UgZmlsdGVyIG91dCBhbGwgbm92ZWwgdmFyaWFudHMgd2l0aCBBRiA8IDEwJSkuCgo8ZGV0YWlscz4KPHN1bW1hcnk+RGV0YWlsczwvc3VtbWFyeT4KClZhcmlhbnRzIGFyZSB0eXBpY2FsbHkgY2FsbGVkIGluIGJjYmlvIGJ5IDMgZGlmZmVyZW50IGNhbGxlcnMsIHdpdGggY2FsbHMgc3VwcG9ydGVkIGJ5IGF0IGxlYXN0IDIgb2YgdGhlbSB1c2VkICgiZW5zZW1ibGUiIGFwcHJvYWNoKS4KSW4gc29tZSBjYXNlcyBvbmx5IGEgc2luZ2xlIGNhbGxlciBpcyB1c2VkIGR1ZSB0byB0ZWNobmljYWwgcmVhc29ucyAoZS5nLiBoaWdobHkgbXV0YXRlZCBGRlBFIHNhbXBsZSkuCgpUaGUgZm9sbG93aW5nIHBvc3QtcHJvY2Vzc2luZyBzdGVwcyBvY2N1cjoKCjEuIGBzb21hdGljX3ZjZl9hbm5vdGF0ZWA6IFthbm5vdGF0ZSBWQ0ZdKGh0dHBzOi8vZ2l0aHViLmNvbS91bWNjci92Y2Zfc3R1ZmYvYmxvYi9tYXN0ZXIvdmNmX3N0dWZmL2ZpbHRlcmluZy9hbm5vdGF0ZV9zb21hdGljX3ZjZi5zbWspCiAgICBhZ2FpbnN0IGRhdGFiYXNlcyBvZiBrbm93biBob3RzcG90cywgZ2VybWxpbmUgdmFyaWFudHMsIGxvdyBtYXBwYWJpbGl0eSByZWdpb25zLCBVTUNDUiBwYW5lbCBvZiBub3JtYWxzCjIuIGBzb21hdGljX3ZjZl9maWx0ZXJgOiBbZmlsdGVyIFZDRl0oaHR0cHM6Ly9naXRodWIuY29tL3VtY2NyL3ZjZl9zdHVmZi9ibG9iL21hc3Rlci9zY3JpcHRzL2ZpbHRlcl9zb21hdGljX3ZjZikKICAgIHRvIHJlbW92ZSBnZXJtbGluZSB2YXJpYW50cyBhbmQgYXJ0ZWZhY3RzLCBidXQga2VlcCBrbm93biBob3RzcG90cwozLiBBcyBwcmVwYXJhdGlvbiBmb3IgdGhlIGFsbGVsaWMgZnJlcXVlbmNpZXMgcGxvdHM6CiAgICAqIGBzdWJzZXRfdG9fZ2lhYmA6IGtlZXAgdmFyaWFudHMgaW4gJ2hpZ2ggY29uZmlkZW5jZScgcmVnaW9ucyBhcyBkZXRlcm1pbmVkIGJ5IHRoZSBbR2Vub21lIGluIGEgQm90dGxlIGNvbnNvcnRpdW1dKGh0dHA6Ly9qaW1iLnN0YW5mb3JkLmVkdS9naWFiLykKICAgICoga2VlcCBvbmx5IHZhcmlhbnRzIHdpdGggQUYgYWJvdmUgMTAlCjQuIEFsbGVsZSBmcmVxdWVuY2llcyBmb3IgZ2xvYmFsIGFuZCBrZXlnZW5lczoKICAgICogYGFmc2A6IGdyYWIgb25seSB0aGUgYElORk8vVFVNT1JfQUZgIGZpZWxkIGFuZCBvdXRwdXQgdG8gZmluYWwgdHh0IGZpbGUKICAgICogYGFmc19rZXlnZW5lc2A6IGdyYWIgdGhlIGBDSFJPTWAsIGBQT1NgLCBgSURgLCBgUkVGYCwgYEFMVGAgYW5kIGBJTkZPL1RVTU9SX0FGYAogICAgICBmb3IgdmFyaWFudHMgaW4gdGhlIFVNQ0NSIGNhbmNlciBnZW5lIEJFRCBmaWxlLCBhbmQgb3V0cHV0IHRvIGZpbmFsIHR4dCBmaWxlCjwvZGV0YWlscz4KCgpgYGB7ciBhbGxlbGVfZnJlcV9wbG90X3N0YXRzLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9M30KZ2dwbG90KGRhdGEgPSBhZl9ib3RoLCBhZXMoYWYpKSArCiAgZ2VvbV9oaXN0b2dyYW0oc3RhdCA9ICdiaW4nLCBiaW53aWR0aCA9IDAuMDEsIGZpbGwgPSAiIzAwNjQwMCIpICsKICBmYWNldF93cmFwKH5zZXQsIHNjYWxlcyA9ICdmcmVlX3knLCBkcm9wID0gRkFMU0UpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJBbGxlbGUgRnJlcXVlbmN5IiwKICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIGJ5ID0gMC4xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLCAxKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgaGp1c3QgPSAxKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJBRiBjb3VudCBkaXN0cmlidXRpb24iKSkKYGBgCgojIyMgTXV0YXRpb25hbCBTaWduYXR1cmVzIHsudGFic2V0IC50YWJzZXQtZmFkZSAjc2lnbmF0dXJlc30KCkRlY2lwaGVyaW5nIHRoZSBtdXRhdGlvbmFsIHNpZ25hdHVyZSBvZiBhIHR1bW9yIHNhbXBsZSBjYW4gcHJvdmlkZSBpbnNpZ2h0IGludG8gdGhlIG11dGF0aW9uYWwKcHJvY2Vzc2VzIGludm9sdmVkIGluIGNhcmNpbm9nZW5lc2lzIGFuZCBoZWxwIGluIGNhbmNlciB0cmVhdG1lbnQgYW5kIHByZXZlbnRpb24uClRoZSBbTXV0YXRpb25hbFBhdHRlcm5zXShodHRwOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvaHRtbC9NdXRhdGlvbmFsUGF0dGVybnMuaHRtbCkKUiBwYWNrYWdlIGlzIHVzZWQgdG8gZ2VuZXJhdGUgYSBtdXRhdGlvbiBzaWduYXR1cmUgZm9yIHRoZSBzYW1wbGUuIFdlIHVzZSB0aGUgZmluYWwgZmlsdGVyZWQgc29tYXRpYwpjYWxscyBhcyBpbnB1dC4KCiMjIyMgQ29udGV4dCBzaWduYXR1cmUKCmBgYHtyIHBsb3RfOTZfcHJvZiwgZmlnLmhlaWdodD0zfQpNdXRhdGlvbmFsUGF0dGVybnM6OnBsb3RfOTZfcHJvZmlsZShtdXRfbWF0LCBjb25kZW5zZWQgPSBUUlVFKQpgYGAKCiMjIyMgUG9pbnQgbXV0YXRpb24gc3BlY3RydW0KCjxkZXRhaWxzPgo8c3VtbWFyeT5EZXNjcmlwdGlvbjwvc3VtbWFyeT4KCldlIGNhbiBjb3VudCB0aGUgbXV0YXRpb24gdHlwZSBvY2N1cnJlbmNlcyBmb3IgdGhlIGlucHV0IFZDRi4KRm9yIGBDPlRgIG11dGF0aW9ucywgYSBkaXN0aW5jdGlvbiBpcyBtYWRlIGJldHdlZW4gYEM+VGAgYXQgQ3BHIHNpdGVzCmFuZCBvdGhlciBzaXRlcywgYXMgZGVhbWluYXRpb24gb2YgbWV0aHlsYXRlZCBjeXRvc2luZSBhdCBDcEcgc2l0ZXMgaXMgYSBjb21tb24gbXV0YXRpb25hbApwcm9jZXNzLiBUaGlzIGlzIHRoZSByZWFzb24gdGhlIHJlZmVyZW5jZSBnZW5vbWUgaXMgbmVlZGVkLgoKQSBtdXRhdGlvbiBzcGVjdHJ1bSBzaG93cyB0aGUgcmVsYXRpdmUgY29udHJpYnV0aW9uIG9mIGVhY2ggbXV0YXRpb24gdHlwZSBpbiB0aGUgYmFzZQpzdWJzdGl0dXRpb24gY2F0YWxvZ3MuIFdlIGNhbiBwbG90IHRoZSBtZWFuIHJlbGF0aXZlIGNvbnRyaWJ1dGlvbiBvZgplYWNoIG9mIHRoZSA2IGJhc2Ugc3Vic3RpdHV0aW9uIHR5cGVzIG92ZXIgYWxsIHNhbXBsZXMuIEVycm9yIGJhcnMgaW5kaWNhdGUgc3RhbmRhcmQgZGV2aWF0aW9uCm92ZXIgYWxsIHNhbXBsZXMuIFRoZSB0b3RhbCBudW1iZXIgb2YgbXV0YXRpb25zIGlzIGluZGljYXRlZC4gV2UgY2FuIGFsc28gZGlzdGluZ3Vpc2gKYmV0d2VlbiBgQz5UYCBhdCBDcEcgc2l0ZXMgYW5kIG90aGVyIHNpdGVzLgoKPC9kZXRhaWxzPgoKYGBge3IgcGxvdF9tdXRfdHlwZV9vY2N1cnJlbmNlcywgZmlnLmhlaWdodD0zfQp0eXBlX29jY3VycmVuY2VzIDwtIG11dF90eXBlX29jY3VycmVuY2VzKHZjZl9saXN0ID0gc29tYXRpY19zbnYsIHJlZl9nZW5vbWUgPSByZWZfZ2Vub21lKQpwbG90X3NwZWN0cnVtKHR5cGVfb2NjdXJyZW5jZXMsIENUID0gVFJVRSkKYGBgCgojIyMjIFRyYW5zY3JpcHRpb25hbCBzdHJhbmQgYmlhcwoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKV2UgY2FuIGRldGVybWluZSBpZiBhIGdlbmUgbXV0YXRpb24gaXMgb24gdGhlIHRyYW5zY3JpYmVkIG9yIG5vbi10cmFuc2NyaWJlZApzdHJhbmQsIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGV2YWx1YXRlIHRoZSBpbnZvbHZlbWVudCBvZiB0cmFuc2NyaXB0aW9uLWNvdXBsZWQKcmVwYWlyLiBCeSBjb252ZW50aW9uIGJhc2Ugc3Vic3RpdHV0aW9ucyBhcmUgcmVnYXJkZWQgYXMgQz5YIG9yIFQ+WCwgc28gd2UgdHJ5CnRvIGRldGVybWluZSB3aGV0aGVyIHRoZSBDIG9yIFQgYmFzZSBpcyBvbiB0aGUgc2FtZSBzdHJhbmQgYXMgdGhlIGdlbmUKZGVmaW5pdGlvbi4gQmFzZSBzdWJzdGl0dXRpb25zIG9uIHRoZSBzYW1lIHN0cmFuZCBhcyB0aGUgZ2VuZSBkZWZpbml0aW9uIGFyZQpjb25zaWRlcmVkICd1bnRyYW5zY3JpYmVkJywgYW5kIG9uIHRoZSBvcHBvc2l0ZSBzdHJhbmQgJ3RyYW5zY3JpYmVkJywgc2luY2UgdGhlCmdlbmUgZGVmaW5pdGlvbnMgcmVwb3J0IHRoZSBjb2Rpbmcgb3Igc2Vuc2Ugc3RyYW5kLCB3aGljaCBpcyB1bnRyYW5zY3JpYmVkLiBObwpzdHJhbmQgaW5mb3JtYXRpb24gaXMgcmVwb3J0ZWQgZm9yIGJhc2Ugc3Vic3RpdHV0aW9ucyB0aGF0IG92ZXJsYXAgd2l0aCBtb3JlCnRoYW4gb25lIGdlbmUgb24gZGlmZmVyZW50IHN0cmFuZHMuCgo8L2RldGFpbHM+CgpgYGB7ciB0cmFuX3N0cmFuZF9iaWFzLCBmaWcuaGVpZ2h0PTN9CiMgR2V0IGtub3duIGdlbmVzIHRhYmxlIGZyb20gVUNTQwppZiAocGFyYW1zJGdlbm9tZV9idWlsZCA9PSAnaGcxOScpIHsKICBnZW5lc19saXN0IDwtIGdlbmVzKFR4RGIuSHNhcGllbnMuVUNTQy5oZzE5Lmtub3duR2VuZSkKfSBlbHNlIHsKICBnZW5lc19saXN0IDwtIGdlbmVzKFR4RGIuSHNhcGllbnMuVUNTQy5oZzM4Lmtub3duR2VuZSkKfQoKIyBNdXRhdGlvbiBjb3VudCBtYXRyaXggd2l0aCBzdHJhbmQgaW5mbyAoNCo2KjQ9OTYgLT4gOTYqMj0xOTIpCm11dF9tYXRfcyA8LSBNdXRhdGlvbmFsUGF0dGVybnM6Om11dF9tYXRyaXhfc3RyYW5kZWQoc29tYXRpY19zbnYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmX2dlbm9tZSA9IHJlZl9nZW5vbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VzID0gZ2VuZXNfbGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlID0gInRyYW5zY3JpcHRpb24iKQoKIyBNdXRhdGlvbiBjb3VudCBwZXIgdHlwZSBhbmQgc3RyYW5kCnN0cmFuZF9jb3VudHMgPC0gTXV0YXRpb25hbFBhdHRlcm5zOjpzdHJhbmRfb2NjdXJyZW5jZXMobXV0X21hdF9zLCBieSA9ICJhbGwiKQojIFBvaXNzb24gdGVzdCBmb3Igc3RyYW5kIGFzeW1tZXRyeSBzaWduaWZpY2FuY2UgdGVzdGluZwpzdHJhbmRfYmlhcyA8LSBNdXRhdGlvbmFsUGF0dGVybnM6OnN0cmFuZF9iaWFzX3Rlc3Qoc3RyYW5kX2NvdW50cykKCiMgbXV0YXRpb24gc3BlY3RydW0gd2l0aCBzdHJhbmQgZGlzdGluY3Rpb24KTXV0YXRpb25hbFBhdHRlcm5zOjpwbG90X3N0cmFuZChzdHJhbmRfY291bnRzLCBtb2RlID0gInJlbGF0aXZlIikKIyBlZmZlY3Qgc2l6ZSBvZiBzdHJhbmQgYmlhcwpNdXRhdGlvbmFsUGF0dGVybnM6OnBsb3Rfc3RyYW5kX2JpYXMoc3RyYW5kX2JpYXMpCmBgYAoKIyMjIyBSZXBsaWNhdGl2ZSBzdHJhbmQgYmlhcwoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKVGhlIGludm9sdmVtZW50IG9mIHJlcGxpY2F0aW9uLWFzc29jaWF0ZWQgbWVjaGFuaXNtcyBjYW4gYmUgZXZhbHVhdGVkIGJ5CnRlc3RpbmcgZm9yIGEgbXV0YXRpb25hbCBiaWFzIGJldHdlZW4gdGhlIGxlYWRpbmcgYW5kIGxhZ2dpbmcgc3RyYW5kLgpUaGUgcmVwbGljYXRpb24gc3RyYW5kIGlzIGRlcGVuZGVudCBvbiB0aGUgbG9jYXRpb25zIG9mIHJlcGxpY2F0aW9uCm9yaWdpbnMgZnJvbSB3aGljaCBETkEgcmVwbGljYXRpb24gaXMgZmlyZWQuCkhvd2V2ZXIsIHJlcGxpY2F0aW9uIHRpbWluZyBpcyBkeW5hbWljIGFuZCBjZWxsLXR5cGUgc3BlY2lmaWMsCndoaWNoIG1ha2VzIHJlcGxpY2F0aW9uIHN0cmFuZCBkZXRlcm1pbmF0aW9uIGxlc3Mgc3RyYWlnaHRmb3J3YXJkIHRoYW4KdHJhbnNjcmlwdGlvbmFsIHN0cmFuZCBiaWFzIGFuYWx5c2lzLgpSZXBsaWNhdGlvbiB0aW1pbmcgcHJvZmlsZXMgY2FuIGJlIGdlbmVyYXRlZCB3aXRoClJlcGxpLVNlcSBleHBlcmltZW50cy4gT25jZSB0aGUgcmVwbGljYXRpb24gZGlyZWN0aW9uIGlzIGRlZmluZWQsCmEgc3RyYW5kIGFzeW1tZXRyeSBhbmFseXNpcyBjYW4gYmUgcGVyZm9ybWVkIHNpbWlsYXJseSBhcyB0aGUgdHJhbnNjcmlwdGlvbgpzdHJhbmQgYmlhcyBhbmFseXNpcy4KCjwvZGV0YWlscz4KCmBgYHtyIHJlcF9zdHJhbmRfYmlhcywgZmlnLmhlaWdodD0zfQpyZXBsaV9maWxlIDwtIHN5c3RlbS5maWxlKCJleHRkYXRhL1JlcGxpY2F0aW9uRGlyZWN0aW9uUmVnaW9ucy5iZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2thZ2UgPSAiTXV0YXRpb25hbFBhdHRlcm5zIikKIyBzdGFydC9zdG9wIGNvbnRhaW4gc2NpZW50aWZpYyBub3RhdGlvbiwgc28gbmVlZCB0byBiZSBkb3VibGVzCnJlcGxpX3N0cmFuZCA8LQogIHJlYWRyOjpyZWFkX3RzdihyZXBsaV9maWxlLCBjb2xfbmFtZXMgPSBUUlVFLCBjb2xfdHlwZXMgPSAiY2RkY2MiKSAlPiUKICBkcGx5cjo6bXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMuZmFjdG9yKQpyZXBsaV9zdHJhbmRfZ3JhbmdlcyA8LSBHUmFuZ2VzKAogIHNlcW5hbWVzID0gcmVwbGlfc3RyYW5kJENociwKICByYW5nZXMgPSBJUmFuZ2VzKHN0YXJ0ID0gcmVwbGlfc3RyYW5kJFN0YXJ0ICsgMSwKICAgICAgICAgICAgICAgICAgIGVuZCA9IHJlcGxpX3N0cmFuZCRTdG9wKSwKICBzdHJhbmRfaW5mbyA9IHJlcGxpX3N0cmFuZCRDbGFzcykKCnNlcWxldmVsc1N0eWxlKHJlcGxpX3N0cmFuZF9ncmFuZ2VzKSA8LSBzZXFsZXZlbHNTdHlsZShiYXNlOjpnZXQocmVmX2dlbm9tZSkpCgptdXRfbWF0X3NfcmVwIDwtCiAgTXV0YXRpb25hbFBhdHRlcm5zOjptdXRfbWF0cml4X3N0cmFuZGVkKAogICAgdmNmX2xpc3QgPSBzb21hdGljX3NudiwKICAgIHJlZl9nZW5vbWUgPSByZWZfZ2Vub21lLAogICAgcmFuZ2VzID0gcmVwbGlfc3RyYW5kX2dyYW5nZXMsCiAgICBtb2RlID0gInJlcGxpY2F0aW9uIikKIyBNdXRhdGlvbiBjb3VudCBwZXIgdHlwZSBhbmQgc3RyYW5kCnN0cmFuZF9jb3VudHNfcmVwIDwtIHN0cmFuZF9vY2N1cnJlbmNlcyhtdXRfbWF0X3NfcmVwLCBieSA9ICJhbGwiKQojIFBvaXNzb24gdGVzdCBmb3Igc3RyYW5kIGFzeW1tZXRyeSBzaWduaWZpY2FuY2UgdGVzdGluZwpzdHJhbmRfYmlhc19yZXAgPC0gc3RyYW5kX2JpYXNfdGVzdChzdHJhbmRfY291bnRzX3JlcCkKCk11dGF0aW9uYWxQYXR0ZXJuczo6cGxvdF9zdHJhbmQoc3RyYW5kX2NvdW50c19yZXAsIG1vZGUgPSAicmVsYXRpdmUiKQpNdXRhdGlvbmFsUGF0dGVybnM6OnBsb3Rfc3RyYW5kX2JpYXMoc3RyYW5kX2JpYXNfcmVwKQpgYGAKCiMjIyBTaWduYXR1cmUgQ29udHJpYnV0aW9uIHsudGFic2V0IC50YWJzZXQtZmFkZSAjY29udHJpYnV0aW9uc30KCjxkZXRhaWxzPgo8c3VtbWFyeT5EZXNjcmlwdGlvbjwvc3VtbWFyeT4KClRoZSBjb250cmlidXRpb24gb2YgYW55IHNldCBvZiBzaWduYXR1cmVzIHRvIHRoZSBtdXRhdGlvbmFsIHByb2ZpbGUgb2YgYQpzYW1wbGUgY2FuIGJlIHF1YW50aWZpZWQuIFRoaXMgdW5pcXVlIGZlYXR1cmUgaXMgc3BlY2lmaWNhbGx5IHVzZWZ1bApmb3IgbXV0YXRpb25hbCBzaWduYXR1cmUgYW5hbHlzZXMgb2Ygc21hbGwgY29ob3J0cyBvciBpbmRpdmlkdWFsIHNhbXBsZXMsCmJ1dCBhbHNvIHRvIHJlbGF0ZSBvd24gZmluZGluZ3MgdG8ga25vd24gc2lnbmF0dXJlcyBhbmQgcHVibGlzaGVkIGZpbmRpbmdzLgpUaGUgYGZpdF90b19zaWduYXR1cmVzYCBmdW5jdGlvbiBmaW5kcyB0aGUgb3B0aW1hbCBsaW5lYXIgY29tYmluYXRpb24gb2YKbXV0YXRpb25hbCBzaWduYXR1cmVzIHRoYXQgbW9zdCBjbG9zZWx5IHJlY29uc3RydWN0cwp0aGUgbXV0YXRpb24gbWF0cml4IGJ5IHNvbHZpbmcgYSBub24tbmVnYXRpdmUgbGVhc3Qtc3F1YXJlcyBjb25zdHJhaW50cyBwcm9ibGVtLgoKU2hvd24gYXJlIHNpZ25hdHVyZXMgd2l0aCBwb3NpdGl2ZSBDb250cmlidXRpb24gdmFsdWVzLCBhbG9uZyB3aXRoIHN1bW1hcmlzZWQgZGVzY3JpcHRpb25zCmFuZCByZWZlcmVuY2Ugc2lnbmF0dXJlIHBsb3RzIGZyb20gPGh0dHBzOi8vY2FuY2VyLnNhbmdlci5hYy51ay9jb3NtaWMvc2lnbmF0dXJlcz4uCgo8L2RldGFpbHM+Cgo8cD4mbmJzcDs8L3A+CgojIyMjIE9MRAoKYGBge3IgbXV0YXRpb25hbF9zaWduYXR1cmVfY29udHJpYnV0aW9ufQpzaWdfdGFibGUgPC0KICByZWFkcjo6cmVhZF90c3YoZmlsZSA9ICJtaXNjL3NpZy92Ml9tYXIyMDE1L3NpZ25hdHVyZXNfZGVzY3JpcHRpb24udHN2IiwgY29sX3R5cGVzID0gImNjIikgJT4lCiAgZHBseXI6Om11dGF0ZShQbG90ID0gcGFzdGUwKCIhW10obWlzYy9zaWcvdjJfbWFyMjAxNS9pbWcvc2lnLSIsIHNpZ25hdHVyZSwgIi5wbmcpIiksCiAgICAgICAgICAgICAgICBzaWduYXR1cmUgPSBwYXN0ZTAoIlNpZyIsIHNpZ25hdHVyZSkpICU+JQogIGRwbHlyOjpzZWxlY3QoU2lnbmF0dXJlID0gc2lnbmF0dXJlLCBEZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLCBQbG90KQoKbXV0X3NpZ19jb250ciAlPiUKICBkcGx5cjo6bGVmdF9qb2luKHNpZ190YWJsZSwgYnkgPSAiU2lnbmF0dXJlIikgJT4lCiAga25pdHI6OmthYmxlKCkgJT4lCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmb250X3NpemUgPSAxMikgJT4lCiAga2FibGVFeHRyYTo6c2Nyb2xsX2JveChoZWlnaHQgPSAiNDAwcHgiKQpgYGAKCiMjIyMgTkVXCgpgYGB7ciBtdXRhdGlvbmFsX3NpZ25hdHVyZV9jb250cmlidXRpb24yfQpzaWdfdGFibGUyIDwtCiAgcmVhZHI6OnJlYWRfdHN2KGZpbGUgPSAibWlzYy9zaWcvdjNfbWF5MjAxOS9zaWduYXR1cmVzX2Rlc2NyaXB0aW9uLnRzdiIsIGNvbF90eXBlcyA9ICJjYyIpICU+JQogIGRwbHlyOjptdXRhdGUoUGxvdCA9IHBhc3RlMCgiIVtdKG1pc2Mvc2lnL3YzX21heTIwMTkvaW1nL3NicyIsIHNpZ25hdHVyZSwgIi5wbmcpIiksCiAgICAgICAgICAgICAgICBzaWduYXR1cmUgPSBwYXN0ZTAoIlNCUyIsIHNpZ25hdHVyZSkpICU+JQogIGRwbHlyOjpzZWxlY3QoU2lnbmF0dXJlID0gc2lnbmF0dXJlLCBEZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLCBQbG90KQoKcG9zc2libGVfc2VxX2FydGVmYWN0cyA8LSBjKCJTQlMyNyIsICJTQlM0MyIsICJTQlM0NSIsICJTQlM0NiIsICJTQlM0NyIsICJTQlM0OCIsICJTQlM0OSIsICJTQlM1MCIsICJTQlM1MSIsICJTQlM1MiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0JTNTMiLCAiU0JTNTQiLCAiU0JTNTUiLCAiU0JTNTYiLCAiU0JTNTciLCAiU0JTNTgiLCAiU0JTNTkiLCAiU0JTNjAiKQoKbXV0X3NpZ19jb250cjIgJT4lCiAgZHBseXI6OmxlZnRfam9pbihzaWdfdGFibGUyLCBieSA9ICJTaWduYXR1cmUiKSAlPiUKICBkcGx5cjo6bXV0YXRlKFNpZ25hdHVyZSA9IGlmZWxzZShTaWduYXR1cmUgJWluJSBwb3NzaWJsZV9zZXFfYXJ0ZWZhY3RzLCBwYXN0ZTAoU2lnbmF0dXJlLCAiIChTQSkiKSwgU2lnbmF0dXJlKSkgJT4lCiAga25pdHI6OmthYmxlKCkgJT4lCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmb250X3NpemUgPSAxMikgJT4lCiAga2FibGVFeHRyYTo6c2Nyb2xsX2JveChoZWlnaHQgPSAiNDAwcHgiKQpgYGAKCjxwPiZuYnNwOzwvcD4KCiMjIyBSYWluZmFsbCBQbG90IHsjcmFpbmZhbGx9ClJhaW5mYWxsIHBsb3RzIHNob3cgdGhlIGRpc3RyaWJ1dGlvbiBvZiBtdXRhdGlvbnMgYWxvbmcgdGhlIGdlbm9tZSwgd2l0aCBtdXRhdGlvbiB0eXBlcwppbmRpY2F0ZWQgd2l0aCBkaWZmZXJlbnQgY29sb3JzLiBUaGUgeS1heGlzIGNvcnJlc3BvbmRzIHRvIHRoZSBkaXN0YW5jZSBvZiBhIG11dGF0aW9uIGZyb20gdGhlCnByZXZpb3VzIG11dGF0aW9uLCBhbmQgaXMgbG9nMTAgdHJhbnNmb3JtZWQuIERyb3AtZG93bnMgZnJvbSB0aGUgcGxvdHMgaW5kaWNhdGUgY2x1c3RlcnMgb3IKImhvdHNwb3RzIiBvZiBtdXRhdGlvbnMuCgpgYGB7ciBtdXRhdGlvbmFscGF0dGVybnNfcmFpbmZhbGwsIG91dC53aWR0aD0iOTAlIiwgZmlnLndpZHRoPTE0fQojIFdoZW4gdGhlcmUgaXMgb25seSAxIG9yIGxvd2VyIG51bWJlciBvZiB2YXJpYW50cyBvbiBhIGNocm9tb3NvbWUsIE11dGF0aW9uYWxQYXR0ZXJuczo6cGxvdF9yYWluZmFsbCB3aWxsIGNyYXNoIHdpdGggYW4gZXJyb3IuIFNvIG5lZWQgdG8gY2hlY2sgaWYgaXQgd2lsbCB3b3JrIGJlZm9yZWhhbmQuCmNocm9tb3NvbWVzID0gc2VxbmFtZXMoZ2V0KHJlZl9nZW5vbWUpKVsxOjIyXQp2Y2YgPSBzb21hdGljX3NudltbMV1dCmNocl9zdWJzZXQgPSB2Y2Zbc2VxbmFtZXModmNmKSA9PSBjaHJvbW9zb21lc1sxXV0KbiA9IGxlbmd0aChjaHJfc3Vic2V0KQp3aWxsX3dvcmsgPSBGQUxTRQpmb3IgKGkgaW4gMTpsZW5ndGgoY2hyb21vc29tZXMpKSB7CiAgY2hyX3N1YnNldCA9IHZjZltzZXFuYW1lcyh2Y2YpID09IGNocm9tb3NvbWVzW2ldXQogIG4gPSBsZW5ndGgoY2hyX3N1YnNldCkKICBpZiAobiA+PSAyKSB7CiAgICB3aWxsX3dvcmsgPSBUUlVFCiAgfQp9CmlmICh3aWxsX3dvcmspIHsKICBNdXRhdGlvbmFsUGF0dGVybnM6OnBsb3RfcmFpbmZhbGwoc29tYXRpY19zbnZbWzFdXSwgY2hyb21vc29tZXMgPSBzZXFuYW1lcyhnZXQocmVmX2dlbm9tZSkpWzE6MjJdLCBjZXggPSAxLjIsIHlsaW0gPSAxZSswOSkKfQpgYGAKCgojIyBDaXJjb3MgUGxvdHMgey50YWJzZXQgLnRhYnNldC1mYWRlICNjaXJjb3N9CkNpcmNvcyBwbG90cyBhcmUgZ2VuZXJhdGVkIGJ5IFBVUlBMRS4KVGhlIGZpcnN0IEJBRiBwbG90IGlzIGJhc2VkIG9uIFBVUlBMRSBkYXRhIGFuZCBjb25maWd1cmF0aW9uIGZpbGVzLgoKIyMjIEJBRiwgVG90YWwvTWlub3IgQ04sIFNWcwoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKKiBfX1RyYWNrMV9fOiBDaHJvbW9zb21lcy4gRGFya2VyIHNoYWRlZCBhcmVhczogZ2FwcyBpbiByZWZlcmVuY2UgZ2Vub21lCiAgKGNlbnRyb21lcmVzLCBoZXRlcm9jaHJvbWF0aW4gJiBtaXNzaW5nIHNob3J0IGFybXMpCiogX19UcmFjazJfXzogPHNwYW4gc3R5bGU9ImNvbG9yOiM4QTJCRTIiPkJldGEgQWxsZWxlIEZyZXF1ZW5jeTwvc3Bhbj4uCiAgR2l2ZW4gdGhhdCB0aGUgQkFGIHBvaW50cyBjb3JyZXNwb25kIHRvIGFsbGVsZSBmcmVxdWVuY2llcyBvZiBoZXRlcm96eWdvdXMgU05QcyB0aGF0IGFyZSBjb21tb24gaW4gZ2VybWxpbmUgc2FtcGxlcywKICB0aGVyZSBzaG91bGRuJ3QgYmUgYW55IGluIGNocm9tb3NvbWUgWSAoYW5kIGNocm9tb3NvbWUgWCB3aGVuIG1hbGUpLgoqIF9fVHJhY2szX186IF9fVG90YWxfXyBjb3B5IG51bWJlciBjaGFuZ2VzIGFkanVzdGVkIGZvciB0dW1vciBwdXJpdHksCiAgaW5jbHVkaW5nIGZvY2FsIGFuZCBjaHJvbW9zb21hbCBzb21hdGljIGV2ZW50cy4KICA8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj5SZWQ8L3NwYW4+ID0gTG9zczsgPHNwYW4gc3R5bGU9ImNvbG9yOiMzMkNEMzIiPkdyZWVuPC9zcGFuPiA9IEdhaW4uCiAgU2NhbGVkIGZyb20gMCAoY29tcGxldGUgbG9zcykgdG8gNiAoaGlnaCBsZXZlbCBnYWlucykuCiAgSWYgPiA2LCBzaG93biBhcyA2IHdpdGggYSBncmVlbiBkb3Qgb24gdGhlIG91dGVybW9zdCBncmVlbiBncmlkbGluZS4KKiBfX1RyYWNrNF9fOiBfX01pbm9yX18gYWxsZWxlIGNvcHkgbnVtYmVycy4gUmFuZ2UgZnJvbSAwIHRvIDMuCiAgRXhwZWN0ZWQgbm9ybWFsIG1pbm9yIGFsbGVsZSBjb3B5IG51bWJlciBpcyAxLCBhbmQgYW55dGhpbmcgYmVsb3cgMSBpcyBzaG93bgogIGFzIGEgbG9zcyAoPHNwYW4gc3R5bGU9ImNvbG9yOiNFRTc2MDAiPk9yYW5nZTwvc3Bhbj4pLCByZXByZXNlbnRpbmcgYW4gTE9IIGV2ZW50LgogIE1pbm9yIGFsbGVsZSBjb3B5IG51bWJlcnMgYWJvdmUgMSAoPHNwYW4gc3R5bGU9ImNvbG9yOiM3RUMwRUUiPkJsdWU8L3NwYW4+KSBpbmRpY2F0ZSBnYWlucwogIG9mIGJvdGggQSBhbmQgQiBhbGxlbGVzLgoqIF9fVHJhY2s1X18gKElubmVyIGNpcmNsZSk6IE9ic2VydmVkIHN0cnVjdHVyYWwgdmFyaWFudHMgd2l0aGluIG9yIGJldHdlZW4gdGhlIGNocm9tb3NvbWVzLgogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6IzdFQzBFRSI+Qmx1ZTwvc3Bhbj4gPSBUcmFuc2xvY2F0aW9ucwogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj5SZWQ8L3NwYW4+ID0gRGVsZXRpb25zCiAgICAqIDxzcGFuIHN0eWxlPSJjb2xvcjojZTZlNjAwIj5ZZWxsb3c8L3NwYW4+ID0gSW5zZXJ0aW9ucwogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6IzMyQ0QzMiI+R3JlZW48L3NwYW4+ID0gVGFuZGVtIGR1cGxpY2F0aW9ucwogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6IzAwMDAwMCI+QmxhY2s8L3NwYW4+ID0gSW52ZXJzaW9ucwoKPC9kZXRhaWxzPgoKYGBge3IgY2lyY29zX2JhZl9wbG90LCBvdXQud2lkdGg9IjgwJSJ9CmltZ19kaXIgPC0gZmlsZS5wYXRoKCdpbWcnKSAjIGNyZWF0ZWQgYmVmb3JlIHdoZW4gY29weWluZyBwdXJwbGUgZmlsZXMgdG8gdG1wIGRpcgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhmaWxlLnBhdGgoaW1nX2RpciwgcGFzdGUwKHBhcmFtcyRiYXRjaF9uYW1lLCAnLmNpcmNvc19iYWYucG5nJykpKQpgYGAKCgojIyMgU05Wcy9JbmRlbHMsIFRvdGFsL01pbm9yIENOLCBTVnMKCjxkZXRhaWxzPgo8c3VtbWFyeT5EZXNjcmlwdGlvbjwvc3VtbWFyeT4KCiogX19UcmFjazFfXzogQ2hyb21vc29tZXMuIERhcmtlciBzaGFkZWQgYXJlYXM6IGdhcHMgaW4gcmVmZXJlbmNlIGdlbm9tZQogIChjZW50cm9tZXJlcywgaGV0ZXJvY2hyb21hdGluICYgbWlzc2luZyBzaG9ydCBhcm1zKQoqIF9fVHJhY2syX186IFNvbWF0aWMgdmFyaWFudHMgKGluY2wuIGV4b24sIGludHJvbiBhbmQgaW50ZXJnZW5pYyByZWdpb25zKS4KICAgICogb3V0ZXIgcmluZzogU05QIGFsbGVsZSBmcmVxdWVuY2llcywgY29ycmVjdGVkIGZvciB0dW1vciBwdXJpdHkgYW5kIHNjYWxlZCBmcm9tIDAgdG8gMTAwJS4KICAgICAgRWFjaCBkb3QgcmVwcmVzZW50cyBhIHNpbmdsZSBzb21hdGljIHZhcmlhbnQsIGNvbG91cmVkIGFjY29yZGluZyB0byB0aGUKICAgICAgdHlwZSBvZiBiYXNlIGNoYW5nZSAoZS5nLiBDPlQvRz5BIGluIHJlZCkuCiAgICAqIGlubmVyIHJpbmc6IHNob3J0IGluc2VydGlvbiAoeWVsbG93KSBhbmQgZGVsZXRpb24gKHJlZCkgbG9jYXRpb25zLgoqIF9fVHJhY2szX186IE9ic2VydmVkIF9fdG90YWxfXyBjb3B5IG51bWJlciBjaGFuZ2VzIGFkanVzdGVkIGZvciB0dW1vciBwdXJpdHksCiAgaW5jbHVkaW5nIGZvY2FsIGFuZCBjaHJvbW9zb21hbCBzb21hdGljIGV2ZW50cy4KICA8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj5SZWQ8L3NwYW4+ID0gTG9zczsgPHNwYW4gc3R5bGU9ImNvbG9yOiMzMkNEMzIiPkdyZWVuPC9zcGFuPiA9IEdhaW4uCiAgU2NhbGVkIGZyb20gMCAoY29tcGxldGUgbG9zcykgdG8gNiAoaGlnaCBsZXZlbCBnYWlucykuCiAgSWYgPiA2LCBzaG93biBhcyA2IHdpdGggYSBncmVlbiBkb3Qgb24gdGhlIG91dGVybW9zdCBncmVlbiBncmlkbGluZS4KKiBfX1RyYWNrNF9fOiBPYnNlcnZlZCBfX21pbm9yX18gYWxsZWxlIGNvcHkgbnVtYmVycy4gUmFuZ2UgZnJvbSAwIHRvIDMuCiAgRXhwZWN0ZWQgbm9ybWFsIG1pbm9yIGFsbGVsZSBjb3B5IG51bWJlciBpcyAxLCBhbmQgYW55dGhpbmcgYmVsb3cgMSBpcyBzaG93bgogIGFzIGEgbG9zcyAoPHNwYW4gc3R5bGU9ImNvbG9yOiNFRTc2MDAiPk9yYW5nZTwvc3Bhbj4pLCByZXByZXNlbnRpbmcgYW4gTE9IIGV2ZW50LgogIE1pbm9yIGFsbGVsZSBjb3B5IG51bWJlcnMgYWJvdmUgMSAoPHNwYW4gc3R5bGU9ImNvbG9yOiM3RUMwRUUiPkJsdWU8L3NwYW4+KSBpbmRpY2F0ZSBnYWlucwogIG9mIGJvdGggQSBhbmQgQiBhbGxlbGVzLgoqIF9fVHJhY2s1X18gKElubmVyIGNpcmNsZSk6IE9ic2VydmVkIHN0cnVjdHVyYWwgdmFyaWFudHMgd2l0aGluIG9yIGJldHdlZW4gdGhlIGNocm9tb3NvbWVzLgogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6IzdFQzBFRSI+Qmx1ZTwvc3Bhbj4gPSBUcmFuc2xvY2F0aW9ucwogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj5SZWQ8L3NwYW4+ID0gRGVsZXRpb25zCiAgICAqIDxzcGFuIHN0eWxlPSJjb2xvcjojZTZlNjAwIj5ZZWxsb3c8L3NwYW4+ID0gSW5zZXJ0aW9ucwogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6IzMyQ0QzMiI+R3JlZW48L3NwYW4+ID0gVGFuZGVtIGR1cGxpY2F0aW9ucwogICAgKiA8c3BhbiBzdHlsZT0iY29sb3I6IzAwMDAwMCI+QmxhY2s8L3NwYW4+ID0gSW52ZXJzaW9ucwoKPC9kZXRhaWxzPgoKYGBge3IgY2lyY29zX2RlZmF1bHQxLCBvdXQud2lkdGg9IjgwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGZpbGUucGF0aChpbWdfZGlyLCBwYXN0ZTAocGFyYW1zJGJhdGNoX25hbWUsICcuY2lyY29zLnBuZycpKSkKYGBgCgojIyMgQWxsZWxlIFJhdGlvcywgQkFGCgo8ZGV0YWlscz4KPHN1bW1hcnk+RGVzY3JpcHRpb248L3N1bW1hcnk+CgoqIF9fVHJhY2sxX186IENocm9tb3NvbWVzLiBEYXJrZXIgc2hhZGVkIGFyZWFzOiBnYXBzIGluIHJlZmVyZW5jZSBnZW5vbWUKICAoY2VudHJvbWVyZXMsIGhldGVyb2Nocm9tYXRpbiAmIG1pc3Npbmcgc2hvcnQgYXJtcykKKiBfX1RyYWNrMl9fOiA8c3BhbiBzdHlsZT0iY29sb3I6Ymx1ZSI+VHVtb3I8L3NwYW4+IGFuZCA8c3BhbiBzdHlsZT0iY29sb3I6IzMyQ0QzMiI+Tm9ybWFsPC9zcGFuPiBBbGxlbGUgUmF0aW9zCiogX19UcmFjazNfXzogPHNwYW4gc3R5bGU9ImNvbG9yOiNFRTc2MDAiPkJldGEgQWxsZWxlIEZyZXF1ZW5jeTwvc3Bhbj4KICBHaXZlbiB0aGF0IHRoZSBCQUYgcG9pbnRzIGNvcnJlc3BvbmQgdG8gYWxsZWxlIGZyZXF1ZW5jaWVzIG9mIGhldGVyb3p5Z291cyBTTlBzIHRoYXQgYXJlIGNvbW1vbiBpbiBnZXJtbGluZSBzYW1wbGVzLAogIHRoZXJlIHNob3VsZG4ndCBiZSBhbnkgaW4gY2hyb21vc29tZSBZIChhbmQgY2hyb21vc29tZSBYIHdoZW4gbWFsZSkuCgo8L2RldGFpbHM+CgpgYGB7ciBjaXJjb3NfZGVmYXVsdDIsIG91dC53aWR0aD0iODAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoZmlsZS5wYXRoKGltZ19kaXIsIHBhc3RlMChwYXJhbXMkYmF0Y2hfbmFtZSwgJy5pbnB1dC5wbmcnKSkpCmBgYAoKIyMgU3RydWN0dXJhbCBWYXJpYW50cyB7I3N2LXN1bW1hcnl9ClN0cnVjdHVyYWwgdmFyaWFudHMgYXJlIGluZmVycmVkIHdpdGggW01hbnRhXShodHRwczovL2dpdGh1Yi5jb20vaWxsdW1pbmEvbWFudGEpLAphZGp1c3RlZCB1c2luZyBbUFVSUExFXShodHRwczovL2dpdGh1Yi5jb20vaGFydHdpZ21lZGljYWwvaG1mdG9vbHMvdHJlZS9tYXN0ZXIvcHVyaXR5LXBsb2lkeS1lc3RpbWF0b3IjNy1zdHJ1Y3R1cmFsLXZhcmlhbnQtcmVjb3ZlcnktYW5kLXNpbmdsZS1icmVha2VuZC1maWx0ZXJpbmcpLAphbmQgcHJpb3JpdGlzZWQgdXNpbmcgW3NpbXBsZV9zdl9hbm5vdGF0aW9uXShodHRwczovL2dpdGh1Yi5jb20vQXN0cmFaZW5lY2EtTkdTL3NpbXBsZV9zdl9hbm5vdGF0aW9uKS4KQWxsZWxlIGZyZXF1ZW5jaWVzLCBjb3B5IG51bWJlciBjaGFuZ2VzIGFuZCBwbG9pZHkgYXJlIHB1cml0eS1hZGp1c3RlZC4KCjxkZXRhaWxzPgo8c3VtbWFyeT5EZXRhaWxzPC9zdW1tYXJ5PgoKVGhlIGlucHV0IGZpbGUgY29ycmVzcG9uZHMgdG8gYHVtY2NyaXNlZC88YmF0Y2g+L3N0cnVjdHVyYWwvPGJhdGNoPi1tYW50YS50c3ZgLgoKSXQncyBnZW5lcmF0ZWQgdGhyb3VnaCB0aGUgZm9sbG93aW5nIHN0ZXBzOgoKX19TdGVwIDE6IFByb2Nlc3NpbmdfXwoKKiBfX0lucHV0X186IE1hbnRhIHN0cnVjdHVyYWwgdmFyaWFudCBjYWxscyBmcm9tIGJjYmlvCihgZmluYWwvPHR1bW9yLW5hbWU+LzxiYXRjaC1uYW1lPi1zdi1wcmlvcml0aXplLW1hbnRhLnZjZi5nemAgKG9yCmA8YmF0Y2gtbmFtZT4tbWFudGEudmNmLmd6YCBpZiBub3QgcHJpb3JpdGlzZWQpKQoqIFJlbW92ZSBmb2xsb3dpbmcgYW5ub3RhdGlvbnMgZnJvbSBNYW50YSBWQ0Y6CiAgJ0lORk8vU0lNUExFX0FOTicsICdJTkZPL1NWX0hJR0hFU1RfVElFUicsICdGSUxURVIvSW50ZXJnZW5pYycsICdGSUxURVIvTWlzc2luZ0FubicsICdGSUxURVIvUkVKRUNUJwoqIFByaW9yaXRpc2UgdmFyaWFudHMgd2l0aCBbc2ltcGxlX3N2X2Fubm90YXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS92bGFkc2F2ZWxpZXYvc2ltcGxlX3N2X2Fubm90YXRpb24pYAoqIF9fT3V0cHV0X186IGB3b3JrL3tiYXRjaH0vc3RydWN0dXJhbC9wcmlvcml0aXplL3tiYXRjaH0tbWFudGEudmNmLmd6YAoqIEtlZXAgUEFTUyB2YXJpYW50cwoqIElmIG1vcmUgdGhhbiAxMDAsMDAwIHZhcmlhbnRzLCBrZWVwIG9ubHkgdmFyaWFudHMgd2hlcmUgYElORk8vU1ZfVE9QX1RJRVIgPD0gM2AKKiBfX091dHB1dF9fOiBgd29yay97YmF0Y2h9L3N0cnVjdHVyYWwva2VlcF9wYXNzL3tiYXRjaH0tbWFudGEudmNmYAoqIERlYWwgd2l0aCBjaHJvbW9zb21lIGNhcGl0YWxpc2F0aW9uIG9jY3VycmluZyBmcm9tIFNucEVmZgoqIFJ1biBCcmVha1BvaW50SW5zcGVjdG9yIChCUEkpIGlmIGl0IHdhcyBkaXNhYmxlZCBpbiBiY2JpbwoqIF9fT3V0cHV0X186IGB3b3JrL3tiYXRjaH0vc3RydWN0dXJhbC9tYXliZV9icGkve2JhdGNofS1tYW50YS52Y2ZgCgpfX1N0ZXAgMjogRmlsdGVyaW5nX18KCiogS2VlcCBQQVNTIHZhcmlhbnRzIChzaW5jZSBCUEkgdXBkYXRlcyB0aGUgRklMVEVSIGNvbHVtbikKKiBGb3IgQk5EIHZhcmlhbnRzIHJlcXVpcmUgcGFpcmVkIHJlYWRzIHN1cHBvcnQgKFBSKSB0byBiZSBoaWdoZXIgdGhhbiBzcGxpdCByZWFkIHN1cHBvcnQgKFNSKQoqIEtlZXAgYWxsIGBJTkZPL1NWX1RPUF9USUVSIDw9IDJgIHZhcmlhbnRzCiogRm9yIGBJTkZPL1NWX1RPUF9USUVSID4gMmAgdmFyaWFudHMgcmVxdWlyZSBzcGxpdCBfb3JfIHBhaXJlZCByZWFkcyBzdXBwb3J0IG9mIGF0IGxlYXN0IDV4CiogRm9yIGBJTkZPL1NWX1RPUF9USUVSID4gMmAgdmFyaWFudHMgd2l0aCBsb3cgYWxsZWxlIGZyZXF1ZW5jeSBhdCBhbnkgYnJlYWtwb2ludCAoYEJQSV9BRlswIG9yIDFdIDwgMC4xYCksCiAgcmVxdWlyZSBTUiBvciBQUiBzdXBwb3J0IG9mIGF0IGxlYXN0IDEweAoqIF9fT3V0cHV0X186IGB3b3JrL3tiYXRjaH0vc3RydWN0dXJhbC9maWx0L3tiYXRjaH0tbWFudGEudmNmYAoKX19TdGVwIDM6IFBVUlBMRSBhbmQgRkZQRSBjb25kaXRpb25hbF9fCgoqIElmIHRoZSBzYW1wbGUgX2lzIG5vdF8gRkZQRToKICAqIEZlZWQgYWJvdmUgZmlsdGVyZWQgU1ZzIHRvIFBVUlBMRSwgd2hpY2ggb3V0cHV0cyBgcHVycGxlLnN2LnZjZi5nemAgdGhhdCBjb250YWlucyByZXNjdWVkIFNWcwogICogUHJpb3JpdGlzZSB2YXJpYW50cyAoYWdhaW4pCiAgKiBSZW1vdmUgJ0lORk8vQU5OJyBhbm5vdGF0aW9uCiAgKiBfX091dHB1dF9fOiBge2JhdGNofS9zdHJ1Y3R1cmFsL3tiYXRjaH0tbWFudGEudmNmLmd6YAoqIElmIHRoZSBzYW1wbGUgX2lzXyBGRlBFOgogICogSnVzdCBjb3B5IGBmaWx0ZXJlZGAgdmFyaWFudHMgYW5kIGRvbid0IGRvIGFueXRoaW5nCiAgICAoaS5lLiB3ZSBkb24ndCB3YW50IHRoZSByZXNjdWVkIFNWcyBmcm9tIFBVUlBMRSBzaW5jZSB0aGV5J2xsIGxpa2VseSBiZSBoZWFwcykKICAgIChub3RlIHRoYXQgUFVSUExFIHdpbGwgc3RpbGwgZ2V0IGZlZCB3aXRoIHRoZSBgZmlsdGVyZWRgIFNWcykKICAqIF9fT3V0cHV0X186IGB7YmF0Y2h9L3N0cnVjdHVyYWwve2JhdGNofS1tYW50YS52Y2YuZ3pgCgpfX1N0ZXAgNDogVFNWIGZpbmFsIG91dHB1dF9fCgoqIElucHV0OiBge2JhdGNofS9zdHJ1Y3R1cmFsL3tiYXRjaH0tbWFudGEudmNmLmd6YCBWQ0YKKiBPdXRwdXQ6IGB7YmF0Y2h9L3N0cnVjdHVyYWwve2JhdGNofS1tYW50YS50c3ZgIFRTVgoKCmBgYHtyIG1hbnRhX3Rzdl9kZXNjcmlwdGlvbn0KbWFudGFfdHN2X2NvbF9kZXNjciA8LSBkcGx5cjo6dHJpYmJsZSgKICB+Q29sdW1uLCB+RGVzY3JpcHRpb24sCiAgImNhbGxlciIsICJNYW50YSBTViBjYWxsZXIiLAogICJzYW1wbGUiLCAiVHVtb3Igc2FtcGxlIG5hbWUiLAogICJjaHJvbSIsICJDSFJPTSBjb2x1bW4gaW4gVkNGIiwKICAic3RhcnQiLCAiUE9TIGNvbHVtbiBpbiBWQ0YiLAogICJlbmQiLCAiSU5GTy9FTkQ6IEVuZCBwb3NpdGlvbiBvZiB0aGUgdmFyaWFudCBkZXNjcmliZWQgaW4gdGhpcyByZWNvcmQiLAogICJzdnR5cGUiLCAiSU5GTy9TVlRZUEU6IFR5cGUgb2Ygc3RydWN0dXJhbCB2YXJpYW50IiwKICAic3BsaXRfcmVhZF9zdXBwb3J0IiwgIkZPUk1BVC9TUiBvZiB0dW1vciBzYW1wbGU6IFNwbGl0IHJlYWRzIGZvciB0aGUgcmVmIGFuZCBhbHQgYWxsZWxlcyBpbiB0aGUgb3JkZXIgbGlzdGVkLCBmb3IgcmVhZHMgd2hlcmUgUChhbGxlbGV8cmVhZCk+MC45OTkiLAogICJwYWlyZWRfc3VwcG9ydF9QRSIsICJGT1JNQVQvUEUgb2YgdHVtb3Igc2FtcGxlOiA/PyIsCiAgInBhaXJlZF9zdXBwb3J0X1BSIiwgIkZPUk1BVC9QUiBvZiB0dW1vciBzYW1wbGU6IFNwYW5uaW5nIHBhaXJlZC1yZWFkIHN1cHBvcnQgZm9yIHRoZSByZWYgYW5kIGFsdCBhbGxlbGVzIGluIHRoZSBvcmRlciBsaXN0ZWQsIGZvciByZWFkcyB3aGVyZSBQKGFsbGVsZXxyZWFkKT4wLjk5OSIsCiAgIkFGX0JQSSIsICJJTkZPL0JQSV9BRjogQUYgYXQgZWFjaCBicmVha3BvaW50IChzbyBBRl9CUEkxLEFGX0JQSTIpIiwKICAic29tYXRpY3Njb3JlIiwgIklORk8vU09NQVRJQ1NDT1JFOiBTb21hdGljIHZhcmlhbnQgcXVhbGl0eSBzY29yZSIsCiAgInRpZXIiLCAiSU5GTy9TVl9UT1BfVElFUiAob3IgNCBpZiBtaXNzaW5nKTogSGlnaGVzdCBwcmlvcml0eSB0aWVyIGZvciB0aGUgZWZmZWN0cyBvZiBhIHZhcmlhbnQgZW50cnkiLAogICJhbm5vdGF0aW9uIiwgIklORk8vU0lNUExFX0FOTjogU2ltcGxpZmllZCBzdHJ1Y3R1cmFsIHZhcmlhbnQgYW5ub3RhdGlvbjogJ1NWVFlQRSB8IEVGRkVDVCB8IEdFTkUocykgfCBUUkFOU0NSSVBUIHwgUFJJT1JJVFkgKDEtNCknIiwKICAiQUZfUFVSUExFIiwgIklORk8vUFVSUExFX0FGOiBBRiBhdCBlYWNoIGJyZWFrZW5kIChwdXJpdHkgYWRqdXN0ZWQpIChzbyBBRl9QVVJQTEUxLEFGX1BVUlBMRTIpIiwKICAiQ05fUFVSUExFIiwgIklORk8vUFVSUExFX0NOOiBDTiBhdCBlYWNoIGJyZWFrZW5kIChwdXJpdHkgYWRqdXN0ZWQpIChzbyBDTl9QVVJQTEUxLENOX1BVUlBMRTIpIiwKICAiQ05fY2hhbmdlX1BVUlBMRSIsICJJTkZPL1BVUlBMRV9DTl9DSEFOR0U6IGNoYW5nZSBpbiBDTiBhdCBlYWNoIGJyZWFrZW5kIChwdXJpdHkgYWRqdXN0ZWQpIChzbyBDTl9jaGFuZ2VfUFVSUExFMSxDTl9jaGFuZ2VfUFVSUExFMikiLAogICJQbG9pZHlfUFVSUExFIiwgIklORk8vUFVSUExFX1BMT0lEWTogUGxvaWR5IG9mIHZhcmlhbnQgKHB1cml0eSBhZGp1c3RlZCkiLAogICJQVVJQTEVfc3RhdHVzIiwgIklORkVSUkVEIGlmIEZJTFRFUj1JTkZFUlJFRCwgb3IgUkVDT1ZFUkVEIGlmIGhhcyBJTkZPL1JFQ09WRVJFRCwgZWxzZSBibGFuay4gSU5GRVJSRUQ6IEJyZWFrZW5kIGluZmVycmVkIGZyb20gY29weSBudW1iZXIgdHJhbnNpdGlvbiIsCiAgIlNUQVJUX0JQSSIsICJJTkZPL0JQSV9TVEFSVDogQlBJIGFkanVzdGVkIGJyZWFrZW5kIGxvY2F0aW9uIiwKICAiRU5EX0JQSSIsICJJTkZPL0JQSV9FTkQ6IEJQSSBhZGp1c3RlZCBicmVha2VuZCBsb2NhdGlvbiIsCiAgIklEIiwgIklEIGNvbHVtbiBpbiBWQ0YiLAogICJNQVRFSUQiLCAiSU5GTy9NQVRFSUQ6IElEIG9mIG1hdGUgYnJlYWtlbmQiKQoKY2hlY2tfY29sc19kZXNjcmliZWQobWFudGFfdHN2X2NvbF9kZXNjciRDb2x1bW4sIGNvbG5hbWVzKHNvbWF0aWNfc3ZfdHN2KSkKCm1hbnRhX3Rzdl9jb2xfZGVzY3IgJT4lCiAgZHBseXI6OmFycmFuZ2UoQ29sdW1uKSAlPiUKICBkcGx5cjo6bXV0YXRlKENvbHVtbiA9IGthYmxlRXh0cmE6OmNlbGxfc3BlYyhDb2x1bW4sIGJvbGQgPSBUUlVFKSkgJT4lCiAga25pdHI6OmthYmxlKGVzY2FwZSA9IEZBTFNFLCBjYXB0aW9uID0gIkRlc2NyaXB0aW9uIG9mIE1hbnRhIFRTViBjb2x1bW5zIikgJT4lCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICBrYWJsZUV4dHJhOjpzY3JvbGxfYm94KGhlaWdodCA9ICIyNTBweCIpCmBgYAoKYGBge3Igc3ZfdGFibGVfZGVzY3JpcHRpb259CnN2X2NvbF9kZXNjciA8LSBkcGx5cjo6dHJpYmJsZSgKICB+Q29sdW1uLCB+RGVzY3JpcHRpb24sCiAgIm5yb3ciLCAiUm93IG51bWJlciB0aGF0IGNvbm5lY3RzIHZhcmlhbnRzIGJldHdlZW4gdGFibGVzIGluIHNhbWUgdGFiIHNldCIsCiAgInZhcm51bSIsICJPcmlnaW5hbCBldmVudCByb3cgbnVtYmVyIHRoYXQgY29ubmVjdHMgdmFyaWFudHMgdG8gZXZlbnRzIiwKICAiVGllclRvcCIsICJUb3AgcHJpb3JpdHkgb2YgdGhlIGV2ZW50IChmcm9tICdzaW1wbGVfc3ZfYW5ub3RhdGlvbic6IDEgaGlnaGVzdCwgNCBsb3dlc3QpIiwKICAiVGllciIsICJQcmlvcml0eSBvZiB0aGUgc3BlY2lmaWMgZXZlbnQgKGZyb20gJ3NpbXBsZV9zdl9hbm5vdGF0aW9uJzogMSBoaWdoZXN0LCA0IGxvd2VzdCkiLAogICJDaHIiLCAiQ2hyb21vc29tZSIsCiAgIlN0YXJ0IiwgIlN0YXJ0IHBvc2l0aW9uIGFzIGluZmVycmVkIGJ5IEJQSSAoZm9yIFBVUlBMRS1pbmZlcnJlZCBTVnMgd2UgdXNlIFBPUykiLAogICJFbmQiLCBwYXN0ZSgiRW5kIHBvc2l0aW9uLiBGb3IgQk5EcyB0aGlzIGhhcyBiZWVuIGFzc2lnbmVkIHRvIHRoZSBDaHI6U3RhcnQgb2YgdGhlIEJORCdzIG1hdGUgZm9yIGNvbnZlbmllbmNlLiIsCiAgICAgICAgICAgICAgICJWYWx1ZXMgYXJlIGluZmVycmVkIGJ5IEJQSSAoUFVSUExFLWluZmVycmVkIFNWcyBkb24ndCBoYXZlIGFuIEVuZCkuIiksCiAgIklEIiwgIklEIG9mIEJORCBmcm9tIE1hbnRhIChvciBQVVJQTEUgZm9yIFBVUlBMRS1pbmZlcnJlZCBTVnMpKSIsCiAgIk1BVEVJRCIsICJJRCBvZiBCTkQgbWF0ZSBmcm9tIE1hbnRhIiwKICAiQk5EX0lEIiwgIklEIG9mIEJORCBwYWlyIHNpbXBsaWZpZWQuIEJORHMgd2l0aCB0aGUgc2FtZSBCTkRfSUQgYmVsb25nIHRvIHRoZSBzYW1lIHRyYW5zbG9jYXRpb24gZXZlbnQiLAogICJCTkRfbWF0ZSIsICInQScgb3IgJ0InIGRlcGVuZGluZyBvbiBpZiBpdCdzIHRoZSBmaXJzdCBvciBzZWNvbmQgbWF0ZSBpbiB0aGUgQk5EIHBhaXIiLAogICJHZW5lcyIsICJHZW5lcyBpbnZvbHZlZCBpbiB0aGUgZXZlbnQuIERFTC9EVVAvSU5TIGV2ZW50cyBpbnZvbHZpbmcgbW9yZSB0aGFuIDIgZ2VuZXMgYXJlIHNob3duIGluIHNlcGFyYXRlIHRhYmxlLiIsCiAgIlRyYW5zY3JpcHQiLCAiVHJhbnNjcmlwdHMgaW52b2x2ZWQgaW4gdGhlIGV2ZW50LiBERUwvRFVQL0lOUyBldmVudHMgaW52b2x2aW5nIG1vcmUgdGhhbiAyIHRyYW5zY3JpcHRzIGFyZSBzaG93biBpbiBzZXBhcmF0ZSB0YWJsZS4iLAogICJFZmZlY3QiLCBnbHVlOjpnbHVlKCJTViBlZmZlY3QgKGJhc2VkIG9uICIsCiAgICAgICAgICAgICAgICAgICAgICAgIntodG1sdG9vbHM6OmEoaHJlZj0naHR0cDovL3NucGVmZi5zb3VyY2Vmb3JnZS5uZXQvU25wRWZmX21hbnVhbC5odG1sI2lucHV0JywgJ1NucEVmZiBFZmZlY3QgU2VxdWVuY2UgT250b2xvZ3knKX0iLAogICAgICAgICAgICAgICAgICAgICAgICIgLSBhYmJyZXZpYXRpb25zIGFyZSBzaG93biB1bmRlciB7aHRtbHRvb2xzOjphKGhyZWY9JyNzdi1zdW1tYXJ5JywgJ0RldGFpbHMnKX0gaW4gdGhlIEVmZmVjdHMgdGFibGUiKSwKICAiRGV0YWlsIiwgIlByaW9yaXRpc2F0aW9uIGRldGFpbCAoZnJvbSAnc2ltcGxlX3N2X2Fubm90YXRpb24nKSIsCiAgIlBsb2lkeSIsICJQbG9pZHkgb2YgdmFyaWFudCBmcm9tIFBVUlBMRSAocHVyaXR5IGFkanVzdGVkKSIsCiAgIkFGX1BVUlBMRSIsICJQVVJQTEUgQUYgYXQgZWFjaCBicmVha2VuZCBwcmVjZWRlZCBieSB0aGVpciBhdmVyYWdlIiwKICAiQUZfQlBJIiwgIkJQSSBBRiBhdCBlYWNoIGJyZWFrZW5kIHByZWNlZGVkIGJ5IHRoZWlyIGF2ZXJhZ2UiLAogICJDTiIsICJDb3B5IE51bWJlciBhdCBlYWNoIGJyZWFrZW5kIHByZWNlZGVkIGJ5IHRoZWlyIGF2ZXJhZ2UiLAogICJDTkMiLCAiQ29weSBOdW1iZXIgQ2hhbmdlIGF0IGVhY2ggYnJlYWtlbmQgcHJlY2VkZWQgYnkgdGhlaXIgYXZlcmFnZSIsCiAgIlNSX1BSX2FsdCIsICJOdW1iZXIgb2YgU3BsaXQgUmVhZHMgYW5kIFBhaXJlZCBSZWFkcyBzdXBwb3J0aW5nIHRoZSBhbHQgYWxsZWxlLCBmb3IgcmVhZHMgd2hlcmUgUChhbGxlbGV8cmVhZCk+MC45OTkiLAogICJTUl9QUl9yZWYiLCAiTnVtYmVyIG9mIFNwbGl0IFJlYWRzIGFuZCBQYWlyZWQgUmVhZHMgc3VwcG9ydGluZyB0aGUgcmVmIGFsbGVsZSwgZm9yIHJlYWRzIHdoZXJlIFAoYWxsZWxlfHJlYWQpPjAuOTk5IiwKICAiVHlwZSIsICJUeXBlIG9mIHN0cnVjdHVyYWwgdmFyaWFudCIsCiAgIlNTY29yZSIsICJTb21hdGljIHZhcmlhbnQgcXVhbGl0eSBzY29yZSIsCiAgIm50cngiLCAiTnVtYmVyIG9mIHRyYW5zY3JpcHRzIGZvciBnaXZlbiBldmVudCIsCiAgIm5nZW4iLCAiTnVtYmVyIG9mIGdlbmVzIGZvciBnaXZlbiBldmVudCIsCiAgIm5hbm4iLCAiTnVtYmVyIG9mIGFubm90YXRpb25zIGZvciBnaXZlbiBldmVudCIKKQpgYGAKCjxwPiZuYnNwOzwvcD4KCl9fUHJpb3JpdGlzYXRpb24gcHJvY2Vzc19fCgoxLiBBbm5vdGF0ZSB3aXRoIFtTbnBFZmZdKGh0dHA6Ly9zbnBlZmYuc291cmNlZm9yZ2UubmV0L1NucEVmZl9tYW51YWwuaHRtbCkgYmFzZWQgb24gRW5zZW1ibCBnZW5lIG1vZGVsCjIuIFN1YnNldCBhbm5vdGF0aW9ucyB0byBbQVBQUklTIHByaW5jaXBhbCB0cmFuc2NyaXB0c10oaHR0cDovL2FwcHJpcy5iaW9pbmZvLmNuaW8uZXMvIy8pCjMuIFByaW9yaXRpemUgdmFyaWFudHMgd2l0aCBbc2ltcGxlX3N2X2Fubm90YXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS92bGFkc2F2ZWxpZXYvc2ltcGxlX3N2X2Fubm90YXRpb24pCiAgIDEoaGlnaCktMihtb2RlcmF0ZSktMyhsb3cpLTQobm8gaW50ZXJlc3QpOgogICogZXhvbiBsb3NzCiAgICAgLSBvbiBwcmlvcml0aXNhdGlvbiBnZW5lIGxpc3QgKDEpCiAgICAgLSBvdGhlciAoMikKICAqIGdlbmVfZnVzaW9uCiAgICAgLSBwYWlyZWQgKGhpdHMgdHdvIGdlbmVzKQogICAgICAgIC0gb24gbGlzdCBvZiBrbm93biBwYWlycyAoMSkgKGN1cmF0ZWQgYnkgW0hNRl0oaHR0cHM6Ly9yZXNvdXJjZXMuaGFydHdpZ21lZGljYWxmb3VuZGF0aW9uLm5sKSkKICAgICAgICAtIG9uZSBnZW5lIGlzIGEga25vd24gcHJvbWlzY3VvdXMgZnVzaW9uIGdlbmUgKDEpIChjdXJhdGVkIGJ5IFtITUZdKGh0dHBzOi8vcmVzb3VyY2VzLmhhcnR3aWdtZWRpY2FsZm91bmRhdGlvbi5ubCkpCiAgICAgICAgLSBvbiBsaXN0IG9mIEZ1c2lvbkNhdGNoZXIga25vd24gcGFpcnMgKDIpCiAgICAgICAgLSBvdGhlcjoKICAgICAgICAgICAtIG9uZSBvciB0d28gZ2VuZXMgb24gcHJpb3JpdGlzYXRpb24gZ2VuZSBsaXN0ICgyKQogICAgICAgICAgIC0gbmVpdGhlciBnZW5lIG9uIHByaW9yaXRpc2F0aW9uIGdlbmUgbGlzdCAoMykKICAgICAtIHVucGFpcmVkIChoaXRzIG9uZSBnZW5lKQogICAgICAgICAtIG9uIHByaW9yaXRpc2F0aW9uIGdlbmUgbGlzdCAoMikKICAgICAgICAgLSBvdGhlcnMgKDMpCiAgKiB1cHN0cmVhbSBvciBkb3duc3RyZWFtCiAgICAgLSBvbiBwcmlvcml0aXNhdGlvbiBnZW5lIGxpc3QgZ2VuZXMgKDIpICAtIGUuZy4gb25lIGdlbmUgaXMgZ290IGludG8KICAgICAgIGNvbnRyb2wgb2YgYW5vdGhlciBnZW5lJ3MgcHJvbW90ZXIgYW5kIGdldCBvdmVyZXhwcmVzc2VkIChvbmNvZ2VuZSkgb3IgdW5kZXJleHByZXNzZWQgKHRzZ2VuZSkKICAqIExvRiBvciBISUdIIGltcGFjdCBpbiBhIHR1bW9yIHN1cHByZXNzb3IKICAgICAtIG9uIHByaW9yaXRpc2F0aW9uIGdlbmUgbGlzdCAoMikKICAgICAtIG90aGVyIFRTIGdlbmUgKDMpCiAgKiBvdGhlciAoNCkKCiogVXNlIFBVUlBMRSBjb3B5IG51bWJlciBjYWxsZXIgdG8gaW5mZXIgbW9yZSBTViBjYWxscyBmcm9tIGNvcHkgbnVtYmVyIHRyYW5zaXRpb25zIChtYXJrZWQgYXMgJ1BVUlBMRSBJbmZlcnJlZCcpCgpgYGB7ciBlZmZlY3RfYWJicmV2X3RhYn0KZWZmZWN0X2FiYnJldmlhdGlvbnMgJT4lCiAgdGliYmxlOjplbmZyYW1lKHZhbHVlID0gImFiYnJldmlhdGlvbiIpICU+JQogIGRwbHlyOjphcnJhbmdlKGFiYnJldmlhdGlvbikgJT4lCiAgZHBseXI6Om11dGF0ZShuYW1lID0ga2FibGVFeHRyYTo6Y2VsbF9zcGVjKG5hbWUsIGJvbGQgPSBUUlVFKSkgJT4lCiAga25pdHI6OmthYmxlKGVzY2FwZSA9IEZBTFNFKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIGthYmxlRXh0cmE6OnNjcm9sbF9ib3goaGVpZ2h0ID0gIjI1MHB4IikKYGBgCgo8L2RldGFpbHM+Cgo8cD4mbmJzcDs8L3A+CgojIyMgU3VtbWFyeQoKYGBge3Igc3Zfc3VtbWFyeSwgcmVzdWx0cz0nYXNpcyd9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl90aWVyX3ZzX3N2dHlwZSA8LSBmdW5jdGlvbigpIHsKICAgIGwgPC0gbGlzdCh1bm1lbHRlZCA9IHN2X3VubWVsdGVkICU+JSBkcGx5cjo6c2VsZWN0KFRpZXJUb3AsIFR5cGUpLAogICAgICAgICAgICAgIG1lbHRlZCA9IHN2X2FsbCAlPiUgZHBseXI6OnNlbGVjdChUaWVyLCBUeXBlKSkgJT4lCiAgICAgIHB1cnJyOjptYXAoZnVuY3Rpb24oeCkgYWRkbWFyZ2lucyh0YWJsZSh4LCB1c2VOQSA9ICdpZmFueScpKSkKCiAgICBjYXBfdW5tZWx0IDwtIGdsdWU6OmdsdWUoIlNWIHR5cGUgYnkge2h0bWx0b29sczo6c3Ryb25nKCd0b3AnKX0gdGllciB7aHRtbHRvb2xzOjpzdHJvbmcoJ2JlZm9yZScpfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIntodG1sdG9vbHM6OmJyKCl9YnJlYWtpbmcgZG93biBieSBhbm5vdGF0aW9uIikKICAgIGNhcF9tZWx0IDwtIGdsdWU6OmdsdWUoIlNWIHR5cGUgYnkge2h0bWx0b29sczo6c3Ryb25nKCdpbmRpdmlkdWFsJyl9IHRpZXIge2h0bWx0b29sczo6c3Ryb25nKCdhZnRlcicpfSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJ7aHRtbHRvb2xzOjpicigpfWJyZWFraW5nIGRvd24gYnkgYW5ub3RhdGlvbiIpCiAgICB1bm1lbHRlZCA8LSBrbml0cjo6a2FibGUobCR1bm1lbHRlZCwgZm9ybWF0ID0gImh0bWwiLCBjYXB0aW9uID0gY2FwX3VubWVsdCwgb3V0cHV0ID0gRkFMU0UpICU+JQogICAgICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiZmxvYXRfcmlnaHQiKQogICAgbWVsdGVkIDwtIGtuaXRyOjprYWJsZShsJG1lbHRlZCwgZm9ybWF0ID0gImh0bWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gY2FwX21lbHQsIG91dHB1dCA9IEZBTFNFKSAlPiUKICAgICAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImZsb2F0X3JpZ2h0IikKCiAgICBsaXN0KHVubWVsdGVkID0gdW5tZWx0ZWQsIG1lbHRlZCA9IG1lbHRlZCkKICB9CiAgY2F0KGMoJzx0YWJsZT48dHIgdmFsaWduPSJ0b3AiPjx0ZD4nLCBzdl90aWVyX3ZzX3N2dHlwZSgpJHVubWVsdGVkLCAnPC90ZD4nLCAnPHRkPicsIHN2X3RpZXJfdnNfc3Z0eXBlKCkkbWVsdGVkLCAnPC90ZD48L3RyPjwvdGFibGU+JyksIHNlcCA9ICcnKQp9IGVsc2UgewogIGNhdCgiTm8gU1ZzIGNhbGxlZC4iKQp9CmBgYAoKIyMjIFVubWVsdGVkIFZhcmlhbnRzIHsjc3YtdW5tZWx0ZWR9CgpgYGB7ciBzdnRhYl9yYXd9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdnRhYl9yYXcgPC0gc3ZfdW5tZWx0ZWQgJT4lCiAgICBkcGx5cjo6c2VsZWN0KC1hbm5vdGF0aW9uKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKFRpZXJUb3AsIHZhcm51bSkKCiAgc3Z0YWJfcmF3ZHQgPC0gc3Z0YWJfcmF3ICU+JQogICAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIsIGNsZWFyID0gRkFMU0UsIHBsYWluID0gVFJVRSksCiAgICAgICAgICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIGRpc3BsYXkgY29tcGFjdCIsCiAgICAgICAgICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsIGV4dGVuc2lvbnMgPSBjKCJTY3JvbGxlciIsICJCdXR0b25zIiwgIktleVRhYmxlIiksCiAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgIGNvbHVtbkRlZnMgPSBsaXN0KGxpc3QoY2xhc3NOYW1lID0gJ2R0LXJpZ2h0JywgdGFyZ2V0cyA9IGNvbF9pbmRfanMoc3Z0YWJfcmF3LCAiRW5kIikpKSwKICAgICAgICAgICAgICAgICAgICBzY3JvbGxlciA9IFRSVUUsIHNjcm9sbFkgPSA0MDAsIHNjcm9sbFggPSBUUlVFLCBhdXRvV2lkdGggPSBGQUxTRSwga2V5cyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IGMoJ2NzdicpLCBkb20gPSAnQmxmcnRpcCcpKSAlPiUKICAgIERUOjpmb3JtYXRDdXJyZW5jeSh+IFN0YXJ0LCBjdXJyZW5jeSA9ICIiLCBpbnRlcnZhbCA9IDMsIG1hcmsgPSAiLCIsIGRpZ2l0cyA9IDApCn0gZWxzZSB7CiAgc3Z0YWJfcmF3IDwtIE5VTEwKICBzdnRhYl9yYXdkdCA8LSBOVUxMCn0KYGBgCgo8ZGV0YWlscz4KPHN1bW1hcnk+RGVzY3JpcHRpb248L3N1bW1hcnk+CgpgYGB7cn0KaWYgKCFub19zdl9mb3VuZCkgewogIHN2X2RldGFpbF90YWJsZShzdnRhYl9yYXcpCn0gZWxzZSB7CiAgY2F0KCJObyBTVnMgY2FsbGVkLiIpCn0KYGBgCgo8L2RldGFpbHM+CgpgYGB7ciBzdnRhYl9yYXdkdH0KaWYgKCFub19zdl9mb3VuZCkgewogIHN2dGFiX3Jhd2R0Cn0gZWxzZSB7CiAgY2F0KCJObyBTVnMgY2FsbGVkLiIpCn0KYGBgCgojIyMgVHJhbnNsb2NhdGlvbnMgKEJORHMpIHsudGFic2V0IC50YWJzZXQtZmFkZSAjdHJhbnNsb2NhdGlvbnN9CgpgYGB7ciBzdnRhYl9CTkR9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9CTkQgPC0gc3ZfYWxsICU+JQogICAgZHBseXI6OmZpbHRlcihUeXBlID09ICJCTkQiKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobnJvdyA9IGRwbHlyOjpyb3dfbnVtYmVyKCksCiAgICAgICAgICAgICAgICAgIG5yb3cgPSBzcHJpbnRmKGdsdWU6OmdsdWUoIiUwe25jaGFyKG5yb3coLikpfWQiKSwgbnJvdykpICU+JQogICAgZHBseXI6OnNlbGVjdChucm93LCBkcGx5cjo6ZXZlcnl0aGluZygpKQoKICBzdl9CTkRfbWFpbiA8LSBzdl9CTkQgJT4lCiAgICBkcGx5cjo6c2VsZWN0KG5yb3csIHZhcm51bSwgVGllciwgQ2hyLCBTdGFydCwgRW5kLAogICAgICAgICAgICAgICAgICBJRCwgQk5EX0lELCBCTkRfbWF0ZSwKICAgICAgICAgICAgICAgICAgR2VuZXMsIEVmZmVjdCwgRGV0YWlsLCBTUl9QUl9hbHQsIFBsb2lkeSwgQUZfUFVSUExFKQoKICBzdl9CTkRfb3RoZXIgPC0gc3ZfQk5EICU+JQogICAgZHBseXI6OnNlbGVjdChucm93LCBBRl9CUEksIENOQywgQ04sIFNSX1BSX3JlZiwgU1Njb3JlLCBudHJ4LCBUcmFuc2NyaXB0KQoKICBzdl9CTkRfcHVycGxlIDwtIHN2X2FsbCAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoVHlwZSAlaW4lIGMoIlBVUlBMRV9pbmYiKSkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KFRpZXIsIENociwgU3RhcnQsIEVmZmVjdCwgRGV0YWlsLCBQbG9pZHksIENOLCBDTkMsIElEKQoKICBzdl9CTkRfbWFpbmR0IDwtIHN2X0JORF9tYWluICU+JQogICAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIsIGNsZWFyID0gRkFMU0UsIHBsYWluID0gVFJVRSksCiAgICAgICAgICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIGRpc3BsYXkgY29tcGFjdCIsCiAgICAgICAgICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsIGV4dGVuc2lvbnMgPSBjKCJTY3JvbGxlciIsICJCdXR0b25zIiwgIktleVRhYmxlIiksCiAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgIGNvbHVtbkRlZnMgPSBsaXN0KGxpc3QoY2xhc3NOYW1lID0gJ2R0LXJpZ2h0JywgdGFyZ2V0cyA9IGNvbF9pbmRfanMoc3Z0YWJfcmF3LCAiRW5kIikpKSwKICAgICAgICAgICAgICAgICAgICBzY3JvbGxlciA9IFRSVUUsIHNjcm9sbFkgPSA0MDAsIHNjcm9sbFggPSBUUlVFLCBhdXRvV2lkdGggPSBGQUxTRSwga2V5cyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IGMoJ2NzdicpLCBkb20gPSAnQmxmcnRpcCcpKSAlPiUKICAgIERUOjpmb3JtYXRDdXJyZW5jeSh+IFN0YXJ0LCBjdXJyZW5jeSA9ICIiLCBpbnRlcnZhbCA9IDMsIG1hcmsgPSAiLCIsIGRpZ2l0cyA9IDApCgogIHN2X0JORF9vdGhlcmR0IDwtIHN2X0JORF9vdGhlciAlPiUKICAgIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiLCBjbGVhciA9IEZBTFNFLCBwbGFpbiA9IFRSVUUpLAogICAgICAgICAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBkaXNwbGF5IGNvbXBhY3QiLAogICAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLCBleHRlbnNpb25zID0gYygiU2Nyb2xsZXIiLCAiQnV0dG9ucyIsICJLZXlUYWJsZSIpLAogICAgICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICBzY3JvbGxlciA9IFRSVUUsIHNjcm9sbFkgPSA0MDAsIHNjcm9sbFggPSBUUlVFLCBrZXlzID0gVFJVRSwgYXV0b1dpZHRoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IGMoJ2NzdicpLCBkb20gPSAnQmxmcnRpcCcpKQoKICBzdl9CTkRfcHVycGxlZHQgPC0gc3ZfQk5EX3B1cnBsZSAlPiUKICAgIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiLCBjbGVhciA9IEZBTFNFLCBwbGFpbiA9IFRSVUUpLAogICAgICAgICAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBkaXNwbGF5IGNvbXBhY3QiLAogICAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLCBleHRlbnNpb25zID0gYygiU2Nyb2xsZXIiLCAiQnV0dG9ucyIsICJLZXlUYWJsZSIpLAogICAgICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICBzY3JvbGxlciA9IFRSVUUsIHNjcm9sbFkgPSA0MDAsIHNjcm9sbFggPSBUUlVFLCBhdXRvV2lkdGggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjc3YnKSwKICAgICAgICAgICAgICAgICAgICBkb20gPSAnQmxmcnRpcCcpKSAlPiUKICAgIERUOjpmb3JtYXRDdXJyZW5jeSh+IFN0YXJ0LCBjdXJyZW5jeSA9ICIiLCBpbnRlcnZhbCA9IDMsIG1hcmsgPSAiLCIsIGRpZ2l0cyA9IDApCn0KYGBgCgojIyMjIE1haW4gQ29sdW1ucwoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKYGBge3J9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9kZXRhaWxfdGFibGUoc3ZfQk5EX21haW4pCn0gZWxzZSB7CiAgY2F0KCJObyBTVnMgY2FsbGVkLiIpCn0KYGBgCgo8L2RldGFpbHM+CgpgYGB7ciBzdl9CTkRfbWFpbmR0fQppZiAoIW5vX3N2X2ZvdW5kKSB7CiAgc3ZfQk5EX21haW5kdAp9IGVsc2UgewogIGNhdCgiTm8gU1ZzIGNhbGxlZC4iKQp9CgpgYGAKCiMjIyMgT3RoZXIgQ29sdW1ucwoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKYGBge3J9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9kZXRhaWxfdGFibGUoc3ZfQk5EX290aGVyKQp9IGVsc2UgewogIGNhdCgiTm8gU1ZzIGNhbGxlZC4iKQp9CmBgYAoKPC9kZXRhaWxzPgoKYGBge3Igc3ZfQk5EX290aGVyZHR9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9CTkRfb3RoZXJkdAp9IGVsc2UgewogIGNhdCgiTm8gU1ZzIGNhbGxlZC4iKQp9CmBgYAoKIyMjIyBQVVJQTEUgSW5mZXJyZWQKCjxkZXRhaWxzPgo8c3VtbWFyeT5EZXNjcmlwdGlvbjwvc3VtbWFyeT4KCmBgYHtyfQppZiAoIW5vX3N2X2ZvdW5kKSB7CiAgc3ZfZGV0YWlsX3RhYmxlKHN2X0JORF9wdXJwbGUpCn0gZWxzZSB7CiAgY2F0KCJObyBTVnMgY2FsbGVkLiIpCn0KYGBgCgo8L2RldGFpbHM+CgpgYGB7ciBzdl9CTkRfcHVycGxlZHR9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9CTkRfcHVycGxlZHQKfSBlbHNlIHsKICBjYXQoIk5vIFNWcyBjYWxsZWQuIikKfQpgYGAKCiMjIyBERUwvRFVQL0lOUyB7LnRhYnNldCAudGFic2V0LWZhZGUgI2RlbGR1cGluc30KCmBgYHtyIHN2dGFiX25vQk5EfQppZiAoIW5vX3N2X2ZvdW5kKSB7CiAgc3Zfbm9CTkQgPC0gc3ZfYWxsICU+JQogICAgZHBseXI6OmZpbHRlcighVHlwZSAlaW4lIGMoIkJORCIsICJQVVJQTEVfaW5mIikpICU+JQogICAgZHBseXI6Om11dGF0ZShucm93ID0gZHBseXI6OnJvd19udW1iZXIoKSwKICAgICAgICAgICAgICAgICAgbnJvdyA9IHNwcmludGYoZ2x1ZTo6Z2x1ZSgiJTB7bmNoYXIobnJvdyguKSl9ZCIpLCBucm93KSwKICAgICAgICAgICAgICAgICAgR2VuZXNfb3JpZ2luYWwgPSBHZW5lcywKICAgICAgICAgICAgICAgICAgVHJhbnNjcmlwdF9vcmlnaW5hbCA9IFRyYW5zY3JpcHQpICU+JQogICAgZHBseXI6OnNlbGVjdCgtSUQpCgogIG1heF9nZW5lcyA8LSAyCiAgbWF4X3RyYW5zY3JpcHRzIDwtIDIKCiAgc3Zfbm9CTkRfbWFpbiA8LSBzdl9ub0JORCAlPiUKICAgIGRwbHlyOjptdXRhdGUoR2VuZXMgPSBpZmVsc2UobmdlbiA+IG1heF9nZW5lcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2x1ZTo6Z2x1ZSgiTWFueSBHZW5lcyAoe25nZW59KSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5lcyksCiAgICAgICAgICAgICAgICAgIFRyYW5zY3JpcHQgPSBpZmVsc2UobnRyeCA+IG1heF90cmFuc2NyaXB0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbHVlOjpnbHVlKCJNYW55IFRyYW5zY3JpcHRzICh7bnRyeH0pIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhbnNjcmlwdCkpICU+JQogICAgZHBseXI6OnNlbGVjdChucm93LCB2YXJudW0sIFRpZXJUb3AsIFRpZXIsIFR5cGUsIENociwgU3RhcnQsIEVuZCwgRWZmZWN0LAogICAgICAgICAgICAgICAgICBHZW5lcywgVHJhbnNjcmlwdCwgRGV0YWlsLCBTUl9QUl9hbHQsIEFGX1BVUlBMRSkKCiAgc3Zfbm9CTkRfb3RoZXIgPC0gc3Zfbm9CTkQgJT4lCiAgICBkcGx5cjo6c2VsZWN0KHZhcm51bSwgUGxvaWR5LCBBRl9CUEksIENOQywgQ04sIFNSX1BSX3JlZiwgU1Njb3JlKSAlPiUKICAgIGRwbHlyOjpkaXN0aW5jdCgpCgogIHN2X25vQk5EX21hbnlnZW5lcyA8LSBzdl9ub0JORCAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobmdlbiA+IG1heF9nZW5lcykgJT4lCiAgICBkcGx5cjo6c2VsZWN0KG5yb3csIHZhcm51bSwgVGllciwgVHlwZSwgQ2hyLCBTdGFydCwgRW5kLAogICAgICAgICAgICAgICAgICBFZmZlY3QsIG5nZW4sIEdlbmVzID0gR2VuZXNfb3JpZ2luYWwpCgogIHN2X25vQk5EX21hbnl0eCA8LSBzdl9ub0JORCAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobnRyeCA+IG1heF90cmFuc2NyaXB0cykgJT4lCiAgICBkcGx5cjo6c2VsZWN0KG5yb3csIHZhcm51bSwgVGllciwgVHlwZSwgQ2hyLCBTdGFydCwgRW5kLAogICAgICAgICAgICAgICAgICBFZmZlY3QsIG50cngsIFRyYW5zY3JpcHQgPSBUcmFuc2NyaXB0X29yaWdpbmFsKQoKICBzdl9ub0JORF9tYWluZHQgPC0gc3Zfbm9CTkRfbWFpbiAlPiUKICAgIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiLCBjbGVhciA9IEZBTFNFLCBwbGFpbiA9IFRSVUUpLAogICAgICAgICAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBkaXNwbGF5IGNvbXBhY3QiLAogICAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLCBleHRlbnNpb25zID0gYygiQnV0dG9ucyIpLAogICAgICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICBjb2x1bW5EZWZzID0gbGlzdChsaXN0KGNsYXNzTmFtZSA9ICdkdC1yaWdodCcsIHRhcmdldHMgPSBjb2xfaW5kX2pzKHN2dGFiX3JhdywgIkVuZCIpKSksCiAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDIwLAogICAgICAgICAgICAgICAgICAgIGF1dG9XaWR0aCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjc3YnKSwgZG9tID0gJ0JsZnJ0aXAnKSkgJT4lCiAgICBEVDo6Zm9ybWF0Q3VycmVuY3kofiBTdGFydCwgY3VycmVuY3kgPSAiIiwgaW50ZXJ2YWwgPSAzLCBtYXJrID0gIiwiLCBkaWdpdHMgPSAwKQoKICBzdl9ub0JORF9vdGhlcmR0IDwtIHN2X25vQk5EX290aGVyICU+JQogICAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIsIGNsZWFyID0gRkFMU0UsIHBsYWluID0gVFJVRSksCiAgICAgICAgICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIGRpc3BsYXkgY29tcGFjdCIsCiAgICAgICAgICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsIGV4dGVuc2lvbnMgPSBjKCJCdXR0b25zIiksCiAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAyMCwKICAgICAgICAgICAgICAgICAgICBhdXRvV2lkdGggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnY3N2JyksCiAgICAgICAgICAgICAgICAgICAgZG9tID0gJ0JsZnJ0aXAnKSkKCiAgc3Zfbm9CTkRfbWFueWdlbmVzZHQgPC0gc3Zfbm9CTkRfbWFueWdlbmVzICU+JQogICAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIsIGNsZWFyID0gRkFMU0UsIHBsYWluID0gVFJVRSksCiAgICAgICAgICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIGRpc3BsYXkgY29tcGFjdCIsCiAgICAgICAgICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsIGV4dGVuc2lvbnMgPSBjKCJCdXR0b25zIiwgIktleVRhYmxlIiksCiAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgICAgICAgICAgIGNvbHVtbkRlZnMgPSBsaXN0KGxpc3QoY2xhc3NOYW1lID0gJ2R0LXJpZ2h0JywgdGFyZ2V0cyA9IGNvbF9pbmRfanMoc3Z0YWJfcmF3LCAiRW5kIikpKSwKICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTAsCiAgICAgICAgICAgICAgICAgICAgYXV0b1dpZHRoID0gRkFMU0UsIGtleXMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjc3YnKSwKICAgICAgICAgICAgICAgICAgICBkb20gPSAnQmxmcnRpcCcpKSAlPiUKICAgIERUOjpmb3JtYXRDdXJyZW5jeSh+IFN0YXJ0LCBjdXJyZW5jeSA9ICIiLCBpbnRlcnZhbCA9IDMsIG1hcmsgPSAiLCIsIGRpZ2l0cyA9IDApCgogIHN2X25vQk5EX21hbnl0eGR0IDwtIHN2X25vQk5EX21hbnl0eCAlPiUKICAgIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiLCBjbGVhciA9IEZBTFNFLCBwbGFpbiA9IFRSVUUpLAogICAgICAgICAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBkaXNwbGF5IGNvbXBhY3QiLAogICAgICAgICAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLCBleHRlbnNpb25zID0gYygiQnV0dG9ucyIsICJLZXlUYWJsZSIpLAogICAgICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdCgKICAgICAgICAgICAgICAgICAgICBjb2x1bW5EZWZzID0gbGlzdChsaXN0KGNsYXNzTmFtZSA9ICdkdC1yaWdodCcsIHRhcmdldHMgPSBjb2xfaW5kX2pzKHN2dGFiX3JhdywgIkVuZCIpKSksCiAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwLAogICAgICAgICAgICAgICAgICAgIGF1dG9XaWR0aCA9IEZBTFNFLCBrZXlzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnY3N2JyksCiAgICAgICAgICAgICAgICAgICAgZG9tID0gJ0JsZnJ0aXAnKSkgJT4lCiAgICBEVDo6Zm9ybWF0Q3VycmVuY3kofiBTdGFydCwgY3VycmVuY3kgPSAiIiwgaW50ZXJ2YWwgPSAzLCBtYXJrID0gIiwiLCBkaWdpdHMgPSAwKQp9CmBgYAoKIyMjIyBNYWluIENvbHVtbnMKCjxkZXRhaWxzPgo8c3VtbWFyeT5EZXNjcmlwdGlvbjwvc3VtbWFyeT4KCmBgYHtyfQppZiAoIW5vX3N2X2ZvdW5kKSB7CiAgc3ZfZGV0YWlsX3RhYmxlKHN2X25vQk5EX21haW4pCn0gZWxzZSB7CiAgY2F0KCJObyBTVnMgY2FsbGVkLiIpCn0KYGBgCgo8L2RldGFpbHM+CgpgYGB7ciBzdl9ub0JORF9tYWluZHR9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9ub0JORF9tYWluZHQKfSBlbHNlIHsKICBjYXQoIk5vIFNWcyBjYWxsZWQuIikKfQpgYGAKCiMjIyMgT3RoZXIgQ29sdW1ucwoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKYGBge3J9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9kZXRhaWxfdGFibGUoc3Zfbm9CTkRfb3RoZXIpCn0gZWxzZSB7CiAgY2F0KCJObyBTVnMgY2FsbGVkLiIpCn0KYGBgCgo8L2RldGFpbHM+CgpgYGB7ciBzdl9ub0JORDJfZHR9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9ub0JORF9vdGhlcmR0Cn0gZWxzZSB7CiAgY2F0KCJObyBTVnMgY2FsbGVkLiIpCn0KYGBgCgojIyMjIE1hbnkgR2VuZXMKCjxkZXRhaWxzPgo8c3VtbWFyeT5EZXNjcmlwdGlvbjwvc3VtbWFyeT4KCmBgYHtyfQppZiAoIW5vX3N2X2ZvdW5kKSB7CiAgc3ZfZGV0YWlsX3RhYmxlKHN2X25vQk5EX21hbnlnZW5lcykKfSBlbHNlIHsKICBjYXQoIk5vIFNWcyBjYWxsZWQuIikKfQpgYGAKCjwvZGV0YWlscz4KCmBgYHtyIHN2X25vQk5EX21hbnlnZW5lc2R0fQppZiAoIW5vX3N2X2ZvdW5kKSB7CiAgc3Zfbm9CTkRfbWFueWdlbmVzZHQKfSBlbHNlIHsKICBjYXQoIk5vIFNWcyBjYWxsZWQuIikKfQpgYGAKCiMjIyMgTWFueSBUcmFuc2NyaXB0cwoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKYGBge3J9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9kZXRhaWxfdGFibGUoc3Zfbm9CTkRfbWFueXR4KQp9IGVsc2UgewogIGNhdCgiTm8gU1ZzIGNhbGxlZC4iKQp9CmBgYAoKPC9kZXRhaWxzPgoKYGBge3Igc3Zfbm9CTkRfbWFueXR4ZHR9CmlmICghbm9fc3ZfZm91bmQpIHsKICBzdl9ub0JORF9tYW55dHhkdAp9IGVsc2UgewogIGNhdCgiTm8gU1ZzIGNhbGxlZC4iKQp9CmBgYAoKIyMgQ29weSBOdW1iZXIgVmFyaWFudHMgeyNjbnYtcWN9ClRoZSBwdXJpdHkgYW5kIHBsb2lkeSBlc3RpbWF0b3IKW1BVUlBMRV0oaHR0cHM6Ly9naXRodWIuY29tL2hhcnR3aWdtZWRpY2FsL2htZnRvb2xzL3RyZWUvbWFzdGVyL3B1cml0eS1wbG9pZHktZXN0aW1hdG9yKQppcyB1c2VkIHRvIGdlbmVyYXRlIGEgY29weSBudW1iZXIgcHJvZmlsZSBmb3IgdGhlIHNvbWF0aWMgc2FtcGxlLgoKIyMjIFFDLCBQdXJpdHkgYW5kIFBsb2lkeSBTdW1tYXJ5CgpQVVJQTEUgb3V0cHV0cyBhIFFDIHN0YXR1cyBhbG9uZyB3aXRoIGEgc3VtbWFyeQpmb3IgdGhlIGluZmVycmVkIHB1cml0eSBhbmQgcGxvaWR5IG9mIHRoZSBzb21hdGljIHNhbXBsZS4KQSBmYWlsZWQgUUMgc3RhdHVzIGNhbiBiZSBhdHRyaWJ1dGVkIHRvIHNldmVyYWwgZmFjdG9ycwooc2VlIGBEZXNjcmlwdGlvbmAgYmVsb3cpLgoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKX19RQyBTdGF0dXNfXwoKVGhlIFFDIFN0YXR1cyBmaWVsZCByZWZsZWN0cyBob3cgd2UgaGF2ZSBkZXRlcm1pbmVkIHRoZSBwdXJpdHkgb2YgdGhlIHNhbXBsZToKCiogYE5PUk1BTGAgLSBQVVJQTEUgZml0IHRoZSBwdXJpdHkgdXNpbmcgQ09CQUxUIGFuZCBBTUJFUiBvdXRwdXQuCiogYEhJR0hMWV9ESVBMT0lEYCAtIFRoZSBmaXR0ZWQgcHVyaXR5IHNvbHV0aW9uIGlzIGhpZ2hseSBkaXBsb2lkICg+IDk1JSkKICB3aXRoIGEgbGFyZ2UgcmFuZ2Ugb2YgcG90ZW50aWFsIHNvbHV0aW9ucywgYnV0IHNvbWF0aWMgdmFyaWFudHMgYXJlIHVuYWJsZSB0bwogIGhlbHAgZWl0aGVyIGJlY2F1c2UgdGhleSB3ZXJlIG5vdCBzdXBwbGllZCBvciBiZWNhdXNlIHRoZWlyIGltcGxpZWQgcHVyaXR5IHdhcyB0b28gbG93LgoqIGBTT01BVElDYCAtIFNvbWF0aWMgdmFyaWFudHMgaGF2ZSBpbXByb3ZlZCB0aGUgb3RoZXJ3aXNlIGhpZ2hseSBkaXBsb2lkIHNvbHV0aW9uLgoqIGBOT19UVU1PUmAgLSBQVVJQTEUgZmFpbGVkIHRvIGZpbmQgYW55IGFuZXVwbG9pZHkgYW5kIHNvbWF0aWMgdmFyaWFudHMgd2VyZQogIHN1cHBsaWVkIGJ1dCB0aGVyZSB3ZXJlIGZld2VyIHRoYW4gMzAwIHdpdGggb2JzZXJ2ZWQgVkFGID4gMC4xLgoKX19RQyBGYWlsdXJlX18KClRoZXJlIGFyZSBzZXZlcmFsIHJlYXNvbnMgUFVSUExFIG1heSBjbGFzc2lmeSBhIHNhbXBsZSBhcyBmYWlsZWQ6CgoqIGBGQUlMX1NFR01FTlRgOiBtb3JlIHRoYW4gMjIwIGNvcHkgbnVtYmVyIHNlZ21lbnRzIF9fbm90X18gc3VwcG9ydGVkIGF0IGVpdGhlciBlbmQKICBieSBTViBicmVha3BvaW50cy4gSW5kaWNhdGVzIHNhbXBsZXMgd2l0aCBleHRyZW1lIEdDIGJpYXMsIHdpdGggZGlmZmVyZW5jZXMKICBpbiBkZXB0aCBvZiA+PSAxMHggYmV0d2VlbiBoaWdoIGFuZCBsb3cgR0MgcmVnaW9ucy4gR0Mgbm9ybWFsaXNhdGlvbiBpcwogIHVucmVsaWFibGUgd2hlbiB0aGUgY29ycmVjdGlvbnMgYXJlIHNvIGV4dHJlbWUgc28gaXQgaXMgcmVjb21tZW5kZWQgdG8gZmFpbAogIHRoZSBzYW1wbGUgKGNvbmNlcm5zIHdpdGggbWlzY2FsbGVkIGRlbGV0aW9ucyBvciBhbXBsaWZpY2F0aW9ucyBvciBoYXZlCiAgcG9vciBzZW5zaXRpdml0eSBpbiBoaWdoIEdDIHJlZ2lvbnMuCiogYE5PX1RVTU9SYDogbm8gYW5ldXBsb2lkeSBmb3VuZCBhbmQgdGhlIG51bWJlciBvZiBzb21hdGljIFNOVnMgZm91bmQgaXMKICBsZXNzIHRoYW4gMSwwMDAKKiBgTUlOX1BVUklUWWA6IGZpdHRlZCBwdXJpdHkgPCAyMCUKKiBgRkFJTF9ERUxFVEVEX0dFTkVTYDogbW9yZSB0aGFuIDI4MCBkZWxldGVkIGdlbmVzLiBUaGlzIFFDIHN0ZXAgd2FzIGFkZGVkCiAgYWZ0ZXIgb2JzZXJ2aW5nIHRoYXQgaW4gYSBoYW5kZnVsIG9mIHNhbXBsZXMgd2l0aCBoaWdoIE1CIHNjYWxlIHBvc2l0aXZlIEdDCiAgYmlhcyB3ZSBzb21ldGltZXMgc3lzdGVtYXRpY2FsbHkgdW5kZXJlc3RpbWF0ZSB0aGUgY29weSBudW1iZXIgaW4gaGlnaCBHQwogIHJlZ2lvbnMuIFRoaXMgY2FuIGxlYWQgdXMgdG8gaW5jb3JyZWN0bHkgaW5mZXIgaG9tb3p5Z291cyBsb3NzIG9mIGVudGlyZQogIGNocm9tb3NvbWVzLCBwYXJ0aWN1bGFybHkgb24gY2hyb21vc29tZXMgMTcgYW5kIDE5LgoqIGBGQUlMX0dFTkRFUmA6IGlmIHRoZSBBTUJFUiBhbmQgQ09CQUxUIGluZmVycmVkIGdlbmRlcnMgYXJlIGluY29uc2lzdGVudAogIHRoZW4gdGhlIENPQkFMVCBvbmUgaXMgdXNlZCBidXQgdGhlIHNhbXBsZSBpcyBmYWlsZWQuCgo8L2RldGFpbHM+Cgo8cD4mbmJzcDs8L3A+CgpgYGB7ciBwdXJwbGVfcWNfc3VtbWFyeX0KcHVycGxlX3FjX3N1bW1hcnkgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIFZhcmlhYmxlID0ga2FibGVFeHRyYTo6Y2VsbF9zcGVjKFZhcmlhYmxlLCBib2xkID0gVFJVRSksCiAgICB2YWx1ZSA9IGthYmxlRXh0cmE6OmNlbGxfc3BlYyh2YWx1ZSwgYm9sZCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID09ICJQQVNTIiB+ICJncmVlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJGQUlMIiwgdmFsdWUpIH4gInJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID09ICJGRU1BTEUiIH4gInB1cnBsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID09ICJNQUxFIiB+ICJibHVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPT0gIk1BTEVfS0xJTkVGRUxURVIiIH4gInJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID09ICJUUlVFIiB+ICJncmVlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID09ICJGQUxTRSIgfiAicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJibGFjayIpKSkgJT4lCiAga25pdHI6OmthYmxlKGVzY2FwZSA9IEZBTFNFKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKIyMjIFVNQ0NSIEdlbmUgQ05WIENhbGxzIHsjY252LWdlbmV9Cgo8ZGV0YWlscz4KPHN1bW1hcnk+RGVzY3JpcHRpb248L3N1bW1hcnk+CgpQVVJQTEUgY29weSBudW1iZXIgYWx0ZXJhdGlvbnMgaW4gdGhlIFVNQ0NSIENhbmNlciBHZW5lIHBhbmVsICh+MSwyMDAgZ2VuZXMpIC0gZGVzY3JpcHRpb24KaXMgZnJvbSA8aHR0cHM6Ly9naXRodWIuY29tL2hhcnR3aWdtZWRpY2FsL2htZnRvb2xzL2Jsb2IvbWFzdGVyL3B1cml0eS1wbG9pZHktZXN0aW1hdG9yL1JFQURNRS5tZCNnZW5lLWNvcHktbnVtYmVyLWZpbGU+CgpgYGB7ciBwdXJwbGVfZ2VuZV9jbnZfZGVzY3JpcHRpb259CmRwbHlyOjp0cmliYmxlKAogIH5Db2x1bW4sIH5EZXNjcmlwdGlvbiwKICAiZ2VuZSIsICJOYW1lIG9mIGdlbmUiLAogICJtaW5DTi9tYXhDTiIsICJNaW4vTWF4IGNvcHkgbnVtYmVyIGZvdW5kIGluIGdlbmUgZXhvbnMiLAogICJjaHJvbS9zdGFydC9lbmQiLCAiQ2hyb21vc29tZS9zdGFydC9lbmQgbG9jYXRpb24gb2YgZ2VuZSB0cmFuc2NyaXB0IiwKICAiY2hyQmFuZCIsICJDaHJvbW9zb21lIGJhbmQgb2YgdGhlIGdlbmUiLAogICJvbmNvX29yX3RzIiwgIm9uY29nZW5lICgnb25jb2dlbmUnKSwgdHVtb3Igc3VwcHJlc3NvciAoJ3RzZ2VuZScpLCBvciBib3RoICgnb25jbyt0cycpLCBhcyByZXBvcnRlZCBieSBbQ2FuY2VybWluZV0oaHR0cHM6Ly9naXRodWIuY29tL2pha2VsZXZlci9jYW5jZXJtaW5lKSIsCiAgInRyYW5zY3JpcHRJRCIsICJFbnNlbWJsIHRyYW5zY3JpcHQgSUQgKGRvdCB2ZXJzaW9uKSIsCiAgIm1pbk1pbm9yQWxsZWxlUGxvaWR5IiwgIk1pbmltdW0gYWxsZWxlIHBsb2lkeSBmb3VuZCBvdmVyIHRoZSBnZW5lIGV4b25zIC0gdXNlZnVsIGZvciBpZGVudGlmeWluZyBMT0ggZXZlbnRzIiwKICAic29tUmVnIChzb21hdGljUmVnaW9ucykiLCAiQ291bnQgb2Ygc29tYXRpYyBjb3B5IG51bWJlciByZWdpb25zIHRoaXMgZ2VuZSBzcGFucyIsCiAgImdlcm1EZWxSZWcgKGdlcm1saW5lSG9tRGVsZXRpb25SZWdpb25zIC8gZ2VybWxpbmVIZXRUb0hvbURlbGV0aW9uUmVnaW9ucykiLCAiTnVtYmVyIG9mIHJlZ2lvbnMgc3Bhbm5lZCBieSB0aGlzIGdlbmUgdGhhdCBhcmUgKGhvbW96eWdvdXNseSBkZWxldGVkIGluIHRoZSBnZXJtbGluZSAvIGJvdGggaGV0ZXJvenlnb3VzbHkgZGVsZXRlZCBpbiB0aGUgZ2VybWxpbmUgYW5kIGhvbW96eWdvdXNseSBkZWxldGVkIGluIHRoZSB0dW1vcikiLAogICJtaW5SZWcgKG1pblJlZ2lvbnMpIiwgIk51bWJlciBvZiBzb21hdGljIHJlZ2lvbnMgaW5zaWRlIHRoZSBnZW5lIHRoYXQgc2hhcmUgdGhlIG1pbiBjb3B5IG51bWJlciIsCiAgIm1pblJlZ1N0YXJ0RW5kIiwgIlN0YXJ0L0VuZCBiYXNlIG9mIHRoZSBjb3B5IG51bWJlciByZWdpb24gb3ZlcmxhcHBpbmcgdGhlIGdlbmUgd2l0aCB0aGUgbWluaW11bSBjb3B5IG51bWJlciIsCiAgIm1pblJlZ1N1cHBvcnRTdGFydEVuZE1ldGhvZCIsICJTdGFydC9lbmQgc3VwcG9ydCBvZiB0aGUgQ04gcmVnaW9uIG92ZXJsYXBwaW5nIHRoZSBnZW5lIHdpdGggdGhlIG1pbiBDTiAocGx1cyBkZXRlcm1pbmF0aW9uIG1ldGhvZCkiCikgJT4lCiAgZHBseXI6Om11dGF0ZSgKICAgIENvbHVtbiA9IGthYmxlRXh0cmE6OmNlbGxfc3BlYyhDb2x1bW4sIGJvbGQgPSBUUlVFKSkgJT4lCiAga25pdHI6OmthYmxlKGVzY2FwZSA9IEZBTFNFKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIGthYmxlRXh0cmE6OnNjcm9sbF9ib3goaGVpZ2h0ID0gIjIwMHB4IikKYGBgCgo8L2RldGFpbHM+Cgo8cD4mbmJzcDs8L3A+CgpgYGB7ciBwdXJwbGVfZ2VuZV9jbnZfdGFifQpwdXJwbGVfZ2VuZV9jbnYgJT4lCiAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIsIGNsZWFyID0gRkFMU0UsIHBsYWluID0gVFJVRSksCiAgICAgICAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBkaXNwbGF5IGNvbXBhY3QiLAogICAgICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwgZXh0ZW5zaW9ucyA9IGMoIlNjcm9sbGVyIiwgIkJ1dHRvbnMiLCAiS2V5VGFibGUiKSwKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbGVyID0gVFJVRSwgc2Nyb2xsWSA9IDQwMCwgc2Nyb2xsWCA9IFRSVUUsIGF1dG9XaWR0aCA9IFRSVUUsIGtleXMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IGMoJ2NzdicsICdleGNlbCcpLCBkb20gPSAnQmZydGlwJykpICU+JQogIERUOjpmb3JtYXRDdXJyZW5jeSh+IHN0YXJ0ICsgZW5kLCBjdXJyZW5jeSA9ICIiLCBpbnRlcnZhbCA9IDMsIG1hcmsgPSAiLCIsIGRpZ2l0cyA9IDApICU+JQogIERUOjpmb3JtYXRSb3VuZCh+IG1pbkNOICsgbWF4Q04sIGRpZ2l0cyA9IDEpCmBgYAoKIyMjIEdlbm9tZS13aWRlIENOViBTZWdtZW50cyB7I2Nudi1zZWdzfQoKPGRldGFpbHM+CjxzdW1tYXJ5PkRlc2NyaXB0aW9uPC9zdW1tYXJ5PgoKUFVSUExFIG91dHB1dHMgYSBmaWxlIHdpdGggdGhlIGNvcHkgbnVtYmVyIHByb2ZpbGUgb2YgYWxsIGNvbnRpZ3VvdXMgc2VnbWVudHMKb2YgdGhlIHR1bW9yIHNhbXBsZToKClBVUlBMRSBjb3B5IG51bWJlciBwcm9maWxlIG9mIGFsbCAoY29udGlndW91cykgc2VnbWVudHMgb2YgdGhlIHR1bW9yIHNhbXBsZSAtIGRlc2NyaXB0aW9uCmlzIGZyb20gPGh0dHBzOi8vZ2l0aHViLmNvbS9oYXJ0d2lnbWVkaWNhbC9obWZ0b29scy9ibG9iL21hc3Rlci9wdXJpdHktcGxvaWR5LWVzdGltYXRvci9SRUFETUUubWQjY29weS1udW1iZXItZmlsZT4KCgpgYGB7ciBwdXJwbGVfc2VnX2Rlc2NyaXB0aW9ufQpkcGx5cjo6dHJpYmJsZSgKICB+Q29sdW1uLCB+RGVzY3JpcHRpb24sCiAgIkNoci9TdGFydC9FbmQiLCAiQ29vcmRpbmF0ZXMgb2YgY29weSBudW1iZXIgc2VnbWVudCIsCiAgIkNOIiwgIkZpdHRlZCBhYnNvbHV0ZSBjb3B5IG51bWJlciBvZiBzZWdtZW50IGFkanVzdGVkIGZvciBwdXJpdHkgYW5kIHBsb2lkeSIsCiAgIlBsb2lkeSBNaW4rTWFqIiwgIlBsb2lkeSBvZiBtaW5vciArIG1ham9yIGFsbGVsZSBhZGp1c3RlZCBmb3IgcHVyaXR5IiwKICAiQkFGIiwgIlR1bW9yIEJBRiBhZnRlciBhZGp1c3RlZCBmb3IgcHVyaXR5IGFuZCBwbG9pZHkiLAogICJCYWZDb3VudCIsICJDb3VudCBvZiBBTUJFUiBiYWYgcG9pbnRzIGNvdmVyZWQgYnkgdGhpcyBzZWdtZW50IiwKICAiU3RhcnQvRW5kIFNlZ1N1cHBvcnQiLCAiVHlwZSBvZiBTViBzdXBwb3J0IGZvciB0aGUgQ04gYnJlYWtwb2ludCBhdCBzdGFydC9lbmQgb2YgcmVnaW9uLiBBbGxvd2VkIHZhbHVlczogQ0VOVFJPTUVSRSwgVEVMT01FUkUsIElOViwgREVMLCBEVVAsIEJORCAodHJhbnNsb2NhdGlvbiksIFNHTCAoc2luZ2xlIGJyZWFrZW5kIFNWIHN1cHBvcnQpLCBOT05FIChubyBTViBzdXBwb3J0IGZvciBDTiBicmVha3BvaW50KSwgTVVMVCAobXVsdGlwbGUgU1Ygc3VwcG9ydCBhdCBleGFjdCBicmVha3BvaW50KSIsCiAgIk1ldGhvZCIsICJNZXRob2QgdXNlZCB0byBkZXRlcm1pbmUgdGhlIENOIG9mIHRoZSByZWdpb24uIEFsbG93ZWQgdmFsdWVzOiBCQUZfV0VJR0hURUQgKGF2ZyBvZiBhbGwgZGVwdGggd2luZG93cyBmb3IgdGhlIHJlZ2lvbiksIFNUUlVDVFVSQUxfVkFSSUFOVCAoaW5mZXJyZWQgdXNpbmcgcGxvaWR5IG9mIGZsYW5raW5nIFNWcyksIExPTkdfQVJNIChpbmZlcnJlZCBmcm9tIHRoZSBsb25nIGFybSksIEdFUk1MSU5FX0FNUExJRklDQVRJT04gKGluZmVycmVkIHVzaW5nIHNwZWNpYWwgbG9naWMgdG8gaGFuZGxlIHJlZ2lvbnMgb2YgZ2VybWxpbmUgYW1wbGlmaWNhdGlvbikiLAogICJ3aW5kb3dDb3VudCIsICJDb3VudCBvZiBDT0JBTFQgd2luZG93cyBjb3ZlcmVkIGJ5IHRoaXMgc2VnbWVudCIsCiAgIkdDIiwgIlByb3BvcnRpb24gb2Ygc2VnbWVudCB0aGF0IGlzIEcgb3IgQyIpICU+JQogIGRwbHlyOjptdXRhdGUoCiAgICBDb2x1bW4gPSBrYWJsZUV4dHJhOjpjZWxsX3NwZWMoQ29sdW1uLCBib2xkID0gVFJVRSkpICU+JQogIGtuaXRyOjprYWJsZShlc2NhcGUgPSBGQUxTRSkgJT4lCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICBrYWJsZUV4dHJhOjpzY3JvbGxfYm94KGhlaWdodCA9ICIyMDBweCIpCmBgYAoKPC9kZXRhaWxzPgoKPHA+Jm5ic3A7PC9wPgoKYGBge3IgcHVycGxlX2dsb2JhbF9jbnZfdGFifQpwdXJwbGVfZ2xvYmFsX2NudiAlPiUKICBkcGx5cjo6bXV0YXRlKENociA9IGFzLmZhY3RvcihgY2hyb21vc29tZWApLAogICAgICAgICAgICAgICAgbWlub3JBbGxlbGVQbG9pZHkgPSByb3VuZChtaW5vckFsbGVsZVBsb2lkeSwgMSksCiAgICAgICAgICAgICAgICBtYWpvckFsbGVsZVBsb2lkeSA9IHJvdW5kKG1ham9yQWxsZWxlUGxvaWR5LCAxKSwKICAgICAgICAgICAgICAgIGBQbG9pZHkgTWluK01hamAgPSBwYXN0ZTAobWlub3JBbGxlbGVQbG9pZHksICIrIiwgbWFqb3JBbGxlbGVQbG9pZHkpLAogICAgICAgICAgICAgICAgY29weU51bWJlciA9IHJvdW5kKGNvcHlOdW1iZXIsIDEpLAogICAgICAgICAgICAgICAgYmFmQWRqID0gcm91bmQoYmFmLCAyKSwKICAgICAgICAgICAgICAgIGdjQ29udGVudCA9IHJvdW5kKGdjQ29udGVudCwgMiksCiAgICAgICAgICAgICAgICBgU3RhcnQvRW5kIFNlZ1N1cHBvcnRgID0gcGFzdGUwKHNlZ21lbnRTdGFydFN1cHBvcnQsICItIiwgc2VnbWVudEVuZFN1cHBvcnQpLAogICAgICAgICAgICAgICAgYEJBRiAoY291bnQpYCA9IHBhc3RlMChiYWZBZGosICIgKCIsIGJhZkNvdW50LCAiKSIpLAogICAgICAgICAgICAgICAgYEdDICh3aW5kb3dDb3VudClgID0gcGFzdGUwKGdjQ29udGVudCwgIiAoIiwgZGVwdGhXaW5kb3dDb3VudCwgIikiKSkgJT4lCiAgZHBseXI6OnNlbGVjdChDaHIsIFN0YXJ0ID0gc3RhcnQsIEVuZCA9IGVuZCwgQ04gPSBjb3B5TnVtYmVyLCBgUGxvaWR5IE1pbitNYWpgLAogICAgICAgICAgICAgICAgYFN0YXJ0L0VuZCBTZWdTdXBwb3J0YCwgTWV0aG9kID0gbWV0aG9kLCBgQkFGIChjb3VudClgLCBgR0MgKHdpbmRvd0NvdW50KWApICU+JQogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiLCBjbGVhciA9IEZBTFNFLCBwbGFpbiA9IFRSVUUpLAogICAgICAgICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgZGlzcGxheSBjb21wYWN0IiwKICAgICAgICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsIGV4dGVuc2lvbnMgPSBjKCJTY3JvbGxlciIsICJCdXR0b25zIiwgIktleVRhYmxlIiksCiAgICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdChzY3JvbGxlciA9IFRSVUUsIHNjcm9sbFkgPSA0MDAsIHNjcm9sbFggPSBUUlVFLCBhdXRvV2lkdGggPSBUUlVFLCBrZXlzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjc3YnLCAnZXhjZWwnKSwgZG9tID0gJ0JmcnRpcCcpKSAlPiUKICBEVDo6Zm9ybWF0Q3VycmVuY3kofiBTdGFydCArIEVuZCwgY3VycmVuY3kgPSAiIiwgaW50ZXJ2YWwgPSAzLCBtYXJrID0gIiwiLCBkaWdpdHMgPSAwKQpgYGAKCiMjIyBQVVJQTEUgQ2hhcnRzIHsudGFic2V0IC50YWJzZXQtZmFkZSAjcHVycGxlLWNoYXJ0c30KUFVSUExFIGdlbmVyYXRlcyBjaGFydHMgZm9yIHN1bW1hcmlzaW5nIHR1bW9yIHNhbXBsZSBjaGFyYWN0ZXJpc3RpY3MuCkRlc2NyaXB0aW9uIGlzIGZyb20gdGhlIFtQVVJQTEUgZG9jc10oaHR0cHM6Ly9naXRodWIuY29tL2hhcnR3aWdtZWRpY2FsL2htZnRvb2xzL3RyZWUvbWFzdGVyL3B1cml0eS1wbG9pZHktZXN0aW1hdG9yI2NoYXJ0cykuCgojIyMjIENvcHkgbnVtYmVyIC8gTWlub3IgYWxsZWxlIHBsb2lkeQpUaGUgZm9sbG93aW5nIGZpZ3VyZXMgc2hvdyB0aGUgQU1CRVIgQkFGIGNvdW50IHdlaWdodGVkIGRpc3RyaWJ1dGlvbiBvZgpjb3B5IG51bWJlciBhbmQgbWlub3IgYWxsZWxlIHBsb2lkeSB0aHJvdWdob3V0IHRoZSBmaXR0ZWQgc2VnbWVudHMuCkNvcHkgbnVtYmVycyBhcmUgYnJva2VuIGRvd24gYnkgY29sb3VyIGludG8gdGhlaXIgcmVzcGVjdGl2ZSBtaW5vcgphbGxlbGUgcGxvaWR5IChNQVApIHdoaWxlIHRoZSBtaW5vciBhbGxlbGUgcGxvaWR5IGZpZ3VyZSBpcyBicm9rZW4KZG93biBieSBjb3B5IG51bWJlci4KCmBgYHtyIHB1cnBsZV9wbG90X2NvcHludW1iZXIsIG91dC53aWR0aD0iNDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoYyhmaWxlLnBhdGgoaW1nX2RpciwgcGFzdGUwKHBhcmFtcyRiYXRjaF9uYW1lLCAnLmNvcHludW1iZXIucG5nJykpLAogICAgICAgICAgICAgICAgICAgICAgICBmaWxlLnBhdGgoaW1nX2RpciwgcGFzdGUwKHBhcmFtcyRiYXRjaF9uYW1lLCAnLm1hcC5wbmcnKSkpKQpgYGAKCiMjIyMgUmFpbmZhbGwKSWYgYSBzb21hdGljIHZhcmlhbnQgVkNGIGhhcyBiZWVuIHN1cHBsaWVkLCBhIGZpZ3VyZSB3aWxsIGJlIHByb2R1Y2VkCnNob3dpbmcgdGhlIHNvbWF0aWMgdmFyaWFudCBwbG9pZHkgYnJva2VuIGRvd24gYnkgY29weSBudW1iZXIgYXMgd2VsbAphcyBhIHJhaW5mYWxsIHBsb3Qgd2l0aCBrYXRhZWdpcyBjbHVzdGVycyBoaWdobGlnaHRlZCBpbiBncmV5LgoKYGBge3IgcHVycGxlX3Bsb3Rfc29tYXRpYywgb3V0LndpZHRoPSI0MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhmaWxlLnBhdGgoaW1nX2RpciwgcGFzdGUwKHBhcmFtcyRiYXRjaF9uYW1lLCAnLnNvbWF0aWMucG5nJykpKQpgYGAKCmBgYHtyIHB1cnBsZV9wbG90X3NvbWF0aWNyYWluZmFsbCwgb3V0LndpZHRoPSI5MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhmaWxlLnBhdGgoaW1nX2RpciwgcGFzdGUwKHBhcmFtcyRiYXRjaF9uYW1lLCAnLnNvbWF0aWMucmFpbmZhbGwucG5nJykpKQpgYGAKCiMjIyMgUHVyaXR5L3Bsb2lkeQpUaGUgZm9sbG93aW5nICdzdW5yaXNlJyBjaGFydCBzaG93cyB0aGUgcmFuZ2Ugb2Ygc2NvcmVzIG9mIGFsbCBleGFtaW5lZCBzb2x1dGlvbnMgb2YKcHVyaXR5IGFuZCBwbG9pZHkuIENyb3NzaGFpcnMgaWRlbnRpZnkgdGhlIGJlc3QgcHVyaXR5IC8gcGxvaWR5IHNvbHV0aW9uLgoKYGBge3IgcHVycGxlX3Bsb3RfcHVyaXR5cmFuZ2UsIG91dC53aWR0aD0iNDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoZmlsZS5wYXRoKGltZ19kaXIsIHBhc3RlMChwYXJhbXMkYmF0Y2hfbmFtZSwgJy5wdXJpdHkucmFuZ2UucG5nJykpKQpgYGAKCiMjIyMgQ2xvbmFsaXR5ClRoZSBmb2xsb3dpbmcgZGlhZ3JhbSBpbGx1c3RyYXRlcyB0aGUgY2xvbmFsaXR5IG1vZGVsIG9mIGEgdHlwaWNhbCBzYW1wbGUuCgpUaGUgdG9wIGZpZ3VyZSBzaG93cyB0aGUgaGlzdG9ncmFtIG9mIHNvbWF0aWMgcGxvaWR5IGZvciBhbGwgU05WcyBhbmQgSU5ERUxzIGluIGJsdWUuClN1cGVyaW1wb3NlZCBhcmUgcGVha3MgaW4gZGlmZmVyZW50IGNvbG91cnMgZml0dGVkIGZyb20gdGhlIHNhbXBsZSBhcyBkZXNjcmliZWQgaW4gdGhlCmRvY3Mgd2hpbGUgdGhlIGJsYWNrIGxpbmUgc2hvd3MgdGhlIG92ZXJhbGwgZml0dGVkIHBsb2lkeSBkaXN0cmlidXRpb24uIFJlZCBmaWxsZWQKcGVha3MgYXJlIGJlbG93IHRoZSAwLjg1IHN1YmNsb25hbCB0aHJlc2hvbGQuCgpXZSBjYW4gZGV0ZXJtaW5lIHRoZSBsaWtlbGlob29kIG9mIGEgdmFyaWFudCBiZWluZyBzdWJjbG9uYWwgYXQKYW55IGdpdmVuIHBsb2lkeSBhcyBzaG93biBpbiB0aGUgYm90dG9tIGhhbGYgb2YgdGhlIGZpZ3VyZS4KCmBgYHtyIHB1cnBsZV9wbG90X3NvbWF0aWNjbG9uYWxpdHksIG91dC53aWR0aD0iNTAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoZmlsZS5wYXRoKGltZ19kaXIsIHBhc3RlMChwYXJhbXMkYmF0Y2hfbmFtZSwgJy5zb21hdGljLmNsb25hbGl0eS5wbmcnKSkpCmBgYAoKIyMjIyBTZWdtZW50ClRoZSBjb250cmlidXRpb24gb2YgZWFjaCBmaXR0ZWQgc2VnbWVudCB0byB0aGUgZmluYWwgc2NvcmUgb2YgdGhlIGJlc3QgZml0IGlzIHNob3duIGluCnRoZSBmb2xsb3dpbmcgZmlndXJlLiBFYWNoIHNlZ21lbnQgaXMgZGl2aWRlZCBpbnRvIGl0cyBtYWpvciBhbmQgbWlub3IgYWxsZWxlIHBsb2lkeS4KVGhlIGFyZWEgb2YgZWFjaCBjaXJjbGUgc2hvd3MgdGhlIHdlaWdodCAoQU1CRVIgYmFmIGNvdW50KSBvZiBlYWNoIHNlZ21lbnQuCgpgYGB7ciBwdXJwbGVfcGxvdF9zZWdtZW50LCBvdXQud2lkdGg9IjQwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGZpbGUucGF0aChpbWdfZGlyLCBwYXN0ZTAocGFyYW1zJGJhdGNoX25hbWUsICcuc2VnbWVudC5wbmcnKSkpCmBgYAoKIyMgT25jb3ZpcnVzZXMgey50YWJzZXQgLnRhYnNldC1mYWRlICNvbmNvdmlydXNlc30KCk9uY292aXJ1c2VzIGFuZCB0aGVpciBpbnRlZ3JhdGlvbiBzaXRlcy4gVmlyYWwgc2VxdWVuY2VzIGFyZSBvYnRhaW5lZCBmcm9tIHRoZQo8YSBocmVmPSJodHRwczovL2dkYy5jYW5jZXIuZ292L2Fib3V0LWRhdGEvZGF0YS1oYXJtb25pemF0aW9uLWFuZC1nZW5lcmF0aW9uL2dkYy1yZWZlcmVuY2UtZmlsZXMiPkdEQyBkYXRhYmFzZTwvYT4uCkhvc3QgZ2VuZXMgYXJlIHJlcG9ydGVkIGlmIHRoZSBpbnRlZ3JhdGlvbiBzaXRlIGZhbGxzIG9uIGEgZ2VuZSBvciBhdCBsZWFzdCBiZWZvcmUgMTAwa2JwIG9mIHRoZSBnZW5lIHN0YXJ0LgoKYGBge3Igb25jb3ZpcnVzZXNfdGFibGV9CnByZXNlbnRfdmlydXNlcyA8LSBwYXJhbXMkb25jb3ZpcmFsX3ByZXNlbnRfdmlydXNlcwpicmVha3BvaW50c190c3YgPC0gcGFyYW1zJG9uY292aXJhbF9icmVha3BvaW50c190c3YKIyBwcmVzZW50X3ZpcnVzZXMgPC0gJy9Vc2Vycy92c2F2ZWxpZXYvdG1wL29uY292aS9wcmVzZW50X3ZpcnVzZXMudHh0JwojIGJyZWFrcG9pbnRzX3RzdiA8LSAnL1VzZXJzL3ZzYXZlbGlldi90bXAvb25jb3ZpL29uY292aXJhbF9icmVha3BvaW50cy50c3YnCgppZiAoYnJlYWtwb2ludHNfdHN2ICE9ICIiICYmIGZpbGUuZXhpc3RzKGJyZWFrcG9pbnRzX3RzdikpIHsKICBicmVha3BvaW50cyA8LSByZWFkcjo6cmVhZF90c3YoYnJlYWtwb2ludHNfdHN2LCBjb2xfbmFtZXMgPSBULCBjb2xfdHlwZXMgPSAiY2NpaWNpY2NjYyIpCiAgYnJlYWtwb2ludHMgJT4lIAogICAgZHBseXI6OnNlbGVjdChDb250aWcgPSBjb250aWcsIFN0YXJ0ID0gc3RhcnQsIEVuZCA9IGVuZCwgYFJlYWQgc3VwcG9ydGAgPSBQQUlSX0NPVU5ULCBgQWZmZWN0ZWQgZ2VuZXNgID0gR2VuZXMsIGBTViB0eXBlYCA9IHN2dHlwZSwgSUQsIE1BVEVJRCkgJT4lCiAgICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIiwgY2xlYXIgPSBGQUxTRSwgcGxhaW4gPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgZGlzcGxheSBjb21wYWN0IiwKICAgICAgICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwgZXh0ZW5zaW9ucyA9IGMoIlNjcm9sbGVyIiwgIkJ1dHRvbnMiLCAiS2V5VGFibGUiKSwKICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsZXIgPSBUUlVFLCBzY3JvbGxZID0gNDAwLCBzY3JvbGxYID0gVFJVRSwgYXV0b1dpZHRoID0gVFJVRSwga2V5cyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjc3YnLCAnZXhjZWwnKSwgZG9tID0gJ0JmcnRpcCcpKSAlPiUKICAgIERUOjpmb3JtYXRDdXJyZW5jeSh+IFN0YXJ0ICsgRW5kLCBjdXJyZW5jeSA9ICIiLCBpbnRlcnZhbCA9IDMsIG1hcmsgPSAiLCIsIGRpZ2l0cyA9IDApCn0gZWxzZSB7CiAgdmlydXNlcyA9IHJlYWRyOjpyZWFkX2ZpbGUocHJlc2VudF92aXJ1c2VzKQogIGlmIChzdHJfbGVuZ3RoKHZpcnVzZXMpID4gMCkgewogICAgY2F0KHN0cl9jKCJEZXRlY2VkIHNpZ25pZmljYW50IHRyYWNlcyBvZiBjb250ZW50IG9mIHRoZSBmb2xsb3dpbmcgdmlydXNlczogIiwgdmlydXNlcywgIiwgaG93ZXZlciBubyBldmlkZW5jZSBvZiB2aXJhbCBpbnRlZ3JhdGlvbiBpbnRvIHRoZSBob3N0IGdlbm9tZSBpcyBvYnNlcnZlZC4iKSkKICB9IGVsc2UgewogICAgY2F0KCJObyBvbmNvdmlyYWwgY29udGVudCBkZXRlY3RlZCBpbiB0aGlzIHNhbXBsZS4iKQogIH0KfQoKYGBgCgojIyBBZGRlbmR1bSB7LnRhYnNldCAudGFic2V0LWZhZGUgI2FkZGVuZHVtfQoKPGEgaHJlZj0iI3RvcCI+QmFjayB0byB0b3A8L2E+CgojIyMgQ29uZGEgUGtncyBNYWluCgpgYGB7ciBjb25kYV9saXN0X21haW59CmNvbmRhX3BrZ3MgPC0gcmVhZHI6OnJlYWRfdGFibGUyKHBhcmFtcyRjb25kYV9saXN0LCBjb2xfbmFtZXMgPSBjKCJuYW1lIiwgInZlcnNpb24iLCAiYnVpbGQiLCAiY2hhbm5lbCIsICJlbnYiKSwgY29sX3R5cGVzID0gImNjY2NjIikgJT4lCiAgZHBseXI6OmFycmFuZ2UobmFtZSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KG5hbWUsIHZlcnNpb24sIGJ1aWxkLCBjaGFubmVsKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKGVudnMgPSBwYXN0ZShlbnYsIGNvbGxhcHNlID0gIiwgIikpCgptYWluX3BrZ3MgPC0gYygKICAiXmNhY2FvIiwgIl5jb25wYWlyJCIsICJeY3BzciIsCiAgIl5ncmlkc3MiLCAiXmhtZnRvb2xzIiwgIl5yZWZlcmVuY2UiLCAiXmh0c2xpYiQiLAogICJebXVsdGlxYyIsICJebmdzIiwKICAicGFuZG9jIiwgIl5wY2dyIiwgIl5weXRob24kIiwKICAiXnItYmFzZSQiLCAic25ha2VtYWtlIiwKICAiXnVtY2NyaXNlJCIpICU+JQogIHBhc3RlKGNvbGxhcHNlID0gInwiKQoKY29uZGFfcGtncyAlPiUKICBkcGx5cjo6ZmlsdGVyKGdyZXBsKG1haW5fcGtncywgbmFtZSkpICU+JQogIGRwbHlyOjphcnJhbmdlKGRlc2MobmFtZSkpICU+JQogIGtuaXRyOjprYWJsZShmb3JtYXQgPSAiaHRtbCIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IFRSVUUsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICBrYWJsZUV4dHJhOjpjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSkgJT4lCiAga2FibGVFeHRyYTo6c2Nyb2xsX2JveChoZWlnaHQgPSAiMzAwcHgiKQpgYGAKCiMjIyBSZXBvcnQgSW5wdXRzCgpgYGB7ciByZXBvcnRfaW5wdXRzfQpkcGx5cjo6dGliYmxlKGtleSA9IG5hbWVzKHBhcmFtcyksIHZhbHVlID0gdW5saXN0KHBhcmFtcykpICU+JQogIGtuaXRyOjprYWJsZShmb3JtYXQgPSAiaHRtbCIpICU+JQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAga2FibGVFeHRyYTo6Y29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUpICU+JQogIGthYmxlRXh0cmE6OnNjcm9sbF9ib3goaGVpZ2h0ID0gIjIwMHB4IikKYGBgCgojIyMgQ29uZGEgUGtncyBBbGwKCmBgYHtyIGNvbmRhX2xpc3RfYWxsfQpjb25kYV9wa2dzICU+JQogIERUOjpkYXRhdGFibGUoZmlsdGVyID0gbGlzdChwb3NpdGlvbiA9ICJ0b3AiLCBjbGVhciA9IEZBTFNFLCBwbGFpbiA9IFRSVUUpLAogICAgICAgICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwgZXh0ZW5zaW9ucyA9IGMoIlNjcm9sbGVyIiwgIkJ1dHRvbnMiKSwKICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbGVyID0gVFJVRSwgc2Nyb2xsWCA9IFRSVUUsIHNjcm9sbFkgPSA0MDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnY3N2JyksIGRvbSA9ICdCZnJ0aXAnKSkKYGBgCgpgYGB7ciBzZXNzaW9uX2luZm8sIGV2YWw9Rn0Kc2kgPC0gZGV2dG9vbHM6OnNlc3Npb25faW5mbyhpbmNsdWRlX2Jhc2UgPSBUUlVFKQpzaV9wbCA8LSB1bmNsYXNzKHNpJHBsYXRmb3JtKSAlPiUgYXNfdGliYmxlKCkgJT4lIHQoKQojIHNpX3BrZyA8LSB1bmNsYXNzKHNpJHBhY2thZ2VzKSAlPiUKIyAgIGRwbHlyOjphc190aWJibGUoKSAlPiUKIyAgIGRwbHlyOjpzZWxlY3QocGFja2FnZSwgdmVyc2lvbiA9IG9uZGlza3ZlcnNpb24sIHBhdGgsIGRhdGVzdGFtcCA9IGRhdGUpCgpkcGx5cjo6dGliYmxlKHZhciA9IHJvdy5uYW1lcyhzaV9wbCksCiAgICAgICAgICAgICAgdmFsdWUgPSBzaV9wbFssICwgZHJvcCA9IFRSVUVdKSAlPiUKICBrbml0cjo6a2FibGUoZm9ybWF0ID0gImh0bWwiKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIGthYmxlRXh0cmE6OmNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFKQpgYGAKCmBgYHtyIHNlc3Npb25faW5mb19wa2dzLCBldmFsPUZ9CmtuaXRyOjprYWJsZShzaV9wa2csIGZvcm1hdCA9ICJodG1sIikgJT4lCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gVFJVRSwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIGthYmxlRXh0cmE6OmNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFKSAlPiUKICBrYWJsZUV4dHJhOjpzY3JvbGxfYm94KGhlaWdodCA9ICI0MDBweCIpCmBgYAoKPHA+Jm5ic3A7PC9wPgoK