load libraries————————————

1. Load DE results

obj <- readRDS("../../0-Most_important_Seurat_objects/All_samples_Merged_with_STCAT_Annotation_final-5-09-2025.rds")
Loading required namespace: SeuratObject

2. Volcano plot (log2FC vs -log10 adjP)

# Choose significance thresholds (tunable)
fc_cut <- 1        # >=1 log2 fold for highlighting (change as appropriate)
padj_cut <- 0.05   # significance threshold

de <- de %>% mutate(
  sig = case_when(
    p_val_adj < padj_cut & avg_logFC >= fc_cut  ~ "Up",
    p_val_adj < padj_cut & avg_logFC <= -fc_cut ~ "Down",
    TRUE ~ "NS"
  ),
  neglog10padj = -log10(pmax(p_val_adj, 1e-300))
)

# volcano plot
volcano_plot <- ggplot(de, aes(x = avg_logFC, y = neglog10padj)) +
  geom_point(aes(color = sig), alpha = 0.6, size = 1.5) +
  scale_color_manual(values = c("Up"="red","Down"="blue","NS"="grey70")) +
  geom_vline(xintercept = c(-fc_cut, fc_cut), linetype=2, color="black") +
  geom_hline(yintercept = -log10(padj_cut), linetype=2, color="black") +
  theme_bw() +
  labs(x = "avg_logFC", y = "-log10(adj p-value)", color = "Direction",
       title = "Volcano plot: pseudobulk DE (Malignant vs Control)") +
  theme(plot.title = element_text(hjust = 0.5))

# label top hits (customize genes to label)
genes_to_label <- c("CLIC1","YWHAH","COX5A","MYBL2", "NME1", "MYLB6", "SLC25A5", "TXNIP", "BTG1", "CDKN1B", "ZFP36")
volcano_plot <- volcano_plot +
  geom_text_repel(data = filter(de, gene %in% genes_to_label),
                  aes(label = gene),
                  size = 3.5, max.overlaps = 30)

# # Save
ggsave("volcano_pseudobulk.png", volcano_plot, width = 7, height = 6, dpi = 300)


volcano_plot

Volcano plot2

library(EnhancedVolcano)

genes_to_label <- c("CLIC1","YWHAH","COX5A","MYBL2", "NME1", 
                    "MYLB6", "SLC25A5", "TXNIP", "BTG1", 
                    "CDKN1B", "ZFP36")

fc_cut <- 1
padj_cut <- 0.05

# Determine fold change range for x-axis
fc_range <- range(de$avg_logFC, na.rm = TRUE)
fc_buffer <- 1  # add small buffer for aesthetics

EnhancedVolcano(de,
                lab = de$gene,
                x = 'avg_logFC',
                y = 'p_val_adj',
                selectLab = genes_to_label,    # only label these genes
                xlab = bquote(~Log[2]~ 'fold change'),
                pCutoff = 10e-14,
                FCcutoff = 2.0,
                pointSize = 4.0,
                labSize = 6.0,
                labCol = 'black',
                labFace = 'bold',
                boxedLabels = TRUE,
                colAlpha = 4/5,
                legendPosition = 'right',
                legendLabSize = 14,
                legendIconSize = 4.0,
                drawConnectors = TRUE,
                widthConnectors = 1.0,
                colConnectors = 'black')

NA
NA

Volcano plot3

library(EnhancedVolcano)

genes_to_label <- c("CLIC1","YWHAH","COX5A","MYBL2", "NME1", 
                    "MYLB6", "SLC25A5", "TXNIP", "BTG1", 
                    "CDKN1B", "ZFP36")

fc_cut <- 1
padj_cut <- 0.05

# Determine fold change range for x-axis
fc_range <- range(de$avg_logFC, na.rm = TRUE)
fc_buffer <- 1  # add small buffer for aesthetics

EnhancedVolcano(de,
                lab = de$gene,
                x = 'avg_logFC',
                y = 'p_val_adj',
                selectLab = genes_to_label,    # only label these genes
                xlab = bquote(~Log[2]~ 'fold change'),
                pCutoff = 0.05,
                FCcutoff = 1.0,
                pointSize = 3.0,
                labSize = 6.0,
                labCol = 'black',
                labFace = 'bold',
                boxedLabels = TRUE,
                parseLabels = TRUE,
                col = c('black', 'pink', 'purple', 'red3'),
                colAlpha = 4/5,
                legendPosition = 'bottom',
                legendLabSize = 14,
                legendIconSize = 4.0,
                drawConnectors = TRUE,
                widthConnectors = 1.0,
                colConnectors = 'black') + coord_flip()

NA
NA

Volcano plot4

library(EnhancedVolcano)


# Example thresholds
pval_cut_high <- 1e-10      # extremely significant genes
fc_cut_high <- 2.0           # very high fold-change
fc_cut_signif <- 1.0         # regular significant fold-change
pval_cut_signif <- 0.05      # regular significance

# Select genes to label
selectLab_italics <- de$gene[ 
  (de$p_val_adj < pval_cut_high) |                        # extremely significant
  ((abs(de$avg_logFC) > fc_cut_signif) & (de$p_val_adj < pval_cut_signif))  # large effect + sig
]


EnhancedVolcano(de,
                lab = de$gene,
                x = 'avg_logFC',
                y = 'p_val_adj',
                selectLab = selectLab_italics,
                xlab = bquote(~Log[2]~ 'fold change'),
                pCutoff = pval_cut_signif,
                FCcutoff = fc_cut_signif,
                pointSize = 3.0,
                labSize = 6.0,
                labCol = 'black',
                labFace = 'bold',
                boxedLabels = TRUE,
                parseLabels = FALSE,   # <-- important
                col = c('black', 'pink', 'purple', 'red3'),
                colAlpha = 0.8,
                legendPosition = 'bottom',
                legendLabSize = 14,
                legendIconSize = 4.0,
                drawConnectors = TRUE,
                widthConnectors = 1.0,
                colConnectors = 'black'
)

3. Prepare preranked list for GSEA (fgsea)

4. Dotplot function

Dotplot function

5. Enrichment map / cnetplot for leading-edge genes


#### Enrichment map / cnetplot for leading-edge genes ####
library(clusterProfiler)
library(enrichplot)
library(tidyverse)

make_cnet_emap <- function(fgsea_res,
                           dataset_name,
                           padj_cutoff = 0.25,
                           topN_fallback = 10,
                           showCategory = 15,
                           fold_change_vec = NULL,
                           save_plots = TRUE) {
  
  message("Processing dataset: ", dataset_name)
  
  # 1) Try to filter by padj
  leading_list <- fgsea_res %>%
    filter(padj < padj_cutoff) %>%
    select(pathway, leadingEdge) %>%
    mutate(leadingEdge = map(leadingEdge, as.character)) %>%
    deframe()
  
  # 2) Fallback to topN
  if (length(leading_list) < 2) {
    message("⚠ No significant pathways. Using top ", topN_fallback, " by NES.")
    leading_list <- fgsea_res %>%
      arrange(padj, desc(abs(NES))) %>%
      slice_head(n = topN_fallback) %>%
      select(pathway, leadingEdge) %>%
      mutate(leadingEdge = map(leadingEdge, as.character)) %>%
      deframe()
  }
  
  if (length(leading_list) < 2) {
    message("❌ Still too few pathways for ", dataset_name)
    return(NULL)
  }
  
  # Convert to TERM2GENE for plotting
  lead_term2gene <- enframe(leading_list, name = "TERM", value = "GENE") %>%
    unnest(cols = c(GENE))
  
  # ---- Build fake enrichmentResult object ----
  enr <- enricher(
    gene = unique(unlist(leading_list)),  # union of leading-edge genes
    TERM2GENE = lead_term2gene,
    minGSSize = 1, maxGSSize = 5000
  )
  
  # ---- cnetplot ----
  cnet <- cnetplot(
    enr,
    foldChange = fold_change_vec,
    showCategory = showCategory,
    circular = FALSE,
    colorEdge = TRUE
  ) + ggtitle(paste("Cnetplot —", dataset_name))
  
  if (save_plots) {
    ggsave(paste0("cnetplot_leadingEdge_", dataset_name, ".png"),
           cnet, width = 12, height = 8, dpi = 300)
  }
  
  # ---- emapplot ----
  emap <- pairwise_termsim(enr)
  emap_plot <- emapplot(emap, showCategory = showCategory) +
    ggtitle(paste("Enrichment Map —", dataset_name))
  
  if (save_plots) {
    ggsave(paste0("emapplot_leadingEdge_", dataset_name, ".png"),
           emap_plot, width = 12, height = 8, dpi = 300)
  }
  
  return(list(enrich_res = enr, cnet = cnet, emap = emap_plot))
}

library(Seurat)
library(cowplot)
library(SeuratObject)


topPathways <- fg_h[["pathway"]] %>% head(10)
titles <- sub("HALLMARK_", "", topPathways)


# Make sure topPathways are in the Hallmark list
topPathways <- intersect(topPathways, names(pathways_h))

# Titles for plots
titles <- sub("HALLMARK_", "", topPathways)

# Use SCT assay explicitly
DefaultAssay(obj) <- "SCT"

# Run plotCoregulationProfileReduction
ps <- plotCoregulationProfileReduction(
  pathways_h[topPathways],
  obj,
  assay = "SCT",         # explicitly use SCT assay
  title = titles,
  reduction = "umap"
)

# Combine plots
cowplot::plot_grid(plotlist = ps[1:length(ps)], ncol = 2)

NA
NA
NA

library(dplyr)
library(Seurat)
library(cowplot)
library(SeuratObject)

# 1️⃣ Sort the Hallmark FGSEA table by NES
fg_h_sorted <- fg_h %>% arrange(desc(NES))  # descending NES

# 2️⃣ Get top 10 up and top 10 down pathways
top_up   <- fg_h_sorted$pathway[1:10]       # top 10 up by NES
top_down <- fg_h_sorted %>% arrange(NES) %>% slice(1:10) %>% pull(pathway)  # top 10 down

# 3️⃣ Combine up and down
topPathways <- c(top_up, top_down)

# Keep only pathways that exist in the Hallmark gene sets
topPathways <- intersect(topPathways, names(pathways_h))

# Titles for plotting
titles <- sub("HALLMARK_", "", topPathways)

# Use SCT assay explicitly
DefaultAssay(obj) <- "SCT"

# 4️⃣ Run co-regulation UMAP
ps <- plotCoregulationProfileReduction(
  pathways_h[topPathways],
  obj,
  assay = "SCT",
  title = titles,
  reduction = "umap"
)

# 5️⃣ Combine plots in a grid
cowplot::plot_grid(plotlist = ps[1:length(ps)], ncol = 4)

NA
NA

library(Seurat)
library(cowplot)
library(SeuratObject)


topPathways <- fg_kegg[["pathway"]] %>% head(10)
titles <- sub("KEGG_", "", topPathways)


# Make sure topPathways are in the Hallmark list
topPathways <- intersect(topPathways, names(pathways_kegg))

# Titles for plots
titles <- sub("KEGG_", "", topPathways)

# Use SCT assay explicitly
DefaultAssay(obj) <- "SCT"

# Run plotCoregulationProfileReduction
ps <- plotCoregulationProfileReduction(
  pathways_kegg[topPathways],
  obj,
  assay = "SCT",         # explicitly use SCT assay
  title = titles,
  reduction = "umap"
)

# Combine plots
cowplot::plot_grid(plotlist = ps[1:length(ps)], ncol = 2)

NA
NA
NA

library(Seurat)
library(cowplot)
library(SeuratObject)


topPathways <- fg_react[["pathway"]] %>% head(10)
titles <- sub("REACTOME_", "", topPathways)


# Make sure topPathways are in the Hallmark list
topPathways <- intersect(topPathways, names(pathways_react))

# Titles for plots
titles <- sub("REACTOME_", "", topPathways)

# Use SCT assay explicitly
DefaultAssay(obj) <- "SCT"

# Run plotCoregulationProfileReduction
ps <- plotCoregulationProfileReduction(
  pathways_react[topPathways],
  obj,
  assay = "SCT",         # explicitly use SCT assay
  title = titles,
  reduction = "umap"
)

# Combine plots
cowplot::plot_grid(plotlist = ps[1:length(ps)], ncol = 2)

NA
NA
NA

# Sort Reactome FGSEA table by NES
fg_react_sorted <- fg_react %>% arrange(desc(NES))

# Top 10 up and top 10 down
top_up   <- fg_react_sorted$pathway[1:10]
top_down <- fg_react_sorted %>% arrange(NES) %>% slice(1:10) %>% pull(pathway)

# Combine and keep only pathways present in Reactome gene sets
topPathways <- intersect(c(top_up, top_down), names(pathways_react))

# Titles
titles <- sub("REACTOME_", "", topPathways)

# SCT assay
DefaultAssay(obj) <- "SCT"

# Run co-regulation UMAP
ps <- plotCoregulationProfileReduction(
  pathways_react[topPathways],
  obj,
  assay = "SCT",
  title = titles,
  reduction = "umap"
)

# Combine plots
cowplot::plot_grid(plotlist = ps[1:length(ps)], ncol = 2)

NA
NA
NA

library(Seurat)
library(cowplot)
library(SeuratObject)


topPathways <- fg_bp[["pathway"]] %>% head(10)
titles <- sub("GO_", "", topPathways)


# Make sure topPathways are in the Hallmark list
topPathways <- intersect(topPathways, names(pathways_bp))

# Titles for plots
titles <- sub("GO_", "", topPathways)

# Use SCT assay explicitly
DefaultAssay(obj) <- "SCT"

# Run plotCoregulationProfileReduction
ps <- plotCoregulationProfileReduction(
  pathways_bp[topPathways],
  obj,
  assay = "SCT",         # explicitly use SCT assay
  title = titles,
  reduction = "umap"
)

# Combine plots
cowplot::plot_grid(plotlist = ps[1:length(ps)], ncol = 2)

NA
NA
NA

# Sort GO:BP FGSEA table by NES
fg_bp_sorted <- fg_bp %>% arrange(desc(NES))

# Top 10 up and top 10 down
top_up   <- fg_bp_sorted$pathway[1:10]
top_down <- fg_bp_sorted %>% arrange(NES) %>% slice(1:10) %>% pull(pathway)

# Combine and keep only pathways present in GO:BP gene sets
topPathways <- intersect(c(top_up, top_down), names(pathways_bp))

# Titles
titles <- sub("GO_BP_", "", topPathways)

# SCT assay
DefaultAssay(obj) <- "SCT"

# Run co-regulation UMAP
ps <- plotCoregulationProfileReduction(
  pathways_bp[topPathways],
  obj,
  assay = "SCT",
  title = titles,
  reduction = "umap"
)

# Combine plots
cowplot::plot_grid(plotlist = ps[1:length(ps)], ncol = 2)

NA
NA
LS0tCnRpdGxlOiAiZmdzZWEgQW5hbHlzaXMgZm9yIE5ld21vb24gUHJlcGFyYXRpb24iCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKCiMjIGxvYWQgbGlicmFyaWVzLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKIyAxLiBMb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShmZ3NlYSkKbGlicmFyeShtc2lnZGJyKQpsaWJyYXJ5KGVucmljaHBsb3QpCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KGdncmVwZWwpCgpgYGAKCgojIDEuIExvYWQgREUgcmVzdWx0cwpgYGB7ciBsb2FkU2V1cmF0fQoKZGVfZmlsZSA8LSAiLi4vMS1MSUJSQV9Qc2V1ZG9idWxrX0Rlc2VxMl9MUlRfZmlsdGVyZWRfb25fbWVhbi5jc3YiCmRlIDwtIHJlYWQuY3N2KGRlX2ZpbGUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKaGVhZChkZSkKCgpvYmogPC0gcmVhZFJEUygiLi4vLi4vMC1Nb3N0X2ltcG9ydGFudF9TZXVyYXRfb2JqZWN0cy9BbGxfc2FtcGxlc19NZXJnZWRfd2l0aF9TVENBVF9Bbm5vdGF0aW9uX2ZpbmFsLTUtMDktMjAyNS5yZHMiKQoKYGBgCgoKIyAyLiBWb2xjYW5vIHBsb3QgKGxvZzJGQyB2cyAtbG9nMTAgYWRqUCkKYGBge3IsIGZpZy5oZWlnaHQ9IDYsIGZpZy53aWR0aD0gMTB9CiMgQ2hvb3NlIHNpZ25pZmljYW5jZSB0aHJlc2hvbGRzICh0dW5hYmxlKQpmY19jdXQgPC0gMSAgICAgICAgIyA+PTEgbG9nMiBmb2xkIGZvciBoaWdobGlnaHRpbmcgKGNoYW5nZSBhcyBhcHByb3ByaWF0ZSkKcGFkal9jdXQgPC0gMC4wNSAgICMgc2lnbmlmaWNhbmNlIHRocmVzaG9sZAoKZGUgPC0gZGUgJT4lIG11dGF0ZSgKICBzaWcgPSBjYXNlX3doZW4oCiAgICBwX3ZhbF9hZGogPCBwYWRqX2N1dCAmIGF2Z19sb2dGQyA+PSBmY19jdXQgIH4gIlVwIiwKICAgIHBfdmFsX2FkaiA8IHBhZGpfY3V0ICYgYXZnX2xvZ0ZDIDw9IC1mY19jdXQgfiAiRG93biIsCiAgICBUUlVFIH4gIk5TIgogICksCiAgbmVnbG9nMTBwYWRqID0gLWxvZzEwKHBtYXgocF92YWxfYWRqLCAxZS0zMDApKQopCgojIHZvbGNhbm8gcGxvdAp2b2xjYW5vX3Bsb3QgPC0gZ2dwbG90KGRlLCBhZXMoeCA9IGF2Z19sb2dGQywgeSA9IG5lZ2xvZzEwcGFkaikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IHNpZyksIGFscGhhID0gMC42LCBzaXplID0gMS41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlVwIj0icmVkIiwiRG93biI9ImJsdWUiLCJOUyI9ImdyZXk3MCIpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygtZmNfY3V0LCBmY19jdXQpLCBsaW5ldHlwZT0yLCBjb2xvcj0iYmxhY2siKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKHBhZGpfY3V0KSwgbGluZXR5cGU9MiwgY29sb3I9ImJsYWNrIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeCA9ICJhdmdfbG9nRkMiLCB5ID0gIi1sb2cxMChhZGogcC12YWx1ZSkiLCBjb2xvciA9ICJEaXJlY3Rpb24iLAogICAgICAgdGl0bGUgPSAiVm9sY2FubyBwbG90OiBwc2V1ZG9idWxrIERFIChNYWxpZ25hbnQgdnMgQ29udHJvbCkiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgojIGxhYmVsIHRvcCBoaXRzIChjdXN0b21pemUgZ2VuZXMgdG8gbGFiZWwpCmdlbmVzX3RvX2xhYmVsIDwtIGMoIkNMSUMxIiwiWVdIQUgiLCJDT1g1QSIsIk1ZQkwyIiwgIk5NRTEiLCAiTVlMQjYiLCAiU0xDMjVBNSIsICJUWE5JUCIsICJCVEcxIiwgIkNES04xQiIsICJaRlAzNiIpCnZvbGNhbm9fcGxvdCA8LSB2b2xjYW5vX3Bsb3QgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gZmlsdGVyKGRlLCBnZW5lICVpbiUgZ2VuZXNfdG9fbGFiZWwpLAogICAgICAgICAgICAgICAgICBhZXMobGFiZWwgPSBnZW5lKSwKICAgICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgbWF4Lm92ZXJsYXBzID0gMzApCgojICMgU2F2ZQpnZ3NhdmUoInZvbGNhbm9fcHNldWRvYnVsay5wbmciLCB2b2xjYW5vX3Bsb3QsIHdpZHRoID0gNywgaGVpZ2h0ID0gNiwgZHBpID0gMzAwKQoKCnZvbGNhbm9fcGxvdAoKYGBgCiMjIFZvbGNhbm8gcGxvdDIKYGBge3IsIGZpZy5oZWlnaHQ9IDEyLCBmaWcud2lkdGg9IDE0fQpsaWJyYXJ5KEVuaGFuY2VkVm9sY2FubykKCmdlbmVzX3RvX2xhYmVsIDwtIGMoIkNMSUMxIiwiWVdIQUgiLCJDT1g1QSIsIk1ZQkwyIiwgIk5NRTEiLCAKICAgICAgICAgICAgICAgICAgICAiTVlMQjYiLCAiU0xDMjVBNSIsICJUWE5JUCIsICJCVEcxIiwgCiAgICAgICAgICAgICAgICAgICAgIkNES04xQiIsICJaRlAzNiIpCgpmY19jdXQgPC0gMQpwYWRqX2N1dCA8LSAwLjA1CgojIERldGVybWluZSBmb2xkIGNoYW5nZSByYW5nZSBmb3IgeC1heGlzCmZjX3JhbmdlIDwtIHJhbmdlKGRlJGF2Z19sb2dGQywgbmEucm0gPSBUUlVFKQpmY19idWZmZXIgPC0gMSAgIyBhZGQgc21hbGwgYnVmZmVyIGZvciBhZXN0aGV0aWNzCgpFbmhhbmNlZFZvbGNhbm8oZGUsCiAgICAgICAgICAgICAgICBsYWIgPSBkZSRnZW5lLAogICAgICAgICAgICAgICAgeCA9ICdhdmdfbG9nRkMnLAogICAgICAgICAgICAgICAgeSA9ICdwX3ZhbF9hZGonLAogICAgICAgICAgICAgICAgc2VsZWN0TGFiID0gZ2VuZXNfdG9fbGFiZWwsICAgICMgb25seSBsYWJlbCB0aGVzZSBnZW5lcwogICAgICAgICAgICAgICAgeGxhYiA9IGJxdW90ZSh+TG9nWzJdfiAnZm9sZCBjaGFuZ2UnKSwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAxMGUtMTQsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDIuMCwKICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgIGxhYlNpemUgPSA2LjAsCiAgICAgICAgICAgICAgICBsYWJDb2wgPSAnYmxhY2snLAogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIGNvbEFscGhhID0gNC81LAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLAogICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDE0LAogICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAxLjAsCiAgICAgICAgICAgICAgICBjb2xDb25uZWN0b3JzID0gJ2JsYWNrJykKCgpgYGAKIyMgVm9sY2FubyBwbG90MwpgYGB7ciwgZmlnLmhlaWdodD0gMTIsIGZpZy53aWR0aD0gMTR9CmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQoKZ2VuZXNfdG9fbGFiZWwgPC0gYygiQ0xJQzEiLCJZV0hBSCIsIkNPWDVBIiwiTVlCTDIiLCAiTk1FMSIsIAogICAgICAgICAgICAgICAgICAgICJNWUxCNiIsICJTTEMyNUE1IiwgIlRYTklQIiwgIkJURzEiLCAKICAgICAgICAgICAgICAgICAgICAiQ0RLTjFCIiwgIlpGUDM2IikKCmZjX2N1dCA8LSAxCnBhZGpfY3V0IDwtIDAuMDUKCiMgRGV0ZXJtaW5lIGZvbGQgY2hhbmdlIHJhbmdlIGZvciB4LWF4aXMKZmNfcmFuZ2UgPC0gcmFuZ2UoZGUkYXZnX2xvZ0ZDLCBuYS5ybSA9IFRSVUUpCmZjX2J1ZmZlciA8LSAxICAjIGFkZCBzbWFsbCBidWZmZXIgZm9yIGFlc3RoZXRpY3MKCkVuaGFuY2VkVm9sY2FubyhkZSwKICAgICAgICAgICAgICAgIGxhYiA9IGRlJGdlbmUsCiAgICAgICAgICAgICAgICB4ID0gJ2F2Z19sb2dGQycsCiAgICAgICAgICAgICAgICB5ID0gJ3BfdmFsX2FkaicsCiAgICAgICAgICAgICAgICBzZWxlY3RMYWIgPSBnZW5lc190b19sYWJlbCwgICAgIyBvbmx5IGxhYmVsIHRoZXNlIGdlbmVzCiAgICAgICAgICAgICAgICB4bGFiID0gYnF1b3RlKH5Mb2dbMl1+ICdmb2xkIGNoYW5nZScpLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuMCwKICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDMuMCwKICAgICAgICAgICAgICAgIGxhYlNpemUgPSA2LjAsCiAgICAgICAgICAgICAgICBsYWJDb2wgPSAnYmxhY2snLAogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIHBhcnNlTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIGNvbCA9IGMoJ2JsYWNrJywgJ3BpbmsnLCAncHVycGxlJywgJ3JlZDMnKSwKICAgICAgICAgICAgICAgIGNvbEFscGhhID0gNC81LAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAnYm90dG9tJywKICAgICAgICAgICAgICAgIGxlZ2VuZExhYlNpemUgPSAxNCwKICAgICAgICAgICAgICAgIGxlZ2VuZEljb25TaXplID0gNC4wLAogICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgd2lkdGhDb25uZWN0b3JzID0gMS4wLAogICAgICAgICAgICAgICAgY29sQ29ubmVjdG9ycyA9ICdibGFjaycpICsgY29vcmRfZmxpcCgpCgoKYGBgCgojIyBWb2xjYW5vIHBsb3Q0CmBgYHtyLCBmaWcuaGVpZ2h0PSAxMiwgZmlnLndpZHRoPSAxNH0KbGlicmFyeShFbmhhbmNlZFZvbGNhbm8pCgoKIyBFeGFtcGxlIHRocmVzaG9sZHMKcHZhbF9jdXRfaGlnaCA8LSAxZS0xMCAgICAgICMgZXh0cmVtZWx5IHNpZ25pZmljYW50IGdlbmVzCmZjX2N1dF9oaWdoIDwtIDIuMCAgICAgICAgICAgIyB2ZXJ5IGhpZ2ggZm9sZC1jaGFuZ2UKZmNfY3V0X3NpZ25pZiA8LSAxLjAgICAgICAgICAjIHJlZ3VsYXIgc2lnbmlmaWNhbnQgZm9sZC1jaGFuZ2UKcHZhbF9jdXRfc2lnbmlmIDwtIDAuMDUgICAgICAjIHJlZ3VsYXIgc2lnbmlmaWNhbmNlCgojIFNlbGVjdCBnZW5lcyB0byBsYWJlbApzZWxlY3RMYWJfaXRhbGljcyA8LSBkZSRnZW5lWyAKICAoZGUkcF92YWxfYWRqIDwgcHZhbF9jdXRfaGlnaCkgfCAgICAgICAgICAgICAgICAgICAgICAgICMgZXh0cmVtZWx5IHNpZ25pZmljYW50CiAgKChhYnMoZGUkYXZnX2xvZ0ZDKSA+IGZjX2N1dF9zaWduaWYpICYgKGRlJHBfdmFsX2FkaiA8IHB2YWxfY3V0X3NpZ25pZikpICAjIGxhcmdlIGVmZmVjdCArIHNpZwpdCgoKRW5oYW5jZWRWb2xjYW5vKGRlLAogICAgICAgICAgICAgICAgbGFiID0gZGUkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAnYXZnX2xvZ0ZDJywKICAgICAgICAgICAgICAgIHkgPSAncF92YWxfYWRqJywKICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IHNlbGVjdExhYl9pdGFsaWNzLAogICAgICAgICAgICAgICAgeGxhYiA9IGJxdW90ZSh+TG9nWzJdfiAnZm9sZCBjaGFuZ2UnKSwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSBwdmFsX2N1dF9zaWduaWYsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IGZjX2N1dF9zaWduaWYsCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNi4wLAogICAgICAgICAgICAgICAgbGFiQ29sID0gJ2JsYWNrJywKICAgICAgICAgICAgICAgIGxhYkZhY2UgPSAnYm9sZCcsCiAgICAgICAgICAgICAgICBib3hlZExhYmVscyA9IFRSVUUsCiAgICAgICAgICAgICAgICBwYXJzZUxhYmVscyA9IEZBTFNFLCAgICMgPC0tIGltcG9ydGFudAogICAgICAgICAgICAgICAgY29sID0gYygnYmxhY2snLCAncGluaycsICdwdXJwbGUnLCAncmVkMycpLAogICAgICAgICAgICAgICAgY29sQWxwaGEgPSAwLjgsCiAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdib3R0b20nLAogICAgICAgICAgICAgICAgbGVnZW5kTGFiU2l6ZSA9IDE0LAogICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAxLjAsCiAgICAgICAgICAgICAgICBjb2xDb25uZWN0b3JzID0gJ2JsYWNrJwopCgpgYGAKCgojIDMuIFByZXBhcmUgcHJlcmFua2VkIGxpc3QgZm9yIEdTRUEgKGZnc2VhKQpgYGB7ciwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPSAxNn0KCiMgUmFua2luZzogc2lnbmVkX3N0YXQgPSBsb2dGQyAqIC1sb2cxMChwYWRqKQpkZSA8LSBkZSAlPiUgbXV0YXRlKHNpZ25lZF9zdGF0ID0gYXZnX2xvZ0ZDICogKC1sb2cxMChwX3ZhbF9hZGogKyAxZS0zMDApKSkKcmFua3MgPC0gZGUgJT4lIGFycmFuZ2UoZGVzYyhzaWduZWRfc3RhdCkpICU+JSBkaXN0aW5jdChnZW5lLCAua2VlcF9hbGw9VFJVRSkKcmFua3NfdmVjIDwtIHJhbmtzJHNpZ25lZF9zdGF0OyBuYW1lcyhyYW5rc192ZWMpIDwtIHJhbmtzJGdlbmUKcmFua3NfdmVjIDwtIHJhbmtzX3ZlY1shaXMubmEobmFtZXMocmFua3NfdmVjKSkgJiAhZHVwbGljYXRlZChuYW1lcyhyYW5rc192ZWMpKV0KCiMgTG9hZCBNU2lnREIgZ2VuZSBzZXRzCgojIEhhbGxtYXJrCm1zaWdfaCA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiSCIpICU+JQogIGRwbHlyOjpzZWxlY3QoZ3NfbmFtZSwgZ2VuZV9zeW1ib2wpCnBhdGh3YXlzX2ggPC0gc3BsaXQobXNpZ19oJGdlbmVfc3ltYm9sLCBtc2lnX2gkZ3NfbmFtZSkKCiMgQzIgY2Fub25pY2FsIHBhdGh3YXlzOiBLRUdHICsgUmVhY3RvbWUKbXNpZ19jMiA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzIiKSAlPiUKICBkcGx5cjo6c2VsZWN0KGdzX25hbWUsIGdzX3N1YmNvbGxlY3Rpb24sIGdlbmVfc3ltYm9sKQoKIyBLRUdHIC0gY2hvb3NlIE1lZGljdXMgb3IgTGVnYWN5Cm1zaWdfa2VnZyA8LSBtc2lnZGJyKAogIHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwKICBjYXRlZ29yeSA9ICJDMiIsCiAgc3ViY2F0ZWdvcnkgPSAiQ1A6S0VHR19MRUdBQ1kiICAgIyBvciAiQ1A6S0VHR19MRUdBQ1kiCikgJT4lCiAgc2VsZWN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKQoKcGF0aHdheXNfa2VnZyA8LSBzcGxpdChtc2lnX2tlZ2ckZ2VuZV9zeW1ib2wsIG1zaWdfa2VnZyRnc19uYW1lKQoKIyBSZWFjdG9tZQptc2lnX3JlYWN0IDwtIG1zaWdfYzIgJT4lIGZpbHRlcihnc19zdWJjb2xsZWN0aW9uID09ICJDUDpSRUFDVE9NRSIpICU+JSBzZWxlY3QoZ3NfbmFtZSwgZ2VuZV9zeW1ib2wpCnBhdGh3YXlzX3JlYWN0IDwtIHNwbGl0KG1zaWdfcmVhY3QkZ2VuZV9zeW1ib2wsIG1zaWdfcmVhY3QkZ3NfbmFtZSkKCiMgR08gQmlvbG9naWNhbCBQcm9jZXNzCm1zaWdfYnAgPC0gbXNpZ2RicihzcGVjaWVzID0gIkhvbW8gc2FwaWVucyIsIGNhdGVnb3J5ID0gIkM1Iiwgc3ViY2F0ZWdvcnkgPSAiQlAiKSAlPiUKICBkcGx5cjo6c2VsZWN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKQpwYXRod2F5c19icCA8LSBzcGxpdChtc2lnX2JwJGdlbmVfc3ltYm9sLCBtc2lnX2JwJGdzX25hbWUpCgojIGZnc2VhIGZ1bmN0aW9uCnJ1bl9mZ3NlYSA8LSBmdW5jdGlvbihwYXRod2F5cywgcmFua3NfdmVjLCBsYWJlbCl7CiAgc2V0LnNlZWQoNDIpCiAgZmcgPC0gZmdzZWFNdWx0aWxldmVsKHBhdGh3YXlzID0gcGF0aHdheXMsIHN0YXRzID0gcmFua3NfdmVjKQogIGZnIDwtIGFzX3RpYmJsZShmZykgJT4lCiAgICBhcnJhbmdlKHBhZGopICU+JQogICAgbXV0YXRlKAogICAgICBkYXRhc2V0ID0gbGFiZWwsCiAgICAgIGxlYWRpbmdFZGdlQ291bnQgPSBsZW5ndGhzKGxlYWRpbmdFZGdlKSwKICAgICAgbGVhZGluZ0VkZ2UgPSBzYXBwbHkobGVhZGluZ0VkZ2UsIGZ1bmN0aW9uKHgpIHBhc3RlKHgsIGNvbGxhcHNlID0gIjsiKSkKICAgICkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KGRhdGFzZXQsIHBhdGh3YXksIE5FUywgcGFkaiwgcHZhbCwgc2l6ZSwgbGVhZGluZ0VkZ2UsIGxlYWRpbmdFZGdlQ291bnQpCiAgd3JpdGUuY3N2KGZnLCBwYXN0ZTAoImZnc2VhXyIsIGxhYmVsLCAiX3Jlc3VsdHMuY3N2IiksIHJvdy5uYW1lcyA9IEZBTFNFKQogIHJldHVybihmZykKfQoKIyBSdW4gR1NFQSBmb3IgZWFjaCBkYXRhc2V0CmZnX2ggICAgIDwtIHJ1bl9mZ3NlYShwYXRod2F5c19oLCByYW5rc192ZWMsICJoYWxsbWFyayIpCmZnX2tlZ2cgIDwtIHJ1bl9mZ3NlYShwYXRod2F5c19rZWdnLCByYW5rc192ZWMsICJrZWdnIikKZmdfcmVhY3QgPC0gcnVuX2Znc2VhKHBhdGh3YXlzX3JlYWN0LCByYW5rc192ZWMsICJyZWFjdG9tZSIpCmZnX2JwICAgIDwtIHJ1bl9mZ3NlYShwYXRod2F5c19icCwgcmFua3NfdmVjLCAiZ29fYnAiKQoKYGBgCgoKCiMgNC4gRG90cGxvdCBmdW5jdGlvbgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9IDEyfQoKIyBEb3RwbG90IGZ1bmN0aW9uCmRvdHBsb3RfZmdzZWEgPC0gZnVuY3Rpb24oZmdfdGJsLCBsYWJlbCwgdG9wTj0xMCwgd2lkdGg9MTAsIGhlaWdodD02KXsKICBmZ190b3BfdXAgPC0gZmdfdGJsICU+JSBmaWx0ZXIoTkVTID4gMCkgJT4lIGFycmFuZ2UoZGVzYyhORVMpKSAlPiUgc2xpY2VfaGVhZChuID0gdG9wTikKICBmZ190b3BfZG93biA8LSBmZ190YmwgJT4lIGZpbHRlcihORVMgPCAwKSAlPiUgYXJyYW5nZShORVMpICU+JSBzbGljZV9oZWFkKG4gPSB0b3BOKQogIGZnX3RvcCA8LSBiaW5kX3Jvd3MoZmdfdG9wX3VwLCBmZ190b3BfZG93bikKICAKICBwIDwtIGdncGxvdChmZ190b3AsIGFlcyh4ID0gTkVTLCB5ID0gcmVvcmRlcihwYXRod2F5LCBORVMpKSkgKwogICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IGxlYWRpbmdFZGdlQ291bnQsIGNvbG9yID0gcGFkaikpICsKICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhvcHRpb24gPSAibWFnbWEiLCBkaXJlY3Rpb24gPSAtMSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIGxhYnModGl0bGUgPSBwYXN0ZTAoIlByZXJhbmtlZCBHU0VBIOKAlCAiLCBsYWJlbCwgIiAoVG9wICIsIHRvcE4sICIgdXAgJiBkb3duKSIpLAogICAgICAgICB4ID0gIk5vcm1hbGl6ZWQgRW5yaWNobWVudCBTY29yZSAoTkVTKSIsCiAgICAgICAgIHkgPSAiIiwKICAgICAgICAgc2l6ZSA9ICJMZWFkaW5nIGVkZ2UgZ2VuZXMiLAogICAgICAgICBjb2xvciA9ICJGRFIgKHBhZGopIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCiAgCiAgZ2dzYXZlKHBhc3RlMCgiZmdzZWFfIiwgbGFiZWwsICJfZG90cGxvdC5wbmciKSwgcCwgd2lkdGggPSB3aWR0aCwgaGVpZ2h0ID0gaGVpZ2h0LCBkcGkgPSAzMDApCiAgcmV0dXJuKHApCn0KCiMgTWFrZSBkb3RwbG90cwpwX2ggICAgIDwtIGRvdHBsb3RfZmdzZWEoZmdfaCwgIkhhbGxtYXJrIikKcF9rZWdnICA8LSBkb3RwbG90X2Znc2VhKGZnX2tlZ2csICJLRUdHIikKcF9yZWFjdCA8LSBkb3RwbG90X2Znc2VhKGZnX3JlYWN0LCAiUmVhY3RvbWUiKQpwX2JwICAgIDwtIGRvdHBsb3RfZmdzZWEoZmdfYnAsICJHTzpCUCIpCgoKCmZnX2gkbGVhZGluZ0VkZ2UgICAgIDwtIGFzLmNoYXJhY3RlcihmZ19oJGxlYWRpbmdFZGdlKQpmZ19rZWdnJGxlYWRpbmdFZGdlICA8LSBhcy5jaGFyYWN0ZXIoZmdfa2VnZyRsZWFkaW5nRWRnZSkKZmdfcmVhY3QkbGVhZGluZ0VkZ2UgPC0gYXMuY2hhcmFjdGVyKGZnX3JlYWN0JGxlYWRpbmdFZGdlKQpmZ19icCRsZWFkaW5nRWRnZSAgICA8LSBhcy5jaGFyYWN0ZXIoZmdfYnAkbGVhZGluZ0VkZ2UpCgpmZ19hbGwgPC0gYmluZF9yb3dzKGZnX2gsIGZnX2tlZ2csIGZnX3JlYWN0LCBmZ19icCkKd3JpdGUuY3N2KGZnX2FsbCwgImZnc2VhX2FsbF9yZXN1bHRzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKbGlicmFyeSh0aWR5dGV4dCkKCmZnX2FsbCA8LSBiaW5kX3Jvd3MoZmdfaCwgZmdfa2VnZywgZmdfcmVhY3QsIGZnX2JwKQp3cml0ZS5jc3YoZmdfYWxsLCAiZmdzZWFfYWxsX3Jlc3VsdHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpmZ19hbGwgJT4lCiAgZ3JvdXBfYnkoZGF0YXNldCkgJT4lIHNsaWNlX21pbihwYWRqLCBuID0gMTApICU+JQogIGdncGxvdChhZXMoeCA9IE5FUywgeSA9IHJlb3JkZXJfd2l0aGluKHBhdGh3YXksIE5FUywgZGF0YXNldCksCiAgICAgICAgICAgICBjb2xvciA9IHBhZGosIHNpemUgPSBsZWFkaW5nRWRnZUNvdW50KSkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfeV9yZW9yZGVyZWQoKSArCiAgZmFjZXRfd3JhcCh+ZGF0YXNldCwgc2NhbGVzID0gImZyZWVfeSIpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2Mob3B0aW9uID0gIm1hZ21hIiwgZGlyZWN0aW9uID0gLTEpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiVG9wIEdTRUEgcGF0aHdheXMgYWNyb3NzIEhhbGxtYXJrLCBLRUdHLCBSZWFjdG9tZSwgYW5kIEdPLUJQIiwKICAgICAgIHggPSAiTkVTIiwgeSA9ICIiLCBzaXplID0gIkxlYWRpbmcgZWRnZSIsIGNvbG9yID0gIkZEUiAocGFkaikiKQoKYGBgCgojIyBEb3RwbG90IGZ1bmN0aW9uCmBgYHtyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD0gNn0KIyBQcmVwYXJlIHRvcCBwYXRod2F5cwoKdG9wTiA8LSAzICAjIHRvcCAzIHVwIGFuZCBkb3duIHBlciBkYXRhc2V0CgpnZXRfdG9wX3VwZG93biA8LSBmdW5jdGlvbihmZ190YmwsIGRhdGFzZXRfbmFtZSwgdG9wTj0zKXsKICBmZ190b3BfdXAgPC0gZmdfdGJsICU+JSBmaWx0ZXIoTkVTID4gMCkgJT4lIGFycmFuZ2UoZGVzYyhORVMpKSAlPiUgc2xpY2VfaGVhZChuPXRvcE4pCiAgZmdfdG9wX2Rvd24gPC0gZmdfdGJsICU+JSBmaWx0ZXIoTkVTIDwgMCkgJT4lIGFycmFuZ2UoTkVTKSAlPiUgc2xpY2VfaGVhZChuPXRvcE4pCiAgZmdfdG9wIDwtIGJpbmRfcm93cyhmZ190b3BfdXAsIGZnX3RvcF9kb3duKQogIGZnX3RvcCRkYXRhc2V0IDwtIGRhdGFzZXRfbmFtZQogIGZnX3RvcCRkaXJlY3Rpb24gPC0gaWZlbHNlKGZnX3RvcCRORVMgPiAwLCAiVXAiLCAiRG93biIpCiAgZmdfdG9wJGRpcmVjdGlvbiA8LSBhcy5jaGFyYWN0ZXIoZmdfdG9wJGRpcmVjdGlvbikgICAjIDwtLS0gZm9yY2UgY2hhcmFjdGVyCiAgcmV0dXJuKGZnX3RvcCkKfQoKCiMgQ29tYmluZSB0b3AgcGF0aHdheXMgZnJvbSBlYWNoIGRhdGFzZXQKZmdfY29tYmluZWQgPC0gYmluZF9yb3dzKAogIGdldF90b3BfdXBkb3duKGZnX2gsICJIYWxsbWFyayIsIHRvcE4pLAogIGdldF90b3BfdXBkb3duKGZnX2tlZ2csICJLRUdHIiwgdG9wTiksCiAgZ2V0X3RvcF91cGRvd24oZmdfcmVhY3QsICJSZWFjdG9tZSIsIHRvcE4pLAogIGdldF90b3BfdXBkb3duKGZnX2JwLCAiR086QlAiLCB0b3BOKQopCgojIEVuc3VyZSBsZWFkaW5nRWRnZSBpcyBjaGFyYWN0ZXIgZm9yIENTVgpmZ19jb21iaW5lZCRsZWFkaW5nRWRnZSA8LSBhcy5jaGFyYWN0ZXIoZmdfY29tYmluZWQkbGVhZGluZ0VkZ2UpCgojIFBsb3QgY29tYmluZWQgZG90cGxvdApsaWJyYXJ5KGdncGxvdDIpCgpwX2NvbWJpbmVkIDwtIGdncGxvdChmZ19jb21iaW5lZCwgCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gTkVTLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSByZW9yZGVyKHBhdGh3YXksIE5FUyksCiAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGRpcmVjdGlvbiwgICMgVXAgPSByZWQsIERvd24gPSBibHVlCiAgICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IGRhdGFzZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gbGVhZGluZ0VkZ2VDb3VudCkpICsKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJVcCI9InJlZCIsICJEb3duIj0iYmx1ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlPSIiLAogICAgICAgeD0iTm9ybWFsaXplZCBFbnJpY2htZW50IFNjb3JlIChORVMpIiwKICAgICAgIHk9IlBhdGh3YXkiLAogICAgICAgY29sb3I9IkRpcmVjdGlvbiIsCiAgICAgICBzaGFwZT0iRGF0YXNldCIsCiAgICAgICBzaXplPSJMZWFkaW5nIGVkZ2UgZ2VuZXMiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT04LCBmYWNlPSJib2xkIikpICAjIDwtLS0gbWFrZSBsYWJlbHMgYm9sZAoKIyBTYXZlIGZpZ3VyZQpnZ3NhdmUoImZnc2VhX3RvcDNfdXBkb3duX2NvbWJpbmVkLnBuZyIsIHBfY29tYmluZWQsIHdpZHRoPTksIGhlaWdodD02LCBkcGk9MzAwKQoKcF9jb21iaW5lZAoKCgoKYGBgCgoKIyA1LiBFbnJpY2htZW50IG1hcCAvIGNuZXRwbG90IGZvciBsZWFkaW5nLWVkZ2UgZ2VuZXMKYGBge3IsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0gMTZ9CgojIyMjIEVucmljaG1lbnQgbWFwIC8gY25ldHBsb3QgZm9yIGxlYWRpbmctZWRnZSBnZW5lcyAjIyMjCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KGVucmljaHBsb3QpCmxpYnJhcnkodGlkeXZlcnNlKQoKIyAtLS0tIEZ1bmN0aW9uIC0tLS0KbWFrZV9jbmV0X2VtYXAgPC0gZnVuY3Rpb24oZmdzZWFfcmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRod2F5cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXNldF9uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICBwYWRqX2N1dG9mZiA9IDAuMjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcE5fZmFsbGJhY2sgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd0NhdGVnb3J5ID0gMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbGRfY2hhbmdlX3ZlYyA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdmVfcGxvdHMgPSBUUlVFKSB7CiAgCiAgbWVzc2FnZSgiUHJvY2Vzc2luZyBkYXRhc2V0OiAiLCBkYXRhc2V0X25hbWUpCiAgCiAgIyAxKSBUcnkgdG8gZmlsdGVyIGJ5IHBhZGoKICBsZWFkaW5nX2xpc3QgPC0gZmdzZWFfcmVzICU+JQogICAgZmlsdGVyKHBhZGogPCBwYWRqX2N1dG9mZikgJT4lCiAgICBzZWxlY3QocGF0aHdheSwgbGVhZGluZ0VkZ2UpICU+JQogICAgbXV0YXRlKGxlYWRpbmdFZGdlID0gbWFwKGxlYWRpbmdFZGdlLCBhcy5jaGFyYWN0ZXIpKSAlPiUKICAgIGRlZnJhbWUoKQogIAogICMgMikgRmFsbGJhY2s6IGlmIHRvbyBmZXcsIHRha2UgdG9wTiBwYXRod2F5cyBieSBORVMKICBpZiAobGVuZ3RoKGxlYWRpbmdfbGlzdCkgPCAyKSB7CiAgICBtZXNzYWdlKCLimqAgTm8gcGF0aHdheXMgcGFzcyBwYWRqIDwiLCBwYWRqX2N1dG9mZiwgCiAgICAgICAgICAgICIgZm9yICIsIGRhdGFzZXRfbmFtZSwgIi4gVXNpbmcgdG9wICIsIHRvcE5fZmFsbGJhY2ssICIgcGF0aHdheXMgYnkgTkVTLiIpCiAgICAKICAgIGxlYWRpbmdfbGlzdCA8LSBmZ3NlYV9yZXMgJT4lCiAgICAgIGFycmFuZ2UocGFkaiwgZGVzYyhhYnMoTkVTKSkpICU+JQogICAgICBzbGljZV9oZWFkKG4gPSB0b3BOX2ZhbGxiYWNrKSAlPiUKICAgICAgc2VsZWN0KHBhdGh3YXksIGxlYWRpbmdFZGdlKSAlPiUKICAgICAgbXV0YXRlKGxlYWRpbmdFZGdlID0gbWFwKGxlYWRpbmdFZGdlLCBhcy5jaGFyYWN0ZXIpKSAlPiUKICAgICAgZGVmcmFtZSgpCiAgfQogIAogIGlmIChsZW5ndGgobGVhZGluZ19saXN0KSA8IDIpIHsKICAgIG1lc3NhZ2UoIuKdjCBTdGlsbCB0b28gZmV3IHBhdGh3YXlzIGZvciAiLCBkYXRhc2V0X25hbWUsICIg4oCUIHNraXBwaW5nLiIpCiAgICByZXR1cm4oTlVMTCkKICB9CiAgCiAgIyBURVJNMkdFTkUgY29udmVyc2lvbgogIGxlYWRfdGVybTJnZW5lIDwtIGVuZnJhbWUobGVhZGluZ19saXN0LCBuYW1lID0gIlRFUk0iLCB2YWx1ZSA9ICJHRU5FIikgJT4lCiAgICB1bm5lc3QoY29scyA9IGMoR0VORSkpCiAgCiAgIyBVbmlvbiBvZiBsZWFkaW5nLWVkZ2UgZ2VuZXMKICB1bmlvbl9sZWFkaW5nX2dlbmVzIDwtIHVuaXF1ZSh1bmxpc3QobGVhZGluZ19saXN0KSkKICAKICBpZiAobGVuZ3RoKHVuaW9uX2xlYWRpbmdfZ2VuZXMpIDwgMikgewogICAgbWVzc2FnZSgi4p2MIFRvbyBmZXcgbGVhZGluZy1lZGdlIGdlbmVzIGZvciAiLCBkYXRhc2V0X25hbWUsICIg4oCUIHNraXBwaW5nLiIpCiAgICByZXR1cm4oTlVMTCkKICB9CiAgCiAgIyBSdW4gZW5yaWNobWVudCAodmVyeSByZWxheGVkIG1pbi9tYXggc2l6ZXMpCiAgZW5yIDwtIGVucmljaGVyKAogICAgdW5pb25fbGVhZGluZ19nZW5lcywKICAgIFRFUk0yR0VORSA9IGxlYWRfdGVybTJnZW5lLAogICAgbWluR1NTaXplID0gMSwKICAgIG1heEdTU2l6ZSA9IDUwMDAKICApCiAgCiAgaWYgKGlzLm51bGwoZW5yKSB8fCBucm93KGVucikgPT0gMCkgewogICAgbWVzc2FnZSgi4p2MIE5vIGVucmljaG1lbnQgcmVzdWx0IGZvciAiLCBkYXRhc2V0X25hbWUpCiAgICByZXR1cm4oTlVMTCkKICB9CiAgCiAgIyAtLS0tIGNuZXRwbG90IC0tLS0KICBjbmV0IDwtIGNuZXRwbG90KAogICAgZW5yLAogICAgZm9sZENoYW5nZSA9IGZvbGRfY2hhbmdlX3ZlYywKICAgIHNob3dDYXRlZ29yeSA9IHNob3dDYXRlZ29yeSwKICAgIGNpcmN1bGFyID0gRkFMU0UsCiAgICBjb2xvckVkZ2UgPSBUUlVFCiAgKSArIGdndGl0bGUocGFzdGUoIkNuZXRwbG90IOKAlCIsIGRhdGFzZXRfbmFtZSkpCiAgCiAgaWYgKHNhdmVfcGxvdHMpIHsKICAgIGdnc2F2ZSgKICAgICAgcGFzdGUwKCJjbmV0cGxvdF9sZWFkaW5nRWRnZV8iLCBkYXRhc2V0X25hbWUsICIucG5nIiksCiAgICAgIGNuZXQsCiAgICAgIHdpZHRoID0gMTIsIGhlaWdodCA9IDgsIGRwaSA9IDMwMAogICAgKQogIH0KICAKICAjIC0tLS0gZW1hcHBsb3QgLS0tLQogIGVtYXAgPC0gcGFpcndpc2VfdGVybXNpbShlbnIpCiAgZW1hcF9wbG90IDwtIGVtYXBwbG90KGVtYXAsIHNob3dDYXRlZ29yeSA9IHNob3dDYXRlZ29yeSkgKwogICAgZ2d0aXRsZShwYXN0ZSgiRW5yaWNobWVudCBNYXAg4oCUIiwgZGF0YXNldF9uYW1lKSkKICAKICBpZiAoc2F2ZV9wbG90cykgewogICAgZ2dzYXZlKAogICAgICBwYXN0ZTAoImVtYXBwbG90X2xlYWRpbmdFZGdlXyIsIGRhdGFzZXRfbmFtZSwgIi5wbmciKSwKICAgICAgZW1hcF9wbG90LAogICAgICB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDAKICAgICkKICB9CiAgCiAgcmV0dXJuKGxpc3QoZW5yaWNoX3JlcyA9IGVuciwgY25ldCA9IGNuZXQsIGVtYXAgPSBlbWFwX3Bsb3QpKQp9CgojIC0tLS0gUnVuIGZvciBhbGwgZGF0YXNldHMgLS0tLQojIE9wdGlvbmFsOiBmb2xkLWNoYW5nZSB2ZWN0b3IgZnJvbSBERSByZXN1bHRzCmZvbGRfY2hhbmdlX3ZlYyA8LSBzZXROYW1lcyhkZSRhdmdfbG9nRkMsIGRlJGdlbmUpCgpyZXNfaCAgICAgPC0gbWFrZV9jbmV0X2VtYXAoZmdfaCwgICAgIHBhdGh3YXlzX2gsICAgICAiSGFsbG1hcmsiLCBmb2xkX2NoYW5nZV92ZWMgPSBmb2xkX2NoYW5nZV92ZWMpCnJlc19rZWdnICA8LSBtYWtlX2NuZXRfZW1hcChmZ19rZWdnLCAgcGF0aHdheXNfa2VnZywgICJLRUdHIiwgICAgIGZvbGRfY2hhbmdlX3ZlYyA9IGZvbGRfY2hhbmdlX3ZlYykKcmVzX3JlYWN0IDwtIG1ha2VfY25ldF9lbWFwKGZnX3JlYWN0LCBwYXRod2F5c19yZWFjdCwgIlJlYWN0b21lIiwgZm9sZF9jaGFuZ2VfdmVjID0gZm9sZF9jaGFuZ2VfdmVjKQpyZXNfYnAgICAgPC0gbWFrZV9jbmV0X2VtYXAoZmdfYnAsICAgIHBhdGh3YXlzX2JwLCAgICAiR09fQlAiLCAgICBmb2xkX2NoYW5nZV92ZWMgPSBmb2xkX2NoYW5nZV92ZWMpCgptZXNzYWdlKCLinIUgRmluaXNoZWQgQ25ldC9FbnJpY2htZW50IG1hcCBwbG90cyBmb3IgYWxsIGRhdGFzZXRzIikKCmBgYAoKCmBgYHtyLCAgZmlnLmhlaWdodD0yMiwgZmlnLndpZHRoPSAyNn0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQoKCnRvcFBhdGh3YXlzIDwtIGZnX2hbWyJwYXRod2F5Il1dICU+JSBoZWFkKDEwKQp0aXRsZXMgPC0gc3ViKCJIQUxMTUFSS18iLCAiIiwgdG9wUGF0aHdheXMpCgoKIyBNYWtlIHN1cmUgdG9wUGF0aHdheXMgYXJlIGluIHRoZSBIYWxsbWFyayBsaXN0CnRvcFBhdGh3YXlzIDwtIGludGVyc2VjdCh0b3BQYXRod2F5cywgbmFtZXMocGF0aHdheXNfaCkpCgojIFRpdGxlcyBmb3IgcGxvdHMKdGl0bGVzIDwtIHN1YigiSEFMTE1BUktfIiwgIiIsIHRvcFBhdGh3YXlzKQoKIyBVc2UgU0NUIGFzc2F5IGV4cGxpY2l0bHkKRGVmYXVsdEFzc2F5KG9iaikgPC0gIlNDVCIKCiMgUnVuIHBsb3RDb3JlZ3VsYXRpb25Qcm9maWxlUmVkdWN0aW9uCnBzIDwtIHBsb3RDb3JlZ3VsYXRpb25Qcm9maWxlUmVkdWN0aW9uKAogIHBhdGh3YXlzX2hbdG9wUGF0aHdheXNdLAogIG9iaiwKICBhc3NheSA9ICJTQ1QiLCAgICAgICAgICMgZXhwbGljaXRseSB1c2UgU0NUIGFzc2F5CiAgdGl0bGUgPSB0aXRsZXMsCiAgcmVkdWN0aW9uID0gInVtYXAiCikKCiMgQ29tYmluZSBwbG90cwpjb3dwbG90OjpwbG90X2dyaWQocGxvdGxpc3QgPSBwc1sxOmxlbmd0aChwcyldLCBuY29sID0gMikKCgoKYGBgCmBgYHtyLCAgZmlnLmhlaWdodD0yMiwgZmlnLndpZHRoPSAyNn0KCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQoKIyAx77iP4oOjIFNvcnQgdGhlIEhhbGxtYXJrIEZHU0VBIHRhYmxlIGJ5IE5FUwpmZ19oX3NvcnRlZCA8LSBmZ19oICU+JSBhcnJhbmdlKGRlc2MoTkVTKSkgICMgZGVzY2VuZGluZyBORVMKCiMgMu+4j+KDoyBHZXQgdG9wIDEwIHVwIGFuZCB0b3AgMTAgZG93biBwYXRod2F5cwp0b3BfdXAgICA8LSBmZ19oX3NvcnRlZCRwYXRod2F5WzE6MTBdICAgICAgICMgdG9wIDEwIHVwIGJ5IE5FUwp0b3BfZG93biA8LSBmZ19oX3NvcnRlZCAlPiUgYXJyYW5nZShORVMpICU+JSBzbGljZSgxOjEwKSAlPiUgcHVsbChwYXRod2F5KSAgIyB0b3AgMTAgZG93bgoKIyAz77iP4oOjIENvbWJpbmUgdXAgYW5kIGRvd24KdG9wUGF0aHdheXMgPC0gYyh0b3BfdXAsIHRvcF9kb3duKQoKIyBLZWVwIG9ubHkgcGF0aHdheXMgdGhhdCBleGlzdCBpbiB0aGUgSGFsbG1hcmsgZ2VuZSBzZXRzCnRvcFBhdGh3YXlzIDwtIGludGVyc2VjdCh0b3BQYXRod2F5cywgbmFtZXMocGF0aHdheXNfaCkpCgojIFRpdGxlcyBmb3IgcGxvdHRpbmcKdGl0bGVzIDwtIHN1YigiSEFMTE1BUktfIiwgIiIsIHRvcFBhdGh3YXlzKQoKIyBVc2UgU0NUIGFzc2F5IGV4cGxpY2l0bHkKRGVmYXVsdEFzc2F5KG9iaikgPC0gIlNDVCIKCiMgNO+4j+KDoyBSdW4gY28tcmVndWxhdGlvbiBVTUFQCnBzIDwtIHBsb3RDb3JlZ3VsYXRpb25Qcm9maWxlUmVkdWN0aW9uKAogIHBhdGh3YXlzX2hbdG9wUGF0aHdheXNdLAogIG9iaiwKICBhc3NheSA9ICJTQ1QiLAogIHRpdGxlID0gdGl0bGVzLAogIHJlZHVjdGlvbiA9ICJ1bWFwIgopCgojIDXvuI/ig6MgQ29tYmluZSBwbG90cyBpbiBhIGdyaWQKY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gcHNbMTpsZW5ndGgocHMpXSwgbmNvbCA9IDQpCgoKYGBgCmBgYHtyLCAgZmlnLmhlaWdodD0yMiwgZmlnLndpZHRoPSAyNn0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQoKCnRvcFBhdGh3YXlzIDwtIGZnX2tlZ2dbWyJwYXRod2F5Il1dICU+JSBoZWFkKDEwKQp0aXRsZXMgPC0gc3ViKCJLRUdHXyIsICIiLCB0b3BQYXRod2F5cykKCgojIE1ha2Ugc3VyZSB0b3BQYXRod2F5cyBhcmUgaW4gdGhlIEhhbGxtYXJrIGxpc3QKdG9wUGF0aHdheXMgPC0gaW50ZXJzZWN0KHRvcFBhdGh3YXlzLCBuYW1lcyhwYXRod2F5c19rZWdnKSkKCiMgVGl0bGVzIGZvciBwbG90cwp0aXRsZXMgPC0gc3ViKCJLRUdHXyIsICIiLCB0b3BQYXRod2F5cykKCiMgVXNlIFNDVCBhc3NheSBleHBsaWNpdGx5CkRlZmF1bHRBc3NheShvYmopIDwtICJTQ1QiCgojIFJ1biBwbG90Q29yZWd1bGF0aW9uUHJvZmlsZVJlZHVjdGlvbgpwcyA8LSBwbG90Q29yZWd1bGF0aW9uUHJvZmlsZVJlZHVjdGlvbigKICBwYXRod2F5c19rZWdnW3RvcFBhdGh3YXlzXSwKICBvYmosCiAgYXNzYXkgPSAiU0NUIiwgICAgICAgICAjIGV4cGxpY2l0bHkgdXNlIFNDVCBhc3NheQogIHRpdGxlID0gdGl0bGVzLAogIHJlZHVjdGlvbiA9ICJ1bWFwIgopCgojIENvbWJpbmUgcGxvdHMKY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gcHNbMTpsZW5ndGgocHMpXSwgbmNvbCA9IDIpCgoKCmBgYAoKCgpgYGB7ciwgIGZpZy5oZWlnaHQ9MjIsIGZpZy53aWR0aD0gMjZ9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKCgp0b3BQYXRod2F5cyA8LSBmZ19yZWFjdFtbInBhdGh3YXkiXV0gJT4lIGhlYWQoMTApCnRpdGxlcyA8LSBzdWIoIlJFQUNUT01FXyIsICIiLCB0b3BQYXRod2F5cykKCgojIE1ha2Ugc3VyZSB0b3BQYXRod2F5cyBhcmUgaW4gdGhlIEhhbGxtYXJrIGxpc3QKdG9wUGF0aHdheXMgPC0gaW50ZXJzZWN0KHRvcFBhdGh3YXlzLCBuYW1lcyhwYXRod2F5c19yZWFjdCkpCgojIFRpdGxlcyBmb3IgcGxvdHMKdGl0bGVzIDwtIHN1YigiUkVBQ1RPTUVfIiwgIiIsIHRvcFBhdGh3YXlzKQoKIyBVc2UgU0NUIGFzc2F5IGV4cGxpY2l0bHkKRGVmYXVsdEFzc2F5KG9iaikgPC0gIlNDVCIKCiMgUnVuIHBsb3RDb3JlZ3VsYXRpb25Qcm9maWxlUmVkdWN0aW9uCnBzIDwtIHBsb3RDb3JlZ3VsYXRpb25Qcm9maWxlUmVkdWN0aW9uKAogIHBhdGh3YXlzX3JlYWN0W3RvcFBhdGh3YXlzXSwKICBvYmosCiAgYXNzYXkgPSAiU0NUIiwgICAgICAgICAjIGV4cGxpY2l0bHkgdXNlIFNDVCBhc3NheQogIHRpdGxlID0gdGl0bGVzLAogIHJlZHVjdGlvbiA9ICJ1bWFwIgopCgojIENvbWJpbmUgcGxvdHMKY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gcHNbMTpsZW5ndGgocHMpXSwgbmNvbCA9IDIpCgoKCmBgYAoKYGBge3IsICBmaWcuaGVpZ2h0PTMwLCBmaWcud2lkdGg9IDIwfQoKIyBTb3J0IFJlYWN0b21lIEZHU0VBIHRhYmxlIGJ5IE5FUwpmZ19yZWFjdF9zb3J0ZWQgPC0gZmdfcmVhY3QgJT4lIGFycmFuZ2UoZGVzYyhORVMpKQoKIyBUb3AgMTAgdXAgYW5kIHRvcCAxMCBkb3duCnRvcF91cCAgIDwtIGZnX3JlYWN0X3NvcnRlZCRwYXRod2F5WzE6MTBdCnRvcF9kb3duIDwtIGZnX3JlYWN0X3NvcnRlZCAlPiUgYXJyYW5nZShORVMpICU+JSBzbGljZSgxOjEwKSAlPiUgcHVsbChwYXRod2F5KQoKIyBDb21iaW5lIGFuZCBrZWVwIG9ubHkgcGF0aHdheXMgcHJlc2VudCBpbiBSZWFjdG9tZSBnZW5lIHNldHMKdG9wUGF0aHdheXMgPC0gaW50ZXJzZWN0KGModG9wX3VwLCB0b3BfZG93biksIG5hbWVzKHBhdGh3YXlzX3JlYWN0KSkKCiMgVGl0bGVzCnRpdGxlcyA8LSBzdWIoIlJFQUNUT01FXyIsICIiLCB0b3BQYXRod2F5cykKCiMgU0NUIGFzc2F5CkRlZmF1bHRBc3NheShvYmopIDwtICJTQ1QiCgojIFJ1biBjby1yZWd1bGF0aW9uIFVNQVAKcHMgPC0gcGxvdENvcmVndWxhdGlvblByb2ZpbGVSZWR1Y3Rpb24oCiAgcGF0aHdheXNfcmVhY3RbdG9wUGF0aHdheXNdLAogIG9iaiwKICBhc3NheSA9ICJTQ1QiLAogIHRpdGxlID0gdGl0bGVzLAogIHJlZHVjdGlvbiA9ICJ1bWFwIgopCgojIENvbWJpbmUgcGxvdHMKY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gcHNbMTpsZW5ndGgocHMpXSwgbmNvbCA9IDIpCgoKCmBgYAoKCgpgYGB7ciwgIGZpZy5oZWlnaHQ9MjIsIGZpZy53aWR0aD0gMjZ9CgpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKCgp0b3BQYXRod2F5cyA8LSBmZ19icFtbInBhdGh3YXkiXV0gJT4lIGhlYWQoMTApCnRpdGxlcyA8LSBzdWIoIkdPXyIsICIiLCB0b3BQYXRod2F5cykKCgojIE1ha2Ugc3VyZSB0b3BQYXRod2F5cyBhcmUgaW4gdGhlIEhhbGxtYXJrIGxpc3QKdG9wUGF0aHdheXMgPC0gaW50ZXJzZWN0KHRvcFBhdGh3YXlzLCBuYW1lcyhwYXRod2F5c19icCkpCgojIFRpdGxlcyBmb3IgcGxvdHMKdGl0bGVzIDwtIHN1YigiR09fIiwgIiIsIHRvcFBhdGh3YXlzKQoKIyBVc2UgU0NUIGFzc2F5IGV4cGxpY2l0bHkKRGVmYXVsdEFzc2F5KG9iaikgPC0gIlNDVCIKCiMgUnVuIHBsb3RDb3JlZ3VsYXRpb25Qcm9maWxlUmVkdWN0aW9uCnBzIDwtIHBsb3RDb3JlZ3VsYXRpb25Qcm9maWxlUmVkdWN0aW9uKAogIHBhdGh3YXlzX2JwW3RvcFBhdGh3YXlzXSwKICBvYmosCiAgYXNzYXkgPSAiU0NUIiwgICAgICAgICAjIGV4cGxpY2l0bHkgdXNlIFNDVCBhc3NheQogIHRpdGxlID0gdGl0bGVzLAogIHJlZHVjdGlvbiA9ICJ1bWFwIgopCgojIENvbWJpbmUgcGxvdHMKY293cGxvdDo6cGxvdF9ncmlkKHBsb3RsaXN0ID0gcHNbMTpsZW5ndGgocHMpXSwgbmNvbCA9IDIpCgoKCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9MzAsIGZpZy53aWR0aD0gMjB9CgojIFNvcnQgR086QlAgRkdTRUEgdGFibGUgYnkgTkVTCmZnX2JwX3NvcnRlZCA8LSBmZ19icCAlPiUgYXJyYW5nZShkZXNjKE5FUykpCgojIFRvcCAxMCB1cCBhbmQgdG9wIDEwIGRvd24KdG9wX3VwICAgPC0gZmdfYnBfc29ydGVkJHBhdGh3YXlbMToxMF0KdG9wX2Rvd24gPC0gZmdfYnBfc29ydGVkICU+JSBhcnJhbmdlKE5FUykgJT4lIHNsaWNlKDE6MTApICU+JSBwdWxsKHBhdGh3YXkpCgojIENvbWJpbmUgYW5kIGtlZXAgb25seSBwYXRod2F5cyBwcmVzZW50IGluIEdPOkJQIGdlbmUgc2V0cwp0b3BQYXRod2F5cyA8LSBpbnRlcnNlY3QoYyh0b3BfdXAsIHRvcF9kb3duKSwgbmFtZXMocGF0aHdheXNfYnApKQoKIyBUaXRsZXMKdGl0bGVzIDwtIHN1YigiR09fQlBfIiwgIiIsIHRvcFBhdGh3YXlzKQoKIyBTQ1QgYXNzYXkKRGVmYXVsdEFzc2F5KG9iaikgPC0gIlNDVCIKCiMgUnVuIGNvLXJlZ3VsYXRpb24gVU1BUApwcyA8LSBwbG90Q29yZWd1bGF0aW9uUHJvZmlsZVJlZHVjdGlvbigKICBwYXRod2F5c19icFt0b3BQYXRod2F5c10sCiAgb2JqLAogIGFzc2F5ID0gIlNDVCIsCiAgdGl0bGUgPSB0aXRsZXMsCiAgcmVkdWN0aW9uID0gInVtYXAiCikKCiMgQ29tYmluZSBwbG90cwpjb3dwbG90OjpwbG90X2dyaWQocGxvdGxpc3QgPSBwc1sxOmxlbmd0aChwcyldLCBuY29sID0gMikKCgpgYGA=