Description: Use kallisto to quantify P. meandrina RNAseq transcript abundances

Inputs:

Trimmed RNAseq reads (e.g. *.fastq.gz). P. meandrina reads found here.

Transcripts FASTA (e.g. *.fna.gz), found here.

Outputs:

kalisto counts matrix (kallisto.isoform.counts.matrix)


1 Create a Bash variables file

This allows usage of Bash variables (e.g. paths to common directories) across R Markdown chunks.

{
echo "#### Assign Variables ####"
echo ""

echo "# Data directories"
echo 'export Pmea_dir=/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea'
echo 'export output_dir_top=${Pmea_dir}/output/14-Pmea-RNAseq-kallisto'
echo 'export transcriptome_fasta_dir=${Pmea_dir}/data/Pmea'
echo 'export trimmed_reads_dir=${output_dir_top}/trimmed-reads'
echo 'export kallisto_output_dir=${output_dir_top}/kallisto'
echo ""

echo "# Input/Output files"
echo 'export transcriptome_fasta_name="Pocillopora_meandrina_HIv1.genes.cds.fna.gz"'
echo 'export transcriptome_fasta="${transcriptome_fasta_dir}/${transcriptome_fasta_name}"'
echo 'export kallisto_index_name="Pmea_kallisto_index.idx"'

echo "# External data URLs"
echo 'export trimmed_reads_url="https://gannet.fish.washington.edu/Atumefaciens/20230519-E5_coral-fastqc-fastp-multiqc-RNAseq/P_meandrina/trimmed/"'
echo 'export transcriptome_fasta_url="http://cyanophora.rutgers.edu/Pocillopora_meandrina/Pocillopora_meandrina_HIv1.genes.cds.fna.gz"'
echo ""

echo "# Set filename patterns"
echo "export fastq_pattern='*.fastq.gz'"
echo "export R1_fastq_pattern='*_R1.fastq.gz'"
echo "export R2_fastq_pattern='*_R2.fastq.gz'"
echo ""

echo "# Paths to programs"
echo 'export kallisto=/home/shared/kallisto_linux-v0.50.1/kallisto'
echo 'export trinity_abund_to_matrix=/home/shared/trinityrnaseq-v2.12.0/util/abundance_estimates_to_matrix.pl'
echo ""

echo "# Set number of CPUs to use"
echo 'export threads=20'
echo ""

echo "# Programs associative array"
echo "declare -A programs_array"
echo "programs_array=("
echo '[kallisto]="${kallisto}" \'
echo '[trinity_abund_to_matrix]="${trinity_abund_to_matrix}" \'
echo ")"

} > .bashvars

cat .bashvars
#### Assign Variables ####

# Data directories
export Pmea_dir=/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea
export output_dir_top=${Pmea_dir}/output/14-Pmea-RNAseq-kallisto
export transcriptome_fasta_dir=${Pmea_dir}/data/Pmea
export trimmed_reads_dir=${output_dir_top}/trimmed-reads
export kallisto_output_dir=${output_dir_top}/kallisto

# Input/Output files
export transcriptome_fasta_name="Pocillopora_meandrina_HIv1.genes.cds.fna.gz"
export transcriptome_fasta="${transcriptome_fasta_dir}/${transcriptome_fasta_name}"
export kallisto_index_name="Pmea_kallisto_index.idx"
# External data URLs
export trimmed_reads_url="https://gannet.fish.washington.edu/Atumefaciens/20230519-E5_coral-fastqc-fastp-multiqc-RNAseq/P_meandrina/trimmed/"
export transcriptome_fasta_url="http://cyanophora.rutgers.edu/Pocillopora_meandrina/Pocillopora_meandrina_HIv1.genes.cds.fna.gz"

# Set filename patterns
export fastq_pattern='*.fastq.gz'
export R1_fastq_pattern='*_R1.fastq.gz'
export R2_fastq_pattern='*_R2.fastq.gz'

# Paths to programs
export kallisto=/home/shared/kallisto_linux-v0.50.1/kallisto
export trinity_abund_to_matrix=/home/shared/trinityrnaseq-v2.12.0/util/abundance_estimates_to_matrix.pl

# Set number of CPUs to use
export threads=20

# Programs associative array
declare -A programs_array
programs_array=(
[kallisto]="${kallisto}" \
[trinity_abund_to_matrix]="${trinity_abund_to_matrix}" \
)

2 Download trimmed RNAseq reads

Reads are downloaded from: https://gannet.fish.washington.edu/Atumefaciens/20230519-E5_coral-fastqc-fastp-multiqc-RNAseq/A_pulchra/trimmed/

The --cut-dirs 4 command cuts the preceding directory structure (i.e. Atumefaciens/20230519-E5_coral-fastqc-fastp-multiqc-RNAseq/P_meandrina/trimmed/) so that we just end up with the reads.

# Load bash variables into memory
source .bashvars

wget \
--directory-prefix ${trimmed_reads_dir} \
--recursive \
--no-check-certificate \
--continue \
--cut-dirs 4 \
--no-host-directories \
--no-parent \
--quiet \
--accept "RNA-*.fastq.gz" ${trimmed_reads_url}

ls -lh "${trimmed_reads_dir}"

4 Retrieve the reference transcriptome

# Load bash variables into memory
source .bashvars

wget \
--directory-prefix ${transcriptome_fasta_dir} \
--no-check-certificate \
--continue \
--no-host-directories \
--no-directories \
--no-parent \
--quiet \
--execute robots=off \
--accept "${transcriptome_fasta_name}" ${transcriptome_fasta_url}

ls -lh "${transcriptome_fasta_dir}"

4.1 Verify transcriptome FastA MD5 checksum

No checksum file(s) provided with download, so skippping this step

5 Align to reference transcriptome (Kallisto pseudoalignment)

5.1 Building Index

# Load bash variables into memory
source .bashvars

cd "${kallisto_output_dir}"

${programs_array[kallisto]} index \
--threads=${threads} \
--index="${kallisto_index_name}" \
"${transcriptome_fasta}"

ls -lh ${kallisto_output_dir}

[build] loading fasta file /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/data/Pmea/Pocillopora_meandrina_HIv1.genes.cds.fna.gz
[build] k-mer length: 31
KmerStream::KmerStream(): Start computing k-mer cardinality estimations (1/2)
KmerStream::KmerStream(): Start computing k-mer cardinality estimations (1/2)
KmerStream::KmerStream(): Finished
CompactedDBG::build(): Estimated number of k-mers occurring at least once: 38035051
CompactedDBG::build(): Estimated number of minimizer occurring at least once: 9356951
CompactedDBG::filter(): Processed 42887685 k-mers in 31840 reads
CompactedDBG::filter(): Found 37946112 unique k-mers
CompactedDBG::filter(): Number of blocks in Bloom filter is 260007
CompactedDBG::construct(): Extract approximate unitigs (1/2)
CompactedDBG::construct(): Extract approximate unitigs (2/2)
CompactedDBG::construct(): Closed all input files

CompactedDBG::construct(): Splitting unitigs (1/2)

CompactedDBG::construct(): Splitting unitigs (2/2)
CompactedDBG::construct(): Before split: 269060 unitigs
CompactedDBG::construct(): After split (1/1): 269060 unitigs
CompactedDBG::construct(): Unitigs split: 869
CompactedDBG::construct(): Unitigs deleted: 0

CompactedDBG::construct(): Joining unitigs
CompactedDBG::construct(): After join: 251521 unitigs
CompactedDBG::construct(): Joined 17687 unitigs
[build] building MPHF
[build] creating equivalence classes ... 
[build] target de Bruijn graph has k-mer length 31 and minimizer length 23
[build] target de Bruijn graph has 251521 contigs and contains 37979144 k-mers 

total 56M
-rw-r--r-- 1 shedurkin labmembers 2.0M Jan 31 16:25 kallisto.isoform.counts.matrix
-rw-r--r-- 1 shedurkin labmembers    0 Jan 31 16:25 kallisto.isoform.TMM.EXPR.matrix
-rw-r--r-- 1 shedurkin labmembers 2.4M Jan 31 16:25 kallisto.isoform.TPM.not_cross_norm
-rw-r--r-- 1 shedurkin labmembers  532 Jan 31 16:25 kallisto.isoform.TPM.not_cross_norm.runTMM.R
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:38 kallisto_quant_sample47
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:42 kallisto_quant_sample48
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:46 kallisto_quant_sample50
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:50 kallisto_quant_sample53
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:53 kallisto_quant_sample57
-rw-r--r-- 1 shedurkin labmembers  51M Jan 31 16:28 Pmea_kallisto_index.idx

5.2 Sample Quantification

Kallisto can run quantification on either single- or paired-end reads. The default option is paired-end, which requires the input of an even number of paired fastq files (e.g., pairA_R1.fastq, pairA_R2.fastq). To use single-end mode, include the –single flag, as well as -l (–fragment-length=DOUBLE, estimated avg. fragment length) and -s (–sd=DOUBLE, estimates stand. dev. of fragment length), and a number of fastq files. Again, gzipped files are acceptable.

Kallisto quant is rather finicky about how you input sets of paired reads, and you can only input a single pair at a time. To circumvent, I’ll create symlinks to each of the input files with simplified names, create a quantification function, and apply it iteratively to each pair using a loop.

# Load bash variables into memory
source .bashvars

# Create sym links to each of the trimmed read files with simplified names

for file in "${trimmed_reads_dir}"/*.fastp-trim.20230519.fastq.gz; do
    # Extract sample ID and read number from the file name
    sample_id=$(echo "$file" | grep -oP 'RNA-POC-\K\d+')
    read_number=$(echo "$file" | grep -oP '_R\K\d+')

    # Create the shortened name
    shortened_name="sample${sample_id}_R${read_number}.fastq.gz"

    # Create symbolic link
    ln -s "$file" "${trimmed_reads_dir}/${shortened_name}"

    echo "Created link: ${shortened_name}"
done

ls -lh ${trimmed_reads_dir}
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample47_R1.fastq.gz': File exists
Created link: sample47_R1.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample47_R2.fastq.gz': File exists
Created link: sample47_R2.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample48_R1.fastq.gz': File exists
Created link: sample48_R1.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample48_R2.fastq.gz': File exists
Created link: sample48_R2.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample50_R1.fastq.gz': File exists
Created link: sample50_R1.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample50_R2.fastq.gz': File exists
Created link: sample50_R2.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample53_R1.fastq.gz': File exists
Created link: sample53_R1.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample53_R2.fastq.gz': File exists
Created link: sample53_R2.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample57_R1.fastq.gz': File exists
Created link: sample57_R1.fastq.gz
ln: failed to create symbolic link '/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/sample57_R2.fastq.gz': File exists
Created link: sample57_R2.fastq.gz
total 31G
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:57 multiqc_data
-rw-r--r-- 1 shedurkin labmembers 3.2G May 19  2023 RNA-POC-47-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 3.3G May 19  2023 RNA-POC-47-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 3.0G May 19  2023 RNA-POC-48-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 3.1G May 19  2023 RNA-POC-48-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 3.3G May 19  2023 RNA-POC-50-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 3.4G May 19  2023 RNA-POC-50-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 3.2G May 19  2023 RNA-POC-53-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 3.3G May 19  2023 RNA-POC-53-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 2.5G May 19  2023 RNA-POC-57-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
-rw-r--r-- 1 shedurkin labmembers 2.6G May 19  2023 RNA-POC-57-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample47_R1.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-47-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample47_R2.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-47-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample48_R1.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-48-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample48_R2.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-48-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample50_R1.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-50-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample50_R2.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-50-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample53_R1.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-53-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample53_R2.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-53-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample57_R1.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-57-S1-TP2_R1_001.fastp-trim.20230519.fastq.gz
lrwxrwxrwx 1 shedurkin labmembers  149 Jan 30 18:33 sample57_R2.fastq.gz -> /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/trimmed-reads/RNA-POC-57-S1-TP2_R2_001.fastp-trim.20230519.fastq.gz
# Load bash variables into memory
source .bashvars

# Function to run kallisto quant. Takes two (paired) reads as input, outputs to sample-associated directory
run_kallisto_quant() {
    source .bashvars  # Source .bashvars inside the function to make its variables accessible
    local R1_fastq=${1}
    local R2_fastq=${2}
    
    cd ${kallisto_output_dir}
    sample_num=$(basename "${R1_fastq}" "_R1.fastq.gz")
    mkdir kallisto_quant_${sample_num}

    ${programs_array[kallisto]} quant \
        --threads=${threads} \
        --index="${kallisto_output_dir}/${kallisto_index_name}" \
        --output-dir="${kallisto_output_dir}/kallisto_quant_${sample_num}" \
        --bootstrap-samples=100 \
        ${trimmed_reads_dir}/${R1_fastq} ${trimmed_reads_dir}/${R2_fastq}
}



# Iteratively apply run_kallisto_quant on each pair of input reads
# This will take a while!(20-30 min for 5 samples)
for file_r1 in "${trimmed_reads_dir}"/*_R1.fastq.gz; do
    # Extract the sample name from the file name
    sample_name=$(basename "${file_r1}" "_R1.fastq.gz")

    # Form the file names (function takes input file names, not paths)
    file_r1_name="${sample_name}_R1.fastq.gz"
    file_r2_name="${sample_name}_R2.fastq.gz"

    # Check that the sample hasn't already been quantified
    if [ ! -d "${kallisto_output_dir}/kallisto_quant_${sample_name}" ]; then
    
        # Check if the corresponding R2 file exists
        if [ -e "${trimmed_reads_dir}/${file_r2}" ]; then
            # Run kallisto quant on the file pair
            run_kallisto_quant "${file_r1_name}" "${file_r2_name}" 

            echo "Processed sample: ${sample_name}"
        fi
    else
        echo "Sample already processed: ${sample_name}"
    fi
done

5.3 Trinity Matrix with Kallisto Output

# Load bash variables into memory
source .bashvars

cd ${kallisto_output_dir}

${programs_array[trinity_abund_to_matrix]} \
--est_method 'kallisto' \
--gene_trans_map 'none' \
--out_prefix 'kallisto' \
--name_sample_by_basedir ${kallisto_output_dir}/kallisto_quant_*/abundance.tsv

ls -lh ${kallisto_output_dir}
-reading file: /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/kallisto/kallisto_quant_sample47/abundance.tsv
-reading file: /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/kallisto/kallisto_quant_sample48/abundance.tsv
-reading file: /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/kallisto/kallisto_quant_sample50/abundance.tsv
-reading file: /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/kallisto/kallisto_quant_sample53/abundance.tsv
-reading file: /home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/kallisto/kallisto_quant_sample57/abundance.tsv


* Outputting combined matrix.

/home/shared/trinityrnaseq-v2.12.0/util/support_scripts/run_TMM_scale_matrix.pl --matrix kallisto.isoform.TPM.not_cross_norm > kallisto.isoform.TMM.EXPR.matrixCMD: R --no-save --no-restore --no-site-file --no-init-file -q < kallisto.isoform.TPM.not_cross_norm.runTMM.R 1>&2 
sh: 1: R: not found
Error, cmd: R --no-save --no-restore --no-site-file --no-init-file -q < kallisto.isoform.TPM.not_cross_norm.runTMM.R 1>&2  died with ret (32512)  at /home/shared/trinityrnaseq-v2.12.0/util/support_scripts/run_TMM_scale_matrix.pl line 105.
Error, CMD: /home/shared/trinityrnaseq-v2.12.0/util/support_scripts/run_TMM_scale_matrix.pl --matrix kallisto.isoform.TPM.not_cross_norm > kallisto.isoform.TMM.EXPR.matrix died with ret 6400 at /home/shared/trinityrnaseq-v2.12.0/util/abundance_estimates_to_matrix.pl line 385.
total 56M
-rw-r--r-- 1 shedurkin labmembers 2.0M Jan 31 16:28 kallisto.isoform.counts.matrix
-rw-r--r-- 1 shedurkin labmembers    0 Jan 31 16:28 kallisto.isoform.TMM.EXPR.matrix
-rw-r--r-- 1 shedurkin labmembers 2.4M Jan 31 16:28 kallisto.isoform.TPM.not_cross_norm
-rw-r--r-- 1 shedurkin labmembers  532 Jan 31 16:28 kallisto.isoform.TPM.not_cross_norm.runTMM.R
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:38 kallisto_quant_sample47
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:42 kallisto_quant_sample48
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:46 kallisto_quant_sample50
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:50 kallisto_quant_sample53
drwxr-xr-x 2 shedurkin labmembers 4.0K Jan 30 18:53 kallisto_quant_sample57
-rw-r--r-- 1 shedurkin labmembers  51M Jan 31 16:28 Pmea_kallisto_index.idx

6 Summary

LS0tCnRpdGxlOiAiMTQtUG1lYS1STkFzZXEta2FsbGlzdG8iCmF1dGhvcjogIkthdGhsZWVuIER1cmtpbiIKZGF0ZTogIjIwMjQtMDEtMzAiCmFsd2F5c19hbGxvd19odG1sOiB0cnVlCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICBnaXRodWJfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBodG1sX3ByZXZpZXc6IHRydWUgCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwgICAgICAgICAjIERpc3BsYXkgY29kZSBjaHVua3MKICBldmFsID0gRkFMU0UsICAgICAgICAjIEV2YWx1YXRlIGNvZGUgY2h1bmtzCiAgd2FybmluZyA9IEZBTFNFLCAgICAgIyBIaWRlIHdhcm5pbmdzCiAgbWVzc2FnZSA9IEZBTFNFLCAgICAgIyBIaWRlIG1lc3NhZ2VzCiAgY29tbWVudCA9ICIiICAgICAgICAgIyBQcmV2ZW50cyBhcHBlbmRpbmcgJyMjJyB0byBiZWdpbm5pbmcgb2YgbGluZXMgaW4gY29kZSBvdXRwdXQKKQpgYGAKCioqRGVzY3JpcHRpb246KioKVXNlIGthbGxpc3RvIHRvIHF1YW50aWZ5ICpQLiBtZWFuZHJpbmEqIFJOQXNlcSB0cmFuc2NyaXB0IGFidW5kYW5jZXMKCioqSW5wdXRzOioqCgpUcmltbWVkIFJOQXNlcSByZWFkcyAoZS5nLiBgKi5mYXN0cS5nemApLiAgKlAuIG1lYW5kcmluYSogcmVhZHMgZm91bmQgW2hlcmVdKGh0dHBzOi8vZ2FubmV0LmZpc2gud2FzaGluZ3Rvbi5lZHUvQXR1bWVmYWNpZW5zLzIwMjMwNTE5LUU1X2NvcmFsLWZhc3RxYy1mYXN0cC1tdWx0aXFjLVJOQXNlcS9QX21lYW5kcmluYS90cmltbWVkLykuCgpUcmFuc2NyaXB0cyBGQVNUQSAoZS5nLiBgKi5mbmEuZ3pgKSwgZm91bmQgW2hlcmVdKGh0dHA6Ly9jeWFub3Bob3JhLnJ1dGdlcnMuZWR1L1BvY2lsbG9wb3JhX21lYW5kcmluYS8pLgoKKipPdXRwdXRzOioqCgprYWxpc3RvIGNvdW50cyBtYXRyaXggKGBrYWxsaXN0by5pc29mb3JtLmNvdW50cy5tYXRyaXhgKQoKLS0tCgoKIyBDcmVhdGUgYSBCYXNoIHZhcmlhYmxlcyBmaWxlCgpUaGlzIGFsbG93cyB1c2FnZSBvZiBCYXNoIHZhcmlhYmxlcyAoZS5nLiBwYXRocyB0byBjb21tb24gZGlyZWN0b3JpZXMpIGFjcm9zcyBSIE1hcmtkb3duIGNodW5rcy4KYGBge3Igc2F2ZS1iYXNoLXZhcmlhYmxlcy10by1ydmFycy1maWxlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CnsKZWNobyAiIyMjIyBBc3NpZ24gVmFyaWFibGVzICMjIyMiCmVjaG8gIiIKCmVjaG8gIiMgRGF0YSBkaXJlY3RvcmllcyIKZWNobyAnZXhwb3J0IFBtZWFfZGlyPS9ob21lL3NoYXJlZC84VEJfSEREXzAyL3NoZWR1cmtpbi9kZWVwLWRpdmUvRi1QbWVhJwplY2hvICdleHBvcnQgb3V0cHV0X2Rpcl90b3A9JHtQbWVhX2Rpcn0vb3V0cHV0LzE0LVBtZWEtUk5Bc2VxLWthbGxpc3RvJwplY2hvICdleHBvcnQgdHJhbnNjcmlwdG9tZV9mYXN0YV9kaXI9JHtQbWVhX2Rpcn0vZGF0YS9QbWVhJwplY2hvICdleHBvcnQgdHJpbW1lZF9yZWFkc19kaXI9JHtvdXRwdXRfZGlyX3RvcH0vdHJpbW1lZC1yZWFkcycKZWNobyAnZXhwb3J0IGthbGxpc3RvX291dHB1dF9kaXI9JHtvdXRwdXRfZGlyX3RvcH0va2FsbGlzdG8nCmVjaG8gIiIKCmVjaG8gIiMgSW5wdXQvT3V0cHV0IGZpbGVzIgplY2hvICdleHBvcnQgdHJhbnNjcmlwdG9tZV9mYXN0YV9uYW1lPSJQb2NpbGxvcG9yYV9tZWFuZHJpbmFfSEl2MS5nZW5lcy5jZHMuZm5hLmd6IicKZWNobyAnZXhwb3J0IHRyYW5zY3JpcHRvbWVfZmFzdGE9IiR7dHJhbnNjcmlwdG9tZV9mYXN0YV9kaXJ9LyR7dHJhbnNjcmlwdG9tZV9mYXN0YV9uYW1lfSInCmVjaG8gJ2V4cG9ydCBrYWxsaXN0b19pbmRleF9uYW1lPSJQbWVhX2thbGxpc3RvX2luZGV4LmlkeCInCgplY2hvICIjIEV4dGVybmFsIGRhdGEgVVJMcyIKZWNobyAnZXhwb3J0IHRyaW1tZWRfcmVhZHNfdXJsPSJodHRwczovL2dhbm5ldC5maXNoLndhc2hpbmd0b24uZWR1L0F0dW1lZmFjaWVucy8yMDIzMDUxOS1FNV9jb3JhbC1mYXN0cWMtZmFzdHAtbXVsdGlxYy1STkFzZXEvUF9tZWFuZHJpbmEvdHJpbW1lZC8iJwplY2hvICdleHBvcnQgdHJhbnNjcmlwdG9tZV9mYXN0YV91cmw9Imh0dHA6Ly9jeWFub3Bob3JhLnJ1dGdlcnMuZWR1L1BvY2lsbG9wb3JhX21lYW5kcmluYS9Qb2NpbGxvcG9yYV9tZWFuZHJpbmFfSEl2MS5nZW5lcy5jZHMuZm5hLmd6IicKZWNobyAiIgoKZWNobyAiIyBTZXQgZmlsZW5hbWUgcGF0dGVybnMiCmVjaG8gImV4cG9ydCBmYXN0cV9wYXR0ZXJuPScqLmZhc3RxLmd6JyIKZWNobyAiZXhwb3J0IFIxX2Zhc3RxX3BhdHRlcm49JypfUjEuZmFzdHEuZ3onIgplY2hvICJleHBvcnQgUjJfZmFzdHFfcGF0dGVybj0nKl9SMi5mYXN0cS5neiciCmVjaG8gIiIKCmVjaG8gIiMgUGF0aHMgdG8gcHJvZ3JhbXMiCmVjaG8gJ2V4cG9ydCBrYWxsaXN0bz0vaG9tZS9zaGFyZWQva2FsbGlzdG9fbGludXgtdjAuNTAuMS9rYWxsaXN0bycKZWNobyAnZXhwb3J0IHRyaW5pdHlfYWJ1bmRfdG9fbWF0cml4PS9ob21lL3NoYXJlZC90cmluaXR5cm5hc2VxLXYyLjEyLjAvdXRpbC9hYnVuZGFuY2VfZXN0aW1hdGVzX3RvX21hdHJpeC5wbCcKZWNobyAiIgoKZWNobyAiIyBTZXQgbnVtYmVyIG9mIENQVXMgdG8gdXNlIgplY2hvICdleHBvcnQgdGhyZWFkcz0yMCcKZWNobyAiIgoKZWNobyAiIyBQcm9ncmFtcyBhc3NvY2lhdGl2ZSBhcnJheSIKZWNobyAiZGVjbGFyZSAtQSBwcm9ncmFtc19hcnJheSIKZWNobyAicHJvZ3JhbXNfYXJyYXk9KCIKZWNobyAnW2thbGxpc3RvXT0iJHtrYWxsaXN0b30iIFwnCmVjaG8gJ1t0cmluaXR5X2FidW5kX3RvX21hdHJpeF09IiR7dHJpbml0eV9hYnVuZF90b19tYXRyaXh9IiBcJwplY2hvICIpIgoKfSA+IC5iYXNodmFycwoKY2F0IC5iYXNodmFycwpgYGAKCgojIERvd25sb2FkIHRyaW1tZWQgUk5Bc2VxIHJlYWRzCgpSZWFkcyBhcmUgZG93bmxvYWRlZCBmcm9tOiBodHRwczovL2dhbm5ldC5maXNoLndhc2hpbmd0b24uZWR1L0F0dW1lZmFjaWVucy8yMDIzMDUxOS1FNV9jb3JhbC1mYXN0cWMtZmFzdHAtbXVsdGlxYy1STkFzZXEvQV9wdWxjaHJhL3RyaW1tZWQvCgpUaGUgYC0tY3V0LWRpcnMgNGAgY29tbWFuZCBjdXRzIHRoZSBwcmVjZWRpbmcgZGlyZWN0b3J5IHN0cnVjdHVyZSAoaS5lLiBgQXR1bWVmYWNpZW5zLzIwMjMwNTE5LUU1X2NvcmFsLWZhc3RxYy1mYXN0cC1tdWx0aXFjLVJOQXNlcS9QX21lYW5kcmluYS90cmltbWVkL2ApIHNvIHRoYXQgd2UganVzdCBlbmQgdXAgd2l0aCB0aGUgcmVhZHMuCgpgYGB7YmFzaCBkb3dubG9hZC10cmltbWVkLXJlYWRzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKd2dldCBcCi0tZGlyZWN0b3J5LXByZWZpeCAke3RyaW1tZWRfcmVhZHNfZGlyfSBcCi0tcmVjdXJzaXZlIFwKLS1uby1jaGVjay1jZXJ0aWZpY2F0ZSBcCi0tY29udGludWUgXAotLWN1dC1kaXJzIDQgXAotLW5vLWhvc3QtZGlyZWN0b3JpZXMgXAotLW5vLXBhcmVudCBcCi0tcXVpZXQgXAotLWFjY2VwdCAiUk5BLSouZmFzdHEuZ3oiICR7dHJpbW1lZF9yZWFkc191cmx9CgpscyAtbGggIiR7dHJpbW1lZF9yZWFkc19kaXJ9IgpgYGAKCiMgRmFzdFFDL011bHRpUUMgb24gdHJpbW1lZCByZWFkcwoKQWxyZWFkeSBwZXJmb3JtZWQsIGNhbiB2aWV3IG11bHRpcWMgcmVwb3J0IGF0IGh0dHBzOi8vZ2FubmV0LmZpc2gud2FzaGluZ3Rvbi5lZHUvQXR1bWVmYWNpZW5zLzIwMjMwNTE5LUU1X2NvcmFsLWZhc3RxYy1mYXN0cC1tdWx0aXFjLVJOQXNlcS9QX21lYW5kcmluYS90cmltbWVkL211bHRpcWNfcmVwb3J0Lmh0bWwKCiMgUmV0cmlldmUgdGhlIHJlZmVyZW5jZSB0cmFuc2NyaXB0b21lCgpgYGB7ciBkb3dubG9hZC10cmFuc2NyaXB0b21lLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKd2dldCBcCi0tZGlyZWN0b3J5LXByZWZpeCAke3RyYW5zY3JpcHRvbWVfZmFzdGFfZGlyfSBcCi0tbm8tY2hlY2stY2VydGlmaWNhdGUgXAotLWNvbnRpbnVlIFwKLS1uby1ob3N0LWRpcmVjdG9yaWVzIFwKLS1uby1kaXJlY3RvcmllcyBcCi0tbm8tcGFyZW50IFwKLS1xdWlldCBcCi0tZXhlY3V0ZSByb2JvdHM9b2ZmIFwKLS1hY2NlcHQgIiR7dHJhbnNjcmlwdG9tZV9mYXN0YV9uYW1lfSIgJHt0cmFuc2NyaXB0b21lX2Zhc3RhX3VybH0KCmxzIC1saCAiJHt0cmFuc2NyaXB0b21lX2Zhc3RhX2Rpcn0iCmBgYAoKIyMgVmVyaWZ5IHRyYW5zY3JpcHRvbWUgRmFzdEEgTUQ1IGNoZWNrc3VtCgpObyBjaGVja3N1bSBmaWxlKHMpIHByb3ZpZGVkIHdpdGggZG93bmxvYWQsIHNvIHNraXBwcGluZyB0aGlzIHN0ZXAKCiMgQWxpZ24gdG8gcmVmZXJlbmNlIHRyYW5zY3JpcHRvbWUgKEthbGxpc3RvIHBzZXVkb2FsaWdubWVudCkKCiMjIEJ1aWxkaW5nIEluZGV4CgpgYGB7ciBrYWxsaXN0by1pbmRleGluZywgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKY2QgIiR7a2FsbGlzdG9fb3V0cHV0X2Rpcn0iCgoke3Byb2dyYW1zX2FycmF5W2thbGxpc3RvXX0gaW5kZXggXAotLXRocmVhZHM9JHt0aHJlYWRzfSBcCi0taW5kZXg9IiR7a2FsbGlzdG9faW5kZXhfbmFtZX0iIFwKIiR7dHJhbnNjcmlwdG9tZV9mYXN0YX0iCgpscyAtbGggJHtrYWxsaXN0b19vdXRwdXRfZGlyfQpgYGAKCgojIyBTYW1wbGUgUXVhbnRpZmljYXRpb24KCkthbGxpc3RvIGNhbiBydW4gcXVhbnRpZmljYXRpb24gb24gZWl0aGVyIHNpbmdsZS0gb3IgcGFpcmVkLWVuZCByZWFkcy4gVGhlIGRlZmF1bHQgb3B0aW9uIGlzIHBhaXJlZC1lbmQsIHdoaWNoIHJlcXVpcmVzIHRoZSBpbnB1dCBvZiBhbiBldmVuIG51bWJlciBvZiBwYWlyZWQgZmFzdHEgZmlsZXMgKGUuZy4sIHBhaXJBX1IxLmZhc3RxLCBwYWlyQV9SMi5mYXN0cSkuIApUbyB1c2Ugc2luZ2xlLWVuZCBtb2RlLCBpbmNsdWRlIHRoZSAtLXNpbmdsZSBmbGFnLCBhcyB3ZWxsIGFzIC1sICgtLWZyYWdtZW50LWxlbmd0aD1ET1VCTEUsIGVzdGltYXRlZCBhdmcuIGZyYWdtZW50IGxlbmd0aCkgYW5kIC1zICgtLXNkPURPVUJMRSwgZXN0aW1hdGVzIHN0YW5kLiBkZXYuIG9mIGZyYWdtZW50IGxlbmd0aCksIGFuZCBhIG51bWJlciBvZiBmYXN0cSBmaWxlcy4KQWdhaW4sIGd6aXBwZWQgZmlsZXMgYXJlIGFjY2VwdGFibGUuCgpLYWxsaXN0byBxdWFudCBpcyByYXRoZXIgZmluaWNreSBhYm91dCBob3cgeW91IGlucHV0IHNldHMgb2YgcGFpcmVkIHJlYWRzLCBhbmQgeW91IGNhbiBvbmx5IGlucHV0IGEgc2luZ2xlIHBhaXIgYXQgYSB0aW1lLiBUbyBjaXJjdW12ZW50LCBJJ2xsIGNyZWF0ZSBzeW1saW5rcyB0byBlYWNoIG9mIHRoZSBpbnB1dCBmaWxlcyB3aXRoIHNpbXBsaWZpZWQgbmFtZXMsIGNyZWF0ZSBhIHF1YW50aWZpY2F0aW9uIGZ1bmN0aW9uLCBhbmQgYXBwbHkgaXQgaXRlcmF0aXZlbHkgdG8gZWFjaCBwYWlyIHVzaW5nIGEgbG9vcC4KCmBgYHtyIHJlbmFtZS10cmltbWVkLXJlYWRzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIENyZWF0ZSBzeW0gbGlua3MgdG8gZWFjaCBvZiB0aGUgdHJpbW1lZCByZWFkIGZpbGVzIHdpdGggc2ltcGxpZmllZCBuYW1lcwoKZm9yIGZpbGUgaW4gIiR7dHJpbW1lZF9yZWFkc19kaXJ9Ii8qLmZhc3RwLXRyaW0uMjAyMzA1MTkuZmFzdHEuZ3o7IGRvCiAgICAjIEV4dHJhY3Qgc2FtcGxlIElEIGFuZCByZWFkIG51bWJlciBmcm9tIHRoZSBmaWxlIG5hbWUKICAgIHNhbXBsZV9pZD0kKGVjaG8gIiRmaWxlIiB8IGdyZXAgLW9QICdSTkEtUE9DLVxLXGQrJykKICAgIHJlYWRfbnVtYmVyPSQoZWNobyAiJGZpbGUiIHwgZ3JlcCAtb1AgJ19SXEtcZCsnKQoKICAgICMgQ3JlYXRlIHRoZSBzaG9ydGVuZWQgbmFtZQogICAgc2hvcnRlbmVkX25hbWU9InNhbXBsZSR7c2FtcGxlX2lkfV9SJHtyZWFkX251bWJlcn0uZmFzdHEuZ3oiCgogICAgIyBDcmVhdGUgc3ltYm9saWMgbGluawogICAgbG4gLXMgIiRmaWxlIiAiJHt0cmltbWVkX3JlYWRzX2Rpcn0vJHtzaG9ydGVuZWRfbmFtZX0iCgogICAgZWNobyAiQ3JlYXRlZCBsaW5rOiAke3Nob3J0ZW5lZF9uYW1lfSIKZG9uZQoKbHMgLWxoICR7dHJpbW1lZF9yZWFkc19kaXJ9CmBgYAoKYGBge3Iga2FsbGlzdG8tcXVhbnRpZmljYXRpb24sIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIEZ1bmN0aW9uIHRvIHJ1biBrYWxsaXN0byBxdWFudC4gVGFrZXMgdHdvIChwYWlyZWQpIHJlYWRzIGFzIGlucHV0LCBvdXRwdXRzIHRvIHNhbXBsZS1hc3NvY2lhdGVkIGRpcmVjdG9yeQpydW5fa2FsbGlzdG9fcXVhbnQoKSB7CiAgICBzb3VyY2UgLmJhc2h2YXJzICAjIFNvdXJjZSAuYmFzaHZhcnMgaW5zaWRlIHRoZSBmdW5jdGlvbiB0byBtYWtlIGl0cyB2YXJpYWJsZXMgYWNjZXNzaWJsZQogICAgbG9jYWwgUjFfZmFzdHE9JHsxfQogICAgbG9jYWwgUjJfZmFzdHE9JHsyfQogICAgCiAgICBjZCAke2thbGxpc3RvX291dHB1dF9kaXJ9CiAgICBzYW1wbGVfbnVtPSQoYmFzZW5hbWUgIiR7UjFfZmFzdHF9IiAiX1IxLmZhc3RxLmd6IikKICAgIG1rZGlyIGthbGxpc3RvX3F1YW50XyR7c2FtcGxlX251bX0KCiAgICAke3Byb2dyYW1zX2FycmF5W2thbGxpc3RvXX0gcXVhbnQgXAogICAgICAgIC0tdGhyZWFkcz0ke3RocmVhZHN9IFwKICAgICAgICAtLWluZGV4PSIke2thbGxpc3RvX291dHB1dF9kaXJ9LyR7a2FsbGlzdG9faW5kZXhfbmFtZX0iIFwKICAgICAgICAtLW91dHB1dC1kaXI9IiR7a2FsbGlzdG9fb3V0cHV0X2Rpcn0va2FsbGlzdG9fcXVhbnRfJHtzYW1wbGVfbnVtfSIgXAogICAgICAgIC0tYm9vdHN0cmFwLXNhbXBsZXM9MTAwIFwKICAgICAgICAke3RyaW1tZWRfcmVhZHNfZGlyfS8ke1IxX2Zhc3RxfSAke3RyaW1tZWRfcmVhZHNfZGlyfS8ke1IyX2Zhc3RxfQp9CgoKCiMgSXRlcmF0aXZlbHkgYXBwbHkgcnVuX2thbGxpc3RvX3F1YW50IG9uIGVhY2ggcGFpciBvZiBpbnB1dCByZWFkcwojIFRoaXMgd2lsbCB0YWtlIGEgd2hpbGUhKDIwLTMwIG1pbiBmb3IgNSBzYW1wbGVzKQpmb3IgZmlsZV9yMSBpbiAiJHt0cmltbWVkX3JlYWRzX2Rpcn0iLypfUjEuZmFzdHEuZ3o7IGRvCiAgICAjIEV4dHJhY3QgdGhlIHNhbXBsZSBuYW1lIGZyb20gdGhlIGZpbGUgbmFtZQogICAgc2FtcGxlX25hbWU9JChiYXNlbmFtZSAiJHtmaWxlX3IxfSIgIl9SMS5mYXN0cS5neiIpCgogICAgIyBGb3JtIHRoZSBmaWxlIG5hbWVzIChmdW5jdGlvbiB0YWtlcyBpbnB1dCBmaWxlIG5hbWVzLCBub3QgcGF0aHMpCiAgICBmaWxlX3IxX25hbWU9IiR7c2FtcGxlX25hbWV9X1IxLmZhc3RxLmd6IgogICAgZmlsZV9yMl9uYW1lPSIke3NhbXBsZV9uYW1lfV9SMi5mYXN0cS5neiIKCiAgICAjIENoZWNrIHRoYXQgdGhlIHNhbXBsZSBoYXNuJ3QgYWxyZWFkeSBiZWVuIHF1YW50aWZpZWQKICAgIGlmIFsgISAtZCAiJHtrYWxsaXN0b19vdXRwdXRfZGlyfS9rYWxsaXN0b19xdWFudF8ke3NhbXBsZV9uYW1lfSIgXTsgdGhlbgogICAgCiAgICAgICAgIyBDaGVjayBpZiB0aGUgY29ycmVzcG9uZGluZyBSMiBmaWxlIGV4aXN0cwogICAgICAgIGlmIFsgLWUgIiR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7ZmlsZV9yMn0iIF07IHRoZW4KICAgICAgICAgICAgIyBSdW4ga2FsbGlzdG8gcXVhbnQgb24gdGhlIGZpbGUgcGFpcgogICAgICAgICAgICBydW5fa2FsbGlzdG9fcXVhbnQgIiR7ZmlsZV9yMV9uYW1lfSIgIiR7ZmlsZV9yMl9uYW1lfSIgCgogICAgICAgICAgICBlY2hvICJQcm9jZXNzZWQgc2FtcGxlOiAke3NhbXBsZV9uYW1lfSIKICAgICAgICBmaQogICAgZWxzZQogICAgICAgIGVjaG8gIlNhbXBsZSBhbHJlYWR5IHByb2Nlc3NlZDogJHtzYW1wbGVfbmFtZX0iCiAgICBmaQpkb25lCmBgYAoKCiMjIFRyaW5pdHkgTWF0cml4IHdpdGggS2FsbGlzdG8gT3V0cHV0CgpgYGB7ciBrYWxsaXN0by10cmluaXR5LW1hdHJpeCwgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKY2QgJHtrYWxsaXN0b19vdXRwdXRfZGlyfQoKJHtwcm9ncmFtc19hcnJheVt0cmluaXR5X2FidW5kX3RvX21hdHJpeF19IFwKLS1lc3RfbWV0aG9kICdrYWxsaXN0bycgXAotLWdlbmVfdHJhbnNfbWFwICdub25lJyBcCi0tb3V0X3ByZWZpeCAna2FsbGlzdG8nIFwKLS1uYW1lX3NhbXBsZV9ieV9iYXNlZGlyICR7a2FsbGlzdG9fb3V0cHV0X2Rpcn0va2FsbGlzdG9fcXVhbnRfKi9hYnVuZGFuY2UudHN2CgpscyAtbGggJHtrYWxsaXN0b19vdXRwdXRfZGlyfQpgYGAKCgojIFN1bW1hcnkKCg==