1. load libraries
2. Load Seurat Object
load ("/home/bioinfo/0-imp_Robj/Harmony_integrated_All_samples_Merged_with_PBMC10x_with_harmony_clustering.Robj")
2. Initial Visualization
All_samples_Merged <- SetIdent(All_samples_Merged, value = "Harmony_snn_res.0.9")
DimPlot(All_samples_Merged,group.by = "cell_line",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T)

DimPlot(All_samples_Merged,
group.by = "Harmony_snn_res.0.9",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T)

DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T)

3. Perform DE analysis using the FindMarkers
All_samples_Merged <- SetIdent(All_samples_Merged, value = "Harmony_snn_res.0.9")
Patient_cell_lines_vs_PBMC_Tcells <- FindMarkers(All_samples_Merged,
ident.1 = c("3", "8", "10", "18", "1", "2", "13", "6", "16", "19", "4", "7", "9"),
ident.2 = c("0", "5", "14", "24", "20")
)
# Convert to data frame and add gene names as a new column
Patient_cell_lines_vs_PBMC_Tcells <- as.data.frame(Patient_cell_lines_vs_PBMC_Tcells)
Patient_cell_lines_vs_PBMC_Tcells$gene <- rownames(Patient_cell_lines_vs_PBMC_Tcells)
# Rearranging the columns for better readability (optional)
Patient_cell_lines_vs_PBMC_Tcells <- Patient_cell_lines_vs_PBMC_Tcells[, c("gene", "p_val", "avg_log2FC", "pct.1", "pct.2", "p_val_adj")]
#write.csv(Patient_cell_lines_vs_PBMC_Tcells, "Patient_cell_lines_vs_PBMC_Tcells.csv", row.names = FALSE)
Warning messages:
1: ggrepel: 25 unlabeled data points (too many overlaps). Consider increasing max.overlaps
2: ggrepel: 25 unlabeled data points (too many overlaps). Consider increasing max.overlaps
3: ggrepel: 15 unlabeled data points (too many overlaps). Consider increasing max.overlaps
4: ggrepel: 13 unlabeled data points (too many overlaps). Consider increasing max.overlaps
5: ggrepel: 8 unlabeled data points (too many overlaps). Consider increasing max.overlaps
6: ggrepel: 7 unlabeled data points (too many overlaps). Consider increasing max.overlaps
7: ggrepel: 7 unlabeled data points (too many overlaps). Consider increasing max.overlaps
EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells ,
lab=rownames(Patient_cell_lines_vs_PBMC_Tcells),
x ="avg_log2FC",
y ="p_val_adj",
title = "Sézary Cell Lines vs PBMC T cells",
pCutoff = 0.05,
FCcutoff = 1.5,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = TRUE,
pointSize = 3.0,
labSize = 5.0,
drawConnectors = TRUE,
widthConnectors = 0.25)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells,
lab = ifelse((Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5 | Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5) &
Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05,
rownames(Patient_cell_lines_vs_PBMC_Tcells),
""), # Label only significant genes
x = "avg_log2FC",
y = "p_val_adj",
title = "Sézary Cell Lines vs PBMC T cells",
pCutoff = 0.05,
FCcutoff = 1.5,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = TRUE,
pointSize = 3.0,
labSize = 5.0,
drawConnectors = TRUE,
widthConnectors = 0.25)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells,
lab = Patient_cell_lines_vs_PBMC_Tcells$gene,
x = "avg_log2FC",
y = "p_val_adj",
selectLab = c('EPCAM', 'BCAT1', 'KIR3DL2', 'FOXM1', 'TWIST1', 'TNFSF9',
'CD80', 'IL1B', 'TRBV7.6', 'TRBV5.4', 'TRBV12.4',
'UBE2C', 'PCLAF', 'TYMS', 'CDC20', 'RPS4Y1',
'IL7R', 'TCF7', 'PTTG1', 'RRM2', 'MKI67', 'CD70',
'IL2RA','TRBV6-2', 'TRBV10-3', 'TRBV4-2', 'TRBV9', 'TRBV7-9',
'TRAV12-1', 'CD8B', 'FCGR3A', 'GNLY', 'FOXP3', 'SELL',
'GIMAP1', 'RIPOR2', 'LEF1', 'HOXC9', 'SP5',
'CCL17', 'ETV4', 'THY1', 'FOXA2', 'ITGAD', 'S100P', 'TBX4',
'ID1', 'XCL1', 'SOX2', 'CD27', 'CD28','PLS3','CD70','RAB25' , 'TRBV27', 'TRBV2'),
title = "Sézary Cell Lines vs PBMC T cells",
xlab = bquote(~Log[2]~ 'fold change'),
pCutoff = 0.05,
FCcutoff = 1.5,
pointSize = 3.0,
labSize = 5.0,
boxedLabels = TRUE,
colAlpha = 0.5,
legendPosition = 'right',
legendLabSize = 10,
legendIconSize = 4.0,
drawConnectors = TRUE,
widthConnectors = 0.5,
colConnectors = 'grey50',
arrowheads = FALSE,
max.overlaps = 30)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

4. Enrichment Analysis
#Step-by-Step Guide for Gene Set Enrichment Analysis (GSEA) or Over-Representation Analysis (ORA)
# Load the packages
library(clusterProfiler)
clusterProfiler v4.14.0 Learn more at https://yulab-smu.top/contribution-knowledge-mining/
Please cite:
T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu.
clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. The Innovation. 2021,
2(3):100141
Attaching package: 'clusterProfiler'
The following object is masked from 'package:stats':
filter
library(org.Hs.eg.db)
Loading required package: AnnotationDbi
Loading required package: stats4
Loading required package: BiocGenerics
Attaching package: 'BiocGenerics'
The following object is masked from 'package:gridExtra':
combine
The following objects are masked from 'package:dplyr':
combine, intersect, setdiff, union
The following object is masked from 'package:SeuratObject':
intersect
The following objects are masked from 'package:stats':
IQR, mad, sd, var, xtabs
The following objects are masked from 'package:base':
anyDuplicated, aperm, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated,
eval, evalq, Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget,
order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce, rownames, sapply, saveRDS,
setdiff, table, tapply, union, unique, unsplit, which.max, which.min
Loading required package: Biobase
Welcome to Bioconductor
Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see
'citation("Biobase")', and for packages 'citation("pkgname")'.
Loading required package: IRanges
Loading required package: S4Vectors
Attaching package: 'S4Vectors'
The following object is masked from 'package:clusterProfiler':
rename
The following objects are masked from 'package:dplyr':
first, rename
The following object is masked from 'package:utils':
findMatches
The following objects are masked from 'package:base':
expand.grid, I, unname
Attaching package: 'IRanges'
The following object is masked from 'package:clusterProfiler':
slice
The following objects are masked from 'package:dplyr':
collapse, desc, slice
The following object is masked from 'package:sp':
%over%
Attaching package: 'AnnotationDbi'
The following object is masked from 'package:clusterProfiler':
select
The following object is masked from 'package:dplyr':
select
library(enrichplot)
enrichplot v1.26.0 Learn more at https://yulab-smu.top/contribution-knowledge-mining/
Please cite:
Guangchuang Yu, Li-Gen Wang, and Qing-Yu He. ChIPseeker: an R/Bioconductor package for ChIP peak annotation,
comparison and visualization. Bioinformatics. 2015, 31(14):2382-2383
library(ReactomePA)
ReactomePA v1.50.0 Learn more at https://yulab-smu.top/contribution-knowledge-mining/
Please cite:
Guangchuang Yu, Qing-Yu He. ReactomePA: an R/Bioconductor package for reactome pathway analysis and
visualization. Molecular BioSystems. 2016, 12(2):477-479
# Get upregulated genes
upregulated_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5 & Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, ])
# Get downregulated genes
downregulated_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5 & Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, ])
#Gene Ontology (GO) Enrichment Analysis
# GO enrichment for upregulated genes
go_up <- enrichGO(gene = upregulated_genes,
OrgDb = org.Hs.eg.db,
keyType = "SYMBOL",
ont = "BP", # "BP" for Biological Processes, "MF" for Molecular Function, "CC" for Cellular Component
pAdjustMethod = "BH",
pvalueCutoff = 0.05)
# GO enrichment for downregulated genes
go_down <- enrichGO(gene = downregulated_genes,
OrgDb = org.Hs.eg.db,
keyType = "SYMBOL",
ont = "BP",
pAdjustMethod = "BH",
pvalueCutoff = 0.05)
# Visualize the top enriched GO terms
dotplot(go_up, showCategory = 20, title = "GO Enrichment for Upregulated Genes")

dotplot(go_down, showCategory = 20, title = "GO Enrichment for Downregulated Genes")

#KEGG Pathway Enrichment
# Convert gene symbols to Entrez IDs for KEGG analysis
upregulated_entrez <- bitr(upregulated_genes, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:many mapping between keys and columns
Warning: 10.4% of input gene IDs are fail to map...
downregulated_entrez <- bitr(downregulated_genes, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:1 mapping between keys and columns
Warning: 16.3% of input gene IDs are fail to map...
# KEGG pathway enrichment for upregulated genes
kegg_up <- enrichKEGG(gene = upregulated_entrez,
organism = "hsa",
pvalueCutoff = 0.05)
Reading KEGG annotation online: "https://rest.kegg.jp/link/hsa/pathway"...
Reading KEGG annotation online: "https://rest.kegg.jp/list/pathway/hsa"...
# KEGG pathway enrichment for downregulated genes
kegg_down <- enrichKEGG(gene = downregulated_entrez,
organism = "hsa",
pvalueCutoff = 0.05)
# Visualize KEGG pathway results
dotplot(kegg_up, showCategory = 20, title = "KEGG Pathway Enrichment for Upregulated Genes")

dotplot(kegg_down, showCategory = 20, title = "KEGG Pathway Enrichment for Downregulated Genes")

#Reactome Pathway Enrichment
# Reactome pathway enrichment for upregulated genes
reactome_up <- enrichPathway(gene = upregulated_entrez,
organism = "human",
pvalueCutoff = 0.05)
# Reactome pathway enrichment for downregulated genes
reactome_down <- enrichPathway(gene = downregulated_entrez,
organism = "human",
pvalueCutoff = 0.05)
# Visualize Reactome pathways
dotplot(reactome_up, showCategory = 20, title = "Reactome Pathway Enrichment for Upregulated Genes")

dotplot(reactome_down, showCategory = 20, title = "Reactome Pathway Enrichment for Downregulated Genes")

# Gene Set Enrichment Analysis (GSEA) (Optional)
# Create a ranked list of genes
gene_list <- Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC
names(gene_list) <- rownames(Patient_cell_lines_vs_PBMC_Tcells)
gene_list <- sort(gene_list, decreasing = TRUE)
# Convert gene symbols to Entrez IDs
gene_df <- bitr(names(gene_list), fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:many mapping between keys and columns
Warning: 11.19% of input gene IDs are fail to map...
# Ensure the gene list matches the Entrez IDs
gene_list <- gene_list[names(gene_list) %in% gene_df$SYMBOL]
# Replace gene symbols with Entrez IDs
names(gene_list) <- gene_df$ENTREZID[match(names(gene_list), gene_df$SYMBOL)]
# Run GSEA using KEGG
gsea_kegg <- gseKEGG(geneList = gene_list,
organism = "hsa",
pvalueCutoff = 0.05)
using 'fgsea' for GSEA analysis, please cite Korotkevich et al (2019).
preparing geneSet collections...
GSEA analysis...
Warning: There are ties in the preranked stats (0.27% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Warning: There were 1 pathways for which P-values were not calculated properly due to unbalanced (positive and negative) gene-level statistic values. For such pathways pval, padj, NES, log2err are set to NA. You can try to increase the value of the argument nPermSimple (for example set it nPermSimple = 10000)Warning: For some of the pathways the P-values were likely overestimated. For such pathways log2err is set to NA.Warning: For some pathways, in reality P-values are less than 1e-10. You can set the `eps` argument to zero for better estimation.leading edge analysis...
done...
# Plot the GSEA results
gseaplot(gsea_kegg, geneSetID = 1, title = "Top KEGG Pathway")

# Extract the name of the top KEGG pathway
top_pathway <- gsea_kegg@result[1, "Description"]
# Plot GSEA with the top pathway's name as the title
gseaplot(gsea_kegg, geneSetID = 1, title = top_pathway)

NA
NA
5. Bar PLOT
# Filter for significant pathways
top_kegg_up <- kegg_up@result[kegg_up@result$p.adjust < 0.05, ]
top_kegg_down <- kegg_down@result[kegg_down@result$p.adjust < 0.05, ]
# If there are not enough pathways, consider relaxing the threshold or checking the output
top_kegg_up <- top_kegg_up[order(-top_kegg_up$p.adjust), ][1:10, ]
top_kegg_down <- top_kegg_down[order(top_kegg_down$p.adjust), ][1:10, ]
# Combine into one data frame
top_pathways <- rbind(
data.frame(Pathway = top_kegg_up$Description, p.adjust = top_kegg_up$p.adjust, Direction = "Upregulated"),
data.frame(Pathway = top_kegg_down$Description, p.adjust = top_kegg_down$p.adjust, Direction = "Downregulated")
)
# Convert p.adjust to -log10(p.adjust) for visualization
top_pathways$neg_log10_p <- -log10(top_pathways$p.adjust)
# Create the barplot
ggplot(top_pathways, aes(x = reorder(Pathway, neg_log10_p), y = neg_log10_p, fill = Direction)) +
geom_bar(stat = "identity", position = position_dodge()) +
scale_fill_manual(values = c("Upregulated" = "red", "Downregulated" = "blue")) +
coord_flip() + # Flip the coordinates for better readability
labs(title = "Top Significant Pathways",
x = "Pathways",
y = "-Log10 Adjusted P-Value") +
theme_minimal() +
theme(legend.title = element_blank())

# Load necessary library
library(ggplot2)
# Create the barplot
ggplot(top_pathways, aes(x = Pathway, y = neg_log10_p, fill = Direction)) +
geom_bar(stat = "identity", position = "identity") + # Use position = "identity"
scale_fill_manual(values = c("Upregulated" = "red", "Downregulated" = "blue")) +
coord_flip() + # Flip the coordinates for better readability
labs(title = "Top Significant Pathways",
x = "Pathways",
y = "-Log10 Adjusted P-Value") +
theme_minimal() +
theme(legend.title = element_blank())

NA
NA
NA
5. ggplot2 for Volcano
library(ggplot2)
library(ggrepel)
# Identify top and bottom genes
top_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5, ]
bottom_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, ]
# Create a new column for color based on significance
Patient_cell_lines_vs_PBMC_Tcells$color <- ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5, "Upregulated genes",
ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, "Downregulated genes", "Nonsignificant"))
# Create a volcano plot
ggplot(Patient_cell_lines_vs_PBMC_Tcells, aes(x = avg_log2FC, y = -log10(p_val_adj))) +
geom_point(aes(color = color), alpha = 0.7, size = 2) +
# Add labels for top and bottom genes
geom_text_repel(data = top_genes, aes(label = gene), color = "black", vjust = 1, fontface = "bold") +
geom_text_repel(data = bottom_genes, aes(label = gene), color = "black", vjust = -1, fontface = "bold") +
# Customize labels and title
labs(title = "Volcano Plot",
x = "log2 Fold Change",
y = "-log10(p-value)") +
# Add significance threshold lines
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black") +
geom_vline(xintercept = c(-1.5, 2), linetype = "dashed", color = "black") +
# Set colors for top and bottom genes
scale_color_manual(values = c("Upregulated genes" = "red", "Downregulated genes" = "blue", "Nonsignificant" = "darkgrey")) +
# Customize theme if needed
theme_minimal()

NA
NA
NA
NA
NA
LS0tCnRpdGxlOiAiRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMgb2YgU1MgdnMgUEJNQzEwWCtQQk1DIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KEF6aW11dGgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQpgYGAKCiMgMi4gTG9hZCBTZXVyYXQgT2JqZWN0IApgYGB7ciBsb2FkX3NldXJhdCwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9Cgpsb2FkICgiL2hvbWUvYmlvaW5mby8wLWltcF9Sb2JqL0hhcm1vbnlfaW50ZWdyYXRlZF9BbGxfc2FtcGxlc19NZXJnZWRfd2l0aF9QQk1DMTB4X3dpdGhfaGFybW9ueV9jbHVzdGVyaW5nLlJvYmoiKQogCgpgYGAKCgojIDIuIEluaXRpYWwgVmlzdWFsaXphdGlvbgpgYGB7ciBWLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gU2V0SWRlbnQoQWxsX3NhbXBsZXNfTWVyZ2VkLCB2YWx1ZSA9ICJIYXJtb255X3Nubl9yZXMuMC45IikKICAKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgIGdyb3VwLmJ5ID0gIkhhcm1vbnlfc25uX3Jlcy4wLjkiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBUKQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMiIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IFQpCgpgYGAKCiMgMy4gUGVyZm9ybSBERSBhbmFseXNpcyB1c2luZyB0aGUgRmluZE1hcmtlcnMgCmBgYHtyIGRhdGExLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gU2V0SWRlbnQoQWxsX3NhbXBsZXNfTWVyZ2VkLCB2YWx1ZSA9ICJIYXJtb255X3Nubl9yZXMuMC45IikKClBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyA8LSBGaW5kTWFya2VycyhBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4xID0gYygiMyIsICI4IiwgIjEwIiwgIjE4IiwgIjEiLCAiMiIsICIxMyIsICI2IiwgIjE2IiwgIjE5IiwgIjQiLCAiNyIsICI5IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjIgPSBjKCIwIiwgIjUiLCAiMTQiLCAiMjQiLCAiMjAiKQogICAgICAgICAgICAgICAgICAgICAgICAgICApCgoKCiMgQ29udmVydCB0byBkYXRhIGZyYW1lIGFuZCBhZGQgZ2VuZSBuYW1lcyBhcyBhIG5ldyBjb2x1bW4KUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzIDwtIGFzLmRhdGEuZnJhbWUoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKQpQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkZ2VuZSA8LSByb3duYW1lcyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMpCgojIFJlYXJyYW5naW5nIHRoZSBjb2x1bW5zIGZvciBiZXR0ZXIgcmVhZGFiaWxpdHkgKG9wdGlvbmFsKQpQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMgPC0gUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzWywgYygiZ2VuZSIsICJwX3ZhbCIsICJhdmdfbG9nMkZDIiwgInBjdC4xIiwgInBjdC4yIiwgInBfdmFsX2FkaiIpXQoKI3dyaXRlLmNzdihQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMsICJQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgoKYGBgCgpgYGB7ciBlbmhhbmNlZFYsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNn0KCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMgLCAKICAgICAgICAgICAgICAgIGxhYj1yb3duYW1lcyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMpLAogICAgICAgICAgICAgICAgeCA9ImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSJwX3ZhbF9hZGoiLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiU8OpemFyeSBDZWxsIExpbmVzIHZzIFBCTUMgVCBjZWxscyIsCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMS41LCAKICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywgCiAgICAgICAgICAgICAgICBsYWJDb2wgPSAnYmxhY2snLAogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDMuMCwKICAgICAgICAgICAgICAgIGxhYlNpemUgPSA1LjAsIAogICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgd2lkdGhDb25uZWN0b3JzID0gMC4yNSkKCgoKCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMsIAogICAgICAgICAgICAgICAgbGFiID0gaWZlbHNlKChQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA+IDEuNSB8IFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDIDwgLTEuNSkgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkcF92YWxfYWRqIDwgMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIpLCAgIyBMYWJlbCBvbmx5IHNpZ25pZmljYW50IGdlbmVzCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHRpdGxlID0gIlPDqXphcnkgQ2VsbCBMaW5lcyB2cyBQQk1DIFQgY2VsbHMiLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuNSwgCiAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsIAogICAgICAgICAgICAgICAgbGFiQ29sID0gJ2JsYWNrJywKICAgICAgICAgICAgICAgIGxhYkZhY2UgPSAnYm9sZCcsCiAgICAgICAgICAgICAgICBib3hlZExhYmVscyA9IFRSVUUsCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNS4wLCAKICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuMjUpCgoKCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMsIAogICAgICAgICAgICAgICAgbGFiID0gUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGdlbmUsCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IGMoJ0VQQ0FNJywgJ0JDQVQxJywgJ0tJUjNETDInLCAnRk9YTTEnLCAnVFdJU1QxJywgJ1RORlNGOScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ0Q4MCcsICAnSUwxQicsICdUUkJWNy42JywgJ1RSQlY1LjQnLCAnVFJCVjEyLjQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVUJFMkMnLCAnUENMQUYnLCAnVFlNUycsICdDREMyMCcsICdSUFM0WTEnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lMN1InLCAnVENGNycsICdQVFRHMScsICdSUk0yJywgJ01LSTY3JywgJ0NENzAnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lMMlJBJywnVFJCVjYtMicsICdUUkJWMTAtMycsICdUUkJWNC0yJywgJ1RSQlY5JywgJ1RSQlY3LTknLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RSQVYxMi0xJywgJ0NEOEInLCAnRkNHUjNBJywgJ0dOTFknLCAnRk9YUDMnLCAnU0VMTCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnR0lNQVAxJywgJ1JJUE9SMicsICdMRUYxJywgJ0hPWEM5JywgJ1NQNScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDQ0wxNycsICdFVFY0JywgJ1RIWTEnLCAnRk9YQTInLCAnSVRHQUQnLCAnUzEwMFAnLCAnVEJYNCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUQxJywgJ1hDTDEnLCAnU09YMicsICdDRDI3JywgJ0NEMjgnLCdQTFMzJywnQ0Q3MCcsJ1JBQjI1JyAsICdUUkJWMjcnLCAnVFJCVjInKSwKICAgICAgICAgICAgICAgIHRpdGxlID0gIlPDqXphcnkgQ2VsbCBMaW5lcyB2cyBQQk1DIFQgY2VsbHMiLAogICAgICAgICAgICAgICAgeGxhYiA9IGJxdW90ZSh+TG9nWzJdfiAnZm9sZCBjaGFuZ2UnKSwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjUsIAogICAgICAgICAgICAgICAgcG9pbnRTaXplID0gMy4wLAogICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDUuMCwKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIGNvbEFscGhhID0gMC41LAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLAogICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjUsCiAgICAgICAgICAgICAgICBjb2xDb25uZWN0b3JzID0gJ2dyZXk1MCcsCiAgICAgICAgICAgICAgICBhcnJvd2hlYWRzID0gRkFMU0UsCiAgICAgICAgICAgICAgICBtYXgub3ZlcmxhcHMgPSAzMCkKCmBgYAoKIyA0LiBFbnJpY2htZW50IEFuYWx5c2lzCmBgYHtyIGRhdGEyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CgojU3RlcC1ieS1TdGVwIEd1aWRlIGZvciBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSBvciBPdmVyLVJlcHJlc2VudGF0aW9uIEFuYWx5c2lzIChPUkEpCgojIExvYWQgdGhlIHBhY2thZ2VzCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KG9yZy5Icy5lZy5kYikKbGlicmFyeShlbnJpY2hwbG90KQpsaWJyYXJ5KFJlYWN0b21lUEEpCgoKIyBHZXQgdXByZWd1bGF0ZWQgZ2VuZXMKdXByZWd1bGF0ZWRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDID4gMS41ICYgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUsIF0pCgojIEdldCBkb3ducmVndWxhdGVkIGdlbmVzCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDIDwgLTEuNSAmIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdKQoKI0dlbmUgT250b2xvZ3kgKEdPKSBFbnJpY2htZW50IEFuYWx5c2lzCiMgR08gZW5yaWNobWVudCBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMKZ29fdXAgPC0gZW5yaWNoR08oZ2VuZSA9IHVwcmVndWxhdGVkX2dlbmVzLCAKICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAgICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMsICJNRiIgZm9yIE1vbGVjdWxhciBGdW5jdGlvbiwgIkNDIiBmb3IgQ2VsbHVsYXIgQ29tcG9uZW50CiAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgR08gZW5yaWNobWVudCBmb3IgZG93bnJlZ3VsYXRlZCBnZW5lcwpnb19kb3duIDwtIGVucmljaEdPKGdlbmUgPSBkb3ducmVndWxhdGVkX2dlbmVzLCAKICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJTWU1CT0wiLCAKICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAKICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlzdWFsaXplIHRoZSB0b3AgZW5yaWNoZWQgR08gdGVybXMKZG90cGxvdChnb191cCwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIkdPIEVucmljaG1lbnQgZm9yIFVwcmVndWxhdGVkIEdlbmVzIikKZG90cGxvdChnb19kb3duLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiR08gRW5yaWNobWVudCBmb3IgRG93bnJlZ3VsYXRlZCBHZW5lcyIpCgojS0VHRyBQYXRod2F5IEVucmljaG1lbnQKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzIGZvciBLRUdHIGFuYWx5c2lzCnVwcmVndWxhdGVkX2VudHJleiA8LSBiaXRyKHVwcmVndWxhdGVkX2dlbmVzLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikkRU5UUkVaSUQKZG93bnJlZ3VsYXRlZF9lbnRyZXogPC0gYml0cihkb3ducmVndWxhdGVkX2dlbmVzLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikkRU5UUkVaSUQKCiMgS0VHRyBwYXRod2F5IGVucmljaG1lbnQgZm9yIHVwcmVndWxhdGVkIGdlbmVzCmtlZ2dfdXAgPC0gZW5yaWNoS0VHRyhnZW5lID0gdXByZWd1bGF0ZWRfZW50cmV6LCAKICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYSIsIAogICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgS0VHRyBwYXRod2F5IGVucmljaG1lbnQgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMKa2VnZ19kb3duIDwtIGVucmljaEtFR0coZ2VuZSA9IGRvd25yZWd1bGF0ZWRfZW50cmV6LCAKICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBLRUdHIHBhdGh3YXkgcmVzdWx0cwpkb3RwbG90KGtlZ2dfdXAsIHNob3dDYXRlZ29yeSA9IDIwLCB0aXRsZSA9ICJLRUdHIFBhdGh3YXkgRW5yaWNobWVudCBmb3IgVXByZWd1bGF0ZWQgR2VuZXMiKQpkb3RwbG90KGtlZ2dfZG93biwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIktFR0cgUGF0aHdheSBFbnJpY2htZW50IGZvciBEb3ducmVndWxhdGVkIEdlbmVzIikKCiNSZWFjdG9tZSBQYXRod2F5IEVucmljaG1lbnQKCiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciB1cHJlZ3VsYXRlZCBnZW5lcwpyZWFjdG9tZV91cCA8LSBlbnJpY2hQYXRod2F5KGdlbmUgPSB1cHJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImh1bWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciBkb3ducmVndWxhdGVkIGdlbmVzCnJlYWN0b21lX2Rvd24gPC0gZW5yaWNoUGF0aHdheShnZW5lID0gZG93bnJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHVtYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBSZWFjdG9tZSBwYXRod2F5cwpkb3RwbG90KHJlYWN0b21lX3VwLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiUmVhY3RvbWUgUGF0aHdheSBFbnJpY2htZW50IGZvciBVcHJlZ3VsYXRlZCBHZW5lcyIpCmRvdHBsb3QocmVhY3RvbWVfZG93biwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIlJlYWN0b21lIFBhdGh3YXkgRW5yaWNobWVudCBmb3IgRG93bnJlZ3VsYXRlZCBHZW5lcyIpCgoKIyBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSAoT3B0aW9uYWwpCiMgQ3JlYXRlIGEgcmFua2VkIGxpc3Qgb2YgZ2VuZXMKZ2VuZV9saXN0IDwtIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDCm5hbWVzKGdlbmVfbGlzdCkgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKQpnZW5lX2xpc3QgPC0gc29ydChnZW5lX2xpc3QsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzCmdlbmVfZGYgPC0gYml0cihuYW1lcyhnZW5lX2xpc3QpLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikKCiMgRW5zdXJlIHRoZSBnZW5lIGxpc3QgbWF0Y2hlcyB0aGUgRW50cmV6IElEcwpnZW5lX2xpc3QgPC0gZ2VuZV9saXN0W25hbWVzKGdlbmVfbGlzdCkgJWluJSBnZW5lX2RmJFNZTUJPTF0KCiMgUmVwbGFjZSBnZW5lIHN5bWJvbHMgd2l0aCBFbnRyZXogSURzCm5hbWVzKGdlbmVfbGlzdCkgPC0gZ2VuZV9kZiRFTlRSRVpJRFttYXRjaChuYW1lcyhnZW5lX2xpc3QpLCBnZW5lX2RmJFNZTUJPTCldCgoKIyBSdW4gR1NFQSB1c2luZyBLRUdHCmdzZWFfa2VnZyA8LSBnc2VLRUdHKGdlbmVMaXN0ID0gZ2VuZV9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFBsb3QgdGhlIEdTRUEgcmVzdWx0cwpnc2VhcGxvdChnc2VhX2tlZ2csIGdlbmVTZXRJRCA9IDEsIHRpdGxlID0gIlRvcCBLRUdHIFBhdGh3YXkiKQoKIyBFeHRyYWN0IHRoZSBuYW1lIG9mIHRoZSB0b3AgS0VHRyBwYXRod2F5CnRvcF9wYXRod2F5IDwtIGdzZWFfa2VnZ0ByZXN1bHRbMSwgIkRlc2NyaXB0aW9uIl0KCiMgUGxvdCBHU0VBIHdpdGggdGhlIHRvcCBwYXRod2F5J3MgbmFtZSBhcyB0aGUgdGl0bGUKZ3NlYXBsb3QoZ3NlYV9rZWdnLCBnZW5lU2V0SUQgPSAxLCB0aXRsZSA9IHRvcF9wYXRod2F5KQoKCmBgYAoKIyA1LiBCYXIgUExPVApgYGB7ciBkYXRhMywgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgRmlsdGVyIGZvciBzaWduaWZpY2FudCBwYXRod2F5cwp0b3Bfa2VnZ191cCA8LSBrZWdnX3VwQHJlc3VsdFtrZWdnX3VwQHJlc3VsdCRwLmFkanVzdCA8IDAuMDUsIF0KdG9wX2tlZ2dfZG93biA8LSBrZWdnX2Rvd25AcmVzdWx0W2tlZ2dfZG93bkByZXN1bHQkcC5hZGp1c3QgPCAwLjA1LCBdCgojIElmIHRoZXJlIGFyZSBub3QgZW5vdWdoIHBhdGh3YXlzLCBjb25zaWRlciByZWxheGluZyB0aGUgdGhyZXNob2xkIG9yIGNoZWNraW5nIHRoZSBvdXRwdXQKdG9wX2tlZ2dfdXAgPC0gdG9wX2tlZ2dfdXBbb3JkZXIoLXRvcF9rZWdnX3VwJHAuYWRqdXN0KSwgXVsxOjEwLCBdCnRvcF9rZWdnX2Rvd24gPC0gdG9wX2tlZ2dfZG93bltvcmRlcih0b3Bfa2VnZ19kb3duJHAuYWRqdXN0KSwgXVsxOjEwLCBdCgojIENvbWJpbmUgaW50byBvbmUgZGF0YSBmcmFtZQp0b3BfcGF0aHdheXMgPC0gcmJpbmQoCiAgZGF0YS5mcmFtZShQYXRod2F5ID0gdG9wX2tlZ2dfdXAkRGVzY3JpcHRpb24sIHAuYWRqdXN0ID0gdG9wX2tlZ2dfdXAkcC5hZGp1c3QsIERpcmVjdGlvbiA9ICJVcHJlZ3VsYXRlZCIpLAogIGRhdGEuZnJhbWUoUGF0aHdheSA9IHRvcF9rZWdnX2Rvd24kRGVzY3JpcHRpb24sIHAuYWRqdXN0ID0gdG9wX2tlZ2dfZG93biRwLmFkanVzdCwgRGlyZWN0aW9uID0gIkRvd25yZWd1bGF0ZWQiKQopCgojIENvbnZlcnQgcC5hZGp1c3QgdG8gLWxvZzEwKHAuYWRqdXN0KSBmb3IgdmlzdWFsaXphdGlvbgp0b3BfcGF0aHdheXMkbmVnX2xvZzEwX3AgPC0gLWxvZzEwKHRvcF9wYXRod2F5cyRwLmFkanVzdCkKCiMgQ3JlYXRlIHRoZSBiYXJwbG90CmdncGxvdCh0b3BfcGF0aHdheXMsIGFlcyh4ID0gcmVvcmRlcihQYXRod2F5LCBuZWdfbG9nMTBfcCksIHkgPSBuZWdfbG9nMTBfcCwgZmlsbCA9IERpcmVjdGlvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVXByZWd1bGF0ZWQiID0gInJlZCIsICJEb3ducmVndWxhdGVkIiA9ICJibHVlIikpICsKICBjb29yZF9mbGlwKCkgKyAgIyBGbGlwIHRoZSBjb29yZGluYXRlcyBmb3IgYmV0dGVyIHJlYWRhYmlsaXR5CiAgbGFicyh0aXRsZSA9ICJUb3AgU2lnbmlmaWNhbnQgUGF0aHdheXMiLAogICAgICAgeCA9ICJQYXRod2F5cyIsCiAgICAgICB5ID0gIi1Mb2cxMCBBZGp1c3RlZCBQLVZhbHVlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJ5CmxpYnJhcnkoZ2dwbG90MikKCiMgQ3JlYXRlIHRoZSBiYXJwbG90CmdncGxvdCh0b3BfcGF0aHdheXMsIGFlcyh4ID0gUGF0aHdheSwgeSA9IG5lZ19sb2cxMF9wLCBmaWxsID0gRGlyZWN0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsgICMgVXNlIHBvc2l0aW9uID0gImlkZW50aXR5IgogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIlVwcmVndWxhdGVkIiA9ICJyZWQiLCAiRG93bnJlZ3VsYXRlZCIgPSAiYmx1ZSIpKSArCiAgY29vcmRfZmxpcCgpICsgICMgRmxpcCB0aGUgY29vcmRpbmF0ZXMgZm9yIGJldHRlciByZWFkYWJpbGl0eQogIGxhYnModGl0bGUgPSAiVG9wIFNpZ25pZmljYW50IFBhdGh3YXlzIiwKICAgICAgIHggPSAiUGF0aHdheXMiLAogICAgICAgeSA9ICItTG9nMTAgQWRqdXN0ZWQgUC1WYWx1ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCgoKYGBgCgojIDUuIHBlcmZvcm0gZ2VuZSBlbnJpY2htZW50IGFuYWx5c2lzIGFuZCBpZGVudGlmeSBwYXRod2F5cwpgYGB7ciBkYXRhNCwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgTG9hZCB0aGUgcGFja2FnZXMKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkob3JnLkhzLmVnLmRiKQoKIyBBc3N1bWluZyBgc2lnbmlmaWNhbnRfZ2VuZXNgIGlzIHlvdXIgbGlzdCBvZiBzaWduaWZpY2FudCBnZW5lIHN5bWJvbHMKc2lnbmlmaWNhbnRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzWwogICAgKFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDID4gMS41IHwgCiAgICAgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPCAtMS41KSAmIAogICAgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUsIF0pCgplbnRyZXpfaWRzIDwtIGJpdHIoc2lnbmlmaWNhbnRfZ2VuZXMsIGZyb21UeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICAgdG9UeXBlID0gIkVOVFJFWklEIiwgCiAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYikKCmtlZ2dfcmVzdWx0cyA8LSBlbnJpY2hLRUdHKGdlbmUgPSBlbnRyZXpfaWRzJEVOVFJFWklELAogICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICdoc2EnLAogICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBWaWV3IHJlc3VsdHMKaGVhZChrZWdnX3Jlc3VsdHMpCgoKZ29fcmVzdWx0cyA8LSBlbnJpY2hHTyhnZW5lID0gZW50cmV6X2lkcyRFTlRSRVpJRCwKICAgICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwKICAgICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAjIEJpb2xvZ2ljYWwgUHJvY2VzcwogICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpZXcgcmVzdWx0cwpoZWFkKGdvX3Jlc3VsdHMpCgojIERvdCBwbG90IGZvciBLRUdHIHJlc3VsdHMKZG90cGxvdChrZWdnX3Jlc3VsdHMsIHNob3dDYXRlZ29yeT0xMCkgKyBnZ3RpdGxlKCJLRUdHIFBhdGh3YXkgRW5yaWNobWVudCIpCgojIERvdCBwbG90IGZvciBHTyByZXN1bHRzCmRvdHBsb3QoZ29fcmVzdWx0cywgc2hvd0NhdGVnb3J5PTEwKSArIGdndGl0bGUoIkdPIEJpb2xvZ2ljYWwgUHJvY2VzcyBFbnJpY2htZW50IikKCgpgYGAKCgojIDUuIGdncGxvdDIgZm9yIFZvbGNhbm8KYGBge3IgZGF0YTUsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkKCiMgSWRlbnRpZnkgdG9wIGFuZCBib3R0b20gZ2VuZXMKdG9wX2dlbmVzIDwtIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxsc1tQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkcF92YWxfYWRqIDwgMC4wNSAmIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDID4gMS41LCBdCmJvdHRvbV9nZW5lcyA8LSBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHNbUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUgJiBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsIF0KCiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBmb3IgY29sb3IgYmFzZWQgb24gc2lnbmlmaWNhbmNlClBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRjb2xvciA8LSBpZmVsc2UoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPiAxLjUsICJVcHJlZ3VsYXRlZCBnZW5lcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsICJEb3ducmVndWxhdGVkIGdlbmVzIiwgIk5vbnNpZ25pZmljYW50IikpCgojIENyZWF0ZSBhIHZvbGNhbm8gcGxvdApnZ3Bsb3QoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzLCBhZXMoeCA9IGF2Z19sb2cyRkMsIHkgPSAtbG9nMTAocF92YWxfYWRqKSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGNvbG9yKSwgYWxwaGEgPSAwLjcsIHNpemUgPSAyKSArCiAgCiAgIyBBZGQgbGFiZWxzIGZvciB0b3AgYW5kIGJvdHRvbSBnZW5lcwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gdG9wX2dlbmVzLCBhZXMobGFiZWwgPSBnZW5lKSwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IDEsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSBib3R0b21fZ2VuZXMsIGFlcyhsYWJlbCA9IGdlbmUpLCBjb2xvciA9ICJibGFjayIsIHZqdXN0ID0gLTEsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgCiAgIyBDdXN0b21pemUgbGFiZWxzIGFuZCB0aXRsZQogIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IiwKICAgICAgIHggPSAibG9nMiBGb2xkIENoYW5nZSIsCiAgICAgICB5ID0gIi1sb2cxMChwLXZhbHVlKSIpICsKICAKICAjIEFkZCBzaWduaWZpY2FuY2UgdGhyZXNob2xkIGxpbmVzCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xLjUsIDIpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsKICAKICAjIFNldCBjb2xvcnMgZm9yIHRvcCBhbmQgYm90dG9tIGdlbmVzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlVwcmVndWxhdGVkIGdlbmVzIiA9ICJyZWQiLCAiRG93bnJlZ3VsYXRlZCBnZW5lcyIgPSAiYmx1ZSIsICJOb25zaWduaWZpY2FudCIgPSAiZGFya2dyZXkiKSkgKwogIAogICMgQ3VzdG9taXplIHRoZW1lIGlmIG5lZWRlZAogIHRoZW1lX21pbmltYWwoKQoKCgoKCmBgYAoKCgoK