Plan

Background

This dataset contains RNA Seq data of an experiment to determine the transcriptomic changes caused by Radiation and IL12 treatment on murine B16 melanoma tumors.

The transcriptomic profile.

KEY
Non-radiated (no RT)= 0Gy
Irradiated (RT) = 8Gy)
AAV #216 = Adenoassociated Virus/ Inducible Luciferase transgene
AAV #189 = Adenoassociated Virus/ Inducible Interleukin 12 transgene

#set wd
setwd("C:/Users/Lenovo/MIB Assignments/NOTES/Bioinformatica/Bioinformatics Practice R/AFRILAB IL12 RNA Seq")

#Load Libraries 
library(Biobase)
library(BiocManager)

#EDA, DEA packages
library(edgeR)
library(limma)
library(DESeq2)

#Data visualisation
library(ggplot2)
library(ggrepel)
suppressPackageStartupMessages(library(ComplexHeatmap))
library(VennDiagram)
#BiocManager::install("EnhancedVolcano")
library(EnhancedVolcano)

#Data manipulation
library(tidyverse) 
library(dplyr)
library(reshape2)
library(writexl)
library(readxl)

##****** Mouse gene annotation package

#BiocManager::install("org.Mm.eg.db")
library(org.Mm.eg.db)

#BiocManager::install("biomaRt")
library(biomaRt)

#BiocManager::install("AnnotationDbi")
library(AnnotationDbi)

#Pathway Analysis
library(clusterProfiler)
library(enrichplot)

Loading Data

Count Matrix (Data was normalised by Limma-Voom)

Tidy up Metadata and extract groups and samples of interest

Create Graphics for Weight. This only makes sense if you have the starting weight for normalization.


## Load Count Data 
count_data <- read_xlsx("DataRaw.xlsx")
count_data <-  as.data.frame(count_data)
#class(count_data)
head(count_data)
#View(count_data)

##gene_metadata
gene_metadata <- count_data[, 1:11]

## Load Sample Metadata
sample_metadata <- read_xlsx("Muestras transcriptoma.xlsx")
sample_metadata <- as.data.frame(sample_metadata, header=TRUE)
#View(sample_metadata)

Exploratory Data Analysis

RNA types present in the Data

With a hint from the previous table (gene_metadata) and as seen below, I found that the RNA data or the annotated genes contains not only the mRNA but many other types of RNA (non-coding RNA) including ribosomal RNA, siRNAs, TECs and other RNAs that maybe involved in regulation of transcription and epigenetics.

Therefore, I will extract mRNAs only and analyse that as they make up majority of the sequences and I will also analyse the non-coding RNA separately. This is exciting!!


rna_types <- table(gene_metadata$gene_type) 
rna_types <- as.data.frame(rna_types)
#View(rna_types)

##* Ordering from Highest frequency to least didnt chnage the order on the plot.
##* The approach below did.

## Frequency of the different RNA types 
rna_types %>%
  arrange(Freq) %>%    # First sort by Freq This sort the dataframe but NOT the factor levels
  mutate(Var1=factor(Var1, levels=Var1)) %>%   # This trick update the factor levels
  ggplot(aes(x=Var1, y=Freq)) +  #note that the data object (rna_types) is only refered to at the start 
  ggtitle("RNA types and their Frequency")+  
  geom_col(color="red", fill="purple") +
  theme_classic() + 
  theme(axis.text.x = element_text(angle=90), axis)+
  coord_flip() +
  ylab("Frequency")+
  xlab("Gene type")

NA
NA

Select only mRNA counts for analysis.

Here we will retain mRNA protein-coding counts and we shall explore the rest of the non-coding RNAs.

## select counts for only mRNA (protein coding genes)

counts_mrna <- count_data[count_data$gene_type=="protein_coding" , ]
#dim(counts_mrna) ## [1] 21797    28 SUCCESS

Select counts for conditions to explore for example;
a) No Radiation, No AAV
b) No radiation, inducible Luciferase
c) Radiation , inducible Luciferase
d) Radiation, inducibe IL12

The BI6-JAK-Knockout samples (G,H,I) will be ommited for this anlaysis.

## protein coding counts for selected samples.

#colnames(counts_mrna)
counts_mrna <- counts_mrna[ , c("gene_id", "A_S7", "B_S8", "C_S9", "D_S10", "E_S11", "F_S12", "J_S16", "K_S17", "L_S18", "M_S19", "N_S20", "O_S21", "P_S22", "Q_S23")]

rownames(counts_mrna) <- counts_mrna$gene_id
counts_mrna <- counts_mrna[,-1]

## metadata_all groups of interest ---------------------------------------

metadata_all <- sample_metadata[-c(4,8,9,10,11, 12, 14, 20), ]
metadata_all$sample_id <- c("A_S7", "B_S8", "C_S9", "D_S10", "E_S11", "F_S12", "M_S19","J_S16", "K_S17", "L_S18","P_S22", "Q_S23", "N_S20", "O_S21")
metadata_all$group <- c("no_RT_no_AAV", "no_RT_no_AAV", "no_RT_no_AAV","RT_iIL12","RT_iIL12","RT_iIL12", "RT_iLuc","RT_iLuc","RT_iLuc", "RT_iLuc", "no_RT_iIL12","no_RT_iIL12", "no_RT_iIL12", "no_RT_iIL12")
metadata_all$group_description <- c("No Radiotherapy, No AAV mouse 1","No Radiotherapy, No AAV mouse 2","No Radiotherapy, No AAV mouse 3", "Radiotherapy + inducible IL12 mouse 1","Radiotherapy + inducible IL12 mouse 2","Radiotherapy + inducible IL12 mouse 3", "Radiotherapy + inducible Luciferase mouse 1", "Radiotherapy + inducible Luciferase mouse 2", "Radiotherapy + inducible Luciferase mouse 3","Radiotherapy + inducible Luciferase mouse 4", "No Radiotherapy + inducible IL12 mouse 1", "No Radiotherapy + inducible IL12 mouse 2",  "No Radiotherapy + inducible IL12 mouse 3",  "No Radiotherapy + inducible IL12 mouse 4")


#customise rownames to sample_id
rownames(metadata_all) <- metadata_all$sample_id

# make group object
group <- factor(metadata_all$group)
group <- relevel(factor(group), ref = "no_RT_no_AAV") #makes "no_RT+no_AAV" the reference group instead
levels(group)
[1] "no_RT_no_AAV" "no_RT_iIL12"  "RT_iIL12"     "RT_iLuc"     

Now that we have extracted the samples of interest and their related data, we will explore this data using graphics. The B16 Knockout group was removed and is not a part of this analysis.

Each condition has replicates

A comprehensive comparison and contrast will be presented in Chapter II of this analysis.

Counts Filtering


## Filter counts-----------

# create filtering criteria
myge_filter <- edgeR::filterByExpr(counts_mrna, group=group, min.count = 10, min.total.count = 15)

# apply filter in criteria
counts_mrna_filt <- counts_mrna[myge_filter, ]
#View(counts_mrna_filt)

dim(counts_mrna_filt) #[1] 12417    14
[1] 12417    14

Normalise the filtered counts

We will, normalise with edgeR TMM method and then apply limma-Voom instead of DEseq2,

Why?
Because we would like a more accurate DEGs with the lowest False Discovery Rate (FDR) possible.

## Data Normalization using TMM 

# create a DGE list

dge <- edgeR::DGEList(counts = counts_mrna_filt, group= group)

counts_mrna_norm <- calcNormFactors(dge, method = "TMM")

Depth Chart

Tumor Weight (Sacrificed same day)

Differential Expression Analysis

From the DataRaw file, I was able to extract the gene metadata. Therefore there was no need to map all over again.

We will use limma-voom to extract the DEGs.

Voom Transformation

# create a design matrix 
design_matrix <- model.matrix(~group) #choosing intercept
colnames(design_matrix) 
[1] "(Intercept)"      "groupno_RT_iIL12" "groupRT_iIL12"    "groupRT_iLuc"    
## Voom transformation 
voom_t <- voom(counts_mrna_norm, design_matrix, plot = TRUE)

Limma - Linear Model fitting

## limma (linear model fitting)
#?lmFit

#create fit data
fit <- lmFit(voom_t, design =  design_matrix)

# Statistical test (eBayes)
fit_ebayes <- eBayes(fit)

Output Matrix

#output matrix with fold change and adj.p-value<=0.05 = gene expression significant

#topTable function is part of the limma library
#We will use it to extract the output or result matrix 

results <- topTable(fit_ebayes, coef = ncol(design_matrix), number = Inf, adjust.method = "BH")

#Above, Benjamini-Hochberg (BH) was applied for FDR correction

head(results, n=10)
NA
NA

Significantly Expressed Genes

How many genes are differentially expressed if we define a threshold of: adj.p-value<=0.05 and |log2(FCh)|>0.58 ? These will be saved as sigGenes

Both Statistical and Biological relevance.

sigGenes <- results[results$adj.P.Val<=0.05 & results$logFC>0.58, ] #it is the rows that we are filtering based on the defined criteria but we want all columns to come back.

dim(sigGenes) # [1] 11001     6
[1] 115   6

11001 genes are significantly expressed.

VISUALIZATION I

Principle Component Analysis - PCA

pca <- prcomp(t(voom_t$E), scale. = TRUE)
pca_data_to_plot <- data.frame(PC1 = pca$x[,1], PC2 = pca$x[,2], group = group)

pca_plot <- ggplot(pca_data_to_plot, aes(x = PC1, y = PC2, color = group)) +
  geom_point(size=4) +
  theme_minimal() +
  labs(title = "PCA - RNA-seq ALL Samples", x = "PC1", y = "PC2")+
  geom_text_repel(aes(label=rownames(pca_data_to_plot)))

#ggsave("PCA_ALL.png", plot = pca_plot)
pca_plot

Observation: The groups are clearly distinct as seen by the huge variance in the PC1 (main) axis. However, the no RT + inducible IL12 duplicate samples appear to be very distinct.

Cluster plot

Volcano Plot

Biological relevance vs Statistical significance.


## Volcano Plot

ggplot(results, aes(x = logFC, y = -log10(adj.P.Val))) + 
  # All genes = BLACK (These don't change)
  geom_point(color = "black", alpha = 0.3) +
  
  #Overexpressed genes = RED
  geom_point(data=results[results$logFC > 0.58 & results$adj.P.Val <= 0.05,], 
             aes(x = logFC, y = -log10(adj.P.Val)), color="red", alpha = 0.7) +
  
  #Under expressed genes = BLUE
  geom_point(data=results[results$logFC < -0.58 & results$adj.P.Val <= 0.05,], 
             aes(x = logFC, y = -log10(adj.P.Val)), color="blue", alpha = 0.7) +
  
  #ref lines
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "blue") +
  geom_vline(xintercept = c(0.58, -0.58), linetype = "dashed", color = "gray") +
  
  theme_minimal() + 
  
  labs(title = "Volcano Plot - Differential Expression",
       x = "Log2 Fold Change", 
       y = "-Log10 P-value")

NA
NA
NA

DEGS HeatMap

Top 20 DEGS


# Since we already Voom transformed the data, we can z transform it without renormalizing.
Z_score_voom <- t(scale(t(voom_t$E), center = TRUE, scale = TRUE))

#Order by Fc from Big to Small
sigGenes_ordFch <- sigGenes[order(sigGenes$logFC, decreasing = TRUE),]
#View(sigGenes_ordFch)


# -----------------------------------

## Adding the gene metadata to the sigGenes_ordFch

rownames(gene_metadata) <- gene_metadata$gene_id

sigGenes_ordFch_metadata <- gene_metadata[match(rownames(sigGenes_ordFch), gene_metadata$gene_id), c("gene_type", "gene_name")]

sigGenes_ordFch_annotated  <- cbind(sigGenes_ordFch, sigGenes_ordFch_metadata) #success
#head(sigGenes_ordFch_annotated)

# -----------------------------------


treatment_colors <- c(
  "RT_iLuc" = "#EF476F",            
  "no_RT_iIL12" = "#FFD166",
  "no_RT_no_AAV"= "#06D6A0", 
  "RT_iIL12"= "#118AB2" 
)   

# Column annotation
column_ha <- HeatmapAnnotation(
  Treatment = group,  #treatment group
  col = list(Treatment = treatment_colors)  #treatment stage coloring
)


# heatmap for top 20 DE genes
Heatmap(Z_score_voom[rownames(sigGenes_ordFch)[1:20],], 
        row_names_gp = gpar(fontsize = 5),        
        top_annotation = column_ha, 
        row_names_side = "left", 
        row_labels = sigGenes_ordFch_annotated$gene_name[1:20]
)

DEGs Table

Top 10 DEGs

head(sigGenes_ordFch_annotated, n=10)
#mygenes <- head(sigGenes_ordFch_annotated, n=10)
#mygenes$gene_name

CHAPTER II: CONTRASTS

In the previous chapter, a general analysis of the groups has been performed (compared to baseline group). In this chapter, we will define and explore changes between different groups with depth.
Groups of interest will be compared against each other.

For this, we will have to fit the data again, starting from the normalisation, design matrix. Define contrast and visualise the comparisons.

Reanalysis (Independent Comparisons)

For the purposes of this comparison, we will name the groups as below

Control = no_RT_no_AAV
TreatA = no_RT_iIL12
TreatB = RT_iLuc
TreatC = RT_iIL12

## defining group for new analysis
group2 <- factor(metadata_all$group)
levels(group2)
[1] "no_RT_iIL12"  "no_RT_no_AAV" "RT_iIL12"     "RT_iLuc"     
# normalise data 
dge2 <- edgeR::DGEList(counts = counts_mrna_filt, group= group2)
counts_mrna_norm2 <- calcNormFactors(dge2, method = "TMM")


# create a design matrix 2 
design_matrix2 <- model.matrix(~0 + group2) #no intercept
colnames(design_matrix2) <- levels(group2) #no intercept defined


# Define contrasts of interest
contrast.matrix <- makeContrasts(
  TreatA_vs_Control = no_RT_iIL12 - no_RT_no_AAV, #Uninduced AAV-iIL12
  TreatB_vs_Control = RT_iLuc - no_RT_no_AAV, #RT effects
  TreatC_vs_TreatB = RT_iIL12 - RT_iLuc, #effects of RT + induced iIL12 
  levels = colnames(design_matrix2)
)


## Voom transformation 
voom_t2 <- voom(counts_mrna_norm2, design_matrix2)


## limma (linear model fitting)
fit2 <- lmFit(voom_t2, design =  design_matrix2)
fit2c <- contrasts.fit(fit2, contrast.matrix)

# Statistical test (eBayes)
fit_ebayes2 <- eBayes(fit2c)


##RESULTS contrasts

results_TreatA_vs_Control <- topTable(fit_ebayes2, coef = "TreatA_vs_Control", n = Inf, adjust.method = "BH")

results_TreatB_vs_Control <- topTable(fit_ebayes2, coef = "TreatB_vs_Control", n = Inf, adjust.method = "BH")

results_TreatC_vs_TreatB <- topTable(fit_ebayes2, coef = "TreatC_vs_TreatB", n = Inf, adjust.method = "BH")

Contrast

Pairwise Comparison of groups forexample No Radiation,No AAv vs No Radiation + IL12 to determine the changes caused by an inunduced AAV-IL12.

  • Volcano plots for all comparison sets with labeled genes.
  • Heatmaps for all comparisons sets.
  • Histograms for important genes in a comparison set.

Volcano Plots

Volcano Plot ——- no_RT_iIL12 vs no_RT_no_AAV (Control)

Volcano Plot ——- RT_iLuc vs no_RT_no_AAV (Control)

Volcano Plot ——- RT_iLuc vs RT_iIL12

Heatmaps for Sig genes

Significant UPREGULATED Genes for Contrasts.


## Significant UPREGULATED Genes for Contrasts------

sigGenes_AvsCtr_UP <- results_TreatA_vs_Control[results_TreatA_vs_Control$adj.P.Val<=0.05 & results_TreatA_vs_Control$logFC>0.58, ]

sigGenes_BvsCtr_UP <- results_TreatB_vs_Control[results_TreatB_vs_Control$adj.P.Val<=0.05 & results_TreatB_vs_Control$logFC>0.58, ]

sigGenes_CvsB_UP <- results_TreatC_vs_TreatB[results_TreatC_vs_TreatB$adj.P.Val<=0.05 & results_TreatC_vs_TreatB$logFC>0.58, ]

Significant DOWNREGULATED Genes for Contrasts.


## Significant DOWNREGULATED Genes for Contrasts------

sigGenes_AvsCtr_DW <- results_TreatA_vs_Control[results_TreatA_vs_Control$adj.P.Val<=0.05 & results_TreatA_vs_Control$logFC< -0.58, ]

sigGenes_BvsCtr_DW <- results_TreatB_vs_Control[results_TreatB_vs_Control$adj.P.Val<=0.05 & results_TreatB_vs_Control$logFC< -0.58, ]

sigGenes_CvsB_DW <- results_TreatC_vs_TreatB[results_TreatC_vs_TreatB$adj.P.Val<=0.05 & results_TreatC_vs_TreatB$logFC< -0.58, ]

RT_iLuc vs RT_IL12 Heatmap

Venn diagram

PATHWAY ANALYSIS

Pathway analysis in contrasts.

Now that differentially expressed genes have been identified, we will analyse enriched pathways in our data groups. This will help us make biological meaning of the actual changes happening in our data.

Fore each of these analysis only code for one will be shown and just results for the rest.

Data Prep for pathway analysis.

Our data has Ensembl Ids and ORA Go input requires entrez Ids


library(biomaRt)

# Connect to the Ensembl mouse database
ensembl <- useEnsembl(biomart = "genes", dataset = "mmusculus_gene_ensembl")

# IDs to convert
ensembl_ids <- rownames(gene_metadata)

# Remove version numbers (the part after the dot)
ensembl_ids_no_version <- sub("\\.[0-9]+$", "", ensembl_ids)

# Get the mapping between Ensembl and Entrez IDs
entrez_id_mapping <- getBM(
  attributes = c("ensembl_gene_id", "entrezgene_id", "external_gene_name"),
  filters = "ensembl_gene_id",
  values = ensembl_ids_no_version,
  mart = ensembl
)

# View results
print(entrez_id_mapping)
NA
NA
NA

ORA GO Analysis

no_RT_iIL12 vs no_RT_no_AAV (Control)

GSEA - Gene Set Enrichmment Analysis

no.RT_iL12 vs no.RT_no.AAV


# no.RT_iL12 vs no.RT_no.AAV

# Define the ranked genes list based on logFCh.

AvsCtrl_geneList <- results_TreatA_vs_Control$logFC


names(AvsCtrl_geneList) <- sub("\\.[0-9]+$", "", rownames(results_TreatA_vs_Control)) #removes version components (everything after dot) --- substitute("these", "with this", in)

AvsCtrl_geneList_ranked <- AvsCtrl_geneList[order(AvsCtrl_geneList, decreasing = TRUE)]

# Perform the GSEA based on GO terms

gsea_go <- gseGO(geneList     = AvsCtrl_geneList_ranked,
              OrgDb        = org.Mm.eg.db,
              keyType = "ENSEMBL",
              ont          = "BP",
              minGSSize    = 100,
              maxGSSize    = 500,
              pvalueCutoff = 0.01,
              verbose      = FALSE)

View(gsea_go@result)

# Results visualization

layout(matrix(c(1, 2, 3), nrow = 1, ncol = 3, byrow = TRUE))

# Dotplot
dotplot(gsea_go, 
        x = "GeneRatio",
        color = "NES",
        size = "p.adjust",
        showCategory=10) + ggtitle("GSEA: no.RT_AAV.iL12 vs no.RT_no.AAV")


#Network Plot
cnetplot(gsea_go, node_label="category", 
               cex.params = list(cex_label_category = 1.2),
               categorySize="p.adjust", color.params = list(foldChange = AvsCtrl_geneList_ranked))


# Treeplot
gsea_go2 <- pairwise_termsim(gsea_go)

treeplot(gsea_go2, showCategory = 10)

RT_iLuc vs no.RT_no.AAV

GSEA: RT.AAV_iLuc vs RT_AAV.iIL12

SELECTED GENES

Possible Targets

The following are significant differentially expressed genes with a adjusted P value < 0.01 according to the contrasts. However, in the graphics below, the expression of these genes in each independent group will be plotted to see how they changed and in which direction.

For this we will use the contrasts to obtain gene ids and then plot them using their normalized expression data (voom$E) for each group. This normalized expression data is independent expression for each gene in each group, not linked to any comparison.

Top 40 sig expression in: no_RT_iIL12 vs no_RT_no_AAV

library(gridExtra)

###****** GENES plot 
###*

# TreatA vs Ctr - most sigificant genes (adj.p.val< 0.01) and highest FC

topSig_AvsCtr <- results_TreatA_vs_Control[(results_TreatA_vs_Control$logFC > 1.5 | results_TreatA_vs_Control$logFC < -1.5 & results_TreatA_vs_Control$adj.P.Val < 0.01), ]

#These are arranged from the most different in each group therefore I will not rearrange them according to fold change or p value. 

#By adj.P.Val
topSig_AvsCtr <- topSig_AvsCtr[order(topSig_AvsCtr$adj.P.Val, decreasing = FALSE), ]

#By FoldChange
#topSig_AvsCtr_ordFch <- topSig_AvsCtr[order(topSig_AvsCtr$logFC, decreasing = TRUE), ]



#Plot top 40 of each instance in both groups being compared

ids_to_plot_AvsCtr <- head(topSig_AvsCtr, n=40)
#These are arranged from the most different in each group therefore I will not rearrange them according to fold change or p value. 
  
## Expression data to plot all groups----- could change to pval
expr_data_to_plot_AvsCtr <- as.data.frame(t(voom_t$E[rownames(ids_to_plot_AvsCtr), ]))  
colnames(expr_data_to_plot_AvsCtr) <- ids_to_plot_AvsCtr$gene_name
expr_data_to_plot_AvsCtr$group <- metadata_all$group

#Only select for **no_RT_no_AAV** and **no_RT_iIL12***
#I used the rownames instead of group names because the group name only selected 2 samples of each group
expr_data_to_plot_AvsCtr <- expr_data_to_plot_AvsCtr[rownames(expr_data_to_plot_AvsCtr)==c( "A_S7","B_S8","C_S9", "N_S20", "O_S21", "P_S22", "Q_S23"), ]

# Convert from wide to long format
expr_data_to_plot_AvsCtr <- expr_data_to_plot_AvsCtr %>%
  pivot_longer(cols = -group, names_to = "gene", values_to = "expression")



#dput(group)
## Plot topSig_AvsCtr_ordFch

ggplot(data = expr_data_to_plot_AvsCtr, mapping=aes(x=gene, y=expression, fill = group)) +
  geom_boxplot(color="#e9ecef", alpha=0.6, position = 'identity')+
  scale_fill_manual(values=c("no_RT_iIL12" ="#69b3a2", "no_RT_no_AAV" ="#404080")) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "blue") + 
  ggtitle("Top 40 sig expression in: no_RT_iIL12 vs no_RT_no_AAV")+
  theme(axis.text.x = element_text(angle = 90,hjust=1)) 

NA
NA
NA

Top 40 sig expression in: RT_AAV.iLuc & no_RT_no_AAV

RT_iLuc vs RT_iIL12 Top 40 Sig genes

Multiple Plots

Conclusion

REFERENCES

Articles

Idi genes

Zuniga, O., Byrum, S., & Wolfe, A. R. (2022). Discovery of the inhibitor of DNA binding 1 as a novel marker for radioresistance in pancreatic cancer using genome-wide RNA-seq. Cancer drug resistance (Alhambra, Calif.), 5(4), 926–938. https://doi.org/10.20517/cdr.2022.60

Session Info

sessionInfo()
LS0tDQp0aXRsZTogIkFBViBJTDEyIFJUIFJOQSBTZXEiDQphdXRob3I6ICJKYXNvbiBMdWJlZ2EiDQpkYXRlOiAiMjAyNS0wNC0yOCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgdG9jOiB0cnVlDQogICAgY3NzOiBybWRzdHlsZTMuY3NzDQogIGh0bWxfbm90ZWJvb2s6DQogICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICBjc3M6IHJtZHN0eWxlMy5jc3MNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQojIyBQbGFuICANCi0gTG9hZCBEYXRhICAgDQotIEVEQSAtIERhdGEgRXhwbG9yYXRpb24gICANCi0gREVBIC0gRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gKFVzZWQgREVTZXEyKSAgDQotIEdPIC0gUGF0aHdheSBBbmFseXNpcyAgDQoNCg0KIyMgQmFja2dyb3VuZA0KDQpUaGlzIGRhdGFzZXQgY29udGFpbnMgUk5BIFNlcSBkYXRhIG9mIGFuIGV4cGVyaW1lbnQgKnRvIGRldGVybWluZSB0aGUgdHJhbnNjcmlwdG9taWMgY2hhbmdlcyBjYXVzZWQgYnkgUmFkaWF0aW9uIGFuZCBJTDEyIHRyZWF0bWVudCBvbiBtdXJpbmUgQjE2IG1lbGFub21hIHR1bW9ycyouDQoNClRoZSB0cmFuc2NyaXB0b21pYyBwcm9maWxlLiANCg0KDQoqKktFWSoqICANCk5vbi1yYWRpYXRlZCAobm8gUlQpPSAwR3kgICANCklycmFkaWF0ZWQgKFJUKSA9IDhHeSkgIA0KQUFWICMyMTYgPSBBZGVub2Fzc29jaWF0ZWQgVmlydXMvIEluZHVjaWJsZSBMdWNpZmVyYXNlIHRyYW5zZ2VuZSAgIA0KQUFWICMxODkgPSBBZGVub2Fzc29jaWF0ZWQgVmlydXMvIEluZHVjaWJsZSBJbnRlcmxldWtpbiAxMiB0cmFuc2dlbmUgIA0KDQoNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojc2V0IHdkDQpzZXR3ZCgiQzovVXNlcnMvTGVub3ZvL01JQiBBc3NpZ25tZW50cy9OT1RFUy9CaW9pbmZvcm1hdGljYS9CaW9pbmZvcm1hdGljcyBQcmFjdGljZSBSL0FGUklMQUIgSUwxMiBSTkEgU2VxIikNCg0KI0xvYWQgTGlicmFyaWVzIA0KbGlicmFyeShCaW9iYXNlKQ0KbGlicmFyeShCaW9jTWFuYWdlcikNCg0KI0VEQSwgREVBIHBhY2thZ2VzDQpsaWJyYXJ5KGVkZ2VSKQ0KbGlicmFyeShsaW1tYSkNCmxpYnJhcnkoREVTZXEyKQ0KDQojRGF0YSB2aXN1YWxpc2F0aW9uDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncmVwZWwpDQpsaWJyYXJ5KGhyYnJ0aGVtZXMpDQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShDb21wbGV4SGVhdG1hcCkpDQpsaWJyYXJ5KFZlbm5EaWFncmFtKQ0KI0Jpb2NNYW5hZ2VyOjppbnN0YWxsKCJFbmhhbmNlZFZvbGNhbm8iKQ0KbGlicmFyeShFbmhhbmNlZFZvbGNhbm8pDQoNCiNEYXRhIG1hbmlwdWxhdGlvbg0KbGlicmFyeSh0aWR5dmVyc2UpIA0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KHdyaXRleGwpDQpsaWJyYXJ5KHJlYWR4bCkNCg0KIyMqKioqKiogTW91c2UgZ2VuZSBhbm5vdGF0aW9uIHBhY2thZ2UNCg0KI0Jpb2NNYW5hZ2VyOjppbnN0YWxsKCJvcmcuTW0uZWcuZGIiKQ0KbGlicmFyeShvcmcuTW0uZWcuZGIpDQoNCiNCaW9jTWFuYWdlcjo6aW5zdGFsbCgiYmlvbWFSdCIpDQpsaWJyYXJ5KGJpb21hUnQpDQoNCiNCaW9jTWFuYWdlcjo6aW5zdGFsbCgiQW5ub3RhdGlvbkRiaSIpDQpsaWJyYXJ5KEFubm90YXRpb25EYmkpDQoNCiNQYXRod2F5IEFuYWx5c2lzDQpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikNCmxpYnJhcnkoZW5yaWNocGxvdCkNCg0KYGBgDQoNCiMjIExvYWRpbmcgRGF0YQ0KDQpDb3VudCBNYXRyaXggKERhdGEgd2FzIG5vcm1hbGlzZWQgYnkgTGltbWEtVm9vbSkNCg0KVGlkeSB1cCBNZXRhZGF0YSBhbmQgZXh0cmFjdCBncm91cHMgYW5kIHNhbXBsZXMgb2YgaW50ZXJlc3QNCg0KDQoNCkNyZWF0ZSBHcmFwaGljcyBmb3IgV2VpZ2h0LiBUaGlzIG9ubHkgbWFrZXMgc2Vuc2UgaWYgeW91IGhhdmUgdGhlIHN0YXJ0aW5nIHdlaWdodCBmb3Igbm9ybWFsaXphdGlvbi4NCg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89VFJVRX0NCg0KIyMgTG9hZCBDb3VudCBEYXRhIA0KY291bnRfZGF0YSA8LSByZWFkX3hsc3goIkRhdGFSYXcueGxzeCIpDQpjb3VudF9kYXRhIDwtICBhcy5kYXRhLmZyYW1lKGNvdW50X2RhdGEpDQojY2xhc3MoY291bnRfZGF0YSkNCmhlYWQoY291bnRfZGF0YSkNCiNWaWV3KGNvdW50X2RhdGEpDQoNCiMjZ2VuZV9tZXRhZGF0YQ0KZ2VuZV9tZXRhZGF0YSA8LSBjb3VudF9kYXRhWywgMToxMV0NCg0KIyMgTG9hZCBTYW1wbGUgTWV0YWRhdGENCnNhbXBsZV9tZXRhZGF0YSA8LSByZWFkX3hsc3goIk11ZXN0cmFzIHRyYW5zY3JpcHRvbWEueGxzeCIpDQpzYW1wbGVfbWV0YWRhdGEgPC0gYXMuZGF0YS5mcmFtZShzYW1wbGVfbWV0YWRhdGEsIGhlYWRlcj1UUlVFKQ0KI1ZpZXcoc2FtcGxlX21ldGFkYXRhKQ0KDQpgYGANCg0KDQojIyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIA0KDQoNCiMjIyMgUk5BIHR5cGVzIHByZXNlbnQgaW4gdGhlIERhdGEgIA0KDQpXaXRoIGEgaGludCBmcm9tIHRoZSBwcmV2aW91cyB0YWJsZSAoZ2VuZV9tZXRhZGF0YSkgYW5kIGFzIHNlZW4gYmVsb3csIEkgZm91bmQgdGhhdCB0aGUgUk5BIGRhdGEgb3IgdGhlIGFubm90YXRlZCBnZW5lcyBjb250YWlucyBub3Qgb25seSB0aGUgbVJOQSBidXQgbWFueSBvdGhlciB0eXBlcyBvZiBSTkEgKG5vbi1jb2RpbmcgUk5BKSBpbmNsdWRpbmcgcmlib3NvbWFsIFJOQSwgc2lSTkFzLCBURUNzIGFuZCBvdGhlciBSTkFzIHRoYXQgbWF5YmUgaW52b2x2ZWQgaW4gcmVndWxhdGlvbiBvZiB0cmFuc2NyaXB0aW9uIGFuZCBlcGlnZW5ldGljcy4gDQoNClRoZXJlZm9yZSwgSSB3aWxsIGV4dHJhY3QgbVJOQXMgb25seSBhbmQgYW5hbHlzZSB0aGF0IGFzIHRoZXkgbWFrZSB1cCBtYWpvcml0eSBvZiB0aGUgc2VxdWVuY2VzIGFuZCBJIHdpbGwgYWxzbyBhbmFseXNlIHRoZSBub24tY29kaW5nIFJOQSBzZXBhcmF0ZWx5LiBUaGlzIGlzIGV4Y2l0aW5nISENCg0KYGBge3J9DQoNCnJuYV90eXBlcyA8LSB0YWJsZShnZW5lX21ldGFkYXRhJGdlbmVfdHlwZSkgDQpybmFfdHlwZXMgPC0gYXMuZGF0YS5mcmFtZShybmFfdHlwZXMpDQojVmlldyhybmFfdHlwZXMpDQoNCiMjKiBPcmRlcmluZyBmcm9tIEhpZ2hlc3QgZnJlcXVlbmN5IHRvIGxlYXN0IGRpZG50IGNobmFnZSB0aGUgb3JkZXIgb24gdGhlIHBsb3QuDQojIyogVGhlIGFwcHJvYWNoIGJlbG93IGRpZC4NCg0KIyMgRnJlcXVlbmN5IG9mIHRoZSBkaWZmZXJlbnQgUk5BIHR5cGVzIA0Kcm5hX3R5cGVzICU+JQ0KICBhcnJhbmdlKEZyZXEpICU+JSAgICAjIEZpcnN0IHNvcnQgYnkgRnJlcSBUaGlzIHNvcnQgdGhlIGRhdGFmcmFtZSBidXQgTk9UIHRoZSBmYWN0b3IgbGV2ZWxzDQogIG11dGF0ZShWYXIxPWZhY3RvcihWYXIxLCBsZXZlbHM9VmFyMSkpICU+JSAgICMgVGhpcyB0cmljayB1cGRhdGUgdGhlIGZhY3RvciBsZXZlbHMNCiAgZ2dwbG90KGFlcyh4PVZhcjEsIHk9RnJlcSkpICsgICNub3RlIHRoYXQgdGhlIGRhdGEgb2JqZWN0IChybmFfdHlwZXMpIGlzIG9ubHkgcmVmZXJlZCB0byBhdCB0aGUgc3RhcnQgDQogIGdndGl0bGUoIlJOQSB0eXBlcyBhbmQgdGhlaXIgRnJlcXVlbmN5IikrICANCiAgZ2VvbV9jb2woY29sb3I9InJlZCIsIGZpbGw9InB1cnBsZSIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSwgYXhpcykrDQogIGNvb3JkX2ZsaXAoKSArDQogIHlsYWIoIkZyZXF1ZW5jeSIpKw0KICB4bGFiKCJHZW5lIHR5cGUiKQ0KDQoNCmBgYA0KIyMjIyBTZWxlY3Qgb25seSBtUk5BIGNvdW50cyBmb3IgYW5hbHlzaXMuICANCg0KSGVyZSB3ZSB3aWxsIHJldGFpbiBtUk5BICoqcHJvdGVpbi1jb2RpbmcqKiBjb3VudHMgYW5kIHdlIHNoYWxsIGV4cGxvcmUgdGhlIHJlc3Qgb2YgdGhlICoqbm9uLWNvZGluZyBSTkFzKiouIA0KYGBge3J9DQojIyBzZWxlY3QgY291bnRzIGZvciBvbmx5IG1STkEgKHByb3RlaW4gY29kaW5nIGdlbmVzKQ0KDQpjb3VudHNfbXJuYSA8LSBjb3VudF9kYXRhW2NvdW50X2RhdGEkZ2VuZV90eXBlPT0icHJvdGVpbl9jb2RpbmciICwgXQ0KI2RpbShjb3VudHNfbXJuYSkgIyMgWzFdIDIxNzk3ICAgIDI4IFNVQ0NFU1MNCg0KYGBgDQoNClNlbGVjdCBjb3VudHMgZm9yIGNvbmRpdGlvbnMgdG8gZXhwbG9yZSBmb3IgZXhhbXBsZTsgIA0KYSkgTm8gUmFkaWF0aW9uLCBObyBBQVYgIA0KYikgTm8gcmFkaWF0aW9uLCBpbmR1Y2libGUgTHVjaWZlcmFzZSAgIA0KYykgUmFkaWF0aW9uICwgaW5kdWNpYmxlIEx1Y2lmZXJhc2UgIA0KZCkgUmFkaWF0aW9uLCBpbmR1Y2liZSBJTDEyICANCg0KVGhlIEJJNi1KQUstS25vY2tvdXQgc2FtcGxlcyAoRyxILEkpIHdpbGwgYmUgb21taXRlZCBmb3IgdGhpcyBhbmxheXNpcy4gDQoNCmBgYHtyfQ0KIyMgcHJvdGVpbiBjb2RpbmcgY291bnRzIGZvciBzZWxlY3RlZCBzYW1wbGVzLg0KDQojY29sbmFtZXMoY291bnRzX21ybmEpDQpjb3VudHNfbXJuYSA8LSBjb3VudHNfbXJuYVsgLCBjKCJnZW5lX2lkIiwgIkFfUzciLCAiQl9TOCIsICJDX1M5IiwgIkRfUzEwIiwgIkVfUzExIiwgIkZfUzEyIiwgIkpfUzE2IiwgIktfUzE3IiwgIkxfUzE4IiwgIk1fUzE5IiwgIk5fUzIwIiwgIk9fUzIxIiwgIlBfUzIyIiwgIlFfUzIzIildDQoNCnJvd25hbWVzKGNvdW50c19tcm5hKSA8LSBjb3VudHNfbXJuYSRnZW5lX2lkDQpjb3VudHNfbXJuYSA8LSBjb3VudHNfbXJuYVssLTFdDQoNCiMjIG1ldGFkYXRhX2FsbCBncm91cHMgb2YgaW50ZXJlc3QgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCm1ldGFkYXRhX2FsbCA8LSBzYW1wbGVfbWV0YWRhdGFbLWMoNCw4LDksMTAsMTEsIDEyLCAxNCwgMjApLCBdDQptZXRhZGF0YV9hbGwkc2FtcGxlX2lkIDwtIGMoIkFfUzciLCAiQl9TOCIsICJDX1M5IiwgIkRfUzEwIiwgIkVfUzExIiwgIkZfUzEyIiwgIk1fUzE5IiwiSl9TMTYiLCAiS19TMTciLCAiTF9TMTgiLCJQX1MyMiIsICJRX1MyMyIsICJOX1MyMCIsICJPX1MyMSIpDQptZXRhZGF0YV9hbGwkZ3JvdXAgPC0gYygibm9fUlRfbm9fQUFWIiwgIm5vX1JUX25vX0FBViIsICJub19SVF9ub19BQVYiLCJSVF9pSUwxMiIsIlJUX2lJTDEyIiwiUlRfaUlMMTIiLCAiUlRfaUx1YyIsIlJUX2lMdWMiLCJSVF9pTHVjIiwgIlJUX2lMdWMiLCAibm9fUlRfaUlMMTIiLCJub19SVF9pSUwxMiIsICJub19SVF9pSUwxMiIsICJub19SVF9pSUwxMiIpDQptZXRhZGF0YV9hbGwkZ3JvdXBfZGVzY3JpcHRpb24gPC0gYygiTm8gUmFkaW90aGVyYXB5LCBObyBBQVYgbW91c2UgMSIsIk5vIFJhZGlvdGhlcmFweSwgTm8gQUFWIG1vdXNlIDIiLCJObyBSYWRpb3RoZXJhcHksIE5vIEFBViBtb3VzZSAzIiwgIlJhZGlvdGhlcmFweSArIGluZHVjaWJsZSBJTDEyIG1vdXNlIDEiLCJSYWRpb3RoZXJhcHkgKyBpbmR1Y2libGUgSUwxMiBtb3VzZSAyIiwiUmFkaW90aGVyYXB5ICsgaW5kdWNpYmxlIElMMTIgbW91c2UgMyIsICJSYWRpb3RoZXJhcHkgKyBpbmR1Y2libGUgTHVjaWZlcmFzZSBtb3VzZSAxIiwgIlJhZGlvdGhlcmFweSArIGluZHVjaWJsZSBMdWNpZmVyYXNlIG1vdXNlIDIiLCAiUmFkaW90aGVyYXB5ICsgaW5kdWNpYmxlIEx1Y2lmZXJhc2UgbW91c2UgMyIsIlJhZGlvdGhlcmFweSArIGluZHVjaWJsZSBMdWNpZmVyYXNlIG1vdXNlIDQiLCAiTm8gUmFkaW90aGVyYXB5ICsgaW5kdWNpYmxlIElMMTIgbW91c2UgMSIsICJObyBSYWRpb3RoZXJhcHkgKyBpbmR1Y2libGUgSUwxMiBtb3VzZSAyIiwgICJObyBSYWRpb3RoZXJhcHkgKyBpbmR1Y2libGUgSUwxMiBtb3VzZSAzIiwgICJObyBSYWRpb3RoZXJhcHkgKyBpbmR1Y2libGUgSUwxMiBtb3VzZSA0IikNCg0KDQojY3VzdG9taXNlIHJvd25hbWVzIHRvIHNhbXBsZV9pZA0Kcm93bmFtZXMobWV0YWRhdGFfYWxsKSA8LSBtZXRhZGF0YV9hbGwkc2FtcGxlX2lkDQoNCiMgbWFrZSBncm91cCBvYmplY3QNCmdyb3VwIDwtIGZhY3RvcihtZXRhZGF0YV9hbGwkZ3JvdXApDQpncm91cCA8LSByZWxldmVsKGZhY3Rvcihncm91cCksIHJlZiA9ICJub19SVF9ub19BQVYiKSAjbWFrZXMgIm5vX1JUK25vX0FBViIgdGhlIHJlZmVyZW5jZSBncm91cCBpbnN0ZWFkDQpsZXZlbHMoZ3JvdXApDQoNCmBgYA0KDQpOb3cgdGhhdCB3ZSBoYXZlIGV4dHJhY3RlZCB0aGUgc2FtcGxlcyBvZiBpbnRlcmVzdCBhbmQgdGhlaXIgcmVsYXRlZCBkYXRhLCB3ZSB3aWxsIGV4cGxvcmUgdGhpcyBkYXRhIHVzaW5nIGdyYXBoaWNzLiBUaGUgQjE2IEtub2Nrb3V0IGdyb3VwIHdhcyByZW1vdmVkIGFuZCBpcyBub3QgYSBwYXJ0IG9mIHRoaXMgYW5hbHlzaXMuDQoNCkVhY2ggY29uZGl0aW9uIGhhcyByZXBsaWNhdGVzDQoNCioqQSBjb21wcmVoZW5zaXZlIGNvbXBhcmlzb24gYW5kIGNvbnRyYXN0IHdpbGwgYmUgcHJlc2VudGVkIGluIENoYXB0ZXIgSUkgb2YgdGhpcyBhbmFseXNpcy4qKg0KDQojIyMjIENvdW50cyBGaWx0ZXJpbmcgIA0KDQpgYGB7cn0NCg0KIyMgRmlsdGVyIGNvdW50cy0tLS0tLS0tLS0tDQoNCiMgY3JlYXRlIGZpbHRlcmluZyBjcml0ZXJpYQ0KbXlnZV9maWx0ZXIgPC0gZWRnZVI6OmZpbHRlckJ5RXhwcihjb3VudHNfbXJuYSwgZ3JvdXA9Z3JvdXAsIG1pbi5jb3VudCA9IDEwLCBtaW4udG90YWwuY291bnQgPSAxNSkNCg0KIyBhcHBseSBmaWx0ZXIgaW4gY3JpdGVyaWENCmNvdW50c19tcm5hX2ZpbHQgPC0gY291bnRzX21ybmFbbXlnZV9maWx0ZXIsIF0NCiNWaWV3KGNvdW50c19tcm5hX2ZpbHQpDQoNCmRpbShjb3VudHNfbXJuYV9maWx0KSAjWzFdIDEyNDE3ICAgIDE0DQoNCmBgYA0KDQojIyMjIE5vcm1hbGlzZSB0aGUgZmlsdGVyZWQgY291bnRzICAgIA0KDQpXZSB3aWxsLCBub3JtYWxpc2Ugd2l0aCBlZGdlUiBUTU0gbWV0aG9kIGFuZCB0aGVuIGFwcGx5ICoqbGltbWEtVm9vbSoqIGluc3RlYWQgb2YgREVzZXEyLCAgDQoNCioqV2h5PyoqICAgICANCkJlY2F1c2Ugd2Ugd291bGQgbGlrZSBhIG1vcmUgYWNjdXJhdGUgREVHcyB3aXRoIHRoZSBsb3dlc3QgRmFsc2UgRGlzY292ZXJ5IFJhdGUgKEZEUikgcG9zc2libGUuDQoNCg0KYGBge3J9DQojIyBEYXRhIE5vcm1hbGl6YXRpb24gdXNpbmcgVE1NIA0KDQojIGNyZWF0ZSBhIERHRSBsaXN0DQoNCmRnZSA8LSBlZGdlUjo6REdFTGlzdChjb3VudHMgPSBjb3VudHNfbXJuYV9maWx0LCBncm91cD0gZ3JvdXApDQoNCmNvdW50c19tcm5hX25vcm0gPC0gY2FsY05vcm1GYWN0b3JzKGRnZSwgbWV0aG9kID0gIlRNTSIpDQoNCg0KYGBgDQoNCg0KRGVwdGggQ2hhcnQNCg0KDQpUdW1vciBXZWlnaHQgKFNhY3JpZmljZWQgc2FtZSBkYXkpDQoNCg0KDQojIyBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbiBBbmFseXNpcyAgDQoNCkZyb20gdGhlIERhdGFSYXcgZmlsZSwgSSB3YXMgYWJsZSB0byBleHRyYWN0IHRoZSBnZW5lIG1ldGFkYXRhLiBUaGVyZWZvcmUgdGhlcmUgd2FzIG5vIG5lZWQgdG8gbWFwIGFsbCBvdmVyIGFnYWluLiANCg0KV2Ugd2lsbCB1c2UgbGltbWEtdm9vbSB0byBleHRyYWN0IHRoZSBERUdzLiAgDQoNCg0KIyMjIyBWb29tIFRyYW5zZm9ybWF0aW9uIA0KDQoNCmBgYHtyfQ0KIyBjcmVhdGUgYSBkZXNpZ24gbWF0cml4IA0KZGVzaWduX21hdHJpeCA8LSBtb2RlbC5tYXRyaXgofmdyb3VwKSAjY2hvb3NpbmcgaW50ZXJjZXB0DQpjb2xuYW1lcyhkZXNpZ25fbWF0cml4KSANCg0KIyMgVm9vbSB0cmFuc2Zvcm1hdGlvbiANCnZvb21fdCA8LSB2b29tKGNvdW50c19tcm5hX25vcm0sIGRlc2lnbl9tYXRyaXgsIHBsb3QgPSBUUlVFKQ0KDQpgYGANCg0KDQojIyMjIExpbW1hIC0gTGluZWFyIE1vZGVsIGZpdHRpbmcNCg0KYGBge3J9DQojIyBsaW1tYSAobGluZWFyIG1vZGVsIGZpdHRpbmcpDQojP2xtRml0DQoNCiNjcmVhdGUgZml0IGRhdGENCmZpdCA8LSBsbUZpdCh2b29tX3QsIGRlc2lnbiA9ICBkZXNpZ25fbWF0cml4KQ0KDQojIFN0YXRpc3RpY2FsIHRlc3QgKGVCYXllcykNCmZpdF9lYmF5ZXMgPC0gZUJheWVzKGZpdCkNCg0KYGBgDQoNCg0KIyMjIyBPdXRwdXQgTWF0cml4IA0KDQpgYGB7cn0NCiNvdXRwdXQgbWF0cml4IHdpdGggZm9sZCBjaGFuZ2UgYW5kIGFkai5wLXZhbHVlPD0wLjA1ID0gZ2VuZSBleHByZXNzaW9uIHNpZ25pZmljYW50DQoNCiN0b3BUYWJsZSBmdW5jdGlvbiBpcyBwYXJ0IG9mIHRoZSBsaW1tYSBsaWJyYXJ5DQojV2Ugd2lsbCB1c2UgaXQgdG8gZXh0cmFjdCB0aGUgb3V0cHV0IG9yIHJlc3VsdCBtYXRyaXggDQoNCnJlc3VsdHMgPC0gdG9wVGFibGUoZml0X2ViYXllcywgY29lZiA9IG5jb2woZGVzaWduX21hdHJpeCksIG51bWJlciA9IEluZiwgYWRqdXN0Lm1ldGhvZCA9ICJCSCIpDQoNCiNBYm92ZSwgQmVuamFtaW5pLUhvY2hiZXJnIChCSCkgd2FzIGFwcGxpZWQgZm9yIEZEUiBjb3JyZWN0aW9uDQoNCmhlYWQocmVzdWx0cywgbj0xMCkNCg0KDQpgYGANCg0KDQojIyMjIFNpZ25pZmljYW50bHkgRXhwcmVzc2VkIEdlbmVzDQoNCkhvdyBtYW55IGdlbmVzIGFyZSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgaWYgd2UgZGVmaW5lIGEgdGhyZXNob2xkIG9mOiBhZGoucC12YWx1ZTw9MC4wNSBhbmQgfGxvZzIoRkNoKXw+MC41OCA/ICAgIFRoZXNlIHdpbGwgYmUgc2F2ZWQgYXMgKipzaWdHZW5lcyoqDQoNCkJvdGggU3RhdGlzdGljYWwgYW5kIEJpb2xvZ2ljYWwgcmVsZXZhbmNlLg0KDQoNCg0KYGBge3J9DQpzaWdHZW5lcyA8LSByZXN1bHRzW3Jlc3VsdHMkYWRqLlAuVmFsPD0wLjA1ICYgcmVzdWx0cyRsb2dGQz4wLjU4LCBdICNpdCBpcyB0aGUgcm93cyB0aGF0IHdlIGFyZSBmaWx0ZXJpbmcgYmFzZWQgb24gdGhlIGRlZmluZWQgY3JpdGVyaWEgYnV0IHdlIHdhbnQgYWxsIGNvbHVtbnMgdG8gY29tZSBiYWNrLg0KDQpkaW0oc2lnR2VuZXMpICMgWzFdIDExMDAxICAgICA2DQpgYGANCioqMTEwMDEgZ2VuZXMqKiBhcmUgc2lnbmlmaWNhbnRseSBleHByZXNzZWQuDQoNCg0KDQojIyBWSVNVQUxJWkFUSU9OIEkNCg0KIyMjIyBQcmluY2lwbGUgQ29tcG9uZW50IEFuYWx5c2lzIC0gUENBIA0KDQpgYGB7cn0NCnBjYSA8LSBwcmNvbXAodCh2b29tX3QkRSksIHNjYWxlLiA9IFRSVUUpDQpwY2FfZGF0YV90b19wbG90IDwtIGRhdGEuZnJhbWUoUEMxID0gcGNhJHhbLDFdLCBQQzIgPSBwY2EkeFssMl0sIGdyb3VwID0gZ3JvdXApDQoNCnBjYV9wbG90IDwtIGdncGxvdChwY2FfZGF0YV90b19wbG90LCBhZXMoeCA9IFBDMSwgeSA9IFBDMiwgY29sb3IgPSBncm91cCkpICsNCiAgZ2VvbV9wb2ludChzaXplPTQpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJQQ0EgLSBSTkEtc2VxIEFMTCBTYW1wbGVzIiwgeCA9ICJQQzEiLCB5ID0gIlBDMiIpKw0KICBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsPXJvd25hbWVzKHBjYV9kYXRhX3RvX3Bsb3QpKSkNCg0KI2dnc2F2ZSgiUENBX0FMTC5wbmciLCBwbG90ID0gcGNhX3Bsb3QpDQpwY2FfcGxvdA0KDQpgYGANCg0KKipPYnNlcnZhdGlvbjoqKiBUaGUgZ3JvdXBzIGFyZSBjbGVhcmx5IGRpc3RpbmN0IGFzIHNlZW4gYnkgdGhlIGh1Z2UgdmFyaWFuY2UgaW4gdGhlIFBDMSAobWFpbikgYXhpcy4gSG93ZXZlciwgdGhlIG5vIFJUICsgaW5kdWNpYmxlIElMMTIgZHVwbGljYXRlIHNhbXBsZXMgYXBwZWFyIHRvIGJlIHZlcnkgZGlzdGluY3QuIA0KDQoNCiMjIyMgQ2x1c3RlciBwbG90DQoNCg0KDQojIyMjIFZvbGNhbm8gUGxvdCANCg0KQmlvbG9naWNhbCByZWxldmFuY2UgdnMgU3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlLg0KDQpgYGB7cn0NCg0KIyMgVm9sY2FubyBQbG90DQoNCmdncGxvdChyZXN1bHRzLCBhZXMoeCA9IGxvZ0ZDLCB5ID0gLWxvZzEwKGFkai5QLlZhbCkpKSArIA0KICAjIEFsbCBnZW5lcyA9IEJMQUNLIChUaGVzZSBkb24ndCBjaGFuZ2UpDQogIGdlb21fcG9pbnQoY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKw0KICANCiAgI092ZXJleHByZXNzZWQgZ2VuZXMgPSBSRUQNCiAgZ2VvbV9wb2ludChkYXRhPXJlc3VsdHNbcmVzdWx0cyRsb2dGQyA+IDAuNTggJiByZXN1bHRzJGFkai5QLlZhbCA8PSAwLjA1LF0sIA0KICAgICAgICAgICAgIGFlcyh4ID0gbG9nRkMsIHkgPSAtbG9nMTAoYWRqLlAuVmFsKSksIGNvbG9yPSJyZWQiLCBhbHBoYSA9IDAuNykgKw0KICANCiAgI1VuZGVyIGV4cHJlc3NlZCBnZW5lcyA9IEJMVUUNCiAgZ2VvbV9wb2ludChkYXRhPXJlc3VsdHNbcmVzdWx0cyRsb2dGQyA8IC0wLjU4ICYgcmVzdWx0cyRhZGouUC5WYWwgPD0gMC4wNSxdLCANCiAgICAgICAgICAgICBhZXMoeCA9IGxvZ0ZDLCB5ID0gLWxvZzEwKGFkai5QLlZhbCkpLCBjb2xvcj0iYmx1ZSIsIGFscGhhID0gMC43KSArDQogIA0KICAjcmVmIGxpbmVzDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IC1sb2cxMCgwLjA1KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygwLjU4LCAtMC41OCksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyYXkiKSArDQogIA0KICB0aGVtZV9taW5pbWFsKCkgKyANCiAgDQogIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IC0gRGlmZmVyZW50aWFsIEV4cHJlc3Npb24iLA0KICAgICAgIHggPSAiTG9nMiBGb2xkIENoYW5nZSIsIA0KICAgICAgIHkgPSAiLUxvZzEwIFAtdmFsdWUiKQ0KDQoNCg0KYGBgDQoNCg0KDQojIyMjIERFR1MgSGVhdE1hcA0KDQpUb3AgMjAgREVHUyANCg0KYGBge3J9DQoNCiMgU2luY2Ugd2UgYWxyZWFkeSBWb29tIHRyYW5zZm9ybWVkIHRoZSBkYXRhLCB3ZSBjYW4geiB0cmFuc2Zvcm0gaXQgd2l0aG91dCByZW5vcm1hbGl6aW5nLg0KWl9zY29yZV92b29tIDwtIHQoc2NhbGUodCh2b29tX3QkRSksIGNlbnRlciA9IFRSVUUsIHNjYWxlID0gVFJVRSkpDQoNCiNPcmRlciBieSBGYyBmcm9tIEJpZyB0byBTbWFsbA0Kc2lnR2VuZXNfb3JkRmNoIDwtIHNpZ0dlbmVzW29yZGVyKHNpZ0dlbmVzJGxvZ0ZDLCBkZWNyZWFzaW5nID0gVFJVRSksXQ0KI1ZpZXcoc2lnR2VuZXNfb3JkRmNoKQ0KDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgQWRkaW5nIHRoZSBnZW5lIG1ldGFkYXRhIHRvIHRoZSBzaWdHZW5lc19vcmRGY2gNCg0Kcm93bmFtZXMoZ2VuZV9tZXRhZGF0YSkgPC0gZ2VuZV9tZXRhZGF0YSRnZW5lX2lkDQoNCnNpZ0dlbmVzX29yZEZjaF9tZXRhZGF0YSA8LSBnZW5lX21ldGFkYXRhW21hdGNoKHJvd25hbWVzKHNpZ0dlbmVzX29yZEZjaCksIGdlbmVfbWV0YWRhdGEkZ2VuZV9pZCksIGMoImdlbmVfdHlwZSIsICJnZW5lX25hbWUiKV0NCg0Kc2lnR2VuZXNfb3JkRmNoX2Fubm90YXRlZCAgPC0gY2JpbmQoc2lnR2VuZXNfb3JkRmNoLCBzaWdHZW5lc19vcmRGY2hfbWV0YWRhdGEpICNzdWNjZXNzDQojaGVhZChzaWdHZW5lc19vcmRGY2hfYW5ub3RhdGVkKQ0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCg0KdHJlYXRtZW50X2NvbG9ycyA8LSBjKA0KICAiUlRfaUx1YyIgPSAiI0VGNDc2RiIsICAgICAgICAgICAgDQogICJub19SVF9pSUwxMiIgPSAiI0ZGRDE2NiIsDQogICJub19SVF9ub19BQVYiPSAiIzA2RDZBMCIsIA0KICAiUlRfaUlMMTIiPSAiIzExOEFCMiIgDQopICAgDQoNCiMgQ29sdW1uIGFubm90YXRpb24NCmNvbHVtbl9oYSA8LSBIZWF0bWFwQW5ub3RhdGlvbigNCiAgVHJlYXRtZW50ID0gZ3JvdXAsICAjdHJlYXRtZW50IGdyb3VwDQogIGNvbCA9IGxpc3QoVHJlYXRtZW50ID0gdHJlYXRtZW50X2NvbG9ycykgICN0cmVhdG1lbnQgc3RhZ2UgY29sb3JpbmcNCikNCg0KDQojIGhlYXRtYXAgZm9yIHRvcCAyMCBERSBnZW5lcw0KSGVhdG1hcChaX3Njb3JlX3Zvb21bcm93bmFtZXMoc2lnR2VuZXNfb3JkRmNoKVsxOjIwXSxdLCANCiAgICAgICAgcm93X25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDUpLCAgICAgICAgDQogICAgICAgIHRvcF9hbm5vdGF0aW9uID0gY29sdW1uX2hhLCANCiAgICAgICAgcm93X25hbWVzX3NpZGUgPSAibGVmdCIsIA0KICAgICAgICByb3dfbGFiZWxzID0gc2lnR2VuZXNfb3JkRmNoX2Fubm90YXRlZCRnZW5lX25hbWVbMToyMF0NCikNCg0KYGBgDQoNCg0KIyMjIyBERUdzIFRhYmxlDQoNClRvcCAxMCBERUdzICAgDQoNCmBgYHtyfQ0KaGVhZChzaWdHZW5lc19vcmRGY2hfYW5ub3RhdGVkLCBuPTEwKQ0KI215Z2VuZXMgPC0gaGVhZChzaWdHZW5lc19vcmRGY2hfYW5ub3RhdGVkLCBuPTEwKQ0KI215Z2VuZXMkZ2VuZV9uYW1lDQpgYGANCg0KDQojIyBDSEFQVEVSIElJOiBDT05UUkFTVFMgDQoNCkluIHRoZSBwcmV2aW91cyBjaGFwdGVyLCBhIGdlbmVyYWwgYW5hbHlzaXMgb2YgdGhlIGdyb3VwcyBoYXMgYmVlbiBwZXJmb3JtZWQgKGNvbXBhcmVkIHRvIGJhc2VsaW5lIGdyb3VwKS4gSW4gdGhpcyBjaGFwdGVyLCB3ZSB3aWxsIGRlZmluZSBhbmQgZXhwbG9yZSBjaGFuZ2VzIGJldHdlZW4gZGlmZmVyZW50IGdyb3VwcyB3aXRoIGRlcHRoLiAgDQpHcm91cHMgb2YgaW50ZXJlc3Qgd2lsbCBiZSBjb21wYXJlZCBhZ2FpbnN0IGVhY2ggb3RoZXIuIA0KDQpGb3IgdGhpcywgd2Ugd2lsbCBoYXZlIHRvIGZpdCB0aGUgZGF0YSBhZ2Fpbiwgc3RhcnRpbmcgZnJvbSB0aGUgbm9ybWFsaXNhdGlvbiwgZGVzaWduIG1hdHJpeC4gRGVmaW5lIGNvbnRyYXN0IGFuZCB2aXN1YWxpc2UgdGhlIGNvbXBhcmlzb25zLg0KDQoNCg0KIyMjIyBSZWFuYWx5c2lzIChJbmRlcGVuZGVudCBDb21wYXJpc29ucykNCg0KRm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIGNvbXBhcmlzb24sIHdlIHdpbGwgbmFtZSB0aGUgZ3JvdXBzIGFzIGJlbG93DQoNCkNvbnRyb2wgPSBub19SVF9ub19BQVYgICAgICAgIA0KVHJlYXRBICA9IG5vX1JUX2lJTDEyICAgDQpUcmVhdEIgID0gUlRfaUx1YyAgDQpUcmVhdEMgID0gUlRfaUlMMTIgIA0KDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1UUlVFfQ0KIyMgZGVmaW5pbmcgZ3JvdXAgZm9yIG5ldyBhbmFseXNpcw0KZ3JvdXAyIDwtIGZhY3RvcihtZXRhZGF0YV9hbGwkZ3JvdXApDQpsZXZlbHMoZ3JvdXAyKQ0KDQoNCiMgbm9ybWFsaXNlIGRhdGEgDQpkZ2UyIDwtIGVkZ2VSOjpER0VMaXN0KGNvdW50cyA9IGNvdW50c19tcm5hX2ZpbHQsIGdyb3VwPSBncm91cDIpDQpjb3VudHNfbXJuYV9ub3JtMiA8LSBjYWxjTm9ybUZhY3RvcnMoZGdlMiwgbWV0aG9kID0gIlRNTSIpDQoNCg0KIyBjcmVhdGUgYSBkZXNpZ24gbWF0cml4IDIgDQpkZXNpZ25fbWF0cml4MiA8LSBtb2RlbC5tYXRyaXgofjAgKyBncm91cDIpICNubyBpbnRlcmNlcHQNCmNvbG5hbWVzKGRlc2lnbl9tYXRyaXgyKSA8LSBsZXZlbHMoZ3JvdXAyKSAjbm8gaW50ZXJjZXB0IGRlZmluZWQNCg0KDQojIERlZmluZSBjb250cmFzdHMgb2YgaW50ZXJlc3QNCmNvbnRyYXN0Lm1hdHJpeCA8LSBtYWtlQ29udHJhc3RzKA0KICBUcmVhdEFfdnNfQ29udHJvbCA9IG5vX1JUX2lJTDEyIC0gbm9fUlRfbm9fQUFWLCAjVW5pbmR1Y2VkIEFBVi1pSUwxMg0KICBUcmVhdEJfdnNfQ29udHJvbCA9IFJUX2lMdWMgLSBub19SVF9ub19BQVYsICNSVCBlZmZlY3RzDQogIFRyZWF0Q192c19UcmVhdEIgPSBSVF9pSUwxMiAtIFJUX2lMdWMsICNlZmZlY3RzIG9mIFJUICsgaW5kdWNlZCBpSUwxMiANCiAgbGV2ZWxzID0gY29sbmFtZXMoZGVzaWduX21hdHJpeDIpDQopDQoNCg0KIyMgVm9vbSB0cmFuc2Zvcm1hdGlvbiANCnZvb21fdDIgPC0gdm9vbShjb3VudHNfbXJuYV9ub3JtMiwgZGVzaWduX21hdHJpeDIpDQoNCg0KIyMgbGltbWEgKGxpbmVhciBtb2RlbCBmaXR0aW5nKQ0KZml0MiA8LSBsbUZpdCh2b29tX3QyLCBkZXNpZ24gPSAgZGVzaWduX21hdHJpeDIpDQpmaXQyYyA8LSBjb250cmFzdHMuZml0KGZpdDIsIGNvbnRyYXN0Lm1hdHJpeCkNCg0KIyBTdGF0aXN0aWNhbCB0ZXN0IChlQmF5ZXMpDQpmaXRfZWJheWVzMiA8LSBlQmF5ZXMoZml0MmMpDQoNCg0KIyNSRVNVTFRTIGNvbnRyYXN0cw0KDQpyZXN1bHRzX1RyZWF0QV92c19Db250cm9sIDwtIHRvcFRhYmxlKGZpdF9lYmF5ZXMyLCBjb2VmID0gIlRyZWF0QV92c19Db250cm9sIiwgbiA9IEluZiwgYWRqdXN0Lm1ldGhvZCA9ICJCSCIpDQoNCnJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wgPC0gdG9wVGFibGUoZml0X2ViYXllczIsIGNvZWYgPSAiVHJlYXRCX3ZzX0NvbnRyb2wiLCBuID0gSW5mLCBhZGp1c3QubWV0aG9kID0gIkJIIikNCg0KcmVzdWx0c19UcmVhdENfdnNfVHJlYXRCIDwtIHRvcFRhYmxlKGZpdF9lYmF5ZXMyLCBjb2VmID0gIlRyZWF0Q192c19UcmVhdEIiLCBuID0gSW5mLCBhZGp1c3QubWV0aG9kID0gIkJIIikNCg0KYGBgDQoNCg0KDQojIyMjIENvbnRyYXN0DQoNClBhaXJ3aXNlIENvbXBhcmlzb24gb2YgZ3JvdXBzICBmb3JleGFtcGxlICpObyBSYWRpYXRpb24sTm8gQUF2KiB2cyAqTm8gUmFkaWF0aW9uICsgSUwxMiogdG8gZGV0ZXJtaW5lIHRoZSBjaGFuZ2VzIGNhdXNlZCBieSBhbiBpbnVuZHVjZWQgQUFWLUlMMTIuDQoNCg0KLSBWb2xjYW5vIHBsb3RzIGZvciBhbGwgY29tcGFyaXNvbiBzZXRzIHdpdGggbGFiZWxlZCBnZW5lcy4NCi0gSGVhdG1hcHMgZm9yIGFsbCBjb21wYXJpc29ucyBzZXRzLg0KLSBIaXN0b2dyYW1zIGZvciBpbXBvcnRhbnQgZ2VuZXMgaW4gYSBjb21wYXJpc29uIHNldC4NCg0KDQojIyMjIFZvbGNhbm8gUGxvdHMgIA0KDQpWb2xjYW5vIFBsb3QgLS0tLS0tLSBub19SVF9pSUwxMiB2cyAgbm9fUlRfbm9fQUFWIChDb250cm9sKQ0KDQpgYGB7cn0NCiMjIFZvbGNhbm8gUGxvdCAtLS0tLS0tIG5vX1JUX2lJTDEyIHZzICBub19SVF9ub19BQVYgKENvbnRyb2wpDQoNCiNMQUJFTFMgb2YgdG9wIGdlbmVzDQpyZXN1bHRzX1RyZWF0QV92c19Db250cm9sJGdlbmVfbmFtZSA8LWdlbmVfbWV0YWRhdGFbbWF0Y2gocm93bmFtZXMocmVzdWx0c19UcmVhdEFfdnNfQ29udHJvbCksIGdlbmVfbWV0YWRhdGEkZ2VuZV9pZCksIGMoImdlbmVfbmFtZSIpXQ0KDQojIFNlbGVjdCB0b3AgZ2VuZXMgYnkgcC12YWx1ZSBhbmQgZm9sZCBjaGFuZ2UgDQp0b3BfZ2VuZXNfQXZzQ3RyIDwtIHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkZ2VuZV9uYW1lWw0KICAocmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbCRsb2dGQyA+IDEuNSB8IHJlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkbG9nRkMgPCAtMS41KSAmIA0KICAgIHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkYWRqLlAuVmFsIDwgMC4wMQ0KXQ0KDQojc3Vic2V0IG9mIGdlbmVzIHRvIGxhYmVsDQpsYWJlbF9kYXRhX0F2c0N0ciA8LSByZXN1bHRzX1RyZWF0QV92c19Db250cm9sW3Jlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkZ2VuZV9uYW1lICVpbiUgdG9wX2dlbmVzX0F2c0N0ciwgXQ0KDQoNCiMgUExPVCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQp2b2xjYW5vX0F2c0N0ciA8LSBnZ3Bsb3QocmVzdWx0c19UcmVhdEFfdnNfQ29udHJvbCwgYWVzKHggPSBsb2dGQywgeSA9IC1sb2cxMChhZGouUC5WYWwpKSkgKyANCiAgIyBBbGwgZ2VuZXMgPSBCTEFDSyAoVGhlc2UgZG9uJ3QgY2hhbmdlKQ0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsNCiAgDQogICNPdmVyZXhwcmVzc2VkIGdlbmVzID0gUkVEDQogIGdlb21fcG9pbnQoZGF0YT1yZXN1bHRzX1RyZWF0QV92c19Db250cm9sW3Jlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkbG9nRkMgPiAwLjU4ICYgcmVzdWx0c19UcmVhdEFfdnNfQ29udHJvbCRhZGouUC5WYWwgPD0gMC4wNSxdLCANCiAgICAgICAgICAgICBhZXMoeCA9IGxvZ0ZDLCB5ID0gLWxvZzEwKGFkai5QLlZhbCkpLCBjb2xvcj0icmVkIiwgYWxwaGEgPSAwLjcpICsNCiAgDQogICNVbmRlciBleHByZXNzZWQgZ2VuZXMgPSBCTFVFDQogIGdlb21fcG9pbnQoZGF0YT1yZXN1bHRzX1RyZWF0QV92c19Db250cm9sW3Jlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkbG9nRkMgPCAtMC41OCAmIHJlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkYWRqLlAuVmFsIDw9IDAuMDUsXSwgDQogICAgICAgICAgICAgYWVzKHggPSBsb2dGQywgeSA9IC1sb2cxMChhZGouUC5WYWwpKSwgY29sb3I9ImJsdWUiLCBhbHBoYSA9IDAuNykgKw0KICANCiAgI3JlZiBsaW5lcw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAtbG9nMTAoMC4wNSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsdWUiKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoMC41OCwgLTAuNTgpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5IikgKw0KICANCiAgdGhlbWVfbWluaW1hbCgpICsgDQogIA0KICBsYWJzKHRpdGxlID0gIm5vX1JUX2lJTDEyIHZzICBub19SVF9ub19BQVYiLA0KICAgICAgIHggPSAibG9nRkMiLCANCiAgICAgICB5ID0gIi1sb2cxMChhZGouUC5WYWwpIikrDQogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gbGFiZWxfZGF0YV9BdnNDdHIsIGFlcyhsYWJlbD10b3BfZ2VuZXNfQXZzQ3RyKSkNCg0KI2dnc2F2ZSgidm9sY2Fub19BdnNDdHIucG5nIiwgcGxvdCA9IHZvbGNhbm9fQXZzQ3RyKQ0KDQp2b2xjYW5vX0F2c0N0cg0KYGBgDQoNCg0KDQpWb2xjYW5vIFBsb3QgLS0tLS0tLSBSVF9pTHVjIHZzICBub19SVF9ub19BQVYgKENvbnRyb2wpDQoNCmBgYHtyfQ0KIyMgVm9sY2FubyBQbG90IC0tLS0tLS0gUlRfaUx1YyB2cyAgbm9fUlRfbm9fQUFWIChDb250cm9sKQ0KDQojTEFCRUxTIG9mIHRvcCBnZW5lcw0KcmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbCRnZW5lX25hbWUgPC1nZW5lX21ldGFkYXRhW21hdGNoKHJvd25hbWVzKHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wpLCBnZW5lX21ldGFkYXRhJGdlbmVfaWQpLCBjKCJnZW5lX25hbWUiKV0NCg0KIyBTZWxlY3QgdG9wIGdlbmVzIGJ5IHAtdmFsdWUgYW5kIGZvbGQgY2hhbmdlIA0KdG9wX2dlbmVzIDwtIHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkZ2VuZV9uYW1lWw0KICAocmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbCRsb2dGQyA+IDEuNSB8IHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkbG9nRkMgPCAtMS41KSAmIA0KICAgIHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkYWRqLlAuVmFsIDwgMC4wMQ0KXQ0KDQojc3Vic2V0IG9mIGdlbmVzIHRvIGxhYmVsDQpsYWJlbF9kYXRhX0J2c0N0ciA8LSByZXN1bHRzX1RyZWF0Ql92c19Db250cm9sW3Jlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkZ2VuZV9uYW1lICVpbiUgdG9wX2dlbmVzLCBdDQoNCiMgUExPVCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0Kdm9sY2Fub19CdnNDdHIgPC0gZ2dwbG90KHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wsIGFlcyh4ID0gbG9nRkMsIHkgPSAtbG9nMTAoYWRqLlAuVmFsKSkpICsgDQogICMgQWxsIGdlbmVzID0gQkxBQ0sgKFRoZXNlIGRvbid0IGNoYW5nZSkNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArDQogIA0KICAjT3ZlcmV4cHJlc3NlZCBnZW5lcyA9IFJFRA0KICBnZW9tX3BvaW50KGRhdGE9cmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbFtyZXN1bHRzX1RyZWF0Ql92c19Db250cm9sJGxvZ0ZDID4gMC41OCAmIHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkYWRqLlAuVmFsIDw9IDAuMDUsXSwgDQogICAgICAgICAgICAgYWVzKHggPSBsb2dGQywgeSA9IC1sb2cxMChhZGouUC5WYWwpKSwgY29sb3I9InJlZCIsIGFscGhhID0gMC43KSArDQogIA0KICAjVW5kZXIgZXhwcmVzc2VkIGdlbmVzID0gQkxVRQ0KICBnZW9tX3BvaW50KGRhdGE9cmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbFtyZXN1bHRzX1RyZWF0Ql92c19Db250cm9sJGxvZ0ZDIDwgLTAuNTggJiByZXN1bHRzX1RyZWF0Ql92c19Db250cm9sJGFkai5QLlZhbCA8PSAwLjA1LF0sIA0KICAgICAgICAgICAgIGFlcyh4ID0gbG9nRkMsIHkgPSAtbG9nMTAoYWRqLlAuVmFsKSksIGNvbG9yPSJibHVlIiwgYWxwaGEgPSAwLjcpICsNCiAgDQogICNyZWYgbGluZXMNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibHVlIikgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDAuNTgsIC0wLjU4KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JheSIpICsNCiAgDQogIHRoZW1lX21pbmltYWwoKSArIA0KICANCiAgbGFicyh0aXRsZSA9ICJSVF9pTHVjIHZzICBub19SVF9ub19BQVYiLA0KICAgICAgIHggPSAibG9nRkMiLCANCiAgICAgICB5ID0gIi1sb2cxMChhZGouUC5WYWwpIikrDQogIGdlb21fdGV4dF9yZXBlbChkYXRhPSBsYWJlbF9kYXRhX0J2c0N0ciwgYWVzKGxhYmVsPXRvcF9nZW5lcykpDQoNCiNnZ3NhdmUoInZvbGNhbm9fQnZzQ3RyLnBuZyIsIHBsb3QgPSB2b2xjYW5vX0J2c0N0cikNCg0Kdm9sY2Fub19CdnNDdHINCmBgYA0KDQoNClZvbGNhbm8gUGxvdCAtLS0tLS0tIFJUX2lMdWMgdnMgIFJUX2lJTDEyDQoNCmBgYHtyfQ0KIyMgVm9sY2FubyBQbG90IC0tLS0tLS0gUlRfaUx1YyB2cyAgUlRfaUlMMTINCg0KI0xBQkVMUyBvZiB0b3AgZ2VuZXMNCnJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QiRnZW5lX25hbWUgPC1nZW5lX21ldGFkYXRhW21hdGNoKHJvd25hbWVzKHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QiksIGdlbmVfbWV0YWRhdGEkZ2VuZV9pZCksIGMoImdlbmVfbmFtZSIpXQ0KDQojIFNlbGVjdCB0b3AgZ2VuZXMgYnkgYWRqdXN0ZWQgcC12YWx1ZSBhbmQgZm9sZCBjaGFuZ2UgDQp0b3BfZ2VuZXNfQ3ZzQiA8LSByZXN1bHRzX1RyZWF0Q192c19UcmVhdEIkZ2VuZV9uYW1lWw0KICAocmVzdWx0c19UcmVhdENfdnNfVHJlYXRCJGxvZ0ZDID4gMS41IHwgcmVzdWx0c19UcmVhdENfdnNfVHJlYXRCJGxvZ0ZDIDwgLTEuNSkgJiANCiAgICByZXN1bHRzX1RyZWF0Q192c19UcmVhdEIkYWRqLlAuVmFsIDwgMC4wMQ0KXQ0KDQojc3Vic2V0IG9mIGdlbmVzIHRvIGxhYmVsDQpsYWJlbF9kYXRhX0N2c0IgPC0gcmVzdWx0c19UcmVhdENfdnNfVHJlYXRCW3Jlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QiRnZW5lX25hbWUgJWluJSB0b3BfZ2VuZXNfQ3ZzQiwgXQ0KDQoNCiMgUExPVCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQp2b2xjYW5vX0N2c0IgPC0gZ2dwbG90KHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QiwgYWVzKHggPSBsb2dGQywgeSA9IC1sb2cxMChhZGouUC5WYWwpKSkgKyANCiAgIyBBbGwgZ2VuZXMgPSBCTEFDSyAoVGhlc2UgZG9uJ3QgY2hhbmdlKQ0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsNCiAgDQogICNPdmVyZXhwcmVzc2VkIGdlbmVzID0gUkVEDQogIGdlb21fcG9pbnQoZGF0YT1yZXN1bHRzX1RyZWF0Q192c19UcmVhdEJbcmVzdWx0c19UcmVhdENfdnNfVHJlYXRCJGxvZ0ZDID4gMC41OCAmIHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QiRhZGouUC5WYWwgPD0gMC4wNSxdLCANCiAgICAgICAgICAgICBhZXMoeCA9IGxvZ0ZDLCB5ID0gLWxvZzEwKGFkai5QLlZhbCkpLCBjb2xvcj0icmVkIiwgYWxwaGEgPSAwLjcpICsNCiAgDQogICNVbmRlciBleHByZXNzZWQgZ2VuZXMgPSBCTFVFDQogIGdlb21fcG9pbnQoZGF0YT1yZXN1bHRzX1RyZWF0Q192c19UcmVhdEJbcmVzdWx0c19UcmVhdENfdnNfVHJlYXRCJGxvZ0ZDIDwgLTAuNTggJiByZXN1bHRzX1RyZWF0Q192c19UcmVhdEIkYWRqLlAuVmFsIDw9IDAuMDUsXSwgDQogICAgICAgICAgICAgYWVzKHggPSBsb2dGQywgeSA9IC1sb2cxMChhZGouUC5WYWwpKSwgY29sb3I9ImJsdWUiLCBhbHBoYSA9IDAuNykgKw0KICANCiAgI3JlZiBsaW5lcw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAtbG9nMTAoMC4wNSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsdWUiKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoMC41OCwgLTAuNTgpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5IikgKw0KICANCiAgdGhlbWVfbWluaW1hbCgpICsgDQogIA0KICBsYWJzKHRpdGxlID0gIlJUX2lMdWMgdnMgIFJUX2lJTDEyIiwNCiAgICAgICB4ID0gImxvZ0ZDIiwgDQogICAgICAgeSA9ICItbG9nMTAoYWRqLlAuVmFsKSIpKw0KICBnZW9tX3RleHRfcmVwZWwoZGF0YT0gbGFiZWxfZGF0YV9DdnNCLCBhZXMobGFiZWw9dG9wX2dlbmVzX0N2c0IpKQ0KDQojZ2dzYXZlKCJ2b2xjYW5vX0N2c0IucG5nIiwgcGxvdCA9IHZvbGNhbm9fQ3ZzQikNCg0Kdm9sY2Fub19DdnNCDQoNCmBgYA0KDQoNCg0KDQojIyMjIEhlYXRtYXBzIGZvciBTaWcgZ2VuZXMNCg0KIyMjIyBTaWduaWZpY2FudCBVUFJFR1VMQVRFRCBHZW5lcyBmb3IgQ29udHJhc3RzLg0KDQpgYGB7cn0NCg0KIyMgU2lnbmlmaWNhbnQgVVBSRUdVTEFURUQgR2VuZXMgZm9yIENvbnRyYXN0cy0tLS0tLQ0KDQpzaWdHZW5lc19BdnNDdHJfVVAgPC0gcmVzdWx0c19UcmVhdEFfdnNfQ29udHJvbFtyZXN1bHRzX1RyZWF0QV92c19Db250cm9sJGFkai5QLlZhbDw9MC4wNSAmIHJlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkbG9nRkM+MC41OCwgXQ0KDQpzaWdHZW5lc19CdnNDdHJfVVAgPC0gcmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbFtyZXN1bHRzX1RyZWF0Ql92c19Db250cm9sJGFkai5QLlZhbDw9MC4wNSAmIHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkbG9nRkM+MC41OCwgXQ0KDQpzaWdHZW5lc19DdnNCX1VQIDwtIHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QltyZXN1bHRzX1RyZWF0Q192c19UcmVhdEIkYWRqLlAuVmFsPD0wLjA1ICYgcmVzdWx0c19UcmVhdENfdnNfVHJlYXRCJGxvZ0ZDPjAuNTgsIF0NCg0KDQpgYGANCg0KDQoNCiMjIyMgU2lnbmlmaWNhbnQgRE9XTlJFR1VMQVRFRCBHZW5lcyBmb3IgQ29udHJhc3RzLg0KDQpgYGB7cn0NCg0KIyMgU2lnbmlmaWNhbnQgRE9XTlJFR1VMQVRFRCBHZW5lcyBmb3IgQ29udHJhc3RzLS0tLS0tDQoNCnNpZ0dlbmVzX0F2c0N0cl9EVyA8LSByZXN1bHRzX1RyZWF0QV92c19Db250cm9sW3Jlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkYWRqLlAuVmFsPD0wLjA1ICYgcmVzdWx0c19UcmVhdEFfdnNfQ29udHJvbCRsb2dGQzwgLTAuNTgsIF0NCg0Kc2lnR2VuZXNfQnZzQ3RyX0RXIDwtIHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2xbcmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbCRhZGouUC5WYWw8PTAuMDUgJiByZXN1bHRzX1RyZWF0Ql92c19Db250cm9sJGxvZ0ZDPCAtMC41OCwgXQ0KDQpzaWdHZW5lc19DdnNCX0RXIDwtIHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QltyZXN1bHRzX1RyZWF0Q192c19UcmVhdEIkYWRqLlAuVmFsPD0wLjA1ICYgcmVzdWx0c19UcmVhdENfdnNfVHJlYXRCJGxvZ0ZDPCAtMC41OCwgXQ0KDQoNCmBgYA0KDQoNCg0KKipSVF9pTHVjIHZzIFJUX0lMMTIgSGVhdG1hcCoqDQoNCg0KDQojIyMjIFZlbm4gZGlhZ3JhbSANCg0KDQoNCiMjIFBBVEhXQVkgQU5BTFlTSVMgIA0KDQpQYXRod2F5IGFuYWx5c2lzIGluIGNvbnRyYXN0cy4gDQoNCk5vdyB0aGF0IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBoYXZlIGJlZW4gaWRlbnRpZmllZCwgd2Ugd2lsbCBhbmFseXNlIGVucmljaGVkIHBhdGh3YXlzIGluIG91ciBkYXRhIGdyb3Vwcy4gVGhpcyB3aWxsIGhlbHAgdXMgbWFrZSBiaW9sb2dpY2FsIG1lYW5pbmcgb2YgdGhlIGFjdHVhbCBjaGFuZ2VzIGhhcHBlbmluZyBpbiBvdXIgZGF0YS4NCg0KRm9yZSBlYWNoIG9mIHRoZXNlIGFuYWx5c2lzIG9ubHkgY29kZSBmb3Igb25lIHdpbGwgYmUgc2hvd24gYW5kIGp1c3QgcmVzdWx0cyBmb3IgdGhlIHJlc3QuDQoNCiMjIyMgRGF0YSBQcmVwIGZvciBwYXRod2F5IGFuYWx5c2lzLg0KDQpPdXIgZGF0YSBoYXMgKipFbnNlbWJsIElkcyoqIGFuZCBPUkEgR28gaW5wdXQgcmVxdWlyZXMgKiplbnRyZXogSWRzKiogDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KGJpb21hUnQpDQoNCiMgQ29ubmVjdCB0byB0aGUgRW5zZW1ibCBtb3VzZSBkYXRhYmFzZQ0KZW5zZW1ibCA8LSB1c2VFbnNlbWJsKGJpb21hcnQgPSAiZ2VuZXMiLCBkYXRhc2V0ID0gIm1tdXNjdWx1c19nZW5lX2Vuc2VtYmwiKQ0KDQojIElEcyB0byBjb252ZXJ0DQplbnNlbWJsX2lkcyA8LSByb3duYW1lcyhnZW5lX21ldGFkYXRhKQ0KDQojIFJlbW92ZSB2ZXJzaW9uIG51bWJlcnMgKHRoZSBwYXJ0IGFmdGVyIHRoZSBkb3QpDQplbnNlbWJsX2lkc19ub192ZXJzaW9uIDwtIHN1YigiXFwuWzAtOV0rJCIsICIiLCBlbnNlbWJsX2lkcykgIy0tLSBzdWJzdGl0dXRlKCJ0aGVzZSIsICJ3aXRoIHRoaXMiLCBpbikNCg0KIyBHZXQgdGhlIG1hcHBpbmcgYmV0d2VlbiBFbnNlbWJsIGFuZCBFbnRyZXogSURzDQplbnRyZXpfaWRfbWFwcGluZyA8LSBnZXRCTSgNCiAgYXR0cmlidXRlcyA9IGMoImVuc2VtYmxfZ2VuZV9pZCIsICJlbnRyZXpnZW5lX2lkIiwgImV4dGVybmFsX2dlbmVfbmFtZSIpLA0KICBmaWx0ZXJzID0gImVuc2VtYmxfZ2VuZV9pZCIsDQogIHZhbHVlcyA9IGVuc2VtYmxfaWRzX25vX3ZlcnNpb24sDQogIG1hcnQgPSBlbnNlbWJsDQopDQoNCiMgVmlldyByZXN1bHRzDQojcHJpbnQoZW50cmV6X2lkX21hcHBpbmcpDQoNCg0KDQpgYGANCg0KDQojIyMjIE9SQSBHTyBBbmFseXNpcyANCg0KKipub19SVF9pSUwxMiB2cyAgbm9fUlRfbm9fQUFWIChDb250cm9sKSoqDQoNCmBgYHtyIGV2YWw9RkFMU0UsIGVjaG89RkFMU0V9DQoNCiMgIE92ZXIgUmVwcmVzZW50YXRpb24gQW5hbHlzaXMgKE9SQSkNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBEZWZpbmUgdGhlIHNldCBvZiBnZW5lcyB0byB0ZXN0DQoNCiMgbm9fUlRfaUlMMTIgdnMgIG5vX1JUX25vX0FBViAoQ29udHJvbCkNCiNzaWdHZW5lc19BdnNDdHJfVVANCg0KIyBXZSBhcmUgZ29pbmcgdG8gYXNzZXNzIHRoZSB1cC1yZWd1bGF0ZWQgZ2VuZXMNCg0KIyBEZWZpbmUgdGhlIHJhbmtlZCBnZW5lcyBsaXN0IGJhc2VkIG9uIGxvZ0ZDaC4NCg0Kc2lnR2VuZXNfQXZzQ3RyX1VQIDwtICBzaWdHZW5lc19BdnNDdHJfVVBbb3JkZXIoc2lnR2VuZXNfQXZzQ3RyX1VQJGxvZ0ZDICwgZGVjcmVhc2luZyA9IFRSVUUpLCBdDQojVmlldyhzaWdHZW5lc19BdnNDdHJfVVApDQoNCiMgS2VlcCB0aGUgVVAtcmVndWxhdGVkIGdlbmVzDQp1cF9yZWd1bGF0ZWRfZ2VuZXMgPC0gcm93bmFtZXMoc2lnR2VuZXNfQXZzQ3RyX1VQKQ0KDQp1cF9yZWd1bGF0ZWRfZ2VuZXMgPC0gc3ViKCJcXC5bMC05XSskIiwgIiIsIGVuc2VtYmxfaWRzKSAjcmVtb3ZlcyB2ZXJzaW9uIGNvbXBvbmVudHMgKGV2ZXJ5dGhpbmcgYWZ0ZXIgZG90KSAtLS0gc3Vic3RpdHV0ZSgidGhlc2UiLCAid2l0aCB0aGlzIiwgaW4pDQoNCmJhY2tncm91bmRfZ2VuZXNfQUN0ciA8LSByb3duYW1lcyhyZXN1bHRzX1RyZWF0QV92c19Db250cm9sKQ0KYmFja2dyb3VuZF9nZW5lc19BQ3RyIDwtc3ViKCJcXC5bMC05XSskIiwgIiIsIGJhY2tncm91bmRfZ2VuZXNfQUN0cikgIA0KICANCiMgUGVyZm9ybSB0aGUgT1JBIGJhc2VkIG9uIEdPIHRlcm1zDQoNCiMgR08gb3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcw0KDQojdW5pdmVyc2UgPSBiYWNrZ3JvdW5kIGdlbmVzLi4uIGNoZWNrIGlmIGkgaGF2ZSB1c2VkIHRoZSBjb3JyZWN0IGJhY2tncm91bmQNCm9yYV9nb191cCA8LSBlbnJpY2hHTyhnZW5lICAgICAgICAgID0gdXBfcmVndWxhdGVkX2dlbmVzLA0KICAgICAgICAgICAgICAgICAgICAgIHVuaXZlcnNlICAgICAgPSBiYWNrZ3JvdW5kX2dlbmVzX0FDdHIsIA0KICAgICAgICAgICAgICAgICAgICAgIE9yZ0RiICAgICAgICAgPSBvcmcuTW0uZWcuZGIsDQogICAgICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJFTlNFTUJMIiwNCiAgICAgICAgICAgICAgICAgICAgICBvbnQgICAgICAgICAgID0gIkJQIiwNCiAgICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwNCiAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgID0gMC4wMSwNCiAgICAgICAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgID0gMC4wNSwNCiAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZSAgICAgID0gVFJVRSkNCg0KI29yYV9nb191cA0KVmlldyhvcmFfZ29fdXBAcmVzdWx0KQ0KDQojIFJlc3VsdHMgdmlzdWFsaXphdGlvbg0KDQpsYXlvdXQobWF0cml4KGMoMSwgMiwgMyksIG5yb3cgPSAxLCBuY29sID0gMywgYnlyb3cgPSBUUlVFKSkNCg0KIyBCYXJwbG90DQpiYXJwbG90KG9yYV9nb191cCwgc2hvd0NhdGVnb3J5PTEwLCB0aXRsZSA9Ik9SQSBHT19VUDogbm9fUlRfaUlMMTIgIHZzICBub19SVF9ub19BQVYgKENvbnRyb2wpIikgDQoNCiMgTmV0d29yaw0KY25ldHBsb3Qob3JhX2dvX3VwLCBub2RlX2xhYmVsPSJjYXRlZ29yeSIsIA0KICAgICAgICAgICAgICAgY2V4LnBhcmFtcyA9IGxpc3QoY2V4X2xhYmVsX2NhdGVnb3J5ID0gMS4yKSkNCg0KY25ldHBsb3Qob3JhX2dvX3VwLCBub2RlX2xhYmVsPSJnZW5lIiwgDQogICAgICAgICAgICAgICBjZXgucGFyYW1zID0gbGlzdChjZXhfbGFiZWxfY2F0ZWdvcnkgPSAxLjIpKQ0KDQpgYGANCg0KDQoNCg0KIyMjIyBHU0VBICAtIEdlbmUgU2V0IEVucmljaG1tZW50IEFuYWx5c2lzDQoNCiANCioqbm8uUlRfaUwxMiB2cyBuby5SVF9uby5BQVYqKg0KDQpgYGB7ciBldmFsPVRSVUUsZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQ0KDQojIG5vLlJUX2lMMTIgdnMgbm8uUlRfbm8uQUFWDQoNCiMgRGVmaW5lIHRoZSByYW5rZWQgZ2VuZXMgbGlzdCBiYXNlZCBvbiBsb2dGQ2guDQoNCkF2c0N0cmxfZ2VuZUxpc3QgPC0gcmVzdWx0c19UcmVhdEFfdnNfQ29udHJvbCRsb2dGQw0KDQoNCm5hbWVzKEF2c0N0cmxfZ2VuZUxpc3QpIDwtIHN1YigiXFwuWzAtOV0rJCIsICIiLCByb3duYW1lcyhyZXN1bHRzX1RyZWF0QV92c19Db250cm9sKSkgI3JlbW92ZXMgdmVyc2lvbiBjb21wb25lbnRzIChldmVyeXRoaW5nIGFmdGVyIGRvdCkgLS0tIHN1YnN0aXR1dGUoInRoZXNlIiwgIndpdGggdGhpcyIsIGluKQ0KDQpBdnNDdHJsX2dlbmVMaXN0X3JhbmtlZCA8LSBBdnNDdHJsX2dlbmVMaXN0W29yZGVyKEF2c0N0cmxfZ2VuZUxpc3QsIGRlY3JlYXNpbmcgPSBUUlVFKV0NCg0KIyBQZXJmb3JtIHRoZSBHU0VBIGJhc2VkIG9uIEdPIHRlcm1zDQoNCmdzZWFfZ28gPC0gZ3NlR08oZ2VuZUxpc3QgICAgID0gQXZzQ3RybF9nZW5lTGlzdF9yYW5rZWQsDQogICAgICAgICAgICAgIE9yZ0RiICAgICAgICA9IG9yZy5NbS5lZy5kYiwNCiAgICAgICAgICAgICAga2V5VHlwZSA9ICJFTlNFTUJMIiwNCiAgICAgICAgICAgICAgb250ICAgICAgICAgID0gIkJQIiwNCiAgICAgICAgICAgICAgbWluR1NTaXplICAgID0gMTAwLA0KICAgICAgICAgICAgICBtYXhHU1NpemUgICAgPSA1MDAsDQogICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDEsDQogICAgICAgICAgICAgIHZlcmJvc2UgICAgICA9IEZBTFNFKQ0KDQpWaWV3KGdzZWFfZ29AcmVzdWx0KQ0KDQojIFJlc3VsdHMgdmlzdWFsaXphdGlvbg0KDQpsYXlvdXQobWF0cml4KGMoMSwgMiwgMyksIG5yb3cgPSAxLCBuY29sID0gMywgYnlyb3cgPSBUUlVFKSkNCg0KIyBEb3RwbG90DQpkb3RwbG90KGdzZWFfZ28sIA0KICAgICAgICB4ID0gIkdlbmVSYXRpbyIsDQogICAgICAgIGNvbG9yID0gIk5FUyIsDQogICAgICAgIHNpemUgPSAicC5hZGp1c3QiLA0KICAgICAgICBzaG93Q2F0ZWdvcnk9MTApICsgZ2d0aXRsZSgiR1NFQTogbm8uUlRfQUFWLmlMMTIgdnMgbm8uUlRfbm8uQUFWIikNCg0KI05ldHdvcmsgUGxvdA0KY25ldHBsb3QoZ3NlYV9nbywgbm9kZV9sYWJlbD0iY2F0ZWdvcnkiLCANCiAgICAgICAgICAgICAgIGNleC5wYXJhbXMgPSBsaXN0KGNleF9sYWJlbF9jYXRlZ29yeSA9IDEuMiksDQogICAgICAgICAgICAgICBjYXRlZ29yeVNpemU9InAuYWRqdXN0IiwgY29sb3IucGFyYW1zID0gbGlzdChmb2xkQ2hhbmdlID0gQXZzQ3RybF9nZW5lTGlzdF9yYW5rZWQpKQ0KDQojIFRyZWVwbG90DQpnc2VhX2dvMiA8LSBwYWlyd2lzZV90ZXJtc2ltKGdzZWFfZ28pDQoNCnRyZWVwbG90KGdzZWFfZ28yLCBzaG93Q2F0ZWdvcnkgPSAxMCkNCg0KYGBgDQoqKlJUX2lMdWMgdnMgbm8uUlRfbm8uQUFWKioNCmBgYHtyIGV2YWw9VFJVRSxlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0UsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9DQoNCiMgUlRfaUx1YyB2cyBuby5SVF9uby5BQVYNCg0KIyBEZWZpbmUgdGhlIHJhbmtlZCBnZW5lcyBsaXN0IGJhc2VkIG9uIGxvZ0ZDaC4NCg0KQnZzQ3RybF9nZW5lTGlzdCA8LSByZXN1bHRzX1RyZWF0Ql92c19Db250cm9sJGxvZ0ZDDQoNCg0KbmFtZXMoQnZzQ3RybF9nZW5lTGlzdCkgPC0gc3ViKCJcXC5bMC05XSskIiwgIiIsIHJvd25hbWVzKHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wpKSAjcmVtb3ZlcyB2ZXJzaW9uIGNvbXBvbmVudHMgKGV2ZXJ5dGhpbmcgYWZ0ZXIgZG90KSAtLS0gc3Vic3RpdHV0ZSgidGhlc2UiLCAid2l0aCB0aGlzIiwgaW4pDQoNCkJ2c0N0cmxfZ2VuZUxpc3RfcmFua2VkIDwtIEJ2c0N0cmxfZ2VuZUxpc3Rbb3JkZXIoQnZzQ3RybF9nZW5lTGlzdCwgZGVjcmVhc2luZyA9IFRSVUUpXQ0KDQojIFBlcmZvcm0gdGhlIEdTRUEgYmFzZWQgb24gR08gdGVybXMNCg0KZ3NlYV9nbyA8LSBnc2VHTyhnZW5lTGlzdCAgICAgPSBCdnNDdHJsX2dlbmVMaXN0X3JhbmtlZCwNCiAgICAgICAgICAgICAgT3JnRGIgICAgICAgID0gb3JnLk1tLmVnLmRiLA0KICAgICAgICAgICAgICBrZXlUeXBlID0gIkVOU0VNQkwiLA0KICAgICAgICAgICAgICBvbnQgICAgICAgICAgPSAiQlAiLA0KICAgICAgICAgICAgICBtaW5HU1NpemUgICAgPSAxMDAsDQogICAgICAgICAgICAgIG1heEdTU2l6ZSAgICA9IDUwMCwNCiAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wMSwNCiAgICAgICAgICAgICAgcEFkanVzdE1ldGhvZCA9ICJCSCIsDQogICAgICAgICAgICAgIHZlcmJvc2UgICAgICA9IEZBTFNFKQ0KDQojVmlldyhnc2VhX2dvQHJlc3VsdCkNCg0KIyBSZXN1bHRzIHZpc3VhbGl6YXRpb24NCg0KbGF5b3V0KG1hdHJpeChjKDEsIDIsIDMpLCBucm93ID0gMSwgbmNvbCA9IDMsIGJ5cm93ID0gVFJVRSkpDQoNCiMgRG90cGxvdA0KZG90cGxvdChnc2VhX2dvLCANCiAgICAgICAgeCA9ICJHZW5lUmF0aW8iLA0KICAgICAgICBjb2xvciA9ICJORVMiLA0KICAgICAgICBzaXplID0gInAuYWRqdXN0IiwNCiAgICAgICAgc2hvd0NhdGVnb3J5PTE1KSt0aGVtZV9taW5pbWFsKCkgKyBnZ3RpdGxlKCJHU0VBOiBSVF9BQVYuaUx1YyB2cyBuby5SVF9uby5BQVYiKSArIA0KICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3c9InJlZCIsIGhpZ2g9ImJsdWUiLCANCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLCBtYXgoZ3NlYV9nb0ByZXN1bHQkTkVTKSkpDQoNCg0KI05ldHdvcmsgUGxvdA0KY25ldHBsb3QoZ3NlYV9nbywgbm9kZV9sYWJlbD0iY2F0ZWdvcnkiLA0KICAgICAgICAgICAgICAgY2V4LnBhcmFtcyA9IGxpc3QoY2V4X2xhYmVsX2NhdGVnb3J5ID0gMS4yKSwNCiAgICAgICAgICAgICAgIGNhdGVnb3J5U2l6ZT0icC5hZGp1c3QiLCBjb2xvci5wYXJhbXMgPSBsaXN0KGZvbGRDaGFuZ2UgPSBCdnNDdHJsX2dlbmVMaXN0X3JhbmtlZCkpDQoNCiMgVHJlZXBsb3QNCmdzZWFfZ28yIDwtIHBhaXJ3aXNlX3Rlcm1zaW0oZ3NlYV9nbykNCnRyZWVwbG90KGdzZWFfZ28yLCBzaG93Q2F0ZWdvcnkgPSAxMCkNCg0KYGBgDQoNCioqR1NFQTogUlQuQUFWX2lMdWMgdnMgUlRfQUFWLmlJTDEyKioNCg0KYGBge3IgZXZhbD1UUlVFLGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0NCg0KIyBSVC5BQVZfaUx1YyB2cyBSVF9BQVYuaUlMMTINCg0KIyBEZWZpbmUgdGhlIHJhbmtlZCBnZW5lcyBsaXN0IGJhc2VkIG9uIGxvZ0ZDaC4NCg0KQ3ZzQl9nZW5lTGlzdCA8LSByZXN1bHRzX1RyZWF0Q192c19UcmVhdEIkbG9nRkMNCg0KbmFtZXMoQ3ZzQl9nZW5lTGlzdCkgPC0gc3ViKCJcXC5bMC05XSskIiwgIiIsIHJvd25hbWVzKHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QikpICNyZW1vdmVzIHZlcnNpb24gY29tcG9uZW50cyAoZXZlcnl0aGluZyBhZnRlciBkb3QpIC0tLSBzdWJzdGl0dXRlKCJ0aGVzZSIsICJ3aXRoIHRoaXMiLCBpbikNCg0KQ3ZzQl9nZW5lTGlzdF9yYW5rZWQgPC0gQ3ZzQl9nZW5lTGlzdFtvcmRlcihDdnNCX2dlbmVMaXN0LCBkZWNyZWFzaW5nID0gVFJVRSldDQoNCiMgUGVyZm9ybSB0aGUgR1NFQSBiYXNlZCBvbiBHTyB0ZXJtcw0KDQpnc2VhX2dvIDwtIGdzZUdPKGdlbmVMaXN0ICAgICA9IEN2c0JfZ2VuZUxpc3RfcmFua2VkLA0KICAgICAgICAgICAgICBPcmdEYiAgICAgICAgPSBvcmcuTW0uZWcuZGIsDQogICAgICAgICAgICAgIGtleVR5cGUgPSAiRU5TRU1CTCIsDQogICAgICAgICAgICAgIG9udCAgICAgICAgICA9ICJCUCIsDQogICAgICAgICAgICAgIG1pbkdTU2l6ZSAgICA9IDEwMCwNCiAgICAgICAgICAgICAgbWF4R1NTaXplICAgID0gNTAwLA0KICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjAxLA0KICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwNCiAgICAgICAgICAgICAgdmVyYm9zZSAgICAgID0gRkFMU0UpDQoNCiNWaWV3KGdzZWFfZ29AcmVzdWx0KQ0KDQojIFJlc3VsdHMgdmlzdWFsaXphdGlvbg0KDQpsYXlvdXQobWF0cml4KGMoMSwgMiwgMyksIG5yb3cgPSAxLCBuY29sID0gMywgYnlyb3cgPSBUUlVFKSkNCg0KIyBEb3RwbG90DQpkb3RwbG90KGdzZWFfZ28sIA0KICAgICAgICB4ID0gIkdlbmVSYXRpbyIsDQogICAgICAgIGNvbG9yID0gIk5FUyIsDQogICAgICAgIHNpemUgPSAicC5hZGp1c3QiLA0KICAgICAgICBzaG93Q2F0ZWdvcnk9MTApKyB0aGVtZV9taW5pbWFsKCkgKyBnZ3RpdGxlKCJHU0VBOiBSVC5BQVZfaUx1YyB2cyBSVF9BQVYuaUlMMTIiKQ0KDQojTmV0d29yayBQbG90DQpjbmV0cGxvdChnc2VhX2dvLCBub2RlX2xhYmVsPSJjYXRlZ29yeSIsIA0KICAgICAgICAgICAgICAgY2V4LnBhcmFtcyA9IGxpc3QoY2V4X2xhYmVsX2NhdGVnb3J5ID0gMS4yKSwNCiAgICAgICAgICAgICAgIGNhdGVnb3J5U2l6ZT0icC5hZGp1c3QiLCBjb2xvci5wYXJhbXMgPSBsaXN0KGZvbGRDaGFuZ2UgPSBCdnNDdHJsX2dlbmVMaXN0X3JhbmtlZCkpDQoNCiMgVHJlZXBsb3QNCmdzZWFfZ28yIDwtIHBhaXJ3aXNlX3Rlcm1zaW0oZ3NlYV9nbykNCg0KdHJlZXBsb3QoZ3NlYV9nbzIsIHNob3dDYXRlZ29yeSA9IDEwKQ0KDQpgYGANCg0KDQojIyBTRUxFQ1RFRCBHRU5FUyANCg0KIyMjIyBQb3NzaWJsZSBUYXJnZXRzIA0KDQpUaGUgZm9sbG93aW5nIGFyZSBzaWduaWZpY2FudCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgd2l0aCBhIGFkanVzdGVkIFAgdmFsdWUgPCAwLjAxIGFjY29yZGluZyB0byB0aGUgY29udHJhc3RzLiBIb3dldmVyLCBpbiB0aGUgZ3JhcGhpY3MgYmVsb3csIHRoZSBleHByZXNzaW9uIG9mIHRoZXNlIGdlbmVzIGluIGVhY2ggaW5kZXBlbmRlbnQgZ3JvdXAgd2lsbCBiZSBwbG90dGVkIHRvIHNlZSBob3cgdGhleSBjaGFuZ2VkIGFuZCBpbiB3aGljaCBkaXJlY3Rpb24uIA0KDQpGb3IgdGhpcyB3ZSB3aWxsIHVzZSB0aGUgY29udHJhc3RzIHRvIG9idGFpbiBnZW5lIGlkcyBhbmQgdGhlbiBwbG90IHRoZW0gdXNpbmcgdGhlaXIgbm9ybWFsaXplZCBleHByZXNzaW9uIGRhdGEgKHZvb20kRSkgZm9yIGVhY2ggZ3JvdXAuIFRoaXMgbm9ybWFsaXplZCBleHByZXNzaW9uIGRhdGEgaXMgaW5kZXBlbmRlbnQgZXhwcmVzc2lvbiBmb3IgZWFjaCBnZW5lIGluIGVhY2ggZ3JvdXAsIG5vdCBsaW5rZWQgdG8gYW55IGNvbXBhcmlzb24uDQoNCioqVG9wIDQwIHNpZyBleHByZXNzaW9uIGluOiBub19SVF9pSUwxMiB2cyBub19SVF9ub19BQVYqKg0KDQpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NiAsZXZhbD1UUlVFLCBlY2hvPVRSVUV9DQojIyMqKioqKiogR0VORVMgcGxvdCANCg0KIyBUcmVhdEEgdnMgQ3RyIC0gbW9zdCBzaWduaWZpY2FudCBnZW5lcyAoYWRqLnAudmFsPCAwLjAxKSBhbmQgc2lnbmlmaWNhbnQgRkMNCg0KIyBUb3AgNDAgc2lnIGV4cHJlc3Npb24gaW46IG5vX1JUX2lJTDEyIHZzIG5vX1JUX25vX0FBVg0KDQp0b3BTaWdfQXZzQ3RyIDwtIHJlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2xbKHJlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkbG9nRkMgPiAxLjUgfCByZXN1bHRzX1RyZWF0QV92c19Db250cm9sJGxvZ0ZDIDwgLTEuNSAmIHJlc3VsdHNfVHJlYXRBX3ZzX0NvbnRyb2wkYWRqLlAuVmFsIDwgMC4wMSksIF0NCg0KI1RoZXNlIGFyZSBhcnJhbmdlZCBmcm9tIHRoZSBtb3N0IGRpZmZlcmVudCBpbiBlYWNoIGdyb3VwIHRoZXJlZm9yZSBJIHdpbGwgbm90IHJlYXJyYW5nZSB0aGVtIGFjY29yZGluZyB0byBmb2xkIGNoYW5nZSBvciBwIHZhbHVlLiANCg0KI0J5IGFkai5QLlZhbA0KdG9wU2lnX0F2c0N0ciA8LSB0b3BTaWdfQXZzQ3RyW29yZGVyKHRvcFNpZ19BdnNDdHIkYWRqLlAuVmFsLCBkZWNyZWFzaW5nID0gRkFMU0UpLCBdDQoNCiNCeSBGb2xkQ2hhbmdlDQojdG9wU2lnX0F2c0N0cl9vcmRGY2ggPC0gdG9wU2lnX0F2c0N0cltvcmRlcih0b3BTaWdfQXZzQ3RyJGxvZ0ZDLCBkZWNyZWFzaW5nID0gVFJVRSksIF0NCg0KI1Bsb3QgdG9wIDQwIG9mIGVhY2ggaW5zdGFuY2UgaW4gYm90aCBncm91cHMgYmVpbmcgY29tcGFyZWQNCmlkc190b19wbG90X0F2c0N0ciA8LSBoZWFkKHRvcFNpZ19BdnNDdHIsIG49NDApDQogDQojIyBFeHByZXNzaW9uIGRhdGEgdG8gcGxvdCBhbGwgZ3JvdXBzLS0tLS0gY291bGQgY2hhbmdlIHRvIHB2YWwNCmV4cHJfZGF0YV90b19wbG90X0F2c0N0ciA8LSBhcy5kYXRhLmZyYW1lKHQodm9vbV90JEVbcm93bmFtZXMoaWRzX3RvX3Bsb3RfQXZzQ3RyKSwgXSkpICANCmNvbG5hbWVzKGV4cHJfZGF0YV90b19wbG90X0F2c0N0cikgPC0gaWRzX3RvX3Bsb3RfQXZzQ3RyJGdlbmVfbmFtZQ0KZXhwcl9kYXRhX3RvX3Bsb3RfQXZzQ3RyJGdyb3VwIDwtIG1ldGFkYXRhX2FsbCRncm91cA0KDQojT25seSBzZWxlY3QgZm9yICoqbm9fUlRfbm9fQUFWKiogYW5kICoqbm9fUlRfaUlMMTIqKioNCiNJIHVzZWQgdGhlIHJvd25hbWVzIGluc3RlYWQgb2YgZ3JvdXAgbmFtZXMgYmVjYXVzZSB0aGUgZ3JvdXAgbmFtZSBvbmx5IHNlbGVjdGVkIDIgc2FtcGxlcyBvZiBlYWNoIGdyb3VwDQpleHByX2RhdGFfdG9fcGxvdF9BdnNDdHIgPC0gZXhwcl9kYXRhX3RvX3Bsb3RfQXZzQ3RyW3Jvd25hbWVzKGV4cHJfZGF0YV90b19wbG90X0F2c0N0cik9PWMoICJBX1M3IiwiQl9TOCIsIkNfUzkiLCAiTl9TMjAiLCAiT19TMjEiLCAiUF9TMjIiLCAiUV9TMjMiKSwgXQ0KDQojIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0DQpleHByX2RhdGFfdG9fcGxvdF9BdnNDdHIgPC0gZXhwcl9kYXRhX3RvX3Bsb3RfQXZzQ3RyICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IC1ncm91cCwgbmFtZXNfdG8gPSAiZ2VuZSIsIHZhbHVlc190byA9ICJleHByZXNzaW9uIikNCg0KDQojIyBQbG90IHRvcFNpZ19BdnNDdHJfb3JkRmNoDQoNCmdncGxvdChkYXRhID0gZXhwcl9kYXRhX3RvX3Bsb3RfQXZzQ3RyLCBtYXBwaW5nPWFlcyh4PWdlbmUsIHk9ZXhwcmVzc2lvbiwgZmlsbCA9IGdyb3VwKSkgKw0KICBnZW9tX2JveHBsb3QoY29sb3I9IiNlOWVjZWYiLCBhbHBoYT0wLjYsIHBvc2l0aW9uID0gJ2lkZW50aXR5JykrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJub19SVF9pSUwxMiIgPSIjNjliM2EyIiwgIm5vX1JUX25vX0FBViIgPSIjNDA0MDgwIikpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmx1ZSIpICsgDQogIGdndGl0bGUoIlRvcCA0MCBzaWcgZXhwcmVzc2lvbiBpbjogbm9fUlRfaUlMMTIgdnMgbm9fUlRfbm9fQUFWIikrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsaGp1c3Q9MSkpIA0KDQoNCg0KYGBgDQoNCioqKlRvcCA0MCBzaWcgZXhwcmVzc2lvbiBpbjogUlRfQUFWLmlMdWMgJiBub19SVF9ub19BQVYqKioNCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02ICxldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIFRvcCA0MCBzaWcgZXhwcmVzc2lvbiBpbjogUlRfQUFWLmlMdWMgJiBub19SVF9ub19BQVYNCiMgbW9zdCBzaWdpZmljYW50IGdlbmVzIChhZGoucC52YWw8IDAuMDEpIGFuZCBoaWdoZXN0IEZDDQoNCnRvcFNpZ19CdnNDdHIgPC0gcmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbFsocmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbCRsb2dGQyA+IDEuNSB8IHJlc3VsdHNfVHJlYXRCX3ZzX0NvbnRyb2wkbG9nRkMgPCAtMS41ICYgcmVzdWx0c19UcmVhdEJfdnNfQ29udHJvbCRhZGouUC5WYWwgPCAwLjAxKSwgXQ0KDQoNCiNUaGVzZSBhcmUgYXJyYW5nZWQgYnkgYnkgYWRqLlAuVmFsDQp0b3BTaWdfQnZzQ3RyIDwtIHRvcFNpZ19CdnNDdHJbb3JkZXIodG9wU2lnX0J2c0N0ciRhZGouUC5WYWwsIGRlY3JlYXNpbmcgPSBGQUxTRSksIF0NCg0KDQojUGxvdCB0b3AgNDAgb2YgZWFjaCBpbnN0YW5jZSBpbiBib3RoIGdyb3VwcyBiZWluZyBjb21wYXJlZA0KDQppZHNfdG9fcGxvdF9CdnNDdHIgPC0gaGVhZCh0b3BTaWdfQnZzQ3RyLCBuPTQwKQ0KI1RoZXNlIGFyZSBhcnJhbmdlZCBmcm9tIHRoZSBtb3N0IGRpZmZlcmVudCBpbiBlYWNoIGdyb3VwIHRoZXJlZm9yZSBJIHdpbGwgbm90IHJlYXJyYW5nZSB0aGVtIGFjY29yZGluZyB0byBmb2xkIGNoYW5nZSBvciBwIHZhbHVlLiANCiAgDQojIyBFeHByZXNzaW9uIGRhdGEgdG8gcGxvdCBhbGwgZ3JvdXBzLS0tLS0gY291bGQgY2hhbmdlIHRvIHB2YWwNCmV4cHJfZGF0YV90b19wbG90X0J2c0N0ciA8LSBhcy5kYXRhLmZyYW1lKHQodm9vbV90JEVbcm93bmFtZXMoaWRzX3RvX3Bsb3RfQnZzQ3RyKSwgXSkpICANCmNvbG5hbWVzKGV4cHJfZGF0YV90b19wbG90X0J2c0N0cikgPC0gaWRzX3RvX3Bsb3RfQnZzQ3RyJGdlbmVfbmFtZQ0KZXhwcl9kYXRhX3RvX3Bsb3RfQnZzQ3RyJGdyb3VwIDwtIG1ldGFkYXRhX2FsbCRncm91cA0KDQojT25seSBzZWxlY3QgZm9yICoqUlRfQUFWLmlMdWMqKiBhbmQgKipub19SVF9pSUwxMioqKg0KI0kgdXNlZCB0aGUgcm93bmFtZXMgaW5zdGVhZCBvZiBncm91cCBuYW1lcyBiZWNhdXNlIHRoZSBncm91cCBuYW1lIG9ubHkgc2VsZWN0ZWQgMiBzYW1wbGVzIG9mIGVhY2ggZ3JvdXANCiNyb3duYW1lcyhleHByX2RhdGFfdG9fcGxvdF9CdnNDdHIpDQoNCmV4cHJfZGF0YV90b19wbG90X0J2c0N0ciA8LSBleHByX2RhdGFfdG9fcGxvdF9CdnNDdHJbZXhwcl9kYXRhX3RvX3Bsb3RfQnZzQ3RyJGdyb3VwPT1jKCAiUlRfaUx1YyIsICAibm9fUlRfbm9fQUFWIiksIF0NCg0KDQojIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0DQpleHByX2RhdGFfdG9fcGxvdF9CdnNDdHIgPC0gZXhwcl9kYXRhX3RvX3Bsb3RfQnZzQ3RyICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IC1ncm91cCwgbmFtZXNfdG8gPSAiZ2VuZSIsIHZhbHVlc190byA9ICJleHByZXNzaW9uIikNCg0KDQojIyBQbG90IHRvcFNpZ19CdnNDdHINCg0KZ2dwbG90KGRhdGEgPSBleHByX2RhdGFfdG9fcGxvdF9CdnNDdHIsIG1hcHBpbmc9YWVzKHg9Z2VuZSwgeT1leHByZXNzaW9uLCBmaWxsID0gZ3JvdXApKSArDQogIGdlb21fYm94cGxvdChjb2xvcj0iI2U5ZWNlZiIsIGFscGhhPTAuNiwgcG9zaXRpb24gPSAnaWRlbnRpdHknKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIlJUX2lMdWMiID0iI0VDODU3RiIsICJub19SVF9ub19BQVYiID0iIzQwNDA4MCIpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsdWUiKSArIA0KICBnZ3RpdGxlKCJUb3AgNDAgc2lnIGV4cHJlc3Npb24gaW46IFJUX0FBVi5pTHVjICYgbm9fUlRfbm9fQUFWIikrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsaGp1c3Q9MSkpIA0KDQoNCg0KYGBgDQoNCg0KKioqUlRfaUx1YyB2cyBSVF9pSUwxMiBUb3AgNDAgU2lnIGdlbmVzKioqDQoNCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02ICxldmFsPVRSVUUsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIFJUX2lMdWMgdnMgUlRfaUlMMTIgLSBtb3N0IHNpZ2lmaWNhbnQgZ2VuZXMgKGFkai5wLnZhbDwgMC4wMSkgYW5kIGhpZ2hlc3QgRkMNCg0KdG9wU2lnX0N2c0N0ciA8LSByZXN1bHRzX1RyZWF0Q192c19UcmVhdEJbKHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QiRsb2dGQyA+IDEuNSB8IHJlc3VsdHNfVHJlYXRDX3ZzX1RyZWF0QiRsb2dGQyA8IC0xLjUgJiByZXN1bHRzX1RyZWF0Q192c19UcmVhdEIkYWRqLlAuVmFsIDwgMC4wMSksIF0NCg0KDQojVGhlc2UgYXJlIGFycmFuZ2VkIGJ5IGJ5IGFkai5QLlZhbA0KdG9wU2lnX0N2c0N0ciA8LSB0b3BTaWdfQ3ZzQ3RyW29yZGVyKHRvcFNpZ19DdnNDdHIkYWRqLlAuVmFsLCBkZWNyZWFzaW5nID0gRkFMU0UpLCBdDQoNCg0KI1Bsb3QgdG9wIDQwIG9mIGVhY2ggaW5zdGFuY2UgaW4gYm90aCBncm91cHMgYmVpbmcgY29tcGFyZWQNCg0KaWRzX3RvX3Bsb3RfQ3ZzQiA8LSBoZWFkKHRvcFNpZ19DdnNDdHIsIG49NDApDQojVGhlc2UgYXJlIGFycmFuZ2VkIGZyb20gdGhlIG1vc3QgZGlmZmVyZW50IGluIGVhY2ggZ3JvdXAgdGhlcmVmb3JlIEkgd2lsbCBub3QgcmVhcnJhbmdlIHRoZW0gYWNjb3JkaW5nIHRvIGZvbGQgY2hhbmdlIG9yIHAgdmFsdWUuIA0KICANCiMjIEV4cHJlc3Npb24gZGF0YSB0byBwbG90IGFsbCBncm91cHMtLS0tLSBjb3VsZCBjaGFuZ2UgdG8gcHZhbA0KZXhwcl9kYXRhX3RvX3Bsb3RfQ3ZzQiA8LSBhcy5kYXRhLmZyYW1lKHQodm9vbV90JEVbcm93bmFtZXMoaWRzX3RvX3Bsb3RfQ3ZzQiksIF0pKSAgDQpjb2xuYW1lcyhleHByX2RhdGFfdG9fcGxvdF9DdnNCKSA8LSBpZHNfdG9fcGxvdF9DdnNCJGdlbmVfbmFtZQ0KZXhwcl9kYXRhX3RvX3Bsb3RfQ3ZzQiRncm91cCA8LSBtZXRhZGF0YV9hbGwkZ3JvdXANCg0KI09ubHkgc2VsZWN0IGZvciAqKlJUX0FBVi5pTHVjKiogYW5kICoqbm9fUlRfaUlMMTIqKioNCiNJIHVzZWQgdGhlIHJvd25hbWVzIGluc3RlYWQgb2YgZ3JvdXAgbmFtZXMgYmVjYXVzZSB0aGUgZ3JvdXAgbmFtZSBvbmx5IHNlbGVjdGVkIDIgc2FtcGxlcyBvZiBlYWNoIGdyb3VwDQojcm93bmFtZXMoZXhwcl9kYXRhX3RvX3Bsb3RfQnZzQ3RyKQ0KDQpleHByX2RhdGFfdG9fcGxvdF9DdnNCIDwtIGV4cHJfZGF0YV90b19wbG90X0N2c0JbZXhwcl9kYXRhX3RvX3Bsb3RfQ3ZzQiRncm91cD09YyggIlJUX2lMdWMiLCAgIlJUX2lJTDEyIiksIF0NCg0KDQojIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0DQpleHByX2RhdGFfdG9fcGxvdF9DdnNCIDwtIGV4cHJfZGF0YV90b19wbG90X0N2c0IgJT4lDQogIHBpdm90X2xvbmdlcihjb2xzID0gLWdyb3VwLCBuYW1lc190byA9ICJnZW5lIiwgdmFsdWVzX3RvID0gImV4cHJlc3Npb24iKQ0KDQoNCiMjIFBsb3QNCg0KZ2dwbG90KGRhdGEgPSBleHByX2RhdGFfdG9fcGxvdF9DdnNCLCBtYXBwaW5nPWFlcyh4PWdlbmUsIHk9ZXhwcmVzc2lvbiwgZmlsbCA9IGdyb3VwKSkgKw0KICBnZW9tX2JveHBsb3QoY29sb3I9IiNlOWVjZWYiLCBhbHBoYT0wLjYsIHBvc2l0aW9uID0gJ2lkZW50aXR5JykrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJSVF9pTHVjIiA9IiNFQzg1N0YiLCAiUlRfaUlMMTIiID0iZ3JlZW4iKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibHVlIikgKyANCiAgZ2d0aXRsZSgiVG9wIDQwIHNpZyBleHByZXNzaW9uIGluOiBSVF9BQVYuaUx1YyAmIFJUX0FBVi5pSUwxMiIpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLGhqdXN0PTEpKSANCg0KYGBgDQoNCg0KIyMjIyBNdWx0aXBsZSBQbG90cyANCg0KYGBge3IgZXZhbD1GQUxTRSwgZWNobz1GQUxTRX0NCg0KIyMjKioqKioqKioqKioqKioqKioqKioqDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCg0KI2xpc3Qgb2YgZ2VuZXMNCnNvbV9tdXRfaWRzIDwtIGdlbmVfbWFwcGluZ19tZXRhZGF0YV9DT01QTEVURSRSb3cubmFtZXNbZ2VuZV9tYXBwaW5nX21ldGFkYXRhX0NPTVBMRVRFJGhnbmNfc3ltYm9sICVpbiUgYygiQVNYTDEiLCAiUlVOWDEiLCAiU0YzQjEiLCAiU1JTRjIiLCAiVEVUMiIsICJUUDUzIildDQoNCnNvbV9tdXRfZGF0YV90b19wbG90IDwtIGFzLmRhdGEuZnJhbWUodChkZHMuZmlsdC5kZWFfbm9ybVtzb21fbXV0X2lkcywgXSkpDQoNCiMgQ3JlYXRlZCBuYW1lZCB2ZWN0b3IsIGlkX3RvX3N5bWJvbCwgIEVuc2VtYmwgSURzIGFzIG5hbWVzLCBHZW5lIFN5bWJvbHMgYXMgdmFsdWVzDQppZF90b19zeW1ib2wgPC0gYygNCiAgIkVOU0cwMDAwMDE3MTQ1NiIgPSAiQVNYTDEiLA0KICAiRU5TRzAwMDAwMTU5MjE2IiA9ICJSVU5YMSIsDQogICJFTlNHMDAwMDAxMTU1MjQiID0gIlNGM0IxIiwNCiAgIkVOU0cwMDAwMDE2MTU0NyIgPSAiU1JTRjIiLA0KICAiRU5TRzAwMDAwMTY4NzY5IiA9ICJURVQyIiwNCiAgIkVOU0cwMDAwMDE0MTUxMCIgPSAiVFA1MyINCikNCg0KIyBSZXBsYWNlIGNvbHVtbiBuYW1lcyB1c2luZyB0aGUgbmFtZWQgdmVjdG9yDQpjb2xuYW1lcyhzb21fbXV0X2RhdGFfdG9fcGxvdCkgPC0gaWRfdG9fc3ltYm9sW2NvbG5hbWVzKHNvbV9tdXRfZGF0YV90b19wbG90KV0NCg0KIyBhZGQgc2FtcGxlIGdyb3VwcyBjb2x1bW4NCnNvbV9tdXRfZGF0YV90b19wbG90JGdyb3VwPC0gc2FtcGxlX21ldGFkYXRhWyxjKCJncm91cCIpXQ0KDQojIFBMT1RTIA0KIyBDb252ZXJ0IGZyb20gd2lkZSB0byBsb25nIGZvcm1hdA0Kc29tX211dF9kYXRhX3RvX3Bsb3RfbG9uZyA8LSBzb21fbXV0X2RhdGFfdG9fcGxvdCAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtZ3JvdXAsIG5hbWVzX3RvID0gImdlbmUiLCB2YWx1ZXNfdG8gPSAiZXhwcmVzc2lvbiIpDQoNCiNWaWV3KHNvbV9tdXRfZGF0YV90b19wbG90X2xvbmcpDQoNCiMgR2VuZXJhdGUgaW5kaXZpZHVhbCBwbG90cyBmb3IgZWFjaCBnZW5lDQpwbG90cyA8LSBsYXBwbHkodW5pcXVlKHNvbV9tdXRfZGF0YV90b19wbG90X2xvbmckZ2VuZSksIGZ1bmN0aW9uKGcpIHsNCiAgZ2dwbG90KHNvbV9tdXRfZGF0YV90b19wbG90X2xvbmcgJT4lIGZpbHRlcihnZW5lID09IGcpLCBhZXMoeCA9IGdyb3VwLCB5ID0gZXhwcmVzc2lvbiwgZmlsbCA9IGdyb3VwKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICBnZ3RpdGxlKGcpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gIDEpKQ0KfSkNCg0KIyBBcnJhbmdlIHBsb3RzIGluIGEgZ3JpZA0KZ3JpZC5hcnJhbmdlKGdyb2JzID0gcGxvdHMsIG5jb2wgPSAzKQ0KDQpgYGANCg0KDQojIyBDb25jbHVzaW9uIA0KDQojIyBSRUZFUkVOQ0VTICANCiMjIyMgQXJ0aWNsZXMgICANCg0KKipJZGkgZ2VuZXMqKg0KDQoqWnVuaWdhLCBPLiwgQnlydW0sIFMuLCAmIFdvbGZlLCBBLiBSLiAoMjAyMikuIERpc2NvdmVyeSBvZiB0aGUgaW5oaWJpdG9yIG9mIEROQSBiaW5kaW5nIDEgYXMgYSBub3ZlbCBtYXJrZXIgZm9yIHJhZGlvcmVzaXN0YW5jZSBpbiBwYW5jcmVhdGljIGNhbmNlciB1c2luZyBnZW5vbWUtd2lkZSBSTkEtc2VxLiBDYW5jZXIgZHJ1ZyByZXNpc3RhbmNlIChBbGhhbWJyYSwgQ2FsaWYuKSwgNSg0KSwgOTI24oCTOTM4LiBodHRwczovL2RvaS5vcmcvMTAuMjA1MTcvY2RyLjIwMjIuNjAqDQoNCiMjIyMgU2Vzc2lvbiBJbmZvICANCmBgYHtyfQ0Kc2Vzc2lvbkluZm8oKQ0KYGBgDQoNCg0KDQo=