Abstract

Despite the increasing popularity of DNA metabarcoding in the assessment of aquatic ecosystems using fish eDNA or ichthyoplankton, challenges have hampered its broader application in the Neotropical freshwaters. Using five mock communities composed of fish species from two Neotropical river basins, we evaluated the influence of DNA concentration and choice of mitochondrial 12S molecular markers (MiFish, NeoFish and Teleo) on species detection and Relative Read Abundance (RRA) using DNA metabarcoding. Of the three 12S markers analysed, only MiFish detected all species from all mock communities. The performance of a taxonomy-free approach using ASV/MOTUs was not as precise as assigning DNA reads to species using a curated 12S library that includes approximately 100 fish species, since more than one ASV/MOTU was observed for the same specimen. Thus, here we showcase the importance of a custom reference database to allow precise assignment of Neotropical fish species in metabarcoding studies and that the RRA is dependent on community composition, marker and DNA concentration. We highlight the importance of controlled experiments using known species communities before large investments are made in assessing biodiversity using non-invasive methods that apply DNA metabarcoding.

Bioinformatics

Data acquisiton

Download demultiplexed samples from Base Space using the bs interface.

#navigate to raw-data folder
cd $raw_data_folder/$run_folder;

#authenticate to BaseSpace (only at first log in)
bs auth;

#list datasets from runs on your BaseSpace
bs list datasets;

#create folders to organize fastq files
mkdir ~/runs/run_01mar21/fastq/;        #edna
mkdir ~/runs/run_09fev21/fastq/;        #edna
mkdir ~/runs/run_29jul20/fastq/;        #edna

#download runs from BaseSpace
bs download project -n fish_eDNA -o ~/runs/run_29jul20/fastq/ --extension=fastq.gz;          #primeira corrida LGC
bs download project -n eDNA_2run_B -o ~/runs/run_09fev21/fastq/ --extension=fastq.gz;        #segunda corrida LGC
bs download project -n iSeqRun2_Daniel -o ~/runs/run_01mar21/fastq/ --extension=fastq.gz;    #amostras iSeq ecomol

#organize all fastq files of each run in a single folder
mkdir ~/runs/run_01mar21/fastq/all;
mkdir ~/runs/run_09fev21/fastq/all;
mkdir ~/runs/run_29jul20/fastq/all;

#move all fastqfiles to a single folder
mv ~/runs/run_01mar21/fastq/*/*fastq.gz ~/runs/run_01mar21/fastq/all;
mv ~/runs/run_09fev21/fastq/*/*fastq.gz ~/runs/run_09fev21/fastq/all;
mv ~/runs/run_29jul20/fastq/*/*fastq.gz ~/runs/run_29jul20/fastq/all;


Load R libs and system programs

# 0 - load libraries ----
{
  library(dplyr)
  library(tidyr)
  library(tibble)
  library(stringr)
  library(ggplot2)
  library(ggbreak)
  library(ggtree)
  library(phyloseq)
  library(Biostrings)
  library(Matrix)
  library(ShortRead)
  library(dada2)
  library(DECIPHER)
  library(future)
  library(vegan)
  library(ape)
  library(phangorn)
  library(adegenet)
}

#set complete path to cutadapt executable
cutadapt <- "/usr/local/bin/cutadapt"

#important 
prjct_path <- "~/prjcts/fish_eDNA/sfjq"

notes_path <- paste0(prjct_path,"/notes")

results_path <- paste0(prjct_path,"/results")

figs_path <- paste0(results_path,"/figs")

prcj_radical <- "SFJq_fish_metabarcoding"
#path to project data folder were the processed reads will be stored
data_path <- paste0(prjct_path,"/data/reads")


Quality control

Chech overall quality of sequencing runs for all samples


Demultiplex SFJQ sample (MiFish & NeoFish mixed)

#Demultiplex SFJQ sample (MiFish & NeoFish mixed)
#samples MiniSeq LGC
cutadapt -j 79 --no-indels  -g file:~/prjcts/fish_eDNA/sfjq/data/primers_neo_mi.fasta  -G file:~/prjcts/fish_eDNA/sfjq/data/primers_neo_mi.fasta  -o ~/runs/run_09fev21/fastq/all/sfjq_dmx/SFJQ-{name1}-{name2}_R1_001.fastq.gz  -p ~/runs/run_09fev21/fastq/all/sfjq_dmx/SFJQ-{name1}-{name2}_R2_001.fastq.gz  ~/runs/run_09fev21/fastq/all/SFJQ-neo-mi_S23_L001_R1_001.fastq  ~/runs/run_09fev21/fastq/all/SFJQ-neo-mi_S23_L001_R2_001.fastq 2> ~/runs/run_09fev21/fastq/all/sfjq_dmx/cut_SFJQ_demux.txt

cp ~/runs/run_09fev21/fastq/all/sfjq_dmx/SFJQ-neo_FWD-neo_REV.* ~/runs/run_01mar21/fastq/all/
cp ~/runs/run_09fev21/fastq/all/sfjq_dmx/SFJQ-mif_FWD-mif_REV.* ~/runs/run_09fev21/fastq/all/

mv ~/runs/run_01mar21/fastq/all/SFJQ-neo-mi_S23_L001_R* ~/runs/run_01mar21/fastq/all/sfjq_dmx/


#samples iSeq Ecomol
cutadapt -j 79 --no-indels  -g file:~/prjcts/fish_eDNA/sfjq/data/primers_neo_mi.fasta  -G file:~/prjcts/fish_eDNA/sfjq/data/primers_neo_mi.fasta  -o ~/runs/run_01mar21/fastq/all/sfjq_dmx/Da23-{name1}-{name2}_R1_001.fastq.gz  -p ~/runs/run_01mar21/fastq/all/sfjq_dmx/Da23-{name1}-{name2}_R2_001.fastq.gz  ~/runs/run_01mar21/fastq/all/Da23_S72_L001_R1_001.fastq ~/runs/run_01mar21/fastq/all/Da23_S72_L001_R2_001.fastq 2> ~/runs/run_01mar21/fastq/all/sfjq_dmx/cut_SFJQ_demux.txt

cp ~/runs/run_01mar21/fastq/all/sfjq_dmx/Da23-neo_FWD-neo_REV.* ~/runs/run_01mar21/fastq/all/
cp ~/runs/run_01mar21/fastq/all/sfjq_dmx/Da23-mif_FWD-mif_REV.* ~/runs/run_01mar21/fastq/all/

mv ~/runs/run_01mar21/fastq/all/Da23_S72_L001_R* ~/runs/run_01mar21/fastq/all/sfjq_dmx/

Set path to raw data

#1 - load runs raw data ----
## All libs are demultiplexed
{
  # PATH to the directory containing raw fastq files after unzipping.
  libs_path1 <- "~/runs/run_29jul20/fastq/all"
  libs_path2 <- "~/runs/run_09fev21/fastq/all" 
  libs_path3 <- "~/runs/run_01mar21/fastq/all" 
}
#check content
list.files(path = libs_path1,pattern = "fastq") 
list.files(path = libs_path2,pattern = "fastq") 
list.files(path = libs_path3,pattern = "fastq") 

Identify sample names radicals

#2 - get sample names ----

# Forward and reverse fastq filenames have format: SAMPLENAME_R1_001.fastq and SAMPLENAME_R2_001.fastq
{
  all_fnFs1 <- sort(list.files(libs_path1, pattern="_R1_001.fastq", full.names = TRUE))
  all_fnRs1 <- sort(list.files(libs_path1, pattern="_R2_001.fastq", full.names = TRUE))

  all_fnFs2 <- sort(list.files(libs_path2, pattern="_R1_001.fastq", full.names = TRUE))
  all_fnRs2 <- sort(list.files(libs_path2, pattern="_R2_001.fastq", full.names = TRUE))

  all_fnFs3 <- sort(list.files(libs_path3, pattern="_R1_001.fastq", full.names = TRUE))
  all_fnRs3 <- sort(list.files(libs_path3, pattern="_R2_001.fastq", full.names = TRUE))

  all_fnFs <- c(all_fnFs1,all_fnFs2,all_fnFs3)
  all_fnRs <- c(all_fnRs1,all_fnRs2,all_fnRs3)
}
#load csv with primers and respective samples
primers_n_samples <- read.csv(file = "~/prjcts/fish_eDNA/sfjq/data/primers_n_samples_sfjq.csv",
         header = TRUE)


#3 - map sample names to reads files ----
primers_n_samples <- primers_n_samples %>%
  mutate("R1" = "R1",
         "R2" = "R2")

for (sample in 1:nrow(primers_n_samples)) {
  
  primers_n_samples$R1[sample] <-
   all_fnFs[grep(pattern =  paste0("/",primers_n_samples$File_name[sample]),x = all_fnFs)]
  
  primers_n_samples$R2[sample] <-
   all_fnRs[grep(pattern =  paste0("/",primers_n_samples$File_name[sample]),x = all_fnRs)]

}


Define sample levels

#4 - set sample levels
primers_n_samples$File_name

sample_levels <- c(
"Da23-mif", "SFJQ-mif",
"Da23-neo", "SFJQ-neo",
"Da20","SFnNorm-mi",
"Da19","SFnNorm-neo",
"Da22","SFNorm-mi",
"Da21","SFNorm-neo",
"pJequei-N-norm-N","pJequei-N-norm-M","pJequei-N-norm-T",
"pJequei-norm-N","pJequei-norm-M","pJequei-norm-T",
"Cassaum","neg-PCR2")

primer_levels <- c("NeoFish", "MiFish", "Teleo","NeoFish/MiFish", "NeoFish/MiFish/Teleo")


### Remove primers from reads

As the primer-derived sequences are identical, they are not informative and thus must be removed for the following steps.


Load primer sequences

#4- identify primers ----

#primers sequences used for each sample
# inosine pairs with A, C, U
#                    T, G, A = IUPAC code:  D
#cutadapt  accepts IUPAC code !!!!!!!!
{
  #neo
  neo_FWD <- "CGCCGTCGCAAGCTTACCCT"
  names(neo_FWD) <- "neo_FWD"
  neo_REV <- "AGTGACGGGCGGTGTGTGC"
  names(neo_REV) <- "neo_REV" 
  
  #mif
  mif_FWD <- "GTCGGTAAAACTCGTGCCAGC"
  names(mif_FWD) <- "mif_FWD"
  mif_REV <- "ACATAGTGGGGTATCTAATCCCAGTTTG"
 # mif_REV <- "CATAGTGGGGTATCTAATCCCAGTTTG" #original
  names(mif_REV) <- "mif_REV" 
  
  #tel
  tel_FWD <- "ACACCGCCCGTCACTCT"
  names(tel_FWD) <- "tel_FWD"
  tel_REV <- "ACTTCCGGTACACTTACCATG"
  names(tel_REV) <- "tel_REV"  
  
  
#creates a list of single row tibbles for each primer
primers <- tibble(Primers = c(neo_FWD,neo_REV,
                              mif_FWD,mif_REV,
                              tel_FWD,tel_REV)) %>% 
  mutate(`Primer names`= names(Primers)) %>% 
  split(1:nrow(.))
}


Generate sequences for complement, reverse, and reverse complement for each primer

The function allOrients is used to generate all possible orientations for primers FWD e REV.

#5 - check primer orientation ----

#function to get all possible primer orientations
allOrients <- function(primers) {
   # Create all orientations of the input sequence
    # Must be a tibble with cols = c(Primers,`Primer names`)
  
   require(Biostrings)
   dna <- Biostrings::DNAString(primers$Primers)  # The Biostrings works w/ DNAString objects rather than character vectors
   orients <- c(Forward = dna, 
                Complement = Biostrings::complement(dna), 
                Reverse = Biostrings::reverse(dna),
                RevComp = Biostrings::reverseComplement(dna))
   names(orients) <- paste0(names(orients))
   
   primer_tbl <- sapply(orients, toString)
   
   primer_tbl <- dplyr::tibble(Sequence = primer_tbl,
                        `Primer orientation` = names(primer_tbl)) %>% 
     dplyr::mutate(Primer = primers$`Primer names`) %>%
     unite(col=`Orientation name`, Primer ,`Primer orientation`,remove = FALSE)
   
   return(primer_tbl)  # Convert back to character vector
}


#apply function 
primers_all_orients <- purrr::map_dfr(primers, allOrients)

names(primers_all_orients$Sequence) <- primers_all_orients$`Orientation name`


Remove reads with undetermined bases (Ns) and unpaired

Reads with undetermined bases prevent proper primer identification and ASV determination. These sequences must be removed from the data.

#6 - pre filter reads with Ns for primer checking ----
# create names for N-cleaned files

primers_n_samples <- primers_n_samples %>%
  mutate("R1 N-cleaned" = "R1 N-cleaned",
         "R2 N-cleaned" = "R2 N-cleaned")

for (sample in 1:nrow(primers_n_samples)) {
  primers_n_samples$`R1 N-cleaned`[sample] <-
   paste0(data_path,"/N-cleaned/",primers_n_samples$File_name[sample],"_R1_N-cleaned.fastq.gz")
  primers_n_samples$`R2 N-cleaned`[sample] <-
   paste0(data_path,"/N-cleaned/",primers_n_samples$File_name[sample],"_R2_N-cleaned.fastq.gz")
}

# remove reads with Ns to make primer filtering more accurate

dada2::filterAndTrim(
  fwd = primers_n_samples$R1, filt = primers_n_samples$`R1 N-cleaned`, 
  rev = primers_n_samples$R2, filt.rev = primers_n_samples$`R2 N-cleaned`,
  maxN = 0, multithread = TRUE, matchIDs = TRUE,
  verbose = TRUE, compress = TRUE)

# pivote table to longer format
primers_n_samples <- primers_n_samples %>% 
  pivot_longer(cols = c(R1,R2,`R1 N-cleaned`,`R2 N-cleaned`),
               names_to = "Stage", values_to = "Read file")


Count primer presence on reads

Before primer removal it is possible to count their presence on the reads. This procedures is carried on independently for each sample.

#6 - count primer orientation hits ----

#function to count primer on each specific library
primerHits <- function(primer, fn) {
   # Counts number of reads in which the primer is found
   nhits <- Biostrings::vcountPattern(primer, ShortRead::sread(ShortRead::readFastq(fn)), fixed = FALSE)
   return(sum(nhits > 0))
}

#function to call primerHits for multiple primers
multi_primerHits <- function(Read_file,primers){
  primer_counts <- purrr::map_df(primers,.f = primerHits, fn = Read_file)
  primer_counts <- primer_counts %>%  mutate(`Read file` = Read_file)
  return(primer_counts)
}
###########

#vector of read files to look on for primers
reads_seqs <- primers_n_samples %>% 
  filter(Stage %in% c("R1 N-cleaned", "R2 N-cleaned")) %>% 
  select(`Read file`) %>% as.list()
 

#named vector of primer sequences
primers_seqs <- primers_all_orients$Sequence


cores_to_be_used <- future::availableCores() - 2 # Usar todos os cores -2 = 78

future::plan(future::multisession(workers = cores_to_be_used))


#count primers
primers_in_Nreads <- furrr::future_map_dfr(reads_seqs$`Read file`, .f = multi_primerHits, primers = primers_seqs, .options = furrr::furrr_options(seed = NULL))

#get sample information into primers_in_Nreads table
primers_in_Nreads <- left_join(primers_in_Nreads,primers_n_samples,by = "Read file")

# 
# primers_in_Nreads_bckp <- primers_in_Nreads
# primers_in_Nreads <- primers_in_Nreads_bckp

Prepare primer counts for ploting

#7- prepare primer counts for plots ----

# cat(paste0(colnames(primers_in_Nreads),"\n"))

primers_in_Nreads <-
  primers_in_Nreads %>% 
  select(# `Read file
 File_name, Type, Group, Library, Primer, Run, Stage,
         neo_FWD_Forward, neo_REV_Forward, neo_FWD_Complement, neo_REV_Complement, 
         neo_FWD_Reverse, neo_REV_Reverse, neo_FWD_RevComp, neo_REV_RevComp, 
         mif_FWD_Forward, mif_REV_Forward, mif_FWD_Complement, mif_REV_Complement, 
         mif_FWD_Reverse, mif_REV_Reverse, mif_FWD_RevComp, mif_REV_RevComp, 
         tel_FWD_Forward, tel_REV_Forward, tel_FWD_Complement, tel_REV_Complement, 
         tel_FWD_Reverse, tel_REV_Reverse, tel_FWD_RevComp, tel_REV_RevComp)


#write.csv(x = primer_hits_tbl, file = "~/prjcts/fish_eDNA/notes/jequiDNApool/csv/primers_hits_in_reads.csv")

str(primers_in_Nreads)
colnames(primers_in_Nreads)
rownames(primers_in_Nreads)

primers_in_Nreads$Primer
primers_in_Nreads$Library


#8- prepare primer counts for plots in ggplot----

#convert primer hits table to long format
primers_in_Nreads_long <- primers_in_Nreads %>% 
  gather(key = Sequences, 
         value = Count,  
         neo_FWD_Forward, neo_FWD_Complement, neo_FWD_Reverse,neo_FWD_RevComp, 
         neo_REV_Forward, neo_REV_Complement, neo_REV_Reverse, neo_REV_RevComp,
         mif_FWD_Forward, mif_FWD_Complement, mif_FWD_Reverse, mif_FWD_RevComp, 
         mif_REV_Forward, mif_REV_Complement, mif_REV_Reverse, mif_REV_RevComp,
         tel_FWD_Forward, tel_FWD_Complement, tel_FWD_Reverse, tel_FWD_RevComp, 
         tel_REV_Forward, tel_REV_Complement, tel_REV_Reverse, tel_REV_RevComp
         ) %>% 
  mutate(Sequences = factor(Sequences,
                            levels = c("neo_FWD_Forward","neo_FWD_RevComp",
                                       "neo_REV_Forward","neo_REV_RevComp",
                                       "neo_FWD_Complement","neo_FWD_Reverse",
                                       "neo_REV_Complement","neo_REV_Reverse",
                                       
                                       
                                       "mif_FWD_Forward","mif_FWD_RevComp",
                                       "mif_REV_Forward","mif_REV_RevComp",
                                       "mif_FWD_Complement","mif_FWD_Reverse",
                                       "mif_REV_Complement","mif_REV_Reverse",
                                       
                                       
                                       "tel_FWD_Forward","tel_FWD_RevComp",
                                       "tel_REV_Forward","tel_REV_RevComp",
                                       "tel_FWD_Complement","tel_FWD_Reverse",
                                       "tel_REV_Complement","tel_REV_Reverse")),
                                       
                                       
         File_name = factor(File_name,levels = sample_levels),
         Run = as.factor(Run),
         Primer = factor(Primer,levels = c("NeoFish",
                                           "MiFish",
                                           "Teleo",
                                           "NeoFish/MiFish",
                                           "NeoFish/MiFish/Teleo"))) 



# PLOT 1: primers counts in reads tile plot - only primers FWD & REV, foward & revcomp ----
primers_tile <- 
  primers_in_Nreads_long %>% 
  # filter(Sequences  %in% c(
  #   "mif_REV_RevComp", "mif_REV_Forward", "mif_FWD_RevComp", "mif_FWD_Forward",
  #   "neo_REV_RevComp", "neo_REV_Forward", "neo_FWD_RevComp", "neo_FWD_Forward",
  #   "tel_REV_RevComp", "tel_REV_Forward", "tel_FWD_RevComp", "tel_FWD_Forward")) %>% 
  mutate(File_name = factor(File_name,levels = sample_levels)) %>% 
  ggplot2::ggplot(aes(y=File_name,x=Sequences,fill=log10(Count)
                      # ,col=Stage
                      )) +
  geom_tile()+
  geom_text(aes(label = Count),size=1)+
  # scale_fill_gradient(low="white", high="darkgreen",trans="log10") +
  scale_fill_gradientn(name = "Primer counts",
                       colours = c("white","darkgreen"),
                       values = c(0,1),
                       na.value ="white") +
  theme_light(base_line_size = 1,base_size = 6) +
  theme(axis.text.x = element_text(angle = 45,hjust = 1)) +
  geom_hline(yintercept = c(40.5,82.5,86.5,116.5),color = "grey") +
  geom_vline(xintercept = c(4.5,8.5,12.5,16.5),color = "grey") +
  # coord_fixed(ratio = 0.20) +
  xlab("Primers") +
  ylab("Amostra") +
  ggtitle(label = "eDNA 1st, 2nd & 3rd runs",
              subtitle = "Primer presence on sample reads") 

primers_tile

ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/1-primers_in_reads_all_FR.png",
     plot = primers_tile,
     device = "png",
     width = 27,
     height = 40,
     units = "cm",
     dpi = 600)

ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/1-primers_in_reads_all_FR.pdf",
     plot = primers_tile,
     device = "pdf",
     width = 27,
     height = 40,
     units = "cm",
     dpi = 600)


#9- write csv file with primer hits counts per lib ----
write.csv(x = primer_hits_tbl,file = "~/prjcts/fish_eDNA/sfjq/results/primers_hits_tbl.csv",
          row.names = FALSE)

Remove primers from reads

Primer removal with Cutadapt

The cutadapt software (DOI:10.14806/ej.17.1.200) was used for primer removal on read sequences.

#10 - cutadapt ----

#set or create cutadapt processed reads dir path
path.cut <- file.path(data_path, "cutadapt")
if(!dir.exists(path.cut)) dir.create(path.cut)


Generate and execute primer-specific commands

The original DADA2 ITS protocol removes only FWD and REV reverse complement sequences. This protocol is adjusted for selecting reads only of the expected primer and removing the primer.

# opitional: remove all primers from all reads and samples ----

#10 - map sample names to reads files ----

#name outputs
cutadapt_files <- primers_n_samples %>% 
  filter(Stage %in% c("R1 N-cleaned","R2 N-cleaned")) %>% 
  mutate(`Read file` = str_replace_all(.$`Read file`,pattern = "N-cleaned",replacement = "cutadapt")) %>% 
  mutate(Stage = str_replace_all(.$Stage,pattern = "N-cleaned",replacement = "cutadapt"))


primers_n_samples <- bind_rows(primers_n_samples,cutadapt_files)

#all ----
{ 
          #make reverse complements
        #  the XXX_Complement and XXX_reverse have no hits so were ignored at last plot and from now on
          all_FWD.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("FWD_Forward"))] 
          all_FWD.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("FWD_RevComp"))] 
          all_REV.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("REV_Forward"))] 
          all_REV.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("REV_RevComp"))] 
  
}
  
#remove primers and filter only the reads that contain the expected primer ----
{
  #MiFish ----
  mif_FWD.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("mif_FWD_Forward"))] 
  mif_FWD.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("mif_FWD_RevComp"))] 
  mif_REV.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("mif_REV_Forward"))] 
  mif_REV.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("mif_REV_RevComp"))] 
  
  #NeoFish ----
  neo_FWD.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("neo_FWD_Forward"))] 
  neo_FWD.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("neo_FWD_RevComp"))] 
  neo_REV.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("neo_REV_Forward"))] 
  neo_REV.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("neo_REV_RevComp"))] 
  
  #Teleo ----
  tel_FWD.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("tel_FWD_Forward"))]
  tel_FWD.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("tel_FWD_RevComp"))]
  tel_REV.orients <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("tel_REV_Forward"))]
  tel_REV.RC <-  primers_all_orients$Sequence[primers_all_orients$`Orientation name` %>% grep(pattern = c("tel_REV_RevComp"))]
  }
  
                #creat flags
                # Trim FWD and the reverse-complement of REV off of R1 (forward reads)
                all_R1.flags <- paste("-g", all_FWD.orients, "-a", all_REV.RC)
                # Trim REV and the reverse-complement of FWD off of R2 (reverse reads)
                all_R2.flags <- paste("-G", all_REV.orients, "-A", all_FWD.RC)
                
#create primer-specific tags ----
  {
  #MiFish ----
  # Trim FWD and the reverse-complement of REV off of R1 (forward reads)
  mif_R1.flags <- paste("-g", mif_FWD.orients, "-a", mif_REV.RC)
  # Trim REV and the reverse-complement of FWD off of R2 (reverse reads)
  mif_R2.flags <- paste("-G", mif_REV.orients, "-A", mif_FWD.RC)
  
  #NeoFish ----
  # Trim FWD and the reverse-complement of REV off of R1 (forward reads)
  neo_R1.flags <- paste("-g", neo_FWD.orients, "-a", neo_REV.RC)
  # Trim REV and the reverse-complement of FWD off of R2 (reverse reads)
  neo_R2.flags <- paste("-G", neo_REV.orients, "-A", neo_FWD.RC)
  
  #Teleo ----
  # Trim FWD and the reverse-complement of REV off of R1 (forward reads)
  tel_R1.flags <- paste("-g", tel_FWD.orients, "-a", tel_REV.RC)
  # Trim REV and the reverse-complement of FWD off of R2 (reverse reads)
  tel_R2.flags <- paste("-G", tel_REV.orients, "-A", tel_FWD.RC)
  }

#cutadapt files path and names ----
{
        all_fnFs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 cutadapt"]
        names(all_fnFs.cut) <- all_fnFs.cut %>% 
            str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
            str_remove(pattern = "_cutadapt.fastq.gz")
        all_fnRs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 cutadapt"]
        names(all_fnRs.cut) <- all_fnRs.cut %>% 
            str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
            str_remove(pattern = "_cutadapt.fastq.gz")
        
        all_fnFs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 N-cleaned"]
        all_fnRs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 N-cleaned"]

}

{
  #neo ----
  neo_fnFs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 cutadapt" & primers_n_samples$Primer == "NeoFish"]
    names(neo_fnFs.cut) <- neo_fnFs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  neo_fnRs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 cutadapt" & primers_n_samples$Primer == "NeoFish"]
    names(neo_fnRs.cut) <- neo_fnRs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  neo_fnFs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 N-cleaned" & primers_n_samples$Primer == "NeoFish"]
    names(neo_fnFs.filtN) <- neo_fnFs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
  
  neo_fnRs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 N-cleaned" & primers_n_samples$Primer == "NeoFish"]
    names(neo_fnRs.filtN) <- neo_fnRs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
    
  #mif ----
  mif_fnFs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 cutadapt" & primers_n_samples$Primer == "MiFish"]
    names(mif_fnFs.cut) <- mif_fnFs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  mif_fnRs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 cutadapt" & primers_n_samples$Primer == "MiFish"]
    names(mif_fnRs.cut) <- mif_fnRs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  mif_fnFs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 N-cleaned" & primers_n_samples$Primer == "MiFish"]
    names(mif_fnFs.filtN) <- mif_fnFs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
  
  mif_fnRs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 N-cleaned" & primers_n_samples$Primer == "MiFish"]
    names(mif_fnRs.filtN) <- mif_fnRs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
    
      
  #tel ----
  tel_fnFs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 cutadapt" & primers_n_samples$Primer == "Teleo"]
    names(tel_fnFs.cut) <- tel_fnFs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  tel_fnRs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 cutadapt" & primers_n_samples$Primer == "Teleo"]
    names(tel_fnRs.cut) <- tel_fnRs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  tel_fnFs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 N-cleaned" & primers_n_samples$Primer == "Teleo"]
    names(tel_fnFs.filtN) <- tel_fnFs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
  
  tel_fnRs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 N-cleaned" & primers_n_samples$Primer == "Teleo"]
    names(tel_fnRs.filtN) <- tel_fnRs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
    
          
  #neo/mif & neo/mif/tel ----
  nmt_fnFs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 cutadapt" & primers_n_samples$Primer %in% c("NeoFish/MiFish","NeoFish/MiFish/Teleo")]
    names(nmt_fnFs.cut) <- nmt_fnFs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  nmt_fnRs.cut <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 cutadapt" & primers_n_samples$Primer %in% c("NeoFish/MiFish","NeoFish/MiFish/Teleo")]
    names(nmt_fnRs.cut) <- nmt_fnRs.cut %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/cutadapt/")) %>% 
      str_remove(pattern = "_cutadapt.fastq.gz")

  nmt_fnFs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 N-cleaned" & primers_n_samples$Primer %in% c("NeoFish/MiFish","NeoFish/MiFish/Teleo")]
    names(nmt_fnFs.filtN) <- nmt_fnFs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
  
  nmt_fnRs.filtN <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 N-cleaned" & primers_n_samples$Primer %in% c("NeoFish/MiFish","NeoFish/MiFish/Teleo")]
    names(nmt_fnRs.filtN) <- nmt_fnRs.filtN %>% 
      str_remove(pattern = paste0("~/prjcts/fish_eDNA/sfjq/data/reads/N-cleaned/")) %>% 
      str_remove(pattern = "_N-cleaned.fastq.gz")
  
}


# e essa ordem tá perigosa
names(primers_n_samples$`Read file`)<- primers_n_samples$File_name


primers_n_samples$`Read file`[primers_n_samples$Stage %in% c("R1 N-cleaned", "R2 N-cleaned")] %>%  length()

#TODO esse tem q ir pro purrr...


# Run Cutadapt
#   output folder must exist
for(i in 1:40) {
# for(i in seq_along(all_fnFs)) {
system2(cutadapt, args = c(all_R1.flags, all_R2.flags, "-n", 2, # -n 2 required to remove FWD and REV from reads
"-o", all_fnFs.cut[i], "-p", all_fnRs.cut[i], # output files
all_fnFs.filtN[i], all_fnRs.filtN[i],  # input files
"--minimum-length 10")) # guarantee no zerolength reads
}


length(neo_fnFs.cut)
length(mif_fnFs.cut)
length(mif_fnRs.cut)
length(tel_fnFs.cut)
length(nmt_fnFs.cut)


#run cutadapt by primer ----

#MiFish ----
for(i in 1:length(mif_fnFs.cut)) {
# for(i in seq_along(all_fnFs)) {
system2(cutadapt, args = c(mif_R1.flags, mif_R2.flags, "-n", 2, # -n 2 required to remove FWD and REV from reads
"-o", mif_fnFs.cut[i], "-p", mif_fnRs.cut[i], # output files
mif_fnFs.filtN[i], mif_fnRs.filtN[i],  # input files
"--minimum-length 10 --discard-untrimmed")) # guarantee no zerolength reads
}

#NeoFish ----
for(i in 1:length(neo_fnFs.cut)) {
# for(i in seq_along(all_fnFs)) {
system2(cutadapt, args = c(neo_R1.flags, neo_R2.flags, "-n", 2, # -n 2 required to remove FWD and REV from reads
"-o", neo_fnFs.cut[i], "-p", neo_fnRs.cut[i], # output files
neo_fnFs.filtN[i], neo_fnRs.filtN[i],  # input files
"--minimum-length 10 --discard-untrimmed")) # guarantee no zerolength reads
}


#Teleo ----
for(i in 1:length(tel_fnFs.cut)) {
# for(i in seq_along(all_fnFs)) {
system2(cutadapt, args = c(tel_R1.flags, tel_R2.flags, "-n", 2, # -n 2 required to remove FWD and REV from reads
"-o", tel_fnFs.cut[i], "-p", tel_fnRs.cut[i], # output files
tel_fnFs.filtN[i], tel_fnRs.filtN[i],  # input files
"--minimum-length 10 --discard-untrimmed")) # guarantee no zerolength reads
}


#neo/mif & neo/mif/tel ----
  
for(i in 1:length(nmt_fnFs.cut)) {
# for(i in seq_along(all_fnFs)) {
system2(cutadapt, args = c(all_R1.flags, all_R2.flags, "-n", 2, # -n 2 required to remove FWD and REV from reads
"-o", nmt_fnFs.cut[i], "-p", nmt_fnRs.cut[i], # output files
nmt_fnFs.filtN[i], nmt_fnRs.filtN[i],  # input files
"--minimum-length 10 --discard-untrimmed")) # guarantee no zerolength reads
}


# as  Da23-mif & neo & SFJQ-mif & neo were previously demultiplexed, they do not bear the primers, so all reads are filtered out


Check primer removal

Change de library number index in order to check the presence of remaining primer sequences on each lib data. It is expected that all removed orientation counts change to zero since the primer sequences are removed.

# only ofr didatic purposes (or logical error checking)
# 8 - check for remaining adapters ----
# As a sanity check, we will count the presence of primers in the first cutadapt-ed sample:


#vector of read files to look on for primers
reads_seqs_cut <- primers_n_samples %>% 
  filter(Stage %in% c("R2 cutadapt", "R2 cutadapt")) %>% 
  select(`Read file`) %>% as.list()


#count primers
future::plan(future::multisession(workers = cores_to_be_used))
primers_in_cut_reads <- furrr::future_map_dfr(reads_seqs_cut$`Read file`, .f = multi_primerHits, primers = primers_seqs, .options = furrr::furrr_options(seed = NULL))

 # 
# primers_in_Nreads <- purrr::map_df(reads_seqs,.f = multi_primerHits, primers = primers_seqs)

#get sample information into primers_in_Nreads table
primers_in_cut_reads <- left_join(primers_in_cut_reads,primers_n_samples,by = "Read file")

# primers_in_cut_reads_bckp <- primers_in_cut_reads
# primers_in_cut_reads <- primers_in_cut_reads_bckp

primers_in_cut_reads <-
  primers_in_cut_reads %>% 
  select(# `Read file
 File_name, Type, Group, Library, Primer, Run, Stage,
         neo_FWD_Forward, neo_REV_Forward, neo_FWD_Complement, neo_REV_Complement, 
         neo_FWD_Reverse, neo_REV_Reverse, neo_FWD_RevComp, neo_REV_RevComp, 
         mif_FWD_Forward, mif_REV_Forward, mif_FWD_Complement, mif_REV_Complement, 
         mif_FWD_Reverse, mif_REV_Reverse, mif_FWD_RevComp, mif_REV_RevComp, 
         tel_FWD_Forward, tel_REV_Forward, tel_FWD_Complement, tel_REV_Complement, 
         tel_FWD_Reverse, tel_REV_Reverse, tel_FWD_RevComp, tel_REV_RevComp)

#convert primer hits table to long format
primers_in_cut_reads_long <- primers_in_cut_reads %>% 
  gather(key = Sequences, 
         value = Count,  
         neo_FWD_Forward, neo_FWD_Complement,
         neo_FWD_Reverse,neo_FWD_RevComp, 
         neo_REV_Forward, neo_REV_Complement,
         neo_REV_Reverse, neo_REV_RevComp,
         mif_FWD_Forward, mif_FWD_Complement,
         mif_FWD_Reverse, mif_FWD_RevComp, 
         mif_REV_Forward, mif_REV_Complement,
         mif_REV_Reverse, mif_REV_RevComp,
         tel_FWD_Forward, tel_FWD_Complement,
         tel_FWD_Reverse, tel_FWD_RevComp, 
         tel_REV_Forward, tel_REV_Complement,
         tel_REV_Reverse, tel_REV_RevComp) %>% 
  mutate(Sequences = factor(Sequences,levels = c("neo_FWD_Forward", "neo_REV_Forward",
                                                 "neo_FWD_RevComp", "neo_REV_RevComp",
                                                 "neo_FWD_Complement", "neo_REV_Complement",
                                                 "neo_FWD_Reverse", "neo_REV_Reverse",
                                       
                                                 "mif_FWD_Forward", "mif_REV_Forward",
                                                 "mif_FWD_RevComp", "mif_REV_RevComp",
                                                 "mif_FWD_Complement", "mif_REV_Complement",
                                                 "mif_FWD_Reverse", "mif_REV_Reverse",
                                       
                                                "tel_FWD_Forward", "tel_REV_Forward",
                                                "tel_FWD_RevComp", "tel_REV_RevComp",
                                                "tel_FWD_Complement", "tel_REV_Complement",
                                                "tel_FWD_Reverse", "tel_REV_Reverse")),
         File_name = factor(File_name,levels = sample_levels),
         Run = as.factor(Run),
         Primer = factor(Primer,levels = c("NeoFish","MiFish","Teleo","NeoFish/MiFish","NeoFish/MiFish/Teleo"))) 



# PLOT 1: primers counts in reads tile plot - only primers FWD & REV, foward & revcomp ----
primers_tile_clean <- 
  primers_in_cut_reads_long %>% 
  filter(Sequences  %in% c(
    "mif_REV_RevComp", "mif_REV_Forward", "mif_FWD_RevComp", "mif_FWD_Forward",
    "neo_REV_RevComp", "neo_REV_Forward", "neo_FWD_RevComp", "neo_FWD_Forward",
    "tel_REV_RevComp", "tel_REV_Forward", "tel_FWD_RevComp", "tel_FWD_Forward")) %>% 
  filter(Run %in% c("LGC_MiniSeq_1")) %>% 
  ggplot2::ggplot(aes(y=File_name,x=Sequences,fill=log10(Count))) +
  geom_tile()+
  geom_text(aes(label = Count),size=1)+
  # scale_fill_gradient(low="white", high="darkgreen",trans="log10") +
  scale_fill_gradientn(name = "Primer counts",
                       colours = c("white","darkgreen"),
                       values = c(0,1),
                       na.value ="white") +
  theme_light(base_line_size = 1,base_size = 6) +
  theme(axis.text.x = element_text(angle = 45,hjust = 1)) +
  geom_hline(yintercept = c(40.5,82.5,86.5,116.5),color = "grey") +
  geom_vline(xintercept = c(4.5,8.5,12.5,16.5),color = "grey") +
  # coord_fixed(ratio = 0.20) +
  xlab("Primers") +
  ylab("Amostra") +
  ggtitle(label = "eDNA 1st, 2nd & 3rd runs",
              subtitle = "Primer presence on sample reads") 
# +
#   facet_wrap(~Run, drop = TRUE)


primers_tile_clean



Quality filtering

Here the DADA2 pipeline starts.


Set input libs paths

Define the paths to the libraries after cutadapt primer removal.

# 9 - load clean seqs to DADA2 pipe ----

all_fnFs.cut <- c(mif_fnFs.cut,neo_fnFs.cut,tel_fnFs.cut,nmt_fnFs.cut)
all_fnRs.cut <- c(mif_fnRs.cut,neo_fnRs.cut,tel_fnRs.cut,nmt_fnRs.cut)


all_fnFs.cut
all_fnRs.cut


Set quality filtering output files names

# 11 - quality filter preparation ----


#name outputs
Qfilter_files <- primers_n_samples %>% 
  filter(Stage %in% c("R1 N-cleaned","R2 N-cleaned")) %>% 
  mutate(`Read file` = str_replace_all(.$`Read file`,pattern = "N-cleaned",replacement = "Qfiltered")) %>% 
  mutate(Stage = str_replace_all(.$Stage,pattern = "N-cleaned",replacement = "Qfiltered"))

primers_n_samples <- bind_rows(primers_n_samples,Qfilter_files)

#rename files so all can be traceble
names(primers_n_samples$`Read file`) <- primers_n_samples$File_name


# Qfiltered files path and names

all_filtFs <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R1 Qfiltered"]
names(all_filtFs) <- all_filtFs %>% 
    str_remove(pattern = paste0(data_path,"/Qfiltered/")) %>% 
    str_remove(pattern = "_Qfiltered.fastq.gz")
all_filtRs <- primers_n_samples$`Read file`[primers_n_samples$Stage == "R2 Qfiltered"]
names(all_filtRs) <- all_filtRs %>% 
    str_remove(pattern = paste0(data_path,"/Qfiltered/")) %>% 
    str_remove(pattern = "_Qfiltered.fastq.gz")


Quality filtering

On this step it is possible to filter by size but, as we have already removed primers from the beginning/end of the reads, it is expected that the remaining sequences are already trimmed to lengths compatible with their respective amplicons. Thus, no length trimming was conducted.

# 12 - dada filtering ----

# We’ll use standard filtering parameters: maxN=0 (DADA2 requires no Ns), truncQ=2, rm.phix=TRUE and maxEE=2. The maxEE parameter sets the maximum number of “expected errors” allowed in a read, which is a better filter than simply averaging quality scores.

length(all_fnFs.cut)
length(all_filtFs)
length(all_fnRs.cut)
length(all_filtRs)

#sorting for next step not to mix files
all_fnFs.cut <- base::sort(all_fnFs.cut)
all_filtFs <- base::sort(all_filtFs)
all_fnRs.cut <- base::sort(all_fnRs.cut)
all_filtRs <- base::sort(all_filtRs)
names(all_fnFs.cut)
names(all_filtFs)
names(all_fnRs.cut)
names(all_filtRs)

#all

all_filtered_out <- dada2::filterAndTrim(fwd = all_fnFs.cut,
                                         filt = all_filtFs, 
                                         rev = all_fnRs.cut,
                                         filt.rev = all_filtRs,
                                         # truncLen=c(240,160),
                                         maxN=0,
                                         maxEE=c(2,2),
                                         # truncQ=2,
                                         rm.phix=TRUE,
                                         compress=TRUE, multithread=TRUE,verbose = TRUE,matchIDs = TRUE) # On Windows set multithread=FALSE
head(all_filtered_out)


View post-filtering quality profiles

#check quality profile after filtering and trimming
plotQualityProfile(all_filtFs[2])
plotQualityProfile(all_filtRs[2:8])

plotQualityProfile(mif_filtFs[])
plotQualityProfile(mif_filtRs[])


Identify error rates intrinsic to sequencing

# 13 - learn error rates ----

#Learn the Error Rates
primers_n_samples$Run %>%  unique()

#run LGC_MiniSeq_1 ----
run1_errF <- learnErrors(primers_n_samples$`Read file`[primers_n_samples$Run == "LGC_MiniSeq_1" & 
                                                         primers_n_samples$Stage == "R1 Qfiltered"], 
                        multithread=TRUE,randomize = TRUE)
run1_errR <- learnErrors(primers_n_samples$`Read file`[primers_n_samples$Run == "LGC_MiniSeq_1" & 
                                                         primers_n_samples$Stage == "R2 Qfiltered"], 
                        multithread=TRUE,randomize = TRUE)

#run LGC_MiniSeq_2 ----
run2_errF <- learnErrors(primers_n_samples$`Read file`[primers_n_samples$Run == "LGC_MiniSeq_2" & 
                                                         primers_n_samples$Stage == "R1 Qfiltered"], 
                        multithread=TRUE,randomize = TRUE)
run2_errR <- learnErrors(primers_n_samples$`Read file`[primers_n_samples$Run == "LGC_MiniSeq_2" & 
                                                         primers_n_samples$Stage == "R2 Qfiltered"], 
                        multithread=TRUE,randomize = TRUE)

#run ecomol_iSeq ----
run3_errF <- learnErrors(primers_n_samples$`Read file`[primers_n_samples$Run == "ecomol_iSeq" & 
                                                         primers_n_samples$Stage == "R1 Qfiltered"], 
                        multithread=TRUE,randomize = TRUE)
run3_errR <- learnErrors(primers_n_samples$`Read file`[primers_n_samples$Run == "ecomol_iSeq" & 
                                                         primers_n_samples$Stage == "R2 Qfiltered"], 
                        multithread=TRUE,randomize = TRUE)


#   # plotErrors(run3_errF, nominalQ=TRUE)
#   # plotErrors(run3_errR, nominalQ=TRUE)


Dereplication: grouping into ASVs

On this step each library is reduced to its unique composing sequences and their counts.

# 14 - dada dereplication ----


names(primers_n_samples$`Read file`) <- primers_n_samples$File_name ###!!!!!!!!!!!!! Everything must have unique names from here

unique(primers_n_samples$`Read file`)
names(primers_n_samples$`Read file`)


#run LGC_MiniSeq_1 ----
LGC_1_derep_forward <- derepFastq(primers_n_samples$`Read file`[
  primers_n_samples$Run == "LGC_MiniSeq_1" & 
    primers_n_samples$Stage == "R1 Qfiltered"], verbose=TRUE)
# names(all_derep_forward) <- all_sample.names

LGC_1_derep_reverse <- derepFastq(primers_n_samples$`Read file`[
  primers_n_samples$Run == "LGC_MiniSeq_1" & 
    primers_n_samples$Stage == "R2 Qfiltered"], verbose=TRUE)
# names(all_derep_reverse) <- all_sample.names

LGC_1_dadaFs <- dada(LGC_1_derep_forward, err=run1_errF, multithread=TRUE)
LGC_1_dadaRs <- dada(LGC_1_derep_reverse, err=run1_errR, multithread=TRUE)

#run LGC_MiniSeq_2 ----
LGC_2_derep_forward <- derepFastq(primers_n_samples$`Read file`[
  primers_n_samples$Run == "LGC_MiniSeq_2" & 
    primers_n_samples$Stage == "R1 Qfiltered"], verbose=TRUE)
# names(all_derep_forward) <- all_sample.names

LGC_2_derep_reverse <- derepFastq(primers_n_samples$`Read file`[
  primers_n_samples$Run == "LGC_MiniSeq_2" & 
    primers_n_samples$Stage == "R2 Qfiltered"], verbose=TRUE)
# names(all_derep_reverse) <- all_sample.names

LGC_2_dadaFs <- dada(LGC_2_derep_forward, err=run2_errF, multithread=TRUE)
LGC_2_dadaRs <- dada(LGC_2_derep_reverse, err=run2_errR, multithread=TRUE)

#run ecomol_iSeq ----
ecomol_derep_forward <- derepFastq(primers_n_samples$`Read file`[
  primers_n_samples$Run == "ecomol_iSeq" & 
    primers_n_samples$Stage == "R1 Qfiltered"], verbose=TRUE)
# names(all_derep_forward) <- all_sample.names

ecomol_derep_reverse <- derepFastq(primers_n_samples$`Read file`[
  primers_n_samples$Run == "ecomol_iSeq" & 
    primers_n_samples$Stage == "R2 Qfiltered"], verbose=TRUE)
# names(all_derep_reverse) <- all_sample.names

ecomol_dadaFs <- dada(ecomol_derep_forward, err=run3_errF, multithread=TRUE)
ecomol_dadaRs <- dada(ecomol_derep_reverse, err=run3_errR, multithread=TRUE)


all_dadaFs <- c(ecomol_dadaFs,LGC_2_dadaFs,LGC_1_dadaFs)
all_dadaRs <- c(ecomol_dadaRs,LGC_2_dadaRs,LGC_1_dadaRs)

names(all_dadaFs)


Merge read pairs

On this step the forward an reverse reads are merged, by overlap, in order to reconstruct the insert full sequence. As we have samples from three runs, they are all worked independently.

# 15 - merge read pairs ----

#run1 ----
run1_mergers <- mergePairs(dadaF = LGC_1_dadaFs,
                          derepF = LGC_1_derep_forward,
                          dadaR = LGC_1_dadaRs,
                          derepR = LGC_1_derep_reverse,
                          minOverlap = 20,
                          maxMismatch = 0,   # changed from 0 to 1 since a lot was being left out for single mismatch
                          returnRejects = TRUE,
                          verbose=TRUE)

#run2 ----
run2_mergers <- mergePairs(dadaF = LGC_2_dadaFs,
                          derepF = LGC_2_derep_forward,
                          dadaR = LGC_2_dadaRs,
                          derepR = LGC_2_derep_reverse,
                          minOverlap = 20,
                          maxMismatch = 0,   # changed from 0 to 1 since a lot was being left out for single mismatch
                          returnRejects = TRUE,
                          verbose=TRUE)

#run1 ----
run3_mergers <- mergePairs(dadaF = ecomol_dadaFs,
                          derepF = ecomol_derep_forward,
                          dadaR = ecomol_dadaRs,
                          derepR = ecomol_derep_reverse,
                          minOverlap = 20,
                          maxMismatch = 0,   # changed from 0 to 1 since a lot was being left out for single mismatch
                          returnRejects = TRUE,
                          verbose=TRUE)

all_mergers <- c(run3_mergers,run2_mergers,run1_mergers)

names(all_mergers)

length(all_dadaFs)
length(all_dadaRs)
head(all_mergers[[12]])
length(all_dadaFs)
names(all_mergers)
str(all_mergers)
class(all_mergers)


# all_seqtab <- makeSequenceTable(samples = c(run3_mergers,run2_mergers,run1_mergers))   #talvez essa função aceite varios mergers
all_seqtab <- makeSequenceTable(samples = all_mergers)
dim(all_seqtab)
View(all_seqtab)
str(all_seqtab)
# Inspect distribution of sequence lengths
table(nchar(getSequences(all_seqtab)))
table(nchar(getSequences(all_seqtab))) %>% plot()


names(all_dadaFs)
names(all_derep_forward)
names(all_dadaRs)
names(all_derep_reverse)


Remove chimeras

Chimeras are artificial read pairs that might have been generated erroneously on sequencing. The DADA2 package estimates the probability of a sequence to be chimeric given the abundancy of its parental sequnces. After chimeric sequences removal, the remaining ASVs length distribution is assessed. On further steps it will be used to restrict analisys to ASVs compatible with each primer amplicons’ length interval, in order to keep of unexpected ASVs.

# 16 - remove chimeras ----


# any(colnames(C1conc_seqtab) %in% colnames(all_seqtab))

all_seqtab.nochim <- removeBimeraDenovo(all_seqtab, method="consensus", multithread=TRUE, verbose=TRUE)
dim(all_seqtab.nochim)
sum(all_seqtab.nochim)/sum(all_seqtab) # =  0.8404743 , perda de 16% na abundancia
#count proportion of ASVs of a given length
table(nchar(getSequences(all_seqtab.nochim)))
table(nchar(getSequences(all_seqtab.nochim))) %>% plot()
rownames(all_seqtab.nochim)



View(all_seqtab.nochim)
str(all_seqtab.nochim)


Count reads and remaining ASVs

# 17 - count reads proportion throughout the pipeline ----

getN <- function(x) sum(getUniques(x))

#preparing subtables with named rows to combine latter
#raw files

names(primers_n_samples$`Read file`) <- primers_n_samples$Library 

raw_reads <- primers_n_samples %>% filter(Stage %in% c("R1","R2")) 

raw_reads_counts <- ShortRead::countFastq(dirPath = raw_reads$`Read file`) %>% as_tibble(rownames = "Read file")
raw_reads_counts <- left_join(x = raw_reads_counts, y = (raw_reads %>%  mutate(`Read file` = basename(`Read file`)) 
                                                         ),by = "Read file")

tbl_raw_FWD <- raw_reads_counts[raw_reads_counts$Stage %in% c("R1"),] %>% select(File_name, records) %>% `colnames<-`(c("File_name", "Raw FWD"))
tbl_raw_REV <- raw_reads_counts[raw_reads_counts$Stage %in% c("R2"),] %>% select(File_name, records) %>% `colnames<-`(c("File_name", "Raw REV"))



tbl_Denoised_FWD <- (sapply(all_dadaFs, getN) %>% as_tibble(rownames = "File_name")) %>% `colnames<-`(c("File_name", "Denoised FWD"))
tbl_Denoised_REV <- (sapply(all_dadaRs, getN) %>% as_tibble(rownames = "File_name")) %>% `colnames<-`(c("File_name", "Denoised REV"))
tbl_Merged <- (rowSums(all_seqtab) %>% as_tibble(rownames = "File_name")) %>% `colnames<-`(c("File_name", "Merged"))
tbl_Non_chimeric <- (rowSums(all_seqtab.nochim) %>% as_tibble(rownames = "File_name")) %>% `colnames<-`(c("File_name", "Non-chimeric"))

# combine all counts by sample to plot

all_track <- all_filtered_out %>%  as_tibble(rownames = "File_name") %>% 
  mutate(`File_name` = str_remove(string = `File_name`, pattern = "_R1_cutadapt.fastq.gz")) %>% 
  left_join(tbl_raw_FWD,by = "File_name") %>% 
  left_join(tbl_raw_REV,by = "File_name") %>% 
  left_join(tbl_Denoised_FWD,by = "File_name") %>% 
  left_join(tbl_Denoised_REV,by = "File_name") %>% 
  left_join(tbl_Merged,by = "File_name") %>% 
  left_join(tbl_Non_chimeric,by = "File_name") %>% 
  left_join(primers_n_samples[primers_n_samples$Stage == "R1",],by = "File_name") %>% 
  select(!c("Stage", "Read file"))



colnames(all_track) <- c("File_name","N-cleaned", "Filtered","Raw FWD", "Raw REV", "Denoised FWD", "Denoised REV", "Merged", "Non-Chimeric", "Type", "Group", "Library", "Primer", "Run")




# Combine tables together (if there is more than one)
track_tbl <- bind_rows(all_track)


{
all_track$File_name[all_track$File_name == "Cassaum"] <- "Positive Control\n(P.glauca)"
all_track$File_name[all_track$File_name == "Da19"] <- "Da19"
all_track$File_name[all_track$File_name == "Da20"] <- "Da20"
all_track$File_name[all_track$File_name == "Da21"] <- "Da21"
all_track$File_name[all_track$File_name == "Da22"] <- "Da22"
all_track$File_name[all_track$File_name == "Da23-mif"] <- "Da23-mif"
all_track$File_name[all_track$File_name == "Da23-neo"] <- "Da23-neo"
all_track$File_name[all_track$File_name == "neg-PCR2"] <- "neg-PCR2"
all_track$File_name[all_track$File_name == "pJequei-N-norm-M"] <- "Non-normalized JQmc\nMiFish"
all_track$File_name[all_track$File_name == "pJequei-N-norm-N"] <- "Non-normalized JQmc\nNeoFish"
all_track$File_name[all_track$File_name == "pJequei-N-norm-T"] <- "Non-normalized JQmc\nTeleo"
all_track$File_name[all_track$File_name == "pJequei-norm-M"] <- "Normalized JQmc\nMiFish"
all_track$File_name[all_track$File_name == "pJequei-norm-N"] <- "Normalized JQmc\nNeoFish"
all_track$File_name[all_track$File_name == "pJequei-norm-T"] <- "Normalized JQmc\nTeleo"
all_track$File_name[all_track$File_name == "SFJQ-mif"] <- "Normalized SFJQmc\nMiFish"
all_track$File_name[all_track$File_name == "SFJQ-neo"] <- "Normalized SFJQmc\nNeoFish"
all_track$File_name[all_track$File_name == "SFnNorm-mi"] <- "Non-normalized SFmc\nMiFish"
all_track$File_name[all_track$File_name == "SFnNorm-neo"] <- "Non-normalized SFmc\nNeoFish"
all_track$File_name[all_track$File_name == "SFNorm-mi"] <- "Normalized SFmc\nMiFish"
all_track$File_name[all_track$File_name == "SFNorm-neo"] <- "Normalized SFmc\nNeoFish"
}


# save reads counts table



writexl::write_xlsx(x = all_track,
                    path = "~/prjcts/fish_eDNA/sfjq/results/sfjq_read_counts_along_quality_control.xlsx",
                    col_names = TRUE,format_headers = TRUE)






# plot reads proportion troughout the pipeline ----


track_tbl$Primer %>% unique()
track_tbl$File_name %>% unique()

#TODO
# https://bhaskarvk.github.io/colormap/
#https://www.thinkingondata.com/something-about-viridis-library/
#set colors here ss




#perda por filtrar N
all_track %>% mutate(perda = `N-cleaned`/`Raw FWD`)


#18 - set colors for downstream plots ----

# colors 
scales::show_col(colors5)



colors5 <- c("#017504","#000791","#820000","#780058","#ff5500") #neo,mi,tel,all
colors_norm <- c("#017504","#4fc952",
                 "#000791","#3862eb",
                 "#820000","#bf4b4b")
scales::show_col(colors_norm)
scales::show_col(colors5)

#PLOT2 - sample track plot ----

# # track_tbl$File_name %>% paste0('"\n"',collapse = "") %>% cat()
# track_tbl$File_name %>% unique() %>% base::sort() %>% paste0(collapse = '\n') %>%  cat()
# sample_levels


 {
track_tbl$File_name[track_tbl$File_name == "Cassaum"] <- "Positive Control\n(P.glauca)"
track_tbl$File_name[track_tbl$File_name == "Da19"] <- "Da19"
track_tbl$File_name[track_tbl$File_name == "Da20"] <- "Da20"
track_tbl$File_name[track_tbl$File_name == "Da21"] <- "Da21"
track_tbl$File_name[track_tbl$File_name == "Da22"] <- "Da22"
track_tbl$File_name[track_tbl$File_name == "Da23-mif"] <- "Da23-mif"
track_tbl$File_name[track_tbl$File_name == "Da23-neo"] <- "Da23-neo"
#track_tbl$File_name[track_tbl$File_name == "neg-PCR2"] <-
track_tbl$File_name[track_tbl$File_name == "pJequei-N-norm-M"] <- "Non-normalized JQmc\nMiFish"
track_tbl$File_name[track_tbl$File_name == "pJequei-N-norm-N"] <- "Non-normalized JQmc\nNeoFish"
track_tbl$File_name[track_tbl$File_name == "pJequei-N-norm-T"] <- "Non-normalized JQmc\nTeleo"
track_tbl$File_name[track_tbl$File_name == "pJequei-norm-M"] <- "Normalized JQmc\nMiFish"
track_tbl$File_name[track_tbl$File_name == "pJequei-norm-N"] <- "Normalized JQmc\nNeoFish"
track_tbl$File_name[track_tbl$File_name == "pJequei-norm-T"] <- "Normalized JQmc\nTeleo"
track_tbl$File_name[track_tbl$File_name == "SFJQ-mif"] <- "Normalized SFJQmc\nMiFish"
track_tbl$File_name[track_tbl$File_name == "SFJQ-neo"] <- "Normalized SFJQmc\nNeoFish"
track_tbl$File_name[track_tbl$File_name == "SFnNorm-mi"] <- "Non-normalized SFmc\nMiFish"
track_tbl$File_name[track_tbl$File_name == "SFnNorm-neo"] <- "Non-normalized SFmc\nNeoFish"
track_tbl$File_name[track_tbl$File_name == "SFNorm-mi"] <- "Normalized SFmc\nMiFish"
track_tbl$File_name[track_tbl$File_name == "SFNorm-neo"] <- "Normalized SFmc\nNeoFish"
}




sample_levels <- c(
"Da23-mif", "Normalized SFJQmc\nMiFish",
"Da23-neo", "Normalized SFJQmc\nNeoFish",
"Da20","Non-normalized SFmc\nMiFish",
"Da19","Non-normalized SFmc\nNeoFish",
"Da22","Normalized SFmc\nMiFish",
"Da21","Normalized SFmc\nNeoFish",
"Non-normalized JQmc\nNeoFish","Non-normalized JQmc\nMiFish","Non-normalized JQmc\nTeleo",
"Normalized JQmc\nNeoFish","Normalized JQmc\nMiFish","Normalized JQmc\nTeleo",
"Positive Control\n(P.glauca)","neg-PCR2")


# Prepare counts for ploting ----

  track_tbl <- track_tbl %>%
  gather(key = "Stage",
        value = "Read Number",
        "Raw REV","Raw FWD",
        "N-cleaned", "Filtered", "Denoised FWD",
        "Denoised REV", "Merged", "Non-Chimeric") %>%
  mutate(Stage = factor(Stage, levels = c("Non-Chimeric", "Merged", "Denoised REV", "Denoised FWD", "Filtered","N-cleaned", "Raw REV","Raw FWD"))) %>%
  mutate(
    Primer = factor(Primer, levels = c("NeoFish", "MiFish", "Teleo","NeoFish/MiFish",  "NeoFish/MiFish/Teleo")),
    File_name = factor(File_name,levels = sample_levels))

  options(scipen = 22)
  
  # track_tbl %>% base::sort(track_tbl$Sample) 

# ploting ----
    
  track_plot <- track_tbl %>% 
    # filter(Run %in% c("LGC_MiniSeq_1", "LGC_MiniSeq_2")) %>% 
    # filter(Group %in% c("DNA pool")) %>% 
    ggplot(aes(y = Stage,x = `Read Number`, fill = Primer, group = Stage)) +
    geom_bar(stat="identity") +
    geom_hline(yintercept = 300000, col = 1, linetype = 2) +
    scale_fill_manual(labels = c("NeoFish", "MiFish", "Teleo", "NeoFish/MiFish","NeoFish/MiFish/Teleo"),
                      values = alpha(colour = colors5,
                                     alpha =  0.75)) +
    labs(title = "LGC eDNA 1st & 2nd runs",
         subtitle = "Read counts per library and filtering step",
         x = "Read counts",
         y = "Data filtering step")+
    facet_wrap(~File_name,ncol = 6) +
    coord_fixed(ratio = 60000) +
    theme_bw(base_size = 7) +
    theme(legend.position = "bottom") +
    theme(axis.title = ggtext::element_markdown())

track_plot 







# save plot
ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SFJQ_sample_track_plot.png",
     plot = track_plot,
     device = "png",
     width = 12,
     height = 10,
     units = "cm",
     dpi = 600)

# save plot
ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SFJQ_sample_track_plot.svg",
     plot = track_plot,
     device = "svg",
     width = 12,
     height = 10,
     units = "cm",
     dpi = 600)


ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SFJQ_sample_track_plot.pdf",
     plot = track_plot,
     device = "pdf",
     width = 20,
     height = 16,
     units = "cm",
     dpi = 600)

Reads proportions are displayed below. The experimental design intended the same read yield for all libs, between 200K a 250K reads. The deviations of this reange are probably due to dosage/pipetting errors.



Classify taxonomy

On this step the ASVs identified by the DADA2 pipeline, jointly for all libraries of each primer, are associated (or not) to any of the sequences on the Reference 12S Sequences Database. DADA2 has two strategies to identify taxa. The first, assignSpecies, identify perfect matches of the ASVs in the Reference Database. The second, assignTaxonomy, use a RDP Naive Bayesian Classifier algorithm (Wang, 2007) with kmer size 8 and 100 bootstrap replicates to associate ASVs to the Reference Database Sequences. In the latter, the taxonomy ranks classification is proportional to the sequence similarity, although this relation is not yet clear to us.

#19 - classify taxonomy exactly ----

all_sps <- dada2::assignSpecies(seqs = all_seqtab.nochim,allowMultiple = 10,
                         refFasta =  "~/prjcts/fish_eDNA/data/refs/db/LGC/jul21/dada_tax_fullDB_order_SPs_jul21.fasta",
                         tryRC=TRUE,
                         n = 20000,
                         verbose = TRUE)


#check how many ASVs were exactly identified as species

View(all_sps)

      all_csv_sp <- all_sps %>% as_tibble() %>% mutate(ASV = rownames(all_sps))
      colnames(all_csv_sp) <- c("exact Genus", "exact Species", "ASV")
#20 - classify taxonomy ----

all_taxa <- dada2::assignTaxonomy(seqs = all_seqtab.nochim,
                     refFasta =  "~/prjcts/fish_eDNA/data/refs/db/LGC/jul21/dada_tax_fullDB_order_jul21.fasta",
                           multithread=TRUE, tryRC=TRUE,taxLevels = c("Kingdom","Phylum","Class","Order","Family", "Genus", "Species","Specimen","Basin"),outputBootstraps = TRUE)


all_taxa$boot



Here the DADA2 pipeline ends.





Phyloseq

On this step the ASVs associated to taxonomic ranks by DADA2 and their respective counts by library, are combined using the Phyloseq package.


Generate sample metadata table

Here the experiment metadata is associated to each sample.

# 22 - create sample table ----

#create a sample table for each primer

# primers_n_samples$File_name

all_samdf <- unique(primers_n_samples[1:6])

samdf<- all_samdf

#rownames must me assigned in order to the next step to work

samdf <- samdf %>% as.data.frame()
rownames(samdf) <- samdf$File_name


This sample metadata table was created with the information available for the samples analyzed on this first run. This table must be customized for each experiment.




Phyloseq data interpretation

#23 - interpret dada on phyloseq ----

all_ps <- phyloseq(otu_table(all_seqtab.nochim, taxa_are_rows = FALSE),
                   sample_data(samdf),
                   tax_table(all_taxa$tax))
                   # tax_table(all_taxa))

rownames(all_seqtab.nochim)


Merge and Flex Phyloseq results

Many different graphics can be generated, together or in isolation, for all primers/libraries and taxonomic ranks.

#24 - merge ps analisys ----

#melt phyloseq object into tbl
all_ps_tbl <- psmelt(all_ps) %>% as_tibble() %>% filter(Abundance >= 1)

colnames(all_ps_tbl)[colnames(all_ps_tbl) == "OTU"] <- "ASV"

unique(all_ps_tbl$ASV)
# unique(neo_ps_tbl$ASV)
# unique(mif_ps_tbl$ASV)

all_ps_tbl$Sample %>%  unique()
all_ps_tbl$Primer %>%  unique()

#concatenate exact species table

all_ps_tbl <- left_join(by = "ASV",x=all_ps_tbl,y= all_csv_sp)

# backup table
# all_ps_tbl_bckp <- all_ps_tbl
# all_ps_tbl <- all_ps_tbl_bckp

metaBLASTEr - Identify ASVs with inhouse BLASTn

This package is currently under development, but fully functional. You will need a working NCBI-BLAST+ installed and a BLAST formated reference DB on the same linux server your Rstudio-server is running (but we are improoving it to run on IOS).

# blastn ----

install.packages('BLASTr', repos = "https://heronoh.r-universe.dev")
# Annotate all ASVs by blastN

asvs_blast <- all_ps_tbl$ASV %>% unique() %>% as.character() 




#Identify using metaBLASTr package ----
# paralela com 2 threads ----
tictoc::tic("Parallel - Furrr 2 threads")

blast_res <- BLASTr::parallel_blast(
  db_path = "/data/databases/nt_jun2023/nt",
  asvs = asvs_blast_all,
  out_file = "~/prjcts/fish_eDNA/sfjq/results/blast/blast_out_res_1.csv",
  out_RDS = "~/prjcts/fish_eDNA/sfjq/results/blast/blast_out_res_1.RDS",
  total_cores = 80,
  perc_id = 80,
  num_threads = 2,
  perc_qcov_hsp = 80,
  num_alignments = 3,
  blast_type = "blastn"
)

tictoc::toc()# 


# #Save env
   base::save.image("~/prjcts/fish_eDNA/sfjq//env-canastra_posBLAST-25jul23.RData")

   



colnames(blast_res)

# blast_res <- blast_res %>% rename("OTU" ="Sequence")
# blast_res <- blast_res %>% rename("Sequence" ="OTU")

blast_res_full <- bind_rows(blast_res) %>% 
  select(-c("OTU")) %>%
  filter(!is.na(`1_subject header`))

nrow(blast_res)
dim(blast_res)

blast_res <- blast_res %>%  filter(`1_res` == 1 ) #remover o que não deu nada            

str(blast_res)

Rename samples for plots

primers_n_samples
sample_levels

{
all_ps_tbl$File_name[all_ps_tbl$File_name == "Cassaum"] <- "Positive Control\n(P.glauca)"
all_ps_tbl$File_name[all_ps_tbl$File_name == "Da19"] <- "Non-normalized SFmc\nNeoFish B"
all_ps_tbl$File_name[all_ps_tbl$File_name == "Da20"] <- "Non-normalized SFmc\nMiFish B"
all_ps_tbl$File_name[all_ps_tbl$File_name == "Da21"] <- "Normalized SFmc\nNeoFish B"
all_ps_tbl$File_name[all_ps_tbl$File_name == "Da22"] <- "Normalized SFmc\nMiFish B"
all_ps_tbl$File_name[all_ps_tbl$File_name == "Da23-mif"] <- "SFJQ-mif B"
all_ps_tbl$File_name[all_ps_tbl$File_name == "Da23-neo"] <- "SFJQ-neo B"
all_ps_tbl$File_name[all_ps_tbl$File_name == "neg-PCR2"] <-"neg-PCR2"
all_ps_tbl$File_name[all_ps_tbl$File_name == "pJequei-N-norm-M"] <- "Non-normalized JQmc\nMiFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "pJequei-N-norm-N"] <- "Non-normalized JQmc\nNeoFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "pJequei-N-norm-T"] <- "Non-normalized JQmc\nTeleo"
all_ps_tbl$File_name[all_ps_tbl$File_name == "pJequei-norm-M"] <- "Normalized JQmc\nMiFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "pJequei-norm-N"] <- "Normalized JQmc\nNeoFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "pJequei-norm-T"] <- "Normalized JQmc\nTeleo"
all_ps_tbl$File_name[all_ps_tbl$File_name == "SFJQ-mif"] <- "Normalized SFJQmc\nMiFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "SFJQ-neo"] <- "Normalized SFJQmc\nNeoFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "SFnNorm-mi"] <- "Non-normalized SFmc\nMiFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "SFnNorm-neo"] <- "Non-normalized SFmc\nNeoFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "SFNorm-mi"] <- "Normalized SFmc\nMiFish"
all_ps_tbl$File_name[all_ps_tbl$File_name == "SFNorm-neo"] <- "Normalized SFmc\nNeoFish"
}

{
all_ps_tbl$Sample[all_ps_tbl$Sample == "Cassaum"] <- "Positive Control\n(P.glauca)"
all_ps_tbl$Sample[all_ps_tbl$Sample == "Da19"] <- "Non-normalized SFmc\nNeoFish B"
all_ps_tbl$Sample[all_ps_tbl$Sample == "Da20"] <- "Non-normalized SFmc\nMiFish B"
all_ps_tbl$Sample[all_ps_tbl$Sample == "Da21"] <- "Normalized SFmc\nNeoFish B"
all_ps_tbl$Sample[all_ps_tbl$Sample == "Da22"] <- "Normalized SFmc\nMiFish B"
all_ps_tbl$Sample[all_ps_tbl$Sample == "Da23-mif"] <- "Normalized SFJQmc\nMiFish B"
all_ps_tbl$Sample[all_ps_tbl$Sample == "Da23-neo"] <- "Normalized SFJQmc\nNeoFish B"
all_ps_tbl$Sample[all_ps_tbl$Sample == "neg-PCR2"] <- "neg-PCR2"
all_ps_tbl$Sample[all_ps_tbl$Sample == "pJequei-N-norm-M"] <- "Non-normalized JQmc\nMiFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "pJequei-N-norm-N"] <- "Non-normalized JQmc\nNeoFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "pJequei-N-norm-T"] <- "Non-normalized JQmc\nTeleo"
all_ps_tbl$Sample[all_ps_tbl$Sample == "pJequei-norm-M"] <- "Normalized JQmc\nMiFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "pJequei-norm-N"] <- "Normalized JQmc\nNeoFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "pJequei-norm-T"] <- "Normalized JQmc\nTeleo"
all_ps_tbl$Sample[all_ps_tbl$Sample == "SFJQ-mif"] <- "Normalized SFJQmc\nMiFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "SFJQ-neo"] <- "Normalized SFJQmc\nNeoFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "SFnNorm-mi"] <- "Non-normalized SFmc\nMiFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "SFnNorm-neo"] <- "Non-normalized SFmc\nNeoFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "SFNorm-mi"] <- "Normalized SFmc\nMiFish"
all_ps_tbl$Sample[all_ps_tbl$Sample == "SFNorm-neo"] <- "Normalized SFmc\nNeoFish"
}




all_ps_tbl$Group %>%  unique() %>% base::sort()


# all_ps_tbl$Group <- all_ps_tbl$Group %>% unfactor()
{
all_ps_tbl$Group[all_ps_tbl$Group %in% c("JqNnorm")] <- "Non-normalized JQmc"
all_ps_tbl$Group[all_ps_tbl$Group %in% c("JqNorm")] <- "Normalized JQmc"
all_ps_tbl$Group[all_ps_tbl$Group %in% c("SFnNorm")] <- "Non-normalized SFmc"
all_ps_tbl$Group[all_ps_tbl$Group %in% c("SFNorm")] <- "Normalized SFmc"
all_ps_tbl$Group[all_ps_tbl$Group %in% c("SFJQ")] <- "Normalized SFJQmc"
all_ps_tbl$Group[all_ps_tbl$Group %in% c("Positive control")] <- "Positive control\n(P. glauca)"
}
all_ps_tbl$Group %>% unique()

all_ps_tbl$Group <- all_ps_tbl$Group %>%  factor(levels = c("Non-normalized JQmc",
                                                            "Normalized JQmc",
                                                            "Non-normalized SFmc",
                                                            "Normalized SFmc",
                                                            "Normalized SFJQmc",
                                                            "Positive control\n(P. glauca)"))


sample_levels <- c(
"Normalized SFJQmc\nMiFish B", "Normalized SFJQmc\nMiFish",
"Normalized SFJQmc\nNeoFish B", "Normalized SFJQmc\nNeoFish",

"Normalized SFmc\nMiFish B","Normalized SFmc\nMiFish",
"Non-normalized SFmc\nMiFish B","Non-normalized SFmc\nMiFish",
"Normalized SFmc\nNeoFish B","Normalized SFmc\nNeoFish",
"Non-normalized SFmc\nNeoFish B","Non-normalized SFmc\nNeoFish",

"Non-normalized JQmc\nMiFish","Normalized JQmc\nMiFish",
"Non-normalized JQmc\nNeoFish","Normalized JQmc\nNeoFish",
"Non-normalized JQmc\nTeleo","Normalized JQmc\nTeleo",

"Positive Control\n(P.glauca)","neg-PCR2")

# all_ps_tbl_blast$Sample[all_ps_tbl_blast$Sample %in% c("pool não-normalizado\nMiFish")] 

all_ps_tbl$Sample <- all_ps_tbl$Sample %>%  factor(levels = sample_levels)


class(asvs_blast)

  
all_ps_tbl_blast <- left_join(x = all_ps_tbl,y = blast_res,by = "ASV")

colnames(all_ps_tbl_blast)

#all_ps_tbl_blast_bckp <- all_ps_tbl_blast
#all_ps_tbl_blast <- all_ps_tbl_blast_bckp

ASVs seqs

#25 - recover all ASVs sequences to prepare fasta ----


#all ----
# giving our seq headers more manageable names (ASV_1, ASV_2...)
# all_asv_seqs <- tibble("ASV" = colnames(seqtab.nochim))
all_asv_seqs <- tibble("ASV" = asvs_blast)

all_asv_seqs <- all_asv_seqs %>% 
  mutate("ASV length" = nchar(ASV),
         "ASV header" = as.character(""))

all_asv_seqs <- all_asv_seqs[base::order(all_asv_seqs$`ASV length`),]
  for (i in 1:nrow(all_asv_seqs)) {

    all_asv_seqs$`ASV header`[i] <- paste0(">ASV_", i, "_", all_asv_seqs$`ASV length`[i], "bp")

  }


#combine ASV headers and all_ps_tbl
all_ps_tbl_blast <- dplyr::left_join(x = all_ps_tbl_blast,    
                               y = all_asv_seqs,
                               by = "ASV" )


# making and writing out a fasta of our final ASV seqs with tax
for (asv in 1:nrow(all_asv_seqs)) {
  
  tax <- all_ps_tbl_blast %>% 
    filter(ASV == all_asv_seqs$ASV[asv]) %>% 
    select("Kingdom", "Phylum", "Class", "Order", "Family", "Genus", "Species", "Specimen") %>% 
    unique() %>% 
    paste0(collapse = "|")
  
  all_asv_seqs$`ASV header`[asv] <- paste0(all_asv_seqs$`ASV header`[asv],"_",tax)
  
  # if (condition) {
  # fazer algum teste pra ver ser ta certo
  # }
}

#write fasta file with ASVs and Taxonomy
all_asv_fasta <- c(rbind(all_asv_seqs$`ASV header`, all_asv_seqs$ASV))

write(all_asv_fasta, "~/prjcts/fish_eDNA/sfjq/results/sfjq_all_ASVs_all_primers.fasta")

SWARM - ASVs to OTUs

# #swarm

asvs_abd <- all_ps_tbl_blast %>%
  group_by(`ASV`,`ASV header`) %>%
  mutate("ASV total abundance" = sum(Abundance)) %>%
  select(c(`ASV`,`ASV header`,`ASV total abundance`)) %>%
  unique() %>%
  mutate(`ASV header` = paste0(`ASV header`,"_",`ASV total abundance`))


asvs_abd$ASV %>% unique()
asvs_abd$`ASV header` %>% unique()


#write fasta file with ASVs and  abundance
# all_asv_fasta_abd <- c(rbind(asvs_abd$`ASV header primer`, asvs_abd$`ASV`))
all_asv_fasta_abd <- c(rbind(asvs_abd$`ASV header`, asvs_abd$`ASV`))

# write(all_asv_fasta_abd, "~/prjcts/fish_eDNA/sfjq/results/sfjq_ASVs_abd_primer.fasta")
write(all_asv_fasta_abd, paste0(results_path,"/sfjq_ASVs_abd.fasta"))

# ~/prjcts/fish_eDNA/sfjq/swarm$ swarm -t 50 ~/prjcts/fish_eDNA/sfjq/results/sfjq_ASVs_abd.fasta -s sfjq_swarm.stats -o sfjq_swarm.out -w sfjq_representative_OTUs.fasta -i sfjq_swarm.structure -f


swarm_clust <- readr::read_lines("~/prjcts/fish_eDNA/sfjq/swarm/sfjq_swarm.out")





asvs_abd <- asvs_abd %>% mutate("OTU"= 0)



for (asv in 1:nrow(asvs_abd)){
  for (line in 1:length(swarm_clust)) {
    if (str_detect(string =  swarm_clust[line],
                   pattern = str_remove(asvs_abd$`ASV header`[asv],
                                        pattern = ">"))) {
  asvs_abd$OTU[asv] <- line
    }
    }
}



all_ps_tbl_blast <- left_join(x = all_ps_tbl_blast,y = asvs_abd[,c(1,3,4)],by="ASV" ) 

# all_ps_tbl_blast %>% select(`final ID`,OTU) %>% View() 
# all_ps_tbl_blast %>% select(`final ID`,OTU) %>% select(OTU) %>% unique() 
# all_ps_tbl_blast %>% select(ASV,`final ID`,OTU) %>% select(ASV) %>% unique() 


all_ps_tbl_blast$OTU %>% unique()
all_ps_tbl_blast$Group %>% unique()

Calculate sample abundances —-

#add ASV legth to table
# all_ps_tbl_blast_bckp2 <- all_ps_tbl_blast
# all_ps_tbl_blast <- all_ps_tbl_blast_bckp2


all_ps_tbl_blast <- all_ps_tbl_blast %>% 
  mutate("Relative abundance to all samples" = 0,
         "Relative abundance on sample" = 0,
         "Sample total abundance" = 0)

abd_total <- sum(all_ps_tbl_blast$Abundance)




all_ps_tbl_blast <- all_ps_tbl_blast %>%
  group_by(Sample) %>%
  mutate("Sample total abundance" = sum(Abundance),
         "Relative abundance to all samples" = Abundance/abd_total,
         "Relative abundance on sample" = Abundance/`Sample total abundance`) %>%
  ungroup()

Set final identification from all possibilities

all_ps_tbl_blast <- all_ps_tbl_blast %>% 
  mutate(`exact GenSp` = paste(`exact Genus`,`exact Species`,sep=" "))



all_ps_tbl_blast <- all_ps_tbl_blast %>% 
  mutate("final ID" = if_else((`exact Species` %in% c(NA,"NA", "NA NA")),
                              if_else((Species %in% c(NA,"NA")),
                                      if_else(Genus %in% c(NA,"NA"),
                                              substr(as.character(`1_subject header`),1,30),
                                              Genus),
                                      Species),
                              as.character(`exact GenSp`)))

#Group/correct species for ploting

# all_ps_tbl_blast_bckp3 <- all_ps_tbl_blast

#Species detected
all_ps_tbl_blast$`final ID` %>% unique() %>% base::sort()
{
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Astyanax aff_fasciatus","Astyanax cf_fasciatus"))] <- "Astyanax fasciatus"
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Astyanax cf_lacustris"))] <- "Astyanax lacustris"
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Characidium sp"))] <- "Characidium"
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Hypostomus sp"))] <- "Hypostomus"
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Hoplias malabaricus/sp"))] <- "Hoplias malabaricus"
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Rhamdia aff_quelen"))] <- "Rhamdia quelen"
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Coptodon zillii KAUM:I:90126 m"))] <- "Coptodon zillii"
all_ps_tbl_blast$`final ID`[(all_ps_tbl_blast$`final ID` %in% c("Trachelyopterus cf_galeatus/galeatus"))] <- "Trachelyopterus galeatus"
}

Identify primers expected ASV legth range

# create ranges column
all_ps_tbl_blast <- all_ps_tbl_blast %>%
   mutate("Expected length" = "FALSE")


# fill ranges column with expected primer insert ranges

for (asv in 1:nrow(all_ps_tbl_blast)) {
   if (all_ps_tbl_blast$Primer[asv] == "NeoFish") {
      if (all_ps_tbl_blast$`ASV length`[asv] >= 185 && all_ps_tbl_blast$`ASV length`[asv] <= 200) {
         all_ps_tbl_blast$`Expected length`[asv] <- "in range"
      }else{
         all_ps_tbl_blast$`Expected length`[asv] <- "out of range"
         }

   }
   if (all_ps_tbl_blast$Primer[asv] == "MiFish") {
      if (all_ps_tbl_blast$`ASV length`[asv] >= 165 && all_ps_tbl_blast$`ASV length`[asv] <= 180) {
         all_ps_tbl_blast$`Expected length`[asv] <- "in range"
      }else{
         all_ps_tbl_blast$`Expected length`[asv] <- "out of range"
      }

   }
  if (all_ps_tbl_blast$Primer[asv] == "Teleo") {
      if (all_ps_tbl_blast$`ASV length`[asv] >= 60 && all_ps_tbl_blast$`ASV length`[asv] <= 75) {
         all_ps_tbl_blast$`Expected length`[asv] <- "in range"
      }else{
         all_ps_tbl_blast$`Expected length`[asv] <- "out of range"
      }

   }
  if (all_ps_tbl_blast$Primer[asv] == "NeoFish/MiFish") {
      if (all_ps_tbl_blast$`ASV length`[asv] >= 165 && all_ps_tbl_blast$`ASV length`[asv] <= 200) {
         all_ps_tbl_blast$`Expected length`[asv] <- "in range"
      }else{
         all_ps_tbl_blast$`Expected length`[asv] <- "out of range"
      }

   }
  if (all_ps_tbl_blast$Primer[asv] == "NeoFish/MiFish/Teleo") {
      if (all_ps_tbl_blast$`ASV length`[asv] %in% c(60:75,165:180,185:200)) {
         all_ps_tbl_blast$`Expected length`[asv] <- "in range"
      }else{
         all_ps_tbl_blast$`Expected length`[asv] <- "out of range"
      }

   }

}


#factorize comlumn
all_ps_tbl_blast$`Expected length` <- as.factor(all_ps_tbl_blast$`Expected length`)

#Reorder table

paste0(colnames(all_ps_tbl_blast),"\n") %>%  cat()


# all_ps_tbl_blast_bckp4 <- all_ps_tbl_blast
# all_ps_tbl_blast <- all_ps_tbl_blast_bckp4


all_ps_tbl_blast <- 
  all_ps_tbl_blast %>% 
  select(c("Sample","Group","Type","Primer","File_name","Library","Run",
           "final ID",
           "Abundance",
           "Relative abundance to all samples",
           "Relative abundance on sample",
           "Sample total abundance",
           "Kingdom","Phylum","Class","Order","Family",
           "Genus","Species","Specimen","Basin",
           "exact Genus","exact Species",
           "exact GenSp",
           "1_subject header","1_subject",
           "1_indentity","1_length",
           # "1_mismatches","1_gaps",
           # "1_query start","1_query end","1_subject start",
           # "1_subject end","1_e-value","1_bitscore",
           "2_subject header","2_subject",
           "2_indentity","2_length",
           # "2_mismatches","2_gaps",
           # "2_query start","2_query end","2_subject start",
           # "2_subject end","2_e-value","2_bitscore",
           "3_subject header","3_subject",
           "3_indentity","3_length",
           # "3_mismatches","3_gaps",
           # "3_query start","3_query end","3_subject start",
           # "3_subject end","3_e-value","3_bitscore",
           "ASV","ASV length","ASV header","Expected length","OTU"
           ))

# paste0(colnames(all_ps_tbl_blast),"\n") %>%  cat()
names(all_ps_tbl_blast)[which(names(all_ps_tbl_blast)=="ASV")] <- "ASV (Sequence)"
names(all_ps_tbl_blast)[which(names(all_ps_tbl_blast)== "ASV length")] <- "ASV size (pb)"

###save complete table

#order by abundance

smp_abd_ID <- all_ps_tbl_blast[rev(base::order(all_ps_tbl_blast$Abundance)),] %>% 
  filter(`Abundance` > 0) 

dim(smp_abd_ID)

writexl::write_xlsx(x = smp_abd_ID,
                    path = "~/prjcts/fish_eDNA/sfjq/results/sfjq_all_analysis_info_06-03-22.xlsx",
                    col_names = TRUE,format_headers = TRUE)





ASVs_per_sample <- all_ps_tbl_blast %>% 
  # filter(Run %in% c("LGC_MiniSeq_1", "LGC_MiniSeq_2")) %>%
  filter(!`final ID` %in% c(NA,"NA")) %>% 
  mutate("Sample" = factor(Sample,levels = sample_levels)) %>%
  group_by(Sample) %>%
   summarize("Library" = unique(`Library`),
     "Group" = unique(Group),
             "Primer" = unique(Primer),
             "Total ASV" = length(unique(`ASV (Sequence)`[Abundance != 0])),
             "ASVs out of range" = length(unique(`ASV (Sequence)`[Abundance != 0 & `Expected length` == "out of range"])),
             "ASVs in range" = length(unique(`ASV (Sequence)`[Abundance != 0 & `Expected length` == "in range"]))
             ,
             "Identified Species" = length(unique(`final ID`[Abundance != 0 & `Expected length` == "in range"]))
             ) 


writexl::write_xlsx(x = ASVs_per_sample,
                    path = "~/prjcts/fish_eDNA/sfjq/results/sfjq_ASVs_per_sample_06-07-21.xlsx",
                    col_names = TRUE,format_headers = TRUE)

curing: manual checking of the species assignment

all_ps_tbl_bl_cur <- smp_abd_ID



all_ps_tbl_bl_cur <- all_ps_tbl_bl_cur %>% 
  mutate("revised final ID" = `final ID`)


all_ps_tbl_bl_cur$`revised final ID` %>% unique() %>%  sort()




#correct misidentifications one by one
{
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("Prochilodus")] <- "Prochilodus argenteus/hartii"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("Prochilodus argenteus")] <- "Prochilodus argenteus/hartii"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("Pimelodus")] <- "Pimelodus pohli"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("Astyanax")] <- "Astyanax lacustris"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("Hypostomus")] <- "Hypostomus alatus"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("NA elegans/gilbert")] <- "Cyphocharax gilbert"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("NA lepidura/xenodon")] <- "Curimatella lepidura"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("Roeboides xenodon")] <- "Curimatella lepidura"
all_ps_tbl_bl_cur$`revised final ID`[all_ps_tbl_bl_cur$`revised final ID` %in% c("Curimatella lepidura")] <- "Roeboides xenodon"





all_ps_tbl_bl_cur$`revised final ID`[(all_ps_tbl_bl_cur$`revised final ID` %in% c("Hoplias brasiliensis/intermedius")) & 
                                       all_ps_tbl_bl_cur$Group %in% c("Non-normalized SFmc","Normalized SFmc")] <- "Hoplias intermedius"


all_ps_tbl_bl_cur$`revised final ID`[(all_ps_tbl_bl_cur$`revised final ID` %in% c("Hoplias brasiliensis/intermedius")) & 
                                       all_ps_tbl_bl_cur$Group %in% c("Non-normalized JQmc","Normalized JQmc")] <- "Hoplias brasiliensis"



all_ps_tbl_bl_cur$`revised final ID`[(all_ps_tbl_bl_cur$`revised final ID` %in% c("Hoplias intermedius")) & 
                                       all_ps_tbl_bl_cur$Group %in% c("Normalized SFJQmc")] <- "Hoplias brasiliensis/intermedius"




all_ps_tbl_bl_cur$`revised final ID`[(all_ps_tbl_bl_cur$`revised final ID` %in% c("Hoplias intermedius")) & 
                                       all_ps_tbl_bl_cur$Group %in% c("Non-normalized JQmc","Normalized JQmc")] <- "Hoplias brasiliensis"

}

Identify expected species

As this was a controlled experiment, we must identify the species that were expected and those who were not.

#duplicate final ID so we can identify partially identified species

# all_ps_tbl_blast_bckp5 <- all_ps_tbl_blast 
# all_ps_tbl_blast <- all_ps_tbl_blast_bckp5
# 
#                           all_ps_tbl_blast <- all_ps_tbl_bl_cur %>%
#                             mutate(`revised final ID` = `final ID`)



# expctd_sps_tbl <- read.csv(file = "~/prjcts/fish_eDNA/sfjq/data/sfjq_species.csv",
# expctd_sps_tbl <- read.csv(file = "~/prjcts/fish_eDNA/sfjq/data/sfjq_species_06mar22.csv",
# expctd_sps_tbl <- read.csv(file = "~/prjcts/fish_eDNA/sfjq/data/sfjq_species_10mar22.csv",
expctd_sps_tbl <- read.csv(file = "~/prjcts/fish_eDNA/sfjq/data/sfjq_species_02jun22.csv",
                           header = TRUE, check.names = FALSE) %>% as_tibble() 

#mudei o T. chalceus de 0.0073 para 0.0299 no pool SF

colnames(expctd_sps_tbl)[colnames(expctd_sps_tbl) == "Species"] <- "revised final ID"

Proportions table

As this was a controlled experiment, we must identify the species that were expected and those who were not.

# tabelas de proporções ----
# JQmc ----

# criando a tabela de proporções do JQ


# if used left_join, p hartii wont show up
all_ps_tbl_jq <- full_join(
  all_ps_tbl_bl_cur[all_ps_tbl_bl_cur$Sample %in% c(
  "Normalized JQmc\nNeoFish", "Non-normalized JQmc\nNeoFish",
  "Normalized JQmc\nMiFish", "Non-normalized JQmc\nMiFish",
  "Normalized JQmc\nTeleo", "Non-normalized JQmc\nTeleo"),],
  expctd_sps_tbl[expctd_sps_tbl$Pool=="JQ",c(2:9)],
          by = "revised final ID") 

# all_ps_tbl_jq %>% select(`revised final ID`,Abundance,`Relative abundance on sample`, 64:73) %>% View()

all_ps_tbl_jq$`Expected Species` <- "not expected"

all_ps_tbl_jq$`revised final ID` %>% unique()

all_ps_tbl_jq <- all_ps_tbl_jq %>% mutate( 
  # `Expected Species`=if_else((!is.na(`Full name`) & (.$`revised final ID` %in% expected_sps)),"expected","not expected")
  `Expected Species`=if_else((!is.na(`Full name`)),"expected","not expected")
  )

colnames(all_ps_tbl_jq)


jq_proportions <- all_ps_tbl_jq %>%
  select(c(1:24,37:50)) %>%
  pivot_longer(cols = c("Percentage on respective Norm pool", "Percentage on respective Non-norm pool" ),
               names_to = "Pool",values_to = "Proportion") %>% 
  # mutate(Proportion = Proportion*100) %>% 
  mutate(Sample = factor(Sample,levels = c(
    "Normalized JQmc\nNeoFish", "Non-normalized JQmc\nNeoFish",
    "Normalized JQmc\nMiFish", "Non-normalized JQmc\nMiFish",
    "Normalized JQmc\nTeleo", "Non-normalized JQmc\nTeleo"
    # ,
    # "Non-normalized SFmc\nMiFish","Non-normalized SFmc\nNeoFish",
    # "Normalized SFmc\nMiFish","Normalized SFmc\nNeoFish",
    # "Normalized SFJQmc\nMiFish", "Normalized SFJQmc\nNeoFish"
    ))) %>%
  filter((Sample %in% c("Non-normalized JQmc\nNeoFish", "Non-normalized JQmc\nMiFish", "Non-normalized JQmc\nTeleo"
                        # , "Non-normalized SFmc\nMiFish","Non-normalized SFmc\nNeoFish"
                        ) & Pool %in% c("Percentage on respective Non-norm pool"
                                        ) )|(Sample %in% c("Normalized JQmc\nNeoFish", "Normalized JQmc\nMiFish", "Normalized JQmc\nTeleo"
                                                           # , "Normalized SFmc\nMiFish", "Normalized SFmc\nNeoFish", "Normalized SFJQmc\nMiFish", "Normalized SFJQmc\nNeoFish"
                                                           ) & Pool %in% c("Percentage on respective Norm pool") )) %>% 
  group_by(Sample,`revised final ID`) %>%
  summarize(Proportion = unique(Proportion),
            `Relative abundance on sample` = sum(`Relative abundance on sample`),
            Sample = unique(Sample),
            # `revised final ID` = unique(`revised final ID`),
            `revised final ID` = unique(`revised final ID`),
            Primer = unique(Primer),
            `Expected Species` = unique(`Expected Species`),
            Pool = unique(Pool),
            `Num ASVs` = length(`ASV (Sequence)`),
            `Num OTUs` = length(unique(OTU))) %>% 
  ungroup()


#SFmc ----

# criando a tabela de proporções do 

all_ps_tbl_sf <- full_join(
  all_ps_tbl_bl_cur[all_ps_tbl_bl_cur$Sample %in% c(
  "Normalized SFmc\nNeoFish", "Non-normalized SFmc\nNeoFish",
  "Normalized SFmc\nMiFish", "Non-normalized SFmc\nMiFish"),],
  expctd_sps_tbl[expctd_sps_tbl$Pool=="SF",c(2:9)],
          by = "revised final ID")

# all_ps_tbl_jq %>% select(`revised final ID`,Abundance,`Relative abundance on sample`, 64:73) %>% View()

all_ps_tbl_sf$`Expected Species` <- "not expected"

all_ps_tbl_sf$`revised final ID` %>% unique()

all_ps_tbl_sf <- all_ps_tbl_sf %>% mutate( 
  # `Expected Species`=if_else((!is.na(`Full name`) & (.$`revised final ID` %in% expected_sps)),"expected","not expected")
  `Expected Species`=if_else((!is.na(`Full name`)),"expected","not expected")
  )

colnames(all_ps_tbl_sf)


sf_proportions <- all_ps_tbl_sf %>%
  # select(c(1:15,63:68,73:74)) %>% 
  select(c(1:24,37:50)) %>%
  pivot_longer(cols = c("Percentage on respective Norm pool", "Percentage on respective Non-norm pool" ),
               names_to = "Pool",values_to = "Proportion") %>% 
  # mutate(Proportion = Proportion*100) %>% 
  mutate(Sample = factor(Sample,levels = c(
    "Normalized SFmc\nNeoFish", "Non-normalized SFmc\nNeoFish",
    "Normalized SFmc\nMiFish", "Non-normalized SFmc\nMiFish"
    # ,
    # "Non-normalized SFmc\nMiFish","Non-normalized SFmc\nNeoFish",
    # "Normalized SFmc\nMiFish","Normalized SFmc\nNeoFish",
    # "Normalized SFJQmc\nMiFish", "Normalized SFJQmc\nNeoFish"
    ))) %>%
  filter((Sample %in% c("Non-normalized SFmc\nNeoFish", "Non-normalized SFmc\nMiFish"
                        # , "Non-normalized SFmc\nMiFish","Non-normalized SFmc\nNeoFish"
                        ) & Pool %in% c("Percentage on respective Non-norm pool"
                                        ) )|(Sample %in% c("Normalized SFmc\nNeoFish", "Normalized SFmc\nMiFish"
                                                           # , "Normalized SFmc\nMiFish", "Normalized SFmc\nNeoFish", "Normalized SFJQmc\nMiFish", "Normalized SFJQmc\nNeoFish"
                                                           ) & Pool %in% c("Percentage on respective Norm pool") )) %>% 
  group_by(Sample,`revised final ID`) %>% 
  summarize(Proportion = unique(Proportion),
            `Relative abundance on sample` = sum(`Relative abundance on sample`),
            Sample = unique(Sample),
            # `revised final ID` = unique(`revised final ID`),
            `revised final ID` = unique(`revised final ID`),
            Primer = unique(Primer),
            `Expected Species` = unique(`Expected Species`),
            Pool = unique(Pool),
            `Num ASVs` = length(`ASV (Sequence)`),
            `Num OTUs` = length(unique(OTU))) %>% 
  ungroup()


#SFJQmc ----
# View(expctd_sps_tbl[expctd_sps_tbl$Pool=="SFJQ",c(2:9)])
# criando a tabela de proporções do SFJQ

all_ps_tbl_sfjq <- full_join(
  all_ps_tbl_bl_cur[all_ps_tbl_bl_cur$Sample %in% c(
  "Normalized SFJQmc\nNeoFish", "Normalized SFJQmc\nMiFish"),],
  expctd_sps_tbl[expctd_sps_tbl$Pool=="SFJQ",c(2:9)],
          by = "revised final ID")


# all_ps_tbl_jq %>% select(`revised final ID`,Abundance,`Relative abundance on sample`, 64:73) %>% View()

all_ps_tbl_sfjq$`Expected Species` <- "not expected"

all_ps_tbl_sfjq$`revised final ID` %>% unique()

all_ps_tbl_sfjq <- all_ps_tbl_sfjq %>% mutate( 
  # `Expected Species`=if_else((!is.na(`Full name`) & (.$`revised final ID` %in% expected_sps)),"expected","not expected")
  `Expected Species`=if_else((!is.na(`Full name`)),"expected","not expected")
  )

colnames(all_ps_tbl_sfjq)


sfjq_proportions <- all_ps_tbl_sfjq %>%
  select(c(1:24,37:50)) %>%
  # select(c(1:15,63:68,73:74)) %>% 
  pivot_longer(cols = c("Percentage on respective Norm pool", "Percentage on respective Non-norm pool" ),
               names_to = "Pool",values_to = "Proportion") %>% 
  # mutate(Proportion = Proportion*100) %>% 
  mutate(Sample = factor(Sample,levels = c(
    "Normalized SFJQmc\nNeoFish", "Normalized SFJQmc\nMiFish"
    ))) %>%
  filter((Sample %in% c("Normalized SFJQmc\nNeoFish", "Normalized SFJQmc\nMiFish"
                        ) & Pool %in% c("Percentage on respective Norm pool"
                                        ) )) %>% 
  group_by(Sample,`revised final ID`) %>% 
  summarize(Proportion = unique(Proportion),
            `Relative abundance on sample` = sum(`Relative abundance on sample`),
            Sample = unique(Sample),
            # `revised final ID` = unique(`revised final ID`),
            `revised final ID` = unique(`revised final ID`),
            Primer = unique(Primer),
            `Expected Species` = unique(`Expected Species`),
            Pool = unique(Pool),
            `Num ASVs` = length(`ASV (Sequence)`),
            `Num OTUs` = length(unique(OTU))) %>% 
  ungroup()



#this table will be used
all_ps_tbl_sfjq_full <-  dplyr::bind_rows(all_ps_tbl_sfjq,all_ps_tbl_sf,all_ps_tbl_jq)



all_ps_tbl_sfjq_full %>% colnames() %>% unique() %>% paste0(collapse = '",\n"') %>% cat()

Pearson correlations between DNA input and sequence yield

#correlação entre o DNA input e reads ABD -----

# JQmc
{
jq_df_neo_norm <- jq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Normalized JQmc\nNeoFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

jq_df_mif_norm <- jq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Normalized JQmc\nMiFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

jq_df_tel_norm <- jq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Normalized JQmc\nTeleo")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

jq_df_neo_skew <- jq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Non-normalized JQmc\nNeoFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

jq_df_mif_skew <- jq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Non-normalized JQmc\nMiFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

jq_df_tel_skew <- jq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Non-normalized JQmc\nTeleo")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

#SF 
sf_df_neo_norm <- sf_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Normalized SFmc\nNeoFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

sf_df_mif_norm <- sf_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Normalized SFmc\nMiFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

sf_df_neo_skew <- sf_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Non-normalized SFmc\nNeoFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

sf_df_mif_skew <- sf_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Non-normalized SFmc\nMiFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

# SFJQ
sfjq_df_neo_norm <- sfjq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Normalized SFJQmc\nNeoFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()

sfjq_df_mif_norm <- sfjq_proportions %>% 
  ungroup() %>% 
  filter(Sample %in% c("Normalized SFJQmc\nMiFish")) %>% 
  select(c(2,3,4)) %>% as.data.frame() %>% na.exclude()
}




#correlações 
#JQmc
cor.test(x = jq_df_neo_norm$Proportion ,
         y = jq_df_neo_norm$`Relative abundance on sample` ,
         method = "pearson")


cor.test(x = jq_df_neo_skew$Proportion ,
         y = jq_df_neo_skew$`Relative abundance on sample` ,
         method = "pearson")



cor.test(x = jq_df_mif_norm$Proportion ,
         y = jq_df_mif_norm$`Relative abundance on sample` ,
         method = "pearson")


cor.test(x = jq_df_mif_skew$Proportion ,
         y = jq_df_mif_skew$`Relative abundance on sample` ,
         method = "pearson")


cor.test(x = jq_df_tel_norm$Proportion ,
         y = jq_df_tel_norm$`Relative abundance on sample` ,
         method = "pearson")


cor.test(x = jq_df_tel_skew$Proportion ,
         y = jq_df_tel_skew$`Relative abundance on sample` ,
         method = "pearson")

#SF
cor.test(x = sf_df_neo_norm$Proportion ,
         y = sf_df_neo_norm$`Relative abundance on sample` ,
         method = "pearson",)


cor.test(x = sf_df_neo_skew$Proportion ,
         y = sf_df_neo_skew$`Relative abundance on sample` ,
         method = "pearson")



cor.test(x = sf_df_mif_norm$Proportion ,
         y = sf_df_mif_norm$`Relative abundance on sample` ,
         method = "pearson")


cor.test(x = sf_df_mif_skew$Proportion ,
         y = sf_df_mif_skew$`Relative abundance on sample` ,
         method = "pearson")

Richness analysis on Vegan

library(vegan)
# data(dune)
# decorana(dune)

# class(dune)
#1- prepare data for entry in vegan ----

all_ps_blst_vegan <- all_ps_tbl_bl_cur %>% 
  filter(`Expected length` %in% c("in range")) %>% 
  mutate("Normalization" = str_split(.$Group,pattern = " ",2,simplify = TRUE)[,1],
         "Mock Community" = str_split(.$Group,pattern = " ",2,simplify = TRUE)[,2]) %>% 
  filter(!(Sample %in% c("Positive Control\n(P.glauca)","neg-PCR2"))) %>%   #remove control samples
  select(c(Sample,Group,Normalization,`Mock Community`,Type,Primer,File_name,Library,Run,`final ID`,`Relative abundance on sample`)) %>% 
  group_by(Sample,`final ID`,Group,Type,Primer,File_name,Library,Run,Normalization,`Mock Community`) %>% 
  summarise(`Relative abundance on sample` = sum(`Relative abundance on sample`)) %>% 
  pivot_wider(c(Sample,Group,Type,Primer,File_name,Library,Run,Normalization,`Mock Community`),names_from = `final ID` ,values_from = `Relative abundance on sample`) %>% 
  mutate_if(is.numeric, ~replace(., is.na(.), 0)) %>% 
  # mutate(Library = unfactor(Library)) %>% 
  mutate("Sample number" = 0) %>% 
  ungroup()  %>% 
  select(`Sample number`, 1:(ncol(.)-1)) %>% 
  mutate(Normalization = factor(Normalization))

#2- associate sample numbers to sample names ----
for (sample in 1:nrow(all_ps_blst_vegan)) {
  all_ps_blst_vegan$`Sample number`[sample] <- sample 
  
}

#tirando as amostras da ecomol pra facilitar

all_ps_blst_vegan <- all_ps_blst_vegan[all_ps_blst_vegan$Run %in% c("LGC_MiniSeq_1", "LGC_MiniSeq_2"),] 




colnames(all_ps_blst_vegan)
hist(colSums(all_ps_blst_vegan[,-c(1:10)]))
hist(rowSums(all_ps_blst_vegan[,-c(1:10)]))
all_ps_blst_vegan[,-c(1:10)]

all_ps_blst_vegan %>% select(Sample, `Sample number`)
# all_ps_blst_vegan %>% select(`Sample number`, 1:(ncol(.)-1))

#3- create data.frame of species counts: rownames are Sample numbers ----

all_ps_blst_vegan_df <- all_ps_blst_vegan %>% 
  # filter(Run %in% c("LGC_MiniSeq_1", "LGC_MiniSeq_2")) %>% 
  select(-c("Sample", "Group", "Type", "Primer", "File_name", "Library", "Run","Normalization","Mock Community")) %>% 
  select(base::sort(colnames(.))) %>% 
  as.data.frame() 

#4- name rows as Sample numbers and remove column ----
row.names(all_ps_blst_vegan_df) <- all_ps_blst_vegan_df$`Sample number`
all_ps_blst_vegan_df <- all_ps_blst_vegan_df %>% 
  select(-c(`Sample number`))

library(vegan)
#5- 

all_ps_ord <- decorana(veg = all_ps_blst_vegan_df)

all_ps_ord %>% summary()

all_ps_ord %>% str()

all_ps_ord$cproj


plot(all_ps_ord)
plot(all_ps_ord,type = "p")
plot(all_ps_ord,type = "c") 

points(all_ps_ord, display = "sites", cex = 0.8, pch=21, col="red", bg="yellow")
text(all_ps_ord, display = "sites", cex=0.7, col="blue")
text(all_ps_ord, display = "spec", cex=0.7, col="blue")



#6- NMDS analisys ----



# library(vegan)
# data(varespec)
#6a- Calculate distances ----
all_ps_vg_dist <- vegdist(all_ps_blst_vegan_df, method="bray")

vegan::scores(all_ps_vg_dist)

# all_ps_vg_dist_metaMDS <- metaMDS(comm = all_ps_vg_dist, autotransform = FALSE) 
# actually autotransform = FALSE doesn't seem to change the results

# plot(all_ps_vg_dist_metaMDS)

# all_ps_vg_dist_metaMDS_2 <- metaMDS(comm = all_ps_vg_dist, distance = "bray", k =2)

# plot(all_ps_vg_dist_metaMDS_2)

#selecionar apenas espécies esperadas?

all_ps_blst_vegan_df %>% ncol()
all_ps_blst_vegan_df <- all_ps_blst_vegan_df[,(colnames(all_ps_blst_vegan_df) %in% expected_sps)]


all_ps_blst_vegan_df %>% ncol()
all_ps_vg_dist <- vegdist(all_ps_blst_vegan_df, method="bray")

all_ps_ord <- decorana(veg = all_ps_blst_vegan_df)

all_ps_ord %>% summary()

all_ps_ord %>% str()

all_ps_ord$cproj
all_ps_ord


plot(all_ps_ord)
plot(all_ps_ord,type = "p")
plot(all_ps_ord,type = "c") 
vegan::scores(all_ps_vg_dist)




# all_ps_blst_vegan_df[,(colnames(all_ps_blst_vegan_df) %in% expected_sps)] %>% colnames()
# all_ps_blst_vegan_df%>% colnames()



all_ps_vegan_ord_meta <- metaMDS(veg = all_ps_blst_vegan_df, comm = all_ps_vg_dist)
# actually autotransform = FALSE doesn't seem to change the results
plot(all_ps_vegan_ord_meta, type = "t")


all_ps_vegan_ord_meta %>% str()
all_ps_vegan_ord_meta$stress


  
#6b- extract NMDS scores from results
  
all_vegan_meta <- (vegan::scores(all_ps_vegan_ord_meta) %>% tidyr::as_tibble(rownames = "Sample number")) %>% mutate(`Sample number` = as.numeric(`Sample number`))
            # all_vegan_meta <- as.data.frame(vegan::scores(all_ps_vegan_ord_meta))
            
            #Using the scores function from vegan to extract the site scores and convert to a data.frame
            
            # all_vegan_meta$`Sample number` <- rownames(all_vegan_meta) %>% as.numeric()  
            
            # all_vegan_meta %>% left_join()# create a column of site names, from the rownames of data.scores
            
            # all_vegan_meta <- all_vegan_meta  %>% as_tibble() # create a column of site names, from the rownames of data.scores

#7- bring NMDS scores to complete table

all_vegan_meta_tbl <- left_join(x = unique(all_ps_blst_vegan[,c(1:10)]),y = all_vegan_meta, by = "Sample number") %>% 
  mutate(Primer=factor(Primer,levels = c("NeoFish", "MiFish", "Teleo")),
         `Mock Community`=factor(`Mock Community`))





library(factoextra)
library(ggforce)



nmds_PLOT <- all_vegan_meta_tbl %>% 
  # filter(Run %in% c("LGC_MiniSeq_1", "LGC_MiniSeq_2")) %>% 
  ggplot(aes(x = NMDS1,y = NMDS2, col = Primer,shape = Normalization,label = Sample,Group = `Mock Community`))+
    # stat_ellipse()+ 
  geom_point(size = 11)+
  theme_light(base_size = 18) +
  theme(legend.position="bottom") +
  coord_fixed(ratio = 1) +
  # ggrepel::geom_label_repel(label.size = 0.8,size = 3,min.segment.length = 2) +
  # ggrepel::geom_text_repel(col="black",size = 3,min.segment.length = 2) +
  # scale_shape_manual() %>% 
  scale_color_manual(
    # labels = c("NeoFish", "MiFish", "Teleo", "NeoFish/MiFish", "NeoFish/MiFish/Teleo"),
    labels = c("NeoFish", "MiFish", "Teleo"),
                     values = alpha(colour = colors_norm[c(1,3,5)] ))+
  annotate(geom = "text",
           x=c(0.275),y=c(-0.275),label=paste0("Stress: ",round(all_ps_vegan_ord_meta$stress,digits = 4)),size=5) +

    # ADD ggforce's ellipses
  ggforce::geom_mark_ellipse(inherit.aes = FALSE,
                             aes(x = NMDS1,y = NMDS2,
                                 group=`Mock Community`,
                                 label=`Mock Community`),
                             n = 100,
                             expand = 0.03,
                             label.fontsize = 20,con.cap = 0.1) 
  
    # facet_wrap(~`Mock Community`,ncol = 2)
  
#   
nmds_PLOT
  # 
# ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SFJQ_NMDS.pdf",
ggsave(file = "~/outros/sfjq_temp/SFJQ_NMDS.pdf",
     plot = nmds_PLOT,
     device = "pdf",
     width = 40,
     height =25,
     units = "cm",
     dpi = 300)

ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SFJQ_NMDS.png",
     plot = nmds_PLOT,
     device = "png",
     width = 31,
     height =20,
     units = "cm",
     dpi = 300)




# anosim----

################################# anosin function###############################
anosin_auto<- function(tbl,cols_out, Coluna){
  df <- tbl[,c(1,(1+cols_out):ncol(tbl))] %>% 
    as.data.frame() %>% 
    `rownames<-`(.$`Sample number`) %>% 
    select(-c("Sample number"))
  
  ano <- anosim(df, grouping = tbl[[Coluna]],
       permutations = 9999, distance = "bray", strata = NULL)
  return(ano)
  
}
################################################################################


#Primers ----
#Todas MC juntas
all_ps_blst_vegan %>% 
  # filter(`Mock Community` %in% c("SFmc")) %>% 
anosin_auto(cols_out = 10,Coluna = "Primer")

#Apenas JQ
all_ps_blst_vegan %>% 
  filter(`Mock Community` %in% c("JQmc")) %>% 
anosin_auto(cols_out = 10,Coluna = "Primer")

#Apenas SF
all_ps_blst_vegan %>% 
  filter(`Mock Community` %in% c("SFmc")) %>% 
anosin_auto(cols_out = 10,Coluna = "Primer")

#Apenas SFJQ
all_ps_blst_vegan %>% 
  filter(`Mock Community` %in% c("SFJQmc")) %>% 
anosin_auto(cols_out = 10,Coluna = "Primer")


#Normalization ----
#Todas MC juntas
all_ps_blst_vegan %>% 
anosin_auto(cols_out = 10,Coluna = "Normalization")

#Apenas JQ
all_ps_blst_vegan %>% 
  filter(`Mock Community` %in% c("JQmc")) %>% 
anosin_auto(cols_out = 10,Coluna = "Normalization")

#Apenas SF
all_ps_blst_vegan %>% 
  filter(`Mock Community` %in% c("SFmc")) %>% 
anosin_auto(cols_out = 10,Coluna = "Normalization")

#Apenas SFJQ
all_ps_blst_vegan %>% 
  filter(`Mock Community` %in% c("SFJQmc")) %>% 
anosin_auto(cols_out = 10,Coluna = "Normalization")


all_vegan_meta_tbl %>% 
  filter(Run %in% c("LGC_MiniSeq_1","LGC_MiniSeq_2")) %>% 
  select(Sample,`Sample number`,Primer)

Ploting ASVs

# all_ps_tbl_blast_bckp6 <- all_ps_tbl_blast

all_ps_tbl_blast <- all_ps_tbl_bl_cur 




#28- ASVs plots by sample and species ----

options(set.seed(seed = 13))

#28a- ASV size distribution - alphabetical----
all_ps_tbl_blast$Run %>% unique()
  
ASV_size_by_Sample <- all_ps_tbl_blast %>%
  filter(!Sample %in% c("Positive Control\n(P.glauca)")) %>% 
  filter(!Run %in% c("ecomol_iSeq")) %>% 
  mutate(Sample = factor(Sample,levels = sample_levels)) %>% 
  mutate(Primer = factor(Primer,levels = c("NeoFish", "MiFish", 
                                           "Teleo", "NeoFish/MiFish/Teleo"))) %>% 
  ggplot(aes(y=Sample,
             x=`ASV size (pb)`,
             colour = Primer,
             size=`Relative abundance on sample`,
             shape=`Expected length`
             )) +
  geom_jitter(height = 0.2,
              width = 0) +
  ggplot2::scale_colour_manual(
                     values = ggplot2::alpha(colour = colors5[1:4] ,alpha =  0.3)) +
  coord_fixed(ratio = 8) +
  scale_x_continuous(breaks = c(20,60,80,100,120,140,160,180,200,220,240,260,280,300,320,340),expand = c(0.02,0.02)) +
  xlab("ASV length (bp)") +
  ylab("Sample") +
  ggtitle(label = "SFJQ mock communities ",
          subtitle = "All ASVs found in samples, by length and abundance") +
  theme_bw(base_size = 15) +
  theme(legend.position = "right") 

ASV_size_by_Sample


ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/3-ASV_size_by_sample.png",
     plot = ASV_size_by_Sample,
     device = "png",
     width = 18,
     height = 10,
     dpi = 600)

ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/3-ASV_size_by_sample.svg",
     plot = ASV_size_by_Sample,
     device = "svg",
     width = 18,
     height = 10,
     dpi = 600)

ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/3-ASV_size_by_sample.pdf",
     plot = ASV_size_by_Sample,
     device = "pdf",
     width = 18,
     height = 10,
     dpi = 600)
dev.off()



##################### paper ################################# ----

#29 - ASVS - sample X species (12S) - distribution: blast---- 
all_ps_tbl_blast$Group %>%unique()

#Jq & SF DNA pools - ASVs size and species by sample----

all_ps_tbl_blast$Sample %>% unfactor() %>% unique() %>% base::sort()
all_ps_tbl_blast$`revised final ID` %>% unique() %>% base::sort() %>% paste0(collapse = '", \n"') %>% cat()
all_ps_tbl_blast$`final ID` %>% unique() %>% base::sort() %>% paste0(collapse = '", \n"') %>% cat()


pool_labels <- c(
  "Normalized JQmc" = "Jequitinhonha\nNormalized DNA pool",
  "Non-normalized JQmc" = "Jequitinhonha\nNon-Normalized DNA pool",
  "Normalized SFJQmc" = "São Francisco & Jequitinhonha\nNormalized DNA pool",
  "Non-normalized SFmc" = "São Francisco\nNon-Normalized DNA pool",
  "Normalized SFmc" = "São Francisco\nNormalized DNA pool"
)

pools_levels <- c(
"Normalized JQmc",
"Non-normalized JQmc",
"Normalized SFJQmc",
"Normalized SFmc",
"Non-normalized SFmc"
)

#final ID levels
{
finalID_levels<- c(
#jq
"Astyanax lacustris", 
"Australoheros sp", 
"Delturus brevis", 
"Eugerres brasilianus", 
"Hypomasticus steindachneri", 

"Hypostomus nigrolineatus", 
"Megaleporinus elongatus", 
"Megaleporinus garmani", 
"Moenkhausia costae", 
"Rhamdia quelen", 
"Steindachneridion amblyurum", 
"Wertheimeria maculata",
#ambos
"Gymnotus carapo", 
"Hoplias", 
"Hoplias brasiliensis", 

"Hoplias intermedius", 
"Hoplias malabaricus", 
"Prochilodus", 
"Prochilodus argenteus", 
 
"Prochilodus costatus", 
"Steindachnerina elegans", 
"Trachelyopterus galeatus",
#sf

"Astyanax fasciatus", 
"Brycon orthotaenia", 
"Characidium lagosantense", 
"Crenicichla lepidota", 
# "Curimatella lepidura", esse é na vdd roeboides
"Roeboides xenodon",
"Eigenmannia virescens", 
"Franciscodoras marmoratus", 
"Hypostomus alatus", 
"Imparfinis minutus", 
"Leporinus reinhardti", 
"Microglanis leptostriatus", 
"Moenkhausia sanctaefilomenae", 
"Myleus micans", 
"Pamphorichthys hollandi", 
"Phalloceros uai", 

"Pimelodus maculatus", 
"Pimelodus pohli", 
"Pseudoplatystoma corruscans", 
"Pterygoplichthys etentaculatus", 
"Serrasalmus brandtii", 
"Tetragonopterus chalceus", 

#partial
"Astyanax", 
"Hoplias brasiliensis/intermedius",
"Hypostomus", 
"Pimelodus", 
"Prochilodus argenteus/hartii",
#trash


"NA elegans/gilbert", 
"NA lepidura/xenodon", 
"Acestrorhynchus lacustris",
"Coptodon zillii",
"Cyphocharax gilbert",
"Geophagus brasiliensis",
"Planaltina myersi", 
"Poecilia reticulata mitochondr"
)
}
finalID_levels[finalID_levels %>% duplicated()]



# final ID levels 2
{
finalID_levels <- c(
"Acestrorhynchus lacustris", 
"Acinocheirodon melanogramma", 
"Astyanax fasciatus", 
"Astyanax lacustris", 
"Australoheros sp", 
"Bos taurus", 
"Brycon orthotaenia", 
"Characidium lagosantense", 
"Coptodon zillii", 
"Crenicichla lepidota", 
# "Curimatella lepidura", agora é roeboides
"Roeboides xenodon",
"Cyphocharax gilbert", 
"Delturus brevis", 
"Eigenmannia virescens", 
"Eugerres brasilianus", 
"Franciscodoras marmoratus", 
"Geophagus brasiliensis", 
"Gymnotus carapo", 
"Hoplias brasiliensis", 
"Hoplias intermedius", 
"Hoplias malabaricus", 
"Hypomasticus steindachneri", 
"Hypostomus alatus", 
"Hypostomus nigrolineatus", 
"Imparfinis minutus", 
"Leporinus reinhardti", 
"Megaleporinus elongatus", 
"Megaleporinus garmani", 
"Microglanis leptostriatus", 
"Moenkhausia costae", 
"Moenkhausia sanctaefilomenae", 
"Myleus micans", 
"Pamphorichthys hollandi", 
"Phalloceros uai", 
"Pimelodus maculatus", 
"Pimelodus pohli", 
"Planaltina myersi", 
"Prionace glauca", 
"Prochilodus argenteus", 
"Prochilodus costatus", 
"Prochilodus hartii",
"Pseudoplatystoma corruscans", 
"Pterygoplichthys etentaculatus", 
"Rhamdia quelen", 
"Roeboides xenodon", 
"Serrasalmus brandtii", 
"Steindachneridion amblyurum", 
"Tetragonopterus chalceus", 
"Trachelyopterus galeatus", 
"Wertheimeria maculata",

#partial
"Astyanax", 
"Hoplias brasiliensis/intermedius", 
"Hypostomus", 
"Pimelodus", 
"Prochilodus", 
"Prochilodus argenteus/hartii")
}

sps_remove <- c(
NA,"NA",
"Acestrorhynchus lacustris", 
"Acinocheirodon melanogramma", 
"Bos taurus", 
"Coptodon zillii", 
"Curimatella lepidura", 
"Eugerres brasilianus", 
"Geophagus brasiliensis", 
"Leporinus reinhardti", 
"Moenkhausia costae", 
"Planaltina myersi", 
"Prionace glauca", 
"Pseudoplatystoma corruscans"
)

Images arcticle

Fold-change bar plots

##Ven diagram

##Upset plot

DNA/RRA correlation plots

colnames(all_ps_tbl_sfjq_full_uniq)
all_ps_tbl_sfjq_full_uniq$Group
all_ps_tbl_sfjq_full_uniq$MC
all_ps_tbl_sfjq_full_uniq$Normalization




######função pra plotar lm

# lm_eqn <- function(df){
#     m <- lm(y ~ x, df);
#     eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, 
#          list(a = format(unname(coef(m)[1]), digits = 2),
#               b = format(unname(coef(m)[2]), digits = 2),
#              r2 = format(summary(m)$r.squared, digits = 3)))
#     as.character(as.expression(eq));
# }





#inclinação das retas ----

#LM
 models_corr <- all_ps_tbl_sfjq_full_uniq %>% 
   filter(Normalization %in% c("Non-normalized")) %>% 
   # filter(Primer %in% c("NeoFish")) %>% 
  group_by(Primer,MC) %>% 
   select(c("Percentage on respective Non-norm pool", "Relative abundance on sample")) %>% 
  do(model = lm(formula = `Percentage on respective Non-norm pool` ~ `Relative abundance on sample`, data = .))
   # lm(formula = `Percentage on respective Non-norm pool` ~ `Relative abundance on sample`)
   # aov(formula = `Percentage on respective Non-norm pool` ~ `Relative abundance on sample`)

models_corr$model
models_corr$Primer
models_corr$MC



models_corr$model[[1]] %>% broom::glance(model) #NeoFish JQmc
models_corr$model[[2]] %>% broom::glance(model) #NeoFish SFmc
models_corr$model[[3]] %>% broom::glance(model) #MiFish JQmc
models_corr$model[[4]] %>% broom::glance(model) #MiFish SFmc
models_corr$model[[5]] %>% broom::glance(model) #Teleo JQmc

#AOV
models_corr <- all_ps_tbl_sfjq_full_uniq %>% 
   filter(Normalization %in% c("Non-normalized")) %>% 
   # filter(Primer %in% c("NeoFish")) %>% 
  group_by(Primer) %>% 
   select(c("Percentage on respective Non-norm pool", "Relative abundance on sample")) %>% 
  do(model = aov(formula = `Percentage on respective Non-norm pool` ~ `Relative abundance on sample`, data = .))
   # lm(formula = `Percentage on respective Non-norm pool` ~ `Relative abundance on sample`)
   # aov(formula = `Percentage on respective Non-norm pool` ~ `Relative abundance on sample`)

models_corr$model
models_corr$Primer

models_corr$model[[1]] %>% broom::tidy()
models_corr$model[[2]] %>% broom::tidy()
models_corr$model[[3]] %>% broom::tidy()



#JQmc ----
# jq_coef <- lm(`Percentage on respective Non-norm pool` ~ `Relative abundance on sample`,
#    (all_ps_tbl_sfjq_full_uniq %>% 
#       filter(MC %in% c("JQmc")) %>% 
#       filter(Normalization %in% c("Non-normalized"))))




############################ tentando com a tib com norm e n norm na mesma coluna
tab_curated_SFJQ_all_pools %>% colnames()


sfjq_sp_corr <-
  tab_curated_SFJQ_all_pools %>% 
  ggplot(aes(x=`input DNA (%)`,
             y=`RRA (%)`,
             col=Primer,
             shape=Pool))+
  geom_point() + 
  # geom_smooth(method=lm) +
  # coord_fixed()+
  scale_colour_manual(values = alpha(colour = colors_norm[c(1,3,5)] ,alpha =  0.8)) +
  # scale_shape_manual(drop=TRUE) +
  xlab("Input DNA (%)") +
  ylab("Relative Read Abundance (%)") +
  ggtitle("SFmc & JQmc: Correlation between\nInput DNA and RRA") +
  scale_x_sqrt(breaks=c(0,0.0001,0.001,0.01,0.025,0.05,0.1,0.2,0.3,0.4,0.6,0.8,1)*100) +
  scale_y_sqrt(breaks=c(0,0.0001,0.001,0.01,0.025,0.05,0.1,0.2,0.3,0.4,0.6,0.8,1)*100) +
  coord_fixed(ratio = 1)+
  geom_smooth(method=lm) +
  theme_bw(base_size = 10) +
  # facet_wrap(MC~Primer,ncol = 3) 
  facet_wrap(Primer~Group,ncol = 5) 
# +
#   scale_x_log10() +
#   scale_y_log10()
# minor_breaks = mb
# minor_breaks = mb

ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SFJQ_RRA_DNA_bySp2.png", plot = sfjq_sp_corr, device = "png", width = 30, height = 15, units = "cm", dpi = 600)









###########################




sfjq_sp_corr <- all_ps_tbl_sfjq_full_uniq %>% 
  # filter(MC %in% c("JQmc")) %>%
  filter(Normalization %in% c("Non-normalized")) %>%
  # mutate(`Percentage on respective Non-norm pool`= if_else(`Percentage on respective Non-norm pool` %in% c(NA,"NA"),0,`Percentage on respective Non-norm pool`)) %>% 
  # mutate(`Relative abundance on sample`= if_else(`Relative abundance on sample` %in% c(NA,"NA"),0,`Relative abundance on sample`)) %>% View()
  
  ggplot(aes(x=`Percentage on respective Non-norm pool`*100,
             y=`Relative abundance on sample`*100,
             col=Primer,
             shape=MC
             ))+
  geom_point() + 
  # geom_smooth(method=lm) +
  # coord_fixed()+
  scale_colour_manual(values = alpha(colour = colors_norm[c(1,3,5)] ,alpha =  0.8)) +
  # scale_shape_manual(drop=TRUE) +
  xlab("Input DNA (%)") +
  ylab("Relative Read Abundance (%)") +
  ggtitle("SFmc & JQmc: Correlation between\nInput DNA and RRA") +
  scale_x_sqrt(breaks=c(0,0.0001,0.001,0.01,0.025,0.05,0.1,0.2,0.3,0.4,0.6,0.8,1)*100) +
  scale_y_sqrt(breaks=c(0,0.0001,0.001,0.01,0.025,0.05,0.1,0.2,0.3,0.4,0.6,0.8,1)*100) +
  coord_fixed(ratio = 1)+
  geom_smooth(method=lm) +
  theme_bw(base_size = 10) +
  # facet_wrap(MC~Primer,ncol = 3) 
  facet_wrap(Primer~Normalization,ncol = 3) 
# +
#   scale_x_log10() +
#   scale_y_log10()
# minor_breaks = mb
# minor_breaks = mb

ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SFJQ_RRA_DNA_bySp.png", plot = sfjq_sp_corr, device = "png", width = 30, height = 15, units = "cm", dpi = 600)




#SFmc ----


library("plotly")

sf_sp_corr <- all_ps_tbl_sfjq_full_uniq %>% 
  filter(MC %in% c("SFmc")) %>% 
  filter(Normalization %in% c("Non-normalized")) %>% 
  # mutate(`Percentage on respective Non-norm pool`= if_else(`Percentage on respective Non-norm pool` %in% c(NA,"NA"),0,`Percentage on respective Non-norm pool`)) %>% 
  # mutate(`Relative abundance on sample`= if_else(`Relative abundance on sample` %in% c(NA,"NA"),0,`Relative abundance on sample`)) %>% View()
  
  ggplot(aes(x=`Percentage on respective Non-norm pool`*100,
             y=`Relative abundance on sample`*100,
             col=Primer,
             shape=MC))+
  geom_point() + 
  # geom_smooth(method=lm) +
  # coord_fixed()+
  scale_colour_manual(values = alpha(colour = colors_norm[c(1,3,5)] ,alpha =  0.8)) +
  xlab("input DNA (%)") +
  ylab("Relative Read Abundance (%)") +
  ggtitle("SFmc: Correlation between\nInput DNA and RRA") +
  scale_x_sqrt(breaks=c(0,0.0001,0.001,0.01,0.025,0.05,0.1,0.2,0.3,0.4,0.6,0.8,1)*100) +
  scale_y_sqrt(breaks=c(0,0.0001,0.001,0.01,0.025,0.05,0.1,0.2,0.3,0.4,0.6,0.8,1)*100) +
  coord_fixed(ratio = 1)+
  geom_smooth(method=lm) +
  theme_bw(base_size = 10) +
  facet_wrap(~Primer,ncol = 3) 
    
    
    
    ggplotly(sf_sp_corr)


ggsave(file = "~/prjcts/fish_eDNA/sfjq/results/figs/SF_RRA_DNA_bySp.png", plot = sf_sp_corr, device = "png", width = 20, height = 15, units = "cm", dpi = 600)

Aditional Graphics

# set colors ----

colors6 <- c("#19821c","#8dbc8f", #neo norm & non norm
             "#171d9a","#8d90c7", #mif norm & non norm
             "#8c1717","#c18d8d"  #tel norm & non norm
             )

scales::show_col(colors6)






# carregando tabela 
# https://docs.google.com/spreadsheets/d/1sTsOaI999E9Py_f4ll5j838r7CVc991a8mPmd8LvykU/edit#gid=0

tab_curated_SFJQ_all_pools <- read.csv("~/prjcts/fish_eDNA/sfjq/data/SFJQ_all_pools-tabelas_curadas_para_o_R-SFJQmc-copy.csv",check.names = F) %>% 
  as_tibble()

tab_curated_SFJQ_all_pools <- tab_curated_SFJQ_all_pools %>% 
    filter(`input DNA (%)` != 0 & `RRA (%)` !=0) %>%
  group_by(Pool,Normalization,Primer,Species) %>% 
  summarize(Pool = unique(Pool),
            Normalization = unique(Normalization),
            Status = unique(Status),
            Species = unique(Species),
            Primer = unique(Primer),
            `Num ASVs` = `Num ASVs`,
            `Num OTUs` = `Num OTUs`,
            `input DNA (%)` = `input DNA (%)`,
            `RRA (%)` = `RRA (%)`
            # `Expected species` = length(unique(`revised final ID`[`Expected Species` %in% c("expected")])),
            # `Expected species list` = list(unique(base::sort(`revised final ID`[`Expected Species` %in% c("expected")]))),
            # `revised final ID`= unique(`revised final ID`),
            # `RRA (%)` = sum(`Relative abundance on sample`),
            # `Percentage on respective Norm pool` = unique(`Percentage on respective Norm pool`),
            # `Percentage on respective Non-norm pool` = unique(`Percentage on respective Non-norm pool`),
            # `Relative abundance on sample` = unique(`Relative abundance on sample`)
            ) %>%
  ungroup() %>% 
  # mutate(`revised final ID`=factor(`revised final ID`
  #                                  # , levels = rev(finalID_levels)
  #                                  )) %>% 
  mutate(Primer = factor(Primer, levels = c("NeoFish", "MiFish", "Teleo", "NeoFish/MiFish","NeoFish/MiFish/Teleo"))) %>% 
  mutate(`Fold change (RRA/DNA input)` = gtools::foldchange(denom = `input DNA (%)`,num = `RRA (%)`)) %>% 
  unique()
  # mutate(Group = factor(Group,levels = c("Normalized SFJQmc", "Non-normalized JQmc", "Normalized JQmc", "Non-normalized SFmc", "Normalized SFmc" ))) %>% 
  # mutate(MC = str_remove(Group,"Normalized |Non-normalized ")) %>% 
  # mutate(Normalization = str_remove(Group," SFmc| JQmc| SFJQmc")) 


tab_curated_SFJQ_all_pools$`Fold change (RRA/DNA input)` %>% sort() %>% duplicated()

tab_curated_SFJQ_all_pools[c(which(tab_curated_SFJQ_all_pools$`Fold change (RRA/DNA input)` %>% as.character() %>% duplicated()),
                             which(tab_curated_SFJQ_all_pools$`Fold change (RRA/DNA input)` %>% as.character() %>% duplicated())-1),] %>% View()




# SFJQmc ----
## build tree ----
### read 12S db seqs for the species present in pools
SFJQ_Sps_seqs <- Biostrings::readDNAStringSet(filepath = "~/prjcts/fish_eDNA/sfjq/data/trees/SFJQmc-38_SPs_fused-unique.fas") %>%
# SFJQ_Sps_seqs <- Biostrings::readDNAStringSet(filepath = "~/outros/sfjq_temp/trees/SFJQmc-38_SPs_fused-unique.fas") %>% 
  DECIPHER::RemoveGaps()

### align seqs
SFJQ_Sps_algn <- DECIPHER::AlignSeqs(myXStringSet = SFJQ_Sps_seqs, 
                                      refinements = 100,
                                      iterations = 100,
                                      verbose = TRUE)

### generate distance matrix
SFJQ_Sps_dist <- DECIPHER::DistanceMatrix(myXStringSet = SFJQ_Sps_algn,
                                            includeTerminalGaps = FALSE,
                                            correction = "Jukes-Cantor",
                                            processors = 20,
                                            verbose = TRUE)

### generate dendrogram/tree from alignment and distance matrix
SFJQmc_tree <- ape::nj(SFJQ_Sps_dist)
        # tree <- phangorn::NJ(SFJQ_Sps_dist)
class(SFJQmc_tree)

### save tree as newick
ape::write.tree(phy = SFJQmc_tree,file = "~/prjcts/fish_eDNA/sfjq/data/trees/SFJQmc-38_SPs_fused-unique_APEtree.nwk")
# ape::write.tree(phy = SFJQmc_tree,file = "~/outros/sfjq_temp/trees/SFJQmc-38_SPs_fused-unique_APEtree.nwk")

### read tree from file (or stay with the same object)
# SFJQmc_tree <- read.tree("~/outros/sfjq_temp/trees/SFJQmc-38_SPs_fused-unique_APEtree.nwk")
SFJQmc_tree <- read.tree("~/prjcts/fish_eDNA/sfjq/data/trees/SFJQmc-38_SPs_fused-unique_APEtree.nwk")


## species metadata ----
### read table with pools species, input DNA and RRA
# tab_curated_SFJQ_all_pools <- read.csv("~/outros/sfjq_temp/SFJQ_all_pools-tabelas_curadas_para_o_R-SFJQmc.csv",check.names = F)
# tab_curated_SFJQ_all_pools <- read.csv("~/prjcts/fish_eDNA/sfjq/data/SFJQ_all_pools-tabelas_curadas_para_o_R-SFJQmc.csv",check.names = F) %>% 
#   as_tibble()
# 
# tab_curated_SFJQ_all_pools




tab_curated_SFJQ_all_pools %>% colnames()
tab_curated_SFJQ_all_pools %>% unique()
all_ps_tbl_sfjq_full_uniq %>% colnames()





# tab_curated_SFJQ_all_pools  <- all_ps_tbl_sfjq_full_uniq



#converting the corrected table to the format required for next steps


tab_curated_SFJQ_all_pools <-
  all_ps_tbl_sfjq_full_uniq %>%
  pivot_longer(c("Percentage on respective Norm pool", "Percentage on respective Non-norm pool"),
               names_to = "DNA Originary Pool", values_to = "input DNA (%)") %>% 
  pivot_longer(c("Recovered proportion norm", "Recovered proportion non norm"),
               names_to = "Fold Change Originary Pool", values_to = "Fold Change") %>% 
  select(-c(
    # "DNA Originary Pool", "RRA Originary Pool",
            # "Sample,"
            # "Group",
            "Run"
            )) %>% 
  # colnames()
  # View()
  rename(
   Species = `revised final ID`,
  `Num OTUs` = `OTUs`,
  `Num ASVs` = `ASVs`,
  `Num IDs` = `IDs`,
  # `RRA (%)` = `Relative abundance on sample`,
  # `Expected species`, 
  # `Expected species list`,
  # `Fold Change` = `Ratio`,
  `Pool` = `MC`) %>%
  filter((`DNA Originary Pool` %in% c("Percentage on respective Norm pool") & `Normalization` %in% c("Normalized")) |
           (`DNA Originary Pool` %in% c("Percentage on respective Non-norm pool") & `Normalization` %in% c("Non-normalized")) ) %>% 
  filter((`Fold Change Originary Pool` %in% c("Recovered proportion norm") & `Normalization` %in% c("Normalized")) |
           (`Fold Change Originary Pool` %in% c("Recovered proportion non norm") & `Normalization` %in% c("Non-normalized")) ) %>% 
  select(-c("DNA Originary Pool", "Fold Change Originary Pool")) %>% 
  mutate(Status = if_else(`Expected species` == 0, "Contamination","Expected")) %>% 
  mutate(`RRA (%)` = `RRA (%)` * 100,
         `input DNA (%)` = `input DNA (%)` * 100) %>% unite(Normalization, Primer, col = "Primer_norm",remove = F,sep = " ") %>% 
  mutate(Primer_norm = factor(Primer_norm, levels = c("Normalized NeoFish","Normalized MiFish","Normalized Teleo","Non-normalized NeoFish","Non-normalized MiFish","Non-normalized Teleo"))) %>% View()

# all_ps_tbl_sfjq_full_uniq %>% colnames()


 

# tab_curated_SFJQ_all_pools[sort(c(which(tab_curated_SFJQ_all_pools$`Fold Change` %>% as.character() %>% duplicated()),which(tab_curated_SFJQ_all_pools$`Fold Change`%>% as.character() %>% duplicated())-1)),] %>% View()
# tab_curated_SFJQ_all_pools[tab_curated_SFJQ_all_pools$`Fold Change` %>% duplicated(),] %>% View()

### tidy table
tab_curated_SFJQ <- tab_curated_SFJQ_all_pools %>%
  as_tibble() %>%
  filter(Status == "Expected") %>%
  filter(Pool == "SFJQmc") %>%
  # filter(MC == "SFJQmc") %>% 
  # filter(Pool == "SFJQmc") %>% 
  mutate(Primer = factor(Primer, levels = c("NeoFish","MiFish","Teleo")),
         Species = factor(Species),
         # `revised final ID` = factor(`revised final ID`),
         Normalization = factor(Normalization),
         Pool = factor(Pool),
         Status = factor(Status),
         # `RRA (%)` = as.numeric(`Relative abundance on sample`)*100,
         `RRA (%)` = as.numeric(`RRA (%)`),
         `input DNA (%)` = as.numeric(`input DNA (%)`))


## correct tips labels ----
### check tip names in tree
SFJQmc_tree$tip.label


### rename tree tips to mach table
SFJQmc_tree$tip.label
tab_curated_SFJQ$Species %>% unique() %>% sort()

{
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1339_Prochilodus_costatus_JQ_2860"] <- "Prochilodus costatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_5612_Prochilodus_argenteus_hartii"] <- "Prochilodus argenteus/hartii"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_6586_Steindachnerina_elegans-Cyphocharax_gilbert"] <- "Cyphocharax gilbert"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1230_Serrasalmus_brandtii"] <- "Serrasalmus brandtii"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1162_Myleus_micans"] <- "Myleus micans"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_2984_Hypomasticus_steindachneri"] <- "Hypomasticus steindachneri"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_4290_Megaleporinus_garmani"] <- "Megaleporinus garmani"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_1762_Megaleporinus_elongatus"] <- "Megaleporinus elongatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1037_Brycon_orthotaenia"] <- "Brycon orthotaenia"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1381_Characidium_lagosantense"] <- "Characidium lagosantense"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "1136_Acestrorhynchus_lacustris"] <- "Acestrorhynchus lacustris"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_7822_Hoplias_malabaricus"] <- "Hoplias malabaricus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1377_Hoplias_intermedius_brasiliensis"] <- "Hoplias brasiliensis/intermedius"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_0916_Roeboides_xenodon"] <- "Roeboides xenodon"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_0901_Tetragonopterus_chalceus"] <- "Tetragonopterus chalceus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1113_Moenkhausia_sanctaefilomenae"] <- "Moenkhausia sanctaefilomenae"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SFJQ_7812_Moenkhausia_costae"] <- "Moenkhausia costae"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1153_Astyanax_cf_fasciatus"] <- "Astyanax fasciatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_7880_Astyanax_lacustris"] <- "Astyanax lacustris"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1141_Pterygoplichthys_etentaculatus"] <- "Pterygoplichthys etentaculatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1041_Hypostomus_alatus"] <- "Hypostomus alatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_7893_Hypostomus_nigrolineatus"] <- "Hypostomus nigrolineatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1248_Gymnotus_carapo_JQ_1631"] <- "Gymnotus carapo"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1117_Eigenmannia_virescens"] <- "Eigenmannia virescens"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_1936_Delturus_brevis"] <- "Delturus brevis"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_0708_Franciscodoras_marmoratus"] <- "Franciscodoras marmoratus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_7817_Wertheimeria_maculata"] <- "Wertheimeria maculata"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1243_Trachelyopterus_galeatus_JQ_5675"] <- "Trachelyopterus galeatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1403_Pimelodus_pohli"] <- "Pimelodus pohli"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1280_Pimelodus_maculatus"] <- "Pimelodus maculatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "1135_Pseudoplatystoma_corruscans"] <- "Pseudoplatystoma corruscans"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_2996_Steindachneridion_amblyurum"] <- "Steindachneridion amblyurum"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1104_Microglanis_leptostriatus"] <- "Microglanis leptostriatus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1161_Imparfinis_minutus"] <- "Imparfinis minutus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_5645_Rhamdia_aff_quelen"] <- "Rhamdia quelen"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SFJQ_2943_Eugerres_brasilianus"] <- "Eugerres brasilianus"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1368_Phalloceros_uai"] <- "Phalloceros uai"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1099_Pamphorichthys_hollandi"] <- "Pamphorichthys hollandi"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "SF_1264_Crenicichla_lepidota"] <- "Crenicichla lepidota"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "JQ_6584_Australoheros_sp"] <- "Australoheros sp"
SFJQmc_tree$tip.label[SFJQmc_tree$tip.label == "304_Geophagus_brasiliensis"] <- "Geophagus brasiliensis"
}

### check if all names have correspondences
SFJQmc_tree$tip.label %in% tab_curated_SFJQ$Species
tab_curated_SFJQ$Species %in% SFJQmc_tree$tip.label
tab_curated_SFJQ$Species[!tab_curated_SFJQ$Species %in% SFJQmc_tree$tip.label]





### convert ape tree to prettier ggtree object
SFJQmc_tree_plot <- ggtree(SFJQmc_tree) + 
  theme_tree2() +
  geom_tiplab(offset = 0,align = T)+ 
  xlim(0, 0.42)


### save tree plot
# ggsave(file = "~/prjcts/fish_eDNA/sfjq/data/trees/SFJQmc-38_SPs_fused-unique-tree_plot.pdf", plot = SFJQmc_tree_plot, device = "pdf", width = 24, height = 24, units = "cm", dpi = 600)
ggsave(file = "~/outros/sfjq_temp/trees/SFJQmc-38_SPs_fused-unique-tree_plot.pdf", plot = SFJQmc_tree_plot, device = "pdf", width = 24, height = 24, units = "cm", dpi = 600)



### extract tips order from tree to reproduce on plots
SPs_order_in_SFJQ_tree <- ggtree::get_taxa_name(SFJQmc_tree_plot) %>% rev()

            # SPs_order_in_SFJQ_tree <- extract_tree_data(tree_plot) %>% 
            #     dplyr::filter(isTip) %>% 
            #     dplyr::pull(label)



## plots ----
### RRA histogram ----

# library(ggdist)



SFJQmc_RRA_plot <-
  tab_curated_SFJQ %>%
  filter(Pool %in% c("SFJQmc")) %>% 
  mutate(Species = factor(Species,levels = SPs_order_in_SFJQ_tree)) %>% 
  ggplot(aes(y = Species,
             x = `RRA (%)`,
             fill = Primer, 
             col = Normalization
             ))+
  geom_bar(stat = "identity", size = 0.3,width = .75,
           # alpha = 0.7,
           position = position_dodge(preserve = "single" ,width = 1.1)) +
           # position = position_dodgejust(preserve = "single" ,width = 1.2)) +
  scale_color_manual(values = c("#000000","#747474")) +
  scale_fill_manual(values = colors6[c(1,3)]) +
  geom_point(aes(y = Species,
                 x = `input DNA (%)`),
             shape = "|",
             size = 3,
             colour = "#000000") +
  scale_x_break(c(13, 30),
                scales = "fixed") +
  scale_x_continuous(breaks=c(0,5,10,13,30,32)) +
  
  xlab("Relative read abundance (%)")+ 
  # opts(axis.title.y = theme_text(vjust=-0.5))
 theme(axis.text = element_text(vjust = -0.5))

## save plot 

# ggsave(file = "~/prjcts/fish_eDNA/sfjq/data/trees/SFJQmc-38_SPs_fused-unique-RRA_barplot.pdf", plot = SFJQmc_RRA_plot, device = "pdf", width = 18, height = 24, units = "cm", dpi = 600)
dev.off()
ggsave(file = "~/outros/sfjq_temp/trees/SFJQmc-38_SPs_fused-unique-RRA_barplot.pdf", plot = SFJQmc_RRA_plot, device = "pdf", width = 30, height = 24, units = "cm", dpi = 600)




# SFmc ----
## build tree ----
### read 12S db seqs for the species present in pools and select only pool species
names(SFJQ_Sps_seqs) %>% sort() %>% paste0(collapse = '",\n"') %>% cat()

SF_Sps_seqs <- SFJQ_Sps_seqs[c("SF_0708_Franciscodoras_marmoratus", "SF_0901_Tetragonopterus_chalceus",
                               "SF_0916_Roeboides_xenodon", "SF_1037_Brycon_orthotaenia",
                               "SF_1041_Hypostomus_alatus", "SF_1099_Pamphorichthys_hollandi",
                               "SF_1104_Microglanis_leptostriatus", "SF_1113_Moenkhausia_sanctaefilomenae",
                               "SF_1117_Eigenmannia_virescens", "SF_1141_Pterygoplichthys_etentaculatus",
                               "SF_1153_Astyanax_cf_fasciatus", "SF_1161_Imparfinis_minutus",
                               "SF_1162_Myleus_micans", "SF_1230_Serrasalmus_brandtii",
                               "SF_1243_Trachelyopterus_galeatus_JQ_5675", "SF_1248_Gymnotus_carapo_JQ_1631",
                               "SF_1264_Crenicichla_lepidota", "SF_1280_Pimelodus_maculatus",
                               "SF_1339_Prochilodus_costatus_JQ_2860", "SF_1368_Phalloceros_uai",
                               "SF_1377_Hoplias_intermedius_brasiliensis", "SF_1381_Characidium_lagosantense",
                               "SF_1403_Pimelodus_pohli")]
### align seqs
SF_Sps_algn <- DECIPHER::AlignSeqs(myXStringSet = SF_Sps_seqs, 
                                      refinements = 100,
                                      iterations = 100,
                                      verbose = TRUE)

### generate distance matrix
SF_Sps_dist <- DECIPHER::DistanceMatrix(myXStringSet = SF_Sps_algn,
                                            includeTerminalGaps = FALSE,
                                            correction = "Jukes-Cantor",
                                            processors = 20,
                                            verbose = TRUE)

### generate dendrogram/tree from alignment and distance matrix
SFmc_tree <- ape::nj(SF_Sps_dist)
        # tree <- phangorn::NJ(SFJQ_Sps_dist)
class(SFmc_tree)

### save tree as newick
# ape::write.tree(phy = SFmc_tree,file = "~/prjcts/fish_eDNA/sfjq/data/trees/SFmc-23_SPs_fused-unique_APEtree.nwk")
ape::write.tree(phy = SFmc_tree,file = "~/outros/sfjq_temp/trees/SFmc-23_SPs_fused-unique_APEtree.nwk")

### read tree from file (or stay with the same object)
SFmc_tree <- read.tree("~/prjcts/fish_eDNA/sfjq/data/trees/SFmc-23_SPs_fused-unique_APEtree.nwk")
SFmc_tree <- read.tree("~/outros/sfjq_temp/trees/SFmc-23_SPs_fused-unique_APEtree.nwk")

## species metadata ----
### read table with pools species, input DNA and RRA

### tidy table
tab_curated_SF <- tab_curated_SFJQ_all_pools %>% 
  filter(Pool %in% c("SFmc")) %>% 
  filter(Status %in% c("Expected")) %>%
  # filter(MC == "SFJQmc") %>% 
  # filter(Pool == "SFJQmc") %>% 
  mutate(Primer = factor(Primer, levels = c("NeoFish","MiFish","Teleo")),
         Species = factor(Species),
         # `revised final ID` = factor(`revised final ID`),
         Normalization = factor(Normalization),
         Pool = factor(Pool),
         Status = factor(Status),
         # `RRA (%)` = as.numeric(`Relative abundance on sample`)*100,
         `RRA (%)` = as.numeric(`RRA (%)`),
         `input DNA (%)` = as.numeric(`input DNA (%)`))


## correct tips labels ----
### check tip names in tree
SFmc_tree$tip.label


### rename tree tips to mach table
SFmc_tree$tip.label
tab_curated_SF$Species %>% unique() %>% sort()

{
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1339_Prochilodus_costatus_JQ_2860"] <- "Prochilodus costatus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1230_Serrasalmus_brandtii"] <- "Serrasalmus brandtii"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1162_Myleus_micans"] <- "Myleus micans"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1037_Brycon_orthotaenia"] <- "Brycon orthotaenia"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1381_Characidium_lagosantense"] <- "Characidium lagosantense"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1377_Hoplias_intermedius_brasiliensis"] <- "Hoplias intermedius"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_0916_Roeboides_xenodon"] <- "Roeboides xenodon"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_0901_Tetragonopterus_chalceus"] <- "Tetragonopterus chalceus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1113_Moenkhausia_sanctaefilomenae"] <- "Moenkhausia sanctaefilomenae"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1153_Astyanax_cf_fasciatus"] <- "Astyanax fasciatus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1141_Pterygoplichthys_etentaculatus"] <- "Pterygoplichthys etentaculatus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1041_Hypostomus_alatus"] <- "Hypostomus alatus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1248_Gymnotus_carapo_JQ_1631"] <- "Gymnotus carapo"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1117_Eigenmannia_virescens"] <- "Eigenmannia virescens"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_0708_Franciscodoras_marmoratus"] <- "Franciscodoras marmoratus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1243_Trachelyopterus_galeatus_JQ_5675"] <- "Trachelyopterus galeatus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1403_Pimelodus_pohli"] <- "Pimelodus pohli"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1280_Pimelodus_maculatus"] <- "Pimelodus maculatus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1104_Microglanis_leptostriatus"] <- "Microglanis leptostriatus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1161_Imparfinis_minutus"] <- "Imparfinis minutus"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1368_Phalloceros_uai"] <- "Phalloceros uai"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1099_Pamphorichthys_hollandi"] <- "Pamphorichthys hollandi"
SFmc_tree$tip.label[SFmc_tree$tip.label == "SF_1264_Crenicichla_lepidota"] <- "Crenicichla lepidota"
}

### check if all names have correspondences
SFmc_tree$tip.label %in% tab_curated_SF$Species
tab_curated_SF$Species %in% SFmc_tree$tip.label
tab_curated_SF$Species[!tab_curated_SF$Species %in% SFmc_tree$tip.label]





### convert ape tree to prettier ggtree object
SFmc_tree_plot <- ggtree(SFmc_tree) + 
  theme_tree2() +
  geom_tiplab(offset = 0,align = T)+ 
  xlim(0, 0.42)


### save tree plot
# ggsave(file = "~/prjcts/fish_eDNA/sfjq/data/trees/SFmc-23_SPs_fused-unique-tree_plot.pdf", 
ggsave(file = "~/outros/sfjq_temp/trees/SFmc-23_SPs_fused-unique-tree_plot.pdf", 
       plot = SFmc_tree_plot, 
       device = "pdf", 
       width = 24, height = 20, 
       units = "cm", dpi = 600)



### extract tips order from tree to reproduce on plots
SPs_order_in_SF_tree <- get_taxa_name(SFmc_tree_plot) %>% rev()

            # SPs_order_in_SF_tree <- extract_tree_data(tree_plot) %>% 
            #     dplyr::filter(isTip) %>% 
            #     dplyr::pull(label)




## plots ----
### RRA histogram ----

SFmc_RRA_plot <-
  tab_curated_SF %>%
  # filter(Normalization %in% c("Normalized")) %>%
  unite(Normalization, Primer, col = "Primer_norm",remove = F,sep = " ") %>%
  mutate(Primer_norm = factor(Primer_norm, levels = c("Normalized NeoFish","Normalized MiFish","Non-normalized NeoFish","Non-normalized MiFish"))) %>%
  mutate(Species = factor(Species,levels = SPs_order_in_SF_tree)) %>% 
  ggplot(aes(y = Species,
             x = `RRA (%)`,
             # fill = Primer, 
             fill = Primer_norm, 
             col = Normalization
             ))+
  geom_bar(stat = "identity", size = 0.3,width = 1,
           # alpha = 0.7,
           position = position_dodge(preserve = "single" ,width = 1.5)) +
           # position = position_dodgejust(preserve = "single" ,width = 1.2)) +
    scale_fill_manual(values = colors6[c(1,3,2,4)], name = "") +
  geom_point(aes(y = Species,
                 x = `input DNA (%)`,
             colour = Normalization),
             shape = "|",
             size = 3) +
    scale_color_manual(values = c("#747474","#000000")) +
  xlab("Relative read abundance (%)") 
# +
#   scale_color_manual(values = c("#000000","#848484"))

## save plot 

# ggsave(file = "~/prjcts/fish_eDNA/sfjq/data/trees/SFmc-23_SPs_fused-unique-RRA_barplot.pdf", 
#      plot = SFmc_RRA_plot, device = "pdf", width = 24, height = 20, units = "cm", dpi = 600)
ggsave(file = "~/outros/sfjq_temp/trees/SFmc-23_SPs_fused-unique-RRA_barplot.pdf", 
       plot = SFmc_RRA_plot, device = "pdf", width = 30, height = 30, units = "cm", dpi = 600)



# JQmc ----

## build tree ----
### read 12S db seqs for the species present in pools and select only pool species
names(SFJQ_Sps_seqs) %>% sort() %>% paste0(collapse = '",\n"') %>% cat()

JQ_Sps_seqs <- SFJQ_Sps_seqs[c("JQ_1762_Megaleporinus_elongatus",
                               "JQ_1936_Delturus_brevis",
                               "JQ_2984_Hypomasticus_steindachneri",
                               "JQ_2996_Steindachneridion_amblyurum",
                               "JQ_4290_Megaleporinus_garmani",
                               "JQ_5612_Prochilodus_argenteus_hartii",
                               "JQ_5645_Rhamdia_aff_quelen",
                               "JQ_6584_Australoheros_sp",
                               "JQ_6586_Steindachnerina_elegans-Cyphocharax_gilbert",
                               "JQ_7817_Wertheimeria_maculata",
                               "JQ_7822_Hoplias_malabaricus",
                               "JQ_7880_Astyanax_lacustris",
                               "JQ_7893_Hypostomus_nigrolineatus",
                               "SF_1243_Trachelyopterus_galeatus_JQ_5675",
                               "SF_1248_Gymnotus_carapo_JQ_1631",
                               "SF_1339_Prochilodus_costatus_JQ_2860",
                               "SF_1377_Hoplias_intermedius_brasiliensis")]
### align seqs
JQ_Sps_algn <- DECIPHER::AlignSeqs(myXStringSet = JQ_Sps_seqs, 
                                      refinements = 100,
                                      iterations = 100,
                                      verbose = TRUE)

### generate distance matrix
JQ_Sps_dist <- DECIPHER::DistanceMatrix(myXStringSet = JQ_Sps_algn,
                                            includeTerminalGaps = FALSE,
                                            correction = "Jukes-Cantor",
                                            processors = 20,
                                            verbose = TRUE)

### generate dendrogram/tree from alignment and distance matrix
JQmc_tree <- ape::nj(JQ_Sps_dist)
        # tree <- phangorn::NJ(SFJQ_Sps_dist)
class(JQmc_tree)

### save tree as newick
# ape::write.tree(phy = JQmc_tree,file = "~/prjcts/fish_eDNA/sfjq/data/trees/JQmc-23_SPs_fused-unique_APEtree.nwk")
ape::write.tree(phy = JQmc_tree,file = "~/outros/sfjq_temp/trees/JQmc-23_SPs_fused-unique_APEtree.nwk")

### read tree from file (or stay with the same object)
JQmc_tree <- read.tree("~/prjcts/fish_eDNA/sfjq/data/trees/JQmc-23_SPs_fused-unique_APEtree.nw")
# JQmc_tree <- read.tree("~/outros/sfjq_temp/trees/JQmc-23_SPs_fused-unique_APEtree.nwk")

## species metadata ----
### read table with pools species, input DNA and RRA

### tidy table
tab_curated_JQ <- tab_curated_SFJQ_all_pools %>% 
  filter(Pool %in% c("JQmc")) %>% 
  filter(Status %in% c("Expected")) %>%
  # filter(MC == "SFJQmc") %>% 
  # filter(Pool == "SFJQmc") %>% 
  mutate(Primer = factor(Primer, levels = c("NeoFish","MiFish","Teleo")),
         Species = factor(Species),
         # `revised final ID` = factor(`revised final ID`),
         Normalization = factor(Normalization),
         Pool = factor(Pool),
         Status = factor(Status),
         # `RRA (%)` = as.numeric(`Relative abundance on sample`)*100,
         `RRA (%)` = as.numeric(`RRA (%)`),
         `input DNA (%)` = as.numeric(`input DNA (%)`))


## correct tips labels ----
### check tip names in tree
JQmc_tree$tip.label


### rename tree tips to mach table
JQmc_tree$tip.label
tab_curated_JQ$Species %>% unique() %>% sort()

{
JQmc_tree$tip.label[JQmc_tree$tip.label == "SF_1339_Prochilodus_costatus_JQ_2860"] <- "Prochilodus costatus"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_5612_Prochilodus_argenteus_hartii"] <- "Prochilodus argenteus/hartii"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_6586_Steindachnerina_elegans-Cyphocharax_gilbert"] <- "Cyphocharax gilbert"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_2984_Hypomasticus_steindachneri"] <- "Hypomasticus steindachneri"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_4290_Megaleporinus_garmani"] <- "Megaleporinus garmani"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_1762_Megaleporinus_elongatus"] <- "Megaleporinus elongatus"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_7822_Hoplias_malabaricus"] <- "Hoplias malabaricus"
JQmc_tree$tip.label[JQmc_tree$tip.label == "SF_1377_Hoplias_intermedius_brasiliensis"] <- "Hoplias brasiliensis"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_7880_Astyanax_lacustris"] <- "Astyanax lacustris"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_7893_Hypostomus_nigrolineatus"] <- "Hypostomus nigrolineatus"
JQmc_tree$tip.label[JQmc_tree$tip.label == "SF_1248_Gymnotus_carapo_JQ_1631"] <- "Gymnotus carapo"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_1936_Delturus_brevis"] <- "Delturus brevis"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_7817_Wertheimeria_maculata"] <- "Wertheimeria maculata"
JQmc_tree$tip.label[JQmc_tree$tip.label == "SF_1243_Trachelyopterus_galeatus_JQ_5675"] <- "Trachelyopterus galeatus"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_2996_Steindachneridion_amblyurum"] <- "Steindachneridion amblyurum"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_5645_Rhamdia_aff_quelen"] <- "Rhamdia quelen"
JQmc_tree$tip.label[JQmc_tree$tip.label == "JQ_6584_Australoheros_sp"] <- "Australoheros sp"
}

### check if all names have correspondences
JQmc_tree$tip.label %in% tab_curated_JQ$Species
tab_curated_JQ$Species %in% JQmc_tree$tip.label
tab_curated_JQ$Species[!tab_curated_JQ$Species %in% JQmc_tree$tip.label]




#invert branches to match Siluriformes position on the top


JQmc_tree$edge
JQmc_tree %>% as_tibble() %>% View()


JQmc_tree  %>% 
  ggtree() + 
  # geom_text(aes(label=node)) + 
  theme_tree2() +
  geom_tiplab(offset = 0,align = T)+ 
  xlim(0, 0.42)%>% 
  ggtree::flip(node1 = 21,node2 = 20)
 

rotateNodes(tree = JQmc_tree, "all") %>%
  ggtree() + 
  theme_tree2() +
  geom_tiplab(offset = 0,align = T)+ 
  xlim(0, 0.42)



### convert ape tree to prettier ggtree object
JQmc_tree_plot <- ggtree(JQmc_tree) + 
  theme_tree2() +
  geom_tiplab(offset = 0,align = T)+ 
  xlim(0, 0.42)


### save tree plot
# ggsave(file = "~/prjcts/fish_eDNA/sfjq/data/trees/JQmc-17_SPs_fused-unique-tree_plot.pdf", 
ggsave(file = "~/outros/sfjq_temp/trees/JQmc-17_SPs_fused-unique-tree_plot.pdf", 
       plot = JQmc_tree_plot, 
       device = "pdf", 
       width = 24, height = 24, 
       units = "cm", dpi = 600)



### extract tips order from tree to reproduce on plots
SPs_order_in_JQ_tree <- get_taxa_name(JQmc_tree_plot) %>% rev()

            # SPs_order_in_JQ_tree <- extract_tree_data(tree_plot) %>% 
            #     dplyr::filter(isTip) %>% 
            #     dplyr::pull(label)




## plots ----
### RRA histogram ----

JQmc_RRA_plot <-
  tab_curated_JQ %>%
    unite(Normalization, Primer, col = "Primer_norm",remove = F,sep = " ") %>%
  mutate(Primer_norm = factor(Primer_norm, levels = c("Normalized NeoFish","Normalized MiFish","Normalized Teleo","Non-normalized NeoFish","Non-normalized MiFish","Non-normalized Teleo"))) %>%
  mutate(Species = factor(Species,levels = SPs_order_in_JQ_tree)) %>% 
  ggplot(aes(y = Species,
             x = `RRA (%)`,
             fill = Primer_norm, 
             col = Normalization
             ))+
  geom_bar(stat = "identity", size = 0.3,width = 1,
           # alpha = 0.7,
           position = position_dodge(preserve = "single" ,width = 1.5)) +
           # position = position_dodgejust(preserve = "single" ,width = 1.2)) +
  scale_fill_manual(values = colors6[c(1,3,5,2,4,6)], name = "") +
  geom_point(aes(y = Species,
                 x = `input DNA (%)`,
             colour = Normalization),
             shape = "|",
             size = 3) +
    scale_color_manual(values = c("#747474","#000000")) +
  xlab("Relative read abundance (%)") 


## save plot 

# ggsave(file = "~/prjcts/fish_eDNA/sfjq/data/trees/JQmc-23_SPs_fused-unique-RRA_barplot.pdf", plot = JQmc_RRA_plot, device = "pdf", width = 24, height = 20, units = "cm", dpi = 600)
ggsave(file = "~/outros/sfjq_temp/trees/JQmc-17_SPs_fused-unique-RRA_barplot.pdf", plot = JQmc_RRA_plot, device = "pdf", width = 30, height = 30, units = "cm", dpi = 600)




#arvore ----


# SFJQmc_tree <- read.tree("~/prjcts/fish_eDNA/sfjq/data/12S_full_SFJQmc_fused_SPs_e_3_contams.nwk")




ggplot(SFJQmc_tree) + geom_tree() + theme_tree()

# This is convenient shorthand

# # tree_plot <- 
#   ggtree(SFJQmc_tree) + 
#   theme_tree2() +
#   geom_tiplab(offset = 0,align = T)+ 
#   xlim(0, 0.42) 

  
  tree_plot
  
  
  
    
#TODO create function to build double graph of tree and bars

  
  
# newick tree to plot along the graph
  tree4plot <- SFJQmc_tree

  
# table for ggplot to go alongside the tree (long format, can have factors)
  tbl4plot <- tab_curated_SFJQ
  
# plot to put by side (y axis must be the species in tree (column name == Species))
  plot4tree <- SFJQmc_RRA_plot
  
  
  
### generate plot from plylo object (.nwk read by ape::read.tree)
  

class(SFJQmc_tree)

tree4plot$edge.length %>% sort() %>% sum() 
tree4plot %>% str()


tree_plot$data

# tree_plot <-
  ggtree(tr = tree4plot,layout = "rectangular") +
  theme_tree2() +
  # geom_tiplab(offset = 0,align = T)+
  geom_tiplab(align = T)+
  xlim(0, 0.42)
  
  
### extract tips order from tree to reproduce on plots
SPs_order_in_tree <- ggtree::get_taxa_name(SFJQmc_tree_plot) %>% rev()
  
  
  
  plot4tree$data %>% 
    dplyr::mutate(Species = factor(Species, levels = SPs_order_in_tree))
    
  
  
    
    
    ## check tip names in tree
JQmc_tree$tip.label







### convert ape tree to prettier ggtree object
JQmc_tree_plot <- ggtree(JQmc_tree) + 
  theme_tree2() +
  geom_tiplab(offset = 0,align = T)+ 
  xlim(0, 0.42)
    
    
treeNbar_plot  <- function(){
    
  }  
  

# https://www.r-bloggers.com/2016/12/add-layer-to-specific-panel-of-facet_plot-output-2/
# facet_plot(tree_plot, panel = 'Stacked Barplot', 
#            data = tab_curated_SFJQ, geom = geom_histogram,
#            mapping = aes(x = Species,y =`RRA (%)`,  fill = as.factor(Primer)),
#            stat='identity',position = 'dodge' )
# 
# # 
# p3 <- facet_plot(tree_plot, panel='bar', data=tab_curated_SFJQ, geom=geom_bar, 
#                  aes(x=`RRA (%)`, y=Species,fill = Primer),
#                  stat = "identity",
#                  position = "dodge")


#https://oup.silverchair-cdn.com/oup/backfile/Content_public/Journal/mbe/35/12/10.1093_molbev_msy194/3/msy194_supp.pdf?Expires=1648204036&Signature=gZC6A1vfyaUWOyL~fKn8wxgY~3fbTBI3jPOGbVtwZSzv3jlXISjCahA37gwR3QTr6oN0SK-bdwAlHQyaPpkdj2~yi5scNQXAQrUi0EQNOqkOo3HUvFvCr-Dir2y7N03vIo5urr1n2idrPclTXtTRtiu7avn255T5eg~cXv0NBNUgiVFcwHHnZ81qQUrSdiA54wIvEs~RF18DYkp-Gla1CJT0eUGuYF8LfFXG5Dq1CgcZV0qGs0fKgfIKRlAT~AP25Xxkdh20RzAkqgBFvxp0JazrVOz5uvdok3uSu3023etErTxhaW7rm67VkCUBVxRgtG8GdFT3fOFJAsPg26Wagw__&Key-Pair-Id=APKAIE5G5CRDK6RD3PGA

# 
# tree_plot %<+% tab_curated_SFJQ + 
#   geom_histogram(aes(y = Species,
#                      x = `RRA (%)`,
#                      fill = Primer),
#                  stat = "identity",
#                  position = "dodge")

colnames(tab_curated_SFJQ)[colnames(tab_curated_SFJQ) == "Species"] <- "tip.label"



p2 <- 
  facet_plot(p = tree_plot, panel = "SNP", data = tab_curated_SFJQ, geom = geom_histogram,
                 mapping=aes(y = tip.label, x = `RRA (%)`, fill = Primer),
                 stat = "identity",
                 position = "dodge") +
# %>%
#   facet_plot("Trait", bar_data, ggstance::geom_barh,
#              aes(x = dummy_bar_value, color = location, fill = location),
#              stat = "identity", width = .6) +
  theme_tree2(legend.position=c(.05, .85))
print(p2)



p2 <- tree_plot + geom_facet(panel = "RRA (%)",
                       data = tab_curated_SFJQ,
                       geom = geom_bar,
                       mapping = aes(x=`RRA (%)`, fill = Primer),orientation = 'y',stat="identity")





extract_tree_data <- function(tree_disp, displayorder=TRUE) {
    td_out <- tree_disp$data
    if (displayorder) {
       td_out <- dplyr::arrange(td_out,y)
    }
    return(td_out)
}

SPs_order_in_tree <- extract_tree_data(tree_plot) %>% 
    dplyr::filter(isTip) %>% 
    dplyr::pull(label)

dendrograms of ASVs & db species

fold change standard deviation

References

This analyses were based and inpired on other incredible resources, listed below:


#Bonus

NeoFish redesign

This is a dinamic report, intended to show the current state of analyses. Many procedures and conclusions might change as the pipeline evolves. If you notice errors/mistakes/typos, or have any suggestions, we would be glad to know.

LS0tCnRpdGxlOiAiRE5BIG1ldGFiYXJjb2Rpbmcgb2YgbW9jayBjb21tdW5pdGllcyBoaWdobGlnaHRzIHBvdGVudGlhbCBiaWFzZXMgd2hlbiBhc3Nlc3NpbmcgTmVvdHJvcGljYWwgZmlzaCBkaXZlcnNpdHkiCmF1dGhvcjogCiAgLSAiSGlsw6FyaW8sIE9IOyBNZW5kZXMsIElTOyBTYWxlcywgTkc7IENhcnZhbGhvLCBEQyIKZGF0ZTogIjI3LzA3LzIwMjMiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgdGhlbWU6IGZsYXRseQogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKICAgIHRvY19mbG9hdDogdHJ1ZQogIGJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWIgCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMga25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCioqKgoKXHBhZ2VicmVhawoKCiMgQWJzdHJhY3QKCkRlc3BpdGUgdGhlIGluY3JlYXNpbmcgcG9wdWxhcml0eSBvZiBETkEgbWV0YWJhcmNvZGluZyBpbiB0aGUKYXNzZXNzbWVudCBvZiBhcXVhdGljIGVjb3N5c3RlbXMgdXNpbmcgZmlzaCBlRE5BIG9yIGljaHRoeW9wbGFua3RvbiwKY2hhbGxlbmdlcyBoYXZlIGhhbXBlcmVkIGl0cyBicm9hZGVyIGFwcGxpY2F0aW9uIGluIHRoZSBOZW90cm9waWNhbApmcmVzaHdhdGVycy4gVXNpbmcgZml2ZSBtb2NrIGNvbW11bml0aWVzIGNvbXBvc2VkIG9mIGZpc2ggc3BlY2llcyBmcm9tCnR3byBOZW90cm9waWNhbCByaXZlciBiYXNpbnMsIHdlIGV2YWx1YXRlZCB0aGUgaW5mbHVlbmNlIG9mIEROQQpjb25jZW50cmF0aW9uIGFuZCBjaG9pY2Ugb2YgbWl0b2Nob25kcmlhbCAxMlMgbW9sZWN1bGFyIG1hcmtlcnMKKE1pRmlzaCwgTmVvRmlzaCBhbmQgVGVsZW8pIG9uIHNwZWNpZXMgZGV0ZWN0aW9uIGFuZCBSZWxhdGl2ZSBSZWFkCkFidW5kYW5jZSAoUlJBKSB1c2luZyBETkEgbWV0YWJhcmNvZGluZy4gT2YgdGhlIHRocmVlIDEyUyBtYXJrZXJzCmFuYWx5c2VkLCBvbmx5IE1pRmlzaCBkZXRlY3RlZCBhbGwgc3BlY2llcyBmcm9tIGFsbCBtb2NrIGNvbW11bml0aWVzLgpUaGUgcGVyZm9ybWFuY2Ugb2YgYSB0YXhvbm9teS1mcmVlIGFwcHJvYWNoIHVzaW5nIEFTVi9NT1RVcyB3YXMKbm90IGFzIHByZWNpc2UgYXMgYXNzaWduaW5nIEROQSByZWFkcyB0byBzcGVjaWVzIHVzaW5nIGEgY3VyYXRlZCAxMlMKbGlicmFyeSB0aGF0IGluY2x1ZGVzIGFwcHJveGltYXRlbHkgMTAwIGZpc2ggc3BlY2llcywgc2luY2UgbW9yZSB0aGFuIG9uZQpBU1YvTU9UVSB3YXMgb2JzZXJ2ZWQgZm9yIHRoZSBzYW1lIHNwZWNpbWVuLiBUaHVzLCBoZXJlIHdlCnNob3djYXNlIHRoZSBpbXBvcnRhbmNlIG9mIGEgY3VzdG9tIHJlZmVyZW5jZSBkYXRhYmFzZSB0byBhbGxvdwpwcmVjaXNlIGFzc2lnbm1lbnQgb2YgTmVvdHJvcGljYWwgZmlzaCBzcGVjaWVzIGluIG1ldGFiYXJjb2Rpbmcgc3R1ZGllcwphbmQgdGhhdCB0aGUgUlJBIGlzIGRlcGVuZGVudCBvbiBjb21tdW5pdHkgY29tcG9zaXRpb24sIG1hcmtlciBhbmQKRE5BIGNvbmNlbnRyYXRpb24uIFdlIGhpZ2hsaWdodCB0aGUgaW1wb3J0YW5jZSBvZiBjb250cm9sbGVkCmV4cGVyaW1lbnRzIHVzaW5nIGtub3duIHNwZWNpZXMgY29tbXVuaXRpZXMgYmVmb3JlIGxhcmdlIGludmVzdG1lbnRzCmFyZSBtYWRlIGluIGFzc2Vzc2luZyBiaW9kaXZlcnNpdHkgdXNpbmcgbm9uLWludmFzaXZlIG1ldGhvZHMgdGhhdAphcHBseSBETkEgbWV0YWJhcmNvZGluZy4KCgoKIyBCaW9pbmZvcm1hdGljcwoKIyMgRGF0YSBhY3F1aXNpdG9uICAKCkRvd25sb2FkIGRlbXVsdGlwbGV4ZWQgc2FtcGxlcyBmcm9tIF9CYXNlIFNwYWNlXyB1c2luZyB0aGUgX2JzXyBpbnRlcmZhY2UuICAKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojbmF2aWdhdGUgdG8gcmF3LWRhdGEgZm9sZGVyCmNkICRyYXdfZGF0YV9mb2xkZXIvJHJ1bl9mb2xkZXI7CgojYXV0aGVudGljYXRlIHRvIEJhc2VTcGFjZSAob25seSBhdCBmaXJzdCBsb2cgaW4pCmJzIGF1dGg7CgojbGlzdCBkYXRhc2V0cyBmcm9tIHJ1bnMgb24geW91ciBCYXNlU3BhY2UKYnMgbGlzdCBkYXRhc2V0czsKCiNjcmVhdGUgZm9sZGVycyB0byBvcmdhbml6ZSBmYXN0cSBmaWxlcwpta2RpciB+L3J1bnMvcnVuXzAxbWFyMjEvZmFzdHEvOyAgICAgICAgI2VkbmEKbWtkaXIgfi9ydW5zL3J1bl8wOWZldjIxL2Zhc3RxLzsgICAgICAgICNlZG5hCm1rZGlyIH4vcnVucy9ydW5fMjlqdWwyMC9mYXN0cS87ICAgICAgICAjZWRuYQoKI2Rvd25sb2FkIHJ1bnMgZnJvbSBCYXNlU3BhY2UKYnMgZG93bmxvYWQgcHJvamVjdCAtbiBmaXNoX2VETkEgLW8gfi9ydW5zL3J1bl8yOWp1bDIwL2Zhc3RxLyAtLWV4dGVuc2lvbj1mYXN0cS5nejsgICAgICAgICAgI3ByaW1laXJhIGNvcnJpZGEgTEdDCmJzIGRvd25sb2FkIHByb2plY3QgLW4gZUROQV8ycnVuX0IgLW8gfi9ydW5zL3J1bl8wOWZldjIxL2Zhc3RxLyAtLWV4dGVuc2lvbj1mYXN0cS5nejsgICAgICAgICNzZWd1bmRhIGNvcnJpZGEgTEdDCmJzIGRvd25sb2FkIHByb2plY3QgLW4gaVNlcVJ1bjJfRGFuaWVsIC1vIH4vcnVucy9ydW5fMDFtYXIyMS9mYXN0cS8gLS1leHRlbnNpb249ZmFzdHEuZ3o7ICAgICNhbW9zdHJhcyBpU2VxIGVjb21vbAoKI29yZ2FuaXplIGFsbCBmYXN0cSBmaWxlcyBvZiBlYWNoIHJ1biBpbiBhIHNpbmdsZSBmb2xkZXIKbWtkaXIgfi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbDsKbWtkaXIgfi9ydW5zL3J1bl8wOWZldjIxL2Zhc3RxL2FsbDsKbWtkaXIgfi9ydW5zL3J1bl8yOWp1bDIwL2Zhc3RxL2FsbDsKCiNtb3ZlIGFsbCBmYXN0cWZpbGVzIHRvIGEgc2luZ2xlIGZvbGRlcgptdiB+L3J1bnMvcnVuXzAxbWFyMjEvZmFzdHEvKi8qZmFzdHEuZ3ogfi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbDsKbXYgfi9ydW5zL3J1bl8wOWZldjIxL2Zhc3RxLyovKmZhc3RxLmd6IH4vcnVucy9ydW5fMDlmZXYyMS9mYXN0cS9hbGw7Cm12IH4vcnVucy9ydW5fMjlqdWwyMC9mYXN0cS8qLypmYXN0cS5neiB+L3J1bnMvcnVuXzI5anVsMjAvZmFzdHEvYWxsOwoKYGBgCgo8YnI+CgojIyBMb2FkIF9SIGxpYnNfIGFuZCBzeXN0ZW0gcHJvZ3JhbXMKCmBgYHtyLCBldmFsPUZBTFNFLGVjaG89VFJVRX0KIyAwIC0gbG9hZCBsaWJyYXJpZXMgLS0tLQp7CiAgbGlicmFyeShkcGx5cikKICBsaWJyYXJ5KHRpZHlyKQogIGxpYnJhcnkodGliYmxlKQogIGxpYnJhcnkoc3RyaW5ncikKICBsaWJyYXJ5KGdncGxvdDIpCiAgbGlicmFyeShnZ2JyZWFrKQogIGxpYnJhcnkoZ2d0cmVlKQogIGxpYnJhcnkocGh5bG9zZXEpCiAgbGlicmFyeShCaW9zdHJpbmdzKQogIGxpYnJhcnkoTWF0cml4KQogIGxpYnJhcnkoU2hvcnRSZWFkKQogIGxpYnJhcnkoZGFkYTIpCiAgbGlicmFyeShERUNJUEhFUikKICBsaWJyYXJ5KGZ1dHVyZSkKICBsaWJyYXJ5KHZlZ2FuKQogIGxpYnJhcnkoYXBlKQogIGxpYnJhcnkocGhhbmdvcm4pCiAgbGlicmFyeShhZGVnZW5ldCkKfQoKI3NldCBjb21wbGV0ZSBwYXRoIHRvIGN1dGFkYXB0IGV4ZWN1dGFibGUKY3V0YWRhcHQgPC0gIi91c3IvbG9jYWwvYmluL2N1dGFkYXB0IgoKI2ltcG9ydGFudCAKcHJqY3RfcGF0aCA8LSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEiCgpub3Rlc19wYXRoIDwtIHBhc3RlMChwcmpjdF9wYXRoLCIvbm90ZXMiKQoKcmVzdWx0c19wYXRoIDwtIHBhc3RlMChwcmpjdF9wYXRoLCIvcmVzdWx0cyIpCgpmaWdzX3BhdGggPC0gcGFzdGUwKHJlc3VsdHNfcGF0aCwiL2ZpZ3MiKQoKcHJjal9yYWRpY2FsIDwtICJTRkpxX2Zpc2hfbWV0YWJhcmNvZGluZyIKI3BhdGggdG8gcHJvamVjdCBkYXRhIGZvbGRlciB3ZXJlIHRoZSBwcm9jZXNzZWQgcmVhZHMgd2lsbCBiZSBzdG9yZWQKZGF0YV9wYXRoIDwtIHBhc3RlMChwcmpjdF9wYXRoLCIvZGF0YS9yZWFkcyIpCgpgYGAKCjxicj4KCiMjIFF1YWxpdHkgY29udHJvbAoKQ2hlY2ggb3ZlcmFsbCBxdWFsaXR5IG9mIHNlcXVlbmNpbmcgcnVucyBmb3IgYWxsIHNhbXBsZXMKCmBgYHtiYXNoLCBldmFsPUZBTFNFLGVjaG89VFJVRX0KCgpgYGAKCjxicj4KCgojIyBEZW11bHRpcGxleCBTRkpRIHNhbXBsZSAoTWlGaXNoICYgTmVvRmlzaCBtaXhlZCkKCmBgYHtiYXNoLCBldmFsPUZBTFNFLGVjaG89VFJVRX0KI0RlbXVsdGlwbGV4IFNGSlEgc2FtcGxlIChNaUZpc2ggJiBOZW9GaXNoIG1peGVkKQojc2FtcGxlcyBNaW5pU2VxIExHQwpjdXRhZGFwdCAtaiA3OSAtLW5vLWluZGVscyAgLWcgZmlsZTp+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3ByaW1lcnNfbmVvX21pLmZhc3RhICAtRyBmaWxlOn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcHJpbWVyc19uZW9fbWkuZmFzdGEgIC1vIH4vcnVucy9ydW5fMDlmZXYyMS9mYXN0cS9hbGwvc2ZqcV9kbXgvU0ZKUS17bmFtZTF9LXtuYW1lMn1fUjFfMDAxLmZhc3RxLmd6ICAtcCB+L3J1bnMvcnVuXzA5ZmV2MjEvZmFzdHEvYWxsL3NmanFfZG14L1NGSlEte25hbWUxfS17bmFtZTJ9X1IyXzAwMS5mYXN0cS5neiAgfi9ydW5zL3J1bl8wOWZldjIxL2Zhc3RxL2FsbC9TRkpRLW5lby1taV9TMjNfTDAwMV9SMV8wMDEuZmFzdHEgIH4vcnVucy9ydW5fMDlmZXYyMS9mYXN0cS9hbGwvU0ZKUS1uZW8tbWlfUzIzX0wwMDFfUjJfMDAxLmZhc3RxIDI+IH4vcnVucy9ydW5fMDlmZXYyMS9mYXN0cS9hbGwvc2ZqcV9kbXgvY3V0X1NGSlFfZGVtdXgudHh0CgpjcCB+L3J1bnMvcnVuXzA5ZmV2MjEvZmFzdHEvYWxsL3NmanFfZG14L1NGSlEtbmVvX0ZXRC1uZW9fUkVWLiogfi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbC8KY3Agfi9ydW5zL3J1bl8wOWZldjIxL2Zhc3RxL2FsbC9zZmpxX2RteC9TRkpRLW1pZl9GV0QtbWlmX1JFVi4qIH4vcnVucy9ydW5fMDlmZXYyMS9mYXN0cS9hbGwvCgptdiB+L3J1bnMvcnVuXzAxbWFyMjEvZmFzdHEvYWxsL1NGSlEtbmVvLW1pX1MyM19MMDAxX1IqIH4vcnVucy9ydW5fMDFtYXIyMS9mYXN0cS9hbGwvc2ZqcV9kbXgvCgoKI3NhbXBsZXMgaVNlcSBFY29tb2wKY3V0YWRhcHQgLWogNzkgLS1uby1pbmRlbHMgIC1nIGZpbGU6fi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9wcmltZXJzX25lb19taS5mYXN0YSAgLUcgZmlsZTp+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3ByaW1lcnNfbmVvX21pLmZhc3RhICAtbyB+L3J1bnMvcnVuXzAxbWFyMjEvZmFzdHEvYWxsL3NmanFfZG14L0RhMjMte25hbWUxfS17bmFtZTJ9X1IxXzAwMS5mYXN0cS5neiAgLXAgfi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbC9zZmpxX2RteC9EYTIzLXtuYW1lMX0te25hbWUyfV9SMl8wMDEuZmFzdHEuZ3ogIH4vcnVucy9ydW5fMDFtYXIyMS9mYXN0cS9hbGwvRGEyM19TNzJfTDAwMV9SMV8wMDEuZmFzdHEgfi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbC9EYTIzX1M3Ml9MMDAxX1IyXzAwMS5mYXN0cSAyPiB+L3J1bnMvcnVuXzAxbWFyMjEvZmFzdHEvYWxsL3NmanFfZG14L2N1dF9TRkpRX2RlbXV4LnR4dAoKY3Agfi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbC9zZmpxX2RteC9EYTIzLW5lb19GV0QtbmVvX1JFVi4qIH4vcnVucy9ydW5fMDFtYXIyMS9mYXN0cS9hbGwvCmNwIH4vcnVucy9ydW5fMDFtYXIyMS9mYXN0cS9hbGwvc2ZqcV9kbXgvRGEyMy1taWZfRldELW1pZl9SRVYuKiB+L3J1bnMvcnVuXzAxbWFyMjEvZmFzdHEvYWxsLwoKbXYgfi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbC9EYTIzX1M3Ml9MMDAxX1IqIH4vcnVucy9ydW5fMDFtYXIyMS9mYXN0cS9hbGwvc2ZqcV9kbXgvCmBgYAoKIyMgU2V0IHBhdGggdG8gcmF3IGRhdGEKCmBgYHtyLCBldmFsPUZBTFNFLGVjaG89VFJVRX0KIzEgLSBsb2FkIHJ1bnMgcmF3IGRhdGEgLS0tLQojIyBBbGwgbGlicyBhcmUgZGVtdWx0aXBsZXhlZAp7CiAgIyBQQVRIIHRvIHRoZSBkaXJlY3RvcnkgY29udGFpbmluZyByYXcgZmFzdHEgZmlsZXMgYWZ0ZXIgdW56aXBwaW5nLgogIGxpYnNfcGF0aDEgPC0gIn4vcnVucy9ydW5fMjlqdWwyMC9mYXN0cS9hbGwiCiAgbGlic19wYXRoMiA8LSAifi9ydW5zL3J1bl8wOWZldjIxL2Zhc3RxL2FsbCIgCiAgbGlic19wYXRoMyA8LSAifi9ydW5zL3J1bl8wMW1hcjIxL2Zhc3RxL2FsbCIgCn0KI2NoZWNrIGNvbnRlbnQKbGlzdC5maWxlcyhwYXRoID0gbGlic19wYXRoMSxwYXR0ZXJuID0gImZhc3RxIikgCmxpc3QuZmlsZXMocGF0aCA9IGxpYnNfcGF0aDIscGF0dGVybiA9ICJmYXN0cSIpIApsaXN0LmZpbGVzKHBhdGggPSBsaWJzX3BhdGgzLHBhdHRlcm4gPSAiZmFzdHEiKSAKCmBgYAoKIyMjIElkZW50aWZ5IHNhbXBsZSBuYW1lcyByYWRpY2FscwoKYGBge3IsIGV2YWw9RkFMU0UsZWNobz1UUlVFfQojMiAtIGdldCBzYW1wbGUgbmFtZXMgLS0tLQoKIyBGb3J3YXJkIGFuZCByZXZlcnNlIGZhc3RxIGZpbGVuYW1lcyBoYXZlIGZvcm1hdDogU0FNUExFTkFNRV9SMV8wMDEuZmFzdHEgYW5kIFNBTVBMRU5BTUVfUjJfMDAxLmZhc3RxCnsKICBhbGxfZm5GczEgPC0gc29ydChsaXN0LmZpbGVzKGxpYnNfcGF0aDEsIHBhdHRlcm49Il9SMV8wMDEuZmFzdHEiLCBmdWxsLm5hbWVzID0gVFJVRSkpCiAgYWxsX2ZuUnMxIDwtIHNvcnQobGlzdC5maWxlcyhsaWJzX3BhdGgxLCBwYXR0ZXJuPSJfUjJfMDAxLmZhc3RxIiwgZnVsbC5uYW1lcyA9IFRSVUUpKQoKICBhbGxfZm5GczIgPC0gc29ydChsaXN0LmZpbGVzKGxpYnNfcGF0aDIsIHBhdHRlcm49Il9SMV8wMDEuZmFzdHEiLCBmdWxsLm5hbWVzID0gVFJVRSkpCiAgYWxsX2ZuUnMyIDwtIHNvcnQobGlzdC5maWxlcyhsaWJzX3BhdGgyLCBwYXR0ZXJuPSJfUjJfMDAxLmZhc3RxIiwgZnVsbC5uYW1lcyA9IFRSVUUpKQoKICBhbGxfZm5GczMgPC0gc29ydChsaXN0LmZpbGVzKGxpYnNfcGF0aDMsIHBhdHRlcm49Il9SMV8wMDEuZmFzdHEiLCBmdWxsLm5hbWVzID0gVFJVRSkpCiAgYWxsX2ZuUnMzIDwtIHNvcnQobGlzdC5maWxlcyhsaWJzX3BhdGgzLCBwYXR0ZXJuPSJfUjJfMDAxLmZhc3RxIiwgZnVsbC5uYW1lcyA9IFRSVUUpKQoKICBhbGxfZm5GcyA8LSBjKGFsbF9mbkZzMSxhbGxfZm5GczIsYWxsX2ZuRnMzKQogIGFsbF9mblJzIDwtIGMoYWxsX2ZuUnMxLGFsbF9mblJzMixhbGxfZm5SczMpCn0KI2xvYWQgY3N2IHdpdGggcHJpbWVycyBhbmQgcmVzcGVjdGl2ZSBzYW1wbGVzCnByaW1lcnNfbl9zYW1wbGVzIDwtIHJlYWQuY3N2KGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9wcmltZXJzX25fc2FtcGxlc19zZmpxLmNzdiIsCiAgICAgICAgIGhlYWRlciA9IFRSVUUpCgoKIzMgLSBtYXAgc2FtcGxlIG5hbWVzIHRvIHJlYWRzIGZpbGVzIC0tLS0KcHJpbWVyc19uX3NhbXBsZXMgPC0gcHJpbWVyc19uX3NhbXBsZXMgJT4lCiAgbXV0YXRlKCJSMSIgPSAiUjEiLAogICAgICAgICAiUjIiID0gIlIyIikKCmZvciAoc2FtcGxlIGluIDE6bnJvdyhwcmltZXJzX25fc2FtcGxlcykpIHsKICAKICBwcmltZXJzX25fc2FtcGxlcyRSMVtzYW1wbGVdIDwtCiAgIGFsbF9mbkZzW2dyZXAocGF0dGVybiA9ICBwYXN0ZTAoIi8iLHByaW1lcnNfbl9zYW1wbGVzJEZpbGVfbmFtZVtzYW1wbGVdKSx4ID0gYWxsX2ZuRnMpXQogIAogIHByaW1lcnNfbl9zYW1wbGVzJFIyW3NhbXBsZV0gPC0KICAgYWxsX2ZuUnNbZ3JlcChwYXR0ZXJuID0gIHBhc3RlMCgiLyIscHJpbWVyc19uX3NhbXBsZXMkRmlsZV9uYW1lW3NhbXBsZV0pLHggPSBhbGxfZm5ScyldCgp9CgpgYGAKCjxicj4KCiMjIyBEZWZpbmUgc2FtcGxlIGxldmVscwpgYGB7ciwgZXZhbD1GQUxTRSxlY2hvPVRSVUV9CiM0IC0gc2V0IHNhbXBsZSBsZXZlbHMKcHJpbWVyc19uX3NhbXBsZXMkRmlsZV9uYW1lCgpzYW1wbGVfbGV2ZWxzIDwtIGMoCiJEYTIzLW1pZiIsICJTRkpRLW1pZiIsCiJEYTIzLW5lbyIsICJTRkpRLW5lbyIsCiJEYTIwIiwiU0ZuTm9ybS1taSIsCiJEYTE5IiwiU0ZuTm9ybS1uZW8iLAoiRGEyMiIsIlNGTm9ybS1taSIsCiJEYTIxIiwiU0ZOb3JtLW5lbyIsCiJwSmVxdWVpLU4tbm9ybS1OIiwicEplcXVlaS1OLW5vcm0tTSIsInBKZXF1ZWktTi1ub3JtLVQiLAoicEplcXVlaS1ub3JtLU4iLCJwSmVxdWVpLW5vcm0tTSIsInBKZXF1ZWktbm9ybS1UIiwKIkNhc3NhdW0iLCJuZWctUENSMiIpCgpwcmltZXJfbGV2ZWxzIDwtIGMoIk5lb0Zpc2giLCAiTWlGaXNoIiwgIlRlbGVvIiwiTmVvRmlzaC9NaUZpc2giLCAiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKQoKYGBgCjxicj4KIyMjIFJlbW92ZSBwcmltZXJzIGZyb20gcmVhZHMKICAKQXMgdGhlIHByaW1lci1kZXJpdmVkIHNlcXVlbmNlcyBhcmUgaWRlbnRpY2FsLCB0aGV5IGFyZSBub3QgaW5mb3JtYXRpdmUgYW5kIHRodXMgbXVzdCBiZSByZW1vdmVkIGZvciB0aGUgZm9sbG93aW5nIHN0ZXBzLgoKPGJyPgoKIyMjIyBMb2FkIHByaW1lciBzZXF1ZW5jZXMKCmBgYHtyLCBldmFsPUZBTFNFLGVjaG89VFJVRX0KIzQtIGlkZW50aWZ5IHByaW1lcnMgLS0tLQoKI3ByaW1lcnMgc2VxdWVuY2VzIHVzZWQgZm9yIGVhY2ggc2FtcGxlCiMgaW5vc2luZSBwYWlycyB3aXRoIEEsIEMsIFUKIyAgICAgICAgICAgICAgICAgICAgVCwgRywgQSA9IElVUEFDIGNvZGU6ICBECiNjdXRhZGFwdCAgYWNjZXB0cyBJVVBBQyBjb2RlICEhISEhISEhCnsKICAjbmVvCiAgbmVvX0ZXRCA8LSAiQ0dDQ0dUQ0dDQUFHQ1RUQUNDQ1QiCiAgbmFtZXMobmVvX0ZXRCkgPC0gIm5lb19GV0QiCiAgbmVvX1JFViA8LSAiQUdUR0FDR0dHQ0dHVEdUR1RHQyIKICBuYW1lcyhuZW9fUkVWKSA8LSAibmVvX1JFViIgCiAgCiAgI21pZgogIG1pZl9GV0QgPC0gIkdUQ0dHVEFBQUFDVENHVEdDQ0FHQyIKICBuYW1lcyhtaWZfRldEKSA8LSAibWlmX0ZXRCIKICBtaWZfUkVWIDwtICJBQ0FUQUdUR0dHR1RBVENUQUFUQ0NDQUdUVFRHIgogIyBtaWZfUkVWIDwtICJDQVRBR1RHR0dHVEFUQ1RBQVRDQ0NBR1RUVEciICNvcmlnaW5hbAogIG5hbWVzKG1pZl9SRVYpIDwtICJtaWZfUkVWIiAKICAKICAjdGVsCiAgdGVsX0ZXRCA8LSAiQUNBQ0NHQ0NDR1RDQUNUQ1QiCiAgbmFtZXModGVsX0ZXRCkgPC0gInRlbF9GV0QiCiAgdGVsX1JFViA8LSAiQUNUVENDR0dUQUNBQ1RUQUNDQVRHIgogIG5hbWVzKHRlbF9SRVYpIDwtICJ0ZWxfUkVWIiAgCiAgCiAgCiNjcmVhdGVzIGEgbGlzdCBvZiBzaW5nbGUgcm93IHRpYmJsZXMgZm9yIGVhY2ggcHJpbWVyCnByaW1lcnMgPC0gdGliYmxlKFByaW1lcnMgPSBjKG5lb19GV0QsbmVvX1JFViwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlmX0ZXRCxtaWZfUkVWLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZWxfRldELHRlbF9SRVYpKSAlPiUgCiAgbXV0YXRlKGBQcmltZXIgbmFtZXNgPSBuYW1lcyhQcmltZXJzKSkgJT4lIAogIHNwbGl0KDE6bnJvdyguKSkKfQpgYGAKCjxicj4KCiMjIyMgR2VuZXJhdGUgc2VxdWVuY2VzIGZvciBjb21wbGVtZW50LCByZXZlcnNlLCBhbmQgcmV2ZXJzZSBjb21wbGVtZW50IGZvciBlYWNoIHByaW1lcgogIApUaGUgZnVuY3Rpb24gX2FsbE9yaWVudHNfIGlzIHVzZWQgdG8gZ2VuZXJhdGUgYWxsIHBvc3NpYmxlIG9yaWVudGF0aW9ucyBmb3IgcHJpbWVycyBGV0QgZSBSRVYuCgpgYGB7ciBldmFsPUZBTFNFLGVjaG89VFJVRX0KIzUgLSBjaGVjayBwcmltZXIgb3JpZW50YXRpb24gLS0tLQoKI2Z1bmN0aW9uIHRvIGdldCBhbGwgcG9zc2libGUgcHJpbWVyIG9yaWVudGF0aW9ucwphbGxPcmllbnRzIDwtIGZ1bmN0aW9uKHByaW1lcnMpIHsKICAgIyBDcmVhdGUgYWxsIG9yaWVudGF0aW9ucyBvZiB0aGUgaW5wdXQgc2VxdWVuY2UKICAgICMgTXVzdCBiZSBhIHRpYmJsZSB3aXRoIGNvbHMgPSBjKFByaW1lcnMsYFByaW1lciBuYW1lc2ApCiAgCiAgIHJlcXVpcmUoQmlvc3RyaW5ncykKICAgZG5hIDwtIEJpb3N0cmluZ3M6OkROQVN0cmluZyhwcmltZXJzJFByaW1lcnMpICAjIFRoZSBCaW9zdHJpbmdzIHdvcmtzIHcvIEROQVN0cmluZyBvYmplY3RzIHJhdGhlciB0aGFuIGNoYXJhY3RlciB2ZWN0b3JzCiAgIG9yaWVudHMgPC0gYyhGb3J3YXJkID0gZG5hLCAKICAgICAgICAgICAgICAgIENvbXBsZW1lbnQgPSBCaW9zdHJpbmdzOjpjb21wbGVtZW50KGRuYSksIAogICAgICAgICAgICAgICAgUmV2ZXJzZSA9IEJpb3N0cmluZ3M6OnJldmVyc2UoZG5hKSwKICAgICAgICAgICAgICAgIFJldkNvbXAgPSBCaW9zdHJpbmdzOjpyZXZlcnNlQ29tcGxlbWVudChkbmEpKQogICBuYW1lcyhvcmllbnRzKSA8LSBwYXN0ZTAobmFtZXMob3JpZW50cykpCiAgIAogICBwcmltZXJfdGJsIDwtIHNhcHBseShvcmllbnRzLCB0b1N0cmluZykKICAgCiAgIHByaW1lcl90YmwgPC0gZHBseXI6OnRpYmJsZShTZXF1ZW5jZSA9IHByaW1lcl90YmwsCiAgICAgICAgICAgICAgICAgICAgICAgIGBQcmltZXIgb3JpZW50YXRpb25gID0gbmFtZXMocHJpbWVyX3RibCkpICU+JSAKICAgICBkcGx5cjo6bXV0YXRlKFByaW1lciA9IHByaW1lcnMkYFByaW1lciBuYW1lc2ApICU+JQogICAgIHVuaXRlKGNvbD1gT3JpZW50YXRpb24gbmFtZWAsIFByaW1lciAsYFByaW1lciBvcmllbnRhdGlvbmAscmVtb3ZlID0gRkFMU0UpCiAgIAogICByZXR1cm4ocHJpbWVyX3RibCkgICMgQ29udmVydCBiYWNrIHRvIGNoYXJhY3RlciB2ZWN0b3IKfQoKCiNhcHBseSBmdW5jdGlvbiAKcHJpbWVyc19hbGxfb3JpZW50cyA8LSBwdXJycjo6bWFwX2RmcihwcmltZXJzLCBhbGxPcmllbnRzKQoKbmFtZXMocHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZSkgPC0gcHJpbWVyc19hbGxfb3JpZW50cyRgT3JpZW50YXRpb24gbmFtZWAKCmBgYAoKPGJyPgoKIyMjIyBSZW1vdmUgcmVhZHMgd2l0aCB1bmRldGVybWluZWQgYmFzZXMgKiooTnMpKiogYW5kIHVucGFpcmVkCgpSZWFkcyB3aXRoIHVuZGV0ZXJtaW5lZCBiYXNlcyBwcmV2ZW50IHByb3BlciBwcmltZXIgaWRlbnRpZmljYXRpb24gYW5kIEFTViBkZXRlcm1pbmF0aW9uLiBUaGVzZSBzZXF1ZW5jZXMgbXVzdCBiZSByZW1vdmVkIGZyb20gdGhlIGRhdGEuCgpgYGB7ciBldmFsPUZBTFNFfQojNiAtIHByZSBmaWx0ZXIgcmVhZHMgd2l0aCBOcyBmb3IgcHJpbWVyIGNoZWNraW5nIC0tLS0KIyBjcmVhdGUgbmFtZXMgZm9yIE4tY2xlYW5lZCBmaWxlcwoKcHJpbWVyc19uX3NhbXBsZXMgPC0gcHJpbWVyc19uX3NhbXBsZXMgJT4lCiAgbXV0YXRlKCJSMSBOLWNsZWFuZWQiID0gIlIxIE4tY2xlYW5lZCIsCiAgICAgICAgICJSMiBOLWNsZWFuZWQiID0gIlIyIE4tY2xlYW5lZCIpCgpmb3IgKHNhbXBsZSBpbiAxOm5yb3cocHJpbWVyc19uX3NhbXBsZXMpKSB7CiAgcHJpbWVyc19uX3NhbXBsZXMkYFIxIE4tY2xlYW5lZGBbc2FtcGxlXSA8LQogICBwYXN0ZTAoZGF0YV9wYXRoLCIvTi1jbGVhbmVkLyIscHJpbWVyc19uX3NhbXBsZXMkRmlsZV9uYW1lW3NhbXBsZV0sIl9SMV9OLWNsZWFuZWQuZmFzdHEuZ3oiKQogIHByaW1lcnNfbl9zYW1wbGVzJGBSMiBOLWNsZWFuZWRgW3NhbXBsZV0gPC0KICAgcGFzdGUwKGRhdGFfcGF0aCwiL04tY2xlYW5lZC8iLHByaW1lcnNfbl9zYW1wbGVzJEZpbGVfbmFtZVtzYW1wbGVdLCJfUjJfTi1jbGVhbmVkLmZhc3RxLmd6IikKfQoKIyByZW1vdmUgcmVhZHMgd2l0aCBOcyB0byBtYWtlIHByaW1lciBmaWx0ZXJpbmcgbW9yZSBhY2N1cmF0ZQoKZGFkYTI6OmZpbHRlckFuZFRyaW0oCiAgZndkID0gcHJpbWVyc19uX3NhbXBsZXMkUjEsIGZpbHQgPSBwcmltZXJzX25fc2FtcGxlcyRgUjEgTi1jbGVhbmVkYCwgCiAgcmV2ID0gcHJpbWVyc19uX3NhbXBsZXMkUjIsIGZpbHQucmV2ID0gcHJpbWVyc19uX3NhbXBsZXMkYFIyIE4tY2xlYW5lZGAsCiAgbWF4TiA9IDAsIG11bHRpdGhyZWFkID0gVFJVRSwgbWF0Y2hJRHMgPSBUUlVFLAogIHZlcmJvc2UgPSBUUlVFLCBjb21wcmVzcyA9IFRSVUUpCgojIHBpdm90ZSB0YWJsZSB0byBsb25nZXIgZm9ybWF0CnByaW1lcnNfbl9zYW1wbGVzIDwtIHByaW1lcnNfbl9zYW1wbGVzICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoUjEsUjIsYFIxIE4tY2xlYW5lZGAsYFIyIE4tY2xlYW5lZGApLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJTdGFnZSIsIHZhbHVlc190byA9ICJSZWFkIGZpbGUiKQoKYGBgCgo8YnI+CgojIyMjIENvdW50IHByaW1lciBwcmVzZW5jZSBvbiByZWFkcwoKQmVmb3JlIHByaW1lciByZW1vdmFsIGl0IGlzIHBvc3NpYmxlIHRvIGNvdW50IHRoZWlyIHByZXNlbmNlIG9uIHRoZSByZWFkcy4gVGhpcyBwcm9jZWR1cmVzIGlzIGNhcnJpZWQgb24gaW5kZXBlbmRlbnRseSBmb3IgZWFjaCBzYW1wbGUuIAoKYGBge3IgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiM2IC0gY291bnQgcHJpbWVyIG9yaWVudGF0aW9uIGhpdHMgLS0tLQoKI2Z1bmN0aW9uIHRvIGNvdW50IHByaW1lciBvbiBlYWNoIHNwZWNpZmljIGxpYnJhcnkKcHJpbWVySGl0cyA8LSBmdW5jdGlvbihwcmltZXIsIGZuKSB7CiAgICMgQ291bnRzIG51bWJlciBvZiByZWFkcyBpbiB3aGljaCB0aGUgcHJpbWVyIGlzIGZvdW5kCiAgIG5oaXRzIDwtIEJpb3N0cmluZ3M6OnZjb3VudFBhdHRlcm4ocHJpbWVyLCBTaG9ydFJlYWQ6OnNyZWFkKFNob3J0UmVhZDo6cmVhZEZhc3RxKGZuKSksIGZpeGVkID0gRkFMU0UpCiAgIHJldHVybihzdW0obmhpdHMgPiAwKSkKfQoKI2Z1bmN0aW9uIHRvIGNhbGwgcHJpbWVySGl0cyBmb3IgbXVsdGlwbGUgcHJpbWVycwptdWx0aV9wcmltZXJIaXRzIDwtIGZ1bmN0aW9uKFJlYWRfZmlsZSxwcmltZXJzKXsKICBwcmltZXJfY291bnRzIDwtIHB1cnJyOjptYXBfZGYocHJpbWVycywuZiA9IHByaW1lckhpdHMsIGZuID0gUmVhZF9maWxlKQogIHByaW1lcl9jb3VudHMgPC0gcHJpbWVyX2NvdW50cyAlPiUgIG11dGF0ZShgUmVhZCBmaWxlYCA9IFJlYWRfZmlsZSkKICByZXR1cm4ocHJpbWVyX2NvdW50cykKfQojIyMjIyMjIyMjIwoKI3ZlY3RvciBvZiByZWFkIGZpbGVzIHRvIGxvb2sgb24gZm9yIHByaW1lcnMKcmVhZHNfc2VxcyA8LSBwcmltZXJzX25fc2FtcGxlcyAlPiUgCiAgZmlsdGVyKFN0YWdlICVpbiUgYygiUjEgTi1jbGVhbmVkIiwgIlIyIE4tY2xlYW5lZCIpKSAlPiUgCiAgc2VsZWN0KGBSZWFkIGZpbGVgKSAlPiUgYXMubGlzdCgpCiAKCiNuYW1lZCB2ZWN0b3Igb2YgcHJpbWVyIHNlcXVlbmNlcwpwcmltZXJzX3NlcXMgPC0gcHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZQoKCmNvcmVzX3RvX2JlX3VzZWQgPC0gZnV0dXJlOjphdmFpbGFibGVDb3JlcygpIC0gMiAjIFVzYXIgdG9kb3Mgb3MgY29yZXMgLTIgPSA3OAoKZnV0dXJlOjpwbGFuKGZ1dHVyZTo6bXVsdGlzZXNzaW9uKHdvcmtlcnMgPSBjb3Jlc190b19iZV91c2VkKSkKCgojY291bnQgcHJpbWVycwpwcmltZXJzX2luX05yZWFkcyA8LSBmdXJycjo6ZnV0dXJlX21hcF9kZnIocmVhZHNfc2VxcyRgUmVhZCBmaWxlYCwgLmYgPSBtdWx0aV9wcmltZXJIaXRzLCBwcmltZXJzID0gcHJpbWVyc19zZXFzLCAub3B0aW9ucyA9IGZ1cnJyOjpmdXJycl9vcHRpb25zKHNlZWQgPSBOVUxMKSkKCiNnZXQgc2FtcGxlIGluZm9ybWF0aW9uIGludG8gcHJpbWVyc19pbl9OcmVhZHMgdGFibGUKcHJpbWVyc19pbl9OcmVhZHMgPC0gbGVmdF9qb2luKHByaW1lcnNfaW5fTnJlYWRzLHByaW1lcnNfbl9zYW1wbGVzLGJ5ID0gIlJlYWQgZmlsZSIpCgojIAojIHByaW1lcnNfaW5fTnJlYWRzX2Jja3AgPC0gcHJpbWVyc19pbl9OcmVhZHMKIyBwcmltZXJzX2luX05yZWFkcyA8LSBwcmltZXJzX2luX05yZWFkc19iY2twCgpgYGAKCiMjIyMgUHJlcGFyZSBwcmltZXIgY291bnRzIGZvciBwbG90aW5nCgpgYGB7ciwgZWNobz1UUlVFLGV2YWw9RkFMU0V9CiM3LSBwcmVwYXJlIHByaW1lciBjb3VudHMgZm9yIHBsb3RzIC0tLS0KCiMgY2F0KHBhc3RlMChjb2xuYW1lcyhwcmltZXJzX2luX05yZWFkcyksIlxuIikpCgpwcmltZXJzX2luX05yZWFkcyA8LQogIHByaW1lcnNfaW5fTnJlYWRzICU+JSAKICBzZWxlY3QoIyBgUmVhZCBmaWxlCiBGaWxlX25hbWUsIFR5cGUsIEdyb3VwLCBMaWJyYXJ5LCBQcmltZXIsIFJ1biwgU3RhZ2UsCiAgICAgICAgIG5lb19GV0RfRm9yd2FyZCwgbmVvX1JFVl9Gb3J3YXJkLCBuZW9fRldEX0NvbXBsZW1lbnQsIG5lb19SRVZfQ29tcGxlbWVudCwgCiAgICAgICAgIG5lb19GV0RfUmV2ZXJzZSwgbmVvX1JFVl9SZXZlcnNlLCBuZW9fRldEX1JldkNvbXAsIG5lb19SRVZfUmV2Q29tcCwgCiAgICAgICAgIG1pZl9GV0RfRm9yd2FyZCwgbWlmX1JFVl9Gb3J3YXJkLCBtaWZfRldEX0NvbXBsZW1lbnQsIG1pZl9SRVZfQ29tcGxlbWVudCwgCiAgICAgICAgIG1pZl9GV0RfUmV2ZXJzZSwgbWlmX1JFVl9SZXZlcnNlLCBtaWZfRldEX1JldkNvbXAsIG1pZl9SRVZfUmV2Q29tcCwgCiAgICAgICAgIHRlbF9GV0RfRm9yd2FyZCwgdGVsX1JFVl9Gb3J3YXJkLCB0ZWxfRldEX0NvbXBsZW1lbnQsIHRlbF9SRVZfQ29tcGxlbWVudCwgCiAgICAgICAgIHRlbF9GV0RfUmV2ZXJzZSwgdGVsX1JFVl9SZXZlcnNlLCB0ZWxfRldEX1JldkNvbXAsIHRlbF9SRVZfUmV2Q29tcCkKCgojd3JpdGUuY3N2KHggPSBwcmltZXJfaGl0c190YmwsIGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL25vdGVzL2plcXVpRE5BcG9vbC9jc3YvcHJpbWVyc19oaXRzX2luX3JlYWRzLmNzdiIpCgpzdHIocHJpbWVyc19pbl9OcmVhZHMpCmNvbG5hbWVzKHByaW1lcnNfaW5fTnJlYWRzKQpyb3duYW1lcyhwcmltZXJzX2luX05yZWFkcykKCnByaW1lcnNfaW5fTnJlYWRzJFByaW1lcgpwcmltZXJzX2luX05yZWFkcyRMaWJyYXJ5CgoKIzgtIHByZXBhcmUgcHJpbWVyIGNvdW50cyBmb3IgcGxvdHMgaW4gZ2dwbG90LS0tLQoKI2NvbnZlcnQgcHJpbWVyIGhpdHMgdGFibGUgdG8gbG9uZyBmb3JtYXQKcHJpbWVyc19pbl9OcmVhZHNfbG9uZyA8LSBwcmltZXJzX2luX05yZWFkcyAlPiUgCiAgZ2F0aGVyKGtleSA9IFNlcXVlbmNlcywgCiAgICAgICAgIHZhbHVlID0gQ291bnQsICAKICAgICAgICAgbmVvX0ZXRF9Gb3J3YXJkLCBuZW9fRldEX0NvbXBsZW1lbnQsIG5lb19GV0RfUmV2ZXJzZSxuZW9fRldEX1JldkNvbXAsIAogICAgICAgICBuZW9fUkVWX0ZvcndhcmQsIG5lb19SRVZfQ29tcGxlbWVudCwgbmVvX1JFVl9SZXZlcnNlLCBuZW9fUkVWX1JldkNvbXAsCiAgICAgICAgIG1pZl9GV0RfRm9yd2FyZCwgbWlmX0ZXRF9Db21wbGVtZW50LCBtaWZfRldEX1JldmVyc2UsIG1pZl9GV0RfUmV2Q29tcCwgCiAgICAgICAgIG1pZl9SRVZfRm9yd2FyZCwgbWlmX1JFVl9Db21wbGVtZW50LCBtaWZfUkVWX1JldmVyc2UsIG1pZl9SRVZfUmV2Q29tcCwKICAgICAgICAgdGVsX0ZXRF9Gb3J3YXJkLCB0ZWxfRldEX0NvbXBsZW1lbnQsIHRlbF9GV0RfUmV2ZXJzZSwgdGVsX0ZXRF9SZXZDb21wLCAKICAgICAgICAgdGVsX1JFVl9Gb3J3YXJkLCB0ZWxfUkVWX0NvbXBsZW1lbnQsIHRlbF9SRVZfUmV2ZXJzZSwgdGVsX1JFVl9SZXZDb21wCiAgICAgICAgICkgJT4lIAogIG11dGF0ZShTZXF1ZW5jZXMgPSBmYWN0b3IoU2VxdWVuY2VzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygibmVvX0ZXRF9Gb3J3YXJkIiwibmVvX0ZXRF9SZXZDb21wIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5lb19SRVZfRm9yd2FyZCIsIm5lb19SRVZfUmV2Q29tcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJuZW9fRldEX0NvbXBsZW1lbnQiLCJuZW9fRldEX1JldmVyc2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibmVvX1JFVl9Db21wbGVtZW50IiwibmVvX1JFVl9SZXZlcnNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWlmX0ZXRF9Gb3J3YXJkIiwibWlmX0ZXRF9SZXZDb21wIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1pZl9SRVZfRm9yd2FyZCIsIm1pZl9SRVZfUmV2Q29tcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtaWZfRldEX0NvbXBsZW1lbnQiLCJtaWZfRldEX1JldmVyc2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWlmX1JFVl9Db21wbGVtZW50IiwibWlmX1JFVl9SZXZlcnNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidGVsX0ZXRF9Gb3J3YXJkIiwidGVsX0ZXRF9SZXZDb21wIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRlbF9SRVZfRm9yd2FyZCIsInRlbF9SRVZfUmV2Q29tcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0ZWxfRldEX0NvbXBsZW1lbnQiLCJ0ZWxfRldEX1JldmVyc2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidGVsX1JFVl9Db21wbGVtZW50IiwidGVsX1JFVl9SZXZlcnNlIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgIEZpbGVfbmFtZSA9IGZhY3RvcihGaWxlX25hbWUsbGV2ZWxzID0gc2FtcGxlX2xldmVscyksCiAgICAgICAgIFJ1biA9IGFzLmZhY3RvcihSdW4pLAogICAgICAgICBQcmltZXIgPSBmYWN0b3IoUHJpbWVyLGxldmVscyA9IGMoIk5lb0Zpc2giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1pRmlzaCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGVsZW8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5lb0Zpc2gvTWlGaXNoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZW9GaXNoL01pRmlzaC9UZWxlbyIpKSkgCgoKCiMgUExPVCAxOiBwcmltZXJzIGNvdW50cyBpbiByZWFkcyB0aWxlIHBsb3QgLSBvbmx5IHByaW1lcnMgRldEICYgUkVWLCBmb3dhcmQgJiByZXZjb21wIC0tLS0KcHJpbWVyc190aWxlIDwtIAogIHByaW1lcnNfaW5fTnJlYWRzX2xvbmcgJT4lIAogICMgZmlsdGVyKFNlcXVlbmNlcyAgJWluJSBjKAogICMgICAibWlmX1JFVl9SZXZDb21wIiwgIm1pZl9SRVZfRm9yd2FyZCIsICJtaWZfRldEX1JldkNvbXAiLCAibWlmX0ZXRF9Gb3J3YXJkIiwKICAjICAgIm5lb19SRVZfUmV2Q29tcCIsICJuZW9fUkVWX0ZvcndhcmQiLCAibmVvX0ZXRF9SZXZDb21wIiwgIm5lb19GV0RfRm9yd2FyZCIsCiAgIyAgICJ0ZWxfUkVWX1JldkNvbXAiLCAidGVsX1JFVl9Gb3J3YXJkIiwgInRlbF9GV0RfUmV2Q29tcCIsICJ0ZWxfRldEX0ZvcndhcmQiKSkgJT4lIAogIG11dGF0ZShGaWxlX25hbWUgPSBmYWN0b3IoRmlsZV9uYW1lLGxldmVscyA9IHNhbXBsZV9sZXZlbHMpKSAlPiUgCiAgZ2dwbG90Mjo6Z2dwbG90KGFlcyh5PUZpbGVfbmFtZSx4PVNlcXVlbmNlcyxmaWxsPWxvZzEwKENvdW50KQogICAgICAgICAgICAgICAgICAgICAgIyAsY29sPVN0YWdlCiAgICAgICAgICAgICAgICAgICAgICApKSArCiAgZ2VvbV90aWxlKCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IENvdW50KSxzaXplPTEpKwogICMgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9IndoaXRlIiwgaGlnaD0iZGFya2dyZWVuIix0cmFucz0ibG9nMTAiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4obmFtZSA9ICJQcmltZXIgY291bnRzIiwKICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXJzID0gYygid2hpdGUiLCJkYXJrZ3JlZW4iKSwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKDAsMSksCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSJ3aGl0ZSIpICsKICB0aGVtZV9saWdodChiYXNlX2xpbmVfc2l6ZSA9IDEsYmFzZV9zaXplID0gNikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsaGp1c3QgPSAxKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGMoNDAuNSw4Mi41LDg2LjUsMTE2LjUpLGNvbG9yID0gImdyZXkiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYyg0LjUsOC41LDEyLjUsMTYuNSksY29sb3IgPSAiZ3JleSIpICsKICAjIGNvb3JkX2ZpeGVkKHJhdGlvID0gMC4yMCkgKwogIHhsYWIoIlByaW1lcnMiKSArCiAgeWxhYigiQW1vc3RyYSIpICsKICBnZ3RpdGxlKGxhYmVsID0gImVETkEgMXN0LCAybmQgJiAzcmQgcnVucyIsCiAgICAgICAgICAgICAgc3VidGl0bGUgPSAiUHJpbWVyIHByZXNlbmNlIG9uIHNhbXBsZSByZWFkcyIpIAoKcHJpbWVyc190aWxlCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvMS1wcmltZXJzX2luX3JlYWRzX2FsbF9GUi5wbmciLAogICAgIHBsb3QgPSBwcmltZXJzX3RpbGUsCiAgICAgZGV2aWNlID0gInBuZyIsCiAgICAgd2lkdGggPSAyNywKICAgICBoZWlnaHQgPSA0MCwKICAgICB1bml0cyA9ICJjbSIsCiAgICAgZHBpID0gNjAwKQoKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzLzEtcHJpbWVyc19pbl9yZWFkc19hbGxfRlIucGRmIiwKICAgICBwbG90ID0gcHJpbWVyc190aWxlLAogICAgIGRldmljZSA9ICJwZGYiLAogICAgIHdpZHRoID0gMjcsCiAgICAgaGVpZ2h0ID0gNDAsCiAgICAgdW5pdHMgPSAiY20iLAogICAgIGRwaSA9IDYwMCkKCgojOS0gd3JpdGUgY3N2IGZpbGUgd2l0aCBwcmltZXIgaGl0cyBjb3VudHMgcGVyIGxpYiAtLS0tCndyaXRlLmNzdih4ID0gcHJpbWVyX2hpdHNfdGJsLGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9wcmltZXJzX2hpdHNfdGJsLmNzdiIsCiAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSkKCmBgYAoKCiMjIyBSZW1vdmUgcHJpbWVycyBmcm9tIHJlYWRzCiMjIyMgUHJpbWVyIHJlbW92YWwgd2l0aCAqKl9DdXRhZGFwdF8qKiAKClRoZSAqKl9jdXRhZGFwdF8qKiBzb2Z0d2FyZSAoW0RPSToxMC4xNDgwNi9lai4xNy4xLjIwMF0oaHR0cDovL2pvdXJuYWwuZW1ibmV0Lm9yZy9pbmRleC5waHAvZW1ibmV0am91cm5hbC9hcnRpY2xlL3ZpZXcvMjAwKSkgd2FzIHVzZWQgZm9yIHByaW1lciByZW1vdmFsIG9uIHJlYWQgc2VxdWVuY2VzLgoKYGBge3IgZXZhbD1GQUxTRX0KIzEwIC0gY3V0YWRhcHQgLS0tLQoKI3NldCBvciBjcmVhdGUgY3V0YWRhcHQgcHJvY2Vzc2VkIHJlYWRzIGRpciBwYXRoCnBhdGguY3V0IDwtIGZpbGUucGF0aChkYXRhX3BhdGgsICJjdXRhZGFwdCIpCmlmKCFkaXIuZXhpc3RzKHBhdGguY3V0KSkgZGlyLmNyZWF0ZShwYXRoLmN1dCkKCmBgYAoKPGJyPgoKIyMjIyBHZW5lcmF0ZSBhbmQgZXhlY3V0ZSBwcmltZXItc3BlY2lmaWMgY29tbWFuZHMKClRoZSBvcmlnaW5hbCBEQURBMiBJVFMgcHJvdG9jb2wgcmVtb3ZlcyBvbmx5IF9GV0RfIGFuZCBfUkVWIHJldmVyc2UgY29tcGxlbWVudF8gc2VxdWVuY2VzLiBUaGlzIHByb3RvY29sIGlzIGFkanVzdGVkIGZvciBzZWxlY3RpbmcgcmVhZHMgb25seSBvZiB0aGUgZXhwZWN0ZWQgcHJpbWVyIGFuZCByZW1vdmluZyB0aGUgcHJpbWVyLiAKCmBgYHtyIGV2YWw9RkFMU0V9CiMgb3BpdGlvbmFsOiByZW1vdmUgYWxsIHByaW1lcnMgZnJvbSBhbGwgcmVhZHMgYW5kIHNhbXBsZXMgLS0tLQoKIzEwIC0gbWFwIHNhbXBsZSBuYW1lcyB0byByZWFkcyBmaWxlcyAtLS0tCgojbmFtZSBvdXRwdXRzCmN1dGFkYXB0X2ZpbGVzIDwtIHByaW1lcnNfbl9zYW1wbGVzICU+JSAKICBmaWx0ZXIoU3RhZ2UgJWluJSBjKCJSMSBOLWNsZWFuZWQiLCJSMiBOLWNsZWFuZWQiKSkgJT4lIAogIG11dGF0ZShgUmVhZCBmaWxlYCA9IHN0cl9yZXBsYWNlX2FsbCguJGBSZWFkIGZpbGVgLHBhdHRlcm4gPSAiTi1jbGVhbmVkIixyZXBsYWNlbWVudCA9ICJjdXRhZGFwdCIpKSAlPiUgCiAgbXV0YXRlKFN0YWdlID0gc3RyX3JlcGxhY2VfYWxsKC4kU3RhZ2UscGF0dGVybiA9ICJOLWNsZWFuZWQiLHJlcGxhY2VtZW50ID0gImN1dGFkYXB0IikpCgoKcHJpbWVyc19uX3NhbXBsZXMgPC0gYmluZF9yb3dzKHByaW1lcnNfbl9zYW1wbGVzLGN1dGFkYXB0X2ZpbGVzKQoKI2FsbCAtLS0tCnsgCiAgICAgICAgICAjbWFrZSByZXZlcnNlIGNvbXBsZW1lbnRzCiAgICAgICAgIyAgdGhlIFhYWF9Db21wbGVtZW50IGFuZCBYWFhfcmV2ZXJzZSBoYXZlIG5vIGhpdHMgc28gd2VyZSBpZ25vcmVkIGF0IGxhc3QgcGxvdCBhbmQgZnJvbSBub3cgb24KICAgICAgICAgIGFsbF9GV0Qub3JpZW50cyA8LSAgcHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZVtwcmltZXJzX2FsbF9vcmllbnRzJGBPcmllbnRhdGlvbiBuYW1lYCAlPiUgZ3JlcChwYXR0ZXJuID0gYygiRldEX0ZvcndhcmQiKSldIAogICAgICAgICAgYWxsX0ZXRC5SQyA8LSAgcHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZVtwcmltZXJzX2FsbF9vcmllbnRzJGBPcmllbnRhdGlvbiBuYW1lYCAlPiUgZ3JlcChwYXR0ZXJuID0gYygiRldEX1JldkNvbXAiKSldIAogICAgICAgICAgYWxsX1JFVi5vcmllbnRzIDwtICBwcmltZXJzX2FsbF9vcmllbnRzJFNlcXVlbmNlW3ByaW1lcnNfYWxsX29yaWVudHMkYE9yaWVudGF0aW9uIG5hbWVgICU+JSBncmVwKHBhdHRlcm4gPSBjKCJSRVZfRm9yd2FyZCIpKV0gCiAgICAgICAgICBhbGxfUkVWLlJDIDwtICBwcmltZXJzX2FsbF9vcmllbnRzJFNlcXVlbmNlW3ByaW1lcnNfYWxsX29yaWVudHMkYE9yaWVudGF0aW9uIG5hbWVgICU+JSBncmVwKHBhdHRlcm4gPSBjKCJSRVZfUmV2Q29tcCIpKV0gCiAgCn0KICAKI3JlbW92ZSBwcmltZXJzIGFuZCBmaWx0ZXIgb25seSB0aGUgcmVhZHMgdGhhdCBjb250YWluIHRoZSBleHBlY3RlZCBwcmltZXIgLS0tLQp7CiAgI01pRmlzaCAtLS0tCiAgbWlmX0ZXRC5vcmllbnRzIDwtICBwcmltZXJzX2FsbF9vcmllbnRzJFNlcXVlbmNlW3ByaW1lcnNfYWxsX29yaWVudHMkYE9yaWVudGF0aW9uIG5hbWVgICU+JSBncmVwKHBhdHRlcm4gPSBjKCJtaWZfRldEX0ZvcndhcmQiKSldIAogIG1pZl9GV0QuUkMgPC0gIHByaW1lcnNfYWxsX29yaWVudHMkU2VxdWVuY2VbcHJpbWVyc19hbGxfb3JpZW50cyRgT3JpZW50YXRpb24gbmFtZWAgJT4lIGdyZXAocGF0dGVybiA9IGMoIm1pZl9GV0RfUmV2Q29tcCIpKV0gCiAgbWlmX1JFVi5vcmllbnRzIDwtICBwcmltZXJzX2FsbF9vcmllbnRzJFNlcXVlbmNlW3ByaW1lcnNfYWxsX29yaWVudHMkYE9yaWVudGF0aW9uIG5hbWVgICU+JSBncmVwKHBhdHRlcm4gPSBjKCJtaWZfUkVWX0ZvcndhcmQiKSldIAogIG1pZl9SRVYuUkMgPC0gIHByaW1lcnNfYWxsX29yaWVudHMkU2VxdWVuY2VbcHJpbWVyc19hbGxfb3JpZW50cyRgT3JpZW50YXRpb24gbmFtZWAgJT4lIGdyZXAocGF0dGVybiA9IGMoIm1pZl9SRVZfUmV2Q29tcCIpKV0gCiAgCiAgI05lb0Zpc2ggLS0tLQogIG5lb19GV0Qub3JpZW50cyA8LSAgcHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZVtwcmltZXJzX2FsbF9vcmllbnRzJGBPcmllbnRhdGlvbiBuYW1lYCAlPiUgZ3JlcChwYXR0ZXJuID0gYygibmVvX0ZXRF9Gb3J3YXJkIikpXSAKICBuZW9fRldELlJDIDwtICBwcmltZXJzX2FsbF9vcmllbnRzJFNlcXVlbmNlW3ByaW1lcnNfYWxsX29yaWVudHMkYE9yaWVudGF0aW9uIG5hbWVgICU+JSBncmVwKHBhdHRlcm4gPSBjKCJuZW9fRldEX1JldkNvbXAiKSldIAogIG5lb19SRVYub3JpZW50cyA8LSAgcHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZVtwcmltZXJzX2FsbF9vcmllbnRzJGBPcmllbnRhdGlvbiBuYW1lYCAlPiUgZ3JlcChwYXR0ZXJuID0gYygibmVvX1JFVl9Gb3J3YXJkIikpXSAKICBuZW9fUkVWLlJDIDwtICBwcmltZXJzX2FsbF9vcmllbnRzJFNlcXVlbmNlW3ByaW1lcnNfYWxsX29yaWVudHMkYE9yaWVudGF0aW9uIG5hbWVgICU+JSBncmVwKHBhdHRlcm4gPSBjKCJuZW9fUkVWX1JldkNvbXAiKSldIAogIAogICNUZWxlbyAtLS0tCiAgdGVsX0ZXRC5vcmllbnRzIDwtICBwcmltZXJzX2FsbF9vcmllbnRzJFNlcXVlbmNlW3ByaW1lcnNfYWxsX29yaWVudHMkYE9yaWVudGF0aW9uIG5hbWVgICU+JSBncmVwKHBhdHRlcm4gPSBjKCJ0ZWxfRldEX0ZvcndhcmQiKSldCiAgdGVsX0ZXRC5SQyA8LSAgcHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZVtwcmltZXJzX2FsbF9vcmllbnRzJGBPcmllbnRhdGlvbiBuYW1lYCAlPiUgZ3JlcChwYXR0ZXJuID0gYygidGVsX0ZXRF9SZXZDb21wIikpXQogIHRlbF9SRVYub3JpZW50cyA8LSAgcHJpbWVyc19hbGxfb3JpZW50cyRTZXF1ZW5jZVtwcmltZXJzX2FsbF9vcmllbnRzJGBPcmllbnRhdGlvbiBuYW1lYCAlPiUgZ3JlcChwYXR0ZXJuID0gYygidGVsX1JFVl9Gb3J3YXJkIikpXQogIHRlbF9SRVYuUkMgPC0gIHByaW1lcnNfYWxsX29yaWVudHMkU2VxdWVuY2VbcHJpbWVyc19hbGxfb3JpZW50cyRgT3JpZW50YXRpb24gbmFtZWAgJT4lIGdyZXAocGF0dGVybiA9IGMoInRlbF9SRVZfUmV2Q29tcCIpKV0KICB9CiAgCiAgICAgICAgICAgICAgICAjY3JlYXQgZmxhZ3MKICAgICAgICAgICAgICAgICMgVHJpbSBGV0QgYW5kIHRoZSByZXZlcnNlLWNvbXBsZW1lbnQgb2YgUkVWIG9mZiBvZiBSMSAoZm9yd2FyZCByZWFkcykKICAgICAgICAgICAgICAgIGFsbF9SMS5mbGFncyA8LSBwYXN0ZSgiLWciLCBhbGxfRldELm9yaWVudHMsICItYSIsIGFsbF9SRVYuUkMpCiAgICAgICAgICAgICAgICAjIFRyaW0gUkVWIGFuZCB0aGUgcmV2ZXJzZS1jb21wbGVtZW50IG9mIEZXRCBvZmYgb2YgUjIgKHJldmVyc2UgcmVhZHMpCiAgICAgICAgICAgICAgICBhbGxfUjIuZmxhZ3MgPC0gcGFzdGUoIi1HIiwgYWxsX1JFVi5vcmllbnRzLCAiLUEiLCBhbGxfRldELlJDKQogICAgICAgICAgICAgICAgCiNjcmVhdGUgcHJpbWVyLXNwZWNpZmljIHRhZ3MgLS0tLQogIHsKICAjTWlGaXNoIC0tLS0KICAjIFRyaW0gRldEIGFuZCB0aGUgcmV2ZXJzZS1jb21wbGVtZW50IG9mIFJFViBvZmYgb2YgUjEgKGZvcndhcmQgcmVhZHMpCiAgbWlmX1IxLmZsYWdzIDwtIHBhc3RlKCItZyIsIG1pZl9GV0Qub3JpZW50cywgIi1hIiwgbWlmX1JFVi5SQykKICAjIFRyaW0gUkVWIGFuZCB0aGUgcmV2ZXJzZS1jb21wbGVtZW50IG9mIEZXRCBvZmYgb2YgUjIgKHJldmVyc2UgcmVhZHMpCiAgbWlmX1IyLmZsYWdzIDwtIHBhc3RlKCItRyIsIG1pZl9SRVYub3JpZW50cywgIi1BIiwgbWlmX0ZXRC5SQykKICAKICAjTmVvRmlzaCAtLS0tCiAgIyBUcmltIEZXRCBhbmQgdGhlIHJldmVyc2UtY29tcGxlbWVudCBvZiBSRVYgb2ZmIG9mIFIxIChmb3J3YXJkIHJlYWRzKQogIG5lb19SMS5mbGFncyA8LSBwYXN0ZSgiLWciLCBuZW9fRldELm9yaWVudHMsICItYSIsIG5lb19SRVYuUkMpCiAgIyBUcmltIFJFViBhbmQgdGhlIHJldmVyc2UtY29tcGxlbWVudCBvZiBGV0Qgb2ZmIG9mIFIyIChyZXZlcnNlIHJlYWRzKQogIG5lb19SMi5mbGFncyA8LSBwYXN0ZSgiLUciLCBuZW9fUkVWLm9yaWVudHMsICItQSIsIG5lb19GV0QuUkMpCiAgCiAgI1RlbGVvIC0tLS0KICAjIFRyaW0gRldEIGFuZCB0aGUgcmV2ZXJzZS1jb21wbGVtZW50IG9mIFJFViBvZmYgb2YgUjEgKGZvcndhcmQgcmVhZHMpCiAgdGVsX1IxLmZsYWdzIDwtIHBhc3RlKCItZyIsIHRlbF9GV0Qub3JpZW50cywgIi1hIiwgdGVsX1JFVi5SQykKICAjIFRyaW0gUkVWIGFuZCB0aGUgcmV2ZXJzZS1jb21wbGVtZW50IG9mIEZXRCBvZmYgb2YgUjIgKHJldmVyc2UgcmVhZHMpCiAgdGVsX1IyLmZsYWdzIDwtIHBhc3RlKCItRyIsIHRlbF9SRVYub3JpZW50cywgIi1BIiwgdGVsX0ZXRC5SQykKICB9CgojY3V0YWRhcHQgZmlsZXMgcGF0aCBhbmQgbmFtZXMgLS0tLQp7CiAgICAgICAgYWxsX2ZuRnMuY3V0IDwtIHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMSBjdXRhZGFwdCJdCiAgICAgICAgbmFtZXMoYWxsX2ZuRnMuY3V0KSA8LSBhbGxfZm5Gcy5jdXQgJT4lIAogICAgICAgICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvY3V0YWRhcHQvIikpICU+JSAKICAgICAgICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9jdXRhZGFwdC5mYXN0cS5neiIpCiAgICAgICAgYWxsX2ZuUnMuY3V0IDwtIHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMiBjdXRhZGFwdCJdCiAgICAgICAgbmFtZXMoYWxsX2ZuUnMuY3V0KSA8LSBhbGxfZm5Scy5jdXQgJT4lIAogICAgICAgICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvY3V0YWRhcHQvIikpICU+JSAKICAgICAgICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9jdXRhZGFwdC5mYXN0cS5neiIpCiAgICAgICAgCiAgICAgICAgYWxsX2ZuRnMuZmlsdE4gPC0gcHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIxIE4tY2xlYW5lZCJdCiAgICAgICAgYWxsX2ZuUnMuZmlsdE4gPC0gcHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIyIE4tY2xlYW5lZCJdCgp9Cgp7CiAgI25lbyAtLS0tCiAgbmVvX2ZuRnMuY3V0IDwtIHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMSBjdXRhZGFwdCIgJiBwcmltZXJzX25fc2FtcGxlcyRQcmltZXIgPT0gIk5lb0Zpc2giXQogICAgbmFtZXMobmVvX2ZuRnMuY3V0KSA8LSBuZW9fZm5Gcy5jdXQgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvY3V0YWRhcHQvIikpICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9jdXRhZGFwdC5mYXN0cS5neiIpCgogIG5lb19mblJzLmN1dCA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjIgY3V0YWRhcHQiICYgcHJpbWVyc19uX3NhbXBsZXMkUHJpbWVyID09ICJOZW9GaXNoIl0KICAgIG5hbWVzKG5lb19mblJzLmN1dCkgPC0gbmVvX2ZuUnMuY3V0ICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gcGFzdGUwKCJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3JlYWRzL2N1dGFkYXB0LyIpKSAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9ICJfY3V0YWRhcHQuZmFzdHEuZ3oiKQoKICBuZW9fZm5Gcy5maWx0TiA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjEgTi1jbGVhbmVkIiAmIHByaW1lcnNfbl9zYW1wbGVzJFByaW1lciA9PSAiTmVvRmlzaCJdCiAgICBuYW1lcyhuZW9fZm5Gcy5maWx0TikgPC0gbmVvX2ZuRnMuZmlsdE4gJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvTi1jbGVhbmVkLyIpKSAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9ICJfTi1jbGVhbmVkLmZhc3RxLmd6IikKICAKICBuZW9fZm5Scy5maWx0TiA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjIgTi1jbGVhbmVkIiAmIHByaW1lcnNfbl9zYW1wbGVzJFByaW1lciA9PSAiTmVvRmlzaCJdCiAgICBuYW1lcyhuZW9fZm5Scy5maWx0TikgPC0gbmVvX2ZuUnMuZmlsdE4gJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvTi1jbGVhbmVkLyIpKSAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9ICJfTi1jbGVhbmVkLmZhc3RxLmd6IikKICAgIAogICNtaWYgLS0tLQogIG1pZl9mbkZzLmN1dCA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjEgY3V0YWRhcHQiICYgcHJpbWVyc19uX3NhbXBsZXMkUHJpbWVyID09ICJNaUZpc2giXQogICAgbmFtZXMobWlmX2ZuRnMuY3V0KSA8LSBtaWZfZm5Gcy5jdXQgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvY3V0YWRhcHQvIikpICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9jdXRhZGFwdC5mYXN0cS5neiIpCgogIG1pZl9mblJzLmN1dCA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjIgY3V0YWRhcHQiICYgcHJpbWVyc19uX3NhbXBsZXMkUHJpbWVyID09ICJNaUZpc2giXQogICAgbmFtZXMobWlmX2ZuUnMuY3V0KSA8LSBtaWZfZm5Scy5jdXQgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvY3V0YWRhcHQvIikpICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9jdXRhZGFwdC5mYXN0cS5neiIpCgogIG1pZl9mbkZzLmZpbHROIDwtIHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMSBOLWNsZWFuZWQiICYgcHJpbWVyc19uX3NhbXBsZXMkUHJpbWVyID09ICJNaUZpc2giXQogICAgbmFtZXMobWlmX2ZuRnMuZmlsdE4pIDwtIG1pZl9mbkZzLmZpbHROICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gcGFzdGUwKCJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3JlYWRzL04tY2xlYW5lZC8iKSkgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSAiX04tY2xlYW5lZC5mYXN0cS5neiIpCiAgCiAgbWlmX2ZuUnMuZmlsdE4gPC0gcHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIyIE4tY2xlYW5lZCIgJiBwcmltZXJzX25fc2FtcGxlcyRQcmltZXIgPT0gIk1pRmlzaCJdCiAgICBuYW1lcyhtaWZfZm5Scy5maWx0TikgPC0gbWlmX2ZuUnMuZmlsdE4gJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvTi1jbGVhbmVkLyIpKSAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9ICJfTi1jbGVhbmVkLmZhc3RxLmd6IikKICAgIAogICAgICAKICAjdGVsIC0tLS0KICB0ZWxfZm5Gcy5jdXQgPC0gcHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIxIGN1dGFkYXB0IiAmIHByaW1lcnNfbl9zYW1wbGVzJFByaW1lciA9PSAiVGVsZW8iXQogICAgbmFtZXModGVsX2ZuRnMuY3V0KSA8LSB0ZWxfZm5Gcy5jdXQgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvY3V0YWRhcHQvIikpICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9jdXRhZGFwdC5mYXN0cS5neiIpCgogIHRlbF9mblJzLmN1dCA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjIgY3V0YWRhcHQiICYgcHJpbWVyc19uX3NhbXBsZXMkUHJpbWVyID09ICJUZWxlbyJdCiAgICBuYW1lcyh0ZWxfZm5Scy5jdXQpIDwtIHRlbF9mblJzLmN1dCAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9IHBhc3RlMCgifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9yZWFkcy9jdXRhZGFwdC8iKSkgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSAiX2N1dGFkYXB0LmZhc3RxLmd6IikKCiAgdGVsX2ZuRnMuZmlsdE4gPC0gcHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIxIE4tY2xlYW5lZCIgJiBwcmltZXJzX25fc2FtcGxlcyRQcmltZXIgPT0gIlRlbGVvIl0KICAgIG5hbWVzKHRlbF9mbkZzLmZpbHROKSA8LSB0ZWxfZm5Gcy5maWx0TiAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9IHBhc3RlMCgifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9yZWFkcy9OLWNsZWFuZWQvIikpICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9OLWNsZWFuZWQuZmFzdHEuZ3oiKQogIAogIHRlbF9mblJzLmZpbHROIDwtIHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMiBOLWNsZWFuZWQiICYgcHJpbWVyc19uX3NhbXBsZXMkUHJpbWVyID09ICJUZWxlbyJdCiAgICBuYW1lcyh0ZWxfZm5Scy5maWx0TikgPC0gdGVsX2ZuUnMuZmlsdE4gJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvTi1jbGVhbmVkLyIpKSAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9ICJfTi1jbGVhbmVkLmZhc3RxLmd6IikKICAgIAogICAgICAgICAgCiAgI25lby9taWYgJiBuZW8vbWlmL3RlbCAtLS0tCiAgbm10X2ZuRnMuY3V0IDwtIHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMSBjdXRhZGFwdCIgJiBwcmltZXJzX25fc2FtcGxlcyRQcmltZXIgJWluJSBjKCJOZW9GaXNoL01pRmlzaCIsIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIildCiAgICBuYW1lcyhubXRfZm5Gcy5jdXQpIDwtIG5tdF9mbkZzLmN1dCAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9IHBhc3RlMCgifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9yZWFkcy9jdXRhZGFwdC8iKSkgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSAiX2N1dGFkYXB0LmZhc3RxLmd6IikKCiAgbm10X2ZuUnMuY3V0IDwtIHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMiBjdXRhZGFwdCIgJiBwcmltZXJzX25fc2FtcGxlcyRQcmltZXIgJWluJSBjKCJOZW9GaXNoL01pRmlzaCIsIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIildCiAgICBuYW1lcyhubXRfZm5Scy5jdXQpIDwtIG5tdF9mblJzLmN1dCAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9IHBhc3RlMCgifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9yZWFkcy9jdXRhZGFwdC8iKSkgJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSAiX2N1dGFkYXB0LmZhc3RxLmd6IikKCiAgbm10X2ZuRnMuZmlsdE4gPC0gcHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIxIE4tY2xlYW5lZCIgJiBwcmltZXJzX25fc2FtcGxlcyRQcmltZXIgJWluJSBjKCJOZW9GaXNoL01pRmlzaCIsIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIildCiAgICBuYW1lcyhubXRfZm5Gcy5maWx0TikgPC0gbm10X2ZuRnMuZmlsdE4gJT4lIAogICAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvcmVhZHMvTi1jbGVhbmVkLyIpKSAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9ICJfTi1jbGVhbmVkLmZhc3RxLmd6IikKICAKICBubXRfZm5Scy5maWx0TiA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjIgTi1jbGVhbmVkIiAmIHByaW1lcnNfbl9zYW1wbGVzJFByaW1lciAlaW4lIGMoIk5lb0Zpc2gvTWlGaXNoIiwiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKV0KICAgIG5hbWVzKG5tdF9mblJzLmZpbHROKSA8LSBubXRfZm5Scy5maWx0TiAlPiUgCiAgICAgIHN0cl9yZW1vdmUocGF0dGVybiA9IHBhc3RlMCgifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9yZWFkcy9OLWNsZWFuZWQvIikpICU+JSAKICAgICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9OLWNsZWFuZWQuZmFzdHEuZ3oiKQogIAp9CgoKIyBlIGVzc2Egb3JkZW0gdMOhIHBlcmlnb3NhCm5hbWVzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgKTwtIHByaW1lcnNfbl9zYW1wbGVzJEZpbGVfbmFtZQoKCnByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFN0YWdlICVpbiUgYygiUjEgTi1jbGVhbmVkIiwgIlIyIE4tY2xlYW5lZCIpXSAlPiUgIGxlbmd0aCgpCgojVE9ETyBlc3NlIHRlbSBxIGlyIHBybyBwdXJyci4uLgoKCiMgUnVuIEN1dGFkYXB0CiMgICBvdXRwdXQgZm9sZGVyIG11c3QgZXhpc3QKZm9yKGkgaW4gMTo0MCkgewojIGZvcihpIGluIHNlcV9hbG9uZyhhbGxfZm5GcykpIHsKc3lzdGVtMihjdXRhZGFwdCwgYXJncyA9IGMoYWxsX1IxLmZsYWdzLCBhbGxfUjIuZmxhZ3MsICItbiIsIDIsICMgLW4gMiByZXF1aXJlZCB0byByZW1vdmUgRldEIGFuZCBSRVYgZnJvbSByZWFkcwoiLW8iLCBhbGxfZm5Gcy5jdXRbaV0sICItcCIsIGFsbF9mblJzLmN1dFtpXSwgIyBvdXRwdXQgZmlsZXMKYWxsX2ZuRnMuZmlsdE5baV0sIGFsbF9mblJzLmZpbHROW2ldLCAgIyBpbnB1dCBmaWxlcwoiLS1taW5pbXVtLWxlbmd0aCAxMCIpKSAjIGd1YXJhbnRlZSBubyB6ZXJvbGVuZ3RoIHJlYWRzCn0KCgpsZW5ndGgobmVvX2ZuRnMuY3V0KQpsZW5ndGgobWlmX2ZuRnMuY3V0KQpsZW5ndGgobWlmX2ZuUnMuY3V0KQpsZW5ndGgodGVsX2ZuRnMuY3V0KQpsZW5ndGgobm10X2ZuRnMuY3V0KQoKCiNydW4gY3V0YWRhcHQgYnkgcHJpbWVyIC0tLS0KCiNNaUZpc2ggLS0tLQpmb3IoaSBpbiAxOmxlbmd0aChtaWZfZm5Gcy5jdXQpKSB7CiMgZm9yKGkgaW4gc2VxX2Fsb25nKGFsbF9mbkZzKSkgewpzeXN0ZW0yKGN1dGFkYXB0LCBhcmdzID0gYyhtaWZfUjEuZmxhZ3MsIG1pZl9SMi5mbGFncywgIi1uIiwgMiwgIyAtbiAyIHJlcXVpcmVkIHRvIHJlbW92ZSBGV0QgYW5kIFJFViBmcm9tIHJlYWRzCiItbyIsIG1pZl9mbkZzLmN1dFtpXSwgIi1wIiwgbWlmX2ZuUnMuY3V0W2ldLCAjIG91dHB1dCBmaWxlcwptaWZfZm5Gcy5maWx0TltpXSwgbWlmX2ZuUnMuZmlsdE5baV0sICAjIGlucHV0IGZpbGVzCiItLW1pbmltdW0tbGVuZ3RoIDEwIC0tZGlzY2FyZC11bnRyaW1tZWQiKSkgIyBndWFyYW50ZWUgbm8gemVyb2xlbmd0aCByZWFkcwp9CgojTmVvRmlzaCAtLS0tCmZvcihpIGluIDE6bGVuZ3RoKG5lb19mbkZzLmN1dCkpIHsKIyBmb3IoaSBpbiBzZXFfYWxvbmcoYWxsX2ZuRnMpKSB7CnN5c3RlbTIoY3V0YWRhcHQsIGFyZ3MgPSBjKG5lb19SMS5mbGFncywgbmVvX1IyLmZsYWdzLCAiLW4iLCAyLCAjIC1uIDIgcmVxdWlyZWQgdG8gcmVtb3ZlIEZXRCBhbmQgUkVWIGZyb20gcmVhZHMKIi1vIiwgbmVvX2ZuRnMuY3V0W2ldLCAiLXAiLCBuZW9fZm5Scy5jdXRbaV0sICMgb3V0cHV0IGZpbGVzCm5lb19mbkZzLmZpbHROW2ldLCBuZW9fZm5Scy5maWx0TltpXSwgICMgaW5wdXQgZmlsZXMKIi0tbWluaW11bS1sZW5ndGggMTAgLS1kaXNjYXJkLXVudHJpbW1lZCIpKSAjIGd1YXJhbnRlZSBubyB6ZXJvbGVuZ3RoIHJlYWRzCn0KCgojVGVsZW8gLS0tLQpmb3IoaSBpbiAxOmxlbmd0aCh0ZWxfZm5Gcy5jdXQpKSB7CiMgZm9yKGkgaW4gc2VxX2Fsb25nKGFsbF9mbkZzKSkgewpzeXN0ZW0yKGN1dGFkYXB0LCBhcmdzID0gYyh0ZWxfUjEuZmxhZ3MsIHRlbF9SMi5mbGFncywgIi1uIiwgMiwgIyAtbiAyIHJlcXVpcmVkIHRvIHJlbW92ZSBGV0QgYW5kIFJFViBmcm9tIHJlYWRzCiItbyIsIHRlbF9mbkZzLmN1dFtpXSwgIi1wIiwgdGVsX2ZuUnMuY3V0W2ldLCAjIG91dHB1dCBmaWxlcwp0ZWxfZm5Gcy5maWx0TltpXSwgdGVsX2ZuUnMuZmlsdE5baV0sICAjIGlucHV0IGZpbGVzCiItLW1pbmltdW0tbGVuZ3RoIDEwIC0tZGlzY2FyZC11bnRyaW1tZWQiKSkgIyBndWFyYW50ZWUgbm8gemVyb2xlbmd0aCByZWFkcwp9CgoKI25lby9taWYgJiBuZW8vbWlmL3RlbCAtLS0tCiAgCmZvcihpIGluIDE6bGVuZ3RoKG5tdF9mbkZzLmN1dCkpIHsKIyBmb3IoaSBpbiBzZXFfYWxvbmcoYWxsX2ZuRnMpKSB7CnN5c3RlbTIoY3V0YWRhcHQsIGFyZ3MgPSBjKGFsbF9SMS5mbGFncywgYWxsX1IyLmZsYWdzLCAiLW4iLCAyLCAjIC1uIDIgcmVxdWlyZWQgdG8gcmVtb3ZlIEZXRCBhbmQgUkVWIGZyb20gcmVhZHMKIi1vIiwgbm10X2ZuRnMuY3V0W2ldLCAiLXAiLCBubXRfZm5Scy5jdXRbaV0sICMgb3V0cHV0IGZpbGVzCm5tdF9mbkZzLmZpbHROW2ldLCBubXRfZm5Scy5maWx0TltpXSwgICMgaW5wdXQgZmlsZXMKIi0tbWluaW11bS1sZW5ndGggMTAgLS1kaXNjYXJkLXVudHJpbW1lZCIpKSAjIGd1YXJhbnRlZSBubyB6ZXJvbGVuZ3RoIHJlYWRzCn0KCgojIGFzICBEYTIzLW1pZiAmIG5lbyAmIFNGSlEtbWlmICYgbmVvIHdlcmUgcHJldmlvdXNseSBkZW11bHRpcGxleGVkLCB0aGV5IGRvIG5vdCBiZWFyIHRoZSBwcmltZXJzLCBzbyBhbGwgcmVhZHMgYXJlIGZpbHRlcmVkIG91dAoKCmBgYAoKPGJyPgoKIyMjIyBDaGVjayBwcmltZXIgcmVtb3ZhbCAKCkNoYW5nZSBkZSBsaWJyYXJ5IG51bWJlciBpbmRleCBpbiBvcmRlciB0byBjaGVjayB0aGUgcHJlc2VuY2Ugb2YgcmVtYWluaW5nIHByaW1lciBzZXF1ZW5jZXMgb24gZWFjaCBsaWIgZGF0YS4KSXQgaXMgZXhwZWN0ZWQgdGhhdCBhbGwgcmVtb3ZlZCBvcmllbnRhdGlvbiBjb3VudHMgY2hhbmdlIHRvIHplcm8gc2luY2UgdGhlIHByaW1lciBzZXF1ZW5jZXMgYXJlIHJlbW92ZWQuCgpgYGB7ciBldmFsPUZBTFNFfQojIG9ubHkgb2ZyIGRpZGF0aWMgcHVycG9zZXMgKG9yIGxvZ2ljYWwgZXJyb3IgY2hlY2tpbmcpCiMgOCAtIGNoZWNrIGZvciByZW1haW5pbmcgYWRhcHRlcnMgLS0tLQojIEFzIGEgc2FuaXR5IGNoZWNrLCB3ZSB3aWxsIGNvdW50IHRoZSBwcmVzZW5jZSBvZiBwcmltZXJzIGluIHRoZSBmaXJzdCBjdXRhZGFwdC1lZCBzYW1wbGU6CgoKI3ZlY3RvciBvZiByZWFkIGZpbGVzIHRvIGxvb2sgb24gZm9yIHByaW1lcnMKcmVhZHNfc2Vxc19jdXQgPC0gcHJpbWVyc19uX3NhbXBsZXMgJT4lIAogIGZpbHRlcihTdGFnZSAlaW4lIGMoIlIyIGN1dGFkYXB0IiwgIlIyIGN1dGFkYXB0IikpICU+JSAKICBzZWxlY3QoYFJlYWQgZmlsZWApICU+JSBhcy5saXN0KCkKCgojY291bnQgcHJpbWVycwpmdXR1cmU6OnBsYW4oZnV0dXJlOjptdWx0aXNlc3Npb24od29ya2VycyA9IGNvcmVzX3RvX2JlX3VzZWQpKQpwcmltZXJzX2luX2N1dF9yZWFkcyA8LSBmdXJycjo6ZnV0dXJlX21hcF9kZnIocmVhZHNfc2Vxc19jdXQkYFJlYWQgZmlsZWAsIC5mID0gbXVsdGlfcHJpbWVySGl0cywgcHJpbWVycyA9IHByaW1lcnNfc2VxcywgLm9wdGlvbnMgPSBmdXJycjo6ZnVycnJfb3B0aW9ucyhzZWVkID0gTlVMTCkpCgogIyAKIyBwcmltZXJzX2luX05yZWFkcyA8LSBwdXJycjo6bWFwX2RmKHJlYWRzX3NlcXMsLmYgPSBtdWx0aV9wcmltZXJIaXRzLCBwcmltZXJzID0gcHJpbWVyc19zZXFzKQoKI2dldCBzYW1wbGUgaW5mb3JtYXRpb24gaW50byBwcmltZXJzX2luX05yZWFkcyB0YWJsZQpwcmltZXJzX2luX2N1dF9yZWFkcyA8LSBsZWZ0X2pvaW4ocHJpbWVyc19pbl9jdXRfcmVhZHMscHJpbWVyc19uX3NhbXBsZXMsYnkgPSAiUmVhZCBmaWxlIikKCiMgcHJpbWVyc19pbl9jdXRfcmVhZHNfYmNrcCA8LSBwcmltZXJzX2luX2N1dF9yZWFkcwojIHByaW1lcnNfaW5fY3V0X3JlYWRzIDwtIHByaW1lcnNfaW5fY3V0X3JlYWRzX2Jja3AKCnByaW1lcnNfaW5fY3V0X3JlYWRzIDwtCiAgcHJpbWVyc19pbl9jdXRfcmVhZHMgJT4lIAogIHNlbGVjdCgjIGBSZWFkIGZpbGUKIEZpbGVfbmFtZSwgVHlwZSwgR3JvdXAsIExpYnJhcnksIFByaW1lciwgUnVuLCBTdGFnZSwKICAgICAgICAgbmVvX0ZXRF9Gb3J3YXJkLCBuZW9fUkVWX0ZvcndhcmQsIG5lb19GV0RfQ29tcGxlbWVudCwgbmVvX1JFVl9Db21wbGVtZW50LCAKICAgICAgICAgbmVvX0ZXRF9SZXZlcnNlLCBuZW9fUkVWX1JldmVyc2UsIG5lb19GV0RfUmV2Q29tcCwgbmVvX1JFVl9SZXZDb21wLCAKICAgICAgICAgbWlmX0ZXRF9Gb3J3YXJkLCBtaWZfUkVWX0ZvcndhcmQsIG1pZl9GV0RfQ29tcGxlbWVudCwgbWlmX1JFVl9Db21wbGVtZW50LCAKICAgICAgICAgbWlmX0ZXRF9SZXZlcnNlLCBtaWZfUkVWX1JldmVyc2UsIG1pZl9GV0RfUmV2Q29tcCwgbWlmX1JFVl9SZXZDb21wLCAKICAgICAgICAgdGVsX0ZXRF9Gb3J3YXJkLCB0ZWxfUkVWX0ZvcndhcmQsIHRlbF9GV0RfQ29tcGxlbWVudCwgdGVsX1JFVl9Db21wbGVtZW50LCAKICAgICAgICAgdGVsX0ZXRF9SZXZlcnNlLCB0ZWxfUkVWX1JldmVyc2UsIHRlbF9GV0RfUmV2Q29tcCwgdGVsX1JFVl9SZXZDb21wKQoKI2NvbnZlcnQgcHJpbWVyIGhpdHMgdGFibGUgdG8gbG9uZyBmb3JtYXQKcHJpbWVyc19pbl9jdXRfcmVhZHNfbG9uZyA8LSBwcmltZXJzX2luX2N1dF9yZWFkcyAlPiUgCiAgZ2F0aGVyKGtleSA9IFNlcXVlbmNlcywgCiAgICAgICAgIHZhbHVlID0gQ291bnQsICAKICAgICAgICAgbmVvX0ZXRF9Gb3J3YXJkLCBuZW9fRldEX0NvbXBsZW1lbnQsCiAgICAgICAgIG5lb19GV0RfUmV2ZXJzZSxuZW9fRldEX1JldkNvbXAsIAogICAgICAgICBuZW9fUkVWX0ZvcndhcmQsIG5lb19SRVZfQ29tcGxlbWVudCwKICAgICAgICAgbmVvX1JFVl9SZXZlcnNlLCBuZW9fUkVWX1JldkNvbXAsCiAgICAgICAgIG1pZl9GV0RfRm9yd2FyZCwgbWlmX0ZXRF9Db21wbGVtZW50LAogICAgICAgICBtaWZfRldEX1JldmVyc2UsIG1pZl9GV0RfUmV2Q29tcCwgCiAgICAgICAgIG1pZl9SRVZfRm9yd2FyZCwgbWlmX1JFVl9Db21wbGVtZW50LAogICAgICAgICBtaWZfUkVWX1JldmVyc2UsIG1pZl9SRVZfUmV2Q29tcCwKICAgICAgICAgdGVsX0ZXRF9Gb3J3YXJkLCB0ZWxfRldEX0NvbXBsZW1lbnQsCiAgICAgICAgIHRlbF9GV0RfUmV2ZXJzZSwgdGVsX0ZXRF9SZXZDb21wLCAKICAgICAgICAgdGVsX1JFVl9Gb3J3YXJkLCB0ZWxfUkVWX0NvbXBsZW1lbnQsCiAgICAgICAgIHRlbF9SRVZfUmV2ZXJzZSwgdGVsX1JFVl9SZXZDb21wKSAlPiUgCiAgbXV0YXRlKFNlcXVlbmNlcyA9IGZhY3RvcihTZXF1ZW5jZXMsbGV2ZWxzID0gYygibmVvX0ZXRF9Gb3J3YXJkIiwgIm5lb19SRVZfRm9yd2FyZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibmVvX0ZXRF9SZXZDb21wIiwgIm5lb19SRVZfUmV2Q29tcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibmVvX0ZXRF9Db21wbGVtZW50IiwgIm5lb19SRVZfQ29tcGxlbWVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibmVvX0ZXRF9SZXZlcnNlIiwgIm5lb19SRVZfUmV2ZXJzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1pZl9GV0RfRm9yd2FyZCIsICJtaWZfUkVWX0ZvcndhcmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1pZl9GV0RfUmV2Q29tcCIsICJtaWZfUkVWX1JldkNvbXAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1pZl9GV0RfQ29tcGxlbWVudCIsICJtaWZfUkVWX0NvbXBsZW1lbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1pZl9GV0RfUmV2ZXJzZSIsICJtaWZfUkVWX1JldmVyc2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRlbF9GV0RfRm9yd2FyZCIsICJ0ZWxfUkVWX0ZvcndhcmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidGVsX0ZXRF9SZXZDb21wIiwgInRlbF9SRVZfUmV2Q29tcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0ZWxfRldEX0NvbXBsZW1lbnQiLCAidGVsX1JFVl9Db21wbGVtZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRlbF9GV0RfUmV2ZXJzZSIsICJ0ZWxfUkVWX1JldmVyc2UiKSksCiAgICAgICAgIEZpbGVfbmFtZSA9IGZhY3RvcihGaWxlX25hbWUsbGV2ZWxzID0gc2FtcGxlX2xldmVscyksCiAgICAgICAgIFJ1biA9IGFzLmZhY3RvcihSdW4pLAogICAgICAgICBQcmltZXIgPSBmYWN0b3IoUHJpbWVyLGxldmVscyA9IGMoIk5lb0Zpc2giLCJNaUZpc2giLCJUZWxlbyIsIk5lb0Zpc2gvTWlGaXNoIiwiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKSkpIAoKCgojIFBMT1QgMTogcHJpbWVycyBjb3VudHMgaW4gcmVhZHMgdGlsZSBwbG90IC0gb25seSBwcmltZXJzIEZXRCAmIFJFViwgZm93YXJkICYgcmV2Y29tcCAtLS0tCnByaW1lcnNfdGlsZV9jbGVhbiA8LSAKICBwcmltZXJzX2luX2N1dF9yZWFkc19sb25nICU+JSAKICBmaWx0ZXIoU2VxdWVuY2VzICAlaW4lIGMoCiAgICAibWlmX1JFVl9SZXZDb21wIiwgIm1pZl9SRVZfRm9yd2FyZCIsICJtaWZfRldEX1JldkNvbXAiLCAibWlmX0ZXRF9Gb3J3YXJkIiwKICAgICJuZW9fUkVWX1JldkNvbXAiLCAibmVvX1JFVl9Gb3J3YXJkIiwgIm5lb19GV0RfUmV2Q29tcCIsICJuZW9fRldEX0ZvcndhcmQiLAogICAgInRlbF9SRVZfUmV2Q29tcCIsICJ0ZWxfUkVWX0ZvcndhcmQiLCAidGVsX0ZXRF9SZXZDb21wIiwgInRlbF9GV0RfRm9yd2FyZCIpKSAlPiUgCiAgZmlsdGVyKFJ1biAlaW4lIGMoIkxHQ19NaW5pU2VxXzEiKSkgJT4lIAogIGdncGxvdDI6OmdncGxvdChhZXMoeT1GaWxlX25hbWUseD1TZXF1ZW5jZXMsZmlsbD1sb2cxMChDb3VudCkpKSArCiAgZ2VvbV90aWxlKCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IENvdW50KSxzaXplPTEpKwogICMgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9IndoaXRlIiwgaGlnaD0iZGFya2dyZWVuIix0cmFucz0ibG9nMTAiKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4obmFtZSA9ICJQcmltZXIgY291bnRzIiwKICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXJzID0gYygid2hpdGUiLCJkYXJrZ3JlZW4iKSwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKDAsMSksCiAgICAgICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSJ3aGl0ZSIpICsKICB0aGVtZV9saWdodChiYXNlX2xpbmVfc2l6ZSA9IDEsYmFzZV9zaXplID0gNikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsaGp1c3QgPSAxKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGMoNDAuNSw4Mi41LDg2LjUsMTE2LjUpLGNvbG9yID0gImdyZXkiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYyg0LjUsOC41LDEyLjUsMTYuNSksY29sb3IgPSAiZ3JleSIpICsKICAjIGNvb3JkX2ZpeGVkKHJhdGlvID0gMC4yMCkgKwogIHhsYWIoIlByaW1lcnMiKSArCiAgeWxhYigiQW1vc3RyYSIpICsKICBnZ3RpdGxlKGxhYmVsID0gImVETkEgMXN0LCAybmQgJiAzcmQgcnVucyIsCiAgICAgICAgICAgICAgc3VidGl0bGUgPSAiUHJpbWVyIHByZXNlbmNlIG9uIHNhbXBsZSByZWFkcyIpIAojICsKIyAgIGZhY2V0X3dyYXAoflJ1biwgZHJvcCA9IFRSVUUpCgoKcHJpbWVyc190aWxlX2NsZWFuCgpgYGAKCjxicj48YnI+CgojIyMgUXVhbGl0eSBmaWx0ZXJpbmcKCkhlcmUgdGhlICoqREFEQTIqKiBwaXBlbGluZSBzdGFydHMuCgo8YnI+CgojIyMjIFNldCBpbnB1dCBsaWJzIHBhdGhzCgpEZWZpbmUgdGhlIHBhdGhzIHRvIHRoZSBsaWJyYXJpZXMgYWZ0ZXIgX2N1dGFkYXB0XyBwcmltZXIgcmVtb3ZhbC4KCmBgYHtyLCBldmFsPUZBTFNFfQojIDkgLSBsb2FkIGNsZWFuIHNlcXMgdG8gREFEQTIgcGlwZSAtLS0tCgphbGxfZm5Gcy5jdXQgPC0gYyhtaWZfZm5Gcy5jdXQsbmVvX2ZuRnMuY3V0LHRlbF9mbkZzLmN1dCxubXRfZm5Gcy5jdXQpCmFsbF9mblJzLmN1dCA8LSBjKG1pZl9mblJzLmN1dCxuZW9fZm5Scy5jdXQsdGVsX2ZuUnMuY3V0LG5tdF9mblJzLmN1dCkKCgphbGxfZm5Gcy5jdXQKYWxsX2ZuUnMuY3V0CgpgYGAKCjxicj4KCiMjIyMgU2V0IHF1YWxpdHkgZmlsdGVyaW5nIG91dHB1dCBmaWxlcyBuYW1lcwoKYGBge3IsIGV2YWw9RkFMU0V9CiMgMTEgLSBxdWFsaXR5IGZpbHRlciBwcmVwYXJhdGlvbiAtLS0tCgoKI25hbWUgb3V0cHV0cwpRZmlsdGVyX2ZpbGVzIDwtIHByaW1lcnNfbl9zYW1wbGVzICU+JSAKICBmaWx0ZXIoU3RhZ2UgJWluJSBjKCJSMSBOLWNsZWFuZWQiLCJSMiBOLWNsZWFuZWQiKSkgJT4lIAogIG11dGF0ZShgUmVhZCBmaWxlYCA9IHN0cl9yZXBsYWNlX2FsbCguJGBSZWFkIGZpbGVgLHBhdHRlcm4gPSAiTi1jbGVhbmVkIixyZXBsYWNlbWVudCA9ICJRZmlsdGVyZWQiKSkgJT4lIAogIG11dGF0ZShTdGFnZSA9IHN0cl9yZXBsYWNlX2FsbCguJFN0YWdlLHBhdHRlcm4gPSAiTi1jbGVhbmVkIixyZXBsYWNlbWVudCA9ICJRZmlsdGVyZWQiKSkKCnByaW1lcnNfbl9zYW1wbGVzIDwtIGJpbmRfcm93cyhwcmltZXJzX25fc2FtcGxlcyxRZmlsdGVyX2ZpbGVzKQoKI3JlbmFtZSBmaWxlcyBzbyBhbGwgY2FuIGJlIHRyYWNlYmxlCm5hbWVzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgKSA8LSBwcmltZXJzX25fc2FtcGxlcyRGaWxlX25hbWUKCgojIFFmaWx0ZXJlZCBmaWxlcyBwYXRoIGFuZCBuYW1lcwoKYWxsX2ZpbHRGcyA8LSBwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjEgUWZpbHRlcmVkIl0KbmFtZXMoYWxsX2ZpbHRGcykgPC0gYWxsX2ZpbHRGcyAlPiUgCiAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSBwYXN0ZTAoZGF0YV9wYXRoLCIvUWZpbHRlcmVkLyIpKSAlPiUgCiAgICBzdHJfcmVtb3ZlKHBhdHRlcm4gPSAiX1FmaWx0ZXJlZC5mYXN0cS5neiIpCmFsbF9maWx0UnMgPC0gcHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIyIFFmaWx0ZXJlZCJdCm5hbWVzKGFsbF9maWx0UnMpIDwtIGFsbF9maWx0UnMgJT4lIAogICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gcGFzdGUwKGRhdGFfcGF0aCwiL1FmaWx0ZXJlZC8iKSkgJT4lIAogICAgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl9RZmlsdGVyZWQuZmFzdHEuZ3oiKQoKCgpgYGAKCjxicj4KCiMjIyMgUXVhbGl0eSBmaWx0ZXJpbmcKCk9uIHRoaXMgc3RlcCBpdCBpcyBwb3NzaWJsZSB0byBmaWx0ZXIgYnkgc2l6ZSBidXQsIGFzIHdlIGhhdmUgYWxyZWFkeSByZW1vdmVkIHByaW1lcnMgZnJvbSB0aGUgYmVnaW5uaW5nL2VuZCBvZiB0aGUgcmVhZHMsIGl0IGlzIGV4cGVjdGVkIHRoYXQgdGhlIHJlbWFpbmluZyBzZXF1ZW5jZXMgYXJlIGFscmVhZHkgdHJpbW1lZCB0byBsZW5ndGhzIGNvbXBhdGlibGUgd2l0aCB0aGVpciByZXNwZWN0aXZlIGFtcGxpY29ucy4gVGh1cywgbm8gbGVuZ3RoIHRyaW1taW5nIHdhcyBjb25kdWN0ZWQuCgoKYGBge3IsIGV2YWw9RkFMU0V9CiMgMTIgLSBkYWRhIGZpbHRlcmluZyAtLS0tCgojIFdl4oCZbGwgdXNlIHN0YW5kYXJkIGZpbHRlcmluZyBwYXJhbWV0ZXJzOiBtYXhOPTAgKERBREEyIHJlcXVpcmVzIG5vIE5zKSwgdHJ1bmNRPTIsIHJtLnBoaXg9VFJVRSBhbmQgbWF4RUU9Mi4gVGhlIG1heEVFIHBhcmFtZXRlciBzZXRzIHRoZSBtYXhpbXVtIG51bWJlciBvZiDigJxleHBlY3RlZCBlcnJvcnPigJ0gYWxsb3dlZCBpbiBhIHJlYWQsIHdoaWNoIGlzIGEgYmV0dGVyIGZpbHRlciB0aGFuIHNpbXBseSBhdmVyYWdpbmcgcXVhbGl0eSBzY29yZXMuCgpsZW5ndGgoYWxsX2ZuRnMuY3V0KQpsZW5ndGgoYWxsX2ZpbHRGcykKbGVuZ3RoKGFsbF9mblJzLmN1dCkKbGVuZ3RoKGFsbF9maWx0UnMpCgojc29ydGluZyBmb3IgbmV4dCBzdGVwIG5vdCB0byBtaXggZmlsZXMKYWxsX2ZuRnMuY3V0IDwtIGJhc2U6OnNvcnQoYWxsX2ZuRnMuY3V0KQphbGxfZmlsdEZzIDwtIGJhc2U6OnNvcnQoYWxsX2ZpbHRGcykKYWxsX2ZuUnMuY3V0IDwtIGJhc2U6OnNvcnQoYWxsX2ZuUnMuY3V0KQphbGxfZmlsdFJzIDwtIGJhc2U6OnNvcnQoYWxsX2ZpbHRScykKbmFtZXMoYWxsX2ZuRnMuY3V0KQpuYW1lcyhhbGxfZmlsdEZzKQpuYW1lcyhhbGxfZm5Scy5jdXQpCm5hbWVzKGFsbF9maWx0UnMpCgojYWxsCgphbGxfZmlsdGVyZWRfb3V0IDwtIGRhZGEyOjpmaWx0ZXJBbmRUcmltKGZ3ZCA9IGFsbF9mbkZzLmN1dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ID0gYWxsX2ZpbHRGcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV2ID0gYWxsX2ZuUnMuY3V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHQucmV2ID0gYWxsX2ZpbHRScywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRydW5jTGVuPWMoMjQwLDE2MCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Tj0wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEVFPWMoMiwyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRydW5jUT0yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJtLnBoaXg9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wcmVzcz1UUlVFLCBtdWx0aXRocmVhZD1UUlVFLHZlcmJvc2UgPSBUUlVFLG1hdGNoSURzID0gVFJVRSkgIyBPbiBXaW5kb3dzIHNldCBtdWx0aXRocmVhZD1GQUxTRQpoZWFkKGFsbF9maWx0ZXJlZF9vdXQpCgpgYGAKCjxicj4KCiMjIyMgVmlldyBwb3N0LWZpbHRlcmluZyBxdWFsaXR5IHByb2ZpbGVzCgpgYGB7ciwgZXZhbD1GQUxTRX0KI2NoZWNrIHF1YWxpdHkgcHJvZmlsZSBhZnRlciBmaWx0ZXJpbmcgYW5kIHRyaW1taW5nCnBsb3RRdWFsaXR5UHJvZmlsZShhbGxfZmlsdEZzWzJdKQpwbG90UXVhbGl0eVByb2ZpbGUoYWxsX2ZpbHRSc1syOjhdKQoKcGxvdFF1YWxpdHlQcm9maWxlKG1pZl9maWx0RnNbXSkKcGxvdFF1YWxpdHlQcm9maWxlKG1pZl9maWx0UnNbXSkKCgpgYGAKPGJyPgoKIyMjIElkZW50aWZ5IGVycm9yIHJhdGVzIGludHJpbnNpYyB0byBzZXF1ZW5jaW5nCgpgYGB7ciwgZXZhbD1GQUxTRX0KIyAxMyAtIGxlYXJuIGVycm9yIHJhdGVzIC0tLS0KCiNMZWFybiB0aGUgRXJyb3IgUmF0ZXMKcHJpbWVyc19uX3NhbXBsZXMkUnVuICU+JSAgdW5pcXVlKCkKCiNydW4gTEdDX01pbmlTZXFfMSAtLS0tCnJ1bjFfZXJyRiA8LSBsZWFybkVycm9ycyhwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFtwcmltZXJzX25fc2FtcGxlcyRSdW4gPT0gIkxHQ19NaW5pU2VxXzEiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMSBRZmlsdGVyZWQiXSwgCiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpdGhyZWFkPVRSVUUscmFuZG9taXplID0gVFJVRSkKcnVuMV9lcnJSIDwtIGxlYXJuRXJyb3JzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFJ1biA9PSAiTEdDX01pbmlTZXFfMSIgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIyIFFmaWx0ZXJlZCJdLCAKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGl0aHJlYWQ9VFJVRSxyYW5kb21pemUgPSBUUlVFKQoKI3J1biBMR0NfTWluaVNlcV8yIC0tLS0KcnVuMl9lcnJGIDwtIGxlYXJuRXJyb3JzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFJ1biA9PSAiTEdDX01pbmlTZXFfMiIgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIxIFFmaWx0ZXJlZCJdLCAKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGl0aHJlYWQ9VFJVRSxyYW5kb21pemUgPSBUUlVFKQpydW4yX2VyclIgPC0gbGVhcm5FcnJvcnMocHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbcHJpbWVyc19uX3NhbXBsZXMkUnVuID09ICJMR0NfTWluaVNlcV8yIiAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjIgUWZpbHRlcmVkIl0sIAogICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXRocmVhZD1UUlVFLHJhbmRvbWl6ZSA9IFRSVUUpCgojcnVuIGVjb21vbF9pU2VxIC0tLS0KcnVuM19lcnJGIDwtIGxlYXJuRXJyb3JzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFJ1biA9PSAiZWNvbW9sX2lTZXEiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMSBRZmlsdGVyZWQiXSwgCiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpdGhyZWFkPVRSVUUscmFuZG9taXplID0gVFJVRSkKcnVuM19lcnJSIDwtIGxlYXJuRXJyb3JzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgW3ByaW1lcnNfbl9zYW1wbGVzJFJ1biA9PSAiZWNvbW9sX2lTZXEiICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMiBRZmlsdGVyZWQiXSwgCiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpdGhyZWFkPVRSVUUscmFuZG9taXplID0gVFJVRSkKCgojICAgIyBwbG90RXJyb3JzKHJ1bjNfZXJyRiwgbm9taW5hbFE9VFJVRSkKIyAgICMgcGxvdEVycm9ycyhydW4zX2VyclIsIG5vbWluYWxRPVRSVUUpCmBgYAoKPGJyPgoKIyMjIERlcmVwbGljYXRpb246IGdyb3VwaW5nIGludG8gQVNWcwoKT24gdGhpcyBzdGVwIGVhY2ggbGlicmFyeSBpcyByZWR1Y2VkIHRvIGl0cyB1bmlxdWUgY29tcG9zaW5nIHNlcXVlbmNlcyBhbmQgdGhlaXIgY291bnRzLgoKYGBge3IsIGV2YWw9RkFMU0V9CiMgMTQgLSBkYWRhIGRlcmVwbGljYXRpb24gLS0tLQoKCm5hbWVzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgKSA8LSBwcmltZXJzX25fc2FtcGxlcyRGaWxlX25hbWUgIyMjISEhISEhISEhISEhISBFdmVyeXRoaW5nIG11c3QgaGF2ZSB1bmlxdWUgbmFtZXMgZnJvbSBoZXJlCgp1bmlxdWUocHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWApCm5hbWVzKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgKQoKCiNydW4gTEdDX01pbmlTZXFfMSAtLS0tCkxHQ18xX2RlcmVwX2ZvcndhcmQgPC0gZGVyZXBGYXN0cShwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFsKICBwcmltZXJzX25fc2FtcGxlcyRSdW4gPT0gIkxHQ19NaW5pU2VxXzEiICYgCiAgICBwcmltZXJzX25fc2FtcGxlcyRTdGFnZSA9PSAiUjEgUWZpbHRlcmVkIl0sIHZlcmJvc2U9VFJVRSkKIyBuYW1lcyhhbGxfZGVyZXBfZm9yd2FyZCkgPC0gYWxsX3NhbXBsZS5uYW1lcwoKTEdDXzFfZGVyZXBfcmV2ZXJzZSA8LSBkZXJlcEZhc3RxKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgWwogIHByaW1lcnNfbl9zYW1wbGVzJFJ1biA9PSAiTEdDX01pbmlTZXFfMSIgJiAKICAgIHByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMiBRZmlsdGVyZWQiXSwgdmVyYm9zZT1UUlVFKQojIG5hbWVzKGFsbF9kZXJlcF9yZXZlcnNlKSA8LSBhbGxfc2FtcGxlLm5hbWVzCgpMR0NfMV9kYWRhRnMgPC0gZGFkYShMR0NfMV9kZXJlcF9mb3J3YXJkLCBlcnI9cnVuMV9lcnJGLCBtdWx0aXRocmVhZD1UUlVFKQpMR0NfMV9kYWRhUnMgPC0gZGFkYShMR0NfMV9kZXJlcF9yZXZlcnNlLCBlcnI9cnVuMV9lcnJSLCBtdWx0aXRocmVhZD1UUlVFKQoKI3J1biBMR0NfTWluaVNlcV8yIC0tLS0KTEdDXzJfZGVyZXBfZm9yd2FyZCA8LSBkZXJlcEZhc3RxKHByaW1lcnNfbl9zYW1wbGVzJGBSZWFkIGZpbGVgWwogIHByaW1lcnNfbl9zYW1wbGVzJFJ1biA9PSAiTEdDX01pbmlTZXFfMiIgJiAKICAgIHByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMSBRZmlsdGVyZWQiXSwgdmVyYm9zZT1UUlVFKQojIG5hbWVzKGFsbF9kZXJlcF9mb3J3YXJkKSA8LSBhbGxfc2FtcGxlLm5hbWVzCgpMR0NfMl9kZXJlcF9yZXZlcnNlIDwtIGRlcmVwRmFzdHEocHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbCiAgcHJpbWVyc19uX3NhbXBsZXMkUnVuID09ICJMR0NfTWluaVNlcV8yIiAmIAogICAgcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIyIFFmaWx0ZXJlZCJdLCB2ZXJib3NlPVRSVUUpCiMgbmFtZXMoYWxsX2RlcmVwX3JldmVyc2UpIDwtIGFsbF9zYW1wbGUubmFtZXMKCkxHQ18yX2RhZGFGcyA8LSBkYWRhKExHQ18yX2RlcmVwX2ZvcndhcmQsIGVycj1ydW4yX2VyckYsIG11bHRpdGhyZWFkPVRSVUUpCkxHQ18yX2RhZGFScyA8LSBkYWRhKExHQ18yX2RlcmVwX3JldmVyc2UsIGVycj1ydW4yX2VyclIsIG11bHRpdGhyZWFkPVRSVUUpCgojcnVuIGVjb21vbF9pU2VxIC0tLS0KZWNvbW9sX2RlcmVwX2ZvcndhcmQgPC0gZGVyZXBGYXN0cShwcmltZXJzX25fc2FtcGxlcyRgUmVhZCBmaWxlYFsKICBwcmltZXJzX25fc2FtcGxlcyRSdW4gPT0gImVjb21vbF9pU2VxIiAmIAogICAgcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIxIFFmaWx0ZXJlZCJdLCB2ZXJib3NlPVRSVUUpCiMgbmFtZXMoYWxsX2RlcmVwX2ZvcndhcmQpIDwtIGFsbF9zYW1wbGUubmFtZXMKCmVjb21vbF9kZXJlcF9yZXZlcnNlIDwtIGRlcmVwRmFzdHEocHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWBbCiAgcHJpbWVyc19uX3NhbXBsZXMkUnVuID09ICJlY29tb2xfaVNlcSIgJiAKICAgIHByaW1lcnNfbl9zYW1wbGVzJFN0YWdlID09ICJSMiBRZmlsdGVyZWQiXSwgdmVyYm9zZT1UUlVFKQojIG5hbWVzKGFsbF9kZXJlcF9yZXZlcnNlKSA8LSBhbGxfc2FtcGxlLm5hbWVzCgplY29tb2xfZGFkYUZzIDwtIGRhZGEoZWNvbW9sX2RlcmVwX2ZvcndhcmQsIGVycj1ydW4zX2VyckYsIG11bHRpdGhyZWFkPVRSVUUpCmVjb21vbF9kYWRhUnMgPC0gZGFkYShlY29tb2xfZGVyZXBfcmV2ZXJzZSwgZXJyPXJ1bjNfZXJyUiwgbXVsdGl0aHJlYWQ9VFJVRSkKCgphbGxfZGFkYUZzIDwtIGMoZWNvbW9sX2RhZGFGcyxMR0NfMl9kYWRhRnMsTEdDXzFfZGFkYUZzKQphbGxfZGFkYVJzIDwtIGMoZWNvbW9sX2RhZGFScyxMR0NfMl9kYWRhUnMsTEdDXzFfZGFkYVJzKQoKbmFtZXMoYWxsX2RhZGFGcykKCmBgYAoKPGJyPgoKIyMjIE1lcmdlIHJlYWQgcGFpcnMgCgpPbiB0aGlzIHN0ZXAgdGhlIGZvcndhcmQgYW4gcmV2ZXJzZSByZWFkcyBhcmUgbWVyZ2VkLCBieSBvdmVybGFwLCBpbiBvcmRlciB0byByZWNvbnN0cnVjdCB0aGUgaW5zZXJ0IGZ1bGwgc2VxdWVuY2UuCkFzIHdlIGhhdmUgc2FtcGxlcyBmcm9tIHRocmVlIHJ1bnMsIHRoZXkgYXJlIGFsbCB3b3JrZWQgaW5kZXBlbmRlbnRseS4KCmBgYHtyLCBldmFsPUZBTFNFfQojIDE1IC0gbWVyZ2UgcmVhZCBwYWlycyAtLS0tCgojcnVuMSAtLS0tCnJ1bjFfbWVyZ2VycyA8LSBtZXJnZVBhaXJzKGRhZGFGID0gTEdDXzFfZGFkYUZzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRlcmVwRiA9IExHQ18xX2RlcmVwX2ZvcndhcmQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGFkYVIgPSBMR0NfMV9kYWRhUnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVyZXBSID0gTEdDXzFfZGVyZXBfcmV2ZXJzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5PdmVybGFwID0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4TWlzbWF0Y2ggPSAwLCAgICMgY2hhbmdlZCBmcm9tIDAgdG8gMSBzaW5jZSBhIGxvdCB3YXMgYmVpbmcgbGVmdCBvdXQgZm9yIHNpbmdsZSBtaXNtYXRjaAogICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVyblJlamVjdHMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VFJVRSkKCiNydW4yIC0tLS0KcnVuMl9tZXJnZXJzIDwtIG1lcmdlUGFpcnMoZGFkYUYgPSBMR0NfMl9kYWRhRnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVyZXBGID0gTEdDXzJfZGVyZXBfZm9yd2FyZCwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYWRhUiA9IExHQ18yX2RhZGFScywKICAgICAgICAgICAgICAgICAgICAgICAgICBkZXJlcFIgPSBMR0NfMl9kZXJlcF9yZXZlcnNlLAogICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk92ZXJsYXAgPSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhNaXNtYXRjaCA9IDAsICAgIyBjaGFuZ2VkIGZyb20gMCB0byAxIHNpbmNlIGEgbG90IHdhcyBiZWluZyBsZWZ0IG91dCBmb3Igc2luZ2xlIG1pc21hdGNoCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuUmVqZWN0cyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFKQoKI3J1bjEgLS0tLQpydW4zX21lcmdlcnMgPC0gbWVyZ2VQYWlycyhkYWRhRiA9IGVjb21vbF9kYWRhRnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVyZXBGID0gZWNvbW9sX2RlcmVwX2ZvcndhcmQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGFkYVIgPSBlY29tb2xfZGFkYVJzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGRlcmVwUiA9IGVjb21vbF9kZXJlcF9yZXZlcnNlLAogICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk92ZXJsYXAgPSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhNaXNtYXRjaCA9IDAsICAgIyBjaGFuZ2VkIGZyb20gMCB0byAxIHNpbmNlIGEgbG90IHdhcyBiZWluZyBsZWZ0IG91dCBmb3Igc2luZ2xlIG1pc21hdGNoCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuUmVqZWN0cyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFKQoKYWxsX21lcmdlcnMgPC0gYyhydW4zX21lcmdlcnMscnVuMl9tZXJnZXJzLHJ1bjFfbWVyZ2VycykKCm5hbWVzKGFsbF9tZXJnZXJzKQoKbGVuZ3RoKGFsbF9kYWRhRnMpCmxlbmd0aChhbGxfZGFkYVJzKQpoZWFkKGFsbF9tZXJnZXJzW1sxMl1dKQpsZW5ndGgoYWxsX2RhZGFGcykKbmFtZXMoYWxsX21lcmdlcnMpCnN0cihhbGxfbWVyZ2VycykKY2xhc3MoYWxsX21lcmdlcnMpCgoKIyBhbGxfc2VxdGFiIDwtIG1ha2VTZXF1ZW5jZVRhYmxlKHNhbXBsZXMgPSBjKHJ1bjNfbWVyZ2VycyxydW4yX21lcmdlcnMscnVuMV9tZXJnZXJzKSkgICAjdGFsdmV6IGVzc2EgZnVuw6fDo28gYWNlaXRlIHZhcmlvcyBtZXJnZXJzCmFsbF9zZXF0YWIgPC0gbWFrZVNlcXVlbmNlVGFibGUoc2FtcGxlcyA9IGFsbF9tZXJnZXJzKQpkaW0oYWxsX3NlcXRhYikKVmlldyhhbGxfc2VxdGFiKQpzdHIoYWxsX3NlcXRhYikKIyBJbnNwZWN0IGRpc3RyaWJ1dGlvbiBvZiBzZXF1ZW5jZSBsZW5ndGhzCnRhYmxlKG5jaGFyKGdldFNlcXVlbmNlcyhhbGxfc2VxdGFiKSkpCnRhYmxlKG5jaGFyKGdldFNlcXVlbmNlcyhhbGxfc2VxdGFiKSkpICU+JSBwbG90KCkKCgpuYW1lcyhhbGxfZGFkYUZzKQpuYW1lcyhhbGxfZGVyZXBfZm9yd2FyZCkKbmFtZXMoYWxsX2RhZGFScykKbmFtZXMoYWxsX2RlcmVwX3JldmVyc2UpCgpgYGAKCjxicj4KCiMjIyBSZW1vdmUgX2NoaW1lcmFzXyAKCl9DaGltZXJhc18gYXJlIGFydGlmaWNpYWwgcmVhZCBwYWlycyB0aGF0IG1pZ2h0IGhhdmUgYmVlbiBnZW5lcmF0ZWQgZXJyb25lb3VzbHkgb24gc2VxdWVuY2luZy4gVGhlICoqREFEQTIqKiBwYWNrYWdlIGVzdGltYXRlcyB0aGUgcHJvYmFiaWxpdHkgb2YgYSBzZXF1ZW5jZSB0byBiZSBjaGltZXJpYyBnaXZlbiB0aGUgYWJ1bmRhbmN5IG9mIGl0cyBwYXJlbnRhbCBzZXF1bmNlcy4gQWZ0ZXIgY2hpbWVyaWMgc2VxdWVuY2VzIHJlbW92YWwsIHRoZSByZW1haW5pbmcgQVNWcyBsZW5ndGggZGlzdHJpYnV0aW9uIGlzIGFzc2Vzc2VkLiBPbiBmdXJ0aGVyIHN0ZXBzIGl0IHdpbGwgYmUgdXNlZCB0byByZXN0cmljdCBhbmFsaXN5cyB0byBBU1ZzIGNvbXBhdGlibGUgd2l0aCBlYWNoIHByaW1lciBhbXBsaWNvbnMnIGxlbmd0aCBpbnRlcnZhbCwgaW4gb3JkZXIgdG8ga2VlcCBvZiB1bmV4cGVjdGVkIEFTVnMuCgpgYGB7ciwgZXZhbD1GQUxTRX0KIyAxNiAtIHJlbW92ZSBjaGltZXJhcyAtLS0tCgoKIyBhbnkoY29sbmFtZXMoQzFjb25jX3NlcXRhYikgJWluJSBjb2xuYW1lcyhhbGxfc2VxdGFiKSkKCmFsbF9zZXF0YWIubm9jaGltIDwtIHJlbW92ZUJpbWVyYURlbm92byhhbGxfc2VxdGFiLCBtZXRob2Q9ImNvbnNlbnN1cyIsIG11bHRpdGhyZWFkPVRSVUUsIHZlcmJvc2U9VFJVRSkKZGltKGFsbF9zZXF0YWIubm9jaGltKQpzdW0oYWxsX3NlcXRhYi5ub2NoaW0pL3N1bShhbGxfc2VxdGFiKSAjID0gIDAuODQwNDc0MyAsIHBlcmRhIGRlIDE2JSBuYSBhYnVuZGFuY2lhCiNjb3VudCBwcm9wb3J0aW9uIG9mIEFTVnMgb2YgYSBnaXZlbiBsZW5ndGgKdGFibGUobmNoYXIoZ2V0U2VxdWVuY2VzKGFsbF9zZXF0YWIubm9jaGltKSkpCnRhYmxlKG5jaGFyKGdldFNlcXVlbmNlcyhhbGxfc2VxdGFiLm5vY2hpbSkpKSAlPiUgcGxvdCgpCnJvd25hbWVzKGFsbF9zZXF0YWIubm9jaGltKQoKCgpWaWV3KGFsbF9zZXF0YWIubm9jaGltKQpzdHIoYWxsX3NlcXRhYi5ub2NoaW0pCgpgYGAKPGJyPgoKIyMjIENvdW50IHJlYWRzIGFuZCByZW1haW5pbmcgQVNWcwoKYGBge3IsIGV2YWw9RkFMU0V9CiMgMTcgLSBjb3VudCByZWFkcyBwcm9wb3J0aW9uIHRocm91Z2hvdXQgdGhlIHBpcGVsaW5lIC0tLS0KCmdldE4gPC0gZnVuY3Rpb24oeCkgc3VtKGdldFVuaXF1ZXMoeCkpCgojcHJlcGFyaW5nIHN1YnRhYmxlcyB3aXRoIG5hbWVkIHJvd3MgdG8gY29tYmluZSBsYXR0ZXIKI3JhdyBmaWxlcwoKbmFtZXMocHJpbWVyc19uX3NhbXBsZXMkYFJlYWQgZmlsZWApIDwtIHByaW1lcnNfbl9zYW1wbGVzJExpYnJhcnkgCgpyYXdfcmVhZHMgPC0gcHJpbWVyc19uX3NhbXBsZXMgJT4lIGZpbHRlcihTdGFnZSAlaW4lIGMoIlIxIiwiUjIiKSkgCgpyYXdfcmVhZHNfY291bnRzIDwtIFNob3J0UmVhZDo6Y291bnRGYXN0cShkaXJQYXRoID0gcmF3X3JlYWRzJGBSZWFkIGZpbGVgKSAlPiUgYXNfdGliYmxlKHJvd25hbWVzID0gIlJlYWQgZmlsZSIpCnJhd19yZWFkc19jb3VudHMgPC0gbGVmdF9qb2luKHggPSByYXdfcmVhZHNfY291bnRzLCB5ID0gKHJhd19yZWFkcyAlPiUgIG11dGF0ZShgUmVhZCBmaWxlYCA9IGJhc2VuYW1lKGBSZWFkIGZpbGVgKSkgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksYnkgPSAiUmVhZCBmaWxlIikKCnRibF9yYXdfRldEIDwtIHJhd19yZWFkc19jb3VudHNbcmF3X3JlYWRzX2NvdW50cyRTdGFnZSAlaW4lIGMoIlIxIiksXSAlPiUgc2VsZWN0KEZpbGVfbmFtZSwgcmVjb3JkcykgJT4lIGBjb2xuYW1lczwtYChjKCJGaWxlX25hbWUiLCAiUmF3IEZXRCIpKQp0YmxfcmF3X1JFViA8LSByYXdfcmVhZHNfY291bnRzW3Jhd19yZWFkc19jb3VudHMkU3RhZ2UgJWluJSBjKCJSMiIpLF0gJT4lIHNlbGVjdChGaWxlX25hbWUsIHJlY29yZHMpICU+JSBgY29sbmFtZXM8LWAoYygiRmlsZV9uYW1lIiwgIlJhdyBSRVYiKSkKCgoKdGJsX0Rlbm9pc2VkX0ZXRCA8LSAoc2FwcGx5KGFsbF9kYWRhRnMsIGdldE4pICU+JSBhc190aWJibGUocm93bmFtZXMgPSAiRmlsZV9uYW1lIikpICU+JSBgY29sbmFtZXM8LWAoYygiRmlsZV9uYW1lIiwgIkRlbm9pc2VkIEZXRCIpKQp0YmxfRGVub2lzZWRfUkVWIDwtIChzYXBwbHkoYWxsX2RhZGFScywgZ2V0TikgJT4lIGFzX3RpYmJsZShyb3duYW1lcyA9ICJGaWxlX25hbWUiKSkgJT4lIGBjb2xuYW1lczwtYChjKCJGaWxlX25hbWUiLCAiRGVub2lzZWQgUkVWIikpCnRibF9NZXJnZWQgPC0gKHJvd1N1bXMoYWxsX3NlcXRhYikgJT4lIGFzX3RpYmJsZShyb3duYW1lcyA9ICJGaWxlX25hbWUiKSkgJT4lIGBjb2xuYW1lczwtYChjKCJGaWxlX25hbWUiLCAiTWVyZ2VkIikpCnRibF9Ob25fY2hpbWVyaWMgPC0gKHJvd1N1bXMoYWxsX3NlcXRhYi5ub2NoaW0pICU+JSBhc190aWJibGUocm93bmFtZXMgPSAiRmlsZV9uYW1lIikpICU+JSBgY29sbmFtZXM8LWAoYygiRmlsZV9uYW1lIiwgIk5vbi1jaGltZXJpYyIpKQoKIyBjb21iaW5lIGFsbCBjb3VudHMgYnkgc2FtcGxlIHRvIHBsb3QKCmFsbF90cmFjayA8LSBhbGxfZmlsdGVyZWRfb3V0ICU+JSAgYXNfdGliYmxlKHJvd25hbWVzID0gIkZpbGVfbmFtZSIpICU+JSAKICBtdXRhdGUoYEZpbGVfbmFtZWAgPSBzdHJfcmVtb3ZlKHN0cmluZyA9IGBGaWxlX25hbWVgLCBwYXR0ZXJuID0gIl9SMV9jdXRhZGFwdC5mYXN0cS5neiIpKSAlPiUgCiAgbGVmdF9qb2luKHRibF9yYXdfRldELGJ5ID0gIkZpbGVfbmFtZSIpICU+JSAKICBsZWZ0X2pvaW4odGJsX3Jhd19SRVYsYnkgPSAiRmlsZV9uYW1lIikgJT4lIAogIGxlZnRfam9pbih0YmxfRGVub2lzZWRfRldELGJ5ID0gIkZpbGVfbmFtZSIpICU+JSAKICBsZWZ0X2pvaW4odGJsX0Rlbm9pc2VkX1JFVixieSA9ICJGaWxlX25hbWUiKSAlPiUgCiAgbGVmdF9qb2luKHRibF9NZXJnZWQsYnkgPSAiRmlsZV9uYW1lIikgJT4lIAogIGxlZnRfam9pbih0YmxfTm9uX2NoaW1lcmljLGJ5ID0gIkZpbGVfbmFtZSIpICU+JSAKICBsZWZ0X2pvaW4ocHJpbWVyc19uX3NhbXBsZXNbcHJpbWVyc19uX3NhbXBsZXMkU3RhZ2UgPT0gIlIxIixdLGJ5ID0gIkZpbGVfbmFtZSIpICU+JSAKICBzZWxlY3QoIWMoIlN0YWdlIiwgIlJlYWQgZmlsZSIpKQoKCgpjb2xuYW1lcyhhbGxfdHJhY2spIDwtIGMoIkZpbGVfbmFtZSIsIk4tY2xlYW5lZCIsICJGaWx0ZXJlZCIsIlJhdyBGV0QiLCAiUmF3IFJFViIsICJEZW5vaXNlZCBGV0QiLCAiRGVub2lzZWQgUkVWIiwgIk1lcmdlZCIsICJOb24tQ2hpbWVyaWMiLCAiVHlwZSIsICJHcm91cCIsICJMaWJyYXJ5IiwgIlByaW1lciIsICJSdW4iKQoKCgoKIyBDb21iaW5lIHRhYmxlcyB0b2dldGhlciAoaWYgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSkKdHJhY2tfdGJsIDwtIGJpbmRfcm93cyhhbGxfdHJhY2spCgoKewphbGxfdHJhY2skRmlsZV9uYW1lW2FsbF90cmFjayRGaWxlX25hbWUgPT0gIkNhc3NhdW0iXSA8LSAiUG9zaXRpdmUgQ29udHJvbFxuKFAuZ2xhdWNhKSIKYWxsX3RyYWNrJEZpbGVfbmFtZVthbGxfdHJhY2skRmlsZV9uYW1lID09ICJEYTE5Il0gPC0gIkRhMTkiCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAiRGEyMCJdIDwtICJEYTIwIgphbGxfdHJhY2skRmlsZV9uYW1lW2FsbF90cmFjayRGaWxlX25hbWUgPT0gIkRhMjEiXSA8LSAiRGEyMSIKYWxsX3RyYWNrJEZpbGVfbmFtZVthbGxfdHJhY2skRmlsZV9uYW1lID09ICJEYTIyIl0gPC0gIkRhMjIiCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAiRGEyMy1taWYiXSA8LSAiRGEyMy1taWYiCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAiRGEyMy1uZW8iXSA8LSAiRGEyMy1uZW8iCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAibmVnLVBDUjIiXSA8LSAibmVnLVBDUjIiCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAicEplcXVlaS1OLW5vcm0tTSJdIDwtICJOb24tbm9ybWFsaXplZCBKUW1jXG5NaUZpc2giCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAicEplcXVlaS1OLW5vcm0tTiJdIDwtICJOb24tbm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIgphbGxfdHJhY2skRmlsZV9uYW1lW2FsbF90cmFjayRGaWxlX25hbWUgPT0gInBKZXF1ZWktTi1ub3JtLVQiXSA8LSAiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuVGVsZW8iCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAicEplcXVlaS1ub3JtLU0iXSA8LSAiTm9ybWFsaXplZCBKUW1jXG5NaUZpc2giCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAicEplcXVlaS1ub3JtLU4iXSA8LSAiTm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIgphbGxfdHJhY2skRmlsZV9uYW1lW2FsbF90cmFjayRGaWxlX25hbWUgPT0gInBKZXF1ZWktbm9ybS1UIl0gPC0gIk5vcm1hbGl6ZWQgSlFtY1xuVGVsZW8iCmFsbF90cmFjayRGaWxlX25hbWVbYWxsX3RyYWNrJEZpbGVfbmFtZSA9PSAiU0ZKUS1taWYiXSA8LSAiTm9ybWFsaXplZCBTRkpRbWNcbk1pRmlzaCIKYWxsX3RyYWNrJEZpbGVfbmFtZVthbGxfdHJhY2skRmlsZV9uYW1lID09ICJTRkpRLW5lbyJdIDwtICJOb3JtYWxpemVkIFNGSlFtY1xuTmVvRmlzaCIKYWxsX3RyYWNrJEZpbGVfbmFtZVthbGxfdHJhY2skRmlsZV9uYW1lID09ICJTRm5Ob3JtLW1pIl0gPC0gIk5vbi1ub3JtYWxpemVkIFNGbWNcbk1pRmlzaCIKYWxsX3RyYWNrJEZpbGVfbmFtZVthbGxfdHJhY2skRmlsZV9uYW1lID09ICJTRm5Ob3JtLW5lbyJdIDwtICJOb24tbm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIgphbGxfdHJhY2skRmlsZV9uYW1lW2FsbF90cmFjayRGaWxlX25hbWUgPT0gIlNGTm9ybS1taSJdIDwtICJOb3JtYWxpemVkIFNGbWNcbk1pRmlzaCIKYWxsX3RyYWNrJEZpbGVfbmFtZVthbGxfdHJhY2skRmlsZV9uYW1lID09ICJTRk5vcm0tbmVvIl0gPC0gIk5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIKfQoKCiMgc2F2ZSByZWFkcyBjb3VudHMgdGFibGUKCgoKd3JpdGV4bDo6d3JpdGVfeGxzeCh4ID0gYWxsX3RyYWNrLAogICAgICAgICAgICAgICAgICAgIHBhdGggPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9zZmpxX3JlYWRfY291bnRzX2Fsb25nX3F1YWxpdHlfY29udHJvbC54bHN4IiwKICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBUUlVFLGZvcm1hdF9oZWFkZXJzID0gVFJVRSkKCgoKCgoKIyBwbG90IHJlYWRzIHByb3BvcnRpb24gdHJvdWdob3V0IHRoZSBwaXBlbGluZSAtLS0tCgoKdHJhY2tfdGJsJFByaW1lciAlPiUgdW5pcXVlKCkKdHJhY2tfdGJsJEZpbGVfbmFtZSAlPiUgdW5pcXVlKCkKCiNUT0RPCiMgaHR0cHM6Ly9iaGFza2FydmsuZ2l0aHViLmlvL2NvbG9ybWFwLwojaHR0cHM6Ly93d3cudGhpbmtpbmdvbmRhdGEuY29tL3NvbWV0aGluZy1hYm91dC12aXJpZGlzLWxpYnJhcnkvCiNzZXQgY29sb3JzIGhlcmUgc3MKCgoKCiNwZXJkYSBwb3IgZmlsdHJhciBOCmFsbF90cmFjayAlPiUgbXV0YXRlKHBlcmRhID0gYE4tY2xlYW5lZGAvYFJhdyBGV0RgKQoKCiMxOCAtIHNldCBjb2xvcnMgZm9yIGRvd25zdHJlYW0gcGxvdHMgLS0tLQoKIyBjb2xvcnMgCnNjYWxlczo6c2hvd19jb2woY29sb3JzNSkKCgoKY29sb3JzNSA8LSBjKCIjMDE3NTA0IiwiIzAwMDc5MSIsIiM4MjAwMDAiLCIjNzgwMDU4IiwiI2ZmNTUwMCIpICNuZW8sbWksdGVsLGFsbApjb2xvcnNfbm9ybSA8LSBjKCIjMDE3NTA0IiwiIzRmYzk1MiIsCiAgICAgICAgICAgICAgICAgIiMwMDA3OTEiLCIjMzg2MmViIiwKICAgICAgICAgICAgICAgICAiIzgyMDAwMCIsIiNiZjRiNGIiKQpzY2FsZXM6OnNob3dfY29sKGNvbG9yc19ub3JtKQpzY2FsZXM6OnNob3dfY29sKGNvbG9yczUpCgojUExPVDIgLSBzYW1wbGUgdHJhY2sgcGxvdCAtLS0tCgojICMgdHJhY2tfdGJsJEZpbGVfbmFtZSAlPiUgcGFzdGUwKCciXG4iJyxjb2xsYXBzZSA9ICIiKSAlPiUgY2F0KCkKIyB0cmFja190YmwkRmlsZV9uYW1lICU+JSB1bmlxdWUoKSAlPiUgYmFzZTo6c29ydCgpICU+JSBwYXN0ZTAoY29sbGFwc2UgPSAnXG4nKSAlPiUgIGNhdCgpCiMgc2FtcGxlX2xldmVscwoKCiB7CnRyYWNrX3RibCRGaWxlX25hbWVbdHJhY2tfdGJsJEZpbGVfbmFtZSA9PSAiQ2Fzc2F1bSJdIDwtICJQb3NpdGl2ZSBDb250cm9sXG4oUC5nbGF1Y2EpIgp0cmFja190YmwkRmlsZV9uYW1lW3RyYWNrX3RibCRGaWxlX25hbWUgPT0gIkRhMTkiXSA8LSAiRGExOSIKdHJhY2tfdGJsJEZpbGVfbmFtZVt0cmFja190YmwkRmlsZV9uYW1lID09ICJEYTIwIl0gPC0gIkRhMjAiCnRyYWNrX3RibCRGaWxlX25hbWVbdHJhY2tfdGJsJEZpbGVfbmFtZSA9PSAiRGEyMSJdIDwtICJEYTIxIgp0cmFja190YmwkRmlsZV9uYW1lW3RyYWNrX3RibCRGaWxlX25hbWUgPT0gIkRhMjIiXSA8LSAiRGEyMiIKdHJhY2tfdGJsJEZpbGVfbmFtZVt0cmFja190YmwkRmlsZV9uYW1lID09ICJEYTIzLW1pZiJdIDwtICJEYTIzLW1pZiIKdHJhY2tfdGJsJEZpbGVfbmFtZVt0cmFja190YmwkRmlsZV9uYW1lID09ICJEYTIzLW5lbyJdIDwtICJEYTIzLW5lbyIKI3RyYWNrX3RibCRGaWxlX25hbWVbdHJhY2tfdGJsJEZpbGVfbmFtZSA9PSAibmVnLVBDUjIiXSA8LQp0cmFja190YmwkRmlsZV9uYW1lW3RyYWNrX3RibCRGaWxlX25hbWUgPT0gInBKZXF1ZWktTi1ub3JtLU0iXSA8LSAiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIgp0cmFja190YmwkRmlsZV9uYW1lW3RyYWNrX3RibCRGaWxlX25hbWUgPT0gInBKZXF1ZWktTi1ub3JtLU4iXSA8LSAiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTmVvRmlzaCIKdHJhY2tfdGJsJEZpbGVfbmFtZVt0cmFja190YmwkRmlsZV9uYW1lID09ICJwSmVxdWVpLU4tbm9ybS1UIl0gPC0gIk5vbi1ub3JtYWxpemVkIEpRbWNcblRlbGVvIgp0cmFja190YmwkRmlsZV9uYW1lW3RyYWNrX3RibCRGaWxlX25hbWUgPT0gInBKZXF1ZWktbm9ybS1NIl0gPC0gIk5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIgp0cmFja190YmwkRmlsZV9uYW1lW3RyYWNrX3RibCRGaWxlX25hbWUgPT0gInBKZXF1ZWktbm9ybS1OIl0gPC0gIk5vcm1hbGl6ZWQgSlFtY1xuTmVvRmlzaCIKdHJhY2tfdGJsJEZpbGVfbmFtZVt0cmFja190YmwkRmlsZV9uYW1lID09ICJwSmVxdWVpLW5vcm0tVCJdIDwtICJOb3JtYWxpemVkIEpRbWNcblRlbGVvIgp0cmFja190YmwkRmlsZV9uYW1lW3RyYWNrX3RibCRGaWxlX25hbWUgPT0gIlNGSlEtbWlmIl0gPC0gIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giCnRyYWNrX3RibCRGaWxlX25hbWVbdHJhY2tfdGJsJEZpbGVfbmFtZSA9PSAiU0ZKUS1uZW8iXSA8LSAiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2giCnRyYWNrX3RibCRGaWxlX25hbWVbdHJhY2tfdGJsJEZpbGVfbmFtZSA9PSAiU0ZuTm9ybS1taSJdIDwtICJOb24tbm9ybWFsaXplZCBTRm1jXG5NaUZpc2giCnRyYWNrX3RibCRGaWxlX25hbWVbdHJhY2tfdGJsJEZpbGVfbmFtZSA9PSAiU0ZuTm9ybS1uZW8iXSA8LSAiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIKdHJhY2tfdGJsJEZpbGVfbmFtZVt0cmFja190YmwkRmlsZV9uYW1lID09ICJTRk5vcm0tbWkiXSA8LSAiTm9ybWFsaXplZCBTRm1jXG5NaUZpc2giCnRyYWNrX3RibCRGaWxlX25hbWVbdHJhY2tfdGJsJEZpbGVfbmFtZSA9PSAiU0ZOb3JtLW5lbyJdIDwtICJOb3JtYWxpemVkIFNGbWNcbk5lb0Zpc2giCn0KCgoKCnNhbXBsZV9sZXZlbHMgPC0gYygKIkRhMjMtbWlmIiwgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giLAoiRGEyMy1uZW8iLCAiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2giLAoiRGEyMCIsIk5vbi1ub3JtYWxpemVkIFNGbWNcbk1pRmlzaCIsCiJEYTE5IiwiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIsCiJEYTIyIiwiTm9ybWFsaXplZCBTRm1jXG5NaUZpc2giLAoiRGEyMSIsIk5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIsCiJOb24tbm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIiwiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIiwiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuVGVsZW8iLAoiTm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIiwiTm9ybWFsaXplZCBKUW1jXG5NaUZpc2giLCJOb3JtYWxpemVkIEpRbWNcblRlbGVvIiwKIlBvc2l0aXZlIENvbnRyb2xcbihQLmdsYXVjYSkiLCJuZWctUENSMiIpCgoKIyBQcmVwYXJlIGNvdW50cyBmb3IgcGxvdGluZyAtLS0tCgogIHRyYWNrX3RibCA8LSB0cmFja190YmwgJT4lCiAgZ2F0aGVyKGtleSA9ICJTdGFnZSIsCiAgICAgICAgdmFsdWUgPSAiUmVhZCBOdW1iZXIiLAogICAgICAgICJSYXcgUkVWIiwiUmF3IEZXRCIsCiAgICAgICAgIk4tY2xlYW5lZCIsICJGaWx0ZXJlZCIsICJEZW5vaXNlZCBGV0QiLAogICAgICAgICJEZW5vaXNlZCBSRVYiLCAiTWVyZ2VkIiwgIk5vbi1DaGltZXJpYyIpICU+JQogIG11dGF0ZShTdGFnZSA9IGZhY3RvcihTdGFnZSwgbGV2ZWxzID0gYygiTm9uLUNoaW1lcmljIiwgIk1lcmdlZCIsICJEZW5vaXNlZCBSRVYiLCAiRGVub2lzZWQgRldEIiwgIkZpbHRlcmVkIiwiTi1jbGVhbmVkIiwgIlJhdyBSRVYiLCJSYXcgRldEIikpKSAlPiUKICBtdXRhdGUoCiAgICBQcmltZXIgPSBmYWN0b3IoUHJpbWVyLCBsZXZlbHMgPSBjKCJOZW9GaXNoIiwgIk1pRmlzaCIsICJUZWxlbyIsIk5lb0Zpc2gvTWlGaXNoIiwgICJOZW9GaXNoL01pRmlzaC9UZWxlbyIpKSwKICAgIEZpbGVfbmFtZSA9IGZhY3RvcihGaWxlX25hbWUsbGV2ZWxzID0gc2FtcGxlX2xldmVscykpCgogIG9wdGlvbnMoc2NpcGVuID0gMjIpCiAgCiAgIyB0cmFja190YmwgJT4lIGJhc2U6OnNvcnQodHJhY2tfdGJsJFNhbXBsZSkgCgojIHBsb3RpbmcgLS0tLQogICAgCiAgdHJhY2tfcGxvdCA8LSB0cmFja190YmwgJT4lIAogICAgIyBmaWx0ZXIoUnVuICVpbiUgYygiTEdDX01pbmlTZXFfMSIsICJMR0NfTWluaVNlcV8yIikpICU+JSAKICAgICMgZmlsdGVyKEdyb3VwICVpbiUgYygiRE5BIHBvb2wiKSkgJT4lIAogICAgZ2dwbG90KGFlcyh5ID0gU3RhZ2UseCA9IGBSZWFkIE51bWJlcmAsIGZpbGwgPSBQcmltZXIsIGdyb3VwID0gU3RhZ2UpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDMwMDAwMCwgY29sID0gMSwgbGluZXR5cGUgPSAyKSArCiAgICBzY2FsZV9maWxsX21hbnVhbChsYWJlbHMgPSBjKCJOZW9GaXNoIiwgIk1pRmlzaCIsICJUZWxlbyIsICJOZW9GaXNoL01pRmlzaCIsIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIiksCiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBhbHBoYShjb2xvdXIgPSBjb2xvcnM1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAgMC43NSkpICsKICAgIGxhYnModGl0bGUgPSAiTEdDIGVETkEgMXN0ICYgMm5kIHJ1bnMiLAogICAgICAgICBzdWJ0aXRsZSA9ICJSZWFkIGNvdW50cyBwZXIgbGlicmFyeSBhbmQgZmlsdGVyaW5nIHN0ZXAiLAogICAgICAgICB4ID0gIlJlYWQgY291bnRzIiwKICAgICAgICAgeSA9ICJEYXRhIGZpbHRlcmluZyBzdGVwIikrCiAgICBmYWNldF93cmFwKH5GaWxlX25hbWUsbmNvbCA9IDYpICsKICAgIGNvb3JkX2ZpeGVkKHJhdGlvID0gNjAwMDApICsKICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDcpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgICB0aGVtZShheGlzLnRpdGxlID0gZ2d0ZXh0OjplbGVtZW50X21hcmtkb3duKCkpCgp0cmFja19wbG90IAoKCgoKCgoKIyBzYXZlIHBsb3QKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL1NGSlFfc2FtcGxlX3RyYWNrX3Bsb3QucG5nIiwKICAgICBwbG90ID0gdHJhY2tfcGxvdCwKICAgICBkZXZpY2UgPSAicG5nIiwKICAgICB3aWR0aCA9IDEyLAogICAgIGhlaWdodCA9IDEwLAogICAgIHVuaXRzID0gImNtIiwKICAgICBkcGkgPSA2MDApCgojIHNhdmUgcGxvdApnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvU0ZKUV9zYW1wbGVfdHJhY2tfcGxvdC5zdmciLAogICAgIHBsb3QgPSB0cmFja19wbG90LAogICAgIGRldmljZSA9ICJzdmciLAogICAgIHdpZHRoID0gMTIsCiAgICAgaGVpZ2h0ID0gMTAsCiAgICAgdW5pdHMgPSAiY20iLAogICAgIGRwaSA9IDYwMCkKCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvU0ZKUV9zYW1wbGVfdHJhY2tfcGxvdC5wZGYiLAogICAgIHBsb3QgPSB0cmFja19wbG90LAogICAgIGRldmljZSA9ICJwZGYiLAogICAgIHdpZHRoID0gMjAsCiAgICAgaGVpZ2h0ID0gMTYsCiAgICAgdW5pdHMgPSAiY20iLAogICAgIGRwaSA9IDYwMCkKCgpgYGAKClJlYWRzIHByb3BvcnRpb25zIGFyZSBkaXNwbGF5ZWQgYmVsb3cuIFRoZSBleHBlcmltZW50YWwgZGVzaWduIGludGVuZGVkIHRoZSBzYW1lIHJlYWQgeWllbGQgZm9yIGFsbCBsaWJzLCBiZXR3ZWVuICAyMDBLIGEgMjUwSyByZWFkcy4gVGhlIGRldmlhdGlvbnMgb2YgdGhpcyByZWFuZ2UgYXJlIHByb2JhYmx5IGR1ZSB0byBkb3NhZ2UvcGlwZXR0aW5nIGVycm9ycy4KCjxicj4KCjxicj4KCiMjIENsYXNzaWZ5IHRheG9ub215CgpPbiB0aGlzIHN0ZXAgdGhlIEFTVnMgaWRlbnRpZmllZCBieSB0aGUgKipEQURBMioqIHBpcGVsaW5lLCBqb2ludGx5IGZvciBhbGwgbGlicmFyaWVzIG9mIGVhY2ggcHJpbWVyLCBhcmUgYXNzb2NpYXRlZCAob3Igbm90KSB0byBhbnkgb2YgdGhlIHNlcXVlbmNlcyBvbiB0aGUgUmVmZXJlbmNlIDEyUyBTZXF1ZW5jZXMgRGF0YWJhc2UuIERBREEyIGhhcyB0d28gc3RyYXRlZ2llcyB0byBpZGVudGlmeSB0YXhhLiBUaGUgZmlyc3QsIF9hc3NpZ25TcGVjaWVzXywgaWRlbnRpZnkgcGVyZmVjdCBtYXRjaGVzIG9mIHRoZSBBU1ZzIGluIHRoZSBSZWZlcmVuY2UgRGF0YWJhc2UuIFRoZSBzZWNvbmQsIF9hc3NpZ25UYXhvbm9teV8sIHVzZSBhIFJEUCBOYWl2ZSBCYXllc2lhbiBDbGFzc2lmaWVyIGFsZ29yaXRobSAoV2FuZywgMjAwNykgd2l0aCBrbWVyIHNpemUgOCBhbmQgMTAwIGJvb3RzdHJhcCByZXBsaWNhdGVzIHRvIGFzc29jaWF0ZSBBU1ZzIHRvIHRoZSBSZWZlcmVuY2UgRGF0YWJhc2UgU2VxdWVuY2VzLiBJbiB0aGUgbGF0dGVyLCB0aGUgdGF4b25vbXkgcmFua3MgY2xhc3NpZmljYXRpb24gaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSBzZXF1ZW5jZSBzaW1pbGFyaXR5LCBhbHRob3VnaCB0aGlzIHJlbGF0aW9uIGlzIG5vdCB5ZXQgY2xlYXIgdG8gdXMuCgpgYGB7ciwgZXZhbD1GQUxTRX0KCiMxOSAtIGNsYXNzaWZ5IHRheG9ub215IGV4YWN0bHkgLS0tLQoKYWxsX3NwcyA8LSBkYWRhMjo6YXNzaWduU3BlY2llcyhzZXFzID0gYWxsX3NlcXRhYi5ub2NoaW0sYWxsb3dNdWx0aXBsZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgcmVmRmFzdGEgPSAgIn4vcHJqY3RzL2Zpc2hfZUROQS9kYXRhL3JlZnMvZGIvTEdDL2p1bDIxL2RhZGFfdGF4X2Z1bGxEQl9vcmRlcl9TUHNfanVsMjEuZmFzdGEiLAogICAgICAgICAgICAgICAgICAgICAgICAgdHJ5UkM9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSAyMDAwMCwKICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKCiNjaGVjayBob3cgbWFueSBBU1ZzIHdlcmUgZXhhY3RseSBpZGVudGlmaWVkIGFzIHNwZWNpZXMKClZpZXcoYWxsX3NwcykKCgogICAgICBhbGxfY3N2X3NwIDwtIGFsbF9zcHMgJT4lIGFzX3RpYmJsZSgpICU+JSBtdXRhdGUoQVNWID0gcm93bmFtZXMoYWxsX3NwcykpCiAgICAgIGNvbG5hbWVzKGFsbF9jc3Zfc3ApIDwtIGMoImV4YWN0IEdlbnVzIiwgImV4YWN0IFNwZWNpZXMiLCAiQVNWIikKCmBgYAoKYGBge3IsIGV2YWw9RkFMU0V9CiMyMCAtIGNsYXNzaWZ5IHRheG9ub215IC0tLS0KCmFsbF90YXhhIDwtIGRhZGEyOjphc3NpZ25UYXhvbm9teShzZXFzID0gYWxsX3NlcXRhYi5ub2NoaW0sCiAgICAgICAgICAgICAgICAgICAgIHJlZkZhc3RhID0gICJ+L3ByamN0cy9maXNoX2VETkEvZGF0YS9yZWZzL2RiL0xHQy9qdWwyMS9kYWRhX3RheF9mdWxsREJfb3JkZXJfanVsMjEuZmFzdGEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXRocmVhZD1UUlVFLCB0cnlSQz1UUlVFLHRheExldmVscyA9IGMoIktpbmdkb20iLCJQaHlsdW0iLCJDbGFzcyIsIk9yZGVyIiwiRmFtaWx5IiwgIkdlbnVzIiwgIlNwZWNpZXMiLCJTcGVjaW1lbiIsIkJhc2luIiksb3V0cHV0Qm9vdHN0cmFwcyA9IFRSVUUpCgoKYWxsX3RheGEkYm9vdAoKYGBgCgpgYGB7ciwgZXZhbD1GQUxTRSxlY2hvPUZBTFNFfQojIENsYXNzaWZ5IHRheG9ub215IHdpdGggREVDSVBIRVIKCiMgaW1wb3J0IHRyYWluaW5nIHNlcXVlbmNlcwpmYXMgPC0gc3lzdGVtLmZpbGUoImV4dGRhdGEiLCAiNTBTX3JpYm9zb21hbF9wcm90ZWluX0wyLmZhcyIsIHBhY2thZ2U9IkRFQ0lQSEVSIikKZG5hIDwtIHJlYWRETkFTdHJpbmdTZXQoZmFzKQoKIyBwYXJzZSB0aGUgaGVhZGVycyB0byBvYnRhaW4gYSB0YXhvbm9teQpzIDwtIHN0cnNwbGl0KG5hbWVzKGRuYSksICIgIikKZ2VudXMgPC0gc2FwcGx5KHMsIGBbYCwgMSkKc3BlY2llcyA8LSBzYXBwbHkocywgYFtgLCAyKQp0YXhvbm9teSA8LSBwYXN0ZSgiUm9vdCIsIGdlbnVzLCBzcGVjaWVzLCBzZXA9IjsgIikKaGVhZCh0YXhvbm9teSkKCiMgdHJhaW4gdGhlIGNsYXNzaWZpZXIKIyMgTm90IHJ1bjogCnRyYWluaW5nU2V0IDwtIExlYXJuVGF4YShkbmEsIHRheG9ub215KQp0cmFpbmluZ1NldAoKCkxHQzEyU2RiIDwtIEJpb3N0cmluZ3M6OnJlYWRETkFTdHJpbmdTZXQoZmlsZXBhdGggPSJ+L3ByamN0cy9maXNoX2VETkEvZGF0YS9yZWZzL2RiL0xHQy9mZXYyMS9kZWNpcGhlcl90YXhfZnVsbERCX29yZGVyX2ZldjIxLmZhc3RhIiApCiMjcHJlcGFyZSBEQgpMR0MxMlNkYl90cmFpbmluZ1NldCA8LSBERUNJUEhFUjo6TGVhcm5UYXhhKHRyYWluID0gTEdDMTJTZGIsdGF4b25vbXkgPSBuYW1lcyhMR0MxMlNkYikpCkxHQzEyU2RiX3RyYWluaW5nU2V0JHByb2JsZW1Hcm91cHMKCgojIyBjcmVhdGluZyBETkFTdHJpbmdTZXQgb2JqZWN0IG9mIG91ciBBU1ZzCmRuYSA8LSBETkFTdHJpbmdTZXQoZ2V0U2VxdWVuY2VzKGFsbF9zZXF0YWIubm9jaGltKSkKCndyaXRlLnRhYmxlKGFzdl90YXgsICJBU1ZzX3RheG9ub215LnRzdiIsIHNlcCA9ICJcdCIsIHF1b3RlPUYsIGNvbC5uYW1lcz1OQSkKCnRheF9pbmZvW1syXV0KCnN0cih0YXhfaW5mbykKVmlldyhhc3ZfdGF4KQoKCgpsaWJyYXJ5KGRlY29udGFtKQoKCmBgYAoKPGJyPjxicj4KCkhlcmUgdGhlICoqREFEQTIqKiBwaXBlbGluZSBlbmRzLgoKPGJyPjxicj48YnI+PGJyPgoKIyMgUGh5bG9zZXEKCk9uIHRoaXMgc3RlcCB0aGUgQVNWcyBhc3NvY2lhdGVkIHRvIHRheG9ub21pYyByYW5rcyBieSAqKkRBREEyKiogYW5kIHRoZWlyIHJlc3BlY3RpdmUgY291bnRzIGJ5IGxpYnJhcnksIGFyZSBjb21iaW5lZCB1c2luZyB0aGUgKipQaHlsb3NlcSoqIHBhY2thZ2UuCgo8YnI+CgojIyMgR2VuZXJhdGUgc2FtcGxlIG1ldGFkYXRhIHRhYmxlCgpIZXJlIHRoZSBleHBlcmltZW50IG1ldGFkYXRhIGlzIGFzc29jaWF0ZWQgdG8gZWFjaCBzYW1wbGUuCgpgYGB7ciwgZXZhbD1GQUxTRX0KIyAyMiAtIGNyZWF0ZSBzYW1wbGUgdGFibGUgLS0tLQoKI2NyZWF0ZSBhIHNhbXBsZSB0YWJsZSBmb3IgZWFjaCBwcmltZXIKCiMgcHJpbWVyc19uX3NhbXBsZXMkRmlsZV9uYW1lCgphbGxfc2FtZGYgPC0gdW5pcXVlKHByaW1lcnNfbl9zYW1wbGVzWzE6Nl0pCgpzYW1kZjwtIGFsbF9zYW1kZgoKI3Jvd25hbWVzIG11c3QgbWUgYXNzaWduZWQgaW4gb3JkZXIgdG8gdGhlIG5leHQgc3RlcCB0byB3b3JrCgpzYW1kZiA8LSBzYW1kZiAlPiUgYXMuZGF0YS5mcmFtZSgpCnJvd25hbWVzKHNhbWRmKSA8LSBzYW1kZiRGaWxlX25hbWUKYGBgCgo8YnI+CgpUaGlzIHNhbXBsZSBtZXRhZGF0YSB0YWJsZSB3YXMgY3JlYXRlZCB3aXRoIHRoZSBpbmZvcm1hdGlvbiBhdmFpbGFibGUgZm9yIHRoZSBzYW1wbGVzIGFuYWx5emVkIG9uIHRoaXMgZmlyc3QgcnVuLiBUaGlzIHRhYmxlIG11c3QgYmUgY3VzdG9taXplZCBmb3IgZWFjaCBleHBlcmltZW50LgoKPGJyPgoKYGBge3IsIGV2YWw9RkFMU0UsIGVjaG89RkFMU0V9CiMga25pdHI6OmthYmxlKHNhbWRmLGFsaWduID0gJ2MnKQojZXN0YSBydWltCgpgYGAKCjxicj48YnI+CgoKIyMjICoqUGh5bG9zZXEqKiBkYXRhIGludGVycHJldGF0aW9uCgpgYGB7ciwgZXZhbD1GQUxTRX0KIzIzIC0gaW50ZXJwcmV0IGRhZGEgb24gcGh5bG9zZXEgLS0tLQoKYWxsX3BzIDwtIHBoeWxvc2VxKG90dV90YWJsZShhbGxfc2VxdGFiLm5vY2hpbSwgdGF4YV9hcmVfcm93cyA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgIHNhbXBsZV9kYXRhKHNhbWRmKSwKICAgICAgICAgICAgICAgICAgIHRheF90YWJsZShhbGxfdGF4YSR0YXgpKQogICAgICAgICAgICAgICAgICAgIyB0YXhfdGFibGUoYWxsX3RheGEpKQoKcm93bmFtZXMoYWxsX3NlcXRhYi5ub2NoaW0pCgpgYGAKCjxicj4KCiMjIyBNZXJnZSBhbmQgRmxleCBQaHlsb3NlcSByZXN1bHRzIAoKTWFueSBkaWZmZXJlbnQgZ3JhcGhpY3MgY2FuIGJlIGdlbmVyYXRlZCwgdG9nZXRoZXIgb3IgaW4gaXNvbGF0aW9uLCBmb3IgYWxsIHByaW1lcnMvbGlicmFyaWVzIGFuZCB0YXhvbm9taWMgcmFua3MuCgpgYGB7ciwgZXZhbD1GQUxTRX0KIzI0IC0gbWVyZ2UgcHMgYW5hbGlzeXMgLS0tLQoKI21lbHQgcGh5bG9zZXEgb2JqZWN0IGludG8gdGJsCmFsbF9wc190YmwgPC0gcHNtZWx0KGFsbF9wcykgJT4lIGFzX3RpYmJsZSgpICU+JSBmaWx0ZXIoQWJ1bmRhbmNlID49IDEpCgpjb2xuYW1lcyhhbGxfcHNfdGJsKVtjb2xuYW1lcyhhbGxfcHNfdGJsKSA9PSAiT1RVIl0gPC0gIkFTViIKCnVuaXF1ZShhbGxfcHNfdGJsJEFTVikKIyB1bmlxdWUobmVvX3BzX3RibCRBU1YpCiMgdW5pcXVlKG1pZl9wc190YmwkQVNWKQoKYWxsX3BzX3RibCRTYW1wbGUgJT4lICB1bmlxdWUoKQphbGxfcHNfdGJsJFByaW1lciAlPiUgIHVuaXF1ZSgpCgojY29uY2F0ZW5hdGUgZXhhY3Qgc3BlY2llcyB0YWJsZQoKYWxsX3BzX3RibCA8LSBsZWZ0X2pvaW4oYnkgPSAiQVNWIix4PWFsbF9wc190YmwseT0gYWxsX2Nzdl9zcCkKCiMgYmFja3VwIHRhYmxlCiMgYWxsX3BzX3RibF9iY2twIDwtIGFsbF9wc190YmwKIyBhbGxfcHNfdGJsIDwtIGFsbF9wc190YmxfYmNrcAoKYGBgCgojIyBtZXRhQkxBU1RFciAtIElkZW50aWZ5IEFTVnMgd2l0aCBpbmhvdXNlIEJMQVNUbgoKClRoaXMgcGFja2FnZSBpcyBjdXJyZW50bHkgdW5kZXIgZGV2ZWxvcG1lbnQsIGJ1dCBmdWxseSBmdW5jdGlvbmFsLiBZb3Ugd2lsbCBuZWVkIGEgd29ya2luZyBOQ0JJLUJMQVNUKyBpbnN0YWxsZWQgYW5kIGEgQkxBU1QgZm9ybWF0ZWQgcmVmZXJlbmNlIERCIG9uIHRoZSBzYW1lIGxpbnV4IHNlcnZlciB5b3VyIFJzdHVkaW8tc2VydmVyIGlzIHJ1bm5pbmcgKGJ1dCB3ZSBhcmUgaW1wcm9vdmluZyBpdCB0byBydW4gb24gSU9TKS4KCmBgYHtyLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KIyBibGFzdG4gLS0tLQoKaW5zdGFsbC5wYWNrYWdlcygnQkxBU1RyJywgcmVwb3MgPSAiaHR0cHM6Ly9oZXJvbm9oLnItdW5pdmVyc2UuZGV2IikKIyBBbm5vdGF0ZSBhbGwgQVNWcyBieSBibGFzdE4KCmFzdnNfYmxhc3QgPC0gYWxsX3BzX3RibCRBU1YgJT4lIHVuaXF1ZSgpICU+JSBhcy5jaGFyYWN0ZXIoKSAKCgoKCiNJZGVudGlmeSB1c2luZyBtZXRhQkxBU1RyIHBhY2thZ2UgLS0tLQojIHBhcmFsZWxhIGNvbSAyIHRocmVhZHMgLS0tLQp0aWN0b2M6OnRpYygiUGFyYWxsZWwgLSBGdXJyciAyIHRocmVhZHMiKQoKYmxhc3RfcmVzIDwtIEJMQVNUcjo6cGFyYWxsZWxfYmxhc3QoCiAgZGJfcGF0aCA9ICIvZGF0YS9kYXRhYmFzZXMvbnRfanVuMjAyMy9udCIsCiAgYXN2cyA9IGFzdnNfYmxhc3RfYWxsLAogIG91dF9maWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvYmxhc3QvYmxhc3Rfb3V0X3Jlc18xLmNzdiIsCiAgb3V0X1JEUyA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2JsYXN0L2JsYXN0X291dF9yZXNfMS5SRFMiLAogIHRvdGFsX2NvcmVzID0gODAsCiAgcGVyY19pZCA9IDgwLAogIG51bV90aHJlYWRzID0gMiwKICBwZXJjX3Fjb3ZfaHNwID0gODAsCiAgbnVtX2FsaWdubWVudHMgPSAzLAogIGJsYXN0X3R5cGUgPSAiYmxhc3RuIgopCgp0aWN0b2M6OnRvYygpIyAKCgojICNTYXZlIGVudgogICBiYXNlOjpzYXZlLmltYWdlKCJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS8vZW52LWNhbmFzdHJhX3Bvc0JMQVNULTI1anVsMjMuUkRhdGEiKQoKICAgCgoKCmNvbG5hbWVzKGJsYXN0X3JlcykKCiMgYmxhc3RfcmVzIDwtIGJsYXN0X3JlcyAlPiUgcmVuYW1lKCJPVFUiID0iU2VxdWVuY2UiKQojIGJsYXN0X3JlcyA8LSBibGFzdF9yZXMgJT4lIHJlbmFtZSgiU2VxdWVuY2UiID0iT1RVIikKCmJsYXN0X3Jlc19mdWxsIDwtIGJpbmRfcm93cyhibGFzdF9yZXMpICU+JSAKICBzZWxlY3QoLWMoIk9UVSIpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGAxX3N1YmplY3QgaGVhZGVyYCkpCgpucm93KGJsYXN0X3JlcykKZGltKGJsYXN0X3JlcykKCmJsYXN0X3JlcyA8LSBibGFzdF9yZXMgJT4lICBmaWx0ZXIoYDFfcmVzYCA9PSAxICkgI3JlbW92ZXIgbyBxdWUgbsOjbyBkZXUgbmFkYSAgICAgICAgICAgIAoKc3RyKGJsYXN0X3JlcykKIApgYGAKCiMjIyBSZW5hbWUgc2FtcGxlcyBmb3IgcGxvdHMKCmBgYHtyLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KcHJpbWVyc19uX3NhbXBsZXMKc2FtcGxlX2xldmVscwoKewphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAiQ2Fzc2F1bSJdIDwtICJQb3NpdGl2ZSBDb250cm9sXG4oUC5nbGF1Y2EpIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAiRGExOSJdIDwtICJOb24tbm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIEIiCmFsbF9wc190YmwkRmlsZV9uYW1lW2FsbF9wc190YmwkRmlsZV9uYW1lID09ICJEYTIwIl0gPC0gIk5vbi1ub3JtYWxpemVkIFNGbWNcbk1pRmlzaCBCIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAiRGEyMSJdIDwtICJOb3JtYWxpemVkIFNGbWNcbk5lb0Zpc2ggQiIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gIkRhMjIiXSA8LSAiTm9ybWFsaXplZCBTRm1jXG5NaUZpc2ggQiIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gIkRhMjMtbWlmIl0gPC0gIlNGSlEtbWlmIEIiCmFsbF9wc190YmwkRmlsZV9uYW1lW2FsbF9wc190YmwkRmlsZV9uYW1lID09ICJEYTIzLW5lbyJdIDwtICJTRkpRLW5lbyBCIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAibmVnLVBDUjIiXSA8LSJuZWctUENSMiIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gInBKZXF1ZWktTi1ub3JtLU0iXSA8LSAiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAicEplcXVlaS1OLW5vcm0tTiJdIDwtICJOb24tbm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAicEplcXVlaS1OLW5vcm0tVCJdIDwtICJOb24tbm9ybWFsaXplZCBKUW1jXG5UZWxlbyIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gInBKZXF1ZWktbm9ybS1NIl0gPC0gIk5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAicEplcXVlaS1ub3JtLU4iXSA8LSAiTm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAicEplcXVlaS1ub3JtLVQiXSA8LSAiTm9ybWFsaXplZCBKUW1jXG5UZWxlbyIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gIlNGSlEtbWlmIl0gPC0gIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giCmFsbF9wc190YmwkRmlsZV9uYW1lW2FsbF9wc190YmwkRmlsZV9uYW1lID09ICJTRkpRLW5lbyJdIDwtICJOb3JtYWxpemVkIFNGSlFtY1xuTmVvRmlzaCIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gIlNGbk5vcm0tbWkiXSA8LSAiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIgphbGxfcHNfdGJsJEZpbGVfbmFtZVthbGxfcHNfdGJsJEZpbGVfbmFtZSA9PSAiU0ZuTm9ybS1uZW8iXSA8LSAiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gIlNGTm9ybS1taSJdIDwtICJOb3JtYWxpemVkIFNGbWNcbk1pRmlzaCIKYWxsX3BzX3RibCRGaWxlX25hbWVbYWxsX3BzX3RibCRGaWxlX25hbWUgPT0gIlNGTm9ybS1uZW8iXSA8LSAiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIgp9Cgp7CmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJDYXNzYXVtIl0gPC0gIlBvc2l0aXZlIENvbnRyb2xcbihQLmdsYXVjYSkiCmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJEYTE5Il0gPC0gIk5vbi1ub3JtYWxpemVkIFNGbWNcbk5lb0Zpc2ggQiIKYWxsX3BzX3RibCRTYW1wbGVbYWxsX3BzX3RibCRTYW1wbGUgPT0gIkRhMjAiXSA8LSAiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIEIiCmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJEYTIxIl0gPC0gIk5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCBCIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAiRGEyMiJdIDwtICJOb3JtYWxpemVkIFNGbWNcbk1pRmlzaCBCIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAiRGEyMy1taWYiXSA8LSAiTm9ybWFsaXplZCBTRkpRbWNcbk1pRmlzaCBCIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAiRGEyMy1uZW8iXSA8LSAiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2ggQiIKYWxsX3BzX3RibCRTYW1wbGVbYWxsX3BzX3RibCRTYW1wbGUgPT0gIm5lZy1QQ1IyIl0gPC0gIm5lZy1QQ1IyIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAicEplcXVlaS1OLW5vcm0tTSJdIDwtICJOb24tbm9ybWFsaXplZCBKUW1jXG5NaUZpc2giCmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJwSmVxdWVpLU4tbm9ybS1OIl0gPC0gIk5vbi1ub3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giCmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJwSmVxdWVpLU4tbm9ybS1UIl0gPC0gIk5vbi1ub3JtYWxpemVkIEpRbWNcblRlbGVvIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAicEplcXVlaS1ub3JtLU0iXSA8LSAiTm9ybWFsaXplZCBKUW1jXG5NaUZpc2giCmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJwSmVxdWVpLW5vcm0tTiJdIDwtICJOb3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giCmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJwSmVxdWVpLW5vcm0tVCJdIDwtICJOb3JtYWxpemVkIEpRbWNcblRlbGVvIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAiU0ZKUS1taWYiXSA8LSAiTm9ybWFsaXplZCBTRkpRbWNcbk1pRmlzaCIKYWxsX3BzX3RibCRTYW1wbGVbYWxsX3BzX3RibCRTYW1wbGUgPT0gIlNGSlEtbmVvIl0gPC0gIk5vcm1hbGl6ZWQgU0ZKUW1jXG5OZW9GaXNoIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAiU0ZuTm9ybS1taSJdIDwtICJOb24tbm9ybWFsaXplZCBTRm1jXG5NaUZpc2giCmFsbF9wc190YmwkU2FtcGxlW2FsbF9wc190YmwkU2FtcGxlID09ICJTRm5Ob3JtLW5lbyJdIDwtICJOb24tbm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAiU0ZOb3JtLW1pIl0gPC0gIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIgphbGxfcHNfdGJsJFNhbXBsZVthbGxfcHNfdGJsJFNhbXBsZSA9PSAiU0ZOb3JtLW5lbyJdIDwtICJOb3JtYWxpemVkIFNGbWNcbk5lb0Zpc2giCn0KCgoKCmFsbF9wc190YmwkR3JvdXAgJT4lICB1bmlxdWUoKSAlPiUgYmFzZTo6c29ydCgpCgoKIyBhbGxfcHNfdGJsJEdyb3VwIDwtIGFsbF9wc190YmwkR3JvdXAgJT4lIHVuZmFjdG9yKCkKewphbGxfcHNfdGJsJEdyb3VwW2FsbF9wc190YmwkR3JvdXAgJWluJSBjKCJKcU5ub3JtIildIDwtICJOb24tbm9ybWFsaXplZCBKUW1jIgphbGxfcHNfdGJsJEdyb3VwW2FsbF9wc190YmwkR3JvdXAgJWluJSBjKCJKcU5vcm0iKV0gPC0gIk5vcm1hbGl6ZWQgSlFtYyIKYWxsX3BzX3RibCRHcm91cFthbGxfcHNfdGJsJEdyb3VwICVpbiUgYygiU0ZuTm9ybSIpXSA8LSAiTm9uLW5vcm1hbGl6ZWQgU0ZtYyIKYWxsX3BzX3RibCRHcm91cFthbGxfcHNfdGJsJEdyb3VwICVpbiUgYygiU0ZOb3JtIildIDwtICJOb3JtYWxpemVkIFNGbWMiCmFsbF9wc190YmwkR3JvdXBbYWxsX3BzX3RibCRHcm91cCAlaW4lIGMoIlNGSlEiKV0gPC0gIk5vcm1hbGl6ZWQgU0ZKUW1jIgphbGxfcHNfdGJsJEdyb3VwW2FsbF9wc190YmwkR3JvdXAgJWluJSBjKCJQb3NpdGl2ZSBjb250cm9sIildIDwtICJQb3NpdGl2ZSBjb250cm9sXG4oUC4gZ2xhdWNhKSIKfQphbGxfcHNfdGJsJEdyb3VwICU+JSB1bmlxdWUoKQoKYWxsX3BzX3RibCRHcm91cCA8LSBhbGxfcHNfdGJsJEdyb3VwICU+JSAgZmFjdG9yKGxldmVscyA9IGMoIk5vbi1ub3JtYWxpemVkIEpRbWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaXplZCBKUW1jIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vbi1ub3JtYWxpemVkIFNGbWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaXplZCBTRm1jIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGl6ZWQgU0ZKUW1jIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBvc2l0aXZlIGNvbnRyb2xcbihQLiBnbGF1Y2EpIikpCgoKc2FtcGxlX2xldmVscyA8LSBjKAoiTm9ybWFsaXplZCBTRkpRbWNcbk1pRmlzaCBCIiwgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giLAoiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2ggQiIsICJOb3JtYWxpemVkIFNGSlFtY1xuTmVvRmlzaCIsCgoiTm9ybWFsaXplZCBTRm1jXG5NaUZpc2ggQiIsIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwKIk5vbi1ub3JtYWxpemVkIFNGbWNcbk1pRmlzaCBCIiwiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwKIk5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCBCIiwiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiwKIk5vbi1ub3JtYWxpemVkIFNGbWNcbk5lb0Zpc2ggQiIsIk5vbi1ub3JtYWxpemVkIFNGbWNcbk5lb0Zpc2giLAoKIk5vbi1ub3JtYWxpemVkIEpRbWNcbk1pRmlzaCIsIk5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIiwKIk5vbi1ub3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giLCJOb3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giLAoiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuVGVsZW8iLCJOb3JtYWxpemVkIEpRbWNcblRlbGVvIiwKCiJQb3NpdGl2ZSBDb250cm9sXG4oUC5nbGF1Y2EpIiwibmVnLVBDUjIiKQoKIyBhbGxfcHNfdGJsX2JsYXN0JFNhbXBsZVthbGxfcHNfdGJsX2JsYXN0JFNhbXBsZSAlaW4lIGMoInBvb2wgbsOjby1ub3JtYWxpemFkb1xuTWlGaXNoIildIAoKYWxsX3BzX3RibCRTYW1wbGUgPC0gYWxsX3BzX3RibCRTYW1wbGUgJT4lICBmYWN0b3IobGV2ZWxzID0gc2FtcGxlX2xldmVscykKCgpjbGFzcyhhc3ZzX2JsYXN0KQoKICAKYWxsX3BzX3RibF9ibGFzdCA8LSBsZWZ0X2pvaW4oeCA9IGFsbF9wc190YmwseSA9IGJsYXN0X3JlcyxieSA9ICJBU1YiKQoKY29sbmFtZXMoYWxsX3BzX3RibF9ibGFzdCkKCiNhbGxfcHNfdGJsX2JsYXN0X2Jja3AgPC0gYWxsX3BzX3RibF9ibGFzdAojYWxsX3BzX3RibF9ibGFzdCA8LSBhbGxfcHNfdGJsX2JsYXN0X2Jja3AKCmBgYAoKCiMjIEFTVnMgc2VxcyAKCmBgYHtyLGVjaG89VFJVRSwgZXZhbD1GQUxTRX0KIzI1IC0gcmVjb3ZlciBhbGwgQVNWcyBzZXF1ZW5jZXMgdG8gcHJlcGFyZSBmYXN0YSAtLS0tCgoKI2FsbCAtLS0tCiMgZ2l2aW5nIG91ciBzZXEgaGVhZGVycyBtb3JlIG1hbmFnZWFibGUgbmFtZXMgKEFTVl8xLCBBU1ZfMi4uLikKIyBhbGxfYXN2X3NlcXMgPC0gdGliYmxlKCJBU1YiID0gY29sbmFtZXMoc2VxdGFiLm5vY2hpbSkpCmFsbF9hc3Zfc2VxcyA8LSB0aWJibGUoIkFTViIgPSBhc3ZzX2JsYXN0KQoKYWxsX2Fzdl9zZXFzIDwtIGFsbF9hc3Zfc2VxcyAlPiUgCiAgbXV0YXRlKCJBU1YgbGVuZ3RoIiA9IG5jaGFyKEFTViksCiAgICAgICAgICJBU1YgaGVhZGVyIiA9IGFzLmNoYXJhY3RlcigiIikpCgphbGxfYXN2X3NlcXMgPC0gYWxsX2Fzdl9zZXFzW2Jhc2U6Om9yZGVyKGFsbF9hc3Zfc2VxcyRgQVNWIGxlbmd0aGApLF0KICBmb3IgKGkgaW4gMTpucm93KGFsbF9hc3Zfc2VxcykpIHsKCiAgICBhbGxfYXN2X3NlcXMkYEFTViBoZWFkZXJgW2ldIDwtIHBhc3RlMCgiPkFTVl8iLCBpLCAiXyIsIGFsbF9hc3Zfc2VxcyRgQVNWIGxlbmd0aGBbaV0sICJicCIpCgogIH0KCgojY29tYmluZSBBU1YgaGVhZGVycyBhbmQgYWxsX3BzX3RibAphbGxfcHNfdGJsX2JsYXN0IDwtIGRwbHlyOjpsZWZ0X2pvaW4oeCA9IGFsbF9wc190YmxfYmxhc3QsICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGFsbF9hc3Zfc2VxcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gIkFTViIgKQoKCiMgbWFraW5nIGFuZCB3cml0aW5nIG91dCBhIGZhc3RhIG9mIG91ciBmaW5hbCBBU1Ygc2VxcyB3aXRoIHRheApmb3IgKGFzdiBpbiAxOm5yb3coYWxsX2Fzdl9zZXFzKSkgewogIAogIHRheCA8LSBhbGxfcHNfdGJsX2JsYXN0ICU+JSAKICAgIGZpbHRlcihBU1YgPT0gYWxsX2Fzdl9zZXFzJEFTVlthc3ZdKSAlPiUgCiAgICBzZWxlY3QoIktpbmdkb20iLCAiUGh5bHVtIiwgIkNsYXNzIiwgIk9yZGVyIiwgIkZhbWlseSIsICJHZW51cyIsICJTcGVjaWVzIiwgIlNwZWNpbWVuIikgJT4lIAogICAgdW5pcXVlKCkgJT4lIAogICAgcGFzdGUwKGNvbGxhcHNlID0gInwiKQogIAogIGFsbF9hc3Zfc2VxcyRgQVNWIGhlYWRlcmBbYXN2XSA8LSBwYXN0ZTAoYWxsX2Fzdl9zZXFzJGBBU1YgaGVhZGVyYFthc3ZdLCJfIix0YXgpCiAgCiAgIyBpZiAoY29uZGl0aW9uKSB7CiAgIyBmYXplciBhbGd1bSB0ZXN0ZSBwcmEgdmVyIHNlciB0YSBjZXJ0bwogICMgfQp9Cgojd3JpdGUgZmFzdGEgZmlsZSB3aXRoIEFTVnMgYW5kIFRheG9ub215CmFsbF9hc3ZfZmFzdGEgPC0gYyhyYmluZChhbGxfYXN2X3NlcXMkYEFTViBoZWFkZXJgLCBhbGxfYXN2X3NlcXMkQVNWKSkKCndyaXRlKGFsbF9hc3ZfZmFzdGEsICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL3NmanFfYWxsX0FTVnNfYWxsX3ByaW1lcnMuZmFzdGEiKQoKYGBgCgoKIyMjIFNXQVJNIC0gQVNWcyB0byBPVFVzCgpgYGB7cixlY2hvPVRSVUUsIGV2YWw9RkFMU0V9CiMgI3N3YXJtCgphc3ZzX2FiZCA8LSBhbGxfcHNfdGJsX2JsYXN0ICU+JQogIGdyb3VwX2J5KGBBU1ZgLGBBU1YgaGVhZGVyYCkgJT4lCiAgbXV0YXRlKCJBU1YgdG90YWwgYWJ1bmRhbmNlIiA9IHN1bShBYnVuZGFuY2UpKSAlPiUKICBzZWxlY3QoYyhgQVNWYCxgQVNWIGhlYWRlcmAsYEFTViB0b3RhbCBhYnVuZGFuY2VgKSkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgbXV0YXRlKGBBU1YgaGVhZGVyYCA9IHBhc3RlMChgQVNWIGhlYWRlcmAsIl8iLGBBU1YgdG90YWwgYWJ1bmRhbmNlYCkpCgoKYXN2c19hYmQkQVNWICU+JSB1bmlxdWUoKQphc3ZzX2FiZCRgQVNWIGhlYWRlcmAgJT4lIHVuaXF1ZSgpCgoKI3dyaXRlIGZhc3RhIGZpbGUgd2l0aCBBU1ZzIGFuZCAgYWJ1bmRhbmNlCiMgYWxsX2Fzdl9mYXN0YV9hYmQgPC0gYyhyYmluZChhc3ZzX2FiZCRgQVNWIGhlYWRlciBwcmltZXJgLCBhc3ZzX2FiZCRgQVNWYCkpCmFsbF9hc3ZfZmFzdGFfYWJkIDwtIGMocmJpbmQoYXN2c19hYmQkYEFTViBoZWFkZXJgLCBhc3ZzX2FiZCRgQVNWYCkpCgojIHdyaXRlKGFsbF9hc3ZfZmFzdGFfYWJkLCAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9zZmpxX0FTVnNfYWJkX3ByaW1lci5mYXN0YSIpCndyaXRlKGFsbF9hc3ZfZmFzdGFfYWJkLCBwYXN0ZTAocmVzdWx0c19wYXRoLCIvc2ZqcV9BU1ZzX2FiZC5mYXN0YSIpKQoKIyB+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9zd2FybSQgc3dhcm0gLXQgNTAgfi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9zZmpxX0FTVnNfYWJkLmZhc3RhIC1zIHNmanFfc3dhcm0uc3RhdHMgLW8gc2ZqcV9zd2FybS5vdXQgLXcgc2ZqcV9yZXByZXNlbnRhdGl2ZV9PVFVzLmZhc3RhIC1pIHNmanFfc3dhcm0uc3RydWN0dXJlIC1mCgoKc3dhcm1fY2x1c3QgPC0gcmVhZHI6OnJlYWRfbGluZXMoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3N3YXJtL3NmanFfc3dhcm0ub3V0IikKCgoKCgphc3ZzX2FiZCA8LSBhc3ZzX2FiZCAlPiUgbXV0YXRlKCJPVFUiPSAwKQoKCgpmb3IgKGFzdiBpbiAxOm5yb3coYXN2c19hYmQpKXsKICBmb3IgKGxpbmUgaW4gMTpsZW5ndGgoc3dhcm1fY2x1c3QpKSB7CiAgICBpZiAoc3RyX2RldGVjdChzdHJpbmcgPSAgc3dhcm1fY2x1c3RbbGluZV0sCiAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gc3RyX3JlbW92ZShhc3ZzX2FiZCRgQVNWIGhlYWRlcmBbYXN2XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiPiIpKSkgewogIGFzdnNfYWJkJE9UVVthc3ZdIDwtIGxpbmUKICAgIH0KICAgIH0KfQoKCgphbGxfcHNfdGJsX2JsYXN0IDwtIGxlZnRfam9pbih4ID0gYWxsX3BzX3RibF9ibGFzdCx5ID0gYXN2c19hYmRbLGMoMSwzLDQpXSxieT0iQVNWIiApIAoKIyBhbGxfcHNfdGJsX2JsYXN0ICU+JSBzZWxlY3QoYGZpbmFsIElEYCxPVFUpICU+JSBWaWV3KCkgCiMgYWxsX3BzX3RibF9ibGFzdCAlPiUgc2VsZWN0KGBmaW5hbCBJRGAsT1RVKSAlPiUgc2VsZWN0KE9UVSkgJT4lIHVuaXF1ZSgpIAojIGFsbF9wc190YmxfYmxhc3QgJT4lIHNlbGVjdChBU1YsYGZpbmFsIElEYCxPVFUpICU+JSBzZWxlY3QoQVNWKSAlPiUgdW5pcXVlKCkgCgoKYWxsX3BzX3RibF9ibGFzdCRPVFUgJT4lIHVuaXF1ZSgpCmFsbF9wc190YmxfYmxhc3QkR3JvdXAgJT4lIHVuaXF1ZSgpCgpgYGAKCiMjIENhbGN1bGF0ZSBzYW1wbGUgYWJ1bmRhbmNlcyAtLS0tCgpgYGB7ciwgZXZhbD1GQUxTRX0KCiNhZGQgQVNWIGxlZ3RoIHRvIHRhYmxlCiMgYWxsX3BzX3RibF9ibGFzdF9iY2twMiA8LSBhbGxfcHNfdGJsX2JsYXN0CiMgYWxsX3BzX3RibF9ibGFzdCA8LSBhbGxfcHNfdGJsX2JsYXN0X2Jja3AyCgoKYWxsX3BzX3RibF9ibGFzdCA8LSBhbGxfcHNfdGJsX2JsYXN0ICU+JSAKICBtdXRhdGUoIlJlbGF0aXZlIGFidW5kYW5jZSB0byBhbGwgc2FtcGxlcyIgPSAwLAogICAgICAgICAiUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZSIgPSAwLAogICAgICAgICAiU2FtcGxlIHRvdGFsIGFidW5kYW5jZSIgPSAwKQoKYWJkX3RvdGFsIDwtIHN1bShhbGxfcHNfdGJsX2JsYXN0JEFidW5kYW5jZSkKCgoKCmFsbF9wc190YmxfYmxhc3QgPC0gYWxsX3BzX3RibF9ibGFzdCAlPiUKICBncm91cF9ieShTYW1wbGUpICU+JQogIG11dGF0ZSgiU2FtcGxlIHRvdGFsIGFidW5kYW5jZSIgPSBzdW0oQWJ1bmRhbmNlKSwKICAgICAgICAgIlJlbGF0aXZlIGFidW5kYW5jZSB0byBhbGwgc2FtcGxlcyIgPSBBYnVuZGFuY2UvYWJkX3RvdGFsLAogICAgICAgICAiUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZSIgPSBBYnVuZGFuY2UvYFNhbXBsZSB0b3RhbCBhYnVuZGFuY2VgKSAlPiUKICB1bmdyb3VwKCkKCmBgYAoKIyMjIFNldCBmaW5hbCBpZGVudGlmaWNhdGlvbiBmcm9tIGFsbCBwb3NzaWJpbGl0aWVzCgpgYGB7ciwgZXZhbD1GQUxTRX0KCgphbGxfcHNfdGJsX2JsYXN0IDwtIGFsbF9wc190YmxfYmxhc3QgJT4lIAogIG11dGF0ZShgZXhhY3QgR2VuU3BgID0gcGFzdGUoYGV4YWN0IEdlbnVzYCxgZXhhY3QgU3BlY2llc2Asc2VwPSIgIikpCgoKCmFsbF9wc190YmxfYmxhc3QgPC0gYWxsX3BzX3RibF9ibGFzdCAlPiUgCiAgbXV0YXRlKCJmaW5hbCBJRCIgPSBpZl9lbHNlKChgZXhhY3QgU3BlY2llc2AgJWluJSBjKE5BLCJOQSIsICJOQSBOQSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZSgoU3BlY2llcyAlaW4lIGMoTkEsIk5BIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoR2VudXMgJWluJSBjKE5BLCJOQSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic3RyKGFzLmNoYXJhY3RlcihgMV9zdWJqZWN0IGhlYWRlcmApLDEsMzApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2VudXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNwZWNpZXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5jaGFyYWN0ZXIoYGV4YWN0IEdlblNwYCkpKQoKCmBgYAoKI0dyb3VwL2NvcnJlY3Qgc3BlY2llcyBmb3IgcGxvdGluZwoKYGBge3IsZWNobz1UUlVFLCBldmFsPUZBTFNFfQojIGFsbF9wc190YmxfYmxhc3RfYmNrcDMgPC0gYWxsX3BzX3RibF9ibGFzdAoKI1NwZWNpZXMgZGV0ZWN0ZWQKYWxsX3BzX3RibF9ibGFzdCRgZmluYWwgSURgICU+JSB1bmlxdWUoKSAlPiUgYmFzZTo6c29ydCgpCnsKYWxsX3BzX3RibF9ibGFzdCRgZmluYWwgSURgWyhhbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGAgJWluJSBjKCJBc3R5YW5heCBhZmZfZmFzY2lhdHVzIiwiQXN0eWFuYXggY2ZfZmFzY2lhdHVzIikpXSA8LSAiQXN0eWFuYXggZmFzY2lhdHVzIgphbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGBbKGFsbF9wc190YmxfYmxhc3QkYGZpbmFsIElEYCAlaW4lIGMoIkFzdHlhbmF4IGNmX2xhY3VzdHJpcyIpKV0gPC0gIkFzdHlhbmF4IGxhY3VzdHJpcyIKYWxsX3BzX3RibF9ibGFzdCRgZmluYWwgSURgWyhhbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGAgJWluJSBjKCJDaGFyYWNpZGl1bSBzcCIpKV0gPC0gIkNoYXJhY2lkaXVtIgphbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGBbKGFsbF9wc190YmxfYmxhc3QkYGZpbmFsIElEYCAlaW4lIGMoIkh5cG9zdG9tdXMgc3AiKSldIDwtICJIeXBvc3RvbXVzIgphbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGBbKGFsbF9wc190YmxfYmxhc3QkYGZpbmFsIElEYCAlaW4lIGMoIkhvcGxpYXMgbWFsYWJhcmljdXMvc3AiKSldIDwtICJIb3BsaWFzIG1hbGFiYXJpY3VzIgphbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGBbKGFsbF9wc190YmxfYmxhc3QkYGZpbmFsIElEYCAlaW4lIGMoIlJoYW1kaWEgYWZmX3F1ZWxlbiIpKV0gPC0gIlJoYW1kaWEgcXVlbGVuIgphbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGBbKGFsbF9wc190YmxfYmxhc3QkYGZpbmFsIElEYCAlaW4lIGMoIkNvcHRvZG9uIHppbGxpaSBLQVVNOkk6OTAxMjYgbSIpKV0gPC0gIkNvcHRvZG9uIHppbGxpaSIKYWxsX3BzX3RibF9ibGFzdCRgZmluYWwgSURgWyhhbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGAgJWluJSBjKCJUcmFjaGVseW9wdGVydXMgY2ZfZ2FsZWF0dXMvZ2FsZWF0dXMiKSldIDwtICJUcmFjaGVseW9wdGVydXMgZ2FsZWF0dXMiCn0KCmBgYAoKCiMjIyBJZGVudGlmeSBwcmltZXJzIGV4cGVjdGVkIEFTViBsZWd0aCByYW5nZQoKYGBge3IsIGV2YWw9RkFMU0V9CgojIGNyZWF0ZSByYW5nZXMgY29sdW1uCmFsbF9wc190YmxfYmxhc3QgPC0gYWxsX3BzX3RibF9ibGFzdCAlPiUKICAgbXV0YXRlKCJFeHBlY3RlZCBsZW5ndGgiID0gIkZBTFNFIikKCgojIGZpbGwgcmFuZ2VzIGNvbHVtbiB3aXRoIGV4cGVjdGVkIHByaW1lciBpbnNlcnQgcmFuZ2VzCgpmb3IgKGFzdiBpbiAxOm5yb3coYWxsX3BzX3RibF9ibGFzdCkpIHsKICAgaWYgKGFsbF9wc190YmxfYmxhc3QkUHJpbWVyW2Fzdl0gPT0gIk5lb0Zpc2giKSB7CiAgICAgIGlmIChhbGxfcHNfdGJsX2JsYXN0JGBBU1YgbGVuZ3RoYFthc3ZdID49IDE4NSAmJiBhbGxfcHNfdGJsX2JsYXN0JGBBU1YgbGVuZ3RoYFthc3ZdIDw9IDIwMCkgewogICAgICAgICBhbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgW2Fzdl0gPC0gImluIHJhbmdlIgogICAgICB9ZWxzZXsKICAgICAgICAgYWxsX3BzX3RibF9ibGFzdCRgRXhwZWN0ZWQgbGVuZ3RoYFthc3ZdIDwtICJvdXQgb2YgcmFuZ2UiCiAgICAgICAgIH0KCiAgIH0KICAgaWYgKGFsbF9wc190YmxfYmxhc3QkUHJpbWVyW2Fzdl0gPT0gIk1pRmlzaCIpIHsKICAgICAgaWYgKGFsbF9wc190YmxfYmxhc3QkYEFTViBsZW5ndGhgW2Fzdl0gPj0gMTY1ICYmIGFsbF9wc190YmxfYmxhc3QkYEFTViBsZW5ndGhgW2Fzdl0gPD0gMTgwKSB7CiAgICAgICAgIGFsbF9wc190YmxfYmxhc3QkYEV4cGVjdGVkIGxlbmd0aGBbYXN2XSA8LSAiaW4gcmFuZ2UiCiAgICAgIH1lbHNlewogICAgICAgICBhbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgW2Fzdl0gPC0gIm91dCBvZiByYW5nZSIKICAgICAgfQoKICAgfQogIGlmIChhbGxfcHNfdGJsX2JsYXN0JFByaW1lclthc3ZdID09ICJUZWxlbyIpIHsKICAgICAgaWYgKGFsbF9wc190YmxfYmxhc3QkYEFTViBsZW5ndGhgW2Fzdl0gPj0gNjAgJiYgYWxsX3BzX3RibF9ibGFzdCRgQVNWIGxlbmd0aGBbYXN2XSA8PSA3NSkgewogICAgICAgICBhbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgW2Fzdl0gPC0gImluIHJhbmdlIgogICAgICB9ZWxzZXsKICAgICAgICAgYWxsX3BzX3RibF9ibGFzdCRgRXhwZWN0ZWQgbGVuZ3RoYFthc3ZdIDwtICJvdXQgb2YgcmFuZ2UiCiAgICAgIH0KCiAgIH0KICBpZiAoYWxsX3BzX3RibF9ibGFzdCRQcmltZXJbYXN2XSA9PSAiTmVvRmlzaC9NaUZpc2giKSB7CiAgICAgIGlmIChhbGxfcHNfdGJsX2JsYXN0JGBBU1YgbGVuZ3RoYFthc3ZdID49IDE2NSAmJiBhbGxfcHNfdGJsX2JsYXN0JGBBU1YgbGVuZ3RoYFthc3ZdIDw9IDIwMCkgewogICAgICAgICBhbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgW2Fzdl0gPC0gImluIHJhbmdlIgogICAgICB9ZWxzZXsKICAgICAgICAgYWxsX3BzX3RibF9ibGFzdCRgRXhwZWN0ZWQgbGVuZ3RoYFthc3ZdIDwtICJvdXQgb2YgcmFuZ2UiCiAgICAgIH0KCiAgIH0KICBpZiAoYWxsX3BzX3RibF9ibGFzdCRQcmltZXJbYXN2XSA9PSAiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKSB7CiAgICAgIGlmIChhbGxfcHNfdGJsX2JsYXN0JGBBU1YgbGVuZ3RoYFthc3ZdICVpbiUgYyg2MDo3NSwxNjU6MTgwLDE4NToyMDApKSB7CiAgICAgICAgIGFsbF9wc190YmxfYmxhc3QkYEV4cGVjdGVkIGxlbmd0aGBbYXN2XSA8LSAiaW4gcmFuZ2UiCiAgICAgIH1lbHNlewogICAgICAgICBhbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgW2Fzdl0gPC0gIm91dCBvZiByYW5nZSIKICAgICAgfQoKICAgfQoKfQoKCiNmYWN0b3JpemUgY29tbHVtbgphbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgIDwtIGFzLmZhY3RvcihhbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgKQoKYGBgCgoKI1Jlb3JkZXIgdGFibGUgCgpgYGB7ciwgZXZhbD1GQUxTRX0KCnBhc3RlMChjb2xuYW1lcyhhbGxfcHNfdGJsX2JsYXN0KSwiXG4iKSAlPiUgIGNhdCgpCgoKIyBhbGxfcHNfdGJsX2JsYXN0X2Jja3A0IDwtIGFsbF9wc190YmxfYmxhc3QKIyBhbGxfcHNfdGJsX2JsYXN0IDwtIGFsbF9wc190YmxfYmxhc3RfYmNrcDQKCgphbGxfcHNfdGJsX2JsYXN0IDwtIAogIGFsbF9wc190YmxfYmxhc3QgJT4lIAogIHNlbGVjdChjKCJTYW1wbGUiLCJHcm91cCIsIlR5cGUiLCJQcmltZXIiLCJGaWxlX25hbWUiLCJMaWJyYXJ5IiwiUnVuIiwKICAgICAgICAgICAiZmluYWwgSUQiLAogICAgICAgICAgICJBYnVuZGFuY2UiLAogICAgICAgICAgICJSZWxhdGl2ZSBhYnVuZGFuY2UgdG8gYWxsIHNhbXBsZXMiLAogICAgICAgICAgICJSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlIiwKICAgICAgICAgICAiU2FtcGxlIHRvdGFsIGFidW5kYW5jZSIsCiAgICAgICAgICAgIktpbmdkb20iLCJQaHlsdW0iLCJDbGFzcyIsIk9yZGVyIiwiRmFtaWx5IiwKICAgICAgICAgICAiR2VudXMiLCJTcGVjaWVzIiwiU3BlY2ltZW4iLCJCYXNpbiIsCiAgICAgICAgICAgImV4YWN0IEdlbnVzIiwiZXhhY3QgU3BlY2llcyIsCiAgICAgICAgICAgImV4YWN0IEdlblNwIiwKICAgICAgICAgICAiMV9zdWJqZWN0IGhlYWRlciIsIjFfc3ViamVjdCIsCiAgICAgICAgICAgIjFfaW5kZW50aXR5IiwiMV9sZW5ndGgiLAogICAgICAgICAgICMgIjFfbWlzbWF0Y2hlcyIsIjFfZ2FwcyIsCiAgICAgICAgICAgIyAiMV9xdWVyeSBzdGFydCIsIjFfcXVlcnkgZW5kIiwiMV9zdWJqZWN0IHN0YXJ0IiwKICAgICAgICAgICAjICIxX3N1YmplY3QgZW5kIiwiMV9lLXZhbHVlIiwiMV9iaXRzY29yZSIsCiAgICAgICAgICAgIjJfc3ViamVjdCBoZWFkZXIiLCIyX3N1YmplY3QiLAogICAgICAgICAgICIyX2luZGVudGl0eSIsIjJfbGVuZ3RoIiwKICAgICAgICAgICAjICIyX21pc21hdGNoZXMiLCIyX2dhcHMiLAogICAgICAgICAgICMgIjJfcXVlcnkgc3RhcnQiLCIyX3F1ZXJ5IGVuZCIsIjJfc3ViamVjdCBzdGFydCIsCiAgICAgICAgICAgIyAiMl9zdWJqZWN0IGVuZCIsIjJfZS12YWx1ZSIsIjJfYml0c2NvcmUiLAogICAgICAgICAgICIzX3N1YmplY3QgaGVhZGVyIiwiM19zdWJqZWN0IiwKICAgICAgICAgICAiM19pbmRlbnRpdHkiLCIzX2xlbmd0aCIsCiAgICAgICAgICAgIyAiM19taXNtYXRjaGVzIiwiM19nYXBzIiwKICAgICAgICAgICAjICIzX3F1ZXJ5IHN0YXJ0IiwiM19xdWVyeSBlbmQiLCIzX3N1YmplY3Qgc3RhcnQiLAogICAgICAgICAgICMgIjNfc3ViamVjdCBlbmQiLCIzX2UtdmFsdWUiLCIzX2JpdHNjb3JlIiwKICAgICAgICAgICAiQVNWIiwiQVNWIGxlbmd0aCIsIkFTViBoZWFkZXIiLCJFeHBlY3RlZCBsZW5ndGgiLCJPVFUiCiAgICAgICAgICAgKSkKCiMgcGFzdGUwKGNvbG5hbWVzKGFsbF9wc190YmxfYmxhc3QpLCJcbiIpICU+JSAgY2F0KCkKbmFtZXMoYWxsX3BzX3RibF9ibGFzdClbd2hpY2gobmFtZXMoYWxsX3BzX3RibF9ibGFzdCk9PSJBU1YiKV0gPC0gIkFTViAoU2VxdWVuY2UpIgpuYW1lcyhhbGxfcHNfdGJsX2JsYXN0KVt3aGljaChuYW1lcyhhbGxfcHNfdGJsX2JsYXN0KT09ICJBU1YgbGVuZ3RoIildIDwtICJBU1Ygc2l6ZSAocGIpIgoKYGBgCgojIyNzYXZlIGNvbXBsZXRlIHRhYmxlCmBgYHtyLCBldmFsPUZBTFNFfQoKI29yZGVyIGJ5IGFidW5kYW5jZQoKc21wX2FiZF9JRCA8LSBhbGxfcHNfdGJsX2JsYXN0W3JldihiYXNlOjpvcmRlcihhbGxfcHNfdGJsX2JsYXN0JEFidW5kYW5jZSkpLF0gJT4lIAogIGZpbHRlcihgQWJ1bmRhbmNlYCA+IDApIAoKZGltKHNtcF9hYmRfSUQpCgp3cml0ZXhsOjp3cml0ZV94bHN4KHggPSBzbXBfYWJkX0lELAogICAgICAgICAgICAgICAgICAgIHBhdGggPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9zZmpxX2FsbF9hbmFseXNpc19pbmZvXzA2LTAzLTIyLnhsc3giLAogICAgICAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IFRSVUUsZm9ybWF0X2hlYWRlcnMgPSBUUlVFKQoKCgoKCkFTVnNfcGVyX3NhbXBsZSA8LSBhbGxfcHNfdGJsX2JsYXN0ICU+JSAKICAjIGZpbHRlcihSdW4gJWluJSBjKCJMR0NfTWluaVNlcV8xIiwgIkxHQ19NaW5pU2VxXzIiKSkgJT4lCiAgZmlsdGVyKCFgZmluYWwgSURgICVpbiUgYyhOQSwiTkEiKSkgJT4lIAogIG11dGF0ZSgiU2FtcGxlIiA9IGZhY3RvcihTYW1wbGUsbGV2ZWxzID0gc2FtcGxlX2xldmVscykpICU+JQogIGdyb3VwX2J5KFNhbXBsZSkgJT4lCiAgIHN1bW1hcml6ZSgiTGlicmFyeSIgPSB1bmlxdWUoYExpYnJhcnlgKSwKICAgICAiR3JvdXAiID0gdW5pcXVlKEdyb3VwKSwKICAgICAgICAgICAgICJQcmltZXIiID0gdW5pcXVlKFByaW1lciksCiAgICAgICAgICAgICAiVG90YWwgQVNWIiA9IGxlbmd0aCh1bmlxdWUoYEFTViAoU2VxdWVuY2UpYFtBYnVuZGFuY2UgIT0gMF0pKSwKICAgICAgICAgICAgICJBU1ZzIG91dCBvZiByYW5nZSIgPSBsZW5ndGgodW5pcXVlKGBBU1YgKFNlcXVlbmNlKWBbQWJ1bmRhbmNlICE9IDAgJiBgRXhwZWN0ZWQgbGVuZ3RoYCA9PSAib3V0IG9mIHJhbmdlIl0pKSwKICAgICAgICAgICAgICJBU1ZzIGluIHJhbmdlIiA9IGxlbmd0aCh1bmlxdWUoYEFTViAoU2VxdWVuY2UpYFtBYnVuZGFuY2UgIT0gMCAmIGBFeHBlY3RlZCBsZW5ndGhgID09ICJpbiByYW5nZSJdKSkKICAgICAgICAgICAgICwKICAgICAgICAgICAgICJJZGVudGlmaWVkIFNwZWNpZXMiID0gbGVuZ3RoKHVuaXF1ZShgZmluYWwgSURgW0FidW5kYW5jZSAhPSAwICYgYEV4cGVjdGVkIGxlbmd0aGAgPT0gImluIHJhbmdlIl0pKQogICAgICAgICAgICAgKSAKCgp3cml0ZXhsOjp3cml0ZV94bHN4KHggPSBBU1ZzX3Blcl9zYW1wbGUsCiAgICAgICAgICAgICAgICAgICAgcGF0aCA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL3NmanFfQVNWc19wZXJfc2FtcGxlXzA2LTA3LTIxLnhsc3giLAogICAgICAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IFRSVUUsZm9ybWF0X2hlYWRlcnMgPSBUUlVFKQoKCgpgYGAKCiMjIGN1cmluZzogbWFudWFsIGNoZWNraW5nIG9mIHRoZSBzcGVjaWVzIGFzc2lnbm1lbnQKYGBge3IsIGV2YWw9RkFMU0V9CgoKYWxsX3BzX3RibF9ibF9jdXIgPC0gc21wX2FiZF9JRAoKCgphbGxfcHNfdGJsX2JsX2N1ciA8LSBhbGxfcHNfdGJsX2JsX2N1ciAlPiUgCiAgbXV0YXRlKCJyZXZpc2VkIGZpbmFsIElEIiA9IGBmaW5hbCBJRGApCgoKYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgICU+JSB1bmlxdWUoKSAlPiUgIHNvcnQoKQoKCgoKI2NvcnJlY3QgbWlzaWRlbnRpZmljYXRpb25zIG9uZSBieSBvbmUKewphbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGBbYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgICVpbiUgYygiUHJvY2hpbG9kdXMiKV0gPC0gIlByb2NoaWxvZHVzIGFyZ2VudGV1cy9oYXJ0aWkiCmFsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYFthbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGAgJWluJSBjKCJQcm9jaGlsb2R1cyBhcmdlbnRldXMiKV0gPC0gIlByb2NoaWxvZHVzIGFyZ2VudGV1cy9oYXJ0aWkiCmFsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYFthbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGAgJWluJSBjKCJQaW1lbG9kdXMiKV0gPC0gIlBpbWVsb2R1cyBwb2hsaSIKYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgW2FsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYCAlaW4lIGMoIkFzdHlhbmF4IildIDwtICJBc3R5YW5heCBsYWN1c3RyaXMiCmFsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYFthbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGAgJWluJSBjKCJIeXBvc3RvbXVzIildIDwtICJIeXBvc3RvbXVzIGFsYXR1cyIKYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgW2FsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYCAlaW4lIGMoIk5BIGVsZWdhbnMvZ2lsYmVydCIpXSA8LSAiQ3lwaG9jaGFyYXggZ2lsYmVydCIKYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgW2FsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYCAlaW4lIGMoIk5BIGxlcGlkdXJhL3hlbm9kb24iKV0gPC0gIkN1cmltYXRlbGxhIGxlcGlkdXJhIgphbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGBbYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgICVpbiUgYygiUm9lYm9pZGVzIHhlbm9kb24iKV0gPC0gIkN1cmltYXRlbGxhIGxlcGlkdXJhIgphbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGBbYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgICVpbiUgYygiQ3VyaW1hdGVsbGEgbGVwaWR1cmEiKV0gPC0gIlJvZWJvaWRlcyB4ZW5vZG9uIgoKCgoKCmFsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYFsoYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgICVpbiUgYygiSG9wbGlhcyBicmFzaWxpZW5zaXMvaW50ZXJtZWRpdXMiKSkgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsX3BzX3RibF9ibF9jdXIkR3JvdXAgJWluJSBjKCJOb24tbm9ybWFsaXplZCBTRm1jIiwiTm9ybWFsaXplZCBTRm1jIildIDwtICJIb3BsaWFzIGludGVybWVkaXVzIgoKCmFsbF9wc190YmxfYmxfY3VyJGByZXZpc2VkIGZpbmFsIElEYFsoYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgICVpbiUgYygiSG9wbGlhcyBicmFzaWxpZW5zaXMvaW50ZXJtZWRpdXMiKSkgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsX3BzX3RibF9ibF9jdXIkR3JvdXAgJWluJSBjKCJOb24tbm9ybWFsaXplZCBKUW1jIiwiTm9ybWFsaXplZCBKUW1jIildIDwtICJIb3BsaWFzIGJyYXNpbGllbnNpcyIKCgoKYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgWyhhbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGAgJWluJSBjKCJIb3BsaWFzIGludGVybWVkaXVzIikpICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbF9wc190YmxfYmxfY3VyJEdyb3VwICVpbiUgYygiTm9ybWFsaXplZCBTRkpRbWMiKV0gPC0gIkhvcGxpYXMgYnJhc2lsaWVuc2lzL2ludGVybWVkaXVzIgoKCgoKYWxsX3BzX3RibF9ibF9jdXIkYHJldmlzZWQgZmluYWwgSURgWyhhbGxfcHNfdGJsX2JsX2N1ciRgcmV2aXNlZCBmaW5hbCBJRGAgJWluJSBjKCJIb3BsaWFzIGludGVybWVkaXVzIikpICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbF9wc190YmxfYmxfY3VyJEdyb3VwICVpbiUgYygiTm9uLW5vcm1hbGl6ZWQgSlFtYyIsIk5vcm1hbGl6ZWQgSlFtYyIpXSA8LSAiSG9wbGlhcyBicmFzaWxpZW5zaXMiCgp9CgpgYGAKCiMjIyBJZGVudGlmeSBleHBlY3RlZCBzcGVjaWVzCgpBcyB0aGlzIHdhcyBhIGNvbnRyb2xsZWQgZXhwZXJpbWVudCwgd2UgbXVzdCBpZGVudGlmeSB0aGUgc3BlY2llcyB0aGF0IHdlcmUgZXhwZWN0ZWQgYW5kIHRob3NlIHdobyB3ZXJlIG5vdC4KCmBgYHtyLCBldmFsPUZBTFNFfQoKI2R1cGxpY2F0ZSBmaW5hbCBJRCBzbyB3ZSBjYW4gaWRlbnRpZnkgcGFydGlhbGx5IGlkZW50aWZpZWQgc3BlY2llcwoKIyBhbGxfcHNfdGJsX2JsYXN0X2Jja3A1IDwtIGFsbF9wc190YmxfYmxhc3QgCiMgYWxsX3BzX3RibF9ibGFzdCA8LSBhbGxfcHNfdGJsX2JsYXN0X2Jja3A1CiMgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxfcHNfdGJsX2JsYXN0IDwtIGFsbF9wc190YmxfYmxfY3VyICU+JQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoYHJldmlzZWQgZmluYWwgSURgID0gYGZpbmFsIElEYCkKCgoKIyBleHBjdGRfc3BzX3RibCA8LSByZWFkLmNzdihmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL2RhdGEvc2ZqcV9zcGVjaWVzLmNzdiIsCiMgZXhwY3RkX3Nwc190YmwgPC0gcmVhZC5jc3YoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3NmanFfc3BlY2llc18wNm1hcjIyLmNzdiIsCiMgZXhwY3RkX3Nwc190YmwgPC0gcmVhZC5jc3YoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3NmanFfc3BlY2llc18xMG1hcjIyLmNzdiIsCmV4cGN0ZF9zcHNfdGJsIDwtIHJlYWQuY3N2KGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9zZmpxX3NwZWNpZXNfMDJqdW4yMi5jc3YiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBUUlVFLCBjaGVjay5uYW1lcyA9IEZBTFNFKSAlPiUgYXNfdGliYmxlKCkgCgojbXVkZWkgbyBULiBjaGFsY2V1cyBkZSAwLjAwNzMgcGFyYSAwLjAyOTkgbm8gcG9vbCBTRgoKY29sbmFtZXMoZXhwY3RkX3Nwc190YmwpW2NvbG5hbWVzKGV4cGN0ZF9zcHNfdGJsKSA9PSAiU3BlY2llcyJdIDwtICJyZXZpc2VkIGZpbmFsIElEIgoKYGBgCgoKCgojIyMgUHJvcG9ydGlvbnMgdGFibGUKCkFzIHRoaXMgd2FzIGEgY29udHJvbGxlZCBleHBlcmltZW50LCB3ZSBtdXN0IGlkZW50aWZ5IHRoZSBzcGVjaWVzIHRoYXQgd2VyZSBleHBlY3RlZCBhbmQgdGhvc2Ugd2hvIHdlcmUgbm90LgoKYGBge3IsIGV2YWw9RkFMU0V9CgojIHRhYmVsYXMgZGUgcHJvcG9yw6fDtWVzIC0tLS0KIyBKUW1jIC0tLS0KCiMgY3JpYW5kbyBhIHRhYmVsYSBkZSBwcm9wb3LDp8O1ZXMgZG8gSlEKCgojIGlmIHVzZWQgbGVmdF9qb2luLCBwIGhhcnRpaSB3b250IHNob3cgdXAKYWxsX3BzX3RibF9qcSA8LSBmdWxsX2pvaW4oCiAgYWxsX3BzX3RibF9ibF9jdXJbYWxsX3BzX3RibF9ibF9jdXIkU2FtcGxlICVpbiUgYygKICAiTm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIiwgIk5vbi1ub3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giLAogICJOb3JtYWxpemVkIEpRbWNcbk1pRmlzaCIsICJOb24tbm9ybWFsaXplZCBKUW1jXG5NaUZpc2giLAogICJOb3JtYWxpemVkIEpRbWNcblRlbGVvIiwgIk5vbi1ub3JtYWxpemVkIEpRbWNcblRlbGVvIiksXSwKICBleHBjdGRfc3BzX3RibFtleHBjdGRfc3BzX3RibCRQb29sPT0iSlEiLGMoMjo5KV0sCiAgICAgICAgICBieSA9ICJyZXZpc2VkIGZpbmFsIElEIikgCgojIGFsbF9wc190YmxfanEgJT4lIHNlbGVjdChgcmV2aXNlZCBmaW5hbCBJRGAsQWJ1bmRhbmNlLGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCwgNjQ6NzMpICU+JSBWaWV3KCkKCmFsbF9wc190YmxfanEkYEV4cGVjdGVkIFNwZWNpZXNgIDwtICJub3QgZXhwZWN0ZWQiCgphbGxfcHNfdGJsX2pxJGByZXZpc2VkIGZpbmFsIElEYCAlPiUgdW5pcXVlKCkKCmFsbF9wc190YmxfanEgPC0gYWxsX3BzX3RibF9qcSAlPiUgbXV0YXRlKCAKICAjIGBFeHBlY3RlZCBTcGVjaWVzYD1pZl9lbHNlKCghaXMubmEoYEZ1bGwgbmFtZWApICYgKC4kYHJldmlzZWQgZmluYWwgSURgICVpbiUgZXhwZWN0ZWRfc3BzKSksImV4cGVjdGVkIiwibm90IGV4cGVjdGVkIikKICBgRXhwZWN0ZWQgU3BlY2llc2A9aWZfZWxzZSgoIWlzLm5hKGBGdWxsIG5hbWVgKSksImV4cGVjdGVkIiwibm90IGV4cGVjdGVkIikKICApCgpjb2xuYW1lcyhhbGxfcHNfdGJsX2pxKQoKCmpxX3Byb3BvcnRpb25zIDwtIGFsbF9wc190YmxfanEgJT4lCiAgc2VsZWN0KGMoMToyNCwzNzo1MCkpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbCIsICJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbCIgKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiUG9vbCIsdmFsdWVzX3RvID0gIlByb3BvcnRpb24iKSAlPiUgCiAgIyBtdXRhdGUoUHJvcG9ydGlvbiA9IFByb3BvcnRpb24qMTAwKSAlPiUgCiAgbXV0YXRlKFNhbXBsZSA9IGZhY3RvcihTYW1wbGUsbGV2ZWxzID0gYygKICAgICJOb3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giLCAiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTmVvRmlzaCIsCiAgICAiTm9ybWFsaXplZCBKUW1jXG5NaUZpc2giLCAiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIiwKICAgICJOb3JtYWxpemVkIEpRbWNcblRlbGVvIiwgIk5vbi1ub3JtYWxpemVkIEpRbWNcblRlbGVvIgogICAgIyAsCiAgICAjICJOb24tbm9ybWFsaXplZCBTRm1jXG5NaUZpc2giLCJOb24tbm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiwKICAgICMgIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiwKICAgICMgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giLCAiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2giCiAgICApKSkgJT4lCiAgZmlsdGVyKChTYW1wbGUgJWluJSBjKCJOb24tbm9ybWFsaXplZCBKUW1jXG5OZW9GaXNoIiwgIk5vbi1ub3JtYWxpemVkIEpRbWNcbk1pRmlzaCIsICJOb24tbm9ybWFsaXplZCBKUW1jXG5UZWxlbyIKICAgICAgICAgICAgICAgICAgICAgICAgIyAsICJOb24tbm9ybWFsaXplZCBTRm1jXG5NaUZpc2giLCJOb24tbm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIgogICAgICAgICAgICAgICAgICAgICAgICApICYgUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSApfChTYW1wbGUgJWluJSBjKCJOb3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giLCAiTm9ybWFsaXplZCBKUW1jXG5NaUZpc2giLCAiTm9ybWFsaXplZCBKUW1jXG5UZWxlbyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICwgIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwgIk5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIsICJOb3JtYWxpemVkIFNGSlFtY1xuTWlGaXNoIiwgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5OZW9GaXNoIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJiBQb29sICVpbiUgYygiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbCIpICkpICU+JSAKICBncm91cF9ieShTYW1wbGUsYHJldmlzZWQgZmluYWwgSURgKSAlPiUKICBzdW1tYXJpemUoUHJvcG9ydGlvbiA9IHVuaXF1ZShQcm9wb3J0aW9uKSwKICAgICAgICAgICAgYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgID0gc3VtKGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCksCiAgICAgICAgICAgIFNhbXBsZSA9IHVuaXF1ZShTYW1wbGUpLAogICAgICAgICAgICAjIGByZXZpc2VkIGZpbmFsIElEYCA9IHVuaXF1ZShgcmV2aXNlZCBmaW5hbCBJRGApLAogICAgICAgICAgICBgcmV2aXNlZCBmaW5hbCBJRGAgPSB1bmlxdWUoYHJldmlzZWQgZmluYWwgSURgKSwKICAgICAgICAgICAgUHJpbWVyID0gdW5pcXVlKFByaW1lciksCiAgICAgICAgICAgIGBFeHBlY3RlZCBTcGVjaWVzYCA9IHVuaXF1ZShgRXhwZWN0ZWQgU3BlY2llc2ApLAogICAgICAgICAgICBQb29sID0gdW5pcXVlKFBvb2wpLAogICAgICAgICAgICBgTnVtIEFTVnNgID0gbGVuZ3RoKGBBU1YgKFNlcXVlbmNlKWApLAogICAgICAgICAgICBgTnVtIE9UVXNgID0gbGVuZ3RoKHVuaXF1ZShPVFUpKSkgJT4lIAogIHVuZ3JvdXAoKQoKCiNTRm1jIC0tLS0KCiMgY3JpYW5kbyBhIHRhYmVsYSBkZSBwcm9wb3LDp8O1ZXMgZG8gCgphbGxfcHNfdGJsX3NmIDwtIGZ1bGxfam9pbigKICBhbGxfcHNfdGJsX2JsX2N1clthbGxfcHNfdGJsX2JsX2N1ciRTYW1wbGUgJWluJSBjKAogICJOb3JtYWxpemVkIFNGbWNcbk5lb0Zpc2giLCAiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIsCiAgIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwgIk5vbi1ub3JtYWxpemVkIFNGbWNcbk1pRmlzaCIpLF0sCiAgZXhwY3RkX3Nwc190YmxbZXhwY3RkX3Nwc190YmwkUG9vbD09IlNGIixjKDI6OSldLAogICAgICAgICAgYnkgPSAicmV2aXNlZCBmaW5hbCBJRCIpCgojIGFsbF9wc190YmxfanEgJT4lIHNlbGVjdChgcmV2aXNlZCBmaW5hbCBJRGAsQWJ1bmRhbmNlLGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCwgNjQ6NzMpICU+JSBWaWV3KCkKCmFsbF9wc190Ymxfc2YkYEV4cGVjdGVkIFNwZWNpZXNgIDwtICJub3QgZXhwZWN0ZWQiCgphbGxfcHNfdGJsX3NmJGByZXZpc2VkIGZpbmFsIElEYCAlPiUgdW5pcXVlKCkKCmFsbF9wc190Ymxfc2YgPC0gYWxsX3BzX3RibF9zZiAlPiUgbXV0YXRlKCAKICAjIGBFeHBlY3RlZCBTcGVjaWVzYD1pZl9lbHNlKCghaXMubmEoYEZ1bGwgbmFtZWApICYgKC4kYHJldmlzZWQgZmluYWwgSURgICVpbiUgZXhwZWN0ZWRfc3BzKSksImV4cGVjdGVkIiwibm90IGV4cGVjdGVkIikKICBgRXhwZWN0ZWQgU3BlY2llc2A9aWZfZWxzZSgoIWlzLm5hKGBGdWxsIG5hbWVgKSksImV4cGVjdGVkIiwibm90IGV4cGVjdGVkIikKICApCgpjb2xuYW1lcyhhbGxfcHNfdGJsX3NmKQoKCnNmX3Byb3BvcnRpb25zIDwtIGFsbF9wc190Ymxfc2YgJT4lCiAgIyBzZWxlY3QoYygxOjE1LDYzOjY4LDczOjc0KSkgJT4lIAogIHNlbGVjdChjKDE6MjQsMzc6NTApKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb3JtIHBvb2wiLCAiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2wiICksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlBvb2wiLHZhbHVlc190byA9ICJQcm9wb3J0aW9uIikgJT4lIAogICMgbXV0YXRlKFByb3BvcnRpb24gPSBQcm9wb3J0aW9uKjEwMCkgJT4lIAogIG11dGF0ZShTYW1wbGUgPSBmYWN0b3IoU2FtcGxlLGxldmVscyA9IGMoCiAgICAiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiwgIk5vbi1ub3JtYWxpemVkIFNGbWNcbk5lb0Zpc2giLAogICAgIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwgIk5vbi1ub3JtYWxpemVkIFNGbWNcbk1pRmlzaCIKICAgICMgLAogICAgIyAiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIsCiAgICAjICJOb3JtYWxpemVkIFNGbWNcbk1pRmlzaCIsIk5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIsCiAgICAjICJOb3JtYWxpemVkIFNGSlFtY1xuTWlGaXNoIiwgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5OZW9GaXNoIgogICAgKSkpICU+JQogIGZpbHRlcigoU2FtcGxlICVpbiUgYygiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIsICJOb24tbm9ybWFsaXplZCBTRm1jXG5NaUZpc2giCiAgICAgICAgICAgICAgICAgICAgICAgICMgLCAiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIiwiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTmVvRmlzaCIKICAgICAgICAgICAgICAgICAgICAgICAgKSAmIFBvb2wgJWluJSBjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKXwoU2FtcGxlICVpbiUgYygiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiwgIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgLCAiTm9ybWFsaXplZCBTRm1jXG5NaUZpc2giLCAiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiwgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giLCAiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2giCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmIFBvb2wgJWluJSBjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9ybSBwb29sIikgKSkgJT4lIAogIGdyb3VwX2J5KFNhbXBsZSxgcmV2aXNlZCBmaW5hbCBJRGApICU+JSAKICBzdW1tYXJpemUoUHJvcG9ydGlvbiA9IHVuaXF1ZShQcm9wb3J0aW9uKSwKICAgICAgICAgICAgYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgID0gc3VtKGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCksCiAgICAgICAgICAgIFNhbXBsZSA9IHVuaXF1ZShTYW1wbGUpLAogICAgICAgICAgICAjIGByZXZpc2VkIGZpbmFsIElEYCA9IHVuaXF1ZShgcmV2aXNlZCBmaW5hbCBJRGApLAogICAgICAgICAgICBgcmV2aXNlZCBmaW5hbCBJRGAgPSB1bmlxdWUoYHJldmlzZWQgZmluYWwgSURgKSwKICAgICAgICAgICAgUHJpbWVyID0gdW5pcXVlKFByaW1lciksCiAgICAgICAgICAgIGBFeHBlY3RlZCBTcGVjaWVzYCA9IHVuaXF1ZShgRXhwZWN0ZWQgU3BlY2llc2ApLAogICAgICAgICAgICBQb29sID0gdW5pcXVlKFBvb2wpLAogICAgICAgICAgICBgTnVtIEFTVnNgID0gbGVuZ3RoKGBBU1YgKFNlcXVlbmNlKWApLAogICAgICAgICAgICBgTnVtIE9UVXNgID0gbGVuZ3RoKHVuaXF1ZShPVFUpKSkgJT4lIAogIHVuZ3JvdXAoKQoKCiNTRkpRbWMgLS0tLQojIFZpZXcoZXhwY3RkX3Nwc190YmxbZXhwY3RkX3Nwc190YmwkUG9vbD09IlNGSlEiLGMoMjo5KV0pCiMgY3JpYW5kbyBhIHRhYmVsYSBkZSBwcm9wb3LDp8O1ZXMgZG8gU0ZKUQoKYWxsX3BzX3RibF9zZmpxIDwtIGZ1bGxfam9pbigKICBhbGxfcHNfdGJsX2JsX2N1clthbGxfcHNfdGJsX2JsX2N1ciRTYW1wbGUgJWluJSBjKAogICJOb3JtYWxpemVkIFNGSlFtY1xuTmVvRmlzaCIsICJOb3JtYWxpemVkIFNGSlFtY1xuTWlGaXNoIiksXSwKICBleHBjdGRfc3BzX3RibFtleHBjdGRfc3BzX3RibCRQb29sPT0iU0ZKUSIsYygyOjkpXSwKICAgICAgICAgIGJ5ID0gInJldmlzZWQgZmluYWwgSUQiKQoKCiMgYWxsX3BzX3RibF9qcSAlPiUgc2VsZWN0KGByZXZpc2VkIGZpbmFsIElEYCxBYnVuZGFuY2UsYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgLCA2NDo3MykgJT4lIFZpZXcoKQoKYWxsX3BzX3RibF9zZmpxJGBFeHBlY3RlZCBTcGVjaWVzYCA8LSAibm90IGV4cGVjdGVkIgoKYWxsX3BzX3RibF9zZmpxJGByZXZpc2VkIGZpbmFsIElEYCAlPiUgdW5pcXVlKCkKCmFsbF9wc190Ymxfc2ZqcSA8LSBhbGxfcHNfdGJsX3NmanEgJT4lIG11dGF0ZSggCiAgIyBgRXhwZWN0ZWQgU3BlY2llc2A9aWZfZWxzZSgoIWlzLm5hKGBGdWxsIG5hbWVgKSAmICguJGByZXZpc2VkIGZpbmFsIElEYCAlaW4lIGV4cGVjdGVkX3NwcykpLCJleHBlY3RlZCIsIm5vdCBleHBlY3RlZCIpCiAgYEV4cGVjdGVkIFNwZWNpZXNgPWlmX2Vsc2UoKCFpcy5uYShgRnVsbCBuYW1lYCkpLCJleHBlY3RlZCIsIm5vdCBleHBlY3RlZCIpCiAgKQoKY29sbmFtZXMoYWxsX3BzX3RibF9zZmpxKQoKCnNmanFfcHJvcG9ydGlvbnMgPC0gYWxsX3BzX3RibF9zZmpxICU+JQogIHNlbGVjdChjKDE6MjQsMzc6NTApKSAlPiUKICAjIHNlbGVjdChjKDE6MTUsNjM6NjgsNzM6NzQpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9ybSBwb29sIiwgIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sIiApLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJQb29sIix2YWx1ZXNfdG8gPSAiUHJvcG9ydGlvbiIpICU+JSAKICAjIG11dGF0ZShQcm9wb3J0aW9uID0gUHJvcG9ydGlvbioxMDApICU+JSAKICBtdXRhdGUoU2FtcGxlID0gZmFjdG9yKFNhbXBsZSxsZXZlbHMgPSBjKAogICAgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5OZW9GaXNoIiwgIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giCiAgICApKSkgJT4lCiAgZmlsdGVyKChTYW1wbGUgJWluJSBjKCJOb3JtYWxpemVkIFNGSlFtY1xuTmVvRmlzaCIsICJOb3JtYWxpemVkIFNGSlFtY1xuTWlGaXNoIgogICAgICAgICAgICAgICAgICAgICAgICApICYgUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb3JtIHBvb2wiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICkpICU+JSAKICBncm91cF9ieShTYW1wbGUsYHJldmlzZWQgZmluYWwgSURgKSAlPiUgCiAgc3VtbWFyaXplKFByb3BvcnRpb24gPSB1bmlxdWUoUHJvcG9ydGlvbiksCiAgICAgICAgICAgIGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCA9IHN1bShgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApLAogICAgICAgICAgICBTYW1wbGUgPSB1bmlxdWUoU2FtcGxlKSwKICAgICAgICAgICAgIyBgcmV2aXNlZCBmaW5hbCBJRGAgPSB1bmlxdWUoYHJldmlzZWQgZmluYWwgSURgKSwKICAgICAgICAgICAgYHJldmlzZWQgZmluYWwgSURgID0gdW5pcXVlKGByZXZpc2VkIGZpbmFsIElEYCksCiAgICAgICAgICAgIFByaW1lciA9IHVuaXF1ZShQcmltZXIpLAogICAgICAgICAgICBgRXhwZWN0ZWQgU3BlY2llc2AgPSB1bmlxdWUoYEV4cGVjdGVkIFNwZWNpZXNgKSwKICAgICAgICAgICAgUG9vbCA9IHVuaXF1ZShQb29sKSwKICAgICAgICAgICAgYE51bSBBU1ZzYCA9IGxlbmd0aChgQVNWIChTZXF1ZW5jZSlgKSwKICAgICAgICAgICAgYE51bSBPVFVzYCA9IGxlbmd0aCh1bmlxdWUoT1RVKSkpICU+JSAKICB1bmdyb3VwKCkKCgoKI3RoaXMgdGFibGUgd2lsbCBiZSB1c2VkCmFsbF9wc190Ymxfc2ZqcV9mdWxsIDwtICBkcGx5cjo6YmluZF9yb3dzKGFsbF9wc190Ymxfc2ZqcSxhbGxfcHNfdGJsX3NmLGFsbF9wc190YmxfanEpCgoKCmFsbF9wc190Ymxfc2ZqcV9mdWxsICU+JSBjb2xuYW1lcygpICU+JSB1bmlxdWUoKSAlPiUgcGFzdGUwKGNvbGxhcHNlID0gJyIsXG4iJykgJT4lIGNhdCgpCgoKYGBgCgoKIyMjIFBlYXJzb24gY29ycmVsYXRpb25zIGJldHdlZW4gRE5BIGlucHV0IGFuZCBzZXF1ZW5jZSB5aWVsZAoKYGBge3IsZWNobz1UUlVFLCBldmFsPUZBTFNFfQoKI2NvcnJlbGHDp8OjbyBlbnRyZSBvIEROQSBpbnB1dCBlIHJlYWRzIEFCRCAtLS0tLQoKIyBKUW1jCnsKanFfZGZfbmVvX25vcm0gPC0ganFfcHJvcG9ydGlvbnMgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKFNhbXBsZSAlaW4lIGMoIk5vcm1hbGl6ZWQgSlFtY1xuTmVvRmlzaCIpKSAlPiUgCiAgc2VsZWN0KGMoMiwzLDQpKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBuYS5leGNsdWRlKCkKCmpxX2RmX21pZl9ub3JtIDwtIGpxX3Byb3BvcnRpb25zICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihTYW1wbGUgJWluJSBjKCJOb3JtYWxpemVkIEpRbWNcbk1pRmlzaCIpKSAlPiUgCiAgc2VsZWN0KGMoMiwzLDQpKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSBuYS5leGNsdWRlKCkKCmpxX2RmX3RlbF9ub3JtIDwtIGpxX3Byb3BvcnRpb25zICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihTYW1wbGUgJWluJSBjKCJOb3JtYWxpemVkIEpRbWNcblRlbGVvIikpICU+JSAKICBzZWxlY3QoYygyLDMsNCkpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIG5hLmV4Y2x1ZGUoKQoKanFfZGZfbmVvX3NrZXcgPC0ganFfcHJvcG9ydGlvbnMgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKFNhbXBsZSAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giKSkgJT4lIAogIHNlbGVjdChjKDIsMyw0KSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgbmEuZXhjbHVkZSgpCgpqcV9kZl9taWZfc2tldyA8LSBqcV9wcm9wb3J0aW9ucyAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoU2FtcGxlICVpbiUgYygiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIikpICU+JSAKICBzZWxlY3QoYygyLDMsNCkpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIG5hLmV4Y2x1ZGUoKQoKanFfZGZfdGVsX3NrZXcgPC0ganFfcHJvcG9ydGlvbnMgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKFNhbXBsZSAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIEpRbWNcblRlbGVvIikpICU+JSAKICBzZWxlY3QoYygyLDMsNCkpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIG5hLmV4Y2x1ZGUoKQoKI1NGIApzZl9kZl9uZW9fbm9ybSA8LSBzZl9wcm9wb3J0aW9ucyAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoU2FtcGxlICVpbiUgYygiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIikpICU+JSAKICBzZWxlY3QoYygyLDMsNCkpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIG5hLmV4Y2x1ZGUoKQoKc2ZfZGZfbWlmX25vcm0gPC0gc2ZfcHJvcG9ydGlvbnMgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKFNhbXBsZSAlaW4lIGMoIk5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIikpICU+JSAKICBzZWxlY3QoYygyLDMsNCkpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIG5hLmV4Y2x1ZGUoKQoKc2ZfZGZfbmVvX3NrZXcgPC0gc2ZfcHJvcG9ydGlvbnMgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKFNhbXBsZSAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIFNGbWNcbk5lb0Zpc2giKSkgJT4lIAogIHNlbGVjdChjKDIsMyw0KSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgbmEuZXhjbHVkZSgpCgpzZl9kZl9taWZfc2tldyA8LSBzZl9wcm9wb3J0aW9ucyAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoU2FtcGxlICVpbiUgYygiTm9uLW5vcm1hbGl6ZWQgU0ZtY1xuTWlGaXNoIikpICU+JSAKICBzZWxlY3QoYygyLDMsNCkpICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIG5hLmV4Y2x1ZGUoKQoKIyBTRkpRCnNmanFfZGZfbmVvX25vcm0gPC0gc2ZqcV9wcm9wb3J0aW9ucyAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoU2FtcGxlICVpbiUgYygiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2giKSkgJT4lIAogIHNlbGVjdChjKDIsMyw0KSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgbmEuZXhjbHVkZSgpCgpzZmpxX2RmX21pZl9ub3JtIDwtIHNmanFfcHJvcG9ydGlvbnMgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKFNhbXBsZSAlaW4lIGMoIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giKSkgJT4lIAogIHNlbGVjdChjKDIsMyw0KSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgbmEuZXhjbHVkZSgpCn0KCgoKCiNjb3JyZWxhw6fDtWVzIAojSlFtYwpjb3IudGVzdCh4ID0ganFfZGZfbmVvX25vcm0kUHJvcG9ydGlvbiAsCiAgICAgICAgIHkgPSBqcV9kZl9uZW9fbm9ybSRgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAgLAogICAgICAgICBtZXRob2QgPSAicGVhcnNvbiIpCgoKY29yLnRlc3QoeCA9IGpxX2RmX25lb19za2V3JFByb3BvcnRpb24gLAogICAgICAgICB5ID0ganFfZGZfbmVvX3NrZXckYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgICwKICAgICAgICAgbWV0aG9kID0gInBlYXJzb24iKQoKCgpjb3IudGVzdCh4ID0ganFfZGZfbWlmX25vcm0kUHJvcG9ydGlvbiAsCiAgICAgICAgIHkgPSBqcV9kZl9taWZfbm9ybSRgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAgLAogICAgICAgICBtZXRob2QgPSAicGVhcnNvbiIpCgoKY29yLnRlc3QoeCA9IGpxX2RmX21pZl9za2V3JFByb3BvcnRpb24gLAogICAgICAgICB5ID0ganFfZGZfbWlmX3NrZXckYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgICwKICAgICAgICAgbWV0aG9kID0gInBlYXJzb24iKQoKCmNvci50ZXN0KHggPSBqcV9kZl90ZWxfbm9ybSRQcm9wb3J0aW9uICwKICAgICAgICAgeSA9IGpxX2RmX3RlbF9ub3JtJGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCAsCiAgICAgICAgIG1ldGhvZCA9ICJwZWFyc29uIikKCgpjb3IudGVzdCh4ID0ganFfZGZfdGVsX3NrZXckUHJvcG9ydGlvbiAsCiAgICAgICAgIHkgPSBqcV9kZl90ZWxfc2tldyRgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAgLAogICAgICAgICBtZXRob2QgPSAicGVhcnNvbiIpCgojU0YKY29yLnRlc3QoeCA9IHNmX2RmX25lb19ub3JtJFByb3BvcnRpb24gLAogICAgICAgICB5ID0gc2ZfZGZfbmVvX25vcm0kYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgICwKICAgICAgICAgbWV0aG9kID0gInBlYXJzb24iLCkKCgpjb3IudGVzdCh4ID0gc2ZfZGZfbmVvX3NrZXckUHJvcG9ydGlvbiAsCiAgICAgICAgIHkgPSBzZl9kZl9uZW9fc2tldyRgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAgLAogICAgICAgICBtZXRob2QgPSAicGVhcnNvbiIpCgoKCmNvci50ZXN0KHggPSBzZl9kZl9taWZfbm9ybSRQcm9wb3J0aW9uICwKICAgICAgICAgeSA9IHNmX2RmX21pZl9ub3JtJGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCAsCiAgICAgICAgIG1ldGhvZCA9ICJwZWFyc29uIikKCgpjb3IudGVzdCh4ID0gc2ZfZGZfbWlmX3NrZXckUHJvcG9ydGlvbiAsCiAgICAgICAgIHkgPSBzZl9kZl9taWZfc2tldyRgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAgLAogICAgICAgICBtZXRob2QgPSAicGVhcnNvbiIpCgpgYGAKCgojIyBSaWNobmVzcyBhbmFseXNpcyBvbiBWZWdhbgpgYGB7cixlY2hvPVRSVUUsIGV2YWw9RkFMU0V9CmxpYnJhcnkodmVnYW4pCiMgZGF0YShkdW5lKQojIGRlY29yYW5hKGR1bmUpCgojIGNsYXNzKGR1bmUpCiMxLSBwcmVwYXJlIGRhdGEgZm9yIGVudHJ5IGluIHZlZ2FuIC0tLS0KCmFsbF9wc19ibHN0X3ZlZ2FuIDwtIGFsbF9wc190YmxfYmxfY3VyICU+JSAKICBmaWx0ZXIoYEV4cGVjdGVkIGxlbmd0aGAgJWluJSBjKCJpbiByYW5nZSIpKSAlPiUgCiAgbXV0YXRlKCJOb3JtYWxpemF0aW9uIiA9IHN0cl9zcGxpdCguJEdyb3VwLHBhdHRlcm4gPSAiICIsMixzaW1wbGlmeSA9IFRSVUUpWywxXSwKICAgICAgICAgIk1vY2sgQ29tbXVuaXR5IiA9IHN0cl9zcGxpdCguJEdyb3VwLHBhdHRlcm4gPSAiICIsMixzaW1wbGlmeSA9IFRSVUUpWywyXSkgJT4lIAogIGZpbHRlcighKFNhbXBsZSAlaW4lIGMoIlBvc2l0aXZlIENvbnRyb2xcbihQLmdsYXVjYSkiLCJuZWctUENSMiIpKSkgJT4lICAgI3JlbW92ZSBjb250cm9sIHNhbXBsZXMKICBzZWxlY3QoYyhTYW1wbGUsR3JvdXAsTm9ybWFsaXphdGlvbixgTW9jayBDb21tdW5pdHlgLFR5cGUsUHJpbWVyLEZpbGVfbmFtZSxMaWJyYXJ5LFJ1bixgZmluYWwgSURgLGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCkpICU+JSAKICBncm91cF9ieShTYW1wbGUsYGZpbmFsIElEYCxHcm91cCxUeXBlLFByaW1lcixGaWxlX25hbWUsTGlicmFyeSxSdW4sTm9ybWFsaXphdGlvbixgTW9jayBDb21tdW5pdHlgKSAlPiUgCiAgc3VtbWFyaXNlKGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCA9IHN1bShgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApKSAlPiUgCiAgcGl2b3Rfd2lkZXIoYyhTYW1wbGUsR3JvdXAsVHlwZSxQcmltZXIsRmlsZV9uYW1lLExpYnJhcnksUnVuLE5vcm1hbGl6YXRpb24sYE1vY2sgQ29tbXVuaXR5YCksbmFtZXNfZnJvbSA9IGBmaW5hbCBJRGAgLHZhbHVlc19mcm9tID0gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKSAlPiUgCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIH5yZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSkgJT4lIAogICMgbXV0YXRlKExpYnJhcnkgPSB1bmZhY3RvcihMaWJyYXJ5KSkgJT4lIAogIG11dGF0ZSgiU2FtcGxlIG51bWJlciIgPSAwKSAlPiUgCiAgdW5ncm91cCgpICAlPiUgCiAgc2VsZWN0KGBTYW1wbGUgbnVtYmVyYCwgMToobmNvbCguKS0xKSkgJT4lIAogIG11dGF0ZShOb3JtYWxpemF0aW9uID0gZmFjdG9yKE5vcm1hbGl6YXRpb24pKQoKIzItIGFzc29jaWF0ZSBzYW1wbGUgbnVtYmVycyB0byBzYW1wbGUgbmFtZXMgLS0tLQpmb3IgKHNhbXBsZSBpbiAxOm5yb3coYWxsX3BzX2Jsc3RfdmVnYW4pKSB7CiAgYWxsX3BzX2Jsc3RfdmVnYW4kYFNhbXBsZSBudW1iZXJgW3NhbXBsZV0gPC0gc2FtcGxlIAogIAp9CgojdGlyYW5kbyBhcyBhbW9zdHJhcyBkYSBlY29tb2wgcHJhIGZhY2lsaXRhcgoKYWxsX3BzX2Jsc3RfdmVnYW4gPC0gYWxsX3BzX2Jsc3RfdmVnYW5bYWxsX3BzX2Jsc3RfdmVnYW4kUnVuICVpbiUgYygiTEdDX01pbmlTZXFfMSIsICJMR0NfTWluaVNlcV8yIiksXSAKCgoKCmNvbG5hbWVzKGFsbF9wc19ibHN0X3ZlZ2FuKQpoaXN0KGNvbFN1bXMoYWxsX3BzX2Jsc3RfdmVnYW5bLC1jKDE6MTApXSkpCmhpc3Qocm93U3VtcyhhbGxfcHNfYmxzdF92ZWdhblssLWMoMToxMCldKSkKYWxsX3BzX2Jsc3RfdmVnYW5bLC1jKDE6MTApXQoKYWxsX3BzX2Jsc3RfdmVnYW4gJT4lIHNlbGVjdChTYW1wbGUsIGBTYW1wbGUgbnVtYmVyYCkKIyBhbGxfcHNfYmxzdF92ZWdhbiAlPiUgc2VsZWN0KGBTYW1wbGUgbnVtYmVyYCwgMToobmNvbCguKS0xKSkKCiMzLSBjcmVhdGUgZGF0YS5mcmFtZSBvZiBzcGVjaWVzIGNvdW50czogcm93bmFtZXMgYXJlIFNhbXBsZSBudW1iZXJzIC0tLS0KCmFsbF9wc19ibHN0X3ZlZ2FuX2RmIDwtIGFsbF9wc19ibHN0X3ZlZ2FuICU+JSAKICAjIGZpbHRlcihSdW4gJWluJSBjKCJMR0NfTWluaVNlcV8xIiwgIkxHQ19NaW5pU2VxXzIiKSkgJT4lIAogIHNlbGVjdCgtYygiU2FtcGxlIiwgIkdyb3VwIiwgIlR5cGUiLCAiUHJpbWVyIiwgIkZpbGVfbmFtZSIsICJMaWJyYXJ5IiwgIlJ1biIsIk5vcm1hbGl6YXRpb24iLCJNb2NrIENvbW11bml0eSIpKSAlPiUgCiAgc2VsZWN0KGJhc2U6OnNvcnQoY29sbmFtZXMoLikpKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpIAoKIzQtIG5hbWUgcm93cyBhcyBTYW1wbGUgbnVtYmVycyBhbmQgcmVtb3ZlIGNvbHVtbiAtLS0tCnJvdy5uYW1lcyhhbGxfcHNfYmxzdF92ZWdhbl9kZikgPC0gYWxsX3BzX2Jsc3RfdmVnYW5fZGYkYFNhbXBsZSBudW1iZXJgCmFsbF9wc19ibHN0X3ZlZ2FuX2RmIDwtIGFsbF9wc19ibHN0X3ZlZ2FuX2RmICU+JSAKICBzZWxlY3QoLWMoYFNhbXBsZSBudW1iZXJgKSkKCmxpYnJhcnkodmVnYW4pCiM1LSAKCmFsbF9wc19vcmQgPC0gZGVjb3JhbmEodmVnID0gYWxsX3BzX2Jsc3RfdmVnYW5fZGYpCgphbGxfcHNfb3JkICU+JSBzdW1tYXJ5KCkKCmFsbF9wc19vcmQgJT4lIHN0cigpCgphbGxfcHNfb3JkJGNwcm9qCgoKcGxvdChhbGxfcHNfb3JkKQpwbG90KGFsbF9wc19vcmQsdHlwZSA9ICJwIikKcGxvdChhbGxfcHNfb3JkLHR5cGUgPSAiYyIpIAoKcG9pbnRzKGFsbF9wc19vcmQsIGRpc3BsYXkgPSAic2l0ZXMiLCBjZXggPSAwLjgsIHBjaD0yMSwgY29sPSJyZWQiLCBiZz0ieWVsbG93IikKdGV4dChhbGxfcHNfb3JkLCBkaXNwbGF5ID0gInNpdGVzIiwgY2V4PTAuNywgY29sPSJibHVlIikKdGV4dChhbGxfcHNfb3JkLCBkaXNwbGF5ID0gInNwZWMiLCBjZXg9MC43LCBjb2w9ImJsdWUiKQoKCgojNi0gTk1EUyBhbmFsaXN5cyAtLS0tCgoKCiMgbGlicmFyeSh2ZWdhbikKIyBkYXRhKHZhcmVzcGVjKQojNmEtIENhbGN1bGF0ZSBkaXN0YW5jZXMgLS0tLQphbGxfcHNfdmdfZGlzdCA8LSB2ZWdkaXN0KGFsbF9wc19ibHN0X3ZlZ2FuX2RmLCBtZXRob2Q9ImJyYXkiKQoKdmVnYW46OnNjb3JlcyhhbGxfcHNfdmdfZGlzdCkKCiMgYWxsX3BzX3ZnX2Rpc3RfbWV0YU1EUyA8LSBtZXRhTURTKGNvbW0gPSBhbGxfcHNfdmdfZGlzdCwgYXV0b3RyYW5zZm9ybSA9IEZBTFNFKSAKIyBhY3R1YWxseSBhdXRvdHJhbnNmb3JtID0gRkFMU0UgZG9lc24ndCBzZWVtIHRvIGNoYW5nZSB0aGUgcmVzdWx0cwoKIyBwbG90KGFsbF9wc192Z19kaXN0X21ldGFNRFMpCgojIGFsbF9wc192Z19kaXN0X21ldGFNRFNfMiA8LSBtZXRhTURTKGNvbW0gPSBhbGxfcHNfdmdfZGlzdCwgZGlzdGFuY2UgPSAiYnJheSIsIGsgPTIpCgojIHBsb3QoYWxsX3BzX3ZnX2Rpc3RfbWV0YU1EU18yKQoKI3NlbGVjaW9uYXIgYXBlbmFzIGVzcMOpY2llcyBlc3BlcmFkYXM/CgphbGxfcHNfYmxzdF92ZWdhbl9kZiAlPiUgbmNvbCgpCmFsbF9wc19ibHN0X3ZlZ2FuX2RmIDwtIGFsbF9wc19ibHN0X3ZlZ2FuX2RmWywoY29sbmFtZXMoYWxsX3BzX2Jsc3RfdmVnYW5fZGYpICVpbiUgZXhwZWN0ZWRfc3BzKV0KCgphbGxfcHNfYmxzdF92ZWdhbl9kZiAlPiUgbmNvbCgpCmFsbF9wc192Z19kaXN0IDwtIHZlZ2Rpc3QoYWxsX3BzX2Jsc3RfdmVnYW5fZGYsIG1ldGhvZD0iYnJheSIpCgphbGxfcHNfb3JkIDwtIGRlY29yYW5hKHZlZyA9IGFsbF9wc19ibHN0X3ZlZ2FuX2RmKQoKYWxsX3BzX29yZCAlPiUgc3VtbWFyeSgpCgphbGxfcHNfb3JkICU+JSBzdHIoKQoKYWxsX3BzX29yZCRjcHJvagphbGxfcHNfb3JkCgoKcGxvdChhbGxfcHNfb3JkKQpwbG90KGFsbF9wc19vcmQsdHlwZSA9ICJwIikKcGxvdChhbGxfcHNfb3JkLHR5cGUgPSAiYyIpIAp2ZWdhbjo6c2NvcmVzKGFsbF9wc192Z19kaXN0KQoKCgoKIyBhbGxfcHNfYmxzdF92ZWdhbl9kZlssKGNvbG5hbWVzKGFsbF9wc19ibHN0X3ZlZ2FuX2RmKSAlaW4lIGV4cGVjdGVkX3NwcyldICU+JSBjb2xuYW1lcygpCiMgYWxsX3BzX2Jsc3RfdmVnYW5fZGYlPiUgY29sbmFtZXMoKQoKCgphbGxfcHNfdmVnYW5fb3JkX21ldGEgPC0gbWV0YU1EUyh2ZWcgPSBhbGxfcHNfYmxzdF92ZWdhbl9kZiwgY29tbSA9IGFsbF9wc192Z19kaXN0KQojIGFjdHVhbGx5IGF1dG90cmFuc2Zvcm0gPSBGQUxTRSBkb2Vzbid0IHNlZW0gdG8gY2hhbmdlIHRoZSByZXN1bHRzCnBsb3QoYWxsX3BzX3ZlZ2FuX29yZF9tZXRhLCB0eXBlID0gInQiKQoKCmFsbF9wc192ZWdhbl9vcmRfbWV0YSAlPiUgc3RyKCkKYWxsX3BzX3ZlZ2FuX29yZF9tZXRhJHN0cmVzcwoKCiAgCiM2Yi0gZXh0cmFjdCBOTURTIHNjb3JlcyBmcm9tIHJlc3VsdHMKICAKYWxsX3ZlZ2FuX21ldGEgPC0gKHZlZ2FuOjpzY29yZXMoYWxsX3BzX3ZlZ2FuX29yZF9tZXRhKSAlPiUgdGlkeXI6OmFzX3RpYmJsZShyb3duYW1lcyA9ICJTYW1wbGUgbnVtYmVyIikpICU+JSBtdXRhdGUoYFNhbXBsZSBudW1iZXJgID0gYXMubnVtZXJpYyhgU2FtcGxlIG51bWJlcmApKQogICAgICAgICAgICAjIGFsbF92ZWdhbl9tZXRhIDwtIGFzLmRhdGEuZnJhbWUodmVnYW46OnNjb3JlcyhhbGxfcHNfdmVnYW5fb3JkX21ldGEpKQogICAgICAgICAgICAKICAgICAgICAgICAgI1VzaW5nIHRoZSBzY29yZXMgZnVuY3Rpb24gZnJvbSB2ZWdhbiB0byBleHRyYWN0IHRoZSBzaXRlIHNjb3JlcyBhbmQgY29udmVydCB0byBhIGRhdGEuZnJhbWUKICAgICAgICAgICAgCiAgICAgICAgICAgICMgYWxsX3ZlZ2FuX21ldGEkYFNhbXBsZSBudW1iZXJgIDwtIHJvd25hbWVzKGFsbF92ZWdhbl9tZXRhKSAlPiUgYXMubnVtZXJpYygpICAKICAgICAgICAgICAgCiAgICAgICAgICAgICMgYWxsX3ZlZ2FuX21ldGEgJT4lIGxlZnRfam9pbigpIyBjcmVhdGUgYSBjb2x1bW4gb2Ygc2l0ZSBuYW1lcywgZnJvbSB0aGUgcm93bmFtZXMgb2YgZGF0YS5zY29yZXMKICAgICAgICAgICAgCiAgICAgICAgICAgICMgYWxsX3ZlZ2FuX21ldGEgPC0gYWxsX3ZlZ2FuX21ldGEgICU+JSBhc190aWJibGUoKSAjIGNyZWF0ZSBhIGNvbHVtbiBvZiBzaXRlIG5hbWVzLCBmcm9tIHRoZSByb3duYW1lcyBvZiBkYXRhLnNjb3JlcwoKIzctIGJyaW5nIE5NRFMgc2NvcmVzIHRvIGNvbXBsZXRlIHRhYmxlCgphbGxfdmVnYW5fbWV0YV90YmwgPC0gbGVmdF9qb2luKHggPSB1bmlxdWUoYWxsX3BzX2Jsc3RfdmVnYW5bLGMoMToxMCldKSx5ID0gYWxsX3ZlZ2FuX21ldGEsIGJ5ID0gIlNhbXBsZSBudW1iZXIiKSAlPiUgCiAgbXV0YXRlKFByaW1lcj1mYWN0b3IoUHJpbWVyLGxldmVscyA9IGMoIk5lb0Zpc2giLCAiTWlGaXNoIiwgIlRlbGVvIikpLAogICAgICAgICBgTW9jayBDb21tdW5pdHlgPWZhY3RvcihgTW9jayBDb21tdW5pdHlgKSkKCgoKCgpsaWJyYXJ5KGZhY3RvZXh0cmEpCmxpYnJhcnkoZ2dmb3JjZSkKCgoKbm1kc19QTE9UIDwtIGFsbF92ZWdhbl9tZXRhX3RibCAlPiUgCiAgIyBmaWx0ZXIoUnVuICVpbiUgYygiTEdDX01pbmlTZXFfMSIsICJMR0NfTWluaVNlcV8yIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBOTURTMSx5ID0gTk1EUzIsIGNvbCA9IFByaW1lcixzaGFwZSA9IE5vcm1hbGl6YXRpb24sbGFiZWwgPSBTYW1wbGUsR3JvdXAgPSBgTW9jayBDb21tdW5pdHlgKSkrCiAgICAjIHN0YXRfZWxsaXBzZSgpKyAKICBnZW9tX3BvaW50KHNpemUgPSAxMSkrCiAgdGhlbWVfbGlnaHQoYmFzZV9zaXplID0gMTgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpICsKICAjIGdncmVwZWw6Omdlb21fbGFiZWxfcmVwZWwobGFiZWwuc2l6ZSA9IDAuOCxzaXplID0gMyxtaW4uc2VnbWVudC5sZW5ndGggPSAyKSArCiAgIyBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoY29sPSJibGFjayIsc2l6ZSA9IDMsbWluLnNlZ21lbnQubGVuZ3RoID0gMikgKwogICMgc2NhbGVfc2hhcGVfbWFudWFsKCkgJT4lIAogIHNjYWxlX2NvbG9yX21hbnVhbCgKICAgICMgbGFiZWxzID0gYygiTmVvRmlzaCIsICJNaUZpc2giLCAiVGVsZW8iLCAiTmVvRmlzaC9NaUZpc2giLCAiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKSwKICAgIGxhYmVscyA9IGMoIk5lb0Zpc2giLCAiTWlGaXNoIiwgIlRlbGVvIiksCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGFscGhhKGNvbG91ciA9IGNvbG9yc19ub3JtW2MoMSwzLDUpXSApKSsKICBhbm5vdGF0ZShnZW9tID0gInRleHQiLAogICAgICAgICAgIHg9YygwLjI3NSkseT1jKC0wLjI3NSksbGFiZWw9cGFzdGUwKCJTdHJlc3M6ICIscm91bmQoYWxsX3BzX3ZlZ2FuX29yZF9tZXRhJHN0cmVzcyxkaWdpdHMgPSA0KSksc2l6ZT01KSArCgoKICAgICMgQUREIGdnZm9yY2UncyBlbGxpcHNlcwogIGdnZm9yY2U6Omdlb21fbWFya19lbGxpcHNlKGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBOTURTMSx5ID0gTk1EUzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwPWBNb2NrIENvbW11bml0eWAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPWBNb2NrIENvbW11bml0eWApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSAxMDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gMC4wMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbC5mb250c2l6ZSA9IDIwLGNvbi5jYXAgPSAwLjEpIAogIAogICAgIyBmYWNldF93cmFwKH5gTW9jayBDb21tdW5pdHlgLG5jb2wgPSAyKQogIAojICAgCm5tZHNfUExPVAogICMgCiMgZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL1NGSlFfTk1EUy5wZGYiLApnZ3NhdmUoZmlsZSA9ICJ+L291dHJvcy9zZmpxX3RlbXAvU0ZKUV9OTURTLnBkZiIsCiAgICAgcGxvdCA9IG5tZHNfUExPVCwKICAgICBkZXZpY2UgPSAicGRmIiwKICAgICB3aWR0aCA9IDQwLAogICAgIGhlaWdodCA9MjUsCiAgICAgdW5pdHMgPSAiY20iLAogICAgIGRwaSA9IDMwMCkKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9TRkpRX05NRFMucG5nIiwKICAgICBwbG90ID0gbm1kc19QTE9ULAogICAgIGRldmljZSA9ICJwbmciLAogICAgIHdpZHRoID0gMzEsCiAgICAgaGVpZ2h0ID0yMCwKICAgICB1bml0cyA9ICJjbSIsCiAgICAgZHBpID0gMzAwKQoKCgoKIyBhbm9zaW0tLS0tCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgYW5vc2luIGZ1bmN0aW9uIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwphbm9zaW5fYXV0bzwtIGZ1bmN0aW9uKHRibCxjb2xzX291dCwgQ29sdW5hKXsKICBkZiA8LSB0YmxbLGMoMSwoMStjb2xzX291dCk6bmNvbCh0YmwpKV0gJT4lIAogICAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICAgIGByb3duYW1lczwtYCguJGBTYW1wbGUgbnVtYmVyYCkgJT4lIAogICAgc2VsZWN0KC1jKCJTYW1wbGUgbnVtYmVyIikpCiAgCiAgYW5vIDwtIGFub3NpbShkZiwgZ3JvdXBpbmcgPSB0YmxbW0NvbHVuYV1dLAogICAgICAgcGVybXV0YXRpb25zID0gOTk5OSwgZGlzdGFuY2UgPSAiYnJheSIsIHN0cmF0YSA9IE5VTEwpCiAgcmV0dXJuKGFubykKICAKfQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiNQcmltZXJzIC0tLS0KI1RvZGFzIE1DIGp1bnRhcwphbGxfcHNfYmxzdF92ZWdhbiAlPiUgCiAgIyBmaWx0ZXIoYE1vY2sgQ29tbXVuaXR5YCAlaW4lIGMoIlNGbWMiKSkgJT4lIAphbm9zaW5fYXV0byhjb2xzX291dCA9IDEwLENvbHVuYSA9ICJQcmltZXIiKQoKI0FwZW5hcyBKUQphbGxfcHNfYmxzdF92ZWdhbiAlPiUgCiAgZmlsdGVyKGBNb2NrIENvbW11bml0eWAgJWluJSBjKCJKUW1jIikpICU+JSAKYW5vc2luX2F1dG8oY29sc19vdXQgPSAxMCxDb2x1bmEgPSAiUHJpbWVyIikKCiNBcGVuYXMgU0YKYWxsX3BzX2Jsc3RfdmVnYW4gJT4lIAogIGZpbHRlcihgTW9jayBDb21tdW5pdHlgICVpbiUgYygiU0ZtYyIpKSAlPiUgCmFub3Npbl9hdXRvKGNvbHNfb3V0ID0gMTAsQ29sdW5hID0gIlByaW1lciIpCgojQXBlbmFzIFNGSlEKYWxsX3BzX2Jsc3RfdmVnYW4gJT4lIAogIGZpbHRlcihgTW9jayBDb21tdW5pdHlgICVpbiUgYygiU0ZKUW1jIikpICU+JSAKYW5vc2luX2F1dG8oY29sc19vdXQgPSAxMCxDb2x1bmEgPSAiUHJpbWVyIikKCgojTm9ybWFsaXphdGlvbiAtLS0tCiNUb2RhcyBNQyBqdW50YXMKYWxsX3BzX2Jsc3RfdmVnYW4gJT4lIAphbm9zaW5fYXV0byhjb2xzX291dCA9IDEwLENvbHVuYSA9ICJOb3JtYWxpemF0aW9uIikKCiNBcGVuYXMgSlEKYWxsX3BzX2Jsc3RfdmVnYW4gJT4lIAogIGZpbHRlcihgTW9jayBDb21tdW5pdHlgICVpbiUgYygiSlFtYyIpKSAlPiUgCmFub3Npbl9hdXRvKGNvbHNfb3V0ID0gMTAsQ29sdW5hID0gIk5vcm1hbGl6YXRpb24iKQoKI0FwZW5hcyBTRgphbGxfcHNfYmxzdF92ZWdhbiAlPiUgCiAgZmlsdGVyKGBNb2NrIENvbW11bml0eWAgJWluJSBjKCJTRm1jIikpICU+JSAKYW5vc2luX2F1dG8oY29sc19vdXQgPSAxMCxDb2x1bmEgPSAiTm9ybWFsaXphdGlvbiIpCgojQXBlbmFzIFNGSlEKYWxsX3BzX2Jsc3RfdmVnYW4gJT4lIAogIGZpbHRlcihgTW9jayBDb21tdW5pdHlgICVpbiUgYygiU0ZKUW1jIikpICU+JSAKYW5vc2luX2F1dG8oY29sc19vdXQgPSAxMCxDb2x1bmEgPSAiTm9ybWFsaXphdGlvbiIpCgoKYWxsX3ZlZ2FuX21ldGFfdGJsICU+JSAKICBmaWx0ZXIoUnVuICVpbiUgYygiTEdDX01pbmlTZXFfMSIsIkxHQ19NaW5pU2VxXzIiKSkgJT4lIAogIHNlbGVjdChTYW1wbGUsYFNhbXBsZSBudW1iZXJgLFByaW1lcikKCgpgYGAKCiMjIyBQbG90aW5nIEFTVnMKCmBgYHtyLGVjaG89VFJVRSwgZXZhbD1GQUxTRX0KCiMgYWxsX3BzX3RibF9ibGFzdF9iY2twNiA8LSBhbGxfcHNfdGJsX2JsYXN0CgphbGxfcHNfdGJsX2JsYXN0IDwtIGFsbF9wc190YmxfYmxfY3VyIAoKCgoKIzI4LSBBU1ZzIHBsb3RzIGJ5IHNhbXBsZSBhbmQgc3BlY2llcyAtLS0tCgpvcHRpb25zKHNldC5zZWVkKHNlZWQgPSAxMykpCgojMjhhLSBBU1Ygc2l6ZSBkaXN0cmlidXRpb24gLSBhbHBoYWJldGljYWwtLS0tCmFsbF9wc190YmxfYmxhc3QkUnVuICU+JSB1bmlxdWUoKQogIApBU1Zfc2l6ZV9ieV9TYW1wbGUgPC0gYWxsX3BzX3RibF9ibGFzdCAlPiUKICBmaWx0ZXIoIVNhbXBsZSAlaW4lIGMoIlBvc2l0aXZlIENvbnRyb2xcbihQLmdsYXVjYSkiKSkgJT4lIAogIGZpbHRlcighUnVuICVpbiUgYygiZWNvbW9sX2lTZXEiKSkgJT4lIAogIG11dGF0ZShTYW1wbGUgPSBmYWN0b3IoU2FtcGxlLGxldmVscyA9IHNhbXBsZV9sZXZlbHMpKSAlPiUgCiAgbXV0YXRlKFByaW1lciA9IGZhY3RvcihQcmltZXIsbGV2ZWxzID0gYygiTmVvRmlzaCIsICJNaUZpc2giLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUZWxlbyIsICJOZW9GaXNoL01pRmlzaC9UZWxlbyIpKSkgJT4lIAogIGdncGxvdChhZXMoeT1TYW1wbGUsCiAgICAgICAgICAgICB4PWBBU1Ygc2l6ZSAocGIpYCwKICAgICAgICAgICAgIGNvbG91ciA9IFByaW1lciwKICAgICAgICAgICAgIHNpemU9YFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgLAogICAgICAgICAgICAgc2hhcGU9YEV4cGVjdGVkIGxlbmd0aGAKICAgICAgICAgICAgICkpICsKICBnZW9tX2ppdHRlcihoZWlnaHQgPSAwLjIsCiAgICAgICAgICAgICAgd2lkdGggPSAwKSArCiAgZ2dwbG90Mjo6c2NhbGVfY29sb3VyX21hbnVhbCgKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gZ2dwbG90Mjo6YWxwaGEoY29sb3VyID0gY29sb3JzNVsxOjRdICxhbHBoYSA9ICAwLjMpKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSA4KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMjAsNjAsODAsMTAwLDEyMCwxNDAsMTYwLDE4MCwyMDAsMjIwLDI0MCwyNjAsMjgwLDMwMCwzMjAsMzQwKSxleHBhbmQgPSBjKDAuMDIsMC4wMikpICsKICB4bGFiKCJBU1YgbGVuZ3RoIChicCkiKSArCiAgeWxhYigiU2FtcGxlIikgKwogIGdndGl0bGUobGFiZWwgPSAiU0ZKUSBtb2NrIGNvbW11bml0aWVzICIsCiAgICAgICAgICBzdWJ0aXRsZSA9ICJBbGwgQVNWcyBmb3VuZCBpbiBzYW1wbGVzLCBieSBsZW5ndGggYW5kIGFidW5kYW5jZSIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpIAoKQVNWX3NpemVfYnlfU2FtcGxlCgoKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzLzMtQVNWX3NpemVfYnlfc2FtcGxlLnBuZyIsCiAgICAgcGxvdCA9IEFTVl9zaXplX2J5X1NhbXBsZSwKICAgICBkZXZpY2UgPSAicG5nIiwKICAgICB3aWR0aCA9IDE4LAogICAgIGhlaWdodCA9IDEwLAogICAgIGRwaSA9IDYwMCkKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy8zLUFTVl9zaXplX2J5X3NhbXBsZS5zdmciLAogICAgIHBsb3QgPSBBU1Zfc2l6ZV9ieV9TYW1wbGUsCiAgICAgZGV2aWNlID0gInN2ZyIsCiAgICAgd2lkdGggPSAxOCwKICAgICBoZWlnaHQgPSAxMCwKICAgICBkcGkgPSA2MDApCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvMy1BU1Zfc2l6ZV9ieV9zYW1wbGUucGRmIiwKICAgICBwbG90ID0gQVNWX3NpemVfYnlfU2FtcGxlLAogICAgIGRldmljZSA9ICJwZGYiLAogICAgIHdpZHRoID0gMTgsCiAgICAgaGVpZ2h0ID0gMTAsCiAgICAgZHBpID0gNjAwKQpkZXYub2ZmKCkKCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHBhcGVyICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAtLS0tCgojMjkgLSBBU1ZTIC0gc2FtcGxlIFggc3BlY2llcyAoMTJTKSAtIGRpc3RyaWJ1dGlvbjogYmxhc3QtLS0tIAphbGxfcHNfdGJsX2JsYXN0JEdyb3VwICU+JXVuaXF1ZSgpCgojSnEgJiBTRiBETkEgcG9vbHMgLSBBU1ZzIHNpemUgYW5kIHNwZWNpZXMgYnkgc2FtcGxlLS0tLQoKYWxsX3BzX3RibF9ibGFzdCRTYW1wbGUgJT4lIHVuZmFjdG9yKCkgJT4lIHVuaXF1ZSgpICU+JSBiYXNlOjpzb3J0KCkKYWxsX3BzX3RibF9ibGFzdCRgcmV2aXNlZCBmaW5hbCBJRGAgJT4lIHVuaXF1ZSgpICU+JSBiYXNlOjpzb3J0KCkgJT4lIHBhc3RlMChjb2xsYXBzZSA9ICciLCBcbiInKSAlPiUgY2F0KCkKYWxsX3BzX3RibF9ibGFzdCRgZmluYWwgSURgICU+JSB1bmlxdWUoKSAlPiUgYmFzZTo6c29ydCgpICU+JSBwYXN0ZTAoY29sbGFwc2UgPSAnIiwgXG4iJykgJT4lIGNhdCgpCgoKcG9vbF9sYWJlbHMgPC0gYygKICAiTm9ybWFsaXplZCBKUW1jIiA9ICJKZXF1aXRpbmhvbmhhXG5Ob3JtYWxpemVkIEROQSBwb29sIiwKICAiTm9uLW5vcm1hbGl6ZWQgSlFtYyIgPSAiSmVxdWl0aW5ob25oYVxuTm9uLU5vcm1hbGl6ZWQgRE5BIHBvb2wiLAogICJOb3JtYWxpemVkIFNGSlFtYyIgPSAiU8OjbyBGcmFuY2lzY28gJiBKZXF1aXRpbmhvbmhhXG5Ob3JtYWxpemVkIEROQSBwb29sIiwKICAiTm9uLW5vcm1hbGl6ZWQgU0ZtYyIgPSAiU8OjbyBGcmFuY2lzY29cbk5vbi1Ob3JtYWxpemVkIEROQSBwb29sIiwKICAiTm9ybWFsaXplZCBTRm1jIiA9ICJTw6NvIEZyYW5jaXNjb1xuTm9ybWFsaXplZCBETkEgcG9vbCIKKQoKcG9vbHNfbGV2ZWxzIDwtIGMoCiJOb3JtYWxpemVkIEpRbWMiLAoiTm9uLW5vcm1hbGl6ZWQgSlFtYyIsCiJOb3JtYWxpemVkIFNGSlFtYyIsCiJOb3JtYWxpemVkIFNGbWMiLAoiTm9uLW5vcm1hbGl6ZWQgU0ZtYyIKKQoKI2ZpbmFsIElEIGxldmVscwp7CmZpbmFsSURfbGV2ZWxzPC0gYygKI2pxCiJBc3R5YW5heCBsYWN1c3RyaXMiLCAKIkF1c3RyYWxvaGVyb3Mgc3AiLCAKIkRlbHR1cnVzIGJyZXZpcyIsIAoiRXVnZXJyZXMgYnJhc2lsaWFudXMiLCAKIkh5cG9tYXN0aWN1cyBzdGVpbmRhY2huZXJpIiwgCgoiSHlwb3N0b211cyBuaWdyb2xpbmVhdHVzIiwgCiJNZWdhbGVwb3JpbnVzIGVsb25nYXR1cyIsIAoiTWVnYWxlcG9yaW51cyBnYXJtYW5pIiwgCiJNb2Vua2hhdXNpYSBjb3N0YWUiLCAKIlJoYW1kaWEgcXVlbGVuIiwgCiJTdGVpbmRhY2huZXJpZGlvbiBhbWJseXVydW0iLCAKIldlcnRoZWltZXJpYSBtYWN1bGF0YSIsCiNhbWJvcwoiR3ltbm90dXMgY2FyYXBvIiwgCiJIb3BsaWFzIiwgCiJIb3BsaWFzIGJyYXNpbGllbnNpcyIsIAoKIkhvcGxpYXMgaW50ZXJtZWRpdXMiLCAKIkhvcGxpYXMgbWFsYWJhcmljdXMiLCAKIlByb2NoaWxvZHVzIiwgCiJQcm9jaGlsb2R1cyBhcmdlbnRldXMiLCAKIAoiUHJvY2hpbG9kdXMgY29zdGF0dXMiLCAKIlN0ZWluZGFjaG5lcmluYSBlbGVnYW5zIiwgCiJUcmFjaGVseW9wdGVydXMgZ2FsZWF0dXMiLAojc2YKCiJBc3R5YW5heCBmYXNjaWF0dXMiLCAKIkJyeWNvbiBvcnRob3RhZW5pYSIsIAoiQ2hhcmFjaWRpdW0gbGFnb3NhbnRlbnNlIiwgCiJDcmVuaWNpY2hsYSBsZXBpZG90YSIsIAojICJDdXJpbWF0ZWxsYSBsZXBpZHVyYSIsIGVzc2Ugw6kgbmEgdmRkIHJvZWJvaWRlcwoiUm9lYm9pZGVzIHhlbm9kb24iLAoiRWlnZW5tYW5uaWEgdmlyZXNjZW5zIiwgCiJGcmFuY2lzY29kb3JhcyBtYXJtb3JhdHVzIiwgCiJIeXBvc3RvbXVzIGFsYXR1cyIsIAoiSW1wYXJmaW5pcyBtaW51dHVzIiwgCiJMZXBvcmludXMgcmVpbmhhcmR0aSIsIAoiTWljcm9nbGFuaXMgbGVwdG9zdHJpYXR1cyIsIAoiTW9lbmtoYXVzaWEgc2FuY3RhZWZpbG9tZW5hZSIsIAoiTXlsZXVzIG1pY2FucyIsIAoiUGFtcGhvcmljaHRoeXMgaG9sbGFuZGkiLCAKIlBoYWxsb2Nlcm9zIHVhaSIsIAoKIlBpbWVsb2R1cyBtYWN1bGF0dXMiLCAKIlBpbWVsb2R1cyBwb2hsaSIsIAoiUHNldWRvcGxhdHlzdG9tYSBjb3JydXNjYW5zIiwgCiJQdGVyeWdvcGxpY2h0aHlzIGV0ZW50YWN1bGF0dXMiLCAKIlNlcnJhc2FsbXVzIGJyYW5kdGlpIiwgCiJUZXRyYWdvbm9wdGVydXMgY2hhbGNldXMiLCAKCiNwYXJ0aWFsCiJBc3R5YW5heCIsIAoiSG9wbGlhcyBicmFzaWxpZW5zaXMvaW50ZXJtZWRpdXMiLAoiSHlwb3N0b211cyIsIAoiUGltZWxvZHVzIiwgCiJQcm9jaGlsb2R1cyBhcmdlbnRldXMvaGFydGlpIiwKI3RyYXNoCgoKIk5BIGVsZWdhbnMvZ2lsYmVydCIsIAoiTkEgbGVwaWR1cmEveGVub2RvbiIsIAoiQWNlc3Ryb3JoeW5jaHVzIGxhY3VzdHJpcyIsCiJDb3B0b2RvbiB6aWxsaWkiLAoiQ3lwaG9jaGFyYXggZ2lsYmVydCIsCiJHZW9waGFndXMgYnJhc2lsaWVuc2lzIiwKIlBsYW5hbHRpbmEgbXllcnNpIiwgCiJQb2VjaWxpYSByZXRpY3VsYXRhIG1pdG9jaG9uZHIiCikKfQpmaW5hbElEX2xldmVsc1tmaW5hbElEX2xldmVscyAlPiUgZHVwbGljYXRlZCgpXQoKCgojIGZpbmFsIElEIGxldmVscyAyCnsKZmluYWxJRF9sZXZlbHMgPC0gYygKIkFjZXN0cm9yaHluY2h1cyBsYWN1c3RyaXMiLCAKIkFjaW5vY2hlaXJvZG9uIG1lbGFub2dyYW1tYSIsIAoiQXN0eWFuYXggZmFzY2lhdHVzIiwgCiJBc3R5YW5heCBsYWN1c3RyaXMiLCAKIkF1c3RyYWxvaGVyb3Mgc3AiLCAKIkJvcyB0YXVydXMiLCAKIkJyeWNvbiBvcnRob3RhZW5pYSIsIAoiQ2hhcmFjaWRpdW0gbGFnb3NhbnRlbnNlIiwgCiJDb3B0b2RvbiB6aWxsaWkiLCAKIkNyZW5pY2ljaGxhIGxlcGlkb3RhIiwgCiMgIkN1cmltYXRlbGxhIGxlcGlkdXJhIiwgYWdvcmEgw6kgcm9lYm9pZGVzCiJSb2Vib2lkZXMgeGVub2RvbiIsCiJDeXBob2NoYXJheCBnaWxiZXJ0IiwgCiJEZWx0dXJ1cyBicmV2aXMiLCAKIkVpZ2VubWFubmlhIHZpcmVzY2VucyIsIAoiRXVnZXJyZXMgYnJhc2lsaWFudXMiLCAKIkZyYW5jaXNjb2RvcmFzIG1hcm1vcmF0dXMiLCAKIkdlb3BoYWd1cyBicmFzaWxpZW5zaXMiLCAKIkd5bW5vdHVzIGNhcmFwbyIsIAoiSG9wbGlhcyBicmFzaWxpZW5zaXMiLCAKIkhvcGxpYXMgaW50ZXJtZWRpdXMiLCAKIkhvcGxpYXMgbWFsYWJhcmljdXMiLCAKIkh5cG9tYXN0aWN1cyBzdGVpbmRhY2huZXJpIiwgCiJIeXBvc3RvbXVzIGFsYXR1cyIsIAoiSHlwb3N0b211cyBuaWdyb2xpbmVhdHVzIiwgCiJJbXBhcmZpbmlzIG1pbnV0dXMiLCAKIkxlcG9yaW51cyByZWluaGFyZHRpIiwgCiJNZWdhbGVwb3JpbnVzIGVsb25nYXR1cyIsIAoiTWVnYWxlcG9yaW51cyBnYXJtYW5pIiwgCiJNaWNyb2dsYW5pcyBsZXB0b3N0cmlhdHVzIiwgCiJNb2Vua2hhdXNpYSBjb3N0YWUiLCAKIk1vZW5raGF1c2lhIHNhbmN0YWVmaWxvbWVuYWUiLCAKIk15bGV1cyBtaWNhbnMiLCAKIlBhbXBob3JpY2h0aHlzIGhvbGxhbmRpIiwgCiJQaGFsbG9jZXJvcyB1YWkiLCAKIlBpbWVsb2R1cyBtYWN1bGF0dXMiLCAKIlBpbWVsb2R1cyBwb2hsaSIsIAoiUGxhbmFsdGluYSBteWVyc2kiLCAKIlByaW9uYWNlIGdsYXVjYSIsIAoiUHJvY2hpbG9kdXMgYXJnZW50ZXVzIiwgCiJQcm9jaGlsb2R1cyBjb3N0YXR1cyIsIAoiUHJvY2hpbG9kdXMgaGFydGlpIiwKIlBzZXVkb3BsYXR5c3RvbWEgY29ycnVzY2FucyIsIAoiUHRlcnlnb3BsaWNodGh5cyBldGVudGFjdWxhdHVzIiwgCiJSaGFtZGlhIHF1ZWxlbiIsIAoiUm9lYm9pZGVzIHhlbm9kb24iLCAKIlNlcnJhc2FsbXVzIGJyYW5kdGlpIiwgCiJTdGVpbmRhY2huZXJpZGlvbiBhbWJseXVydW0iLCAKIlRldHJhZ29ub3B0ZXJ1cyBjaGFsY2V1cyIsIAoiVHJhY2hlbHlvcHRlcnVzIGdhbGVhdHVzIiwgCiJXZXJ0aGVpbWVyaWEgbWFjdWxhdGEiLAoKI3BhcnRpYWwKIkFzdHlhbmF4IiwgCiJIb3BsaWFzIGJyYXNpbGllbnNpcy9pbnRlcm1lZGl1cyIsIAoiSHlwb3N0b211cyIsIAoiUGltZWxvZHVzIiwgCiJQcm9jaGlsb2R1cyIsIAoiUHJvY2hpbG9kdXMgYXJnZW50ZXVzL2hhcnRpaSIpCn0KCnNwc19yZW1vdmUgPC0gYygKTkEsIk5BIiwKIkFjZXN0cm9yaHluY2h1cyBsYWN1c3RyaXMiLCAKIkFjaW5vY2hlaXJvZG9uIG1lbGFub2dyYW1tYSIsIAoiQm9zIHRhdXJ1cyIsIAoiQ29wdG9kb24gemlsbGlpIiwgCiJDdXJpbWF0ZWxsYSBsZXBpZHVyYSIsIAoiRXVnZXJyZXMgYnJhc2lsaWFudXMiLCAKIkdlb3BoYWd1cyBicmFzaWxpZW5zaXMiLCAKIkxlcG9yaW51cyByZWluaGFyZHRpIiwgCiJNb2Vua2hhdXNpYSBjb3N0YWUiLCAKIlBsYW5hbHRpbmEgbXllcnNpIiwgCiJQcmlvbmFjZSBnbGF1Y2EiLCAKIlBzZXVkb3BsYXR5c3RvbWEgY29ycnVzY2FucyIKKQoKCmBgYAoKIyBJbWFnZXMgYXJjdGljbGUKCmBgYHtyLGVjaG89RkFMU0UsZXZhbD1GQUxTRX0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyNhcnRpZ28gbmFpcmEgLS0tLQoKCmFsbF9wc190YmxfYmxhc3QkYGZpbmFsIElEYFthbGxfcHNfdGJsX2JsYXN0JGBFeHBlY3RlZCBsZW5ndGhgICVpbiUgYygiaW4gcmFuZ2UiKV0gJT4lIHVuaXF1ZSgpCgoKCiNub3cgd2UgYXJlIGdvaW5nIHRvIGVkaXQgCiMgYWxsX3BzX3RibF9zZmpxX2Z1bGxfYmNrcCAgPC0gYWxsX3BzX3RibF9zZmpxX2Z1bGwgIAoKCmFsbF9wc190Ymxfc2ZqcV9mdWxsJGByZXZpc2VkIGZpbmFsIElEYCAlPiUgdW5pcXVlKCkKCgoKIyBBU1ZzIFZzLiBPVFVzCgoKYWxsX3BzX3RibF9zZmpxJFNhbXBsZSAlPiUgdW5pcXVlKCkKCgojIAojIGFsbF9wc190Ymxfc2ZqcV9mdWxsICU+JQojICAgIyBmaWx0ZXIoYEV4cGVjdGVkIGxlbmd0aGAgJWluJSBjKCJpbiByYW5nZSIpKSAlPiUgCiMgICAjIGZpbHRlcihgRXhwZWN0ZWQgU3BlY2llc2AgJWluJSBjKCJleHBlY3RlZCIpKSAlPiUgCiMgICBmaWx0ZXIoUnVuICVpbiUgYygiTEdDX01pbmlTZXFfMSIsICJMR0NfTWluaVNlcV8yIikpICU+JSAKIyAgICMgc3Vic2V0KCEoU2FtcGxlICVpbiUgYygiUG9zaXRpdmUgQ29udHJvbFxuKFAuZ2xhdWNhKSIpKSkgJT4lIAojICAgZ3JvdXBfYnkoU2FtcGxlKSAlPiUgCiMgICBzZWxlY3QoYygxOjgsMTg6MjQsNjE6NzQpKSAlPiUgVmlldygpCgphbGxfcHNfdGJsX3NmanFfZnVsbCRgcmV2aXNlZCBmaW5hbCBJRGBbYWxsX3BzX3RibF9zZmpxX2Z1bGwkYEV4cGVjdGVkIFNwZWNpZXNgID09ICJub3QgZXhwZWN0ZWQiXSAlPiUgdW5pcXVlKCkgJT4lIGJhc2U6OnNvcnQoKQoKYWxsX3BzX3RibF9zZmpxX2Z1bGwkYHJldmlzZWQgZmluYWwgSURgW2FsbF9wc190Ymxfc2ZqcV9mdWxsJGBFeHBlY3RlZCBTcGVjaWVzYCA9PSAiZXhwZWN0ZWQiJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbF9wc190Ymxfc2ZqcV9mdWxsJFByaW1lciA9PSAiTmVvRmlzaCImCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxfcHNfdGJsX3NmanFfZnVsbCRHcm91cCA9PSAiTm9ybWFsaXplZCBTRkpRbWMiXSAlPiUgdW5pcXVlKCkgJT4lIGJhc2U6OnNvcnQoKQoKYWxsX3BzX3RibF9zZmpxX2Z1bGwkYHJldmlzZWQgZmluYWwgSURgW2FsbF9wc190Ymxfc2ZqcV9mdWxsJGBFeHBlY3RlZCBTcGVjaWVzYCA9PSAiZXhwZWN0ZWQiJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbF9wc190Ymxfc2ZqcV9mdWxsJFByaW1lciA9PSAiTWlGaXNoIiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbF9wc190Ymxfc2ZqcV9mdWxsJEdyb3VwID09ICJOb3JtYWxpemVkIFNGSlFtYyJdICU+JSB1bmlxdWUoKSAlPiUgYmFzZTo6c29ydCgpCgoKCkFTVnNfbl9PVFVzX3RibCRgRXhwZWN0ZWQgc3BlY2llcyBsaXN0YFtBU1ZzX25fT1RVc190YmwkYElEIHR5cGVgID09ICJTcGVjaWVzIiBdCgoKQVNWc19uX09UVXNfdGJsIDwtIGFsbF9wc190Ymxfc2ZqcV9mdWxsICU+JSAKICBmaWx0ZXIoYEV4cGVjdGVkIGxlbmd0aGAgJWluJSBjKCJpbiByYW5nZSIpKSAlPiUKICAjIGZpbHRlcihgRXhwZWN0ZWQgU3BlY2llc2AgJWluJSBjKCJleHBlY3RlZCIpKSAlPiUgCiAgZmlsdGVyKFJ1biAlaW4lIGMoIkxHQ19NaW5pU2VxXzEiLCAiTEdDX01pbmlTZXFfMiIpKSAlPiUgCiAgIyBzdWJzZXQoIShTYW1wbGUgJWluJSBjKCJQb3NpdGl2ZSBDb250cm9sXG4oUC5nbGF1Y2EpIikpKSAlPiUgCiAgZ3JvdXBfYnkoU2FtcGxlKSAlPiUgCiAgc3VtbWFyaXplKFNhbXBsZSA9IHVuaXF1ZShTYW1wbGUpLAogICAgICAgICAgICBSdW4gPSB1bmlxdWUoUnVuKSwKICAgICAgICAgICAgR3JvdXAgPSB1bmlxdWUoR3JvdXApLAogICAgICAgICAgICBPVFVzID0gbGVuZ3RoKHVuaXF1ZShPVFUpKSwKICAgICAgICAgICAgQVNWcyA9IGxlbmd0aCh1bmlxdWUoYEFTViAoU2VxdWVuY2UpYCkpLAogICAgICAgICAgICBJRHMgPSBsZW5ndGgodW5pcXVlKGByZXZpc2VkIGZpbmFsIElEYCkpLAogICAgICAgICAgICAjIGFsbF9JRHMgPSBsZW5ndGgodW5pcXVlKGBGdWxsIG5hbWVgKSksCiAgICAgICAgICAgIFByaW1lciA9IHVuaXF1ZShQcmltZXIpLAogICAgICAgICAgICAjIGBTcGVjaWVzYCA9IGxlbmd0aCh1bmlxdWUoYGZpbmFsIElEYFtgRXhwZWN0ZWQgU3BlY2llc2AgJWluJSBjKCJleHBlY3RlZCIpXSkpLCAgICAgICAjU3BlY2llcyB3aWxsIG5vdyBjb3JyZXNwb25kIHRvIEV4cGVjdGVkIFNwZWNpZXMKICAgICAgICAgICAgYFNwZWNpZXNgID0gbGVuZ3RoKHVuaXF1ZShgcmV2aXNlZCBmaW5hbCBJRGApKSwgICAgICAgI1NwZWNpZXMgd2lsbCBub3cgY29ycmVzcG9uZCB0byBFeHBlY3RlZCBTcGVjaWVzCiAgICAgICAgICAgICMgYEV4cGVjdGVkIHNwZWNpZXMgbGlzdGAgPSBsaXN0KHVuaXF1ZShiYXNlOjpzb3J0KGBmaW5hbCBJRGBbYEV4cGVjdGVkIFNwZWNpZXNgICVpbiUgYygiZXhwZWN0ZWQiKV0pKSkKICAgICAgICAgICAgYEV4cGVjdGVkIHNwZWNpZXMgbGlzdGAgPSBsaXN0KHVuaXF1ZShiYXNlOjpzb3J0KGByZXZpc2VkIGZpbmFsIElEYCkpKQogICAgICAgICAgICApICU+JSAKICBtdXRhdGUoU2FtcGxlID0gZmFjdG9yKFNhbXBsZSxsZXZlbHMgPSBzYW1wbGVfbGV2ZWxzKSkgJT4lIAogIHRpZHlyOjpwaXZvdF9sb25nZXIoY29scyA9IGMoT1RVcyxBU1ZzLElEcyxgU3BlY2llc2ApLG5hbWVzX3RvID0gIklEIHR5cGUiLHZhbHVlc190byA9ICJDb3VudHMiKSAlPiUKICBtdXRhdGUoYElEIHR5cGVgID0gZmFjdG9yKGBJRCB0eXBlYCxsZXZlbHMgPSBjKCJBU1ZzIiwiT1RVcyIsIklEcyIsIlNwZWNpZXMiKSkpICU+JQogIG11dGF0ZShHcm91cCA9IGZhY3RvcihHcm91cCxsZXZlbHMgPSBjKCJOb24tbm9ybWFsaXplZCBKUW1jIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsaXplZCBKUW1jIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9uLW5vcm1hbGl6ZWQgU0ZtYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGl6ZWQgU0ZtYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGl6ZWQgU0ZKUW1jIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKSAlPiUKICBtdXRhdGUoTm9ybSA9IGlmZWxzZShHcm91cCAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIEpRbWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9uLW5vcm1hbGl6ZWQgU0ZtYyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwiTm9uLU5vcm1hbGl6ZWQiLCJOb3JtYWxpemVkIikpICU+JSAKICBtdXRhdGUoTm9ybSA9IGZhY3RvcihOb3JtKSkgJT4lIAogIG11dGF0ZShNQyA9IHN0cl9yZW1vdmVfYWxsKHN0cmluZyA9IEdyb3VwLCBwYXR0ZXJuID0gIk5vcm1hbGl6ZWQgfE5vbi1ub3JtYWxpemVkICIpKQoKQVNWc19uX09UVXNfdGJsJGBFeHBlY3RlZCBzcGVjaWVzIGxpc3RgCgpBU1ZzX25fT1RVc190YmwkYEV4cGVjdGVkIHNwZWNpZXMgbGlzdGBbQVNWc19uX09UVXNfdGJsJGBJRCB0eXBlYCAlaW4lIGMoIlNwZWNpZXMiKV0KCgoKIyBBU1ZzLCBPVFVzIGFuZCBTcGVjaWVzIHBsb3QgLS0tLQpBU1ZzX25fT1RVc190YmwkU2FtcGxlICU+JSB1bmlxdWUoKQpBU1ZzX25fT1RVU19wbG90CgoKI0NvbW8gY29tYmluYWRvIGNvbSBuYWlhcmEKQVNWc19uX09UVVNfcGxvdCA8LSBBU1ZzX25fT1RVc190YmwgJT4lIAogIGZpbHRlcighYElEIHR5cGVgICVpbiUgYygiSURzIikpICU+JSAKICBmaWx0ZXIoTm9ybSAlaW4lIGMoIk5vcm1hbGl6ZWQiKSkgJT4lIAogIG11dGF0ZShTYW1wbGUgPSBzdHJfcmVtb3ZlKFNhbXBsZSwiTm9ybWFsaXplZCAiKSkgJT4lIAogIG11dGF0ZShTYW1wbGUgPSBmYWN0b3IoU2FtcGxlLCBsZXZlbHMgPSBjKCJTRkpRbWNcbk1pRmlzaCIsIlNGSlFtY1xuTmVvRmlzaCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNGbWNcbk1pRmlzaCIsIlNGbWNcbk5lb0Zpc2giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKUW1jXG5NaUZpc2giLCJKUW1jXG5OZW9GaXNoIiwiSlFtY1xuVGVsZW8iKSkpICU+JSAKICBnZ3Bsb3QyOjpnZ3Bsb3QoYWVzKHggPSBTYW1wbGUsCiAgICAgICAgICAgICAgICAgICAgICB5ID0gQ291bnRzICwKICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBgSUQgdHlwZWAsIAogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBgSUQgdHlwZWApKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIscG9zaXRpb24gPSAiZG9kZ2UiKSsKICB4bGFiKCJTYW1wbGUiKSArCiAgeWxhYigiQ291bnRzIikgKwogIHRoZW1lX2xpZ2h0KGJhc2Vfc2l6ZSA9IDE2KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2E4YWZiOCIsICIjNmE3NDgxIiwgIiMzNTNhNDEiLCAiIzI1MjgyZCIpKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4PTAuNSwgeGVuZD0yLjUsIHk9MzgsIHllbmQ9MzgsbGluZXR5cGU9Ik9yaWdpbmFsIG51bWJlclxub2Ygc3BlY2llc1xuaW4gZWFjaCBwb29sIiksIGNvbG91cj0iYmxhY2siLHNpemU9MC43NSkgKwogIGdlb21fc2VnbWVudChhZXMoeD0yLjUsIHhlbmQ9NC41LCB5PTIzLCB5ZW5kPTIzLGxpbmV0eXBlPSJPcmlnaW5hbCBudW1iZXJcbm9mIHNwZWNpZXNcbmluIGVhY2ggcG9vbCIpLCBjb2xvdXI9ImJsYWNrIixzaXplPTAuNzUpICsKICBnZW9tX3NlZ21lbnQoYWVzKHg9NC41LCB4ZW5kPTcuNSwgeT0xNywgeWVuZD0xNyxsaW5ldHlwZT0iT3JpZ2luYWwgbnVtYmVyXG5vZiBzcGVjaWVzXG5pbiBlYWNoIHBvb2wiKSwgY29sb3VyPSJibGFjayIsc2l6ZT0wLjc1KSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKCIiLHZhbHVlcz1jKCJPcmlnaW5hbCBudW1iZXJcbm9mIHNwZWNpZXNcbmluIGVhY2ggcG9vbCI9MykpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDIuNSw0LjUpKSArCiAgIyBnZ3RpdGxlKGxhYmVsID0gIk5vcm1hbGl6ZWQgU0ZKUSBtb2NrIGNvbW11bml0aWVzIiwKICAjICAgICAgICAgICAgIHN1YnRpdGxlID0gIkFscGhhIGRpdmVyc2l0eSBlc3RpbWF0aW9uIHVzaW5nIGRpZmZlcmVudCBldmlkZW5jZXMiKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiSWRlbnRpZmljYXRpb24gbGV2ZWwiKSkgKwogIHlsYWIobGFiZWwgPSAiQWxwaGEgZGl2ZXNpdHkiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1Db3VudHMpLCAKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIAogICAgICAgICAgICB2anVzdCA9IDEuNCwKICAgICAgICAgICAgY29sb3VyID0gIiNmZmZmZmYiLCBzaXplID0gNykrCiAgYW5ub3RhdGUoZ2VvbSA9ICJyZWN0IiwKICB4bWluPWMoMC42LDIuNiw0LjYpLCB4bWF4PWMoMS40LDMuNCw1LjQpLCNtaWZpc2gKICB5bWluPWMoLTEuMCksIHltYXg9YygwKSwKICBhbHBoYT0xLGZpbGw9IiMwMDA3OTEiKSsKICBhbm5vdGF0ZShnZW9tID0gInJlY3QiLAogIHhtaW49YygxLjYsMy42LDUuNiksIHhtYXg9YygyLjQsNC40LDYuNCksI25lb2Zpc2gKICB5bWluPWMoLTEuMCksIHltYXg9YygwKSwKICBhbHBoYT0xLGZpbGw9IiMwMTc1MDQiKSsKICBhbm5vdGF0ZShnZW9tID0gInJlY3QiLAogIHhtaW49Yyg2LjYpLCB4bWF4PWMoNy40KSwjdGVsZW8KICB5bWluPWMoLTEuMCksIHltYXg9YygwKSwKICBhbHBoYT0xLGZpbGw9IiM4MjAwMDAiKSsKICBhbm5vdGF0ZShnZW9tID0gInRleHQiLAogIHg9YygxLjUsMy41LDYuNSkseT1jKDUxLDUxLDUxKSxsYWJlbD1jKCJTRkpRbWMiLCJTRm1jIiwiSlFtYyIpLHNpemU9OCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC0xLjUsNTMpLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJNaUZpc2giLCJOZW9GaXNoIiwiTWlGaXNoIiwiTmVvRmlzaCIsIk1pRmlzaCIsIk5lb0Zpc2giLCJUZWxlbyIpKQoKCgoKQVNWc19uX09UVVNfcGxvdApzY2FsZXM6OnNob3dfY29sKGNvbG9yczUpCgoKIyBnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3Mvc2ZqcS1BU1ZzX3ZzX09UVXMucGRmIiwKZ2dzYXZlKGZpbGUgPSAifi9vdXRyb3Mvc2ZqcV90ZW1wL3RyZWVzL3NmanEtQVNWc192c19PVFVzLnBkZiIsCiAgICAgcGxvdCA9IEFTVnNfbl9PVFVTX3Bsb3QsCiAgICAgZGV2aWNlID0gInBkZiIsCiAgICAgd2lkdGggPSAxNCwKICAgICBoZWlnaHQgPSAxMCwKICAgICBkcGkgPSA2MDApCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3Mvc2ZqcS1BU1ZzX3ZzX09UVXMuc3ZnIiwKICAgICBwbG90ID0gQVNWc19uX09UVVNfcGxvdCwKICAgICBkZXZpY2UgPSAic3ZnIiwKICAgICB3aWR0aCA9IDE0LAogICAgIGhlaWdodCA9IDEwLAogICAgIGRwaSA9IDYwMCkKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9zZmpxLUFTVnNfdnNfT1RVcy5wbmciLAogICAgIHBsb3QgPSBBU1ZzX25fT1RVU19wbG90LAogICAgIGRldmljZSA9ICJwbmciLAogICAgIHdpZHRoID0gMTYsCiAgICAgaGVpZ2h0ID0gMTAsCiAgICAgZHBpID0gNjAwKQoKCmBgYAoKIyMgRm9sZC1jaGFuZ2UgYmFyIHBsb3RzCgpgYGB7ciwgZXZhbCA9IEZBTFNFLCBlY2hvPUZBTFNFfQojIEZvbGQtY2hhbmdlIHBsb3RzIC0tLS0KCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjZm9sZCBjaGFuZ2UgcGxvdHMgLS0tLQojcGxvdHMgd2l0aCBtaXJyb3JlZCB4IGF4aXMsIHdpdGggbG9nIHZhbHVlcwpsaWJyYXJ5KCJnZ2FsbGluIikKI0pRbWMgLS0tLQogICA8LQogIGpxX3Byb3BvcnRpb25zICU+JSAKICBtdXRhdGUoUHJpbWVyID0gZmFjdG9yKFByaW1lciwgbGV2ZWxzID0gYygiTmVvRmlzaCIsICJNaUZpc2giLCAiVGVsZW8iLCAiTmVvRmlzaC9NaUZpc2giLCAiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKSkpICU+JSAKICBmaWx0ZXIoYEV4cGVjdGVkIFNwZWNpZXNgICVpbiUgYygiZXhwZWN0ZWQiKSkgJT4lCiAgbXV0YXRlKGZvbGRfY2hhbmdlID0gZ3Rvb2xzOjpmb2xkY2hhbmdlKGRlbm9tID0gUHJvcG9ydGlvbixudW0gPSBgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApKSAlPiUKICAjIG11dGF0ZShmb2xkX2NoYW5nZSA9IGd0b29sczo6Zm9sZGNoYW5nZTJsb2dyYXRpbyhmb2xkY2hhbmdlID0gZ3Rvb2xzOjpmb2xkY2hhbmdlKGRlbm9tID0gUHJvcG9ydGlvbixudW0gPSBgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApKSxiYXNlPTIpICU+JSAKICAjIG11dGF0ZShgZmluYWwgSURgID0gZmFjdG9yKGBmaW5hbCBJRGApKSAlPiUgCiAgbXV0YXRlKGByZXZpc2VkIGZpbmFsIElEYCA9IGZhY3RvcihgcmV2aXNlZCBmaW5hbCBJRGApKSAlPiUgCiAgZ2dwbG90KGFlcyh4PSBmb2xkX2NoYW5nZSwKICAgICAgICAgICAgIHk9IGByZXZpc2VkIGZpbmFsIElEYCwgZmlsbCA9IFByaW1lciwgYWxwaGEgPSBQb29sKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgIHBvc2l0aW9uID1wb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAic2luZ2xlIikpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yc19ub3JtW2MoMSwzLDUpXSkrCiAgc2NhbGVfYWxwaGFfbWFudWFsKHZhbHVlcyA9IGMoMC40LCAwLjkpLGxhYmVscyA9IGMoIk5vbi1ub3JtYWxpemVkIHBvb2wiLCJOb3JtYWxpemVkIHBvb2wiKSkrCiAgeWxhYigiU3BlY2llcyIpICsKICB4bGFiKCJQcm9wb3J0aW9uIG9mIHJlYWRzIGRpdmlkZWQgYnkgcHJvcG9ydGlvbiBvZiBpbnB1dCBETkEgaW4gSlFtYyIpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gZ2dhbGxpbjo6cHNldWRvbG9nMTBfdHJhbnMsCiAgYnJlYWtzID0gYygtMzAwMCwtMjAwMCwtMTAwMCwtNTAwLC0xMDAsLTUwLC0xMCwtNSwtMSwwLDEsNSwxMCw1MCwxMDAsNTAwLDEwMDAsMjAwMCkpICsKICB0aGVtZV9saW5lZHJhdyhiYXNlX3NpemUgPSAxNSkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xLDEpLGxpbmV0eXBlPTIsc2l6ZT0wLjI1KSAgKwogIGZhY2V0X3dyYXAoflByaW1lcixuY29sID0gMSkgKwogIGFubm90YXRlKGdlb20gPSAicmVjdCIsCiAgeG1pbj1jKC0xKSwgeG1heD1jKDEpLAogIHltaW49YygwLjUpLCB5bWF4PWMoMTcuNSksCiAgYWxwaGE9MC4xLGZpbGw9IiMwMDAwMDAiKQoKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9TRkpRX3Byb3BfanFfZm9sZGNoYW5nZS5wbmciLAogICAgICAgcGxvdCA9IGpxX3BvcnBfcGxvdCwKICAgICAgIGRldmljZSA9ICJwbmciLAogICAgICAgd2lkdGggPSAxNCwKICAgICAgIGhlaWdodCA9IDEyLAogICAgICAgZHBpID0gMzAwKQpqcV9wcm9wb3J0aW9ucyRgZmluYWwgSURgICU+JSB1bmlxdWUoKQoKI1NGbWMgLS0tLQpzZl9wb3JwX3Bsb3QgPC0KICBzZl9wcm9wb3J0aW9ucyAlPiUgCiAgbXV0YXRlKFByaW1lciA9IGZhY3RvcihQcmltZXIsIGxldmVscyA9IGMoIk5lb0Zpc2giLCAiTWlGaXNoIiwgIlRlbGVvIiwgIk5lb0Zpc2gvTWlGaXNoIiwgIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIikpKSAlPiUgCiAgZmlsdGVyKGBFeHBlY3RlZCBTcGVjaWVzYCAlaW4lIGMoImV4cGVjdGVkIikpICU+JQogIG11dGF0ZShmb2xkX2NoYW5nZSA9IGd0b29sczo6Zm9sZGNoYW5nZShkZW5vbSA9IFByb3BvcnRpb24sbnVtID0gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKSkgJT4lIAogIG11dGF0ZShgZmluYWwgSURgID0gZmFjdG9yKGBmaW5hbCBJRGApKSAlPiUgCiAgZ2dwbG90KGFlcyh4PSBmb2xkX2NoYW5nZSwKICAgICAgICAgICAgIHk9IGBmaW5hbCBJRGAsIGZpbGwgPSBQcmltZXIsIGFscGhhID0gUG9vbCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBwb3NpdGlvbiA9cG9zaXRpb25fZG9kZ2UyKHByZXNlcnZlID0gInNpbmdsZSIpKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfbm9ybVtjKDEsMyw1KV0pKwogIHNjYWxlX2FscGhhX21hbnVhbCh2YWx1ZXMgPSBjKDAuNCwgMC45KSxsYWJlbHMgPSBjKCJOb24tbm9ybWFsaXplZCBwb29sIiwiTm9ybWFsaXplZCBwb29sIikpKwogIHlsYWIoIlNwZWNpZXMiKSArCiAgeGxhYigiUHJvcG9ydGlvbiBvZiByZWFkcyBkaXZpZGVkIGJ5IHByb3BvcnRpb24gb2YgaW5wdXQgRE5BIGluIEpRbWMiKSArIAogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9IGdnYWxsaW46OnBzZXVkb2xvZzEwX3RyYW5zLAogIGJyZWFrcyA9IGMoLTMwMDAsLTIwMDAsLTEwMDAsLTUwMCwtMTAwLC01MCwtMTAsLTUsLTEsMCwxLDUsMTAsNTAsMTAwLDUwMCwxMDAwLDIwMDApKSArCiAgdGhlbWVfbGluZWRyYXcoYmFzZV9zaXplID0gMTUpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygtMSwxKSxsaW5ldHlwZT0yLHNpemU9MC4yNSkgICsKICBmYWNldF93cmFwKH5QcmltZXIsbmNvbCA9IDEpICsKICBhbm5vdGF0ZShnZW9tID0gInJlY3QiLAogIHhtaW49YygtMSksIHhtYXg9YygxKSwKICB5bWluPWMoMC41KSwgeW1heD1jKDIzLjUpLAogIGFscGhhPTAuMSxmaWxsPSIjMDAwMDAwIikKICAKICAKCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvU0ZKUV9wcm9wX3NmX2ZvbGRjaGFuZ2UucG5nIiwKICAgICBwbG90ID0gc2ZfcG9ycF9wbG90LAogICAgIGRldmljZSA9ICJwbmciLAogICAgIHdpZHRoID0gMTQsCiAgICAgaGVpZ2h0ID0gMTAsCiAgICAgZHBpID0gMzAwKQojb2xkIG9uZGVzIHdpdGhvdXQgbWlycm9yZWQgYXhpcyAtLS0tCiMgSlFtYyAtLS0tCiNwcm9wb3J0aW9ucwpqcV9wb3JwX3Bsb3QgPC0KICBqcV9wcm9wb3J0aW9ucyAlPiUgCiAgbXV0YXRlKFByaW1lciA9IGZhY3RvcihQcmltZXIsIGxldmVscyA9IGMoIk5lb0Zpc2giLCAiTWlGaXNoIiwgIlRlbGVvIiwgIk5lb0Zpc2gvTWlGaXNoIiwgIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIikpKSAlPiUgCiAgZmlsdGVyKGBFeHBlY3RlZCBTcGVjaWVzYCAlaW4lIGMoImV4cGVjdGVkIikpICU+JQogICMgZ2dwbG90KGFlcyh4PSBhcy5udW1lcmljKChgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAvUHJvcG9ydGlvbikpLAogICAgIyBnZ3Bsb3QoYWVzKHg9IGd0b29sczo6Zm9sZGNoYW5nZShkZW5vbSA9IFByb3BvcnRpb24sbnVtID0gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKSwKICBnZ3Bsb3QoYWVzKHg9IGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYC9Qcm9wb3J0aW9uLAogICMgZ2dwbG90KGFlcyh4PSBmb2xkX2NoYW5nZSwKICAgICAgICAgICAgIHk9IGBmaW5hbCBJRGAsIGZpbGwgPSBQcmltZXIsIGFscGhhID0gUG9vbAogICAgICAgICAgICAgKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLAogICAgcG9zaXRpb24gPXBvc2l0aW9uX2RvZGdlMihwcmVzZXJ2ZSA9ICJzaW5nbGUiKQogICAgICAgICAgICkrCiAgIyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzAwMDAwZiIsIiM5Njk1OTUiKSwKICAjICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJOb24tbm9ybWFsaXplZCIsIk5vcm1hbGl6ZWQiKSkrCiAgIyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBhbHBoYShjb2xvdXIgPSBjb2xvcnNfbm9ybSAsYWxwaGEgPSAgMC44KSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JzX25vcm1bYygxLDMsNSldKSsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjQsIDAuOSksbGFiZWxzID0gYygiTm9uLW5vcm1hbGl6ZWQgcG9vbCIsIk5vcm1hbGl6ZWQgcG9vbCIpKSsKICB5bGFiKCJTcGVjaWVzIikgKwogICMgc2NhbGVfeF9icmVhayhjKDIwLCA4MCkpICsKICAjIHhsaW0oYygwLDIwKSkrCiAgeGxhYigiUHJvcG9ydGlvbiBvZiByZWFkcyBkaXZpZGVkIGJ5IHByb3BvcnRpb24gb2YgaW5wdXQgRE5BIGluIEpRbWMiKSArCiAgc2NhbGVfeF9zcXJ0KGJyZWFrcz1jKDAuMDI1LDAuMSwwLjI1LDAuNSwxLDIsMyw0LDUsNiw3LDgsMTAsMTIsMTQpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSxsaW5ldHlwZT0yLHNpemU9MC41KSAgKwogIGZhY2V0X3dyYXAoflByaW1lcixuY29sID0gMSkKCgogZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL1NGSlFfcHJvcF9qcS5wbmciLAogICAgIHBsb3QgPSBqcV9wb3JwX3Bsb3QsCiAgICAgZGV2aWNlID0gInBuZyIsCiAgICAgd2lkdGggPSAxMiwKICAgICBoZWlnaHQgPSA4LAogICAgIGRwaSA9IDMwMCkKCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvU0ZKUV9wcm9wX2pxLnBkZiIsCiAgICAgcGxvdCA9IGpxX3BvcnBfcGxvdCwKICAgICBkZXZpY2UgPSAicGRmIiwKICAgICB3aWR0aCA9IDEyLAogICAgIGhlaWdodCA9IDgsCiAgICAgZHBpID0gMzAwKQoKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9TRkpRX3Byb3BfanEuc3ZnIiwKICAgICBwbG90ID0ganFfcG9ycF9wbG90LAogICAgIGRldmljZSA9ICJzdmciLAogICAgIHdpZHRoID0gMTIsCiAgICAgaGVpZ2h0ID0gOCwKICAgICBkcGkgPSAzMDApCgoKCgoKIyBTRm1jIC0tLS0KI3Byb3BvcnRpb25zCnNmX3BvcnBfcGxvdCA8LQogIHNmX3Byb3BvcnRpb25zICU+JSAKICBtdXRhdGUoUHJpbWVyID0gZmFjdG9yKFByaW1lciwgbGV2ZWxzID0gYygiTmVvRmlzaCIsICJNaUZpc2giLCAiVGVsZW8iLCAiTmVvRmlzaC9NaUZpc2giLCAiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKSkpICU+JSAKICBmaWx0ZXIoYEV4cGVjdGVkIFNwZWNpZXNgICVpbiUgYygiZXhwZWN0ZWQiKSkgJT4lIAogIGdncGxvdChhZXMoeD0gYXMubnVtZXJpYygoYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgL1Byb3BvcnRpb24pKSwKICAgICAgICAgICAgIHk9IGBmaW5hbCBJRGAsIGZpbGwgPSBQcmltZXIsIGFscGhhID0gUG9vbAogICAgICAgICAgICAgKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLAogICAgcG9zaXRpb24gPXBvc2l0aW9uX2RvZGdlMihwcmVzZXJ2ZSA9ICJzaW5nbGUiKQogICAgICAgICAgICkrCiAgIyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzAwMDAwZiIsIiM5Njk1OTUiKSwKICAjICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJOb24tbm9ybWFsaXplZCIsIk5vcm1hbGl6ZWQiKSkrCiAgIyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBhbHBoYShjb2xvdXIgPSBjb2xvcnNfbm9ybSAsYWxwaGEgPSAgMC44KSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JzX25vcm1bYygxLDMsNSldKSsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjQsIDAuOSksbGFiZWxzID0gYygiTm9uLW5vcm1hbGl6ZWQgcG9vbCIsIk5vcm1hbGl6ZWQgcG9vbCIpKSsKICB5bGFiKCJTcGVjaWVzIikgKwogICMgc2NhbGVfeF9icmVhayhjKDYsIDQwKSkgKwogICMgeGxpbShjKDAsMjApKSsKICB4bGFiKCJQcm9wb3J0aW9uIG9mIHJlYWRzIGRpdmlkZWQgYnkgcHJvcG9ydGlvbiBvZiBpbnB1dCBETkEgaW4gU0ZtYyIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLGxpbmV0eXBlPTIsc2l6ZT0wLjUpICArCiAgc2NhbGVfeF9zcXJ0KGJyZWFrcz1jKDAuMDI1LDAuMSwwLjI1LDAuNSwxLDIsMyw0LDUsNiw3LDgsMTAsMTIpKSArCiAgZmFjZXRfd3JhcCh+UHJpbWVyLG5jb2wgPSAxKSAKCgoKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL1NGSlFfcHJvcF9zZi5wbmciLAogICAgIHBsb3QgPSBzZl9wb3JwX3Bsb3QsCiAgICAgZGV2aWNlID0gInBuZyIsCiAgICAgd2lkdGggPSAxMiwKICAgICBoZWlnaHQgPSA2LAogICAgIGRwaSA9IDMwMCkKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9TRkpRX3Byb3Bfc2YucGRmIiwKICAgICBwbG90ID0gc2ZfcG9ycF9wbG90LAogICAgIGRldmljZSA9ICJwZGYiLAogICAgIHdpZHRoID0gMTIsCiAgICAgaGVpZ2h0ID0gNiwKICAgICBkcGkgPSAzMDApCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvU0ZKUV9wcm9wX3NmLnN2ZyIsCiAgICAgcGxvdCA9IHNmX3BvcnBfcGxvdCwKICAgICBkZXZpY2UgPSAic3ZnIiwKICAgICB3aWR0aCA9IDEyLAogICAgIGhlaWdodCA9IDgsCiAgICAgZHBpID0gMzAwKQoKIyBhbGxfcHNfdGJsX2JsYXN0JE9UVVthbGxfcHNfdGJsX2JsYXN0JGBmaW5hbCBJRGAgPT0iVGV0cmFnb25vcHRlcnVzIGNoYWxjZXVzIl0gJT4lIHVuaXF1ZSgpCiMgCiMgYWxsX3BzX3RibF9ibGFzdCRgZmluYWwgSURgW2FsbF9wc190YmxfYmxhc3QkT1RVICVpbiUgYyg3LDksODcsODgsOTMsMTMyKV0KCgojIFNGSlFtYyAtLS0tCiNwcm9wb3J0aW9ucwpzZl9wb3JwX3Bsb3QgPC0KICBzZmpxX3Byb3BvcnRpb25zICU+JSAKICBtdXRhdGUoUHJpbWVyID0gZmFjdG9yKFByaW1lciwgbGV2ZWxzID0gYygiTmVvRmlzaCIsICJNaUZpc2giLCAiVGVsZW8iLCAiTmVvRmlzaC9NaUZpc2giLCAiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKSkpICU+JSAKICAgICMgbXV0YXRlKFByb3BvcnRpb24gPSA0LjM1KSAlPiUgCiAgZmlsdGVyKGBFeHBlY3RlZCBTcGVjaWVzYCAlaW4lIGMoImV4cGVjdGVkIikpICU+JQogIGdncGxvdChhZXMoeD0gYXMubnVtZXJpYyhgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAvUHJvcG9ydGlvbiksCiAgICAgICAgICAgICB5PSBgZmluYWwgSURgLCBmaWxsID0gUHJpbWVyLGFscGhhID0gUG9vbAogICAgICAgICAgICAgKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLAogICAgIyBwb3NpdGlvbiA9cG9zaXRpb25fZG9kZ2UyKHByZXNlcnZlID0gInNpbmdsZSIpCiAgICBwb3NpdGlvbiA9ICJkb2RnZSIKICAgICkrCiAgIyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzAwMDAwZiIsIiM5Njk1OTUiKSwKICAjICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJOb24tbm9ybWFsaXplZCIsIk5vcm1hbGl6ZWQiKSkrCiAgIyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBhbHBoYShjb2xvdXIgPSBjb2xvcnNfbm9ybSAsYWxwaGEgPSAgMC44KSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JzX25vcm1bYygxLDMsNSldKSsKICBzY2FsZV9hbHBoYV9tYW51YWwobmFtZSA9IE5VTEwsIHZhbHVlcyA9IGMoMC45KSxsYWJlbHMgPSBOVUxMLGd1aWRlID0gTlVMTCkrCiAgIyBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjQsIDAuOSksCiAgIyAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTm9uLW5vcm1hbGl6ZWQgcG9vbCIsIk5vcm1hbGl6ZWQgcG9vbCIpKSsKICB5bGFiKCJTcGVjaWVzIikgKwogICMgc2NhbGVfeF9icmVhayhjKDcuNSwgNDApKSArCiAgIyB4bGltKGMoMCw0MCkpKwogIHhsYWIoIlByb3BvcnRpb24gb2YgQVNWcyBpbiBzYW1wbGUgZGl2aWRlZCBieSBwcm9wb3J0aW9uIG9mIEROQSBpbnB1dCBpbiBTRkpRbWMiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSxsaW5ldHlwZT0yKSAgKwogIGZhY2V0X3dyYXAoflByaW1lcixuY29sID0gMSkKCgoKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9TRkpRX3Byb3Bfc2ZqcS5wbmciLAogICAgIHBsb3QgPSBzZmpxX3BvcnBfcGxvdCwKICAgICBkZXZpY2UgPSAicG5nIiwKICAgICB3aWR0aCA9IDEyLAogICAgIGhlaWdodCA9IDgsCiAgICAgZHBpID0gMzAwKQoKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL1NGSlFfcHJvcF9zZmpxLnBkZiIsCiAgICAgcGxvdCA9IHNmanFfcG9ycF9wbG90LAogICAgIGRldmljZSA9ICJwZGYiLAogICAgIHdpZHRoID0gMTIsCiAgICAgaGVpZ2h0ID0gOCwKICAgICBkcGkgPSAzMDApCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvU0ZKUV9wcm9wX3NmanEuc3ZnIiwKICAgICBwbG90ID0gc2ZqcV9wb3JwX3Bsb3QsCiAgICAgZGV2aWNlID0gInN2ZyIsCiAgICAgd2lkdGggPSAxMiwKICAgICBoZWlnaHQgPSA4LAogICAgIGRwaSA9IDMwMCkKCgoKCgoKCmFsbF9wc190YmxfYmxhc3QgJT4lIAogIHNlbGVjdChQcmltZXIsT1RVLGByZXZpc2VkIGZpbmFsIElEYCkgJT4lIHVuaXF1ZSgpICU+JSBWaWV3KCkKCgpgYGAKCgoKCgojI1ZlbiBkaWFncmFtCgpgYGB7ciBlY2hvPUZBTFNFLGV2YWw9RkFMU0V9CnsKCiAgCiAgI05lb0Zpc2gKbmVvX2xpc3RfU0Zfbm9ybSA8LSBzZl9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbc2ZfcHJvcG9ydGlvbnMkUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb3JtIHBvb2wiKSAmICghaXMubmEoc2ZfcHJvcG9ydGlvbnMkUHJvcG9ydGlvbikpICYgc2ZfcHJvcG9ydGlvbnMkUHJpbWVyICVpbiUgYygiTmVvRmlzaCIpXSAlPiUgdW5pcXVlKCkgJT4lIGxpc3QoKQpuYW1lcyhuZW9fbGlzdF9TRl9ub3JtKSA8LSAiTmVvRmlzaCAtIHBvb2wgU0YgLSBOb3JtYWxpemVkIgoKCm5lb19saXN0X0pRX25vcm0gPC0ganFfcHJvcG9ydGlvbnMkYHJldmlzZWQgZmluYWwgSURgW2pxX3Byb3BvcnRpb25zJFBvb2wgJWluJSBjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9ybSBwb29sIikgJiAoIWlzLm5hKGpxX3Byb3BvcnRpb25zJFByb3BvcnRpb24pKSAmIGpxX3Byb3BvcnRpb25zJFByaW1lciAlaW4lIGMoIk5lb0Zpc2giKV0gJT4lIHVuaXF1ZSgpICU+JSBsaXN0KCkKbmFtZXMobmVvX2xpc3RfSlFfbm9ybSkgPC0gIk5lb0Zpc2ggLSBwb29sIEpRIC0gTm9ybWFsaXplZCIKCgpuZW9fbGlzdF9TRkpRX25vcm0gPC0gc2ZqcV9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbc2ZqcV9wcm9wb3J0aW9ucyRQb29sICVpbiUgYygiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbCIpICYgKCFpcy5uYShzZmpxX3Byb3BvcnRpb25zJFByb3BvcnRpb24pKSAmIHNmanFfcHJvcG9ydGlvbnMkUHJpbWVyICVpbiUgYygiTmVvRmlzaCIpXSAlPiUgdW5pcXVlKCkgJT4lIGxpc3QoKQpuYW1lcyhuZW9fbGlzdF9TRkpRX25vcm0pIDwtICJOZW9GaXNoIC0gcG9vbCBTRkpRIC0gTm9ybWFsaXplZCIKCgoKbmVvX2xpc3RfU0ZfTm5vcm0gPC0gc2ZfcHJvcG9ydGlvbnMkYHJldmlzZWQgZmluYWwgSURgW3NmX3Byb3BvcnRpb25zJFBvb2wgJWluJSBjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbCIpICYgKCFpcy5uYShzZl9wcm9wb3J0aW9ucyRQcm9wb3J0aW9uKSkgJiBzZl9wcm9wb3J0aW9ucyRQcmltZXIgJWluJSBjKCJOZW9GaXNoIildICU+JSB1bmlxdWUoKSAlPiUgbGlzdCgpCm5hbWVzKG5lb19saXN0X1NGX05ub3JtKSA8LSAiTmVvRmlzaCAtIHBvb2wgU0YgLSBOb24tbm9ybWFsaXplZCIKCgpuZW9fbGlzdF9KUV9Obm9ybSA8LSBqcV9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbanFfcHJvcG9ydGlvbnMkUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sIikgJiAoIWlzLm5hKGpxX3Byb3BvcnRpb25zJFByb3BvcnRpb24pKSAmIGpxX3Byb3BvcnRpb25zJFByaW1lciAlaW4lIGMoIk5lb0Zpc2giKV0gJT4lIHVuaXF1ZSgpICU+JSBsaXN0KCkKbmFtZXMobmVvX2xpc3RfSlFfTm5vcm0pIDwtICJOZW9GaXNoIC0gcG9vbCBKUSAtIE5vbi1ub3JtYWxpemVkIgoKCgojTWlGaXNoCm1pZl9saXN0X1NGX25vcm0gPC0gc2ZfcHJvcG9ydGlvbnMkYHJldmlzZWQgZmluYWwgSURgW3NmX3Byb3BvcnRpb25zJFBvb2wgJWluJSBjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9ybSBwb29sIikgJiAoIWlzLm5hKHNmX3Byb3BvcnRpb25zJFByb3BvcnRpb24pKSAmIHNmX3Byb3BvcnRpb25zJFByaW1lciAlaW4lIGMoIk1pRmlzaCIpXSAlPiUgdW5pcXVlKCkgJT4lIGxpc3QoKQpuYW1lcyhtaWZfbGlzdF9TRl9ub3JtKSA8LSAiTWlGaXNoIC0gcG9vbCBTRiAtIE5vcm1hbGl6ZWQiCgoKbWlmX2xpc3RfSlFfbm9ybSA8LSBqcV9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbanFfcHJvcG9ydGlvbnMkUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb3JtIHBvb2wiKSAmICghaXMubmEoanFfcHJvcG9ydGlvbnMkUHJvcG9ydGlvbikpICYganFfcHJvcG9ydGlvbnMkUHJpbWVyICVpbiUgYygiTWlGaXNoIildICU+JSB1bmlxdWUoKSAlPiUgbGlzdCgpCm5hbWVzKG1pZl9saXN0X0pRX25vcm0pIDwtICJNaUZpc2ggLSBwb29sIEpRIC0gTm9ybWFsaXplZCIKCgptaWZfbGlzdF9TRkpRX25vcm0gPC0gc2ZqcV9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbc2ZqcV9wcm9wb3J0aW9ucyRQb29sICVpbiUgYygiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbCIpICYgKCFpcy5uYShzZmpxX3Byb3BvcnRpb25zJFByb3BvcnRpb24pKSAmIHNmanFfcHJvcG9ydGlvbnMkUHJpbWVyICVpbiUgYygiTWlGaXNoIildICU+JSB1bmlxdWUoKSAlPiUgbGlzdCgpCm5hbWVzKG1pZl9saXN0X1NGSlFfbm9ybSkgPC0gIk1pRmlzaCAtIHBvb2wgU0ZKUSAtIE5vcm1hbGl6ZWQiCgoKCgptaWZfbGlzdF9TRl9Obm9ybSA8LSBzZl9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbc2ZfcHJvcG9ydGlvbnMkUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sIikgJiAoIWlzLm5hKHNmX3Byb3BvcnRpb25zJFByb3BvcnRpb24pKSAmIHNmX3Byb3BvcnRpb25zJFByaW1lciAlaW4lIGMoIk1pRmlzaCIpXSAlPiUgdW5pcXVlKCkgJT4lIGxpc3QoKQpuYW1lcyhtaWZfbGlzdF9TRl9Obm9ybSkgPC0gIk1pRmlzaCAtIHBvb2wgU0YgLSBOb24tbm9ybWFsaXplZCIKCgptaWZfbGlzdF9KUV9Obm9ybSA8LSBqcV9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbanFfcHJvcG9ydGlvbnMkUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sIikgJiAoIWlzLm5hKGpxX3Byb3BvcnRpb25zJFByb3BvcnRpb24pKSAmIGpxX3Byb3BvcnRpb25zJFByaW1lciAlaW4lIGMoIk1pRmlzaCIpXSAlPiUgdW5pcXVlKCkgJT4lIGxpc3QoKQpuYW1lcyhtaWZfbGlzdF9KUV9Obm9ybSkgPC0gIk1pRmlzaCAtIHBvb2wgSlEgLSBOb24tbm9ybWFsaXplZCIKCgoKCiN0ZWxlbwoKdGVsX2xpc3RfSlFfbm9ybSA8LSBqcV9wcm9wb3J0aW9ucyRgcmV2aXNlZCBmaW5hbCBJRGBbanFfcHJvcG9ydGlvbnMkUG9vbCAlaW4lIGMoIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb3JtIHBvb2wiKSAmICghaXMubmEoanFfcHJvcG9ydGlvbnMkUHJvcG9ydGlvbikpICYganFfcHJvcG9ydGlvbnMkUHJpbWVyICVpbiUgYygiVGVsZW8iKV0gJT4lIHVuaXF1ZSgpICU+JSBsaXN0KCkKbmFtZXModGVsX2xpc3RfSlFfbm9ybSkgPC0gIlRlbGVvIC0gcG9vb2wgSlEgLSBOb3JtYWxpemVkIgoKCnRlbF9saXN0X0pRX05ub3JtIDwtIGpxX3Byb3BvcnRpb25zJGByZXZpc2VkIGZpbmFsIElEYFtqcV9wcm9wb3J0aW9ucyRQb29sICVpbiUgYygiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2wiKSAmICghaXMubmEoanFfcHJvcG9ydGlvbnMkUHJvcG9ydGlvbikpICYganFfcHJvcG9ydGlvbnMkUHJpbWVyICVpbiUgYygiVGVsZW8iKV0gJT4lIHVuaXF1ZSgpICU+JSBsaXN0KCkKbmFtZXModGVsX2xpc3RfSlFfTm5vcm0pIDwtICJUZWxlbyAtIHBvb29sIEpRIC0gTm9uLW5vcm1hbGl6ZWQiCgoKfQoKIyBzcHNfcGVyX3Bvb2wgPC0gYyhuZW9fbGlzdF9TRl9ub3JtLCBuZW9fbGlzdF9KUV9ub3JtLCBuZW9fbGlzdF9TRkpRX25vcm0sIG5lb19saXN0X1NGX05ub3JtLCBuZW9fbGlzdF9KUV9Obm9ybSwgCiMgICBtaWZfbGlzdF9TRl9ub3JtLCBtaWZfbGlzdF9KUV9ub3JtLCBtaWZfbGlzdF9TRkpRX25vcm0sIG1pZl9saXN0X1NGX05ub3JtLCBtaWZfbGlzdF9KUV9Obm9ybSwgCiMgICB0ZWxfbGlzdF9KUV9ub3JtLCB0ZWxfbGlzdF9KUV9Obm9ybSkKCiNKUQogIGFsbF9zcHNfSlEgPC0gYyhjKG5lb19saXN0X0pRX25vcm0sbmVvX2xpc3RfSlFfTm5vcm0sIG1pZl9saXN0X0pRX25vcm0sIG1pZl9saXN0X0pRX05ub3JtLCB0ZWxfbGlzdF9KUV9ub3JtLCB0ZWxfbGlzdF9KUV9Obm9ybSkgJT4lIHVubGlzdCgpICU+JSB1bmlxdWUoKSwiUHJvY2hpbG9kdXMgaGFydGlpIikgJT4lIHNvcnQoKSAlPiUgbGlzdCgpCiAgbmFtZXMoYWxsX3Nwc19KUSkgPC0gIkpRIG9yaWdpbmFsIHNwZWNpZXMiCiNTRgogIGFsbF9zcHNfU0YgPC0gYyhuZW9fbGlzdF9TRl9ub3JtLCBuZW9fbGlzdF9TRl9Obm9ybSwgbWlmX2xpc3RfU0Zfbm9ybSwgbWlmX2xpc3RfU0ZfTm5vcm0pICU+JSB1bmxpc3QoKSAlPiUgdW5pcXVlKCkgJT4lIHNvcnQoKSAlPiUgbGlzdCgpCgogIG5hbWVzKGFsbF9zcHNfU0YpIDwtICJTRiBvcmlnaW5hbCBzcGVjaWVzIgogIAogI1NGSlEgCiAgYWxsX3Nwc19TRkpRIDwtIGMoYyhuZW9fbGlzdF9TRl9ub3JtLCBuZW9fbGlzdF9KUV9ub3JtLCBuZW9fbGlzdF9TRkpRX25vcm0sIG5lb19saXN0X1NGX05ub3JtLCBuZW9fbGlzdF9KUV9Obm9ybSwgCiAgbWlmX2xpc3RfU0Zfbm9ybSwgbWlmX2xpc3RfSlFfbm9ybSwgbWlmX2xpc3RfU0ZKUV9ub3JtLCBtaWZfbGlzdF9TRl9Obm9ybSwgbWlmX2xpc3RfSlFfTm5vcm0sIAogIHRlbF9saXN0X0pRX25vcm0sIHRlbF9saXN0X0pRX05ub3JtKSAlPiUgdW5saXN0KCkgJT4lIHVuaXF1ZSgpLCJQcm9jaGlsb2R1cyBoYXJ0aWkiKSAlPiUgc29ydCgpICU+JSBsaXN0KCkKCiAgbmFtZXMoYWxsX3Nwc19TRkpRKSA8LSAiU0ZKUSBvcmlnaW5hbCBzcGVjaWVzIgogIAojU0Zfbm9ybQoKCnNhcHBseShzcHNfcGVyX3Bvb2wsIGxlbmd0aCkKCgojdmVubiBkaWFncmFtIC0tLS0KCnNmX25vcm1fdmVubiA8LSBjKGFsbF9zcHNfU0YsbmVvX2xpc3RfU0Zfbm9ybSxtaWZfbGlzdF9TRl9ub3JtKQoKYWxsX3Nwc19TRkpRICU+JSB1bmxpc3QoKSAlPiUgcGFzdGUwKGNvbGxhcHNlID0gIlxuIikgJT4lIGNhdCgpCm5lb19saXN0X1NGX25vcm0gJT4lIHVubGlzdCgpICAlPiUgcGFzdGUwKGNvbGxhcHNlID0gIiwiKQptaWZfbGlzdF9TRl9ub3JtICU+JSB1bmxpc3QoKSAgJT4lIHBhc3RlMChjb2xsYXBzZSA9ICIsIikKCmxpYnJhcnkobWFkZTQpCgoKCgp6IDwtIGNvbXBhcmVsaXN0cyh1bmxpc3QoYWxsX3Nwc19KUSksdW5saXN0KHRlbF9saXN0X0pRX25vcm0pKQoKeiA8LSBjb21wYXJlbGlzdHModW5saXN0KGFsbF9zcHNfU0ZKUSksdW5saXN0KG1pZl9saXN0X1NGSlFfbm9ybSkseD0iU2V0LkRpZmYiKQp6JFNldC5EaWZmCgoKaW50ZXJzZWN0KGFsbF9zcHNfU0YsbmVvX2xpc3RfU0Zfbm9ybSkKCgpsaWJyYXJ5KGdndmVubikKZ2d2ZW5uKHNmX25vcm1fdmVubixzdHJva2VfY29sb3I9IlJlZCIsCiAgICAgICBzdHJva2VfbGluZXR5cGU9InNvbGlkIixzaG93X2VsZW1lbnRzID0gVFJVRSwgIGxhYmVsX3NlcCA9ICJcbiIpCgoKCmBgYAoKCgoKCiMjVXBzZXQgcGxvdAoKYGBge3IgZWNobz1GQUxTRSxldmFsPUZBTFNFfQoKCnNmanFfc3BzX2xpc3QgPC0gYWxsX3BzX3RibF9zZmpxX2Z1bGwgJT4lCiAgZHBseXI6Omdyb3VwX3NwbGl0KFNhbXBsZSkgJT4lCiAgcHVycnI6Om1hcCh+IC54ICU+JSBkcGx5cjo6cHVsbChgZmluYWwgSURgKSkKCm5hbWVzKHNmanFfc3BzX2xpc3QpIDwtIHVuaXF1ZShhbGxfcHNfdGJsX3NmanFfZnVsbCRTYW1wbGUpCgoKCgpzZmpxX3Nwc19saXN0IDwtIGFsbF9wc190Ymxfc2ZqcV9mdWxsICU+JQogIGRwbHlyOjpncm91cF9zcGxpdChgZmluYWwgSURgKSAlPiUKICBwdXJycjo6bWFwKH4gLnggJT4lIGRwbHlyOjpwdWxsKFNhbXBsZSkpCgpuYW1lcyhzZmpxX3Nwc19saXN0KSA8LSB1bmlxdWUoYWxsX3BzX3RibF9zZmpxX2Z1bGwkYGZpbmFsIElEYCkKCgpzZmpxX3Nwc19saXN0ICU+JSBzdHIoKQoKbGlicmFyeSgiVXBTZXRSIikKCgpsZW5ndGgoc2ZqcV9zcHNfbGlzdCkKClVwU2V0Ujo6dXBzZXQoVXBTZXRSOjpmcm9tTGlzdChzZmpxX3Nwc19saXN0KSwgb3JkZXIuYnkgPSAiZnJlcSIsbnNldHMgPSBsZW5ndGgoc2ZqcV9zcHNfbGlzdCksbmludGVyc2VjdHMgPSAxMDApClVwU2V0Ujo6dXBzZXQoVXBTZXRSOjpmcm9tTGlzdChzZmpxX3Nwc19saXN0KSwgb3JkZXIuYnkgPSAiZnJlcSIsbnNldHMgPSBsZW5ndGgoc2ZqcV9zcHNfbGlzdCksbmludGVyc2VjdHMgPSAxMDApCgpnZW5vbWVzX29ydGhzX2RmICU+JSBwaGVhdG1hcDo6cGhlYXRtYXAoKQoKZ2Vub21lc19vcnRoc19kZiAlPiUgY29sU3VtcygpICU+JSB0YWJsZSgpICU+JSBwbG90KCkKCmBgYAoKCgpgYGB7ciBlY2hvPUZBTFNFLGV2YWw9RkFMU0V9CiNwbG90cyBvZiBpZGVudGlmaWVkIHNwZWNpZXMgZGV0ZWN0ZWQgZm9yIGVhY2ggcG9vbCAKI0pRIGxldmVscy0tLS0KCmFsbF9wc190Ymxfc2ZqcV9mdWxsJGBmaW5hbCBJRGAgJT4lIGJhc2U6OnNvcnQoKSAlPiUgdW5pcXVlKCkgJT4lIHBhc3RlMChjb2xsYXBzZSA9ICciLFxuIicpICU+JSBjYXQoKQoKewogIGZpbmFsSURfbGV2ZWxzX1NGYW5kSlEgPC1jKAoKICAKIyBKUQogIAoiQXN0eWFuYXggbGFjdXN0cmlzIiwKIkF1c3RyYWxvaGVyb3Mgc3AiLAoiQ3lwaG9jaGFyYXggZ2lsYmVydCIsCiJEZWx0dXJ1cyBicmV2aXMiLAoiSG9wbGlhcyBicmFzaWxpZW5zaXMiLAoiSG9wbGlhcyBtYWxhYmFyaWN1cyIsCiJIeXBvbWFzdGljdXMgc3RlaW5kYWNobmVyaSIsCiJIeXBvc3RvbXVzIG5pZ3JvbGluZWF0dXMiLAoiTWVnYWxlcG9yaW51cyBlbG9uZ2F0dXMiLAoiTWVnYWxlcG9yaW51cyBnYXJtYW5pIiwKIlByb2NoaWxvZHVzIGFyZ2VudGV1cyIsCiJSaGFtZGlhIHF1ZWxlbiIsCiJTdGVpbmRhY2huZXJpZGlvbiBhbWJseXVydW0iLAoiV2VydGhlaW1lcmlhIG1hY3VsYXRhIiwKCgojIEpRJlNGCiJHeW1ub3R1cyBjYXJhcG8iLAoiUHJvY2hpbG9kdXMgY29zdGF0dXMiLAoiVHJhY2hlbHlvcHRlcnVzIGdhbGVhdHVzIiwKCiNTRgoiQXN0eWFuYXggZmFzY2lhdHVzIiwKIkJyeWNvbiBvcnRob3RhZW5pYSIsCiJDaGFyYWNpZGl1bSBsYWdvc2FudGVuc2UiLAoiQ3JlbmljaWNobGEgbGVwaWRvdGEiLAoiRWlnZW5tYW5uaWEgdmlyZXNjZW5zIiwKIkZyYW5jaXNjb2RvcmFzIG1hcm1vcmF0dXMiLAoiSG9wbGlhcyBpbnRlcm1lZGl1cyIsCiJIeXBvc3RvbXVzIGFsYXR1cyIsCiJJbXBhcmZpbmlzIG1pbnV0dXMiLAoiTWljcm9nbGFuaXMgbGVwdG9zdHJpYXR1cyIsCiJNb2Vua2hhdXNpYSBzYW5jdGFlZmlsb21lbmFlIiwKIk15bGV1cyBtaWNhbnMiLAoiUGFtcGhvcmljaHRoeXMgaG9sbGFuZGkiLAoiUGhhbGxvY2Vyb3MgdWFpIiwKIlBpbWVsb2R1cyBtYWN1bGF0dXMiLAoiUGltZWxvZHVzIHBvaGxpIiwKIlB0ZXJ5Z29wbGljaHRoeXMgZXRlbnRhY3VsYXR1cyIsCiJSb2Vib2lkZXMgeGVub2RvbiIsCiJTZXJyYXNhbG11cyBicmFuZHRpaSIsCiJUZXRyYWdvbm9wdGVydXMgY2hhbGNldXMiLAoKI3NmanEKIk1vZW5raGF1c2lhIGNvc3RhZSIsCiJFdWdlcnJlcyBicmFzaWxpYW51cyIsCgoKI290aGVyCiJBY2VzdHJvcmh5bmNodXMgbGFjdXN0cmlzIiwKIkFjaW5vY2hlaXJvZG9uIG1lbGFub2dyYW1tYSIsCiJBc3R5YW5heCIsCiJDb3B0b2RvbiB6aWxsaWkiLAoiQ3VyaW1hdGVsbGEgbGVwaWR1cmEiLAoiR2VvcGhhZ3VzIGJyYXNpbGllbnNpcyIsCiJIb3BsaWFzIGJyYXNpbGllbnNpcy9pbnRlcm1lZGl1cyIsCiJIeXBvc3RvbXVzIiwKIkxlcG9yaW51cyByZWluaGFyZHRpIiwKIlBpbWVsb2R1cyIsCiJQbGFuYWx0aW5hIG15ZXJzaSIsCiJQcm9jaGlsb2R1cyIsCiJQcm9jaGlsb2R1cyBhcmdlbnRldXMvaGFydGlpIiwKIlBzZXVkb3BsYXR5c3RvbWEgY29ycnVzY2FucyIKCgopCn0KIyBjb3JyZWN0aW5nIGNvbXBsZXRlIHRhYmxlIC0tLS0KCgphbGxfcHNfdGJsX3NmanFfZnVsbCAlPiUgY29sbmFtZXMoKQoKCgogIGFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEgPC0gYWxsX3BzX3RibF9zZmpxX2Z1bGwgJT4lIAogICAgZmlsdGVyKGBFeHBlY3RlZCBsZW5ndGhgICVpbiUgYygiaW4gcmFuZ2UiKSkgJT4lCiAgIyBmaWx0ZXIoYEV4cGVjdGVkIFNwZWNpZXNgICVpbiUgYygiZXhwZWN0ZWQiKSkgJT4lIAogIGZpbHRlcihSdW4gJWluJSBjKCJMR0NfTWluaVNlcV8xIiwgIkxHQ19NaW5pU2VxXzIiKSkgJT4lIAogICMgc3Vic2V0KCEoU2FtcGxlICVpbiUgYygiUG9zaXRpdmUgQ29udHJvbFxuKFAuZ2xhdWNhKSIpKSkgJT4lIAogIGdyb3VwX2J5KFNhbXBsZSxgcmV2aXNlZCBmaW5hbCBJRGApICU+JSAKICBzdW1tYXJpemUoU2FtcGxlID0gdW5pcXVlKFNhbXBsZSksCiAgICAgICAgICAgIFJ1biA9IHVuaXF1ZShSdW4pLAogICAgICAgICAgICBHcm91cCA9IHVuaXF1ZShHcm91cCksCiAgICAgICAgICAgIE9UVXMgPSBsZW5ndGgodW5pcXVlKE9UVSkpLAogICAgICAgICAgICBBU1ZzID0gbGVuZ3RoKHVuaXF1ZShgQVNWIChTZXF1ZW5jZSlgKSksCiAgICAgICAgICAgIElEcyA9IGxlbmd0aCh1bmlxdWUoYHJldmlzZWQgZmluYWwgSURgKSksCiAgICAgICAgICAgIFByaW1lciA9IHVuaXF1ZShQcmltZXIpLAogICAgICAgICAgICBgRXhwZWN0ZWQgc3BlY2llc2AgPSBsZW5ndGgodW5pcXVlKGByZXZpc2VkIGZpbmFsIElEYFtgRXhwZWN0ZWQgU3BlY2llc2AgJWluJSBjKCJleHBlY3RlZCIpXSkpLAogICAgICAgICAgICBgRXhwZWN0ZWQgc3BlY2llcyBsaXN0YCA9IGxpc3QodW5pcXVlKGJhc2U6OnNvcnQoYHJldmlzZWQgZmluYWwgSURgW2BFeHBlY3RlZCBTcGVjaWVzYCAlaW4lIGMoImV4cGVjdGVkIildKSkpLAogICAgICAgICAgICAjIGByZXZpc2VkIGZpbmFsIElEYD0gdW5pcXVlKGByZXZpc2VkIGZpbmFsIElEYCksCiAgICAgICAgICAgIGBSUkEgKCUpYCA9IHN1bShgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApLAogICAgICAgICAgICBgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbGAgPSB1bmlxdWUoYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb3JtIHBvb2xgKSwKICAgICAgICAgICAgYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCA9IHVuaXF1ZShgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2xgKSwKICAgICAgICAgICAgYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgID0gdW5pcXVlKGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCkKICAgICAgICAgICAgKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShgcmV2aXNlZCBmaW5hbCBJRGA9ZmFjdG9yKGByZXZpc2VkIGZpbmFsIElEYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgLCBsZXZlbHMgPSByZXYoZmluYWxJRF9sZXZlbHMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkgJT4lIAogIG11dGF0ZShQcmltZXIgPSBmYWN0b3IoUHJpbWVyLCBsZXZlbHMgPSBjKCJOZW9GaXNoIiwgIk1pRmlzaCIsICJUZWxlbyIsICJOZW9GaXNoL01pRmlzaCIsIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIiksKSkgJT4lIAogIG11dGF0ZShgUmVjb3ZlcmVkIHByb3BvcnRpb24gbm9ybWAgPSBndG9vbHM6OmZvbGRjaGFuZ2UoZGVub20gPSBgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbGAsbnVtID0gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKSkgJT4lIAogIG11dGF0ZShgUmVjb3ZlcmVkIHByb3BvcnRpb24gbm9uIG5vcm1gID0gZ3Rvb2xzOjpmb2xkY2hhbmdlKGRlbm9tID0gYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCxudW0gPSBgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApKSAlPiUgCiAgbXV0YXRlKFJhdGlvID0gaWZfZWxzZShHcm91cCAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIEpRbWMiLCAiTm9uLW5vcm1hbGl6ZWQgU0ZtYyIpLCBgUmVjb3ZlcmVkIHByb3BvcnRpb24gbm9uIG5vcm1gLGBSZWNvdmVyZWQgcHJvcG9ydGlvbiBub3JtYCkpICU+JSAKICBtdXRhdGUoUmF0aW8gPSBpZl9lbHNlKFJhdGlvIDw9IC0yMCwgLTIwLCBSYXRpbykpICU+JSAKICBtdXRhdGUoR3JvdXAgPSBmYWN0b3IoR3JvdXAsbGV2ZWxzID0gYygiTm9ybWFsaXplZCBTRkpRbWMiLCAiTm9uLW5vcm1hbGl6ZWQgSlFtYyIsICJOb3JtYWxpemVkIEpRbWMiLCAiTm9uLW5vcm1hbGl6ZWQgU0ZtYyIsICJOb3JtYWxpemVkIFNGbWMiICkpKSAlPiUgCiAgbXV0YXRlKE1DID0gc3RyX3JlbW92ZShHcm91cCwiTm9ybWFsaXplZCB8Tm9uLW5vcm1hbGl6ZWQgIikpICU+JSAKICBtdXRhdGUoTm9ybWFsaXphdGlvbiA9IHN0cl9yZW1vdmUoR3JvdXAsIiBTRm1jfCBKUW1jfCBTRkpRbWMiKSkgCiAgCiAgCiAgIyAgbXV0YXRlKGBSZWNvdmVyZWQgcHJvcG9ydGlvbiBub3JtYCA9IGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYC9gUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbGApICU+JSAKICAjIG11dGF0ZShgUmVjb3ZlcmVkIHByb3BvcnRpb24gbm9uIG5vcm1gID0gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgL2BQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbGApCiAgIyAKICAKCgoKCiNub3ZvcyBncmFmaWNvcyBkZSBwcm9wb3LDp8O1ZXMgLS0tLQojIGFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEgJT4lIAojICBtdXRhdGUoUHJpbWVyID0gZmFjdG9yKFByaW1lciwgbGV2ZWxzID0gYygiTmVvRmlzaCIsICJNaUZpc2giLCAiVGVsZW8iLCAiTmVvRmlzaC9NaUZpc2giLCAiTmVvRmlzaC9NaUZpc2gvVGVsZW8iKSkpICU+JSAKIyAgIGZpbHRlcihgRXhwZWN0ZWQgU3BlY2llc2AgPT0gMSkgJT4lCiMgICBnZ3Bsb3QoYWVzKHg9IFJhdGlvKSwKIyAgICAgICAgICAgICAgeT0gYHJldmlzZWQgZmluYWwgSURgLCBmaWxsID0gUHJpbWVyLCBhbHBoYSA9IFBvb2wKIyAgICAgICAgICAgICAgKSkgKwojICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsCiMgICAgIHBvc2l0aW9uID1wb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAic2luZ2xlIikKIyAgICAgICAgICAgICkrCiMgICAjIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDAwMDBmIiwiIzk2OTU5NSIpLAojICAgIyAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTm9uLW5vcm1hbGl6ZWQiLCJOb3JtYWxpemVkIikpKwojICAgIyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBhbHBoYShjb2xvdXIgPSBjb2xvcnNfbm9ybSAsYWxwaGEgPSAgMC44KSkrCiMgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfbm9ybVtjKDEsMyw1KV0pKwojICAgc2NhbGVfYWxwaGFfbWFudWFsKHZhbHVlcyA9IGMoMC40LCAwLjkpLGxhYmVscyA9IGMoIk5vbi1ub3JtYWxpemVkIHBvb2wiLCJOb3JtYWxpemVkIHBvb2wiKSkrCiMgICB5bGFiKCJTcGVjaWVzIikgKwojICAgIyBzY2FsZV94X2JyZWFrKGMoMjAsIDgwKSkgKwojICAgIyB4bGltKGMoMCwyMCkpKwojICAgeGxhYigiUHJvcG9ydGlvbiBvZiBBU1ZzIGluIHNhbXBsZSBkaXZpZGVkIGJ5IHByb3BvcnRpb24gb2YgRE5BIGlucHV0IGluIEpRbWMiKSArCiMgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLGxpbmV0eXBlPTIpICArCiMgICBmYWNldF93cmFwKH5QcmltZXIsbmNvbCA9IDEpCgoKCiMtLS0tCgoKCgoKCiNKUSBub3JtLS0tLQpqcV9ub3JtX3ByZXNlbmNlX3Bsb3QgPC0gYWxsX3BzX3RibF9zZmpxX2Z1bGxfdW5pcSAlPiUgCiAgZmlsdGVyKEdyb3VwICVpbiUgYygiTm9ybWFsaXplZCBKUW1jIikpICU+JSAKICBmaWx0ZXIoIWByZXZpc2VkIGZpbmFsIElEYCVpbiUgYygKICAgIE5BLCJOQSIsCiAgICAiQWNpbm9jaGVpcm9kb24gbWVsYW5vZ3JhbW1hIiwKICAgICJCcnljb24gb3J0aG90YWVuaWEiLAogICAgIkhvcGxpYXMgaW50ZXJtZWRpdXMiLAogICAgIk1vZW5raGF1c2lhIGNvc3RhZSIsCiAgICAiU2VycmFzYWxtdXMgYnJhbmR0aWkiKSkgJT4lIAogIGdncGxvdChhZXMoeT1gcmV2aXNlZCBmaW5hbCBJRGAsCiAgICAgICAgICAgICB4PVNhbXBsZSwKICAgICAgICAgICAgIGZpbGw9UHJpbWVyLAogICAgICAgICAgICAgYWxwaGE9YFJlY292ZXJlZCBwcm9wb3J0aW9uIG5vcm1gKSkgKwogIGFubm90YXRlKGdlb20gPSAicmVjdCIsCiAgICAgICAgICAgeG1pbj1jKDAuNDUpLCB4bWF4PWMoMy41NSksCiAgICAgICAgICAgeW1pbj1jKDAuNSksIHltYXg9Yyg0LjUpLAogICAgICAgICAgIGFscGhhPTAuNSxmaWxsPSJ5ZWxsb3ciKSArCiAgZ2VvbV9yYXN0ZXIoKSArCiAgIyB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYWxwaGEoY29sb3VyID0gY29sb3JzNSkpICsKICBzY2FsZV9hbHBoYShuYW1lPSJSZWNvdmVyZWQgc2VxdWVuY2UgY291bnRzL1xuSW5wdXQgRE5BIixicmVha3MgPSBjKDAuMDEsMSwyLDMsNCw1LDYsNyw4LDksMTAsMjApLHJhbmdlID0gYygwLjA1LDEpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAoMjEqMykvODAgKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1BU1ZzKSxhbHBoYT0xKSsKICB0aGVtZV9taW5pbWFsKGJhc2VfbGluZV9zaXplID0gMCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKSArCiAgeWxhYihsYWJlbCA9ICJUYXhvbm9teSIpCgpqcV9ub3JtX3ByZXNlbmNlX3Bsb3QKCiNKUSBub24tbm9ybS0tLS0KanFfbm9uX25vcm1fcHJlc2VuY2VfcGxvdCA8LSBhbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxICU+JSAKICBmaWx0ZXIoR3JvdXAgJWluJSBjKCJOb24tbm9ybWFsaXplZCBKUW1jIikpICU+JSAKICBmaWx0ZXIoIWByZXZpc2VkIGZpbmFsIElEYCVpbiUgYygKICAgIE5BLCJOQSIsCiAgICAiQWNpbm9jaGVpcm9kb24gbWVsYW5vZ3JhbW1hIiwKICAgICJCcnljb24gb3J0aG90YWVuaWEiLAogICAgIkhvcGxpYXMgaW50ZXJtZWRpdXMiLAogICAgIk1vZW5raGF1c2lhIGNvc3RhZSIsCiAgICAiU2VycmFzYWxtdXMgYnJhbmR0aWkiLAogICAgIkNvcHRvZG9uIHppbGxpaSIpKSAlPiUgCiAgZ2dwbG90KGFlcyh5PWByZXZpc2VkIGZpbmFsIElEYCwKICAgICAgICAgICAgIHg9U2FtcGxlLAogICAgICAgICAgICAgZmlsbD1QcmltZXIsCiAgICAgICAgICAgICBhbHBoYT1gUmVjb3ZlcmVkIHByb3BvcnRpb24gbm9uIG5vcm1gKSkgKwogIGFubm90YXRlKGdlb20gPSAicmVjdCIsCiAgICAgICAgICAgeG1pbj1jKDAuNDUpLCB4bWF4PWMoMy41NSksCiAgICAgICAgICAgeW1pbj1jKDAuNSksIHltYXg9YygyLjUpLAogICAgICAgICAgIGFscGhhPTAuNSxmaWxsPSJ5ZWxsb3ciKSArCiAgZ2VvbV9yYXN0ZXIoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYWxwaGEoY29sb3VyID0gY29sb3JzNSkpICsKICBzY2FsZV9hbHBoYShuYW1lPSJSZWNvdmVyZWQgc2VxdWVuY2UgY291bnRzL1xuSW5wdXQgRE5BIixicmVha3MgPSBjKDAuMDEsMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMjApLHJhbmdlID0gYygwLjA1LDEpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAoMTkqMykvODAgKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1BU1ZzKSxhbHBoYT0xLHNpemU9NCkrCiAgdGhlbWVfbWluaW1hbChiYXNlX2xpbmVfc2l6ZSA9IDApICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkgKwogIHlsYWIobGFiZWwgPSAiVGF4b25vbXkiKQoKanFfbm9uX25vcm1fcHJlc2VuY2VfcGxvdAoKI1NGIG5vcm0tLS0tCnNmX25vcm1fcHJlc2VuY2VfcGxvdCA8LSBhbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxICU+JSAKICBmaWx0ZXIoR3JvdXAgJWluJSBjKCJOb3JtYWxpemVkIFNGbWMiKSkgJT4lIAogIGZpbHRlcighYHJldmlzZWQgZmluYWwgSURgJWluJSBjKAogICAgTkEsIk5BIiwKICAgICJBY2VzdHJvcmh5bmNodXMgbGFjdXN0cmlzIiwKICAgICJBc3R5YW5heCBsYWN1c3RyaXMiLAogICAgIkN1cmltYXRlbGxhIGxlcGlkdXJhIiwKICAgICJEZWx0dXJ1cyBicmV2aXMiLAogICAgIkdlb3BoYWd1cyBicmFzaWxpZW5zaXMiLAogICAgIkxlcG9yaW51cyByZWluaGFyZHRpIiwKICAgICJNb2Vua2hhdXNpYSBjb3N0YWUiLAogICAgIlBsYW5hbHRpbmEgbXllcnNpIgogICAgKSkgJT4lIAogIGdncGxvdChhZXMoeT1gcmV2aXNlZCBmaW5hbCBJRGAsCiAgICAgICAgICAgICB4PVNhbXBsZSwKICAgICAgICAgICAgIGZpbGw9UHJpbWVyLAogICAgICAgICAgICAgYWxwaGE9YFJlY292ZXJlZCBwcm9wb3J0aW9uIG5vcm1gKSkgKwogICMgZ2VvbV90aWxlKGNvbG91ciA9ICIjMzMzMzMzIiwgd2lkdGg9MC45NSwgaGVpZ2h0PTAuOTUsIHNpemU9MSxsaW5lc2l6ZT0wLjA1KSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJyZWN0IiwKICAgICAgICAgICB4bWluPWMoMC40NSksIHhtYXg9YygyLjU1KSwKICAgICAgICAgICB5bWluPWMoMC41KSwgeW1heD1jKDIuNSksCiAgICAgICAgICAgYWxwaGE9MC41LGZpbGw9InllbGxvdyIpICsKICBnZW9tX3Jhc3RlcigpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBhbHBoYShjb2xvdXIgPSBjb2xvcnM1KSkgKwogIHNjYWxlX2FscGhhKG5hbWU9IlJlY292ZXJlZCBzZXF1ZW5jZSBjb3VudHMvXG5JbnB1dCBETkEiLGJyZWFrcyA9IGMoMC4wMSwxLDIsMyw0LDUsNiw3LDgsOSwxMCwyMCkscmFuZ2UgPSBjKDAuMDUsMSkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwgMCkpICsKICBjb29yZF9maXhlZChyYXRpbyA9ICgyNSoyKS84MCApICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPUFTVnMpLGFscGhhPTEpICsKICB0aGVtZV9taW5pbWFsKGJhc2VfbGluZV9zaXplID0gMCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKSArCiAgeWxhYihsYWJlbCA9ICJUYXhvbm9teSIpCgpzZl9ub3JtX3ByZXNlbmNlX3Bsb3QKCiNTRiBub24tbm9ybS0tLS0Kc2Zfbm9uX25vcm1fcHJlc2VuY2VfcGxvdCA8LSBhbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxICU+JSAKICBmaWx0ZXIoR3JvdXAgJWluJSBjKCJOb24tbm9ybWFsaXplZCBTRm1jIikpICU+JSAKICBmaWx0ZXIoIWByZXZpc2VkIGZpbmFsIElEYCVpbiUgYygKICAgICMgTkEsIk5BIiwKICAgICJBY2VzdHJvcmh5bmNodXMgbGFjdXN0cmlzIiwKICAgICJBc3R5YW5heCBsYWN1c3RyaXMiLAogICAgIkN1cmltYXRlbGxhIGxlcGlkdXJhIiwKICAgICJEZWx0dXJ1cyBicmV2aXMiLAogICAgIkdlb3BoYWd1cyBicmFzaWxpZW5zaXMiLAogICAgIkxlcG9yaW51cyByZWluaGFyZHRpIiwKICAgICJNb2Vua2hhdXNpYSBjb3N0YWUiLAogICAgIlBsYW5hbHRpbmEgbXllcnNpIgogICAgKSkgJT4lIAogIGdncGxvdChhZXMoeT1gcmV2aXNlZCBmaW5hbCBJRGAsCiAgICAgICAgICAgICB4PVNhbXBsZSwKICAgICAgICAgICAgIGZpbGw9UHJpbWVyLAogICAgICAgICAgICAgYWxwaGE9YFJlY292ZXJlZCBwcm9wb3J0aW9uIG5vbiBub3JtYCkpICsKICBhbm5vdGF0ZShnZW9tID0gInJlY3QiLAogICAgICAgICAgIHhtaW49YygwLjQ1KSwgeG1heD1jKDIuNTUpLAogICAgICAgICAgIHltaW49YygwLjUpLCB5bWF4PWMoMi41KSwKICAgICAgICAgICBhbHBoYT0wLjUsZmlsbD0ieWVsbG93IikgKwogIGdlb21fcmFzdGVyKCkgKwogICMgdGhlbWUocGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X3JlY3QoZmlsbD0iI2ZmZmZmZiIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYWxwaGEoY29sb3VyID0gY29sb3JzNSkpICsKICBzY2FsZV9hbHBoYShuYW1lPSJSZWNvdmVyZWQgc2VxdWVuY2UgY291bnRzL1xuSW5wdXQgRE5BIixicmVha3MgPSBjKDAuMDEsMSwyLDMsNCw1LDYsNyw4LDksMTAsMjApKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAoMjcqMikvODApICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPUFTVnMpLGFscGhhPTEpICsKICB0aGVtZV9taW5pbWFsKGJhc2VfbGluZV9zaXplID0gMCxiYXNlX3NpemUgPSAxMCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKSArCiAgeWxhYihsYWJlbCA9ICJUYXhvbm9teSIpCgpzZl9ub25fbm9ybV9wcmVzZW5jZV9wbG90CiNTRkpRIG5vcm0tLS0tCnNmanFfbm9ybV9wcmVzZW5jZV9wbG90IDwtIGFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEgJT4lIAogIG11dGF0ZShgcmV2aXNlZCBmaW5hbCBJRGAgPSBmYWN0b3IoYHJldmlzZWQgZmluYWwgSURgLCBsZXZlbHMgPSByZXYoZmluYWxJRF9sZXZlbHNfU0ZhbmRKUSkpKSAlPiUgCiAgZmlsdGVyKEdyb3VwICVpbiUgYygiTm9ybWFsaXplZCBTRkpRbWMiKSkgJT4lIAogIGZpbHRlcighYHJldmlzZWQgZmluYWwgSURgJWluJSBjKAogICAgTkEsIk5BIiwKICAgICJBY2VzdHJvcmh5bmNodXMgbGFjdXN0cmlzIiwKICAgICJHZW9waGFndXMgYnJhc2lsaWVuc2lzIiwKICAgICJQc2V1ZG9wbGF0eXN0b21hIGNvcnJ1c2NhbnMiCiAgICApKSAlPiUgCiAgZ2dwbG90KGFlcyh5PWByZXZpc2VkIGZpbmFsIElEYCwKICAgICAgICAgICAgIHg9U2FtcGxlLAogICAgICAgICAgICAgZmlsbD1QcmltZXIsCiAgICAgICAgICAgICBhbHBoYT1gUmVjb3ZlcmVkIHByb3BvcnRpb24gbm9ybWApKSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJyZWN0IiwKICAgICAgICAgICB4bWluPWMoMC40NSksIHhtYXg9YygyLjU1KSwKICAgICAgICAgICB5bWluPWMoMC41KSwgeW1heD1jKDQuNSksCiAgICAgICAgICAgYWxwaGE9MC41LGZpbGw9InllbGxvdyIpICsKICBnZW9tX3Jhc3RlcigpICsKICAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGFscGhhKGNvbG91ciA9IGNvbG9yczUpKSArCiAgc2NhbGVfYWxwaGEobmFtZT0iUmVjb3ZlcmVkIHNlcXVlbmNlIGNvdW50cy9cbklucHV0IEROQSIsYnJlYWtzID0gYygwLjAxLDEsMiwzLDQsNSw2LDcsOCw5LDEwLDIwKSxyYW5nZSA9IGMoMC4wNSwxKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3lfZGlzY3JldGUoZXhwYW5kID0gYygwLCAwKSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gKDQyKjIpLzEyMCApICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPUFTVnMpLGFscGhhPTEpICsKICB0aGVtZV9taW5pbWFsKGJhc2VfbGluZV9zaXplID0gMCxiYXNlX3NpemUgPSAxMCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKSArCiAgeWxhYihsYWJlbCA9ICJUYXhvbm9teSIpCgpzZmpxX25vcm1fcHJlc2VuY2VfcGxvdAojLS0tLQoKCiNzYXZlIHBsb3RzIC0tLS0KCmpxX25vcm1fcHJlc2VuY2VfcGxvdApqcV9ub25fbm9ybV9wcmVzZW5jZV9wbG90CnNmX25vcm1fcHJlc2VuY2VfcGxvdApzZl9ub25fbm9ybV9wcmVzZW5jZV9wbG90CnNmanFfbm9ybV9wcmVzZW5jZV9wbG90CgoKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL2pxX25vcm1fcHJlc2VuY2VfcGxvdC5wbmciLCBwbG90ID0ganFfbm9ybV9wcmVzZW5jZV9wbG90LCBkZXZpY2UgPSAicG5nIiwgd2lkdGggPSAxOCwgaGVpZ2h0ID0gMjQsIHVuaXRzID0gImNtIiwgZHBpID0gNjAwKQoKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL2pxX25vbl9ub3JtX3ByZXNlbmNlX3Bsb3QucG5nIiwgcGxvdCA9IGpxX25vbl9ub3JtX3ByZXNlbmNlX3Bsb3QsIGRldmljZSA9ICJwbmciLCB3aWR0aCA9IDIyLCBoZWlnaHQgPSAyNCwgdW5pdHMgPSAiY20iLCBkcGkgPSA2MDApCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3Mvc2Zfbm9ybV9wcmVzZW5jZV9wbG90LnBuZyIsIHBsb3QgPSBzZl9ub3JtX3ByZXNlbmNlX3Bsb3QsIGRldmljZSA9ICJwbmciLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSAyOCwgdW5pdHMgPSAiY20iLCBkcGkgPSA2MDApCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3Mvc2Zfbm9uX25vcm1fcHJlc2VuY2VfcGxvdC5wbmciLCBwbG90ID0gc2Zfbm9uX25vcm1fcHJlc2VuY2VfcGxvdCwgZGV2aWNlID0gInBuZyIsIHdpZHRoID0gMjAsIGhlaWdodCA9IDMwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9zZmpxX25vcm1fcHJlc2VuY2VfcGxvdC5wbmciLCBwbG90ID0gc2ZqcV9ub3JtX3ByZXNlbmNlX3Bsb3QsIGRldmljZSA9ICJwbmciLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSA0NSwgdW5pdHMgPSAiY20iLCBkcGkgPSA2MDApCgoKCmd0b29sczo6Zm9sZGNoYW5nZSgzLjc2NTUwNWUtMDIsMC4wNTYpCmd0b29sczo6Zm9sZGNoYW5nZSgwLjA1NiwzLjc2NTUwNWUtMDIpCmd0b29sczo6Zm9sZGNoYW5nZSgyLjQ1ODc3NWUtMDUsMC4wNTU2KQpndG9vbHM6OmZvbGRjaGFuZ2UoMC4wNTU2LDIuNDU4Nzc1ZS0wNSkKCiN0ZW50YW5kbyBmYXplciB0b2RvcyBqdW50b3MgLS0tLQoKCiNvcmdhbml6aW5nIGJ5IG9yZGVycy0tLS0Ke2ZpbmFsSURfbGV2ZWxzX1NGYW5kSlFfdGF4IDwtIGMoCiNTRkpRCiAgIk1vZW5raGF1c2lhIGNvc3RhZSIsCiAgIkV1Z2VycmVzIGJyYXNpbGlhbnVzIiwKewojU0YKICAiQnJ5Y29uIG9ydGhvdGFlbmlhIiwKICAiQXN0eWFuYXggZmFzY2lhdHVzIiwKICAiTW9lbmtoYXVzaWEgc2FuY3RhZWZpbG9tZW5hZSIsCiAgIlJvZWJvaWRlcyB4ZW5vZG9uIiwKICAiVGV0cmFnb25vcHRlcnVzIGNoYWxjZXVzIiwKICAiQ2hhcmFjaWRpdW0gbGFnb3NhbnRlbnNlIiwKICAiSG9wbGlhcyBpbnRlcm1lZGl1cyIsCiAgIk15bGV1cyBtaWNhbnMiLAogICJTZXJyYXNhbG11cyBicmFuZHRpaSIsCiAgIkNyZW5pY2ljaGxhIGxlcGlkb3RhIiwKICAiUGFtcGhvcmljaHRoeXMgaG9sbGFuZGkiLAogICJQaGFsbG9jZXJvcyB1YWkiLAogICJFaWdlbm1hbm5pYSB2aXJlc2NlbnMiLAogICJGcmFuY2lzY29kb3JhcyBtYXJtb3JhdHVzIiwKICAiSW1wYXJmaW5pcyBtaW51dHVzIiwKICAiSHlwb3N0b211cyBhbGF0dXMiLAogICJQdGVyeWdvcGxpY2h0aHlzIGV0ZW50YWN1bGF0dXMiLAogICJQaW1lbG9kdXMgbWFjdWxhdHVzIiwKICAiUGltZWxvZHVzIHBvaGxpIiwKICAiTWljcm9nbGFuaXMgbGVwdG9zdHJpYXR1cyIsCgoKI1NGICYgSlEKICAiR3ltbm90dXMgY2FyYXBvIiwKICAiVHJhY2hlbHlvcHRlcnVzIGdhbGVhdHVzIiwKICAiUHJvY2hpbG9kdXMgY29zdGF0dXMiLAojSlEKICAiUHJvY2hpbG9kdXMgYXJnZW50ZXVzIiwKICAiUHJvY2hpbG9kdXMgaGFydGlpIiwKICAgICAgICAjICJQcm9jaGlsb2R1cyBhcmdlbnRldXMvaGFydGlpIiwKICAgICAgICAjICJQcm9jaGlsb2R1cyIsCiAgIkh5cG9tYXN0aWN1cyBzdGVpbmRhY2huZXJpIiwKICAiTWVnYWxlcG9yaW51cyBlbG9uZ2F0dXMiLAogICJNZWdhbGVwb3JpbnVzIGdhcm1hbmkiLAogICJBc3R5YW5heCBsYWN1c3RyaXMiLAogICJDeXBob2NoYXJheCBnaWxiZXJ0IiwKICAiSG9wbGlhcyBicmFzaWxpZW5zaXMiLAogICJIb3BsaWFzIG1hbGFiYXJpY3VzIiwKICAiUHJvY2hpbG9kdXMgYXJnZW50ZXVzIiwKICAiUHJvY2hpbG9kdXMgaGFydGlpIiwKICAiQXVzdHJhbG9oZXJvcyBzcCIsCiAgIldlcnRoZWltZXJpYSBtYWN1bGF0YSIsCiAgIkRlbHR1cnVzIGJyZXZpcyIsCiAgIkh5cG9zdG9tdXMgbmlncm9saW5lYXR1cyIsCiAgIlJoYW1kaWEgcXVlbGVuIiwKICAiU3RlaW5kYWNobmVyaWRpb24gYW1ibHl1cnVtIiwKI290aGVyCiMgIkFjZXN0cm9yaHluY2h1cyBsYWN1c3RyaXMiLAojICJBY2lub2NoZWlyb2RvbiBtZWxhbm9ncmFtbWEiLAogICJBc3R5YW5heCIsCiMgIkNvcHRvZG9uIHppbGxpaSIsCiMgIkN1cmltYXRlbGxhIGxlcGlkdXJhIiwKIyAiR2VvcGhhZ3VzIGJyYXNpbGllbnNpcyIsCiJIb3BsaWFzIGJyYXNpbGllbnNpcy9pbnRlcm1lZGl1cyIsCiJIeXBvc3RvbXVzIiwKIyAiTGVwb3JpbnVzIHJlaW5oYXJkdGkiLAoiUGltZWxvZHVzIiwKIyAiUGxhbmFsdGluYSBteWVyc2kiLAoiUHJvY2hpbG9kdXMiLAoiUHJvY2hpbG9kdXMgYXJnZW50ZXVzL2hhcnRpaSIKIyAsIlBzZXVkb3BsYXR5c3RvbWEgY29ycnVzY2FucyIKKSAlPiUgdW5pcXVlKCkKfQoKIyB0YXhvbm9taWNhbHkgb3JkZXJlZCAtLS0tCgojIHtmaW5hbElEX2xldmVsc19TRmFuZEpRX3RheCA8LSBjKCAiUHJvY2hpbG9kdXMgYXJnZW50ZXVzIiwgIlByb2NoaWxvZHVzIGhhcnRpaSIsICJQcm9jaGlsb2R1cyBjb3N0YXR1cyIsICAgIlByb2NoaWxvZHVzIiwgICAiUHJvY2hpbG9kdXMgYXJnZW50ZXVzL2hhcnRpaSIsICJDeXBob2NoYXJheCBnaWxiZXJ0IiwgIk15bGV1cyBtaWNhbnMiLCAiU2VycmFzYWxtdXMgYnJhbmR0aWkiLCAiTWVnYWxlcG9yaW51cyBlbG9uZ2F0dXMiLCAiTWVnYWxlcG9yaW51cyBnYXJtYW5pIiwgIkh5cG9tYXN0aWN1cyBzdGVpbmRhY2huZXJpIiwgIkhvcGxpYXMgbWFsYWJhcmljdXMiLCAiSG9wbGlhcyBpbnRlcm1lZGl1cyIsICJIb3BsaWFzIGJyYXNpbGllbnNpcyIsICAgIkhvcGxpYXMgYnJhc2lsaWVuc2lzL2ludGVybWVkaXVzIiwgIkJyeWNvbiBvcnRob3RhZW5pYSIsICJDaGFyYWNpZGl1bSBsYWdvc2FudGVuc2UiLCAiUm9lYm9pZGVzIHhlbm9kb24iLCAiVGV0cmFnb25vcHRlcnVzIGNoYWxjZXVzIiwgIk1vZW5raGF1c2lhIHNhbmN0YWVmaWxvbWVuYWUiLCAiTW9lbmtoYXVzaWEgY29zdGFlIiwgIkFzdHlhbmF4IGxhY3VzdHJpcyIsICJBc3R5YW5heCBmYXNjaWF0dXMiLCAgICAgIkFzdHlhbmF4IiwgIkRlbHR1cnVzIGJyZXZpcyIsICJQdGVyeWdvcGxpY2h0aHlzIGV0ZW50YWN1bGF0dXMiLCAiSHlwb3N0b211cyBuaWdyb2xpbmVhdHVzIiwgIkh5cG9zdG9tdXMgYWxhdHVzIiwgICAiSHlwb3N0b211cyIsICJUcmFjaGVseW9wdGVydXMgZ2FsZWF0dXMiLCAiRnJhbmNpc2NvZG9yYXMgbWFybW9yYXR1cyIsICJXZXJ0aGVpbWVyaWEgbWFjdWxhdGEiLCAiUmhhbWRpYSBxdWVsZW4iLCAiSW1wYXJmaW5pcyBtaW51dHVzIiwgIk1pY3JvZ2xhbmlzIGxlcHRvc3RyaWF0dXMiLCAiU3RlaW5kYWNobmVyaWRpb24gYW1ibHl1cnVtIiwgIlBpbWVsb2R1cyBwb2hsaSIsICJQaW1lbG9kdXMgbWFjdWxhdHVzIiwgICAiUGltZWxvZHVzIiwgIkVpZ2VubWFubmlhIHZpcmVzY2VucyIsICJHeW1ub3R1cyBjYXJhcG8iLCAiRXVnZXJyZXMgYnJhc2lsaWFudXMiLCAiUGFtcGhvcmljaHRoeXMgaG9sbGFuZGkiLCAiUGhhbGxvY2Vyb3MgdWFpIiwgIkNyZW5pY2ljaGxhIGxlcGlkb3RhIiwgIkF1c3RyYWxvaGVyb3Mgc3AiKSAlPiUgdW5pcXVlKCkKIyB9CgoKCiMtLS0tCgphbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxJGBSZWNvdmVyZWQgcHJvcG9ydGlvbiBub3JtYCAlPiUgYmFzZTo6c29ydCgpCgojIGJyb3dzZVZpZ25ldHRlcygidHJlZWlvIikKCmFsbF9zZk5qcV9ub3JtX3ByZXNlbmNlX3Bsb3QgPC0KICBhbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxICU+JQogIGZpbHRlcighYHJldmlzZWQgZmluYWwgSURgICVpbiUgYygKICAgICJQc2V1ZG9wbGF0eXN0b21hIGNvcnJ1c2NhbnMiLAogICAgIlBsYW5hbHRpbmEgbXllcnNpIiwKICAgICJMZXBvcmludXMgcmVpbmhhcmR0aSIsCiAgICAiQWNlc3Ryb3JoeW5jaHVzIGxhY3VzdHJpcyIsCiAgICAiQWNpbm9jaGVpcm9kb24gbWVsYW5vZ3JhbW1hIiwKICAgICJDb3B0b2RvbiB6aWxsaWkiLAogICAgIkN1cmltYXRlbGxhIGxlcGlkdXJhIiwKICAgICJHZW9waGFndXMgYnJhc2lsaWVuc2lzIikpICU+JSAKICBtdXRhdGUoYHJldmlzZWQgZmluYWwgSURgID0gZmFjdG9yKGByZXZpc2VkIGZpbmFsIElEYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAsIGxldmVscyA9IHJldihmaW5hbElEX2xldmVsc19TRmFuZEpRX3RheCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpICU+JSAKICAjIG11dGF0ZShTYW1wbGUgPSBmYWN0b3IoU2FtcGxlLCBsZXZlbHMgPSBzYW1wbGVfbGV2ZWxzKSkgJT4lIAogIG11dGF0ZShTYW1wbGUgPSBmYWN0b3IoU2FtcGxlLCBsZXZlbHMgPSBjKAoiTm9ybWFsaXplZCBTRm1jXG5NaUZpc2ggQiIsCiJOb3JtYWxpemVkIFNGbWNcbk1pRmlzaCIsCiJOb24tbm9ybWFsaXplZCBTRm1jXG5NaUZpc2ggQiIsCiJOb24tbm9ybWFsaXplZCBTRm1jXG5NaUZpc2giLAoiTm9ybWFsaXplZCBTRkpRbWNcbk1pRmlzaCBCIiwKIk5vcm1hbGl6ZWQgU0ZKUW1jXG5NaUZpc2giLAoiTm9uLW5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIiwKIk5vcm1hbGl6ZWQgSlFtY1xuTWlGaXNoIiwKCiJOb3JtYWxpemVkIFNGbWNcbk5lb0Zpc2ggQiIgICAgLAoiTm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiwKIk5vbi1ub3JtYWxpemVkIFNGbWNcbk5lb0Zpc2ggQiIsCiJOb24tbm9ybWFsaXplZCBTRm1jXG5OZW9GaXNoIiAgLAoiTm9ybWFsaXplZCBTRkpRbWNcbk5lb0Zpc2ggQiIgICwKIk5vcm1hbGl6ZWQgU0ZKUW1jXG5OZW9GaXNoIiwKIk5vbi1ub3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giICAsCiJOb3JtYWxpemVkIEpRbWNcbk5lb0Zpc2giLAoKIk5vbi1ub3JtYWxpemVkIEpRbWNcblRlbGVvIiwKIk5vcm1hbGl6ZWQgSlFtY1xuVGVsZW8iICAgICAgICAsCiJQb3NpdGl2ZSBDb250cm9sXG4oUC5nbGF1Y2EpIiwKIm5lZy1QQ1IyIikpKSAlPiUgCiAgZmlsdGVyKCFgcmV2aXNlZCBmaW5hbCBJRGAlaW4lIGMoCiAgICBOQSwiTkEiLAogICAgIkFjZXN0cm9yaHluY2h1cyBsYWN1c3RyaXMiLAogICAgIkNvcHRvZG9uIHppbGxpaSIsCiAgICAiQ3VyaW1hdGVsYSBsZXBpZHVyYSIsCiAgICAiQWNpbm9jaGVpcm9kb24gbWVsYW5vZ3JhbW1hIiwKICAgICJDdXJpbWF0ZWxsYSBsZXBpZHVyYSIsCiAgICAiUGxhbmFsdGluYSBteWVyc2kiLAogICAgIlBzZXVkb3BsYXR5c3RvbWEgY29ycnVzY2FucyIsCiAgICBOQSwiTkEiKSkgJT4lIAogIGZpbHRlcihHcm91cCAlaW4lIGMoIk5vcm1hbGl6ZWQgU0ZtYyIsIk5vcm1hbGl6ZWQgSlFtYyIsIk5vcm1hbGl6ZWQgU0ZKUW1jIikpICU+JQogIGdncGxvdChhZXMoeT1gcmV2aXNlZCBmaW5hbCBJRGAsCiAgICAgICAgICAgICB4PVNhbXBsZSwKICAgICAgICAgICAgIGZpbGw9UmF0aW8pKSArCiAgZ2VvbV90aWxlKHdpZHRoPTEsY29sPSJibGFjayIsIGxpbmVqb2luID0gInJvdW5kIikgKwogICMgZ2VvbV90aWxlKGFlcyhjb2w9Tm9ybWFsaXphdGlvbiksd2lkdGg9MiwgbGluZWpvaW4gPSAicm91bmQiKSArCiAgIyB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDAwMDAwIiwiIzg3ODc4NyIpKSsKICBzY2FsZV9maWxsX2dyYWRpZW50MigKICAgICMgY29sb3Vycz1jKCIjMDAwMGZmIiwiIzAwMDBmZiIsICIjZmYwMDAwIiksCiAgICAjIGxvdyA9ICIjZmYwMDAwIixoaWdoID0gIiMwMDAwZmYiLAogICAgbG93ID0gIiNjYzAwMDAiLGhpZ2ggPSAiIzAwNzAwMCIsCiAgICBtaWQgPSAiI2ZmZmZmZiIsbWlkcG9pbnQgPSAwLAogICAgbmEudmFsdWUgPSAiZ29sZCIsCiAgICBndWlkZSA9ICJjb2xvdXJiYXIiLAogICAgbGltaXRzID0gYygtMjAsIDIwKSwKICAgIG5hbWUgPSAiRm9sZCB2YXJpYXRpb24gZnJvbVxuaW5wdXQgRE5BIHRvIFJSQSIKICAgICkgKwogICMgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAsIDApKSArCiAgIyBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwgMCksCiAgIyAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoMikpICsKICAjIGNvb3JkX2ZpeGVkKHJhdGlvID0gMC4yNSkgKwogICAgCiAgICAjIG5hbmlhcjo6Z2VvbV9taXNzX3BvaW50KCkgKwogIGdlb21fdGV4dChhZXMobGFiZWw9QVNWcyksYWxwaGE9MSkrCiAgdGhlbWVfbWluaW1hbChiYXNlX2xpbmVfc2l6ZSA9IDAuMSxiYXNlX3NpemUgPSAxNSkgKwogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0iI2ZmZmZmZiIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShkcm9wPUZBTFNFKSArCiAgeWxhYihsYWJlbCA9ICJUYXhvbm9teSIpICsKICAgZmFjZXRfd3JhcCh+UHJpbWVyICxuY29sID0gMyxzaHJpbmsgPSBUKSAKICAgIyBmYWNldF9ncmlkKH5QcmltZXIgLGRyb3AgPSBUUlVFLCkKCiAKIGFsbF9zZk5qcV9ub3JtX3ByZXNlbmNlX3Bsb3QKCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvYWxsX3NmTmpxX25vcm1fcHJlc2VuY2VfcGxvdC5zdmciLCBwbG90ID0gYWxsX3NmTmpxX25vcm1fcHJlc2VuY2VfcGxvdCwgZGV2aWNlID0gInN2ZyIsIHdpZHRoID0gNDUsIGhlaWdodCA9IDQwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvYWxsX3NmTmpxX25vcm1fcHJlc2VuY2VfcGxvdF8ybm9ybXMucGRmIiwgcGxvdCA9IGFsbF9zZk5qcV9ub3JtX3ByZXNlbmNlX3Bsb3QsIGRldmljZSA9ICJwZGYiLCB3aWR0aCA9IDEwMCwgaGVpZ2h0ID0gNDAsIHVuaXRzID0gImNtIiwgZHBpID0gNjAwKQoKCgpzY2FsZXM6OnNob3dfY29sKGNvbG9yczUpCiAgCgoKYGBgCgojIyBETkEvUlJBIGNvcnJlbGF0aW9uIHBsb3RzCmBgYHtyIGVjaG89VFJVRSxldmFsPUZBTFNFfQoKY29sbmFtZXMoYWxsX3BzX3RibF9zZmpxX2Z1bGxfdW5pcSkKYWxsX3BzX3RibF9zZmpxX2Z1bGxfdW5pcSRHcm91cAphbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxJE1DCmFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEkTm9ybWFsaXphdGlvbgoKCgoKIyMjIyMjZnVuw6fDo28gcHJhIHBsb3RhciBsbQoKIyBsbV9lcW4gPC0gZnVuY3Rpb24oZGYpewojICAgICBtIDwtIGxtKHkgfiB4LCBkZik7CiMgICAgIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKHkpID09IGEgKyBiICUuJSBpdGFsaWMoeCkqIiwifn5pdGFsaWMocileMn4iPSJ+cjIsIAojICAgICAgICAgIGxpc3QoYSA9IGZvcm1hdCh1bm5hbWUoY29lZihtKVsxXSksIGRpZ2l0cyA9IDIpLAojICAgICAgICAgICAgICAgYiA9IGZvcm1hdCh1bm5hbWUoY29lZihtKVsyXSksIGRpZ2l0cyA9IDIpLAojICAgICAgICAgICAgICByMiA9IGZvcm1hdChzdW1tYXJ5KG0pJHIuc3F1YXJlZCwgZGlnaXRzID0gMykpKQojICAgICBhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpOwojIH0KCgoKCgojaW5jbGluYcOnw6NvIGRhcyByZXRhcyAtLS0tCgojTE0KIG1vZGVsc19jb3JyIDwtIGFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEgJT4lIAogICBmaWx0ZXIoTm9ybWFsaXphdGlvbiAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIikpICU+JSAKICAgIyBmaWx0ZXIoUHJpbWVyICVpbiUgYygiTmVvRmlzaCIpKSAlPiUgCiAgZ3JvdXBfYnkoUHJpbWVyLE1DKSAlPiUgCiAgIHNlbGVjdChjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbCIsICJSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlIikpICU+JSAKICBkbyhtb2RlbCA9IGxtKGZvcm11bGEgPSBgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2xgIH4gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgLCBkYXRhID0gLikpCiAgICMgbG0oZm9ybXVsYSA9IGBQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbGAgfiBgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApCiAgICMgYW92KGZvcm11bGEgPSBgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2xgIH4gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKQoKbW9kZWxzX2NvcnIkbW9kZWwKbW9kZWxzX2NvcnIkUHJpbWVyCm1vZGVsc19jb3JyJE1DCgoKCm1vZGVsc19jb3JyJG1vZGVsW1sxXV0gJT4lIGJyb29tOjpnbGFuY2UobW9kZWwpICNOZW9GaXNoIEpRbWMKbW9kZWxzX2NvcnIkbW9kZWxbWzJdXSAlPiUgYnJvb206OmdsYW5jZShtb2RlbCkgI05lb0Zpc2ggU0ZtYwptb2RlbHNfY29yciRtb2RlbFtbM11dICU+JSBicm9vbTo6Z2xhbmNlKG1vZGVsKSAjTWlGaXNoIEpRbWMKbW9kZWxzX2NvcnIkbW9kZWxbWzRdXSAlPiUgYnJvb206OmdsYW5jZShtb2RlbCkgI01pRmlzaCBTRm1jCm1vZGVsc19jb3JyJG1vZGVsW1s1XV0gJT4lIGJyb29tOjpnbGFuY2UobW9kZWwpICNUZWxlbyBKUW1jCgojQU9WCm1vZGVsc19jb3JyIDwtIGFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEgJT4lIAogICBmaWx0ZXIoTm9ybWFsaXphdGlvbiAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIikpICU+JSAKICAgIyBmaWx0ZXIoUHJpbWVyICVpbiUgYygiTmVvRmlzaCIpKSAlPiUgCiAgZ3JvdXBfYnkoUHJpbWVyKSAlPiUgCiAgIHNlbGVjdChjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbCIsICJSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlIikpICU+JSAKICBkbyhtb2RlbCA9IGFvdihmb3JtdWxhID0gYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCB+IGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCwgZGF0YSA9IC4pKQogICAjIGxtKGZvcm11bGEgPSBgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2xgIH4gYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKQogICAjIGFvdihmb3JtdWxhID0gYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCB+IGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCkKCm1vZGVsc19jb3JyJG1vZGVsCm1vZGVsc19jb3JyJFByaW1lcgoKbW9kZWxzX2NvcnIkbW9kZWxbWzFdXSAlPiUgYnJvb206OnRpZHkoKQptb2RlbHNfY29yciRtb2RlbFtbMl1dICU+JSBicm9vbTo6dGlkeSgpCm1vZGVsc19jb3JyJG1vZGVsW1szXV0gJT4lIGJyb29tOjp0aWR5KCkKCgoKI0pRbWMgLS0tLQojIGpxX2NvZWYgPC0gbG0oYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCB+IGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCwKIyAgICAoYWxsX3BzX3RibF9zZmpxX2Z1bGxfdW5pcSAlPiUgCiMgICAgICAgZmlsdGVyKE1DICVpbiUgYygiSlFtYyIpKSAlPiUgCiMgICAgICAgZmlsdGVyKE5vcm1hbGl6YXRpb24gJWluJSBjKCJOb24tbm9ybWFsaXplZCIpKSkpCgoKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHRlbnRhbmRvIGNvbSBhIHRpYiBjb20gbm9ybSBlIG4gbm9ybSBuYSBtZXNtYSBjb2x1bmEKdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgJT4lIGNvbG5hbWVzKCkKCgpzZmpxX3NwX2NvcnIgPC0KICB0YWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyAlPiUgCiAgZ2dwbG90KGFlcyh4PWBpbnB1dCBETkEgKCUpYCwKICAgICAgICAgICAgIHk9YFJSQSAoJSlgLAogICAgICAgICAgICAgY29sPVByaW1lciwKICAgICAgICAgICAgIHNoYXBlPVBvb2wpKSsKICBnZW9tX3BvaW50KCkgKyAKICAjIGdlb21fc21vb3RoKG1ldGhvZD1sbSkgKwogICMgY29vcmRfZml4ZWQoKSsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGFscGhhKGNvbG91ciA9IGNvbG9yc19ub3JtW2MoMSwzLDUpXSAsYWxwaGEgPSAgMC44KSkgKwogICMgc2NhbGVfc2hhcGVfbWFudWFsKGRyb3A9VFJVRSkgKwogIHhsYWIoIklucHV0IEROQSAoJSkiKSArCiAgeWxhYigiUmVsYXRpdmUgUmVhZCBBYnVuZGFuY2UgKCUpIikgKwogIGdndGl0bGUoIlNGbWMgJiBKUW1jOiBDb3JyZWxhdGlvbiBiZXR3ZWVuXG5JbnB1dCBETkEgYW5kIFJSQSIpICsKICBzY2FsZV94X3NxcnQoYnJlYWtzPWMoMCwwLjAwMDEsMC4wMDEsMC4wMSwwLjAyNSwwLjA1LDAuMSwwLjIsMC4zLDAuNCwwLjYsMC44LDEpKjEwMCkgKwogIHNjYWxlX3lfc3FydChicmVha3M9YygwLDAuMDAwMSwwLjAwMSwwLjAxLDAuMDI1LDAuMDUsMC4xLDAuMiwwLjMsMC40LDAuNiwwLjgsMSkqMTAwKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0pICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMCkgKwogICMgZmFjZXRfd3JhcChNQ35QcmltZXIsbmNvbCA9IDMpIAogIGZhY2V0X3dyYXAoUHJpbWVyfkdyb3VwLG5jb2wgPSA1KSAKIyArCiMgICBzY2FsZV94X2xvZzEwKCkgKwojICAgc2NhbGVfeV9sb2cxMCgpCiMgbWlub3JfYnJlYWtzID0gbWIKIyBtaW5vcl9icmVha3MgPSBtYgoKZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9maWdzL1NGSlFfUlJBX0ROQV9ieVNwMi5wbmciLCBwbG90ID0gc2ZqcV9zcF9jb3JyLCBkZXZpY2UgPSAicG5nIiwgd2lkdGggPSAzMCwgaGVpZ2h0ID0gMTUsIHVuaXRzID0gImNtIiwgZHBpID0gNjAwKQoKCgoKCgoKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCgoKCnNmanFfc3BfY29yciA8LSBhbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxICU+JSAKICAjIGZpbHRlcihNQyAlaW4lIGMoIkpRbWMiKSkgJT4lCiAgZmlsdGVyKE5vcm1hbGl6YXRpb24gJWluJSBjKCJOb24tbm9ybWFsaXplZCIpKSAlPiUKICAjIG11dGF0ZShgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2xgPSBpZl9lbHNlKGBQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbGAgJWluJSBjKE5BLCJOQSIpLDAsYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCkpICU+JSAKICAjIG11dGF0ZShgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWA9IGlmX2Vsc2UoYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgICVpbiUgYyhOQSwiTkEiKSwwLGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCkpICU+JSBWaWV3KCkKICAKICBnZ3Bsb3QoYWVzKHg9YFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCoxMDAsCiAgICAgICAgICAgICB5PWBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCoxMDAsCiAgICAgICAgICAgICBjb2w9UHJpbWVyLAogICAgICAgICAgICAgc2hhcGU9TUMKICAgICAgICAgICAgICkpKwogIGdlb21fcG9pbnQoKSArIAogICMgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSArCiAgIyBjb29yZF9maXhlZCgpKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYWxwaGEoY29sb3VyID0gY29sb3JzX25vcm1bYygxLDMsNSldICxhbHBoYSA9ICAwLjgpKSArCiAgIyBzY2FsZV9zaGFwZV9tYW51YWwoZHJvcD1UUlVFKSArCiAgeGxhYigiSW5wdXQgRE5BICglKSIpICsKICB5bGFiKCJSZWxhdGl2ZSBSZWFkIEFidW5kYW5jZSAoJSkiKSArCiAgZ2d0aXRsZSgiU0ZtYyAmIEpRbWM6IENvcnJlbGF0aW9uIGJldHdlZW5cbklucHV0IEROQSBhbmQgUlJBIikgKwogIHNjYWxlX3hfc3FydChicmVha3M9YygwLDAuMDAwMSwwLjAwMSwwLjAxLDAuMDI1LDAuMDUsMC4xLDAuMiwwLjMsMC40LDAuNiwwLjgsMSkqMTAwKSArCiAgc2NhbGVfeV9zcXJ0KGJyZWFrcz1jKDAsMC4wMDAxLDAuMDAxLDAuMDEsMC4wMjUsMC4wNSwwLjEsMC4yLDAuMywwLjQsMC42LDAuOCwxKSoxMDApICsKICBjb29yZF9maXhlZChyYXRpbyA9IDEpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwKSArCiAgIyBmYWNldF93cmFwKE1DflByaW1lcixuY29sID0gMykgCiAgZmFjZXRfd3JhcChQcmltZXJ+Tm9ybWFsaXphdGlvbixuY29sID0gMykgCiMgKwojICAgc2NhbGVfeF9sb2cxMCgpICsKIyAgIHNjYWxlX3lfbG9nMTAoKQojIG1pbm9yX2JyZWFrcyA9IG1iCiMgbWlub3JfYnJlYWtzID0gbWIKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9TRkpRX1JSQV9ETkFfYnlTcC5wbmciLCBwbG90ID0gc2ZqcV9zcF9jb3JyLCBkZXZpY2UgPSAicG5nIiwgd2lkdGggPSAzMCwgaGVpZ2h0ID0gMTUsIHVuaXRzID0gImNtIiwgZHBpID0gNjAwKQoKCgoKI1NGbWMgLS0tLQoKCmxpYnJhcnkoInBsb3RseSIpCgpzZl9zcF9jb3JyIDwtIGFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEgJT4lIAogIGZpbHRlcihNQyAlaW4lIGMoIlNGbWMiKSkgJT4lIAogIGZpbHRlcihOb3JtYWxpemF0aW9uICVpbiUgYygiTm9uLW5vcm1hbGl6ZWQiKSkgJT4lIAogICMgbXV0YXRlKGBQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbGA9IGlmX2Vsc2UoYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCAlaW4lIGMoTkEsIk5BIiksMCxgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2xgKSkgJT4lIAogICMgbXV0YXRlKGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYD0gaWZfZWxzZShgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAgJWluJSBjKE5BLCJOQSIpLDAsYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKSkgJT4lIFZpZXcoKQogIAogIGdncGxvdChhZXMoeD1gUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2xgKjEwMCwKICAgICAgICAgICAgIHk9YFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgKjEwMCwKICAgICAgICAgICAgIGNvbD1QcmltZXIsCiAgICAgICAgICAgICBzaGFwZT1NQykpKwogIGdlb21fcG9pbnQoKSArIAogICMgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSArCiAgIyBjb29yZF9maXhlZCgpKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYWxwaGEoY29sb3VyID0gY29sb3JzX25vcm1bYygxLDMsNSldICxhbHBoYSA9ICAwLjgpKSArCiAgeGxhYigiaW5wdXQgRE5BICglKSIpICsKICB5bGFiKCJSZWxhdGl2ZSBSZWFkIEFidW5kYW5jZSAoJSkiKSArCiAgZ2d0aXRsZSgiU0ZtYzogQ29ycmVsYXRpb24gYmV0d2VlblxuSW5wdXQgRE5BIGFuZCBSUkEiKSArCiAgc2NhbGVfeF9zcXJ0KGJyZWFrcz1jKDAsMC4wMDAxLDAuMDAxLDAuMDEsMC4wMjUsMC4wNSwwLjEsMC4yLDAuMywwLjQsMC42LDAuOCwxKSoxMDApICsKICBzY2FsZV95X3NxcnQoYnJlYWtzPWMoMCwwLjAwMDEsMC4wMDEsMC4wMSwwLjAyNSwwLjA1LDAuMSwwLjIsMC4zLDAuNCwwLjYsMC44LDEpKjEwMCkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTApICsKICBmYWNldF93cmFwKH5QcmltZXIsbmNvbCA9IDMpIAogICAgCiAgICAKICAgIAogICAgZ2dwbG90bHkoc2Zfc3BfY29ycikKCgpnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL2ZpZ3MvU0ZfUlJBX0ROQV9ieVNwLnBuZyIsIHBsb3QgPSBzZl9zcF9jb3JyLCBkZXZpY2UgPSAicG5nIiwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMTUsIHVuaXRzID0gImNtIiwgZHBpID0gNjAwKQoKCgpgYGAKCgoKCgojIyAgQWRpdGlvbmFsIEdyYXBoaWNzCmBgYHtyIGVjaG89VFJVRSxldmFsPUZBTFNFfQojIHNldCBjb2xvcnMgLS0tLQoKY29sb3JzNiA8LSBjKCIjMTk4MjFjIiwiIzhkYmM4ZiIsICNuZW8gbm9ybSAmIG5vbiBub3JtCiAgICAgICAgICAgICAiIzE3MWQ5YSIsIiM4ZDkwYzciLCAjbWlmIG5vcm0gJiBub24gbm9ybQogICAgICAgICAgICAgIiM4YzE3MTciLCIjYzE4ZDhkIiAgI3RlbCBub3JtICYgbm9uIG5vcm0KICAgICAgICAgICAgICkKCnNjYWxlczo6c2hvd19jb2woY29sb3JzNikKCgoKCgoKIyBjYXJyZWdhbmRvIHRhYmVsYSAKIyBodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xc1RzT2FJOTk5RTlQeV9mNGxsNWo4MzhyN0NWYzk5MWE4bVBtZDhMdnlrVS9lZGl0I2dpZD0wCgp0YWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyA8LSByZWFkLmNzdigifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9TRkpRX2FsbF9wb29scy10YWJlbGFzX2N1cmFkYXNfcGFyYV9vX1ItU0ZKUW1jLWNvcHkuY3N2IixjaGVjay5uYW1lcyA9IEYpICU+JSAKICBhc190aWJibGUoKQoKdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgPC0gdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgJT4lIAogICAgZmlsdGVyKGBpbnB1dCBETkEgKCUpYCAhPSAwICYgYFJSQSAoJSlgICE9MCkgJT4lCiAgZ3JvdXBfYnkoUG9vbCxOb3JtYWxpemF0aW9uLFByaW1lcixTcGVjaWVzKSAlPiUgCiAgc3VtbWFyaXplKFBvb2wgPSB1bmlxdWUoUG9vbCksCiAgICAgICAgICAgIE5vcm1hbGl6YXRpb24gPSB1bmlxdWUoTm9ybWFsaXphdGlvbiksCiAgICAgICAgICAgIFN0YXR1cyA9IHVuaXF1ZShTdGF0dXMpLAogICAgICAgICAgICBTcGVjaWVzID0gdW5pcXVlKFNwZWNpZXMpLAogICAgICAgICAgICBQcmltZXIgPSB1bmlxdWUoUHJpbWVyKSwKICAgICAgICAgICAgYE51bSBBU1ZzYCA9IGBOdW0gQVNWc2AsCiAgICAgICAgICAgIGBOdW0gT1RVc2AgPSBgTnVtIE9UVXNgLAogICAgICAgICAgICBgaW5wdXQgRE5BICglKWAgPSBgaW5wdXQgRE5BICglKWAsCiAgICAgICAgICAgIGBSUkEgKCUpYCA9IGBSUkEgKCUpYAogICAgICAgICAgICAjIGBFeHBlY3RlZCBzcGVjaWVzYCA9IGxlbmd0aCh1bmlxdWUoYHJldmlzZWQgZmluYWwgSURgW2BFeHBlY3RlZCBTcGVjaWVzYCAlaW4lIGMoImV4cGVjdGVkIildKSksCiAgICAgICAgICAgICMgYEV4cGVjdGVkIHNwZWNpZXMgbGlzdGAgPSBsaXN0KHVuaXF1ZShiYXNlOjpzb3J0KGByZXZpc2VkIGZpbmFsIElEYFtgRXhwZWN0ZWQgU3BlY2llc2AgJWluJSBjKCJleHBlY3RlZCIpXSkpKSwKICAgICAgICAgICAgIyBgcmV2aXNlZCBmaW5hbCBJRGA9IHVuaXF1ZShgcmV2aXNlZCBmaW5hbCBJRGApLAogICAgICAgICAgICAjIGBSUkEgKCUpYCA9IHN1bShgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApLAogICAgICAgICAgICAjIGBQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9ybSBwb29sYCA9IHVuaXF1ZShgUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbGApLAogICAgICAgICAgICAjIGBQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9uLW5vcm0gcG9vbGAgPSB1bmlxdWUoYFBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sYCksCiAgICAgICAgICAgICMgYFJlbGF0aXZlIGFidW5kYW5jZSBvbiBzYW1wbGVgID0gdW5pcXVlKGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCkKICAgICAgICAgICAgKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogICMgbXV0YXRlKGByZXZpc2VkIGZpbmFsIElEYD1mYWN0b3IoYHJldmlzZWQgZmluYWwgSURgCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICwgbGV2ZWxzID0gcmV2KGZpbmFsSURfbGV2ZWxzKQogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkgJT4lIAogIG11dGF0ZShQcmltZXIgPSBmYWN0b3IoUHJpbWVyLCBsZXZlbHMgPSBjKCJOZW9GaXNoIiwgIk1pRmlzaCIsICJUZWxlbyIsICJOZW9GaXNoL01pRmlzaCIsIk5lb0Zpc2gvTWlGaXNoL1RlbGVvIikpKSAlPiUgCiAgbXV0YXRlKGBGb2xkIGNoYW5nZSAoUlJBL0ROQSBpbnB1dClgID0gZ3Rvb2xzOjpmb2xkY2hhbmdlKGRlbm9tID0gYGlucHV0IEROQSAoJSlgLG51bSA9IGBSUkEgKCUpYCkpICU+JSAKICB1bmlxdWUoKQogICMgbXV0YXRlKEdyb3VwID0gZmFjdG9yKEdyb3VwLGxldmVscyA9IGMoIk5vcm1hbGl6ZWQgU0ZKUW1jIiwgIk5vbi1ub3JtYWxpemVkIEpRbWMiLCAiTm9ybWFsaXplZCBKUW1jIiwgIk5vbi1ub3JtYWxpemVkIFNGbWMiLCAiTm9ybWFsaXplZCBTRm1jIiApKSkgJT4lIAogICMgbXV0YXRlKE1DID0gc3RyX3JlbW92ZShHcm91cCwiTm9ybWFsaXplZCB8Tm9uLW5vcm1hbGl6ZWQgIikpICU+JSAKICAjIG11dGF0ZShOb3JtYWxpemF0aW9uID0gc3RyX3JlbW92ZShHcm91cCwiIFNGbWN8IEpRbWN8IFNGSlFtYyIpKSAKCgp0YWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyRgRm9sZCBjaGFuZ2UgKFJSQS9ETkEgaW5wdXQpYCAlPiUgc29ydCgpICU+JSBkdXBsaWNhdGVkKCkKCnRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzW2Mod2hpY2godGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMkYEZvbGQgY2hhbmdlIChSUkEvRE5BIGlucHV0KWAgJT4lIGFzLmNoYXJhY3RlcigpICU+JSBkdXBsaWNhdGVkKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWNoKHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzJGBGb2xkIGNoYW5nZSAoUlJBL0ROQSBpbnB1dClgICU+JSBhcy5jaGFyYWN0ZXIoKSAlPiUgZHVwbGljYXRlZCgpKS0xKSxdICU+JSBWaWV3KCkKCgoKCiMgU0ZKUW1jIC0tLS0KIyMgYnVpbGQgdHJlZSAtLS0tCiMjIyByZWFkIDEyUyBkYiBzZXFzIGZvciB0aGUgc3BlY2llcyBwcmVzZW50IGluIHBvb2xzClNGSlFfU3BzX3NlcXMgPC0gQmlvc3RyaW5nczo6cmVhZEROQVN0cmluZ1NldChmaWxlcGF0aCA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL1NGSlFtYy0zOF9TUHNfZnVzZWQtdW5pcXVlLmZhcyIpICU+JQojIFNGSlFfU3BzX3NlcXMgPC0gQmlvc3RyaW5nczo6cmVhZEROQVN0cmluZ1NldChmaWxlcGF0aCA9ICJ+L291dHJvcy9zZmpxX3RlbXAvdHJlZXMvU0ZKUW1jLTM4X1NQc19mdXNlZC11bmlxdWUuZmFzIikgJT4lIAogIERFQ0lQSEVSOjpSZW1vdmVHYXBzKCkKCiMjIyBhbGlnbiBzZXFzClNGSlFfU3BzX2FsZ24gPC0gREVDSVBIRVI6OkFsaWduU2VxcyhteVhTdHJpbmdTZXQgPSBTRkpRX1Nwc19zZXFzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZpbmVtZW50cyA9IDEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRpb25zID0gMTAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKIyMjIGdlbmVyYXRlIGRpc3RhbmNlIG1hdHJpeApTRkpRX1Nwc19kaXN0IDwtIERFQ0lQSEVSOjpEaXN0YW5jZU1hdHJpeChteVhTdHJpbmdTZXQgPSBTRkpRX1Nwc19hbGduLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVUZXJtaW5hbEdhcHMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uID0gIkp1a2VzLUNhbnRvciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc29ycyA9IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKIyMjIGdlbmVyYXRlIGRlbmRyb2dyYW0vdHJlZSBmcm9tIGFsaWdubWVudCBhbmQgZGlzdGFuY2UgbWF0cml4ClNGSlFtY190cmVlIDwtIGFwZTo6bmooU0ZKUV9TcHNfZGlzdCkKICAgICAgICAjIHRyZWUgPC0gcGhhbmdvcm46Ok5KKFNGSlFfU3BzX2Rpc3QpCmNsYXNzKFNGSlFtY190cmVlKQoKIyMjIHNhdmUgdHJlZSBhcyBuZXdpY2sKYXBlOjp3cml0ZS50cmVlKHBoeSA9IFNGSlFtY190cmVlLGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS90cmVlcy9TRkpRbWMtMzhfU1BzX2Z1c2VkLXVuaXF1ZV9BUEV0cmVlLm53ayIpCiMgYXBlOjp3cml0ZS50cmVlKHBoeSA9IFNGSlFtY190cmVlLGZpbGUgPSAifi9vdXRyb3Mvc2ZqcV90ZW1wL3RyZWVzL1NGSlFtYy0zOF9TUHNfZnVzZWQtdW5pcXVlX0FQRXRyZWUubndrIikKCiMjIyByZWFkIHRyZWUgZnJvbSBmaWxlIChvciBzdGF5IHdpdGggdGhlIHNhbWUgb2JqZWN0KQojIFNGSlFtY190cmVlIDwtIHJlYWQudHJlZSgifi9vdXRyb3Mvc2ZqcV90ZW1wL3RyZWVzL1NGSlFtYy0zOF9TUHNfZnVzZWQtdW5pcXVlX0FQRXRyZWUubndrIikKU0ZKUW1jX3RyZWUgPC0gcmVhZC50cmVlKCJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL1NGSlFtYy0zOF9TUHNfZnVzZWQtdW5pcXVlX0FQRXRyZWUubndrIikKCgojIyBzcGVjaWVzIG1ldGFkYXRhIC0tLS0KIyMjIHJlYWQgdGFibGUgd2l0aCBwb29scyBzcGVjaWVzLCBpbnB1dCBETkEgYW5kIFJSQQojIHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzIDwtIHJlYWQuY3N2KCJ+L291dHJvcy9zZmpxX3RlbXAvU0ZKUV9hbGxfcG9vbHMtdGFiZWxhc19jdXJhZGFzX3BhcmFfb19SLVNGSlFtYy5jc3YiLGNoZWNrLm5hbWVzID0gRikKIyB0YWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyA8LSByZWFkLmNzdigifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS9TRkpRX2FsbF9wb29scy10YWJlbGFzX2N1cmFkYXNfcGFyYV9vX1ItU0ZKUW1jLmNzdiIsY2hlY2submFtZXMgPSBGKSAlPiUgCiMgICBhc190aWJibGUoKQojIAojIHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzCgoKCgp0YWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyAlPiUgY29sbmFtZXMoKQp0YWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyAlPiUgdW5pcXVlKCkKYWxsX3BzX3RibF9zZmpxX2Z1bGxfdW5pcSAlPiUgY29sbmFtZXMoKQoKCgoKCiMgdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgIDwtIGFsbF9wc190Ymxfc2ZqcV9mdWxsX3VuaXEKCgoKI2NvbnZlcnRpbmcgdGhlIGNvcnJlY3RlZCB0YWJsZSB0byB0aGUgZm9ybWF0IHJlcXVpcmVkIGZvciBuZXh0IHN0ZXBzCgoKdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgPC0KICBhbGxfcHNfdGJsX3NmanFfZnVsbF91bmlxICU+JQogIHBpdm90X2xvbmdlcihjKCJQZXJjZW50YWdlIG9uIHJlc3BlY3RpdmUgTm9ybSBwb29sIiwgIlBlcmNlbnRhZ2Ugb24gcmVzcGVjdGl2ZSBOb24tbm9ybSBwb29sIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIkROQSBPcmlnaW5hcnkgUG9vbCIsIHZhbHVlc190byA9ICJpbnB1dCBETkEgKCUpIikgJT4lIAogIHBpdm90X2xvbmdlcihjKCJSZWNvdmVyZWQgcHJvcG9ydGlvbiBub3JtIiwgIlJlY292ZXJlZCBwcm9wb3J0aW9uIG5vbiBub3JtIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIkZvbGQgQ2hhbmdlIE9yaWdpbmFyeSBQb29sIiwgdmFsdWVzX3RvID0gIkZvbGQgQ2hhbmdlIikgJT4lIAogIHNlbGVjdCgtYygKICAgICMgIkROQSBPcmlnaW5hcnkgUG9vbCIsICJSUkEgT3JpZ2luYXJ5IFBvb2wiLAogICAgICAgICAgICAjICJTYW1wbGUsIgogICAgICAgICAgICAjICJHcm91cCIsCiAgICAgICAgICAgICJSdW4iCiAgICAgICAgICAgICkpICU+JSAKICAjIGNvbG5hbWVzKCkKICAjIFZpZXcoKQogIHJlbmFtZSgKICAgU3BlY2llcyA9IGByZXZpc2VkIGZpbmFsIElEYCwKICBgTnVtIE9UVXNgID0gYE9UVXNgLAogIGBOdW0gQVNWc2AgPSBgQVNWc2AsCiAgYE51bSBJRHNgID0gYElEc2AsCiAgIyBgUlJBICglKWAgPSBgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWAsCiAgIyBgRXhwZWN0ZWQgc3BlY2llc2AsIAogICMgYEV4cGVjdGVkIHNwZWNpZXMgbGlzdGAsCiAgIyBgRm9sZCBDaGFuZ2VgID0gYFJhdGlvYCwKICBgUG9vbGAgPSBgTUNgKSAlPiUKICBmaWx0ZXIoKGBETkEgT3JpZ2luYXJ5IFBvb2xgICVpbiUgYygiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vcm0gcG9vbCIpICYgYE5vcm1hbGl6YXRpb25gICVpbiUgYygiTm9ybWFsaXplZCIpKSB8CiAgICAgICAgICAgKGBETkEgT3JpZ2luYXJ5IFBvb2xgICVpbiUgYygiUGVyY2VudGFnZSBvbiByZXNwZWN0aXZlIE5vbi1ub3JtIHBvb2wiKSAmIGBOb3JtYWxpemF0aW9uYCAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIikpICkgJT4lIAogIGZpbHRlcigoYEZvbGQgQ2hhbmdlIE9yaWdpbmFyeSBQb29sYCAlaW4lIGMoIlJlY292ZXJlZCBwcm9wb3J0aW9uIG5vcm0iKSAmIGBOb3JtYWxpemF0aW9uYCAlaW4lIGMoIk5vcm1hbGl6ZWQiKSkgfAogICAgICAgICAgIChgRm9sZCBDaGFuZ2UgT3JpZ2luYXJ5IFBvb2xgICVpbiUgYygiUmVjb3ZlcmVkIHByb3BvcnRpb24gbm9uIG5vcm0iKSAmIGBOb3JtYWxpemF0aW9uYCAlaW4lIGMoIk5vbi1ub3JtYWxpemVkIikpICkgJT4lIAogIHNlbGVjdCgtYygiRE5BIE9yaWdpbmFyeSBQb29sIiwgIkZvbGQgQ2hhbmdlIE9yaWdpbmFyeSBQb29sIikpICU+JSAKICBtdXRhdGUoU3RhdHVzID0gaWZfZWxzZShgRXhwZWN0ZWQgc3BlY2llc2AgPT0gMCwgIkNvbnRhbWluYXRpb24iLCJFeHBlY3RlZCIpKSAlPiUgCiAgbXV0YXRlKGBSUkEgKCUpYCA9IGBSUkEgKCUpYCAqIDEwMCwKICAgICAgICAgYGlucHV0IEROQSAoJSlgID0gYGlucHV0IEROQSAoJSlgICogMTAwKSAlPiUgdW5pdGUoTm9ybWFsaXphdGlvbiwgUHJpbWVyLCBjb2wgPSAiUHJpbWVyX25vcm0iLHJlbW92ZSA9IEYsc2VwID0gIiAiKSAlPiUgCiAgbXV0YXRlKFByaW1lcl9ub3JtID0gZmFjdG9yKFByaW1lcl9ub3JtLCBsZXZlbHMgPSBjKCJOb3JtYWxpemVkIE5lb0Zpc2giLCJOb3JtYWxpemVkIE1pRmlzaCIsIk5vcm1hbGl6ZWQgVGVsZW8iLCJOb24tbm9ybWFsaXplZCBOZW9GaXNoIiwiTm9uLW5vcm1hbGl6ZWQgTWlGaXNoIiwiTm9uLW5vcm1hbGl6ZWQgVGVsZW8iKSkpICU+JSBWaWV3KCkKCiMgYWxsX3BzX3RibF9zZmpxX2Z1bGxfdW5pcSAlPiUgY29sbmFtZXMoKQoKCiAKCiMgdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHNbc29ydChjKHdoaWNoKHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzJGBGb2xkIENoYW5nZWAgJT4lIGFzLmNoYXJhY3RlcigpICU+JSBkdXBsaWNhdGVkKCkpLHdoaWNoKHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzJGBGb2xkIENoYW5nZWAlPiUgYXMuY2hhcmFjdGVyKCkgJT4lIGR1cGxpY2F0ZWQoKSktMSkpLF0gJT4lIFZpZXcoKQojIHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzW3RhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzJGBGb2xkIENoYW5nZWAgJT4lIGR1cGxpY2F0ZWQoKSxdICU+JSBWaWV3KCkKCiMjIyB0aWR5IHRhYmxlCnRhYl9jdXJhdGVkX1NGSlEgPC0gdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgZmlsdGVyKFN0YXR1cyA9PSAiRXhwZWN0ZWQiKSAlPiUKICBmaWx0ZXIoUG9vbCA9PSAiU0ZKUW1jIikgJT4lCiAgIyBmaWx0ZXIoTUMgPT0gIlNGSlFtYyIpICU+JSAKICAjIGZpbHRlcihQb29sID09ICJTRkpRbWMiKSAlPiUgCiAgbXV0YXRlKFByaW1lciA9IGZhY3RvcihQcmltZXIsIGxldmVscyA9IGMoIk5lb0Zpc2giLCJNaUZpc2giLCJUZWxlbyIpKSwKICAgICAgICAgU3BlY2llcyA9IGZhY3RvcihTcGVjaWVzKSwKICAgICAgICAgIyBgcmV2aXNlZCBmaW5hbCBJRGAgPSBmYWN0b3IoYHJldmlzZWQgZmluYWwgSURgKSwKICAgICAgICAgTm9ybWFsaXphdGlvbiA9IGZhY3RvcihOb3JtYWxpemF0aW9uKSwKICAgICAgICAgUG9vbCA9IGZhY3RvcihQb29sKSwKICAgICAgICAgU3RhdHVzID0gZmFjdG9yKFN0YXR1cyksCiAgICAgICAgICMgYFJSQSAoJSlgID0gYXMubnVtZXJpYyhgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApKjEwMCwKICAgICAgICAgYFJSQSAoJSlgID0gYXMubnVtZXJpYyhgUlJBICglKWApLAogICAgICAgICBgaW5wdXQgRE5BICglKWAgPSBhcy5udW1lcmljKGBpbnB1dCBETkEgKCUpYCkpCgoKIyMgY29ycmVjdCB0aXBzIGxhYmVscyAtLS0tCiMjIyBjaGVjayB0aXAgbmFtZXMgaW4gdHJlZQpTRkpRbWNfdHJlZSR0aXAubGFiZWwKCgojIyMgcmVuYW1lIHRyZWUgdGlwcyB0byBtYWNoIHRhYmxlClNGSlFtY190cmVlJHRpcC5sYWJlbAp0YWJfY3VyYXRlZF9TRkpRJFNwZWNpZXMgJT4lIHVuaXF1ZSgpICU+JSBzb3J0KCkKCnsKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTMzOV9Qcm9jaGlsb2R1c19jb3N0YXR1c19KUV8yODYwIl0gPC0gIlByb2NoaWxvZHVzIGNvc3RhdHVzIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV81NjEyX1Byb2NoaWxvZHVzX2FyZ2VudGV1c19oYXJ0aWkiXSA8LSAiUHJvY2hpbG9kdXMgYXJnZW50ZXVzL2hhcnRpaSIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfNjU4Nl9TdGVpbmRhY2huZXJpbmFfZWxlZ2Fucy1DeXBob2NoYXJheF9naWxiZXJ0Il0gPC0gIkN5cGhvY2hhcmF4IGdpbGJlcnQiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEyMzBfU2VycmFzYWxtdXNfYnJhbmR0aWkiXSA8LSAiU2VycmFzYWxtdXMgYnJhbmR0aWkiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzExNjJfTXlsZXVzX21pY2FucyJdIDwtICJNeWxldXMgbWljYW5zIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV8yOTg0X0h5cG9tYXN0aWN1c19zdGVpbmRhY2huZXJpIl0gPC0gIkh5cG9tYXN0aWN1cyBzdGVpbmRhY2huZXJpIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV80MjkwX01lZ2FsZXBvcmludXNfZ2FybWFuaSJdIDwtICJNZWdhbGVwb3JpbnVzIGdhcm1hbmkiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIkpRXzE3NjJfTWVnYWxlcG9yaW51c19lbG9uZ2F0dXMiXSA8LSAiTWVnYWxlcG9yaW51cyBlbG9uZ2F0dXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEwMzdfQnJ5Y29uX29ydGhvdGFlbmlhIl0gPC0gIkJyeWNvbiBvcnRob3RhZW5pYSIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTM4MV9DaGFyYWNpZGl1bV9sYWdvc2FudGVuc2UiXSA8LSAiQ2hhcmFjaWRpdW0gbGFnb3NhbnRlbnNlIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICIxMTM2X0FjZXN0cm9yaHluY2h1c19sYWN1c3RyaXMiXSA8LSAiQWNlc3Ryb3JoeW5jaHVzIGxhY3VzdHJpcyIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfNzgyMl9Ib3BsaWFzX21hbGFiYXJpY3VzIl0gPC0gIkhvcGxpYXMgbWFsYWJhcmljdXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEzNzdfSG9wbGlhc19pbnRlcm1lZGl1c19icmFzaWxpZW5zaXMiXSA8LSAiSG9wbGlhcyBicmFzaWxpZW5zaXMvaW50ZXJtZWRpdXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzA5MTZfUm9lYm9pZGVzX3hlbm9kb24iXSA8LSAiUm9lYm9pZGVzIHhlbm9kb24iClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzA5MDFfVGV0cmFnb25vcHRlcnVzX2NoYWxjZXVzIl0gPC0gIlRldHJhZ29ub3B0ZXJ1cyBjaGFsY2V1cyIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTExM19Nb2Vua2hhdXNpYV9zYW5jdGFlZmlsb21lbmFlIl0gPC0gIk1vZW5raGF1c2lhIHNhbmN0YWVmaWxvbWVuYWUiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGSlFfNzgxMl9Nb2Vua2hhdXNpYV9jb3N0YWUiXSA8LSAiTW9lbmtoYXVzaWEgY29zdGFlIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMTUzX0FzdHlhbmF4X2NmX2Zhc2NpYXR1cyJdIDwtICJBc3R5YW5heCBmYXNjaWF0dXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIkpRXzc4ODBfQXN0eWFuYXhfbGFjdXN0cmlzIl0gPC0gIkFzdHlhbmF4IGxhY3VzdHJpcyIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTE0MV9QdGVyeWdvcGxpY2h0aHlzX2V0ZW50YWN1bGF0dXMiXSA8LSAiUHRlcnlnb3BsaWNodGh5cyBldGVudGFjdWxhdHVzIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMDQxX0h5cG9zdG9tdXNfYWxhdHVzIl0gPC0gIkh5cG9zdG9tdXMgYWxhdHVzIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV83ODkzX0h5cG9zdG9tdXNfbmlncm9saW5lYXR1cyJdIDwtICJIeXBvc3RvbXVzIG5pZ3JvbGluZWF0dXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEyNDhfR3ltbm90dXNfY2FyYXBvX0pRXzE2MzEiXSA8LSAiR3ltbm90dXMgY2FyYXBvIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMTE3X0VpZ2VubWFubmlhX3ZpcmVzY2VucyJdIDwtICJFaWdlbm1hbm5pYSB2aXJlc2NlbnMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIkpRXzE5MzZfRGVsdHVydXNfYnJldmlzIl0gPC0gIkRlbHR1cnVzIGJyZXZpcyIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMDcwOF9GcmFuY2lzY29kb3Jhc19tYXJtb3JhdHVzIl0gPC0gIkZyYW5jaXNjb2RvcmFzIG1hcm1vcmF0dXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIkpRXzc4MTdfV2VydGhlaW1lcmlhX21hY3VsYXRhIl0gPC0gIldlcnRoZWltZXJpYSBtYWN1bGF0YSIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTI0M19UcmFjaGVseW9wdGVydXNfZ2FsZWF0dXNfSlFfNTY3NSJdIDwtICJUcmFjaGVseW9wdGVydXMgZ2FsZWF0dXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzE0MDNfUGltZWxvZHVzX3BvaGxpIl0gPC0gIlBpbWVsb2R1cyBwb2hsaSIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTI4MF9QaW1lbG9kdXNfbWFjdWxhdHVzIl0gPC0gIlBpbWVsb2R1cyBtYWN1bGF0dXMiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIjExMzVfUHNldWRvcGxhdHlzdG9tYV9jb3JydXNjYW5zIl0gPC0gIlBzZXVkb3BsYXR5c3RvbWEgY29ycnVzY2FucyIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfMjk5Nl9TdGVpbmRhY2huZXJpZGlvbl9hbWJseXVydW0iXSA8LSAiU3RlaW5kYWNobmVyaWRpb24gYW1ibHl1cnVtIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMTA0X01pY3JvZ2xhbmlzX2xlcHRvc3RyaWF0dXMiXSA8LSAiTWljcm9nbGFuaXMgbGVwdG9zdHJpYXR1cyIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTE2MV9JbXBhcmZpbmlzX21pbnV0dXMiXSA8LSAiSW1wYXJmaW5pcyBtaW51dHVzIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV81NjQ1X1JoYW1kaWFfYWZmX3F1ZWxlbiJdIDwtICJSaGFtZGlhIHF1ZWxlbiIKU0ZKUW1jX3RyZWUkdGlwLmxhYmVsW1NGSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZKUV8yOTQzX0V1Z2VycmVzX2JyYXNpbGlhbnVzIl0gPC0gIkV1Z2VycmVzIGJyYXNpbGlhbnVzIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMzY4X1BoYWxsb2Nlcm9zX3VhaSJdIDwtICJQaGFsbG9jZXJvcyB1YWkiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEwOTlfUGFtcGhvcmljaHRoeXNfaG9sbGFuZGkiXSA8LSAiUGFtcGhvcmljaHRoeXMgaG9sbGFuZGkiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEyNjRfQ3JlbmljaWNobGFfbGVwaWRvdGEiXSA8LSAiQ3JlbmljaWNobGEgbGVwaWRvdGEiClNGSlFtY190cmVlJHRpcC5sYWJlbFtTRkpRbWNfdHJlZSR0aXAubGFiZWwgPT0gIkpRXzY1ODRfQXVzdHJhbG9oZXJvc19zcCJdIDwtICJBdXN0cmFsb2hlcm9zIHNwIgpTRkpRbWNfdHJlZSR0aXAubGFiZWxbU0ZKUW1jX3RyZWUkdGlwLmxhYmVsID09ICIzMDRfR2VvcGhhZ3VzX2JyYXNpbGllbnNpcyJdIDwtICJHZW9waGFndXMgYnJhc2lsaWVuc2lzIgp9CgojIyMgY2hlY2sgaWYgYWxsIG5hbWVzIGhhdmUgY29ycmVzcG9uZGVuY2VzClNGSlFtY190cmVlJHRpcC5sYWJlbCAlaW4lIHRhYl9jdXJhdGVkX1NGSlEkU3BlY2llcwp0YWJfY3VyYXRlZF9TRkpRJFNwZWNpZXMgJWluJSBTRkpRbWNfdHJlZSR0aXAubGFiZWwKdGFiX2N1cmF0ZWRfU0ZKUSRTcGVjaWVzWyF0YWJfY3VyYXRlZF9TRkpRJFNwZWNpZXMgJWluJSBTRkpRbWNfdHJlZSR0aXAubGFiZWxdCgoKCgoKIyMjIGNvbnZlcnQgYXBlIHRyZWUgdG8gcHJldHRpZXIgZ2d0cmVlIG9iamVjdApTRkpRbWNfdHJlZV9wbG90IDwtIGdndHJlZShTRkpRbWNfdHJlZSkgKyAKICB0aGVtZV90cmVlMigpICsKICBnZW9tX3RpcGxhYihvZmZzZXQgPSAwLGFsaWduID0gVCkrIAogIHhsaW0oMCwgMC40MikKCgojIyMgc2F2ZSB0cmVlIHBsb3QKIyBnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL1NGSlFtYy0zOF9TUHNfZnVzZWQtdW5pcXVlLXRyZWVfcGxvdC5wZGYiLCBwbG90ID0gU0ZKUW1jX3RyZWVfcGxvdCwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gMjQsIGhlaWdodCA9IDI0LCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKZ2dzYXZlKGZpbGUgPSAifi9vdXRyb3Mvc2ZqcV90ZW1wL3RyZWVzL1NGSlFtYy0zOF9TUHNfZnVzZWQtdW5pcXVlLXRyZWVfcGxvdC5wZGYiLCBwbG90ID0gU0ZKUW1jX3RyZWVfcGxvdCwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gMjQsIGhlaWdodCA9IDI0LCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKCgoKIyMjIGV4dHJhY3QgdGlwcyBvcmRlciBmcm9tIHRyZWUgdG8gcmVwcm9kdWNlIG9uIHBsb3RzClNQc19vcmRlcl9pbl9TRkpRX3RyZWUgPC0gZ2d0cmVlOjpnZXRfdGF4YV9uYW1lKFNGSlFtY190cmVlX3Bsb3QpICU+JSByZXYoKQoKICAgICAgICAgICAgIyBTUHNfb3JkZXJfaW5fU0ZKUV90cmVlIDwtIGV4dHJhY3RfdHJlZV9kYXRhKHRyZWVfcGxvdCkgJT4lIAogICAgICAgICAgICAjICAgICBkcGx5cjo6ZmlsdGVyKGlzVGlwKSAlPiUgCiAgICAgICAgICAgICMgICAgIGRwbHlyOjpwdWxsKGxhYmVsKQoKCgojIyBwbG90cyAtLS0tCiMjIyBSUkEgaGlzdG9ncmFtIC0tLS0KCiMgbGlicmFyeShnZ2Rpc3QpCgoKClNGSlFtY19SUkFfcGxvdCA8LQogIHRhYl9jdXJhdGVkX1NGSlEgJT4lCiAgZmlsdGVyKFBvb2wgJWluJSBjKCJTRkpRbWMiKSkgJT4lIAogIG11dGF0ZShTcGVjaWVzID0gZmFjdG9yKFNwZWNpZXMsbGV2ZWxzID0gU1BzX29yZGVyX2luX1NGSlFfdHJlZSkpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBTcGVjaWVzLAogICAgICAgICAgICAgeCA9IGBSUkEgKCUpYCwKICAgICAgICAgICAgIGZpbGwgPSBQcmltZXIsIAogICAgICAgICAgICAgY29sID0gTm9ybWFsaXphdGlvbgogICAgICAgICAgICAgKSkrCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHNpemUgPSAwLjMsd2lkdGggPSAuNzUsCiAgICAgICAgICAgIyBhbHBoYSA9IDAuNywKICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHByZXNlcnZlID0gInNpbmdsZSIgLHdpZHRoID0gMS4xKSkgKwogICAgICAgICAgICMgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZWp1c3QocHJlc2VydmUgPSAic2luZ2xlIiAsd2lkdGggPSAxLjIpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwMDAwMDAiLCIjNzQ3NDc0IikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnM2W2MoMSwzKV0pICsKICBnZW9tX3BvaW50KGFlcyh5ID0gU3BlY2llcywKICAgICAgICAgICAgICAgICB4ID0gYGlucHV0IEROQSAoJSlgKSwKICAgICAgICAgICAgIHNoYXBlID0gInwiLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBjb2xvdXIgPSAiIzAwMDAwMCIpICsKICBzY2FsZV94X2JyZWFrKGMoMTMsIDMwKSwKICAgICAgICAgICAgICAgIHNjYWxlcyA9ICJmaXhlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPWMoMCw1LDEwLDEzLDMwLDMyKSkgKwogIAogIHhsYWIoIlJlbGF0aXZlIHJlYWQgYWJ1bmRhbmNlICglKSIpKyAKICAjIG9wdHMoYXhpcy50aXRsZS55ID0gdGhlbWVfdGV4dCh2anVzdD0tMC41KSkKIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0wLjUpKQoKIyMgc2F2ZSBwbG90IAoKIyBnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL1NGSlFtYy0zOF9TUHNfZnVzZWQtdW5pcXVlLVJSQV9iYXJwbG90LnBkZiIsIHBsb3QgPSBTRkpRbWNfUlJBX3Bsb3QsIGRldmljZSA9ICJwZGYiLCB3aWR0aCA9IDE4LCBoZWlnaHQgPSAyNCwgdW5pdHMgPSAiY20iLCBkcGkgPSA2MDApCmRldi5vZmYoKQpnZ3NhdmUoZmlsZSA9ICJ+L291dHJvcy9zZmpxX3RlbXAvdHJlZXMvU0ZKUW1jLTM4X1NQc19mdXNlZC11bmlxdWUtUlJBX2JhcnBsb3QucGRmIiwgcGxvdCA9IFNGSlFtY19SUkFfcGxvdCwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gMzAsIGhlaWdodCA9IDI0LCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKCgoKCiMgU0ZtYyAtLS0tCiMjIGJ1aWxkIHRyZWUgLS0tLQojIyMgcmVhZCAxMlMgZGIgc2VxcyBmb3IgdGhlIHNwZWNpZXMgcHJlc2VudCBpbiBwb29scyBhbmQgc2VsZWN0IG9ubHkgcG9vbCBzcGVjaWVzCm5hbWVzKFNGSlFfU3BzX3NlcXMpICU+JSBzb3J0KCkgJT4lIHBhc3RlMChjb2xsYXBzZSA9ICciLFxuIicpICU+JSBjYXQoKQoKU0ZfU3BzX3NlcXMgPC0gU0ZKUV9TcHNfc2Vxc1tjKCJTRl8wNzA4X0ZyYW5jaXNjb2RvcmFzX21hcm1vcmF0dXMiLCAiU0ZfMDkwMV9UZXRyYWdvbm9wdGVydXNfY2hhbGNldXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNGXzA5MTZfUm9lYm9pZGVzX3hlbm9kb24iLCAiU0ZfMTAzN19Ccnljb25fb3J0aG90YWVuaWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNGXzEwNDFfSHlwb3N0b211c19hbGF0dXMiLCAiU0ZfMTA5OV9QYW1waG9yaWNodGh5c19ob2xsYW5kaSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0ZfMTEwNF9NaWNyb2dsYW5pc19sZXB0b3N0cmlhdHVzIiwgIlNGXzExMTNfTW9lbmtoYXVzaWFfc2FuY3RhZWZpbG9tZW5hZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0ZfMTExN19FaWdlbm1hbm5pYV92aXJlc2NlbnMiLCAiU0ZfMTE0MV9QdGVyeWdvcGxpY2h0aHlzX2V0ZW50YWN1bGF0dXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNGXzExNTNfQXN0eWFuYXhfY2ZfZmFzY2lhdHVzIiwgIlNGXzExNjFfSW1wYXJmaW5pc19taW51dHVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRl8xMTYyX015bGV1c19taWNhbnMiLCAiU0ZfMTIzMF9TZXJyYXNhbG11c19icmFuZHRpaSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0ZfMTI0M19UcmFjaGVseW9wdGVydXNfZ2FsZWF0dXNfSlFfNTY3NSIsICJTRl8xMjQ4X0d5bW5vdHVzX2NhcmFwb19KUV8xNjMxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRl8xMjY0X0NyZW5pY2ljaGxhX2xlcGlkb3RhIiwgIlNGXzEyODBfUGltZWxvZHVzX21hY3VsYXR1cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0ZfMTMzOV9Qcm9jaGlsb2R1c19jb3N0YXR1c19KUV8yODYwIiwgIlNGXzEzNjhfUGhhbGxvY2Vyb3NfdWFpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRl8xMzc3X0hvcGxpYXNfaW50ZXJtZWRpdXNfYnJhc2lsaWVuc2lzIiwgIlNGXzEzODFfQ2hhcmFjaWRpdW1fbGFnb3NhbnRlbnNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRl8xNDAzX1BpbWVsb2R1c19wb2hsaSIpXQojIyMgYWxpZ24gc2VxcwpTRl9TcHNfYWxnbiA8LSBERUNJUEhFUjo6QWxpZ25TZXFzKG15WFN0cmluZ1NldCA9IFNGX1Nwc19zZXFzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZpbmVtZW50cyA9IDEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRpb25zID0gMTAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKIyMjIGdlbmVyYXRlIGRpc3RhbmNlIG1hdHJpeApTRl9TcHNfZGlzdCA8LSBERUNJUEhFUjo6RGlzdGFuY2VNYXRyaXgobXlYU3RyaW5nU2V0ID0gU0ZfU3BzX2FsZ24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZVRlcm1pbmFsR2FwcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlY3Rpb24gPSAiSnVrZXMtQ2FudG9yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzb3JzID0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IFRSVUUpCgojIyMgZ2VuZXJhdGUgZGVuZHJvZ3JhbS90cmVlIGZyb20gYWxpZ25tZW50IGFuZCBkaXN0YW5jZSBtYXRyaXgKU0ZtY190cmVlIDwtIGFwZTo6bmooU0ZfU3BzX2Rpc3QpCiAgICAgICAgIyB0cmVlIDwtIHBoYW5nb3JuOjpOSihTRkpRX1Nwc19kaXN0KQpjbGFzcyhTRm1jX3RyZWUpCgojIyMgc2F2ZSB0cmVlIGFzIG5ld2ljawojIGFwZTo6d3JpdGUudHJlZShwaHkgPSBTRm1jX3RyZWUsZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL1NGbWMtMjNfU1BzX2Z1c2VkLXVuaXF1ZV9BUEV0cmVlLm53ayIpCmFwZTo6d3JpdGUudHJlZShwaHkgPSBTRm1jX3RyZWUsZmlsZSA9ICJ+L291dHJvcy9zZmpxX3RlbXAvdHJlZXMvU0ZtYy0yM19TUHNfZnVzZWQtdW5pcXVlX0FQRXRyZWUubndrIikKCiMjIyByZWFkIHRyZWUgZnJvbSBmaWxlIChvciBzdGF5IHdpdGggdGhlIHNhbWUgb2JqZWN0KQpTRm1jX3RyZWUgPC0gcmVhZC50cmVlKCJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL1NGbWMtMjNfU1BzX2Z1c2VkLXVuaXF1ZV9BUEV0cmVlLm53ayIpClNGbWNfdHJlZSA8LSByZWFkLnRyZWUoIn4vb3V0cm9zL3NmanFfdGVtcC90cmVlcy9TRm1jLTIzX1NQc19mdXNlZC11bmlxdWVfQVBFdHJlZS5ud2siKQoKIyMgc3BlY2llcyBtZXRhZGF0YSAtLS0tCiMjIyByZWFkIHRhYmxlIHdpdGggcG9vbHMgc3BlY2llcywgaW5wdXQgRE5BIGFuZCBSUkEKCiMjIyB0aWR5IHRhYmxlCnRhYl9jdXJhdGVkX1NGIDwtIHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzICU+JSAKICBmaWx0ZXIoUG9vbCAlaW4lIGMoIlNGbWMiKSkgJT4lIAogIGZpbHRlcihTdGF0dXMgJWluJSBjKCJFeHBlY3RlZCIpKSAlPiUKICAjIGZpbHRlcihNQyA9PSAiU0ZKUW1jIikgJT4lIAogICMgZmlsdGVyKFBvb2wgPT0gIlNGSlFtYyIpICU+JSAKICBtdXRhdGUoUHJpbWVyID0gZmFjdG9yKFByaW1lciwgbGV2ZWxzID0gYygiTmVvRmlzaCIsIk1pRmlzaCIsIlRlbGVvIikpLAogICAgICAgICBTcGVjaWVzID0gZmFjdG9yKFNwZWNpZXMpLAogICAgICAgICAjIGByZXZpc2VkIGZpbmFsIElEYCA9IGZhY3RvcihgcmV2aXNlZCBmaW5hbCBJRGApLAogICAgICAgICBOb3JtYWxpemF0aW9uID0gZmFjdG9yKE5vcm1hbGl6YXRpb24pLAogICAgICAgICBQb29sID0gZmFjdG9yKFBvb2wpLAogICAgICAgICBTdGF0dXMgPSBmYWN0b3IoU3RhdHVzKSwKICAgICAgICAgIyBgUlJBICglKWAgPSBhcy5udW1lcmljKGBSZWxhdGl2ZSBhYnVuZGFuY2Ugb24gc2FtcGxlYCkqMTAwLAogICAgICAgICBgUlJBICglKWAgPSBhcy5udW1lcmljKGBSUkEgKCUpYCksCiAgICAgICAgIGBpbnB1dCBETkEgKCUpYCA9IGFzLm51bWVyaWMoYGlucHV0IEROQSAoJSlgKSkKCgojIyBjb3JyZWN0IHRpcHMgbGFiZWxzIC0tLS0KIyMjIGNoZWNrIHRpcCBuYW1lcyBpbiB0cmVlClNGbWNfdHJlZSR0aXAubGFiZWwKCgojIyMgcmVuYW1lIHRyZWUgdGlwcyB0byBtYWNoIHRhYmxlClNGbWNfdHJlZSR0aXAubGFiZWwKdGFiX2N1cmF0ZWRfU0YkU3BlY2llcyAlPiUgdW5pcXVlKCkgJT4lIHNvcnQoKQoKewpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEzMzlfUHJvY2hpbG9kdXNfY29zdGF0dXNfSlFfMjg2MCJdIDwtICJQcm9jaGlsb2R1cyBjb3N0YXR1cyIKU0ZtY190cmVlJHRpcC5sYWJlbFtTRm1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMjMwX1NlcnJhc2FsbXVzX2JyYW5kdGlpIl0gPC0gIlNlcnJhc2FsbXVzIGJyYW5kdGlpIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzExNjJfTXlsZXVzX21pY2FucyJdIDwtICJNeWxldXMgbWljYW5zIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEwMzdfQnJ5Y29uX29ydGhvdGFlbmlhIl0gPC0gIkJyeWNvbiBvcnRob3RhZW5pYSIKU0ZtY190cmVlJHRpcC5sYWJlbFtTRm1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMzgxX0NoYXJhY2lkaXVtX2xhZ29zYW50ZW5zZSJdIDwtICJDaGFyYWNpZGl1bSBsYWdvc2FudGVuc2UiClNGbWNfdHJlZSR0aXAubGFiZWxbU0ZtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTM3N19Ib3BsaWFzX2ludGVybWVkaXVzX2JyYXNpbGllbnNpcyJdIDwtICJIb3BsaWFzIGludGVybWVkaXVzIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzA5MTZfUm9lYm9pZGVzX3hlbm9kb24iXSA8LSAiUm9lYm9pZGVzIHhlbm9kb24iClNGbWNfdHJlZSR0aXAubGFiZWxbU0ZtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMDkwMV9UZXRyYWdvbm9wdGVydXNfY2hhbGNldXMiXSA8LSAiVGV0cmFnb25vcHRlcnVzIGNoYWxjZXVzIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzExMTNfTW9lbmtoYXVzaWFfc2FuY3RhZWZpbG9tZW5hZSJdIDwtICJNb2Vua2hhdXNpYSBzYW5jdGFlZmlsb21lbmFlIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzExNTNfQXN0eWFuYXhfY2ZfZmFzY2lhdHVzIl0gPC0gIkFzdHlhbmF4IGZhc2NpYXR1cyIKU0ZtY190cmVlJHRpcC5sYWJlbFtTRm1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMTQxX1B0ZXJ5Z29wbGljaHRoeXNfZXRlbnRhY3VsYXR1cyJdIDwtICJQdGVyeWdvcGxpY2h0aHlzIGV0ZW50YWN1bGF0dXMiClNGbWNfdHJlZSR0aXAubGFiZWxbU0ZtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTA0MV9IeXBvc3RvbXVzX2FsYXR1cyJdIDwtICJIeXBvc3RvbXVzIGFsYXR1cyIKU0ZtY190cmVlJHRpcC5sYWJlbFtTRm1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMjQ4X0d5bW5vdHVzX2NhcmFwb19KUV8xNjMxIl0gPC0gIkd5bW5vdHVzIGNhcmFwbyIKU0ZtY190cmVlJHRpcC5sYWJlbFtTRm1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMTE3X0VpZ2VubWFubmlhX3ZpcmVzY2VucyJdIDwtICJFaWdlbm1hbm5pYSB2aXJlc2NlbnMiClNGbWNfdHJlZSR0aXAubGFiZWxbU0ZtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMDcwOF9GcmFuY2lzY29kb3Jhc19tYXJtb3JhdHVzIl0gPC0gIkZyYW5jaXNjb2RvcmFzIG1hcm1vcmF0dXMiClNGbWNfdHJlZSR0aXAubGFiZWxbU0ZtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTI0M19UcmFjaGVseW9wdGVydXNfZ2FsZWF0dXNfSlFfNTY3NSJdIDwtICJUcmFjaGVseW9wdGVydXMgZ2FsZWF0dXMiClNGbWNfdHJlZSR0aXAubGFiZWxbU0ZtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTQwM19QaW1lbG9kdXNfcG9obGkiXSA8LSAiUGltZWxvZHVzIHBvaGxpIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzEyODBfUGltZWxvZHVzX21hY3VsYXR1cyJdIDwtICJQaW1lbG9kdXMgbWFjdWxhdHVzIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzExMDRfTWljcm9nbGFuaXNfbGVwdG9zdHJpYXR1cyJdIDwtICJNaWNyb2dsYW5pcyBsZXB0b3N0cmlhdHVzIgpTRm1jX3RyZWUkdGlwLmxhYmVsW1NGbWNfdHJlZSR0aXAubGFiZWwgPT0gIlNGXzExNjFfSW1wYXJmaW5pc19taW51dHVzIl0gPC0gIkltcGFyZmluaXMgbWludXR1cyIKU0ZtY190cmVlJHRpcC5sYWJlbFtTRm1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMzY4X1BoYWxsb2Nlcm9zX3VhaSJdIDwtICJQaGFsbG9jZXJvcyB1YWkiClNGbWNfdHJlZSR0aXAubGFiZWxbU0ZtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTA5OV9QYW1waG9yaWNodGh5c19ob2xsYW5kaSJdIDwtICJQYW1waG9yaWNodGh5cyBob2xsYW5kaSIKU0ZtY190cmVlJHRpcC5sYWJlbFtTRm1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMjY0X0NyZW5pY2ljaGxhX2xlcGlkb3RhIl0gPC0gIkNyZW5pY2ljaGxhIGxlcGlkb3RhIgp9CgojIyMgY2hlY2sgaWYgYWxsIG5hbWVzIGhhdmUgY29ycmVzcG9uZGVuY2VzClNGbWNfdHJlZSR0aXAubGFiZWwgJWluJSB0YWJfY3VyYXRlZF9TRiRTcGVjaWVzCnRhYl9jdXJhdGVkX1NGJFNwZWNpZXMgJWluJSBTRm1jX3RyZWUkdGlwLmxhYmVsCnRhYl9jdXJhdGVkX1NGJFNwZWNpZXNbIXRhYl9jdXJhdGVkX1NGJFNwZWNpZXMgJWluJSBTRm1jX3RyZWUkdGlwLmxhYmVsXQoKCgoKCiMjIyBjb252ZXJ0IGFwZSB0cmVlIHRvIHByZXR0aWVyIGdndHJlZSBvYmplY3QKU0ZtY190cmVlX3Bsb3QgPC0gZ2d0cmVlKFNGbWNfdHJlZSkgKyAKICB0aGVtZV90cmVlMigpICsKICBnZW9tX3RpcGxhYihvZmZzZXQgPSAwLGFsaWduID0gVCkrIAogIHhsaW0oMCwgMC40MikKCgojIyMgc2F2ZSB0cmVlIHBsb3QKIyBnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL1NGbWMtMjNfU1BzX2Z1c2VkLXVuaXF1ZS10cmVlX3Bsb3QucGRmIiwgCmdnc2F2ZShmaWxlID0gIn4vb3V0cm9zL3NmanFfdGVtcC90cmVlcy9TRm1jLTIzX1NQc19mdXNlZC11bmlxdWUtdHJlZV9wbG90LnBkZiIsIAogICAgICAgcGxvdCA9IFNGbWNfdHJlZV9wbG90LCAKICAgICAgIGRldmljZSA9ICJwZGYiLCAKICAgICAgIHdpZHRoID0gMjQsIGhlaWdodCA9IDIwLCAKICAgICAgIHVuaXRzID0gImNtIiwgZHBpID0gNjAwKQoKCgojIyMgZXh0cmFjdCB0aXBzIG9yZGVyIGZyb20gdHJlZSB0byByZXByb2R1Y2Ugb24gcGxvdHMKU1BzX29yZGVyX2luX1NGX3RyZWUgPC0gZ2V0X3RheGFfbmFtZShTRm1jX3RyZWVfcGxvdCkgJT4lIHJldigpCgogICAgICAgICAgICAjIFNQc19vcmRlcl9pbl9TRl90cmVlIDwtIGV4dHJhY3RfdHJlZV9kYXRhKHRyZWVfcGxvdCkgJT4lIAogICAgICAgICAgICAjICAgICBkcGx5cjo6ZmlsdGVyKGlzVGlwKSAlPiUgCiAgICAgICAgICAgICMgICAgIGRwbHlyOjpwdWxsKGxhYmVsKQoKCgoKIyMgcGxvdHMgLS0tLQojIyMgUlJBIGhpc3RvZ3JhbSAtLS0tCgpTRm1jX1JSQV9wbG90IDwtCiAgdGFiX2N1cmF0ZWRfU0YgJT4lCiAgIyBmaWx0ZXIoTm9ybWFsaXphdGlvbiAlaW4lIGMoIk5vcm1hbGl6ZWQiKSkgJT4lCiAgdW5pdGUoTm9ybWFsaXphdGlvbiwgUHJpbWVyLCBjb2wgPSAiUHJpbWVyX25vcm0iLHJlbW92ZSA9IEYsc2VwID0gIiAiKSAlPiUKICBtdXRhdGUoUHJpbWVyX25vcm0gPSBmYWN0b3IoUHJpbWVyX25vcm0sIGxldmVscyA9IGMoIk5vcm1hbGl6ZWQgTmVvRmlzaCIsIk5vcm1hbGl6ZWQgTWlGaXNoIiwiTm9uLW5vcm1hbGl6ZWQgTmVvRmlzaCIsIk5vbi1ub3JtYWxpemVkIE1pRmlzaCIpKSkgJT4lCiAgbXV0YXRlKFNwZWNpZXMgPSBmYWN0b3IoU3BlY2llcyxsZXZlbHMgPSBTUHNfb3JkZXJfaW5fU0ZfdHJlZSkpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBTcGVjaWVzLAogICAgICAgICAgICAgeCA9IGBSUkEgKCUpYCwKICAgICAgICAgICAgICMgZmlsbCA9IFByaW1lciwgCiAgICAgICAgICAgICBmaWxsID0gUHJpbWVyX25vcm0sIAogICAgICAgICAgICAgY29sID0gTm9ybWFsaXphdGlvbgogICAgICAgICAgICAgKSkrCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHNpemUgPSAwLjMsd2lkdGggPSAxLAogICAgICAgICAgICMgYWxwaGEgPSAwLjcsCiAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZShwcmVzZXJ2ZSA9ICJzaW5nbGUiICx3aWR0aCA9IDEuNSkpICsKICAgICAgICAgICAjIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2VqdXN0KHByZXNlcnZlID0gInNpbmdsZSIgLHdpZHRoID0gMS4yKSkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JzNltjKDEsMywyLDQpXSwgbmFtZSA9ICIiKSArCiAgZ2VvbV9wb2ludChhZXMoeSA9IFNwZWNpZXMsCiAgICAgICAgICAgICAgICAgeCA9IGBpbnB1dCBETkEgKCUpYCwKICAgICAgICAgICAgIGNvbG91ciA9IE5vcm1hbGl6YXRpb24pLAogICAgICAgICAgICAgc2hhcGUgPSAifCIsCiAgICAgICAgICAgICBzaXplID0gMykgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM3NDc0NzQiLCIjMDAwMDAwIikpICsKICB4bGFiKCJSZWxhdGl2ZSByZWFkIGFidW5kYW5jZSAoJSkiKSAKIyArCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzAwMDAwMCIsIiM4NDg0ODQiKSkKCiMjIHNhdmUgcGxvdCAKCiMgZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS90cmVlcy9TRm1jLTIzX1NQc19mdXNlZC11bmlxdWUtUlJBX2JhcnBsb3QucGRmIiwgCiMgICAgICBwbG90ID0gU0ZtY19SUkFfcGxvdCwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gMjQsIGhlaWdodCA9IDIwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKZ2dzYXZlKGZpbGUgPSAifi9vdXRyb3Mvc2ZqcV90ZW1wL3RyZWVzL1NGbWMtMjNfU1BzX2Z1c2VkLXVuaXF1ZS1SUkFfYmFycGxvdC5wZGYiLCAKICAgICAgIHBsb3QgPSBTRm1jX1JSQV9wbG90LCBkZXZpY2UgPSAicGRmIiwgd2lkdGggPSAzMCwgaGVpZ2h0ID0gMzAsIHVuaXRzID0gImNtIiwgZHBpID0gNjAwKQoKCgojIEpRbWMgLS0tLQoKIyMgYnVpbGQgdHJlZSAtLS0tCiMjIyByZWFkIDEyUyBkYiBzZXFzIGZvciB0aGUgc3BlY2llcyBwcmVzZW50IGluIHBvb2xzIGFuZCBzZWxlY3Qgb25seSBwb29sIHNwZWNpZXMKbmFtZXMoU0ZKUV9TcHNfc2VxcykgJT4lIHNvcnQoKSAlPiUgcGFzdGUwKGNvbGxhcHNlID0gJyIsXG4iJykgJT4lIGNhdCgpCgpKUV9TcHNfc2VxcyA8LSBTRkpRX1Nwc19zZXFzW2MoIkpRXzE3NjJfTWVnYWxlcG9yaW51c19lbG9uZ2F0dXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkpRXzE5MzZfRGVsdHVydXNfYnJldmlzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKUV8yOTg0X0h5cG9tYXN0aWN1c19zdGVpbmRhY2huZXJpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKUV8yOTk2X1N0ZWluZGFjaG5lcmlkaW9uX2FtYmx5dXJ1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSlFfNDI5MF9NZWdhbGVwb3JpbnVzX2dhcm1hbmkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkpRXzU2MTJfUHJvY2hpbG9kdXNfYXJnZW50ZXVzX2hhcnRpaSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSlFfNTY0NV9SaGFtZGlhX2FmZl9xdWVsZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkpRXzY1ODRfQXVzdHJhbG9oZXJvc19zcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSlFfNjU4Nl9TdGVpbmRhY2huZXJpbmFfZWxlZ2Fucy1DeXBob2NoYXJheF9naWxiZXJ0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKUV83ODE3X1dlcnRoZWltZXJpYV9tYWN1bGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSlFfNzgyMl9Ib3BsaWFzX21hbGFiYXJpY3VzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJKUV83ODgwX0FzdHlhbmF4X2xhY3VzdHJpcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSlFfNzg5M19IeXBvc3RvbXVzX25pZ3JvbGluZWF0dXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNGXzEyNDNfVHJhY2hlbHlvcHRlcnVzX2dhbGVhdHVzX0pRXzU2NzUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNGXzEyNDhfR3ltbm90dXNfY2FyYXBvX0pRXzE2MzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNGXzEzMzlfUHJvY2hpbG9kdXNfY29zdGF0dXNfSlFfMjg2MCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0ZfMTM3N19Ib3BsaWFzX2ludGVybWVkaXVzX2JyYXNpbGllbnNpcyIpXQojIyMgYWxpZ24gc2VxcwpKUV9TcHNfYWxnbiA8LSBERUNJUEhFUjo6QWxpZ25TZXFzKG15WFN0cmluZ1NldCA9IEpRX1Nwc19zZXFzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWZpbmVtZW50cyA9IDEwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRpb25zID0gMTAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFKQoKIyMjIGdlbmVyYXRlIGRpc3RhbmNlIG1hdHJpeApKUV9TcHNfZGlzdCA8LSBERUNJUEhFUjo6RGlzdGFuY2VNYXRyaXgobXlYU3RyaW5nU2V0ID0gSlFfU3BzX2FsZ24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZVRlcm1pbmFsR2FwcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlY3Rpb24gPSAiSnVrZXMtQ2FudG9yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzb3JzID0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IFRSVUUpCgojIyMgZ2VuZXJhdGUgZGVuZHJvZ3JhbS90cmVlIGZyb20gYWxpZ25tZW50IGFuZCBkaXN0YW5jZSBtYXRyaXgKSlFtY190cmVlIDwtIGFwZTo6bmooSlFfU3BzX2Rpc3QpCiAgICAgICAgIyB0cmVlIDwtIHBoYW5nb3JuOjpOSihTRkpRX1Nwc19kaXN0KQpjbGFzcyhKUW1jX3RyZWUpCgojIyMgc2F2ZSB0cmVlIGFzIG5ld2ljawojIGFwZTo6d3JpdGUudHJlZShwaHkgPSBKUW1jX3RyZWUsZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL0pRbWMtMjNfU1BzX2Z1c2VkLXVuaXF1ZV9BUEV0cmVlLm53ayIpCmFwZTo6d3JpdGUudHJlZShwaHkgPSBKUW1jX3RyZWUsZmlsZSA9ICJ+L291dHJvcy9zZmpxX3RlbXAvdHJlZXMvSlFtYy0yM19TUHNfZnVzZWQtdW5pcXVlX0FQRXRyZWUubndrIikKCiMjIyByZWFkIHRyZWUgZnJvbSBmaWxlIChvciBzdGF5IHdpdGggdGhlIHNhbWUgb2JqZWN0KQpKUW1jX3RyZWUgPC0gcmVhZC50cmVlKCJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL0pRbWMtMjNfU1BzX2Z1c2VkLXVuaXF1ZV9BUEV0cmVlLm53IikKIyBKUW1jX3RyZWUgPC0gcmVhZC50cmVlKCJ+L291dHJvcy9zZmpxX3RlbXAvdHJlZXMvSlFtYy0yM19TUHNfZnVzZWQtdW5pcXVlX0FQRXRyZWUubndrIikKCiMjIHNwZWNpZXMgbWV0YWRhdGEgLS0tLQojIyMgcmVhZCB0YWJsZSB3aXRoIHBvb2xzIHNwZWNpZXMsIGlucHV0IEROQSBhbmQgUlJBCgojIyMgdGlkeSB0YWJsZQp0YWJfY3VyYXRlZF9KUSA8LSB0YWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyAlPiUgCiAgZmlsdGVyKFBvb2wgJWluJSBjKCJKUW1jIikpICU+JSAKICBmaWx0ZXIoU3RhdHVzICVpbiUgYygiRXhwZWN0ZWQiKSkgJT4lCiAgIyBmaWx0ZXIoTUMgPT0gIlNGSlFtYyIpICU+JSAKICAjIGZpbHRlcihQb29sID09ICJTRkpRbWMiKSAlPiUgCiAgbXV0YXRlKFByaW1lciA9IGZhY3RvcihQcmltZXIsIGxldmVscyA9IGMoIk5lb0Zpc2giLCJNaUZpc2giLCJUZWxlbyIpKSwKICAgICAgICAgU3BlY2llcyA9IGZhY3RvcihTcGVjaWVzKSwKICAgICAgICAgIyBgcmV2aXNlZCBmaW5hbCBJRGAgPSBmYWN0b3IoYHJldmlzZWQgZmluYWwgSURgKSwKICAgICAgICAgTm9ybWFsaXphdGlvbiA9IGZhY3RvcihOb3JtYWxpemF0aW9uKSwKICAgICAgICAgUG9vbCA9IGZhY3RvcihQb29sKSwKICAgICAgICAgU3RhdHVzID0gZmFjdG9yKFN0YXR1cyksCiAgICAgICAgICMgYFJSQSAoJSlgID0gYXMubnVtZXJpYyhgUmVsYXRpdmUgYWJ1bmRhbmNlIG9uIHNhbXBsZWApKjEwMCwKICAgICAgICAgYFJSQSAoJSlgID0gYXMubnVtZXJpYyhgUlJBICglKWApLAogICAgICAgICBgaW5wdXQgRE5BICglKWAgPSBhcy5udW1lcmljKGBpbnB1dCBETkEgKCUpYCkpCgoKIyMgY29ycmVjdCB0aXBzIGxhYmVscyAtLS0tCiMjIyBjaGVjayB0aXAgbmFtZXMgaW4gdHJlZQpKUW1jX3RyZWUkdGlwLmxhYmVsCgoKIyMjIHJlbmFtZSB0cmVlIHRpcHMgdG8gbWFjaCB0YWJsZQpKUW1jX3RyZWUkdGlwLmxhYmVsCnRhYl9jdXJhdGVkX0pRJFNwZWNpZXMgJT4lIHVuaXF1ZSgpICU+JSBzb3J0KCkKCnsKSlFtY190cmVlJHRpcC5sYWJlbFtKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMzM5X1Byb2NoaWxvZHVzX2Nvc3RhdHVzX0pRXzI4NjAiXSA8LSAiUHJvY2hpbG9kdXMgY29zdGF0dXMiCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfNTYxMl9Qcm9jaGlsb2R1c19hcmdlbnRldXNfaGFydGlpIl0gPC0gIlByb2NoaWxvZHVzIGFyZ2VudGV1cy9oYXJ0aWkiCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfNjU4Nl9TdGVpbmRhY2huZXJpbmFfZWxlZ2Fucy1DeXBob2NoYXJheF9naWxiZXJ0Il0gPC0gIkN5cGhvY2hhcmF4IGdpbGJlcnQiCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfMjk4NF9IeXBvbWFzdGljdXNfc3RlaW5kYWNobmVyaSJdIDwtICJIeXBvbWFzdGljdXMgc3RlaW5kYWNobmVyaSIKSlFtY190cmVlJHRpcC5sYWJlbFtKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV80MjkwX01lZ2FsZXBvcmludXNfZ2FybWFuaSJdIDwtICJNZWdhbGVwb3JpbnVzIGdhcm1hbmkiCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfMTc2Ml9NZWdhbGVwb3JpbnVzX2Vsb25nYXR1cyJdIDwtICJNZWdhbGVwb3JpbnVzIGVsb25nYXR1cyIKSlFtY190cmVlJHRpcC5sYWJlbFtKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV83ODIyX0hvcGxpYXNfbWFsYWJhcmljdXMiXSA8LSAiSG9wbGlhcyBtYWxhYmFyaWN1cyIKSlFtY190cmVlJHRpcC5sYWJlbFtKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMzc3X0hvcGxpYXNfaW50ZXJtZWRpdXNfYnJhc2lsaWVuc2lzIl0gPC0gIkhvcGxpYXMgYnJhc2lsaWVuc2lzIgpKUW1jX3RyZWUkdGlwLmxhYmVsW0pRbWNfdHJlZSR0aXAubGFiZWwgPT0gIkpRXzc4ODBfQXN0eWFuYXhfbGFjdXN0cmlzIl0gPC0gIkFzdHlhbmF4IGxhY3VzdHJpcyIKSlFtY190cmVlJHRpcC5sYWJlbFtKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV83ODkzX0h5cG9zdG9tdXNfbmlncm9saW5lYXR1cyJdIDwtICJIeXBvc3RvbXVzIG5pZ3JvbGluZWF0dXMiCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiU0ZfMTI0OF9HeW1ub3R1c19jYXJhcG9fSlFfMTYzMSJdIDwtICJHeW1ub3R1cyBjYXJhcG8iCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfMTkzNl9EZWx0dXJ1c19icmV2aXMiXSA8LSAiRGVsdHVydXMgYnJldmlzIgpKUW1jX3RyZWUkdGlwLmxhYmVsW0pRbWNfdHJlZSR0aXAubGFiZWwgPT0gIkpRXzc4MTdfV2VydGhlaW1lcmlhX21hY3VsYXRhIl0gPC0gIldlcnRoZWltZXJpYSBtYWN1bGF0YSIKSlFtY190cmVlJHRpcC5sYWJlbFtKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJTRl8xMjQzX1RyYWNoZWx5b3B0ZXJ1c19nYWxlYXR1c19KUV81Njc1Il0gPC0gIlRyYWNoZWx5b3B0ZXJ1cyBnYWxlYXR1cyIKSlFtY190cmVlJHRpcC5sYWJlbFtKUW1jX3RyZWUkdGlwLmxhYmVsID09ICJKUV8yOTk2X1N0ZWluZGFjaG5lcmlkaW9uX2FtYmx5dXJ1bSJdIDwtICJTdGVpbmRhY2huZXJpZGlvbiBhbWJseXVydW0iCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfNTY0NV9SaGFtZGlhX2FmZl9xdWVsZW4iXSA8LSAiUmhhbWRpYSBxdWVsZW4iCkpRbWNfdHJlZSR0aXAubGFiZWxbSlFtY190cmVlJHRpcC5sYWJlbCA9PSAiSlFfNjU4NF9BdXN0cmFsb2hlcm9zX3NwIl0gPC0gIkF1c3RyYWxvaGVyb3Mgc3AiCn0KCiMjIyBjaGVjayBpZiBhbGwgbmFtZXMgaGF2ZSBjb3JyZXNwb25kZW5jZXMKSlFtY190cmVlJHRpcC5sYWJlbCAlaW4lIHRhYl9jdXJhdGVkX0pRJFNwZWNpZXMKdGFiX2N1cmF0ZWRfSlEkU3BlY2llcyAlaW4lIEpRbWNfdHJlZSR0aXAubGFiZWwKdGFiX2N1cmF0ZWRfSlEkU3BlY2llc1shdGFiX2N1cmF0ZWRfSlEkU3BlY2llcyAlaW4lIEpRbWNfdHJlZSR0aXAubGFiZWxdCgoKCgojaW52ZXJ0IGJyYW5jaGVzIHRvIG1hdGNoIFNpbHVyaWZvcm1lcyBwb3NpdGlvbiBvbiB0aGUgdG9wCgoKSlFtY190cmVlJGVkZ2UKSlFtY190cmVlICU+JSBhc190aWJibGUoKSAlPiUgVmlldygpCgoKSlFtY190cmVlICAlPiUgCiAgZ2d0cmVlKCkgKyAKICAjIGdlb21fdGV4dChhZXMobGFiZWw9bm9kZSkpICsgCiAgdGhlbWVfdHJlZTIoKSArCiAgZ2VvbV90aXBsYWIob2Zmc2V0ID0gMCxhbGlnbiA9IFQpKyAKICB4bGltKDAsIDAuNDIpJT4lIAogIGdndHJlZTo6ZmxpcChub2RlMSA9IDIxLG5vZGUyID0gMjApCiAKCnJvdGF0ZU5vZGVzKHRyZWUgPSBKUW1jX3RyZWUsICJhbGwiKSAlPiUKICBnZ3RyZWUoKSArIAogIHRoZW1lX3RyZWUyKCkgKwogIGdlb21fdGlwbGFiKG9mZnNldCA9IDAsYWxpZ24gPSBUKSsgCiAgeGxpbSgwLCAwLjQyKQoKCgojIyMgY29udmVydCBhcGUgdHJlZSB0byBwcmV0dGllciBnZ3RyZWUgb2JqZWN0CkpRbWNfdHJlZV9wbG90IDwtIGdndHJlZShKUW1jX3RyZWUpICsgCiAgdGhlbWVfdHJlZTIoKSArCiAgZ2VvbV90aXBsYWIob2Zmc2V0ID0gMCxhbGlnbiA9IFQpKyAKICB4bGltKDAsIDAuNDIpCgoKIyMjIHNhdmUgdHJlZSBwbG90CiMgZ2dzYXZlKGZpbGUgPSAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvZGF0YS90cmVlcy9KUW1jLTE3X1NQc19mdXNlZC11bmlxdWUtdHJlZV9wbG90LnBkZiIsIApnZ3NhdmUoZmlsZSA9ICJ+L291dHJvcy9zZmpxX3RlbXAvdHJlZXMvSlFtYy0xN19TUHNfZnVzZWQtdW5pcXVlLXRyZWVfcGxvdC5wZGYiLCAKICAgICAgIHBsb3QgPSBKUW1jX3RyZWVfcGxvdCwgCiAgICAgICBkZXZpY2UgPSAicGRmIiwgCiAgICAgICB3aWR0aCA9IDI0LCBoZWlnaHQgPSAyNCwgCiAgICAgICB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKCgoKIyMjIGV4dHJhY3QgdGlwcyBvcmRlciBmcm9tIHRyZWUgdG8gcmVwcm9kdWNlIG9uIHBsb3RzClNQc19vcmRlcl9pbl9KUV90cmVlIDwtIGdldF90YXhhX25hbWUoSlFtY190cmVlX3Bsb3QpICU+JSByZXYoKQoKICAgICAgICAgICAgIyBTUHNfb3JkZXJfaW5fSlFfdHJlZSA8LSBleHRyYWN0X3RyZWVfZGF0YSh0cmVlX3Bsb3QpICU+JSAKICAgICAgICAgICAgIyAgICAgZHBseXI6OmZpbHRlcihpc1RpcCkgJT4lIAogICAgICAgICAgICAjICAgICBkcGx5cjo6cHVsbChsYWJlbCkKCgoKCiMjIHBsb3RzIC0tLS0KIyMjIFJSQSBoaXN0b2dyYW0gLS0tLQoKSlFtY19SUkFfcGxvdCA8LQogIHRhYl9jdXJhdGVkX0pRICU+JQogICAgdW5pdGUoTm9ybWFsaXphdGlvbiwgUHJpbWVyLCBjb2wgPSAiUHJpbWVyX25vcm0iLHJlbW92ZSA9IEYsc2VwID0gIiAiKSAlPiUKICBtdXRhdGUoUHJpbWVyX25vcm0gPSBmYWN0b3IoUHJpbWVyX25vcm0sIGxldmVscyA9IGMoIk5vcm1hbGl6ZWQgTmVvRmlzaCIsIk5vcm1hbGl6ZWQgTWlGaXNoIiwiTm9ybWFsaXplZCBUZWxlbyIsIk5vbi1ub3JtYWxpemVkIE5lb0Zpc2giLCJOb24tbm9ybWFsaXplZCBNaUZpc2giLCJOb24tbm9ybWFsaXplZCBUZWxlbyIpKSkgJT4lCiAgbXV0YXRlKFNwZWNpZXMgPSBmYWN0b3IoU3BlY2llcyxsZXZlbHMgPSBTUHNfb3JkZXJfaW5fSlFfdHJlZSkpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBTcGVjaWVzLAogICAgICAgICAgICAgeCA9IGBSUkEgKCUpYCwKICAgICAgICAgICAgIGZpbGwgPSBQcmltZXJfbm9ybSwgCiAgICAgICAgICAgICBjb2wgPSBOb3JtYWxpemF0aW9uCiAgICAgICAgICAgICApKSsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgc2l6ZSA9IDAuMyx3aWR0aCA9IDEsCiAgICAgICAgICAgIyBhbHBoYSA9IDAuNywKICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHByZXNlcnZlID0gInNpbmdsZSIgLHdpZHRoID0gMS41KSkgKwogICAgICAgICAgICMgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZWp1c3QocHJlc2VydmUgPSAic2luZ2xlIiAsd2lkdGggPSAxLjIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JzNltjKDEsMyw1LDIsNCw2KV0sIG5hbWUgPSAiIikgKwogIGdlb21fcG9pbnQoYWVzKHkgPSBTcGVjaWVzLAogICAgICAgICAgICAgICAgIHggPSBgaW5wdXQgRE5BICglKWAsCiAgICAgICAgICAgICBjb2xvdXIgPSBOb3JtYWxpemF0aW9uKSwKICAgICAgICAgICAgIHNoYXBlID0gInwiLAogICAgICAgICAgICAgc2l6ZSA9IDMpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjNzQ3NDc0IiwiIzAwMDAwMCIpKSArCiAgeGxhYigiUmVsYXRpdmUgcmVhZCBhYnVuZGFuY2UgKCUpIikgCgoKIyMgc2F2ZSBwbG90IAoKIyBnZ3NhdmUoZmlsZSA9ICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhL3RyZWVzL0pRbWMtMjNfU1BzX2Z1c2VkLXVuaXF1ZS1SUkFfYmFycGxvdC5wZGYiLCBwbG90ID0gSlFtY19SUkFfcGxvdCwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gMjQsIGhlaWdodCA9IDIwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKZ2dzYXZlKGZpbGUgPSAifi9vdXRyb3Mvc2ZqcV90ZW1wL3RyZWVzL0pRbWMtMTdfU1BzX2Z1c2VkLXVuaXF1ZS1SUkFfYmFycGxvdC5wZGYiLCBwbG90ID0gSlFtY19SUkFfcGxvdCwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gMzAsIGhlaWdodCA9IDMwLCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKCgoKCiNhcnZvcmUgLS0tLQoKCiMgU0ZKUW1jX3RyZWUgPC0gcmVhZC50cmVlKCJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9kYXRhLzEyU19mdWxsX1NGSlFtY19mdXNlZF9TUHNfZV8zX2NvbnRhbXMubndrIikKCgoKCmdncGxvdChTRkpRbWNfdHJlZSkgKyBnZW9tX3RyZWUoKSArIHRoZW1lX3RyZWUoKQoKIyBUaGlzIGlzIGNvbnZlbmllbnQgc2hvcnRoYW5kCgojICMgdHJlZV9wbG90IDwtIAojICAgZ2d0cmVlKFNGSlFtY190cmVlKSArIAojICAgdGhlbWVfdHJlZTIoKSArCiMgICBnZW9tX3RpcGxhYihvZmZzZXQgPSAwLGFsaWduID0gVCkrIAojICAgeGxpbSgwLCAwLjQyKSAKCiAgCiAgdHJlZV9wbG90CiAgCiAgCiAgCiAgICAKI1RPRE8gY3JlYXRlIGZ1bmN0aW9uIHRvIGJ1aWxkIGRvdWJsZSBncmFwaCBvZiB0cmVlIGFuZCBiYXJzCgogIAogIAojIG5ld2ljayB0cmVlIHRvIHBsb3QgYWxvbmcgdGhlIGdyYXBoCiAgdHJlZTRwbG90IDwtIFNGSlFtY190cmVlCgogIAojIHRhYmxlIGZvciBnZ3Bsb3QgdG8gZ28gYWxvbmdzaWRlIHRoZSB0cmVlIChsb25nIGZvcm1hdCwgY2FuIGhhdmUgZmFjdG9ycykKICB0Ymw0cGxvdCA8LSB0YWJfY3VyYXRlZF9TRkpRCiAgCiMgcGxvdCB0byBwdXQgYnkgc2lkZSAoeSBheGlzIG11c3QgYmUgdGhlIHNwZWNpZXMgaW4gdHJlZSAoY29sdW1uIG5hbWUgPT0gU3BlY2llcykpCiAgcGxvdDR0cmVlIDwtIFNGSlFtY19SUkFfcGxvdAogIAogIAogIAojIyMgZ2VuZXJhdGUgcGxvdCBmcm9tIHBseWxvIG9iamVjdCAoLm53ayByZWFkIGJ5IGFwZTo6cmVhZC50cmVlKQogIAoKY2xhc3MoU0ZKUW1jX3RyZWUpCgp0cmVlNHBsb3QkZWRnZS5sZW5ndGggJT4lIHNvcnQoKSAlPiUgc3VtKCkgCnRyZWU0cGxvdCAlPiUgc3RyKCkKCgp0cmVlX3Bsb3QkZGF0YQoKIyB0cmVlX3Bsb3QgPC0KICBnZ3RyZWUodHIgPSB0cmVlNHBsb3QsbGF5b3V0ID0gInJlY3Rhbmd1bGFyIikgKwogIHRoZW1lX3RyZWUyKCkgKwogICMgZ2VvbV90aXBsYWIob2Zmc2V0ID0gMCxhbGlnbiA9IFQpKwogIGdlb21fdGlwbGFiKGFsaWduID0gVCkrCiAgeGxpbSgwLCAwLjQyKQogIAogIAojIyMgZXh0cmFjdCB0aXBzIG9yZGVyIGZyb20gdHJlZSB0byByZXByb2R1Y2Ugb24gcGxvdHMKU1BzX29yZGVyX2luX3RyZWUgPC0gZ2d0cmVlOjpnZXRfdGF4YV9uYW1lKFNGSlFtY190cmVlX3Bsb3QpICU+JSByZXYoKQogIAogIAogIAogIHBsb3Q0dHJlZSRkYXRhICU+JSAKICAgIGRwbHlyOjptdXRhdGUoU3BlY2llcyA9IGZhY3RvcihTcGVjaWVzLCBsZXZlbHMgPSBTUHNfb3JkZXJfaW5fdHJlZSkpCiAgICAKICAKICAKICAgIAogICAgCiAgICAjIyBjaGVjayB0aXAgbmFtZXMgaW4gdHJlZQpKUW1jX3RyZWUkdGlwLmxhYmVsCgoKCgoKCgojIyMgY29udmVydCBhcGUgdHJlZSB0byBwcmV0dGllciBnZ3RyZWUgb2JqZWN0CkpRbWNfdHJlZV9wbG90IDwtIGdndHJlZShKUW1jX3RyZWUpICsgCiAgdGhlbWVfdHJlZTIoKSArCiAgZ2VvbV90aXBsYWIob2Zmc2V0ID0gMCxhbGlnbiA9IFQpKyAKICB4bGltKDAsIDAuNDIpCiAgICAKICAgIAp0cmVlTmJhcl9wbG90ICA8LSBmdW5jdGlvbigpewogICAgCiAgfSAgCiAgCgojIGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tLzIwMTYvMTIvYWRkLWxheWVyLXRvLXNwZWNpZmljLXBhbmVsLW9mLWZhY2V0X3Bsb3Qtb3V0cHV0LTIvCiMgZmFjZXRfcGxvdCh0cmVlX3Bsb3QsIHBhbmVsID0gJ1N0YWNrZWQgQmFycGxvdCcsIAojICAgICAgICAgICAgZGF0YSA9IHRhYl9jdXJhdGVkX1NGSlEsIGdlb20gPSBnZW9tX2hpc3RvZ3JhbSwKIyAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IFNwZWNpZXMseSA9YFJSQSAoJSlgLCAgZmlsbCA9IGFzLmZhY3RvcihQcmltZXIpKSwKIyAgICAgICAgICAgIHN0YXQ9J2lkZW50aXR5Jyxwb3NpdGlvbiA9ICdkb2RnZScgKQojIAojICMgCiMgcDMgPC0gZmFjZXRfcGxvdCh0cmVlX3Bsb3QsIHBhbmVsPSdiYXInLCBkYXRhPXRhYl9jdXJhdGVkX1NGSlEsIGdlb209Z2VvbV9iYXIsIAojICAgICAgICAgICAgICAgICAgYWVzKHg9YFJSQSAoJSlgLCB5PVNwZWNpZXMsZmlsbCA9IFByaW1lciksCiMgICAgICAgICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKIyAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImRvZGdlIikKCgojaHR0cHM6Ly9vdXAuc2lsdmVyY2hhaXItY2RuLmNvbS9vdXAvYmFja2ZpbGUvQ29udGVudF9wdWJsaWMvSm91cm5hbC9tYmUvMzUvMTIvMTAuMTA5M19tb2xiZXZfbXN5MTk0LzMvbXN5MTk0X3N1cHAucGRmP0V4cGlyZXM9MTY0ODIwNDAzNiZTaWduYXR1cmU9Z1pDNkExdmZ5YVVXT3lMfmZLbjh3eGdZfjNmYlRCSTNqUE9HYlZ0d1pTenYzamxYSVNqQ2FoQTM3Z3dSM1FUcjZvTjBTSy1iZHdBbEhReWFQcGtkajJ+eWk1c2NOUVhBUXJVaTBFUU5PcWtPbzNIVXZGdkNyLURpcjJ5N04wM3ZJbzV1cnIxbjJpZHJQY2xUWHRUUnRpdTdhdm4yNTVUNWVnfmNYdjBOQk5VZ2lWRmN3SEhuWjgxcVFVclNkaUE1NHdJdkVzflJGMThEWWtwLUdsYTFDSlQwZVVHdVlGOExmRlhHNURxMUNnY1pWMHFHczBmS2dmSUtSbEFUfkFQMjVYeGtkaDIwUnpBa3FnQkZ2eHAwSmF6clZPejV1dmRvazN1U3UzMDIzZXRFclR4aGFXN3JtNjdWa0NVQlZ4Umd0RzhHZEZUM2ZPRkpBc1BnMjZXYWd3X18mS2V5LVBhaXItSWQ9QVBLQUlFNUc1Q1JESzZSRDNQR0EKCiMgCiMgdHJlZV9wbG90ICU8KyUgdGFiX2N1cmF0ZWRfU0ZKUSArIAojICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSBTcGVjaWVzLAojICAgICAgICAgICAgICAgICAgICAgIHggPSBgUlJBICglKWAsCiMgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IFByaW1lciksCiMgICAgICAgICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKIyAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImRvZGdlIikKCmNvbG5hbWVzKHRhYl9jdXJhdGVkX1NGSlEpW2NvbG5hbWVzKHRhYl9jdXJhdGVkX1NGSlEpID09ICJTcGVjaWVzIl0gPC0gInRpcC5sYWJlbCIKCgoKcDIgPC0gCiAgZmFjZXRfcGxvdChwID0gdHJlZV9wbG90LCBwYW5lbCA9ICJTTlAiLCBkYXRhID0gdGFiX2N1cmF0ZWRfU0ZKUSwgZ2VvbSA9IGdlb21faGlzdG9ncmFtLAogICAgICAgICAgICAgICAgIG1hcHBpbmc9YWVzKHkgPSB0aXAubGFiZWwsIHggPSBgUlJBICglKWAsIGZpbGwgPSBQcmltZXIpLAogICAgICAgICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImRvZGdlIikgKwojICU+JQojICAgZmFjZXRfcGxvdCgiVHJhaXQiLCBiYXJfZGF0YSwgZ2dzdGFuY2U6Omdlb21fYmFyaCwKIyAgICAgICAgICAgICAgYWVzKHggPSBkdW1teV9iYXJfdmFsdWUsIGNvbG9yID0gbG9jYXRpb24sIGZpbGwgPSBsb2NhdGlvbiksCiMgICAgICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IC42KSArCiAgdGhlbWVfdHJlZTIobGVnZW5kLnBvc2l0aW9uPWMoLjA1LCAuODUpKQpwcmludChwMikKCgoKcDIgPC0gdHJlZV9wbG90ICsgZ2VvbV9mYWNldChwYW5lbCA9ICJSUkEgKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gdGFiX2N1cmF0ZWRfU0ZKUSwKICAgICAgICAgICAgICAgICAgICAgICBnZW9tID0gZ2VvbV9iYXIsCiAgICAgICAgICAgICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4PWBSUkEgKCUpYCwgZmlsbCA9IFByaW1lciksb3JpZW50YXRpb24gPSAneScsc3RhdD0iaWRlbnRpdHkiKQoKCgoKCmV4dHJhY3RfdHJlZV9kYXRhIDwtIGZ1bmN0aW9uKHRyZWVfZGlzcCwgZGlzcGxheW9yZGVyPVRSVUUpIHsKICAgIHRkX291dCA8LSB0cmVlX2Rpc3AkZGF0YQogICAgaWYgKGRpc3BsYXlvcmRlcikgewogICAgICAgdGRfb3V0IDwtIGRwbHlyOjphcnJhbmdlKHRkX291dCx5KQogICAgfQogICAgcmV0dXJuKHRkX291dCkKfQoKU1BzX29yZGVyX2luX3RyZWUgPC0gZXh0cmFjdF90cmVlX2RhdGEodHJlZV9wbG90KSAlPiUgCiAgICBkcGx5cjo6ZmlsdGVyKGlzVGlwKSAlPiUgCiAgICBkcGx5cjo6cHVsbChsYWJlbCkKCgoKYGBgCgojIyBkZW5kcm9ncmFtcyBvZiBBU1ZzICYgZGIgc3BlY2llcwoKYGBge3IgZWNobz1GQUxTRSxldmFsPUZBTFNFfQojIGdlbmVyYXRlIGZhc3RhIGZpbGVzIGZvciB0aGUgQVNWcyBvZiBhbmQgcHJpbWVyLCBpZGVudGlmeWluZyB0aGUgcG9vbCB3aGVyZSBpdCB3YXMgZm91bmQKCmFsbF9wc190Ymxfc2ZqcV9mdWxsICU+JSAgY29sbmFtZXMoKQoKCmlkZW50aWZpZWRfQVNWcyA8LSBhbGxfcHNfdGJsX3NmanFfZnVsbCAlPiUgCiAgZ3JvdXBfYnkoUHJpbWVyLCBgQVNWIChTZXF1ZW5jZSlgKSAlPiUgCiAgc3VtbWFyaXNlKGBTYW1wbGVgID0gdW5pcXVlKGBTYW1wbGVgKSwKICAgICAgICAgICAgT1RVID0gdW5pcXVlKE9UVSksCiAgICAgICAgICAgIGBmaW5hbCBJRGAgPSB1bmlxdWUoYGZpbmFsIElEYCksCiAgICAgICAgICAgIGBBU1YgaGVhZGVyYCA9IHVuaXF1ZShgQVNWIGhlYWRlcmApKSAKCgppZGVudGlmaWVkX0FTVnMkU2FtcGxlIDwtIGlkZW50aWZpZWRfQVNWcyRTYW1wbGUgJT4lIHN0cl9yZXBsYWNlX2FsbChwYXR0ZXJuID0gIlxuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiLSIpCiAgCgoKaWRlbnRpZmllZF9BU1ZzIDwtIGlkZW50aWZpZWRfQVNWcyAlPiUgdW5pdGUoZmluYWxfaGVhZGVyLGBBU1YgaGVhZGVyYCwgT1RVLCBTYW1wbGUsIGBmaW5hbCBJRGAsc2VwID0gIi0iKQoKCiAgCiN3cml0ZSBmYXN0YSBmaWxlIHdpdGggQVNWcyBhbmQgVGF4b25vbXkKCmRpci5jcmVhdGUoIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvQVNWcyIsc2hvd1dhcm5pbmdzID0gVCkKCiNOZW9GaXNoCmlkZW50aWZpZWRfQVNWcyAlPiUgCiAgZmlsdGVyKFByaW1lciAlaW4lIGMoIk5lb0Zpc2giKSkgCiAgCgpuZW9BU1ZzX2Zhc3RhIDwtIGMocmJpbmQoaWRlbnRpZmllZF9BU1ZzJGZpbmFsX2hlYWRlcltpZGVudGlmaWVkX0FTVnMkUHJpbWVyID09Ik5lb0Zpc2giXSwKICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50aWZpZWRfQVNWcyRgQVNWIChTZXF1ZW5jZSlgW2lkZW50aWZpZWRfQVNWcyRQcmltZXIgPT0iTmVvRmlzaCJdKSkKCndyaXRlKG5lb0FTVnNfZmFzdGEsICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL0FTVnMvTmVvRmlzaF9BU1ZzX0lEZWQuZmFzdGEiKQoKCgojTWlGaXNoCmlkZW50aWZpZWRfQVNWcyAlPiUgCiAgZmlsdGVyKFByaW1lciAlaW4lIGMoIk1pRmlzaCIpKSAKICAKCm1pZkFTVnNfZmFzdGEgPC0gYyhyYmluZChpZGVudGlmaWVkX0FTVnMkZmluYWxfaGVhZGVyW2lkZW50aWZpZWRfQVNWcyRQcmltZXIgPT0iTWlGaXNoIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudGlmaWVkX0FTVnMkYEFTViAoU2VxdWVuY2UpYFtpZGVudGlmaWVkX0FTVnMkUHJpbWVyID09Ik1pRmlzaCJdKSkKCndyaXRlKG1pZkFTVnNfZmFzdGEsICJ+L3ByamN0cy9maXNoX2VETkEvc2ZqcS9yZXN1bHRzL0FTVnMvTWlGaXNoX0FTVnNfSURlZC5mYXN0YSIpCgoKCiNUZWxlbwppZGVudGlmaWVkX0FTVnMgJT4lIAogIGZpbHRlcihQcmltZXIgJWluJSBjKCJUZWxlbyIpKSAKICAKCnRlbEFTVnNfZmFzdGEgPC0gYyhyYmluZChpZGVudGlmaWVkX0FTVnMkZmluYWxfaGVhZGVyW2lkZW50aWZpZWRfQVNWcyRQcmltZXIgPT0iVGVsZW8iXSwKICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50aWZpZWRfQVNWcyRgQVNWIChTZXF1ZW5jZSlgW2lkZW50aWZpZWRfQVNWcyRQcmltZXIgPT0iVGVsZW8iXSkpCgp3cml0ZSh0ZWxBU1ZzX2Zhc3RhLCAifi9wcmpjdHMvZmlzaF9lRE5BL3NmanEvcmVzdWx0cy9BU1ZzL1RlbGVvX0FTVnNfSURlZC5mYXN0YSIpCgoKCgpgYGAKCgoKIyMgZm9sZCBjaGFuZ2Ugc3RhbmRhcmQgZGV2aWF0aW9uCgoKYGBge3IgZWNobz1GQUxTRSxldmFsPUZBTFNFfQoKClNQc19vcmRlcl9pbl9TRkpRX3RyZWUgJT4lIHBhc3RlMChjb2xsYXBzZSA9ICciLCBcbiInKSAlPiUgY2F0KCkKCnRpYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzIDwtIHRhYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzICU+JQogIG11dGF0ZShTcGVjaWVzPXJlcGxhY2UoU3BlY2llcywgU3BlY2llcyAlaW4lIGMoIkhvcGxpYXMgYnJhc2lsaWVuc2lzIiwgIkhvcGxpYXMgaW50ZXJtZWRpdXMiKSwgIkhvcGxpYXMgYnJhc2lsaWVuc2lzL2ludGVybWVkaXVzIikpICU+JQogIGFzX3RpYmJsZSgpICU+JQogIGZpbHRlcihTdGF0dXMgPT0gIkV4cGVjdGVkIikgJT4lCiAgbXV0YXRlKFByaW1lciA9IGZhY3RvcihQcmltZXIsIGxldmVscyA9IGMoIk5lb0Zpc2giLCJNaUZpc2giLCJUZWxlbyIpKSwKICAgICAgICAgU3BlY2llcyA9IGZhY3RvcihTcGVjaWVzLCBsZXZlbHMgPSBjKCJDaGFyYWNpZGl1bSBsYWdvc2FudGVuc2UiLCAiQnJ5Y29uIG9ydGhvdGFlbmlhIiwiSG9wbGlhcyBtYWxhYmFyaWN1cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICJIb3BsaWFzIGJyYXNpbGllbnNpcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSG9wbGlhcyBicmFzaWxpZW5zaXMvaW50ZXJtZWRpdXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAiSG9wbGlhcyBpbnRlcm1lZGl1cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2VycmFzYWxtdXMgYnJhbmR0aWkiLCAiTXlsZXVzIG1pY2FucyIsICJDeXBob2NoYXJheCBnaWxiZXJ0IiwgIlByb2NoaWxvZHVzIGNvc3RhdHVzIiwiUHJvY2hpbG9kdXMgYXJnZW50ZXVzL2hhcnRpaSIsICJIeXBvbWFzdGljdXMgc3RlaW5kYWNobmVyaSIsIk1lZ2FsZXBvcmludXMgZ2FybWFuaSIsIk1lZ2FsZXBvcmludXMgZWxvbmdhdHVzIiwiUm9lYm9pZGVzIHhlbm9kb24iLCJUZXRyYWdvbm9wdGVydXMgY2hhbGNldXMiLCAiTW9lbmtoYXVzaWEgY29zdGFlIiwiTW9lbmtoYXVzaWEgc2FuY3RhZWZpbG9tZW5hZSIsICJBc3R5YW5heCBmYXNjaWF0dXMiLCJBc3R5YW5heCBsYWN1c3RyaXMiLCAiRXVnZXJyZXMgYnJhc2lsaWFudXMiLCJDcmVuaWNpY2hsYSBsZXBpZG90YSIsICJBdXN0cmFsb2hlcm9zIHNwIiwiUGhhbGxvY2Vyb3MgdWFpIiwiUGFtcGhvcmljaHRoeXMgaG9sbGFuZGkiLCJHeW1ub3R1cyBjYXJhcG8iLCJFaWdlbm1hbm5pYSB2aXJlc2NlbnMiLCJEZWx0dXJ1cyBicmV2aXMiLCJQdGVyeWdvcGxpY2h0aHlzIGV0ZW50YWN1bGF0dXMiLCAiSHlwb3N0b211cyBhbGF0dXMiLCAiSHlwb3N0b211cyBuaWdyb2xpbmVhdHVzIiwiVHJhY2hlbHlvcHRlcnVzIGdhbGVhdHVzIiwgIkZyYW5jaXNjb2RvcmFzIG1hcm1vcmF0dXMiLCAiV2VydGhlaW1lcmlhIG1hY3VsYXRhIiwgIkltcGFyZmluaXMgbWludXR1cyIsIlJoYW1kaWEgcXVlbGVuIiwgIk1pY3JvZ2xhbmlzIGxlcHRvc3RyaWF0dXMiLCAiU3RlaW5kYWNobmVyaWRpb24gYW1ibHl1cnVtIiwgIlBpbWVsb2R1cyBwb2hsaSIsICJQaW1lbG9kdXMgbWFjdWxhdHVzIikpLAogICAgICAgICBOb3JtYWxpemF0aW9uID0gZmFjdG9yKE5vcm1hbGl6YXRpb24pLAogICAgICAgICBQb29sID0gZmFjdG9yKFBvb2wpLAogICAgICAgICBTdGF0dXMgPSBmYWN0b3IoU3RhdHVzKSkgCiMgJT4lIAojICBncm91cF9ieShOb3JtYWxpemF0aW9uLFByaW1lcixTcGVjaWVzKSAlPiUgCiMgICBzdW1tYXJpemUoUG9vbCA9IHVuaXF1ZShQb29sKSwKIyAgICAgICAgICAgICBOb3JtYWxpemF0aW9uID0gdW5pcXVlKE5vcm1hbGl6YXRpb24pLAojICAgICAgICAgICAgIFN0YXR1cyA9IHVuaXF1ZShTdGF0dXMpLAojICAgICAgICAgICAgIFNwZWNpZXMgPSB1bmlxdWUoU3BlY2llcyksCiMgICAgICAgICAgICAgUHJpbWVyID0gdW5pcXVlKFByaW1lciksCiMgICAgICAgICAgICAgYE51bSBBU1ZzYCA9IHN1bShgTnVtIEFTVnNgKSwKIyAgICAgICAgICAgICBgTnVtIE9UVXNgID0gc3VtKGBOdW0gT1RVc2ApLAojICAgICAgICAgICAgIGBpbnB1dCBETkEgKCUpYCA9IHN1bShgaW5wdXQgRE5BICglKWApLAojICAgICAgICAgICAgIGBSUkEgKCUpYCA9IHN1bShgUlJBICglKWApCiMgICAgICAgICAgICAgKSAlPiUKIyAgIHVuZ3JvdXAoKSAlPiUgICAKIyAgIG11dGF0ZShgRm9sZCBjaGFuZ2UgKFJSQS9ETkEgaW5wdXQpYCA9IGd0b29sczo6Zm9sZGNoYW5nZShkZW5vbSA9IGBpbnB1dCBETkEgKCUpYCxudW0gPSBgUlJBICglKWApKQoKIyAhISEhISEhISEhISEhISEhdmVyc2FvIGFudGlnYSBxdWFuZG8gYSB0YWJfY3VyYXRlZCB2aW5oYSBkIGVkbmV0cm8gZG8gY29kaWdvCiMgdGliX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgPC0gdGFiX2N1cmF0ZWRfU0ZKUV9hbGxfcG9vbHMgJT4lCiMgICBtdXRhdGUoU3BlY2llcz1yZXBsYWNlKFNwZWNpZXMsIFNwZWNpZXMgJWluJSBjKCJIb3BsaWFzIGJyYXNpbGllbnNpcyIsICJIb3BsaWFzIGludGVybWVkaXVzIiksICJIb3BsaWFzIGJyYXNpbGllbnNpcy9pbnRlcm1lZGl1cyIpKSAlPiUKIyAgIGFzX3RpYmJsZSgpICU+JQojICAgZmlsdGVyKFN0YXR1cyA9PSAiRXhwZWN0ZWQiKSAlPiUKIyAgIG11dGF0ZShQcmltZXIgPSBmYWN0b3IoUHJpbWVyLCBsZXZlbHMgPSBjKCJOZW9GaXNoIiwiTWlGaXNoIiwiVGVsZW8iKSksCiMgICAgICAgICAgU3BlY2llcyA9IGZhY3RvcihTcGVjaWVzLCBsZXZlbHMgPSBjKCJDaGFyYWNpZGl1bSBsYWdvc2FudGVuc2UiLCAiQnJ5Y29uIG9ydGhvdGFlbmlhIiwiSG9wbGlhcyBtYWxhYmFyaWN1cyIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgIkhvcGxpYXMgYnJhc2lsaWVuc2lzIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkhvcGxpYXMgYnJhc2lsaWVuc2lzL2ludGVybWVkaXVzIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAiSG9wbGlhcyBpbnRlcm1lZGl1cyIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTZXJyYXNhbG11cyBicmFuZHRpaSIsICJNeWxldXMgbWljYW5zIiwgIkN5cGhvY2hhcmF4IGdpbGJlcnQiLCAiUHJvY2hpbG9kdXMgY29zdGF0dXMiLCJQcm9jaGlsb2R1cyBhcmdlbnRldXMvaGFydGlpIiwgIkh5cG9tYXN0aWN1cyBzdGVpbmRhY2huZXJpIiwiTWVnYWxlcG9yaW51cyBnYXJtYW5pIiwiTWVnYWxlcG9yaW51cyBlbG9uZ2F0dXMiLCJSb2Vib2lkZXMgeGVub2RvbiIsIlRldHJhZ29ub3B0ZXJ1cyBjaGFsY2V1cyIsICJNb2Vua2hhdXNpYSBjb3N0YWUiLCJNb2Vua2hhdXNpYSBzYW5jdGFlZmlsb21lbmFlIiwgIkFzdHlhbmF4IGZhc2NpYXR1cyIsIkFzdHlhbmF4IGxhY3VzdHJpcyIsICJFdWdlcnJlcyBicmFzaWxpYW51cyIsIkNyZW5pY2ljaGxhIGxlcGlkb3RhIiwgIkF1c3RyYWxvaGVyb3Mgc3AiLCJQaGFsbG9jZXJvcyB1YWkiLCJQYW1waG9yaWNodGh5cyBob2xsYW5kaSIsIkd5bW5vdHVzIGNhcmFwbyIsIkVpZ2VubWFubmlhIHZpcmVzY2VucyIsIkRlbHR1cnVzIGJyZXZpcyIsIlB0ZXJ5Z29wbGljaHRoeXMgZXRlbnRhY3VsYXR1cyIsICJIeXBvc3RvbXVzIGFsYXR1cyIsICJIeXBvc3RvbXVzIG5pZ3JvbGluZWF0dXMiLCJUcmFjaGVseW9wdGVydXMgZ2FsZWF0dXMiLCAiRnJhbmNpc2NvZG9yYXMgbWFybW9yYXR1cyIsICJXZXJ0aGVpbWVyaWEgbWFjdWxhdGEiLCAiSW1wYXJmaW5pcyBtaW51dHVzIiwiUmhhbWRpYSBxdWVsZW4iLCAiTWljcm9nbGFuaXMgbGVwdG9zdHJpYXR1cyIsICJTdGVpbmRhY2huZXJpZGlvbiBhbWJseXVydW0iLCAiUGltZWxvZHVzIHBvaGxpIiwgIlBpbWVsb2R1cyBtYWN1bGF0dXMiKSksCiMgICAgICAgICAgTm9ybWFsaXphdGlvbiA9IGZhY3RvcihOb3JtYWxpemF0aW9uKSwKIyAgICAgICAgICBQb29sID0gZmFjdG9yKFBvb2wpLAojICAgICAgICAgIFN0YXR1cyA9IGZhY3RvcihTdGF0dXMpKQojIApsaWJyYXJ5KGdnYWxsaW4pCmxpYnJhcnkocGxvdGx5KQoKI2ZvbGQgY2hhbmdlIGJveHBsb3QgLS0tLQoKICBmb2xkX2NoYW5nZV9ib3hwbG90IDwtIHRpYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzICU+JSAKICBtdXRhdGUoYEZvbGQgY2hhbmdlIChSUkEvRE5BIGlucHV0KWA9aWZfZWxzZSguJGBGb2xkIGNoYW5nZSAoUlJBL0ROQSBpbnB1dClgIDw9IC0yMjAwMDAuMywtNTAwLC4kYEZvbGQgY2hhbmdlIChSUkEvRE5BIGlucHV0KWApKSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHkgPSBTcGVjaWVzLAogICAgICAgICAgICAgICB4ID0gYEZvbGQgY2hhbmdlIChSUkEvRE5BIGlucHV0KWAsCiAgICAgICAgICAgICAgIGNvbCA9IFByaW1lcikpICsKICAgIGZhY2V0X3dyYXAoflByaW1lcikgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xMDAsMTAwKSxsaW5ldHlwZT00KSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGMoLTUwLC0xMCwtNSwtMSw1MCwxMCw1LDEpLAogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDQsCiAgICAgICAgICAgICAgIHNpemUgPSAwLjI1LGFscGhhPTAuNSkrCiAgICBnZW9tX2JveHBsb3QoKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLGhlaWdodCA9IDAuMSxzaXplICA9IDAuNCkrIAogICAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gZ2dhbGxpbjo6cHNldWRvbG9nMTBfdHJhbnMsIAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLTIwMDAsLTEwMDAsLTUwMCwtMTAwLC01MCwtMTAsLTUsLTEsMCwxLDUsMTAsNTAsMTAwLDUwMCwxMDAwLDIwMDApCiAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yczZbYygxLDMsNSldKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1KSkgKwogICAgdGhlbWVfY2xhc3NpYygpKyAKICAgIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmV5OTUiLGNvbG91ciA9ICJibGFjayIpKSsKICAgICMgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYygxOjM4KS0wLjUpCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKHNlcSgxLDM4LDIpKSxzaXplID0gNy41LGFscGhhPTAuMDQpCgoKIyBsaWJyYXJ5KGdncGxvdGx5KQoKCmdncGxvdGx5KHAgPSBmb2xkX2NoYW5nZV9ib3hwbG90KQoKCiNwbG90eS0tLS0KCiMgZm9sZF9jaGFuZ2VfYm94cGxvdGx5IDwtIAogIHRpYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzICU+JSBjb2xuYW1lcwogIHRpYl9jdXJhdGVkX1NGSlFfYWxsX3Bvb2xzICU+JSAKICBncm91cF9ieShTcGVjaWVzKQogIAogIAogIAogIAogIAogIGdncGxvdChhZXMoeSA9IFNwZWNpZXMsCiAgICAgICAgICAgICB4ID0gYEZvbGQgQ2hhbmdlYCwKICAgICAgICAgICAgIGNvbCA9IFByaW1lcikpICsKICBmYWNldF93cmFwKH5QcmltZXIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKC0xMDAsMTAwKSxsaW5ldHlwZT00KSsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLGhlaWdodCA9IDAuMSxzaXplICA9IDAuNCkrIAogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9IGdnYWxsaW46OnBzZXVkb2xvZzEwX3RyYW5zLCAKICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygtMjAwMCwtMTAwMCwtNTAwLC0xMDAsLTUwLC0xMCwtNSwtMSwwLDEsNSwxMCw1MCwxMDAsNTAwLDEwMDAsMjAwMCkKICAgICAgICAgICAgICAgICAgICAgKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnM2W2MoMSwzLDUpXSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUpKSAKCmdnc2F2ZShmaWxlID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9qdW4yMl9zZmpxX2ZvbGRjaGFuZ2VfYm94cGxvdC5wZGYiLCBwbG90ID0gZm9sZF9jaGFuZ2VfYm94cGxvdCwgZGV2aWNlID0gInBkZiIsIHdpZHRoID0gNDAsIGhlaWdodCA9IDI0LCB1bml0cyA9ICJjbSIsIGRwaSA9IDYwMCkKCgoKCiN0ZW50YW5kbyBmYXplciB1bSBwb2ludCByZWdyZXNzaW9uIHNoYWRlIC0tLS0KCgp0aWJfY3VyYXRlZF9TRkpRX2FsbF9wb29scyAlPiUgCiAgICB1bml0ZShOb3JtYWxpemF0aW9uLCBQcmltZXIsIGNvbCA9ICJQcmltZXJfbm9ybSIscmVtb3ZlID0gRixzZXAgPSAiICIpICU+JQogIG11dGF0ZShQcmltZXJfbm9ybSA9IGZhY3RvcihQcmltZXJfbm9ybSwgbGV2ZWxzID0gYygKICAgICJOb3JtYWxpemVkIE5lb0Zpc2giLCJOb24tbm9ybWFsaXplZCBOZW9GaXNoIiwKICAgICJOb3JtYWxpemVkIE1pRmlzaCIsIk5vbi1ub3JtYWxpemVkIE1pRmlzaCIsCiAgICAiTm9ybWFsaXplZCBUZWxlbyIsIk5vbi1ub3JtYWxpemVkIFRlbGVvIikpKSAlPiUKICAjIGNvbG5hbWVzKCkKICBnZ3Bsb3QoYWVzKAogICAgeCA9IGBpbnB1dCBETkEgKCUpYCwKICAgIHkgPSBgUlJBICglKWAsCiAgICBjb2wgPSBQcmltZXJfbm9ybSwKICAgICMgZ3JvdXAgPSBHcm91cCwKICAgIHNoYXBlID0gR3JvdXApKSArCiAgZ2VvbV9wb2ludChzaXplICA9IDAuNSkgKyAKICAjIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9IGdnYWxsaW46OnBzZXVkb2xvZzEwX3RyYW5zLCAKICAjICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC0yMDAwLC0xMDAwLC01MDAsLTEwMCwtNTAsLTEwLC01LC0xLDAsMSw1LDEwLDUwLDEwMCw1MDAsMTAwMCwyMDAwKQogICMgICAgICAgICAgICAgICAgICAgICkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUpKSArCiB4bGFiKCJJbnB1dCBETkEgKCUpIikgKwogIHlsYWIoIlJlbGF0aXZlIFJlYWQgQWJ1bmRhbmNlICglKSIpICsKICBnZ3RpdGxlKCJTRm1jICYgSlFtYzogQ29ycmVsYXRpb24gYmV0d2VlblxuSW5wdXQgRE5BIGFuZCBSUkEiKSArCiAgc2NhbGVfeF9zcXJ0KGJyZWFrcz1jKDAsMC4wMDAxLDAuMDAxLDAuMDEsMC4wMjUsMC4wNSwwLjEsMC4yLDAuMywwLjQsMC42LDAuOCwxKSoxMDApICsKICBzY2FsZV95X3NxcnQoYnJlYWtzPWMoMCwwLjAwMDEsMC4wMDEsMC4wMSwwLjAyNSwwLjA1LDAuMSwwLjIsMC4zLDAuNCwwLjYsMC44LDEpKjEwMCkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLGFlcyhmaWxsPVByaW1lcl9ub3JtKSkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JzNikgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JzNikgKwogIGNvb3JkX2ZpeGVkKCkgKwogICMgZmFjZXRfd3JhcChNQ35QcmltZXIsbmNvbCA9IDMpCiAgZmFjZXRfd3JhcChQb29sflByaW1lcixuY29sID0gNSkgCgoKCgoKYGBgCgojIFJlZmVyZW5jZXMKClRoaXMgYW5hbHlzZXMgd2VyZSBiYXNlZCBhbmQgaW5waXJlZCBvbiBvdGhlciBpbmNyZWRpYmxlIHJlc291cmNlcywgbGlzdGVkIGJlbG93OgoKKiBbU2FtcGxlKEVjb2xvZ3kpIC0tIEpvbiBMZWZjaGVja10oaHR0cHM6Ly9qb25sZWZjaGVjay5uZXQvMjAxMi8xMC8yNC9ubWRzLXR1dG9yaWFsLWluLXIvIzp+OnRleHQ9S2VlcCUyMGdvaW5nJTJDJTIwYW5kJTIwaW1hZ2luZSUyMGFzLGFuZCUyMHRvJTIwc3BhcmUlMjB5b3VyJTIwdGhpbmtlcikuKQoKKiBbUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyBpbiBSOiBwcmNvbXAgdnMgcHJpbmNvbXAgLS0ga2Fzc2FtYmFyYSAgXShodHRwOi8vd3d3LnN0aGRhLmNvbS9lbmdsaXNoL2FydGljbGVzLzMxLXByaW5jaXBhbC1jb21wb25lbnQtbWV0aG9kcy1pbi1yLXByYWN0aWNhbC1ndWlkZS8xMTgtcHJpbmNpcGFsLWNvbXBvbmVudC1hbmFseXNpcy1pbi1yLXByY29tcC12cy1wcmluY29tcC8pCiAgICAKKiBbQW5hbHlzaXMgb2YgY29tbXVuaXR5IGVjb2xvZ3kgZGF0YSBpbiBSIC0tIERhdmlkIFplbGVuw71dKGh0dHBzOi8vd3d3LmRhdmlkemVsZW55Lm5ldC9hbmFkYXQtci9kb2t1LnBocC9lbjpwY29hX25tZHMpCgoKCgpgYGB7ciBlY2hvPUZBTFNFLGV2YWw9RkFMU0V9CiNjaXRlCiMgaHR0cHM6Ly9qb25sZWZjaGVjay5uZXQvMjAxMi8xMC8yNC9ubWRzLXR1dG9yaWFsLWluLXIvIzp+OnRleHQ9S2VlcCUyMGdvaW5nJTJDJTIwYW5kJTIwaW1hZ2luZSUyMGFzLGFuZCUyMHRvJTIwc3BhcmUlMjB5b3VyJTIwdGhpbmtlcikuCgojIGh0dHA6Ly93d3cuc3RoZGEuY29tL2VuZ2xpc2gvYXJ0aWNsZXMvMzEtcHJpbmNpcGFsLWNvbXBvbmVudC1tZXRob2RzLWluLXItcHJhY3RpY2FsLWd1aWRlLzExOC1wcmluY2lwYWwtY29tcG9uZW50LWFuYWx5c2lzLWluLXItcHJjb21wLXZzLXByaW5jb21wLwoKIyBodHRwczovL3d3dy5kYXZpZHplbGVueS5uZXQvYW5hZGF0LXIvZG9rdS5waHAvZW46cGNvYV9ubWRzCgpgYGAKCjxicj4KCgoKCiNCb251cyAKCiMjIE5lb0Zpc2ggcmVkZXNpZ24KCmBgYHtyIGVjaG89RkFMU0UsZXZhbD1GQUxTRX0KI2luZm8gLS0tLQoKIyBhdXRob3I6IEhlcm9uIE8uIEhpbMOhcmlvCiMgcHVycG9zZTogaW50ZWdyYXRlIHNlcXVlbmNlIGZpbGVzIGZyb20gZGlmZmVyZW50IG9yaWdpbnMKIyAgICAgICAgIHRvIGNvbnN0cnVjdCB0aGUgTEdDIDEyUyBzZXF1ZW5jZSBkYXRhYmFzZSBhbmQgZm9ybWF0IGl0CiMgICAgICAgICBmb3IgdXNhZ2UgaW4gREFEQTIuCiMKIyByZWZlcmVuY2VzOgojIGh0dHBzOi8vd3d3LmJpb2NvbmR1Y3Rvci5vcmcvaGVscC9jb3Vyc2UtbWF0ZXJpYWxzLzIwMTYvQmlvQzIwMTYvQ29uY3VycmVudFdvcmtzaG9wczIvV3JpZ2h0L0JpZ0Jpb1NlcURhdGEucGRmCiMgaHR0cHM6Ly93d3cuYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvdmlnbmV0dGVzL0RFQ0lQSEVSL2luc3QvZG9jL0RFQ0lQSEVSaW5nLnBkZgojIGh0dHA6Ly93d3cyLmRlY2lwaGVyLmNvZGVzL1JMZXNzb25zL1JMZXNzb24xNC5odG1sCiMgaHR0cHM6Ly9iZXNqb3VybmFscy5vbmxpbmVsaWJyYXJ5LndpbGV5LmNvbS9kb2kvZnVsbC8xMC4xMTExLzIwNDEtMjEwWC4xMjY4NwojIGh0dHA6Ly93d3cyLmRlY2lwaGVyLmNvZGVzL09saWdvRGVzaWduLmh0bWwKIyBodHRwOi8vd3d3Mi5kZWNpcGhlci5jb2Rlcy9CaW9pbmZvcm1hdGljcy9CaWdCaW9TZXFEYXRhL0JpZ0Jpb1NlcURhdGEyLmh0bWwKIyBodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dkZW5kcm8vdmlnbmV0dGVzL2dnZGVuZHJvLmh0bWwKCiMwLSBsb2FkIGxpYnJhcmllcyAtLS0tCnsKICBsaWJyYXJ5KGdnc2VxbG9nbykKICBsaWJyYXJ5KERFQ0lQSEVSKQp9CiMxLSBpbXBvcnQgc2VxcyB0byBkYiAtLS0tCgojY3JlYXQvbG9hZCBTUUxkYgpkYl9maXNoMTJTIDwtIGRiQ29ubmVjdChTUUxpdGUoKSwgIn4vb3V0cm9zL3NmanFfdGVtcC9kYi9maXNoMTJTX2FsbF9zZXFzX25vdjIxLnNxbCIpCgoKI3NlcXXDqm5jaWFzIGRvIExHQyAxMlMgZGIKIyBTZXFzMkRCKHNlcSA9ICJ+L3ByamN0cy9maXNoX2VETkEvIiwKU2VxczJEQihzZXEgPSAifi9vdXRyb3Mvc2ZqcV90ZW1wL2RiL2RhZGFfdGF4X2Z1bGxEQl9vcmRlcl9TUHNfZGV6MjEuZmFzdGEiLAogICAgICAgIHR5cGUgPSAgIkZBU1RBIixkYkZpbGUgPSAgZGJfZmlzaDEyUywgaWRlbnRpZmllciA9ICAiTEdDIDEyUyBEQiIpCgoKQnJvd3NlREIoZGJfZmlzaDEyUykKCiMyLSBhZGQgc2VxIGluZm8gdG8gREIgLS0tLQoKI3NlcWxlbmd0aHMgdG8gREIKbCA8LSBERUNJUEhFUjo6SWRMZW5ndGhzKGRiRmlsZSA9IGRiX2Zpc2gxMlMpCgpBZGQyREIobCwgZGJfZmlzaDEyUywgdmVyYm9zZT1UUlVFKQpCcm93c2VEQihkYl9maXNoMTJTKQoKIzMtIGdldCBhbGwgc2VxcyBmcm9tIERCIC0tLS0KCgpkbmFfMTJTZGIgPC0gU2VhcmNoREIoZGJGaWxlID0gZGJfZmlzaDEyUyxpZGVudGlmaWVyID0gIkxHQyAxMlMgREIiLG5hbWVCeSA9ICJkZXNjcmlwdGlvbiIpCgojbWVyZ2Ugc2VxIHNldHMKZG5hX2FsbCA8LSBkbmFfMTJTZGIKCgojNC0gY3JlYXRlIGFuZCBhc3NpZ24gbmV3IG5hbWVzIC0tLS0KCkRCX3RibCA8LSB0aWJibGUoIk9yaWdpbmFsIG5hbWVzIiA9IG5hbWVzKGRuYV9hbGwpLAogICAgICAgICAgICAgICAgICJJZGVudGlmaWVyIiA9IGFzLmNoYXJhY3RlcigiIiksCiAgICAgICAgICAgICAgICAgIk5hbWVzIiA9IGFzLmNoYXJhY3RlcigiIiksCiAgICAgICAgICAgICAgICAgIlJpdmVyIGJhc2luIiA9IGFzLmNoYXJhY3RlcigiIiksCiAgICAgICAgICAgICAgICAgIkNsdXN0ZXIiID0gYXMubnVtZXJpYygiIiksCiAgICAgICAgICAgICAgICAgIkNvbXBvc2VkIG5hbWUiPSBhcy5jaGFyYWN0ZXIoIiIpLAogICAgICAgICAgICAgICAgICJnZW51cyI9IGFzLmNoYXJhY3RlcigiIikpICMgaXQgd2lsbCBiZSB1c2VkIHRvIHNlYXJjaCBOQ0JJCgoKIyBpZGVudGlmeSBiYXNpbiBmcm9tIG9yaWdpbiBmaWxlCmZvciAoc2VxIGluIDE6bnJvdyhEQl90YmwpKSB7CiAgaWYgKERCX3RibCRgT3JpZ2luYWwgbmFtZXNgW3NlcV0gJWluJSBuYW1lcyhkbmFfc2YpKSB7CiAgICBEQl90YmwkYFJpdmVyIGJhc2luYFtzZXFdID0gIlNGIn0KCiAgaWYgKERCX3RibCRgT3JpZ2luYWwgbmFtZXNgW3NlcV0gJWluJSBuYW1lcyhkbmFfanEpKSB7CiAgICBEQl90YmwkYFJpdmVyIGJhc2luYFtzZXFdID0gIkpxIn0KCiAgaWYgKERCX3RibCRgT3JpZ2luYWwgbmFtZXNgW3NlcV0gJWluJSBuYW1lcyhkbmFfbm9uKSl7CiAgICBEQl90YmwkYFJpdmVyIGJhc2luYFtzZXFdID0gIk91dCJ9CgogIGlmIChEQl90YmwkYE9yaWdpbmFsIG5hbWVzYFtzZXFdICVpbiUgbmFtZXMoZG5hX3NmanEyKSl7CiAgICBEQl90YmwkYFJpdmVyIGJhc2luYFtzZXFdID0gIlNGSnEyIn0KfQoKCiMgY29ycmVjdCBzcGVjaWVzIG5hbWUKZm9yIChzZXEgaW4gMTpucm93KERCX3RibCkpIHsKCiAgREJfdGJsJElkZW50aWZpZXJbc2VxXSA8LSAgc3RyX3NwbGl0X2ZpeGVkKHN0cmluZyA9IERCX3RibCRgT3JpZ2luYWwgbmFtZXNgW3NlcV0sIHBhdHRlcm4gPSAiXyIsIG4gPSAyKVsxXQogIERCX3RibCROYW1lc1tzZXFdIDwtIHN0cl9zcGxpdF9maXhlZChzdHJpbmcgPSBEQl90YmwkYE9yaWdpbmFsIG5hbWVzYFtzZXFdLCBwYXR0ZXJuID0gIl8iLCBuID0gMilbMl0gJT4lCiAgICBzdHJfcmVwbGFjZV9hbGwocGF0dGVybiA9ICJfIixyZXBsYWNlbWVudCA9ICIgIikgI21ha2UgcmVwbGFjZW1lbnQgdG8gcmVtb3YgYWZmLCBjZi4uLgogIERCX3RibCRnZW51c1tzZXFdIDwtIHN0cl9zcGxpdChzdHJpbmcgPSBEQl90YmwkTmFtZXNbc2VxXSxwYXR0ZXJuID0gIiAiKVtbMV1dWzFdCgp9CgojIGNyZWF0ZSBuZXcgbmFtZSBhbmQgYXNzaWduIHRvIG9yaWdpbmFsIHNlcXVlbmNlcwoKZm9yIChzZXEgaW4gMTpucm93KERCX3RibCkpIHsKICBmb3IgKHNlcTIgaW4gMTpsZW5ndGgoZG5hX2FsbCkpewoKICAgIGlmIChuYW1lcyhkbmFfYWxsKVtzZXEyXSA9PSBEQl90YmwkYE9yaWdpbmFsIG5hbWVzYFtzZXFdKSB7CgogICAgICBuYW1lcyhkbmFfYWxsKVtzZXEyXSA8LSBwYXN0ZTAoREJfdGJsJGBSaXZlciBiYXNpbmBbc2VxXSwiIHwgIixEQl90YmwkTmFtZXNbc2VxXSwiIHwgIixEQl90YmwkSWRlbnRpZmllcltzZXFdKQogICAgICBEQl90YmwkYENvbXBvc2VkIG5hbWVgW3NlcV0gPC0gbmFtZXMoZG5hX2FsbClbc2VxMl0KICAgIH0KICB9Cn0KCgoKIzYtIGFsaWduIERCIHNlcXMgLS0tLQojcmVtb3ZlIG5vbi1maXNoIHNlcXVlbmNlcwoKICAgICAgICAgICAgIyBkbmFfYWxsIDwtIGRuYV9hbGxbIShuYW1lcyhkbmFfYWxsKSAlaW4lIGMoIk91dCB8IEhvbW8gc2FwaWVucyB8IEpOMDM0MTA5LjEiLCAjcmVtb3ZpbmcKICAgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk91dCB8IEJvcyB0YXVydXMgfCBBSjg4NTIwMS4xIikpXSAjcmVtb3ZpbmcKIyBzZWxlY3Qgb25seSBzcGVjaWVzIGluIHBvb2xzCiNvcmluZW50YXJzZXF1ZW5jaWFzIGFudGVzIGRvIGFsaW5oYW1lbnRvIGNhc28gdGVuaGEgYWxndW1hIGludmVydGlkYQoKZG5hX2FsbCAlPiUgbmFtZXMoKSAlPiUgcGFzdGUwKGNvbGxhcHNlID0gJyIsXG4iJykgJT4lIGNhdCgpCgoKCgpjKAoiIHwgIHwgU0YgfCBGcmFuY2lzY29kb3JhcyBtYXJtb3JhdHVzIHwgMDcwOCIsCiIgfCAgfCBTRiB8IFRldHJhZ29ub3B0ZXJ1cyBjaGFsY2V1cyB8IDA5MDEiLAoiIHwgIHwgU0YgfCBSb2Vib2lkZXMgeGVub2RvbiB8IDA5MTYiLAoiIHwgIHwgU0YgfCBCcnljb24gb3J0aG90YWVuaWEgfCAxMDM3IiwKIiB8ICB8IFNGIHwgSHlwb3N0b211cyBhbGF0dXMgfCAxMDQxIiwKIiB8ICB8IFNGIHwgUGFtcGhvcmljaHRoeXMgaG9sbGFuZGkgfCAxMDk5IiwKIiB8ICB8IFNGIHwgTWljcm9nbGFuaXMgbGVwdG9zdHJpYXR1cyB8IDExMDQiLAoiIHwgIHwgU0YgfCBNb2Vua2hhdXNpYSBzYW5jdGFlZmlsb21lbmFlIHwgMTExMyIsCiIgfCAgfCBTRiB8IEVpZ2VubWFubmlhIHZpcmVzY2VucyB8IDExMTciLAoiIHwgIHwgU0YgfCBQdGVyeWdvcGxpY2h0aHlzIGV0ZW50YWN1bGF0dXMgfCAxMTQxIiwKIiB8ICB8IFNGIHwgQXN0eWFuYXggY2YgZmFzY2lhdHVzIHwgMTE1MyIsCiIgfCAgfCBTRiB8IEltcGFyZmluaXMgbWludXR1cyB8IDExNjEiLAoiIHwgIHwgU0YgfCBNeWxldXMgbWljYW5zIHwgMTE2MiIsCiIgfCAgfCBTRiB8IFNlcnJhc2FsbXVzIGJyYW5kdGlpIHwgMTIzMCIsCiIgfCAgfCBTRiB8IFRyYWNoZWx5b3B0ZXJ1cyBnYWxlYXR1cyB8IDEyNDMiLAoiIHwgIHwgU0YgfCBHeW1ub3R1cyBjYXJhcG8gfCAxMjQ4IiwKIiB8ICB8IFNGIHwgQ3JlbmljaWNobGEgbGVwaWRvdGEgfCAxMjY0IiwKIiB8ICB8IFNGIHwgUGltZWxvZHVzIG1hY3VsYXR1cyB8IDEyODAiLAoiIHwgIHwgU0YgfCBQcm9jaGlsb2R1cyBjb3N0YXR1cyB8IDEzMzkiLAoiIHwgIHwgU0YgfCBQaGFsbG9jZXJvcyB1YWkgfCAxMzY4IiwKIiB8ICB8IFNGIHwgSG9wbGlhcyBpbnRlcm1lZGl1cyB8IDEzNzciLAoiIHwgIHwgU0YgfCBDaGFyYWNpZGl1bSBsYWdvc2FudGVuc2UgfCAxMzgxIiwKIiB8ICB8IFNGIHwgUGltZWxvZHVzIHBvaGxpIHwgMTQwMyIsCiIgfCAgfCBKcSB8IEd5bW5vdHVzIGNhcmFwbyB8IDE2MzEiLAoiIHwgIHwgSnEgfCBIeXBvc3RvbXVzIHNwIHwgMTcxMSIsCiIgfCAgfCBKcSB8IE1lZ2FsZXBvcmludXMgZWxvbmdhdHVzIHwgMTc2MiIsCiIgfCAgfCBKcSB8IFByb2NoaWxvZHVzIGhhcnRpaSB8IDE3NjUiLAoiIHwgIHwgSnEgfCBNZWdhbGVwb3JpbnVzIGVsb25nYXR1cyB8IDE3NjEiLAoiIHwgIHwgSnEgfCBIb3BsaWFzIGJyYXNpbGllbnNpcyB8IDE3NzIiLAoiIHwgIHwgSnEgfCBEZWx0dXJ1cyBicmV2aXMgfCAxOTM2IiwKIiB8ICB8IEpxIHwgU3RlaW5kYWNobmVyaW5hIGVsZWdhbnMgfCAyMzEiLAoiIHwgIHwgSnEgfCBIb3Bsb3N0ZXJudW0gbGl0dG9yYWxlIHwgMjY0MyIsCiIgfCAgfCBKcSB8IFByb2NoaWxvZHVzIGNvc3RhdHVzIHwgMjg2MCIsCiIgfCAgfCBKcSB8IENvbG9zc29tYSBtYWNyb3BvbXVtIHwgMjg3MSIsCiIgfCAgfCBKcSB8IEFuY2hvdmllbGxhIGxlcGlkZW50b3N0b2xlIHwgMjkxMiIsCiIgfCAgfCBKcSB8IFdlcnRoZWltZXJpYSBtYWN1bGF0YSB8IDc5MDYiLAoiIHwgIHwgSnEgfCBIeXBvc3RvbXVzIG5pZ3JvbGluZWF0dXMgfCA3ODkzIiwKIiB8ICB8IEpxIHwgTHljZW5ncmF1bGlzIGdyb3NzaWRlbnMgfCAyOTE4IiwKIiB8ICB8IEpxIHwgU2VycmFzYWxtdXMgYnJhbmR0aWkgfCA3ODkwIiwKIiB8ICB8IEpxIHwgQ2ljaGxhc29tYSBmYWNldHVtIHwgMjkyIiwKIiB8ICB8IEpxIHwgQ2ljaGxhIGtlbGJlcmkgfCAyOTMyIiwKIiB8ICB8IEpxIHwgRXVnZXJyZXMgYnJhc2lsaWFudXMgfCAyOTQzIiwKIiB8ICB8IEpxIHwgSHlwb21hc3RpY3VzIHN0ZWluZGFjaG5lcmkgfCAyOTg0IiwKIiB8ICB8IEpxIHwgU3RlaW5kYWNobmVyaWRpb24gYW1ibHl1cnVtIHwgMjk5NiIsCiIgfCAgfCBKcSB8IEdlb3BoYWd1cyBicmFzaWxpZW5zaXMgfCAzMDMiLAoiIHwgIHwgSnEgfCBHZW9waGFndXMgYnJhc2lsaWVuc2lzIHwgMzA0IiwKIiB8ICB8IEpxIHwgUmhhbWRpYSBjZiBqZXF1aXRpbmhvbmhhIHwgMzA1NCIsCiIgfCAgfCBKcSB8IFBhcmVpb3JoYXBoaXMgc3RlcGhhbnVzIHwgNDE5NiIsCiIgfCAgfCBKcSB8IE1lZ2FsZXBvcmludXMgZ2FybWFuaSB8IDQyOTAiLAoiIHwgIHwgSnEgfCBIYXJ0dGlhIGdhcmF2ZWxsb2kgfCA0MzkiLAoiIHwgIHwgSnEgfCBQcm9jaGlsb2R1cyBhcmdlbnRldXMgfCA1NjEyIiwKIiB8ICB8IEpxIHwgUmhhbWRpYSBhZmYgcXVlbGVuIHwgNTY0NSIsCiIgfCAgfCBKcSB8IEh5cG9zdG9tdXMgc3AgfCA1NjUwIiwKIiB8ICB8IEpxIHwgSHlwb21hc3RpY3VzIHN0ZWluZGFjaG5lcmkgfCA1NjY0IiwKIiB8ICB8IEpxIHwgQXN0eWFuYXggY2YgbGFjdXN0cmlzIHwgNTY3MiIsCiIgfCAgfCBKcSB8IFRyYWNoZWx5b3B0ZXJ1cyBjZiBnYWxlYXR1cyB8IDU2NzUiLAoiIHwgIHwgSnEgfCBBc3R5YW5heCBhZmYgZmFzY2lhdHVzIHwgNTY5MyIsCiIgfCAgfCBKcSB8IEFzdHlhbmF4IGFmZiBmYXNjaWF0dXMgfCA1Njk0IiwKIiB8ICB8IEpxIHwgQXN0eWFuYXggYWZmIGZhc2NpYXR1cyB8IDU2OTUiLAoiIHwgIHwgSnEgfCBIeXBvc3RvbXVzIHNwIHwgNTcwMyIsCiIgfCAgfCBKcSB8IEh5cG9zdG9tdXMgc3AgfCA1NzA0IiwKIiB8ICB8IEpxIHwgU2VycmFzYWxtdXMgYnJhbmR0aWkgfCA2MjYxIiwKIiB8ICB8IEpxIHwgVHJhY2hlbHlvcHRlcnVzIHN0cmlhdHVsdXMgfCA2NTgzIiwKIiB8ICB8IEpxIHwgQXVzdHJhbG9oZXJvcyBzcCB8IDY1ODQiLAoiIHwgIHwgSnEgfCBTdGVpbmRhY2huZXJpbmEgZWxlZ2FucyB8IDY1ODYiLAoiIHwgIHwgSnEgfCBDaWNobGEgc3AgfCA2NTkwIiwKIiB8ICB8IEpxIHwgSG9wbGlhcyBzcCB8IDY2MzAiLAoiIHwgIHwgSnEgfCBNZWdhbGVwb3JpbnVzIGVsb25nYXR1cyB8IDY2MzMiLAoiIHwgIHwgSnEgfCBQcm9jaGlsb2R1cyBoYXJ0aWkgfCA3MDMzIiwKIiB8ICB8IEpxIHwgT2xpZ29zYXJjdXMgbWFjcm9sZXBpcyB8IDc2OTAiLAoiIHwgIHwgSnEgfCBNb2Vua2hhdXNpYSBjb3N0YWUgfCA3ODEyIiwKIiB8ICB8IEpxIHwgV2VydGhlaW1lcmlhIG1hY3VsYXRhIHwgNzgxNyIsCiIgfCAgfCBKcSB8IEhvcGxpYXMgbWFsYWJhcmljdXMgfCA3ODIyIiwKIiB8ICB8IEpxIHwgSHlwb21hc3RpY3VzIHN0ZWluZGFjaG5lcmkgfCA3ODI2IiwKIiB8ICB8IEpxIHwgQXN0eWFuYXggbGFjdXN0cmlzIHwgNzg4MCIsCiIgfCAgfCBPdXQgfCBQcmlvbmFjZSBnbGF1Y2EgfCBBRjQ0ODAwOC4xIiwKIiB8ICB8IE91dCB8IEJvcyB0YXVydXMgfCBBSjg4NTIwMS4xIiwKIiB8ICB8IE91dCB8IEhvbW8gc2FwaWVucyB8IEpOMDM0MTA5LjEiLAoiIHwgIHwgT3V0IHwgUHJvY2hpbG9kdXMgY29zdGF0dXMgfCBOQzAyNzY5MC4xIiwKIiB8ICB8IE91dCB8IENhbmlzIGZhbWlsaWFyaXMgfCBBWTcyOTg4MC4xIiwKIiB8ICB8IFNGSnEyIHwgS25vZHVzIG1vZW5raGF1c2lpICB8IEtGMjA5NjE4LjEiLAoiIHwgIHwgU0ZKcTIgfCBDb25vcmh5bmNob3MgY29uaXJvc3RyaXMgfCBKWDg5OTczNy4xIiwKIiB8ICB8IFNGSnEyIHwgTGVwb3JlbGx1cyB2aXR0YXR1cyB8IExDMTA0Mzk5LjEiKQoKCgoKZG5hX2FsbCA8LSBPcmllbnROdWNsZW90aWRlcyhkbmFfYWxsKQpuYW1lcyhkbmFfYWxsKQoKZG5hX2FsaWduZWQgPC0gQWxpZ25TZXFzKG15WFN0cmluZ1NldCA9IGRuYV9hbGwscmVmaW5lbWVudHMgPSA3MDAsaXRlcmF0aW9ucyA9IDcwMCx2ZXJib3NlID0gVFJVRSkKCiMgQnJvd3NlU2VxcyhkbmFfYWxpZ25lZCxjb2xvclBhdHRlcm5zID0gYygzMDAsNjAwKSkKQnJvd3NlU2VxcyhkbmFfYWxpZ25lZCkKCiM3IC0gZGlzdGFuY2UgbWF0cml4IC0tLS0KCmRuYV9hbGdfc3ViIDwtIHN1YnNlcSh4ID0gZG5hX2FsaWduZWQsc3RhcnQgPSAzMDAsZW5kID0gMTEwMCkKCmRuYV9hbGdfc3ViIDwtIFJlbW92ZUdhcHMobXlYU3RyaW5nU2V0ID0gZG5hX2FsZ19zdWIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc29ycyA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZUdhcHMgPSAiYWxsIikKCmRuYV9hbGdfc3ViIDwtICBBbGlnblNlcXMobXlYU3RyaW5nU2V0ID0gZG5hX2FsZ19zdWIscmVmaW5lbWVudHMgPSA3MDAsaXRlcmF0aW9ucyA9IDcwMCx2ZXJib3NlID0gVFJVRSkKCgpCcm93c2VTZXFzKGRuYV9hbGdfc3ViKQoKCiMgSWRlbnRpZnkgY2x1c3RlcnMgZm9yIHByaW1lciBkZXNpZ24KZG5hX2FsZ19zdWJfZGlzdCA8LSBEaXN0YW5jZU1hdHJpeChteVhTdHJpbmdTZXQgPSBkbmFfYWxnX3N1YiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZVRlcm1pbmFsR2FwcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uID0gIkp1a2VzLUNhbnRvciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NvcnMgPSAyMCkKZGltKGRuYV9hbGdfc3ViX2Rpc3QpICMgYSBzeW1tZXRyaWMgbWF0cml4CgojOCAtIENsdXN0ZXJzIC0tLS0KI2lkZW50aWZpY2FyIGNsdXN0ZXJzIG5hIHNlcXVlbmNhaXMgZW0gZnVuw6fDo28gZGUgc3VhcyBkaXN0w6JuY2lhcwoKZG5hX2NsdXN0IDwtIElkQ2x1c3RlcnMoZG5hX2FsZ19zdWJfZGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD0iVVBHTUEiLAogICAgICAgICAgICAgICAgICAgICAgICAgY3V0b2ZmPTAuMDUsCiAgICAgICAgICAgICAgICAgICAgICAgICBzaG93PVRSVUUsICNnZXJhIHVtIGNsYWRvZ3JhbWEsIG11aXRvIGRpZmljaWwgZGUgY29uZmlndXJhci9pbnRlcnByZXRhcgogICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJib3RoIikKaGVhZChkbmFfY2x1c3QpICMgY2x1c3RlciBudW1iZXJzCgoKI0FkaWNpb25hciBhIGluZm8gZGUgY2x1c3RlcnMgbm8gREIKCiMgSWRlbnRpZnkgc2VxdWVuY2VzIGJ5IGNsdXN0ZXIgbmFtZSBpbiB0aGUgZGF0YWJhc2UKQWRkMkRCKGRhdGEuZnJhbWUoCiAgY2x1c3Rlcj1kbmFfY2x1c3RbWzFdXSRjbHVzdGVyKSwKICBkYkZpbGUgPSBkYl9maXNoMTJTLAogIHZlcmJvc2UgPSBUUlVFKQoKQnJvd3NlREIoZGJfZmlzaDEyUyxvcmRlckJ5ID0gImNsdXN0ZXIiKQoKCiNhZGQgY2x1c3RlcnMgdG8gREJfdGJsCgpmb3IgKHNlcSBpbiAxOm5yb3coREJfdGJsKSkgewogIGZvciAoc2VxMiBpbiAxOm5yb3coZG5hX2NsdXN0W1sxXV0pKSB7CgogICAgaWYgKChyb3duYW1lcyhkbmFfY2x1c3RbWzFdXSlbc2VxMl0pID09IChEQl90YmwkYENvbXBvc2VkIG5hbWVgW3NlcV0pKSB7CiAgICAgIERCX3RibCRDbHVzdGVyW3NlcV0gPC0gKGRuYV9jbHVzdFtbMV1dW3NlcTIsXSkKICAgIH0KICB9Cn0KCiMgREJfdGJsICU+JQojICAgYXJyYW5nZShieSA9IENsdXN0ZXIpCgojb3JkZXIgc2VxcyBieSBjbHVzdGVyIGFuZCB3cml0ZSBmYXN0YQpkbmFfb3JkZXIgPC0gZG5hX2FsZ19zdWJbb3JkZXIoREJfdGJsJENsdXN0ZXIpLF0KCgoKCgp3cml0ZVhTdHJpbmdTZXQoeCA9IGRuYV9vcmRlciwKICAgICAgICAgICAgICAgIGZpbGVwYXRoID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9kYXRhL3JlZnMvZGIvREJfb3JkZXJfY2x1c3QuZmFzdGEiLAogICAgICAgICAgICAgICAgZm9ybWF0ID0gImZhc3RhIikKCiMgdGhpcyBmaWxlIHdhcyB1c2VkIHRvIGdlbmVyYXRlIGEgTUx0cmVlIG9uIE1FR0FYLCB0byBpZGVudGlmeSBpZGVudGljIHNlcXVlbmNlcwoKCiM5LSBnZXQgdGF4b25vbWljIGluZm9ybWF0aW9uIHRvIGNvbnN0cnVjdCBEQURBMiBmb3JtYXRlZCBoZWFkZXJzLS0tLQoKI2xvYWQgZW50cmV6IGZ1bmN0aW9uCmV4dHJhY3RfdGF4b25vbXkgPC0gZnVuY3Rpb24ob3JnYW5pc21fbmFtZSkgewogIGAlPiVgIDwtIGRwbHlyOjpgJT4lYAogIG9yZ2FuaXNtX3htbCA8LSBzeXM6OmV4ZWNfaW50ZXJuYWwoImJhc2giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJncyA9IGMoIi9vcHQvc3JjL2VudHJlel90YXhvbm9teS5zaCIsIG9yZ2FuaXNtX25hbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZW91dCA9IDEwMDApCiAgaWYgKGxlbmd0aChzeXM6OmFzX3RleHQob3JnYW5pc21feG1sJHN0ZG91dCkpID09ICAwKSB7CiAgICBtZXNzYWdlKHBhc3RlMCgiZGV1IGVycmFkbyBwYXJhOiAiLG9yZ2FuaXNtX25hbWUpKQogICAgcmV0dXJuKHRpYmJsZSgpKQogIH1lbHNlewogICAgb3JnYW5pc21fZGYgPC0gc3lzOjphc190ZXh0KG9yZ2FuaXNtX3htbCRzdGRvdXQpICU+JQogICAgICBqc29ubGl0ZTo6ZnJvbUpTT04oKQogICAgbWVzc2FnZShwYXN0ZTAoImRldSBjZXJ0byBwYXJhOiAiLG9yZ2FuaXNtX25hbWUpKQoKICAgIHJldHVybihvcmdhbmlzbV9kZikKICB9Cn0KCiNjbGVhciB3YXJuaW5ncwojYXNzaWduKCJsYXN0Lndhcm5pbmciLCBOVUxMLCBlbnZpciA9IGJhc2VlbnYoKSkKCgojIGNyZWF0ZSBhbmQgZmlsbCB0YXhvbm9teSB0YWJsZSBmb3IgdGhlIGZ1bmN0aW9uCnRheG9ub215X2RmIDwtIGRwbHlyOjp0aWJibGUoKQoKb3JnczJzZWFyY2ggPC0gdW5pcXVlKHNvcnQuZGVmYXVsdChEQl90YmwkZ2VudXMpKQoKdGF4b25vbXlfZGYgPC0gcHVycnI6Om1hcF9kZihvcmdzMnNlYXJjaCwgZXh0cmFjdF90YXhvbm9teSkKIyAjdGF4b25vbXlfZGYgPC0gcHVycnI6Om1hcF9kZihEQl90YmwkZ2VudXMsIGV4dHJhY3RfdGF4b25vbXkpCgoKI3RlbnRhbmRvIGNvbSB1bSBmb3IKCnRheG9uc190YmwgPC0gdGliYmxlOjp0aWJibGUoKQoKZm9yICh0YXhhIGluIDE6bGVuZ3RoKG9yZ3Myc2VhcmNoKSkgewoKICAjIHRheG9ub215X2RmIDwtIHB1cnJyOjptYXBfZGYob3JnczJzZWFyY2hbdGF4YV0sIGV4dHJhY3RfdGF4b25vbXkpICN1c2Ugb25seSBpZiBtYXBfZGYgZG9lc250IHdvcmsgZm9yIGFsbCB0b2dldGhlcgoKICB0YXhfZGYgPC0gdGF4b25vbXlfZGZbMV0kVGF4YVNldFtbdGF4YV1dJExpbmVhZ2VFeCRUYXhvbgoKICB0YXhfZGYgPC0gdGF4X2RmICU+JQogICAgbXV0YXRlKCJnZW51cyIgPSB0YXhvbm9teV9kZlsxXSRUYXhhU2V0W1t0YXhhXV0kU2NpZW50aWZpY05hbWUpCgogIHRheG9uc190YmwgPC0gZHBseXI6OmJpbmRfcm93cyh0YXhvbnNfdGJsLHRheF9kZikKCn0KCgoKIyBvcmdzMnNlYXJjaAoKIyB1bmlxdWUodGF4b25zX3RibCRnZW51cykKCgp0YXhvbnNfdGJsX2Jja3AgPC0gdGF4b25zX3RibAoKCiNvIG1hcF9kZiB0YSBkYW5kbyBlcnJvLCB2b3UgZmF6ZXIgY29tIHVtIGZvcgojCiMgdGF4b25vbXlfZGYgPC0gdmVjdG9yKG1vZGUgPSAibGlzdCIsIGxlbmd0aCA9IGxlbmd0aChvcmdzMnNlYXJjaCkpCiMKIyBmb3IgKG9yZyBpbiAxOmxlbmd0aChvcmdzMnNlYXJjaCkpIHsKIwojICAgdGF4b25vbXlfZGZbW29yZ11dPC0gZXh0cmFjdF90YXhvbm9teShvcmdhbmlzbV9uYW1lID0gb3JnczJzZWFyY2hbb3JnXSkKIwojIH0KIwoKCgoKCiMKIwojCiMgIyBjcmVhdGUgYSBhbmQgZmlsbCBhIGRhdGFmcmFtZSBmb3IgdGF4b25vbWljIHJhbmtzCiMgb3Jnc190YmwgPC0gdGliYmxlOjp0aWJibGUoKQojCiMgZm9yIChvcmcgaW4gMTpucm93KHRheG9ub215X2RmKSkgewojCiMgICBzY2luX25hbWUgPC0gdGF4b25vbXlfZGYkVGF4YVNldFtbb3JnXV0kU2NpZW50aWZpY05hbWUKIwojICAgb3JnX3RibCA8LSB0aWJibGU6OmFzX3RpYmJsZSh0YXhvbm9teV9kZiRUYXhhU2V0W1tvcmddXSRMaW5lYWdlRXgkVGF4b24pICU+JQojICAgICBkcGx5cjo6bXV0YXRlKCJnZW51cyIgPSBzY2luX25hbWUpJT4lCiMgICAgIGRwbHlyOjpmaWx0ZXIoUmFuayAlaW4lIGMoImtpbmdkb20iLCJwaHlsdW0iLCJjbGFzcyIsIm9yZGVyIiwiZmFtaWx5IikpICU+JQojICAgICB0aWR5cjo6cGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFJhbmssdmFsdWVzX2Zyb20gPSBjKFNjaWVudGlmaWNOYW1lLFRheElkKSkgJT4lCiMgICAgIGRwbHlyOjpzZWxlY3QoZ2VudXMsZHBseXI6OnN0YXJ0c193aXRoKCJTY2llIikpCiMKIyAgIG9yZ3NfdGJsIDwtIGRwbHlyOjpiaW5kX3Jvd3Mob3Jnc190Ymwsb3JnX3RibCkKIyB9CgoKIyBjcmVhdGUgYSBhbmQgZmlsbCBhIGRhdGFmcmFtZSBmb3IgdGF4b25vbWljIHJhbmtzCm9yZ3NfdGJsIDwtIHRpYmJsZTo6dGliYmxlKCkKCmZvciAob3JnIGluIDE6bGVuZ3RoKG9yZ3Myc2VhcmNoKSkgewoKICBvcmdfdGJsIDwtIHRheG9uc190YmwgJT4lCiAgICBmaWx0ZXIoZ2VudXMgPT0gb3JnczJzZWFyY2hbb3JnXSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKFJhbmsgJWluJSBjKCJraW5nZG9tIiwicGh5bHVtIiwiY2xhc3MiLCJvcmRlciIsImZhbWlseSIpKSAlPiUKICAgIHRpZHlyOjpwaXZvdF93aWRlcihuYW1lc19mcm9tID0gUmFuayx2YWx1ZXNfZnJvbSA9IGMoU2NpZW50aWZpY05hbWUsVGF4SWQpKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoZ2VudXMsZHBseXI6OnN0YXJ0c193aXRoKCJTY2llIikpCgogIG9yZ3NfdGJsIDwtIGRwbHlyOjpiaW5kX3Jvd3Mob3Jnc190Ymwsb3JnX3RibCkKfQoKCgoKIzEwLSBiaW5kIHRheCByYW5rIGNvbHMgdG8gREJfdGJsIC0tLS0KCmNvbG5hbWVzKG9yZ3NfdGJsKSA8LSBzdHJfcmVtb3ZlKHN0cmluZyA9IGNvbG5hbWVzKG9yZ3NfdGJsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJTY2llbnRpZmljTmFtZV8iKQpvcmdzX3RibCA8LSB1bmlxdWUob3Jnc190YmwpCgojIERCX3RibF9iY2twIDwtIERCX3RibAojIERCX3RibCA8LSBEQl90YmxfYmNrcAoKCkRCX3RibCA8LSBsZWZ0X2pvaW4oeCA9IERCX3RibCwgeSA9IG9yZ3NfdGJsLGJ5ID0gImdlbnVzIikKCkRCX3RibCA8LSBEQl90YmwgJT4lIG11dGF0ZSgiaGVhZGVycyIgPSBhcy5jaGFyYWN0ZXIoIiIpKQoKIzExLSBjcmVhdCBmYXN0YSBoZWFkZXJzIHdpdGggcmFua3MgZm9yIERBREEyIC0tLS0KCmZvciAoc2VxIGluIDE6bnJvdyhEQl90YmwpKSB7CiAgREJfdGJsJGhlYWRlcnNbc2VxXSA8LSBwYXN0ZTAoREJfdGJsJGtpbmdkb21bc2VxXSwiOyIsCiAgICAgICAgICAgICAgICAgICAgICBEQl90YmwkcGh5bHVtW3NlcV0sIjsiLAogICAgICAgICAgICAgICAgICAgICAgREJfdGJsJGNsYXNzW3NlcV0sIjsiLAogICAgICAgICAgICAgICAgICAgICAgREJfdGJsJG9yZGVyW3NlcV0sIjsiLAogICAgICAgICAgICAgICAgICAgICAgREJfdGJsJGZhbWlseVtzZXFdLCI7IiwKICAgICAgICAgICAgICAgICAgICAgIERCX3RibCRnZW51c1tzZXFdLCI7IiwKICAgICAgICAgICAgICAgICAgICAgIERCX3RibCROYW1lc1tzZXFdLCI7IiwKICAgICAgICAgICAgICAgICAgICAgIERCX3RibCRJZGVudGlmaWVyW3NlcV0sIjsiLAogICAgICAgICAgICAgICAgICAgICAgREJfdGJsJGBSaXZlciBiYXNpbmBbc2VxXSkKCn0KCiMxMi0gZ2VuZXJhdGUgZmluYWwgREIgZmFzdGEgLS0tLQoKCgpmaW5hbF9kbmEgPC0gUmVtb3ZlR2FwcyhteVhTdHJpbmdTZXQgPSBkbmFfYWxnX3N1YiwKICAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc29ycyA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVHYXBzID0gImFsbCIpCgoKI3JlbmFtZSBmaW5hbCBkbmEgaGVhZGVyCmZvciAoc2VxIGluIDE6bnJvdyhEQl90YmwpKSB7CiAgZm9yIChzZXEyIGluIDE6bGVuZ3RoKGZpbmFsX2RuYSkpewoKICAgIGlmIChuYW1lcyhmaW5hbF9kbmEpW3NlcTJdID09IERCX3RibCRgQ29tcG9zZWQgbmFtZWBbc2VxXSkgewoKICAgICAgbmFtZXMoZmluYWxfZG5hKVtzZXEyXSA8LSBEQl90YmwkaGVhZGVyc1tzZXFdCiAgICB9CiAgfQp9CgoKI29yZGVyIHNlcXMgYnkgY2x1c3RlciBhbmQgd3JpdGUgZmFzdGEKZmluYWxfZG5hX29yZGVyIDwtIGZpbmFsX2RuYVtvcmRlcihEQl90YmwkQ2x1c3RlciksXQoKCgojMTMgLSBJZGVudGlmeSBwcm9ibGVtYXRpYyBzcGVjaWVzIHRvIHJ1bGUgb3V0CgpuYW1lcyhmaW5hbF9kbmFfb3JkZXIpCgoKI3RoZSBzcGVjaWVzIHRvIGJlIHJlbW92ZWQgZnJvbSB0aGUgZmluYWwgZGF0YWJhc2UgYXJlOgoKCgpuYW1lcyhmaW5hbF9kbmFfb3JkZXJbMTk3XSkKIzE5MyAtIFRyYWNoZWx5b3B0ZXJ1cyBzdHJpYXR1bHVzIDY1ODMKbmFtZXMoZmluYWxfZG5hX29yZGVyWzI5XSkKIzE5MyAtIE9ydGhvc3BpbnVzIGZyYW5jaXNjZW5zaXMgMTA3MQoKIyBmaW5hbF9kbmFfY2xlYW4gPC0gZmluYWxfZG5hX29yZGVyWy1jKDI5LDE5NyldCmZpbmFsX2RuYV9jbGVhbiA8LSBmaW5hbF9kbmFfb3JkZXIKCgoKI3dyaXRlIGZhc3RhCndyaXRlWFN0cmluZ1NldCh4ID0gZmluYWxfZG5hX2NsZWFuLGZpbGVwYXRoID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9kYXRhL3JlZnMvZGIvTEdDL2ZldjIxL2RhZGFfdGF4X2Z1bGxEQl9vcmRlcl9mZXYyMS5mYXN0YSIsZm9ybWF0ID0gImZhc3RhIikKIyB3cml0ZVhTdHJpbmdTZXQoeCA9IGZpbmFsX2RuYV9jbGVhbixmaWxlcGF0aCA9ICJ+L3ByamN0cy9maXNoX2VETkEvZGF0YS9yZWZzL2RiL0xHQy9kYWRhX3RheF9mdWxsREJfb3JkZXIuZmFzdGEiLGZvcm1hdCA9ICJmYXN0YSIpCgoKCgojY3JlYXRlIERCIHNlcXMgZm9yIGFzc2lnU3BlY2llcwoKCiNyZW5hbWUgZmluYWwgZG5hIGhlYWRlcgpmb3IgKHNlcSBpbiAxOm5yb3coREJfdGJsKSkgewogIGZvciAoc2VxMiBpbiAxOmxlbmd0aChmaW5hbF9kbmEpKXsKCiAgICBpZiAobmFtZXMoZmluYWxfZG5hKVtzZXEyXSA9PSBEQl90YmwkaGVhZGVyc1tzZXFdKSB7CgogICAgICBuYW1lcyhmaW5hbF9kbmEpW3NlcTJdIDwtIHBhc3RlKERCX3RibCRJZGVudGlmaWVyW3NlcV0sREJfdGJsJE5hbWVzW3NlcV0pCiAgICB9CiAgfQp9CgoKI29yZGVyIHNlcXMgYnkgY2x1c3RlciBhbmQgd3JpdGUgZmFzdGEKZmluYWxfZG5hX29yZGVyIDwtIGZpbmFsX2RuYVtvcmRlcihEQl90YmwkQ2x1c3RlciksXQoKIyBmaW5hbF9kbmFfY2xlYW4gPC0gZmluYWxfZG5hX29yZGVyWy1jKDI5LDE5NyldCmZpbmFsX2RuYV9jbGVhbiA8LSBmaW5hbF9kbmFfb3JkZXIKCiN3cml0ZSBmYXN0YQojIHdyaXRlWFN0cmluZ1NldCh4ID0gZmluYWxfZG5hX2NsZWFuLGZpbGVwYXRoID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9kYXRhL3JlZnMvZGIvTEdDL2RhZGFfdGF4X2Z1bGxEQl9vcmRlcl9TUHMuZmFzdGEiLGZvcm1hdCA9ICJmYXN0YSIpCndyaXRlWFN0cmluZ1NldCh4ID0gZmluYWxfZG5hX2NsZWFuLGZpbGVwYXRoID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9kYXRhL3JlZnMvZGIvTEdDL2ZldjIxL2RhZGFfdGF4X2Z1bGxEQl9vcmRlcl9TUHNfZmV2MjEuZmFzdGEiLGZvcm1hdCA9ICJmYXN0YSIpCgoKCgoKCgoKIyByZW5hbWUgImFmZiIgYW5kICJjZiIKCiMgc2VkIC1pICcvPi8gcy9hZmYgL2FmZl8vJwojIHNlZCAtaSAnLz4vIHMvY2YgL2NmXy8nCgoKCgogIG5lb19GV0Rfc2VxcwogIAogIAoibmVvX0ZXRCIKIlNGIHwgU3luYnJhbmNodXMgbWFybW9yYXR1cyB8IDE0MDQiCiJTRiB8IFN5bmJyYW5jaHVzIG1hcm1vcmF0dXMgfCAxNDA1IgoiSnEgfCBPbGlnb3NhcmN1cyBtYWNyb2xlcGlzIHwgNzY5MCIKIlNGIHwgTGVwb3JpbnVzIG1hY3JvY2VwaGFsdXMgfCAwOTgyIgoiU0ZKcTIgfCBDb25vcmh5bmNob3MgY29uaXJvc3RyaXMgfCBKWDg5OTczNy4xIgoiSnEgfCBSaGFtZGlhIGNmIGplcXVpdGluaG9uaGEgfCAzMDU0IgoiU0YgfCBDZXRvcHNvcmhhbWRpYSBpaGVyaW5naSB8IDEzNzIiCiJTRiB8IEltcGFyZmluaXMgbWludXR1cyB8IDExNjEiCiJTRiB8IEltcGFyZmluaXMgbWludXR1cyB8IDEzNzAiCiJTRiB8IFJoYW1kaWEgcXVlbGVuIHwgMTM2MSIKIkpxIHwgUmhhbWRpYSBhZmYgcXVlbGVuIHwgNTY0NSIKIlNGIHwgUGltZWxvZGVsbGEgdml0dGF0YSB8IDEyODciCiJTRiB8IFBpbWVsb2RlbGxhIHZpdHRhdGEgfCAxMjg4IgoiU0YgfCBQaW1lbG9kZWxsYSB2aXR0YXRhIHwgMTI4OSIKIlNGIHwgUHNldWRvcGxhdHlzdG9tYSBjb3JydXNjYW5zIHwgMTEzNSIKIkpxIHwgU3RlaW5kYWNobmVyaWRpb24gYW1ibHl1cnVtIHwgMjk5NiIKIlNGIHwgUGltZWxvZHVzIG1hY3VsYXR1cyB8IDA3NDkiCiJTRiB8IFBpbWVsb2R1cyBmdXIgfCAxMTQ3IgoiU0YgfCBQaW1lbG9kdXMgbWFjdWxhdHVzIHwgMTI4MCIKIlNGIHwgUGltZWxvZHVzIGZ1ciB8IDEzNDUiCiJTRiB8IFBpbWVsb2R1cyBwb2hsaSB8IDE0MDAiCiJTRiB8IFBpbWVsb2R1cyBwb2hsaSB8IDE0MDEiCiJTRiB8IFBpbWVsb2R1cyBwb2hsaSB8IDE0MDMiCiJTRiB8IE1pY3JvZ2xhbmlzIGxlcHRvc3RyaWF0dXMgfCAxMTAyIgoiU0YgfCBNaWNyb2dsYW5pcyBsZXB0b3N0cmlhdHVzIHwgMTEwNCIKIlNGIHwgUHNldWRvcGltZWxvZHVzIHNwIHwgMDY3MSIKICAKICAKICAKCgoKCiNyZWNvdmVyIERhdGFiYXNlIHJlZ2lvbiBmb3IgcHJpbWVycwoKQnJvd3NlU2VxcyhkbmFfYWxnX3N1YltvcmRlcihEQl90YmwkQ2x1c3RlciksXSkgI2FsbCBzZXFzCgojbmVvIEZXRDogNzQxLTc2MCAgICAgICAgICBDR0NDR1RDR0NBQUdDVFRBQ0NDVApuZW9fRldEX3NlcXMgPC0gc3Vic2VxKGRuYV9hbGdfc3ViW29yZGVyKERCX3RibCRDbHVzdGVyKSxdLDQzMyw0NzIpICMgcHJpbWFyICstMTAKbmVvX0ZXRF9zZXFzIDwtIHN1YnNlcShkbmFfYWxnX3N1YltvcmRlcihEQl90YmwkQ2x1c3RlciksXSw0NDMsNDYyKSAjIHByaW1lciBvbmx5Cm5lb19GV0Rfc2VxcyA8LSBjKEROQVN0cmluZ1NldChuZW9fRldEKSxuZW9fRldEX3NlcXMpCkJyb3dzZVNlcXMobmVvX0ZXRF9zZXFzKSAjbmVvIEZXRCBzZXFzCgpCcm93c2VTZXFzKG5lb19GV0Rfc2Vxcyxjb2xvclBhdHRlcm5zID0gRkFMU0UsaGlnaGxpZ2h0ID0gMSkgI25lbyBGV0Qgc2VxcwoKCgpCcm93c2VTZXFzKG5lb19GV0Rfc2Vxc1tjKAogICJuZW9fRldEIiwKICAiU0YgfCBTeW5icmFuY2h1cyBtYXJtb3JhdHVzIHwgMTQwNCIsCiAgIlNGIHwgU3luYnJhbmNodXMgbWFybW9yYXR1cyB8IDE0MDUiLAogICJKcSB8IE9saWdvc2FyY3VzIG1hY3JvbGVwaXMgfCA3NjkwIiwKICAiU0YgfCBMZXBvcmludXMgbWFjcm9jZXBoYWx1cyB8IDA5ODIiLAogICJTRkpxMiB8IENvbm9yaHluY2hvcyBjb25pcm9zdHJpcyB8IEpYODk5NzM3LjEiLAogICJKcSB8IFJoYW1kaWEgY2YgamVxdWl0aW5ob25oYSB8IDMwNTQiLAogICJTRiB8IENldG9wc29yaGFtZGlhIGloZXJpbmdpIHwgMTM3MiIsCiAgIlNGIHwgSW1wYXJmaW5pcyBtaW51dHVzIHwgMTE2MSIsCiAgIlNGIHwgSW1wYXJmaW5pcyBtaW51dHVzIHwgMTM3MCIsCiAgIlNGIHwgUmhhbWRpYSBxdWVsZW4gfCAxMzYxIiwKICAiSnEgfCBSaGFtZGlhIGFmZiBxdWVsZW4gfCA1NjQ1IiwKICAiU0YgfCBQaW1lbG9kZWxsYSB2aXR0YXRhIHwgMTI4NyIsCiAgIlNGIHwgUGltZWxvZGVsbGEgdml0dGF0YSB8IDEyODgiLAogICJTRiB8IFBpbWVsb2RlbGxhIHZpdHRhdGEgfCAxMjg5IiwKICAiU0YgfCBQc2V1ZG9wbGF0eXN0b21hIGNvcnJ1c2NhbnMgfCAxMTM1IiwKICAiSnEgfCBTdGVpbmRhY2huZXJpZGlvbiBhbWJseXVydW0gfCAyOTk2IiwKICAiU0YgfCBQaW1lbG9kdXMgbWFjdWxhdHVzIHwgMDc0OSIsCiAgIlNGIHwgUGltZWxvZHVzIGZ1ciB8IDExNDciLAogICJTRiB8IFBpbWVsb2R1cyBtYWN1bGF0dXMgfCAxMjgwIiwKICAiU0YgfCBQaW1lbG9kdXMgZnVyIHwgMTM0NSIsCiAgIlNGIHwgUGltZWxvZHVzIHBvaGxpIHwgMTQwMCIsCiAgIlNGIHwgUGltZWxvZHVzIHBvaGxpIHwgMTQwMSIsCiAgIlNGIHwgUGltZWxvZHVzIHBvaGxpIHwgMTQwMyIsCiAgIlNGIHwgTWljcm9nbGFuaXMgbGVwdG9zdHJpYXR1cyB8IDExMDIiLAogICJTRiB8IE1pY3JvZ2xhbmlzIGxlcHRvc3RyaWF0dXMgfCAxMTA0IiwKICAiU0YgfCBQc2V1ZG9waW1lbG9kdXMgc3AgfCAwNjcxIildLGNvbG9yUGF0dGVybnMgPSBGQUxTRSxoaWdobGlnaHQgPSAxKSAjbmVvIEZXRCBzZXFzCgoKc2Vxc19sb2dvX3Bsb3QgPC0gZ2dwbG90Mjo6Z2dwbG90KCkgKwogIGdnc2VxbG9nbzo6Z2VvbV9sb2dvKGRhdGEgPSBhcy5jaGFyYWN0ZXIobmVvX0ZXRF9zZXFzKSwKICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAicHJvYmFiaWxpdHkiKSArCiAgZ2dwbG90Mjo6YW5ub3RhdGUoZ2VvbSA9ICJyZWN0IiwKICAgICAgICAgICAgICAgICAgICB4bWluID0gMTAuNSx4bWF4ID0gMzAuNSwKICAgICAgICAgICAgICAgICAgICB5bWluID0gMSx5bWF4ID0gMS4xNSwKICAgICAgICAgICAgICAgICAgICBmaWxsPSIjYzQxNDIyIiwgYWxwaGE9MC41MCkgKwogIGdncGxvdDI6OmFubm90YXRlKGdlb20gPSAicmVjdCIsCiAgICAgICAgICAgICAgICAgICAgeG1pbiA9IDkuNSx4bWF4ID0gMjkuNSwKICAgICAgICAgICAgICAgICAgICB5bWluID0gLTAuMTUseW1heCA9IDAsCiAgICAgICAgICAgICAgICAgICAgZmlsbD0iIzA4OTkwMCIsIGFscGhhPTAuNTApICsKICBnZ3Bsb3QyOjphbm5vdGF0ZShnZW9tID0gInRleHQiLCBsYWJlbCA9ICJBZGp1c3RlZCBOZW9GaXNoIEZXRCBwcmltZXIiLAogICAgICAgICAgICAgICAgICAgIHggPSAyMCx5ID0gLTAuMDc1KSArCiAgZ2dwbG90Mjo6YW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSAiT3JpZ2luYWwgTmVvRmlzaCBGV0QgcHJpbWVyIiwKICAgICAgICAgICAgICAgICAgICB4ID0gMjAseSA9IDEuMDc1KQoKc2Vxc19sb2dvX3Bsb3QKCmRldi5vZmYoKQoKZ2dwbG90Mjo6Z2dzYXZlKGZpbGVuYW1lID0gIn4vcHJqY3RzL2Zpc2hfZUROQS9zZmpxL3Jlc3VsdHMvZmlncy9OZW9GSXNoX0ZXRF9wcmltZXJfYWRqdXN0bWVudC5wbmciLAogICAgICAgICAgICAgICAgZGV2aWNlID0gInBuZyIsCiAgICAgICAgICAgICAgICB3aWR0aCA9IDQwLCBoZWlnaHQgPSA4LAogICAgICAgICAgICAgICAgdW5pdHMgPSAiY20iKQoKCgoKCkJyb3dzZVNlcXMobmVvX0ZXRF9zZXFzLGNvbG9yUGF0dGVybnMgPSBGQUxTRSxoaWdobGlnaHQgPSAwKSAjbmVvIEZXRCBzZXFzCgojbmVvIFJFVjogOTczLTk5MiAgICAgICAgICBHQy1BQ0FDQUNDR0NDQ0dUQ0FDVApuZW9fUkVWX3NlcXMgPC0gc3Vic2VxKGRuYV9hbGlnbmVkW29yZGVyKERCX3RibCRDbHVzdGVyKSxdLDk3Miw5OTEpCm5lb19SRVZfc2VxcyA8LSBjKEROQVN0cmluZ1NldCgiR0MtQUNBQ0FDQ0dDQ0NHVENBQ1QiKSxuZW9fUkVWX3NlcXMpCkJyb3dzZVNlcXMobmVvX1JFVl9zZXFzKQpCcm93c2VTZXFzKG5lb19SRVZfc2Vxcyxjb2xvclBhdHRlcm5zID0gRkFMU0UsaGlnaGxpZ2h0ID0gMSkgI25lbyBSRVYgc2VxcwoKCiNtaWYgRldEOiAzMDQtMzI1Cm1pZl9GV0Rfc2VxcyA8LSBzdWJzZXEoZG5hX2FsaWduZWRbb3JkZXIoREJfdGJsJENsdXN0ZXIpLF0sMzA0LDMyNSkKbWlmX0ZXRF9zZXFzIDwtIGMoRE5BU3RyaW5nU2V0KCJHVENHR1RBQUFBQ1RDR1QtR0NDQUdDIiksbWlmX0ZXRF9zZXFzKQpCcm93c2VTZXFzKG1pZl9GV0Rfc2VxcykgI21pZiBGV0Qgc2VxcwpCcm93c2VTZXFzKG1pZl9GV0Rfc2Vxcyxjb2xvclBhdHRlcm5zID0gRkFMU0UsaGlnaGxpZ2h0ID0gMSkgI21pZiBGV0Qgc2VxcwpCcm93c2VTZXFzKG1pZl9GV0Rfc2Vxcyxjb2xvclBhdHRlcm5zID0gVFJVRSxoaWdobGlnaHQgPSAxKSAjbWlmIEZXRCBzZXFzCgojbWlmIFJFVjogNTMzLTU1OQptaWZfUkVWX3NlcXMgPC0gc3Vic2VxKGRuYV9hbGlnbmVkW29yZGVyKERCX3RibCRDbHVzdGVyKSxdLDUzMiw1NTkpCm1pZl9SRVZfc2VxcyA8LSBjKEROQVN0cmluZ1NldCgiQ0FBQUNUR0dHQVRUQUdBVEFDQ0NDQUNUQVRHVCIpLG1pZl9SRVZfc2VxcykKQnJvd3NlU2VxcyhtaWZfUkVWX3NlcXMpICNtaWYgUkVWIHNlcXMKQnJvd3NlU2VxcyhtaWZfUkVWX3NlcXMsY29sb3JQYXR0ZXJucyA9IEZBTFNFLGhpZ2hsaWdodCA9IDEpICNtaWYgUkVWIHNlcXMKQnJvd3NlU2VxcyhtaWZfUkVWX3NlcXMsY29sb3JQYXR0ZXJucyA9IFRSVUUsaGlnaGxpZ2h0ID0gMSkgI21pZiBSRVYgc2VxcwoKCgoKCgoKCkJyb3dzZVNlcXMobmVvX0ZXRF9zZXFzLGNvbG9yUGF0dGVybnMgPSBGQUxTRSxoaWdobGlnaHQgPSAxKSAjbmVvIHNlcXMKQnJvd3NlU2VxcyhzdWJzZXEoZG5hX2FsaWduZWRbb3JkZXIoREJfdGJsJENsdXN0ZXIpLF0sNzYxLDk3MikpICNuZW8gc2VxcwpCcm93c2VTZXFzKHN1YnNlcShkbmFfYWxpZ25lZFtvcmRlcihEQl90YmwkQ2x1c3RlciksXSw3NjEsOTcyKSkgI25lbyBzZXFzCiNtaWYgRldEOiAzMDQtMzI1CiNtaWYgUkVWOiA1MzMtNTYwCkJyb3dzZVNlcXMoc3Vic2VxKGRuYV9hbGlnbmVkW29yZGVyKERCX3RibCRDbHVzdGVyKSxdLDMyNiw1MzIpKSAjbWlmIHNlcXMKI3RlbCBGV0Q6IDk3Ny05OTMKI3RlbCBSRVY6IDEwNzgtMTA5OApCcm93c2VTZXFzKHN1YnNlcShkbmFfYWxpZ25lZFtvcmRlcihEQl90YmwkQ2x1c3RlciksXSw5OTQsMTA3NykpICN0ZWwgc2VxcwoKCgoKCiMKIwojIGhvdyBtYW55IHRpbWVzIGVhY2ggc3BlY2llcyBpcyBpbiBwb29sCiMgKGpxX3RibCRTcGVjaWVzICU+JSBzdHJfcmVwbGFjZV9hbGwocGF0dGVybiA9ICIgIixyZXBsYWNlbWVudCA9ICJfIikpICVpbiUKIyAgIChEQl90YmwkYE9yaWdpbmFsIG5hbWVzYCAlPiUgc3RyX3JlbW92ZShwYXR0ZXJuID0gIl4uKi5bWzpkaWdpdDpdXV8iKSApCgoKCiMgQURFTkRVTS0tLS0KIzEzIC0gbWFwIHByaW1lcnMgb24gREIgLS0tLQoKIyBzZXQgcHJpbWVycyBzZXF1ZW5jZXMKbmVvX0ZXRCA8LSAiQ0dDQ0dUQ0dDQUFHQ1RUQUNDQ1QiICNNaW5pX2JhcjMKbmVvX1JFViA8LSAiQUdUR0FDR0dHQ0dHVEdUR1RHQyIgICNNaW5pX2JhcjMKCm1pZl9GV0QgPC0gIkdUQ0dHVEFBQUFDVENHVEdDQ0FHQyIKbWlmX1JFViA8LSAgICAiQ0FUQUdUR0dHR1RBVENUQUFUQ0NDQUdUVFRHIgojIG1pZl9SRVYgPC0gIkFDQVRBR1RHR0dHVEFUQ1RBQVRDQ0NBR1RUVEciCgp0ZWxfRldEIDwtICJBQ0FDQ0dDQ0NHVENBQ1RDVCIgIwp0ZWxfUkVWIDwtICAiQ1RUQ0NHR1RBQ0FDVFRBQ0NBVEciCiMgdGVsX1JFViA8LSAiQUNUVENDR0dUQUNBQ1RUQUNDQVRHIgoKcHJpbWVycyA8LSBETkFTdHJpbmdTZXQoYyhuZW9fRldELCBuZW9fUkVWLCBtaWZfRldELCBtaWZfUkVWLCB0ZWxfRldELCB0ZWxfUkVWKSkKcHJpbWVyc19yZXYgPC0gcmV2ZXJzZUNvbXBsZW1lbnQocHJpbWVycykKCm5hbWVzKHByaW1lcnMpIDwtIGMoIm5lb19GV0QiLCJuZW9fUkVWIiwibWlmX0ZXRCIsIm1pZl9SRVYiLCJ0ZWxfRldEIiwidGVsX1JFViIpCgojIzEzYSAtZ2VuZXJhdGUgcHJpbWVyIG9yaWVudGF0aW9ucy0tLS0KCiNmdW5jdGlvbiB0byBnZXQgYWxsIHBvc3NpYmxlIHByaW1lciBvcmllbnRhdGlvbnMKYWxsT3JpZW50cyA8LSBmdW5jdGlvbihwcmltZXJzKSB7CiAgIyBDcmVhdGUgYWxsIG9yaWVudGF0aW9ucyBvZiB0aGUgaW5wdXQgc2VxdWVuY2UKICByZXF1aXJlKEJpb3N0cmluZ3MpCiAgZG5hIDwtIEROQVN0cmluZyhwcmltZXJzKSAgIyBUaGUgQmlvc3RyaW5ncyB3b3JrcyB3LyBETkFTdHJpbmcgb2JqZWN0cyByYXRoZXIgdGhhbiBjaGFyYWN0ZXIgdmVjdG9ycwogIG9yaWVudHMgPC0gYyhGb3J3YXJkID0gZG5hLCBDb21wbGVtZW50ID0gQmlvc3RyaW5nczo6Y29tcGxlbWVudChkbmEpLCBSZXZlcnNlID0gcmV2ZXJzZShkbmEpLAogICAgICAgICAgICAgICBSZXZDb21wID0gcmV2ZXJzZUNvbXBsZW1lbnQoZG5hKSkKICByZXR1cm4oc2FwcGx5KG9yaWVudHMsIHRvU3RyaW5nKSkgICMgQ29udmVydCBiYWNrIHRvIGNoYXJhY3RlciB2ZWN0b3IKfQoKCiNnZXJhciB0b2RhcyBvcmllbnRhw6fDtWVzIHBvc3PDrXZlaXMgZG9zIHByaW1lcnMKbmVvX0ZXRC5vcmllbnRzIDwtIGFsbE9yaWVudHMobmVvX0ZXRCkKbmFtZXMobmVvX0ZXRC5vcmllbnRzKSA8LSBwYXN0ZTAoIm5lb19GV0QtIiwgbmFtZXMobmVvX0ZXRC5vcmllbnRzKSkKbmVvX1JFVi5vcmllbnRzIDwtIGFsbE9yaWVudHMobmVvX1JFVikKbmFtZXMobmVvX1JFVi5vcmllbnRzKSA8LSBwYXN0ZTAoIm5lb19SRVYtIiwgbmFtZXMobmVvX1JFVi5vcmllbnRzKSkKbWlmX0ZXRC5vcmllbnRzIDwtIGFsbE9yaWVudHMobWlmX0ZXRCkKbmFtZXMobWlmX0ZXRC5vcmllbnRzKSA8LSBwYXN0ZTAoIm1pZl9GV0QtIiwgbmFtZXMobWlmX0ZXRC5vcmllbnRzKSkKbWlmX1JFVi5vcmllbnRzIDwtIGFsbE9yaWVudHMobWlmX1JFVikKbmFtZXMobWlmX1JFVi5vcmllbnRzKSA8LSBwYXN0ZTAoIm1pZl9SRVYtIiwgbmFtZXMobWlmX1JFVi5vcmllbnRzKSkKdGVsX0ZXRC5vcmllbnRzIDwtIGFsbE9yaWVudHModGVsX0ZXRCkKbmFtZXModGVsX0ZXRC5vcmllbnRzKSA8LSBwYXN0ZTAoInRlbF9GV0QtIiwgbmFtZXModGVsX0ZXRC5vcmllbnRzKSkKdGVsX1JFVi5vcmllbnRzIDwtIGFsbE9yaWVudHModGVsX1JFVikKbmFtZXModGVsX1JFVi5vcmllbnRzKSA8LSBwYXN0ZTAoInRlbF9SRVYtIiwgbmFtZXModGVsX1JFVi5vcmllbnRzKSkKCnByaW1lcnNfYWxsIDwtIEROQVN0cmluZ1NldChjKG5lb19GV0Qub3JpZW50cywgbmVvX1JFVi5vcmllbnRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaWZfRldELm9yaWVudHMsIG1pZl9SRVYub3JpZW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVsX0ZXRC5vcmllbnRzLCB0ZWxfUkVWLm9yaWVudHMpKQoKcHJpbWVyc19hbGwKYXMubGlzdChwcmltZXJzX2FsbCkKCiMxM2IgLSBmaW5kIHByaW1lcnMgaW4gYWxpZ25lZCBEQiAtLS0tCgoKbmVvX2RiX2h0bWwgPC0gQnJvd3NlU2VxcyhteVhTdHJpbmdTZXQgPSBkbmFfb3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybnM9cHJpbWVyc19hbGwsICNuZW8gcHJpbWVycwogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yUGF0dGVybnMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9ycyA9IGMoIiMwMGZmMDAiLCIjOTlmZjMzIiwiIzAwZmYwMCIsIiM5OWZmMzMiLCIjMDBmZjAwIiwiIzk5ZmYzMyIsIiMwMGZmMDAiLCIjOTlmZjMzIiwgICMgbmVvIHZlcmRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIzAwMDBmZiIsIiMwMDY2Y2MiLCIjMDAwMGZmIiwiIzAwNjZjYyIsIiMwMDAwZmYiLCIjMDA2NmNjIiwiIzAwMDBmZiIsIiMwMDY2Y2MiLCAgIyBtaWYgYXp1bAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiNmZjAwMDAiLCIjZmYzMzAwIiwiI2ZmMDAwMCIsIiNmZjMzMDAiLCIjZmYwMDAwIiwiI2ZmMzMwMCIsIiNmZjAwMDAiLCIjZmYzMzAwIikpICMgdGVsIHZlcm1lbGhvCgoKCiMxNC0gaXNvbGF0ZSBuZW8gYW1wbGljb24gLS0tLQogICAgICAgICAgICAgICAgICMgY2hhbmdlcyBldmVyeSB0aW1lIGlzIHJlYWxpZ25lZAoKbmVvRldEc3RhcnQgPC0gNjQ1Cm5lb0ZXRGVuZCA8LSA2NjQKbmVvUkVWc3RhcnQgPC0gODcxCm5lb1JFVmVuZCA8LSA4OTAKCgoKCiNpZGVudGlmeSBtaXNtYXRjaGVzIGluIHRoZSBwcmltZXIgc2VxdWVuY2UgYWxpZ25tZW50CgoKCgpwb29sX3Nwc1shKHBvb2xfc3BzICVpbiUgREJfdGJsJE5hbWVzKV0KCgpEQl90YmwkYENvbXBvc2VkIG5hbWVgW0RCX3RibCROYW1lcyAlaW4lIHBvb2xfc3BzXQoKQnJvd3NlU2VxcyhkbmFfb3JkZXJbREJfdGJsJGBDb21wb3NlZCBuYW1lYFtEQl90YmwkTmFtZXMgJWluJSBwb29sX3Nwc11dLGNvbG9yUGF0dGVybnMgPSBGQUxTRSkKCgpuZW9fYW1wbGk8LSBzdWJzZXEoeCA9IGRuYV9hbGlnbmVkLDY4NSw4OTYpCgpCcm93c2VTZXFzKG5lb19hbXBsaSkKCiNyZW5hbWUgbmVvIGFtcGxpIHNlcXMgZm9yIG1lZ2EKCm5lb19hbXBsaQoKbmVvX2RuYV9vcmRlciA8LSBzdWJzZXEoZG5hX29yZGVyLDM2Nyw1NzcpCgpuYW1lcyhuZW9fZG5hX29yZGVyKQoKQnJvd3NlU2VxcyhkbmFfb3JkZXJbMTI2OjEzNl0saGlnaGxpZ2h0ID0gMCx0aHJlc2hvbGQ9MC4yLGNvbG9yUGF0dGVybnMgPSBGQUxTRSkKQnJvd3NlU2VxcyhuZW9fZG5hX29yZGVyW2MoMTg0LDE4NildLGhpZ2hsaWdodCA9IDApCgp3cml0ZVhTdHJpbmdTZXQoeCA9IG5lb19kbmFfb3JkZXIsZmlsZXBhdGggPSAifi9wcmpjdHMvZmlzaF9lRE5BL2RhdGEvcmVmcy9kYi9uZW9fREJfb3JkZXJfY2x1c3QuZmFzdGEiLGZvcm1hdCA9ICJmYXN0YSIpCgpuYW1lcyhuZW9fYW1wbGkpCgpCcm93c2VTZXFzKG5lb19hbXBsaVtjKCJKcSB8IFRyYWNoZWx5b3B0ZXJ1cyBjZiBnYWxlYXR1cyB8IDU2NzUiLCJKcSB8IFRyYWNoZWx5b3B0ZXJ1cyBzdHJpYXR1bHVzIHwgNjU4MyIpXSxoaWdobGlnaHQgPSAxKQoKCgojcGVnYXIgYXBlbmFzIGEgc2VxdWVuY2lhIGRvIHByaW1lciBlIG9yZGVuYXIKCm5lb19GV0RfRE5BRklTSCA8LSBzdWJzZXEoRE5BRklTSCwgbmVvRldEc3RhcnQsIG5lb0ZXRGVuZCwpICU+JSBCaW9jR2VuZXJpY3M6OnNvcnQoKQpuZW9fUkVWX0ROQUZJU0ggPC0gc3Vic2VxKEROQUZJU0gsIG5lb1JFVnN0YXJ0LCBuZW9SRVZlbmQsKSAlPiUgQmlvY0dlbmVyaWNzOjpzb3J0KCkKCgpjb25zZW5zdXNfbmVvX0ZXRCA8LSBDb25zZW5zdXNTZXF1ZW5jZShuZW9fRldEX0ROQUZJU0gpCmNvbnNlbnN1c19uZW9fUkVWIDwtIENvbnNlbnN1c1NlcXVlbmNlKG5lb19SRVZfRE5BRklTSCkKCgojIE5lb0ZJc2ggZ2dzZXFsb2dvIC0tLS0KCgp3cml0ZVhTdHJpbmdTZXQoeCA9IG5lb19hbXBsaSxmaWxlcGF0aCA9ICJ+L3ByamN0cy9maXNoX2VETkEvZGF0YS9yZWZzL2RiL25lb19hbXBsaS5mYXN0YSIsZm9ybWF0ID0gImZhc3RhIikKCgpuYW1lcyhkbmFfYWxsKQpgYGAKCgoKCgoqKlRoaXMgaXMgYSBkaW5hbWljIHJlcG9ydCwgaW50ZW5kZWQgdG8gc2hvdyB0aGUgY3VycmVudCBzdGF0ZSBvZiBhbmFseXNlcy4gTWFueSBwcm9jZWR1cmVzIGFuZCBjb25jbHVzaW9ucyBtaWdodCBjaGFuZ2UgYXMgdGhlIHBpcGVsaW5lIGV2b2x2ZXMuIElmIHlvdSBub3RpY2UgZXJyb3JzL21pc3Rha2VzL3R5cG9zLCBvciBoYXZlIGFueSBzdWdnZXN0aW9ucywgd2Ugd291bGQgYmUgZ2xhZCB0byBrbm93LiBfaGVyb25vaEBnbWFpbC5jb21fKioK