Script for analysis of T. brucei BSF parasites from Briggs et al. 2021

Ran with R version 3.6.3 in Feburary 2021

reticulate::py_discover_config(required_module="phate")
python:         /usr/local/bin/python3
libpython:      /usr/local/opt/python@3.8/Frameworks/Python.framework/Versions/3.8/lib/python3.8/config-3.8-darwin/libpython3.8.dylib
pythonhome:     /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8:/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8
version:        3.8.5 (default, Jul 21 2020, 10:41:41)  [Clang 10.0.0 (clang-1000.11.45.5)]
numpy:          /Users/emmabriggs/Library/Python/3.8/lib/python/site-packages/numpy
numpy_version:  1.19.2
phate:          /Users/emmabriggs/Library/Python/3.8/lib/python/site-packages/phate

NOTE: Python version was forced by RETICULATE_PYTHON
## gglot2 plotting themes used for UMAP plots

UMAP_theme <- theme(axis.line=element_blank(), axis.ticks = element_blank(),  panel.background = element_rect(size=0.5,linetype="solid",color="black"), plot.title = element_text(size = 10, face = "bold", hjust = 0.05, vjust = -8), axis.text.x = element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.y =  element_blank(), legend.title = element_blank())

LOAD IN PROVIDED COUNTS DATA HERE

Load in csv files and generate seurat object

gene ID must be row names and cell barcodes must be column names

Normalise and log transform data with SCRAN

Select variable genes with two methods, scran and seurat

head(var_genes_02)
[1] "Tbrucei---Tb927.11.880"   "Tbrucei---Tb927.10.8940" 
[3] "Tbrucei---Tb927.3.3270"   "Tbrucei---Tb927.1.2390"  
[5] "Tbrucei---Tb927.10.14140" "Tbrucei---Tb927.9.6210"  

Seurat integration of WT replicates

# Find integration anchors - 8 dims was found to give the most robust results by performing several iteration, varying this parameter and asses expression of known marker genes
WT.tryp.anchors <- FindIntegrationAnchors(object.list = list,  dims = 1:8, anchor.features = WT_features)
Some cell names are duplicated across objects provided. Renaming to enforce unique cell names.Scaling features for provided objects

  |                                                  | 0 % ~calculating  
  |+++++++++++++++++++++++++                         | 50% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=02s  
Finding all pairwise anchors

  |                                                  | 0 % ~calculating  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 11571 anchors
Filtering anchors
    Retained 3064 anchors

  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01m 17s
# Find integration anchors - 8 dims was found to give the most robust results by performing several iteration, varying this parameter and asses expression of known marker genes
WT.tryp.anchors <- FindIntegrationAnchors(object.list = list,  dims = 1:8, anchor.features = WT_features)
Some cell names are duplicated across objects provided. Renaming to enforce unique cell names.Scaling features for provided objects

  |                                                  | 0 % ~calculating  
  |+++++++++++++++++++++++++                         | 50% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s  
Finding all pairwise anchors

  |                                                  | 0 % ~calculating  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 11571 anchors
Filtering anchors
    Retained 3064 anchors

  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01m 10s
# Get all genes in both replicate experiment objects
all.genes <- row.names(list[[1]])
# Rerun clustering with selected resolution parameter (selected 0.4 based on clustree results and several iterations)
WT.integrated <- FindClusters(WT.integrated, resolution = 0.4)
Error in FindClusters.Seurat(WT.integrated, resolution = 0.4) : 
  Provided graph.name not present in Seurat object

Identify cell types

Name clusters

PHATE, trajectory inference and differential expression analysis

Trajectory inference with slingshot

#pdf(file = "WT_intergation_ident_PHATE.pdf", width = 4.5, height = 4.5)
plot(reducedDims(sce)$PHATE, col = mycolours[sce$ident], pch = 16, cex = 0.5, bty='l', xlim=rev(c(-0.022, 0.032))) + lines(SlingshotDataSet(sce), col = "black", lwd = 2)
integer(0)

#pdf(file = "WT_intergation_pseudo_PHATE_TI.pdf", width = 4.8, height = 5.3)
plot(reducedDims(sce)$PHATE, col = plotcol, alpha = 0.5,pch = 16, cex = 0.5, xlim=rev(c(-0.023, 0.033)), axes = FALSE, ann = FALSE, xaxt='n', yaxt='n') + lines(SlingshotDataSet(sce), col = "black", lwd = 2)
integer(0)

#pdf(file = "PHATE_WT_GAPHD.pdf", width = 1.8, height = 2)
p + labs(title = "GAPDH", color = "Expression") + NoLegend() + PHATE_theme + ylim(-0.01, 0.01) + xlim(0.033, -0.023)
Scale for 'y' is already present. Adding another scale for 'y', which
will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which
will replace the existing scale.

p <- FeaturePlot(object = WT.integrated, features = "Tbrucei---Tb927.10.14140", min.cutoff = 0, max.cutoff = 4, reduction = "phate") 
p[[1]]$layers[[1]]$aes_params$alpha = 0.5
p[[1]]$layers[[1]]$aes_params$shape = 16
#pdf(file = "PHATE_WT_PYK1.pdf", width = 1.8, height = 2)
p + labs(title = "PYK1", color = "Expression") + NoLegend() + PHATE_theme + ylim(-0.01, 0.01) + xlim(0.033, -0.023)
Scale for 'y' is already present. Adding another scale for 'y', which
will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which
will replace the existing scale.

#dev.off()
p <- FeaturePlot(object = WT.integrated, features = "Tbrucei---Tb927.7.5940", min.cutoff = 0, max.cutoff = 4, reduction = "phate") 
p[[1]]$layers[[1]]$aes_params$alpha = 0.5
p[[1]]$layers[[1]]$aes_params$shape = 16
#pdf(file = "PHATE_WT_PAD2.pdf", width = 1.8, height = 2)
p + labs(title = "PAD2", color = "Expression") + NoLegend() + PHATE_theme + ylim(-0.01, 0.01) + xlim(0.033, -0.023)
Scale for 'y' is already present. Adding another scale for 'y', which
will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which
will replace the existing scale.

#dev.off()
#pdf(file = "PHATE_WT_EP1.pdf", width = 1.8, height = 2)
p + labs(title = "EP1", color = "Expression") + NoLegend() + PHATE_theme + ylim(-0.01, 0.01) + xlim(0.033, -0.023)
Scale for 'y' is already present. Adding another scale for 'y', which
will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which
will replace the existing scale.

Differential exression with tradeSeq

# You can set this control to try and prevent overfitting the data
control <- gam.control()
control$maxit <- 1000

# Get the counts data for the genes you want to use 
counts <- as.matrix(WT.integrated@assays[["RNA"]]@counts)

# Determine the appropriate number of knots (read on trade-seq page how to select best number of knots (points on trajectory))
# Test 3 to 15 knots, select best based on plots
#icMat <- evaluateK(counts = counts, sds = crv, k=3:15, nGenes = 200, verbose=FALSE)

# fit the GAM to the data (selected 6 knots). This takes a bit of time. 
sce_GAM_all_genes <- fitGAM(counts = counts, sds = crv, nknots = 6, control = control)
# save the single cell with GAM 
save(sce_GAM_all_genes, file = "sce_GAM_WT_integrated")
# Test gene expression association with trajectory
assoRes <- associationTest(sce_GAM_all_genes)
write.csv(assoRes, file = "assoRes_WT_integrated2.csv")

## Select genes for clustering into gene modules
## select p value < 0.05 and FC > 2
diff.genes <- subset(assoRes, pvalue < 0.05)
diff.genes <- subset(diff.genes, meanLogFC > 0.301)

#Get list of genes
diff.genes <- as.character(rownames(diff.genes))
write.csv(diff.genes, file = "diff_genes.csv")
# Can test different merging thresholds but just running RSEC. 
RSEC <- RSEC(clusPat$rsec, eraseOld = FALSE, rerunClusterMany = FALSE, mergeMethod="adjP", mergeCutoff=0.95)
Note: Merging will be done on ' makeConsensus ', with clustering index 1

Plot expression of genes as heatmap using scaled expression of differentially expressed genes

Plot individual gene expression


cluster_info <- WT.integrated@active.ident
sce_GAM_all_genes$cluster <- cluster_info

# Get raw counts data
counts <- WT.integrated@assays[["RNA"]]@counts

# Plot

#pdf(file = "Tb927.11.15100_WT_smooth.pdf", width = 1.8, height = 1.5)
plotSmoothers(sce_GAM_all_genes, counts, gene = "Tbrucei---Tb927.11.15100", lwd = 1, sample = 1, alpha = 0.1, pointCol = "cluster") +
  labs(title = "Tb927.11.15100") + scale_color_manual(values = c("#f8766d", "#7cae00", "#01bfc4", "#c77cff")) + guides(color = FALSE) 
  theme(plot.title = element_text(size = 9, face = "bold"), axis.text.x = element_text(size = 8), axis.title.x = element_text(size = 8), axis.title.y = element_text(size = 8), axis.text.y =  element_text(size = 8))
#dev.off()
  

DE analysis of slender vs stumpy cells for each replicate experiment, results detailed in Figure S3

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgV1QgYmxvb2RzdHJlYW0gZm9ybSB0IGJydWNlaSBkaWZmZXJlbnRpYXRpb24iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KIyMgU2NyaXB0IGZvciBhbmFseXNpcyBvZiBULiBicnVjZWkgQlNGIHBhcmFzaXRlcyBmcm9tIEJyaWdncyBldCBhbC4gMjAyMQojIyBSYW4gd2l0aCBSIHZlcnNpb24gMy42LjMgaW4gRmVidXJhcnkgMjAyMQoKYGBge3J9CgojIyMgUmVxdWlyZWQgcGFja2FnZXMgIyMjCgojIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikgdjEuMzAuMQojaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKSB2Mi4zLjIKI2luc3RhbGwucGFja2FnZXMoJ1NldXJhdCcpIHYzLjIuMi45OQojQmlvY01hbmFnZXI6Omluc3RhbGwoInNjcmFuIikgdjEuMTQuNgojQmlvY01hbmFnZXI6Omluc3RhbGwoInNjYXRlciIpIHYxLjE0LjYKI0Jpb2NNYW5hZ2VyOjppbnN0YWxsKCJNQVNUIikgdjEuMTIuMAojQmlvY01hbmFnZXI6Omluc3RhbGwoIlNpbmdsZUNlbGxFeHBlcmltZW50IikgdjEuOC4wCiNCaW9jTWFuYWdlcjo6aW5zdGFsbCgic2xpbmdzaG90IikgdjEuNC4wCiNCaW9jTWFuYWdlcjo6aW5zdGFsbCgidHJhZGVTZXEiKSB2MS4zLjIxCiNCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2x1c3RlckV4cGVyaW1lbnQiKSB2Mi42LjEKI0Jpb2NNYW5hZ2VyOjppbnN0YWxsKCJnZ3B1YnIiKSB2MC40LjAKI0Jpb2NNYW5hZ2VyOjppbnN0YWxsKCJjbHVzdHJlZSIpIHYwLjQuMyAKI0Jpb2NNYW5hZ2VyOjppbnN0YWxsKCJtZ2N2IikgdjEuOC0zNAojIEZvciBwaGF0ZSwgZmlyc3QgaW5zdGFsbCBwaGF0ZVIgcHl0aG9uIHBhY2thZ2UgLSBodHRwczovL2dpdGh1Yi5jb20vS3Jpc2huYXN3YW15TGFiL3BoYXRlUgojaW5zdGFsbC5wYWNrYWdlcygicGhhdGVSIikgdjEuMC43CgojIyNMb2FkIHJlcXVpcmVkIHBhY2thZ2VzIyMKIyBGb3IgcHJlcG9jZXNzaW5nLCByZXBsaWNhdGUgaW50ZWdyYXRpb24gYW5kIGNsdXN0ZXJpbmcgYW5hbHlzaXMKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoc2NyYW4pCmxpYnJhcnkoc2NhdGVyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KE1BU1QpCmxpYnJhcnkoU2luZ2xlQ2VsbEV4cGVyaW1lbnQpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KGNsdXN0cmVlKQoKIyBGb3IgdHJhamVjdG9yeSBpbmZlcmVuY2UgYW5kIERFIGFuYWx5c2lzCmxpYnJhcnkoc2xpbmdzaG90KQpsaWJyYXJ5KHRyYWRlU2VxKQpsaWJyYXJ5KGNsdXN0ZXJFeHBlcmltZW50KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KG1nY3YpCmxpYnJhcnkoQ29tcGxleEhlYXRtYXApCmxpYnJhcnkocGhhdGVSKQojIFNldCBwYXRoIGZvciB0aGUgcGhhdGUgcHl0aG9uIG1vZHVsZQpTeXMuc2V0ZW52KFJFVElDVUxBVEVfUFlUSE9OID0gIi91c3IvbG9jYWwvYmluL3B5dGhvbjMiKQpyZXRpY3VsYXRlOjpweV9kaXNjb3Zlcl9jb25maWcocmVxdWlyZWRfbW9kdWxlPSJwaGF0ZSIpCmBgYAoKCmBgYHtyfQojIyBnZ2xvdDIgcGxvdHRpbmcgdGhlbWVzIHVzZWQgZm9yIFVNQVAgcGxvdHMKClVNQVBfdGhlbWUgPC0gdGhlbWUoYXhpcy5saW5lPWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3Qoc2l6ZT0wLjUsbGluZXR5cGU9InNvbGlkIixjb2xvcj0iYmxhY2siKSwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC4wNSwgdmp1c3QgPSAtOCksIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnkgPSAgZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKIyMjIExPQUQgSU4gUFJPVklERUQgQ09VTlRTIERBVEEgSEVSRSAjIyMjCgojIExvYWQgaW4gY3N2IGZpbGVzIGFuZCBnZW5lcmF0ZSBzZXVyYXQgb2JqZWN0CiMgZ2VuZSBJRCBtdXN0IGJlIHJvdyBuYW1lcyBhbmQgY2VsbCBiYXJjb2RlcyBtdXN0IGJlIGNvbHVtbiBuYW1lcwoKYGBge3J9CgpXVF8wMV9jb3VudHNfZGF0YSA8LSByZWFkLmNzdigiUEFUSC9XVF8wMV9jb3VudHNfZGF0YS5jc3YiLCByb3cubmFtZXM9MSkKCldUXzAxIDwtIENyZWF0ZVNldXJhdE9iamVjdChXVF8wMV9jb3VudHNfZGF0YSwgcHJvamVjdCA9ICJXVF8wMSIpCgpXVF8wMl9jb3VudHNfZGF0YSA8LSByZWFkLmNzdigiUEFUSC9XVF8wMl9jb3VudHNfZGF0YS5jc3YiLCByb3cubmFtZXM9MSkKCldUXzAyIDwtIENyZWF0ZVNldXJhdE9iamVjdChXVF8wMl9jb3VudHNfZGF0YSwgcHJvamVjdCA9ICJXVF8wMiIpCgoKYGBgCgojIyBOb3JtYWxpc2UgYW5kIGxvZyB0cmFuc2Zvcm0gZGF0YSB3aXRoIFNDUkFOICMjCgpgYGB7cn0KIyBFeHBvcnQgdG8gYSBTaW5nbGVDZWxsRXhwZXJpbWVudCBvYmplY3QgCgpzY2VfV1RfMDEgPC0gYXMuU2luZ2xlQ2VsbEV4cGVyaW1lbnQoV1RfMDEpCnNjZV9XVF8wMiA8LSBhcy5TaW5nbGVDZWxsRXhwZXJpbWVudChXVF8wMikKCiMgUHJlLWNsdXN0ZXIgY2VsbHMuIEZhY3RvcnMgYXJlIGZpcnN0IGdlbmVyYXRlZCB3aXRoaW4gY2x1c3RlcnMgdGhlbiByZXNjYWxlZCB0byBub3JtYWxpemUgYmV0d2VlbiBjbHVzdGVycwpxY2x1c3RfMDEgPC0gc2NyYW46OnF1aWNrQ2x1c3RlcihzY2VfV1RfMDEsIG1pbi5zaXplID0gMzApCnFjbHVzdF8wMiA8LSBzY3Jhbjo6cXVpY2tDbHVzdGVyKHNjZV9XVF8wMiwgbWluLnNpemUgPSAzMCkKCiMgQ29tcHV0ZSBzaXplIGZhY3RvcnMgLSByZW1vdmVzIGxvdyBhYnVuZGFuY2UgZ2VuZXMKc2NlX1dUXzAxIDwtIHNjcmFuOjpjb21wdXRlU3VtRmFjdG9ycyhzY2VfV1RfMDEsIGNsdXN0ZXJzID0gcWNsdXN0XzAxKQpzY2VfV1RfMDEgPC0gc2NhdGVyOjpsb2dOb3JtQ291bnRzKHNjZV9XVF8wMSkKCnNjZV9XVF8wMiA8LSBzY3Jhbjo6Y29tcHV0ZVN1bUZhY3RvcnMoc2NlX1dUXzAyLCBjbHVzdGVycyA9IHFjbHVzdF8wMikKc2NlX1dUXzAyIDwtIHNjYXRlcjo6bG9nTm9ybUNvdW50cyhzY2VfV1RfMDIpCgojIyBDb252ZXJ0IGJhY2sgdG8gU2V1cmF0IG9iamVjdCAKV1RfMDEgPC0gYXMuU2V1cmF0KHNjZV9XVF8wMSwgY291bnRzID0gImNvdW50cyIsIGRhdGEgPSAibG9nY291bnRzIikKV1RfMDIgPC0gYXMuU2V1cmF0KHNjZV9XVF8wMiwgY291bnRzID0gImNvdW50cyIsIGRhdGEgPSAibG9nY291bnRzIikKYGBgCgojIyBTZWxlY3QgdmFyaWFibGUgZ2VuZXMgd2l0aCB0d28gbWV0aG9kcywgc2NyYW4gYW5kIHNldXJhdAoKYGBge3J9CiMjIERldGVjdCB2YXJpYWJsZSBnZW5lcyBhbmQgcmVtb3ZlIFZTRyBmb3IgdmFyaWFibGUgZ2VuZSBsaXN0CgojIGZpbmQgdmFpcmJsZSBnZW5lcyB3aXRoIHNjcmFuCmRlY18wMSA8LSBtb2RlbEdlbmVWYXIoc2NlX1dUXzAxKQpkZWNfMDIgPC0gbW9kZWxHZW5lVmFyKHNjZV9XVF8wMikKCnRvcC5odmdzMl8wMSA8LSBnZXRUb3BIVkdzKGRlY18wMSwgbj0zMDAwKQp0b3AuaHZnczJfMDIgPC0gZ2V0VG9wSFZHcyhkZWNfMDIsIG49MzAwMCkKCiMjIHZhcmlhYmxlIGdlbmVzIHdpdGggc2V1cmF0CldUXzAxLmZlYXR1cmVzIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKFdUXzAxLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDMwMDAsIGFzc2F5ID0gIlJOQSIpIApXVF8wMi5mZWF0dXJlcyA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhXVF8wMiwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAzMDAwLCBhc3NheSA9ICJSTkEiKSAKCnRvcDMwMDBfMDEgPC0gaGVhZChWYXJpYWJsZUZlYXR1cmVzKFdUXzAxLmZlYXR1cmVzKSwgMzAwMCkKdG9wMzAwMF8wMiA8LSBoZWFkKFZhcmlhYmxlRmVhdHVyZXMoV1RfMDIuZmVhdHVyZXMpLCAzMDAwKQoKIyMgRmluZCB0aG9zZSBpbiBjb21tb24KY29tbW9uX3Zhcl9nZW5lc18wMSA8LSBpbnRlcnNlY3QodG9wLmh2Z3MyXzAxLCB0b3AzMDAwXzAxKQpjb21tb25fdmFyX2dlbmVzXzAyIDwtIGludGVyc2VjdCh0b3AuaHZnczJfMDIsIHRvcDMwMDBfMDIpCgojIyByZW1vdmUgdGhlIFZTR3MKVlNHX2xpc3QgPC0gcmVhZC50YWJsZSgiVlNHX2xpc3QiLCBxdW90ZT0iXCIiLCBjb21tZW50LmNoYXI9IiIpClZTR3MgPC1hcy5jaGFyYWN0ZXIoVlNHX2xpc3QkVjEpCgp2YXJfZ2VuZXNfMDEgPC0gc3Vic2V0KGNvbW1vbl92YXJfZ2VuZXNfMDEsICEgY29tbW9uX3Zhcl9nZW5lc18wMSAlaW4lIFZTR3MpCnZhcl9nZW5lc18wMiA8LSBzdWJzZXQoY29tbW9uX3Zhcl9nZW5lc18wMiwgISBjb21tb25fdmFyX2dlbmVzXzAyICVpbiUgVlNHcykKCiMgQWRkIHZhcmlhYmxlIGdlbmVzIHRvIG9iamVjdHMKV1RfMDFAYXNzYXlzW1siUk5BIl1dQHZhci5mZWF0dXJlcyA8LSB2YXJfZ2VuZXNfMDEKV1RfMDJAYXNzYXlzW1siUk5BIl1dQHZhci5mZWF0dXJlcyA8LSB2YXJfZ2VuZXNfMDIKCmhlYWQodmFyX2dlbmVzXzAxKQpoZWFkKHZhcl9nZW5lc18wMikKCmBgYAoKCiMjIFNldXJhdCBpbnRlZ3JhdGlvbiBvZiBXVCByZXBsaWNhdGVzICMjCgpgYGB7cn0KbGlzdCA8LSBsaXN0KFdUXzAxLCBXVF8wMikKCiMgRmluZCBjb21tb24gZmVhdHVyZXMgZm9yIGludGVncmF0dW9uIApXVF9mZWF0dXJlcyA8LSBTZWxlY3RJbnRlZ3JhdGlvbkZlYXR1cmVzKG9iamVjdC5saXN0ID0gbGlzdCkKCiMgRmluZCBpbnRlZ3JhdGlvbiBhbmNob3JzIC0gOCBkaW1zIHdhcyBmb3VuZCB0byBnaXZlIHRoZSBtb3N0IHJvYnVzdCByZXN1bHRzIGJ5IHBlcmZvcm1pbmcgc2V2ZXJhbCBpdGVyYXRpb24sIHZhcnlpbmcgdGhpcyBwYXJhbWV0ZXIgYW5kIGFzc2VzIGV4cHJlc3Npb24gb2Yga25vd24gbWFya2VyIGdlbmVzCldULnRyeXAuYW5jaG9ycyA8LSBGaW5kSW50ZWdyYXRpb25BbmNob3JzKG9iamVjdC5saXN0ID0gbGlzdCwgIGRpbXMgPSAxOjgsIGFuY2hvci5mZWF0dXJlcyA9IFdUX2ZlYXR1cmVzKQoKIyBHZXQgYWxsIGdlbmVzIGluIGJvdGggcmVwbGljYXRlIGV4cGVyaW1lbnQgb2JqZWN0cwphbGwuZ2VuZXMgPC0gcm93Lm5hbWVzKGxpc3RbWzFdXSkKZm9yIChpIGluIDI6bGVuZ3RoKGxpc3QpKSB7CiAgYWxsLmdlbmVzIDwtIGludGVyc2VjdChhbGwuZ2VuZXMsIHJvdy5uYW1lcyhsaXN0W1tpXV0pKQp9CgojIEludGVncmF0ZSBzYW1wbGVzCldULmludGVncmF0ZWQgPC0gSW50ZWdyYXRlRGF0YShhbmNob3JzZXQgPSBXVC50cnlwLmFuY2hvcnMsICBkaW1zID0gMTo4LCBmZWF0dXJlcy50by5pbnRlZ3JhdGU9YWxsLmdlbmVzKQoKIyBTY2FsZSB0aGUgZGF0YSBhbmQgcmVncmVzcyB2YXJpYWJsZSBkdWUgdG8gdG90YWwgUk5BLiBUaGlzIGNhbiB0YWtlIHNvbWUgdGltZQpXVC5pbnRlZ3JhdGVkIDwtIFNjYWxlRGF0YShXVC5pbnRlZ3JhdGVkLCB2YXJzLnRvLnJlZ3Jlc3MgPSAibkNvdW50X1JOQSIsIGZlYXR1cmVzID0gYWxsLmdlbmVzKQoKIyMgUENBIGFuYWx5c2lzIGFuZCBzZWxlY3RvaW9uICMjCgpXVC5pbnRlZ3JhdGVkIDwtIFJ1blBDQShvYmplY3QgPSBXVC5pbnRlZ3JhdGVkLCB2ZXJib3NlID0gRkFMU0UsIGZlYXR1cmVzID0gV1RfZmVhdHVyZXMpCgojIERldGVybWluZSBwZXJjZW50IG9mIHZhcmlhdGlvbiBhc3NvY2lhdGVkIHdpdGggZWFjaCBQQwpwY3QgPC0gV1QuaW50ZWdyYXRlZEByZWR1Y3Rpb25zW1sicGNhIl1dQHN0ZGV2IC8gc3VtKFdULmludGVncmF0ZWRAcmVkdWN0aW9uc1tbInBjYSJdXUBzdGRldikgKiAxMDAKIyBDYWxjdWxhdGUgY3VtdWxhdGl2ZSBwZXJjZW50cyBmb3IgZWFjaCBQQwpjdW11IDwtIGN1bXN1bShwY3QpCiMgRGV0ZXJtaW5lIHdoaWNoIFBDIGV4aGliaXRzIGN1bXVsYXRpdmUgcGVyY2VudCBncmVhdGVyIHRoYW4gOTAlIGFuZCAlIHZhcmlhdGlvbiBhc3NvY2lhdGVkIHdpdGggdGhlIFBDIGFzIGxlc3MgdGhhbiA1CmNvMSA8LSB3aGljaChjdW11ID4gOTAgJiBwY3QgPCA1KVsxXQpjbzEKIyBEZXRlcm1pbmUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB2YXJpYXRpb24gb2YgUEMgYW5kIHN1YnNlcXVlbnQgUEMKY28yIDwtIHNvcnQod2hpY2goKHBjdFsxOmxlbmd0aChwY3QpIC0gMV0gLSBwY3RbMjpsZW5ndGgocGN0KV0pID4gMC4wNSksIGRlY3JlYXNpbmcgPSBUKVsxXSArIDEKIyBsYXN0IHBvaW50IHdoZXJlIGNoYW5nZSBvZiAlIG9mIHZhcmlhdGlvbiBpcyBtb3JlIHRoYW4gMC4xJS4KY28yCiMgTWluaW11bSBvZiB0aGUgdHdvIGNhbGN1bGF0aW9uCnBjcyA8LSBtaW4oY28xLCBjbzIpCnBjcwojIENyZWF0ZSBhIGRhdGFmcmFtZSB3aXRoIHZhbHVlcwpwbG90X2RmIDwtIGRhdGEuZnJhbWUocGN0ID0gcGN0LCAKICAgICAgICAgICAgICAgICAgICAgIGN1bXUgPSBjdW11LCAKICAgICAgICAgICAgICAgICAgICAgIHJhbmsgPSAxOmxlbmd0aChwY3QpKQojIEVsYm93IHBsb3QgdG8gdmlzdWFsaXplIAojcGRmKGZpbGUgPSAiZGltX2VibGJvd19wbG90LnBkZiIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMykKZ2dwbG90KHBsb3RfZGYsIGFlcyhjdW11LCBwY3QsIGxhYmVsID0gcmFuaywgY29sb3IgPSByYW5rID4gcGNzKSkgKyAKICBnZW9tX3RleHQoKSArIHhsYWIoIkN1bXVsYXRpdmUgJSB2YXJpYW5jZSIpICsgeWxhYigiJSBvZiB2YXJpYW5jZSIpICsgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iPiAwLjElIHZhcmlhbmNlIikpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSA5MCwgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZT0iZGFzaGVkIikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtaW4ocGN0W3BjdCA+IDVdKSwgY29sb3IgPSAiZ3JleSIpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwgCiAgICAgICAgYXhpcy50ZXh0LnkgPSAgZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCiNkZXYub2ZmKCkKCmBgYAoKYGBge3J9CiMjIENsdXN0ZXJpbmcgYW5hbHlzaXMKCldULmludGVncmF0ZWQgPC0gRmluZE5laWdoYm9ycyhXVC5pbnRlZ3JhdGVkLCBkaW1zID0gMTo4LCBrLnBhcmFtID0gMzAsIG5uLm1ldGhvZCA9ICJhbm5veSIsIGFubm95Lm1ldHJpYyA9ICJldWNsaWRlYW4iKQoKIyMgUnVuIGNsdXN0ZXIgdG8gc2VlIHJlc3VsdHMgb2YgZGlmZmVyZW50IGNsdXN0ZXJpbmcgcmVzb2x1dGlvbnMKI1dUX2NsdXN0cmVlIDwtIEZpbmRDbHVzdGVycyhXVC5pbnRlZ3JhdGVkLCByZXNvbHV0aW9uID0gYygwLjEsIDAuMiwgMC4zLCAwLjQsIDAuNiwgMC44LCAxKSkKCiNwZGYoZmlsZSA9ICJjbHVzdHJlZS5wZGYiLCB3aWR0aCA9IDQsIGhlaWdodCA9IDgpCiNjbHVzdHJlZShXVF9jbHVzdHJlZSwgcHJlZml4ID0gImludGVncmF0ZWRfc25uX3Jlcy4iLCBleHBycyA9IGMoImRhdGEiLCAiY291bnRzIiwgInNjYWxlLmRhdGEiKSwgYXNzYXkgPSBOVUxMKQojZGV2Lm9mZigpCgojIFJlcnVuIGNsdXN0ZXJpbmcgd2l0aCBzZWxlY3RlZCByZXNvbHV0aW9uIHBhcmFtZXRlciAoc2VsZWN0ZWQgMC40IGJhc2VkIG9uIGNsdXN0cmVlIHJlc3VsdHMgYW5kIHNldmVyYWwgaXRlcmF0aW9ucykKV1QuaW50ZWdyYXRlZCA8LSBGaW5kQ2x1c3RlcnMoV1QuaW50ZWdyYXRlZCwgcmVzb2x1dGlvbiA9IDAuNCkKCiMjIFVNQVAgdml6dWFsaXNhdGlvbgoKIyBSdW4gVU1BUCB3aXRoIHNhbWUgbnVtYmVyIG9mIGRpbXMgYXMgZm9yIEZpbmROZWlnaGJvcnMKV1QuaW50ZWdyYXRlZCA8LSBSdW5VTUFQKFdULmludGVncmF0ZWQsIGRpbXMgPSAxOjgsIG1pbi5kaXN0ID0gMC4xKQoKIyBPcmRlciBjbHVzdGVycyBhcyBuZWVkZWQgCmxldmVscyhXVC5pbnRlZ3JhdGVkKSA8LSBjKCIzIiwgIjIiLCAiMSIsICIwIikKCiMgUGxvdCBjZWxscyBieSByZXBsaWNhdGUgZXhwZXJpbWVudCBvciBzZXVyYXQgY2x1YXRlZXIgKGNoYW5nZWUgZ3JvdXAuYnkgcGFyYW1ldGVyKQpwIDwtIERpbVBsb3QoV1QuaW50ZWdyYXRlZCwgcHQuc2l6ZSA9IDAuNSkgCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlVNQVBfV1RfaW50ZXJnYXRpb25fcmVwbGljYXRlLnBkZiIsIHdpZHRoID0gMiwgaGVpZ2h0ID0gMi4yKQpwCiNkZXYub2ZmKCkKYGBgCgpgYGB7cn0KIyBQbG90IGNvbG91cmVkIGJ5IHRvdGFsIFJOQSBwZXIgY2VsbApwIDwtIEZlYXR1cmVQbG90KFdULmludGVncmF0ZWQsIGZlYXR1cmVzID0gIm5GZWF0dXJlX1JOQSIpCnAKYGBgCgoKIyMjIElkZW50aWZ5IGNlbGwgdHlwZXMgIyMjCgpgYGB7cn0KIyMgUGxvdCBrbm93biBtYXJrZXIgcmF3IGV4cHJlc3Npb24KCkRlZmF1bHRBc3NheShXVC5pbnRlZ3JhdGVkKSA8LSAiUk5BIgoKcCA8LSBGZWF0dXJlUGxvdChvYmplY3QgPSBXVC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJUYnJ1Y2VpLS0tVGI5MjcuNi40MjgwIiwgbWluLmN1dG9mZiA9IDAsIG1heC5jdXRvZmYgPSA0KQpwW1sxXV0kbGF5ZXJzW1sxXV0kYWVzX3BhcmFtcyRhbHBoYSA9IDAuNQpwW1sxXV0kbGF5ZXJzW1sxXV0kYWVzX3BhcmFtcyRzaGFwZSA9IDE2CiNwZGYoZmlsZSA9ICJVTUFQX1dUX0dBUEhELnBkZiIsIHdpZHRoID0gMS44LCBoZWlnaHQgPSAyKQpwICsgbGFicyh0aXRsZSA9ICJHQVBESCIsIGNvbG9yID0gIkV4cHJlc3Npb24iKSArIE5vTGVnZW5kKCkgKyBVTUFQX3RoZW1lCiNkZXYub2ZmKCkKYGBgCgpgYGB7cn0KcCA8LSBGZWF0dXJlUGxvdChvYmplY3QgPSBXVC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9ICJUYnJ1Y2VpLS0tVGI5MjcuMTAuMTQxNDAiLCBtaW4uY3V0b2ZmID0gMCwgbWF4LmN1dG9mZiA9IDQpCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlVNQVBfV1RfUFlLMS5wZGYiLCB3aWR0aCA9IDEuOCwgaGVpZ2h0ID0gMikKcCArIGxhYnModGl0bGUgPSAiUFlLMSIsIGNvbG9yID0gIkV4cHJlc3Npb24iKSArIE5vTGVnZW5kKCkgKyBVTUFQX3RoZW1lCiNkZXYub2ZmKCkKYGBgCgoKYGBge3J9CgpwIDwtIEZlYXR1cmVQbG90KG9iamVjdCA9IFdULmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlRicnVjZWktLS1UYjkyNy43LjU5NDAiLCBtaW4uY3V0b2ZmID0gMCwgbWF4LmN1dG9mZiA9IDQpCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlVNQVBfV1RfUEFEMi5wZGYiLCB3aWR0aCA9IDEuOCwgaGVpZ2h0ID0gMikKcCArIGxhYnModGl0bGUgPSAiUEFEMiIsIGNvbG9yID0gIkV4cHJlc3Npb24iKSArIE5vTGVnZW5kKCkgKyBVTUFQX3RoZW1lCiNkZXYub2ZmKCkKYGBgCgpgYGB7cn0KCnAgPC0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gV1QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiVGJydWNlaS0tLVRiOTI3LjEwLjEwMjYwIiwgbWluLmN1dG9mZiA9IDAsIG1heC5jdXRvZmYgPSA0KSArIGxhYnModGl0bGUgPSAiRVAxIiwgY29sb3IgPSAiRXhwcmVzc2lvbiIpCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlVNQVBfV1RfRVAxLnBkZiIsIHdpZHRoID0gMS44LCBoZWlnaHQgPSAyKQpwICsgTm9MZWdlbmQoKSArIFVNQVBfdGhlbWUKI2Rldi5vZmYoKQpgYGAKCgpgYGB7cn0KIyMjIEZpbmQgYWxsIGNsdXN0ZXIgbWFya2VyIGdlbmVzCnRyeXAubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhXVC5pbnRlZ3JhdGVkLCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCBsb2dmYy50aHJlc2hvbGQgPSAwLjI1LCB0ZXN0LnVzZSA9ICJNQVNUIiwgYXNzYXkgPSAiUk5BIikKI3dyaXRlLmNzdih0cnlwLm1hcmtlcnMsIGZpbGUgPSAicmVzMC00X1dUX2ludGVncmF0ZWRfbWFya2VycyIpCgojIyBQbG90IEhlYXRtYXAgCiMgSWRlbnRpZnkgdG9wIGdlbmVzIGZvciBlYWNoIGNsdXN0ZXIKbWFya2VyX2dlbmVzX1d0IDwtIHRyeXAubWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHRvcF9uKG4gPSAxMCwgd3QgPSBhdmdfbG9nRkMpCgojIExhYmVscyB3ZXJlIGdlbmVyYXRlZCBtYW5hbGx5IGFuZCBoYXZlIGJlZW4gcHJvdmlkZWQgaW4gZmlsZSBtYWtlcl9nZW5lc19XdAoKI21hcmtlcl9nZW5lc19XdCA8LSByZWFkLmRlbGltKCJtYXJrZXJfZ2VuZXNfV3QiKQoKCiMgUGxvdCAsIGdlbmUgbmFtZXMgd2VyZSBhZGRlZCB0byBtYXJrZXJzIG1hbnVhbGx5IGluIGV4Y2VsLiAKI3BkZihmaWxlID0gIkhlYXRtYXBfMF80cmVzX1dUX2ludF90b3AxMC5wZGYiLCB3aWR0aCA9IDYsIGhlaWdodCA9IDYpCkRvSGVhdG1hcChXVC5pbnRlZ3JhdGVkLCBmZWF0dXJlcyA9IGFzLmNoYXJhY3RlcihtYXJrZXJfZ2VuZXNfV3QkZ2VuZSksIGxhYmVsID0gRkFMU0UsIGRyYXcubGluZXMgPSBUUlVFLCBhc3NheSA9ICJpbnRlZ3JhdGVkIikgIysgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSByZXYoYXMuY2hhcmFjdGVyKG1hcmtlcl9nZW5lc19XdCRuYW1lKSkpCiNkZXYub2ZmKCkKYGBgCgojIyBOYW1lIGNsdXN0ZXJzCgpgYGB7cn0KIyBOYW1lIGNsdXN0ZXJzLCBvcmRlciB0byBtYXRjaCB0aGF0IHNldCBieSBsZXZlbHMgYWJvdmUKbmV3LmNsdXN0ZXIuaWRzIDwtIGMoIkxTIEEiLCAiTFMgQiIsICJTUyBBIiwgIlNTIEIiKQpuYW1lcyhuZXcuY2x1c3Rlci5pZHMpIDwtIGxldmVscyhXVC5pbnRlZ3JhdGVkKQpXVC5pbnRlZ3JhdGVkIDwtIFJlbmFtZUlkZW50cyhXVC5pbnRlZ3JhdGVkLCBuZXcuY2x1c3Rlci5pZHMpCiMgUGxvdCB0byBjaGVjayBjbHVzdGVyIG5hbWVzCkRpbVBsb3QoV1QuaW50ZWdyYXRlZCkKCgpgYGAKCmBgYHtyfQojIyBNYXJrZXIgZ2VuZSB2aW9saW4gcGxvdHMKCkRlZmF1bHRBc3NheShXVC5pbnRlZ3JhdGVkKSA8LSAiUk5BIgojcGRmKGZpbGUgPSAibWFya2VyX3ZsblBsb3RzLnBkZiIsIGhlaWdodCA9IDgsIHdpZHRoID0gMTEpClZsblBsb3QoV1QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSBjKCJUYnJ1Y2VpLS0tVGI5MjcuMS40MzEwIiwgIlRicnVjZWktLS1UYjkyNy4xMS44ODAiLCJUYnJ1Y2VpLS0tVGI5MjcuOS43NDcwIiwgIlRicnVjZWktLS1DT0lJIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRicnVjZWktLS1UYjkyNy4xMC4xMDU5MCIsICJUYnJ1Y2VpLS0tVGI5MjcuMTAuODk0MCIsIlRicnVjZWktLS1UYjkyNy4zLjIyMzAiLCJUYnJ1Y2VpLS0tVGI5MjcuNS44MTAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGJydWNlaS0tLVRiOTI3LjEwLjIxOTAiLCAiVGJydWNlaS0tLVRiOTI3LjMuMzI3MCIsIlRicnVjZWktLS1UYjkyNy4xMC43NDEwIiwgIlRicnVjZWktLS1UYjkyNy4xMC4xMDI2MCIpLCBwdC5zaXplID0gMCwgbmNvbCA9IDQpIAojZGV2Lm9mZigpCmBgYAoKIyMjIyBQSEFURSwgdHJhamVjdG9yeSBpbmZlcmVuY2UgYW5kIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzICMjIwoKYGBge3J9CiMjIFJ1biBQSEFURSB3aXRoIGludGVncmF0ZWQgZGF0YQoKIyMgZXh0cmFjdCBkYXRhLCBzZXR0aW5nIGNlbGwgYXMgcm93cyBhbmQgZmVhdHVyZXMgYXMgY29sb3VtcwpkYXRhIDwtIFdULmludGVncmF0ZWRAYXNzYXlzW1siaW50ZWdyYXRlZCJdXUBkYXRhCmZlYXR1cmVzIDwtIFdULmludGVncmF0ZWRAYXNzYXlzW1siaW50ZWdyYXRlZCJdXUB2YXIuZmVhdHVyZXMKZGF0YV9zdWJzZXQgPC0gdChkYXRhW2ZlYXR1cmVzLCBdKQoKIyBSdW4gcGhhdGUKcGhhdGVfb3V0cHV0IDwtIHBoYXRlKGRhdGFfc3Vic2V0KQojIEFkZCBwaGF0ZSByZXN1bHQgdG8gc2V1cmF0IG9iamVjdApwaGF0ZV9vdXRwdXQgPC0gYXMubWF0cml4KHBoYXRlX291dHB1dCkKY29sbmFtZXMoeCA9IHBoYXRlX291dHB1dCkgPC0gcGFzdGUwKCJQSEFURV8iLCAxOm5jb2woeCA9IHBoYXRlX291dHB1dCkpCnBoYXRlLnJlZHVjdGlvbiA8LSBDcmVhdGVEaW1SZWR1Y09iamVjdCgKICBlbWJlZGRpbmdzID0gcGhhdGVfb3V0cHV0LAogIGtleSA9ICJQSEFURV8iLAogIGFzc2F5ID0gImludGVncmF0ZWQiKQpXVC5pbnRlZ3JhdGVkQHJlZHVjdGlvbnMkcGhhdGUgPC0gcGhhdGUucmVkdWN0aW9uCgojIFBsb3R0aW5nIHRoZSBQSEFURSByZXN1bHQgKGEgYnVnIGluIHNldXJhdCBtZWFucyBheGlzIGxpbWl0cyBuZWVkIHRvIGJlIHNldCBtYW51YWxseSkKIyBTZXQgUEhBVEUgcGxvdHRpbmcgdGhlbWUKUEhBVEVfdGhlbWUgPC0gdGhlbWUoYXhpcy5saW5lPWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChzaXplPTAuNSxsaW5ldHlwZT0ic29saWQiLGNvbG9yPSJibGFjayIpLAogICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjk1LCB2anVzdCA9IC04KSwKICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueSA9ICBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCiMgUGxvdCBieSByZXBsaWNhdGUgc2FtcGxlCnAgPC0gRGltUGxvdChXVC5pbnRlZ3JhdGVkLCBncm91cC5ieSA9ICJvcmlnLmlkZW50IiwgcmVkdWN0aW9uID0gInBoYXRlIikKcFtbMV1dJGxheWVyc1tbMV1dJGFlc19wYXJhbXMkYWxwaGEgPSAwLjUKcFtbMV1dJGxheWVyc1tbMV1dJGFlc19wYXJhbXMkc2hhcGUgPSAxNgojcGRmKGZpbGUgPSAiV1RfaW50ZXJnYXRpb25fc2FtcGxlLnBkZiIsIHdpZHRoID0gMywgaGVpZ2h0ID0gMykKcCArIFBIQVRFX3RoZW1lICsgeWxpbSgtMC4wMSwgMC4wMSkgKyB4bGltKDAuMDMzLCAtMC4wMjMpICsgTm9MZWdlbmQoKQojZGV2Lm9mZigpCmBgYAoKYGBge3J9CiMgUGxvdCBieSBjbHVzdGVyCnAgPC0gRGltUGxvdChXVC5pbnRlZ3JhdGVkLCBncm91cC5ieSA9ICJpZGVudCIsIHJlZHVjdGlvbiA9ICJwaGF0ZSIpIApwW1sxXV0kbGF5ZXJzW1sxXV0kYWVzX3BhcmFtcyRhbHBoYSA9IDAuNQpwW1sxXV0kbGF5ZXJzW1sxXV0kYWVzX3BhcmFtcyRzaGFwZSA9IDE2CiNwZGYoZmlsZSA9ICJXVF9pbnRlcmdhdGlvbl9pZGVudF9QSEFURS5wZGYiLCB3aWR0aCA9IDMsIGhlaWdodCA9IDMuMikKcCAgKyBQSEFURV90aGVtZSArIHlsaW0oLTAuMDEsIDAuMDEpICsgeGxpbSgwLjAzMywgLTAuMDIzKSArIE5vTGVnZW5kKCkKI2Rldi5vZmYoKQoKIyBTYXZlIGFnYWluIHRvIGtlZXAgUEhBVEUKc2F2ZShXVC5pbnRlZ3JhdGVkLCBmaWxlID0gIldUX2ludGVncmF0ZWRfc2V1cmF0IikKYGBgCgojIyMgVHJhamVjdG9yeSBpbmZlcmVuY2Ugd2l0aCBzbGluZ3Nob3QKYGBge3J9CiMgY29udmVydCB0byBzY2UKc2NlIDwtIGFzLlNpbmdsZUNlbGxFeHBlcmltZW50KFdULmludGVncmF0ZWQsIGFzc2F5ID0gImludGVncmF0ZWQiKQoKIyBSdW4gc2xpbmdzaG90LCBzZXR0aW5nIHRoZSBzdGFydGluZyBjbHVzdGVyCnNjZSA8LSBzbGluZ3Nob3Qoc2NlLCByZWR1Y2VkRGltID0gJ1BIQVRFJywgY2x1c3RlckxhYmVscyA9IHNjZUBjb2xEYXRhQGxpc3REYXRhW1siaWRlbnQiXV0sIHN0YXJ0LmNsdXMgPSAiTFMgQSIpCgojIyBQbG90cwoKIyBDb2xvdXIgYnkgY2x1c3RlcgpteWNvbG91cnMgPC0gYygiI2Y4NzY2ZCIsICIjN2NhZTAwIiwgIiMwMWJmYzQiLCAiI2M3N2NmZiIpCiNwZGYoZmlsZSA9ICJXVF9pbnRlcmdhdGlvbl9pZGVudF9QSEFURS5wZGYiLCB3aWR0aCA9IDQuNSwgaGVpZ2h0ID0gNC41KQpwbG90KHJlZHVjZWREaW1zKHNjZSkkUEhBVEUsIGNvbCA9IG15Y29sb3Vyc1tzY2UkaWRlbnRdLCBwY2ggPSAxNiwgY2V4ID0gMC41LCBidHk9J2wnLCB4bGltPXJldihjKC0wLjAyMiwgMC4wMzIpKSkgKyBsaW5lcyhTbGluZ3Nob3REYXRhU2V0KHNjZSksIGNvbCA9ICJibGFjayIsIGx3ZCA9IDIpCiNkZXYub2ZmKCkgIApgYGAKCmBgYHtyfQojIGNvbG91ciBieSBwc2V1ZG90aW1lIHZhbHVlCmNvbG9ycyA8LSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoMTEsJ1lsT3JSZCcpWy02XSkoMTAwKQpwbG90Y29sIDwtIGNvbG9yc1tjdXQoc2NlJHNsaW5nUHNldWRvdGltZV8xLCBicmVha3M9MTAwKV0KI3BkZihmaWxlID0gIldUX2ludGVyZ2F0aW9uX3BzZXVkb19QSEFURV9USS5wZGYiLCB3aWR0aCA9IDQuOCwgaGVpZ2h0ID0gNS4zKQpwbG90KHJlZHVjZWREaW1zKHNjZSkkUEhBVEUsIGNvbCA9IHBsb3Rjb2wsIGFscGhhID0gMC41LHBjaCA9IDE2LCBjZXggPSAwLjUsIHhsaW09cmV2KGMoLTAuMDIzLCAwLjAzMykpLCBheGVzID0gRkFMU0UsIGFubiA9IEZBTFNFLCB4YXh0PSduJywgeWF4dD0nbicpICsgbGluZXMoU2xpbmdzaG90RGF0YVNldChzY2UpLCBjb2wgPSAiYmxhY2siLCBsd2QgPSAyKQojZGV2Lm9mZigpCmBgYAoKCmBgYHtyfQojIyBDb2xvdXIgY2VsbHMgYnkgbWFya2VyIGdlbmUgZXhwcmVzc2lvbiBsZXZlbApEZWZhdWx0QXNzYXkoV1QuaW50ZWdyYXRlZCkgPC0gIlJOQSIKCnAgPC0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gV1QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiVGJydWNlaS0tLVRiOTI3LjYuNDI4MCIsIG1pbi5jdXRvZmYgPSAwLCBtYXguY3V0b2ZmID0gNCwgcmVkdWN0aW9uID0gInBoYXRlIikgCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlBIQVRFX1dUX0dBUEhELnBkZiIsIHdpZHRoID0gMS44LCBoZWlnaHQgPSAyKQpwICsgbGFicyh0aXRsZSA9ICJHQVBESCIsIGNvbG9yID0gIkV4cHJlc3Npb24iKSArIE5vTGVnZW5kKCkgKyBQSEFURV90aGVtZSArIHlsaW0oLTAuMDEsIDAuMDEpICsgeGxpbSgwLjAzMywgLTAuMDIzKQojZGV2Lm9mZigpCmBgYAoKYGBge3J9CnAgPC0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gV1QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiVGJydWNlaS0tLVRiOTI3LjEwLjE0MTQwIiwgbWluLmN1dG9mZiA9IDAsIG1heC5jdXRvZmYgPSA0LCByZWR1Y3Rpb24gPSAicGhhdGUiKSAKcFtbMV1dJGxheWVyc1tbMV1dJGFlc19wYXJhbXMkYWxwaGEgPSAwLjUKcFtbMV1dJGxheWVyc1tbMV1dJGFlc19wYXJhbXMkc2hhcGUgPSAxNgojcGRmKGZpbGUgPSAiUEhBVEVfV1RfUFlLMS5wZGYiLCB3aWR0aCA9IDEuOCwgaGVpZ2h0ID0gMikKcCArIGxhYnModGl0bGUgPSAiUFlLMSIsIGNvbG9yID0gIkV4cHJlc3Npb24iKSArIE5vTGVnZW5kKCkgKyBQSEFURV90aGVtZSArIHlsaW0oLTAuMDEsIDAuMDEpICsgeGxpbSgwLjAzMywgLTAuMDIzKQojZGV2Lm9mZigpCmBgYAoKYGBge3J9CnAgPC0gRmVhdHVyZVBsb3Qob2JqZWN0ID0gV1QuaW50ZWdyYXRlZCwgZmVhdHVyZXMgPSAiVGJydWNlaS0tLVRiOTI3LjcuNTk0MCIsIG1pbi5jdXRvZmYgPSAwLCBtYXguY3V0b2ZmID0gNCwgcmVkdWN0aW9uID0gInBoYXRlIikgCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlBIQVRFX1dUX1BBRDIucGRmIiwgd2lkdGggPSAxLjgsIGhlaWdodCA9IDIpCnAgKyBsYWJzKHRpdGxlID0gIlBBRDIiLCBjb2xvciA9ICJFeHByZXNzaW9uIikgKyBOb0xlZ2VuZCgpICsgUEhBVEVfdGhlbWUgKyB5bGltKC0wLjAxLCAwLjAxKSArIHhsaW0oMC4wMzMsIC0wLjAyMykKI2Rldi5vZmYoKQpgYGAKCmBgYHtyfQpwIDwtIEZlYXR1cmVQbG90KG9iamVjdCA9IFdULmludGVncmF0ZWQsIGZlYXR1cmVzID0gIlRicnVjZWktLS1UYjkyNy4xMC4xMDI2MCIsIG1pbi5jdXRvZmYgPSAwLCBtYXguY3V0b2ZmID0gNCwgcmVkdWN0aW9uID0gInBoYXRlIikgCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlBIQVRFX1dUX0VQMS5wZGYiLCB3aWR0aCA9IDEuOCwgaGVpZ2h0ID0gMikKcCArIGxhYnModGl0bGUgPSAiRVAxIiwgY29sb3IgPSAiRXhwcmVzc2lvbiIpICsgTm9MZWdlbmQoKSArIFBIQVRFX3RoZW1lICsgeWxpbSgtMC4wMSwgMC4wMSkgKyB4bGltKDAuMDMzLCAtMC4wMjMpCiNkZXYub2ZmKCkgCgojc2F2ZShzY2UsIGZpbGUgPSAic2NlX3NsaW5nc2hvdF9pbnRlZ3JhdGVkX1dUIikKYGBgCgojIyMgRGlmZmVyZW50aWFsIGV4cmVzc2lvbiB3aXRoIHRyYWRlU2VxCmBgYHtyfQoKIyBFeHRyYWN0IGNsdXN0ZXJzCmNsdXN0ZXJzIDwtIHNjZUBjb2xEYXRhQGxpc3REYXRhW1siaWRlbnQiXV0KIyBHZXQgdGhlIGxpbmVhZ2UsIHNlbGVjdGluZyB0aGUgc2FtZSBzdGFydGluZyBjbHVzdGVyIGlmIGFueQpsaW4gPC0gZ2V0TGluZWFnZXMoU2xpbmdzaG90RGF0YVNldChzY2UpLCBjbHVzdGVyTGFiZWxzID0gY2x1c3RlcnMsIHN0YXJ0LmNsdXMgPSAiTFMgQSIpCiMgR2V0IHRoZSBjdXJ2ZXMKY3J2IDwtIGdldEN1cnZlcyhsaW4pCgojIDJkIGRpZmZ1c2lvbiBtYXAgd2l0aCB0aGUgc2xpbmdzaG90IHRyYWplY3RvcnkgYW5kIGNsdXN0ZXIsIGp1c3QgYXMgYSBjaGVjawpwbG90R2VuZUNvdW50KGN1cnZlID0gY3J2LCBjbHVzdGVycyA9IGNsdXN0ZXJzKQpgYGAKCmBgYHtyfQojIFlvdSBjYW4gc2V0IHRoaXMgY29udHJvbCB0byB0cnkgYW5kIHByZXZlbnQgb3ZlcmZpdHRpbmcgdGhlIGRhdGEKY29udHJvbCA8LSBnYW0uY29udHJvbCgpCmNvbnRyb2wkbWF4aXQgPC0gMTAwMAoKIyBHZXQgdGhlIGNvdW50cyBkYXRhIGZvciB0aGUgZ2VuZXMgeW91IHdhbnQgdG8gdXNlIApjb3VudHMgPC0gYXMubWF0cml4KFdULmludGVncmF0ZWRAYXNzYXlzW1siUk5BIl1dQGNvdW50cykKCiMgRGV0ZXJtaW5lIHRoZSBhcHByb3ByaWF0ZSBudW1iZXIgb2Yga25vdHMgKHJlYWQgb24gdHJhZGUtc2VxIHBhZ2UgaG93IHRvIHNlbGVjdCBiZXN0IG51bWJlciBvZiBrbm90cyAocG9pbnRzIG9uIHRyYWplY3RvcnkpKQojIFRlc3QgMyB0byAxNSBrbm90cywgc2VsZWN0IGJlc3QgYmFzZWQgb24gcGxvdHMKI2ljTWF0IDwtIGV2YWx1YXRlSyhjb3VudHMgPSBjb3VudHMsIHNkcyA9IGNydiwgaz0zOjE1LCBuR2VuZXMgPSAyMDAsIHZlcmJvc2U9RkFMU0UpCgojIGZpdCB0aGUgR0FNIHRvIHRoZSBkYXRhIChzZWxlY3RlZCA2IGtub3RzKS4gVGhpcyB0YWtlcyBhIGJpdCBvZiB0aW1lLiAKc2NlX0dBTV9hbGxfZ2VuZXMgPC0gZml0R0FNKGNvdW50cyA9IGNvdW50cywgc2RzID0gY3J2LCBua25vdHMgPSA2LCBjb250cm9sID0gY29udHJvbCkKIyBzYXZlIHRoZSBzaW5nbGUgY2VsbCB3aXRoIEdBTSAKc2F2ZShzY2VfR0FNX2FsbF9nZW5lcywgZmlsZSA9ICJzY2VfR0FNX1dUX2ludGVncmF0ZWQiKQpgYGAKCmBgYHtyfQojIFRlc3QgZ2VuZSBleHByZXNzaW9uIGFzc29jaWF0aW9uIHdpdGggdHJhamVjdG9yeQphc3NvUmVzIDwtIGFzc29jaWF0aW9uVGVzdChzY2VfR0FNX2FsbF9nZW5lcykKd3JpdGUuY3N2KGFzc29SZXMsIGZpbGUgPSAiYXNzb1Jlc19XVF9pbnRlZ3JhdGVkMi5jc3YiKQoKIyMgU2VsZWN0IGdlbmVzIGZvciBjbHVzdGVyaW5nIGludG8gZ2VuZSBtb2R1bGVzCiMjIHNlbGVjdCBwIHZhbHVlIDwgMC4wNSBhbmQgRkMgPiAyCmRpZmYuZ2VuZXMgPC0gc3Vic2V0KGFzc29SZXMsIHB2YWx1ZSA8IDAuMDUpCmRpZmYuZ2VuZXMgPC0gc3Vic2V0KGRpZmYuZ2VuZXMsIG1lYW5Mb2dGQyA+IDAuMzAxKQoKI0dldCBsaXN0IG9mIGdlbmVzCmRpZmYuZ2VuZXMgPC0gYXMuY2hhcmFjdGVyKHJvd25hbWVzKGRpZmYuZ2VuZXMpKQp3cml0ZS5jc3YoZGlmZi5nZW5lcywgZmlsZSA9ICJkaWZmX2dlbmVzLmNzdiIpCmBgYAoKYGBge3J9CiMgU2V0IG51bWJlciBvZiBwb2ludHMgb3ZlciB0cmFqZWN0b3IgdG8gdGVzdApuUG9pbnRzQ2x1cyA8LSAxMDAKCiMgQ2x1c3RlciBnZW5lcyBhbmQgbWVyZ2UgaW50byBjb2V4cHJlc3Npb24gbW9kdWxlcwpjbHVzUGF0IDwtIGNsdXN0ZXJFeHByZXNzaW9uUGF0dGVybnMoc2NlX0dBTV9hbGxfZ2VuZXMsIG5Qb2ludHMgPSBuUG9pbnRzQ2x1cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVzID0gZGlmZi5nZW5lcywgbWVyZ2VNZXRob2Q9ImFkalAiLCBtZXJnZUN1dG9mZj0wLjk1KQpzYXZlKGNsdXNQYXQsIGZpbGUgPSAiY2x1c1BhdF9XVF9pbmV0Z3JhdGVkXzEwMCIpCgojIENhbiB0ZXN0IGRpZmZlcmVudCBtZXJnaW5nIHRocmVzaG9sZHMgYnV0IGp1c3QgcnVubmluZyBSU0VDLiAKUlNFQyA8LSBSU0VDKGNsdXNQYXQkcnNlYywgZXJhc2VPbGQgPSBGQUxTRSwgcmVydW5DbHVzdGVyTWFueSA9IEZBTFNFLCBtZXJnZU1ldGhvZD0iYWRqUCIsIG1lcmdlQ3V0b2ZmPTAuOTUpCgpzYXZlKFJTRUMsIGZpbGUgPSAiUlNFQ19XVF9pbnRlZ3JhdGVkIikKCmBgYAoKIyMgUGxvdCBleHByZXNzaW9uIG9mIGdlbmVzIGFzIGhlYXRtYXAgdXNpbmcgc2NhbGVkIGV4cHJlc3Npb24gb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCgpgYGB7cn0KIyBHZXQgZ2VuZSBtb2R1bGVzCmNsdXN0ZXJMYWJlbHMgPC0gcHJpbWFyeUNsdXN0ZXIoUlNFQykKY2x1c3RlcnNfdW5pcSA8LSB1bmlxdWUoY2x1c3RlckxhYmVscykKCiMgR2V0IHNjYWxlZCBleHByZXNzaW9uIGRhdGEgZm9yIHBsb3R0aW5nCmdlbmVJZCA8LSByb3duYW1lcyhjbHVzUGF0JHloYXRTY2FsZWQpCmRhdGEgPC0gY2x1c1BhdCR5aGF0U2NhbGVkCnJvd25hbWVzKGRhdGEpIDwtIGdlbmVJZAoKIyBPcmRlciBnZW5lcyBiYXNlZCBvbiBnZW5lIG1vZHVsZSAobWFudWFsbHkgc2V0KQpkYXRhIDwtIGRhdGFbLCBzZXFfbGVuKG5jb2woZGF0YSkpXQpkYXRhIDwtIGNiaW5kKGRhdGEsY2x1c3RlckxhYmVscykKZGF0YSA8LSBkYXRhW29yZGVyKGZhY3RvcihkYXRhWyxuY29sKGRhdGEpXSwgbGV2ZWxzID0gYygiLTEiLCAiNSIsIHJldihjKCAiNiIsICI5IiwgIjEiLCAiNCIsICIzIiwgIjIiLCAiOCIsICI3IikpKSkpLF0KCiMgR2V0IGdlbmUgY2x1c3RlcnMgZm9yIGVhY2ggZ2VuZSBmb3IgbGFiZWxsaW5nIHRoZSBoZWF0bWFwLCB0aGVuIHJlbW92ZSBmcm9tIHBsb3R0aW5nIGRhdGEKY2x1c3RlcnMgPC0gZGF0YVssIDEwMV0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiN3cml0ZS5jc3YoZGF0YSwgZmlsZSA9ICJHZW5lX21vZHVsZXNfV1RfaW50ZWdyYXRlZC5jc3YiKQoKZGF0YSA8LWRhdGFbLC0xMDFdCgojIHBsb3QgaGVhdG1hcApjb2xvcnMgPC0gc2V0TmFtZXMoY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDExLCdZbE9yUmQnKVstNl0pKDEwMCksIDE6MTAwKQpwbG90Y29sIDwtIGNvbG9yc1tjdXQoc2NlJHNsaW5nUHNldWRvdGltZV8xLCBicmVha3M9MTAwKV0KaGEgPC0gSGVhdG1hcEFubm90YXRpb24ocHNldWRvdGltZSA9IDE6MTAwLCBjb2wgPSBsaXN0KHBzZXVkb3RpbWUgPSBjb2xvcnMpLCAgc2hvd19sZWdlbmQgPSBGQUxTRSkKcm93X2hhIDwtIHJvd0Fubm90YXRpb24oY2x1c3RlciA9IGNsdXN0ZXJzLCBjb2wgPSBsaXN0KGNsdXN0ZXIgPSBjKCItMSIgPSAiZ3JleSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiNSI9IiNGODc2NkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjYiPSIjREU4QzAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI5Ij0iI0I3OUYwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMSI9IiMwMEJBMzgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjQiPSIjMDBCRkM0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMyI9IiM2MTlDRkYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIiPSIjQzc3Q0ZGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4Ij0iI0Y1NjRFMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiNyI9IiNGRjY0QjAiKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgojcGRmKGZpbGUgPSAiV1RfbW9kdWxlX2hlYXRtYXAucGRmIiwgd2lkdGggPSA0LjUsIGhlaWdodCA9IDUpCkhlYXRtYXAoZGF0YSwgY2x1c3Rlcl9jb2x1bW5zID0gRkFMU0UsIHNob3dfY29sdW1uX25hbWVzID0gRkFMU0UsIGNsdXN0ZXJfcm93cyA9IEZBTFNFLCBzaG93X3Jvd19uYW1lcyA9IEZBTFNFLAogICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQgPSBUUlVFLCBoZWF0bWFwX2xlZ2VuZF9wYXJhbSA9IGxpc3QodGl0bGUgPSAiZXhwcmVzc2lvbiIpLAogICAgICAgIHRvcF9hbm5vdGF0aW9uID0gaGEsIGxlZnRfYW5ub3RhdGlvbiA9IHJvd19oYSkKI2Rldi5vZmYoKQpgYGAKIyMgUGxvdCBpbmRpdmlkdWFsIGdlbmUgZXhwcmVzc2lvbgoKYGBge3J9CgpjbHVzdGVyX2luZm8gPC0gV1QuaW50ZWdyYXRlZEBhY3RpdmUuaWRlbnQKc2NlX0dBTV9hbGxfZ2VuZXMkY2x1c3RlciA8LSBjbHVzdGVyX2luZm8KCiMgR2V0IHJhdyBjb3VudHMgZGF0YQpjb3VudHMgPC0gV1QuaW50ZWdyYXRlZEBhc3NheXNbWyJSTkEiXV1AY291bnRzCgojIFBsb3QKCiNwZGYoZmlsZSA9ICJUYjkyNy4xMS4xNTEwMF9XVF9zbW9vdGgucGRmIiwgd2lkdGggPSAxLjgsIGhlaWdodCA9IDEuNSkKcGxvdFNtb290aGVycyhzY2VfR0FNX2FsbF9nZW5lcywgY291bnRzLCBnZW5lID0gIlRicnVjZWktLS1UYjkyNy4xMS4xNTEwMCIsIGx3ZCA9IDEsIHNhbXBsZSA9IDEsIGFscGhhID0gMC4xLCBwb2ludENvbCA9ICJjbHVzdGVyIikgKwogIGxhYnModGl0bGUgPSAiVGI5MjcuMTEuMTUxMDAiKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjZjg3NjZkIiwgIiM3Y2FlMDAiLCAiIzAxYmZjNCIsICIjYzc3Y2ZmIikpICsgZ3VpZGVzKGNvbG9yID0gRkFMU0UpIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiYm9sZCIpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksIGF4aXMudGV4dC55ID0gIGVsZW1lbnRfdGV4dChzaXplID0gOCkpCiNkZXYub2ZmKCkKICAKYGBgCgoKIyMjIERFIGFuYWx5c2lzIG9mIHNsZW5kZXIgdnMgc3R1bXB5IGNlbGxzIGZvciBlYWNoIHJlcGxpY2F0ZSBleHBlcmltZW50LCByZXN1bHRzIGRldGFpbGVkIGluIEZpZ3VyZSBTMwoKYGBge3J9CiNSZW5hbWUgc2V1cmF0IG9iamVjdCB0byBhdm9pZCBjb25mdXNpb24KV1QuaW50ZWdyYXRlZF8wMiA8LSBXVC5pbnRlZ3JhdGVkCiMgUmVwZWF0IGNsdXN0ZXJpbmcgd2l0aCBsb3dlciByZXNvbHV0aW9uIHRvIGNsdXN0ZXIgc2xlbmRlciBhbmQgc3R1bXB5IGNlbGwgdHlwZXMKCgpXVC5pbnRlZ3JhdGVkXzAyIDwtIEZpbmRDbHVzdGVycyhXVC5pbnRlZ3JhdGVkXzAyLCByZXNvbHV0aW9uID0gMC4xKQoKRGltUGxvdChXVC5pbnRlZ3JhdGVkXzAyKSAgICAKYGBgCgpgYGB7cn0KIyBTdWJzZXQgY2VsbHMgZnJvbSBlYWNoIHJlcGxpY2F0ZSBleHBlcmltZW50IHRvIGFuYWx5c2lzIHNlcGVyYXRlbHkgCldUXzAxIDwtIHN1YnNldChXVC5pbnRlZ3JhdGVkXzAyLCBvcmlnLmlkZW50ID09ICJXVF8wMSIpCldUXzAyIDwtIHN1YnNldChXVC5pbnRlZ3JhdGVkXzAyLCBvcmlnLmlkZW50ID09ICJXVF8wMiIpCgojIFBsb3QgZWFjaCByZXBsaWNhdGUKcCA8LSBEaW1QbG90KFdUXzAxLCBwdC5zaXplID0gMC41KSAKcFtbMV1dJGxheWVyc1tbMV1dJGFlc19wYXJhbXMkYWxwaGEgPSAwLjUKcFtbMV1dJGxheWVyc1tbMV1dJGFlc19wYXJhbXMkc2hhcGUgPSAxNgojcGRmKGZpbGUgPSAiVU1BUF9XVF8wMl9jbHVzLnBkZiIsIHdpZHRoID0gMiwgaGVpZ2h0ID0gMi4yKQpwICsgTm9MZWdlbmQoKSArIFVNQVBfdGhlbWUKI2Rldi5vZmYoKQpgYGAKCgpgYGB7cn0KIyBQbG90IGVhY2ggcmVwbGljYXRlCnAgPC0gRGltUGxvdChXVF8wMiwgcHQuc2l6ZSA9IDAuNSkgCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlVNQVBfV1RfMDJfY2x1cy5wZGYiLCB3aWR0aCA9IDIsIGhlaWdodCA9IDIuMikKcCArIE5vTGVnZW5kKCkgKyBVTUFQX3RoZW1lCiNkZXYub2ZmKCkKYGBgCgoKYGBge3J9CgojIElkZW50aWZ5IERFIGdlbmVzIGJldHdlZW4gc2xlbmRlciBhbmQgc3R1bXB5IGNlbGxzIGZvciBlYWNoIHJlcGxpY2F0ZQoKV1RfMDFfbWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhXVF8wMSwgb25seS5wb3MgPSBUUlVFLCBtaW4ucGN0ID0gMC4yNSwgbG9nZmMudGhyZXNob2xkID0gMC4yNSwgdGVzdC51c2UgPSAiTUFTVCIsIGFzc2F5ID0gIlJOQSIpCiN3cml0ZS5jc3YoV1RfMDFfbWFya2VycywgZmlsZSA9ICJXVF8wMV9tYXJrZXJzLmNzdiIpCgpXVF8wMl9tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKFdUXzAyLCBvbmx5LnBvcyA9IFRSVUUsIG1pbi5wY3QgPSAwLjI1LCBsb2dmYy50aHJlc2hvbGQgPSAwLjI1LCB0ZXN0LnVzZSA9ICJNQVNUIiwgYXNzYXkgPSAiUk5BIikKI3dyaXRlLmNzdihXVF8wMl9tYXJrZXJzLCBmaWxlID0gIldUXzAyX21hcmtlcnMuY3N2IikKCiMgTWFya2VycyB3ZXJlIGV4cGxvdHRlZCBhbmQgcGxvdHRlZCBpbiBncmFwaHBhZAoKIyBHZW5lcmF0ZSBmZWF0dXJlIHBsb3RzIG9mIGluZGl2aWR1YWwgZ2VuZXMKcCA8LSBGZWF0dXJlUGxvdChvYmplY3QgPSBXVF8wMiwgZmVhdHVyZXMgPSAiVGJydWNlaS0tLVRiOTI3LjkuMTQyOTAiLCBtaW4uY3V0b2ZmID0gMCwgbWF4LmN1dG9mZiA9IDQpICsgbGFicyh0aXRsZSA9ICJDSUYyIiwgY29sb3IgPSAiRXhwcmVzc2lvbiIpCnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJGFscGhhID0gMC41CnBbWzFdXSRsYXllcnNbWzFdXSRhZXNfcGFyYW1zJHNoYXBlID0gMTYKI3BkZihmaWxlID0gIlVNQVBfV1RfMDJfQ0lGMi5wZGYiLCB3aWR0aCA9IDEuOCwgaGVpZ2h0ID0gMikKcCArIE5vTGVnZW5kKCkgKyBVTUFQX3RoZW1lCiNkZXYub2ZmKCkKCmBgYAoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLiAKClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4K