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)

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)) 

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)

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") 



library(circlize)
library(scales)

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")

LS0tCnRpdGxlOiAiVENSIEFuYWx5c2lzIgphdXRob3I6ICJOYXNpciBNYWhtb29kIEFiYmFzaSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyBJbnRyb2R1Y3Rpb24KCioqc2NSZXBlcnRvaXJlIGlzIGRlc2lnbmVkIHRvIHRha2UgZmlsdGVyIGNvbnRpZyBvdXRwdXRzIGZyb20gdGhlIDEweCBHZW5vbWljcyBDZWxsIFJhbmdlciBwaXBlbGluZSwgcHJvY2VzcyB0aGF0IGRhdGEgdG8gYXNzaWduIGNsb25vdHlwZSBiYXNlZCBvbiB0d28gVENSIG9yIElnIGNoYWlucyBhbmQgYW5hbHl6ZSB0aGUgY2xvbm90eXBlIGR5bmFtaWNzLiBUaGUgbGF0dGVyIGNhbiBiZSBzZXBhcmF0ZWQgaW50byAxKSBjbG9ub3R5cGUtb25seSBhbmFseXNpcyBmdW5jdGlvbnMsIHN1Y2ggYXMgdW5pcXVlIGNsb25vdHlwZXMgb3IgY2xvbmFsIHNwYWNlIHF1YW50aWZpY2F0aW9uLCBhbmQgMikgaW50ZXJhY3Rpb24gd2l0aCBtUk5BIGV4cHJlc3Npb24gZGF0YSB1c2luZyBTZXVyYXQgb3IgU2luZ2xlQ2VsbEV4cGVyaW1lbnQgcGFja2FnZXMuKioKCiMgTG9hZCBsaWJyYXJpZXMKCmBgYHtyIGxpYnJhcmllcywgaW5jbHVkZT1GQUxTRX0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KEF6aW11dGgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocm1hcmtkb3duKQpsaWJyYXJ5KHRpbnl0ZXgpCgpsaWJyYXJ5KGdyaWQpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShwcmVzdG8pCiNUQ1IgQW5hbHlzaXMKbGlicmFyeShzY1JlcGVydG9pcmUpCmxpYnJhcnkoU2luZ2xlQ2VsbEV4cGVyaW1lbnQpCgpsaWJyYXJ5KGNpcmNsaXplKQpsaWJyYXJ5KHNjYWxlcykKYGBgCgojIExvYWQgU2V1cmF0IE9iamVjdAoKYGBge3IgbG9hZF9zZXVyYXQsIGluY2x1ZGU9RkFMU0V9CgojTG9hZCBTZXVyYXQgT2JqZWN0IG1lcmdlZCBmcm9tIGNlbGwgbGluZXMgYW5kIGEgY29udHJvbChQQk1DKSBhZnRlciBmaWx0cmF0aW9uCmxvYWQoIi9ob21lL2Jpb2luZm8vQ2x1c3Rlcl90b19Db21wdXRlcl9UcmFuc2Zlcl9maWxlc19mb2xkZXIvQWxsX05vcm1hbC1QQk1DX0Fibm9ybWFsLWNlbGxMaW5lc19UX2NlbGxzX01lcmdlZF9Bbm5vdGF0ZWRfVU1BUF9vbl9DbHVzdGVyc190b19VU0UuUm9iaiIpCgpgYGAKCiMgMS4gTG9hZCBjb250aWdzCgoqKnNjUmVwZXJ0b2lyZSBmdW5jdGlvbnMgdXNpbmcgdGhlIGZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3Ygb3V0cHV0IGZyb20gdGhlIDEweCBHZW5vbWljcyBDZWxsIFJhbmdlci4gVGhpcyBmaWxlIGlzIGxvY2F0ZWQgaW4gdGhlIC4vb3V0cy8gZGlyZWN0b3J5IG9mIHRoZSBWREogYWxpZ25tZW50IGZvbGRlci4gVG8gZ2VuZXJhdGUgYSBsaXN0IG9mIGNvbnRpZ3MgdG8gdXNlIGZvciBzY1JlcGVydG9pcmU6KioKCi0gICBsb2FkIHRoZSBmaWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IGZvciBlYWNoIG9mIHRoZSBzYW1wbGVzLgoKLSAgIG1ha2UgYSBsaXN0IGluIHRoZSBSIGVudmlyb25tZW50LgoKCmBgYHtyIFRDUiwgaW5jbHVkZT1GQUxTRX0KCkwxIDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjEzNS41LHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YS9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0wxL291dHMvcGVyX3NhbXBsZV9vdXRzL0wxL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMMiA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MMi9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MMi92ZGpfdC9maWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IikKTDNfQiA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MM19DSVRFX0IvL291dHMvcGVyX3NhbXBsZV9vdXRzL0wzX0NJVEVfQi8vdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkw0X0IgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDRfQi9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MNF9CLy92ZGpfdC9maWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IikKTDUgPC0gcmVhZC5jc3YoIi9ydW4vdXNlci8xMDAwL2d2ZnMvc21iLXNoYXJlOnNlcnZlcj0xMC4xNDQuMTM1LjUsc2hhcmU9Y29tbXVuL05hc2lyL0FsbF9EYXRhL0F1ZHJleV9Hcm9zL0NlbGxSYW5nZXIvTDUvb3V0cy9wZXJfc2FtcGxlX291dHMvTDUvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCkw2IDwtIHJlYWQuY3N2KCIvcnVuL3VzZXIvMTAwMC9ndmZzL3NtYi1zaGFyZTpzZXJ2ZXI9MTAuMTQ0LjEzNS41LHNoYXJlPWNvbW11bi9OYXNpci9BbGxfRGF0YS9BdWRyZXlfR3Jvcy9DZWxsUmFuZ2VyL0w2X0NJVEUvL291dHMvcGVyX3NhbXBsZV9vdXRzL0w2X0NJVEUvL3Zkal90L2ZpbHRlcmVkX2NvbnRpZ19hbm5vdGF0aW9ucy5jc3YiKQpMNyA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9MNy9vdXRzL3Blcl9zYW1wbGVfb3V0cy9MNy92ZGpfdC9maWx0ZXJlZF9jb250aWdfYW5ub3RhdGlvbnMuY3N2IikKUEJNQyA8LSByZWFkLmNzdigiL3J1bi91c2VyLzEwMDAvZ3Zmcy9zbWItc2hhcmU6c2VydmVyPTEwLjE0NC4xMzUuNSxzaGFyZT1jb21tdW4vTmFzaXIvQWxsX0RhdGEvQXVkcmV5X0dyb3MvQ2VsbFJhbmdlci9QQk1DL291dHMvcGVyX3NhbXBsZV9vdXRzL1BCTUMvdmRqX3QvZmlsdGVyZWRfY29udGlnX2Fubm90YXRpb25zLmNzdiIpCgpgYGAKCgojIDIuIENvbWJpbmluZyBDb250aWdzIGludG8gQ2xvbmVzCmBgYHtyIGNvbWJpbmVkVENSLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQoKY29udGlnX2xpc3QgPC0gbGlzdChMMSwgTDIsIEwzX0IsIEw0X0IsTDUsTDYsIEw3KQpjb250aWdfbGlzdF93aXRoX1BCTUMgPC0gbGlzdChMMSwgTDIsIEwzX0IsIEw0X0IsTDUsTDYsIEw3LCBQQk1DKQoKY29tYmluZWQuVENSIDwtIGNvbWJpbmVUQ1IoY29udGlnX2xpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZXMgPSBjKCJMMSIsICJMMiIsICJMM19CIiwgIkw0X0IiLCAiTDUiLCAiTDYiLCAiTDciKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlTkEgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlTXVsdGkgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyTXVsdGkgPSBGQUxTRSkKCmNvbWJpbmVkLlRDUl93aXRoX1BCTUMgPC0gY29tYmluZVRDUihjb250aWdfbGlzdF93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiLCAiTDNfQiIsICJMNF9CIiwgIkw1IiwgIkw2IiwgIkw3IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQQk1DIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU5BID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVNdWx0aSA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyTXVsdGkgPSBGQUxTRSkKCiMgIGV4cG9ydENsb25lcyhjb21iaW5lZC5UQ1IsIAojICAgICAgICAgICAgICAgd3JpdGUuZmlsZSA9IFRSVUUsCiMgICAgICAgICAgICAgICBkaXIgPSAiLi4vVENSX0FuYWx5c2lzLyIsCiMgICAgICAgICAgICAgIGZpbGUubmFtZSA9ICJjbG9uZXMuY3N2IikKIyAKIyBleHBvcnRDbG9uZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiMgICAgICAgICAgICAgIHdyaXRlLmZpbGUgPSBUUlVFLAojICAgICAgICAgICAgICBkaXIgPSAiLi4vVENSX0FuYWx5c2lzLyIsCiMgICAgICAgICAgICAgIGZpbGUubmFtZSA9ICJjbG9uZXNfd2l0aF9QQk1DLmNzdiIpCgpoZWFkKGNvbWJpbmVkLlRDUl93aXRoX1BCTUNbWzFdXSkKCmBgYAojIDMuIEJhc2ljIENsb25hbCBWaXN1YWxpemF0aW9ucwoKIyMgMy4xLiBjbG9uYWxRdWFudApgYGB7ciBDbG9uYWwtVmlzdWFsaXphdGlvbiwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KI2Nsb25hbFF1YW50CiBjbG9uYWxRdWFudChjb21iaW5lZC5UQ1IsIAogICAgICAgICAgICBjbG9uZUNhbGw9InN0cmljdCIsIAogICAgICAgICAgICBjaGFpbiA9ICJib3RoIiwgCiAgICAgICAgICAgIHNjYWxlID0gVFJVRSkKCgpjbG9uYWxRdWFudChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgY2xvbmVDYWxsPSJzdHJpY3QiLCAKICAgICAgICAgICAgY2hhaW4gPSAiYm90aCIsIAogICAgICAgICAgICBzY2FsZSA9IFRSVUUpCgpjbG9uYWxRdWFudChjb21iaW5lZC5UQ1IsIGNsb25lQ2FsbCA9ICJnZW5lIiwgZ3JvdXAuYnkgPSAic2FtcGxlIiwgc2NhbGUgPSBUUlVFKQoKY2xvbmFsUXVhbnQoY29tYmluZWQuVENSX3dpdGhfUEJNQywgY2xvbmVDYWxsID0gImdlbmUiLCBncm91cC5ieSA9ICJzYW1wbGUiLCBzY2FsZSA9IFRSVUUpCmBgYAojIyAzLjIgY2xvbmFsQWJ1bmRhbmNlCmBgYHtyIFYyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojY2xvbmFsQWJ1bmRhbmNlCgpjbG9uYWxBYnVuZGFuY2UoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiZ2VuZSIsICBwYWxldHRlID0gIlppc3NvdSAxIiwKICAgICAgICAgICAgICAgIHNjYWxlID0gRkFMU0UpKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBoY2wuY29sb3JzKDgsImdleXNlciIpKQoKY2xvbmFsQWJ1bmRhbmNlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiLCBwYWxldHRlID0gIlppc3NvdSAxIiwKICAgICAgICAgICAgICAgIHNjYWxlID0gVFJVRSkKYGBgCiMjIDMuMyBjbG9uYWxMZW5ndGgKYGBge3IgVjMsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiNjbG9uYWxMZW5ndGgKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJudCIsIAogICAgICAgICAgICAgY2hhaW4gPSAiYm90aCIpIAoKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgY2hhaW4gPSAiYm90aCIpIAojVFJBCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0ibnQiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKCmNsb25hbExlbmd0aChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgc2NhbGUgPSBUUlVFKSAKCiNUUkIKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJudCIsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpIAoKY2xvbmFsTGVuZ3RoKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICBzY2FsZSA9IFRSVUUpIApgYGAKIyMgMy40IGNsb25hbENvbXBhcmUKYGBge3IgVjQsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiMgY2xvbmFsQ29tcGFyZQpjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLCAKICAgICAgICAgICAgICAgICAgc2FtcGxlcyA9IGMoIkwzX0IiLCAiTDRfQiIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgpjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDUiLCAiTDYiLCJMNyIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgpjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDUiLCJMNiIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgpjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDUiLCJMNyIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgpjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDYiLCJMNyIpLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJhYSIsIAogICAgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCgpjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICB0b3AuY2xvbmVzID0gMTAsIAogICAgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiLCAiTDNfQiIsICJMNF9CIiwgIkw1IiwgIkw2IiwgIkw3IiwgIlBCTUMiKSwgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbD0iYWEiLCAKICAgICAgICAgICAgICAgICAgZ3JhcGggPSAiYWxsdXZpYWwiKQoKIyBjbG9uYWxDb21wYXJlKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAojICAgICAgICAgICAgICAgdG9wLmNsb25lcyA9IDEwLAojICAgICAgICAgICAgICAgaGlnaGxpZ2h0LmNsb25lcyA9IGMoIkNWVlNETlRHR0ZLVElGX0NBU1NWUlJFUkFOVEdFTEZGIiwgIk5BX0NBU1NWUlJFUkFOVEdFTEZGIiksCiMgICAgICAgICAgICAgICByZWxhYmVsLmNsb25lcyA9IFRSVUUsCiMgICAgICAgICAgICAgICBzYW1wbGVzID0gYygiTDEiLCAiTDIiKSwgCiMgICAgICAgICAgICAgICBjbG9uZUNhbGw9ImFhIiwgCiMgICAgICAgICAgICAgICBncmFwaCA9ICJhbGx1dmlhbCIpCiMgCiMgCiMgY2xvbmFsQ29tcGFyZShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCBjbG9uZXMgPSBjKCJDVlZTRE5UR0dGS1RJRl9DQVNTVlJSRVJBTlRHRUxGRiIsICJOQV9DQVNTVlJSRVJBTlRHRUxGRiIpLAojICAgICByZWxhYmVsLmNsb25lcyA9IFRSVUUsIHNhbXBsZXMgPSBjKCJMMSIsICJMMiIpLCBjbG9uZUNhbGwgPSAiYWEiLCBncmFwaCA9ICJhbGx1dmlhbCIpCgpgYGAKIyMgMy41IGNsb25hbFNjYXR0ZXIKYGBge3IgVjUsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiNjbG9uYWxTY2F0dGVyCgpjbG9uYWxTY2F0dGVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDEiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDIiLAogICAgICAgICAgICAgIGRvdC5zaXplID0gInRvdGFsIiwKICAgICAgICAgICAgICBncmFwaCA9ICJwcm9wb3J0aW9uIikKCgpjbG9uYWxTY2F0dGVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDNfQiIsIAogICAgICAgICAgICAgIHkuYXhpcyA9ICJMNF9CIiwKICAgICAgICAgICAgICBkb3Quc2l6ZSA9ICJ0b3RhbCIsCiAgICAgICAgICAgICAgZ3JhcGggPSAicHJvcG9ydGlvbiIpCgpjbG9uYWxTY2F0dGVyKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ImdlbmUiLCAKICAgICAgICAgICAgICB4LmF4aXMgPSAiTDUiLCAKICAgICAgICAgICAgICB5LmF4aXMgPSAiTDYiLAogICAgICAgICAgICAgIGRvdC5zaXplID0gInRvdGFsIiwKICAgICAgICAgICAgICBncmFwaCA9ICJwcm9wb3J0aW9uIikKCmNsb25hbFNjYXR0ZXIoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgY2xvbmVDYWxsID0iZ2VuZSIsIAogICAgICAgICAgICAgIHguYXhpcyA9ICJMNSIsIAogICAgICAgICAgICAgIHkuYXhpcyA9ICJMNyIsCiAgICAgICAgICAgICAgZG90LnNpemUgPSAidG90YWwiLAogICAgICAgICAgICAgIGdyYXBoID0gInByb3BvcnRpb24iKQoKY2xvbmFsU2NhdHRlcihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSJnZW5lIiwgCiAgICAgICAgICAgICAgeC5heGlzID0gIkw2IiwgCiAgICAgICAgICAgICAgeS5heGlzID0gIkw3IiwKICAgICAgICAgICAgICBkb3Quc2l6ZSA9ICJ0b3RhbCIsCiAgICAgICAgICAgICAgZ3JhcGggPSAicHJvcG9ydGlvbiIpCmBgYAojIDQuIFZpc3VhbGl6aW5nIENsb25hbCBEeW5hbWljcwoKIyMgNC4xIGNsb25hbEhvbWVvc3Rhc2lzCmBgYHtyIFY2LCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojIFZpc3VhbGl6aW5nIENsb25hbCBEeW5hbWljcwoKIyBjbG9uYWxIb21lb3N0YXNpcwoKY2xvbmFsSG9tZW9zdGFzaXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIikKCgpjbG9uYWxIb21lb3N0YXNpcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiLAogICAgICAgICAgICAgICAgICBjbG9uZVNpemUgPSBjKFJhcmUgPSAwLjAwMSwgU21hbGwgPSAwLjAxLCBNZWRpdW0gPSAwLjEsIExhcmdlID0gMC4zLCBIeXBlcmV4cGFuZGVkID0xKSkKCmBgYAojIyA0LjIgY2xvbmFsUHJvcG9ydGlvbgpgYGB7ciBTdGF0cywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KIyBjbG9uYWxQcm9wb3J0aW9uCgpjbG9uYWxQcm9wb3J0aW9uKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIikgCgpjbG9uYWxQcm9wb3J0aW9uKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJudCIsCiAgICAgICAgICAgICAgICAgY2xvbmFsU3BsaXQgPSBjKDEsIDUsIDEwLCAxMDAsIDEwMDAsIDEwMDAwKSkgCmBgYAojIDUuIFN1bW1hcml6aW5nIFJlcGVydG9pcmVzCmBgYHtyIERFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQojIFN1bW1hcml6aW5nIFJlcGVydG9pcmVzCgojcGVyY2VudEFBCgpwZXJjZW50QUEoY29tYmluZWQuVENSLCAKICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgYWEubGVuZ3RoID0gMjApCgojIHBvc2l0aW9uYWxFbnRyb3B5CiMgV2UgY2FuIGFsc28gcXVhbnRpZnkgdGhlIGxldmVsIG9mIGVudHJvcHkvZGl2ZXJzaXR5IGFjcm9zcyBhbWlubyBhY2lkIHJlc2lkdWVzIGFsb25nIHRoZSBjZHIzIHNlcXVlbmNlLiBwb3NpdGlvbmFsRW50cm9weSgpIGNvbWJpbmVzIHRoZSBxdWFudGlmaWNhdGlvbiBieSByZXNpZHVlIG9mIHBlcmNlbnRBQSgpIHdpdGggdGhlIGRpdmVyc2l0eSBjYWxscyBpbiBjbG9uYWxEaXZlcnNpdHkoKS4KIyAKIyBtZXRob2QKIyAKIyDigJxzaGFubm9u4oCdIC0gU2hhbm5vbiBEaXZlcnNpdHkKIyDigJxpbnYuc2ltcHNvbuKAnSAtIEludmVyc2UgU2ltcHNvbiBEaXZlcnNpdHkKIyDigJxub3JtLmVudHJvcHnigJ0gLSBOb3JtYWxpemVkIEVudHJvcHkKCnBvc2l0aW9uYWxFbnRyb3B5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgICAgICAgYWEubGVuZ3RoID0gMjApCgoKIyBwb3NpdGlvbmFsUHJvcGVydHkKIyBMaWtlIHBvc2l0aW9uYWxFbnRyb3B5KCksIHdlIGNhbiBhbHNvIGV4YW1pbmUgYSBzZXJpZXMgb2YgYW1pbm8gYWNpZCBwcm9wZXJ0aWVzIGFsb25nIHRoZSBjZHIzIHNlcXVlbmNlcyB1c2luZyBwb3NpdGlvbmFsUHJvcGVydHkoKS4gSW1wb3J0YW50IGRpZmZlcmVuY2VzIGZyb20gdGhlIGFib3ZlIGZ1bmN0aW9uIGZvciBwb3NpdGlvbmFsUHJvcGVydHkoKSBpcyBkcm9wcGluZyBOQSB2YWx1ZXMgYXMgdGhleSB3b3VsZCB2b2lkIHRoZSBtZWFuIGNhbGN1bGF0aW9uLiBwb3NpdGlvbmFsUHJvcGVydHkoKSBhbHNvIGRpc3BsYXkgYSByaWJib24gd2l0aCB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgc3Vycm91bmRpbmcgdGhlIG1lYW4gdmFsdWUgZm9yIHRoZSBzZWxlY3RlZCBwcm9wZXJ0aWVzLgojIAojIG1ldGhvZAojIAojIOKAnEF0Y2hsZXnigJ0gLSBBdGNobGV5IEZhY3RvcnMKIyDigJxLaWRlcmHigJ0gLSBLaWRlcmEgRmFjdG9ycwojIOKAnHN0U2NhbGVz4oCdIC0gc3RTY2FsZXMgVmVjdG9ycwojIOKAnHRTY2FsZXPigJ0gLSB0U2NhbGVzIFZlY3RvcnMKIyDigJxWSFNF4oCdIC0gVmVjdG9ycyBvZiBIeWRyb3Bob2JpYywgU3RlcmljLCBhbmQgRWxlY3Ryb25pYyBwcm9wZXJ0aWVzCgojIHBvc2l0aW9uYWxQcm9wZXJ0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW2MoMSwyKV0sIAojICAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAojICAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwLCAKIyAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQXRjaGxleSIpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg1LCAiaW5mZXJubyIpW2MoMiw0KV0pCiMgCiMgcG9zaXRpb25hbFByb3BlcnR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUNbYygzLDQpXSwgCiMgICAgICAgICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiMgICAgICAgICAgICAgICAgICAgYWEubGVuZ3RoID0gMjAsIAojICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJBdGNobGV5IikgKyAKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBoY2wuY29sb3JzKDUsICJpbmZlcm5vIilbYygyLDQpXSkKIyAKIyBwb3NpdGlvbmFsUHJvcGVydHkoY29tYmluZWQuVENSX3dpdGhfUEJNQ1tjKDUsNildLCAKIyAgICAgICAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKIyAgICAgICAgICAgICAgICAgICBhYS5sZW5ndGggPSAyMCwgCiMgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gIkF0Y2hsZXkiKSArIAojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGhjbC5jb2xvcnMoNSwgImluZmVybm8iKVtjKDIsNCldKQojIAojIHBvc2l0aW9uYWxQcm9wZXJ0eShjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DW2MoNSw3KV0sIAojICAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAojICAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwLCAKIyAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQXRjaGxleSIpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg1LCAiaW5mZXJubyIpW2MoMiw0KV0pCiMgCiMgCiMgcG9zaXRpb25hbFByb3BlcnR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUNbYyg2LDcpXSwgCiMgICAgICAgICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiMgICAgICAgICAgICAgICAgICAgYWEubGVuZ3RoID0gMjAsIAojICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJBdGNobGV5IikgKyAKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBoY2wuY29sb3JzKDUsICJpbmZlcm5vIilbYygyLDQpXSkKIyAKIyBwb3NpdGlvbmFsUHJvcGVydHkoY29tYmluZWQuVENSX3dpdGhfUEJNQ1tjKDUsNiw3KV0sIAojICAgICAgICAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAojICAgICAgICAgICAgICAgICAgIGFhLmxlbmd0aCA9IDIwLCAKIyAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQXRjaGxleSIpICsgCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaGNsLmNvbG9ycyg1LCAiaW5mZXJubyIpW2MoMiw0KV0pCgoKIyB2aXpHZW5lcwojIEEgdmlzdWFsaXphdGlvbiBvZiB0aGUgcmVsYXRpdmUgdXNhZ2Ugb2YgZ2VuZXMgb2YgdGhlIFRDUiBvciBCQ1IsIHVzaW5nIHZpekdlbmVzKCkuIFRoZXJlIGlzIHNvbWUgZnVuY3Rpb25hbCBjcm9zc292ZXIgYmV0d2VlbiB2aXpHZW5lcygpIGFuZCB0d28gZnVuY3Rpb25zIGJlbG93IGNhbGxlZCBwZXJjZW50R2VuZXMoKSBhbmQgcGVyY2VudFZKKCkuIEJ1dCB2aXpHZW5lcygpIGlzIG1vcmUgYWRhcHRhYmxlIHRvIGFsbG93IGZvciBjb21wYXJpc29ucyBhY3Jvc3MgY2hhaW5zLCBzY2FsaW5nLCBldGMuCgp2aXpHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgeC5heGlzID0gIlRSQlYiLAogICAgICAgICB5LmF4aXMgPSBOVUxMLAogICAgICAgICBwbG90ID0gImJhcnBsb3QiLCAgCiAgICAgICAgIHNjYWxlID0gVFJVRSkKCnZpekdlbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgIHguYXhpcyA9ICJUUkFWIiwKICAgICAgICB5LmF4aXMgPSBOVUxMLAogICAgICAgIHBsb3QgPSAiYmFycGxvdCIsICAKICAgICAgICBzY2FsZSA9IFRSVUUpCgp2aXpHZW5lcyhjb21iaW5lZC5UQ1JbYygxLDIsMyw0LDUsNiw3KV0sIAogICAgICAgICB4LmF4aXMgPSAiVFJCViIsCiAgICAgICAgIHkuYXhpcyA9ICJUUkJKIiwKICAgICAgICAgcGxvdCA9ICJoZWF0bWFwIiwgIAogICAgICAgICBzY2FsZSA9IFRSVUUpCgp2aXpHZW5lcyhjb21iaW5lZC5UQ1JbYygxLDIsMyw0LDUsNiw3KV0sIAogICAgICAgICB4LmF4aXMgPSAiVFJBViIsCiAgICAgICAgIHkuYXhpcyA9ICJUUkFKIiwKICAgICAgICAgcGxvdCA9ICJoZWF0bWFwIiwgIAogICAgICAgICBzY2FsZSA9IFRSVUUpCgojIEZvciB0aGUgUDE3IHBhdGllbnQgc2FtcGxlcywgd2hhdCBpZiB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBjaGFpbiBwYWlyaW5ncywgd2UgY2FuIGxvb2sgYXQgVFJCViBhbmQgVFJBViBhdCB0aGUgc2FtZSB0aW1lIHVzaW5nIHRoZW0gYXMgaW5wdXRzIHRvIHguYXhpcyBhbmQgeS5heGlzLgp2aXpHZW5lcyhjb21iaW5lZC5UQ1JbYygxLDIpXSwgCiAgICAgICAgIHguYXhpcyA9ICJUUkJWIiwKICAgICAgICAgeS5heGlzID0gIlRSQVYiLAogICAgICAgICBwbG90ID0gImhlYXRtYXAiLCAKICAgICAgICAgc2NhbGUgPSBGQUxTRSkKIyBwZXJjZW50R2VuZXMKIyBRdWFudGlmeSB0aGUgcHJvcG9ydGlvbiBvZiBWIG9yIEogZ2VuZSB1c2FnZSB3aXRoIHBlcmNlbnRHZW5lcygpLiBMaWtlIHBlcmNlbnRBQSgpLCB3ZSBzZWxlY3QgdGhlIGNoYWluIG9mIGludGVyZXN0IGFuZCB0aGVuIGluZGljYXRlIHRoZSBnZW5lIG9mIGludGVyZXN0IHdpdGggdGhlIGdlbmUgcGFyYW1ldGVyLiBUd28gbWFqb3IgbGltaXRhdGlvbnMgb2YgcGVyY2VudEdlbmVzKCkgYXJlLCAxKSB0aGUgZnVuY3Rpb24gcXVhbnRpZmllcyBvbmx5IFYgb3IgSiBnZW5lcywgYW5kIDIpIHRoZSBxdWFudGlmaWNhdGlvbiBvZiB0aGUgZ2VuZXMgYXJlIGxpbWl0ZWQgdG8gYWxsIHRoZSBWIG9yIEogZ2VuZXMgc2VlbiBhY3Jvc3MgdGhlIHNhbXBsZXMsIG5vdCBhbGwgcG9zc2libGUgViBvciBKIGdlbmVzLgoKcGVyY2VudEdlbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJCIiwgCiAgICAgICAgICAgICBnZW5lID0gIlZnZW5lIikKCnBlcmNlbnRHZW5lcyhjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICAgZ2VuZSA9ICJWZ2VuZSIpCgpwZXJjZW50R2VuZXMoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgICBjaGFpbiA9ICJUUkIiLCAKICAgICAgICAgICAgIGdlbmUgPSAiSmdlbmUiKQoKcGVyY2VudEdlbmVzKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgY2hhaW4gPSAiVFJBIiwgCiAgICAgICAgICAgICBnZW5lID0gIkpnZW5lIikKCgojIHBlcmNlbnRWSgojIFF1YW50aWZ5IHRoZSBwcm9wb3J0aW9uIG9mIFYgYW5kIEogZ2VuZSB1c2FnZSB3aXRoIHBlcmNlbnRWSigpLiBMaWtlIHBlcmNlbnRHZW5lcygpLCB0aGlzIGZ1bmN0aW9uIHdpbGwgcXVhbnRpZnkgdGhlIHBlcmNlbnRhZ2Ugb2YgViBhbmQgSiBwYWlyZWQgdG9nZXRoZXIgYWNyb3NzIGluZGl2aWR1YWwgcmVwZXJ0b2lyZXMuIFRoZSBvdXRwdXQgY2FuIGJlIHZpc3VhbGl6ZWQgdXNpbmcgYSBoZWF0bWFwIG9yIGFzIGlucHV0IGZvciBmdXJ0aGVyIGRpbWVuc2lvbmFsIHJlZHVjdGlvbi4KCnBlcmNlbnRWSihjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgIGNoYWluID0gIlRSQiIpCgpwZXJjZW50VkooY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICBjaGFpbiA9ICJUUkEiKQoKIyBwZXJjZW50S21lcgojIEFub3RoZXIgcXVhbnRpZmljYXRpb24gb2YgdGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBDRFIzIHNlcXVlbmNlIGlzIHRvIGRlZmluZSBtb3RpZnMgYnkgc2xpZGluZyBhY3Jvc3MgdGhlIGFtaW5vIGFjaWQgb3IgbnVjbGVvdGlkZSBzZXF1ZW5jZXMgYXQgc2V0IGludGVydmFscyByZXN1bHRpbmcgaW4gc3Vic3RyaW5ncyBvciBrbWVycy4KIyAKIyBtb3RpZi5sZW5ndGgKIyAKIyBOdW1lcmljYWwgdmFsdWUgZm9yIHRoZSBsZW5ndGggb2YgdGhlIGttZXIuCiMgdG9wLm1vdGlmcwojIAojIERpc3BsYXkgdGhlIG1vc3QgdmFyaWFibGUgZ2VuZXMgZGV0ZXJtaW5lZCBieSBtZWFuIGFic29sdXRlIGRldmlhdGlvbiAoTUFEKS4KcGVyY2VudEttZXIoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJhYSIsCiAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICBtb3RpZi5sZW5ndGggPSAzLCAKICAgICAgICAgICAgdG9wLm1vdGlmcyA9IDI1KQoKcGVyY2VudEttZXIoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJhYSIsCiAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICBtb3RpZi5sZW5ndGggPSAzLCAKICAgICAgICAgICAgdG9wLm1vdGlmcyA9IDI1KQoKcGVyY2VudEttZXIoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJudCIsCiAgICAgICAgICAgIGNoYWluID0gIlRSQiIsIAogICAgICAgICAgICBtb3RpZi5sZW5ndGggPSAzLCAKICAgICAgICAgICAgdG9wLm1vdGlmcyA9IDI1KQoKcGVyY2VudEttZXIoY29tYmluZWQuVENSX3dpdGhfUEJNQywgCiAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJudCIsCiAgICAgICAgICAgIGNoYWluID0gIlRSQSIsIAogICAgICAgICAgICBtb3RpZi5sZW5ndGggPSAzLCAKICAgICAgICAgICAgdG9wLm1vdGlmcyA9IDI1KQpgYGAKIyA2LiBDb21wYXJpbmcgQ2xvbmFsIERpdmVyc2l0eSBhbmQgT3ZlcmxhcApgYGB7ciBjbG9uYWxEaXZlcnNpdHksIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTZ9CiMgY2xvbmFsRGl2ZXJzaXR5CgoKY2xvbmFsRGl2ZXJzaXR5KGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgY2xvbmVDYWxsID0gImdlbmUiKQoKI2Nsb25hbFNpemVEaXN0cmlidXRpb24KCgpjbG9uYWxTaXplRGlzdHJpYnV0aW9uKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJhYSIsIAogICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD0gIndhcmQuRDIiKQoKCgojY2xvbmFsT3ZlcmxhcAoKY2xvbmFsT3ZlcmxhcChjb21iaW5lZC5UQ1Jfd2l0aF9QQk1DLCAKICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAic3RyaWN0IiwgCiAgICAgICAgICAgICAgbWV0aG9kID0gIm1vcmlzaXRhIikKCgpjbG9uYWxPdmVybGFwKGNvbWJpbmVkLlRDUl93aXRoX1BCTUMsIAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJzdHJpY3QiLCAKICAgICAgICAgICAgICBtZXRob2QgPSAicmF3IikKYGBgCiMgNy4gQ29tYmluaW5nIENsb25lcyBhbmQgU2luZ2xlLUNlbGwgT2JqZWN0cwpgYGB7ciBTQywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KCiMgQ29tYmluaW5nIENsb25lcyBhbmQgU2luZ2xlLUNlbGwgT2JqZWN0cwoKI0dldHRpbmcgYSBzYW1wbGUgb2YgYSBTZXVyYXQgb2JqZWN0CnNjUmVwX2V4YW1wbGUgPC0gZ2V0KGRhdGEoIkFsbF9zYW1wbGVzX01lcmdlZCIpKQoKCiNEZWZpbmUgY29sb3IgcGFsZXR0ZSAKY29sb3JibGluZF92ZWN0b3IgPC0gaGNsLmNvbG9ycyhuPTcsIHBhbGV0dGUgPSAiaW5mZXJubyIsIGZpeHVwID0gVFJVRSkKCgpzY1JlcF9leGFtcGxlIDwtIGNvbWJpbmVFeHByZXNzaW9uKGNvbWJpbmVkLlRDUiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NSZXBfZXhhbXBsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVDYWxsPSJnZW5lIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAic2FtcGxlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcG9ydGlvbiA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZVNpemU9YyhTaW5nbGU9MSwgU21hbGw9NSwgTWVkaXVtPTIwLCBMYXJnZT0xMDAsIEh5cGVyZXhwYW5kZWQ9NTAwKSkKCkRpbVBsb3Qoc2NSZXBfZXhhbXBsZSwgZ3JvdXAuYnkgPSAiY2xvbmVTaXplIikKCkRpbVBsb3Qoc2NSZXBfZXhhbXBsZSwgZ3JvdXAuYnkgPSAiY2xvbmVTaXplIikgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1yZXYoY29sb3JibGluZF92ZWN0b3JbYygxLDMsNCw1LDYpXSkpCgoKYGBgCiMgOC4gVmlzdWFsaXphdGlvbnMgZm9yIFNpbmdsZS1DZWxsIE9iamVjdHMKYGBge3IgVl9zYywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Nn0KCiMgVmlzdWFsaXphdGlvbnMgZm9yIFNpbmdsZS1DZWxsIE9iamVjdHMKIyBjbG9uYWxPdmVybGF5CgojQWRkaW5nIHBhdGllbnQgaW5mb3JtYXRpb24Kc2NSZXBfZXhhbXBsZSRQYXRpZW50X29yaWdpbiA8LSBzdWJzdHIoc2NSZXBfZXhhbXBsZSRvcmlnLmlkZW50LCAxLDMpCgpjbG9uYWxPdmVybGF5KHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgZnJlcS5jdXRwb2ludCA9IDEsIAogICAgICAgICAgICAgIGJpbnMgPSAxMCwgCiAgICAgICAgICAgICAgZmFjZXQuYnkgPSAiUGF0aWVudF9vcmlnaW4iKSArIAogICAgICAgICAgICAgIGd1aWRlcyhjb2xvciA9ICJub25lIikKCiNjbG9uYWxOZXR3b3JrCiNnZ3JhcGggbmVlZHMgdG8gYmUgbG9hZGVkIGR1ZSB0byBpc3N1ZXMgd2l0aCBnZ3Bsb3QKbGlicmFyeShnZ3JhcGgpCgpjbG9uYWxOZXR3b3JrKHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICAgICAgICAgICAgICBmaWx0ZXIuY2xvbmVzID0gTlVMTCwKICAgICAgICAgICAgICBmaWx0ZXIuaWRlbnRpdHkgPSBOVUxMLAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJhYSIpCgoKI0V4YW1pbmluZyBDbHVzdGVyIDMgb25seQpjbG9uYWxOZXR3b3JrKHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICAgICAgICAgICAgICBmaWx0ZXIuaWRlbnRpdHkgPSA4LAogICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJhYSIpCgoKc2hhcmVkLmNsb25lcyA8LSBjbG9uYWxOZXR3b3JrKHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGwgPSAiYWEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cG9ydENsb25lcyA9IFRSVUUpCmhlYWQoc2hhcmVkLmNsb25lcykKCgpzY1JlcF9leGFtcGxlIDwtIGhpZ2hsaWdodENsb25lcyhzY1JlcF9leGFtcGxlLCAKICAgICAgICAgICAgICAgICAgICBjbG9uZUNhbGw9ICJhYSIsIAogICAgICAgICAgICAgICAgICAgIHNlcXVlbmNlID0gYygiQ0FUR1BOR1NTTlRHS0xJRjtDQUxTTk5BUkxNRl9DU0FUVEdGWUdZVEYiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNBWVNFU0dHU05ZS0xURl9DU0FMQUdHWVREVFFZRiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDTFZHRVRHUlJBTFRGX0NTQVJHRFJHUVBRSEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0xWR0VUR1JSQUxURl9DU0FSR0RSR1FQUUhGO0NBVFNERktRVlNOUVBRSEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0FUR1BOR1NTTlRHS0xJRl9DU0FUVEdGWUdZVEYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkFfQ1NBUkdEUkdRUFFIRiIpKQoKU2V1cmF0OjpEaW1QbG90KHNjUmVwX2V4YW1wbGUsIGdyb3VwLmJ5ID0gImhpZ2hsaWdodCIpICsgCiAgZ2dwbG90Mjo6dGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCiNjbG9uYWxPY2N1cHkKY2xvbmFsT2NjdXB5KHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgIHguYXhpcyA9ICJzZXVyYXRfY2x1c3RlcnMiKQoKY2xvbmFsT2NjdXB5KHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgICAgICAgICB4LmF4aXMgPSAiaWRlbnQiLCAKICAgICAgICAgICAgICAgICAgICAgcHJvcG9ydGlvbiA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IEZBTFNFKQojIGFsbHV2aWFsQ2xvbmVzCgojIHNjUmVwX2V4YW1wbGUkUGF0aWVudF9vcmlnaW4gPC0gc3Vic3RyKHNjUmVwX2V4YW1wbGUkb3JpZy5pZGVudCwgOCw4KQojIAojIGFsbHV2aWFsQ2xvbmVzKHNjUmVwX2V4YW1wbGUsIAojICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJhYSIsIAojICAgICAgICAgICAgICAgIHkuYXhlcyA9IGMoIlBhdGllbnRfb3JpZ2luIiwgIm9yaWcuaWRlbnQiLCAiQ2VsbF9saW5lX0ltbXVub3BoZW5vdHlwZSIpLCAKIyAgICAgICAgICAgICAgICBjb2xvciA9IGMoIkNBVEdQTkdTU05UR0tMSUY7Q0FMU05OQVJMTUZfQ1NBVFRHRllHWVRGIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNBWVNFU0dHU05ZS0xURl9DU0FMQUdHWVREVFFZRiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNMVkdFVEdSUkFMVEZfQ1NBUkdEUkdRUFFIRiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNMVkdFVEdSUkFMVEZfQ1NBUkdEUkdRUFFIRjtDQVRTREZLUVZTTlFQUUhGIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0FUR1BOR1NTTlRHS0xJRl9DU0FUVEdGWUdZVEYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOQV9DU0FSR0RSR1FQUUhGIikpICsgCiMgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImdyZXkiLCBjb2xvcmJsaW5kX3ZlY3RvclszXSkpCiMgCiMgCiMgCiMgYWxsdXZpYWxDbG9uZXMoc2NSZXBfZXhhbXBsZSwgCiMgICAgICAgICAgICAgICAgICAgIGNsb25lQ2FsbCA9ICJnZW5lIiwgCiMgICAgICAgICAgICAgICAgICAgIHkuYXhlcyA9IGMoIlBhdGllbnRfb3JpZ2luIiwgIm9yaWcuaWRlbnQiLCAiQ2VsbF9saW5lX0ltbXVub3BoZW5vdHlwZSIpLCAKIyAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiaWRlbnQiKSAKCgoKbGlicmFyeShjaXJjbGl6ZSkKbGlicmFyeShzY2FsZXMpCgpjaXJjbGVzIDwtIGdldENpcmNsaXplKHNjUmVwX2V4YW1wbGUsIAogICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIpCgojSnVzdCBhc3NpZ25pbmcgdGhlIG5vcm1hbCBjb2xvcnMgdG8gZWFjaCBjbHVzdGVyCmdyaWQuY29scyA8LSBodWVfcGFsKCkobGVuZ3RoKHVuaXF1ZShzY1JlcF9leGFtcGxlJHNldXJhdF9jbHVzdGVycykpKQpuYW1lcyhncmlkLmNvbHMpIDwtIHVuaXF1ZShzY1JlcF9leGFtcGxlJHNldXJhdF9jbHVzdGVycykKCiNHcmFwaGluZyB0aGUgY2hvcmQgZGlhZ3JhbQpjaG9yZERpYWdyYW0oY2lyY2xlcywgc2VsZi5saW5rID0gMSwgZ3JpZC5jb2wgPSBncmlkLmNvbHMpCgoKY2lyY2xlcyA8LSBnZXRDaXJjbGl6ZShzY1JlcF9leGFtcGxlLCBncm91cC5ieSA9ICJjZWxsX2xpbmUiLCBwcm9wb3J0aW9uID0gVFJVRSkKCmdyaWQuY29scyA8LSBzY2FsZXM6Omh1ZV9wYWwoKShsZW5ndGgodW5pcXVlKHNjUmVwX2V4YW1wbGVAYWN0aXZlLmlkZW50KSkpCm5hbWVzKGdyaWQuY29scykgPC0gbGV2ZWxzKHNjUmVwX2V4YW1wbGVAYWN0aXZlLmlkZW50KQoKY2hvcmREaWFncmFtKGNpcmNsZXMsIAogICAgICAgICAgICAgc2VsZi5saW5rID0gMSwgCiAgICAgICAgICAgICBncmlkLmNvbCA9IGdyaWQuY29scywgCiAgICAgICAgICAgICBkaXJlY3Rpb25hbCA9IDEsIAogICAgICAgICAgICAgZGlyZWN0aW9uLnR5cGUgPSAgImFycm93cyIsCiAgICAgICAgICAgICBsaW5rLmFyci50eXBlID0gImJpZy5hcnJvdyIpCmBgYA==