1. load libraries
3. Create the EnhancedVolcano plot
EnhancedVolcano(Malignant_CD4Tcells_vs_Normal_CD4Tcells,
lab = Malignant_CD4Tcells_vs_Normal_CD4Tcells$gene,
x = "avg_log2FC",
y = "p_val_adj",
title = "MAST with Batch Correction (All Genes)",
pCutoff = 0.05,
FCcutoff = 1.0)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Malignant_CD4Tcells_vs_Normal_CD4Tcells,
lab = Malignant_CD4Tcells_vs_Normal_CD4Tcells$gene,
x = "avg_log2FC",
y = "p_val_adj",
selectLab = c('EPCAM', 'BCAT1', 'KIR3DL2', 'FOXM1', 'TWIST1', 'TNFSF9',
'CD80', 'IL1B', 'RPS4Y1',
'IL7R', 'TCF7', '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 = "Malignant CD4 T cells(cell lines) vs normal CD4 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)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

library(dplyr)
library(EnhancedVolcano)
# Assuming you have a data frame named Malignant_CD4Tcells_vs_Normal_CD4Tcells
# Filter genes based on lowest p-values but include all genes
filtered_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells %>%
arrange(p_val_adj, desc(abs(avg_log2FC)))
# Create the EnhancedVolcano plot with the filtered data
EnhancedVolcano(
filtered_genes,
lab = ifelse(filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_log2FC) >= 1.0, filtered_genes$gene, NA),
x = "avg_log2FC",
y = "p_val_adj",
title = "Malignant CD4 T cells(cell lines) vs normal CD4 T cells",
pCutoff = 0.05,
FCcutoff = 1.0,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = FALSE, # Set to FALSE to remove boxed labels
pointSize = 3.0,
labSize = 5.0,
col = c('grey70', 'black', 'blue', 'red'), # Customize point colors
selectLab = filtered_genes$gene[filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_log2FC) >= 1.0] # Only label significant genes
)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(
filtered_genes,
lab = ifelse(filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_log2FC) >= 1.0, filtered_genes$gene, NA),
x = "avg_log2FC",
y = "p_val_adj",
title = "Malignant CD4 T cells (cell lines) vs Normal CD4 T cells",
subtitle = "Highlighting differentially expressed genes",
pCutoff = 0.05,
FCcutoff = 1.0,
legendPosition = 'right',
colAlpha = 0.8, # Slight transparency for non-significant points
col = c('grey70', 'black', 'blue', 'red'), # Custom color scheme
gridlines.major = TRUE,
gridlines.minor = FALSE,
selectLab = filtered_genes$gene[filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_log2FC) >= 1.0]
)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

4. Enrichment Analysis-1
# Step-by-Step Guide for Gene Set Enrichment Analysis (GSEA) or Over-Representation Analysis (ORA)
# Load the necessary libraries
library(clusterProfiler)
library(org.Hs.eg.db)
library(enrichplot)
library(ReactomePA)
# Get upregulated genes based on log2FC and p-value thresholds
upregulated_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 0.5 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05, ]
# Get downregulated genes based on log2FC and p-value thresholds
downregulated_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -0.5 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05, ]
# Gene Ontology (GO) Enrichment Analysis
# GO enrichment for upregulated genes
go_up <- enrichGO(gene = upregulated_genes$gene,
OrgDb = org.Hs.eg.db,
keyType = "SYMBOL",
ont = "BP", # Biological Process (BP), Molecular Function (MF), Cellular Component (CC)
pAdjustMethod = "BH",
pvalueCutoff = 0.05)
# GO enrichment for downregulated genes
go_down <- enrichGO(gene = downregulated_genes$gene,
OrgDb = org.Hs.eg.db,
keyType = "SYMBOL",
ont = "BP",
pAdjustMethod = "BH",
pvalueCutoff = 0.05)
# Visualize the top enriched GO terms
dotplot(go_up, showCategory = 10, title = "GO Enrichment for Upregulated Genes")

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

# KEGG Pathway Enrichment
# Convert gene symbols to Entrez IDs for KEGG analysis
upregulated_entrez <- bitr(upregulated_genes$gene, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:1 mapping between keys and columns
Avis : 5.78% of input gene IDs are fail to map...
downregulated_entrez <- bitr(downregulated_genes$gene, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:1 mapping between keys and columns
Avis : 15.04% 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)
# 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 = 10, title = "KEGG Pathway Enrichment for Upregulated Genes")

dotplot(kegg_down, showCategory = 6, 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 = 10, title = "Reactome Pathway Enrichment for Upregulated Genes")

#dotplot(reactome_down, showCategory = 10, title = "Reactome Pathway Enrichment for Downregulated Genes")
# Gene Set Enrichment Analysis (GSEA)
# Create a ranked list of genes (log2FC as ranking metric)
gene_list <- Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC
names(gene_list) <- Malignant_CD4Tcells_vs_Normal_CD4Tcells$gene # Use the $gene column for gene symbols
gene_list <- sort(gene_list, decreasing = TRUE)
# Convert gene symbols to Entrez IDs for GSEA
gene_df <- bitr(names(gene_list), fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:many mapping between keys and columns
Avis : 27.85% 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 pathways
gsea_kegg <- gseKEGG(geneList = gene_list,
organism = "hsa",
pvalueCutoff = 0.05)
preparing geneSet collections...
GSEA analysis...
Avis : There are ties in the preranked stats (21.49% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : 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
4.2. Enrichment Analysis-2
# Load necessary libraries
library(clusterProfiler)
library(org.Hs.eg.db)
library(msigdbr)
library(enrichplot)
# Load Hallmark gene sets from msigdbr
hallmark_sets <- msigdbr(species = "Homo sapiens", category = "H") # "H" is for Hallmark gene sets
# Get upregulated and downregulated genes based on log2 fold change and adjusted p-value
upregulated_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 0.5 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05, ]
downregulated_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -0.5 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05, ]
# Convert gene symbols to uppercase for consistency
upregulated_genes$gene <- toupper(upregulated_genes$gene)
downregulated_genes$gene <- toupper(downregulated_genes$gene)
# Check for overlap between your upregulated/downregulated genes and Hallmark gene sets
upregulated_in_hallmark <- intersect(upregulated_genes$gene, hallmark_sets$gene_symbol)
downregulated_in_hallmark <- intersect(downregulated_genes$gene, hallmark_sets$gene_symbol)
# Print the number of overlapping genes for both upregulated and downregulated genes
cat("Number of upregulated genes in Hallmark gene sets:", length(upregulated_in_hallmark), "\n")
Number of upregulated genes in Hallmark gene sets: 1073
cat("Number of downregulated genes in Hallmark gene sets:", length(downregulated_in_hallmark), "\n")
Number of downregulated genes in Hallmark gene sets: 134
# If there are genes to analyze, proceed with enrichment analysis
if (length(upregulated_in_hallmark) > 0) {
# Perform enrichment analysis for upregulated genes using Hallmark gene sets
hallmark_up <- enricher(gene = upregulated_in_hallmark,
TERM2GENE = hallmark_sets[, c("gs_name", "gene_symbol")], # Ensure TERM2GENE uses correct columns
pvalueCutoff = 0.05)
# Check if results exist
if (!is.null(hallmark_up) && nrow(hallmark_up) > 0) {
# Visualize results if available
dotplot(hallmark_up, showCategory = 20, title = "Hallmark Pathway Enrichment for Upregulated Genes")
} else {
cat("No significant enrichment found for upregulated genes.\n")
}
} else {
cat("No upregulated genes overlap with Hallmark gene sets.\n")
}

if (length(downregulated_in_hallmark) > 0) {
# Perform enrichment analysis for downregulated genes using Hallmark gene sets
hallmark_down <- enricher(gene = downregulated_in_hallmark,
TERM2GENE = hallmark_sets[, c("gs_name", "gene_symbol")], # Ensure TERM2GENE uses correct columns
pvalueCutoff = 0.05)
# Check if results exist
if (!is.null(hallmark_down) && nrow(hallmark_down) > 0) {
# Visualize results if available
dotplot(hallmark_down, showCategory = 20, title = "Hallmark Pathway Enrichment for Downregulated Genes")
} else {
cat("No significant enrichment found for downregulated genes.\n")
}
} else {
cat("No downregulated genes overlap with Hallmark gene sets.\n")
}

NA
NA
NA
NA
NA
4.3. Hallmark-GSEA
# Gene Set Enrichment Analysis (GSEA) for Hallmark Pathways
# Create a ranked list of genes (log2FC as ranking metric)
gene_list <- Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC
names(gene_list) <- Malignant_CD4Tcells_vs_Normal_CD4Tcells$gene
gene_list <- sort(gene_list, decreasing = TRUE)
# Convert gene symbols to Entrez IDs for GSEA
gene_df <- bitr(names(gene_list),
fromType = "SYMBOL",
toType = "ENTREZID",
OrgDb = org.Hs.eg.db)
'select()' returned 1:many mapping between keys and columns
Avis : 27.85% of input gene IDs are fail to map...
# Filter out genes without Entrez ID mappings
gene_list <- gene_list[names(gene_list) %in% gene_df$SYMBOL]
# Replace gene symbols with Entrez IDs in the gene list
names(gene_list) <- gene_df$ENTREZID[match(names(gene_list), gene_df$SYMBOL)]
# Run GSEA using Hallmark pathways
gsea_hallmark <- GSEA(geneList = gene_list,
TERM2GENE = hallmark_sets[, c("gs_name", "entrez_gene")],
pvalueCutoff = 0.05)
preparing geneSet collections...
GSEA analysis...
Avis : There are ties in the preranked stats (21.49% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : 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...
# Check and visualize GSEA results
if (!is.null(gsea_hallmark) && nrow(gsea_hallmark) > 0) {
# Visualize top GSEA results for Hallmark pathways
dotplot(gsea_hallmark, showCategory = 20, title = "GSEA for Hallmark Pathways")
# Plot enrichment score for the top pathway
gseaplot(gsea_hallmark, geneSetID = 1, title = "Top Hallmark Pathway")
# Extract the name of the top Hallmark pathway
top_hallmark <- gsea_hallmark@result[1, "Description"]
# Plot GSEA with the top pathway's name as the title
gseaplot(gsea_hallmark, geneSetID = 1, title = top_hallmark)
} else {
cat("No significant GSEA results for Hallmark pathways.\n")
}

NA
NA
NA
5. ggplot2 for Volcano
library(ggplot2)
library(ggrepel)
# Identify top and bottom genes
top_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 0.5, ]
bottom_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -0.5, ]
# Create a new column for color based on significance
Malignant_CD4Tcells_vs_Normal_CD4Tcells$color <- ifelse(Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 0.5, "Upregulated genes",
ifelse(Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -0.5, "Downregulated genes", "Nonsignificant"))
# Create a volcano plot
ggplot(Malignant_CD4Tcells_vs_Normal_CD4Tcells, 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.00001), linetype = "dashed", color = "black") +
geom_vline(xintercept = c(-0.5, 0.5), 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
5. ggplot3 for Volcano
# Load necessary libraries
library(ggplot2)
library(ggrepel)
# Identify top and bottom genes
top_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.00001 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 4, ]
bottom_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.00001 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -4, ]
# Create a new column for color based on significance
Malignant_CD4Tcells_vs_Normal_CD4Tcells$color <- ifelse(Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 0.5,
"Upregulated genes",
ifelse(Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -0.5,
"Downregulated genes",
"Nonsignificant"))
# Create the volcano plot
ggplot(Malignant_CD4Tcells_vs_Normal_CD4Tcells, aes(x = avg_log2FC, y = -log10(p_val_adj))) +
geom_point(aes(color = color), alpha = 0.7, size = 2) +
# Add labels next to the dots without repel lines
geom_text(data = top_genes, aes(label = gene), hjust = -0.2, vjust = 0, size = 3, color = "black", fontface = "bold") +
geom_text(data = bottom_genes, aes(label = gene), hjust = 1.2, vjust = 0, size = 3, color = "black", 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.00001), linetype = "dashed", color = "black") +
geom_vline(xintercept = c(-0.5, 0.5), 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
theme_minimal()

NA
NA
LS0tCnRpdGxlOiAiRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMgb2YgTWFsaWduYW50IENENFRjZWxscyB2cyBDb250cm9sKE5vcm1hbCBDRDQgVGNlbGxzKS1HU0VBIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyh7CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KEF6aW11dGgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQogIAp9KQpgYGAKCiMgMi4gUGVyZm9ybSBERSBhbmFseXNpcyB1c2luZyBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgZ2VuZXMKYGBge3IgZGF0YTEsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIDwtIHJlYWQuY3N2KCIxLU1BU1Rfd2l0aF9TQ1RfYmF0Y2hfcGF0aWVudF9jZWxsbGluZV9hc19Db3ZhcmlhdGVfd2l0aF9tZWFuRXhwcmVzc2lvbi5jc3YiLCBoZWFkZXIgPSBUKQpgYGAKCiMgMy4gQ3JlYXRlIHRoZSBFbmhhbmNlZFZvbGNhbm8gcGxvdApgYGB7ciBlbmhhbmNlZFYsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNn0KCkVuaGFuY2VkVm9sY2FubyhNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMsCiAgICAgICAgICAgICAgICBsYWIgPSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICAgICAgICAgICAgICB5ID0gInBfdmFsX2FkaiIsCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJNQVNUIHdpdGggQmF0Y2ggQ29ycmVjdGlvbiAoQWxsIEdlbmVzKSIsCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMS4wKQoKCkVuaGFuY2VkVm9sY2FubyhNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMsIAogICAgICAgICAgICAgICAgbGFiID0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGdlbmUsCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IGMoJ0VQQ0FNJywgJ0JDQVQxJywgJ0tJUjNETDInLCAnRk9YTTEnLCAnVFdJU1QxJywgJ1RORlNGOScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ0Q4MCcsICAnSUwxQicsICdSUFM0WTEnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lMN1InLCAnVENGNycsICAnTUtJNjcnLCAnQ0Q3MCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUwyUkEnLCdUUkJWNi0yJywgJ1RSQlYxMC0zJywgJ1RSQlY0LTInLCAnVFJCVjknLCAnVFJCVjctOScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVFJBVjEyLTEnLCAnQ0Q4QicsICdGQ0dSM0EnLCAnR05MWScsICdGT1hQMycsICdTRUxMJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdHSU1BUDEnLCAnUklQT1IyJywgJ0xFRjEnLCAnSE9YQzknLCAnU1A1JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0NDTDE3JywgJ0VUVjQnLCAnVEhZMScsICdGT1hBMicsICdJVEdBRCcsICdTMTAwUCcsICdUQlg0JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdJRDEnLCAnWENMMScsICdTT1gyJywgJ0NEMjcnLCAnQ0QyOCcsJ1BMUzMnLCdDRDcwJywnUkFCMjUnICwgJ1RSQlYyNycsICdUUkJWMicpLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiTWFsaWduYW50IENENCBUIGNlbGxzKGNlbGwgbGluZXMpIHZzIG5vcm1hbCBDRDQgVCBjZWxscyIsCiAgICAgICAgICAgICAgICB4bGFiID0gYnF1b3RlKH5Mb2dbMl1+ICdmb2xkIGNoYW5nZScpLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuNSwgCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNS4wLAogICAgICAgICAgICAgICAgYm94ZWRMYWJlbHMgPSBUUlVFLAogICAgICAgICAgICAgICAgY29sQWxwaGEgPSAwLjUsCiAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsCiAgICAgICAgICAgICAgICBsZWdlbmRMYWJTaXplID0gMTAsCiAgICAgICAgICAgICAgICBsZWdlbmRJY29uU2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuNSwKICAgICAgICAgICAgICAgIGNvbENvbm5lY3RvcnMgPSAnZ3JleTUwJywKICAgICAgICAgICAgICAgIGFycm93aGVhZHMgPSBGQUxTRSwKICAgICAgICAgICAgICAgIG1heC5vdmVybGFwcyA9IDMwKQoKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQoKIyBBc3N1bWluZyB5b3UgaGF2ZSBhIGRhdGEgZnJhbWUgbmFtZWQgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzCiMgRmlsdGVyIGdlbmVzIGJhc2VkIG9uIGxvd2VzdCBwLXZhbHVlcyBidXQgaW5jbHVkZSBhbGwgZ2VuZXMKZmlsdGVyZWRfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzICU+JQogIGFycmFuZ2UocF92YWxfYWRqLCBkZXNjKGFicyhhdmdfbG9nMkZDKSkpCgojIENyZWF0ZSB0aGUgRW5oYW5jZWRWb2xjYW5vIHBsb3Qgd2l0aCB0aGUgZmlsdGVyZWQgZGF0YQpFbmhhbmNlZFZvbGNhbm8oCiAgZmlsdGVyZWRfZ2VuZXMsIAogIGxhYiA9IGlmZWxzZShmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nMkZDKSA+PSAxLjAsIGZpbHRlcmVkX2dlbmVzJGdlbmUsIE5BKSwKICB4ID0gImF2Z19sb2cyRkMiLCAKICB5ID0gInBfdmFsX2FkaiIsCiAgdGl0bGUgPSAiTWFsaWduYW50IENENCBUIGNlbGxzKGNlbGwgbGluZXMpIHZzIG5vcm1hbCBDRDQgVCBjZWxscyIsCiAgcEN1dG9mZiA9IDAuMDUsCiAgRkNjdXRvZmYgPSAxLjAsCiAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLCAKICBsYWJDb2wgPSAnYmxhY2snLAogIGxhYkZhY2UgPSAnYm9sZCcsCiAgYm94ZWRMYWJlbHMgPSBGQUxTRSwgICMgU2V0IHRvIEZBTFNFIHRvIHJlbW92ZSBib3hlZCBsYWJlbHMKICBwb2ludFNpemUgPSAzLjAsCiAgbGFiU2l6ZSA9IDUuMCwKICBjb2wgPSBjKCdncmV5NzAnLCAnYmxhY2snLCAnYmx1ZScsICdyZWQnKSwgICMgQ3VzdG9taXplIHBvaW50IGNvbG9ycwogIHNlbGVjdExhYiA9IGZpbHRlcmVkX2dlbmVzJGdlbmVbZmlsdGVyZWRfZ2VuZXMkcF92YWxfYWRqIDw9IDAuMDUgJiBhYnMoZmlsdGVyZWRfZ2VuZXMkYXZnX2xvZzJGQykgPj0gMS4wXSAgIyBPbmx5IGxhYmVsIHNpZ25pZmljYW50IGdlbmVzCikKCgoKRW5oYW5jZWRWb2xjYW5vKAogIGZpbHRlcmVkX2dlbmVzLCAKICBsYWIgPSBpZmVsc2UoZmlsdGVyZWRfZ2VuZXMkcF92YWxfYWRqIDw9IDAuMDUgJiBhYnMoZmlsdGVyZWRfZ2VuZXMkYXZnX2xvZzJGQykgPj0gMS4wLCBmaWx0ZXJlZF9nZW5lcyRnZW5lLCBOQSksCiAgeCA9ICJhdmdfbG9nMkZDIiwgCiAgeSA9ICJwX3ZhbF9hZGoiLAogIHRpdGxlID0gIk1hbGlnbmFudCBDRDQgVCBjZWxscyAoY2VsbCBsaW5lcykgdnMgTm9ybWFsIENENCBUIGNlbGxzIiwKICBzdWJ0aXRsZSA9ICJIaWdobGlnaHRpbmcgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIiwKICBwQ3V0b2ZmID0gMC4wNSwKICBGQ2N1dG9mZiA9IDEuMCwKICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsCiAgY29sQWxwaGEgPSAwLjgsICAjIFNsaWdodCB0cmFuc3BhcmVuY3kgZm9yIG5vbi1zaWduaWZpY2FudCBwb2ludHMKICBjb2wgPSBjKCdncmV5NzAnLCAnYmxhY2snLCAnYmx1ZScsICdyZWQnKSwgICMgQ3VzdG9tIGNvbG9yIHNjaGVtZQogIGdyaWRsaW5lcy5tYWpvciA9IFRSVUUsCiAgZ3JpZGxpbmVzLm1pbm9yID0gRkFMU0UsCiAgc2VsZWN0TGFiID0gZmlsdGVyZWRfZ2VuZXMkZ2VuZVtmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nMkZDKSA+PSAxLjBdCikgCgoKYGBgCgoKIyA0LiBFbnJpY2htZW50IEFuYWx5c2lzLTEKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgU3RlcC1ieS1TdGVwIEd1aWRlIGZvciBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSBvciBPdmVyLVJlcHJlc2VudGF0aW9uIEFuYWx5c2lzIChPUkEpCgojIExvYWQgdGhlIG5lY2Vzc2FyeSBsaWJyYXJpZXMKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkob3JnLkhzLmVnLmRiKQpsaWJyYXJ5KGVucmljaHBsb3QpCmxpYnJhcnkoUmVhY3RvbWVQQSkKCiMgR2V0IHVwcmVndWxhdGVkIGdlbmVzIGJhc2VkIG9uIGxvZzJGQyBhbmQgcC12YWx1ZSB0aHJlc2hvbGRzCnVwcmVndWxhdGVkX2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc1tNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA+IDAuNSAmIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdCgojIEdldCBkb3ducmVndWxhdGVkIGdlbmVzIGJhc2VkIG9uIGxvZzJGQyBhbmQgcC12YWx1ZSB0aHJlc2hvbGRzCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzW01hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDIDwgLTAuNSAmIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdCgojIEdlbmUgT250b2xvZ3kgKEdPKSBFbnJpY2htZW50IEFuYWx5c2lzCiMgR08gZW5yaWNobWVudCBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMKZ29fdXAgPC0gZW5yaWNoR08oZ2VuZSA9IHVwcmVndWxhdGVkX2dlbmVzJGdlbmUsIAogICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgIGtleVR5cGUgPSAiU1lNQk9MIiwgCiAgICAgICAgICAgICAgICAgIG9udCA9ICJCUCIsICAgIyBCaW9sb2dpY2FsIFByb2Nlc3MgKEJQKSwgTW9sZWN1bGFyIEZ1bmN0aW9uIChNRiksIENlbGx1bGFyIENvbXBvbmVudCAoQ0MpCiAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgR08gZW5yaWNobWVudCBmb3IgZG93bnJlZ3VsYXRlZCBnZW5lcwpnb19kb3duIDwtIGVucmljaEdPKGdlbmUgPSBkb3ducmVndWxhdGVkX2dlbmVzJGdlbmUsIAogICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICAgIG9udCA9ICJCUCIsIAogICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBWaXN1YWxpemUgdGhlIHRvcCBlbnJpY2hlZCBHTyB0ZXJtcwpkb3RwbG90KGdvX3VwLCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiR08gRW5yaWNobWVudCBmb3IgVXByZWd1bGF0ZWQgR2VuZXMiKQpkb3RwbG90KGdvX2Rvd24sIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJHTyBFbnJpY2htZW50IGZvciBEb3ducmVndWxhdGVkIEdlbmVzIikKCiMgS0VHRyBQYXRod2F5IEVucmljaG1lbnQKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzIGZvciBLRUdHIGFuYWx5c2lzCnVwcmVndWxhdGVkX2VudHJleiA8LSBiaXRyKHVwcmVndWxhdGVkX2dlbmVzJGdlbmUsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKSRFTlRSRVpJRApkb3ducmVndWxhdGVkX2VudHJleiA8LSBiaXRyKGRvd25yZWd1bGF0ZWRfZ2VuZXMkZ2VuZSwgZnJvbVR5cGUgPSAiU1lNQk9MIiwgdG9UeXBlID0gIkVOVFJFWklEIiwgT3JnRGIgPSBvcmcuSHMuZWcuZGIpJEVOVFJFWklECgojIEtFR0cgcGF0aHdheSBlbnJpY2htZW50IGZvciB1cHJlZ3VsYXRlZCBnZW5lcwprZWdnX3VwIDwtIGVucmljaEtFR0coZ2VuZSA9IHVwcmVndWxhdGVkX2VudHJleiwgCiAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2EiLCAKICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIEtFR0cgcGF0aHdheSBlbnJpY2htZW50IGZvciBkb3ducmVndWxhdGVkIGdlbmVzCmtlZ2dfZG93biA8LSBlbnJpY2hLRUdHKGdlbmUgPSBkb3ducmVndWxhdGVkX2VudHJleiwgCiAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYSIsIAogICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBWaXN1YWxpemUgS0VHRyBwYXRod2F5IHJlc3VsdHMKZG90cGxvdChrZWdnX3VwLCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiS0VHRyBQYXRod2F5IEVucmljaG1lbnQgZm9yIFVwcmVndWxhdGVkIEdlbmVzIikKZG90cGxvdChrZWdnX2Rvd24sIHNob3dDYXRlZ29yeSA9IDYsIHRpdGxlID0gIktFR0cgUGF0aHdheSBFbnJpY2htZW50IGZvciBEb3ducmVndWxhdGVkIEdlbmVzIikKCiMgUmVhY3RvbWUgUGF0aHdheSBFbnJpY2htZW50CiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciB1cHJlZ3VsYXRlZCBnZW5lcwpyZWFjdG9tZV91cCA8LSBlbnJpY2hQYXRod2F5KGdlbmUgPSB1cHJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImh1bWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciBkb3ducmVndWxhdGVkIGdlbmVzCnJlYWN0b21lX2Rvd24gPC0gZW5yaWNoUGF0aHdheShnZW5lID0gZG93bnJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHVtYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBSZWFjdG9tZSBwYXRod2F5cwpkb3RwbG90KHJlYWN0b21lX3VwLCBzaG93Q2F0ZWdvcnkgPSAxMCwgdGl0bGUgPSAiUmVhY3RvbWUgUGF0aHdheSBFbnJpY2htZW50IGZvciBVcHJlZ3VsYXRlZCBHZW5lcyIpCiNkb3RwbG90KHJlYWN0b21lX2Rvd24sIHNob3dDYXRlZ29yeSA9IDEwLCB0aXRsZSA9ICJSZWFjdG9tZSBQYXRod2F5IEVucmljaG1lbnQgZm9yIERvd25yZWd1bGF0ZWQgR2VuZXMiKQoKIyBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKQojIENyZWF0ZSBhIHJhbmtlZCBsaXN0IG9mIGdlbmVzIChsb2cyRkMgYXMgcmFua2luZyBtZXRyaWMpCmdlbmVfbGlzdCA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQwpuYW1lcyhnZW5lX2xpc3QpIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRnZW5lICAjIFVzZSB0aGUgJGdlbmUgY29sdW1uIGZvciBnZW5lIHN5bWJvbHMKZ2VuZV9saXN0IDwtIHNvcnQoZ2VuZV9saXN0LCBkZWNyZWFzaW5nID0gVFJVRSkKCiMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcyBmb3IgR1NFQQpnZW5lX2RmIDwtIGJpdHIobmFtZXMoZ2VuZV9saXN0KSwgZnJvbVR5cGUgPSAiU1lNQk9MIiwgdG9UeXBlID0gIkVOVFJFWklEIiwgT3JnRGIgPSBvcmcuSHMuZWcuZGIpCgojIEVuc3VyZSB0aGUgZ2VuZSBsaXN0IG1hdGNoZXMgdGhlIEVudHJleiBJRHMKZ2VuZV9saXN0IDwtIGdlbmVfbGlzdFtuYW1lcyhnZW5lX2xpc3QpICVpbiUgZ2VuZV9kZiRTWU1CT0xdCgojIFJlcGxhY2UgZ2VuZSBzeW1ib2xzIHdpdGggRW50cmV6IElEcwpuYW1lcyhnZW5lX2xpc3QpIDwtIGdlbmVfZGYkRU5UUkVaSURbbWF0Y2gobmFtZXMoZ2VuZV9saXN0KSwgZ2VuZV9kZiRTWU1CT0wpXQoKIyBSdW4gR1NFQSB1c2luZyBLRUdHIHBhdGh3YXlzCmdzZWFfa2VnZyA8LSBnc2VLRUdHKGdlbmVMaXN0ID0gZ2VuZV9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFBsb3QgdGhlIEdTRUEgcmVzdWx0cwpnc2VhcGxvdChnc2VhX2tlZ2csIGdlbmVTZXRJRCA9IDEsIHRpdGxlID0gIlRvcCBLRUdHIFBhdGh3YXkiKQoKIyBFeHRyYWN0IHRoZSBuYW1lIG9mIHRoZSB0b3AgS0VHRyBwYXRod2F5CnRvcF9wYXRod2F5IDwtIGdzZWFfa2VnZ0ByZXN1bHRbMSwgIkRlc2NyaXB0aW9uIl0KCiMgUGxvdCBHU0VBIHdpdGggdGhlIHRvcCBwYXRod2F5J3MgbmFtZSBhcyB0aGUgdGl0bGUKZ3NlYXBsb3QoZ3NlYV9rZWdnLCBnZW5lU2V0SUQgPSAxLCB0aXRsZSA9IHRvcF9wYXRod2F5KQoKCmBgYAoKCgoKIyA0LjIuIEVucmljaG1lbnQgQW5hbHlzaXMtMgpgYGB7ciAsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9CgojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcwpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShvcmcuSHMuZWcuZGIpCmxpYnJhcnkobXNpZ2RicikKbGlicmFyeShlbnJpY2hwbG90KQoKIyBMb2FkIEhhbGxtYXJrIGdlbmUgc2V0cyBmcm9tIG1zaWdkYnIKaGFsbG1hcmtfc2V0cyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiSCIpICAjICJIIiBpcyBmb3IgSGFsbG1hcmsgZ2VuZSBzZXRzCgojIEdldCB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcyBiYXNlZCBvbiBsb2cyIGZvbGQgY2hhbmdlIGFuZCBhZGp1c3RlZCBwLXZhbHVlCnVwcmVndWxhdGVkX2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc1tNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA+IDAuNSAmIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzW01hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDIDwgLTAuNSAmIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdCgojIENvbnZlcnQgZ2VuZSBzeW1ib2xzIHRvIHVwcGVyY2FzZSBmb3IgY29uc2lzdGVuY3kKdXByZWd1bGF0ZWRfZ2VuZXMkZ2VuZSA8LSB0b3VwcGVyKHVwcmVndWxhdGVkX2dlbmVzJGdlbmUpCmRvd25yZWd1bGF0ZWRfZ2VuZXMkZ2VuZSA8LSB0b3VwcGVyKGRvd25yZWd1bGF0ZWRfZ2VuZXMkZ2VuZSkKCiMgQ2hlY2sgZm9yIG92ZXJsYXAgYmV0d2VlbiB5b3VyIHVwcmVndWxhdGVkL2Rvd25yZWd1bGF0ZWQgZ2VuZXMgYW5kIEhhbGxtYXJrIGdlbmUgc2V0cwp1cHJlZ3VsYXRlZF9pbl9oYWxsbWFyayA8LSBpbnRlcnNlY3QodXByZWd1bGF0ZWRfZ2VuZXMkZ2VuZSwgaGFsbG1hcmtfc2V0cyRnZW5lX3N5bWJvbCkKZG93bnJlZ3VsYXRlZF9pbl9oYWxsbWFyayA8LSBpbnRlcnNlY3QoZG93bnJlZ3VsYXRlZF9nZW5lcyRnZW5lLCBoYWxsbWFya19zZXRzJGdlbmVfc3ltYm9sKQoKIyBQcmludCB0aGUgbnVtYmVyIG9mIG92ZXJsYXBwaW5nIGdlbmVzIGZvciBib3RoIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzCmNhdCgiTnVtYmVyIG9mIHVwcmVndWxhdGVkIGdlbmVzIGluIEhhbGxtYXJrIGdlbmUgc2V0czoiLCBsZW5ndGgodXByZWd1bGF0ZWRfaW5faGFsbG1hcmspLCAiXG4iKQpjYXQoIk51bWJlciBvZiBkb3ducmVndWxhdGVkIGdlbmVzIGluIEhhbGxtYXJrIGdlbmUgc2V0czoiLCBsZW5ndGgoZG93bnJlZ3VsYXRlZF9pbl9oYWxsbWFyayksICJcbiIpCgojIElmIHRoZXJlIGFyZSBnZW5lcyB0byBhbmFseXplLCBwcm9jZWVkIHdpdGggZW5yaWNobWVudCBhbmFseXNpcwppZiAobGVuZ3RoKHVwcmVndWxhdGVkX2luX2hhbGxtYXJrKSA+IDApIHsKICAjIFBlcmZvcm0gZW5yaWNobWVudCBhbmFseXNpcyBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMgdXNpbmcgSGFsbG1hcmsgZ2VuZSBzZXRzCiAgaGFsbG1hcmtfdXAgPC0gZW5yaWNoZXIoZ2VuZSA9IHVwcmVndWxhdGVkX2luX2hhbGxtYXJrLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBURVJNMkdFTkUgPSBoYWxsbWFya19zZXRzWywgYygiZ3NfbmFtZSIsICJnZW5lX3N5bWJvbCIpXSwgICMgRW5zdXJlIFRFUk0yR0VORSB1c2VzIGNvcnJlY3QgY29sdW1ucwogICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCiAgIyBDaGVjayBpZiByZXN1bHRzIGV4aXN0CiAgaWYgKCFpcy5udWxsKGhhbGxtYXJrX3VwKSAmJiBucm93KGhhbGxtYXJrX3VwKSA+IDApIHsKICAgICMgVmlzdWFsaXplIHJlc3VsdHMgaWYgYXZhaWxhYmxlCiAgICBkb3RwbG90KGhhbGxtYXJrX3VwLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiSGFsbG1hcmsgUGF0aHdheSBFbnJpY2htZW50IGZvciBVcHJlZ3VsYXRlZCBHZW5lcyIpCiAgfSBlbHNlIHsKICAgIGNhdCgiTm8gc2lnbmlmaWNhbnQgZW5yaWNobWVudCBmb3VuZCBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMuXG4iKQogIH0KfSBlbHNlIHsKICBjYXQoIk5vIHVwcmVndWxhdGVkIGdlbmVzIG92ZXJsYXAgd2l0aCBIYWxsbWFyayBnZW5lIHNldHMuXG4iKQp9CgppZiAobGVuZ3RoKGRvd25yZWd1bGF0ZWRfaW5faGFsbG1hcmspID4gMCkgewogICMgUGVyZm9ybSBlbnJpY2htZW50IGFuYWx5c2lzIGZvciBkb3ducmVndWxhdGVkIGdlbmVzIHVzaW5nIEhhbGxtYXJrIGdlbmUgc2V0cwogIGhhbGxtYXJrX2Rvd24gPC0gZW5yaWNoZXIoZ2VuZSA9IGRvd25yZWd1bGF0ZWRfaW5faGFsbG1hcmssIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVEVSTTJHRU5FID0gaGFsbG1hcmtfc2V0c1ssIGMoImdzX25hbWUiLCAiZ2VuZV9zeW1ib2wiKV0sICAjIEVuc3VyZSBURVJNMkdFTkUgdXNlcyBjb3JyZWN0IGNvbHVtbnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCiAgIyBDaGVjayBpZiByZXN1bHRzIGV4aXN0CiAgaWYgKCFpcy5udWxsKGhhbGxtYXJrX2Rvd24pICYmIG5yb3coaGFsbG1hcmtfZG93bikgPiAwKSB7CiAgICAjIFZpc3VhbGl6ZSByZXN1bHRzIGlmIGF2YWlsYWJsZQogICAgZG90cGxvdChoYWxsbWFya19kb3duLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiSGFsbG1hcmsgUGF0aHdheSBFbnJpY2htZW50IGZvciBEb3ducmVndWxhdGVkIEdlbmVzIikKICB9IGVsc2UgewogICAgY2F0KCJObyBzaWduaWZpY2FudCBlbnJpY2htZW50IGZvdW5kIGZvciBkb3ducmVndWxhdGVkIGdlbmVzLlxuIikKICB9Cn0gZWxzZSB7CiAgY2F0KCJObyBkb3ducmVndWxhdGVkIGdlbmVzIG92ZXJsYXAgd2l0aCBIYWxsbWFyayBnZW5lIHNldHMuXG4iKQp9CgoKCgoKYGBgCiMgNC4zLiBIYWxsbWFyay1HU0VBCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgR2VuZSBTZXQgRW5yaWNobWVudCBBbmFseXNpcyAoR1NFQSkgZm9yIEhhbGxtYXJrIFBhdGh3YXlzCiMgQ3JlYXRlIGEgcmFua2VkIGxpc3Qgb2YgZ2VuZXMgKGxvZzJGQyBhcyByYW5raW5nIG1ldHJpYykKZ2VuZV9saXN0IDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDCm5hbWVzKGdlbmVfbGlzdCkgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGdlbmUKZ2VuZV9saXN0IDwtIHNvcnQoZ2VuZV9saXN0LCBkZWNyZWFzaW5nID0gVFJVRSkKCiMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcyBmb3IgR1NFQQpnZW5lX2RmIDwtIGJpdHIobmFtZXMoZ2VuZV9saXN0KSwgCiAgICAgICAgICAgICAgICBmcm9tVHlwZSA9ICJTWU1CT0wiLCAKICAgICAgICAgICAgICAgIHRvVHlwZSA9ICJFTlRSRVpJRCIsIAogICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIpCgojIEZpbHRlciBvdXQgZ2VuZXMgd2l0aG91dCBFbnRyZXogSUQgbWFwcGluZ3MKZ2VuZV9saXN0IDwtIGdlbmVfbGlzdFtuYW1lcyhnZW5lX2xpc3QpICVpbiUgZ2VuZV9kZiRTWU1CT0xdCgojIFJlcGxhY2UgZ2VuZSBzeW1ib2xzIHdpdGggRW50cmV6IElEcyBpbiB0aGUgZ2VuZSBsaXN0Cm5hbWVzKGdlbmVfbGlzdCkgPC0gZ2VuZV9kZiRFTlRSRVpJRFttYXRjaChuYW1lcyhnZW5lX2xpc3QpLCBnZW5lX2RmJFNZTUJPTCldCgojIFJ1biBHU0VBIHVzaW5nIEhhbGxtYXJrIHBhdGh3YXlzCmdzZWFfaGFsbG1hcmsgPC0gR1NFQShnZW5lTGlzdCA9IGdlbmVfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICBURVJNMkdFTkUgPSBoYWxsbWFya19zZXRzWywgYygiZ3NfbmFtZSIsICJlbnRyZXpfZ2VuZSIpXSwgCiAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBDaGVjayBhbmQgdmlzdWFsaXplIEdTRUEgcmVzdWx0cwppZiAoIWlzLm51bGwoZ3NlYV9oYWxsbWFyaykgJiYgbnJvdyhnc2VhX2hhbGxtYXJrKSA+IDApIHsKICAjIFZpc3VhbGl6ZSB0b3AgR1NFQSByZXN1bHRzIGZvciBIYWxsbWFyayBwYXRod2F5cwogIGRvdHBsb3QoZ3NlYV9oYWxsbWFyaywgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIkdTRUEgZm9yIEhhbGxtYXJrIFBhdGh3YXlzIikKICAKICAjIFBsb3QgZW5yaWNobWVudCBzY29yZSBmb3IgdGhlIHRvcCBwYXRod2F5CiAgZ3NlYXBsb3QoZ3NlYV9oYWxsbWFyaywgZ2VuZVNldElEID0gMSwgdGl0bGUgPSAiVG9wIEhhbGxtYXJrIFBhdGh3YXkiKQogIAogICMgRXh0cmFjdCB0aGUgbmFtZSBvZiB0aGUgdG9wIEhhbGxtYXJrIHBhdGh3YXkKICB0b3BfaGFsbG1hcmsgPC0gZ3NlYV9oYWxsbWFya0ByZXN1bHRbMSwgIkRlc2NyaXB0aW9uIl0KICAKICAjIFBsb3QgR1NFQSB3aXRoIHRoZSB0b3AgcGF0aHdheSdzIG5hbWUgYXMgdGhlIHRpdGxlCiAgZ3NlYXBsb3QoZ3NlYV9oYWxsbWFyaywgZ2VuZVNldElEID0gMSwgdGl0bGUgPSB0b3BfaGFsbG1hcmspCn0gZWxzZSB7CiAgY2F0KCJObyBzaWduaWZpY2FudCBHU0VBIHJlc3VsdHMgZm9yIEhhbGxtYXJrIHBhdGh3YXlzLlxuIikKfQoKCgpgYGAKCgoKIyA1LiBnZ3Bsb3QyIGZvciBWb2xjYW5vCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3JlcGVsKQoKIyBJZGVudGlmeSB0b3AgYW5kIGJvdHRvbSBnZW5lcwp0b3BfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzW01hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjA1ICYgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGF2Z19sb2cyRkMgPiAwLjUsIF0KYm90dG9tX2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc1tNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkcF92YWxfYWRqIDwgMC4wNSAmIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDIDwgLTAuNSwgXQoKIyBDcmVhdGUgYSBuZXcgY29sdW1uIGZvciBjb2xvciBiYXNlZCBvbiBzaWduaWZpY2FuY2UKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGNvbG9yIDwtIGlmZWxzZShNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA+IDAuNSwgIlVwcmVndWxhdGVkIGdlbmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDIDwgLTAuNSwgIkRvd25yZWd1bGF0ZWQgZ2VuZXMiLCAiTm9uc2lnbmlmaWNhbnQiKSkKCiMgQ3JlYXRlIGEgdm9sY2FubyBwbG90CmdncGxvdChNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMsIGFlcyh4ID0gYXZnX2xvZzJGQywgeSA9IC1sb2cxMChwX3ZhbF9hZGopKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gY29sb3IpLCBhbHBoYSA9IDAuNywgc2l6ZSA9IDIpICsKICAKICAjIEFkZCBsYWJlbHMgZm9yIHRvcCBhbmQgYm90dG9tIGdlbmVzCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSB0b3BfZ2VuZXMsIGFlcyhsYWJlbCA9IGdlbmUpLCBjb2xvciA9ICJibGFjayIsIHZqdXN0ID0gMSwgZm9udGZhY2UgPSAiYm9sZCIpICsKICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGJvdHRvbV9nZW5lcywgYWVzKGxhYmVsID0gZ2VuZSksIGNvbG9yID0gImJsYWNrIiwgdmp1c3QgPSAtMSwgZm9udGZhY2UgPSAiYm9sZCIpICsKICAKICAjIEN1c3RvbWl6ZSBsYWJlbHMgYW5kIHRpdGxlCiAgbGFicyh0aXRsZSA9ICJWb2xjYW5vIFBsb3QiLAogICAgICAgeCA9ICJsb2cyIEZvbGQgQ2hhbmdlIiwKICAgICAgIHkgPSAiLWxvZzEwKHAtdmFsdWUpIikgKwogIAogICMgIyBBZGQgc2lnbmlmaWNhbmNlIHRocmVzaG9sZCBsaW5lcwogICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAtbG9nMTAoMC4wMDAwMSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgKwogICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0wLjUsIDAuNSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgKwogIAogICMgU2V0IGNvbG9ycyBmb3IgdG9wIGFuZCBib3R0b20gZ2VuZXMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiVXByZWd1bGF0ZWQgZ2VuZXMiID0gInJlZCIsICJEb3ducmVndWxhdGVkIGdlbmVzIiA9ICJibHVlIiwgIk5vbnNpZ25pZmljYW50IiA9ICJkYXJrZ3JleSIpKSArCiAgCiAgIyBDdXN0b21pemUgdGhlbWUgaWYgbmVlZGVkCiAgdGhlbWVfbWluaW1hbCgpCgoKCgoKYGBgCgoKIyA1LiBnZ3Bsb3QzIGZvciBWb2xjYW5vCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3JlcGVsKQoKIyBJZGVudGlmeSB0b3AgYW5kIGJvdHRvbSBnZW5lcwp0b3BfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzW01hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjAwMDAxICYgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGF2Z19sb2cyRkMgPiA0LCBdCmJvdHRvbV9nZW5lcyA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHNbTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJHBfdmFsX2FkaiA8IDAuMDAwMDEgJiBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA8IC00LCBdCgojIENyZWF0ZSBhIG5ldyBjb2x1bW4gZm9yIGNvbG9yIGJhc2VkIG9uIHNpZ25pZmljYW5jZQpNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkY29sb3IgPC0gaWZlbHNlKE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDID4gMC41LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVXByZWd1bGF0ZWQgZ2VuZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA8IC0wLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRG93bnJlZ3VsYXRlZCBnZW5lcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9uc2lnbmlmaWNhbnQiKSkKCiMgQ3JlYXRlIHRoZSB2b2xjYW5vIHBsb3QKZ2dwbG90KE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscywgYWVzKHggPSBhdmdfbG9nMkZDLCB5ID0gLWxvZzEwKHBfdmFsX2FkaikpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjb2xvciksIGFscGhhID0gMC43LCBzaXplID0gMikgKwogIAogICMgQWRkIGxhYmVscyBuZXh0IHRvIHRoZSBkb3RzIHdpdGhvdXQgcmVwZWwgbGluZXMKICBnZW9tX3RleHQoZGF0YSA9IHRvcF9nZW5lcywgYWVzKGxhYmVsID0gZ2VuZSksIGhqdXN0ID0gLTAuMiwgdmp1c3QgPSAwLCBzaXplID0gMywgY29sb3IgPSAiYmxhY2siLCBmb250ZmFjZSA9ICJib2xkIikgKwogIGdlb21fdGV4dChkYXRhID0gYm90dG9tX2dlbmVzLCBhZXMobGFiZWwgPSBnZW5lKSwgaGp1c3QgPSAxLjIsIHZqdXN0ID0gMCwgc2l6ZSA9IDMsIGNvbG9yID0gImJsYWNrIiwgZm9udGZhY2UgPSAiYm9sZCIpICsKICAKICAjIEN1c3RvbWl6ZSBsYWJlbHMgYW5kIHRpdGxlCiAgbGFicyh0aXRsZSA9ICJWb2xjYW5vIFBsb3QiLAogICAgICAgeCA9ICJsb2cyIEZvbGQgQ2hhbmdlIiwKICAgICAgIHkgPSAiLWxvZzEwKHAtdmFsdWUpIikgKwogIAogICMgQWRkIHNpZ25pZmljYW5jZSB0aHJlc2hvbGQgbGluZXMKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAtbG9nMTAoMC4wMDAwMSksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoLTAuNSwgMC41KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSArCiAgCiAgIyBTZXQgY29sb3JzIGZvciB0b3AgYW5kIGJvdHRvbSBnZW5lcwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJVcHJlZ3VsYXRlZCBnZW5lcyIgPSAicmVkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRvd25yZWd1bGF0ZWQgZ2VuZXMiID0gImJsdWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9uc2lnbmlmaWNhbnQiID0gImRhcmtncmV5IikpICsKICAKICAjIEN1c3RvbWl6ZSB0aGVtZQogIHRoZW1lX21pbmltYWwoKQoKCmBgYAoK