1. load libraries

#Differential Expression Analysis

2. load seurat object

#Load Seurat Object L7
load("/home/bioinfo/0-imp_Robj/Harmony_integrated_All_samples_Merged_with_PBMC10x_with_harmony_clustering.Robj")
# sct_data <- GetAssayData(All_samples_Merged, assay = "SCT", layer = "data")

# memory.limit(size = 64000)
# 
# # Transpose the data so that cells are rows and genes are columns
# transposed_data <- t(as.data.frame(sct_data))
# 
# # Specify the file name and save as CSV
# write.csv(transposed_data, file = "table/SCT_data_All_samples_Merged_transposed.csv", row.names = TRUE)
# 
# 
# 
# 
# 
# # Extract metadata from Seurat object
# metadata <- All_samples_Merged@meta.data
# 
# # Write metadata to CSV
# write.csv(metadata, file = "Extra/Metadata_All_samples_Merged.csv", row.names = TRUE)

2. create PBMC CD4 T cells file

library(dplyr)

# Load your CSV file
# data <- read.csv("Extra/NewFiles/pbmc_METADATA.csv")
# 
# # Filter rows where all three predicted columns contain "CD4 T"
# filtered_data <- data %>%
#   filter(grepl("CD4 T", predicted.celltype.l1) & 
#          grepl("CD4 T", predicted.celltype.l2) & 
#          grepl("CD4 T", predicted.celltype.l3))
# 
# # Write the filtered data to a new CSV file, including the header
# write.csv(filtered_data, "CD4Tcells_PBMC_Control.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) to a txt file without header
# write.table(filtered_data[, 1], "Extra/NewFiles/PBMC_CD4T_cells.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)
# 
# # Load your CSV file
# data <- read.csv("Extra/NewFiles/Cell_lines/Metadata_All_cell_lines.csv")
# 
# 
# # Define the clusters of interest
# clusters_of_interest <- c(3, 8, 10, 18, 1, 2, 13, 4, 7, 9, 6, 16, 19)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Cell_lines/filtered_cells_of_cell_lines_by_cluster.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Cell_lines/All_cell_lines_cells.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)
# 


# # Load your CSV file
# data <- read.csv("Extra/NewFiles/Cell_lines/Metadata_All_cell_lines.csv")
# 
# # To save P1 (L1+L2)
# # Define the clusters of interest
# clusters_of_interest <- c(3, 8, 10, 18)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P1.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P1.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)
# 
# 
# # To save P1 (L3+L4)
# # Define the clusters of interest
# clusters_of_interest <- c(1, 2, 13)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P2.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P2.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)
# 
# 
# 
# # To save P1 (L5+L6+L7)
# # Define the clusters of interest
# clusters_of_interest <- c(4, 7, 9, 6, 16, 19)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P3.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P3.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)

#Differential Expression Analysis

3. FC SCanner for DE

library(foreach)
library(doParallel)

setwd("/isilon/homes/nabbasi/6-DE/17-SingleCellFCscanner/")

source("scFCscanner_028_in_list.r")

Script to calculate logFC, Filter logFC >2 & logfc <-1.5, exclude lines when mean_L1_L7 <0.2 & control_group <0.2

# #load libraries------------------------------------
# library(dplyr)
# library(tidyverse)
# 
# # Read the TSV file into R
# Exp_Allsample <- read_tsv("Extra/NewFiles/Results/Cell_lines_vs_CD4Tcells/SCT_All_cell_lines_cells_vs_PBMC_CD4T_cells.tsv")
# 
# # Calculate log-fold change using FC column in the file
# Exp_Allsample$log2FC <- log2(Exp_Allsample$FC_All_cell_lines_cells_PBMC_CD4T_cells  )
# 
# # Filter rows based on logFC criteria
# filtered_data <- Exp_Allsample %>% filter(log2FC > 3 | log2FC < -1)
# 
# # Exclude rows with "L1-L7 mean" and "mean control" both less than 0.2
# filtered_data_final <- filtered_data %>% filter(!(mean_All_cell_lines_cells < 0.2 & mean_PBMC_CD4T_cells < 0.2))
# 
# # Writing it to CSV file
# write.csv(filtered_data_final, "Extra/NewFiles/Results/Cell_lines_vs_CD4Tcells/filtered_data_Cell_lines_vs_CD4Tcells.csv", row.names = FALSE)

Script to calculate logFC, Filter logFC >2 & logfc <-1.5, exclude lines when mean_P1 <0.2 & control_group <0.2


# Load necessary libraries ------------------------------------
library(dplyr)
library(readr)  # 'readr' package is recommended for reading .csv and .tsv files efficiently

# Read the TSV file into R
Exp_Allsample <- read_tsv("Extra/NewFiles/Patients_based_on_celllines_Clusters/Results_3_comparisons/SCT_data_All_samples_Merged_transposed_tab_P2_vs_P3.csv")

# Check if the first column name is missing, and if so, set it to "gene"
if (colnames(Exp_Allsample)[1] == "...1") {
  colnames(Exp_Allsample)[1] <- "gene"
}

# Calculate log2 fold-change directly within the pipe (using mutate)
Exp_Allsample <- Exp_Allsample %>%
  mutate(log2FC = log2(FC_P2_P3))  # Using mutate to add log2FC as a new column

# Check the summary statistics and distribution of log2FC before filtering
summary(Exp_Allsample$log2FC)
hist(Exp_Allsample$log2FC, main="Distribution of log2FC", xlab="log2FC", col="lightblue", border="black")

# Choose your own log2FC threshold for both positive and negative values
threshold_positive <- 1  # Set your chosen threshold for positive log2FC
threshold_negative <- -1  # Set your chosen threshold for negative log2FC

# Filter rows based on log2FC criteria (separate thresholds for positive and negative log2FC)
filtered_data_final <- Exp_Allsample %>%
  filter(log2FC > threshold_positive | log2FC < threshold_negative)  # Filter based on both conditions


filtered_data_final <- filtered_data_final %>%
  filter(!(mean_P2 < 0.2 & mean_P3 < 0.2))  

# Write the filtered data to a CSV file
write.csv(filtered_data_final, "Extra/NewFiles/Patients_based_on_celllines_Clusters/Results_3_comparisons/2-filtered_P2_vs_P3.csv", row.names = FALSE)

To extract cell line according to clusters

# Load necessary libraries ------------------------------------
library(dplyr)
library(readr)  # 'readr' package is recommended for reading .csv and .tsv files efficiently

# Load your CSV file
data <- read.csv("/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/Metadata_All_cell_lines.csv")

# Define a helper function to filter and save data
filter_and_save <- function(data, clusters, cell_line, output_csv, output_txt) {
  # Filter data based on clusters and cell line
  filtered_data <- data %>%
    filter(Harmony_snn_res.0.9 %in% clusters, orig.ident == cell_line)

  # Save the filtered data as a CSV file
  write.csv(filtered_data, output_csv, row.names = FALSE)

  # Save the first column (e.g., cell identifiers) as a TXT file without a header
  write.table(filtered_data[, 1], output_txt, row.names = FALSE, col.names = FALSE, quote = FALSE)
}

# Filter for L1 in P1
filter_and_save(
  data = data,
  clusters = c(3, 8, 10, 18),  # Replace with clusters for L1
  cell_line = "L1",  # Specify the cell line (e.g., "L1")
  output_csv = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P1_L1.csv",
  output_txt = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P1_L1.txt"
)

# Filter for L2 in P1
filter_and_save(
  data = data,
  clusters = c(3, 8, 10, 18),  # Replace with clusters for L2
  cell_line = "L2",  # Specify the cell line (e.g., "L2")
  output_csv = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P1_L2.csv",
  output_txt = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P1_L2.txt"
)

# Filter for L3 in P2
filter_and_save(
  data = data,
  clusters = c(1, 2, 13),  # Replace with clusters for L3
  cell_line = "L3",  # Specify the cell line (e.g., "L3")
  output_csv = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P2_L3.csv",
  output_txt = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P2_L3.txt"
)

# Filter for L4 in P2
filter_and_save(
  data = data,
  clusters = c(1, 2, 13),  # Replace with clusters for L4
  cell_line = "L4",  # Specify the cell line (e.g., "L4")
  output_csv = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P2_L4.csv",
  output_txt = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P2_L4.txt"
)

# Filter for L5 in P3
filter_and_save(
  data = data,
  clusters = c(4, 7, 9, 6, 16, 19),  # Replace with clusters for L5
  cell_line = "L5",  # Specify the cell line (e.g., "L5")
  output_csv = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P3_L5.csv",
  output_txt = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P3_L5.txt"
)

# Filter for L6 in P3
filter_and_save(
  data = data,
  clusters = c(4, 7, 9, 6, 16, 19),  # Replace with clusters for L6
  cell_line = "L6",  # Specify the cell line (e.g., "L6")
  output_csv = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P3_L6.csv",
  output_txt = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P3_L6.txt"
)

# Filter for L7 in P3
filter_and_save(
  data = data,
  clusters = c(4, 7, 9, 6, 16, 19),  # Replace with clusters for L7
  cell_line = "L7",  # Specify the cell line (e.g., "L7")
  output_csv = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P3_L7.csv",
  output_txt = "/home/bioinfo/17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/P3_L7.txt"
)

FC SCanner for DE

library(foreach)
library(doParallel)

setwd("/home/bioinfo/17-SingleCellFCscanner/")

source("scFCscanner_028_in_list.r")

To extract cell line according to clusters


# Load necessary libraries ------------------------------------
library(dplyr)
library(readr)  # 'readr' package is recommended for reading .csv and .tsv files efficiently

# Read the TSV file into R
Exp_Allsample <- read_tsv("Extra/NewFiles/Cell_lines/cell_lines/cell_lines_vs_control/P2_L4_vs_PBMC_CD4T_cells.csv")

# Check if the first column name is missing, and if so, set it to "gene"
if (colnames(Exp_Allsample)[1] == "...1") {
  colnames(Exp_Allsample)[1] <- "gene"
}

# Calculate log2 fold-change directly within the pipe (using mutate)
Exp_Allsample <- Exp_Allsample %>%
  mutate(log2FC = log2(FC_P2_L4_PBMC_CD4T_cells))  # Using mutate to add log2FC as a new column

# Check the summary statistics and distribution of log2FC before filtering
summary(Exp_Allsample$log2FC)
hist(Exp_Allsample$log2FC, main="Distribution of log2FC", xlab="log2FC", col="lightblue", border="black")

# Choose your own log2FC threshold for both positive and negative values
threshold_positive <- 3.5  # Set your chosen threshold for positive log2FC
threshold_negative <- -1  # Set your chosen threshold for negative log2FC

# Filter rows based on log2FC criteria (separate thresholds for positive and negative log2FC)
filtered_data <- Exp_Allsample %>%
  filter(log2FC > threshold_positive | log2FC < threshold_negative)  # Filter based on both conditions


filtered_data_final <- filtered_data %>%
  filter(!(mean_P2_L4 < 0.2 & mean_PBMC_CD4T_cells < 0.2))  

# Write the filtered data to a CSV file
write.csv(filtered_data_final, "Extra/NewFiles/Cell_lines/cell_lines/cell_lines_vs_control/filtered_P2_L4_vs_PBMC_CD4T_cells.csv", row.names = FALSE)

To extract Clusters to compare to control

# Load necessary libraries ------------------------------------
library(dplyr)
library(readr)  # 'readr' package is recommended for reading .csv and .tsv files efficiently

# Load your CSV file
data <- read.csv("../17-SingleCellFCscanner/Extra/NewFiles/Cell_lines/Metadata_All_cell_lines.csv")


# # Define the clusters of interest
# clusters_of_interest <- c(3, 8, 10, 18, 1, 2, 13, 4, 7, 9, 6, 16, 19)

# Define the clusters of interest
clusters_of_interest <- c(19)

# Filter cells based on the specified clusters
filtered_data <- data %>%
  filter(Harmony_snn_res.0.9 %in% clusters_of_interest)

# Write the filtered data to a new CSV file
write.csv(filtered_data, "../17-SingleCellFCscanner/Extra/NewFiles/Clusters/filtered_cluster19.csv", row.names = FALSE)

# Save the first column (PBMC cells) without the header to a txt file
write.table(filtered_data[, 1], "Extra/NewFiles/Clusters/Cluster19_cells.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)

To extract cell line according to clusters


# Load necessary libraries ------------------------------------
library(dplyr)
library(readr)  # 'readr' package is recommended for reading .csv and .tsv files efficiently

# Read the TSV file into R
Exp_Allsample <- read_tsv("Extra/NewFiles/Clusters/Clusters_vs_control/C19_cells_vs_PBMC_CD4T_cells.csv")

# Check if the first column name is missing, and if so, set it to "gene"
if (colnames(Exp_Allsample)[1] == "...1") {
  colnames(Exp_Allsample)[1] <- "gene"
}

# Calculate log2 fold-change directly within the pipe (using mutate)
Exp_Allsample <- Exp_Allsample %>%
  mutate(log2FC = log2(FC_Cluster19_cells_PBMC_CD4T_cells))  # Using mutate to add log2FC as a new column

# Check the summary statistics and distribution of log2FC before filtering
summary(Exp_Allsample$log2FC)
hist(Exp_Allsample$log2FC, main="Distribution of log2FC", xlab="log2FC", col="lightblue", border="black")

# Choose your own log2FC threshold for both positive and negative values
threshold_positive <- 4  # Set your chosen threshold for positive log2FC
threshold_negative <- -2  # Set your chosen threshold for negative log2FC

# Filter rows based on log2FC criteria (separate thresholds for positive and negative log2FC)
filtered_data <- Exp_Allsample %>%
  filter(log2FC > threshold_positive | log2FC < threshold_negative)  # Filter based on both conditions


filtered_data_final <- filtered_data %>%
  filter(!(mean_Cluster19_cells < 0.2 & mean_PBMC_CD4T_cells < 0.2))  

# Write the filtered data to a CSV file
write.csv(filtered_data_final, "Extra/NewFiles/Clusters/Clusters_vs_control/2-filtered_C19_vs_PBMC_CD4T_cells.csv", row.names = FALSE)

Barplot for up and down regulated genes

# Define file paths
input_file <- "Extra/NewFiles/Clusters/Clusters_vs_control/2-filtered_C19_vs_PBMC_CD4T_cells.csv"
output_folder <- "Extra/NewFiles/Clusters/Clusters_vs_control/Enrichment_files/"

# Ensure output folder exists
if (!dir.exists(output_folder)) {
  dir.create(output_folder, recursive = TRUE)
}

# Load the data (handling errors gracefully)
data <- tryCatch({
  read_csv(input_file)
}, error = function(e) {
  stop("Error reading input file. Check the file path or format.")
})

# Check if the necessary columns exist
if (!all(c("log2FC", "gene") %in% colnames(data))) {
  stop("Required columns ('log2FC' and 'gene') are missing in the data.")
}

# Filter for upregulated and downregulated genes
upregulated_genes <- data %>% filter(log2FC > 0)
downregulated_genes <- data %>% filter(log2FC < 0)

# Extract only gene names as vectors
upregulated_gene_names <- upregulated_genes %>% pull(gene)
downregulated_gene_names <- downregulated_genes %>% pull(gene)

# Define output file paths
upregulated_file <- file.path(output_folder, "upregulated_gene_names.txt")
downregulated_file <- file.path(output_folder, "downregulated_gene_names.txt")

# Save the gene names to text files
write_lines(upregulated_gene_names, upregulated_file)
write_lines(downregulated_gene_names, downregulated_file)

# Print the number of upregulated and downregulated genes
cat("Number of upregulated genes:", length(upregulated_gene_names), "\n")
cat("Number of downregulated genes:", length(downregulated_gene_names), "\n")
cat("Gene names saved to:\n")
cat("  Upregulated genes: ", upregulated_file, "\n")
cat("  Downregulated genes: ", downregulated_file, "\n")

create PBMC CD4 T cells file

library(dplyr)

# Load your CSV file
data <- read.csv("Extra/NewFiles/Cell_lines/filtered_cells_of_cell_lines_by_cluster.csv")

# Filter rows where all three predicted columns contain "CD4 T"
filtered_data <- data %>%
  filter(grepl("B memory", predicted.celltype.l2) &
         grepl("B memory lambda", predicted.celltype.l3))

# Write the filtered data to a new CSV file, including the header
write.csv(filtered_data, "Extra/NewFiles/B_memory_in_cellline_clusters.csv", row.names = FALSE)

# Save the first column (PBMC cells) to a txt file without header
write.table(filtered_data[, 1], "Extra/NewFiles/B_memory_cells_in_cellline_clusters.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)

# # Load your CSV file
# data <- read.csv("Extra/NewFiles/Cell_lines/Metadata_All_cell_lines.csv")
# 
# 
# # Define the clusters of interest
# clusters_of_interest <- c(3, 8, 10, 18, 1, 2, 13, 4, 7, 9, 6, 16, 19)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Cell_lines/filtered_cells_of_cell_lines_by_cluster.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Cell_lines/All_cell_lines_cells.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)
# 


# # Load your CSV file
# data <- read.csv("Extra/NewFiles/Cell_lines/Metadata_All_cell_lines.csv")
# 
# # To save P1 (L1+L2)
# # Define the clusters of interest
# clusters_of_interest <- c(3, 8, 10, 18)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P1.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P1.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)
# 
# 
# # To save P1 (L3+L4)
# # Define the clusters of interest
# clusters_of_interest <- c(1, 2, 13)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P2.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P2.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)
# 
# 
# 
# # To save P1 (L5+L6+L7)
# # Define the clusters of interest
# clusters_of_interest <- c(4, 7, 9, 6, 16, 19)
# 
# # Filter cells based on the specified clusters
# filtered_data <- data %>%
#   filter(Harmony_snn_res.0.9 %in% clusters_of_interest)
# 
# # Write the filtered data to a new CSV file
# write.csv(filtered_data, "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P3.csv", row.names = FALSE)
# 
# # Save the first column (PBMC cells) without the header to a txt file
# write.table(filtered_data[, 1], "Extra/NewFiles/Patients_based_on_celllines(Clusters)/P3.txt", row.names = FALSE, col.names = FALSE, quote = FALSE)

FC SCanner for DE

library(foreach)
library(doParallel)

setwd("/home/bioinfo/17-SingleCellFCscanner/")

source("scFCscanner_028_in_list.r")

To extract cell line according to clusters


# Load necessary libraries ------------------------------------
library(dplyr)
library(readr)  # 'readr' package is recommended for reading .csv and .tsv files efficiently

# Read the TSV file into R
Exp_Allsample <- read_tsv("Extra/NewFiles/Other_cells_in_celllines/2-FC_scanner_Results/SCT_data_All_samples_Merged_transposed_tab_B_memory_cells_in_cellline_clusters_vs_PBMC_CD4T_cells.csv")

# Check if the first column name is missing, and if so, set it to "gene"
if (colnames(Exp_Allsample)[1] == "...1") {
  colnames(Exp_Allsample)[1] <- "gene"
}

# Calculate log2 fold-change directly within the pipe (using mutate)
Exp_Allsample <- Exp_Allsample %>%
  mutate(log2FC = log2(FC_B_memory_cells_in_cellline_clusters_PBMC_CD4T_cells))  # Using mutate to add log2FC as a new column

# Check the summary statistics and distribution of log2FC before filtering
summary(Exp_Allsample$log2FC)
hist(Exp_Allsample$log2FC, main="Distribution of log2FC", xlab="log2FC", col="lightblue", border="black")

# Choose your own log2FC threshold for both positive and negative values
threshold_positive <- 2.5  # Set your chosen threshold for positive log2FC
threshold_negative <- -1.5  # Set your chosen threshold for negative log2FC

# Filter rows based on log2FC criteria (separate thresholds for positive and negative log2FC)
filtered_data <- Exp_Allsample %>%
  filter(log2FC > threshold_positive | log2FC < threshold_negative)  # Filter based on both conditions


filtered_data_final <- filtered_data %>%
  filter(!(mean_B_memory_cells_in_cellline_clusters < 0.2 & mean_PBMC_CD4T_cells < 0.2))  

# Write the filtered data to a CSV file
write.csv(filtered_data_final, "Extra/NewFiles/Other_cells_in_celllines/3-files_for_Enrichment/2-filtered_B_memory_cells_in_cellline_clusters_vs_PBMC_CD4T_cells.csv", row.names = FALSE)

Barplot for up and down regulated genes

# Define file paths
input_file <- "Extra/NewFiles/Other_cells_in_celllines/3-files_for_Enrichment/2-filtered_NK_Proliferating_cells_in_cellline_clusters_vs_PBMC_CD4T_cells.csv"
output_folder <- "Extra/NewFiles/Other_cells_in_celllines/3-files_for_Enrichment/Enrichment_files/"

# Ensure output folder exists
if (!dir.exists(output_folder)) {
  dir.create(output_folder, recursive = TRUE)
}

# Load the data (handling errors gracefully)
data <- tryCatch({
  read_csv(input_file)
}, error = function(e) {
  stop("Error reading input file. Check the file path or format.")
})

# Check if the necessary columns exist
if (!all(c("log2FC", "gene") %in% colnames(data))) {
  stop("Required columns ('log2FC' and 'gene') are missing in the data.")
}

# Filter for upregulated and downregulated genes
upregulated_genes <- data %>% filter(log2FC > 0)
downregulated_genes <- data %>% filter(log2FC < 0)

# Extract only gene names as vectors
upregulated_gene_names <- upregulated_genes %>% pull(gene)
downregulated_gene_names <- downregulated_genes %>% pull(gene)

# Define output file paths
upregulated_file <- file.path(output_folder, "upregulated_gene_names.txt")
downregulated_file <- file.path(output_folder, "downregulated_gene_names.txt")

# Save the gene names to text files
write_lines(upregulated_gene_names, upregulated_file)
write_lines(downregulated_gene_names, downregulated_file)

# Print the number of upregulated and downregulated genes
cat("Number of upregulated genes:", length(upregulated_gene_names), "\n")
cat("Number of downregulated genes:", length(downregulated_gene_names), "\n")
cat("Gene names saved to:\n")
cat("  Upregulated genes: ", upregulated_file, "\n")
cat("  Downregulated genes: ", downregulated_file, "\n")

To extract cell line according to clusters

# Load necessary libraries ------------------------------------
library(dplyr)

Attachement du package : ‘dplyr’

Les objets suivants sont masqués depuis ‘package:stats’:

    filter, lag

Les objets suivants sont masqués depuis ‘package:base’:

    intersect, setdiff, setequal, union
library(readr)  # 'readr' package is recommended for reading .csv and .tsv files efficiently

# Read the TSV file into R
Exp_Allsample <- read_tsv("Extra/NewFiles/Results/Cell_lines_vs_CD4Tcells/SCT_All_cell_lines_cells_vs_PBMC_CD4T_cells.tsv")
New names:Rows: 27417 Columns: 8── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (1): ...1
dbl (7): mean_All_cell_lines_cells, mean_PBMC_CD4T_cells, Relative_variance_All_cell_lines_cells, Relative_variance_PBMC_CD4T_cells, FC_All_cell_lines_cel...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Check if the first column name is missing, and if so, set it to "gene"
if (colnames(Exp_Allsample)[1] == "...1") {
  colnames(Exp_Allsample)[1] <- "gene"
}

# Calculate log2 fold-change directly within the pipe (using mutate)
Exp_Allsample <- Exp_Allsample %>%
  mutate(log2FC = log2(FC_All_cell_lines_cells_PBMC_CD4T_cells))  # Using mutate to add log2FC as a new column
LS0tCnRpdGxlOiAiREUgd2l0aCBGQyBTY2FubmVyIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICMgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgIyB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CiAgIyBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGZvcmVhY2gpCmxpYnJhcnkoZG9QYXJhbGxlbCkKCgoKCmBgYAojRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMKCiMgMi4gbG9hZCBzZXVyYXQgb2JqZWN0CmBgYHtyIGxvYWRfc2V1cmF0LCAgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiNMb2FkIFNldXJhdCBPYmplY3QgTDcKbG9hZCgiL2hvbWUvYmlvaW5mby8wLWltcF9Sb2JqL0hhcm1vbnlfaW50ZWdyYXRlZF9BbGxfc2FtcGxlc19NZXJnZWRfd2l0aF9QQk1DMTB4X3dpdGhfaGFybW9ueV9jbHVzdGVyaW5nLlJvYmoiKQojIHNjdF9kYXRhIDwtIEdldEFzc2F5RGF0YShBbGxfc2FtcGxlc19NZXJnZWQsIGFzc2F5ID0gIlNDVCIsIGxheWVyID0gImRhdGEiKQoKIyBtZW1vcnkubGltaXQoc2l6ZSA9IDY0MDAwKQojIAojICMgVHJhbnNwb3NlIHRoZSBkYXRhIHNvIHRoYXQgY2VsbHMgYXJlIHJvd3MgYW5kIGdlbmVzIGFyZSBjb2x1bW5zCiMgdHJhbnNwb3NlZF9kYXRhIDwtIHQoYXMuZGF0YS5mcmFtZShzY3RfZGF0YSkpCiMgCiMgIyBTcGVjaWZ5IHRoZSBmaWxlIG5hbWUgYW5kIHNhdmUgYXMgQ1NWCiMgd3JpdGUuY3N2KHRyYW5zcG9zZWRfZGF0YSwgZmlsZSA9ICJ0YWJsZS9TQ1RfZGF0YV9BbGxfc2FtcGxlc19NZXJnZWRfdHJhbnNwb3NlZC5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQojIAojIAojIAojIAojIAojICMgRXh0cmFjdCBtZXRhZGF0YSBmcm9tIFNldXJhdCBvYmplY3QKIyBtZXRhZGF0YSA8LSBBbGxfc2FtcGxlc19NZXJnZWRAbWV0YS5kYXRhCiMgCiMgIyBXcml0ZSBtZXRhZGF0YSB0byBDU1YKIyB3cml0ZS5jc3YobWV0YWRhdGEsIGZpbGUgPSAiRXh0cmEvTWV0YWRhdGFfQWxsX3NhbXBsZXNfTWVyZ2VkLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCgoKYGBgCgojIDIuIGNyZWF0ZSBQQk1DIENENCBUIGNlbGxzIGZpbGUgCmBgYHtyIGF3aywgIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGRwbHlyKQoKIyBMb2FkIHlvdXIgQ1NWIGZpbGUKIyBkYXRhIDwtIHJlYWQuY3N2KCJFeHRyYS9OZXdGaWxlcy9wYm1jX01FVEFEQVRBLmNzdiIpCiMgCiMgIyBGaWx0ZXIgcm93cyB3aGVyZSBhbGwgdGhyZWUgcHJlZGljdGVkIGNvbHVtbnMgY29udGFpbiAiQ0Q0IFQiCiMgZmlsdGVyZWRfZGF0YSA8LSBkYXRhICU+JQojICAgZmlsdGVyKGdyZXBsKCJDRDQgVCIsIHByZWRpY3RlZC5jZWxsdHlwZS5sMSkgJiAKIyAgICAgICAgICBncmVwbCgiQ0Q0IFQiLCBwcmVkaWN0ZWQuY2VsbHR5cGUubDIpICYgCiMgICAgICAgICAgZ3JlcGwoIkNENCBUIiwgcHJlZGljdGVkLmNlbGx0eXBlLmwzKSkKIyAKIyAjIFdyaXRlIHRoZSBmaWx0ZXJlZCBkYXRhIHRvIGEgbmV3IENTViBmaWxlLCBpbmNsdWRpbmcgdGhlIGhlYWRlcgojIHdyaXRlLmNzdihmaWx0ZXJlZF9kYXRhLCAiQ0Q0VGNlbGxzX1BCTUNfQ29udHJvbC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKIyAKIyAjIFNhdmUgdGhlIGZpcnN0IGNvbHVtbiAoUEJNQyBjZWxscykgdG8gYSB0eHQgZmlsZSB3aXRob3V0IGhlYWRlcgojIHdyaXRlLnRhYmxlKGZpbHRlcmVkX2RhdGFbLCAxXSwgIkV4dHJhL05ld0ZpbGVzL1BCTUNfQ0Q0VF9jZWxscy50eHQiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCiMgCiMgIyBMb2FkIHlvdXIgQ1NWIGZpbGUKIyBkYXRhIDwtIHJlYWQuY3N2KCJFeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL01ldGFkYXRhX0FsbF9jZWxsX2xpbmVzLmNzdiIpCiMgCiMgCiMgIyBEZWZpbmUgdGhlIGNsdXN0ZXJzIG9mIGludGVyZXN0CiMgY2x1c3RlcnNfb2ZfaW50ZXJlc3QgPC0gYygzLCA4LCAxMCwgMTgsIDEsIDIsIDEzLCA0LCA3LCA5LCA2LCAxNiwgMTkpCiMgCiMgIyBGaWx0ZXIgY2VsbHMgYmFzZWQgb24gdGhlIHNwZWNpZmllZCBjbHVzdGVycwojIGZpbHRlcmVkX2RhdGEgPC0gZGF0YSAlPiUKIyAgIGZpbHRlcihIYXJtb255X3Nubl9yZXMuMC45ICVpbiUgY2x1c3RlcnNfb2ZfaW50ZXJlc3QpCiMgCiMgIyBXcml0ZSB0aGUgZmlsdGVyZWQgZGF0YSB0byBhIG5ldyBDU1YgZmlsZQojIHdyaXRlLmNzdihmaWx0ZXJlZF9kYXRhLCAiRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9maWx0ZXJlZF9jZWxsc19vZl9jZWxsX2xpbmVzX2J5X2NsdXN0ZXIuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgCiMgIyBTYXZlIHRoZSBmaXJzdCBjb2x1bW4gKFBCTUMgY2VsbHMpIHdpdGhvdXQgdGhlIGhlYWRlciB0byBhIHR4dCBmaWxlCiMgd3JpdGUudGFibGUoZmlsdGVyZWRfZGF0YVssIDFdLCAiRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9BbGxfY2VsbF9saW5lc19jZWxscy50eHQiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCiMgCgoKIyAjIExvYWQgeW91ciBDU1YgZmlsZQojIGRhdGEgPC0gcmVhZC5jc3YoIkV4dHJhL05ld0ZpbGVzL0NlbGxfbGluZXMvTWV0YWRhdGFfQWxsX2NlbGxfbGluZXMuY3N2IikKIyAKIyAjIFRvIHNhdmUgUDEgKEwxK0wyKQojICMgRGVmaW5lIHRoZSBjbHVzdGVycyBvZiBpbnRlcmVzdAojIGNsdXN0ZXJzX29mX2ludGVyZXN0IDwtIGMoMywgOCwgMTAsIDE4KQojIAojICMgRmlsdGVyIGNlbGxzIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgY2x1c3RlcnMKIyBmaWx0ZXJlZF9kYXRhIDwtIGRhdGEgJT4lCiMgICBmaWx0ZXIoSGFybW9ueV9zbm5fcmVzLjAuOSAlaW4lIGNsdXN0ZXJzX29mX2ludGVyZXN0KQojIAojICMgV3JpdGUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBuZXcgQ1NWIGZpbGUKIyB3cml0ZS5jc3YoZmlsdGVyZWRfZGF0YSwgIkV4dHJhL05ld0ZpbGVzL1BhdGllbnRzX2Jhc2VkX29uX2NlbGxsaW5lcyhDbHVzdGVycykvUDEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgCiMgIyBTYXZlIHRoZSBmaXJzdCBjb2x1bW4gKFBCTUMgY2VsbHMpIHdpdGhvdXQgdGhlIGhlYWRlciB0byBhIHR4dCBmaWxlCiMgd3JpdGUudGFibGUoZmlsdGVyZWRfZGF0YVssIDFdLCAiRXh0cmEvTmV3RmlsZXMvUGF0aWVudHNfYmFzZWRfb25fY2VsbGxpbmVzKENsdXN0ZXJzKS9QMS50eHQiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCiMgCiMgCiMgIyBUbyBzYXZlIFAxIChMMytMNCkKIyAjIERlZmluZSB0aGUgY2x1c3RlcnMgb2YgaW50ZXJlc3QKIyBjbHVzdGVyc19vZl9pbnRlcmVzdCA8LSBjKDEsIDIsIDEzKQojIAojICMgRmlsdGVyIGNlbGxzIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgY2x1c3RlcnMKIyBmaWx0ZXJlZF9kYXRhIDwtIGRhdGEgJT4lCiMgICBmaWx0ZXIoSGFybW9ueV9zbm5fcmVzLjAuOSAlaW4lIGNsdXN0ZXJzX29mX2ludGVyZXN0KQojIAojICMgV3JpdGUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBuZXcgQ1NWIGZpbGUKIyB3cml0ZS5jc3YoZmlsdGVyZWRfZGF0YSwgIkV4dHJhL05ld0ZpbGVzL1BhdGllbnRzX2Jhc2VkX29uX2NlbGxsaW5lcyhDbHVzdGVycykvUDIuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgCiMgIyBTYXZlIHRoZSBmaXJzdCBjb2x1bW4gKFBCTUMgY2VsbHMpIHdpdGhvdXQgdGhlIGhlYWRlciB0byBhIHR4dCBmaWxlCiMgd3JpdGUudGFibGUoZmlsdGVyZWRfZGF0YVssIDFdLCAiRXh0cmEvTmV3RmlsZXMvUGF0aWVudHNfYmFzZWRfb25fY2VsbGxpbmVzKENsdXN0ZXJzKS9QMi50eHQiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCiMgCiMgCiMgCiMgIyBUbyBzYXZlIFAxIChMNStMNitMNykKIyAjIERlZmluZSB0aGUgY2x1c3RlcnMgb2YgaW50ZXJlc3QKIyBjbHVzdGVyc19vZl9pbnRlcmVzdCA8LSBjKDQsIDcsIDksIDYsIDE2LCAxOSkKIyAKIyAjIEZpbHRlciBjZWxscyBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIGNsdXN0ZXJzCiMgZmlsdGVyZWRfZGF0YSA8LSBkYXRhICU+JQojICAgZmlsdGVyKEhhcm1vbnlfc25uX3Jlcy4wLjkgJWluJSBjbHVzdGVyc19vZl9pbnRlcmVzdCkKIyAKIyAjIFdyaXRlIHRoZSBmaWx0ZXJlZCBkYXRhIHRvIGEgbmV3IENTViBmaWxlCiMgd3JpdGUuY3N2KGZpbHRlcmVkX2RhdGEsICJFeHRyYS9OZXdGaWxlcy9QYXRpZW50c19iYXNlZF9vbl9jZWxsbGluZXMoQ2x1c3RlcnMpL1AzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQojIAojICMgU2F2ZSB0aGUgZmlyc3QgY29sdW1uIChQQk1DIGNlbGxzKSB3aXRob3V0IHRoZSBoZWFkZXIgdG8gYSB0eHQgZmlsZQojIHdyaXRlLnRhYmxlKGZpbHRlcmVkX2RhdGFbLCAxXSwgIkV4dHJhL05ld0ZpbGVzL1BhdGllbnRzX2Jhc2VkX29uX2NlbGxsaW5lcyhDbHVzdGVycykvUDMudHh0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKYGBgCgojRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMKCiMgMy4gRkMgU0Nhbm5lciBmb3IgREUKYGBge3IgRkNzY2FubmVyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KbGlicmFyeShmb3JlYWNoKQpsaWJyYXJ5KGRvUGFyYWxsZWwpCgpzZXR3ZCgiL2lzaWxvbi9ob21lcy9uYWJiYXNpLzYtREUvMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci8iKQoKc291cmNlKCJzY0ZDc2Nhbm5lcl8wMjhfaW5fbGlzdC5yIikKCmBgYAoKCiMjIFNjcmlwdCB0byBjYWxjdWxhdGUgbG9nRkMsIEZpbHRlciBsb2dGQyA+MiAmIGxvZ2ZjIDwtMS41LCBleGNsdWRlIGxpbmVzIHdoZW4gbWVhbl9MMV9MNyA8MC4yICYgY29udHJvbF9ncm91cCA8MC4yCmBgYHtyIEZDc2Nhbm5lcjIsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojICNsb2FkIGxpYnJhcmllcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIGxpYnJhcnkoZHBseXIpCiMgbGlicmFyeSh0aWR5dmVyc2UpCiMgCiMgIyBSZWFkIHRoZSBUU1YgZmlsZSBpbnRvIFIKIyBFeHBfQWxsc2FtcGxlIDwtIHJlYWRfdHN2KCJFeHRyYS9OZXdGaWxlcy9SZXN1bHRzL0NlbGxfbGluZXNfdnNfQ0Q0VGNlbGxzL1NDVF9BbGxfY2VsbF9saW5lc19jZWxsc192c19QQk1DX0NENFRfY2VsbHMudHN2IikKIyAKIyAjIENhbGN1bGF0ZSBsb2ctZm9sZCBjaGFuZ2UgdXNpbmcgRkMgY29sdW1uIGluIHRoZSBmaWxlCiMgRXhwX0FsbHNhbXBsZSRsb2cyRkMgPC0gbG9nMihFeHBfQWxsc2FtcGxlJEZDX0FsbF9jZWxsX2xpbmVzX2NlbGxzX1BCTUNfQ0Q0VF9jZWxscyAgKQojIAojICMgRmlsdGVyIHJvd3MgYmFzZWQgb24gbG9nRkMgY3JpdGVyaWEKIyBmaWx0ZXJlZF9kYXRhIDwtIEV4cF9BbGxzYW1wbGUgJT4lIGZpbHRlcihsb2cyRkMgPiAzIHwgbG9nMkZDIDwgLTEpCiMgCiMgIyBFeGNsdWRlIHJvd3Mgd2l0aCAiTDEtTDcgbWVhbiIgYW5kICJtZWFuIGNvbnRyb2wiIGJvdGggbGVzcyB0aGFuIDAuMgojIGZpbHRlcmVkX2RhdGFfZmluYWwgPC0gZmlsdGVyZWRfZGF0YSAlPiUgZmlsdGVyKCEobWVhbl9BbGxfY2VsbF9saW5lc19jZWxscyA8IDAuMiAmIG1lYW5fUEJNQ19DRDRUX2NlbGxzIDwgMC4yKSkKIyAKIyAjIFdyaXRpbmcgaXQgdG8gQ1NWIGZpbGUKIyB3cml0ZS5jc3YoZmlsdGVyZWRfZGF0YV9maW5hbCwgIkV4dHJhL05ld0ZpbGVzL1Jlc3VsdHMvQ2VsbF9saW5lc192c19DRDRUY2VsbHMvZmlsdGVyZWRfZGF0YV9DZWxsX2xpbmVzX3ZzX0NENFRjZWxscy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCgoKYGBgCgoKIyMgU2NyaXB0IHRvIGNhbGN1bGF0ZSBsb2dGQywgRmlsdGVyIGxvZ0ZDID4yICYgbG9nZmMgPC0xLjUsIGV4Y2x1ZGUgbGluZXMgd2hlbiBtZWFuX1AxIDwwLjIgJiBjb250cm9sX2dyb3VwIDwwLjIKYGBge3IgRkNzY2FubmVyMywgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkcikgICMgJ3JlYWRyJyBwYWNrYWdlIGlzIHJlY29tbWVuZGVkIGZvciByZWFkaW5nIC5jc3YgYW5kIC50c3YgZmlsZXMgZWZmaWNpZW50bHkKCiMgUmVhZCB0aGUgVFNWIGZpbGUgaW50byBSCkV4cF9BbGxzYW1wbGUgPC0gcmVhZF90c3YoIkV4dHJhL05ld0ZpbGVzL1BhdGllbnRzX2Jhc2VkX29uX2NlbGxsaW5lc19DbHVzdGVycy9SZXN1bHRzXzNfY29tcGFyaXNvbnMvU0NUX2RhdGFfQWxsX3NhbXBsZXNfTWVyZ2VkX3RyYW5zcG9zZWRfdGFiX1AyX3ZzX1AzLmNzdiIpCgojIENoZWNrIGlmIHRoZSBmaXJzdCBjb2x1bW4gbmFtZSBpcyBtaXNzaW5nLCBhbmQgaWYgc28sIHNldCBpdCB0byAiZ2VuZSIKaWYgKGNvbG5hbWVzKEV4cF9BbGxzYW1wbGUpWzFdID09ICIuLi4xIikgewogIGNvbG5hbWVzKEV4cF9BbGxzYW1wbGUpWzFdIDwtICJnZW5lIgp9CgojIENhbGN1bGF0ZSBsb2cyIGZvbGQtY2hhbmdlIGRpcmVjdGx5IHdpdGhpbiB0aGUgcGlwZSAodXNpbmcgbXV0YXRlKQpFeHBfQWxsc2FtcGxlIDwtIEV4cF9BbGxzYW1wbGUgJT4lCiAgbXV0YXRlKGxvZzJGQyA9IGxvZzIoRkNfUDJfUDMpKSAgIyBVc2luZyBtdXRhdGUgdG8gYWRkIGxvZzJGQyBhcyBhIG5ldyBjb2x1bW4KCiMgQ2hlY2sgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBhbmQgZGlzdHJpYnV0aW9uIG9mIGxvZzJGQyBiZWZvcmUgZmlsdGVyaW5nCnN1bW1hcnkoRXhwX0FsbHNhbXBsZSRsb2cyRkMpCmhpc3QoRXhwX0FsbHNhbXBsZSRsb2cyRkMsIG1haW49IkRpc3RyaWJ1dGlvbiBvZiBsb2cyRkMiLCB4bGFiPSJsb2cyRkMiLCBjb2w9ImxpZ2h0Ymx1ZSIsIGJvcmRlcj0iYmxhY2siKQoKIyBDaG9vc2UgeW91ciBvd24gbG9nMkZDIHRocmVzaG9sZCBmb3IgYm90aCBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzCnRocmVzaG9sZF9wb3NpdGl2ZSA8LSAxICAjIFNldCB5b3VyIGNob3NlbiB0aHJlc2hvbGQgZm9yIHBvc2l0aXZlIGxvZzJGQwp0aHJlc2hvbGRfbmVnYXRpdmUgPC0gLTEgICMgU2V0IHlvdXIgY2hvc2VuIHRocmVzaG9sZCBmb3IgbmVnYXRpdmUgbG9nMkZDCgojIEZpbHRlciByb3dzIGJhc2VkIG9uIGxvZzJGQyBjcml0ZXJpYSAoc2VwYXJhdGUgdGhyZXNob2xkcyBmb3IgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIGxvZzJGQykKZmlsdGVyZWRfZGF0YV9maW5hbCA8LSBFeHBfQWxsc2FtcGxlICU+JQogIGZpbHRlcihsb2cyRkMgPiB0aHJlc2hvbGRfcG9zaXRpdmUgfCBsb2cyRkMgPCB0aHJlc2hvbGRfbmVnYXRpdmUpICAjIEZpbHRlciBiYXNlZCBvbiBib3RoIGNvbmRpdGlvbnMKCgpmaWx0ZXJlZF9kYXRhX2ZpbmFsIDwtIGZpbHRlcmVkX2RhdGFfZmluYWwgJT4lCiAgZmlsdGVyKCEobWVhbl9QMiA8IDAuMiAmIG1lYW5fUDMgPCAwLjIpKSAgCgojIFdyaXRlIHRoZSBmaWx0ZXJlZCBkYXRhIHRvIGEgQ1NWIGZpbGUKd3JpdGUuY3N2KGZpbHRlcmVkX2RhdGFfZmluYWwsICJFeHRyYS9OZXdGaWxlcy9QYXRpZW50c19iYXNlZF9vbl9jZWxsbGluZXNfQ2x1c3RlcnMvUmVzdWx0c18zX2NvbXBhcmlzb25zLzItZmlsdGVyZWRfUDJfdnNfUDMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgoKCgpgYGAKCgoKIyMgVG8gZXh0cmFjdCBjZWxsIGxpbmUgYWNjb3JkaW5nIHRvIGNsdXN0ZXJzCmBgYHtyIGNlbGxfbGluZTEsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkcikgICMgJ3JlYWRyJyBwYWNrYWdlIGlzIHJlY29tbWVuZGVkIGZvciByZWFkaW5nIC5jc3YgYW5kIC50c3YgZmlsZXMgZWZmaWNpZW50bHkKCiMgTG9hZCB5b3VyIENTViBmaWxlCmRhdGEgPC0gcmVhZC5jc3YoIi9ob21lL2Jpb2luZm8vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL01ldGFkYXRhX0FsbF9jZWxsX2xpbmVzLmNzdiIpCgojIERlZmluZSBhIGhlbHBlciBmdW5jdGlvbiB0byBmaWx0ZXIgYW5kIHNhdmUgZGF0YQpmaWx0ZXJfYW5kX3NhdmUgPC0gZnVuY3Rpb24oZGF0YSwgY2x1c3RlcnMsIGNlbGxfbGluZSwgb3V0cHV0X2Nzdiwgb3V0cHV0X3R4dCkgewogICMgRmlsdGVyIGRhdGEgYmFzZWQgb24gY2x1c3RlcnMgYW5kIGNlbGwgbGluZQogIGZpbHRlcmVkX2RhdGEgPC0gZGF0YSAlPiUKICAgIGZpbHRlcihIYXJtb255X3Nubl9yZXMuMC45ICVpbiUgY2x1c3RlcnMsIG9yaWcuaWRlbnQgPT0gY2VsbF9saW5lKQoKICAjIFNhdmUgdGhlIGZpbHRlcmVkIGRhdGEgYXMgYSBDU1YgZmlsZQogIHdyaXRlLmNzdihmaWx0ZXJlZF9kYXRhLCBvdXRwdXRfY3N2LCByb3cubmFtZXMgPSBGQUxTRSkKCiAgIyBTYXZlIHRoZSBmaXJzdCBjb2x1bW4gKGUuZy4sIGNlbGwgaWRlbnRpZmllcnMpIGFzIGEgVFhUIGZpbGUgd2l0aG91dCBhIGhlYWRlcgogIHdyaXRlLnRhYmxlKGZpbHRlcmVkX2RhdGFbLCAxXSwgb3V0cHV0X3R4dCwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQp9CgojIEZpbHRlciBmb3IgTDEgaW4gUDEKZmlsdGVyX2FuZF9zYXZlKAogIGRhdGEgPSBkYXRhLAogIGNsdXN0ZXJzID0gYygzLCA4LCAxMCwgMTgpLCAgIyBSZXBsYWNlIHdpdGggY2x1c3RlcnMgZm9yIEwxCiAgY2VsbF9saW5lID0gIkwxIiwgICMgU3BlY2lmeSB0aGUgY2VsbCBsaW5lIChlLmcuLCAiTDEiKQogIG91dHB1dF9jc3YgPSAiL2hvbWUvYmlvaW5mby8xNy1TaW5nbGVDZWxsRkNzY2FubmVyL0V4dHJhL05ld0ZpbGVzL0NlbGxfbGluZXMvUDFfTDEuY3N2IiwKICBvdXRwdXRfdHh0ID0gIi9ob21lL2Jpb2luZm8vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL1AxX0wxLnR4dCIKKQoKIyBGaWx0ZXIgZm9yIEwyIGluIFAxCmZpbHRlcl9hbmRfc2F2ZSgKICBkYXRhID0gZGF0YSwKICBjbHVzdGVycyA9IGMoMywgOCwgMTAsIDE4KSwgICMgUmVwbGFjZSB3aXRoIGNsdXN0ZXJzIGZvciBMMgogIGNlbGxfbGluZSA9ICJMMiIsICAjIFNwZWNpZnkgdGhlIGNlbGwgbGluZSAoZS5nLiwgIkwyIikKICBvdXRwdXRfY3N2ID0gIi9ob21lL2Jpb2luZm8vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL1AxX0wyLmNzdiIsCiAgb3V0cHV0X3R4dCA9ICIvaG9tZS9iaW9pbmZvLzE3LVNpbmdsZUNlbGxGQ3NjYW5uZXIvRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9QMV9MMi50eHQiCikKCiMgRmlsdGVyIGZvciBMMyBpbiBQMgpmaWx0ZXJfYW5kX3NhdmUoCiAgZGF0YSA9IGRhdGEsCiAgY2x1c3RlcnMgPSBjKDEsIDIsIDEzKSwgICMgUmVwbGFjZSB3aXRoIGNsdXN0ZXJzIGZvciBMMwogIGNlbGxfbGluZSA9ICJMMyIsICAjIFNwZWNpZnkgdGhlIGNlbGwgbGluZSAoZS5nLiwgIkwzIikKICBvdXRwdXRfY3N2ID0gIi9ob21lL2Jpb2luZm8vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL1AyX0wzLmNzdiIsCiAgb3V0cHV0X3R4dCA9ICIvaG9tZS9iaW9pbmZvLzE3LVNpbmdsZUNlbGxGQ3NjYW5uZXIvRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9QMl9MMy50eHQiCikKCiMgRmlsdGVyIGZvciBMNCBpbiBQMgpmaWx0ZXJfYW5kX3NhdmUoCiAgZGF0YSA9IGRhdGEsCiAgY2x1c3RlcnMgPSBjKDEsIDIsIDEzKSwgICMgUmVwbGFjZSB3aXRoIGNsdXN0ZXJzIGZvciBMNAogIGNlbGxfbGluZSA9ICJMNCIsICAjIFNwZWNpZnkgdGhlIGNlbGwgbGluZSAoZS5nLiwgIkw0IikKICBvdXRwdXRfY3N2ID0gIi9ob21lL2Jpb2luZm8vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL1AyX0w0LmNzdiIsCiAgb3V0cHV0X3R4dCA9ICIvaG9tZS9iaW9pbmZvLzE3LVNpbmdsZUNlbGxGQ3NjYW5uZXIvRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9QMl9MNC50eHQiCikKCiMgRmlsdGVyIGZvciBMNSBpbiBQMwpmaWx0ZXJfYW5kX3NhdmUoCiAgZGF0YSA9IGRhdGEsCiAgY2x1c3RlcnMgPSBjKDQsIDcsIDksIDYsIDE2LCAxOSksICAjIFJlcGxhY2Ugd2l0aCBjbHVzdGVycyBmb3IgTDUKICBjZWxsX2xpbmUgPSAiTDUiLCAgIyBTcGVjaWZ5IHRoZSBjZWxsIGxpbmUgKGUuZy4sICJMNSIpCiAgb3V0cHV0X2NzdiA9ICIvaG9tZS9iaW9pbmZvLzE3LVNpbmdsZUNlbGxGQ3NjYW5uZXIvRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9QM19MNS5jc3YiLAogIG91dHB1dF90eHQgPSAiL2hvbWUvYmlvaW5mby8xNy1TaW5nbGVDZWxsRkNzY2FubmVyL0V4dHJhL05ld0ZpbGVzL0NlbGxfbGluZXMvUDNfTDUudHh0IgopCgojIEZpbHRlciBmb3IgTDYgaW4gUDMKZmlsdGVyX2FuZF9zYXZlKAogIGRhdGEgPSBkYXRhLAogIGNsdXN0ZXJzID0gYyg0LCA3LCA5LCA2LCAxNiwgMTkpLCAgIyBSZXBsYWNlIHdpdGggY2x1c3RlcnMgZm9yIEw2CiAgY2VsbF9saW5lID0gIkw2IiwgICMgU3BlY2lmeSB0aGUgY2VsbCBsaW5lIChlLmcuLCAiTDYiKQogIG91dHB1dF9jc3YgPSAiL2hvbWUvYmlvaW5mby8xNy1TaW5nbGVDZWxsRkNzY2FubmVyL0V4dHJhL05ld0ZpbGVzL0NlbGxfbGluZXMvUDNfTDYuY3N2IiwKICBvdXRwdXRfdHh0ID0gIi9ob21lL2Jpb2luZm8vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL1AzX0w2LnR4dCIKKQoKIyBGaWx0ZXIgZm9yIEw3IGluIFAzCmZpbHRlcl9hbmRfc2F2ZSgKICBkYXRhID0gZGF0YSwKICBjbHVzdGVycyA9IGMoNCwgNywgOSwgNiwgMTYsIDE5KSwgICMgUmVwbGFjZSB3aXRoIGNsdXN0ZXJzIGZvciBMNwogIGNlbGxfbGluZSA9ICJMNyIsICAjIFNwZWNpZnkgdGhlIGNlbGwgbGluZSAoZS5nLiwgIkw3IikKICBvdXRwdXRfY3N2ID0gIi9ob21lL2Jpb2luZm8vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL1AzX0w3LmNzdiIsCiAgb3V0cHV0X3R4dCA9ICIvaG9tZS9iaW9pbmZvLzE3LVNpbmdsZUNlbGxGQ3NjYW5uZXIvRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9QM19MNy50eHQiCikKCmBgYAoKIyMgRkMgU0Nhbm5lciBmb3IgREUKYGBge3IgRkNzY2FubmVyX2NlbGxsaW5lczIsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGZvcmVhY2gpCmxpYnJhcnkoZG9QYXJhbGxlbCkKCnNldHdkKCIvaG9tZS9iaW9pbmZvLzE3LVNpbmdsZUNlbGxGQ3NjYW5uZXIvIikKCnNvdXJjZSgic2NGQ3NjYW5uZXJfMDI4X2luX2xpc3QuciIpCgoKYGBgCgoKCiMjIFRvIGV4dHJhY3QgY2VsbCBsaW5lIGFjY29yZGluZyB0byBjbHVzdGVycwpgYGB7ciBjZWxsX2xpbmUyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKSAgIyAncmVhZHInIHBhY2thZ2UgaXMgcmVjb21tZW5kZWQgZm9yIHJlYWRpbmcgLmNzdiBhbmQgLnRzdiBmaWxlcyBlZmZpY2llbnRseQoKIyBSZWFkIHRoZSBUU1YgZmlsZSBpbnRvIFIKRXhwX0FsbHNhbXBsZSA8LSByZWFkX3RzdigiRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9jZWxsX2xpbmVzL2NlbGxfbGluZXNfdnNfY29udHJvbC9QMl9MNF92c19QQk1DX0NENFRfY2VsbHMuY3N2IikKCiMgQ2hlY2sgaWYgdGhlIGZpcnN0IGNvbHVtbiBuYW1lIGlzIG1pc3NpbmcsIGFuZCBpZiBzbywgc2V0IGl0IHRvICJnZW5lIgppZiAoY29sbmFtZXMoRXhwX0FsbHNhbXBsZSlbMV0gPT0gIi4uLjEiKSB7CiAgY29sbmFtZXMoRXhwX0FsbHNhbXBsZSlbMV0gPC0gImdlbmUiCn0KCiMgQ2FsY3VsYXRlIGxvZzIgZm9sZC1jaGFuZ2UgZGlyZWN0bHkgd2l0aGluIHRoZSBwaXBlICh1c2luZyBtdXRhdGUpCkV4cF9BbGxzYW1wbGUgPC0gRXhwX0FsbHNhbXBsZSAlPiUKICBtdXRhdGUobG9nMkZDID0gbG9nMihGQ19QMl9MNF9QQk1DX0NENFRfY2VsbHMpKSAgIyBVc2luZyBtdXRhdGUgdG8gYWRkIGxvZzJGQyBhcyBhIG5ldyBjb2x1bW4KCiMgQ2hlY2sgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBhbmQgZGlzdHJpYnV0aW9uIG9mIGxvZzJGQyBiZWZvcmUgZmlsdGVyaW5nCnN1bW1hcnkoRXhwX0FsbHNhbXBsZSRsb2cyRkMpCmhpc3QoRXhwX0FsbHNhbXBsZSRsb2cyRkMsIG1haW49IkRpc3RyaWJ1dGlvbiBvZiBsb2cyRkMiLCB4bGFiPSJsb2cyRkMiLCBjb2w9ImxpZ2h0Ymx1ZSIsIGJvcmRlcj0iYmxhY2siKQoKIyBDaG9vc2UgeW91ciBvd24gbG9nMkZDIHRocmVzaG9sZCBmb3IgYm90aCBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzCnRocmVzaG9sZF9wb3NpdGl2ZSA8LSAzLjUgICMgU2V0IHlvdXIgY2hvc2VuIHRocmVzaG9sZCBmb3IgcG9zaXRpdmUgbG9nMkZDCnRocmVzaG9sZF9uZWdhdGl2ZSA8LSAtMSAgIyBTZXQgeW91ciBjaG9zZW4gdGhyZXNob2xkIGZvciBuZWdhdGl2ZSBsb2cyRkMKCiMgRmlsdGVyIHJvd3MgYmFzZWQgb24gbG9nMkZDIGNyaXRlcmlhIChzZXBhcmF0ZSB0aHJlc2hvbGRzIGZvciBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgbG9nMkZDKQpmaWx0ZXJlZF9kYXRhIDwtIEV4cF9BbGxzYW1wbGUgJT4lCiAgZmlsdGVyKGxvZzJGQyA+IHRocmVzaG9sZF9wb3NpdGl2ZSB8IGxvZzJGQyA8IHRocmVzaG9sZF9uZWdhdGl2ZSkgICMgRmlsdGVyIGJhc2VkIG9uIGJvdGggY29uZGl0aW9ucwoKCmZpbHRlcmVkX2RhdGFfZmluYWwgPC0gZmlsdGVyZWRfZGF0YSAlPiUKICBmaWx0ZXIoIShtZWFuX1AyX0w0IDwgMC4yICYgbWVhbl9QQk1DX0NENFRfY2VsbHMgPCAwLjIpKSAgCgojIFdyaXRlIHRoZSBmaWx0ZXJlZCBkYXRhIHRvIGEgQ1NWIGZpbGUKd3JpdGUuY3N2KGZpbHRlcmVkX2RhdGFfZmluYWwsICJFeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL2NlbGxfbGluZXMvY2VsbF9saW5lc192c19jb250cm9sL2ZpbHRlcmVkX1AyX0w0X3ZzX1BCTUNfQ0Q0VF9jZWxscy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCgoKYGBgCgoKIyMgVG8gZXh0cmFjdCBDbHVzdGVycyB0byBjb21wYXJlIHRvIGNvbnRyb2wKYGBge3IgY2VsbF9saW5lMywgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKSAgIyAncmVhZHInIHBhY2thZ2UgaXMgcmVjb21tZW5kZWQgZm9yIHJlYWRpbmcgLmNzdiBhbmQgLnRzdiBmaWxlcyBlZmZpY2llbnRseQoKIyBMb2FkIHlvdXIgQ1NWIGZpbGUKZGF0YSA8LSByZWFkLmNzdigiLi4vMTctU2luZ2xlQ2VsbEZDc2Nhbm5lci9FeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL01ldGFkYXRhX0FsbF9jZWxsX2xpbmVzLmNzdiIpCgoKIyAjIERlZmluZSB0aGUgY2x1c3RlcnMgb2YgaW50ZXJlc3QKIyBjbHVzdGVyc19vZl9pbnRlcmVzdCA8LSBjKDMsIDgsIDEwLCAxOCwgMSwgMiwgMTMsIDQsIDcsIDksIDYsIDE2LCAxOSkKCiMgRGVmaW5lIHRoZSBjbHVzdGVycyBvZiBpbnRlcmVzdApjbHVzdGVyc19vZl9pbnRlcmVzdCA8LSBjKDE5KQoKIyBGaWx0ZXIgY2VsbHMgYmFzZWQgb24gdGhlIHNwZWNpZmllZCBjbHVzdGVycwpmaWx0ZXJlZF9kYXRhIDwtIGRhdGEgJT4lCiAgZmlsdGVyKEhhcm1vbnlfc25uX3Jlcy4wLjkgJWluJSBjbHVzdGVyc19vZl9pbnRlcmVzdCkKCiMgV3JpdGUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBuZXcgQ1NWIGZpbGUKd3JpdGUuY3N2KGZpbHRlcmVkX2RhdGEsICIuLi8xNy1TaW5nbGVDZWxsRkNzY2FubmVyL0V4dHJhL05ld0ZpbGVzL0NsdXN0ZXJzL2ZpbHRlcmVkX2NsdXN0ZXIxOS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgU2F2ZSB0aGUgZmlyc3QgY29sdW1uIChQQk1DIGNlbGxzKSB3aXRob3V0IHRoZSBoZWFkZXIgdG8gYSB0eHQgZmlsZQp3cml0ZS50YWJsZShmaWx0ZXJlZF9kYXRhWywgMV0sICJFeHRyYS9OZXdGaWxlcy9DbHVzdGVycy9DbHVzdGVyMTlfY2VsbHMudHh0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKYGBgCgoKCiMjIFRvIGV4dHJhY3QgY2VsbCBsaW5lIGFjY29yZGluZyB0byBjbHVzdGVycwpgYGB7ciBjZWxsX2xpbmU0LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKSAgIyAncmVhZHInIHBhY2thZ2UgaXMgcmVjb21tZW5kZWQgZm9yIHJlYWRpbmcgLmNzdiBhbmQgLnRzdiBmaWxlcyBlZmZpY2llbnRseQoKIyBSZWFkIHRoZSBUU1YgZmlsZSBpbnRvIFIKRXhwX0FsbHNhbXBsZSA8LSByZWFkX3RzdigiRXh0cmEvTmV3RmlsZXMvQ2x1c3RlcnMvQ2x1c3RlcnNfdnNfY29udHJvbC9DMTlfY2VsbHNfdnNfUEJNQ19DRDRUX2NlbGxzLmNzdiIpCgojIENoZWNrIGlmIHRoZSBmaXJzdCBjb2x1bW4gbmFtZSBpcyBtaXNzaW5nLCBhbmQgaWYgc28sIHNldCBpdCB0byAiZ2VuZSIKaWYgKGNvbG5hbWVzKEV4cF9BbGxzYW1wbGUpWzFdID09ICIuLi4xIikgewogIGNvbG5hbWVzKEV4cF9BbGxzYW1wbGUpWzFdIDwtICJnZW5lIgp9CgojIENhbGN1bGF0ZSBsb2cyIGZvbGQtY2hhbmdlIGRpcmVjdGx5IHdpdGhpbiB0aGUgcGlwZSAodXNpbmcgbXV0YXRlKQpFeHBfQWxsc2FtcGxlIDwtIEV4cF9BbGxzYW1wbGUgJT4lCiAgbXV0YXRlKGxvZzJGQyA9IGxvZzIoRkNfQ2x1c3RlcjE5X2NlbGxzX1BCTUNfQ0Q0VF9jZWxscykpICAjIFVzaW5nIG11dGF0ZSB0byBhZGQgbG9nMkZDIGFzIGEgbmV3IGNvbHVtbgoKIyBDaGVjayB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzIGFuZCBkaXN0cmlidXRpb24gb2YgbG9nMkZDIGJlZm9yZSBmaWx0ZXJpbmcKc3VtbWFyeShFeHBfQWxsc2FtcGxlJGxvZzJGQykKaGlzdChFeHBfQWxsc2FtcGxlJGxvZzJGQywgbWFpbj0iRGlzdHJpYnV0aW9uIG9mIGxvZzJGQyIsIHhsYWI9ImxvZzJGQyIsIGNvbD0ibGlnaHRibHVlIiwgYm9yZGVyPSJibGFjayIpCgojIENob29zZSB5b3VyIG93biBsb2cyRkMgdGhyZXNob2xkIGZvciBib3RoIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB2YWx1ZXMKdGhyZXNob2xkX3Bvc2l0aXZlIDwtIDQgICMgU2V0IHlvdXIgY2hvc2VuIHRocmVzaG9sZCBmb3IgcG9zaXRpdmUgbG9nMkZDCnRocmVzaG9sZF9uZWdhdGl2ZSA8LSAtMiAgIyBTZXQgeW91ciBjaG9zZW4gdGhyZXNob2xkIGZvciBuZWdhdGl2ZSBsb2cyRkMKCiMgRmlsdGVyIHJvd3MgYmFzZWQgb24gbG9nMkZDIGNyaXRlcmlhIChzZXBhcmF0ZSB0aHJlc2hvbGRzIGZvciBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgbG9nMkZDKQpmaWx0ZXJlZF9kYXRhIDwtIEV4cF9BbGxzYW1wbGUgJT4lCiAgZmlsdGVyKGxvZzJGQyA+IHRocmVzaG9sZF9wb3NpdGl2ZSB8IGxvZzJGQyA8IHRocmVzaG9sZF9uZWdhdGl2ZSkgICMgRmlsdGVyIGJhc2VkIG9uIGJvdGggY29uZGl0aW9ucwoKCmZpbHRlcmVkX2RhdGFfZmluYWwgPC0gZmlsdGVyZWRfZGF0YSAlPiUKICBmaWx0ZXIoIShtZWFuX0NsdXN0ZXIxOV9jZWxscyA8IDAuMiAmIG1lYW5fUEJNQ19DRDRUX2NlbGxzIDwgMC4yKSkgIAoKIyBXcml0ZSB0aGUgZmlsdGVyZWQgZGF0YSB0byBhIENTViBmaWxlCndyaXRlLmNzdihmaWx0ZXJlZF9kYXRhX2ZpbmFsLCAiRXh0cmEvTmV3RmlsZXMvQ2x1c3RlcnMvQ2x1c3RlcnNfdnNfY29udHJvbC8yLWZpbHRlcmVkX0MxOV92c19QQk1DX0NENFRfY2VsbHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgoKCmBgYAoKCiMjIEJhcnBsb3QgZm9yIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCBnZW5lcwpgYGB7ciBjcmVhdGVUWHQtZmlsZXMsIGV2YWwgPSBGQUxTRX0KCiMgRGVmaW5lIGZpbGUgcGF0aHMKaW5wdXRfZmlsZSA8LSAiRXh0cmEvTmV3RmlsZXMvQ2x1c3RlcnMvQ2x1c3RlcnNfdnNfY29udHJvbC8yLWZpbHRlcmVkX0MxOV92c19QQk1DX0NENFRfY2VsbHMuY3N2IgpvdXRwdXRfZm9sZGVyIDwtICJFeHRyYS9OZXdGaWxlcy9DbHVzdGVycy9DbHVzdGVyc192c19jb250cm9sL0VucmljaG1lbnRfZmlsZXMvIgoKIyBFbnN1cmUgb3V0cHV0IGZvbGRlciBleGlzdHMKaWYgKCFkaXIuZXhpc3RzKG91dHB1dF9mb2xkZXIpKSB7CiAgZGlyLmNyZWF0ZShvdXRwdXRfZm9sZGVyLCByZWN1cnNpdmUgPSBUUlVFKQp9CgojIExvYWQgdGhlIGRhdGEgKGhhbmRsaW5nIGVycm9ycyBncmFjZWZ1bGx5KQpkYXRhIDwtIHRyeUNhdGNoKHsKICByZWFkX2NzdihpbnB1dF9maWxlKQp9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIHsKICBzdG9wKCJFcnJvciByZWFkaW5nIGlucHV0IGZpbGUuIENoZWNrIHRoZSBmaWxlIHBhdGggb3IgZm9ybWF0LiIpCn0pCgojIENoZWNrIGlmIHRoZSBuZWNlc3NhcnkgY29sdW1ucyBleGlzdAppZiAoIWFsbChjKCJsb2cyRkMiLCAiZ2VuZSIpICVpbiUgY29sbmFtZXMoZGF0YSkpKSB7CiAgc3RvcCgiUmVxdWlyZWQgY29sdW1ucyAoJ2xvZzJGQycgYW5kICdnZW5lJykgYXJlIG1pc3NpbmcgaW4gdGhlIGRhdGEuIikKfQoKIyBGaWx0ZXIgZm9yIHVwcmVndWxhdGVkIGFuZCBkb3ducmVndWxhdGVkIGdlbmVzCnVwcmVndWxhdGVkX2dlbmVzIDwtIGRhdGEgJT4lIGZpbHRlcihsb2cyRkMgPiAwKQpkb3ducmVndWxhdGVkX2dlbmVzIDwtIGRhdGEgJT4lIGZpbHRlcihsb2cyRkMgPCAwKQoKIyBFeHRyYWN0IG9ubHkgZ2VuZSBuYW1lcyBhcyB2ZWN0b3JzCnVwcmVndWxhdGVkX2dlbmVfbmFtZXMgPC0gdXByZWd1bGF0ZWRfZ2VuZXMgJT4lIHB1bGwoZ2VuZSkKZG93bnJlZ3VsYXRlZF9nZW5lX25hbWVzIDwtIGRvd25yZWd1bGF0ZWRfZ2VuZXMgJT4lIHB1bGwoZ2VuZSkKCiMgRGVmaW5lIG91dHB1dCBmaWxlIHBhdGhzCnVwcmVndWxhdGVkX2ZpbGUgPC0gZmlsZS5wYXRoKG91dHB1dF9mb2xkZXIsICJ1cHJlZ3VsYXRlZF9nZW5lX25hbWVzLnR4dCIpCmRvd25yZWd1bGF0ZWRfZmlsZSA8LSBmaWxlLnBhdGgob3V0cHV0X2ZvbGRlciwgImRvd25yZWd1bGF0ZWRfZ2VuZV9uYW1lcy50eHQiKQoKIyBTYXZlIHRoZSBnZW5lIG5hbWVzIHRvIHRleHQgZmlsZXMKd3JpdGVfbGluZXModXByZWd1bGF0ZWRfZ2VuZV9uYW1lcywgdXByZWd1bGF0ZWRfZmlsZSkKd3JpdGVfbGluZXMoZG93bnJlZ3VsYXRlZF9nZW5lX25hbWVzLCBkb3ducmVndWxhdGVkX2ZpbGUpCgojIFByaW50IHRoZSBudW1iZXIgb2YgdXByZWd1bGF0ZWQgYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMKY2F0KCJOdW1iZXIgb2YgdXByZWd1bGF0ZWQgZ2VuZXM6IiwgbGVuZ3RoKHVwcmVndWxhdGVkX2dlbmVfbmFtZXMpLCAiXG4iKQpjYXQoIk51bWJlciBvZiBkb3ducmVndWxhdGVkIGdlbmVzOiIsIGxlbmd0aChkb3ducmVndWxhdGVkX2dlbmVfbmFtZXMpLCAiXG4iKQpjYXQoIkdlbmUgbmFtZXMgc2F2ZWQgdG86XG4iKQpjYXQoIiAgVXByZWd1bGF0ZWQgZ2VuZXM6ICIsIHVwcmVndWxhdGVkX2ZpbGUsICJcbiIpCmNhdCgiICBEb3ducmVndWxhdGVkIGdlbmVzOiAiLCBkb3ducmVndWxhdGVkX2ZpbGUsICJcbiIpCgoKCmBgYAoKIyMgY3JlYXRlIFBCTUMgQ0Q0IFQgY2VsbHMgZmlsZSAKYGBge3IgZmlsdGVyLCAgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZHBseXIpCgojIExvYWQgeW91ciBDU1YgZmlsZQpkYXRhIDwtIHJlYWQuY3N2KCJFeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL2ZpbHRlcmVkX2NlbGxzX29mX2NlbGxfbGluZXNfYnlfY2x1c3Rlci5jc3YiKQoKIyBGaWx0ZXIgcm93cyB3aGVyZSBhbGwgdGhyZWUgcHJlZGljdGVkIGNvbHVtbnMgY29udGFpbiAiQ0Q0IFQiCmZpbHRlcmVkX2RhdGEgPC0gZGF0YSAlPiUKICBmaWx0ZXIoZ3JlcGwoIkIgbWVtb3J5IiwgcHJlZGljdGVkLmNlbGx0eXBlLmwyKSAmCiAgICAgICAgIGdyZXBsKCJCIG1lbW9yeSBsYW1iZGEiLCBwcmVkaWN0ZWQuY2VsbHR5cGUubDMpKQoKIyBXcml0ZSB0aGUgZmlsdGVyZWQgZGF0YSB0byBhIG5ldyBDU1YgZmlsZSwgaW5jbHVkaW5nIHRoZSBoZWFkZXIKd3JpdGUuY3N2KGZpbHRlcmVkX2RhdGEsICJFeHRyYS9OZXdGaWxlcy9CX21lbW9yeV9pbl9jZWxsbGluZV9jbHVzdGVycy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgU2F2ZSB0aGUgZmlyc3QgY29sdW1uIChQQk1DIGNlbGxzKSB0byBhIHR4dCBmaWxlIHdpdGhvdXQgaGVhZGVyCndyaXRlLnRhYmxlKGZpbHRlcmVkX2RhdGFbLCAxXSwgIkV4dHJhL05ld0ZpbGVzL0JfbWVtb3J5X2NlbGxzX2luX2NlbGxsaW5lX2NsdXN0ZXJzLnR4dCIsIHJvdy5uYW1lcyA9IEZBTFNFLCBjb2wubmFtZXMgPSBGQUxTRSwgcXVvdGUgPSBGQUxTRSkKCiMgIyBMb2FkIHlvdXIgQ1NWIGZpbGUKIyBkYXRhIDwtIHJlYWQuY3N2KCJFeHRyYS9OZXdGaWxlcy9DZWxsX2xpbmVzL01ldGFkYXRhX0FsbF9jZWxsX2xpbmVzLmNzdiIpCiMgCiMgCiMgIyBEZWZpbmUgdGhlIGNsdXN0ZXJzIG9mIGludGVyZXN0CiMgY2x1c3RlcnNfb2ZfaW50ZXJlc3QgPC0gYygzLCA4LCAxMCwgMTgsIDEsIDIsIDEzLCA0LCA3LCA5LCA2LCAxNiwgMTkpCiMgCiMgIyBGaWx0ZXIgY2VsbHMgYmFzZWQgb24gdGhlIHNwZWNpZmllZCBjbHVzdGVycwojIGZpbHRlcmVkX2RhdGEgPC0gZGF0YSAlPiUKIyAgIGZpbHRlcihIYXJtb255X3Nubl9yZXMuMC45ICVpbiUgY2x1c3RlcnNfb2ZfaW50ZXJlc3QpCiMgCiMgIyBXcml0ZSB0aGUgZmlsdGVyZWQgZGF0YSB0byBhIG5ldyBDU1YgZmlsZQojIHdyaXRlLmNzdihmaWx0ZXJlZF9kYXRhLCAiRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9maWx0ZXJlZF9jZWxsc19vZl9jZWxsX2xpbmVzX2J5X2NsdXN0ZXIuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgCiMgIyBTYXZlIHRoZSBmaXJzdCBjb2x1bW4gKFBCTUMgY2VsbHMpIHdpdGhvdXQgdGhlIGhlYWRlciB0byBhIHR4dCBmaWxlCiMgd3JpdGUudGFibGUoZmlsdGVyZWRfZGF0YVssIDFdLCAiRXh0cmEvTmV3RmlsZXMvQ2VsbF9saW5lcy9BbGxfY2VsbF9saW5lc19jZWxscy50eHQiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCiMgCgoKIyAjIExvYWQgeW91ciBDU1YgZmlsZQojIGRhdGEgPC0gcmVhZC5jc3YoIkV4dHJhL05ld0ZpbGVzL0NlbGxfbGluZXMvTWV0YWRhdGFfQWxsX2NlbGxfbGluZXMuY3N2IikKIyAKIyAjIFRvIHNhdmUgUDEgKEwxK0wyKQojICMgRGVmaW5lIHRoZSBjbHVzdGVycyBvZiBpbnRlcmVzdAojIGNsdXN0ZXJzX29mX2ludGVyZXN0IDwtIGMoMywgOCwgMTAsIDE4KQojIAojICMgRmlsdGVyIGNlbGxzIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgY2x1c3RlcnMKIyBmaWx0ZXJlZF9kYXRhIDwtIGRhdGEgJT4lCiMgICBmaWx0ZXIoSGFybW9ueV9zbm5fcmVzLjAuOSAlaW4lIGNsdXN0ZXJzX29mX2ludGVyZXN0KQojIAojICMgV3JpdGUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBuZXcgQ1NWIGZpbGUKIyB3cml0ZS5jc3YoZmlsdGVyZWRfZGF0YSwgIkV4dHJhL05ld0ZpbGVzL1BhdGllbnRzX2Jhc2VkX29uX2NlbGxsaW5lcyhDbHVzdGVycykvUDEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgCiMgIyBTYXZlIHRoZSBmaXJzdCBjb2x1bW4gKFBCTUMgY2VsbHMpIHdpdGhvdXQgdGhlIGhlYWRlciB0byBhIHR4dCBmaWxlCiMgd3JpdGUudGFibGUoZmlsdGVyZWRfZGF0YVssIDFdLCAiRXh0cmEvTmV3RmlsZXMvUGF0aWVudHNfYmFzZWRfb25fY2VsbGxpbmVzKENsdXN0ZXJzKS9QMS50eHQiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCiMgCiMgCiMgIyBUbyBzYXZlIFAxIChMMytMNCkKIyAjIERlZmluZSB0aGUgY2x1c3RlcnMgb2YgaW50ZXJlc3QKIyBjbHVzdGVyc19vZl9pbnRlcmVzdCA8LSBjKDEsIDIsIDEzKQojIAojICMgRmlsdGVyIGNlbGxzIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgY2x1c3RlcnMKIyBmaWx0ZXJlZF9kYXRhIDwtIGRhdGEgJT4lCiMgICBmaWx0ZXIoSGFybW9ueV9zbm5fcmVzLjAuOSAlaW4lIGNsdXN0ZXJzX29mX2ludGVyZXN0KQojIAojICMgV3JpdGUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBuZXcgQ1NWIGZpbGUKIyB3cml0ZS5jc3YoZmlsdGVyZWRfZGF0YSwgIkV4dHJhL05ld0ZpbGVzL1BhdGllbnRzX2Jhc2VkX29uX2NlbGxsaW5lcyhDbHVzdGVycykvUDIuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgCiMgIyBTYXZlIHRoZSBmaXJzdCBjb2x1bW4gKFBCTUMgY2VsbHMpIHdpdGhvdXQgdGhlIGhlYWRlciB0byBhIHR4dCBmaWxlCiMgd3JpdGUudGFibGUoZmlsdGVyZWRfZGF0YVssIDFdLCAiRXh0cmEvTmV3RmlsZXMvUGF0aWVudHNfYmFzZWRfb25fY2VsbGxpbmVzKENsdXN0ZXJzKS9QMi50eHQiLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpCiMgCiMgCiMgCiMgIyBUbyBzYXZlIFAxIChMNStMNitMNykKIyAjIERlZmluZSB0aGUgY2x1c3RlcnMgb2YgaW50ZXJlc3QKIyBjbHVzdGVyc19vZl9pbnRlcmVzdCA8LSBjKDQsIDcsIDksIDYsIDE2LCAxOSkKIyAKIyAjIEZpbHRlciBjZWxscyBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIGNsdXN0ZXJzCiMgZmlsdGVyZWRfZGF0YSA8LSBkYXRhICU+JQojICAgZmlsdGVyKEhhcm1vbnlfc25uX3Jlcy4wLjkgJWluJSBjbHVzdGVyc19vZl9pbnRlcmVzdCkKIyAKIyAjIFdyaXRlIHRoZSBmaWx0ZXJlZCBkYXRhIHRvIGEgbmV3IENTViBmaWxlCiMgd3JpdGUuY3N2KGZpbHRlcmVkX2RhdGEsICJFeHRyYS9OZXdGaWxlcy9QYXRpZW50c19iYXNlZF9vbl9jZWxsbGluZXMoQ2x1c3RlcnMpL1AzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQojIAojICMgU2F2ZSB0aGUgZmlyc3QgY29sdW1uIChQQk1DIGNlbGxzKSB3aXRob3V0IHRoZSBoZWFkZXIgdG8gYSB0eHQgZmlsZQojIHdyaXRlLnRhYmxlKGZpbHRlcmVkX2RhdGFbLCAxXSwgIkV4dHJhL05ld0ZpbGVzL1BhdGllbnRzX2Jhc2VkX29uX2NlbGxsaW5lcyhDbHVzdGVycykvUDMudHh0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQoKYGBgCgojIyBGQyBTQ2FubmVyIGZvciBERQpgYGB7ciBGQ3NjYW5uZXJfY2VsbHMsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGZvcmVhY2gpCmxpYnJhcnkoZG9QYXJhbGxlbCkKCnNldHdkKCIvaG9tZS9iaW9pbmZvLzE3LVNpbmdsZUNlbGxGQ3NjYW5uZXIvIikKCnNvdXJjZSgic2NGQ3NjYW5uZXJfMDI4X2luX2xpc3QuciIpCgoKYGBgCgoKCiMjIFRvIGV4dHJhY3QgY2VsbCBsaW5lIGFjY29yZGluZyB0byBjbHVzdGVycwpgYGB7ciBjZWxsX2xpbmU1LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKSAgIyAncmVhZHInIHBhY2thZ2UgaXMgcmVjb21tZW5kZWQgZm9yIHJlYWRpbmcgLmNzdiBhbmQgLnRzdiBmaWxlcyBlZmZpY2llbnRseQoKIyBSZWFkIHRoZSBUU1YgZmlsZSBpbnRvIFIKRXhwX0FsbHNhbXBsZSA8LSByZWFkX3RzdigiRXh0cmEvTmV3RmlsZXMvT3RoZXJfY2VsbHNfaW5fY2VsbGxpbmVzLzItRkNfc2Nhbm5lcl9SZXN1bHRzL1NDVF9kYXRhX0FsbF9zYW1wbGVzX01lcmdlZF90cmFuc3Bvc2VkX3RhYl9CX21lbW9yeV9jZWxsc19pbl9jZWxsbGluZV9jbHVzdGVyc192c19QQk1DX0NENFRfY2VsbHMuY3N2IikKCiMgQ2hlY2sgaWYgdGhlIGZpcnN0IGNvbHVtbiBuYW1lIGlzIG1pc3NpbmcsIGFuZCBpZiBzbywgc2V0IGl0IHRvICJnZW5lIgppZiAoY29sbmFtZXMoRXhwX0FsbHNhbXBsZSlbMV0gPT0gIi4uLjEiKSB7CiAgY29sbmFtZXMoRXhwX0FsbHNhbXBsZSlbMV0gPC0gImdlbmUiCn0KCiMgQ2FsY3VsYXRlIGxvZzIgZm9sZC1jaGFuZ2UgZGlyZWN0bHkgd2l0aGluIHRoZSBwaXBlICh1c2luZyBtdXRhdGUpCkV4cF9BbGxzYW1wbGUgPC0gRXhwX0FsbHNhbXBsZSAlPiUKICBtdXRhdGUobG9nMkZDID0gbG9nMihGQ19CX21lbW9yeV9jZWxsc19pbl9jZWxsbGluZV9jbHVzdGVyc19QQk1DX0NENFRfY2VsbHMpKSAgIyBVc2luZyBtdXRhdGUgdG8gYWRkIGxvZzJGQyBhcyBhIG5ldyBjb2x1bW4KCiMgQ2hlY2sgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBhbmQgZGlzdHJpYnV0aW9uIG9mIGxvZzJGQyBiZWZvcmUgZmlsdGVyaW5nCnN1bW1hcnkoRXhwX0FsbHNhbXBsZSRsb2cyRkMpCmhpc3QoRXhwX0FsbHNhbXBsZSRsb2cyRkMsIG1haW49IkRpc3RyaWJ1dGlvbiBvZiBsb2cyRkMiLCB4bGFiPSJsb2cyRkMiLCBjb2w9ImxpZ2h0Ymx1ZSIsIGJvcmRlcj0iYmxhY2siKQoKIyBDaG9vc2UgeW91ciBvd24gbG9nMkZDIHRocmVzaG9sZCBmb3IgYm90aCBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzCnRocmVzaG9sZF9wb3NpdGl2ZSA8LSAyLjUgICMgU2V0IHlvdXIgY2hvc2VuIHRocmVzaG9sZCBmb3IgcG9zaXRpdmUgbG9nMkZDCnRocmVzaG9sZF9uZWdhdGl2ZSA8LSAtMS41ICAjIFNldCB5b3VyIGNob3NlbiB0aHJlc2hvbGQgZm9yIG5lZ2F0aXZlIGxvZzJGQwoKIyBGaWx0ZXIgcm93cyBiYXNlZCBvbiBsb2cyRkMgY3JpdGVyaWEgKHNlcGFyYXRlIHRocmVzaG9sZHMgZm9yIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBsb2cyRkMpCmZpbHRlcmVkX2RhdGEgPC0gRXhwX0FsbHNhbXBsZSAlPiUKICBmaWx0ZXIobG9nMkZDID4gdGhyZXNob2xkX3Bvc2l0aXZlIHwgbG9nMkZDIDwgdGhyZXNob2xkX25lZ2F0aXZlKSAgIyBGaWx0ZXIgYmFzZWQgb24gYm90aCBjb25kaXRpb25zCgoKZmlsdGVyZWRfZGF0YV9maW5hbCA8LSBmaWx0ZXJlZF9kYXRhICU+JQogIGZpbHRlcighKG1lYW5fQl9tZW1vcnlfY2VsbHNfaW5fY2VsbGxpbmVfY2x1c3RlcnMgPCAwLjIgJiBtZWFuX1BCTUNfQ0Q0VF9jZWxscyA8IDAuMikpICAKCiMgV3JpdGUgdGhlIGZpbHRlcmVkIGRhdGEgdG8gYSBDU1YgZmlsZQp3cml0ZS5jc3YoZmlsdGVyZWRfZGF0YV9maW5hbCwgIkV4dHJhL05ld0ZpbGVzL090aGVyX2NlbGxzX2luX2NlbGxsaW5lcy8zLWZpbGVzX2Zvcl9FbnJpY2htZW50LzItZmlsdGVyZWRfQl9tZW1vcnlfY2VsbHNfaW5fY2VsbGxpbmVfY2x1c3RlcnNfdnNfUEJNQ19DRDRUX2NlbGxzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKCgpgYGAKCgojIyBCYXJwbG90IGZvciB1cCBhbmQgZG93biByZWd1bGF0ZWQgZ2VuZXMKYGBge3IgY3JlYXRlVFh0LWZpbGVzMiwgZXZhbCA9IEZBTFNFfQoKIyBEZWZpbmUgZmlsZSBwYXRocwppbnB1dF9maWxlIDwtICJFeHRyYS9OZXdGaWxlcy9PdGhlcl9jZWxsc19pbl9jZWxsbGluZXMvMy1maWxlc19mb3JfRW5yaWNobWVudC8yLWZpbHRlcmVkX05LX1Byb2xpZmVyYXRpbmdfY2VsbHNfaW5fY2VsbGxpbmVfY2x1c3RlcnNfdnNfUEJNQ19DRDRUX2NlbGxzLmNzdiIKb3V0cHV0X2ZvbGRlciA8LSAiRXh0cmEvTmV3RmlsZXMvT3RoZXJfY2VsbHNfaW5fY2VsbGxpbmVzLzMtZmlsZXNfZm9yX0VucmljaG1lbnQvRW5yaWNobWVudF9maWxlcy8iCgojIEVuc3VyZSBvdXRwdXQgZm9sZGVyIGV4aXN0cwppZiAoIWRpci5leGlzdHMob3V0cHV0X2ZvbGRlcikpIHsKICBkaXIuY3JlYXRlKG91dHB1dF9mb2xkZXIsIHJlY3Vyc2l2ZSA9IFRSVUUpCn0KCiMgTG9hZCB0aGUgZGF0YSAoaGFuZGxpbmcgZXJyb3JzIGdyYWNlZnVsbHkpCmRhdGEgPC0gdHJ5Q2F0Y2goewogIHJlYWRfY3N2KGlucHV0X2ZpbGUpCn0sIGVycm9yID0gZnVuY3Rpb24oZSkgewogIHN0b3AoIkVycm9yIHJlYWRpbmcgaW5wdXQgZmlsZS4gQ2hlY2sgdGhlIGZpbGUgcGF0aCBvciBmb3JtYXQuIikKfSkKCiMgQ2hlY2sgaWYgdGhlIG5lY2Vzc2FyeSBjb2x1bW5zIGV4aXN0CmlmICghYWxsKGMoImxvZzJGQyIsICJnZW5lIikgJWluJSBjb2xuYW1lcyhkYXRhKSkpIHsKICBzdG9wKCJSZXF1aXJlZCBjb2x1bW5zICgnbG9nMkZDJyBhbmQgJ2dlbmUnKSBhcmUgbWlzc2luZyBpbiB0aGUgZGF0YS4iKQp9CgojIEZpbHRlciBmb3IgdXByZWd1bGF0ZWQgYW5kIGRvd25yZWd1bGF0ZWQgZ2VuZXMKdXByZWd1bGF0ZWRfZ2VuZXMgPC0gZGF0YSAlPiUgZmlsdGVyKGxvZzJGQyA+IDApCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gZGF0YSAlPiUgZmlsdGVyKGxvZzJGQyA8IDApCgojIEV4dHJhY3Qgb25seSBnZW5lIG5hbWVzIGFzIHZlY3RvcnMKdXByZWd1bGF0ZWRfZ2VuZV9uYW1lcyA8LSB1cHJlZ3VsYXRlZF9nZW5lcyAlPiUgcHVsbChnZW5lKQpkb3ducmVndWxhdGVkX2dlbmVfbmFtZXMgPC0gZG93bnJlZ3VsYXRlZF9nZW5lcyAlPiUgcHVsbChnZW5lKQoKIyBEZWZpbmUgb3V0cHV0IGZpbGUgcGF0aHMKdXByZWd1bGF0ZWRfZmlsZSA8LSBmaWxlLnBhdGgob3V0cHV0X2ZvbGRlciwgInVwcmVndWxhdGVkX2dlbmVfbmFtZXMudHh0IikKZG93bnJlZ3VsYXRlZF9maWxlIDwtIGZpbGUucGF0aChvdXRwdXRfZm9sZGVyLCAiZG93bnJlZ3VsYXRlZF9nZW5lX25hbWVzLnR4dCIpCgojIFNhdmUgdGhlIGdlbmUgbmFtZXMgdG8gdGV4dCBmaWxlcwp3cml0ZV9saW5lcyh1cHJlZ3VsYXRlZF9nZW5lX25hbWVzLCB1cHJlZ3VsYXRlZF9maWxlKQp3cml0ZV9saW5lcyhkb3ducmVndWxhdGVkX2dlbmVfbmFtZXMsIGRvd25yZWd1bGF0ZWRfZmlsZSkKCiMgUHJpbnQgdGhlIG51bWJlciBvZiB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcwpjYXQoIk51bWJlciBvZiB1cHJlZ3VsYXRlZCBnZW5lczoiLCBsZW5ndGgodXByZWd1bGF0ZWRfZ2VuZV9uYW1lcyksICJcbiIpCmNhdCgiTnVtYmVyIG9mIGRvd25yZWd1bGF0ZWQgZ2VuZXM6IiwgbGVuZ3RoKGRvd25yZWd1bGF0ZWRfZ2VuZV9uYW1lcyksICJcbiIpCmNhdCgiR2VuZSBuYW1lcyBzYXZlZCB0bzpcbiIpCmNhdCgiICBVcHJlZ3VsYXRlZCBnZW5lczogIiwgdXByZWd1bGF0ZWRfZmlsZSwgIlxuIikKY2F0KCIgIERvd25yZWd1bGF0ZWQgZ2VuZXM6ICIsIGRvd25yZWd1bGF0ZWRfZmlsZSwgIlxuIikKCgoKYGBgCgojIyBUbyBleHRyYWN0IGNlbGwgbGluZSBhY2NvcmRpbmcgdG8gY2x1c3RlcnMKYGBge3IgY2VsbF9saW5lNiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkcikgICMgJ3JlYWRyJyBwYWNrYWdlIGlzIHJlY29tbWVuZGVkIGZvciByZWFkaW5nIC5jc3YgYW5kIC50c3YgZmlsZXMgZWZmaWNpZW50bHkKCiMgUmVhZCB0aGUgVFNWIGZpbGUgaW50byBSCkV4cF9BbGxzYW1wbGUgPC0gcmVhZF90c3YoIkV4dHJhL05ld0ZpbGVzL1Jlc3VsdHMvQ2VsbF9saW5lc192c19DRDRUY2VsbHMvU0NUX0FsbF9jZWxsX2xpbmVzX2NlbGxzX3ZzX1BCTUNfQ0Q0VF9jZWxscy50c3YiKQoKIyBDaGVjayBpZiB0aGUgZmlyc3QgY29sdW1uIG5hbWUgaXMgbWlzc2luZywgYW5kIGlmIHNvLCBzZXQgaXQgdG8gImdlbmUiCmlmIChjb2xuYW1lcyhFeHBfQWxsc2FtcGxlKVsxXSA9PSAiLi4uMSIpIHsKICBjb2xuYW1lcyhFeHBfQWxsc2FtcGxlKVsxXSA8LSAiZ2VuZSIKfQoKIyBDYWxjdWxhdGUgbG9nMiBmb2xkLWNoYW5nZSBkaXJlY3RseSB3aXRoaW4gdGhlIHBpcGUgKHVzaW5nIG11dGF0ZSkKRXhwX0FsbHNhbXBsZSA8LSBFeHBfQWxsc2FtcGxlICU+JQogIG11dGF0ZShsb2cyRkMgPSBsb2cyKEZDX0FsbF9jZWxsX2xpbmVzX2NlbGxzX1BCTUNfQ0Q0VF9jZWxscykpICAjIFVzaW5nIG11dGF0ZSB0byBhZGQgbG9nMkZDIGFzIGEgbmV3IGNvbHVtbgoKCgojIFNhdmUgdGhlIHVwZGF0ZWQgZGF0YWZyYW1lIHRvIGEgQ1NWIGZpbGUKd3JpdGVfY3N2KEV4cF9BbGxzYW1wbGUsICJFeHRyYS9Wb2xjYW5vX2NlbGxsaW5lc192c19Db250cm9sL1NDVF9BbGxfY2VsbF9saW5lc19jZWxsc192c19QQk1DX0NENFRfY2VsbHNfZm9yX1ZvbGNhbm9QbG90LnRzdiIpCgoKCgoKCmBgYAoK