1 Changelog

  • 202308: Moved preprocessing material from the datastructures file to here.

2 Introduction

This document outlines in some detail the tasks performed in order to process the ‘raw’ data.

3 Sequence preprocessing

All of the preprocessing tasks were performed with CYOA and included the following:

  1. All samples were trimmed with trimomatic using options to remove adapters using a supplemented copy of the default adapter database (ILLUMINACLIP:2:30:10:2:keepBothReads), reads with fewer than 40 nucleotides remaining were discarded (MINLEN:40), and a mean quality >= 25 over 4 nucleotide window was used for trimming (SLIDINGWINDOW:4:25). When paired end reads were available, only the properly paired were used for the tasks that follow. The generated scripts for each sample which performed this trimming have the prefix ‘05trim’.
  2. Reads were passed to fastqc using the default parameters to query read quality, remaining adapter content, and as an initial survey for contaminants. The generated scripts which performed this have the prefix ‘06fastqc’
  3. Every sample was passed to kraken2 against its comprehensive ‘standard’ and ‘virus’ databases, updated 2021/06 in order to query for putative contaminants and potentially interesting viral sequences. The scripts which performed this have the prefix ‘11kraken’.
  4. Samples were passed to hisat2 against the hg38 release 100 human genome with the default options as well as the Leishmania panamensis MHOM/COL release 46 in serial. The scripts which performed these operations have the prefixes ‘15hisat2_hg38_100’ and ‘15hisat2_lpanamensis_v46’ respectively.
  5. The resulting alignments were converted to the binary, sorted, compressed, and indexed format via samtools. Additional filters were performed to extract only the non-variant alignments . The scripts which performed this have the prefix ‘19s2b_{genome}’.
  6. These were cross referenced against the relevant feature databases in order to generate count tables by gene via htseq. These scripts have the prefix ‘21hts’.
  7. Each sample was passed to salmon against the transcript databases for hg38 release 100, L. panamensis release 46, and a concatenation of the two. These scripts have the suffix ‘30sal_{genome}’.
  8. A regular expression search was performed for the observed set of spliced leader sequences. The sequence ‘AGTTTCTGTACTTTATTGG’ rather than the entire SL sequence was searched to avoid potential SL variants. The relevant scripts have the prefix ‘50slsearch’.

Given the fact that these tasks were performed over the course of 4 years, during which time we changed sequencing platforms and computational infrastructure, the actual prefixes/suffixes of the various scripts and outputs are not as consistent as I would like.

3.0.1 Trimming raw reads

With the above caveat in mind, I am copy/pasting the little shell fragments I used when trimming the samples:

## trim.sh, this assumes one will manually cd into the new sample's directory and run ../tmrc_trim.sh
## In addition, it assumes that the new data files will reside in the directory 'unprocessed/'.
input=$(/bin/ls -d unprocessed | tr '\n' ':' | sed 's/:$//g')
echo "Running trimomatic on ${input}"
cmd="cyoa --method trim --input ${input} 2>>cyoa_trim.out 1>&2 &"
echo "${cmd}" > cyoa_trim.out
${cmd}

The following is a script which is generated by the above, arbitrarily chosen from sample TMRC30140. If anyone reads it carefully, one might note that this sample is from before I started depositing new raw reads into the ‘unprocessed’ directory, as a result the input reads were in the cwd.

#!/usr/bin/env bash
#SBATCH --export=ALL
#SBATCH --mail-type=NONE
#SBATCH --chdir=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30140
#SBATCH --partition=dpart
#SBATCH --qos=workstation --nice=10
#SBATCH --nodes=1 --requeue
#SBATCH --time=10:00:00
#SBATCH --job-name=01trim_TMRC30140_S3_R1_001
#SBATCH --mem=40G
#SBATCH --cpus-per-task=3
#SBATCH --output=outputs/logs/trim_TMRC30140_S3_R1_001.sbatchout

echo "## Started /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30140/scripts/01trim_TMRC30140_S3_R1_001.sh at $(date) on $(hostname) with id ${SLURM_JOBID}." >> outputs/log.txt

module add trimomatic

## This call to trimomatic removes illumina and epicentre adapters from TMRC30140_S3_R1_001.fastq.gz:TMRC30140_S3_R2_001.fastq.gz.
## It also performs a sliding window removal of anything with quality <25;
## cutadapt provides an alternative to this tool.
## The original sequence data is recompressed and saved in the sequences/ directory.
mkdir -p outputs/01trimomatic
## Note that trimomatic prints all output and errors to STDERR, so send both to output
trimmomatic PE \
  -threads 1 \
  -phred33 \
  TMRC30140_S3_R1_001.fastq.gz TMRC30140_S3_R2_001.fastq.gz \
  TMRC30140_S3_R1_001-trimmed_paired.fastq TMRC30140_S3_R1_001-trimmed_unpaired.fastq \
  TMRC30140_S3_R2_001-trimmed_paired.fastq TMRC30140_S3_R2_001-trimmed_unpaired.fastq \
   ILLUMINACLIP:/cbcb/sw/RedHat-7-x86_64/common/local/perl/5.34/lib/site_perl/5.34.0/auto/share/dist/Bio-Adventure/genome/adapters.fa:2:20:10:2:keepBothReads \
  SLIDINGWINDOW:4:20 MINLEN:40 \
  1>outputs/01trimomatic/TMRC30140_S3_R1_001-trimomatic.out 2>&1
excepted=$(grep "Exception" outputs/TMRC30140_S3_R1_001-trimomatic.out)
## The following is in case the illumina clipping fails, which it does if this has already been run I think.
if [[ "${excepted}" != "" ]]; then
  trimmomatic PE \
    -threads 1 \
    -phred33 \
    TMRC30140_S3_R1_001.fastq.gz TMRC30140_S3_R2_001.fastq.gz \
    TMRC30140_S3_R1_001-trimmed_paired.fastq TMRC30140_S3_R1_001-trimmed_unpaired.fastq \
    TMRC30140_S3_R2_001-trimmed_paired.fastq TMRC30140_S3_R2_001-trimmed_unpaired.fastq \
     SLIDINGWINDOW:4:25 MINLEN:50\
    1>outputs/01trimomatic/TMRC30140_S3_R1_001-trimomatic.out 2>&1
fi
sleep 10
mv TMRC30140_S3_R1_001-trimmed_paired.fastq TMRC30140_S3_R1_001-trimmed.fastq
mv TMRC30140_S3_R2_001-trimmed_paired.fastq TMRC30140_S3_R2_001-trimmed.fastq

## Recompress the unpaired reads, this should not take long.
xz -9e -f TMRC30140_S3_R1_001-trimmed_unpaired.fastq
xz -9e -f TMRC30140_S3_R2_001-trimmed_unpaired.fastq
## Recompress the paired reads.
xz -9e -f TMRC30140_S3_R1_001-trimmed.fastq
xz -9e -f TMRC30140_S3_R2_001-trimmed.fastq
ln -sf TMRC30140_S3_R1_001-trimmed.fastq.xz r1_trimmed.fastq.xz
ln -sf TMRC30140_S3_R2_001-trimmed.fastq.xz r2_trimmed.fastq.xz


## The following lines give status codes and some logging
echo "## Job status: $? " >> outputs/log.txt
echo "## $(hostname) Finished ${SLURM_JOBID} 01trim_TMRC30140_S3_R1_001.sh at $(date), it took $(( SECONDS / 60 )) minutes." >> outputs/log.txt

walltime=$(scontrol show job "${SLURM_JOBID}" | grep RunTime | perl -F'/\s+|=/' -lane '{print $F[2]}')
echo "#### walltime used by ${SLURM_JOBID} was: ${walltime:-null}" >> outputs/log.txt
maxmem=$(sstat --format=MaxVMSize -n "${SLURM_JOBID}.batch")
echo "#### maximum memory used by ${SLURM_JOBID} was: ${maxmem:-null}" >> outputs/log.txt
avecpu=$(sstat --format=AveCPU -n "${SLURM_JOBID}.batch")
echo "#### average cpu used by ${SLURM_JOBID} was: ${avecpu:-null}" >> outputs/log.txt

3.0.2 Mapping the trimmed reads

There is a similar shell fragment used to map these trimmed reads against the hg38_100 genome/transcriptome along with the panamensis genome:

#!/usr/bin/env bash
input=$(/bin/ls *_trimmed.fastq.xz | tr '\n' ':' | sed 's/:$//g')
cyoa --task map --method hisat --species hg38_100 --gff_type gene --gff_tag gene_id  \
  --input ${input} 2>tmrc3_map.out 1>&2 &
cyoa --task map --method hisat --species lpanamensis_v36 --gff_type gene --gff_tag ID \
  --input ${input} 2>>tmrc3_map.out 1>&2 &
cyoa --task map --method salmon --species hg38_100 \
     --input ${input} 2>tmrc3_salmon.out 1>&2 &

The following is the resulting mapping script taken arbitrarily from sample TMRC30205. There are a few aspects of this script which changed from the beginning to end of the project: the prefix # changed, I added some logic to check if the requisite software (in this case hisat2/samtools/htseq) is already in the path, and load it if not. I also changed the htseq output filenames slightly over time to try to make certain that they are consistent and that it is easy to identify the important parameters just from the output filename.

#!/usr/bin/env bash
#SBATCH --chdir=/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30205
#SBATCH --partition=dpart
#SBATCH --qos=workstation --nice=10
#SBATCH --nodes=1 --requeue
#SBATCH --time=10:00:00
#SBATCH --job-name=40hisat2_hg38_100_genome
#SBATCH --mem=48G
#SBATCH --cpus-per-task=4
#SBATCH --output=outputs/logs/hisat2_hg38_100_genome.sbatchout

echo "## Started /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30205/scripts/40hisat2_hg38_100_genome.sh at $(date) on $(hostname) with id ${SLURM_JOBID}." >> outputs/log.txt

module add hisat2 samtools htseq

## This is a hisat2 alignment of  -1 <(less /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30205/r1_trimmed.fastq.xz) -2 <(less /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30205/r2_trimmed.fastq.xz)  against /cbcbhomes/abelew/libraries/genome/indexes/hg38_100

mkdir -p outputs/40hisat2_hg38_100
sleep 3
hisat2 -x /cbcbhomes/abelew/libraries/genome/indexes/hg38_100  \
  -p 4 \
  -q   -1 <(less /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30205/r1_trimmed.fastq.xz) -2 <(less /fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/TMRC30205/r2_trimmed.fastq.xz)  \
  --phred33 \
  --un-gz outputs/40hisat2_hg38_100/TMRC30205_unaldis_hg38_100_genome.fastq \
  --al-gz outputs/40hisat2_hg38_100/TMRC30205_aldis_hg38_100_genome.fastq \
  --un-conc-gz outputs/40hisat2_hg38_100/TMRC30205_unalcon_hg38_100_genome.fastq \
  --al-conc-gz outputs/40hisat2_hg38_100/TMRC30205_alcon_hg38_100_genome.fastq \
  -S outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.sam \
  2>outputs/40hisat2_hg38_100/hisat2_hg38_100_genome_TMRC30205.err \
  1>outputs/40hisat2_hg38_100/hisat2_hg38_100_genome_TMRC30205.out


## The following lines give status codes and some logging
echo "## Job status: $? " >> outputs/log.txt
echo "## $(hostname) Finished ${SLURM_JOBID} 40hisat2_hg38_100_genome.sh at $(date), it took $(( SECONDS / 60 )) minutes." >> outputs/log.txt

walltime=$(scontrol show job "${SLURM_JOBID}" | grep RunTime | perl -F'/\s+|=/' -lane '{print $F[2]}')
echo "#### walltime used by ${SLURM_JOBID} was: ${walltime:-null}" >> outputs/log.txt
maxmem=$(sstat --format=MaxVMSize -n "${SLURM_JOBID}.batch")
echo "#### maximum memory used by ${SLURM_JOBID} was: ${maxmem:-null}" >> outputs/log.txt
avecpu=$(sstat --format=AveCPU -n "${SLURM_JOBID}.batch")
echo "#### average cpu used by ${SLURM_JOBID} was: ${avecpu:-null}" >> outputs/log.txt

From here on I will remove the suffix of the script. Here is the sam to bam conversion script which was created by cyoa.

module add samtools bamtools

## Converting the text sam to a compressed, sorted, indexed bamfile.
## Also printing alignment statistics to outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam.stats
## This job depended on: 133995

echo "Starting samtools"
if $(test ! -r outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.sam); then
    echo "Could not find the samtools input file."
    exit 1
fi
samtools view -u -t /cbcbhomes/abelew/libraries/genome/hg38_100.fasta \
  -S outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.sam -o outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam  \
  2>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam.err 1>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam.out && \

  samtools sort -l 9 outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam -o outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-sorted.bam \
  2>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-sorted.err 1>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-sorted.out && \
  rm outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam && \
  rm outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.sam && \
  mv outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-sorted.bam outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam &&  samtools index outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam

bamtools stats -in outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam 2>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam.stats 1>&2

## The following will fail if this is single-ended.
samtools view -b -f 2 -o outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired.bam outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome.bam && samtools index outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired.bam
bamtools stats -in outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired.bam 2>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired.stats 1>&2

And the counting script for htseq. I changed the output filename for this step on multiple occasions over the course of sample collection.

module add htseq

## Counting the number of hits in outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired.bam for each feature found in /cbcbhomes/abelew/libraries/genome/hg38_100.gff
## Is this stranded? no.  The defaults of htseq are:
##  --order=name --idattr=gene_id --minaqual=10 --type=exon --stranded=yes --mode=union

htseq-count \
  -q -f bam -s no  --type gene  --idattr gene_id \
  outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired.bam \
  /cbcbhomes/abelew/libraries/genome/hg38_100.gff \
  2>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired_all_hg38_100_sno_gene_gene_id.err \
  1>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired_all_hg38_100_sno_gene_gene_id.count && \
    xz -f -9e outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired_all_hg38_100_sno_gene_gene_id.count 2>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired_all_hg38_100_sno_gene_gene_id.err.xz 1>outputs/40hisat2_hg38_100/TMRC30205_hg38_100_genome-paired_all_hg38_100_sno_gene_gene_id.count.xz

The same cyoa invocation produced a series of scripts to aggressively compress the (un)mapped reads from hisat2 and print out some summary statistics of the runs.

Conversely, here is a salmon script which was used for sample TMRC30124 (without the slurm prefix/suffix):

mkdir -p outputs/salmon_hg38_100 && sleep 3 && \
salmon quant -i /cbcbhomes/abelew/libraries/genome/indexes/hg38_100_salmon_index \
  -l A --gcBias --validateMappings  \
   -r <(less r1_trimmed.fastq.gz)  \
  -o outputs/salmon_hg38_100 \
  2>outputs/salmon_hg38_100/salmon.err 1>outputs/salmon_hg38_100/salmon.out
LS0tCnRpdGxlOiAiVE1SQzMgMjAyMzA4OiBDcmVhdGluZyBEYXRhIFN0cnVjdHVyZXMiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICBjb2xsYXBzZWQ6IGZhbHNlCiAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4OwogIH0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoaHBnbHRvb2xzKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoZ2x1ZSkKbGlicmFyeShFdVBhdGhEQikKCnR0IDwtIHNtKGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKSkKa25pdHI6Om9wdHNfa25pdCRzZXQoCiAgcHJvZ3Jlc3MgPSBUUlVFLCB2ZXJib3NlID0gVFJVRSwgd2lkdGggPSA5MCwgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlcnJvciA9IFRSVUUsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA4LCBmaWcucmV0aW5hID0gMiwKICBmaWcucG9zID0gInQiLCBmaWcuYWxpZ24gPSAiY2VudGVyIiwgZHBpID0gaWYgKGtuaXRyOjppc19sYXRleF9vdXRwdXQoKSkgNzIgZWxzZSAzMDAsCiAgb3V0LndpZHRoID0gIjEwMCUiLCBkZXYgPSAic3ZnIiwKICBkZXYuYXJncyA9IGxpc3QocG5nID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKSkKb2xkX29wdGlvbnMgPC0gb3B0aW9ucygKICBkaWdpdHMgPSA0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSBTeXMuZ2V0ZW52KCJWRVJTSU9OIikKcHJldmlvdXNfZmlsZSA8LSAiIgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCiMjdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWU9Z3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSJcXC5yZGFcXC54eiIsIHg9cHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gZ2x1ZSgidG1yYzNfZGF0YXNldHNfe3Zlcn0uUm1kIikKc2F2ZWZpbGUgPC0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcm1kX2ZpbGUpCmRhdGFfc3RydWN0dXJlcyA8LSBjKCkKYGBgCgojIENoYW5nZWxvZwoKKiAyMDIzMDg6IE1vdmVkIHByZXByb2Nlc3NpbmcgbWF0ZXJpYWwgZnJvbSB0aGUgZGF0YXN0cnVjdHVyZXMgZmlsZSB0byBoZXJlLgoKIyBJbnRyb2R1Y3Rpb24KClRoaXMgZG9jdW1lbnQgb3V0bGluZXMgaW4gc29tZSBkZXRhaWwgdGhlIHRhc2tzIHBlcmZvcm1lZCBpbiBvcmRlciB0bwpwcm9jZXNzIHRoZSAncmF3JyBkYXRhLgoKIyBTZXF1ZW5jZSBwcmVwcm9jZXNzaW5nCgpBbGwgb2YgdGhlIHByZXByb2Nlc3NpbmcgdGFza3Mgd2VyZSBwZXJmb3JtZWQgd2l0aCBDWU9BIGFuZCBpbmNsdWRlZAp0aGUgZm9sbG93aW5nOgoKMS4gQWxsIHNhbXBsZXMgd2VyZSB0cmltbWVkIHdpdGggdHJpbW9tYXRpYyB1c2luZyBvcHRpb25zIHRvIHJlbW92ZQogICBhZGFwdGVycyB1c2luZyBhIHN1cHBsZW1lbnRlZCBjb3B5IG9mIHRoZSBkZWZhdWx0IGFkYXB0ZXIgZGF0YWJhc2UKICAgKElMTFVNSU5BQ0xJUDoyOjMwOjEwOjI6a2VlcEJvdGhSZWFkcyksIHJlYWRzIHdpdGggZmV3ZXIgdGhhbiA0MAogICBudWNsZW90aWRlcyByZW1haW5pbmcgd2VyZSBkaXNjYXJkZWQgKE1JTkxFTjo0MCksIGFuZCBhIG1lYW4gcXVhbGl0eQogICA+PSAyNSBvdmVyIDQgbnVjbGVvdGlkZSB3aW5kb3cgd2FzIHVzZWQgZm9yIHRyaW1taW5nCiAgIChTTElESU5HV0lORE9XOjQ6MjUpLiAgV2hlbiBwYWlyZWQgZW5kIHJlYWRzIHdlcmUgYXZhaWxhYmxlLCBvbmx5IHRoZQogICBwcm9wZXJseSBwYWlyZWQgd2VyZSB1c2VkIGZvciB0aGUgdGFza3MgdGhhdCBmb2xsb3cuICBUaGUgZ2VuZXJhdGVkCiAgIHNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlIHdoaWNoIHBlcmZvcm1lZCB0aGlzIHRyaW1taW5nIGhhdmUgdGhlIHByZWZpeAogICDigJgwNXRyaW3igJkuCjIuIFJlYWRzIHdlcmUgcGFzc2VkIHRvIGZhc3RxYyB1c2luZyB0aGUgZGVmYXVsdCBwYXJhbWV0ZXJzIHRvIHF1ZXJ5CiAgIHJlYWQgcXVhbGl0eSwgcmVtYWluaW5nIGFkYXB0ZXIgY29udGVudCwgYW5kIGFzIGFuIGluaXRpYWwgc3VydmV5IGZvcgogICBjb250YW1pbmFudHMuICBUaGUgZ2VuZXJhdGVkIHNjcmlwdHMgd2hpY2ggcGVyZm9ybWVkIHRoaXMgaGF2ZSB0aGUKICAgcHJlZml4IOKAmDA2ZmFzdHFj4oCZCjMuIEV2ZXJ5IHNhbXBsZSB3YXMgcGFzc2VkIHRvIGtyYWtlbjIgYWdhaW5zdCBpdHMgY29tcHJlaGVuc2l2ZQogICDigJhzdGFuZGFyZOKAmSBhbmQg4oCYdmlydXPigJkgZGF0YWJhc2VzLCB1cGRhdGVkIDIwMjEvMDYgaW4gb3JkZXIgdG8gcXVlcnkKICAgZm9yIHB1dGF0aXZlIGNvbnRhbWluYW50cyBhbmQgcG90ZW50aWFsbHkgaW50ZXJlc3RpbmcgdmlyYWwKICAgc2VxdWVuY2VzLiAgVGhlIHNjcmlwdHMgd2hpY2ggcGVyZm9ybWVkIHRoaXMgaGF2ZSB0aGUgcHJlZml4CiAgIOKAmDExa3Jha2Vu4oCZLgo0LiBTYW1wbGVzIHdlcmUgcGFzc2VkIHRvIGhpc2F0MiBhZ2FpbnN0IHRoZSBoZzM4IHJlbGVhc2UgMTAwIGh1bWFuCiAgIGdlbm9tZSB3aXRoIHRoZSBkZWZhdWx0IG9wdGlvbnMgYXMgd2VsbCBhcyB0aGUgTGVpc2htYW5pYSBwYW5hbWVuc2lzCiAgIE1IT00vQ09MIHJlbGVhc2UgNDYgaW4gc2VyaWFsLiAgVGhlIHNjcmlwdHMgd2hpY2ggcGVyZm9ybWVkIHRoZXNlCiAgIG9wZXJhdGlvbnMgaGF2ZSB0aGUgcHJlZml4ZXMg4oCYMTVoaXNhdDJfaGczOF8xMDDigJkgYW5kCiAgIOKAmDE1aGlzYXQyX2xwYW5hbWVuc2lzX3Y0NuKAmSByZXNwZWN0aXZlbHkuCjUuIFRoZSByZXN1bHRpbmcgYWxpZ25tZW50cyB3ZXJlIGNvbnZlcnRlZCB0byB0aGUgYmluYXJ5LCBzb3J0ZWQsCiAgIGNvbXByZXNzZWQsIGFuZCBpbmRleGVkIGZvcm1hdCB2aWEgc2FtdG9vbHMuICBBZGRpdGlvbmFsIGZpbHRlcnMgd2VyZQogICBwZXJmb3JtZWQgdG8gZXh0cmFjdCBvbmx5IHRoZSBub24tdmFyaWFudCBhbGlnbm1lbnRzIC4gIFRoZSBzY3JpcHRzCiAgIHdoaWNoIHBlcmZvcm1lZCB0aGlzIGhhdmUgdGhlIHByZWZpeCDigJgxOXMyYl97Z2Vub21lfeKAmS4KNi4gVGhlc2Ugd2VyZSBjcm9zcyByZWZlcmVuY2VkIGFnYWluc3QgdGhlIHJlbGV2YW50IGZlYXR1cmUgZGF0YWJhc2VzIGluCiAgIG9yZGVyIHRvIGdlbmVyYXRlIGNvdW50IHRhYmxlcyBieSBnZW5lIHZpYSBodHNlcS4gIFRoZXNlIHNjcmlwdHMgaGF2ZQogICB0aGUgcHJlZml4IOKAmDIxaHRz4oCZLgo3LiBFYWNoIHNhbXBsZSB3YXMgcGFzc2VkIHRvIHNhbG1vbiBhZ2FpbnN0IHRoZSB0cmFuc2NyaXB0IGRhdGFiYXNlcyBmb3IKICAgaGczOCByZWxlYXNlIDEwMCwgTC4gcGFuYW1lbnNpcyByZWxlYXNlIDQ2LCBhbmQgYSBjb25jYXRlbmF0aW9uIG9mCiAgIHRoZSB0d28uICBUaGVzZSBzY3JpcHRzIGhhdmUgdGhlIHN1ZmZpeCDigJgzMHNhbF97Z2Vub21lfeKAmS4KOC4gQSByZWd1bGFyIGV4cHJlc3Npb24gc2VhcmNoIHdhcyBwZXJmb3JtZWQgZm9yIHRoZSBvYnNlcnZlZCBzZXQgb2YKICAgc3BsaWNlZCBsZWFkZXIgc2VxdWVuY2VzLiAgVGhlIHNlcXVlbmNlIOKAmEFHVFRUQ1RHVEFDVFRUQVRUR0figJkgcmF0aGVyCiAgIHRoYW4gdGhlIGVudGlyZSBTTCBzZXF1ZW5jZSB3YXMgc2VhcmNoZWQgdG8gYXZvaWQgcG90ZW50aWFsIFNMCiAgIHZhcmlhbnRzLiAgVGhlIHJlbGV2YW50IHNjcmlwdHMgaGF2ZSB0aGUgcHJlZml4IOKAmDUwc2xzZWFyY2jigJkuCgpHaXZlbiB0aGUgZmFjdCB0aGF0IHRoZXNlIHRhc2tzIHdlcmUgcGVyZm9ybWVkIG92ZXIgdGhlIGNvdXJzZSBvZiA0CnllYXJzLCBkdXJpbmcgd2hpY2ggdGltZSB3ZSBjaGFuZ2VkIHNlcXVlbmNpbmcgcGxhdGZvcm1zIGFuZApjb21wdXRhdGlvbmFsIGluZnJhc3RydWN0dXJlLCB0aGUgYWN0dWFsIHByZWZpeGVzL3N1ZmZpeGVzIG9mIHRoZQp2YXJpb3VzIHNjcmlwdHMgYW5kIG91dHB1dHMgYXJlIG5vdCBhcyBjb25zaXN0ZW50IGFzIEkgd291bGQgbGlrZS4KCiMjIyBUcmltbWluZyByYXcgcmVhZHMKCldpdGggdGhlIGFib3ZlIGNhdmVhdCBpbiBtaW5kLCBJIGFtIGNvcHkvcGFzdGluZyB0aGUgbGl0dGxlIHNoZWxsIGZyYWdtZW50cyBJCnVzZWQgd2hlbiB0cmltbWluZyB0aGUgc2FtcGxlczoKCmBgYHtiYXNoIHByZXByb2Nlc3NfZnJhZ21lbnQsIGV2YWw9RkFMU0V9CiMjIHRyaW0uc2gsIHRoaXMgYXNzdW1lcyBvbmUgd2lsbCBtYW51YWxseSBjZCBpbnRvIHRoZSBuZXcgc2FtcGxlJ3MgZGlyZWN0b3J5IGFuZCBydW4gLi4vdG1yY190cmltLnNoCiMjIEluIGFkZGl0aW9uLCBpdCBhc3N1bWVzIHRoYXQgdGhlIG5ldyBkYXRhIGZpbGVzIHdpbGwgcmVzaWRlIGluIHRoZSBkaXJlY3RvcnkgJ3VucHJvY2Vzc2VkLycuCmlucHV0PSQoL2Jpbi9scyAtZCB1bnByb2Nlc3NlZCB8IHRyICdcbicgJzonIHwgc2VkICdzLzokLy9nJykKZWNobyAiUnVubmluZyB0cmltb21hdGljIG9uICR7aW5wdXR9IgpjbWQ9ImN5b2EgLS1tZXRob2QgdHJpbSAtLWlucHV0ICR7aW5wdXR9IDI+PmN5b2FfdHJpbS5vdXQgMT4mMiAmIgplY2hvICIke2NtZH0iID4gY3lvYV90cmltLm91dAoke2NtZH0KYGBgCgpUaGUgZm9sbG93aW5nIGlzIGEgc2NyaXB0IHdoaWNoIGlzIGdlbmVyYXRlZCBieSB0aGUgYWJvdmUsIGFyYml0cmFyaWx5CmNob3NlbiBmcm9tIHNhbXBsZSBUTVJDMzAxNDAuICBJZiBhbnlvbmUgcmVhZHMgaXQgY2FyZWZ1bGx5LCBvbmUgbWlnaHQKbm90ZSB0aGF0IHRoaXMgc2FtcGxlIGlzIGZyb20gYmVmb3JlIEkgc3RhcnRlZCBkZXBvc2l0aW5nIG5ldyByYXcKcmVhZHMgaW50byB0aGUgJ3VucHJvY2Vzc2VkJyBkaXJlY3RvcnksIGFzIGEgcmVzdWx0IHRoZSBpbnB1dCByZWFkcwp3ZXJlIGluIHRoZSBjd2QuCgpgYGB7YmFzaCB0cmltX3NlcXVlbmNlX3NjcmlwdCwgZXZhbD1GQUxTRX0KIyEvdXNyL2Jpbi9lbnYgYmFzaAojU0JBVENIIC0tZXhwb3J0PUFMTAojU0JBVENIIC0tbWFpbC10eXBlPU5PTkUKI1NCQVRDSCAtLWNoZGlyPS9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbHBhbmFtZW5zaXNfdG1yY18yMDE5L3ByZXByb2Nlc3NpbmcvVE1SQzMwMTQwCiNTQkFUQ0ggLS1wYXJ0aXRpb249ZHBhcnQKI1NCQVRDSCAtLXFvcz13b3Jrc3RhdGlvbiAtLW5pY2U9MTAKI1NCQVRDSCAtLW5vZGVzPTEgLS1yZXF1ZXVlCiNTQkFUQ0ggLS10aW1lPTEwOjAwOjAwCiNTQkFUQ0ggLS1qb2ItbmFtZT0wMXRyaW1fVE1SQzMwMTQwX1MzX1IxXzAwMQojU0JBVENIIC0tbWVtPTQwRwojU0JBVENIIC0tY3B1cy1wZXItdGFzaz0zCiNTQkFUQ0ggLS1vdXRwdXQ9b3V0cHV0cy9sb2dzL3RyaW1fVE1SQzMwMTQwX1MzX1IxXzAwMS5zYmF0Y2hvdXQKCmVjaG8gIiMjIFN0YXJ0ZWQgL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9scGFuYW1lbnNpc190bXJjXzIwMTkvcHJlcHJvY2Vzc2luZy9UTVJDMzAxNDAvc2NyaXB0cy8wMXRyaW1fVE1SQzMwMTQwX1MzX1IxXzAwMS5zaCBhdCAkKGRhdGUpIG9uICQoaG9zdG5hbWUpIHdpdGggaWQgJHtTTFVSTV9KT0JJRH0uIiA+PiBvdXRwdXRzL2xvZy50eHQKCm1vZHVsZSBhZGQgdHJpbW9tYXRpYwoKIyMgVGhpcyBjYWxsIHRvIHRyaW1vbWF0aWMgcmVtb3ZlcyBpbGx1bWluYSBhbmQgZXBpY2VudHJlIGFkYXB0ZXJzIGZyb20gVE1SQzMwMTQwX1MzX1IxXzAwMS5mYXN0cS5nejpUTVJDMzAxNDBfUzNfUjJfMDAxLmZhc3RxLmd6LgojIyBJdCBhbHNvIHBlcmZvcm1zIGEgc2xpZGluZyB3aW5kb3cgcmVtb3ZhbCBvZiBhbnl0aGluZyB3aXRoIHF1YWxpdHkgPDI1OwojIyBjdXRhZGFwdCBwcm92aWRlcyBhbiBhbHRlcm5hdGl2ZSB0byB0aGlzIHRvb2wuCiMjIFRoZSBvcmlnaW5hbCBzZXF1ZW5jZSBkYXRhIGlzIHJlY29tcHJlc3NlZCBhbmQgc2F2ZWQgaW4gdGhlIHNlcXVlbmNlcy8gZGlyZWN0b3J5Lgpta2RpciAtcCBvdXRwdXRzLzAxdHJpbW9tYXRpYwojIyBOb3RlIHRoYXQgdHJpbW9tYXRpYyBwcmludHMgYWxsIG91dHB1dCBhbmQgZXJyb3JzIHRvIFNUREVSUiwgc28gc2VuZCBib3RoIHRvIG91dHB1dAp0cmltbW9tYXRpYyBQRSBcCiAgLXRocmVhZHMgMSBcCiAgLXBocmVkMzMgXAogIFRNUkMzMDE0MF9TM19SMV8wMDEuZmFzdHEuZ3ogVE1SQzMwMTQwX1MzX1IyXzAwMS5mYXN0cS5neiBcCiAgVE1SQzMwMTQwX1MzX1IxXzAwMS10cmltbWVkX3BhaXJlZC5mYXN0cSBUTVJDMzAxNDBfUzNfUjFfMDAxLXRyaW1tZWRfdW5wYWlyZWQuZmFzdHEgXAogIFRNUkMzMDE0MF9TM19SMl8wMDEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgVE1SQzMwMTQwX1MzX1IyXzAwMS10cmltbWVkX3VucGFpcmVkLmZhc3RxIFwKICAgSUxMVU1JTkFDTElQOi9jYmNiL3N3L1JlZEhhdC03LXg4Nl82NC9jb21tb24vbG9jYWwvcGVybC81LjM0L2xpYi9zaXRlX3BlcmwvNS4zNC4wL2F1dG8vc2hhcmUvZGlzdC9CaW8tQWR2ZW50dXJlL2dlbm9tZS9hZGFwdGVycy5mYToyOjIwOjEwOjI6a2VlcEJvdGhSZWFkcyBcCiAgU0xJRElOR1dJTkRPVzo0OjIwIE1JTkxFTjo0MCBcCiAgMT5vdXRwdXRzLzAxdHJpbW9tYXRpYy9UTVJDMzAxNDBfUzNfUjFfMDAxLXRyaW1vbWF0aWMub3V0IDI+JjEKZXhjZXB0ZWQ9JChncmVwICJFeGNlcHRpb24iIG91dHB1dHMvVE1SQzMwMTQwX1MzX1IxXzAwMS10cmltb21hdGljLm91dCkKIyMgVGhlIGZvbGxvd2luZyBpcyBpbiBjYXNlIHRoZSBpbGx1bWluYSBjbGlwcGluZyBmYWlscywgd2hpY2ggaXQgZG9lcyBpZiB0aGlzIGhhcyBhbHJlYWR5IGJlZW4gcnVuIEkgdGhpbmsuCmlmIFtbICIke2V4Y2VwdGVkfSIgIT0gIiIgXV07IHRoZW4KICB0cmltbW9tYXRpYyBQRSBcCiAgICAtdGhyZWFkcyAxIFwKICAgIC1waHJlZDMzIFwKICAgIFRNUkMzMDE0MF9TM19SMV8wMDEuZmFzdHEuZ3ogVE1SQzMwMTQwX1MzX1IyXzAwMS5mYXN0cS5neiBcCiAgICBUTVJDMzAxNDBfUzNfUjFfMDAxLXRyaW1tZWRfcGFpcmVkLmZhc3RxIFRNUkMzMDE0MF9TM19SMV8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgICBUTVJDMzAxNDBfUzNfUjJfMDAxLXRyaW1tZWRfcGFpcmVkLmZhc3RxIFRNUkMzMDE0MF9TM19SMl8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cSBcCiAgICAgU0xJRElOR1dJTkRPVzo0OjI1IE1JTkxFTjo1MFwKICAgIDE+b3V0cHV0cy8wMXRyaW1vbWF0aWMvVE1SQzMwMTQwX1MzX1IxXzAwMS10cmltb21hdGljLm91dCAyPiYxCmZpCnNsZWVwIDEwCm12IFRNUkMzMDE0MF9TM19SMV8wMDEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgVE1SQzMwMTQwX1MzX1IxXzAwMS10cmltbWVkLmZhc3RxCm12IFRNUkMzMDE0MF9TM19SMl8wMDEtdHJpbW1lZF9wYWlyZWQuZmFzdHEgVE1SQzMwMTQwX1MzX1IyXzAwMS10cmltbWVkLmZhc3RxCgojIyBSZWNvbXByZXNzIHRoZSB1bnBhaXJlZCByZWFkcywgdGhpcyBzaG91bGQgbm90IHRha2UgbG9uZy4KeHogLTllIC1mIFRNUkMzMDE0MF9TM19SMV8wMDEtdHJpbW1lZF91bnBhaXJlZC5mYXN0cQp4eiAtOWUgLWYgVE1SQzMwMTQwX1MzX1IyXzAwMS10cmltbWVkX3VucGFpcmVkLmZhc3RxCiMjIFJlY29tcHJlc3MgdGhlIHBhaXJlZCByZWFkcy4KeHogLTllIC1mIFRNUkMzMDE0MF9TM19SMV8wMDEtdHJpbW1lZC5mYXN0cQp4eiAtOWUgLWYgVE1SQzMwMTQwX1MzX1IyXzAwMS10cmltbWVkLmZhc3RxCmxuIC1zZiBUTVJDMzAxNDBfUzNfUjFfMDAxLXRyaW1tZWQuZmFzdHEueHogcjFfdHJpbW1lZC5mYXN0cS54egpsbiAtc2YgVE1SQzMwMTQwX1MzX1IyXzAwMS10cmltbWVkLmZhc3RxLnh6IHIyX3RyaW1tZWQuZmFzdHEueHoKCgojIyBUaGUgZm9sbG93aW5nIGxpbmVzIGdpdmUgc3RhdHVzIGNvZGVzIGFuZCBzb21lIGxvZ2dpbmcKZWNobyAiIyMgSm9iIHN0YXR1czogJD8gIiA+PiBvdXRwdXRzL2xvZy50eHQKZWNobyAiIyMgJChob3N0bmFtZSkgRmluaXNoZWQgJHtTTFVSTV9KT0JJRH0gMDF0cmltX1RNUkMzMDE0MF9TM19SMV8wMDEuc2ggYXQgJChkYXRlKSwgaXQgdG9vayAkKCggU0VDT05EUyAvIDYwICkpIG1pbnV0ZXMuIiA+PiBvdXRwdXRzL2xvZy50eHQKCndhbGx0aW1lPSQoc2NvbnRyb2wgc2hvdyBqb2IgIiR7U0xVUk1fSk9CSUR9IiB8IGdyZXAgUnVuVGltZSB8IHBlcmwgLUYnL1xzK3w9LycgLWxhbmUgJ3twcmludCAkRlsyXX0nKQplY2hvICIjIyMjIHdhbGx0aW1lIHVzZWQgYnkgJHtTTFVSTV9KT0JJRH0gd2FzOiAke3dhbGx0aW1lOi1udWxsfSIgPj4gb3V0cHV0cy9sb2cudHh0Cm1heG1lbT0kKHNzdGF0IC0tZm9ybWF0PU1heFZNU2l6ZSAtbiAiJHtTTFVSTV9KT0JJRH0uYmF0Y2giKQplY2hvICIjIyMjIG1heGltdW0gbWVtb3J5IHVzZWQgYnkgJHtTTFVSTV9KT0JJRH0gd2FzOiAke21heG1lbTotbnVsbH0iID4+IG91dHB1dHMvbG9nLnR4dAphdmVjcHU9JChzc3RhdCAtLWZvcm1hdD1BdmVDUFUgLW4gIiR7U0xVUk1fSk9CSUR9LmJhdGNoIikKZWNobyAiIyMjIyBhdmVyYWdlIGNwdSB1c2VkIGJ5ICR7U0xVUk1fSk9CSUR9IHdhczogJHthdmVjcHU6LW51bGx9IiA+PiBvdXRwdXRzL2xvZy50eHQKYGBgCgojIyMgTWFwcGluZyB0aGUgdHJpbW1lZCByZWFkcwoKVGhlcmUgaXMgYSBzaW1pbGFyIHNoZWxsIGZyYWdtZW50IHVzZWQgdG8gbWFwIHRoZXNlIHRyaW1tZWQgcmVhZHMKYWdhaW5zdCB0aGUgaGczOF8xMDAgZ2Vub21lL3RyYW5zY3JpcHRvbWUgYWxvbmcgd2l0aCB0aGUgcGFuYW1lbnNpcwpnZW5vbWU6CgpgYGB7YmFzaCBtYXBfZnJhZ21lbnQsIGV2YWw9RkFMU0V9CiMhL3Vzci9iaW4vZW52IGJhc2gKaW5wdXQ9JCgvYmluL2xzICpfdHJpbW1lZC5mYXN0cS54eiB8IHRyICdcbicgJzonIHwgc2VkICdzLzokLy9nJykKY3lvYSAtLXRhc2sgbWFwIC0tbWV0aG9kIGhpc2F0IC0tc3BlY2llcyBoZzM4XzEwMCAtLWdmZl90eXBlIGdlbmUgLS1nZmZfdGFnIGdlbmVfaWQgIFwKICAtLWlucHV0ICR7aW5wdXR9IDI+dG1yYzNfbWFwLm91dCAxPiYyICYKY3lvYSAtLXRhc2sgbWFwIC0tbWV0aG9kIGhpc2F0IC0tc3BlY2llcyBscGFuYW1lbnNpc192MzYgLS1nZmZfdHlwZSBnZW5lIC0tZ2ZmX3RhZyBJRCBcCiAgLS1pbnB1dCAke2lucHV0fSAyPj50bXJjM19tYXAub3V0IDE+JjIgJgpjeW9hIC0tdGFzayBtYXAgLS1tZXRob2Qgc2FsbW9uIC0tc3BlY2llcyBoZzM4XzEwMCBcCiAgICAgLS1pbnB1dCAke2lucHV0fSAyPnRtcmMzX3NhbG1vbi5vdXQgMT4mMiAmCmBgYAoKVGhlIGZvbGxvd2luZyBpcyB0aGUgcmVzdWx0aW5nIG1hcHBpbmcgc2NyaXB0IHRha2VuIGFyYml0cmFyaWx5IGZyb20Kc2FtcGxlIFRNUkMzMDIwNS4gIFRoZXJlIGFyZSBhIGZldyBhc3BlY3RzIG9mIHRoaXMgc2NyaXB0IHdoaWNoCmNoYW5nZWQgZnJvbSB0aGUgYmVnaW5uaW5nIHRvIGVuZCBvZiB0aGUgcHJvamVjdDogdGhlIHByZWZpeCAjCmNoYW5nZWQsIEkgYWRkZWQgc29tZSBsb2dpYyB0byBjaGVjayBpZiB0aGUgcmVxdWlzaXRlIHNvZnR3YXJlIChpbgp0aGlzIGNhc2UgaGlzYXQyL3NhbXRvb2xzL2h0c2VxKSBpcyBhbHJlYWR5IGluIHRoZSBwYXRoLCBhbmQgbG9hZCBpdAppZiBub3QuICBJIGFsc28gY2hhbmdlZCB0aGUgaHRzZXEgb3V0cHV0IGZpbGVuYW1lcyBzbGlnaHRseSBvdmVyIHRpbWUKdG8gdHJ5IHRvIG1ha2UgY2VydGFpbiB0aGF0IHRoZXkgYXJlIGNvbnNpc3RlbnQgYW5kIHRoYXQgaXQgaXMgZWFzeSB0bwppZGVudGlmeSB0aGUgaW1wb3J0YW50IHBhcmFtZXRlcnMganVzdCBmcm9tIHRoZSBvdXRwdXQgZmlsZW5hbWUuCgpgYGB7YmFzaCBoaXNhdF9tYXBfc2NyaXB0LCBldmFsPUZBTFNFfQojIS91c3IvYmluL2VudiBiYXNoCiNTQkFUQ0ggLS1jaGRpcj0vZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL2xwYW5hbWVuc2lzX3RtcmNfMjAxOS9wcmVwcm9jZXNzaW5nL1RNUkMzMDIwNQojU0JBVENIIC0tcGFydGl0aW9uPWRwYXJ0CiNTQkFUQ0ggLS1xb3M9d29ya3N0YXRpb24gLS1uaWNlPTEwCiNTQkFUQ0ggLS1ub2Rlcz0xIC0tcmVxdWV1ZQojU0JBVENIIC0tdGltZT0xMDowMDowMAojU0JBVENIIC0tam9iLW5hbWU9NDBoaXNhdDJfaGczOF8xMDBfZ2Vub21lCiNTQkFUQ0ggLS1tZW09NDhHCiNTQkFUQ0ggLS1jcHVzLXBlci10YXNrPTQKI1NCQVRDSCAtLW91dHB1dD1vdXRwdXRzL2xvZ3MvaGlzYXQyX2hnMzhfMTAwX2dlbm9tZS5zYmF0Y2hvdXQKCmVjaG8gIiMjIFN0YXJ0ZWQgL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9scGFuYW1lbnNpc190bXJjXzIwMTkvcHJlcHJvY2Vzc2luZy9UTVJDMzAyMDUvc2NyaXB0cy80MGhpc2F0Ml9oZzM4XzEwMF9nZW5vbWUuc2ggYXQgJChkYXRlKSBvbiAkKGhvc3RuYW1lKSB3aXRoIGlkICR7U0xVUk1fSk9CSUR9LiIgPj4gb3V0cHV0cy9sb2cudHh0Cgptb2R1bGUgYWRkIGhpc2F0MiBzYW10b29scyBodHNlcQoKIyMgVGhpcyBpcyBhIGhpc2F0MiBhbGlnbm1lbnQgb2YgIC0xIDwobGVzcyAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL2xwYW5hbWVuc2lzX3RtcmNfMjAxOS9wcmVwcm9jZXNzaW5nL1RNUkMzMDIwNS9yMV90cmltbWVkLmZhc3RxLnh6KSAtMiA8KGxlc3MgL2ZzL2NiY2ItbGFiL25lbHNheWVkL3NjcmF0Y2gvYXRiL3JuYXNlcS9scGFuYW1lbnNpc190bXJjXzIwMTkvcHJlcHJvY2Vzc2luZy9UTVJDMzAyMDUvcjJfdHJpbW1lZC5mYXN0cS54eikgIGFnYWluc3QgL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9pbmRleGVzL2hnMzhfMTAwCgpta2RpciAtcCBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwCnNsZWVwIDMKaGlzYXQyIC14IC9jYmNiaG9tZXMvYWJlbGV3L2xpYnJhcmllcy9nZW5vbWUvaW5kZXhlcy9oZzM4XzEwMCAgXAogIC1wIDQgXAogIC1xICAgLTEgPChsZXNzIC9mcy9jYmNiLWxhYi9uZWxzYXllZC9zY3JhdGNoL2F0Yi9ybmFzZXEvbHBhbmFtZW5zaXNfdG1yY18yMDE5L3ByZXByb2Nlc3NpbmcvVE1SQzMwMjA1L3IxX3RyaW1tZWQuZmFzdHEueHopIC0yIDwobGVzcyAvZnMvY2JjYi1sYWIvbmVsc2F5ZWQvc2NyYXRjaC9hdGIvcm5hc2VxL2xwYW5hbWVuc2lzX3RtcmNfMjAxOS9wcmVwcm9jZXNzaW5nL1RNUkMzMDIwNS9yMl90cmltbWVkLmZhc3RxLnh6KSAgXAogIC0tcGhyZWQzMyBcCiAgLS11bi1neiBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV91bmFsZGlzX2hnMzhfMTAwX2dlbm9tZS5mYXN0cSBcCiAgLS1hbC1neiBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9hbGRpc19oZzM4XzEwMF9nZW5vbWUuZmFzdHEgXAogIC0tdW4tY29uYy1neiBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV91bmFsY29uX2hnMzhfMTAwX2dlbm9tZS5mYXN0cSBcCiAgLS1hbC1jb25jLWd6IG91dHB1dHMvNDBoaXNhdDJfaGczOF8xMDAvVE1SQzMwMjA1X2FsY29uX2hnMzhfMTAwX2dlbm9tZS5mYXN0cSBcCiAgLVMgb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLnNhbSBcCiAgMj5vdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL2hpc2F0Ml9oZzM4XzEwMF9nZW5vbWVfVE1SQzMwMjA1LmVyciBcCiAgMT5vdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL2hpc2F0Ml9oZzM4XzEwMF9nZW5vbWVfVE1SQzMwMjA1Lm91dAoKCiMjIFRoZSBmb2xsb3dpbmcgbGluZXMgZ2l2ZSBzdGF0dXMgY29kZXMgYW5kIHNvbWUgbG9nZ2luZwplY2hvICIjIyBKb2Igc3RhdHVzOiAkPyAiID4+IG91dHB1dHMvbG9nLnR4dAplY2hvICIjIyAkKGhvc3RuYW1lKSBGaW5pc2hlZCAke1NMVVJNX0pPQklEfSA0MGhpc2F0Ml9oZzM4XzEwMF9nZW5vbWUuc2ggYXQgJChkYXRlKSwgaXQgdG9vayAkKCggU0VDT05EUyAvIDYwICkpIG1pbnV0ZXMuIiA+PiBvdXRwdXRzL2xvZy50eHQKCndhbGx0aW1lPSQoc2NvbnRyb2wgc2hvdyBqb2IgIiR7U0xVUk1fSk9CSUR9IiB8IGdyZXAgUnVuVGltZSB8IHBlcmwgLUYnL1xzK3w9LycgLWxhbmUgJ3twcmludCAkRlsyXX0nKQplY2hvICIjIyMjIHdhbGx0aW1lIHVzZWQgYnkgJHtTTFVSTV9KT0JJRH0gd2FzOiAke3dhbGx0aW1lOi1udWxsfSIgPj4gb3V0cHV0cy9sb2cudHh0Cm1heG1lbT0kKHNzdGF0IC0tZm9ybWF0PU1heFZNU2l6ZSAtbiAiJHtTTFVSTV9KT0JJRH0uYmF0Y2giKQplY2hvICIjIyMjIG1heGltdW0gbWVtb3J5IHVzZWQgYnkgJHtTTFVSTV9KT0JJRH0gd2FzOiAke21heG1lbTotbnVsbH0iID4+IG91dHB1dHMvbG9nLnR4dAphdmVjcHU9JChzc3RhdCAtLWZvcm1hdD1BdmVDUFUgLW4gIiR7U0xVUk1fSk9CSUR9LmJhdGNoIikKZWNobyAiIyMjIyBhdmVyYWdlIGNwdSB1c2VkIGJ5ICR7U0xVUk1fSk9CSUR9IHdhczogJHthdmVjcHU6LW51bGx9IiA+PiBvdXRwdXRzL2xvZy50eHQKYGBgCgpGcm9tIGhlcmUgb24gSSB3aWxsIHJlbW92ZSB0aGUgc3VmZml4IG9mIHRoZSBzY3JpcHQuICBIZXJlIGlzIHRoZSBzYW0KdG8gYmFtIGNvbnZlcnNpb24gc2NyaXB0IHdoaWNoIHdhcyBjcmVhdGVkIGJ5IGN5b2EuCgpgYGB7YmFzaCBzYW0yYmFtX3NjcmlwdCwgZXZhbD1GQUxTRX0KbW9kdWxlIGFkZCBzYW10b29scyBiYW10b29scwoKIyMgQ29udmVydGluZyB0aGUgdGV4dCBzYW0gdG8gYSBjb21wcmVzc2VkLCBzb3J0ZWQsIGluZGV4ZWQgYmFtZmlsZS4KIyMgQWxzbyBwcmludGluZyBhbGlnbm1lbnQgc3RhdGlzdGljcyB0byBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUuYmFtLnN0YXRzCiMjIFRoaXMgam9iIGRlcGVuZGVkIG9uOiAxMzM5OTUKCmVjaG8gIlN0YXJ0aW5nIHNhbXRvb2xzIgppZiAkKHRlc3QgISAtciBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUuc2FtKTsgdGhlbgogICAgZWNobyAiQ291bGQgbm90IGZpbmQgdGhlIHNhbXRvb2xzIGlucHV0IGZpbGUuIgogICAgZXhpdCAxCmZpCnNhbXRvb2xzIHZpZXcgLXUgLXQgL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9oZzM4XzEwMC5mYXN0YSBcCiAgLVMgb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLnNhbSAtbyBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUuYmFtICBcCiAgMj5vdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUuYmFtLmVyciAxPm91dHB1dHMvNDBoaXNhdDJfaGczOF8xMDAvVE1SQzMwMjA1X2hnMzhfMTAwX2dlbm9tZS5iYW0ub3V0ICYmIFwKCiAgc2FtdG9vbHMgc29ydCAtbCA5IG91dHB1dHMvNDBoaXNhdDJfaGczOF8xMDAvVE1SQzMwMjA1X2hnMzhfMTAwX2dlbm9tZS5iYW0gLW8gb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXNvcnRlZC5iYW0gXAogIDI+b3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXNvcnRlZC5lcnIgMT5vdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUtc29ydGVkLm91dCAmJiBcCiAgcm0gb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLmJhbSAmJiBcCiAgcm0gb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLnNhbSAmJiBcCiAgbXYgb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXNvcnRlZC5iYW0gb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLmJhbSAmJiAgc2FtdG9vbHMgaW5kZXggb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLmJhbQoKYmFtdG9vbHMgc3RhdHMgLWluIG91dHB1dHMvNDBoaXNhdDJfaGczOF8xMDAvVE1SQzMwMjA1X2hnMzhfMTAwX2dlbm9tZS5iYW0gMj5vdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUuYmFtLnN0YXRzIDE+JjIKCiMjIFRoZSBmb2xsb3dpbmcgd2lsbCBmYWlsIGlmIHRoaXMgaXMgc2luZ2xlLWVuZGVkLgpzYW10b29scyB2aWV3IC1iIC1mIDIgLW8gb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXBhaXJlZC5iYW0gb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLmJhbSAmJiBzYW10b29scyBpbmRleCBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUtcGFpcmVkLmJhbQpiYW10b29scyBzdGF0cyAtaW4gb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXBhaXJlZC5iYW0gMj5vdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUtcGFpcmVkLnN0YXRzIDE+JjIKYGBgCgpBbmQgdGhlIGNvdW50aW5nIHNjcmlwdCBmb3IgaHRzZXEuICBJIGNoYW5nZWQgdGhlIG91dHB1dCBmaWxlbmFtZSBmb3IKdGhpcyBzdGVwIG9uIG11bHRpcGxlIG9jY2FzaW9ucyBvdmVyIHRoZSBjb3Vyc2Ugb2Ygc2FtcGxlIGNvbGxlY3Rpb24uCgpgYGB7YmFzaCBodHNlcV9oZzM4XzEwMCwgZXZhbD1GQUxTRX0KbW9kdWxlIGFkZCBodHNlcQoKIyMgQ291bnRpbmcgdGhlIG51bWJlciBvZiBoaXRzIGluIG91dHB1dHMvNDBoaXNhdDJfaGczOF8xMDAvVE1SQzMwMjA1X2hnMzhfMTAwX2dlbm9tZS1wYWlyZWQuYmFtIGZvciBlYWNoIGZlYXR1cmUgZm91bmQgaW4gL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9oZzM4XzEwMC5nZmYKIyMgSXMgdGhpcyBzdHJhbmRlZD8gbm8uICBUaGUgZGVmYXVsdHMgb2YgaHRzZXEgYXJlOgojIyAgLS1vcmRlcj1uYW1lIC0taWRhdHRyPWdlbmVfaWQgLS1taW5hcXVhbD0xMCAtLXR5cGU9ZXhvbiAtLXN0cmFuZGVkPXllcyAtLW1vZGU9dW5pb24KCmh0c2VxLWNvdW50IFwKICAtcSAtZiBiYW0gLXMgbm8gIC0tdHlwZSBnZW5lICAtLWlkYXR0ciBnZW5lX2lkIFwKICBvdXRwdXRzLzQwaGlzYXQyX2hnMzhfMTAwL1RNUkMzMDIwNV9oZzM4XzEwMF9nZW5vbWUtcGFpcmVkLmJhbSBcCiAgL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9oZzM4XzEwMC5nZmYgXAogIDI+b3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXBhaXJlZF9hbGxfaGczOF8xMDBfc25vX2dlbmVfZ2VuZV9pZC5lcnIgXAogIDE+b3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXBhaXJlZF9hbGxfaGczOF8xMDBfc25vX2dlbmVfZ2VuZV9pZC5jb3VudCAmJiBcCiAgICB4eiAtZiAtOWUgb3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXBhaXJlZF9hbGxfaGczOF8xMDBfc25vX2dlbmVfZ2VuZV9pZC5jb3VudCAyPm91dHB1dHMvNDBoaXNhdDJfaGczOF8xMDAvVE1SQzMwMjA1X2hnMzhfMTAwX2dlbm9tZS1wYWlyZWRfYWxsX2hnMzhfMTAwX3Nub19nZW5lX2dlbmVfaWQuZXJyLnh6IDE+b3V0cHV0cy80MGhpc2F0Ml9oZzM4XzEwMC9UTVJDMzAyMDVfaGczOF8xMDBfZ2Vub21lLXBhaXJlZF9hbGxfaGczOF8xMDBfc25vX2dlbmVfZ2VuZV9pZC5jb3VudC54egpgYGAKClRoZSBzYW1lIGN5b2EgaW52b2NhdGlvbiBwcm9kdWNlZCBhIHNlcmllcyBvZiBzY3JpcHRzIHRvIGFnZ3Jlc3NpdmVseQpjb21wcmVzcyB0aGUgKHVuKW1hcHBlZCByZWFkcyBmcm9tIGhpc2F0MiBhbmQgcHJpbnQgb3V0IHNvbWUgc3VtbWFyeQpzdGF0aXN0aWNzIG9mIHRoZSBydW5zLgoKQ29udmVyc2VseSwgaGVyZSBpcyBhIHNhbG1vbiBzY3JpcHQgd2hpY2ggd2FzIHVzZWQgZm9yIHNhbXBsZQpUTVJDMzAxMjQgKHdpdGhvdXQgdGhlIHNsdXJtIHByZWZpeC9zdWZmaXgpOgoKYGBge2Jhc2ggc2FsbW9uX3NjcmlwdCwgZXZhbD1GQUxTRX0KbWtkaXIgLXAgb3V0cHV0cy9zYWxtb25faGczOF8xMDAgJiYgc2xlZXAgMyAmJiBcCnNhbG1vbiBxdWFudCAtaSAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2luZGV4ZXMvaGczOF8xMDBfc2FsbW9uX2luZGV4IFwKICAtbCBBIC0tZ2NCaWFzIC0tdmFsaWRhdGVNYXBwaW5ncyAgXAogICAtciA8KGxlc3MgcjFfdHJpbW1lZC5mYXN0cS5neikgIFwKICAtbyBvdXRwdXRzL3NhbG1vbl9oZzM4XzEwMCBcCiAgMj5vdXRwdXRzL3NhbG1vbl9oZzM4XzEwMC9zYWxtb24uZXJyIDE+b3V0cHV0cy9zYWxtb25faGczOF8xMDAvc2FsbW9uLm91dApgYGAK