
Introduction
The R markdown documents in this directory are intended to provide a
complete accounting of the analyses performed in the preparation of
“Innate biosignature of treatment failure in patients with cutaneous
leishmaniasis.”
I assume that if anyone ever reads this, s/he is looking for the
source of the data, figures, and tables from that paper and to see if
the methods employed to generate them are good, bad, indifferent, or
garbage. These documents are being generated by a singularity container
which provides the input count tables (Once we have accessions, I will
make a companion which is able to create them), sample sheets, input
documents, and all the software used to process them. The overal
configuration of the container is contained in the toplevel .yml file
and provides the base OS (Debian stable) and the scripts used to install
the software. ‘local/bin/setup_debian.sh’ handles the base container;
‘local/bin/setup_hpgltools.sh’ sets up R, bioconductor, and my package
‘hpgltools’, and ‘local/bin/runscript’ is the script run if one invokes
the container without any arguments; when run it uses the various
installed R packages to ‘render’ the Rmd files in /data to freshly
created html. This README is the first document rendered.
Figure/Table
locations
As of 20240919, Maria Adelaida kindly sent me the putatively final
set of figures/tables. I am going to lay out the location in the html
logs and their Rmd parents where these may be found. If you wish to play
along, make sure you run the entire 01datastructures.Rmd.
Also, this container is automatically regenerated and rerun when I
make changes; so one may just go here to play along (that is where I am
going to hunt down the figures/tables):
https://containerbook.umiacs.io/
Panel B
These move to the document 04differential_expression_tumaco.
Panel B, left,
middle, and right
Section 7.0.4 “Figure 4B: Volcano plots” For some reason I did not
have separate sections for each cell type.
num_color <- color_choices[["clinic_cf"]][["tumaco_failure"]]
den_color <- color_choices[["clinic_cf"]][["tumaco_cure"]]
wanted_genes <- c("FI44L", "IFI27", "PRR5", "PRR5-ARHGAP8", "RHCE",
"FBXO39", "RSAD2", "SMTNL1", "USP18", "AFAP1")
cf_monocyte_table <- t_cf_monocyte_table_sva[["data"]][["outcome"]]
cf_monocyte_volcano <- plot_volcano_condition_de(
cf_monocyte_table, "outcome", label = wanted_genes,
fc_col = "deseq_logfc", p_col = "deseq_adjp", line_position = NULL,
color_high = num_color, color_low = den_color, label_size = 6)
pp(file = glue("images/cf_monocyte_volcano_labeled-v{ver}.svg"))
cf_monocyte_volcano[["plot"]]
dev.off()
Panel C
TODO: Add similar venn ~ section 8
I played with versions of this using AUCC and UpSet plots throughout
the 04differential_expression_tumaco document; but did not generate this
specific image. (Maybe I should make a version of it?)
Table S1
This was manually collated by Maria Adelaida; I think all the numbers
do correspond to the regression f-values/p-values.
Table S2
This is a very slightly modified copy of the sample sheet in
sample_sheets/tmrc3_samples_pruned.xlsx One noteworthy thing: if one
reprocesses the raw data and runs ‘gather_preprocessing_metadata()’, it
will suck up all the logs from any tools for which I have written
regexes and append the results as columns at the right of this. I am
more than a little proud of that.
Table S3
This is a slightly modified copy of the result of the ‘svpc_fstats()’
invocations found at the end of Section 17 in 02visualization. (my
little function adds a funky heatmap to the output)
queries <- c("typeofcells", "visitnumber", "clinic", "donor")
tc_clinical_fpstats <- svpc_fstats(tc_clinical, num_pcs = 5, queries = queries)
Table S4
This is a slightly modified copy of two results:
Biopsies DE
This is a modified version of the result when one invokes
combine_de_tables(), as per section 6.0.2 of
04differential_expression_tumaco; this container should therefore
provide those numbers if one looks in
‘analyses/4_tumaco/DE_Cure_Fail/Biopsies/t_biopsy_cf_table_sva-v202409.xlsx’
That xlsx workbook has a worksheet named ‘outcome’ (the second); this
worksheet comprises columns Q-V from it. (also yay! the numbers are the
same between my container (which changes constantly and gets rebuilt
with each change) and the copy that was used for the paper!)
t_cf_biopsy_table_sva <- combine_de_tables(
t_cf_biopsy_de_sva, keepers = t_cf_contrast,
excel = glue("{cf_prefix}/Biopsies/t_biopsy_cf_table_sva-v{ver}.xlsx"))
t_cf_biopsy_table_sva
Bipsies GO
Looking more carefully at this, I think this is not from my
overrepresentation analysis; but came from STRING?
The invocation for my version of this resides in 05enrichment,
section 2.9.1 and the xlsx file in the container should be found in
‘analyses/Gene_Set_Enrichment/t_cf_biopsy_sig_sva_up_gp-v202409.xlsx’
for gProfiler, and with a similar name containing ‘cp’ for
clusterProfiler.
t_cf_biopsy_sig_sva_gp_up <- simple_gprofiler(
t_cf_biopsy_sig_sva_up,
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_biopsy_sig_sva_up_gp-v{ver}.xlsx"))
t_cf_biopsy_sig_sva_gp_up
## or perhaps if you prefer clusterProfiler
t_cf_biopsy_sig_sva_cp_up <- simple_cprofiler(
t_cf_biopsy_sig_sva_up, de_table = t_cf_biopsy_table_sva,
orgdb = "org.Hs.eg.db",
excel = glue("{xlsx_prefix}/Gene_Set_Enrichment/t_cf_biopsy_sig_sva_up_cp-v{ver}.xlsx"))
Table S5
This is a redacted combination of a few files:
worksheet
Monocytes
Section 6.0.2 provides the invocation of combine_de_tables() which
produces the
‘analysis/4_Tumaco/DE_Cure_Fail/Monocytes/t_monocyte_cf_table-sva-v202409.xlsx’
that comprises the logFC etc values in this worksheet. Interestingly,
the top 5 genes all shifted down in logFC by ~ 0.002 in my
container-derived worksheet vs this table. I think that is an acceptable
difference? I did spot check a few genes in the top 5000 and it looks
like the order is maintained.
t_cf_monocyte_table_sva <- combine_de_tables(
t_cf_monocyte_de_sva, keepers = t_cf_contrast,
excel = glue("{cf_prefix}/Monocytes/t_monocyte_cf_table_sva-v{ver}.xlsx"))
t_cf_monocyte_table_sva
worksheet
Neutrophils
Same logic, but Section 7.0.2 with the analagously named xlsx file in
the Neutrophils directory; these numbers also appear to have shifted
slightly (but this time by ~ 0.001 up to 0.1 logFC) and I do see a
couple of genes out of order… I am going to check in with Maria
Adelaida.
t_cf_neutrophil_table_sva <- combine_de_tables(
t_cf_neutrophil_de_sva, keepers = t_cf_contrast,
excel = glue("{cf_prefix}/Neutrophils/t_neutrophil_cf_table_sva-v{ver}.xlsx"))
t_cf_neutrophil_table_sva
worksheet
Eosinophils
Ibid, section 7.0.3. Once again the values look to have shifted down
by ~ 0.001 to 0.01 logFC.
t_cf_eosinophil_table_sva <- combine_de_tables(
t_cf_eosinophil_de_sva, keepers = t_cf_contrast,
excel = glue("{cf_prefix}/Eosinophils/t_eosinophil_cf_table_sva-v{ver}.xlsx"))
t_cf_eosinophil_table_sva
worksheet
All_innate
This is actually way earlier in the differential expression document,
section 3.1 when the variable ‘t_cf_clinicalnb_table_sva’ is created to
produce the xlsx file
‘analyses/4_tumaco/DE_Cure_Fail/All_Samples/t_clinical_nobiop_cf_table_sva-v202409.xlsx’
These numbers match up pretty much exactly (I set the number of
significant digits to 4 I think, but this worksheet is 3?)
t_cf_clinical_table_sva <- combine_de_tables(
t_cf_clinical_de_sva, keepers = cf_contrast,
excel = glue("{cf_prefix}/All_Samples/t_clinical_cf_table_sva-v{ver}.xlsx"))
t_cf_clinical_table_sva
Table S6
I do not think they used my gProfiler/clusterProfiler results for
this.
Table S7
This comes from 06lrt_gsva, section 3.
with the caveat that I think the C2 and C7 results are more
interesting. Also, the results produced by the container are sparser
with respect to the annotations because I did not want to steal the
gmt/xml annotations from broad. If you happen to have the xml/gmt files,
I left the original invocations there so you can get the full table with
the paper titles etc (also, note that later versions of mSigDB changed
the xml format so that it no longer parses properly in R; so those
functions are now smrt enough to handle the new gmt/json files).
tc_celltype_gsva_h <- simple_gsva(
tc_valid,
signatures = broad_h,
msig_xml = "reference/msigdb/msigdb_v7.5.1.xml",
signature_category = "h")
tc_celltype_gsva_h_sig <- get_sig_gsva_categories(
tc_celltype_gsva_h,
excel = "analyses/3_cali_and_tumaco/GSVA/tc_valid_gsva_h.xlsx")
Table S8
I am reasonably certain that Alejandro produced the inputs for this;
however the container produces nearly identical versions of the pieces
in 07wgcna, section 9.
written_interesting <- write_xlsx(fData(l2input)[interesting_genes, ],
excel = glue("excel/wgcna_interesting_genes-v{ver}.xlsx"))
## Note that we can do similarity matrices on the samples too in order to get
## dendrograms which may get interesting groups of samples?
Table S9
This is not run automatically by the container because it will run
most computers out of memory and/or take a really long time. If your
computer has ~ 512G ram, open 08classifier_highvar.Rmd and run section
11.2; the resulting xlsx output files should look like this (except
cooler because I add some plots).
tc_vall_summary_xlsx <- glue("excel/tc_vall_ml_summary-v{ver}.xlsx")
tc_vall_knn <- classify_n_times(tc_vall_texprs, tc_vall_meta,
outcome_column = ref_col,
method = "knn", sampler = "cv")
written <- write_classifier_summary(tc_vall_knn, excel = tc_vall_summary_xlsx)
tc_vall_gb <- classify_n_times(tc_vall_texprs, tc_vall_meta,
outcome_column = ref_col,
method = "xgbTree", sampler = "cv")
written <- write_classifier_summary(tc_vall_gb, excel = written[["wb"]])
tc_vall_glm <- classify_n_times(tc_vall_texprs, tc_vall_meta,
outcome_column = ref_col,
method = "glmnet", sampler = "cv")
written <- write_classifier_summary(tc_vall_glm, excel = written[["wb"]])
tc_vall_rf <- classify_n_times(tc_vall_texprs, tc_vall_meta,
outcome_column = ref_col,
method = "ranger", sampler = "cv")
written <- write_classifier_summary(tc_vall_rf, excel = written[["wb"]])
openxlsx::saveWorkbook(written[["wb"]], file = tc_vall_summary_xlsx)
Structure
The Rmd files may be rendered in any order with one very important
exception: the 01datastructures.Rmd file must be run first. It reads all
of the sample sheets and count tables and writes out a series of data
files used by all the other documents.
Note: All the references are in the documents, not here.
01datastructures
This is responsible for setting the stage for everything that
follows. It collects annotations from the 2020 ensembl human database,
the experimental metadata from the xlsx files in sample_sheets/, and the
counts found in preprocessing/ and combines them into an initial, large
expressionSet. It tallies up the samples according to many/most of the
likely factors of interest, filters the data, and extracts the various
subsets into separate datastructures.
02visualization
Dominated by a long series of PCA explorations. It is basically a
playground for me to poke at the various data subsets in order to try to
get a feeling for what is the most appropriate way to think about the
data. It was where we eventually decided that we cannot use the Cali
data, for example.
In later iterations it included a series of regression analyses and
further examinations into the sensitivities of the PCA and surrogate
variable analyses. It should be noted that these analyses were entirely
Theresa’s idea, I copied them into this document and made some minor
changes.
03differential_expression_both
This document performs some differential expression analyses using
both the samples from Cali and Tumaco. Partially this was done to
assuage my interest, and partially to reinforce the idea that the Cali
samples really do not play well with others.
04differential_expression_tumaco
Ibid, but only Tumaco. This is the real meat of the analysis and
seeks to try out various ways of performing differential expression
using the Tumaco data in order to see which provide the most robust ways
of examining the potential questions in the data.
05enrichment
Read the xlsx files from 03 and 04 above and pass the resulting gene
sets and/or DE tables to gProfiler2 and clusterProfiler. gProfiler was
used to perform over-representation analyses of the significantly
increased/decreased genes (or both together) of the various contrasts
vs. the databases provided by gProfiler. The same task was performed
using clusterProfiler with two exceptions: clusterProfiler uses the
orgdb annotations for its gene groups and is therefore (by default, but
not exclusively) limited to GO/KEGG/DAVID; conversely, one may trivially
pass the full DE table to clusterProfiler and thus perform the full GSEA
analysis. (I have been playing with passing reactome (via ReactomePA)
and mSigDB to these methods).
06lrt_gsva
Theresa also suggested we try a series of Likelihood Ratio Tests
(LRT) to examine trends in the data; thus making DESeq2/EdgeR sensitive
to not only increased/decreased gene expression across two conditions,
but shared/divergent trends across multiple factors in the metadata.
This document provides a version of this.
At the same time we were doing that, she and I put together a
simplified method for querying the mSigDB via GSVA. These queries are in
this document too.
07wgcna
Alejandro performed a set of WGCNA analyses using the normalized
expression values. He kindly sent me a copy of his R script and I
reformatted it somewhat into this document.
08classifier_highvar
I wanted to explore machine learning classifiers. I had this dataset
(and the parasite transcriptomes) open, so I decided to play with them.
It was never intended for publication by me but as a fun learning
experience; but here it is…
Introduction to the
singularity container
Of the various options, I found singularity to be the most
attractive. I therefore wrote a default Makefile with a few targets to
create and manipulate images because I cannot be bothered to remember
all of the various commands.
The images
I am hoping to create 2 image templates for the TMRC analyses:
preprocessing and analyses. I will therefore have a few locally
maintained shell scripts which contain the base image setup tasks, the
tasks required to setup the tools used, download the data, and perform
the work.
Setting up the base
image
I intend to use Debian stable. I am copying the required setup files
into the current working directory and invoking make to create the
container. I have a few targets which are intended to make this easier
to remember.
Creating the base
image
The following command runs singularity with options suitable to
create the image. This to me is a little unnerving, because a bunch of
stuff gets run as root.
make
Testing stuff out and
making changes
The overlay target drops the user into the container with R/W
permissions. It creates a directory ‘cure_Fail_analyses_overlay’ which
may be modified at will.
make cure_fail_analyses.overlay
Using the container
for arbitrary Rmd/md files
The container’s runscript has some logic built in which can process
arbitrary markdown documents into html via knitr and pandoc.
cd someplace_with_Rmd
/locationofcontainers/cure_fail_host_analyses.sif -i markdown01.Rmd:markdown02.Rmd
LS0tCnRpdGxlOiAiVE1SQzMgYHIgU3lzLmdldGVudignVkVSU0lPTicpYDogUkVBRE1FL0ludHJvZHVjdGlvbiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAga2VlcF9tZDogZmFsc2UKICBtb2RlOiBzZWxmY29udGFpbmVkCiAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgc2VsZl9jb250YWluZWQ6IHRydWUKICB0aGVtZTogcmVhZGFibGUKICB0b2M6IHRydWUKICB0b2NfZmxvYXQ6CiAgIGNvbGxhcHNlZDogZmFsc2UKICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgoKWyFbRE9JXShodHRwczovL3plbm9kby5vcmcvYmFkZ2UvNzEyMTA0NTE4LnN2ZyldKGh0dHBzOi8vemVub2RvLm9yZy9kb2kvMTAuNTI4MS96ZW5vZG8uMTM3OTg3ODgpCgojIEludHJvZHVjdGlvbgoKVGhlIFIgbWFya2Rvd24gZG9jdW1lbnRzIGluIHRoaXMgZGlyZWN0b3J5IGFyZSBpbnRlbmRlZCB0byBwcm92aWRlIGEKY29tcGxldGUgYWNjb3VudGluZyBvZiB0aGUgYW5hbHlzZXMgcGVyZm9ybWVkIGluIHRoZSBwcmVwYXJhdGlvbiBvZgoKIklubmF0ZSBiaW9zaWduYXR1cmUgb2YgdHJlYXRtZW50IGZhaWx1cmUgaW4gcGF0aWVudHMgd2l0aCBjdXRhbmVvdXMKbGVpc2htYW5pYXNpcy4iCgpJIGFzc3VtZSB0aGF0IGlmIGFueW9uZSBldmVyIHJlYWRzIHRoaXMsIHMvaGUgaXMgbG9va2luZyBmb3IgdGhlCnNvdXJjZSBvZiB0aGUgZGF0YSwgZmlndXJlcywgYW5kIHRhYmxlcyBmcm9tIHRoYXQgcGFwZXIgYW5kIHRvIHNlZSBpZgp0aGUgbWV0aG9kcyBlbXBsb3llZCB0byBnZW5lcmF0ZSB0aGVtIGFyZSBnb29kLCBiYWQsIGluZGlmZmVyZW50LCBvcgpnYXJiYWdlLiAgVGhlc2UgZG9jdW1lbnRzIGFyZSBiZWluZyBnZW5lcmF0ZWQgYnkgYSBzaW5ndWxhcml0eQpjb250YWluZXIgd2hpY2ggcHJvdmlkZXMgdGhlIGlucHV0IGNvdW50IHRhYmxlcyAoT25jZSB3ZSBoYXZlCmFjY2Vzc2lvbnMsIEkgd2lsbCBtYWtlIGEgY29tcGFuaW9uIHdoaWNoIGlzIGFibGUgdG8gY3JlYXRlIHRoZW0pLApzYW1wbGUgc2hlZXRzLCBpbnB1dCBkb2N1bWVudHMsIGFuZCBhbGwgdGhlIHNvZnR3YXJlIHVzZWQgdG8gcHJvY2Vzcwp0aGVtLiAgVGhlIG92ZXJhbCBjb25maWd1cmF0aW9uIG9mIHRoZSBjb250YWluZXIgaXMgY29udGFpbmVkIGluIHRoZQp0b3BsZXZlbCAueW1sIGZpbGUgYW5kIHByb3ZpZGVzIHRoZSBiYXNlIE9TIChEZWJpYW4gc3RhYmxlKSBhbmQgdGhlCnNjcmlwdHMgdXNlZCB0byBpbnN0YWxsIHRoZSBzb2Z0d2FyZS4gICdsb2NhbC9iaW4vc2V0dXBfZGViaWFuLnNoJwpoYW5kbGVzIHRoZSBiYXNlIGNvbnRhaW5lcjsgJ2xvY2FsL2Jpbi9zZXR1cF9ocGdsdG9vbHMuc2gnIHNldHMgdXAgUiwKYmlvY29uZHVjdG9yLCBhbmQgbXkgcGFja2FnZSAnaHBnbHRvb2xzJywgYW5kICdsb2NhbC9iaW4vcnVuc2NyaXB0JyBpcwp0aGUgc2NyaXB0IHJ1biBpZiBvbmUgaW52b2tlcyB0aGUgY29udGFpbmVyIHdpdGhvdXQgYW55IGFyZ3VtZW50czsKd2hlbiBydW4gaXQgdXNlcyB0aGUgdmFyaW91cyBpbnN0YWxsZWQgUiBwYWNrYWdlcyB0byAncmVuZGVyJyB0aGUgUm1kCmZpbGVzIGluIC9kYXRhIHRvIGZyZXNobHkgY3JlYXRlZCBodG1sLiAgVGhpcyBSRUFETUUgaXMgdGhlIGZpcnN0CmRvY3VtZW50IHJlbmRlcmVkLgoKIyBGaWd1cmUvVGFibGUgbG9jYXRpb25zCgpBcyBvZiAyMDI0MDkxOSwgTWFyaWEgQWRlbGFpZGEga2luZGx5IHNlbnQgbWUgdGhlIHB1dGF0aXZlbHkgZmluYWwgc2V0Cm9mIGZpZ3VyZXMvdGFibGVzLiAgSSBhbSBnb2luZyB0byBsYXkgb3V0IHRoZSBsb2NhdGlvbiBpbiB0aGUgaHRtbApsb2dzIGFuZCB0aGVpciBSbWQgcGFyZW50cyB3aGVyZSB0aGVzZSBtYXkgYmUgZm91bmQuICBJZiB5b3Ugd2lzaCB0bwpwbGF5IGFsb25nLCBtYWtlIHN1cmUgeW91IHJ1biB0aGUgZW50aXJlIDAxZGF0YXN0cnVjdHVyZXMuUm1kLgoKQWxzbywgdGhpcyBjb250YWluZXIgaXMgYXV0b21hdGljYWxseSByZWdlbmVyYXRlZCBhbmQgcmVydW4gd2hlbiBJCm1ha2UgY2hhbmdlczsgc28gb25lIG1heSBqdXN0IGdvIGhlcmUgdG8gcGxheSBhbG9uZyAodGhhdCBpcyB3aGVyZSBJCmFtIGdvaW5nIHRvIGh1bnQgZG93biB0aGUgZmlndXJlcy90YWJsZXMpOgoKaHR0cHM6Ly9jb250YWluZXJib29rLnVtaWFjcy5pby8KCiMjIEZpZ3VyZSAxCgpUaGVzZSBudW1iZXJzIGFyZSBjb21pbmcgZnJvbSAwMWRhdGFzdHJ1Y3R1cmVzOiAgd2hlbiBjb25zaWRlcmluZyB0aGUKc2FtcGxlcyBmcm9tIHRoZSBwZXJzcGVjdGl2ZSBvZiBob3cgbWFueSBwZW9wbGUgZmFsbCBpbnRvIGVhY2gKY2F0ZWdvcnksIHRoYXQgaXMgY29taW5nIGRpcmVjdGx5IGZyb20gc2VjdGlvbiA0LjEgIk1ldGFkYXRhIFNvdXJjZXMiCmFuZCB0aGUgZGVtb2dyYXBoaWNzIHhsc3ggZmlsZS4gIFRoaXMgcHJvdmlkZXMgdGhlIG51bWJlciBvZiBwZW9wbGUKd2hvIGZhbGwgaW50byBlYWNoIGNhdGVnb3J5IG9mIHBhbmVsIEEvQi4KCiMjIEZpZ3VyZSAyCgojIyMgUGFuZWwgQQoKVE9ETzogQ2xhcmlmeSB2MS92Mi92MyB2cy4gUHJlLVR4LCBNaWQtVHgsIEVuZC1UeCBpbiB0aGUgbm90ZWJvb2sKClRoaXMgaXMgYWxzbyBkZXJpdmVkIGZyb20gMDFkYXRhc3RydWN0dXJlcywgYnV0IGZyb20gdGhlIHBlcnNwZWN0aXZlCm9mIHRoZSBudW1iZXJzIG9mIHNhbXBsZXMgd2hpY2ggc3Vydml2ZSBvdXIgdmFyaW91cyBmaWx0ZXJzLiAgVGh1cywgdG8KYXJyaXZlIGF0IHRoZXNlIG51bWJlcnMsIG9uZSBzaG91bGQgc3RhcnQgYXQgc2VjdGlvbiA2LjEgIkNyZWF0ZQpFeHByZXNzaW9uc2V0LiIgYW5kIHdhbmRlciB0aHJvdWdoIHRoZSBkb2N1bWVudDsgaG93ZXZlciBkb2luZyBzbyB3aWxsCmxpa2VseSBtYWtlIG1vc3QgcGVvcGxlIHNhZCBiZWNhdXNlIGl0IGlzIGEgbG9uZyBqb3VybmV5LiAgSW5zdGVhZCwKeW91IG1heSBza2lwIGRvd24gdG8gc2VjdGlvbiAxNCAiU3VtbWFyaXplOiBUYWJ1bGF0ZSBzYW1wbGUgbnVtYmVycyIuClRoZSBzZWN0aW9uIGxhYmVsZWQgJ0JvdGgnIHByb3ZpZGVzIHRoZXNlIG51bWJlcnMuICBOb3RlLCB0aGlzIHRhYmxlCnVzZWQgdG8gYmUganVzdCBUdW1hY28sIHdoaWNoIGZvbGxvd3MuCgpUaGUgbnVtYmVycyBvZiBzYW1wbGVzIGluIGVhY2ggZ3JvdXAgYXJlIHJlc3RhdGVkIGluIHRoZSBzdW1tYXJpZXMuClRoZSBvbmx5IHJlYWwgY2F2ZWF0IGlzIHRoYXQgSSB3cm90ZSB0aGVtIGFzICd2aXNpdDEnIG9yICd2MScgZm9yClByZS1UeCwgJ3Zpc2l0MicgZm9yIE1pZC1UeCwgYW5kICd2aXNpdDMnIGZvciBFbmQtVHguCgpBbm90aGVyIHdheSB0byByZWNhcGl0dWxhdGUgdGhlc2UgbnVtYmVycyBpcyB0byBjaGVjayBvdXQgdGhlIHNhbmtleQpwbG90cyBpbiBzZWN0aW9uIDggJ1Zpc3VhbGl6ZSB0aGUgc2FtcGxlIGJyZWFrZG93bicuICBBbiBleGFtcGxlIGludm9jYXRpb24gbG9va3MgbGlrZToKCmBgYHtyLCBldmFsPUZBTFNFfQpjbGluaWNfdHlwZV9vdXRjb21lX3NhbmtleSA8LSBwbG90X21ldGFfc2Fua2V5KAogIHRjX3ZhbGlkLCBmYWN0b3JzID0gYygiY2xpbmljIiwgInR5cGVvZmNlbGxzIiwgImZpbmFsb3V0Y29tZSIpLAogIGRyaWxsX2Rvd24gPSBUUlVFLCBjb2xvcl9jaG9pY2VzID0gY29sb3JfY2hvaWNlcykKY2xpbmljX3R5cGVfb3V0Y29tZV9zYW5rZXkKCmNsaW5pY19ldGhuaWNpdHlfb3V0Y29tZV9zYW5rZXkgPC0gcGxvdF9tZXRhX3NhbmtleSgKICB0Y192YWxpZCwgZmFjdG9ycyA9IGMoImNsaW5pYyIsICJldG5pYSIsICJmaW5hbG91dGNvbWUiKSwKICBkcmlsbF9kb3duID0gVFJVRSwgY29sb3JfY2hvaWNlcyA9IGNvbG9yX2Nob2ljZXMpCmNsaW5pY19ldGhuaWNpdHlfb3V0Y29tZV9zYW5rZXkKCmNsaW5pY19zZXhfb3V0Y29tZV9zYW5rZXkgPC0gcGxvdF9tZXRhX3NhbmtleSgKICB0Y192YWxpZCwgZmFjdG9ycyA9IGMoImNsaW5pYyIsICJzZXgiLCAiZmluYWxvdXRjb21lIiksCiAgZHJpbGxfZG93biA9IFRSVUUsIGNvbG9yX2Nob2ljZXMgPSBjb2xvcl9jaG9pY2VzKQpjbGluaWNfc2V4X291dGNvbWVfc2Fua2V5CmBgYAoKIyMjIFBhbmVsIEIKCkZvdW5kIGluIDAydmlzdWFsaXphdGlvbiwgc2VjdGlvbiA4ICJHbG9iYWwgdmlld3Mgb2YgYWxsIGNlbGwgdHlwZXMiCkhleSwgY2hlY2sgaXQsIGRpZmZlcmVudCB0eXBlcyBvZiBpbW11bmUgY2VsbHMgYXJlIGRpZmZlcmVudCEKCk9uZSBpbnZvY2F0aW9uIGxvb2tzIGxpa2UgdGhpcyAodGhlcmUgYXJlIGEgZmV3IHZlcnNpb25zKToKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19wY2EgPC0gcGxvdF9wY2EodGNfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICBwbG90X3RpdGxlID0gIlBDQSAtIENlbGwgdHlwZSIsIHNpemVfY29sdW1uID0gInZpc2l0bnVtYmVyIikKdGNfcGNhCmBgYAoKIyMjIFBhbmVsIEMKCkliaWQuICBCb3RoIHBhbmVscyBhcmUgYWN0dWFsbHkgYSBsaXR0bGUgZnVydGhlciBkb3duIGluIHNlY3Rpb24gOC4xLgoKSGVyZSBpcyB0aGUgaW52b2NhdGlvbjoKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19jZl9jb3JoZWF0IDwtIHBsb3RfY29yaGVhdCh0Y19jZl9ub3JtLCBwbG90X3RpdGxlID0gIkhlaXJhcmNoaWNhbCBjbHVzdGVyaW5nOgogICAgICAgICBjZWxsIHR5cGVzIikKdGNfY2ZfY29yaGVhdApgYGAKCiMjIEZpZ3VyZSAzCgpNYXJpYSBBZGVsYWlkYSBkaWQgYSB0cmVtZW5kb3VzIGFtb3VudCBvZiB3b3JrIHRvIG1vdmUgdGhlIHZhcmlvdXMKZ2dwbG90IGxlZ2VuZHMgYXJvdW5kIHNvIHRoYXQgdGhpcyBmaXRzIGluIGEgc2luZ2xlIHBhbmVsIGluIGEKY29oZXJlbnQgZmFzaGlvbi4KCiMjIyBQYW5lbCBBCgpTZWN0aW9uIDkuOCBvZiAwMnZpc3VhbGl6YXRpb246ICJQQ0E6IENvbXBhcmUgY2xpbmljcyIKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19jbGluaWNfdHlwZV9uYl9wY2EgPC0gcGxvdF9wY2EodGNfY2xpbmljX3R5cGVfbmIpCnRjX2NsaW5pY190eXBlX25iX3BjYQpgYGAKCiMjIyBQYW5lbCBCCgpTZWN0aW9uIDkuNSBvZiAwMnZpc3VhbGl6YXRpb246ICJFb3Npbm9waGlscyBieSBjbGluaWMiCgpgYGB7ciwgZXZhbD1GQUxTRX0KdGNfZW9zaW5vcGhpbHNfcGNhIDwtIHBsb3RfcGNhKHRjX2Vvc2lub3BoaWxzX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpCnRjX2Vvc2lub3BoaWxzX3BjYQpgYGAKCiMjIyBQYW5lbCBDCgpTZWN0aW9uIDkuNiBvZiAwMnZpc3VhbGl6YXRpb246ICJNb25vY3l0ZXMgYnkgY2xuaWMiCgpgYGB7ciwgZXZhbD1GQUxTRX0KdGNfbW9ub2N5dGVzX3BjYSA8LSBwbG90X3BjYSh0Y19tb25vY3l0ZXNfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKdGNfbW9ub2N5dGVzX3BjYQpgYGAKCiMjIyBQYW5lbCBECgpTZWN0aW9uIDkuNyBvZiAwMnZpc3VhbGl6YXRpb246ICJOZXV0cm9waGlscyBieSBjbG5pYyIKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19uZXV0cm9waGlsc19wY2EgPC0gcGxvdF9wY2EodGNfbmV1dHJvcGhpbHNfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKdGNfbmV1dHJvcGhpbHNfcGNhCmBgYAoKIyMjIFBhbmVsIEUKClNlY3Rpb24gOS4xIG9mIDAydmlzdWFsaXphdGlvbjogIkJpb3BzaWVzIgoKYGBge3IsIGV2YWw9RkFMU0V9CnRjX2Jpb3BzaWVzX3BjYSA8LSBwbG90X3BjYSh0Y19iaW9wc2llc19ub3JtKQp0Y19iaW9wc2llc19wY2EKYGBgCgojIyBGaWd1cmUgNAoKIyMjIFBhbmVsIEEsIGxlZnQKClNlY3Rpb24gMTAuMi40ICJGaWd1cmUgNEE6IE1vbm9jeXRlcyIKCmBgYHtyLCBldmFsPUZBTFNFfQp0X21vbm9jeXRlX3BjYSA8LSBwbG90X3BjYSh0X21vbm9jeXRlX25vcm0sCiAgcGxvdF9sYWJlbHMgPSBGQUxTRSkKdF9tb25vY3l0ZV9wY2EKYGBgCgojIyMgUGFuZWwgQSwgbWlkZGxlCgpTZWN0aW9uIDEwLjIuOCAiRmlndXJlIDRBOiBFb3Npbm9waGlscyIKCmBgYHtyLCBldmFsPUZBTFNFfQp0X2Vvc2lub3BoaWxfcGNhIDwtIHBsb3RfcGNhKHRfZW9zaW5vcGhpbF9ub3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RfbGFiZWxzID0gRkFMU0UpCnRfZW9zaW5vcGhpbF9wY2EKYGBgCgojIyMgUGFuZWwgQSwgcmlnaHQKClNlY3Rpb24gMTAuMi42ICJGaWd1cmUgNEE6IE5ldXRyb3BoaWxzIgoKYGBge3IsIGV2YWw9RkFMU0V9CnRfbmV1dHJvcGhpbF9wY2EgPC0gcGxvdF9wY2EodF9uZXV0cm9waGlsX25vcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdF9sYWJlbHMgPSBGQUxTRSkKdF9uZXV0cm9waGlsX3BjYQpgYGAKCiMjIFBhbmVsIEIKClRoZXNlIG1vdmUgdG8gdGhlIGRvY3VtZW50IDA0ZGlmZmVyZW50aWFsX2V4cHJlc3Npb25fdHVtYWNvLgoKIyMjIFBhbmVsIEIsIGxlZnQsIG1pZGRsZSwgYW5kIHJpZ2h0CgpTZWN0aW9uIDcuMC40ICJGaWd1cmUgNEI6IFZvbGNhbm8gcGxvdHMiICBGb3Igc29tZSByZWFzb24gSSBkaWQgbm90CmhhdmUgc2VwYXJhdGUgc2VjdGlvbnMgZm9yIGVhY2ggY2VsbCB0eXBlLgoKYGBge3IsIGV2YWw9RkFMU0V9Cm51bV9jb2xvciA8LSBjb2xvcl9jaG9pY2VzW1siY2xpbmljX2NmIl1dW1sidHVtYWNvX2ZhaWx1cmUiXV0KZGVuX2NvbG9yIDwtIGNvbG9yX2Nob2ljZXNbWyJjbGluaWNfY2YiXV1bWyJ0dW1hY29fY3VyZSJdXQp3YW50ZWRfZ2VuZXMgPC0gYygiRkk0NEwiLCAiSUZJMjciLCAiUFJSNSIsICJQUlI1LUFSSEdBUDgiLCAiUkhDRSIsCiAgICAgICAgICAgICAgICAgICJGQlhPMzkiLCAiUlNBRDIiLCAiU01UTkwxIiwgIlVTUDE4IiwgIkFGQVAxIikKCmNmX21vbm9jeXRlX3RhYmxlIDwtIHRfY2ZfbW9ub2N5dGVfdGFibGVfc3ZhW1siZGF0YSJdXVtbIm91dGNvbWUiXV0KY2ZfbW9ub2N5dGVfdm9sY2FubyA8LSBwbG90X3ZvbGNhbm9fY29uZGl0aW9uX2RlKAogIGNmX21vbm9jeXRlX3RhYmxlLCAib3V0Y29tZSIsIGxhYmVsID0gd2FudGVkX2dlbmVzLAogIGZjX2NvbCA9ICJkZXNlcV9sb2dmYyIsIHBfY29sID0gImRlc2VxX2FkanAiLCBsaW5lX3Bvc2l0aW9uID0gTlVMTCwKICBjb2xvcl9oaWdoID0gbnVtX2NvbG9yLCBjb2xvcl9sb3cgPSBkZW5fY29sb3IsIGxhYmVsX3NpemUgPSA2KQpwcChmaWxlID0gZ2x1ZSgiaW1hZ2VzL2NmX21vbm9jeXRlX3ZvbGNhbm9fbGFiZWxlZC12e3Zlcn0uc3ZnIikpCmNmX21vbm9jeXRlX3ZvbGNhbm9bWyJwbG90Il1dCmRldi5vZmYoKQpgYGAKCiMjIyBQYW5lbCBDCgpUT0RPOiBBZGQgc2ltaWxhciB2ZW5uIH4gc2VjdGlvbiA4CgpJIHBsYXllZCB3aXRoIHZlcnNpb25zIG9mIHRoaXMgdXNpbmcgQVVDQyBhbmQgVXBTZXQgcGxvdHMgdGhyb3VnaG91dAp0aGUgMDRkaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl90dW1hY28gZG9jdW1lbnQ7IGJ1dCBkaWQgbm90IGdlbmVyYXRlCnRoaXMgc3BlY2lmaWMgaW1hZ2UuICAoTWF5YmUgSSBzaG91bGQgbWFrZSBhIHZlcnNpb24gb2YgaXQ/KQoKIyMgRmlndXJlIDUKClRPRE86IENsYXJpZnkgc2VjdGlvbiBuYW1lcwoKSSBkaWQgbm90IHBlcmZvcm0gYW55IG9mIHRoZSBTVFJJTkcgYW5hbHlzZXMgYW5kIHRoZXJlZm9yZSBhbSB1bmFibGUKdG8gY29tbWVudCBvbiBwYW5lbHMgQSxDLEUsRy4gIEkgc2hvdWxkIGJ1ZyBBbGVqYW5kcm8uCgpUaGUgbG93ZXIgcGFuZWxzIGFyZSBhbGwgY29taW5nIGZyb20gMDVlbnJpY2htZW50IGFuZCBhcmUgdXNpbmcgdGhlCnRyZWVwbG90KCkgcmVzdWx0IGZyb20gZ290ZXJtc2ltKCkgb2YgdGhlIGdQcm9maWxlcjIgcmVzdWx0cy4KCiMjIyBQYW5lbCBCCgowNWVucmljaG1lbnQsIHNlY3Rpb24gMi4xMC4xICJnUHJvZmlsZXIiIChJIGFtIGdvaW5nIHRvIGNoYW5nZSB0aGVzZQpoZWFkaW5ncyB0byBiZSBhIGJpdCBtb3JlIGluZm9ybWF0aXZlLi4uKQoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jZl9lb3Npbm9waGlsX3NpZ19zdmFfdXAsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9lb3Npbm9waGlsX3VwX2dwLXZ7dmVyfS54bHN4IikpCnRfY2ZfZW9zaW5vcGhpbF9zaWdfc3ZhX3VwX2dwCmBgYAoKIyMjIFBhbmVsIEQKCjA1ZW5yaWNobWVudCwgU2VjdGlvbiAyLjEyLjEgImdQcm9maWxlciIuCgpgYGB7ciwgZXZhbD1GQUxTRX0KdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX25ldXRyb3BoaWxfc2lnX3N2YV91cCwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX25ldXRyb3BoaWxfdXBfZ3Atdnt2ZXJ9Lnhsc3giKSkKdF9jZl9uZXV0cm9waGlsX3NpZ19zdmFfdXBfZ3AKYGBgCgojIyMgUGFuZWwgRgoKSWJpZCwgU2VjdGlvbiAyLjExLjEgImdQcm9maWxlciIKCmBgYHtyLCBldmFsPUZBTFNFfQp0X2NmX21vbm9jeXRlX3NpZ19zdmFfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcigKICB0X2NmX21vbm9jeXRlX3NpZ19zdmFfdXAsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9tb25vY3l0ZV91cF9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX21vbm9jeXRlX3NpZ19zdmFfdXBfZ3AKYGBgCgojIyMgUGFuZWwgSAoKSWJpZCwgU2VjdGlvbiAyLjQuMSAiZ1Byb2ZpbGVyIiBidXQgaXQgaXMgcHJldHR5IGZhciBkb3duOyBqdXN0IGJlZm9yZQp0aGUgY2x1c3RlclByb2ZpbGVyIGFuYWx5c2VzLgoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2ZfY2xpbmljYWxuYl9ncF9kb3duIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgdF9jbGluaWNhbG5iX2NmX3NpZ19zdmFfZG93biwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfT3ZlcnJlcHJlc2VudGF0aW9uL2NsaW5pY2FsbmJfZmFpbF91cF9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX2NsaW5pY2FsbmJfZ3BfZG93bgoKIyMgYW5kCgpnb190ZXJtc2ltIDwtIGVucmljaHBsb3Q6OnBhaXJ3aXNlX3Rlcm1zaW0odF9jZl9jbGluaWNhbG5iX2dwX2Rvd25bWyJCUF9lbnJpY2giXV0pCnRfY2ZfY2xpbmljYWxuYl9ncF9nb19kb3duX3RyZWUgPC0gc20oZW5yaWNocGxvdDo6dHJlZXBsb3QoZ29fdGVybXNpbSkpCnBwKGZpbGUgPSAiaW1hZ2VzL292ZXJyZXByZXNlbnRhdGlvbi90X2NmX2NsaW5pY2FsbmJfZ3BfZG93bl90cmVlLnBkZiIsCiAgIHdpZHRoID0gdHJlZXBsb3Rfd2lkdGgsIGhlaWdodCA9IHRyZWVwbG90X2hlaWdodCkKdF9jZl9jbGluaWNhbG5iX2dwX2dvX2Rvd25fdHJlZQpkZXYub2ZmKCkKYGBgCgojIyBGaWd1cmUgUzEKClRPRE86IENsYXJpZnkgc2VjdGlvbnMKCkhlYWQgYmFjayB0byAwMnZpc3VhbGl6YXRpb247IHRoaXMgaXMgd2hlcmUgVGhlcmVzYSB0YXVnaHQgbWUKcmVncmVzc2lvbiBhbmFseXNpcyEKCiMjIyBQYW5lbCBBCgowMnZpc3VhbGl6YXRpb24sIE5lYXIgdGhlIGJvdHRvbSBvZiBzZWN0aW9uIDcuMiAiUmVncmVzc2lvbiBhbmFseXNlcwp2cyBvdXRjb21lIiAgKEkgbmVlZCB0byByZW5hbWUgdGhlc2Ugc2VjdGlvbnMgdG9vLCB0aGVzZSBhcmUgY3Jvc3MKY29ycmVsYXRpb25zLCBub3QgcmVncmVzc2lvbjsgSSB1c2VkIHRvIGhhdmUgdGhlbSBhbGwgdG9nZXRoZXIgaW4gYQpiaWcgcGlsZSBhbmQgc3BsaXQgdGhlbSB1cCwgYnV0IGRpZG4ndCBwcm9wZXJseSByZW5hbWUgdGhlIGhlYWRpbmdzLikKCmBgYHtyLCBldmFsPUZBTFNFfQp0X3JlZ3Jlc3Npb25fcXVlcmllcyA8LSBjKCJXZWlnaHQiLCAiU2V4IiwgIkV0aG5pY2l0eSIsICJBZ2UiKQp0X2Nyb3NzX2RmIDwtIHRfcmVncmVzc2lvbl9udW1lcmljWywgdF9yZWdyZXNzaW9uX3F1ZXJpZXNdCnRfcmVncmVzc2lvbl9jcm9zcyA8LSBjb3JyX2Nyb3NzKHRfY3Jvc3NfZGYpCnBwKGZpbGUgPSAiZmlndXJlcy90dW1hY29fd2VpZ2h0X3NleF9ldGhuaWNpdHlfYWdlX251bWVyaWNfY3Jvc3Njb3Iuc3ZnIikKdF9yZWdyZXNzaW9uX2Nyb3NzCmRldi5vZmYoKQpgYGAKCiMjIyBQYW5lbCBCCgowMnZpc3VhbGl6YXRpb24sIDcuMi4xICJDb3B5IHRoZXNlIHdpdGggb25seSB0aGUgVHVtYWNvIHBlb3BsZSIKCmBgYHtyLCBldmFsPUZBTFNFfQpyZWdyZXNzaW9uX3Rlc3RzIDwtIGMoIkFnZSIsICJDbGluaWMiLCAiRXRobmljaXR5IiwgIlNleCIsICJXZWlnaHQiKQpsbV9yZWdyZXNzaW9uX2RlbW9ncmFwaGljcyA8LSBleHRyYWN0X2xpbmVhcl9yZWdyZXNzaW9uKAogIHJlZ3Jlc3Npb25fbnVtZXJpYywgcXVlcnkgPSAiVGhlcmFwZXV0aWNfT3V0Y29tZV9GaW5hbCIsIGZhY3RvcnMgPSByZWdyZXNzaW9uX3Rlc3RzLAogIGV4Y2VsID0gZ2x1ZSgiZXhjZWwvbnVtZXJpY19kZW1vZ3JhcGhpY3NfcmVncmVzc2lvbl9maW5hbF9zZXhfY2xpbmljX2V0aG5pY2l0eV9hZ2Utdnt2ZXJ9Lnhsc3giKSkKCiMjIGFuZAoKcHAoZmlsZSA9ICJpbWFnZXMvZGVtb2dyYXBoaWNzX29ubHlfbGluZWFyX3JlZ3Jlc3Npb24uc3ZnIikKbG1fcmVncmVzc2lvbl9kZW1vZ3JhcGhpY3NbWyJmb3Jlc3QiXV0KZGV2Lm9mZigpCmBgYAoKIyMjIFBhbmVsIEMKCkliaWQsIFNlY3Rpb24gNy4yLjIKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19sb2dfaXRlcmF0aXZlX3JlZ3Jlc3Npb25fZGVtb2dyYXBoaWNzIDwtIGl0ZXJhdGVfbG9naXN0aWNfcmVncmVzc2lvbigKICByZWdyZXNzaW9uX2RmLCBxdWVyeSA9ICJUaGVyYXBldXRpY19PdXRjb21lX0ZpbmFsIiwgZmFjdG9ycyA9IHJlZ3Jlc3Npb25fdGVzdHMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC90Y19zaW1wbGVfbG9naXN0aWNfcmVncmVzc2lvbi12e3Zlcn0ueGxzeCIpKQoKIyMgYW5kCgpwcChmaWxlID0gZ2x1ZSgiZmlndXJlcy90Y19zaW1wbGVfbG9naXN0aWNfcmVncmVzc2lvbi12e3Zlcn0uc3ZnIikpCnRjX2xvZ19pdGVyYXRpdmVfcmVncmVzc2lvbl9kZW1vZ3JhcGhpY3NbWyJmb3Jlc3QiXV0KZGV2Lm9mZigpCmBgYAoKIyMjIFBhbmVsIEQKCkliaWQuCgpgYGB7ciwgZXZhbD1GQUxTRX0KdF9sb2dfcmVncmVzc2lvbl9kZW1vZ3JhcGhpY3MgPC0gZXh0cmFjdF9sb2dpc3RpY19yZWdyZXNzaW9uKAogIHRfcmVncmVzc2lvbl9kZiwgcXVlcnkgPSAiVGhlcmFwZXV0aWNfT3V0Y29tZV9GaW5hbCIsIGZhY3RvcnMgPSB0X3JlZ3Jlc3Npb25fdGVzdHMsCiAgZXhjZWwgPSBnbHVlKCJleGNlbC90X211bHRpdmFyaWFibGVfbG9naXN0aWNfcmVncmVzc2lvbi12e3Zlcn0ueGxzeCIpKQoKIyMgYW5kCgpwcChmaWxlID0gZ2x1ZSgiZmlndXJlcy90X211bHRpdmFyaWFibGVfbG9naXN0aWNfcmVncmVzc2lvbi12e3Zlcn0uc3ZnIikpCnRfbG9nX3JlZ3Jlc3Npb25fZGVtb2dyYXBoaWNzW1siZm9yZXN0Il1dCmRldi5vZmYoKQpgYGAKCiMjIyBQYW5lbHMgRSBhbmQgRgoKVE9ETzogcmVhZGQKCkhtbSBJIGRlbGV0ZWQgdGhlc2UgZnJvbSBteSBub3RlYm9vaywgSSBkaWQgbm90IHRoaW5rIHdlIHdlcmUgZ29pbmcgdG8KdXNlIHRoZW0gYnV0IGluc3RlYWQgb25seSBpbmNsdWRlIEMvRC4gIEFkZGluZyB0aGVtIGJhY2sgbW9tZW50YXJpbHkuCgojIyBGaWd1cmUgUzIKCiMjIyBQYW5lbCBCL0MKClRoZXNlIGFyZSB3YWF5IGRvd24gaW4gU2VjdGlvbiAxNiAiUGFyYXNpdGUgZGlzdHJpYnV0aW9uIiBvZiAwMnZpc3VhbGl6YXRpb24uCgpgYGB7ciwgZXZhbD1GQUxTRX0KbHBfY2Zfbm9ybV9wY2EgPC0gcGxvdF9wY2EobHBfY2Zfbm9ybSkKYGBgCgojIyBGaWd1cmUgUzQKClRPRE86IHJlbmFtZSBzZWN0aW9uCgpPbmUgbXVzdCByZXR1cm4gdG8gMDFkYXRhc3RydWN0dXJlcyBmb3IgdGhpcyBpbWFnZS4gIEl0IHdhcyB1c2VkIHRvCmRlZmluZSB0aGUgY292ZXJhZ2UgY3V0b2ZmIGZvciBmaWx0ZXJpbmcgc2FtcGxlcyBhbmQgaXMgZm91bmQgYXQKc2VjdGlvbiA3LjIgIkZpZ3VyZSBTMjogTm9uLXplcm8gZ2VuZXMgYmVmb3JlIHNhbXBsZSBmaWx0ZXJpbmciICAoSQpndWVzcyBJIHNob3VsZCByZW5hbWUgdGhpcyB0b28pCgpgYGB7ciwgZXZhbD1GQUxTRX0KYWxsX256IDwtIHBsb3Rfbm9uemVybyhoc19leHB0KQpgYGAKCiMjIEZpZ3VyZSBTNQoKVGhlc2UgYXJlIGFsbCBzY2F0dGVyZWQgdGhyb3VnaCAwMnZpc3VhbGl6YXRpb24uCgojIyMgUGFuZWwgQQoKU2VjdGlvbiA5LjggIkNvbXBhcmUgY2xpbmljcyIKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19jbGluaWNfdHlwZV9wY2EgPC0gcGxvdF9wY2EodGNfY2xpbmljX3R5cGVfbm9ybSkKdGNfY2xpbmljX3R5cGVfcGNhCmBgYAoKIyMjIFBhbmVsIEIKClNlY3Rpb24gOS41ICJFb3Npbm9waGlscyBieSBjbGluaWMiICBObyBmYWlscyBmcm9tIENhbGkgZm9yCkVvc2lub3BoaWxzIQoKYGBge3IsIGV2YWw9RkFMU0V9CnRjX2Vvc2lub3BoaWxzX3BjYSA8LSBwbG90X3BjYSh0Y19lb3Npbm9waGlsc19ub3JtLCBwbG90X2xhYmVscyA9IEZBTFNFKQp0Y19lb3Npbm9waGlsc19wY2EKYGBgCgojIyMgUGFuZWwgQwoKU2VjdGlvbiA5LjYgIk1vbm9jeXRlcyBieSBjbGluaWMiCgpgYGB7ciwgZXZhbD1GQUxTRX0KdGNfbW9ub2N5dGVzX3BjYSA8LSBwbG90X3BjYSh0Y19tb25vY3l0ZXNfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKdGNfbW9ub2N5dGVzX3BjYQpgYGAKCiMjIyBQYW5lbCBECgpTZWN0aW9uIDkuNyAiTmV1dHJvcGhpbHMgYnkgY2xpbmljIgoKYGBge3IsIGV2YWw9RkFMU0V9CnRjX25ldXRyb3BoaWxzX3BjYSA8LSBwbG90X3BjYSh0Y19uZXV0cm9waGlsc19ub3JtLCBwbG90X2xhYmVscyA9IEZBTFNFKQp0Y19uZXV0cm9waGlsc19wY2EKYGBgCgojIyMgUGFuZWwgRQoKU2VjdGlvbiA5LjEgIkJpb3BzaWVzIGJ5IGNsaW5pYyIKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19iaW9wc2llc19wY2EgPC0gcGxvdF9wY2EodGNfYmlvcHNpZXNfbm9ybSkKdGNfYmlvcHNpZXNfcGNhCmBgYAoKIyMjIFBhbmVsIEYKCkF0IHRoZSBib3R0b20gb2Ygc2VjdGlvbiA5LjIuMyAiRW9zaW5vcGhpbCBzYW1wbGVzLCBib3RoIGNsaW5pY3MiCgpgYGB7ciwgZXZhbD1GQUxTRX0KcGxvdF9wY2EoZXRuaWFfZW9fbmIpCmBgYAoKIyMjIFBhbmVsIEcKCkF0IHRoZSBib3R0b20gb2Ygc2VjdGlvbiA5LjIuNCAiTW9ub2N5dGUgc2FtcGxlcywgYm90aCBjbGluaWNzIgoKYGBge3IsIGV2YWw9RkFMU0V9CnBsb3RfcGNhKGV0bmlhX21vX25iKQpgYGAKCiMjIyBQYW5lbCBICgpBdCB0aGUgYm90dG9tIG9mIHNlY3Rpb24gOS4yLjUgIk5ldXRyb3BoaWwgc2FtcGxlcywgYm90aCBjbGluaWNzIgoKYGBge3IsIGV2YWw9RkFMU0V9CnBsb3RfcGNhKGV0bmlhX25lX25iKQpgYGAKCiMjIEZpZ3VyZSBTNgoKVE9ETzogU29tZW9uZSBhc2tlZCBtZSB0byBjaGFuZ2VzIHRoZXNlIGNvbG9ycyB0byB0aGlzIHZpY2lvdXMgc2V0IG9mCmdyZWVucy4gIFRoZSBvcmlnaW5hbCBibGFjay9ncmV5L3doaXRlIGlzIG5pY2VyLgoKIyMjIFBhbmVsIEEvQi9DCgpUaGVzZSBpbWFnZXMgYXJlIHNjYXR0ZXJlZCB0aHJvdWdoIHNlY3Rpb24gMTEuNC4xICJDb21wYXJpbmcgMyB2aXNpdHMKYnkgY2VsbCB0eXBlIiAoSSBjaGFuZ2VkIHRoZSBjb2xvcnMgYmFjayBqdXN0IG5vdyAyMDI0MDkxOSwgdGhvc2UKZ3JlZW5zIGFyZSBhIGhvcnJvciBzaG93LCB3aGVyZSB3YXMgQXByaWwgdG8geWVsbCBhdCBtZSE/KQoKYGBge3IsIGV2YWw9RkFMU0V9CnRfdmlzaXRfbW9ub2N5dGVfbm9ybV9wY2EgPC0gcGxvdF9wY2EodF92aXNpdF9tb25vY3l0ZV9ub3JtLCBwbG90X2xhYmVscyA9IEZBTFNFKQpwcChmaWxlID0gImltYWdlcy90X21vbm9jeXRlX3Zpc2l0X25vcm1fcGNhLnBkZiIpCnRfdmlzaXRfbW9ub2N5dGVfbm9ybV9wY2EkcGxvdApkZXYub2ZmKCkKCiMjIHJlcGxhY2UgbW9ub2N5dGUgd2l0aCB0aGUgcmVsZXZhbnQgY2VsbHR5cGVzIGZvciB0aGUgb3RoZXJzLgpgYGAKCiMjIyBQYW5lbCBECgpUaGVzZSBib3R0b20gcGFuZWxzIGFyZSBjb21wYXJpbmcgbXkgc2ltcGxpZmllZCBtb2RlbCB0byBhIG1vcmUKdGhvcm91Z2ggdmlzaXQtaW4tbW9kZWwgYW5hbHlzaXMuICBUaGlzIGZpcnN0LCBtb25vY3l0ZSBjb21wYXJpc29uIGlzCmluIHNlY3Rpb24gNi4wLjIgb2YgMDRkaWZmZXJlbnRpYWxfZXhwcmVzc2lvbl90dW1hY28uCgpOb3RlLCBocGdsdG9vbHMgaXMgbm93IGFibGUgdG8gaGFuZGxlIGFyYml0cmFyaWx5IGNvbXBsZXggbW9kZWxzCmFjcm9zcyBhbGwgbWV0aG9kcyAoZGVzZXEvZWRnZXIvZXRjLi4uKSB0aG91Z2ggSSBkaWRuJ3QgZmluaXNoIGl0CnVudGlsIGEgZmV3IGRheXMgYWdvIGFuZCBpdCBoYXMgbm90IHlldCBiZWVuIGZ1bGx5IHRlc3RlZC4KCmBgYHtyLCBldmFsPUZBTFNFfQojIyBUaGUgb3JpZ2luYWwgcGFpcndpc2UgaW52b2NhdGlvbiB3aXRoIHN2YToKIyN0X2NmX21vbm9jeXRlX2RlX3N2YSA8LSBhbGxfcGFpcndpc2UodF9tb25vY3l0ZSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgcGFyYWxsZWwgPSBGQUxTRSwKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kcyA9IG1ldGhvZHMpCnRlc3RfbW9ub2N5dGVzIDwtIG5vcm1hbGl6ZV9leHB0KHRfbW9ub2N5dGVzLCBmaWx0ZXIgPSAic2ltcGxlIikKYGBgCgpUaGlzIGNvbnRpbnVlcyBmb3IgYSBmZXcgYmxvY2tzIG9mIHJlbGF0aXZlbHkgZGVuc2UgY29kZSBpbnZva2luZyBzdmEKd2l0aCBhIG1vZGVsIGNvbnRhaW5pbmcgdmlzaXQgbnVtYmVyLgoKIyMjIFBhbmVsIEUKCkliaWQsIHNlY3Rpb24gNy4wLjMKClRoaXMgc2VjdGlvbiBpcyBuZWFybHkgaWRlbnRpY2FsbHkgZGVuc2UsIGFuZCBzdGFydHMgd2l0aCB0aGUgZm9sbG93aW5nOgoKYGBge3IsIGV2YWw9RkFMU0V9CiMjIFRoZSBvcmlnaW5hbCBwYWlyd2lzZSBpbnZvY2F0aW9uIHdpdGggc3ZhOgojdF9jZl9lb3Npbm9waGlsX2RlX3N2YSA8LSBhbGxfcGFpcndpc2UodF9lb3Npbm9waGlscywgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIHBhcmFsbGVsPUZBTFNFLCBtZXRob2RzID0gbWV0aG9kcykKdGVzdF9lb3Npbm9waGlscyA8LSBub3JtYWxpemVfZXhwdCh0X2Vvc2lub3BoaWxzLCBmaWx0ZXIgPSAic2ltcGxlIikKYGBgCgojIyMgUGFuZWwgRgoKSWJpZCwgc2VjdGlvbiA3LjAuMgoKVE9ETzogVGhpcyBwb3J0aW9uIG9mIHRoZSAwNGRpZmZlcmVudGlhbF9leHByZXNzaW9uX3R1bWFjbyBpcyBwb29ybHkKb3JnYW5pemVkLgoKYGBge3IsIGV2YWw9RkFMU0V9CiMjIFRoZSBvcmlnaW5hbCBwYWlyd2lzZSBpbnZvY2F0aW9uIHdpdGggc3ZhOgojIyB0X2NmX25ldXRyb3BoaWxfZGVfc3ZhIDwtIGFsbF9wYWlyd2lzZSh0X25ldXRyb3BoaWxzLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLAojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbGxlbCA9IHBhcmFsbGVsLCBmaWx0ZXIgPSBUUlVFLAojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2RzID0gbWV0aG9kcykKdGVzdF9uZXV0cm9waGlscyA8LSBub3JtYWxpemVfZXhwdCh0X25ldXRyb3BoaWxzLCBmaWx0ZXIgPSAic2ltcGxlIikKYGBgCgojIyBGaWd1cmUgUzcKClRoaXMgaW1hZ2VzIGhhcmtlbiBiYWNrIHRvIDAydmlzdWFsaXphdGlvbgoKIyMjIFBhbmVsIEEKClNlY3Rpb24gMTAuMi4xIG9mIDAydmlzdWFsaXphdGlvbgoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2xpbmljYWxfbm9iaW9wX3BjYSA8LSBwbG90X3BjYSh0X2NsaW5pY2FsX25vYmlvcF9ub3JtLCBwbG90X2xhYmVscyA9IEZBTFNFKQpwcChmaWxlID0gImZpZ3VyZXMvdF9jbGluaWNhbF9ub2Jpb3BfZmlneHhhLnBkZiIpCnRfY2xpbmljYWxfbm9iaW9wX3BjYVtbInBsb3QiXV0KZGV2Lm9mZigpCmBgYAoKIyMjIFBhbmVsIEIKClRoZSBuZXh0IGltYWdlIGluIDEwLjIKClRPRE86IENoZWNrIHRoYXQgdGhlIGRldmljZSBpcyBwcm9wZXJseSBjcmVhdGluZyBwZGZzIGluIHRoaXMgc2VjdGlvbjsKaXQgbG9va3MgbGlrZSBpdCBtaWdodCBiZSBjcmVhdGluZyBwbmdzIGZvciBzb21lIG9mIHRoZXNlPwoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2xpbmljYWxfbm9iaW9wX25iX3BjYSA8LSBwbG90X3BjYSh0X2NsaW5pY2FsX25vYmlvcF9uYiwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKcHAoZmlsZSA9ICJmaWd1cmVzL3RfY2xpbmljYWxfbm9iaW9wX3N2YV9maWd4eGIucGRmIikKdF9jbGluaWNhbF9ub2Jpb3BfbmJfcGNhW1sicGxvdCJdXQpkZXYub2ZmKCkKYGBgCgojIyBGaWd1cmUgUzgsIFM5LCBTMTAKClRoZXNlIGFyZSBub3QgaW4gbXkgbm90ZWJvb2tzLgoKIyMgRmlndXJlIFMxMQoKIyMjIFBhbmVsIEEKClNlY3Rpb24gMTAuMi4xCgpgYGB7ciwgZXZhbD1GQUxTRX0KdGNfY2xpbmljYWxfbm9iaW9wX3BjYSA8LSBwbG90X3BjYSh0Y19jbGluaWNhbF9ub2Jpb3Bfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKcHAoZmlsZSA9ICJmaWd1cmVzL3RjX2NsaW5pY2FsX25vYmlvcF9maWd4eGMucGRmIikKdGNfY2xpbmljYWxfbm9iaW9wX3BjYVtbInBsb3QiXV0KYGBgCgojIyMgUGFuZWwgQgoKYW5kIHRoZSBpbW1lZGlhdGVseSBmb2xsb3dpbmcgaW1hZ2UKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19jbGluaWNhbF9ub2Jpb3BfbmJfcGNhIDwtIHBsb3RfcGNhKHRjX2NsaW5pY2FsX25vYmlvcF9uYiwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKcHAoZmlsZSA9ICJmaWd1cmVzL3RjX2NsaW5pY2FsX25vYmlvcF9zdmFfZmlneHhkLnBkZiIpCnRjX2NsaW5pY2FsX25vYmlvcF9uYl9wY2FbWyJwbG90Il1dCmRldi5vZmYoKQpgYGAKCiMjIyBQYW5lbCBDCgpJIHRoaW5rIHRoaXMgaXMgdGhlIG9ubHkgaW1hZ2UgdGFrZW4gZnJvbQowM2RpZmZlcmVudGlhbF9leHByZXNzaW9uX2JvdGg7IGl0IGNvbWVzIGZyb20gc2VjdGlvbiA1LjIuMTsgaW4gbXkKbGFzdCBpdGVyYXRpb24gb2YgdGhlIG5vdGVib29rIGl0IGZhaWxlZCBiZWNhdXNlIEkgZm9yZ290IHRvIHRlbGwgaXQKdG8gdXNlIHRoZSBjb2xvcl9jaG9pY2VzIChmaXhlZCkKCmBgYHtyLCBldmFsPUZBTFNFfQp0Y19jbGluaWNhbF9jZl9kZV9iYXRjaCA8LSBhbGxfcGFpcndpc2UodGNfY2xpbmljYWxfbm9iaW9wLCBmaWx0ZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYWxsZWwgPSBwYXJhbGxlbCwgbW9kZWxfYmF0Y2ggPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kcyA9IG1ldGhvZHMpCmBgYAoKIyMgVGFibGUgUzEKClRoaXMgd2FzIG1hbnVhbGx5IGNvbGxhdGVkIGJ5IE1hcmlhIEFkZWxhaWRhOyBJIHRoaW5rIGFsbCB0aGUgbnVtYmVycwpkbyBjb3JyZXNwb25kIHRvIHRoZSByZWdyZXNzaW9uIGYtdmFsdWVzL3AtdmFsdWVzLgoKIyMgVGFibGUgUzIKClRoaXMgaXMgYSB2ZXJ5IHNsaWdodGx5IG1vZGlmaWVkIGNvcHkgb2YgdGhlIHNhbXBsZSBzaGVldCBpbgpzYW1wbGVfc2hlZXRzL3RtcmMzX3NhbXBsZXNfcHJ1bmVkLnhsc3ggIE9uZSBub3Rld29ydGh5IHRoaW5nOiBpZiBvbmUKcmVwcm9jZXNzZXMgdGhlIHJhdyBkYXRhIGFuZCBydW5zICdnYXRoZXJfcHJlcHJvY2Vzc2luZ19tZXRhZGF0YSgpJywKaXQgd2lsbCBzdWNrIHVwIGFsbCB0aGUgbG9ncyBmcm9tIGFueSB0b29scyBmb3Igd2hpY2ggSSBoYXZlIHdyaXR0ZW4KcmVnZXhlcyBhbmQgYXBwZW5kIHRoZSByZXN1bHRzIGFzIGNvbHVtbnMgYXQgdGhlIHJpZ2h0IG9mIHRoaXMuICBJIGFtCm1vcmUgdGhhbiBhIGxpdHRsZSBwcm91ZCBvZiB0aGF0LgoKIyMgVGFibGUgUzMKClRoaXMgaXMgYSBzbGlnaHRseSBtb2RpZmllZCBjb3B5IG9mIHRoZSByZXN1bHQgb2YgdGhlICdzdnBjX2ZzdGF0cygpJwppbnZvY2F0aW9ucyBmb3VuZCBhdCB0aGUgZW5kIG9mIFNlY3Rpb24gMTcgaW4gMDJ2aXN1YWxpemF0aW9uLiAgKG15CmxpdHRsZSBmdW5jdGlvbiBhZGRzIGEgZnVua3kgaGVhdG1hcCB0byB0aGUgb3V0cHV0KQoKYGBge3IsIGV2YWw9RkFMU0V9CnF1ZXJpZXMgPC0gYygidHlwZW9mY2VsbHMiLCAidmlzaXRudW1iZXIiLCAiY2xpbmljIiwgImRvbm9yIikKdGNfY2xpbmljYWxfZnBzdGF0cyA8LSBzdnBjX2ZzdGF0cyh0Y19jbGluaWNhbCwgbnVtX3BjcyA9IDUsIHF1ZXJpZXMgPSBxdWVyaWVzKQpgYGAKCiMjIFRhYmxlIFM0CgpUaGlzIGlzIGEgc2xpZ2h0bHkgbW9kaWZpZWQgY29weSBvZiB0d28gcmVzdWx0czoKCiMjIyBCaW9wc2llcyBERQoKVGhpcyBpcyBhIG1vZGlmaWVkIHZlcnNpb24gb2YgdGhlIHJlc3VsdCB3aGVuIG9uZSBpbnZva2VzCmNvbWJpbmVfZGVfdGFibGVzKCksIGFzIHBlciBzZWN0aW9uIDYuMC4yIG9mCjA0ZGlmZmVyZW50aWFsX2V4cHJlc3Npb25fdHVtYWNvOyB0aGlzIGNvbnRhaW5lciBzaG91bGQgdGhlcmVmb3JlCnByb3ZpZGUgdGhvc2UgbnVtYmVycyBpZiBvbmUgbG9va3MgaW4KJ2FuYWx5c2VzLzRfdHVtYWNvL0RFX0N1cmVfRmFpbC9CaW9wc2llcy90X2Jpb3BzeV9jZl90YWJsZV9zdmEtdjIwMjQwOS54bHN4JwpUaGF0IHhsc3ggd29ya2Jvb2sgaGFzIGEgd29ya3NoZWV0IG5hbWVkICdvdXRjb21lJyAodGhlIHNlY29uZCk7IHRoaXMKd29ya3NoZWV0IGNvbXByaXNlcyBjb2x1bW5zIFEtViBmcm9tIGl0LiAgKGFsc28geWF5ISB0aGUgbnVtYmVycyBhcmUKdGhlIHNhbWUgYmV0d2VlbiBteSBjb250YWluZXIgKHdoaWNoIGNoYW5nZXMgY29uc3RhbnRseSBhbmQgZ2V0cwpyZWJ1aWx0IHdpdGggZWFjaCBjaGFuZ2UpIGFuZCB0aGUgY29weSB0aGF0IHdhcyB1c2VkIGZvciB0aGUgcGFwZXIhKQoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2ZfYmlvcHN5X3RhYmxlX3N2YSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICB0X2NmX2Jpb3BzeV9kZV9zdmEsIGtlZXBlcnMgPSB0X2NmX2NvbnRyYXN0LAogIGV4Y2VsID0gZ2x1ZSgie2NmX3ByZWZpeH0vQmlvcHNpZXMvdF9iaW9wc3lfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IikpCnRfY2ZfYmlvcHN5X3RhYmxlX3N2YQpgYGAKCiMjIyBCaXBzaWVzIEdPCgpMb29raW5nIG1vcmUgY2FyZWZ1bGx5IGF0IHRoaXMsIEkgdGhpbmsgdGhpcyBpcyBub3QgZnJvbSBteQpvdmVycmVwcmVzZW50YXRpb24gYW5hbHlzaXM7IGJ1dCBjYW1lIGZyb20gU1RSSU5HPwoKVGhlIGludm9jYXRpb24gZm9yIG15IHZlcnNpb24gb2YgdGhpcyByZXNpZGVzIGluIDA1ZW5yaWNobWVudCwgc2VjdGlvbgoyLjkuMSBhbmQgdGhlIHhsc3ggZmlsZSBpbiB0aGUgY29udGFpbmVyIHNob3VsZCBiZSBmb3VuZCBpbgonYW5hbHlzZXMvR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX2Jpb3BzeV9zaWdfc3ZhX3VwX2dwLXYyMDI0MDkueGxzeCcKZm9yIGdQcm9maWxlciwgYW5kIHdpdGggYSBzaW1pbGFyIG5hbWUgY29udGFpbmluZyAnY3AnIGZvcgpjbHVzdGVyUHJvZmlsZXIuCgpgYGB7ciwgZXZhbD1GQUxTRX0KdF9jZl9iaW9wc3lfc2lnX3N2YV9ncF91cCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKAogIHRfY2ZfYmlvcHN5X3NpZ19zdmFfdXAsCiAgZXhjZWwgPSBnbHVlKCJ7eGxzeF9wcmVmaXh9L0dlbmVfU2V0X0VucmljaG1lbnQvdF9jZl9iaW9wc3lfc2lnX3N2YV91cF9ncC12e3Zlcn0ueGxzeCIpKQp0X2NmX2Jpb3BzeV9zaWdfc3ZhX2dwX3VwCgojIyBvciBwZXJoYXBzIGlmIHlvdSBwcmVmZXIgY2x1c3RlclByb2ZpbGVyCgp0X2NmX2Jpb3BzeV9zaWdfc3ZhX2NwX3VwIDwtIHNpbXBsZV9jcHJvZmlsZXIoCiAgdF9jZl9iaW9wc3lfc2lnX3N2YV91cCwgZGVfdGFibGUgPSB0X2NmX2Jpb3BzeV90YWJsZV9zdmEsCiAgb3JnZGIgPSAib3JnLkhzLmVnLmRiIiwKICBleGNlbCA9IGdsdWUoInt4bHN4X3ByZWZpeH0vR2VuZV9TZXRfRW5yaWNobWVudC90X2NmX2Jpb3BzeV9zaWdfc3ZhX3VwX2NwLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMgVGFibGUgUzUKClRoaXMgaXMgYSByZWRhY3RlZCBjb21iaW5hdGlvbiBvZiBhIGZldyBmaWxlczoKCiMjIyB3b3Jrc2hlZXQgTW9ub2N5dGVzCgpTZWN0aW9uIDYuMC4yIHByb3ZpZGVzIHRoZSBpbnZvY2F0aW9uIG9mIGNvbWJpbmVfZGVfdGFibGVzKCkgd2hpY2gKcHJvZHVjZXMgdGhlCidhbmFseXNpcy80X1R1bWFjby9ERV9DdXJlX0ZhaWwvTW9ub2N5dGVzL3RfbW9ub2N5dGVfY2ZfdGFibGUtc3ZhLXYyMDI0MDkueGxzeCcKdGhhdCBjb21wcmlzZXMgdGhlIGxvZ0ZDIGV0YyB2YWx1ZXMgaW4gdGhpcyB3b3Jrc2hlZXQuICBJbnRlcmVzdGluZ2x5LAp0aGUgdG9wIDUgZ2VuZXMgYWxsIHNoaWZ0ZWQgZG93biBpbiBsb2dGQyBieSB+IDAuMDAyIGluIG15CmNvbnRhaW5lci1kZXJpdmVkIHdvcmtzaGVldCB2cyB0aGlzIHRhYmxlLiAgSSB0aGluayB0aGF0IGlzIGFuCmFjY2VwdGFibGUgZGlmZmVyZW5jZT8gIEkgZGlkIHNwb3QgY2hlY2sgYSBmZXcgZ2VuZXMgaW4gdGhlIHRvcCA1MDAwCmFuZCBpdCBsb29rcyBsaWtlIHRoZSBvcmRlciBpcyBtYWludGFpbmVkLgoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2ZfbW9ub2N5dGVfdGFibGVfc3ZhIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogIHRfY2ZfbW9ub2N5dGVfZGVfc3ZhLCBrZWVwZXJzID0gdF9jZl9jb250cmFzdCwKICBleGNlbCA9IGdsdWUoIntjZl9wcmVmaXh9L01vbm9jeXRlcy90X21vbm9jeXRlX2NmX3RhYmxlX3N2YS12e3Zlcn0ueGxzeCIpKQp0X2NmX21vbm9jeXRlX3RhYmxlX3N2YQpgYGAKCiMjIyB3b3Jrc2hlZXQgTmV1dHJvcGhpbHMKClNhbWUgbG9naWMsIGJ1dCBTZWN0aW9uIDcuMC4yIHdpdGggdGhlIGFuYWxhZ291c2x5IG5hbWVkIHhsc3ggZmlsZSBpbgp0aGUgTmV1dHJvcGhpbHMgZGlyZWN0b3J5OyB0aGVzZSBudW1iZXJzIGFsc28gYXBwZWFyIHRvIGhhdmUKc2hpZnRlZCBzbGlnaHRseSAoYnV0IHRoaXMgdGltZSBieSB+IDAuMDAxIHVwIHRvIDAuMSBsb2dGQykgYW5kIEkgZG8Kc2VlIGEgY291cGxlIG9mIGdlbmVzIG91dCBvZiBvcmRlci4uLiAgSSBhbSBnb2luZyB0byBjaGVjayBpbiB3aXRoCk1hcmlhIEFkZWxhaWRhLgoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2ZfbmV1dHJvcGhpbF90YWJsZV9zdmEgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdF9jZl9uZXV0cm9waGlsX2RlX3N2YSwga2VlcGVycyA9IHRfY2ZfY29udHJhc3QsCiAgZXhjZWwgPSBnbHVlKCJ7Y2ZfcHJlZml4fS9OZXV0cm9waGlscy90X25ldXRyb3BoaWxfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IikpCnRfY2ZfbmV1dHJvcGhpbF90YWJsZV9zdmEKYGBgCgojIyMgd29ya3NoZWV0IEVvc2lub3BoaWxzCgpJYmlkLCBzZWN0aW9uIDcuMC4zLiAgT25jZSBhZ2FpbiB0aGUgdmFsdWVzIGxvb2sgdG8gaGF2ZSBzaGlmdGVkIGRvd24KYnkgfiAwLjAwMSB0byAwLjAxIGxvZ0ZDLgoKYGBge3IsIGV2YWw9RkFMU0V9CnRfY2ZfZW9zaW5vcGhpbF90YWJsZV9zdmEgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgdF9jZl9lb3Npbm9waGlsX2RlX3N2YSwga2VlcGVycyA9IHRfY2ZfY29udHJhc3QsCiAgZXhjZWwgPSBnbHVlKCJ7Y2ZfcHJlZml4fS9Fb3Npbm9waGlscy90X2Vvc2lub3BoaWxfY2ZfdGFibGVfc3ZhLXZ7dmVyfS54bHN4IikpCnRfY2ZfZW9zaW5vcGhpbF90YWJsZV9zdmEKYGBgCgojIyMgd29ya3NoZWV0IEFsbF9pbm5hdGUKClRoaXMgaXMgYWN0dWFsbHkgd2F5IGVhcmxpZXIgaW4gdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGRvY3VtZW50LApzZWN0aW9uIDMuMSB3aGVuIHRoZSB2YXJpYWJsZSAndF9jZl9jbGluaWNhbG5iX3RhYmxlX3N2YScgaXMgY3JlYXRlZAp0byBwcm9kdWNlIHRoZSB4bHN4IGZpbGUKJ2FuYWx5c2VzLzRfdHVtYWNvL0RFX0N1cmVfRmFpbC9BbGxfU2FtcGxlcy90X2NsaW5pY2FsX25vYmlvcF9jZl90YWJsZV9zdmEtdjIwMjQwOS54bHN4JwoKVGhlc2UgbnVtYmVycyBtYXRjaCB1cCBwcmV0dHkgbXVjaCBleGFjdGx5IChJIHNldCB0aGUgbnVtYmVyIG9mCnNpZ25pZmljYW50IGRpZ2l0cyB0byA0IEkgdGhpbmssIGJ1dCB0aGlzIHdvcmtzaGVldCBpcyAzPykKCmBgYHtyLCBldmFsPUZBTFNFfQp0X2NmX2NsaW5pY2FsX3RhYmxlX3N2YSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICB0X2NmX2NsaW5pY2FsX2RlX3N2YSwga2VlcGVycyA9IGNmX2NvbnRyYXN0LAogIGV4Y2VsID0gZ2x1ZSgie2NmX3ByZWZpeH0vQWxsX1NhbXBsZXMvdF9jbGluaWNhbF9jZl90YWJsZV9zdmEtdnt2ZXJ9Lnhsc3giKSkKdF9jZl9jbGluaWNhbF90YWJsZV9zdmEKYGBgCgojIyBUYWJsZSBTNgoKSSBkbyBub3QgdGhpbmsgdGhleSB1c2VkIG15IGdQcm9maWxlci9jbHVzdGVyUHJvZmlsZXIgcmVzdWx0cyBmb3IKdGhpcy4KCiMjIFRhYmxlIFM3CgpUaGlzIGNvbWVzIGZyb20gMDZscnRfZ3N2YSwgc2VjdGlvbiAzLgoKd2l0aCB0aGUgY2F2ZWF0IHRoYXQgSSB0aGluayB0aGUgQzIgYW5kIEM3IHJlc3VsdHMgYXJlIG1vcmUKaW50ZXJlc3RpbmcuICBBbHNvLCB0aGUgcmVzdWx0cyBwcm9kdWNlZCBieSB0aGUgY29udGFpbmVyIGFyZSBzcGFyc2VyCndpdGggcmVzcGVjdCB0byB0aGUgYW5ub3RhdGlvbnMgYmVjYXVzZSBJIGRpZCBub3Qgd2FudCB0byBzdGVhbCB0aGUKZ210L3htbCBhbm5vdGF0aW9ucyBmcm9tIGJyb2FkLiAgSWYgeW91IGhhcHBlbiB0byBoYXZlIHRoZSB4bWwvZ210CmZpbGVzLCBJIGxlZnQgdGhlIG9yaWdpbmFsIGludm9jYXRpb25zIHRoZXJlIHNvIHlvdSBjYW4gZ2V0IHRoZSBmdWxsCnRhYmxlIHdpdGggdGhlIHBhcGVyIHRpdGxlcyBldGMgKGFsc28sIG5vdGUgdGhhdCBsYXRlciB2ZXJzaW9ucyBvZgptU2lnREIgY2hhbmdlZCB0aGUgeG1sIGZvcm1hdCBzbyB0aGF0IGl0IG5vIGxvbmdlciBwYXJzZXMgcHJvcGVybHkgaW4KUjsgc28gdGhvc2UgZnVuY3Rpb25zIGFyZSBub3cgc21ydCBlbm91Z2ggdG8gaGFuZGxlIHRoZSBuZXcgZ210L2pzb24KZmlsZXMpLgoKYGBge3IsIGV2YWw9RkFMU0V9CnRjX2NlbGx0eXBlX2dzdmFfaCA8LSBzaW1wbGVfZ3N2YSgKICAgIHRjX3ZhbGlkLAogICAgc2lnbmF0dXJlcyA9IGJyb2FkX2gsCiAgICBtc2lnX3htbCA9ICJyZWZlcmVuY2UvbXNpZ2RiL21zaWdkYl92Ny41LjEueG1sIiwKICAgIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJoIikKdGNfY2VsbHR5cGVfZ3N2YV9oX3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcygKICAgIHRjX2NlbGx0eXBlX2dzdmFfaCwKICAgIGV4Y2VsID0gImFuYWx5c2VzLzNfY2FsaV9hbmRfdHVtYWNvL0dTVkEvdGNfdmFsaWRfZ3N2YV9oLnhsc3giKQpgYGAKCiMjIFRhYmxlIFM4CgpJIGFtIHJlYXNvbmFibHkgY2VydGFpbiB0aGF0IEFsZWphbmRybyBwcm9kdWNlZCB0aGUgaW5wdXRzIGZvciB0aGlzOwpob3dldmVyIHRoZSBjb250YWluZXIgcHJvZHVjZXMgbmVhcmx5IGlkZW50aWNhbCB2ZXJzaW9ucyBvZiB0aGUgcGllY2VzCmluIDA3d2djbmEsIHNlY3Rpb24gOS4KCmBgYHtyLCBldmFsPUZBTFNFfQp3cml0dGVuX2ludGVyZXN0aW5nIDwtIHdyaXRlX3hsc3goZkRhdGEobDJpbnB1dClbaW50ZXJlc3RpbmdfZ2VuZXMsIF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWUoImV4Y2VsL3dnY25hX2ludGVyZXN0aW5nX2dlbmVzLXZ7dmVyfS54bHN4IikpCgojIyBOb3RlIHRoYXQgd2UgY2FuIGRvIHNpbWlsYXJpdHkgbWF0cmljZXMgb24gdGhlIHNhbXBsZXMgdG9vIGluIG9yZGVyIHRvIGdldAojIyBkZW5kcm9ncmFtcyB3aGljaCBtYXkgZ2V0IGludGVyZXN0aW5nIGdyb3VwcyBvZiBzYW1wbGVzPwpgYGAKCiMjIFRhYmxlIFM5CgpUaGlzIGlzIG5vdCBydW4gYXV0b21hdGljYWxseSBieSB0aGUgY29udGFpbmVyIGJlY2F1c2UgaXQgd2lsbCBydW4KbW9zdCBjb21wdXRlcnMgb3V0IG9mIG1lbW9yeSBhbmQvb3IgdGFrZSBhIHJlYWxseSBsb25nIHRpbWUuICBJZiB5b3VyCmNvbXB1dGVyIGhhcyB+IDUxMkcgcmFtLCBvcGVuIDA4Y2xhc3NpZmllcl9oaWdodmFyLlJtZCBhbmQgcnVuIHNlY3Rpb24KMTEuMjsgdGhlIHJlc3VsdGluZyB4bHN4IG91dHB1dCBmaWxlcyBzaG91bGQgbG9vayBsaWtlIHRoaXMgKGV4Y2VwdApjb29sZXIgYmVjYXVzZSBJIGFkZCBzb21lIHBsb3RzKS4KCmBgYHtyLCBldmFsPUZBTFNFfQp0Y192YWxsX3N1bW1hcnlfeGxzeCA8LSBnbHVlKCJleGNlbC90Y192YWxsX21sX3N1bW1hcnktdnt2ZXJ9Lnhsc3giKQp0Y192YWxsX2tubiA8LSBjbGFzc2lmeV9uX3RpbWVzKHRjX3ZhbGxfdGV4cHJzLCB0Y192YWxsX21ldGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZV9jb2x1bW4gPSByZWZfY29sLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJrbm4iLCBzYW1wbGVyID0gImN2IikKd3JpdHRlbiA8LSB3cml0ZV9jbGFzc2lmaWVyX3N1bW1hcnkodGNfdmFsbF9rbm4sIGV4Y2VsID0gdGNfdmFsbF9zdW1tYXJ5X3hsc3gpCnRjX3ZhbGxfZ2IgPC0gY2xhc3NpZnlfbl90aW1lcyh0Y192YWxsX3RleHBycywgdGNfdmFsbF9tZXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZV9jb2x1bW4gPSByZWZfY29sLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInhnYlRyZWUiLCBzYW1wbGVyID0gImN2IikKd3JpdHRlbiA8LSB3cml0ZV9jbGFzc2lmaWVyX3N1bW1hcnkodGNfdmFsbF9nYiwgZXhjZWwgPSB3cml0dGVuW1sid2IiXV0pCnRjX3ZhbGxfZ2xtIDwtIGNsYXNzaWZ5X25fdGltZXModGNfdmFsbF90ZXhwcnMsIHRjX3ZhbGxfbWV0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lX2NvbHVtbiA9IHJlZl9jb2wsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImdsbW5ldCIsIHNhbXBsZXIgPSAiY3YiKQp3cml0dGVuIDwtIHdyaXRlX2NsYXNzaWZpZXJfc3VtbWFyeSh0Y192YWxsX2dsbSwgZXhjZWwgPSB3cml0dGVuW1sid2IiXV0pCnRjX3ZhbGxfcmYgPC0gY2xhc3NpZnlfbl90aW1lcyh0Y192YWxsX3RleHBycywgdGNfdmFsbF9tZXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZV9jb2x1bW4gPSByZWZfY29sLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInJhbmdlciIsIHNhbXBsZXIgPSAiY3YiKQp3cml0dGVuIDwtIHdyaXRlX2NsYXNzaWZpZXJfc3VtbWFyeSh0Y192YWxsX3JmLCBleGNlbCA9IHdyaXR0ZW5bWyJ3YiJdXSkKb3Blbnhsc3g6OnNhdmVXb3JrYm9vayh3cml0dGVuW1sid2IiXV0sIGZpbGUgPSB0Y192YWxsX3N1bW1hcnlfeGxzeCkKYGBgCgojIFN0cnVjdHVyZQoKVGhlIFJtZCBmaWxlcyBtYXkgYmUgcmVuZGVyZWQgaW4gYW55IG9yZGVyIHdpdGggb25lIHZlcnkgaW1wb3J0YW50CmV4Y2VwdGlvbjogdGhlIDAxZGF0YXN0cnVjdHVyZXMuUm1kIGZpbGUgbXVzdCBiZSBydW4gZmlyc3QuICBJdCByZWFkcwphbGwgb2YgdGhlIHNhbXBsZSBzaGVldHMgYW5kIGNvdW50IHRhYmxlcyBhbmQgd3JpdGVzIG91dCBhIHNlcmllcyBvZgpkYXRhIGZpbGVzIHVzZWQgYnkgYWxsIHRoZSBvdGhlciBkb2N1bWVudHMuCgpOb3RlOiBBbGwgdGhlIHJlZmVyZW5jZXMgYXJlIGluIHRoZSBkb2N1bWVudHMsIG5vdCBoZXJlLgoKIyMgMDFkYXRhc3RydWN0dXJlcwoKVGhpcyBpcyByZXNwb25zaWJsZSBmb3Igc2V0dGluZyB0aGUgc3RhZ2UgZm9yIGV2ZXJ5dGhpbmcgdGhhdCBmb2xsb3dzLgpJdCBjb2xsZWN0cyBhbm5vdGF0aW9ucyBmcm9tIHRoZSAyMDIwIGVuc2VtYmwgaHVtYW4gZGF0YWJhc2UsIHRoZQpleHBlcmltZW50YWwgbWV0YWRhdGEgZnJvbSB0aGUgeGxzeCBmaWxlcyBpbiBzYW1wbGVfc2hlZXRzLywgYW5kIHRoZQpjb3VudHMgZm91bmQgaW4gcHJlcHJvY2Vzc2luZy8gYW5kIGNvbWJpbmVzIHRoZW0gaW50byBhbiBpbml0aWFsLApsYXJnZSBleHByZXNzaW9uU2V0LiAgSXQgdGFsbGllcyB1cCB0aGUgc2FtcGxlcyBhY2NvcmRpbmcgdG8gbWFueS9tb3N0Cm9mIHRoZSBsaWtlbHkgZmFjdG9ycyBvZiBpbnRlcmVzdCwgZmlsdGVycyB0aGUgZGF0YSwgYW5kIGV4dHJhY3RzIHRoZQp2YXJpb3VzIHN1YnNldHMgaW50byBzZXBhcmF0ZSBkYXRhc3RydWN0dXJlcy4KCiMjIDAydmlzdWFsaXphdGlvbgoKRG9taW5hdGVkIGJ5IGEgbG9uZyBzZXJpZXMgb2YgUENBIGV4cGxvcmF0aW9ucy4gIEl0IGlzIGJhc2ljYWxseSBhCnBsYXlncm91bmQgZm9yIG1lIHRvIHBva2UgYXQgdGhlIHZhcmlvdXMgZGF0YSBzdWJzZXRzIGluIG9yZGVyIHRvIHRyeQp0byBnZXQgYSBmZWVsaW5nIGZvciB3aGF0IGlzIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byB0aGluayBhYm91dAp0aGUgZGF0YS4gIEl0IHdhcyB3aGVyZSB3ZSBldmVudHVhbGx5IGRlY2lkZWQgdGhhdCB3ZSBjYW5ub3QgdXNlIHRoZQpDYWxpIGRhdGEsIGZvciBleGFtcGxlLgoKSW4gbGF0ZXIgaXRlcmF0aW9ucyBpdCBpbmNsdWRlZCBhIHNlcmllcyBvZiByZWdyZXNzaW9uIGFuYWx5c2VzIGFuZApmdXJ0aGVyIGV4YW1pbmF0aW9ucyBpbnRvIHRoZSBzZW5zaXRpdml0aWVzIG9mIHRoZSBQQ0EgYW5kIHN1cnJvZ2F0ZQp2YXJpYWJsZSBhbmFseXNlcy4gIEl0IHNob3VsZCBiZSBub3RlZCB0aGF0IHRoZXNlIGFuYWx5c2VzIHdlcmUKZW50aXJlbHkgVGhlcmVzYSdzIGlkZWEsIEkgY29waWVkIHRoZW0gaW50byB0aGlzIGRvY3VtZW50IGFuZCBtYWRlCnNvbWUgbWlub3IgY2hhbmdlcy4KCiMjIDAzZGlmZmVyZW50aWFsX2V4cHJlc3Npb25fYm90aAoKVGhpcyBkb2N1bWVudCBwZXJmb3JtcyBzb21lIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2VzIHVzaW5nCmJvdGggdGhlIHNhbXBsZXMgZnJvbSBDYWxpIGFuZCBUdW1hY28uICBQYXJ0aWFsbHkgdGhpcyB3YXMgZG9uZSB0bwphc3N1YWdlIG15IGludGVyZXN0LCBhbmQgcGFydGlhbGx5IHRvIHJlaW5mb3JjZSB0aGUgaWRlYSB0aGF0IHRoZSBDYWxpCnNhbXBsZXMgcmVhbGx5IGRvIG5vdCBwbGF5IHdlbGwgd2l0aCBvdGhlcnMuCgojIyAwNGRpZmZlcmVudGlhbF9leHByZXNzaW9uX3R1bWFjbwoKSWJpZCwgYnV0IG9ubHkgVHVtYWNvLiAgVGhpcyBpcyB0aGUgcmVhbCBtZWF0IG9mIHRoZSBhbmFseXNpcyBhbmQKc2Vla3MgdG8gdHJ5IG91dCB2YXJpb3VzIHdheXMgb2YgcGVyZm9ybWluZyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbgp1c2luZyB0aGUgVHVtYWNvIGRhdGEgaW4gb3JkZXIgdG8gc2VlIHdoaWNoIHByb3ZpZGUgdGhlIG1vc3Qgcm9idXN0CndheXMgb2YgZXhhbWluaW5nIHRoZSBwb3RlbnRpYWwgcXVlc3Rpb25zIGluIHRoZSBkYXRhLgoKIyMgMDVlbnJpY2htZW50CgpSZWFkIHRoZSB4bHN4IGZpbGVzIGZyb20gMDMgYW5kIDA0IGFib3ZlIGFuZCBwYXNzIHRoZSByZXN1bHRpbmcgZ2VuZQpzZXRzIGFuZC9vciBERSB0YWJsZXMgdG8gZ1Byb2ZpbGVyMiBhbmQgY2x1c3RlclByb2ZpbGVyLiAgZ1Byb2ZpbGVyCndhcyB1c2VkIHRvIHBlcmZvcm0gb3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNlcyBvZiB0aGUgc2lnbmlmaWNhbnRseQppbmNyZWFzZWQvZGVjcmVhc2VkIGdlbmVzIChvciBib3RoIHRvZ2V0aGVyKSBvZiB0aGUgdmFyaW91cyBjb250cmFzdHMKdnMuIHRoZSBkYXRhYmFzZXMgcHJvdmlkZWQgYnkgZ1Byb2ZpbGVyLiAgVGhlIHNhbWUgdGFzayB3YXMgcGVyZm9ybWVkCnVzaW5nIGNsdXN0ZXJQcm9maWxlciB3aXRoIHR3byBleGNlcHRpb25zOiBjbHVzdGVyUHJvZmlsZXIgdXNlcyB0aGUKb3JnZGIgYW5ub3RhdGlvbnMgZm9yIGl0cyBnZW5lIGdyb3VwcyBhbmQgaXMgdGhlcmVmb3JlIChieSBkZWZhdWx0LApidXQgbm90IGV4Y2x1c2l2ZWx5KSBsaW1pdGVkIHRvIEdPL0tFR0cvREFWSUQ7IGNvbnZlcnNlbHksIG9uZSBtYXkKdHJpdmlhbGx5IHBhc3MgdGhlIGZ1bGwgREUgdGFibGUgdG8gY2x1c3RlclByb2ZpbGVyIGFuZCB0aHVzIHBlcmZvcm0KdGhlIGZ1bGwgR1NFQSBhbmFseXNpcy4gKEkgaGF2ZSBiZWVuIHBsYXlpbmcgd2l0aCBwYXNzaW5nIHJlYWN0b21lCih2aWEgUmVhY3RvbWVQQSkgYW5kIG1TaWdEQiB0byB0aGVzZSBtZXRob2RzKS4KCiMjIDA2bHJ0X2dzdmEKClRoZXJlc2EgYWxzbyBzdWdnZXN0ZWQgd2UgdHJ5IGEgc2VyaWVzIG9mIExpa2VsaWhvb2QgUmF0aW8gVGVzdHMgKExSVCkKdG8gZXhhbWluZSB0cmVuZHMgaW4gdGhlIGRhdGE7IHRodXMgbWFraW5nIERFU2VxMi9FZGdlUiBzZW5zaXRpdmUgdG8Kbm90IG9ubHkgaW5jcmVhc2VkL2RlY3JlYXNlZCBnZW5lIGV4cHJlc3Npb24gYWNyb3NzIHR3byBjb25kaXRpb25zLApidXQgc2hhcmVkL2RpdmVyZ2VudCB0cmVuZHMgYWNyb3NzIG11bHRpcGxlIGZhY3RvcnMgaW4gdGhlIG1ldGFkYXRhLgpUaGlzIGRvY3VtZW50IHByb3ZpZGVzIGEgdmVyc2lvbiBvZiB0aGlzLgoKQXQgdGhlIHNhbWUgdGltZSB3ZSB3ZXJlIGRvaW5nIHRoYXQsIHNoZSBhbmQgSSBwdXQgdG9nZXRoZXIgYQpzaW1wbGlmaWVkIG1ldGhvZCBmb3IgcXVlcnlpbmcgdGhlIG1TaWdEQiB2aWEgR1NWQS4gIFRoZXNlIHF1ZXJpZXMgYXJlCmluIHRoaXMgZG9jdW1lbnQgdG9vLgoKIyMgMDd3Z2NuYQoKQWxlamFuZHJvIHBlcmZvcm1lZCBhIHNldCBvZiBXR0NOQSBhbmFseXNlcyB1c2luZyB0aGUgbm9ybWFsaXplZApleHByZXNzaW9uIHZhbHVlcy4gIEhlIGtpbmRseSBzZW50IG1lIGEgY29weSBvZiBoaXMgUiBzY3JpcHQgYW5kIEkKcmVmb3JtYXR0ZWQgaXQgc29tZXdoYXQgaW50byB0aGlzIGRvY3VtZW50LgoKIyMgMDhjbGFzc2lmaWVyX2hpZ2h2YXIKCkkgd2FudGVkIHRvIGV4cGxvcmUgbWFjaGluZSBsZWFybmluZyBjbGFzc2lmaWVycy4gSSBoYWQgdGhpcyBkYXRhc2V0CihhbmQgdGhlIHBhcmFzaXRlIHRyYW5zY3JpcHRvbWVzKSBvcGVuLCBzbyBJIGRlY2lkZWQgdG8gcGxheSB3aXRoCnRoZW0uICBJdCB3YXMgbmV2ZXIgaW50ZW5kZWQgZm9yIHB1YmxpY2F0aW9uIGJ5IG1lIGJ1dCBhcyBhIGZ1bgpsZWFybmluZyBleHBlcmllbmNlOyBidXQgaGVyZSBpdCBpcy4uLgoKIyBJbnRyb2R1Y3Rpb24gdG8gdGhlIHNpbmd1bGFyaXR5IGNvbnRhaW5lcgoKT2YgdGhlIHZhcmlvdXMgb3B0aW9ucywgSSBmb3VuZCBzaW5ndWxhcml0eSB0byBiZSB0aGUgbW9zdCBhdHRyYWN0aXZlLgpJIHRoZXJlZm9yZSB3cm90ZSBhIGRlZmF1bHQgTWFrZWZpbGUgd2l0aCBhIGZldyB0YXJnZXRzIHRvIGNyZWF0ZSBhbmQKbWFuaXB1bGF0ZSBpbWFnZXMgYmVjYXVzZSBJIGNhbm5vdCBiZSBib3RoZXJlZCB0byByZW1lbWJlciBhbGwgb2YgdGhlCnZhcmlvdXMgY29tbWFuZHMuCgojIFRoZSBpbWFnZXMKCkkgYW0gaG9waW5nIHRvIGNyZWF0ZSAyIGltYWdlIHRlbXBsYXRlcyBmb3IgdGhlIFRNUkMgYW5hbHlzZXM6CnByZXByb2Nlc3NpbmcgYW5kIGFuYWx5c2VzLiBJIHdpbGwgdGhlcmVmb3JlIGhhdmUgYSBmZXcgbG9jYWxseQptYWludGFpbmVkIHNoZWxsIHNjcmlwdHMgd2hpY2ggY29udGFpbiB0aGUgYmFzZSBpbWFnZSBzZXR1cCB0YXNrcywgdGhlCnRhc2tzIHJlcXVpcmVkIHRvIHNldHVwIHRoZSB0b29scyB1c2VkLCBkb3dubG9hZCB0aGUgZGF0YSwgYW5kIHBlcmZvcm0KdGhlIHdvcmsuCgojIFNldHRpbmcgdXAgdGhlIGJhc2UgaW1hZ2UKCkkgaW50ZW5kIHRvIHVzZSBEZWJpYW4gc3RhYmxlLiAgSSBhbSBjb3B5aW5nIHRoZSByZXF1aXJlZCBzZXR1cCBmaWxlcwppbnRvIHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IGFuZCBpbnZva2luZyBtYWtlIHRvIGNyZWF0ZQp0aGUgY29udGFpbmVyLiAgSSBoYXZlIGEgZmV3IHRhcmdldHMgd2hpY2ggYXJlIGludGVuZGVkIHRvIG1ha2UgdGhpcwplYXNpZXIgdG8gcmVtZW1iZXIuCgojIyBDcmVhdGluZyB0aGUgYmFzZSBpbWFnZQoKVGhlIGZvbGxvd2luZyBjb21tYW5kIHJ1bnMgc2luZ3VsYXJpdHkgd2l0aCBvcHRpb25zIHN1aXRhYmxlIHRvIGNyZWF0ZQp0aGUgaW1hZ2UuICBUaGlzIHRvIG1lIGlzIGEgbGl0dGxlIHVubmVydmluZywgYmVjYXVzZSBhIGJ1bmNoIG9mIHN0dWZmCmdldHMgcnVuIGFzIHJvb3QuCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbWFrZQpgYGAKCiMjIFRlc3Rpbmcgc3R1ZmYgb3V0IGFuZCBtYWtpbmcgY2hhbmdlcwoKVGhlIG92ZXJsYXkgdGFyZ2V0IGRyb3BzIHRoZSB1c2VyIGludG8gdGhlIGNvbnRhaW5lciB3aXRoIFIvVwpwZXJtaXNzaW9ucy4gIEl0IGNyZWF0ZXMgYSBkaXJlY3RvcnkgJ2N1cmVfRmFpbF9hbmFseXNlc19vdmVybGF5JyB3aGljaAptYXkgYmUgbW9kaWZpZWQgYXQgd2lsbC4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQptYWtlIGN1cmVfZmFpbF9hbmFseXNlcy5vdmVybGF5CmBgYAoKIyMgVXNpbmcgdGhlIGNvbnRhaW5lciBmb3IgYXJiaXRyYXJ5IFJtZC9tZCBmaWxlcwoKVGhlIGNvbnRhaW5lcidzIHJ1bnNjcmlwdCBoYXMgc29tZSBsb2dpYyBidWlsdCBpbiB3aGljaCBjYW4gcHJvY2VzcwphcmJpdHJhcnkgbWFya2Rvd24gZG9jdW1lbnRzIGludG8gaHRtbCB2aWEga25pdHIgYW5kIHBhbmRvYy4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBzb21lcGxhY2Vfd2l0aF9SbWQKL2xvY2F0aW9ub2Zjb250YWluZXJzL2N1cmVfZmFpbF9ob3N0X2FuYWx5c2VzLnNpZiAtaSBtYXJrZG93bjAxLlJtZDptYXJrZG93bjAyLlJtZApgYGAK