Introduction

scRepertoire is designed to take filter contig outputs from the 10x Genomics Cell Ranger pipeline, process that data to assign clonotype based on two TCR or Ig chains and analyze the clonotype dynamics. The latter can be separated into 1) clonotype-only analysis functions, such as unique clonotypes or clonal space quantification, and 2) interaction with mRNA expression data using Seurat or SingleCellExperiment packages.

Load libraries

Load Seurat Object

1. Load contigs

scRepertoire functions using the filtered_contig_annotations.csv output from the 10x Genomics Cell Ranger. This file is located in the ./outs/ directory of the VDJ alignment folder. To generate a list of contigs to use for scRepertoire:

  • load the filtered_contig_annotations.csv for each of the samples.

  • make a list in the R environment.

2. Combining Contigs into Clones


contig_list <- list(L1, L2, L3_B, L4_B,L5,L6, L7)
contig_list_with_PBMC <- list(L1, L2, L3_B, L4_B,L5,L6, L7, PBMC)

combined.TCR <- combineTCR(contig_list,
                           samples = c("L1", "L2", "L3_B", "L4_B", "L5", "L6", "L7"),
                           removeNA = FALSE,
                           removeMulti = FALSE,
                           filterMulti = FALSE)

combined.TCR_with_PBMC <- combineTCR(contig_list_with_PBMC, 
                           samples = c("L1", "L2", "L3_B", "L4_B", "L5", "L6", "L7", 
                                       "PBMC"),
                           removeNA = FALSE, 
                           removeMulti = FALSE, 
                           filterMulti = FALSE)

#  exportClones(combined.TCR, 
#               write.file = TRUE,
#               dir = "../TCR_Analysis/",
#              file.name = "clones.csv")
# 
# exportClones(combined.TCR_with_PBMC, 
#              write.file = TRUE,
#              dir = "../TCR_Analysis/",
#              file.name = "clones_with_PBMC.csv")

head(combined.TCR_with_PBMC[[1]])
NA

3. Basic Clonal Visualizations

3.1. clonalQuant

#clonalQuant

 clonalQuant(combined.TCR, 
            cloneCall="strict", 
            chain = "both", 
            scale = TRUE)



clonalQuant(combined.TCR_with_PBMC, 
            cloneCall="strict", 
            chain = "both", 
            scale = TRUE)


clonalQuant(combined.TCR, cloneCall = "gene", group.by = "sample", scale = TRUE)


clonalQuant(combined.TCR_with_PBMC, cloneCall = "gene", group.by = "sample", scale = TRUE)

NA
NA

3.2 clonalAbundance

#clonalAbundance

clonalAbundance(combined.TCR_with_PBMC, 
                cloneCall = "gene",  palette = "Zissou 1",
                scale = FALSE)+ 
  scale_fill_manual(values = hcl.colors(8,"geyser"))

clonalAbundance(combined.TCR_with_PBMC, 
                cloneCall = "gene", palette = "Zissou 1",
                scale = TRUE)

3.3 clonalLength

#clonalLength
clonalLength(combined.TCR_with_PBMC, 
             cloneCall="nt", 
             chain = "both") 

clonalLength(combined.TCR_with_PBMC, 
             cloneCall="aa", 
             chain = "both") 
#TRA
clonalLength(combined.TCR_with_PBMC, 
             cloneCall="nt", 
             chain = "TRA", 
             scale = TRUE) 

clonalLength(combined.TCR_with_PBMC, 
             cloneCall="aa", 
             chain = "TRA", 
             scale = TRUE) 

#TRB
clonalLength(combined.TCR_with_PBMC, 
             cloneCall="nt", 
             chain = "TRB", 
             scale = TRUE) 

clonalLength(combined.TCR_with_PBMC, 
             cloneCall="aa", 
             chain = "TRB", 
             scale = TRUE) 

3.4 clonalCompare

# clonalCompare


clonalCompare(combined.TCR_with_PBMC, 
                  top.clones = 10, 
                  samples = c("L1", "L2"), 
                  cloneCall="aa", 
                  graph = "alluvial")


clonalCompare(combined.TCR_with_PBMC, 
                  top.clones = 10, 
                  samples = c("L3_B", "L4_B"), 
                  cloneCall="aa", 
                  graph = "alluvial")


clonalCompare(combined.TCR_with_PBMC, 
                  top.clones = 10, 
                  samples = c("L5", "L6","L7"), 
                  cloneCall="aa", 
                  graph = "alluvial")



clonalCompare(combined.TCR_with_PBMC, 
                  top.clones = 10, 
                  samples = c("L5","L6"), 
                  cloneCall="aa", 
                  graph = "alluvial")


clonalCompare(combined.TCR_with_PBMC, 
                  top.clones = 10, 
                  samples = c("L5","L7"), 
                  cloneCall="aa", 
                  graph = "alluvial")


clonalCompare(combined.TCR_with_PBMC, 
                  top.clones = 10, 
                  samples = c("L6","L7"), 
                  cloneCall="aa", 
                  graph = "alluvial")


clonalCompare(combined.TCR_with_PBMC, 
                  top.clones = 10, 
                  samples = c("L1", "L2", "L3_B", "L4_B", "L5", "L6", "L7", "PBMC"), 
                  cloneCall="aa", 
                  graph = "alluvial")


# clonalCompare(combined.TCR_with_PBMC, 
#               top.clones = 10,
#               highlight.clones = c("CVVSDNTGGFKTIF_CASSVRRERANTGELFF", "NA_CASSVRRERANTGELFF"),
#               relabel.clones = TRUE,
#               samples = c("L1", "L2"), 
#               cloneCall="aa", 
#               graph = "alluvial")
# 
# 
# clonalCompare(combined.TCR_with_PBMC, clones = c("CVVSDNTGGFKTIF_CASSVRRERANTGELFF", "NA_CASSVRRERANTGELFF"),
#     relabel.clones = TRUE, samples = c("L1", "L2"), cloneCall = "aa", graph = "alluvial")

3.5 clonalScatter

#clonalScatter

clonalScatter(combined.TCR_with_PBMC, 
              cloneCall ="gene", 
              x.axis = "L1", 
              y.axis = "L2",
              dot.size = "total",
              graph = "proportion")



clonalScatter(combined.TCR_with_PBMC, 
              cloneCall ="gene", 
              x.axis = "L3_B", 
              y.axis = "L4_B",
              dot.size = "total",
              graph = "proportion")


clonalScatter(combined.TCR_with_PBMC, 
              cloneCall ="gene", 
              x.axis = "L5", 
              y.axis = "L6",
              dot.size = "total",
              graph = "proportion")


clonalScatter(combined.TCR_with_PBMC, 
              cloneCall ="gene", 
              x.axis = "L5", 
              y.axis = "L7",
              dot.size = "total",
              graph = "proportion")


clonalScatter(combined.TCR_with_PBMC, 
              cloneCall ="gene", 
              x.axis = "L6", 
              y.axis = "L7",
              dot.size = "total",
              graph = "proportion")

4. Visualizing Clonal Dynamics

4.1 clonalHomeostasis

# Visualizing Clonal Dynamics

# clonalHomeostasis

clonalHomeostasis(combined.TCR_with_PBMC, 
                  cloneCall = "gene")



clonalHomeostasis(combined.TCR_with_PBMC, 
                  cloneCall = "gene",
                  cloneSize = c(Rare = 0.001, Small = 0.01, Medium = 0.1, Large = 0.3, Hyperexpanded =1))

4.2 clonalProportion

# clonalProportion

clonalProportion(combined.TCR_with_PBMC, 
                 cloneCall = "gene") 




clonalProportion(combined.TCR_with_PBMC, 
                 cloneCall = "nt",
                 clonalSplit = c(1, 5, 10, 100, 1000, 10000)) 

NA
NA
NA

5. Summarizing Repertoires

# Summarizing Repertoires

#percentAA

percentAA(combined.TCR, 
          chain = "TRB", 
          aa.length = 20)
Warning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generated

# positionalEntropy
# We can also quantify the level of entropy/diversity across amino acid residues along the cdr3 sequence. positionalEntropy() combines the quantification by residue of percentAA() with the diversity calls in clonalDiversity().
# 
# method
# 
# “shannon” - Shannon Diversity
# “inv.simpson” - Inverse Simpson Diversity
# “norm.entropy” - Normalized Entropy

positionalEntropy(combined.TCR_with_PBMC, 
                  chain = "TRB", 
                  aa.length = 20)
Warning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generatedWarning: invalid factor level, NA generated

# positionalProperty
# Like positionalEntropy(), we can also examine a series of amino acid properties along the cdr3 sequences using positionalProperty(). Important differences from the above function for positionalProperty() is dropping NA values as they would void the mean calculation. positionalProperty() also display a ribbon with the 95% confidence interval surrounding the mean value for the selected properties.
# 
# method
# 
# “Atchley” - Atchley Factors
# “Kidera” - Kidera Factors
# “stScales” - stScales Vectors
# “tScales” - tScales Vectors
# “VHSE” - Vectors of Hydrophobic, Steric, and Electronic properties

# positionalProperty(combined.TCR_with_PBMC[c(1,2)], 
#                   chain = "TRB", 
#                   aa.length = 20, 
#                   method = "Atchley") + 
#   scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
# 
# positionalProperty(combined.TCR_with_PBMC[c(3,4)], 
#                   chain = "TRB", 
#                   aa.length = 20, 
#                   method = "Atchley") + 
#   scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
# 
# positionalProperty(combined.TCR_with_PBMC[c(5,6)], 
#                   chain = "TRB", 
#                   aa.length = 20, 
#                   method = "Atchley") + 
#   scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
# 
# positionalProperty(combined.TCR_with_PBMC[c(5,7)], 
#                   chain = "TRB", 
#                   aa.length = 20, 
#                   method = "Atchley") + 
#   scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
# 
# 
# positionalProperty(combined.TCR_with_PBMC[c(6,7)], 
#                   chain = "TRB", 
#                   aa.length = 20, 
#                   method = "Atchley") + 
#   scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])
# 
# positionalProperty(combined.TCR_with_PBMC[c(5,6,7)], 
#                   chain = "TRB", 
#                   aa.length = 20, 
#                   method = "Atchley") + 
#   scale_color_manual(values = hcl.colors(5, "inferno")[c(2,4)])


# vizGenes
# A visualization of the relative usage of genes of the TCR or BCR, using vizGenes(). There is some functional crossover between vizGenes() and two functions below called percentGenes() and percentVJ(). But vizGenes() is more adaptable to allow for comparisons across chains, scaling, etc.

vizGenes(combined.TCR_with_PBMC, 
         x.axis = "TRBV",
         y.axis = NULL,
         plot = "barplot",  
         scale = TRUE)




vizGenes(combined.TCR_with_PBMC, 
        x.axis = "TRAV",
        y.axis = NULL,
        plot = "barplot",  
        scale = TRUE)



vizGenes(combined.TCR[c(1,2,3,4,5,6,7)], 
         x.axis = "TRBV",
         y.axis = "TRBJ",
         plot = "heatmap",  
         scale = TRUE)


vizGenes(combined.TCR[c(1,2,3,4,5,6,7)], 
         x.axis = "TRAV",
         y.axis = "TRAJ",
         plot = "heatmap",  
         scale = TRUE)


# For the P17 patient samples, what if we are interested in chain pairings, we can look at TRBV and TRAV at the same time using them as inputs to x.axis and y.axis.
vizGenes(combined.TCR[c(1,2)], 
         x.axis = "TRBV",
         y.axis = "TRAV",
         plot = "heatmap", 
         scale = FALSE)



# percentGenes
# Quantify the proportion of V or J gene usage with percentGenes(). Like percentAA(), we select the chain of interest and then indicate the gene of interest with the gene parameter. Two major limitations of percentGenes() are, 1) the function quantifies only V or J genes, and 2) the quantification of the genes are limited to all the V or J genes seen across the samples, not all possible V or J genes.

percentGenes(combined.TCR_with_PBMC, 
             chain = "TRB", 
             gene = "Vgene")


percentGenes(combined.TCR_with_PBMC, 
             chain = "TRA", 
             gene = "Vgene")



percentGenes(combined.TCR_with_PBMC, 
             chain = "TRB", 
             gene = "Jgene")


percentGenes(combined.TCR_with_PBMC, 
             chain = "TRA", 
             gene = "Jgene")



# percentVJ
# Quantify the proportion of V and J gene usage with percentVJ(). Like percentGenes(), this function will quantify the percentage of V and J paired together across individual repertoires. The output can be visualized using a heatmap or as input for further dimensional reduction.

percentVJ(combined.TCR_with_PBMC, 
          chain = "TRB")


percentVJ(combined.TCR_with_PBMC, 
          chain = "TRA")



# percentKmer
# Another quantification of the composition of the CDR3 sequence is to define motifs by sliding across the amino acid or nucleotide sequences at set intervals resulting in substrings or kmers.
# 
# motif.length
# 
# Numerical value for the length of the kmer.
# top.motifs
# 
# Display the most variable genes determined by mean absolute deviation (MAD).
percentKmer(combined.TCR_with_PBMC, 
            cloneCall = "aa",
            chain = "TRB", 
            motif.length = 3, 
            top.motifs = 25)


percentKmer(combined.TCR_with_PBMC, 
            cloneCall = "aa",
            chain = "TRA", 
            motif.length = 3, 
            top.motifs = 25)




percentKmer(combined.TCR_with_PBMC, 
            cloneCall = "nt",
            chain = "TRB", 
            motif.length = 3, 
            top.motifs = 25)


percentKmer(combined.TCR_with_PBMC, 
            cloneCall = "nt",
            chain = "TRA", 
            motif.length = 3, 
            top.motifs = 25)

NA
NA
NA
NA
NA
NA
NA
NA
NA

6. Comparing Clonal Diversity and Overlap

# clonalDiversity


clonalDiversity(combined.TCR_with_PBMC, 
                cloneCall = "gene")


#clonalSizeDistribution


clonalSizeDistribution(combined.TCR_with_PBMC, 
                       cloneCall = "aa", 
                       method= "ward.D2")




#clonalOverlap

clonalOverlap(combined.TCR_with_PBMC, 
              cloneCall = "strict", 
              method = "morisita")



clonalOverlap(combined.TCR_with_PBMC, 
              cloneCall = "strict", 
              method = "raw")

7. Combining Clones and Single-Cell Objects


# Combining Clones and Single-Cell Objects

#Getting a sample of a Seurat object
scRep_example <- get(data("All_samples_Merged"))
Warning: data set 'All_samples_Merged' not found
#Define color palette 
colorblind_vector <- hcl.colors(n=7, palette = "inferno", fixup = TRUE)


scRep_example <- combineExpression(combined.TCR, 
                                   scRep_example, 
                                   cloneCall="gene", 
                                   group.by = "sample", 
                                   proportion = FALSE, 
                                   cloneSize=c(Single=1, Small=5, Medium=20, Large=100, Hyperexpanded=500))

DimPlot(scRep_example, group.by = "cloneSize")


DimPlot(scRep_example, group.by = "cloneSize") +
    scale_color_manual(values=rev(colorblind_vector[c(1,3,4,5,6)]))

NA
NA

8. Visualizations for Single-Cell Objects


# Visualizations for Single-Cell Objects
# clonalOverlay

#Adding patient information
scRep_example$Patient_origin <- substr(scRep_example$orig.ident, 1,3)

clonalOverlay(scRep_example, 
              reduction = "umap", 
              freq.cutpoint = 1, 
              bins = 10, 
              facet.by = "Patient_origin") + 
              guides(color = "none")


#clonalNetwork
#ggraph needs to be loaded due to issues with ggplot
library(ggraph)

Attaching package: 'ggraph'

The following object is masked from 'package:sp':

    geometry
clonalNetwork(scRep_example, 
              reduction = "umap", 
              group.by = "seurat_clusters",
              filter.clones = NULL,
              filter.identity = NULL,
              cloneCall = "aa")



#Examining Cluster 3 only
clonalNetwork(scRep_example, 
              reduction = "umap", 
              group.by = "seurat_clusters",
              filter.identity = 8,
              cloneCall = "aa")



shared.clones <- clonalNetwork(scRep_example, 
                               reduction = "umap", 
                               group.by = "seurat_clusters",
                               cloneCall = "aa", 
                               exportClones = TRUE)
head(shared.clones)


scRep_example <- highlightClones(scRep_example, 
                    cloneCall= "aa", 
                    sequence = c("CATGPNGSSNTGKLIF;CALSNNARLMF_CSATTGFYGYTF", 
                                 "CAYSESGGSNYKLTF_CSALAGGYTDTQYF",
                                 "CLVGETGRRALTF_CSARGDRGQPQHF",
                                 "CLVGETGRRALTF_CSARGDRGQPQHF;CATSDFKQVSNQPQHF",
                                 "CATGPNGSSNTGKLIF_CSATTGFYGYTF",
                                 "NA_CSARGDRGQPQHF"
                                 
                                 
                                 
                                 
                                 ))

Seurat::DimPlot(scRep_example, group.by = "highlight") + 
  ggplot2::theme(plot.title = element_blank())



#clonalOccupy
clonalOccupy(scRep_example, 
              x.axis = "seurat_clusters")



clonalOccupy(scRep_example, 
                     x.axis = "ident", 
                     proportion = TRUE, 
                     label = FALSE)

# alluvialClones


# scRep_example$Patient_origin <- substr(scRep_example$orig.ident, 8,8)
# 
# alluvialClones(scRep_example, 
#                cloneCall = "aa", 
#                y.axes = c("Patient_origin", "orig.ident", "Cell_line_Immunophenotype"), 
#                color = c("CATGPNGSSNTGKLIF;CALSNNARLMF_CSATTGFYGYTF", 
#                                  "CAYSESGGSNYKLTF_CSALAGGYTDTQYF",
#                                  "CLVGETGRRALTF_CSARGDRGQPQHF",
#                                  "CLVGETGRRALTF_CSARGDRGQPQHF;CATSDFKQVSNQPQHF",
#                                  "CATGPNGSSNTGKLIF_CSATTGFYGYTF",
#                                  "NA_CSARGDRGQPQHF")) + 
#     scale_fill_manual(values = c("grey", colorblind_vector[3]))
# 
# 
# 
# alluvialClones(scRep_example, 
#                    cloneCall = "gene", 
#                    y.axes = c("Patient_origin", "orig.ident", "Cell_line_Immunophenotype"), 
#                    color = "ident") 



#getCirclize

library(circlize)
========================================
circlize version 0.4.16
CRAN page: https://cran.r-project.org/package=circlize
Github page: https://github.com/jokergoo/circlize
Documentation: https://jokergoo.github.io/circlize_book/book/

If you use it in published research, please cite:
Gu, Z. circlize implements and enhances circular visualization
  in R. Bioinformatics 2014.

This message can be suppressed by:
  suppressPackageStartupMessages(library(circlize))
========================================
library(scales)

Attaching package: 'scales'

The following object is masked from 'package:purrr':

    discard

The following object is masked from 'package:readr':

    col_factor
circles <- getCirclize(scRep_example, 
                       group.by = "seurat_clusters")

#Just assigning the normal colors to each cluster
grid.cols <- hue_pal()(length(unique(scRep_example$seurat_clusters)))
names(grid.cols) <- unique(scRep_example$seurat_clusters)

#Graphing the chord diagram
chordDiagram(circles, self.link = 1, grid.col = grid.cols)








circles <- getCirclize(scRep_example, group.by = "cell_line", proportion = TRUE)

grid.cols <- scales::hue_pal()(length(unique(scRep_example@active.ident)))
names(grid.cols) <- levels(scRep_example@active.ident)

chordDiagram(circles, 
             self.link = 1, 
             grid.col = grid.cols, 
             directional = 1, 
             direction.type =  "arrows",
             link.arr.type = "big.arrow")

NA
NA
NA
NA
LS0tCnRpdGxlOiAiVENSIEFuYWx5c2lzIgphdXRob3I6ICJOYXNpciBNYWhtb29kIEFiYmFzaSIKZGF0ZTogIjIwMjQtMDQtMTkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiAKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCiAgICB0aGVtZTogZGFya2x5CiAgIAotLS0KCiMgSW50cm9kdWN0aW9uCgoqKnNjUmVwZXJ0b2lyZSBpcyBkZXNpZ25lZCB0byB0YWtlIGZpbHRlciBjb250aWcgb3V0cHV0cyBmcm9tIHRoZSAxMHggR2Vub21pY3MgQ2VsbCBSYW5nZXIgcGlwZWxpbmUsIHByb2Nlc3MgdGhhdCBkYXRhIHRvIGFzc2lnbiBjbG9ub3R5cGUgYmFzZWQgb24gdHdvIFRDUiBvciBJZyBjaGFpbnMgYW5kIGFuYWx5emUgdGhlIGNsb25vdHlwZSBkeW5hbWljcy4gVGhlIGxhdHRlciBjYW4gYmUgc2VwYXJhdGVkIGludG8gMSkgY2xvbm90eXBlLW9ubHkgYW5hbHlzaXMgZnVuY3Rpb25zLCBzdWNoIGFzIHVuaXF1ZSBjbG9ub3R5cGVzIG9yIGNsb25hbCBzcGFjZSBxdWFudGlmaWNhdGlvbiwgYW5kIDIpIGludGVyYWN0aW9uIHdpdGggbVJOQSBleHByZXNzaW9uIGRhdGEgdXNpbmcgU2V1cmF0IG9yIFNpbmdsZUNlbGxFeHBlcmltZW50IHBhY2thZ2VzLioqCgojIExvYWQgbGlicmFyaWVzCgpgYGB7ciBsaWJyYXJpZXMsIGluY2x1ZGU9RkFMU0V9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQpsaWJyYXJ5KFNldXJhdERhdGEpCgpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShBemltdXRoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeSh0aW55dGV4KQoKbGlicmFyeShncmlkKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkocHJlc3RvKQojVENSIEFuYWx5c2lzCmxpYnJhcnkoc2NSZXBlcnRvaXJlKQpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQoKbGlicmFyeShjaXJjbGl6ZSkKbGlicmFyeShzY2FsZXMpCmBgYAoKIyBMb2FkIFNldXJhdCBPYmplY3QKCmBgYHtyIGxvYWRfc2V1cmF0LCBpbmNsdWRlPUZBTFNFfQoKI0xvYWQgU2V1cmF0IE9iamVjdCBtZXJnZWQgZnJvbSBjZWxsIGxpbmVzIGFuZCBhIGNvbnRyb2woUEJNQykgYWZ0ZXIgZmlsdHJhdGlvbgpsb2FkKCIuLi8wLjctT0JKL1NTX0FsbF9TYW1wbGVfTWVyZ2VkX0F6aW11dGhfUHJvamVjdFRpbHNfc2luZ2xlUl9BTk5PVEFUSU9OX29uX015X1VNQVAwLjdfSFBDLlJvYmoiKQoKYGBgCgojIDEuIExvYWQgY29udGlncwoKKipzY1JlcGVydG9pcmUgZnVuY3Rpb25zIHVzaW5nIHRoZSBmaWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IG91dHB1dCBmcm9tIHRoZSAxMHggR2Vub21pY3MgQ2VsbCBSYW5nZXIuIFRoaXMgZmlsZSBpcyBsb2NhdGVkIGluIHRoZSAuL291dHMvIGRpcmVjdG9yeSBvZiB0aGUgVkRKIGFsaWdubWVudCBmb2xkZXIuIFRvIGdlbmVyYXRlIGEgbGlzdCBvZiBjb250aWdzIHRvIHVzZSBmb3Igc2NSZXBlcnRvaXJlOioqCgotICAgbG9hZCB0aGUgZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiBmb3IgZWFjaCBvZiB0aGUgc2FtcGxlcy4KCi0gICBtYWtlIGEgbGlzdCBpbiB0aGUgUiBlbnZpcm9ubWVudC4KCgpgYGB7ciBUQ1IsIGluY2x1ZGU9RkFMU0V9CgpMMSA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MMS9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MMS92ZGpfdC9maWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IikKTDIgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDIvb3V0cy9wZXJfc2FtcGxlX291dHMvTDIvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkwzX0IgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDNfQ0lURV9CLy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MM19DSVRFX0IvL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNF9CIDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjEzNS41LHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YS9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w0X0Ivb3V0cy9wZXJfc2FtcGxlX291dHMvTDRfQi8vdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkw1IDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjEzNS41LHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YS9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w1L291dHMvcGVyX3NhbXBsZV9vdXRzL0w1L3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNiA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MNl9DSVRFLy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MNl9DSVRFLy92ZGpfdC9maWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IikKTDcgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDcvb3V0cy9wZXJfc2FtcGxlX291dHMvTDcvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpClBCTUMgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvUEJNQy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9QQk1DL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQoKYGBgCgoKIyAyLiBDb21iaW5pbmcgQ29udGlncyBpbnRvIENsb25lcwpgYGB7ciBjb21iaW5lZFRDUiwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KCmNvbnRpZ19saXN0IDwtIGxpc3QoTDEsIEwyLCBMM19CLCBMNF9CLEw1LEw2LCBMNykKY29udGlnX2xpc3Rfd2l0aF9QQk1DIDwtIGxpc3QoTDEsIEwyLCBMM19CLCBMNF9CLEw1LEw2LCBMNywgUEJNQykKCmNvbWJpbmVkLlRDUiA8LSBjb21iaW5lVENSKGNvbnRpZ19saXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiLCAiTDNfQiIsICJMNF9CIiwgIkw1IiwgIkw2IiwgIkw3IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU5BID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU11bHRpID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlck11bHRpID0gRkFMU0UpCgpjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DIDwtIGNvbWJpbmVUQ1IoY29udGlnX2xpc3Rfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiwgIkwzX0IiLCAiTDRfQiIsICJMNSIsICJMNiIsICJMNyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUEJNQyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVOQSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlTXVsdGkgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlck11bHRpID0gRkFMU0UpCgojICBleHBvcnRDbG9uZXMoY29tYmluZWQuVENSLCAKIyAgICAgICAgICAgICAgIHdyaXRlLmZpbGUgPSBUUlVFLAojICAgICAgICAgICAgICAgZGlyID0gIi4uL1RDUl9BbmFseXNpcy8iLAojICAgICAgICAgICAgICBmaWxlLm5hbWUgPSAiY2xvbmVzLmNzdiIpCiMgCiMgZXhwb3J0Q2xvbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAojICAgICAgICAgICAgICB3cml0ZS5maWxlID0gVFJVRSwKIyAgICAgICAgICAgICAgZGlyID0gIi4uL1RDUl9BbmFseXNpcy8iLAojICAgICAgICAgICAgICBmaWxlLm5hbWUgPSAiY2xvbmVzX3dpdGhfUEJNQy5jc3YiKQoKaGVhZChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW1sxXV0pCgpgYGAKIyAzLiBCYXNpYyBDbG9uYWwgVmlzdWFsaXphdGlvbnMKCiMjIDMuMS4gY2xvbmFsUXVhbnQKYGBge3IgQ2xvbmFsLVZpc3VhbGl6YXRpb24sIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiNjbG9uYWxRdWFudAogY2xvbmFsUXVhbnQoY29tYmluZWQuVENSLCAKICAgICAgICAgICAgY2xvbmVDYWxsPSJzdHJpY3QiLCAKICAgICAgICAgICAgY2hhaW4gPSAiYm90aCIsIAogICAgICAgICAgICBzY2FsZSA9IFRSVUUpCgoKY2xvbmFsUXVhbnQoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgIGNsb25lQ2FsbD0ic3RyaWN0IiwgCiAgICAgICAgICAgIGNoYWluID0gImJvdGgiLCAKICAgICAgICAgICAgc2NhbGUgPSBUUlVFKQoKY2xvbmFsUXVhbnQoY29tYmluZWQuVENSLCBjbG9uZUNhbGwgPSAiZ2VuZSIsIGdyb3VwLmJ5ID0gInNhbXBsZSIsIHNjYWxlID0gVFJVRSkKCmNsb25hbFF1YW50KGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIGNsb25lQ2FsbCA9ICJnZW5lIiwgZ3JvdXAuYnkgPSAic2FtcGxlIiwgc2NhbGUgPSBUUlVFKQpgYGAKIyMgMy4yIGNsb25hbEFidW5kYW5jZQpgYGB7ciBWMiwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KI2Nsb25hbEFidW5kYW5jZQoKY2xvbmFsQWJ1bmRhbmNlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiLCAgcGFsZXR0ZSA9ICJaaXNzb3UgMSIsCiAgICAgICAgICAgICAgICBzY2FsZSA9IEZBTFNFKSsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg4LCJnZXlzZXIiKSkKCmNsb25hbEFidW5kYW5jZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwgcGFsZXR0ZSA9ICJaaXNzb3UgMSIsCiAgICAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpCmBgYAojIyAzLjMgY2xvbmFsTGVuZ3RoCmBgYHtyIFYzLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojY2xvbmFsTGVuZ3RoCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0ibnQiLCAKICAgICAgICAgICAgIGNoYWluID0gImJvdGgiKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgIGNoYWluID0gImJvdGgiKSAKI1RSQQpjbG9uYWxMZW5ndGgoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjbG9uZUNhbGw9Im50IiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgIHNjYWxlID0gVFJVRSkgCgpjbG9uYWxMZW5ndGgoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgIHNjYWxlID0gVFJVRSkgCgojVFJCCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0ibnQiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKYGBgCiMjIDMuNCBjbG9uYWxDb21wYXJlCmBgYHtyIFY0LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojIGNsb25hbENvbXBhcmUKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiksIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICAgICAgIGdyYXBoID0gImFsbHV2aWFsIikKCmNsb25hbENvbXBhcmUoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgIHRvcC5jbG9uZXMgPSAxMCwgCiAgICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBjKCJMM19CIiwgIkw0X0IiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw1IiwgIkw2IiwiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw1IiwiTDYiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw1IiwiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkw2IiwiTDciKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiwgIkwzX0IiLCAiTDRfQiIsICJMNSIsICJMNiIsICJMNyIsICJQQk1DIiksIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiAgICAgICAgICAgICAgICAgIGdyYXBoID0gImFsbHV2aWFsIikKCiMgY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKIyAgICAgICAgICAgICAgIHRvcC5jbG9uZXMgPSAxMCwKIyAgICAgICAgICAgICAgIGhpZ2hsaWdodC5jbG9uZXMgPSBjKCJDVlZTRE5UR0dGS1RJRl9DQVNTVlJSRVJBTlRHRUxGRiIsICJOQV9DQVNTVlJSRVJBTlRHRUxGRiIpLAojICAgICAgICAgICAgICAgcmVsYWJlbC5jbG9uZXMgPSBUUlVFLAojICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwxIiwgIkwyIiksIAojICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAojICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQojIAojIAojIGNsb25hbENvbXBhcmUoY29tYmluZWQuVENSX3dpdGhfUEJNQywgY2xvbmVzID0gYygiQ1ZWU0ROVEdHRktUSUZfQ0FTU1ZSUkVSQU5UR0VMRkYiLCAiTkFfQ0FTU1ZSUkVSQU5UR0VMRkYiKSwKIyAgICAgcmVsYWJlbC5jbG9uZXMgPSBUUlVFLCBzYW1wbGVzID0gYygiTDEiLCAiTDIiKSwgY2xvbmVDYWxsID0gImFhIiwgZ3JhcGggPSAiYWxsdXZpYWwiKQoKYGBgCiMjIDMuNSBjbG9uYWxTY2F0dGVyCmBgYHtyIFY1LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojY2xvbmFsU2NhdHRlcgoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkwxIiwgCiAgICAgICAgICAgICAgeS5heGlzID0gIkwyIiwKICAgICAgICAgICAgICBkb3Quc2l6ZSA9ICJ0b3RhbCIsCiAgICAgICAgICAgICAgZ3JhcGggPSAicHJvcG9ydGlvbiIpCgoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkwzX0IiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDRfQiIsCiAgICAgICAgICAgICAgZG90LnNpemUgPSAidG90YWwiLAogICAgICAgICAgICAgIGdyYXBoID0gInByb3BvcnRpb24iKQoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkw1IiwgCiAgICAgICAgICAgICAgeS5heGlzID0gIkw2IiwKICAgICAgICAgICAgICBkb3Quc2l6ZSA9ICJ0b3RhbCIsCiAgICAgICAgICAgICAgZ3JhcGggPSAicHJvcG9ydGlvbiIpCgpjbG9uYWxTY2F0dGVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDUiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDciLAogICAgICAgICAgICAgIGRvdC5zaXplID0gInRvdGFsIiwKICAgICAgICAgICAgICBncmFwaCA9ICJwcm9wb3J0aW9uIikKCmNsb25hbFNjYXR0ZXIoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0iZ2VuZSIsIAogICAgICAgICAgICAgIHguYXhpcyA9ICJMNiIsIAogICAgICAgICAgICAgIHkuYXhpcyA9ICJMNyIsCiAgICAgICAgICAgICAgZG90LnNpemUgPSAidG90YWwiLAogICAgICAgICAgICAgIGdyYXBoID0gInByb3BvcnRpb24iKQpgYGAKIyA0LiBWaXN1YWxpemluZyBDbG9uYWwgRHluYW1pY3MKCiMjIDQuMSBjbG9uYWxIb21lb3N0YXNpcwpgYGB7ciBWNiwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KIyBWaXN1YWxpemluZyBDbG9uYWwgRHluYW1pY3MKCiMgY2xvbmFsSG9tZW9zdGFzaXMKCmNsb25hbEhvbWVvc3Rhc2lzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIpCgoKY2xvbmFsSG9tZW9zdGFzaXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwKICAgICAgICAgICAgICAgICAgY2xvbmVTaXplID0gYyhSYXJlID0gMC4wMDEsIFNtYWxsID0gMC4wMSwgTWVkaXVtID0gMC4xLCBMYXJnZSA9IDAuMywgSHlwZXJleHBhbmRlZCA9MSkpCgpgYGAKIyMgNC4yIGNsb25hbFByb3BvcnRpb24KYGBge3IgU3RhdHMsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiMgY2xvbmFsUHJvcG9ydGlvbgoKY2xvbmFsUHJvcG9ydGlvbihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIpIAoKY2xvbmFsUHJvcG9ydGlvbihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICAgICAgIGNsb25hbFNwbGl0ID0gYygxLCA1LCAxMCwgMTAwLCAxMDAwLCAxMDAwMCkpIApgYGAKIyA1LiBTdW1tYXJpemluZyBSZXBlcnRvaXJlcwpgYGB7ciBERSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KIyBTdW1tYXJpemluZyBSZXBlcnRvaXJlcwoKI3BlcmNlbnRBQQoKcGVyY2VudEFBKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgIGFhLmxlbmd0aCA9IDIwKQoKIyBwb3NpdGlvbmFsRW50cm9weQojIFdlIGNhbiBhbHNvIHF1YW50aWZ5IHRoZSBsZXZlbCBvZiBlbnRyb3B5L2RpdmVyc2l0eSBhY3Jvc3MgYW1pbm8gYWNpZCByZXNpZHVlcyBhbG9uZyB0aGUgY2RyMyBzZXF1ZW5jZS4gcG9zaXRpb25hbEVudHJvcHkoKSBjb21iaW5lcyB0aGUgcXVhbnRpZmljYXRpb24gYnkgcmVzaWR1ZSBvZiBwZXJjZW50QUEoKSB3aXRoIHRoZSBkaXZlcnNpdHkgY2FsbHMgaW4gY2xvbmFsRGl2ZXJzaXR5KCkuCiMgCiMgbWV0aG9kCiMgCiMg4oCcc2hhbm5vbuKAnSAtIFNoYW5ub24gRGl2ZXJzaXR5CiMg4oCcaW52LnNpbXBzb27igJ0gLSBJbnZlcnNlIFNpbXBzb24gRGl2ZXJzaXR5CiMg4oCcbm9ybS5lbnRyb3B54oCdIC0gTm9ybWFsaXplZCBFbnRyb3B5Cgpwb3NpdGlvbmFsRW50cm9weShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwKQoKCiMgcG9zaXRpb25hbFByb3BlcnR5CiMgTGlrZSBwb3NpdGlvbmFsRW50cm9weSgpLCB3ZSBjYW4gYWxzbyBleGFtaW5lIGEgc2VyaWVzIG9mIGFtaW5vIGFjaWQgcHJvcGVydGllcyBhbG9uZyB0aGUgY2RyMyBzZXF1ZW5jZXMgdXNpbmcgcG9zaXRpb25hbFByb3BlcnR5KCkuIEltcG9ydGFudCBkaWZmZXJlbmNlcyBmcm9tIHRoZSBhYm92ZSBmdW5jdGlvbiBmb3IgcG9zaXRpb25hbFByb3BlcnR5KCkgaXMgZHJvcHBpbmcgTkEgdmFsdWVzIGFzIHRoZXkgd291bGQgdm9pZCB0aGUgbWVhbiBjYWxjdWxhdGlvbi4gcG9zaXRpb25hbFByb3BlcnR5KCkgYWxzbyBkaXNwbGF5IGEgcmliYm9uIHdpdGggdGhlIDk1JSBjb25maWRlbmNlIGludGVydmFsIHN1cnJvdW5kaW5nIHRoZSBtZWFuIHZhbHVlIGZvciB0aGUgc2VsZWN0ZWQgcHJvcGVydGllcy4KIyAKIyBtZXRob2QKIyAKIyDigJxBdGNobGV54oCdIC0gQXRjaGxleSBGYWN0b3JzCiMg4oCcS2lkZXJh4oCdIC0gS2lkZXJhIEZhY3RvcnMKIyDigJxzdFNjYWxlc+KAnSAtIHN0U2NhbGVzIFZlY3RvcnMKIyDigJx0U2NhbGVz4oCdIC0gdFNjYWxlcyBWZWN0b3JzCiMg4oCcVkhTReKAnSAtIFZlY3RvcnMgb2YgSHlkcm9waG9iaWMsIFN0ZXJpYywgYW5kIEVsZWN0cm9uaWMgcHJvcGVydGllcwoKIyBwb3NpdGlvbmFsUHJvcGVydHkoY29tYmluZWQuVENSX3dpdGhfUEJNQ1tjKDEsMildLCAKIyAgICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKIyAgICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiMgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkF0Y2hsZXkiKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQojIAojIHBvc2l0aW9uYWxQcm9wZXJ0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW2MoMyw0KV0sIAojICAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAojICAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwLCAKIyAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQXRjaGxleSIpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg1LCAiaW5mZXJubyIpW2MoMiw0KV0pCiMgCiMgcG9zaXRpb25hbFByb3BlcnR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUNbYyg1LDYpXSwgCiMgICAgICAgICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiMgICAgICAgICAgICAgICAgICAgYWEubGVuZ3RoID0gMjAsIAojICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJBdGNobGV5IikgKyAKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBoY2wuY29sb3JzKDUsICJpbmZlcm5vIilbYygyLDQpXSkKIyAKIyBwb3NpdGlvbmFsUHJvcGVydHkoY29tYmluZWQuVENSX3dpdGhfUEJNQ1tjKDUsNyldLCAKIyAgICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKIyAgICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiMgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkF0Y2hsZXkiKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQojIAojIAojIHBvc2l0aW9uYWxQcm9wZXJ0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW2MoNiw3KV0sIAojICAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAojICAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwLCAKIyAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQXRjaGxleSIpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg1LCAiaW5mZXJubyIpW2MoMiw0KV0pCiMgCiMgcG9zaXRpb25hbFByb3BlcnR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUNbYyg1LDYsNyldLCAKIyAgICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKIyAgICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiMgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkF0Y2hsZXkiKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQoKCiMgdml6R2VuZXMKIyBBIHZpc3VhbGl6YXRpb24gb2YgdGhlIHJlbGF0aXZlIHVzYWdlIG9mIGdlbmVzIG9mIHRoZSBUQ1Igb3IgQkNSLCB1c2luZyB2aXpHZW5lcygpLiBUaGVyZSBpcyBzb21lIGZ1bmN0aW9uYWwgY3Jvc3NvdmVyIGJldHdlZW4gdml6R2VuZXMoKSBhbmQgdHdvIGZ1bmN0aW9ucyBiZWxvdyBjYWxsZWQgcGVyY2VudEdlbmVzKCkgYW5kIHBlcmNlbnRWSigpLiBCdXQgdml6R2VuZXMoKSBpcyBtb3JlIGFkYXB0YWJsZSB0byBhbGxvdyBmb3IgY29tcGFyaXNvbnMgYWNyb3NzIGNoYWlucywgc2NhbGluZywgZXRjLgoKdml6R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgIHguYXhpcyA9ICJUUkJWIiwKICAgICAgICAgeS5heGlzID0gTlVMTCwKICAgICAgICAgcGxvdCA9ICJiYXJwbG90IiwgIAogICAgICAgICBzY2FsZSA9IFRSVUUpCgp2aXpHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICB4LmF4aXMgPSAiVFJBViIsCiAgICAgICAgeS5heGlzID0gTlVMTCwKICAgICAgICBwbG90ID0gImJhcnBsb3QiLCAgCiAgICAgICAgc2NhbGUgPSBUUlVFKQoKdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyLDMsNCw1LDYsNyldLCAKICAgICAgICAgeC5heGlzID0gIlRSQlYiLAogICAgICAgICB5LmF4aXMgPSAiVFJCSiIsCiAgICAgICAgIHBsb3QgPSAiaGVhdG1hcCIsICAKICAgICAgICAgc2NhbGUgPSBUUlVFKQoKdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyLDMsNCw1LDYsNyldLCAKICAgICAgICAgeC5heGlzID0gIlRSQVYiLAogICAgICAgICB5LmF4aXMgPSAiVFJBSiIsCiAgICAgICAgIHBsb3QgPSAiaGVhdG1hcCIsICAKICAgICAgICAgc2NhbGUgPSBUUlVFKQoKIyBGb3IgdGhlIFAxNyBwYXRpZW50IHNhbXBsZXMsIHdoYXQgaWYgd2UgYXJlIGludGVyZXN0ZWQgaW4gY2hhaW4gcGFpcmluZ3MsIHdlIGNhbiBsb29rIGF0IFRSQlYgYW5kIFRSQVYgYXQgdGhlIHNhbWUgdGltZSB1c2luZyB0aGVtIGFzIGlucHV0cyB0byB4LmF4aXMgYW5kIHkuYXhpcy4Kdml6R2VuZXMoY29tYmluZWQuVENSW2MoMSwyKV0sIAogICAgICAgICB4LmF4aXMgPSAiVFJCViIsCiAgICAgICAgIHkuYXhpcyA9ICJUUkFWIiwKICAgICAgICAgcGxvdCA9ICJoZWF0bWFwIiwgCiAgICAgICAgIHNjYWxlID0gRkFMU0UpCiMgcGVyY2VudEdlbmVzCiMgUXVhbnRpZnkgdGhlIHByb3BvcnRpb24gb2YgViBvciBKIGdlbmUgdXNhZ2Ugd2l0aCBwZXJjZW50R2VuZXMoKS4gTGlrZSBwZXJjZW50QUEoKSwgd2Ugc2VsZWN0IHRoZSBjaGFpbiBvZiBpbnRlcmVzdCBhbmQgdGhlbiBpbmRpY2F0ZSB0aGUgZ2VuZSBvZiBpbnRlcmVzdCB3aXRoIHRoZSBnZW5lIHBhcmFtZXRlci4gVHdvIG1ham9yIGxpbWl0YXRpb25zIG9mIHBlcmNlbnRHZW5lcygpIGFyZSwgMSkgdGhlIGZ1bmN0aW9uIHF1YW50aWZpZXMgb25seSBWIG9yIEogZ2VuZXMsIGFuZCAyKSB0aGUgcXVhbnRpZmljYXRpb24gb2YgdGhlIGdlbmVzIGFyZSBsaW1pdGVkIHRvIGFsbCB0aGUgViBvciBKIGdlbmVzIHNlZW4gYWNyb3NzIHRoZSBzYW1wbGVzLCBub3QgYWxsIHBvc3NpYmxlIFYgb3IgSiBnZW5lcy4KCnBlcmNlbnRHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICAgZ2VuZSA9ICJWZ2VuZSIpCgpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgIGdlbmUgPSAiVmdlbmUiKQoKcGVyY2VudEdlbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICBnZW5lID0gIkpnZW5lIikKCnBlcmNlbnRHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgZ2VuZSA9ICJKZ2VuZSIpCgoKIyBwZXJjZW50VkoKIyBRdWFudGlmeSB0aGUgcHJvcG9ydGlvbiBvZiBWIGFuZCBKIGdlbmUgdXNhZ2Ugd2l0aCBwZXJjZW50VkooKS4gTGlrZSBwZXJjZW50R2VuZXMoKSwgdGhpcyBmdW5jdGlvbiB3aWxsIHF1YW50aWZ5IHRoZSBwZXJjZW50YWdlIG9mIFYgYW5kIEogcGFpcmVkIHRvZ2V0aGVyIGFjcm9zcyBpbmRpdmlkdWFsIHJlcGVydG9pcmVzLiBUaGUgb3V0cHV0IGNhbiBiZSB2aXN1YWxpemVkIHVzaW5nIGEgaGVhdG1hcCBvciBhcyBpbnB1dCBmb3IgZnVydGhlciBkaW1lbnNpb25hbCByZWR1Y3Rpb24uCgpwZXJjZW50VkooY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICBjaGFpbiA9ICJUUkIiKQoKcGVyY2VudFZKKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgY2hhaW4gPSAiVFJBIikKCiMgcGVyY2VudEttZXIKIyBBbm90aGVyIHF1YW50aWZpY2F0aW9uIG9mIHRoZSBjb21wb3NpdGlvbiBvZiB0aGUgQ0RSMyBzZXF1ZW5jZSBpcyB0byBkZWZpbmUgbW90aWZzIGJ5IHNsaWRpbmcgYWNyb3NzIHRoZSBhbWlubyBhY2lkIG9yIG51Y2xlb3RpZGUgc2VxdWVuY2VzIGF0IHNldCBpbnRlcnZhbHMgcmVzdWx0aW5nIGluIHN1YnN0cmluZ3Mgb3Iga21lcnMuCiMgCiMgbW90aWYubGVuZ3RoCiMgCiMgTnVtZXJpY2FsIHZhbHVlIGZvciB0aGUgbGVuZ3RoIG9mIHRoZSBrbWVyLgojIHRvcC5tb3RpZnMKIyAKIyBEaXNwbGF5IHRoZSBtb3N0IHZhcmlhYmxlIGdlbmVzIGRldGVybWluZWQgYnkgbWVhbiBhYnNvbHV0ZSBkZXZpYXRpb24gKE1BRCkuCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKCnBlcmNlbnRLbWVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICBjbG9uZUNhbGwgPSAibnQiLAogICAgICAgICAgICBjaGFpbiA9ICJUUkEiLCAKICAgICAgICAgICAgbW90aWYubGVuZ3RoID0gMywgCiAgICAgICAgICAgIHRvcC5tb3RpZnMgPSAyNSkKYGBgCiMgNi4gQ29tcGFyaW5nIENsb25hbCBEaXZlcnNpdHkgYW5kIE92ZXJsYXAKYGBge3IgY2xvbmFsRGl2ZXJzaXR5LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojIGNsb25hbERpdmVyc2l0eQoKCmNsb25hbERpdmVyc2l0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIikKCiNjbG9uYWxTaXplRGlzdHJpYnV0aW9uCgoKY2xvbmFsU2l6ZURpc3RyaWJ1dGlvbihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLCAKICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9ICJ3YXJkLkQyIikKCgoKI2Nsb25hbE92ZXJsYXAKCmNsb25hbE92ZXJsYXAoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0gInN0cmljdCIsIAogICAgICAgICAgICAgIG1ldGhvZCA9ICJtb3Jpc2l0YSIpCgoKY2xvbmFsT3ZlcmxhcChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAic3RyaWN0IiwgCiAgICAgICAgICAgICAgbWV0aG9kID0gInJhdyIpCmBgYAojIDcuIENvbWJpbmluZyBDbG9uZXMgYW5kIFNpbmdsZS1DZWxsIE9iamVjdHMKYGBge3IgU0MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CgojIENvbWJpbmluZyBDbG9uZXMgYW5kIFNpbmdsZS1DZWxsIE9iamVjdHMKCiNHZXR0aW5nIGEgc2FtcGxlIG9mIGEgU2V1cmF0IG9iamVjdApzY1JlcF9leGFtcGxlIDwtIGdldChkYXRhKCJBbGxfc2FtcGxlc19NZXJnZWQiKSkKCgojRGVmaW5lIGNvbG9yIHBhbGV0dGUgCmNvbG9yYmxpbmRfdmVjdG9yIDwtIGhjbC5jb2xvcnMobj03LCBwYWxldHRlID0gImluZmVybm8iLCBmaXh1cCA9IFRSVUUpCgoKc2NSZXBfZXhhbXBsZSA8LSBjb21iaW5lRXhwcmVzc2lvbihjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iZ2VuZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNhbXBsZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BvcnRpb24gPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVTaXplPWMoU2luZ2xlPTEsIFNtYWxsPTUsIE1lZGl1bT0yMCwgTGFyZ2U9MTAwLCBIeXBlcmV4cGFuZGVkPTUwMCkpCgpEaW1QbG90KHNjUmVwX2V4YW1wbGUsIGdyb3VwLmJ5ID0gImNsb25lU2l6ZSIpCgpEaW1QbG90KHNjUmVwX2V4YW1wbGUsIGdyb3VwLmJ5ID0gImNsb25lU2l6ZSIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9cmV2KGNvbG9yYmxpbmRfdmVjdG9yW2MoMSwzLDQsNSw2KV0pKQoKCmBgYAojIDguIFZpc3VhbGl6YXRpb25zIGZvciBTaW5nbGUtQ2VsbCBPYmplY3RzCmBgYHtyIFZfc2MsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CgojIFZpc3VhbGl6YXRpb25zIGZvciBTaW5nbGUtQ2VsbCBPYmplY3RzCiMgY2xvbmFsT3ZlcmxheQoKI0FkZGluZyBwYXRpZW50IGluZm9ybWF0aW9uCnNjUmVwX2V4YW1wbGUkUGF0aWVudF9vcmlnaW4gPC0gc3Vic3RyKHNjUmVwX2V4YW1wbGUkb3JpZy5pZGVudCwgMSwzKQoKY2xvbmFsT3ZlcmxheShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgIGZyZXEuY3V0cG9pbnQgPSAxLCAKICAgICAgICAgICAgICBiaW5zID0gMTAsIAogICAgICAgICAgICAgIGZhY2V0LmJ5ID0gIlBhdGllbnRfb3JpZ2luIikgKyAKICAgICAgICAgICAgICBndWlkZXMoY29sb3IgPSAibm9uZSIpCgojY2xvbmFsTmV0d29yawojZ2dyYXBoIG5lZWRzIHRvIGJlIGxvYWRlZCBkdWUgdG8gaXNzdWVzIHdpdGggZ2dwbG90CmxpYnJhcnkoZ2dyYXBoKQoKY2xvbmFsTmV0d29yayhzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICAgICAgICAgICAgZmlsdGVyLmNsb25lcyA9IE5VTEwsCiAgICAgICAgICAgICAgZmlsdGVyLmlkZW50aXR5ID0gTlVMTCwKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiKQoKCiNFeGFtaW5pbmcgQ2x1c3RlciAzIG9ubHkKY2xvbmFsTmV0d29yayhzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICAgICAgICAgICAgZmlsdGVyLmlkZW50aXR5ID0gOCwKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiKQoKCnNoYXJlZC5jbG9uZXMgPC0gY2xvbmFsTmV0d29yayhzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImFhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBvcnRDbG9uZXMgPSBUUlVFKQpoZWFkKHNoYXJlZC5jbG9uZXMpCgoKc2NSZXBfZXhhbXBsZSA8LSBoaWdobGlnaHRDbG9uZXMoc2NSZXBfZXhhbXBsZSwgCiAgICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSAiYWEiLCAKICAgICAgICAgICAgICAgICAgICBzZXF1ZW5jZSA9IGMoIkNBVEdQTkdTU05UR0tMSUY7Q0FMU05OQVJMTUZfQ1NBVFRHRllHWVRGIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDQVlTRVNHR1NOWUtMVEZfQ1NBTEFHR1lURFRRWUYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0xWR0VUR1JSQUxURl9DU0FSR0RSR1FQUUhGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNMVkdFVEdSUkFMVEZfQ1NBUkdEUkdRUFFIRjtDQVRTREZLUVZTTlFQUUhGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNBVEdQTkdTU05UR0tMSUZfQ1NBVFRHRllHWVRGIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5BX0NTQVJHRFJHUVBRSEYiKSkKClNldXJhdDo6RGltUGxvdChzY1JlcF9leGFtcGxlLCBncm91cC5ieSA9ICJoaWdobGlnaHQiKSArIAogIGdncGxvdDI6OnRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgojY2xvbmFsT2NjdXB5CmNsb25hbE9jY3VweShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAic2V1cmF0X2NsdXN0ZXJzIikKCmNsb25hbE9jY3VweShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICAgICAgICAgeC5heGlzID0gImlkZW50IiwgCiAgICAgICAgICAgICAgICAgICAgIHByb3BvcnRpb24gPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBGQUxTRSkKIyBhbGx1dmlhbENsb25lcwoKIyBzY1JlcF9leGFtcGxlJFBhdGllbnRfb3JpZ2luIDwtIHN1YnN0cihzY1JlcF9leGFtcGxlJG9yaWcuaWRlbnQsIDgsOCkKIyAKIyBhbGx1dmlhbENsb25lcyhzY1JlcF9leGFtcGxlLCAKIyAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLCAKIyAgICAgICAgICAgICAgICB5LmF4ZXMgPSBjKCJQYXRpZW50X29yaWdpbiIsICJvcmlnLmlkZW50IiwgIkNlbGxfbGluZV9JbW11bm9waGVub3R5cGUiKSwgCiMgICAgICAgICAgICAgICAgY29sb3IgPSBjKCJDQVRHUE5HU1NOVEdLTElGO0NBTFNOTkFSTE1GX0NTQVRUR0ZZR1lURiIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDQVlTRVNHR1NOWUtMVEZfQ1NBTEFHR1lURFRRWUYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDTFZHRVRHUlJBTFRGX0NTQVJHRFJHUVBRSEYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDTFZHRVRHUlJBTFRGX0NTQVJHRFJHUVBRSEY7Q0FUU0RGS1FWU05RUFFIRiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNBVEdQTkdTU05UR0tMSUZfQ1NBVFRHRllHWVRGIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkFfQ1NBUkdEUkdRUFFIRiIpKSArIAojICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJncmV5IiwgY29sb3JibGluZF92ZWN0b3JbM10pKQojIAojIAojIAojIGFsbHV2aWFsQ2xvbmVzKHNjUmVwX2V4YW1wbGUsIAojICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIsIAojICAgICAgICAgICAgICAgICAgICB5LmF4ZXMgPSBjKCJQYXRpZW50X29yaWdpbiIsICJvcmlnLmlkZW50IiwgIkNlbGxfbGluZV9JbW11bm9waGVub3R5cGUiKSwgCiMgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImlkZW50IikgCgoKCmxpYnJhcnkoY2lyY2xpemUpCmxpYnJhcnkoc2NhbGVzKQoKY2lyY2xlcyA8LSBnZXRDaXJjbGl6ZShzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICAgICAgICAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiKQoKI0p1c3QgYXNzaWduaW5nIHRoZSBub3JtYWwgY29sb3JzIHRvIGVhY2ggY2x1c3RlcgpncmlkLmNvbHMgPC0gaHVlX3BhbCgpKGxlbmd0aCh1bmlxdWUoc2NSZXBfZXhhbXBsZSRzZXVyYXRfY2x1c3RlcnMpKSkKbmFtZXMoZ3JpZC5jb2xzKSA8LSB1bmlxdWUoc2NSZXBfZXhhbXBsZSRzZXVyYXRfY2x1c3RlcnMpCgojR3JhcGhpbmcgdGhlIGNob3JkIGRpYWdyYW0KY2hvcmREaWFncmFtKGNpcmNsZXMsIHNlbGYubGluayA9IDEsIGdyaWQuY29sID0gZ3JpZC5jb2xzKQoKCmNpcmNsZXMgPC0gZ2V0Q2lyY2xpemUoc2NSZXBfZXhhbXBsZSwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgcHJvcG9ydGlvbiA9IFRSVUUpCgpncmlkLmNvbHMgPC0gc2NhbGVzOjpodWVfcGFsKCkobGVuZ3RoKHVuaXF1ZShzY1JlcF9leGFtcGxlQGFjdGl2ZS5pZGVudCkpKQpuYW1lcyhncmlkLmNvbHMpIDwtIGxldmVscyhzY1JlcF9leGFtcGxlQGFjdGl2ZS5pZGVudCkKCmNob3JkRGlhZ3JhbShjaXJjbGVzLCAKICAgICAgICAgICAgIHNlbGYubGluayA9IDEsIAogICAgICAgICAgICAgZ3JpZC5jb2wgPSBncmlkLmNvbHMsIAogICAgICAgICAgICAgZGlyZWN0aW9uYWwgPSAxLCAKICAgICAgICAgICAgIGRpcmVjdGlvbi50eXBlID0gICJhcnJvd3MiLAogICAgICAgICAgICAgbGluay5hcnIudHlwZSA9ICJiaWcuYXJyb3ciKQpgYGA=