These documents are a series of Leishmania panamensis RNASeq analyses.
This data is in fact in 4 sub-experiments. Lets address them one at a time.
- Preprocessing The steps performed to preprocess the data.
- Annotation Data shared by all experiments (annotations, genomes, etc).
- Snp clustering Cluster samples by snp percentages.
- Macrophage Analyses: Responses of macrophages from 1 donor and 3 strains.
- Infection Analyses: Responses of PBMC cells to strains identified as ‘self-healing’ and ‘chronic’.
- Biopsy Analyses: PBMC samples pre and post-biopsy.
- Antimonial Treatments: A search for differences between responsive and unresponsive samples
TODO
2017-08-24
- Define analyses.
- Set up supplementals.
- Same panels as per Santuza’s paper:
- Coverage
- Boxplot
- correlation
- PCA
- distance
- SMC
2017-07-27
- Find overlaps between the three patients and the groups of ch/un + sh/un
2016-11-29
- Do the following:
- Limma with batch in model, report # genes fc>0, p<=0.05; fc<0, p<=0.05; fc>1.5, p<=0.05; fc<-1.5, p<=0.05
- Limma with combat, report # genes fc>0, p<=0.05; fc<0, p<=0.05, etc.
- Limma without b, report same
- Limma without b+sva, report same
- Take the 4 results and compare them:
- Correlate various fold changes
- Find # genes of 1 in 2, 1 in 3, 1 in 4, 2 in 3, 2 in 4, 3 in 4.
2016-11-03
Do in lexical order, send the first 4 by email asap.
- For macrophage, remove batch b and re-perform metrics.
- For macrophage, look at pca information after adjustment with combat.
- Compare de lists with and without batch b (using combat for batch b containing work)
PBMC: variance partition human, “Are there any genes with variance we can ascribe to condition?” That set of genes is the most interesting. – use the variance parition table and pull the top 200. Report back the % variance by condition for all of these genes.
- Simplify snp plot for keith.
Make separate snp plot of only macrophage and only infection.
2016-09-23
- Add to existing vcfutils pipeline a check that all samples have sufficient coverage. Rsamtools, calculate coverage on all positions stored as gRanges[]. Cross reference these against each snp position and percentage.
- For each existing snp position, make a data structure including the coverage and percentage for all samples
- Given this data structure, keep only those rows with sufficient coverage across all samples. (If any sample has < n reads at position x && at no one sample has it > 0.95 then remove the row)
- The remaining positions should all have 0<=x<=1 percentage. Use them for the following analyses.
- Subset the full data set into a separate plot for each experiment. Plot these heatmaps accordingly.
- If there are interesting clades within these subsets, reuse them for variancePartition/models.
- Assuming the same result applies, use PCA or something to query self/chronic for all samples and see if the funny blue clade is split or not.
2016-09-15
- (2)Re-perform vcfutils pipeline and have it include in its summary a number of coverage, then when merging keep only those positions which have coverage > x for all samples. (done except I didn’t do coverage > x for all samples properly, but the results I think make it a moot point)
- Perform with a set of monocladous samples
- (4)Perform an explicit set of mappings of only the non-human reads and collect mapping stats for keith ;p
- (1)Make 100+% certain that all violin plots are on human data (I think this is true now, done by performing plots of both for all).
- (3)Conversely/simultaneously, query the snp profiles (focus on hpgl0635) to seek snps which define: (Goal is to find positions driving the clustering observed)
- Make a heatmap of snps in the columns and strains in rows and use the % to score. How to choose n out of 92k snps
- For each snp, use snp3 clade as outcome and perform an f-test for each snp and extract the highest n f-statistic snps, then plot the heatmap at i.
- Compare clustering of gene expression vs. SNP genotype.
- Measure variance explained by SNP vs. variance explained by strain by doing varPartition of:
- donor + strain
- donor + snp(3/4/5) and snpclade
- Assuming this works out, fit a model without strain, but instead snp.
Misc
- VCF tools in bioconductor (I am inclined to suggest that these tools sort of suck)
- Exclude <0.9 percentages from: (done – there is no significant difference between the two, the correlations/distances are nearly identical.) DO ME FIRST: newb.
- Step1: Perform varpart and see that variance by snp > variance by strain
- Perform this on the human data and not parasite
- Perform this for both snp3 and snp5 clades
- Make sure to plot donor+strain+healing and donor+snp+healing for snp3/snp5
- Assuming snp3 is appropriate, fit a model of y=donor+snp3+healing
- Assuming it functions properly, we have a set of genes with differential expression taking into account both donor and clustering.
- Bioconductor package ‘variancePartition’
- (1|factor) are random effects ergo; model <- as.formula(“~ (1|donor) + (1|strain) + (1|batch)”)
- Make violin plot of this result, plot residuals vs. healing,
- Repeat above with introduced + (1|healing)
- Copy chr/sh pca plot down to the relabel one sample section to make it easier to follow
- Figure out a way to automatically compare every sample against the SNP profiles generated for all strains.
- Record a set of canonical snps for each strain
- For each sample, use something like bam_whateveritwas to extract those regions
- For each snp profile, count the identities/differences for every snp position and heatmap them?
- Then if they match it should come up the terminal color I think
- Try the same PCA plots with just dropping hpgl0635
- Print full set of plots for the parasite samples before getting into the PCA.
Macrophage tasks
- Re-perform DE analyses with no-sva/ruv but condition+batch (done)
- Collect IGV images for strains ch/sh (done)
- For SVs, plot SV vs. technical variables: %rna, snps (done)
- Take the % of reads mapped to parasite and add it as an experimental parameter (done)
- Extend SV analysis to include condition + batch (not done)
- For the SV methods, plot log2 genes vs. log2fc (?)
- Run RUV/SVA condition + nobatch (done)
- Take SVs and add to the model
- Perform DE
- Plot MA, correlate log2FCs across analyses
- Provide a PCA plot of our final decision for this data and provide a table of coordinates
- Provide DE lists with condition+batch in the model vs. combat adjusted and do comparison
- Provide some ontology/KEGG results
Infection tasks
- Add ‘coordinates’ for all the PCA plots for Maria Adelaida to pick up. done by adding them to all PCA plots
- Send along some PCA coordinates (from the email:) done
- The coordinates of the PCA of PBMCs without batch correction – showing the strong batch effect by patient Ibid #0
- The coordinates of the PCAs of PBMCs after batch correction Ibid #0
- Amend PCA coordinates: first without uninfected, then with
- without batch, patient, strain Ibid #0 – actually did I do them all, I think so
- Will we call the 6 isolates be called ‘strains’, ‘isolates’, ‘cultures’?
- The reason for this question is that they do not necessarily follow well defined rules vis a vis the similarity to the characterized genome.
- Make sure the actual experimental batch comparison is maintained I believe this is correct
- Make sure that it is clear the difference between ‘experimental batch effect’ and ‘donor effect’ I think this is clear, I have a specific call before each comparison now, is there a best way to ensure this?
- Report correlation between factors and components. Done for the case of samples without uninfected
- Fit linear model after removing each factor and observe variance remaining to directly assess %var in each factor. ‘Most elegant method is the mixed effect model’
- Terms agreed to:
- “donor”: (patient) bob jane alice
- “isolate”: (strain) 2171 2172 etc
- “status”: (self healing, chronic, uninfected)
- “batch”: (a b) The two library/RNA isolation dates
- “snp”: (x y z) Clade top (few), clade middle (some), clade bottom (many)
- Make a model of ~ 0 + isolate + donor + batch (maybe not batch) Fit to the data, take residuals, make PCA of the residuals, color by sh/ch
- Compare parasite data clustering to see if some other surrogate factor to make some sense of this a) Goal: attempt to identify the cluster of strains which has peculiar human expression.
- See what happens if I relabel 635 as strain ch2504 Done for some values of ‘done’ I am not certain of the result
- Learn best method
Installation and setup
These are rmarkdown documents which make heavy use of the hpgltools package. The following section demonstrates how to set that up in a clean R environment.
## Use R's install.packages to install devtools.
install.packages("devtools")
## Use devtools to install hpgltools.
devtools::install_github("elsayedlab/hpgltools")
## Load hpgltools into the R environment.
library(hpgltools)
## Use hpgltools' autoloads_all() function to install the many packages used by hpgltools.
autoloads_all()
This document is rather short. In some others I did the preprocessing, shared, etc steps as ‘child’ documents of this and they would be appended here. In this case I did not.
if (!isTRUE(get0("skip_load"))) {
pander::pander(sessionInfo())
message(paste0("This is hpgltools commit: ", get_git_commit()))
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to ", this_save))
tmp <- sm(saveme(filename=this_save))
}
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 2a0661d6e37f8a3d8831eb3bbd6347c0d9c4b3b7
## R> packrat::restore()
## This is hpgltools commit: Thu Mar 29 16:59:07 2018 -0400: 2a0661d6e37f8a3d8831eb3bbd6347c0d9c4b3b7
## Saving to index-v20171110.rda.xz
LS0tCnRpdGxlOiAiTC5wYW5hbWVuc2lzIDIwMTY6IFJOQXNlcSBvZiBMLnBhbmFtZW5zaXMgaW4gaHVtYW4gbWFjcm9waGFnZXMsIGR1cmluZyBpbmZlY3Rpb24sIGluIGJpb3BzaWVzLCBhbmQgd2l0aCBhbnRpbW9uaWFsIHRyZWF0bWVudC4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KaWYgKCFpc1RSVUUoZ2V0MCgic2tpcF9sb2FkIikpKSB7CiAgbGlicmFyeShocGdsdG9vbHMpCiAgdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCiAga25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg9OTAsCiAgICAgICAgICAgICAgICAgICAgICAgZWNobz1UUlVFKQogIGtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGg9OCwKICAgICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodD04LAogICAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCiAgb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKICBnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEwKSkKICB2ZXIgPC0gIjIwMTcxMTEwIgogIHByZXZpb3VzX2ZpbGUgPC0gImluZGV4LlJtZCIKCiAgdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkpCiAgcm1kX2ZpbGUgPC0gImluZGV4LlJtZCIKfQpgYGAKClRoZXNlIGRvY3VtZW50cyBhcmUgYSBzZXJpZXMgb2YgTGVpc2htYW5pYSBwYW5hbWVuc2lzIFJOQVNlcSBhbmFseXNlcy4KClRoaXMgZGF0YSBpcyBpbiBmYWN0IGluIDQgc3ViLWV4cGVyaW1lbnRzLiAgTGV0cyBhZGRyZXNzIHRoZW0gb25lIGF0IGEgdGltZS4KCiogW1ByZXByb2Nlc3NpbmddKHByZXByb2Nlc3NpbmcuaHRtbCkgIFRoZSBzdGVwcyBwZXJmb3JtZWQgdG8gcHJlcHJvY2VzcyB0aGUgZGF0YS4KKiBbQW5ub3RhdGlvbl0oYW5ub3RhdGlvbi5odG1sKSAgRGF0YSBzaGFyZWQgYnkgYWxsIGV4cGVyaW1lbnRzIChhbm5vdGF0aW9ucywgZ2Vub21lcywgZXRjKS4KKiBbU25wIGNsdXN0ZXJpbmddKHNucF9jbHVzdGVyLmh0bWwpICBDbHVzdGVyIHNhbXBsZXMgYnkgc25wIHBlcmNlbnRhZ2VzLgoqIE1hY3JvcGhhZ2UgQW5hbHlzZXM6ICBSZXNwb25zZXMgb2YgbWFjcm9waGFnZXMgZnJvbSAxIGRvbm9yIGFuZCAzIHN0cmFpbnMuCiAgICAqIFtNYWNyb3BoYWdlIFNhbXBsZSBFc3RpbWF0aW9uOiBIdW1hbl0obWFjcm9waGFnZV9lc3RpbWF0aW9uX2h1bWFuLmh0bWwpICBNYWNyb3BoYWdlIHJlc3BvbnNlczogaHBnbDAyNDEtMDI0OAogICAgICBhbmQgaHBnbDA2MzYtMDYzOS4KICAgICogW01hY3JvcGhhZ2UgU2FtcGxlIEVzdGltYXRpb246IFBhcmFzaXRlXShtYWNyb3BoYWdlX2VzdGltYXRpb25fcGFyYXNpdGUuaHRtbCkgIEliaWQgZXhjZXB0IHRoZSBwYXJhc2l0ZSBtYXBwaW5ncy4KICAgICogW01hY3JvcGhhZ2UgRGlmZmVyZW50aWFsIEV4cHJlc3Npb246IEh1bWFuXShtYWNyb3BoYWdlX2V4cHJlc3Npb25faHVtYW4uaHRtbCkgIE1hY3JvcGhhZ2UgcmVzcG9uc2VzOiBodW1hbgogICAgKiBbTWFjcm9waGFnZSBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbjogUGFyYXNpdGVdKG1hY3JvcGhhZ2VfZXhwcmVzc2lvbl9wYXJhc2l0ZS5odG1sKSAgTWFjcm9waGFnZSByZXNwb25zZXM6IHBhcmFzaXRlCiAgICAqIFtNYWNyb3BoYWdlIEdlbmUgT250b2xvZ3k6IEh1bWFuXShtYWNyb3BoYWdlX29udG9sb2d5X2h1bWFuLmh0bWwpICBHZW5lIG9udG9sb2d5IHNlYXJjaGVzOiBodW1hbgogICAgKiBbTWFjcm9waGFnZSBHZW5lIE9udG9sb2d5OiBQYXJhc2l0ZV0obWFjcm9waGFnZV9vbnRvbG9neV9wYXJhc2l0ZS5odG1sKSAgR2VuZSBvbnRvbG9neSBzZWFyY2hlczogcGFyYXNpdGUKKiBJbmZlY3Rpb24gQW5hbHlzZXM6ICBSZXNwb25zZXMgb2YgUEJNQyBjZWxscyB0byBzdHJhaW5zIGlkZW50aWZpZWQgYXMgJ3NlbGYtaGVhbGluZycgYW5kICdjaHJvbmljJy4KICAgICogW0luZmVjdGlvbiBTYW1wbGUgRXN0aW1hdGlvbjogSHVtYW5dKGluZmVjdGlvbl9lc3RpbWF0aW9uX2h1bWFuLmh0bWwpICBJbmZlY3Rpb24gcmVzcG9uc2VzOiBocGdsMDI0MS0wMjQ4CiAgICAgIGFuZCBocGdsMDYzNi0wNjM5LgogICAgKiBbSW5mZWN0aW9uIFNhbXBsZSBFc3RpbWF0aW9uOiBQYXJhc2l0ZV0oaW5mZWN0aW9uX2VzdGltYXRpb25fcGFyYXNpdGUuaHRtbCkgIEliaWQgZXhjZXB0IHRoZSBwYXJhc2l0ZSBtYXBwaW5ncy4KICAgICogW0luZmVjdGlvbiBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbjogSHVtYW5dKGluZmVjdGlvbl9leHByZXNzaW9uX2h1bWFuLmh0bWwpICBJbmZlY3Rpb24gcmVzcG9uc2VzOiBodW1hbgogICAgKiBbSW5mZWN0aW9uIERpZmZlcmVudGlhbCBFeHByZXNzaW9uOiBQYXJhc2l0ZV0oaW5mZWN0aW9uX2V4cHJlc3Npb25fcGFyYXNpdGUuaHRtbCkgIEluZmVjdGlvbiByZXNwb25zZXM6IHBhcmFzaXRlCiAgICAqIFtJbmZlY3Rpb24gR2VuZSBPbnRvbG9neTogSHVtYW5dKGluZmVjdGlvbl9vbnRvbG9neV9odW1hbi5odG1sKSAgR2VuZSBvbnRvbG9neSBzZWFyY2hlczogaHVtYW4KICAgICogW0luZmVjdGlvbiBHZW5lIE9udG9sb2d5OiBQYXJhc2l0ZV0oaW5mZWN0aW9uX29udG9sb2d5X3BhcmFzaXRlLmh0bWwpICBHZW5lIG9udG9sb2d5IHNlYXJjaGVzOiBwYXJhc2l0ZQoqICBCaW9wc3kgQW5hbHlzZXM6ICBQQk1DIHNhbXBsZXMgcHJlIGFuZCBwb3N0LWJpb3BzeS4KICAgICogW0Jpb3BzeSBTYW1wbGUgRXN0aW1hdGlvbjogSHVtYW5dKGJpb3BzeV9lc3RpbWF0aW9uX2h1bWFuLmh0bWwpICBCaW9wc3kgcmVzcG9uc2VzOiBocGdsMDI0MS0wMjQ4CiAgICBhbmQgaHBnbDA2MzYtMDYzOS4KICAgICogW0Jpb3BzeSBTYW1wbGUgRXN0aW1hdGlvbjogUGFyYXNpdGVdKGJpb3BzeV9lc3RpbWF0aW9uX3BhcmFzaXRlLmh0bWwpICBJYmlkIGV4Y2VwdCB0aGUgcGFyYXNpdGUgbWFwcGluZ3MuCiAgICAqIFtCaW9wc3kgRGlmZmVyZW50aWFsIEV4cHJlc3Npb246IEh1bWFuXShiaW9wc3lfZXhwcmVzc2lvbl9odW1hbi5odG1sKSAgQmlvcHN5IHJlc3BvbnNlczogaHVtYW4KICAgICogW0Jpb3BzeSBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbjogUGFyYXNpdGVdKGJpb3BzeV9leHByZXNzaW9uX3BhcmFzaXRlLmh0bWwpICBCaW9wc3kgcmVzcG9uc2VzOiBwYXJhc2l0ZQogICAgKiBbQmlvcHN5IEdlbmUgT250b2xvZ3k6IEh1bWFuXShiaW9wc3lfb250b2xvZ3lfaHVtYW4uaHRtbCkgIEdlbmUgb250b2xvZ3kgc2VhcmNoZXM6IGh1bWFuCiAgICAqIFtCaW9wc3kgR2VuZSBPbnRvbG9neTogUGFyYXNpdGVdKGJpb3BzeV9vbnRvbG9neV9wYXJhc2l0ZS5odG1sKSAgR2VuZSBvbnRvbG9neSBzZWFyY2hlczogcGFyYXNpdGUKKiAgQW50aW1vbmlhbCBUcmVhdG1lbnRzOiAgQSBzZWFyY2ggZm9yIGRpZmZlcmVuY2VzIGJldHdlZW4gcmVzcG9uc2l2ZSBhbmQgdW5yZXNwb25zaXZlIHNhbXBsZXMKICAgICogW0FudGltb25pYWwgU2FtcGxlIEVzdGltYXRpb246IEh1bWFuXShhbnRpbW9uaWFsX2VzdGltYXRpb25faHVtYW4uaHRtbCkgIEFudGltb25pYWwgcmVzcG9uc2VzOiBocGdsMDI0MS0wMjQ4CiAgICBhbmQgaHBnbDA2MzYtMDYzOS4KICAgICogW0FudGltb25pYWwgU2FtcGxlIEVzdGltYXRpb246IFBhcmFzaXRlXShhbnRpbW9uaWFsX2VzdGltYXRpb25fcGFyYXNpdGUuaHRtbCkgIEliaWQgZXhjZXB0IHRoZSBwYXJhc2l0ZSBtYXBwaW5ncy4KICAgICogW0FudGltb25pYWwgRGlmZmVyZW50aWFsIEV4cHJlc3Npb246IEh1bWFuXShhbnRpbW9uaWFsX2V4cHJlc3Npb25faHVtYW4uaHRtbCkgIEFudGltb25pYWwgcmVzcG9uc2VzOiBodW1hbgogICAgKiBbQW50aW1vbmlhbCBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbjogUGFyYXNpdGVdKGFudGltb25pYWxfZXhwcmVzc2lvbl9wYXJhc2l0ZS5odG1sKSAgQW50aW1vbmlhbCByZXNwb25zZXM6IHBhcmFzaXRlCiAgICAqIFtBbnRpbW9uaWFsIEdlbmUgT250b2xvZ3k6IEh1bWFuXShhbnRpbW9uaWFsX29udG9sb2d5X2h1bWFuLmh0bWwpICBHZW5lIG9udG9sb2d5IHNlYXJjaGVzOiBodW1hbgogICAgKiBbQW50aW1vbmlhbCBHZW5lIE9udG9sb2d5OiBQYXJhc2l0ZV0oYW50aW1vbmlhbF9vbnRvbG9neV9wYXJhc2l0ZS5odG1sKSAgR2VuZSBvbnRvbG9neSBzZWFyY2hlczogcGFyYXNpdGUKCiMgVE9ETwoKIyMgMjAxNy0wOC0yNAoKMS4gIERlZmluZSBhbmFseXNlcy4KMi4gIFNldCB1cCBzdXBwbGVtZW50YWxzLgogICAgYS4gIFNhbWUgcGFuZWxzIGFzIHBlciBTYW50dXphJ3MgcGFwZXI6CiAgICAgICogIENvdmVyYWdlCiAgICAgICogIEJveHBsb3QKICAgICAgKiAgY29ycmVsYXRpb24KICAgICAgKiAgUENBCiAgICAgICogIGRpc3RhbmNlCiAgICAgICogIFNNQwoKCgojIyAyMDE3LTA3LTI3CgoxLiAgRmluZCBvdmVybGFwcyBiZXR3ZWVuIHRoZSB0aHJlZSBwYXRpZW50cyBhbmQgdGhlIGdyb3VwcyBvZiBjaC91biArIHNoL3VuCgojIyAyMDE2LTExLTI5CgoqICBEbyB0aGUgZm9sbG93aW5nOgogICAgMS4gIExpbW1hIHdpdGggYmF0Y2ggaW4gbW9kZWwsIHJlcG9ydCAjIGdlbmVzIGZjPjAsIHA8PTAuMDU7ICBmYzwwLCBwPD0wLjA1OyBmYz4xLjUsIHA8PTAuMDU7IGZjPC0xLjUsIHA8PTAuMDUKICAgIDIuICBMaW1tYSB3aXRoIGNvbWJhdCwgcmVwb3J0ICMgZ2VuZXMgZmM+MCwgcDw9MC4wNTsgZmM8MCwgcDw9MC4wNSwgZXRjLgogICAgMy4gIExpbW1hIHdpdGhvdXQgYiwgcmVwb3J0IHNhbWUKICAgIDQuICBMaW1tYSB3aXRob3V0IGIrc3ZhLCByZXBvcnQgc2FtZQoqICBUYWtlIHRoZSA0IHJlc3VsdHMgYW5kIGNvbXBhcmUgdGhlbToKICAgIDEuICBDb3JyZWxhdGUgdmFyaW91cyBmb2xkIGNoYW5nZXMKICAgIDIuICBGaW5kICMgZ2VuZXMgb2YgMSBpbiAyLCAxIGluIDMsIDEgaW4gNCwgMiBpbiAzLCAyIGluIDQsIDMgaW4gNC4KCiMjIDIwMTYtMTEtMDMKCkRvIGluIGxleGljYWwgb3JkZXIsIHNlbmQgdGhlIGZpcnN0IDQgYnkgZW1haWwgYXNhcC4KCiogICAgRm9yIG1hY3JvcGhhZ2UsIHJlbW92ZSBiYXRjaCBiIGFuZCByZS1wZXJmb3JtIG1ldHJpY3MuCiogICAgRm9yIG1hY3JvcGhhZ2UsIGxvb2sgYXQgcGNhIGluZm9ybWF0aW9uIGFmdGVyIGFkanVzdG1lbnQgd2l0aCBjb21iYXQuCiogICAgQ29tcGFyZSBkZSBsaXN0cyB3aXRoIGFuZCB3aXRob3V0IGJhdGNoIGIgKHVzaW5nIGNvbWJhdCBmb3IgYmF0Y2ggYiBjb250YWluaW5nIHdvcmspCiogICAgUEJNQzogdmFyaWFuY2UgcGFydGl0aW9uIGh1bWFuLCAiQXJlIHRoZXJlIGFueSBnZW5lcyB3aXRoIHZhcmlhbmNlIHdlIGNhbiBhc2NyaWJlIHRvIGNvbmRpdGlvbj8iCiAgICBUaGF0IHNldCBvZiBnZW5lcyBpcyB0aGUgbW9zdCBpbnRlcmVzdGluZy4gLS0gdXNlIHRoZSB2YXJpYW5jZSBwYXJpdGlvbiB0YWJsZSBhbmQgcHVsbCB0aGUgdG9wIDIwMC4KICAgIFJlcG9ydCBiYWNrIHRoZSAlIHZhcmlhbmNlIGJ5IGNvbmRpdGlvbiBmb3IgYWxsIG9mIHRoZXNlIGdlbmVzLgoKCiogICAgU2ltcGxpZnkgc25wIHBsb3QgZm9yIGtlaXRoLgoqICAgIE1ha2Ugc2VwYXJhdGUgc25wIHBsb3Qgb2Ygb25seSBtYWNyb3BoYWdlIGFuZCBvbmx5IGluZmVjdGlvbi4KCiMjIDIwMTYtMDktMjMKCjEuICBBZGQgdG8gZXhpc3RpbmcgdmNmdXRpbHMgcGlwZWxpbmUgYSBjaGVjayB0aGF0IF9hbGxfIHNhbXBsZXMgaGF2ZSBzdWZmaWNpZW50IGNvdmVyYWdlLgpSc2FtdG9vbHMsIGNhbGN1bGF0ZSBjb3ZlcmFnZSBvbiBhbGwgcG9zaXRpb25zIHN0b3JlZCBhcyBnUmFuZ2VzW10uICBDcm9zcyByZWZlcmVuY2UgdGhlc2UgYWdhaW5zdAplYWNoIHNucCBwb3NpdGlvbiBhbmQgcGVyY2VudGFnZS4KICAgIGEuICBGb3IgZWFjaCBleGlzdGluZyBzbnAgcG9zaXRpb24sIG1ha2UgYSBkYXRhIHN0cnVjdHVyZSBpbmNsdWRpbmcgdGhlIGNvdmVyYWdlIGFuZCBwZXJjZW50YWdlIGZvciBhbGwgc2FtcGxlcwogICAgYi4gIEdpdmVuIHRoaXMgZGF0YSBzdHJ1Y3R1cmUsIGtlZXAgb25seSB0aG9zZSByb3dzIHdpdGggc3VmZmljaWVudCBjb3ZlcmFnZSBhY3Jvc3MgX2FsbF8KICAgIHNhbXBsZXMuICAoSWYgYW55IHNhbXBsZSBoYXMgPCBuIHJlYWRzIGF0IHBvc2l0aW9uIHggJiYgYXQgbm8gb25lIHNhbXBsZSBoYXMgaXQgPiAwLjk1IHRoZW4KICAgIHJlbW92ZSB0aGUgcm93KQogICAgYy4gIFRoZSByZW1haW5pbmcgcG9zaXRpb25zIHNob3VsZCBhbGwgaGF2ZSAwPD14PD0xIHBlcmNlbnRhZ2UuICBVc2UgdGhlbSBmb3IgdGhlIGZvbGxvd2luZwogICAgYW5hbHlzZXMuCjIuICBTdWJzZXQgdGhlIGZ1bGwgZGF0YSBzZXQgaW50byBhIHNlcGFyYXRlIHBsb3QgZm9yIGVhY2ggZXhwZXJpbWVudC4gIFBsb3QgdGhlc2UgaGVhdG1hcHMKICAgIGFjY29yZGluZ2x5LgogICAgYS4gIElmIHRoZXJlIGFyZSBpbnRlcmVzdGluZyBjbGFkZXMgd2l0aGluIHRoZXNlIHN1YnNldHMsIHJldXNlIHRoZW0gZm9yIHZhcmlhbmNlUGFydGl0aW9uL21vZGVscy4KMy4gIEFzc3VtaW5nIHRoZSBzYW1lIHJlc3VsdCBhcHBsaWVzLCB1c2UgUENBIG9yIHNvbWV0aGluZyB0byBxdWVyeSBzZWxmL2Nocm9uaWMgZm9yIGFsbCBzYW1wbGVzIGFuZAogICAgc2VlIGlmIHRoZSBmdW5ueSBibHVlIGNsYWRlIGlzIHNwbGl0IG9yIG5vdC4KCiMjIDIwMTYtMDktMTUKCmEuICAoMilSZS1wZXJmb3JtIHZjZnV0aWxzIHBpcGVsaW5lIGFuZCBoYXZlIGl0IGluY2x1ZGUgaW4gaXRzIHN1bW1hcnkgYSBudW1iZXIgb2YgY292ZXJhZ2UsICB0aGVuIHdoZW4gbWVyZ2luZyBrZWVwIG9ubHkgdGhvc2UgcG9zaXRpb25zIHdoaWNoIGhhdmUgY292ZXJhZ2UgPiB4IGZvciBfYWxsXyBzYW1wbGVzLiAgKGRvbmUgZXhjZXB0IEkgZGlkbid0IGRvIGNvdmVyYWdlID4geCBmb3IgYWxsIHNhbXBsZXMgcHJvcGVybHksIGJ1dCB0aGUgcmVzdWx0cyBJIHRoaW5rIG1ha2UgaXQgYSBtb290IHBvaW50KQogaS4gUGVyZm9ybSB3aXRoIGEgc2V0IG9mIG1vbm9jbGFkb3VzIHNhbXBsZXMKYi4gICg0KVBlcmZvcm0gYW4gZXhwbGljaXQgc2V0IG9mIG1hcHBpbmdzIG9mIG9ubHkgdGhlIG5vbi1odW1hbiByZWFkcyBhbmQgY29sbGVjdCBtYXBwaW5nIHN0YXRzIGZvciBrZWl0aCA7cAphLiAgKDEpTWFrZSAxMDArJSBjZXJ0YWluIHRoYXQgYWxsIHZpb2xpbiBwbG90cyBhcmUgb24gaHVtYW4gZGF0YSAoSSB0aGluayB0aGlzIGlzIHRydWUgbm93LCBkb25lIGJ5IHBlcmZvcm1pbmcgcGxvdHMgb2YgYm90aCBmb3IgYWxsKS4KYi4gICgzKUNvbnZlcnNlbHkvc2ltdWx0YW5lb3VzbHksIHF1ZXJ5IHRoZSBzbnAgcHJvZmlsZXMgKGZvY3VzIG9uIGhwZ2wwNjM1KSB0bwogICAgc2VlayBzbnBzIHdoaWNoIGRlZmluZTogICAoR29hbCBpcyB0byBmaW5kIHBvc2l0aW9ucyBkcml2aW5nIHRoZSBjbHVzdGVyaW5nIG9ic2VydmVkKQogIGkuICBNYWtlIGEgaGVhdG1hcCBvZiBzbnBzIGluIHRoZSBjb2x1bW5zIGFuZCBzdHJhaW5zIGluIHJvd3MgYW5kIHVzZSB0aGUKICAgICUgdG8gc2NvcmUuICBIb3cgdG8gY2hvb3NlIG4gb3V0IG9mIDkyayBzbnBzCiAgaWkuICBGb3IgZWFjaCBzbnAsIHVzZSBzbnAzIGNsYWRlIGFzIG91dGNvbWUgYW5kIHBlcmZvcm0gYW4gZi10ZXN0IGZvciBlYWNoIHNucCBhbmQgZXh0cmFjdCB0aGUKICAgIGhpZ2hlc3QgbiBmLXN0YXRpc3RpYyBzbnBzLCB0aGVuIHBsb3QgdGhlIGhlYXRtYXAgYXQgaS4KYy4gIENvbXBhcmUgY2x1c3RlcmluZyBvZiBnZW5lIGV4cHJlc3Npb24gdnMuIFNOUCBnZW5vdHlwZS4KZC4gIE1lYXN1cmUgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IFNOUCB2cy4gdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IHN0cmFpbiBieSBkb2luZyB2YXJQYXJ0aXRpb24gb2Y6CiAgaS4gICBkb25vciArIHN0cmFpbgogIGlpLiAgZG9ub3IgKyBzbnAoMy80LzUpIGFuZCBzbnBjbGFkZQogIGlpaS4gQXNzdW1pbmcgdGhpcyB3b3JrcyBvdXQsIGZpdCBhIG1vZGVsIHdpdGhvdXQgc3RyYWluLCBidXQgaW5zdGVhZCBzbnAuCgojIyBNaXNjCgphLiAgVkNGIHRvb2xzIGluIGJpb2NvbmR1Y3RvciAoSSBhbSBpbmNsaW5lZCB0byBzdWdnZXN0IHRoYXQgdGhlc2UgdG9vbHMgc29ydCBvZiBzdWNrKQpiLiAgRXhjbHVkZSA8MC45IHBlcmNlbnRhZ2VzIGZyb206ICAoZG9uZSAtLSB0aGVyZSBpcyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3bywgdGhlIGNvcnJlbGF0aW9ucy9kaXN0YW5jZXMgYXJlIG5lYXJseSBpZGVudGljYWwuKQpETyBNRSBGSVJTVDogbmV3Yi4KYy4gIFN0ZXAxOiAgUGVyZm9ybSB2YXJwYXJ0IGFuZCBzZWUgdGhhdCB2YXJpYW5jZSBieSBzbnAgPiB2YXJpYW5jZSBieSBzdHJhaW4KICAgaS4gIFBlcmZvcm0gdGhpcyBvbiB0aGUgaHVtYW4gZGF0YSBhbmQgbm90IHBhcmFzaXRlCiAgIGlpLiAgUGVyZm9ybSB0aGlzIGZvciBib3RoIHNucDMgYW5kIHNucDUgY2xhZGVzCiAgIGlpaS4gTWFrZSBzdXJlIHRvIHBsb3QgZG9ub3Irc3RyYWluK2hlYWxpbmcgYW5kIGRvbm9yK3NucCtoZWFsaW5nIGZvciBzbnAzL3NucDUKZC4gIEFzc3VtaW5nIHNucDMgaXMgYXBwcm9wcmlhdGUsIGZpdCBhIG1vZGVsIG9mIHk9ZG9ub3Irc25wMytoZWFsaW5nCmUuICBBc3N1bWluZyBpdCBmdW5jdGlvbnMgcHJvcGVybHksIHdlIGhhdmUgYSBzZXQgb2YgZ2VuZXMgd2l0aAogICAgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gdGFraW5nIGludG8gYWNjb3VudCBib3RoIGRvbm9yIGFuZCBjbHVzdGVyaW5nLgoKCjEuICBCaW9jb25kdWN0b3IgcGFja2FnZSAndmFyaWFuY2VQYXJ0aXRpb24nCiAgYS4gICgxfGZhY3RvcikgYXJlIHJhbmRvbSBlZmZlY3RzICBlcmdvOyBtb2RlbCA8LSBhcy5mb3JtdWxhKCJ+ICgxfGRvbm9yKSArICgxfHN0cmFpbikgKyAoMXxiYXRjaCkiKQogIGIuICBNYWtlIHZpb2xpbiBwbG90IG9mIHRoaXMgcmVzdWx0LCBwbG90IHJlc2lkdWFscyB2cy4gaGVhbGluZywKICBjLiAgUmVwZWF0IGFib3ZlIHdpdGggaW50cm9kdWNlZCArICgxfGhlYWxpbmcpCjIuICBDb3B5IGNoci9zaCBwY2EgcGxvdCBkb3duIHRvIHRoZSByZWxhYmVsIG9uZSBzYW1wbGUgc2VjdGlvbiB0byBtYWtlIGl0IGVhc2llciB0byBmb2xsb3cKMy4gIEZpZ3VyZSBvdXQgYSB3YXkgdG8gYXV0b21hdGljYWxseSBjb21wYXJlIGV2ZXJ5IHNhbXBsZSBhZ2FpbnN0IHRoZSBTTlAgcHJvZmlsZXMgZ2VuZXJhdGVkIGZvciBhbGwgc3RyYWlucy4KICBhLiAgUmVjb3JkIGEgc2V0IG9mIGNhbm9uaWNhbCBzbnBzIGZvciBlYWNoIHN0cmFpbgogIGIuICBGb3IgZWFjaCBzYW1wbGUsIHVzZSBzb21ldGhpbmcgbGlrZSBiYW1fd2hhdGV2ZXJpdHdhcyB0byBleHRyYWN0IHRob3NlIHJlZ2lvbnMKICBjLiAgRm9yIGVhY2ggc25wIHByb2ZpbGUsIGNvdW50IHRoZSBpZGVudGl0aWVzL2RpZmZlcmVuY2VzIGZvciBldmVyeSBzbnAgcG9zaXRpb24gYW5kIGhlYXRtYXAgdGhlbT8KICBkLiAgVGhlbiBpZiB0aGV5IG1hdGNoIGl0IHNob3VsZCBjb21lIHVwIHRoZSB0ZXJtaW5hbCBjb2xvciBJIHRoaW5rCjQuICBUcnkgdGhlIHNhbWUgUENBIHBsb3RzIHdpdGgganVzdCBkcm9wcGluZyBocGdsMDYzNQo1LiAgUHJpbnQgZnVsbCBzZXQgb2YgcGxvdHMgZm9yIHRoZSBwYXJhc2l0ZSBzYW1wbGVzIGJlZm9yZSBnZXR0aW5nIGludG8gdGhlIFBDQS4KCiMjIE1hY3JvcGhhZ2UgdGFza3MKCjEuICBSZS1wZXJmb3JtIERFIGFuYWx5c2VzIHdpdGggbm8tc3ZhL3J1diBidXQgY29uZGl0aW9uK2JhdGNoIChkb25lKQoyLiAgQ29sbGVjdCBJR1YgaW1hZ2VzIGZvciBzdHJhaW5zIGNoL3NoIChkb25lKQozLiAgRm9yIFNWcywgcGxvdCBTViB2cy4gdGVjaG5pY2FsIHZhcmlhYmxlczogJXJuYSwgc25wcyAoZG9uZSkKNC4gIFRha2UgdGhlICUgb2YgcmVhZHMgbWFwcGVkIHRvIHBhcmFzaXRlIGFuZCBhZGQgaXQgYXMgYW4gZXhwZXJpbWVudGFsIHBhcmFtZXRlciAoZG9uZSkKNS4gIEV4dGVuZCBTViBhbmFseXNpcyB0byBpbmNsdWRlIGNvbmRpdGlvbiArIGJhdGNoIChub3QgZG9uZSkKNi4gIEZvciB0aGUgU1YgbWV0aG9kcywgcGxvdCBsb2cyIGdlbmVzIHZzLiBsb2cyZmMgKD8pCjcuICBSdW4gUlVWL1NWQSBjb25kaXRpb24gKyBub2JhdGNoIChkb25lKQogIGEuICBUYWtlIFNWcyBhbmQgYWRkIHRvIHRoZSBtb2RlbAogIGIuICBQZXJmb3JtIERFCiAgYy4gIFBsb3QgTUEsIGNvcnJlbGF0ZSBsb2cyRkNzIGFjcm9zcyBhbmFseXNlcwo4LiAgUHJvdmlkZSBhIFBDQSBwbG90IG9mIG91ciBmaW5hbCBkZWNpc2lvbiBmb3IgdGhpcyBkYXRhIGFuZCBwcm92aWRlIGEgdGFibGUgb2YgY29vcmRpbmF0ZXMKOS4gIFByb3ZpZGUgREUgbGlzdHMgd2l0aCBjb25kaXRpb24rYmF0Y2ggaW4gdGhlIG1vZGVsIHZzLiBjb21iYXQgYWRqdXN0ZWQgYW5kIGRvIGNvbXBhcmlzb24KMTAuIFByb3ZpZGUgc29tZSBvbnRvbG9neS9LRUdHIHJlc3VsdHMKCiMjIEluZmVjdGlvbiB0YXNrcwoKMC4gQWRkICdjb29yZGluYXRlcycgZm9yIGFsbCB0aGUgUENBIHBsb3RzIGZvciBNYXJpYSBBZGVsYWlkYSB0byBwaWNrIHVwLgogICAgICAqZG9uZSBieSBhZGRpbmcgdGhlbSB0byBhbGwgUENBIHBsb3RzKgoxLiBTZW5kIGFsb25nIHNvbWUgUENBIGNvb3JkaW5hdGVzIChmcm9tIHRoZSBlbWFpbDopCiAgICAgICpkb25lKgogIGEpIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgUENBIG9mIFBCTUNzIHdpdGhvdXQgYmF0Y2ggY29ycmVjdGlvbiDigJMKICAgICAgc2hvd2luZyB0aGUgc3Ryb25nIGJhdGNoIGVmZmVjdCBieSBwYXRpZW50CiAgICAgICpJYmlkICMwKgogIGIpIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgUENBcyBvZiBQQk1DcyBhZnRlciBiYXRjaCBjb3JyZWN0aW9uCiAgICAgICpJYmlkICMwKgoyLiAgQW1lbmQgUENBIGNvb3JkaW5hdGVzOiAgZmlyc3Qgd2l0aG91dCB1bmluZmVjdGVkLCB0aGVuIHdpdGgKICBhKSAgd2l0aG91dCBiYXRjaCwgcGF0aWVudCwgc3RyYWluCiAgICAgICpJYmlkICMwIC0tIGFjdHVhbGx5IGRpZCBJIGRvIHRoZW0gYWxsLCBJIHRoaW5rIHNvKgozLiAgV2lsbCB3ZSBjYWxsIHRoZSA2IGlzb2xhdGVzIGJlIGNhbGxlZCAnc3RyYWlucycsICdpc29sYXRlcycsICdjdWx0dXJlcyc/CiAgYSkgIFRoZSByZWFzb24gZm9yIHRoaXMgcXVlc3Rpb24gaXMgdGhhdCB0aGV5IGRvIG5vdCBuZWNlc3NhcmlseSBmb2xsb3cgd2VsbCBkZWZpbmVkIHJ1bGVzIHZpcyBhCiAgICAgIHZpcyB0aGUgc2ltaWxhcml0eSB0byB0aGUgY2hhcmFjdGVyaXplZCBnZW5vbWUuCgo0LiAgTWFrZSBzdXJlIHRoZSBhY3R1YWwgZXhwZXJpbWVudGFsIGJhdGNoIGNvbXBhcmlzb24gaXMgbWFpbnRhaW5lZAogICAgICAqSSBiZWxpZXZlIHRoaXMgaXMgY29ycmVjdCoKNS4gIE1ha2Ugc3VyZSB0aGF0IGl0IGlzIGNsZWFyIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gJ2V4cGVyaW1lbnRhbCBiYXRjaCBlZmZlY3QnIGFuZCAnZG9ub3IgZWZmZWN0JwogICAgICAqSSB0aGluayB0aGlzIGlzIGNsZWFyLCBJIGhhdmUgYSBzcGVjaWZpYyBjYWxsIGJlZm9yZSBlYWNoIGNvbXBhcmlzb24gbm93LCBpcyB0aGVyZSBhIGJlc3Qgd2F5IHRvIGVuc3VyZSB0aGlzPyoKNi4gIFJlcG9ydCBjb3JyZWxhdGlvbiBiZXR3ZWVuIGZhY3RvcnMgYW5kIGNvbXBvbmVudHMuCiAgICAgICpEb25lIGZvciB0aGUgY2FzZSBvZiBzYW1wbGVzIHdpdGhvdXQgdW5pbmZlY3RlZCoKNy4gIEZpdCBsaW5lYXIgbW9kZWwgYWZ0ZXIgcmVtb3ZpbmcgZWFjaCBmYWN0b3IgYW5kIG9ic2VydmUgdmFyaWFuY2UgcmVtYWluaW5nIHRvIGRpcmVjdGx5IGFzc2VzcwogICAgJXZhciBpbiBlYWNoIGZhY3Rvci4gICdNb3N0IGVsZWdhbnQgbWV0aG9kIGlzIHRoZSBtaXhlZCBlZmZlY3QgbW9kZWwnCjguICBUZXJtcyBhZ3JlZWQgdG86CiAgICBhKSAgImRvbm9yIjogIChwYXRpZW50KSBib2IgamFuZSBhbGljZQogICAgYikgICJpc29sYXRlIjogIChzdHJhaW4pIDIxNzEgMjE3MiBldGMKICAgIGMpICAic3RhdHVzIjogICAoc2VsZiBoZWFsaW5nLCBjaHJvbmljLCB1bmluZmVjdGVkKQogICAgZCkgICJiYXRjaCI6ICAgIChhIGIpIFRoZSB0d28gbGlicmFyeS9STkEgaXNvbGF0aW9uIGRhdGVzCiAgICBlKSAgInNucCI6ICAgICAgKHggeSB6KSBDbGFkZSB0b3AgKGZldyksIGNsYWRlIG1pZGRsZSAoc29tZSksIGNsYWRlIGJvdHRvbSAobWFueSkKOS4gIE1ha2UgYSBtb2RlbCBvZiB+IDAgKyBpc29sYXRlICsgZG9ub3IgKyBiYXRjaCAobWF5YmUgbm90IGJhdGNoKQogICAgRml0IHRvIHRoZSBkYXRhLCB0YWtlIHJlc2lkdWFscywgbWFrZSBQQ0Egb2YgdGhlIHJlc2lkdWFscywgY29sb3IgYnkgc2gvY2gKMTAuIENvbXBhcmUgcGFyYXNpdGUgZGF0YSBjbHVzdGVyaW5nIHRvIHNlZSBpZiBzb21lIG90aGVyIHN1cnJvZ2F0ZSBmYWN0b3IgdG8gbWFrZSBzb21lIHNlbnNlIG9mCiAgICB0aGlzICAgIGEpICBHb2FsOiBhdHRlbXB0IHRvIGlkZW50aWZ5IHRoZSBjbHVzdGVyIG9mIHN0cmFpbnMgd2hpY2ggaGFzIHBlY3VsaWFyIGh1bWFuIGV4cHJlc3Npb24uCjExLiBTZWUgd2hhdCBoYXBwZW5zIGlmIEkgcmVsYWJlbCA2MzUgYXMgc3RyYWluIGNoMjUwNAogICAgICAqRG9uZSBmb3Igc29tZSB2YWx1ZXMgb2YgJ2RvbmUnIEkgYW0gbm90IGNlcnRhaW4gb2YgdGhlIHJlc3VsdCoKMTIuIExlYXJuIGJlc3QgbWV0aG9kCgojIEluc3RhbGxhdGlvbiBhbmQgc2V0dXAKClRoZXNlIGFyZSBybWFya2Rvd24gZG9jdW1lbnRzIHdoaWNoIG1ha2UgaGVhdnkgdXNlIG9mIHRoZSBocGdsdG9vbHMgcGFja2FnZS4gIFRoZSBmb2xsb3dpbmcgc2VjdGlvbgpkZW1vbnN0cmF0ZXMgaG93IHRvIHNldCB0aGF0IHVwIGluIGEgY2xlYW4gUiBlbnZpcm9ubWVudC4KCmBgYHtyIHNldHVwLCBldmFsPUZBTFNFfQojIyBVc2UgUidzIGluc3RhbGwucGFja2FnZXMgdG8gaW5zdGFsbCBkZXZ0b29scy4KaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQojIyBVc2UgZGV2dG9vbHMgdG8gaW5zdGFsbCBocGdsdG9vbHMuCmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZWxzYXllZGxhYi9ocGdsdG9vbHMiKQojIyBMb2FkIGhwZ2x0b29scyBpbnRvIHRoZSBSIGVudmlyb25tZW50LgpsaWJyYXJ5KGhwZ2x0b29scykKIyMgVXNlIGhwZ2x0b29scycgYXV0b2xvYWRzX2FsbCgpIGZ1bmN0aW9uIHRvIGluc3RhbGwgdGhlIG1hbnkgcGFja2FnZXMgdXNlZCBieSBocGdsdG9vbHMuCmF1dG9sb2Fkc19hbGwoKQpgYGAKClRoaXMgZG9jdW1lbnQgaXMgcmF0aGVyIHNob3J0LiAgSW4gc29tZSBvdGhlcnMgSSBkaWQgdGhlIHByZXByb2Nlc3NpbmcsIHNoYXJlZCwgZXRjIHN0ZXBzIGFzICdjaGlsZCcKZG9jdW1lbnRzIG9mIHRoaXMgYW5kIHRoZXkgd291bGQgYmUgYXBwZW5kZWQgaGVyZS4gIEluIHRoaXMgY2FzZSBJIGRpZCBub3QuCgpgYGB7ciBzYXZlbWV9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIHBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCiAgbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiAgdGhpc19zYXZlIDwtIHBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cm1kX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikKICBtZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHRoaXNfc2F2ZSkpCiAgdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQp9CmBgYAo=