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 > 2 & 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 < -1 & 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 = 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$gene, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:many mapping between keys and columns
Avis : 6.03% 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 : 12.5% 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 = 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)
# 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 (20.52% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Avis : 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)Avis : For some of the pathways the P-values were likely overestimated. For such pathways log2err is set to NA.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 > 2 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05, ]
downregulated_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -1 & 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: 1016
cat("Number of downregulated genes in Hallmark gene sets:", length(downregulated_in_hallmark), "\n")
Number of downregulated genes in Hallmark gene sets: 76
# 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
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 <- Malignant_CD4Tcells_vs_Normal_CD4Tcells[Malignant_CD4Tcells_vs_Normal_CD4Tcells$p_val_adj < 0.05 & Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 1.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 < -1.5, ]
# Create a new column for color based on significance
Malignant_CD4Tcells_vs_Normal_CD4Tcells$color <- ifelse(Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC > 1.5, "Upregulated genes",
ifelse(Malignant_CD4Tcells_vs_Normal_CD4Tcells$avg_log2FC < -1.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.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
LS0tCnRpdGxlOiAiRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMgb2YgTWFsaWduYW50IENENFRjZWxscyB2cyBDb250cm9sKE5vcm1hbCBDRDQgVGNlbGxzKS1HU0VBIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KEF6aW11dGgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQpgYGAKCiMgMi4gUGVyZm9ybSBERSBhbmFseXNpcyB1c2luZyBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgZ2VuZXMKYGBge3IgZGF0YTEsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIDwtIHJlYWQuY3N2KCIwLWltcF9Sb2JqLzEtTUFTVF93aXRoX2JhdGNoX2FzX0NvdmFyaWF0ZV93aXRoX21lYW5FeHByZXNzaW9uLmNzdiIsIGhlYWRlciA9IFQpCmBgYAoKIyAzLiBDcmVhdGUgdGhlIEVuaGFuY2VkVm9sY2FubyBwbG90CmBgYHtyIGVuaGFuY2VkViwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTE2fQoKRW5oYW5jZWRWb2xjYW5vKE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscywKICAgICAgICAgICAgICAgIGxhYiA9IE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRnZW5lLAogICAgICAgICAgICAgICAgeCA9ICJhdmdfbG9nMkZDIiwKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHRpdGxlID0gIk1BU1Qgd2l0aCBCYXRjaCBDb3JyZWN0aW9uIChBbGwgR2VuZXMpIiwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjApCgoKRW5oYW5jZWRWb2xjYW5vKE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscywgCiAgICAgICAgICAgICAgICBsYWIgPSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsIAogICAgICAgICAgICAgICAgeSA9ICJwX3ZhbF9hZGoiLAogICAgICAgICAgICAgICAgc2VsZWN0TGFiID0gYygnRVBDQU0nLCAnQkNBVDEnLCAnS0lSM0RMMicsICdGT1hNMScsICdUV0lTVDEnLCAnVE5GU0Y5JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdDRDgwJywgICdJTDFCJywgJ1JQUzRZMScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUw3UicsICdUQ0Y3JywgICdNS0k2NycsICdDRDcwJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdJTDJSQScsJ1RSQlY2LTInLCAnVFJCVjEwLTMnLCAnVFJCVjQtMicsICdUUkJWOScsICdUUkJWNy05JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdUUkFWMTItMScsICdDRDhCJywgJ0ZDR1IzQScsICdHTkxZJywgJ0ZPWFAzJywgJ1NFTEwnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0dJTUFQMScsICdSSVBPUjInLCAnTEVGMScsICdIT1hDOScsICdTUDUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ0NMMTcnLCAnRVRWNCcsICdUSFkxJywgJ0ZPWEEyJywgJ0lUR0FEJywgJ1MxMDBQJywgJ1RCWDQnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lEMScsICdYQ0wxJywgJ1NPWDInLCAnQ0QyNycsICdDRDI4JywnUExTMycsJ0NENzAnLCdSQUIyNScgLCAnVFJCVjI3JywgJ1RSQlYyJyksCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJNYWxpZ25hbnQgQ0Q0IFQgY2VsbHMoY2VsbCBsaW5lcykgdnMgbm9ybWFsIENENCBUIGNlbGxzIiwKICAgICAgICAgICAgICAgIHhsYWIgPSBicXVvdGUofkxvZ1syXX4gJ2ZvbGQgY2hhbmdlJyksCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMS41LCAKICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDMuMCwKICAgICAgICAgICAgICAgIGxhYlNpemUgPSA1LjAsCiAgICAgICAgICAgICAgICBib3hlZExhYmVscyA9IFRSVUUsCiAgICAgICAgICAgICAgICBjb2xBbHBoYSA9IDAuNSwKICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywKICAgICAgICAgICAgICAgIGxlZ2VuZExhYlNpemUgPSAxMCwKICAgICAgICAgICAgICAgIGxlZ2VuZEljb25TaXplID0gNC4wLAogICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgd2lkdGhDb25uZWN0b3JzID0gMC41LAogICAgICAgICAgICAgICAgY29sQ29ubmVjdG9ycyA9ICdncmV5NTAnLAogICAgICAgICAgICAgICAgYXJyb3doZWFkcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgbWF4Lm92ZXJsYXBzID0gMzApCgoKbGlicmFyeShkcGx5cikKbGlicmFyeShFbmhhbmNlZFZvbGNhbm8pCgojIEFzc3VtaW5nIHlvdSBoYXZlIGEgZGF0YSBmcmFtZSBuYW1lZCBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMKIyBGaWx0ZXIgZ2VuZXMgYmFzZWQgb24gbG93ZXN0IHAtdmFsdWVzIGJ1dCBpbmNsdWRlIGFsbCBnZW5lcwpmaWx0ZXJlZF9nZW5lcyA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgJT4lCiAgYXJyYW5nZShwX3ZhbF9hZGosIGRlc2MoYWJzKGF2Z19sb2cyRkMpKSkKCiMgQ3JlYXRlIHRoZSBFbmhhbmNlZFZvbGNhbm8gcGxvdCB3aXRoIHRoZSBmaWx0ZXJlZCBkYXRhCkVuaGFuY2VkVm9sY2FubygKICBmaWx0ZXJlZF9nZW5lcywgCiAgbGFiID0gaWZlbHNlKGZpbHRlcmVkX2dlbmVzJHBfdmFsX2FkaiA8PSAwLjA1ICYgYWJzKGZpbHRlcmVkX2dlbmVzJGF2Z19sb2cyRkMpID49IDEuMCwgZmlsdGVyZWRfZ2VuZXMkZ2VuZSwgTkEpLAogIHggPSAiYXZnX2xvZzJGQyIsIAogIHkgPSAicF92YWxfYWRqIiwKICB0aXRsZSA9ICJNYWxpZ25hbnQgQ0Q0IFQgY2VsbHMoY2VsbCBsaW5lcykgdnMgbm9ybWFsIENENCBUIGNlbGxzIiwKICBwQ3V0b2ZmID0gMC4wNSwKICBGQ2N1dG9mZiA9IDEuMCwKICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsIAogIGxhYkNvbCA9ICdibGFjaycsCiAgbGFiRmFjZSA9ICdib2xkJywKICBib3hlZExhYmVscyA9IEZBTFNFLCAgIyBTZXQgdG8gRkFMU0UgdG8gcmVtb3ZlIGJveGVkIGxhYmVscwogIHBvaW50U2l6ZSA9IDMuMCwKICBsYWJTaXplID0gNS4wLAogIGNvbCA9IGMoJ2dyZXk3MCcsICdibGFjaycsICdibHVlJywgJ3JlZCcpLCAgIyBDdXN0b21pemUgcG9pbnQgY29sb3JzCiAgc2VsZWN0TGFiID0gZmlsdGVyZWRfZ2VuZXMkZ2VuZVtmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nMkZDKSA+PSAxLjBdICAjIE9ubHkgbGFiZWwgc2lnbmlmaWNhbnQgZ2VuZXMKKQoKCgpFbmhhbmNlZFZvbGNhbm8oCiAgZmlsdGVyZWRfZ2VuZXMsIAogIGxhYiA9IGlmZWxzZShmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nMkZDKSA+PSAxLjAsIGZpbHRlcmVkX2dlbmVzJGdlbmUsIE5BKSwKICB4ID0gImF2Z19sb2cyRkMiLCAKICB5ID0gInBfdmFsX2FkaiIsCiAgdGl0bGUgPSAiTWFsaWduYW50IENENCBUIGNlbGxzIChjZWxsIGxpbmVzKSB2cyBOb3JtYWwgQ0Q0IFQgY2VsbHMiLAogIHN1YnRpdGxlID0gIkhpZ2hsaWdodGluZyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMiLAogIHBDdXRvZmYgPSAwLjA1LAogIEZDY3V0b2ZmID0gMS4wLAogIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywKICBjb2xBbHBoYSA9IDAuOCwgICMgU2xpZ2h0IHRyYW5zcGFyZW5jeSBmb3Igbm9uLXNpZ25pZmljYW50IHBvaW50cwogIGNvbCA9IGMoJ2dyZXk3MCcsICdibGFjaycsICdibHVlJywgJ3JlZCcpLCAgIyBDdXN0b20gY29sb3Igc2NoZW1lCiAgZ3JpZGxpbmVzLm1ham9yID0gVFJVRSwKICBncmlkbGluZXMubWlub3IgPSBGQUxTRSwKICBzZWxlY3RMYWIgPSBmaWx0ZXJlZF9nZW5lcyRnZW5lW2ZpbHRlcmVkX2dlbmVzJHBfdmFsX2FkaiA8PSAwLjA1ICYgYWJzKGZpbHRlcmVkX2dlbmVzJGF2Z19sb2cyRkMpID49IDEuMF0KKSAKCgpgYGAKCgojIDQuIEVucmljaG1lbnQgQW5hbHlzaXMtMQpgYGB7ciBkYXRhMiwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTE2fQoKIyBTdGVwLWJ5LVN0ZXAgR3VpZGUgZm9yIEdlbmUgU2V0IEVucmljaG1lbnQgQW5hbHlzaXMgKEdTRUEpIG9yIE92ZXItUmVwcmVzZW50YXRpb24gQW5hbHlzaXMgKE9SQSkKCiMgTG9hZCB0aGUgbmVjZXNzYXJ5IGxpYnJhcmllcwpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShvcmcuSHMuZWcuZGIpCmxpYnJhcnkoZW5yaWNocGxvdCkKbGlicmFyeShSZWFjdG9tZVBBKQoKIyBHZXQgdXByZWd1bGF0ZWQgZ2VuZXMgYmFzZWQgb24gbG9nMkZDIGFuZCBwLXZhbHVlIHRocmVzaG9sZHMKdXByZWd1bGF0ZWRfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzW01hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDID4gMiAmIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdCgojIEdldCBkb3ducmVndWxhdGVkIGdlbmVzIGJhc2VkIG9uIGxvZzJGQyBhbmQgcC12YWx1ZSB0aHJlc2hvbGRzCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzW01hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDIDwgLTEgJiBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkcF92YWxfYWRqIDwgMC4wNSwgXQoKIyBHZW5lIE9udG9sb2d5IChHTykgRW5yaWNobWVudCBBbmFseXNpcwojIEdPIGVucmljaG1lbnQgZm9yIHVwcmVndWxhdGVkIGdlbmVzCmdvX3VwIDwtIGVucmljaEdPKGdlbmUgPSB1cHJlZ3VsYXRlZF9nZW5lcyRnZW5lLCAKICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAgICMgQmlvbG9naWNhbCBQcm9jZXNzIChCUCksIE1vbGVjdWxhciBGdW5jdGlvbiAoTUYpLCBDZWxsdWxhciBDb21wb25lbnQgKENDKQogICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIEdPIGVucmljaG1lbnQgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMKZ29fZG93biA8LSBlbnJpY2hHTyhnZW5lID0gZG93bnJlZ3VsYXRlZF9nZW5lcyRnZW5lLCAKICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJTWU1CT0wiLCAKICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAKICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlzdWFsaXplIHRoZSB0b3AgZW5yaWNoZWQgR08gdGVybXMKZG90cGxvdChnb191cCwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIkdPIEVucmljaG1lbnQgZm9yIFVwcmVndWxhdGVkIEdlbmVzIikKZG90cGxvdChnb19kb3duLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiR08gRW5yaWNobWVudCBmb3IgRG93bnJlZ3VsYXRlZCBHZW5lcyIpCgojIEtFR0cgUGF0aHdheSBFbnJpY2htZW50CiMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcyBmb3IgS0VHRyBhbmFseXNpcwp1cHJlZ3VsYXRlZF9lbnRyZXogPC0gYml0cih1cHJlZ3VsYXRlZF9nZW5lcyRnZW5lLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikkRU5UUkVaSUQKZG93bnJlZ3VsYXRlZF9lbnRyZXogPC0gYml0cihkb3ducmVndWxhdGVkX2dlbmVzJGdlbmUsIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKSRFTlRSRVpJRAoKIyBLRUdHIHBhdGh3YXkgZW5yaWNobWVudCBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMKa2VnZ191cCA8LSBlbnJpY2hLRUdHKGdlbmUgPSB1cHJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBLRUdHIHBhdGh3YXkgZW5yaWNobWVudCBmb3IgZG93bnJlZ3VsYXRlZCBnZW5lcwprZWdnX2Rvd24gPC0gZW5yaWNoS0VHRyhnZW5lID0gZG93bnJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2EiLCAKICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlzdWFsaXplIEtFR0cgcGF0aHdheSByZXN1bHRzCmRvdHBsb3Qoa2VnZ191cCwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIktFR0cgUGF0aHdheSBFbnJpY2htZW50IGZvciBVcHJlZ3VsYXRlZCBHZW5lcyIpCmRvdHBsb3Qoa2VnZ19kb3duLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiS0VHRyBQYXRod2F5IEVucmljaG1lbnQgZm9yIERvd25yZWd1bGF0ZWQgR2VuZXMiKQoKIyBSZWFjdG9tZSBQYXRod2F5IEVucmljaG1lbnQKIyBSZWFjdG9tZSBwYXRod2F5IGVucmljaG1lbnQgZm9yIHVwcmVndWxhdGVkIGdlbmVzCnJlYWN0b21lX3VwIDwtIGVucmljaFBhdGh3YXkoZ2VuZSA9IHVwcmVndWxhdGVkX2VudHJleiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHVtYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBSZWFjdG9tZSBwYXRod2F5IGVucmljaG1lbnQgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMKcmVhY3RvbWVfZG93biA8LSBlbnJpY2hQYXRod2F5KGdlbmUgPSBkb3ducmVndWxhdGVkX2VudHJleiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJodW1hbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlzdWFsaXplIFJlYWN0b21lIHBhdGh3YXlzCmRvdHBsb3QocmVhY3RvbWVfdXAsIHNob3dDYXRlZ29yeSA9IDIwLCB0aXRsZSA9ICJSZWFjdG9tZSBQYXRod2F5IEVucmljaG1lbnQgZm9yIFVwcmVndWxhdGVkIEdlbmVzIikKZG90cGxvdChyZWFjdG9tZV9kb3duLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiUmVhY3RvbWUgUGF0aHdheSBFbnJpY2htZW50IGZvciBEb3ducmVndWxhdGVkIEdlbmVzIikKCiMgR2VuZSBTZXQgRW5yaWNobWVudCBBbmFseXNpcyAoR1NFQSkKIyBDcmVhdGUgYSByYW5rZWQgbGlzdCBvZiBnZW5lcyAobG9nMkZDIGFzIHJhbmtpbmcgbWV0cmljKQpnZW5lX2xpc3QgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGF2Z19sb2cyRkMKbmFtZXMoZ2VuZV9saXN0KSA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkZ2VuZSAgIyBVc2UgdGhlICRnZW5lIGNvbHVtbiBmb3IgZ2VuZSBzeW1ib2xzCmdlbmVfbGlzdCA8LSBzb3J0KGdlbmVfbGlzdCwgZGVjcmVhc2luZyA9IFRSVUUpCgojIENvbnZlcnQgZ2VuZSBzeW1ib2xzIHRvIEVudHJleiBJRHMgZm9yIEdTRUEKZ2VuZV9kZiA8LSBiaXRyKG5hbWVzKGdlbmVfbGlzdCksIGZyb21UeXBlID0gIlNZTUJPTCIsIHRvVHlwZSA9ICJFTlRSRVpJRCIsIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQoKIyBFbnN1cmUgdGhlIGdlbmUgbGlzdCBtYXRjaGVzIHRoZSBFbnRyZXogSURzCmdlbmVfbGlzdCA8LSBnZW5lX2xpc3RbbmFtZXMoZ2VuZV9saXN0KSAlaW4lIGdlbmVfZGYkU1lNQk9MXQoKIyBSZXBsYWNlIGdlbmUgc3ltYm9scyB3aXRoIEVudHJleiBJRHMKbmFtZXMoZ2VuZV9saXN0KSA8LSBnZW5lX2RmJEVOVFJFWklEW21hdGNoKG5hbWVzKGdlbmVfbGlzdCksIGdlbmVfZGYkU1lNQk9MKV0KCiMgUnVuIEdTRUEgdXNpbmcgS0VHRyBwYXRod2F5cwpnc2VhX2tlZ2cgPC0gZ3NlS0VHRyhnZW5lTGlzdCA9IGdlbmVfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYSIsIAogICAgICAgICAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1KQoKIyBQbG90IHRoZSBHU0VBIHJlc3VsdHMKZ3NlYXBsb3QoZ3NlYV9rZWdnLCBnZW5lU2V0SUQgPSAxLCB0aXRsZSA9ICJUb3AgS0VHRyBQYXRod2F5IikKCiMgRXh0cmFjdCB0aGUgbmFtZSBvZiB0aGUgdG9wIEtFR0cgcGF0aHdheQp0b3BfcGF0aHdheSA8LSBnc2VhX2tlZ2dAcmVzdWx0WzEsICJEZXNjcmlwdGlvbiJdCgojIFBsb3QgR1NFQSB3aXRoIHRoZSB0b3AgcGF0aHdheSdzIG5hbWUgYXMgdGhlIHRpdGxlCmdzZWFwbG90KGdzZWFfa2VnZywgZ2VuZVNldElEID0gMSwgdGl0bGUgPSB0b3BfcGF0aHdheSkKCgpgYGAKIyA0LjIuIEVucmljaG1lbnQgQW5hbHlzaXMtMgpgYGB7ciBkYXRhLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CgojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcwpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShvcmcuSHMuZWcuZGIpCmxpYnJhcnkobXNpZ2RicikKbGlicmFyeShlbnJpY2hwbG90KQoKIyBMb2FkIEhhbGxtYXJrIGdlbmUgc2V0cyBmcm9tIG1zaWdkYnIKaGFsbG1hcmtfc2V0cyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiSCIpICAjICJIIiBpcyBmb3IgSGFsbG1hcmsgZ2VuZSBzZXRzCgojIEdldCB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcyBiYXNlZCBvbiBsb2cyIGZvbGQgY2hhbmdlIGFuZCBhZGp1c3RlZCBwLXZhbHVlCnVwcmVndWxhdGVkX2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc1tNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA+IDIgJiBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkcF92YWxfYWRqIDwgMC4wNSwgXQpkb3ducmVndWxhdGVkX2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc1tNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA8IC0xICYgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUsIF0KCiMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gdXBwZXJjYXNlIGZvciBjb25zaXN0ZW5jeQp1cHJlZ3VsYXRlZF9nZW5lcyRnZW5lIDwtIHRvdXBwZXIodXByZWd1bGF0ZWRfZ2VuZXMkZ2VuZSkKZG93bnJlZ3VsYXRlZF9nZW5lcyRnZW5lIDwtIHRvdXBwZXIoZG93bnJlZ3VsYXRlZF9nZW5lcyRnZW5lKQoKIyBDaGVjayBmb3Igb3ZlcmxhcCBiZXR3ZWVuIHlvdXIgdXByZWd1bGF0ZWQvZG93bnJlZ3VsYXRlZCBnZW5lcyBhbmQgSGFsbG1hcmsgZ2VuZSBzZXRzCnVwcmVndWxhdGVkX2luX2hhbGxtYXJrIDwtIGludGVyc2VjdCh1cHJlZ3VsYXRlZF9nZW5lcyRnZW5lLCBoYWxsbWFya19zZXRzJGdlbmVfc3ltYm9sKQpkb3ducmVndWxhdGVkX2luX2hhbGxtYXJrIDwtIGludGVyc2VjdChkb3ducmVndWxhdGVkX2dlbmVzJGdlbmUsIGhhbGxtYXJrX3NldHMkZ2VuZV9zeW1ib2wpCgojIFByaW50IHRoZSBudW1iZXIgb2Ygb3ZlcmxhcHBpbmcgZ2VuZXMgZm9yIGJvdGggdXByZWd1bGF0ZWQgYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMKY2F0KCJOdW1iZXIgb2YgdXByZWd1bGF0ZWQgZ2VuZXMgaW4gSGFsbG1hcmsgZ2VuZSBzZXRzOiIsIGxlbmd0aCh1cHJlZ3VsYXRlZF9pbl9oYWxsbWFyayksICJcbiIpCmNhdCgiTnVtYmVyIG9mIGRvd25yZWd1bGF0ZWQgZ2VuZXMgaW4gSGFsbG1hcmsgZ2VuZSBzZXRzOiIsIGxlbmd0aChkb3ducmVndWxhdGVkX2luX2hhbGxtYXJrKSwgIlxuIikKCiMgSWYgdGhlcmUgYXJlIGdlbmVzIHRvIGFuYWx5emUsIHByb2NlZWQgd2l0aCBlbnJpY2htZW50IGFuYWx5c2lzCmlmIChsZW5ndGgodXByZWd1bGF0ZWRfaW5faGFsbG1hcmspID4gMCkgewogICMgUGVyZm9ybSBlbnJpY2htZW50IGFuYWx5c2lzIGZvciB1cHJlZ3VsYXRlZCBnZW5lcyB1c2luZyBIYWxsbWFyayBnZW5lIHNldHMKICBoYWxsbWFya191cCA8LSBlbnJpY2hlcihnZW5lID0gdXByZWd1bGF0ZWRfaW5faGFsbG1hcmssIAogICAgICAgICAgICAgICAgICAgICAgICAgIFRFUk0yR0VORSA9IGhhbGxtYXJrX3NldHNbLCBjKCJnc19uYW1lIiwgImdlbmVfc3ltYm9sIildLCAgIyBFbnN1cmUgVEVSTTJHRU5FIHVzZXMgY29ycmVjdCBjb2x1bW5zCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKICAjIENoZWNrIGlmIHJlc3VsdHMgZXhpc3QKICBpZiAoIWlzLm51bGwoaGFsbG1hcmtfdXApICYmIG5yb3coaGFsbG1hcmtfdXApID4gMCkgewogICAgIyBWaXN1YWxpemUgcmVzdWx0cyBpZiBhdmFpbGFibGUKICAgIGRvdHBsb3QoaGFsbG1hcmtfdXAsIHNob3dDYXRlZ29yeSA9IDIwLCB0aXRsZSA9ICJIYWxsbWFyayBQYXRod2F5IEVucmljaG1lbnQgZm9yIFVwcmVndWxhdGVkIEdlbmVzIikKICB9IGVsc2UgewogICAgY2F0KCJObyBzaWduaWZpY2FudCBlbnJpY2htZW50IGZvdW5kIGZvciB1cHJlZ3VsYXRlZCBnZW5lcy5cbiIpCiAgfQp9IGVsc2UgewogIGNhdCgiTm8gdXByZWd1bGF0ZWQgZ2VuZXMgb3ZlcmxhcCB3aXRoIEhhbGxtYXJrIGdlbmUgc2V0cy5cbiIpCn0KCmlmIChsZW5ndGgoZG93bnJlZ3VsYXRlZF9pbl9oYWxsbWFyaykgPiAwKSB7CiAgIyBQZXJmb3JtIGVucmljaG1lbnQgYW5hbHlzaXMgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMgdXNpbmcgSGFsbG1hcmsgZ2VuZSBzZXRzCiAgaGFsbG1hcmtfZG93biA8LSBlbnJpY2hlcihnZW5lID0gZG93bnJlZ3VsYXRlZF9pbl9oYWxsbWFyaywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURVJNMkdFTkUgPSBoYWxsbWFya19zZXRzWywgYygiZ3NfbmFtZSIsICJnZW5lX3N5bWJvbCIpXSwgICMgRW5zdXJlIFRFUk0yR0VORSB1c2VzIGNvcnJlY3QgY29sdW1ucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKICAjIENoZWNrIGlmIHJlc3VsdHMgZXhpc3QKICBpZiAoIWlzLm51bGwoaGFsbG1hcmtfZG93bikgJiYgbnJvdyhoYWxsbWFya19kb3duKSA+IDApIHsKICAgICMgVmlzdWFsaXplIHJlc3VsdHMgaWYgYXZhaWxhYmxlCiAgICBkb3RwbG90KGhhbGxtYXJrX2Rvd24sIHNob3dDYXRlZ29yeSA9IDIwLCB0aXRsZSA9ICJIYWxsbWFyayBQYXRod2F5IEVucmljaG1lbnQgZm9yIERvd25yZWd1bGF0ZWQgR2VuZXMiKQogIH0gZWxzZSB7CiAgICBjYXQoIk5vIHNpZ25pZmljYW50IGVucmljaG1lbnQgZm91bmQgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMuXG4iKQogIH0KfSBlbHNlIHsKICBjYXQoIk5vIGRvd25yZWd1bGF0ZWQgZ2VuZXMgb3ZlcmxhcCB3aXRoIEhhbGxtYXJrIGdlbmUgc2V0cy5cbiIpCn0KCgpgYGAKCiMgNS4gQmFyIFBMT1QKYGBge3IgZGF0YTMsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIEZpbHRlciBmb3Igc2lnbmlmaWNhbnQgcGF0aHdheXMKdG9wX2tlZ2dfdXAgPC0ga2VnZ191cEByZXN1bHRba2VnZ191cEByZXN1bHQkcC5hZGp1c3QgPCAwLjA1LCBdCnRvcF9rZWdnX2Rvd24gPC0ga2VnZ19kb3duQHJlc3VsdFtrZWdnX2Rvd25AcmVzdWx0JHAuYWRqdXN0IDwgMC4wNSwgXQoKIyBJZiB0aGVyZSBhcmUgbm90IGVub3VnaCBwYXRod2F5cywgY29uc2lkZXIgcmVsYXhpbmcgdGhlIHRocmVzaG9sZCBvciBjaGVja2luZyB0aGUgb3V0cHV0CnRvcF9rZWdnX3VwIDwtIHRvcF9rZWdnX3VwW29yZGVyKC10b3Bfa2VnZ191cCRwLmFkanVzdCksIF1bMToxMCwgXQp0b3Bfa2VnZ19kb3duIDwtIHRvcF9rZWdnX2Rvd25bb3JkZXIodG9wX2tlZ2dfZG93biRwLmFkanVzdCksIF1bMToxMCwgXQoKIyBDb21iaW5lIGludG8gb25lIGRhdGEgZnJhbWUKdG9wX3BhdGh3YXlzIDwtIHJiaW5kKAogIGRhdGEuZnJhbWUoUGF0aHdheSA9IHRvcF9rZWdnX3VwJERlc2NyaXB0aW9uLCBwLmFkanVzdCA9IHRvcF9rZWdnX3VwJHAuYWRqdXN0LCBEaXJlY3Rpb24gPSAiVXByZWd1bGF0ZWQiKSwKICBkYXRhLmZyYW1lKFBhdGh3YXkgPSB0b3Bfa2VnZ19kb3duJERlc2NyaXB0aW9uLCBwLmFkanVzdCA9IHRvcF9rZWdnX2Rvd24kcC5hZGp1c3QsIERpcmVjdGlvbiA9ICJEb3ducmVndWxhdGVkIikKKQoKIyBDb252ZXJ0IHAuYWRqdXN0IHRvIC1sb2cxMChwLmFkanVzdCkgZm9yIHZpc3VhbGl6YXRpb24KdG9wX3BhdGh3YXlzJG5lZ19sb2cxMF9wIDwtIC1sb2cxMCh0b3BfcGF0aHdheXMkcC5hZGp1c3QpCgojIENyZWF0ZSB0aGUgYmFycGxvdApnZ3Bsb3QodG9wX3BhdGh3YXlzLCBhZXMoeCA9IHJlb3JkZXIoUGF0aHdheSwgbmVnX2xvZzEwX3ApLCB5ID0gbmVnX2xvZzEwX3AsIGZpbGwgPSBEaXJlY3Rpb24pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIlVwcmVndWxhdGVkIiA9ICJyZWQiLCAiRG93bnJlZ3VsYXRlZCIgPSAiYmx1ZSIpKSArCiAgY29vcmRfZmxpcCgpICsgICMgRmxpcCB0aGUgY29vcmRpbmF0ZXMgZm9yIGJldHRlciByZWFkYWJpbGl0eQogIGxhYnModGl0bGUgPSAiVG9wIFNpZ25pZmljYW50IFBhdGh3YXlzIiwKICAgICAgIHggPSAiUGF0aHdheXMiLAogICAgICAgeSA9ICItTG9nMTAgQWRqdXN0ZWQgUC1WYWx1ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyeQpsaWJyYXJ5KGdncGxvdDIpCgojIENyZWF0ZSB0aGUgYmFycGxvdApnZ3Bsb3QodG9wX3BhdGh3YXlzLCBhZXMoeCA9IFBhdGh3YXksIHkgPSBuZWdfbG9nMTBfcCwgZmlsbCA9IERpcmVjdGlvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArICAjIFVzZSBwb3NpdGlvbiA9ICJpZGVudGl0eSIKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJVcHJlZ3VsYXRlZCIgPSAicmVkIiwgIkRvd25yZWd1bGF0ZWQiID0gImJsdWUiKSkgKwogIGNvb3JkX2ZsaXAoKSArICAjIEZsaXAgdGhlIGNvb3JkaW5hdGVzIGZvciBiZXR0ZXIgcmVhZGFiaWxpdHkKICBsYWJzKHRpdGxlID0gIlRvcCBTaWduaWZpY2FudCBQYXRod2F5cyIsCiAgICAgICB4ID0gIlBhdGh3YXlzIiwKICAgICAgIHkgPSAiLUxvZzEwIEFkanVzdGVkIFAtVmFsdWUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgoKCmBgYAoKIyA1LiBwZXJmb3JtIGdlbmUgZW5yaWNobWVudCBhbmFseXNpcyBhbmQgaWRlbnRpZnkgcGF0aHdheXMKYGBge3IgZGF0YTQsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIFN0ZXAtYnktU3RlcCBHZW5lIEVucmljaG1lbnQgQW5hbHlzaXMgYW5kIFBhdGh3YXkgSWRlbnRpZmljYXRpb24KCiMgTG9hZCBuZWNlc3NhcnkgcGFja2FnZXMKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkob3JnLkhzLmVnLmRiKQpsaWJyYXJ5KGVucmljaHBsb3QpCmxpYnJhcnkoZ2dwbG90MikKCiMgSWRlbnRpZnkgc2lnbmlmaWNhbnQgZ2VuZXMgYmFzZWQgb24gbG9nMkZDIGFuZCBwLXZhbHVlIGNyaXRlcmlhCnNpZ25pZmljYW50X2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc1sKICAgIChNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA+IDEuNSB8IAogICAgIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDIDwgLTEuNSkgJiAKICAgIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdJGdlbmUKCiMgQ29udmVydCBnZW5lIHN5bWJvbHMgdG8gRW50cmV6IElEcyBmb3IgZG93bnN0cmVhbSBhbmFseXNpcwplbnRyZXpfaWRzIDwtIGJpdHIoc2lnbmlmaWNhbnRfZ2VuZXMsIGZyb21UeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICAgdG9UeXBlID0gIkVOVFJFWklEIiwgCiAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYikKCiMgQ2hlY2sgZm9yIGFueSBOQSB2YWx1ZXMgaW4gY29udmVyc2lvbgplbnRyZXpfaWRzIDwtIG5hLm9taXQoZW50cmV6X2lkcykKCiMgUGVyZm9ybSBLRUdHIFBhdGh3YXkgRW5yaWNobWVudAprZWdnX3Jlc3VsdHMgPC0gZW5yaWNoS0VHRyhnZW5lID0gZW50cmV6X2lkcyRFTlRSRVpJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAnaHNhJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlldyBLRUdHIGVucmljaG1lbnQgcmVzdWx0cwpoZWFkKGtlZ2dfcmVzdWx0cykKCiMgUGVyZm9ybSBHTyAoQmlvbG9naWNhbCBQcm9jZXNzKSBFbnJpY2htZW50CmdvX3Jlc3VsdHMgPC0gZW5yaWNoR08oZ2VuZSA9IGVudHJlel9pZHMkRU5UUkVaSUQsCiAgICAgICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsCiAgICAgICAgICAgICAgICAgICAgICAgb250ID0gIkJQIiwgIyBCaW9sb2dpY2FsIFByb2Nlc3MgKEJQKQogICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpZXcgR08gZW5yaWNobWVudCByZXN1bHRzCmhlYWQoZ29fcmVzdWx0cykKCiMgRG90IHBsb3QgZm9yIEtFR0cgcmVzdWx0cwpkb3RwbG90KGtlZ2dfcmVzdWx0cywgc2hvd0NhdGVnb3J5ID0gMTApICsgCiAgZ2d0aXRsZSgiS0VHRyBQYXRod2F5IEVucmljaG1lbnQiKQoKIyBEb3QgcGxvdCBmb3IgR08gcmVzdWx0cwpkb3RwbG90KGdvX3Jlc3VsdHMsIHNob3dDYXRlZ29yeSA9IDEwKSArIAogIGdndGl0bGUoIkdPIEJpb2xvZ2ljYWwgUHJvY2VzcyBFbnJpY2htZW50IikKCgpgYGAKCgojIDUuIGdncGxvdDIgZm9yIFZvbGNhbm8KYGBge3IgZGF0YTUsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkKCiMgSWRlbnRpZnkgdG9wIGFuZCBib3R0b20gZ2VuZXMKdG9wX2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc1tNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkcF92YWxfYWRqIDwgMC4wNSAmIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRhdmdfbG9nMkZDID4gMS41LCBdCmJvdHRvbV9nZW5lcyA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHNbTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUgJiBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsIF0KCiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBmb3IgY29sb3IgYmFzZWQgb24gc2lnbmlmaWNhbmNlCk1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRjb2xvciA8LSBpZmVsc2UoTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGF2Z19sb2cyRkMgPiAxLjUsICJVcHJlZ3VsYXRlZCBnZW5lcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsICJEb3ducmVndWxhdGVkIGdlbmVzIiwgIk5vbnNpZ25pZmljYW50IikpCgojIENyZWF0ZSBhIHZvbGNhbm8gcGxvdApnZ3Bsb3QoTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzLCBhZXMoeCA9IGF2Z19sb2cyRkMsIHkgPSAtbG9nMTAocF92YWxfYWRqKSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGNvbG9yKSwgYWxwaGEgPSAwLjcsIHNpemUgPSAyKSArCiAgCiAgIyBBZGQgbGFiZWxzIGZvciB0b3AgYW5kIGJvdHRvbSBnZW5lcwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gdG9wX2dlbmVzLCBhZXMobGFiZWwgPSBnZW5lKSwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IDEsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGEgPSBib3R0b21fZ2VuZXMsIGFlcyhsYWJlbCA9IGdlbmUpLCBjb2xvciA9ICJibGFjayIsIHZqdXN0ID0gLTEsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgCiAgIyBDdXN0b21pemUgbGFiZWxzIGFuZCB0aXRsZQogIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90IiwKICAgICAgIHggPSAibG9nMiBGb2xkIENoYW5nZSIsCiAgICAgICB5ID0gIi1sb2cxMChwLXZhbHVlKSIpICsKICAKICAjIEFkZCBzaWduaWZpY2FuY2UgdGhyZXNob2xkIGxpbmVzCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xLjUsIDIpLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsKICAKICAjIFNldCBjb2xvcnMgZm9yIHRvcCBhbmQgYm90dG9tIGdlbmVzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlVwcmVndWxhdGVkIGdlbmVzIiA9ICJyZWQiLCAiRG93bnJlZ3VsYXRlZCBnZW5lcyIgPSAiYmx1ZSIsICJOb25zaWduaWZpY2FudCIgPSAiZGFya2dyZXkiKSkgKwogIAogICMgQ3VzdG9taXplIHRoZW1lIGlmIG5lZWRlZAogIHRoZW1lX21pbmltYWwoKQoKCgoKCmBgYAoKCgoK