1. References and resources

Reference

PLoS One. 2013;8(3):e59582. doi: 10.1371/journal.pone.0059582.

Machine

AWS r5.2xlarge and CentOS linux 7 on a Virtual Machine

2. Obtain and/or process genome, reference and index datasets

Make directory ~/genomeAndIndices/Rn/hisat

~/genomeAndIndices/Rn/hisat$ ls -l

-rw-r–r– 1 ubuntu ubuntu 915931500 Mar 13 2016 genome.1.ht2

-rw-r–r– 1 ubuntu ubuntu 682465208 Mar 13 2016 genome.2.ht2

-rw-r–r– 1 ubuntu ubuntu 1320164 Mar 13 2016 genome.3.ht2

-rw-r–r– 1 ubuntu ubuntu 682465202 Mar 13 2016 genome.4.ht2

-rw-r–r– 1 ubuntu ubuntu 1222786247 Mar 13 2016 genome.5.ht2

-rw-r–r– 1 ubuntu ubuntu 694908640 Mar 13 2016 genome.6.ht2

-rw-r–r– 1 ubuntu ubuntu 8 Mar 13 2016 genome.7.ht2

-rw-r–r– 1 ubuntu ubuntu 8 Mar 13 2016 genome.8.ht2

-rwxr-xr-x 1 ubuntu ubuntu 1341 Mar 17 2016 make_rn6.sh

3. Obtain and/process analysis datsets

Make directories

~/data/rnaseq/Rn/PLoS-One-8-e59582$ ls -l

drwxrwxr-x 2 ubuntu ubuntu 4096 Apr 10 02:48 f344_pfc_nicotine

drwxrwxr-x 2 ubuntu ubuntu 4096 Apr 10 03:28 f344_pfc_saline

Convert sra files to fastq files

f344_pfc_nicotine$ fastq-dump –split-3 SRR869032.sra –gzip

f344_pfc_nicotine$ fastq-dump –split-3 SRR869033.sra –gzip

f344_pfc_nicotine$ fastq-dump –split-3 SRR869034.sra –gzip

PLoS-One-8-e59582$ ls -l f344_pfc_nicotine/

-rw-rw-r– 1 ubuntu ubuntu 1918376826 Apr 7 13:08 SRR869032.sra

-rw-rw-r– 1 ubuntu ubuntu 1512702873 Apr 10 03:07 SRR869032_1.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 1565027421 Apr 10 03:07 SRR869032_2.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 1989086241 Apr 7 13:09 SRR869033.sra

-rw-rw-r– 1 ubuntu ubuntu 1559510818 Apr 10 03:11 SRR869033_1.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 1612258618 Apr 10 03:11 SRR869033_2.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 1978327667 Apr 7 13:10 SRR869034.sra

-rw-rw-r– 1 ubuntu ubuntu 1568979784 Apr 10 03:12 SRR869034_1.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 1615385331 Apr 10 03:12 SRR869034_2.fastq.gz

Download sra files (control/saline exposed rat PFC) to f344_pfc_saline directory

f344_pfc_saline$ fastq-dump –split-3 SRR869044.sra –gzip

f344_pfc_saline$ fastq-dump –split-3 SRR869045.sra –gzip

f344_pfc_saline$ fastq-dump –split-3 SRR869046.sra –gzip

PLoS-One-8-e59582$ ls -l f344_pfc_saline/

-rw-rw-r– 1 ubuntu ubuntu 2681330074 Apr 7 12:59 SRR869044.sra

-rw-rw-r– 1 ubuntu ubuntu 2119745955 Apr 10 03:10 SRR869044_1.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 2202580482 Apr 10 03:10 SRR869044_2.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 2709383194 Apr 7 13:01 SRR869045.sra

-rw-rw-r– 1 ubuntu ubuntu 2103892097 Apr 10 03:12 SRR869045_1.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 2198363062 Apr 10 03:12 SRR869045_2.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 2614023328 Apr 7 13:02 SRR869046.sra

-rw-rw-r– 1 ubuntu ubuntu 2054942375 Apr 10 03:13 SRR869046_1.fastq.gz

-rw-rw-r– 1 ubuntu ubuntu 2138446269 Apr 10 03:13 SRR869046_2.fastq.gz

4. Hisat alignment of nicotine treated samples

~/results/rnaseq/Rn/hisat_rat$ hisat2 -p 8 --rna-strandness RF --dta -x ~/genomeAndIndices/Rn/hisat/genome -p 8 -1 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_nicotine/SRR869032_1.fastq.gz -2 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_nicotine/SRR869032_2.fastq.gz -S pfc_nicotine_1.sam --summary-file pfc_nicotine_1_alignStats.txt
28929485 reads; of these:
  28929485 (100.00%) were paired; of these:
    5234698 (18.09%) aligned concordantly 0 times
    22040215 (76.19%) aligned concordantly exactly 1 time
    1654572 (5.72%) aligned concordantly >1 times
    ----
    5234698 pairs aligned concordantly 0 times; of these:
      202195 (3.86%) aligned discordantly 1 time
    ----
    5032503 pairs aligned 0 times concordantly or discordantly; of these:
      10065006 mates make up the pairs; of these:
        7450169 (74.02%) aligned 0 times
        2328861 (23.14%) aligned exactly 1 time
        285976 (2.84%) aligned >1 times
87.12% overall alignment rate
~/results/rnaseq/Rn/hisat_rat$ hisat2 -p 8 --rna-strandness RF --dta -x ~/genomeAndIndices/Rn/hisat/genome -p 8 -1 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_nicotine/SRR869033_1.fastq.gz -2 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_nicotine/SRR869033_2.fastq.gz -S pfc_nicotine_2.sam --summary-file pfc_nicotine_2_alignStats.txt
30057458 reads; of these:
  30057458 (100.00%) were paired; of these:
    5894947 (19.61%) aligned concordantly 0 times
    22432973 (74.63%) aligned concordantly exactly 1 time
    1729538 (5.75%) aligned concordantly >1 times
    ----
    5894947 pairs aligned concordantly 0 times; of these:
      195135 (3.31%) aligned discordantly 1 time
    ----
    5699812 pairs aligned 0 times concordantly or discordantly; of these:
      11399624 mates make up the pairs; of these:
        8870697 (77.82%) aligned 0 times
        2245816 (19.70%) aligned exactly 1 time
        283111 (2.48%) aligned >1 times
85.24% overall alignment rate
 ~/results/rnaseq/Rn/hisat_rat$ hisat2 -p 8 --rna-strandness RF --dta -x ~/genomeAndIndices/Rn/hisat/genome -p 8 -1 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_nicotine/SRR869033_1.fastq.gz -2 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_nicotine/SRR869033_2.fastq.gz -S pfc_nicotine_3.sam --summary-file pfc_nicotine_3_alignStats.txt
30057458 reads; of these:
  30057458 (100.00%) were paired; of these:
    5894947 (19.61%) aligned concordantly 0 times
    22432973 (74.63%) aligned concordantly exactly 1 time
    1729538 (5.75%) aligned concordantly >1 times
    ----
    5894947 pairs aligned concordantly 0 times; of these:
      195135 (3.31%) aligned discordantly 1 time
    ----
    5699812 pairs aligned 0 times concordantly or discordantly; of these:
      11399624 mates make up the pairs; of these:
        8870697 (77.82%) aligned 0 times
        2245816 (19.70%) aligned exactly 1 time
        283111 (2.48%) aligned >1 times
85.24% overall alignment rate

~/results/rnaseq/Rn/hisat_rat$ ls -l

-rw-rw-r– 1 ubuntu ubuntu 14838204512 Apr 11 04:04 pfc_nicotine_1.sam

-rw-rw-r– 1 ubuntu ubuntu 636 Apr 11 04:04 pfc_nicotine_1_alignStats.txt

-rw-rw-r– 1 ubuntu ubuntu 15315339149 Apr 11 04:06 pfc_nicotine_2.sam

-rw-rw-r– 1 ubuntu ubuntu 636 Apr 11 04:06 pfc_nicotine_2_alignStats.txt

-rw-rw-r– 1 ubuntu ubuntu 15315339149 Apr 11 04:07 pfc_nicotine_3.sam

-rw-rw-r– 1 ubuntu ubuntu 636 Apr 11 04:07 pfc_nicotine_3_alignStats.txt

5. Hisat alignment of saline treated samples

~/results/rnaseq/Rn/hisat_rat$ hisat2 -p 8 --rna-strandness RF --dta -x ~/genomeAndIndices/Rn/hisat/genome -p 8 -1 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_saline/SRR869044_1.fastq.gz -2 ~/data/rnaseq/Rn/PLoS-One-8-e59582/f344_pfc_saline/SRR869044_2.fastq.gz -S pfc_saline_1.sam --summary-file pfc_saline_1_alignStats.txt
41584891 reads; of these:
  41584891 (100.00%) were paired; of these:
    6989893 (16.81%) aligned concordantly 0 times
    32175699 (77.37%) aligned concordantly exactly 1 time
    2419299 (5.82%) aligned concordantly >1 times
    ----
    6989893 pairs aligned concordantly 0 times; of these:
      286173 (4.09%) aligned discordantly 1 time
    ----
    6703720 pairs aligned 0 times concordantly or discordantly; of these:
      13407440 mates make up the pairs; of these:
        9651125 (71.98%) aligned 0 times
        3345545 (24.95%) aligned exactly 1 time
        410770 (3.06%) aligned >1 times
88.40% overall alignment rate

~/results/rnaseq/Rn/hisat_rat$ bash hisat.sh

40866035 reads; of these:
  40866035 (100.00%) were paired; of these:
    8541201 (20.90%) aligned concordantly 0 times
    30095075 (73.64%) aligned concordantly exactly 1 time
    2229759 (5.46%) aligned concordantly >1 times
    ----
    8541201 pairs aligned concordantly 0 times; of these:
      288626 (3.38%) aligned discordantly 1 time
    ----
    8252575 pairs aligned 0 times concordantly or discordantly; of these:
      16505150 mates make up the pairs; of these:
        12941288 (78.41%) aligned 0 times
        3176429 (19.25%) aligned exactly 1 time
        387433 (2.35%) aligned >1 times
84.17% overall alignment rate

~/results/rnaseq/Rn/hisat_rat$ bash hisat.sh

39370935 reads; of these:
  39370935 (100.00%) were paired; of these:
    6881431 (17.48%) aligned concordantly 0 times
    30167116 (76.62%) aligned concordantly exactly 1 time
    2322388 (5.90%) aligned concordantly >1 times
    ----
    6881431 pairs aligned concordantly 0 times; of these:
      266341 (3.87%) aligned discordantly 1 time
    ----
    6615090 pairs aligned 0 times concordantly or discordantly; of these:
      13230180 mates make up the pairs; of these:
        9648395 (72.93%) aligned 0 times
        3185174 (24.08%) aligned exactly 1 time
        396611 (3.00%) aligned >1 times
87.75% overall alignment rate

~/results/rnaseq/Rn/hisat_rat$ ls -l

-rw-rw-r– 1 ubuntu ubuntu 21466504794 Apr 11 03:14 pfc_saline_1.sam

-rw-rw-r– 1 ubuntu ubuntu 636 Apr 11 03:14 pfc_saline_1_alignStats.txt

-rw-rw-r– 1 ubuntu ubuntu 20624784869 Apr 11 03:31 pfc_saline_2.sam

-rw-rw-r– 1 ubuntu ubuntu 637 Apr 11 03:31 pfc_saline_2_alignStats.txt

-rw-rw-r– 1 ubuntu ubuntu 20261146118 Apr 11 03:37 pfc_saline_3.sam

-rw-rw-r– 1 ubuntu ubuntu 636 Apr 11 03:37 pfc_saline_3_alignStats.txt

6. Convert SAM files to BAM files

~/results/rnaseq/Rn/hisat_rat$ samtools view -Su pfc_saline_1.sam | samtools sort -o aligned_bam/pfc_saline_1.bam

[bam_sort_core] merging from 38 files…

~/results/rnaseq/Rn/hisat_rat$ samtools view -Su pfc_saline_2.sam | samtools sort -o aligned_bam/pfc_saline_2.bam

[bam_sort_core] merging from 37 files…

~/results/rnaseq/Rn/hisat_rat$ samtools view -Su pfc_saline_3.sam | samtools sort -o aligned_bam/pfc_saline_3.bam

[bam_sort_core] merging from 36 files…

~/results/rnaseq/Rn/hisat_rat$ samtools view -Su pfc_nicotine_1.sam | samtools sort -o aligned_bam/pfc_nicotine_1.bam

[bam_sort_core] merging from 27 files…

~/results/rnaseq/Rn/hisat_rat$ samtools view -Su pfc_nicotine_2.sam | samtools sort -o aligned_bam/pfc_nicotine_2.bam

[bam_sort_core] merging from 28 files…

~/results/rnaseq/Rn/hisat_rat$ samtools view -Su pfc_nicotine_3.sam | samtools sort -o aligned_bam/pfc_nicotine_3.bam

[bam_sort_core] merging from 28 files…

Directory contents

~/results/rnaseq/Rn/hisat_rat$ ls -l aligned_bam/

-rw-rw-r– 1 ubuntu ubuntu 2759958955 Apr 11 04:51 pfc_nicotine_1.bam

-rw-rw-r– 1 ubuntu ubuntu 2828178844 Apr 11 04:53 pfc_nicotine_2.bam

-rw-rw-r– 1 ubuntu ubuntu 2828181083 Apr 11 04:53 pfc_nicotine_3.bam

-rw-rw-r– 1 ubuntu ubuntu 3801587158 Apr 11 05:00 pfc_saline_1.bam

-rw-rw-r– 1 ubuntu ubuntu 3782938510 Apr 11 05:00 pfc_saline_2.bam

-rw-rw-r– 1 ubuntu ubuntu 3713539755 Apr 11 04:59 pfc_saline_3.bam

7. Stringtie processing

Convert BAM files to GTF files

 ~/hisat_rat$ stringtie aligned_bam/pfc_saline_1.bam -p 8 --rf -o assembled_transcripts/pfc_saline_1.gtf

 ~/hisat_rat$ stringtie aligned_bam/pfc_saline_2.bam -p 8 --rf -o assembled_transcripts/pfc_saline_2.gtf

 ~/hisat_rat$ stringtie aligned_bam/pfc_saline_3.bam -p 8 --rf -o assembled_transcripts/pfc_saline_3.gtf

 ~/hisat_rat$ stringtie aligned_bam/pfc_nicotine_1.bam -p 8 --rf -o assembled_transcripts/pfc_nicotine_1.gtf

 ~/hisat_rat$ stringtie aligned_bam/pfc_nicotine_2.bam -p 8 --rf -o assembled_transcripts/pfc_nicotine_2.gtf

 ~/hisat_rat$ stringtie aligned_bam/pfc_nicotine_3.bam -p 8 --rf -o assembled_transcripts/pfc_nicotine_3.gtf

~/results/rnaseq/Rn/hisat_rat$ ls -l assembled_transcripts/

-rw-rw-r– 1 ubuntu ubuntu 49647976 Apr 11 12:57 pfc_nicotine_1.gtf

-rw-rw-r– 1 ubuntu ubuntu 51156594 Apr 11 12:58 pfc_nicotine_2.gtf

-rw-rw-r– 1 ubuntu ubuntu 51156594 Apr 11 12:59 pfc_nicotine_3.gtf

-rw-rw-r– 1 ubuntu ubuntu 58630430 Apr 11 12:53 pfc_saline_1.gtf

-rw-rw-r– 1 ubuntu ubuntu 56885955 Apr 11 13:02 pfc_saline_2.gtf

-rw-rw-r– 1 ubuntu ubuntu 56568985 Apr 11 13:03 pfc_saline_3.gtf

Make a single GTF file for use in differential analysis (DE) using ballgown

~/hisat_rat$ ls assembled_transcripts/*.gtf > mergelist.txt

~/results/rnaseq/Rn/hisat_rat$ cat mergelist.txt

assembled_transcripts/pfc_nicotine_1.gtf
assembled_transcripts/pfc_nicotine_2.gtf
assembled_transcripts/pfc_nicotine_3.gtf
assembled_transcripts/pfc_saline_1.gtf
assembled_transcripts/pfc_saline_2.gtf
assembled_transcripts/pfc_saline_3.gtf

Assemble RNA-Seq alignments into potential transcripts

~/hisat_rat$ stringtie –merge -p 8 -o stringtie_merged.gtf mergelist.txt

~/results/rnaseq/Rn/hisat_rat$ head stringtie_merged.gtf


# stringtie --merge -p 8 -o stringtie_merged.gtf mergelist.txt

# StringTie version 1.3.5

chr1    StringTie   transcript  241681  241935  1000    -   .   gene_id "MSTRG.1"; transcript_id "MSTRG.1.1"; 
chr1    StringTie   exon    241681  241935  1000    -   .   gene_id "MSTRG.1"; transcript_id "MSTRG.1.1"; exon_number "1"; 
chr1    StringTie   transcript  242569  242801  1000    -   .   gene_id "MSTRG.2"; transcript_id "MSTRG.2.1"; 
chr1    StringTie   exon    242569  242801  1000    -   .   gene_id "MSTRG.2"; transcript_id "MSTRG.2.1"; exon_number "1"; 
chr1    StringTie   transcript  242608  242807  1000    +   .   gene_id "MSTRG.3"; transcript_id "MSTRG.3.1"; 
chr1    StringTie   exon    242608  242807  1000    +   .   gene_id "MSTRG.3"; transcript_id "MSTRG.3.1"; exon_number "1"; 
chr1    StringTie   transcript  1545794 1546230 1000    +   .   gene_id "MSTRG.4"; transcript_id "MSTRG.4.1"; 
chr1    StringTie   exon    1545794 1546230 1000    +   .   gene_id "MSTRG.4"; transcript_id "MSTRG.4.1"; exon_number "1"; 

Output Ballgown table files

StringTie v1.3.5 usage:

 -b enable output of Ballgown table files but these files will be created under the directory path given as <dir_path>
    
 -e only estimate the abundance of given reference transcripts (requires -G)
 
 -G reference annotation to use for guiding the assembly process (GTF/GFF3)
 
~/hisat_rat$ stringtie -e -B -p 8 -G stringtie_merged.gtf -o ballgown/pfc_01/pfc_saline_1.gtf aligned_bam/pfc_saline_1.bam

~/hisat_rat$ stringtie -e -B -p 8 -G stringtie_merged.gtf -o ballgown/pfc_02/pfc_saline_2.gtf aligned_bam/pfc_saline_2.bam

~/hisat_rat$ stringtie -e -B -p 8 -G stringtie_merged.gtf -o ballgown/pfc_03/pfc_saline_3.gtf aligned_bam/pfc_saline_3.bam

~/hisat_rat$ stringtie -e -B -p 8 -G stringtie_merged.gtf -o ballgown/pfc_04/pfc_nicotine_1.gtf aligned_bam/pfc_nicotine_1.bam

~/hisat_rat$ stringtie -e -B -p 8 -G stringtie_merged.gtf -o ballgown/pfc_05/pfc_nicotine_2.gtf aligned_bam/pfc_nicotine_2.bam

~/hisat_rat$ stringtie -e -B -p 8 -G stringtie_merged.gtf -o ballgown/pfc_06/pfc_nicotine_3.gtf aligned_bam/pfc_nicotine_3.bam

Directory and some file contents

~/results/rnaseq/Rn/hisat_rat$ ls -l ballgown

drwxr-xr-x 2 ubuntu ubuntu 4096 Apr 11 15:31 pfc_01

drwxr-xr-x 2 ubuntu ubuntu 4096 Apr 11 15:32 pfc_02

drwxr-xr-x 2 ubuntu ubuntu 4096 Apr 11 15:32 pfc_03

drwxr-xr-x 2 ubuntu ubuntu 4096 Apr 11 15:24 pfc_04

drwxr-xr-x 2 ubuntu ubuntu 4096 Apr 11 15:25 pfc_05

drwxr-xr-x 2 ubuntu ubuntu 4096 Apr 11 15:26 pfc_06

~/results/rnaseq/Rn/hisat_rat$ ls -l ballgown/pfc_01/

-rw-rw-r– 1 ubuntu ubuntu 5980883 Apr 11 15:31 e2t.ctab

-rw-rw-r– 1 ubuntu ubuntu 22798511 Apr 11 15:31 e_data.ctab

-rw-rw-r– 1 ubuntu ubuntu 5256005 Apr 11 15:31 i2t.ctab

-rw-rw-r– 1 ubuntu ubuntu 10782189 Apr 11 15:31 i_data.ctab

-rw-rw-r– 1 ubuntu ubuntu 73534031 Apr 11 15:31 pfc_saline_1.gtf

-rw-rw-r– 1 ubuntu ubuntu 4714746 Apr 11 15:31 t_data.ctab

~/results/rnaseq/Rn/hisat_rat$ head ballgown/pfc_01/pfc_saline_1.gtf

# stringtie -e -B -p 8 -G stringtie_merged.gtf -o ballgown/pfc_01/pfc_saline_1.gtf aligned_bam/pfc_saline_1.bam

# StringTie version 1.3.5

chr1    StringTie   transcript  241681  241935  1000    -   .   gene_id "MSTRG.1"; transcript_id "MSTRG.1.1"; cov "1.431373"; FPKM "0.458372"; TPM "1.421554";

chr1    StringTie   exon    241681  241935  1000    -   .   gene_id "MSTRG.1"; transcript_id "MSTRG.1.1"; exon_number "1"; cov "1.431373";

chr1    StringTie   transcript  242608  242807  1000    +   .   gene_id "MSTRG.3"; transcript_id "MSTRG.3.1"; cov "2.966750"; FPKM "0.950050"; TPM "2.946399";

chr1    StringTie   exon    242608  242807  1000    +   .   gene_id "MSTRG.3"; transcript_id "MSTRG.3.1"; exon_number "1"; cov "2.966750";

chr1    StringTie   transcript  242569  242801  1000    -   .   gene_id "MSTRG.2"; transcript_id "MSTRG.2.1"; cov "5.277897"; FPKM "1.690155"; TPM "5.241692";

chr1    StringTie   exon    242569  242801  1000    -   .   gene_id "MSTRG.2"; transcript_id "MSTRG.2.1"; exon_number "1"; cov "5.277897";

chr1    StringTie   transcript  1545794 1546230 1000    +   .   gene_id "MSTRG.4"; transcript_id "MSTRG.4.1"; cov "2.942792"; FPKM "0.942378"; TPM "2.922605";

chr1    StringTie   exon    1545794 1546230 1000    +   .   gene_id "MSTRG.4"; transcript_id "MSTRG.4.1"; exon_number "1"; cov "2.942792";

~/results/rnaseq/Rn/hisat_rat$ head -n 5 ballgown/pfc_01/e_data.ctab

e_id    chr strand  start   end rcount  ucount  mrcount cov cov_sd  mcov    mcov_sd
1   chr1    -   241681  241935  20  2   8.13    3.4275  2.4974  1.1137  1.0974
2   chr1    -   242569  242801  41  19  24.95   8.6395  6.0872  4.8841  4.1833
3   chr1    +   242608  242807  24  8   12.38   5.4850  3.3511  2.6650  1.8097
4   chr1    +   1545794 1546230 36  16  26.00   4.0755  2.4366  2.6865  1.8992

~/results/rnaseq/Rn/hisat_rat$ head -n 5 ballgown/pfc_01/i_data.ctab

i_id    chr strand  start   end rcount  ucount  mrcount
1   chr1    -   1671444 1709226 4   4   4.00
2   chr1    -   1709388 1712447 154 154 154.00
3   chr1    -   1712590 1717434 138 138 138.00
4   chr1    -   1717561 1720411 144 144 144.00

~/results/rnaseq/Rn/hisat_rat$ head -n 5 ballgown/pfc_01/t_data.ctab

t_id    chr strand  start   end t_name          num_exons   length  gene_id gene_name   cov         FPKM
1   chr1    -   241681  241935  MSTRG.1.1   1           255 MSTRG.1 .           1.431373    0.458372
2   chr1    -   242569  242801  MSTRG.2.1   1           233 MSTRG.2 .           5.277897    1.690155
3   chr1    +   242608  242807  MSTRG.3.1   1           200 MSTRG.3 .           2.966750    0.950050
4   chr1    +   1545794 1546230 MSTRG.4.1   1           437 MSTRG.4 .           2.942792    0.942378

9. Ballgown analysis/ perform differential analysis using ballgown

Required libraries

library(ballgown); library(genefilter); library(dplyr); library(devtools); library(gplots)

Attaching package: 㤼㸱ballgown㤼㸲

The following object is masked from 㤼㸱package:base㤼㸲:

    structure


Attaching package: 㤼㸱dplyr㤼㸲

The following objects are masked from 㤼㸱package:ballgown㤼㸲:

    contains, expr, last

The following objects are masked from 㤼㸱package:stats㤼㸲:

    filter, lag

The following objects are masked from 㤼㸱package:base㤼㸲:

    intersect, setdiff, setequal, union


Attaching package: 㤼㸱gplots㤼㸲

The following object is masked from 㤼㸱package:stats㤼㸲:

    lowess

Convert the StringTie data to Ballgown data

data_directory=("ballgown/")
data_directory
[1] "ballgown/"
bg=ballgown(dataDir=data_directory, samplePattern="pfc", meas="all")
Tue Apr 23 22:19:41 2019
Tue Apr 23 22:19:41 2019: Reading linking tables
Tue Apr 23 22:19:42 2019: Reading intron data files
Tue Apr 23 22:19:45 2019: Merging intron data
Tue Apr 23 22:19:48 2019: Reading exon data files
Tue Apr 23 22:19:55 2019: Merging exon data
Tue Apr 23 22:19:56 2019: Reading transcript data files
Tue Apr 23 22:19:58 2019: Merging transcript data
Wrapping up the results
Tue Apr 23 22:19:58 2019
bg
ballgown instance with 55640 transcripts and 6 samples

Structure of the ballgown data and its components: Can be done in few different ways

names(structure(bg))
[1] "intron" "exon"   "trans" 
structure(bg)$exon
GRanges object with 301679 ranges and 2 metadata columns:
                         seqnames          ranges strand |        id transcripts
                            <Rle>       <IRanges>  <Rle> | <integer> <character>
       [1]                   chr1   241681-241935      - |         1           1
       [2]                   chr1   242569-242801      - |         2           2
       [3]                   chr1   242608-242807      + |         3           3
       [4]                   chr1 1545794-1546230      + |         4           4
       [5]                   chr1 1545794-1546231      - |         5           5
       ...                    ...             ...    ... .       ...         ...
  [301675] chrY_KL568157v1_random 3208681-3209783      - |    301675       55636
  [301676] chrY_KL568157v1_random 3219092-3219982      + |    301676       55637
  [301677] chrY_KL568157v1_random 3219092-3219985      - |    301677       55638
  [301678] chrY_KL568161v1_random 7188592-7190249      + |    301678       55639
  [301679] chrY_KL568161v1_random 7188598-7190160      - |    301679       55640
  -------
  seqinfo: 121 sequences from an unspecified genome; no seqlengths
structure(bg)$intron
GRanges object with 247640 ranges and 2 metadata columns:
           seqnames          ranges strand |        id   transcripts
              <Rle>       <IRanges>  <Rle> | <integer>   <character>
       [1]     chr1 1671444-1709226      - |         1            15
       [2]     chr1 1709388-1712447      - |         2 c(15, 17, 18)
       [3]     chr1 1712590-1717434      - |         3 c(15, 17, 18)
       [4]     chr1 1717561-1720411      - |         4 c(15, 17, 18)
       [5]     chr1 1720622-1722140      - |         5            15
       ...      ...             ...    ... .       ...           ...
  [247636]     chrY 1228283-1229180      + |    247636   55627:55629
  [247637]     chrY 1229305-1231811      + |    247637   55627:55629
  [247638]     chrY 1231860-1235052      + |    247638   55627:55629
  [247639]     chrY 1235111-1238311      + |    247639   55627:55629
  [247640]     chrY 1220424-1220824      + |    247640         55628
  -------
  seqinfo: 70 sequences from an unspecified genome; no seqlengths
structure(bg)$trans
GRangesList object of length 55640:
$1 
GRanges object with 1 range and 2 metadata columns:
      seqnames        ranges strand |        id transcripts
         <Rle>     <IRanges>  <Rle> | <integer> <character>
  [1]     chr1 241681-241935      - |         1           1

$2 
GRanges object with 1 range and 2 metadata columns:
      seqnames        ranges strand | id transcripts
  [1]     chr1 242569-242801      - |  2           2

$3 
GRanges object with 1 range and 2 metadata columns:
      seqnames        ranges strand | id transcripts
  [1]     chr1 242608-242807      + |  3           3

...
<55637 more elements>
-------
seqinfo: 121 sequences from an unspecified genome; no seqlengths
structure(bg)
$intron
GRanges object with 247640 ranges and 2 metadata columns:
           seqnames          ranges strand |        id   transcripts
              <Rle>       <IRanges>  <Rle> | <integer>   <character>
       [1]     chr1 1671444-1709226      - |         1            15
       [2]     chr1 1709388-1712447      - |         2 c(15, 17, 18)
       [3]     chr1 1712590-1717434      - |         3 c(15, 17, 18)
       [4]     chr1 1717561-1720411      - |         4 c(15, 17, 18)
       [5]     chr1 1720622-1722140      - |         5            15
       ...      ...             ...    ... .       ...           ...
  [247636]     chrY 1228283-1229180      + |    247636   55627:55629
  [247637]     chrY 1229305-1231811      + |    247637   55627:55629
  [247638]     chrY 1231860-1235052      + |    247638   55627:55629
  [247639]     chrY 1235111-1238311      + |    247639   55627:55629
  [247640]     chrY 1220424-1220824      + |    247640         55628
  -------
  seqinfo: 70 sequences from an unspecified genome; no seqlengths

$exon
GRanges object with 301679 ranges and 2 metadata columns:
                         seqnames          ranges strand |        id transcripts
                            <Rle>       <IRanges>  <Rle> | <integer> <character>
       [1]                   chr1   241681-241935      - |         1           1
       [2]                   chr1   242569-242801      - |         2           2
       [3]                   chr1   242608-242807      + |         3           3
       [4]                   chr1 1545794-1546230      + |         4           4
       [5]                   chr1 1545794-1546231      - |         5           5
       ...                    ...             ...    ... .       ...         ...
  [301675] chrY_KL568157v1_random 3208681-3209783      - |    301675       55636
  [301676] chrY_KL568157v1_random 3219092-3219982      + |    301676       55637
  [301677] chrY_KL568157v1_random 3219092-3219985      - |    301677       55638
  [301678] chrY_KL568161v1_random 7188592-7190249      + |    301678       55639
  [301679] chrY_KL568161v1_random 7188598-7190160      - |    301679       55640
  -------
  seqinfo: 121 sequences from an unspecified genome; no seqlengths

$trans
GRangesList object of length 55640:
$1 
GRanges object with 1 range and 2 metadata columns:
      seqnames        ranges strand |        id transcripts
         <Rle>     <IRanges>  <Rle> | <integer> <character>
  [1]     chr1 241681-241935      - |         1           1

$2 
GRanges object with 1 range and 2 metadata columns:
      seqnames        ranges strand | id transcripts
  [1]     chr1 242569-242801      - |  2           2

$3 
GRanges object with 1 range and 2 metadata columns:
      seqnames        ranges strand | id transcripts
  [1]     chr1 242608-242807      + |  3           3

...
<55637 more elements>
-------
seqinfo: 121 sequences from an unspecified genome; no seqlengths

Create metadata/phenotype data (pData) for the ballgown data to perform differential analysis (DE)

Three (3) replicates per group (saline or nicotine)

pData(bg) = data.frame(id=sampleNames(bg), group=rep(c(0,1), each=3))
pData(bg)

indices

exon_transcript_table = indexes(bg)$e2t
head(exon_transcript_table)
transcript_gene_table = indexes(bg)$t2g
head(transcript_gene_table)
phenotype_table = pData(bg)
phenotype_table

getexpr

FPKM values for each transcript

transcript_fpkm = texpr(bg, "FPKM")
head(transcript_fpkm)
  FPKM.pfc_01 FPKM.pfc_02 FPKM.pfc_03 FPKM.pfc_04 FPKM.pfc_05 FPKM.pfc_06
1    0.458372    0.910474    1.130689    0.624670    1.220050    1.220050
2    1.690155    1.697905    1.266853    1.423263    1.584901    1.584901
3    0.950050    1.330505    1.779630    2.121050    2.266203    2.266203
4    0.942378    1.360096    0.644549    1.238039    2.387492    2.387492
5    0.946076    1.113187    1.024247    1.794179    1.693284    1.693284
6    0.482096    0.767261    0.722560    0.634936    1.210922    1.210922

Coverage information for each transcript

transcript_cov = texpr(bg, "cov")
head(transcript_cov)
  cov.pfc_01 cov.pfc_02 cov.pfc_03 cov.pfc_04 cov.pfc_05 cov.pfc_06
1   1.431373   2.651634   3.311765   1.325490   2.628758   2.628758
2   5.277897   4.944921   3.710587   3.020029   3.414878   3.414878
3   2.966750   3.874917   5.212501   4.500667   4.882833   4.882833
4   2.942792   3.961098   1.887872   2.627002   5.144165   5.144165
5   2.954338   3.242009   3.000000   3.807078   3.648402   3.648402
6   1.505455   2.234545   2.116364   1.347273   2.609091   2.609091

Descriptive stats for each transcripts

whole_tx_table = texpr(bg, "all")
head(whole_tx_table)

Isolate multi-map-corrected average per-base read coverage for each exon

exon_mcov = eexpr(bg, "mcov")
head(exon_mcov)
  mcov.pfc_01 mcov.pfc_02 mcov.pfc_03 mcov.pfc_04 mcov.pfc_05 mcov.pfc_06
1      1.1137      2.2314      2.9922      0.9843      2.2627      2.2627
2      4.8841      4.6094      3.3047      2.7554      3.0644      3.0644
3      2.6650      3.5100      4.7700      3.9450      4.6250      4.6250
4      2.6865      3.7963      1.6293      2.3318      4.9428      4.9428
5      2.7808      3.1187      2.6804      3.5662      3.5799      3.5799
6      1.3818      2.1909      2.0382      1.3473      2.5236      2.5236

Isolate read count for each intron

junction_recount = iexpr(bg)
head(junction_recount)
  rcount.pfc_01 rcount.pfc_02 rcount.pfc_03 rcount.pfc_04 rcount.pfc_05 rcount.pfc_06
1             4             3             0             3             0             0
2           154           124           108           106            63            63
3           138           115           120           107            76            76
4           144           129           127            94            94            94
5             1             0             1             0             1             1
6             4             1             0             0             2             2

Isolate stats for intron

whole_intron_table = iexpr(bg, "all")
head(whole_intron_table)

Isolate gene level expression

gene_expression = gexpr(bg)
head(gene_expression)
            FPKM.pfc_01 FPKM.pfc_02 FPKM.pfc_03 FPKM.pfc_04 FPKM.pfc_05 FPKM.pfc_06
MSTRG.1        0.458372    0.910474    1.130689    0.624670    1.220050    1.220050
MSTRG.10       1.829527    1.922782    1.699969    1.873358    1.850956    1.850956
MSTRG.100      1.907345    2.092099    1.937360    2.462650    1.798789    1.798789
MSTRG.1000     4.583478    4.273662    4.324599    4.178418    4.420674    4.420674
MSTRG.10000    3.866415    3.776652    4.248838    3.407007    2.984207    2.984207
MSTRG.10001    2.672113    2.877509    2.262855    2.764531    2.257430    2.257430

Distribution of gene abundances (measured as FPKM values) across samples, colored by treatment): Boxplots for gene expression (by FPKM) for each sample

tropical= c('darkorange', 'dodgerblue', 'hotpink', 'limegreen', 'yellow')
palette(tropical)
fpkm = texpr(bg, meas="FPKM")
fpkm = log2(fpkm+1)
boxplot(fpkm,
        col=as.numeric(pData(bg)$group), 
        las=2, 
        ylab='log2(FPKM+1)')

Plot heatmap of transcript FPKM across all samples

cols = colorpanel(99, "blue", "black", "yellow")
fpkm = texpr(bg, meas="FPKM")
fpkm = log2(fpkm+1)
heatmap.2(fpkm, density.info = "none", 
          trace = "none", 
          margins = c(8, 5), 
          cexCol = 1.2, 
          keysize = 1,
          col = cols, 
          scale = "none")
Error: cannot allocate vector of size 11.5 Gb

Principal component analysis (PCA)

library(ggfortify)
Loading required package: ggplot2

Attaching package: 㤼㸱ggplot2㤼㸲

The following object is masked from 㤼㸱package:ballgown㤼㸲:

    expr
fpkm = texpr(bg, meas="FPKM")
fpkm = log2(fpkm+1)
pca = (prcomp(t(fpkm)))
autoplot(pca, data=pData(bg), colour = "group", label = T, label.label = "id" )

Additional data extraction

Extract indexes from ballgown object

names(indexes(bg))
[1] "e2t"      "i2t"      "t2g"      "bamfiles" "pData"   

Map exons to transcripts

head(indexes(bg)$e2t)

Map introns to transcripts

head(indexes(bg)$i2t)

Map transcripts to genes

head(indexes(bg)$t2g)

Mapping exons to transcripts and transcripts to gene

exon_transcript_table = indexes(bg)$e2t
transcript_gene_table = indexes(bg)$t2g
head(transcript_gene_table)

Test for differential expression by transcripts and genes: Identify and sort (increasing) the genes and the transcripts by their p-values

For transcripts

results_transcripts = stattest(bg, feature = "transcript", meas = "FPKM", covariate = "group", getFC = TRUE)
write.table(results_transcripts, file = "ballgown_transcript_results.txt", sep = "\t", quote = F, row.names = F)
results_transcripts <- arrange(results_transcripts, pval)
head(results_transcripts)

For genes

results_genes = stattest(bg, feature = "gene", meas = "FPKM", covariate = "group", getFC = TRUE)
write.table(results_genes, file = "ballgown_gene_results.txt", sep = "\t", quote = F, row.names = F)
results_genes <- arrange(results_genes, pval)
head(results_genes)

Plot the transcripts for a gene across samples

plotTranscripts(gene = "MSTRG.6551", gown = bg, samples = sampleNames(bg), meas = "FPKM", colorby = "transcript",
                main = "transcripts from gene MSTRG.6551")

Filter the data and reanalyze (do stattest)

Filter to remove low abundance genes

bg_filt = subset(bg,"rowVars(texpr(bg)) > 1",genomesubset=TRUE)
bg_filt  
ballgown instance with 18410 transcripts and 6 samples

stattest

filt_transcript_results = stattest(bg_filt, feature='transcript', meas='FPKM', covariate='group')
filt_results_transcripts <- arrange(filt_transcript_results, pval)
head(filt_results_transcripts)
filt_gene_results = stattest(bg_filt, feature='gene', meas='FPKM', covariate='group')
filt_results_genes <- arrange(filt_gene_results, pval)
head(filt_gene_results)

Add gene names and gene IDs to the results_transcripts data frame and sort the results from smallest p-value to largest:

filt_results_transcripts = data.frame(geneNames=ballgown::geneNames(bg_filt),
                                 geneIDs=ballgown::geneIDs(bg_filt), filt_transcript_results)
filt_results_transcripts = arrange(filt_results_transcripts,pval)
head(filt_results_transcripts)

Write the results to a CSV (comma-separated values) file that can be shared, distributed and further analyzed

        
write.csv(filt_results_transcripts, "rat_pfc_transcript_results.csv", row.names=FALSE)
write.csv(filt_results_genes, "rat_pfc_genes_results.csv", row.names=FALSE)

Identify transcripts and genes with a q-value of less than 0.05:

subset(filt_results_transcripts,filt_results_transcripts$qval<0.05)
subset(filt_results_genes,filt_results_genes$qval<0.05)

Further analysis: MSTRG.15358/transcript id=22657

plotTranscripts for a single saline sample (pfc_01)

plotTranscripts(gene='MSTRG.15358', 
                gown=bg, 
                samples='pfc_01', 
                meas='FPKM', 
                colorby='transcript', 
                main='transcripts from gene MSTRG.15358: sample pfc_01, FPKM')

plotTranscripts for saline treated samples (pfc_01, pfc_02, pfc_03)

plotTranscripts(gene='MSTRG.15358', 
                gown=bg, 
                samples=c("pfc_01", "pfc_02", "pfc_03"),
                meas='FPKM', 
                colorby='transcript', 
                main='transcripts from gene MSTRG.15358: samples pfc_01-pfc_03, FPKM')

plotTranscripts for nicotine treated samples (pfc_04, pfc_05, pfc_06)

plotTranscripts(gene='MSTRG.15358', 
                gown=bg, 
                samples=c("pfc_04", "pfc_05", "pfc_06"),
                meas='FPKM', 
                colorby='transcript', 
                main='transcripts from gene MSTRG.15358: samples pfc_04-pfc_06, FPKM')

plotMeans for groups (saline=0 and nicotine=1)

plotMeans('MSTRG.15358', bg, groupvar='group', meas='FPKM', colorby='transcript')

Further analysis: MSTRG.17264/transcript id = 25384

plotTranscripts for a single saline sample (pfc_01)

plotTranscripts(gene='MSTRG.17264', 
                gown=bg, 
                samples="pfc_01",
                meas='FPKM', 
                colorby='transcript', 
                main='transcripts from gene MSTRG.17264: samples pfc_01-pfc_03, FPKM')

plotTranscripts for saline treated samples (pfc_01, pfc_02, pfc_03)

plotTranscripts(gene='MSTRG.17264', 
                gown=bg, 
                samples=c("pfc_01", "pfc_02", "pfc_03"),
                meas='FPKM', 
                colorby='transcript', 
                main='transcripts from gene MSTRG.17264: samples pfc_01-pfc_03, FPKM')

plotTranscripts for nicotine treated samples (pfc_04, pfc_05, pfc_06)

plotTranscripts(gene='MSTRG.17264', 
                gown=bg, 
                samples=c("pfc_04", "pfc_05", "pfc_06"),
                meas='FPKM', 
                colorby='transcript', 
                main='transcripts from gene MSTRG.17264: samples pfc_04-pfc_06, FPKM')

plotMeans for groups (saline=0 and nicotine=1)

plotMeans('MSTRG.17264', bg, groupvar='group', meas='FPKM', colorby='transcript')

Plot the structure and expression levels in a sample of all transcripts that share the same gene locus

idx <- which(geneIDs(bg)=="MSTRG.17264")
idx
25382 25384 
25382 25384 

structure and expression levels in a sample (pfc_01) of all transcripts that share the gene locus 25382

plotTranscripts(ballgown::geneIDs(bg)[25382],
                bg,
                main=c('Gene MSTRG.17264 in sample pfc_01'),
                sample=c('pfc_01'))

structure and expression levels in a sample (pfc_01) of all transcripts that share the gene locus 25384

plotTranscripts(ballgown::geneIDs(bg)[25384],
                bg,
                main=c('Gene MSTRG.17264 in sample pfc_01'),
                sample=c('pfc_01'))

Another example: Plot the structure and expression levels in a sample of all transcripts that share the same gene locus

idx2 <- which(geneIDs(bg)=="MSTRG.15358")
idx2
22656 22657 
22656 22657 

structure and expression levels in a sample (pfc_01) of all transcripts that share the gene locus 22656

plotTranscripts(ballgown::geneIDs(bg)[22656],
                bg,
                main=c('Gene MSTRG.15358 in sample pfc_01'),
                sample=c('pfc_01'))

structure and expression levels in a sample (pfc_01) of all transcripts that share the gene locus 22657

plotTranscripts(ballgown::geneIDs(bg)[22657],
                bg,
                main=c('Gene MSTRG.15358 in sample pfc_01'),
                sample=c('pfc_01'))

Plots of individual transcripts across sample: MSTRG.15358

idx4 <- which(geneIDs(bg)=="MSTRG.15358")
idx4
22656 22657 
22656 22657 
ballgown::transcriptNames(bg)[22656]
          22656 
"MSTRG.15358.1" 
plot(fpkm[22656,] ~ pData(bg)$group,
     main=paste(ballgown::geneNames(bg)[22656],' : ', ballgown::transcriptNames(bg)[22656]), 
     pch=19,
     xlab="Treatment",
     ylab='log2(FPKM+1)')
points(fpkm[22656,] ~ jitter(as.numeric(pData(bg)$group)), col=as.numeric(pData(bg)$group))

plot(fpkm[22657,] ~ pData(bg)$group,
     main=paste(ballgown::geneNames(bg)[22657],' : ', ballgown::transcriptNames(bg)[22657]), 
     pch=19,
     xlab="Treatment",
     ylab='log2(FPKM+1)')
points(fpkm[22657,] ~ jitter(as.numeric(pData(bg)$group)), col=as.numeric(pData(bg)$group))

Plots of individual transcripts across sample: MSTRG.17264

idx3 <- which(geneIDs(bg)=="MSTRG.17264")
idx3
25382 25384 
25382 25384 
ballgown::transcriptNames(bg)[25382]
          25382 
"MSTRG.17264.1" 
plot(fpkm[25382,] ~ pData(bg)$group,
     main=paste(ballgown::geneNames(bg)[25382],' : ', ballgown::transcriptNames(bg)[25382]), 
     pch=19,
     xlab="Treatment",
     ylab='log2(FPKM+1)')
points(fpkm[25382,] ~ jitter(as.numeric(pData(bg)$group)), col=as.numeric(pData(bg)$group))

ballgown::transcriptNames(bg)[25384]
          25384 
"MSTRG.17264.2" 
plot(fpkm[25384,] ~ pData(bg)$group,
     main=paste(ballgown::geneNames(bg)[25384],' : ', ballgown::transcriptNames(bg)[25384]), 
     pch=19,
     xlab="Treatment",
     ylab='log2(FPKM+1)')
points(fpkm[25384,] ~ jitter(as.numeric(pData(bg)$group)), col=as.numeric(pData(bg)$group))

plot(fpkm[25384,] ~ pData(bg)$group,
     main=paste(ballgown::geneNames(bg)[25384],' : ', ballgown::transcriptNames(bg)[25384]), 
     pch=19,
     xlab="Treatment",
     ylab='log2(FPKM+1)')
points(fpkm[25384,] ~ jitter(as.numeric(pData(bg)$group)), col=as.numeric(pData(bg)$group))

Some additional plotting: Plot the average expression levels for all transcripts of a gene within different groups

plotMeans('MSTRG.8425', bg, groupvar='group', meas='FPKM', colorby='transcript')

plotMeans('MSTRG.8425', bg_filt, groupvar='group', meas='FPKM', colorby='transcript')
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -InfError in seq.default(min(gtrans$start), max(gtrans$end), by = 1) : 
  'from' must be a finite number
plotMeans('MSTRG.8851', bg, groupvar='group', meas='FPKM', colorby='transcript')

plotMeans('MSTRG.8851', bg_filt, groupvar='group', meas='FPKM', colorby='transcript')

LS0tDQp0aXRsZTogIkFuYWx5c2lzIG9mIGdlbmUgYW5kIGlzb2Zvcm0gZXhwcmVzc2lvbiBpbiBwcmVmcm9udGFsIGNvcnRleCAoUEZDKSBvZiByYXRzIGV4cG9zZWQgdG8gbmljb3RpbmU6IEhpc2F0LXN0cmluZ3RpZS1iYWxsZ293biBwaXBlbGluZSINCmF1dGhvcjogIkJoYWdpcmF0aGkgRGFzaCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KIyMgMS4gUmVmZXJlbmNlcyBhbmQgcmVzb3VyY2VzDQoNCiMjIyMgUmVmZXJlbmNlDQoNClBMb1MgT25lLiAyMDEzOzgoMyk6ZTU5NTgyLiBkb2k6IDEwLjEzNzEvam91cm5hbC5wb25lLjAwNTk1ODIuDQoNCiMjIyMgTWFjaGluZQ0KDQpBV1MgcjUuMnhsYXJnZSBhbmQgQ2VudE9TIGxpbnV4IDcgb24gYSBWaXJ0dWFsIE1hY2hpbmUNCg0KDQoNCg0KIyMgMi4gT2J0YWluIGFuZC9vciBwcm9jZXNzIGdlbm9tZSwgcmVmZXJlbmNlIGFuZCBpbmRleCBkYXRhc2V0cw0KDQoNCiMjIyBNYWtlIGRpcmVjdG9yeSB+L2dlbm9tZUFuZEluZGljZXMvUm4vaGlzYXQNCg0KDQojIyMjIGhpc2F0JCB3Z2V0IGZ0cDovL2Z0cC5jY2Iuamh1LmVkdS9wdWIvaW5mcGhpbG8vaGlzYXQyL2RhdGEvcm42LnRhci5neg0KDQoNCiMjIyMgfi9nZW5vbWVBbmRJbmRpY2VzL1JuL2hpc2F0JCBscyAtbA0KDQotcnctci0tci0tIDEgdWJ1bnR1IHVidW50dSAgOTE1OTMxNTAwIE1hciAxMyAgMjAxNiBnZW5vbWUuMS5odDINCg0KLXJ3LXItLXItLSAxIHVidW50dSB1YnVudHUgIDY4MjQ2NTIwOCBNYXIgMTMgIDIwMTYgZ2Vub21lLjIuaHQyDQoNCi1ydy1yLS1yLS0gMSB1YnVudHUgdWJ1bnR1ICAgIDEzMjAxNjQgTWFyIDEzICAyMDE2IGdlbm9tZS4zLmh0Mg0KDQotcnctci0tci0tIDEgdWJ1bnR1IHVidW50dSAgNjgyNDY1MjAyIE1hciAxMyAgMjAxNiBnZW5vbWUuNC5odDINCg0KLXJ3LXItLXItLSAxIHVidW50dSB1YnVudHUgMTIyMjc4NjI0NyBNYXIgMTMgIDIwMTYgZ2Vub21lLjUuaHQyDQoNCi1ydy1yLS1yLS0gMSB1YnVudHUgdWJ1bnR1ICA2OTQ5MDg2NDAgTWFyIDEzICAyMDE2IGdlbm9tZS42Lmh0Mg0KDQotcnctci0tci0tIDEgdWJ1bnR1IHVidW50dSAgICAgICAgICA4IE1hciAxMyAgMjAxNiBnZW5vbWUuNy5odDINCg0KLXJ3LXItLXItLSAxIHVidW50dSB1YnVudHUgICAgICAgICAgOCBNYXIgMTMgIDIwMTYgZ2Vub21lLjguaHQyDQoNCi1yd3hyLXhyLXggMSB1YnVudHUgdWJ1bnR1ICAgICAgIDEzNDEgTWFyIDE3ICAyMDE2IG1ha2Vfcm42LnNoDQoNCg0KDQoNCg0KDQojIyAzLiBPYnRhaW4gYW5kL3Byb2Nlc3MgYW5hbHlzaXMgZGF0c2V0cw0KDQojIyMgTWFrZSBkaXJlY3RvcmllcyANCg0KIyMjIyB+L2RhdGEvcm5hc2VxL1JuL1BMb1MtT25lLTgtZTU5NTgyJCBscyAtbA0KDQpkcnd4cnd4ci14IDIgdWJ1bnR1IHVidW50dSA0MDk2IEFwciAxMCAwMjo0OCBmMzQ0X3BmY19uaWNvdGluZQ0KDQpkcnd4cnd4ci14IDIgdWJ1bnR1IHVidW50dSA0MDk2IEFwciAxMCAwMzoyOCBmMzQ0X3BmY19zYWxpbmUNCg0KDQojIyMgRG93bmxvYWQgc3JhIGZpbGVzIChuaWNvdGluZSBleHBvc2VkIHJhdCBQRkMpIHRvIGYzNDRfcGZjX25pY290aW5lIGRpcmVjdG9yeQ0KDQoNCiMjIyMgZjM0NF9wZmNfbmljb3RpbmUkIHdnZXQgZnRwOi8vZnRwLXRyYWNlLm5jYmkubmloLmdvdi9zcmEvc3JhLWluc3RhbnQvcmVhZHMvQnlSdW4vc3JhL1NSUi9TUlI4NjkvU1JSODY5MDMyL1NSUjg2OTAzMi5zcmENCg0KIyMjIyBmMzQ0X3BmY19uaWNvdGluZSQgd2dldCBmdHA6Ly9mdHAtdHJhY2UubmNiaS5uaWguZ292L3NyYS9zcmEtaW5zdGFudC9yZWFkcy9CeVJ1bi9zcmEvU1JSL1NSUjg2OS9TUlI4NjkwMzMvU1JSODY5MDMzLnNyYQ0KDQojIyMjIGYzNDRfcGZjX25pY290aW5lJCB3Z2V0IGZ0cDovL2Z0cC10cmFjZS5uY2JpLm5paC5nb3Yvc3JhL3NyYS1pbnN0YW50L3JlYWRzL0J5UnVuL3NyYS9TUlIvU1JSODY5L1NSUjg2OTAzNC9TUlI4NjkwMzQuc3JhDQoNCg0KDQoNCiMjIyBDb252ZXJ0IHNyYSBmaWxlcyB0byBmYXN0cSBmaWxlcw0KDQojIyMjIGYzNDRfcGZjX25pY290aW5lJCBmYXN0cS1kdW1wIC0tc3BsaXQtMyBTUlI4NjkwMzIuc3JhIC0tZ3ppcA0KDQojIyMjIGYzNDRfcGZjX25pY290aW5lJCBmYXN0cS1kdW1wIC0tc3BsaXQtMyBTUlI4NjkwMzMuc3JhIC0tZ3ppcA0KDQojIyMjIGYzNDRfcGZjX25pY290aW5lJCBmYXN0cS1kdW1wIC0tc3BsaXQtMyBTUlI4NjkwMzQuc3JhIC0tZ3ppcA0KDQoNCg0KIyMjIyBQTG9TLU9uZS04LWU1OTU4MiQgbHMgLWwgZjM0NF9wZmNfbmljb3RpbmUvDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDE5MTgzNzY4MjYgQXByICA3IDEzOjA4IFNSUjg2OTAzMi5zcmENCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMTUxMjcwMjg3MyBBcHIgMTAgMDM6MDcgU1JSODY5MDMyXzEuZmFzdHEuZ3oNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMTU2NTAyNzQyMSBBcHIgMTAgMDM6MDcgU1JSODY5MDMyXzIuZmFzdHEuZ3oNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMTk4OTA4NjI0MSBBcHIgIDcgMTM6MDkgU1JSODY5MDMzLnNyYQ0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAxNTU5NTEwODE4IEFwciAxMCAwMzoxMSBTUlI4NjkwMzNfMS5mYXN0cS5neg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAxNjEyMjU4NjE4IEFwciAxMCAwMzoxMSBTUlI4NjkwMzNfMi5mYXN0cS5neg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAxOTc4MzI3NjY3IEFwciAgNyAxMzoxMCBTUlI4NjkwMzQuc3JhDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDE1Njg5Nzk3ODQgQXByIDEwIDAzOjEyIFNSUjg2OTAzNF8xLmZhc3RxLmd6DQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDE2MTUzODUzMzEgQXByIDEwIDAzOjEyIFNSUjg2OTAzNF8yLmZhc3RxLmd6DQoNCg0KIyMjIERvd25sb2FkIHNyYSBmaWxlcyAoY29udHJvbC9zYWxpbmUgZXhwb3NlZCByYXQgUEZDKSB0byBmMzQ0X3BmY19zYWxpbmUgZGlyZWN0b3J5DQoNCg0KIyMjIyBmMzQ0X3BmY19zYWxpbmUkIHdnZXQgZnRwOi8vZnRwLXRyYWNlLm5jYmkubmloLmdvdi9zcmEvc3JhLWluc3RhbnQvcmVhZHMvQnlSdW4vc3JhL1NSUi9TUlI4NjkvU1JSODY5MDQ0L1NSUjg2OTA0NC5zcmENCg0KIyMjIyBmMzQ0X3BmY19zYWxpbmUkIHdnZXQgZnRwOi8vZnRwLXRyYWNlLm5jYmkubmloLmdvdi9zcmEvc3JhLWluc3RhbnQvcmVhZHMvQnlSdW4vc3JhL1NSUi9TUlI4NjkvU1JSODY5MDQ1L1NSUjg2OTA0NS5zcmENCg0KIyMjIyBmMzQ0X3BmY19zYWxpbmUkIHdnZXQgZnRwOi8vZnRwLXRyYWNlLm5jYmkubmloLmdvdi9zcmEvc3JhLWluc3RhbnQvcmVhZHMvQnlSdW4vc3JhL1NSUi9TUlI4NjkvU1JSODY5MDQ2L1NSUjg2OTA0Ni5zcmENCg0KDQoNCg0KIyMjIyBmMzQ0X3BmY19zYWxpbmUkIGZhc3RxLWR1bXAgLS1zcGxpdC0zIFNSUjg2OTA0NC5zcmEgLS1nemlwDQoNCiMjIyMgZjM0NF9wZmNfc2FsaW5lJCBmYXN0cS1kdW1wIC0tc3BsaXQtMyBTUlI4NjkwNDUuc3JhIC0tZ3ppcA0KDQojIyMjIGYzNDRfcGZjX3NhbGluZSQgZmFzdHEtZHVtcCAtLXNwbGl0LTMgU1JSODY5MDQ2LnNyYSAtLWd6aXANCg0KDQoNCiMjIyMgUExvUy1PbmUtOC1lNTk1ODIkIGxzIC1sIGYzNDRfcGZjX3NhbGluZS8NCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMjY4MTMzMDA3NCBBcHIgIDcgMTI6NTkgU1JSODY5MDQ0LnNyYQ0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAyMTE5NzQ1OTU1IEFwciAxMCAwMzoxMCBTUlI4NjkwNDRfMS5mYXN0cS5neg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAyMjAyNTgwNDgyIEFwciAxMCAwMzoxMCBTUlI4NjkwNDRfMi5mYXN0cS5neg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAyNzA5MzgzMTk0IEFwciAgNyAxMzowMSBTUlI4NjkwNDUuc3JhDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDIxMDM4OTIwOTcgQXByIDEwIDAzOjEyIFNSUjg2OTA0NV8xLmZhc3RxLmd6DQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDIxOTgzNjMwNjIgQXByIDEwIDAzOjEyIFNSUjg2OTA0NV8yLmZhc3RxLmd6DQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDI2MTQwMjMzMjggQXByICA3IDEzOjAyIFNSUjg2OTA0Ni5zcmENCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMjA1NDk0MjM3NSBBcHIgMTAgMDM6MTMgU1JSODY5MDQ2XzEuZmFzdHEuZ3oNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMjEzODQ0NjI2OSBBcHIgMTAgMDM6MTMgU1JSODY5MDQ2XzIuZmFzdHEuZ3oNCg0KDQoNCg0KDQoNCg0KIyMgNC4gSGlzYXQgYWxpZ25tZW50IG9mIG5pY290aW5lIHRyZWF0ZWQgc2FtcGxlcw0KDQpgYGANCn4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBoaXNhdDIgLXAgOCAtLXJuYS1zdHJhbmRuZXNzIFJGIC0tZHRhIC14IH4vZ2Vub21lQW5kSW5kaWNlcy9Sbi9oaXNhdC9nZW5vbWUgLXAgOCAtMSB+L2RhdGEvcm5hc2VxL1JuL1BMb1MtT25lLTgtZTU5NTgyL2YzNDRfcGZjX25pY290aW5lL1NSUjg2OTAzMl8xLmZhc3RxLmd6IC0yIH4vZGF0YS9ybmFzZXEvUm4vUExvUy1PbmUtOC1lNTk1ODIvZjM0NF9wZmNfbmljb3RpbmUvU1JSODY5MDMyXzIuZmFzdHEuZ3ogLVMgcGZjX25pY290aW5lXzEuc2FtIC0tc3VtbWFyeS1maWxlIHBmY19uaWNvdGluZV8xX2FsaWduU3RhdHMudHh0DQoNCmBgYA0KDQpgYGANCjI4OTI5NDg1IHJlYWRzOyBvZiB0aGVzZToNCiAgMjg5Mjk0ODUgKDEwMC4wMCUpIHdlcmUgcGFpcmVkOyBvZiB0aGVzZToNCiAgICA1MjM0Njk4ICgxOC4wOSUpIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXMNCiAgICAyMjA0MDIxNSAoNzYuMTklKSBhbGlnbmVkIGNvbmNvcmRhbnRseSBleGFjdGx5IDEgdGltZQ0KICAgIDE2NTQ1NzIgKDUuNzIlKSBhbGlnbmVkIGNvbmNvcmRhbnRseSA+MSB0aW1lcw0KICAgIC0tLS0NCiAgICA1MjM0Njk4IHBhaXJzIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXM7IG9mIHRoZXNlOg0KICAgICAgMjAyMTk1ICgzLjg2JSkgYWxpZ25lZCBkaXNjb3JkYW50bHkgMSB0aW1lDQogICAgLS0tLQ0KICAgIDUwMzI1MDMgcGFpcnMgYWxpZ25lZCAwIHRpbWVzIGNvbmNvcmRhbnRseSBvciBkaXNjb3JkYW50bHk7IG9mIHRoZXNlOg0KICAgICAgMTAwNjUwMDYgbWF0ZXMgbWFrZSB1cCB0aGUgcGFpcnM7IG9mIHRoZXNlOg0KICAgICAgICA3NDUwMTY5ICg3NC4wMiUpIGFsaWduZWQgMCB0aW1lcw0KICAgICAgICAyMzI4ODYxICgyMy4xNCUpIGFsaWduZWQgZXhhY3RseSAxIHRpbWUNCiAgICAgICAgMjg1OTc2ICgyLjg0JSkgYWxpZ25lZCA+MSB0aW1lcw0KODcuMTIlIG92ZXJhbGwgYWxpZ25tZW50IHJhdGUNCg0KYGBgDQoNCg0KYGBgDQp+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgaGlzYXQyIC1wIDggLS1ybmEtc3RyYW5kbmVzcyBSRiAtLWR0YSAteCB+L2dlbm9tZUFuZEluZGljZXMvUm4vaGlzYXQvZ2Vub21lIC1wIDggLTEgfi9kYXRhL3JuYXNlcS9Sbi9QTG9TLU9uZS04LWU1OTU4Mi9mMzQ0X3BmY19uaWNvdGluZS9TUlI4NjkwMzNfMS5mYXN0cS5neiAtMiB+L2RhdGEvcm5hc2VxL1JuL1BMb1MtT25lLTgtZTU5NTgyL2YzNDRfcGZjX25pY290aW5lL1NSUjg2OTAzM18yLmZhc3RxLmd6IC1TIHBmY19uaWNvdGluZV8yLnNhbSAtLXN1bW1hcnktZmlsZSBwZmNfbmljb3RpbmVfMl9hbGlnblN0YXRzLnR4dA0KDQpgYGANCg0KDQpgYGANCjMwMDU3NDU4IHJlYWRzOyBvZiB0aGVzZToNCiAgMzAwNTc0NTggKDEwMC4wMCUpIHdlcmUgcGFpcmVkOyBvZiB0aGVzZToNCiAgICA1ODk0OTQ3ICgxOS42MSUpIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXMNCiAgICAyMjQzMjk3MyAoNzQuNjMlKSBhbGlnbmVkIGNvbmNvcmRhbnRseSBleGFjdGx5IDEgdGltZQ0KICAgIDE3Mjk1MzggKDUuNzUlKSBhbGlnbmVkIGNvbmNvcmRhbnRseSA+MSB0aW1lcw0KICAgIC0tLS0NCiAgICA1ODk0OTQ3IHBhaXJzIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXM7IG9mIHRoZXNlOg0KICAgICAgMTk1MTM1ICgzLjMxJSkgYWxpZ25lZCBkaXNjb3JkYW50bHkgMSB0aW1lDQogICAgLS0tLQ0KICAgIDU2OTk4MTIgcGFpcnMgYWxpZ25lZCAwIHRpbWVzIGNvbmNvcmRhbnRseSBvciBkaXNjb3JkYW50bHk7IG9mIHRoZXNlOg0KICAgICAgMTEzOTk2MjQgbWF0ZXMgbWFrZSB1cCB0aGUgcGFpcnM7IG9mIHRoZXNlOg0KICAgICAgICA4ODcwNjk3ICg3Ny44MiUpIGFsaWduZWQgMCB0aW1lcw0KICAgICAgICAyMjQ1ODE2ICgxOS43MCUpIGFsaWduZWQgZXhhY3RseSAxIHRpbWUNCiAgICAgICAgMjgzMTExICgyLjQ4JSkgYWxpZ25lZCA+MSB0aW1lcw0KODUuMjQlIG92ZXJhbGwgYWxpZ25tZW50IHJhdGUNCg0KYGBgDQoNCg0KYGBgDQogfi9yZXN1bHRzL3JuYXNlcS9Sbi9oaXNhdF9yYXQkIGhpc2F0MiAtcCA4IC0tcm5hLXN0cmFuZG5lc3MgUkYgLS1kdGEgLXggfi9nZW5vbWVBbmRJbmRpY2VzL1JuL2hpc2F0L2dlbm9tZSAtcCA4IC0xIH4vZGF0YS9ybmFzZXEvUm4vUExvUy1PbmUtOC1lNTk1ODIvZjM0NF9wZmNfbmljb3RpbmUvU1JSODY5MDMzXzEuZmFzdHEuZ3ogLTIgfi9kYXRhL3JuYXNlcS9Sbi9QTG9TLU9uZS04LWU1OTU4Mi9mMzQ0X3BmY19uaWNvdGluZS9TUlI4NjkwMzNfMi5mYXN0cS5neiAtUyBwZmNfbmljb3RpbmVfMy5zYW0gLS1zdW1tYXJ5LWZpbGUgcGZjX25pY290aW5lXzNfYWxpZ25TdGF0cy50eHQNCg0KYGBgDQoNCg0KYGBgDQozMDA1NzQ1OCByZWFkczsgb2YgdGhlc2U6DQogIDMwMDU3NDU4ICgxMDAuMDAlKSB3ZXJlIHBhaXJlZDsgb2YgdGhlc2U6DQogICAgNTg5NDk0NyAoMTkuNjElKSBhbGlnbmVkIGNvbmNvcmRhbnRseSAwIHRpbWVzDQogICAgMjI0MzI5NzMgKDc0LjYzJSkgYWxpZ25lZCBjb25jb3JkYW50bHkgZXhhY3RseSAxIHRpbWUNCiAgICAxNzI5NTM4ICg1Ljc1JSkgYWxpZ25lZCBjb25jb3JkYW50bHkgPjEgdGltZXMNCiAgICAtLS0tDQogICAgNTg5NDk0NyBwYWlycyBhbGlnbmVkIGNvbmNvcmRhbnRseSAwIHRpbWVzOyBvZiB0aGVzZToNCiAgICAgIDE5NTEzNSAoMy4zMSUpIGFsaWduZWQgZGlzY29yZGFudGx5IDEgdGltZQ0KICAgIC0tLS0NCiAgICA1Njk5ODEyIHBhaXJzIGFsaWduZWQgMCB0aW1lcyBjb25jb3JkYW50bHkgb3IgZGlzY29yZGFudGx5OyBvZiB0aGVzZToNCiAgICAgIDExMzk5NjI0IG1hdGVzIG1ha2UgdXAgdGhlIHBhaXJzOyBvZiB0aGVzZToNCiAgICAgICAgODg3MDY5NyAoNzcuODIlKSBhbGlnbmVkIDAgdGltZXMNCiAgICAgICAgMjI0NTgxNiAoMTkuNzAlKSBhbGlnbmVkIGV4YWN0bHkgMSB0aW1lDQogICAgICAgIDI4MzExMSAoMi40OCUpIGFsaWduZWQgPjEgdGltZXMNCjg1LjI0JSBvdmVyYWxsIGFsaWdubWVudCByYXRlDQoNCmBgYA0KDQoNCiMjIyMgfi9yZXN1bHRzL3JuYXNlcS9Sbi9oaXNhdF9yYXQkIGxzIC1sDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDE0ODM4MjA0NTEyIEFwciAxMSAwNDowNCBwZmNfbmljb3RpbmVfMS5zYW0NCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgICAgICAgICA2MzYgQXByIDExIDA0OjA0IHBmY19uaWNvdGluZV8xX2FsaWduU3RhdHMudHh0DQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDE1MzE1MzM5MTQ5IEFwciAxMSAwNDowNiBwZmNfbmljb3RpbmVfMi5zYW0NCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgICAgICAgICA2MzYgQXByIDExIDA0OjA2IHBmY19uaWNvdGluZV8yX2FsaWduU3RhdHMudHh0DQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDE1MzE1MzM5MTQ5IEFwciAxMSAwNDowNyBwZmNfbmljb3RpbmVfMy5zYW0NCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgICAgICAgICA2MzYgQXByIDExIDA0OjA3IHBmY19uaWNvdGluZV8zX2FsaWduU3RhdHMudHh0DQoNCg0KDQoNCg0KIyMgNS4gSGlzYXQgYWxpZ25tZW50IG9mIHNhbGluZSB0cmVhdGVkIHNhbXBsZXMNCg0KYGBgDQp+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgaGlzYXQyIC1wIDggLS1ybmEtc3RyYW5kbmVzcyBSRiAtLWR0YSAteCB+L2dlbm9tZUFuZEluZGljZXMvUm4vaGlzYXQvZ2Vub21lIC1wIDggLTEgfi9kYXRhL3JuYXNlcS9Sbi9QTG9TLU9uZS04LWU1OTU4Mi9mMzQ0X3BmY19zYWxpbmUvU1JSODY5MDQ0XzEuZmFzdHEuZ3ogLTIgfi9kYXRhL3JuYXNlcS9Sbi9QTG9TLU9uZS04LWU1OTU4Mi9mMzQ0X3BmY19zYWxpbmUvU1JSODY5MDQ0XzIuZmFzdHEuZ3ogLVMgcGZjX3NhbGluZV8xLnNhbSAtLXN1bW1hcnktZmlsZSBwZmNfc2FsaW5lXzFfYWxpZ25TdGF0cy50eHQNCg0KYGBgDQoNCmBgYA0KNDE1ODQ4OTEgcmVhZHM7IG9mIHRoZXNlOg0KICA0MTU4NDg5MSAoMTAwLjAwJSkgd2VyZSBwYWlyZWQ7IG9mIHRoZXNlOg0KICAgIDY5ODk4OTMgKDE2LjgxJSkgYWxpZ25lZCBjb25jb3JkYW50bHkgMCB0aW1lcw0KICAgIDMyMTc1Njk5ICg3Ny4zNyUpIGFsaWduZWQgY29uY29yZGFudGx5IGV4YWN0bHkgMSB0aW1lDQogICAgMjQxOTI5OSAoNS44MiUpIGFsaWduZWQgY29uY29yZGFudGx5ID4xIHRpbWVzDQogICAgLS0tLQ0KICAgIDY5ODk4OTMgcGFpcnMgYWxpZ25lZCBjb25jb3JkYW50bHkgMCB0aW1lczsgb2YgdGhlc2U6DQogICAgICAyODYxNzMgKDQuMDklKSBhbGlnbmVkIGRpc2NvcmRhbnRseSAxIHRpbWUNCiAgICAtLS0tDQogICAgNjcwMzcyMCBwYWlycyBhbGlnbmVkIDAgdGltZXMgY29uY29yZGFudGx5IG9yIGRpc2NvcmRhbnRseTsgb2YgdGhlc2U6DQogICAgICAxMzQwNzQ0MCBtYXRlcyBtYWtlIHVwIHRoZSBwYWlyczsgb2YgdGhlc2U6DQogICAgICAgIDk2NTExMjUgKDcxLjk4JSkgYWxpZ25lZCAwIHRpbWVzDQogICAgICAgIDMzNDU1NDUgKDI0Ljk1JSkgYWxpZ25lZCBleGFjdGx5IDEgdGltZQ0KICAgICAgICA0MTA3NzAgKDMuMDYlKSBhbGlnbmVkID4xIHRpbWVzDQo4OC40MCUgb3ZlcmFsbCBhbGlnbm1lbnQgcmF0ZQ0KDQpgYGANCg0KDQojIyMjIH4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBiYXNoIGhpc2F0LnNoIA0KDQpgYGANCjQwODY2MDM1IHJlYWRzOyBvZiB0aGVzZToNCiAgNDA4NjYwMzUgKDEwMC4wMCUpIHdlcmUgcGFpcmVkOyBvZiB0aGVzZToNCiAgICA4NTQxMjAxICgyMC45MCUpIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXMNCiAgICAzMDA5NTA3NSAoNzMuNjQlKSBhbGlnbmVkIGNvbmNvcmRhbnRseSBleGFjdGx5IDEgdGltZQ0KICAgIDIyMjk3NTkgKDUuNDYlKSBhbGlnbmVkIGNvbmNvcmRhbnRseSA+MSB0aW1lcw0KICAgIC0tLS0NCiAgICA4NTQxMjAxIHBhaXJzIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXM7IG9mIHRoZXNlOg0KICAgICAgMjg4NjI2ICgzLjM4JSkgYWxpZ25lZCBkaXNjb3JkYW50bHkgMSB0aW1lDQogICAgLS0tLQ0KICAgIDgyNTI1NzUgcGFpcnMgYWxpZ25lZCAwIHRpbWVzIGNvbmNvcmRhbnRseSBvciBkaXNjb3JkYW50bHk7IG9mIHRoZXNlOg0KICAgICAgMTY1MDUxNTAgbWF0ZXMgbWFrZSB1cCB0aGUgcGFpcnM7IG9mIHRoZXNlOg0KICAgICAgICAxMjk0MTI4OCAoNzguNDElKSBhbGlnbmVkIDAgdGltZXMNCiAgICAgICAgMzE3NjQyOSAoMTkuMjUlKSBhbGlnbmVkIGV4YWN0bHkgMSB0aW1lDQogICAgICAgIDM4NzQzMyAoMi4zNSUpIGFsaWduZWQgPjEgdGltZXMNCjg0LjE3JSBvdmVyYWxsIGFsaWdubWVudCByYXRlDQoNCmBgYA0KDQojIyMjIH4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBiYXNoIGhpc2F0LnNoIA0KDQpgYGANCjM5MzcwOTM1IHJlYWRzOyBvZiB0aGVzZToNCiAgMzkzNzA5MzUgKDEwMC4wMCUpIHdlcmUgcGFpcmVkOyBvZiB0aGVzZToNCiAgICA2ODgxNDMxICgxNy40OCUpIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXMNCiAgICAzMDE2NzExNiAoNzYuNjIlKSBhbGlnbmVkIGNvbmNvcmRhbnRseSBleGFjdGx5IDEgdGltZQ0KICAgIDIzMjIzODggKDUuOTAlKSBhbGlnbmVkIGNvbmNvcmRhbnRseSA+MSB0aW1lcw0KICAgIC0tLS0NCiAgICA2ODgxNDMxIHBhaXJzIGFsaWduZWQgY29uY29yZGFudGx5IDAgdGltZXM7IG9mIHRoZXNlOg0KICAgICAgMjY2MzQxICgzLjg3JSkgYWxpZ25lZCBkaXNjb3JkYW50bHkgMSB0aW1lDQogICAgLS0tLQ0KICAgIDY2MTUwOTAgcGFpcnMgYWxpZ25lZCAwIHRpbWVzIGNvbmNvcmRhbnRseSBvciBkaXNjb3JkYW50bHk7IG9mIHRoZXNlOg0KICAgICAgMTMyMzAxODAgbWF0ZXMgbWFrZSB1cCB0aGUgcGFpcnM7IG9mIHRoZXNlOg0KICAgICAgICA5NjQ4Mzk1ICg3Mi45MyUpIGFsaWduZWQgMCB0aW1lcw0KICAgICAgICAzMTg1MTc0ICgyNC4wOCUpIGFsaWduZWQgZXhhY3RseSAxIHRpbWUNCiAgICAgICAgMzk2NjExICgzLjAwJSkgYWxpZ25lZCA+MSB0aW1lcw0KODcuNzUlIG92ZXJhbGwgYWxpZ25tZW50IHJhdGUNCg0KYGBgDQoNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgbHMgLWwNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMjE0NjY1MDQ3OTQgQXByIDExIDAzOjE0IHBmY19zYWxpbmVfMS5zYW0NCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgICAgICAgICA2MzYgQXByIDExIDAzOjE0IHBmY19zYWxpbmVfMV9hbGlnblN0YXRzLnR4dA0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAyMDYyNDc4NDg2OSBBcHIgMTEgMDM6MzEgcGZjX3NhbGluZV8yLnNhbQ0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAgICAgICAgIDYzNyBBcHIgMTEgMDM6MzEgcGZjX3NhbGluZV8yX2FsaWduU3RhdHMudHh0DQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDIwMjYxMTQ2MTE4IEFwciAxMSAwMzozNyBwZmNfc2FsaW5lXzMuc2FtDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1ICAgICAgICAgNjM2IEFwciAxMSAwMzozNyBwZmNfc2FsaW5lXzNfYWxpZ25TdGF0cy50eHQNCg0KDQoNCg0KIyMgNi4gQ29udmVydCBTQU0gZmlsZXMgdG8gQkFNIGZpbGVzDQoNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgc2FtdG9vbHMgdmlldyAtU3UgcGZjX3NhbGluZV8xLnNhbSB8IHNhbXRvb2xzIHNvcnQgLW8gYWxpZ25lZF9iYW0vcGZjX3NhbGluZV8xLmJhbQ0KDQpbYmFtX3NvcnRfY29yZV0gbWVyZ2luZyBmcm9tIDM4IGZpbGVzLi4uDQoNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgc2FtdG9vbHMgdmlldyAtU3UgcGZjX3NhbGluZV8yLnNhbSB8IHNhbXRvb2xzIHNvcnQgLW8gYWxpZ25lZF9iYW0vcGZjX3NhbGluZV8yLmJhbQ0KDQpbYmFtX3NvcnRfY29yZV0gbWVyZ2luZyBmcm9tIDM3IGZpbGVzLi4uDQoNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgc2FtdG9vbHMgdmlldyAtU3UgcGZjX3NhbGluZV8zLnNhbSB8IHNhbXRvb2xzIHNvcnQgLW8gYWxpZ25lZF9iYW0vcGZjX3NhbGluZV8zLmJhbQ0KDQpbYmFtX3NvcnRfY29yZV0gbWVyZ2luZyBmcm9tIDM2IGZpbGVzLi4uDQoNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgc2FtdG9vbHMgdmlldyAtU3UgcGZjX25pY290aW5lXzEuc2FtIHwgc2FtdG9vbHMgc29ydCAtbyBhbGlnbmVkX2JhbS9wZmNfbmljb3RpbmVfMS5iYW0NCg0KW2JhbV9zb3J0X2NvcmVdIG1lcmdpbmcgZnJvbSAyNyBmaWxlcy4uLg0KDQoNCiMjIyMgfi9yZXN1bHRzL3JuYXNlcS9Sbi9oaXNhdF9yYXQkIHNhbXRvb2xzIHZpZXcgLVN1IHBmY19uaWNvdGluZV8yLnNhbSB8IHNhbXRvb2xzIHNvcnQgLW8gYWxpZ25lZF9iYW0vcGZjX25pY290aW5lXzIuYmFtDQoNCltiYW1fc29ydF9jb3JlXSBtZXJnaW5nIGZyb20gMjggZmlsZXMuLi4NCg0KDQojIyMjIH4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBzYW10b29scyB2aWV3IC1TdSBwZmNfbmljb3RpbmVfMy5zYW0gfCBzYW10b29scyBzb3J0IC1vIGFsaWduZWRfYmFtL3BmY19uaWNvdGluZV8zLmJhbQ0KDQoNCltiYW1fc29ydF9jb3JlXSBtZXJnaW5nIGZyb20gMjggZmlsZXMuLi4NCg0KDQojIyMgRGlyZWN0b3J5IGNvbnRlbnRzDQoNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgbHMgLWwgYWxpZ25lZF9iYW0vDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDI3NTk5NTg5NTUgQXByIDExIDA0OjUxIHBmY19uaWNvdGluZV8xLmJhbQ0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAyODI4MTc4ODQ0IEFwciAxMSAwNDo1MyBwZmNfbmljb3RpbmVfMi5iYW0NCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMjgyODE4MTA4MyBBcHIgMTEgMDQ6NTMgcGZjX25pY290aW5lXzMuYmFtDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDM4MDE1ODcxNTggQXByIDExIDA1OjAwIHBmY19zYWxpbmVfMS5iYW0NCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgMzc4MjkzODUxMCBBcHIgMTEgMDU6MDAgcGZjX3NhbGluZV8yLmJhbQ0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAzNzEzNTM5NzU1IEFwciAxMSAwNDo1OSBwZmNfc2FsaW5lXzMuYmFtDQoNCg0KDQoNCg0KIyMgNy4gU3RyaW5ndGllIHByb2Nlc3NpbmcNCg0KIyMjIENvbnZlcnQgQkFNIGZpbGVzIHRvIEdURiBmaWxlcw0KDQpgYGANCiB+L2hpc2F0X3JhdCQgc3RyaW5ndGllIGFsaWduZWRfYmFtL3BmY19zYWxpbmVfMS5iYW0gLXAgOCAtLXJmIC1vIGFzc2VtYmxlZF90cmFuc2NyaXB0cy9wZmNfc2FsaW5lXzEuZ3RmDQoNCiB+L2hpc2F0X3JhdCQgc3RyaW5ndGllIGFsaWduZWRfYmFtL3BmY19zYWxpbmVfMi5iYW0gLXAgOCAtLXJmIC1vIGFzc2VtYmxlZF90cmFuc2NyaXB0cy9wZmNfc2FsaW5lXzIuZ3RmDQoNCiB+L2hpc2F0X3JhdCQgc3RyaW5ndGllIGFsaWduZWRfYmFtL3BmY19zYWxpbmVfMy5iYW0gLXAgOCAtLXJmIC1vIGFzc2VtYmxlZF90cmFuc2NyaXB0cy9wZmNfc2FsaW5lXzMuZ3RmDQoNCiB+L2hpc2F0X3JhdCQgc3RyaW5ndGllIGFsaWduZWRfYmFtL3BmY19uaWNvdGluZV8xLmJhbSAtcCA4IC0tcmYgLW8gYXNzZW1ibGVkX3RyYW5zY3JpcHRzL3BmY19uaWNvdGluZV8xLmd0Zg0KDQogfi9oaXNhdF9yYXQkIHN0cmluZ3RpZSBhbGlnbmVkX2JhbS9wZmNfbmljb3RpbmVfMi5iYW0gLXAgOCAtLXJmIC1vIGFzc2VtYmxlZF90cmFuc2NyaXB0cy9wZmNfbmljb3RpbmVfMi5ndGYNCg0KIH4vaGlzYXRfcmF0JCBzdHJpbmd0aWUgYWxpZ25lZF9iYW0vcGZjX25pY290aW5lXzMuYmFtIC1wIDggLS1yZiAtbyBhc3NlbWJsZWRfdHJhbnNjcmlwdHMvcGZjX25pY290aW5lXzMuZ3RmDQoNCmBgYA0KDQojIyMjIH4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBscyAtbCBhc3NlbWJsZWRfdHJhbnNjcmlwdHMvDQoNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgNDk2NDc5NzYgQXByIDExIDEyOjU3IHBmY19uaWNvdGluZV8xLmd0Zg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSA1MTE1NjU5NCBBcHIgMTEgMTI6NTggcGZjX25pY290aW5lXzIuZ3RmDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDUxMTU2NTk0IEFwciAxMSAxMjo1OSBwZmNfbmljb3RpbmVfMy5ndGYNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgNTg2MzA0MzAgQXByIDExIDEyOjUzIHBmY19zYWxpbmVfMS5ndGYNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgNTY4ODU5NTUgQXByIDExIDEzOjAyIHBmY19zYWxpbmVfMi5ndGYNCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgNTY1Njg5ODUgQXByIDExIDEzOjAzIHBmY19zYWxpbmVfMy5ndGYNCg0KDQoNCg0KIyMjIE1ha2UgYSBzaW5nbGUgR1RGIGZpbGUgZm9yIHVzZSBpbiBkaWZmZXJlbnRpYWwgYW5hbHlzaXMgKERFKSB1c2luZyBiYWxsZ293bg0KDQojIyMjIH4vaGlzYXRfcmF0JCBscyBhc3NlbWJsZWRfdHJhbnNjcmlwdHMvKi5ndGYgPiBtZXJnZWxpc3QudHh0DQoNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgY2F0IG1lcmdlbGlzdC50eHQgDQoNCmBgYA0KYXNzZW1ibGVkX3RyYW5zY3JpcHRzL3BmY19uaWNvdGluZV8xLmd0Zg0KYXNzZW1ibGVkX3RyYW5zY3JpcHRzL3BmY19uaWNvdGluZV8yLmd0Zg0KYXNzZW1ibGVkX3RyYW5zY3JpcHRzL3BmY19uaWNvdGluZV8zLmd0Zg0KYXNzZW1ibGVkX3RyYW5zY3JpcHRzL3BmY19zYWxpbmVfMS5ndGYNCmFzc2VtYmxlZF90cmFuc2NyaXB0cy9wZmNfc2FsaW5lXzIuZ3RmDQphc3NlbWJsZWRfdHJhbnNjcmlwdHMvcGZjX3NhbGluZV8zLmd0Zg0KYGBgDQoNCg0KIyMjIEFzc2VtYmxlIFJOQS1TZXEgYWxpZ25tZW50cyBpbnRvIHBvdGVudGlhbCB0cmFuc2NyaXB0cw0KDQoNCiMjIyMgfi9oaXNhdF9yYXQkIHN0cmluZ3RpZSAtLW1lcmdlIC1wIDggLW8gc3RyaW5ndGllX21lcmdlZC5ndGYgbWVyZ2VsaXN0LnR4dCANCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgaGVhZCBzdHJpbmd0aWVfbWVyZ2VkLmd0ZiANCg0KYGBgDQoNCiMgc3RyaW5ndGllIC0tbWVyZ2UgLXAgOCAtbyBzdHJpbmd0aWVfbWVyZ2VkLmd0ZiBtZXJnZWxpc3QudHh0DQoNCiMgU3RyaW5nVGllIHZlcnNpb24gMS4zLjUNCg0KY2hyMQlTdHJpbmdUaWUJdHJhbnNjcmlwdAkyNDE2ODEJMjQxOTM1CTEwMDAJLQkuCWdlbmVfaWQgIk1TVFJHLjEiOyB0cmFuc2NyaXB0X2lkICJNU1RSRy4xLjEiOyANCmNocjEJU3RyaW5nVGllCWV4b24JMjQxNjgxCTI0MTkzNQkxMDAwCS0JLglnZW5lX2lkICJNU1RSRy4xIjsgdHJhbnNjcmlwdF9pZCAiTVNUUkcuMS4xIjsgZXhvbl9udW1iZXIgIjEiOyANCmNocjEJU3RyaW5nVGllCXRyYW5zY3JpcHQJMjQyNTY5CTI0MjgwMQkxMDAwCS0JLglnZW5lX2lkICJNU1RSRy4yIjsgdHJhbnNjcmlwdF9pZCAiTVNUUkcuMi4xIjsgDQpjaHIxCVN0cmluZ1RpZQlleG9uCTI0MjU2OQkyNDI4MDEJMTAwMAktCS4JZ2VuZV9pZCAiTVNUUkcuMiI7IHRyYW5zY3JpcHRfaWQgIk1TVFJHLjIuMSI7IGV4b25fbnVtYmVyICIxIjsgDQpjaHIxCVN0cmluZ1RpZQl0cmFuc2NyaXB0CTI0MjYwOAkyNDI4MDcJMTAwMAkrCS4JZ2VuZV9pZCAiTVNUUkcuMyI7IHRyYW5zY3JpcHRfaWQgIk1TVFJHLjMuMSI7IA0KY2hyMQlTdHJpbmdUaWUJZXhvbgkyNDI2MDgJMjQyODA3CTEwMDAJKwkuCWdlbmVfaWQgIk1TVFJHLjMiOyB0cmFuc2NyaXB0X2lkICJNU1RSRy4zLjEiOyBleG9uX251bWJlciAiMSI7IA0KY2hyMQlTdHJpbmdUaWUJdHJhbnNjcmlwdAkxNTQ1Nzk0CTE1NDYyMzAJMTAwMAkrCS4JZ2VuZV9pZCAiTVNUUkcuNCI7IHRyYW5zY3JpcHRfaWQgIk1TVFJHLjQuMSI7IA0KY2hyMQlTdHJpbmdUaWUJZXhvbgkxNTQ1Nzk0CTE1NDYyMzAJMTAwMAkrCS4JZ2VuZV9pZCAiTVNUUkcuNCI7IHRyYW5zY3JpcHRfaWQgIk1TVFJHLjQuMSI7IGV4b25fbnVtYmVyICIxIjsgDQoNCmBgYGANCg0KDQojIyMgT3V0cHV0IEJhbGxnb3duIHRhYmxlIGZpbGVzDQoNCmBgYA0KU3RyaW5nVGllIHYxLjMuNSB1c2FnZToNCg0KIC1iIGVuYWJsZSBvdXRwdXQgb2YgQmFsbGdvd24gdGFibGUgZmlsZXMgYnV0IHRoZXNlIGZpbGVzIHdpbGwgYmUgY3JlYXRlZCB1bmRlciB0aGUgZGlyZWN0b3J5IHBhdGggZ2l2ZW4gYXMgPGRpcl9wYXRoPg0KICAgIA0KIC1lIG9ubHkgZXN0aW1hdGUgdGhlIGFidW5kYW5jZSBvZiBnaXZlbiByZWZlcmVuY2UgdHJhbnNjcmlwdHMgKHJlcXVpcmVzIC1HKQ0KIA0KIC1HIHJlZmVyZW5jZSBhbm5vdGF0aW9uIHRvIHVzZSBmb3IgZ3VpZGluZyB0aGUgYXNzZW1ibHkgcHJvY2VzcyAoR1RGL0dGRjMpDQogDQpgYGANCg0KDQpgYGANCn4vaGlzYXRfcmF0JCBzdHJpbmd0aWUgLWUgLUIgLXAgOCAtRyBzdHJpbmd0aWVfbWVyZ2VkLmd0ZiAtbyBiYWxsZ293bi9wZmNfMDEvcGZjX3NhbGluZV8xLmd0ZiBhbGlnbmVkX2JhbS9wZmNfc2FsaW5lXzEuYmFtDQoNCn4vaGlzYXRfcmF0JCBzdHJpbmd0aWUgLWUgLUIgLXAgOCAtRyBzdHJpbmd0aWVfbWVyZ2VkLmd0ZiAtbyBiYWxsZ293bi9wZmNfMDIvcGZjX3NhbGluZV8yLmd0ZiBhbGlnbmVkX2JhbS9wZmNfc2FsaW5lXzIuYmFtDQoNCn4vaGlzYXRfcmF0JCBzdHJpbmd0aWUgLWUgLUIgLXAgOCAtRyBzdHJpbmd0aWVfbWVyZ2VkLmd0ZiAtbyBiYWxsZ293bi9wZmNfMDMvcGZjX3NhbGluZV8zLmd0ZiBhbGlnbmVkX2JhbS9wZmNfc2FsaW5lXzMuYmFtDQoNCn4vaGlzYXRfcmF0JCBzdHJpbmd0aWUgLWUgLUIgLXAgOCAtRyBzdHJpbmd0aWVfbWVyZ2VkLmd0ZiAtbyBiYWxsZ293bi9wZmNfMDQvcGZjX25pY290aW5lXzEuZ3RmIGFsaWduZWRfYmFtL3BmY19uaWNvdGluZV8xLmJhbQ0KDQp+L2hpc2F0X3JhdCQgc3RyaW5ndGllIC1lIC1CIC1wIDggLUcgc3RyaW5ndGllX21lcmdlZC5ndGYgLW8gYmFsbGdvd24vcGZjXzA1L3BmY19uaWNvdGluZV8yLmd0ZiBhbGlnbmVkX2JhbS9wZmNfbmljb3RpbmVfMi5iYW0NCg0Kfi9oaXNhdF9yYXQkIHN0cmluZ3RpZSAtZSAtQiAtcCA4IC1HIHN0cmluZ3RpZV9tZXJnZWQuZ3RmIC1vIGJhbGxnb3duL3BmY18wNi9wZmNfbmljb3RpbmVfMy5ndGYgYWxpZ25lZF9iYW0vcGZjX25pY290aW5lXzMuYmFtDQoNCmBgYA0KDQojIyMgRGlyZWN0b3J5IGFuZCBzb21lIGZpbGUgY29udGVudHMNCg0KIyMjIyB+L3Jlc3VsdHMvcm5hc2VxL1JuL2hpc2F0X3JhdCQgbHMgLWwgYmFsbGdvd24NCg0KZHJ3eHIteHIteCAyIHVidW50dSB1YnVudHUgNDA5NiBBcHIgMTEgMTU6MzEgcGZjXzAxDQoNCmRyd3hyLXhyLXggMiB1YnVudHUgdWJ1bnR1IDQwOTYgQXByIDExIDE1OjMyIHBmY18wMg0KDQpkcnd4ci14ci14IDIgdWJ1bnR1IHVidW50dSA0MDk2IEFwciAxMSAxNTozMiBwZmNfMDMNCg0KZHJ3eHIteHIteCAyIHVidW50dSB1YnVudHUgNDA5NiBBcHIgMTEgMTU6MjQgcGZjXzA0DQoNCmRyd3hyLXhyLXggMiB1YnVudHUgdWJ1bnR1IDQwOTYgQXByIDExIDE1OjI1IHBmY18wNQ0KDQpkcnd4ci14ci14IDIgdWJ1bnR1IHVidW50dSA0MDk2IEFwciAxMSAxNToyNiBwZmNfMDYNCg0KDQojIyMjIH4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBscyAtbCBiYWxsZ293bi9wZmNfMDEvDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1ICA1OTgwODgzIEFwciAxMSAxNTozMSBlMnQuY3RhYg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAyMjc5ODUxMSBBcHIgMTEgMTU6MzEgZV9kYXRhLmN0YWINCg0KLXJ3LXJ3LXItLSAxIHVidW50dSB1YnVudHUgIDUyNTYwMDUgQXByIDExIDE1OjMxIGkydC5jdGFiDQoNCi1ydy1ydy1yLS0gMSB1YnVudHUgdWJ1bnR1IDEwNzgyMTg5IEFwciAxMSAxNTozMSBpX2RhdGEuY3RhYg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSA3MzUzNDAzMSBBcHIgMTEgMTU6MzEgcGZjX3NhbGluZV8xLmd0Zg0KDQotcnctcnctci0tIDEgdWJ1bnR1IHVidW50dSAgNDcxNDc0NiBBcHIgMTEgMTU6MzEgdF9kYXRhLmN0YWINCg0KDQoNCiMjIyMgfi9yZXN1bHRzL3JuYXNlcS9Sbi9oaXNhdF9yYXQkIGhlYWQgYmFsbGdvd24vcGZjXzAxL3BmY19zYWxpbmVfMS5ndGYgDQoNCmBgYA0KIyBzdHJpbmd0aWUgLWUgLUIgLXAgOCAtRyBzdHJpbmd0aWVfbWVyZ2VkLmd0ZiAtbyBiYWxsZ293bi9wZmNfMDEvcGZjX3NhbGluZV8xLmd0ZiBhbGlnbmVkX2JhbS9wZmNfc2FsaW5lXzEuYmFtDQoNCiMgU3RyaW5nVGllIHZlcnNpb24gMS4zLjUNCg0KY2hyMQlTdHJpbmdUaWUJdHJhbnNjcmlwdAkyNDE2ODEJMjQxOTM1CTEwMDAJLQkuCWdlbmVfaWQgIk1TVFJHLjEiOyB0cmFuc2NyaXB0X2lkICJNU1RSRy4xLjEiOyBjb3YgIjEuNDMxMzczIjsgRlBLTSAiMC40NTgzNzIiOyBUUE0gIjEuNDIxNTU0IjsNCg0KY2hyMQlTdHJpbmdUaWUJZXhvbgkyNDE2ODEJMjQxOTM1CTEwMDAJLQkuCWdlbmVfaWQgIk1TVFJHLjEiOyB0cmFuc2NyaXB0X2lkICJNU1RSRy4xLjEiOyBleG9uX251bWJlciAiMSI7IGNvdiAiMS40MzEzNzMiOw0KDQpjaHIxCVN0cmluZ1RpZQl0cmFuc2NyaXB0CTI0MjYwOAkyNDI4MDcJMTAwMAkrCS4JZ2VuZV9pZCAiTVNUUkcuMyI7IHRyYW5zY3JpcHRfaWQgIk1TVFJHLjMuMSI7IGNvdiAiMi45NjY3NTAiOyBGUEtNICIwLjk1MDA1MCI7IFRQTSAiMi45NDYzOTkiOw0KDQpjaHIxCVN0cmluZ1RpZQlleG9uCTI0MjYwOAkyNDI4MDcJMTAwMAkrCS4JZ2VuZV9pZCAiTVNUUkcuMyI7IHRyYW5zY3JpcHRfaWQgIk1TVFJHLjMuMSI7IGV4b25fbnVtYmVyICIxIjsgY292ICIyLjk2Njc1MCI7DQoNCmNocjEJU3RyaW5nVGllCXRyYW5zY3JpcHQJMjQyNTY5CTI0MjgwMQkxMDAwCS0JLglnZW5lX2lkICJNU1RSRy4yIjsgdHJhbnNjcmlwdF9pZCAiTVNUUkcuMi4xIjsgY292ICI1LjI3Nzg5NyI7IEZQS00gIjEuNjkwMTU1IjsgVFBNICI1LjI0MTY5MiI7DQoNCmNocjEJU3RyaW5nVGllCWV4b24JMjQyNTY5CTI0MjgwMQkxMDAwCS0JLglnZW5lX2lkICJNU1RSRy4yIjsgdHJhbnNjcmlwdF9pZCAiTVNUUkcuMi4xIjsgZXhvbl9udW1iZXIgIjEiOyBjb3YgIjUuMjc3ODk3IjsNCg0KY2hyMQlTdHJpbmdUaWUJdHJhbnNjcmlwdAkxNTQ1Nzk0CTE1NDYyMzAJMTAwMAkrCS4JZ2VuZV9pZCAiTVNUUkcuNCI7IHRyYW5zY3JpcHRfaWQgIk1TVFJHLjQuMSI7IGNvdiAiMi45NDI3OTIiOyBGUEtNICIwLjk0MjM3OCI7IFRQTSAiMi45MjI2MDUiOw0KDQpjaHIxCVN0cmluZ1RpZQlleG9uCTE1NDU3OTQJMTU0NjIzMAkxMDAwCSsJLglnZW5lX2lkICJNU1RSRy40IjsgdHJhbnNjcmlwdF9pZCAiTVNUUkcuNC4xIjsgZXhvbl9udW1iZXIgIjEiOyBjb3YgIjIuOTQyNzkyIjsNCg0KYGBgDQoNCg0KDQojIyMjIH4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBoZWFkIC1uIDUgYmFsbGdvd24vcGZjXzAxL2VfZGF0YS5jdGFiIA0KDQpgYGANCmVfaWQJY2hyCXN0cmFuZAlzdGFydAllbmQJcmNvdW50CXVjb3VudAltcmNvdW50CWNvdgljb3Zfc2QJbWNvdgltY292X3NkDQoxCWNocjEJLQkyNDE2ODEJMjQxOTM1CTIwCTIJOC4xMwkzLjQyNzUJMi40OTc0CTEuMTEzNwkxLjA5NzQNCjIJY2hyMQktCTI0MjU2OQkyNDI4MDEJNDEJMTkJMjQuOTUJOC42Mzk1CTYuMDg3Mgk0Ljg4NDEJNC4xODMzDQozCWNocjEJKwkyNDI2MDgJMjQyODA3CTI0CTgJMTIuMzgJNS40ODUwCTMuMzUxMQkyLjY2NTAJMS44MDk3DQo0CWNocjEJKwkxNTQ1Nzk0CTE1NDYyMzAJMzYJMTYJMjYuMDAJNC4wNzU1CTIuNDM2NgkyLjY4NjUJMS44OTkyDQoNCmBgYA0KDQoNCiMjIyMgfi9yZXN1bHRzL3JuYXNlcS9Sbi9oaXNhdF9yYXQkIGhlYWQgLW4gNSBiYWxsZ293bi9wZmNfMDEvaV9kYXRhLmN0YWIgDQoNCmBgYA0KaV9pZAljaHIJc3RyYW5kCXN0YXJ0CWVuZAlyY291bnQJdWNvdW50CW1yY291bnQNCjEJY2hyMQktCTE2NzE0NDQJMTcwOTIyNgk0CTQJNC4wMA0KMgljaHIxCS0JMTcwOTM4OAkxNzEyNDQ3CTE1NAkxNTQJMTU0LjAwDQozCWNocjEJLQkxNzEyNTkwCTE3MTc0MzQJMTM4CTEzOAkxMzguMDANCjQJY2hyMQktCTE3MTc1NjEJMTcyMDQxMQkxNDQJMTQ0CTE0NC4wMA0KDQpgYGANCg0KDQojIyMjIH4vcmVzdWx0cy9ybmFzZXEvUm4vaGlzYXRfcmF0JCBoZWFkIC1uIDUgYmFsbGdvd24vcGZjXzAxL3RfZGF0YS5jdGFiIA0KDQpgYGANCnRfaWQJY2hyCXN0cmFuZAlzdGFydAllbmQJdF9uYW1lCSAgICAgICAgbnVtX2V4b25zCWxlbmd0aAlnZW5lX2lkIGdlbmVfbmFtZQljb3YJICAgICAgICBGUEtNDQoxCWNocjEJLQkyNDE2ODEJMjQxOTM1CU1TVFJHLjEuMQkxCSAgICAgICAgMjU1CU1TVFJHLjEJLgkgICAgICAgIDEuNDMxMzczCTAuNDU4MzcyDQoyCWNocjEJLQkyNDI1NjkJMjQyODAxCU1TVFJHLjIuMQkxCSAgICAgICAgMjMzCU1TVFJHLjIJLgkgICAgICAgIDUuMjc3ODk3CTEuNjkwMTU1DQozCWNocjEJKwkyNDI2MDgJMjQyODA3CU1TVFJHLjMuMQkxCSAgICAgICAgMjAwCU1TVFJHLjMJLgkgICAgICAgIDIuOTY2NzUwCTAuOTUwMDUwDQo0CWNocjEJKwkxNTQ1Nzk0CTE1NDYyMzAJTVNUUkcuNC4xCTEJICAgICAgICA0MzcJTVNUUkcuNAkuCSAgICAgICAgMi45NDI3OTIJMC45NDIzNzgNCg0KYGBgDQoNCg0KDQojIyA5LiBCYWxsZ293biBhbmFseXNpcy8gcGVyZm9ybSBkaWZmZXJlbnRpYWwgYW5hbHlzaXMgdXNpbmcgYmFsbGdvd24NCg0KIyMjIFJlcXVpcmVkIGxpYnJhcmllcw0KDQpgYGB7cn0NCmxpYnJhcnkoYmFsbGdvd24pOyBsaWJyYXJ5KGdlbmVmaWx0ZXIpOyBsaWJyYXJ5KGRwbHlyKTsgbGlicmFyeShkZXZ0b29scyk7IGxpYnJhcnkoZ3Bsb3RzKQ0KYGBgDQoNCg0KDQojIyMgQ29udmVydCB0aGUgU3RyaW5nVGllIGRhdGEgdG8gQmFsbGdvd24gZGF0YQ0KDQpgYGB7cn0NCmRhdGFfZGlyZWN0b3J5PSgiYmFsbGdvd24vIikNCmRhdGFfZGlyZWN0b3J5DQpgYGANCg0KDQoNCg0KYGBge3J9DQpiZz1iYWxsZ293bihkYXRhRGlyPWRhdGFfZGlyZWN0b3J5LCBzYW1wbGVQYXR0ZXJuPSJwZmMiLCBtZWFzPSJhbGwiKQ0KYGBgDQoNCmBgYHtyfQ0KYmcNCmBgYA0KDQoNCiMjIyBTdHJ1Y3R1cmUgb2YgdGhlIGJhbGxnb3duIGRhdGEgYW5kIGl0cyBjb21wb25lbnRzOiBDYW4gYmUgZG9uZSBpbiBmZXcgZGlmZmVyZW50IHdheXMNCg0KDQpgYGB7cn0NCm5hbWVzKHN0cnVjdHVyZShiZykpDQpgYGANCg0KYGBge3J9DQpzdHJ1Y3R1cmUoYmcpJGV4b24NCg0KYGBgDQoNCg0KYGBge3J9DQpzdHJ1Y3R1cmUoYmcpJGludHJvbg0KDQpgYGANCg0KDQpgYGB7cn0NCnN0cnVjdHVyZShiZykkdHJhbnMNCmBgYA0KDQoNCmBgYHtyfQ0Kc3RydWN0dXJlKGJnKQ0KYGBgDQoNCiMjIyBDcmVhdGUgbWV0YWRhdGEvcGhlbm90eXBlIGRhdGEgKHBEYXRhKSBmb3IgdGhlIGJhbGxnb3duIGRhdGEgdG8gcGVyZm9ybSBkaWZmZXJlbnRpYWwgYW5hbHlzaXMgKERFKQ0KDQojIyMjIFRocmVlICgzKSByZXBsaWNhdGVzIHBlciBncm91cCAoc2FsaW5lIG9yIG5pY290aW5lKQ0KDQpgYGB7cn0NCnBEYXRhKGJnKSA9IGRhdGEuZnJhbWUoaWQ9c2FtcGxlTmFtZXMoYmcpLCBncm91cD1yZXAoYygwLDEpLCBlYWNoPTMpKQ0KcERhdGEoYmcpDQpgYGANCg0KIyMjIGluZGljZXMNCg0KYGBge3J9DQpleG9uX3RyYW5zY3JpcHRfdGFibGUgPSBpbmRleGVzKGJnKSRlMnQNCmhlYWQoZXhvbl90cmFuc2NyaXB0X3RhYmxlKQ0KYGBgDQoNCmBgYHtyfQ0KdHJhbnNjcmlwdF9nZW5lX3RhYmxlID0gaW5kZXhlcyhiZykkdDJnDQpoZWFkKHRyYW5zY3JpcHRfZ2VuZV90YWJsZSkNCmBgYA0KDQoNCmBgYHtyfQ0KcGhlbm90eXBlX3RhYmxlID0gcERhdGEoYmcpDQpwaGVub3R5cGVfdGFibGUNCg0KYGBgDQoNCg0KIyMjIGdldGV4cHINCg0KDQojIyMjIEZQS00gdmFsdWVzIGZvciBlYWNoIHRyYW5zY3JpcHQNCg0KYGBge3J9DQp0cmFuc2NyaXB0X2Zwa20gPSB0ZXhwcihiZywgIkZQS00iKQ0KaGVhZCh0cmFuc2NyaXB0X2Zwa20pDQpgYGANCg0KDQojIyMjIENvdmVyYWdlIGluZm9ybWF0aW9uIGZvciBlYWNoIHRyYW5zY3JpcHQNCg0KYGBge3J9DQp0cmFuc2NyaXB0X2NvdiA9IHRleHByKGJnLCAiY292IikNCmhlYWQodHJhbnNjcmlwdF9jb3YpDQpgYGANCg0KDQojIyMjIERlc2NyaXB0aXZlIHN0YXRzIGZvciBlYWNoIHRyYW5zY3JpcHRzDQoNCmBgYHtyfQ0Kd2hvbGVfdHhfdGFibGUgPSB0ZXhwcihiZywgImFsbCIpDQpoZWFkKHdob2xlX3R4X3RhYmxlKQ0KYGBgDQoNCg0KIyMjIyBJc29sYXRlIG11bHRpLW1hcC1jb3JyZWN0ZWQgYXZlcmFnZSBwZXItYmFzZSByZWFkIGNvdmVyYWdlIGZvciBlYWNoIGV4b24NCg0KYGBge3J9DQpleG9uX21jb3YgPSBlZXhwcihiZywgIm1jb3YiKQ0KaGVhZChleG9uX21jb3YpDQpgYGANCg0KDQojIyMjIElzb2xhdGUgcmVhZCBjb3VudCBmb3IgZWFjaCBpbnRyb24NCg0KYGBge3J9DQpqdW5jdGlvbl9yZWNvdW50ID0gaWV4cHIoYmcpDQpoZWFkKGp1bmN0aW9uX3JlY291bnQpDQpgYGANCg0KDQojIyMjIElzb2xhdGUgc3RhdHMgZm9yIGludHJvbg0KDQpgYGB7cn0NCndob2xlX2ludHJvbl90YWJsZSA9IGlleHByKGJnLCAiYWxsIikNCmhlYWQod2hvbGVfaW50cm9uX3RhYmxlKQ0KYGBgDQoNCiMjIyMgSXNvbGF0ZSBnZW5lIGxldmVsIGV4cHJlc3Npb24NCg0KYGBge3J9DQpnZW5lX2V4cHJlc3Npb24gPSBnZXhwcihiZykNCmhlYWQoZ2VuZV9leHByZXNzaW9uKQ0KYGBgDQoNCg0KDQojIyMjIERpc3RyaWJ1dGlvbiBvZiBnZW5lIGFidW5kYW5jZXMgKG1lYXN1cmVkIGFzIEZQS00gdmFsdWVzKSBhY3Jvc3Mgc2FtcGxlcywgY29sb3JlZCBieSB0cmVhdG1lbnQpOiBCb3hwbG90cyBmb3IgZ2VuZSBleHByZXNzaW9uIChieSBGUEtNKSBmb3IgZWFjaCBzYW1wbGUNCg0KYGBge3J9DQoNCnRyb3BpY2FsPSBjKCdkYXJrb3JhbmdlJywgJ2RvZGdlcmJsdWUnLCAnaG90cGluaycsICdsaW1lZ3JlZW4nLCAneWVsbG93JykNCg0KcGFsZXR0ZSh0cm9waWNhbCkNCg0KZnBrbSA9IHRleHByKGJnLCBtZWFzPSJGUEtNIikNCg0KZnBrbSA9IGxvZzIoZnBrbSsxKQ0KDQpib3hwbG90KGZwa20sDQogICAgICAgIGNvbD1hcy5udW1lcmljKHBEYXRhKGJnKSRncm91cCksIA0KICAgICAgICBsYXM9MiwgDQogICAgICAgIHlsYWI9J2xvZzIoRlBLTSsxKScpDQoNCmBgYA0KDQoNCg0KIyMjIyBQbG90IGhlYXRtYXAgIG9mIHRyYW5zY3JpcHQgRlBLTSBhY3Jvc3MgYWxsIHNhbXBsZXMNCg0KYGBge3J9DQpjb2xzID0gY29sb3JwYW5lbCg5OSwgImJsdWUiLCAiYmxhY2siLCAieWVsbG93IikNCg0KZnBrbSA9IHRleHByKGJnLCBtZWFzPSJGUEtNIikNCg0KZnBrbSA9IGxvZzIoZnBrbSsxKQ0KDQpoZWF0bWFwLjIoZnBrbSwgZGVuc2l0eS5pbmZvID0gIm5vbmUiLCANCiAgICAgICAgICB0cmFjZSA9ICJub25lIiwgDQogICAgICAgICAgbWFyZ2lucyA9IGMoOCwgNSksIA0KICAgICAgICAgIGNleENvbCA9IDEuMiwgDQogICAgICAgICAga2V5c2l6ZSA9IDEsDQogICAgICAgICAgY29sID0gY29scywgDQogICAgICAgICAgc2NhbGUgPSAibm9uZSIpDQpgYGANCg0KIyMjIFByaW5jaXBhbCBjb21wb25lbnQgYW5hbHlzaXMgKFBDQSkNCg0KYGBge3J9DQpsaWJyYXJ5KGdnZm9ydGlmeSkNCmBgYA0KDQpgYGB7cn0NCmZwa20gPSB0ZXhwcihiZywgbWVhcz0iRlBLTSIpDQoNCmZwa20gPSBsb2cyKGZwa20rMSkNCg0KcGNhID0gKHByY29tcCh0KGZwa20pKSkNCg0KYXV0b3Bsb3QocGNhLCBkYXRhPXBEYXRhKGJnKSwgY29sb3VyID0gImdyb3VwIiwgbGFiZWwgPSBULCBsYWJlbC5sYWJlbCA9ICJpZCIgKQ0KYGBgDQoNCiMjIyBBZGRpdGlvbmFsIGRhdGEgZXh0cmFjdGlvbg0KDQojIyMjIEV4dHJhY3QgaW5kZXhlcyBmcm9tIGJhbGxnb3duIG9iamVjdA0KDQpgYGB7cn0NCm5hbWVzKGluZGV4ZXMoYmcpKQ0KYGBgDQoNCiMjIyMgTWFwIGV4b25zIHRvIHRyYW5zY3JpcHRzDQoNCmBgYHtyfQ0KaGVhZChpbmRleGVzKGJnKSRlMnQpDQpgYGANCg0KDQoNCiMjIyMgTWFwIGludHJvbnMgdG8gdHJhbnNjcmlwdHMNCg0KYGBge3J9DQpoZWFkKGluZGV4ZXMoYmcpJGkydCkNCmBgYA0KDQojIyMjIE1hcCB0cmFuc2NyaXB0cyB0byBnZW5lcw0KDQpgYGB7cn0NCmhlYWQoaW5kZXhlcyhiZykkdDJnKQ0KYGBgDQoNCiMjIyMgTWFwcGluZyBleG9ucyB0byB0cmFuc2NyaXB0cyBhbmQgdHJhbnNjcmlwdHMgdG8gZ2VuZQ0KDQpgYGB7cn0NCmV4b25fdHJhbnNjcmlwdF90YWJsZSA9IGluZGV4ZXMoYmcpJGUydA0KdHJhbnNjcmlwdF9nZW5lX3RhYmxlID0gaW5kZXhlcyhiZykkdDJnDQpoZWFkKHRyYW5zY3JpcHRfZ2VuZV90YWJsZSkNCmBgYA0KDQojIyMgVGVzdCBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYnkgdHJhbnNjcmlwdHMgYW5kIGdlbmVzOiBJZGVudGlmeSBhbmQgc29ydCAoaW5jcmVhc2luZykgdGhlIGdlbmVzIGFuZCB0aGUgdHJhbnNjcmlwdHMgYnkgdGhlaXIgcC12YWx1ZXMNCg0KIyMjIyBGb3IgdHJhbnNjcmlwdHMNCg0KYGBge3J9DQpyZXN1bHRzX3RyYW5zY3JpcHRzID0gc3RhdHRlc3QoYmcsIGZlYXR1cmUgPSAidHJhbnNjcmlwdCIsIG1lYXMgPSAiRlBLTSIsIGNvdmFyaWF0ZSA9ICJncm91cCIsIGdldEZDID0gVFJVRSkNCndyaXRlLnRhYmxlKHJlc3VsdHNfdHJhbnNjcmlwdHMsIGZpbGUgPSAiYmFsbGdvd25fdHJhbnNjcmlwdF9yZXN1bHRzLnR4dCIsIHNlcCA9ICJcdCIsIHF1b3RlID0gRiwgcm93Lm5hbWVzID0gRikNCnJlc3VsdHNfdHJhbnNjcmlwdHMgPC0gYXJyYW5nZShyZXN1bHRzX3RyYW5zY3JpcHRzLCBwdmFsKQ0KaGVhZChyZXN1bHRzX3RyYW5zY3JpcHRzKQ0KDQpgYGANCg0KDQojIyMjIEZvciBnZW5lcw0KDQpgYGB7cn0NCnJlc3VsdHNfZ2VuZXMgPSBzdGF0dGVzdChiZywgZmVhdHVyZSA9ICJnZW5lIiwgbWVhcyA9ICJGUEtNIiwgY292YXJpYXRlID0gImdyb3VwIiwgZ2V0RkMgPSBUUlVFKQ0Kd3JpdGUudGFibGUocmVzdWx0c19nZW5lcywgZmlsZSA9ICJiYWxsZ293bl9nZW5lX3Jlc3VsdHMudHh0Iiwgc2VwID0gIlx0IiwgcXVvdGUgPSBGLCByb3cubmFtZXMgPSBGKQ0KcmVzdWx0c19nZW5lcyA8LSBhcnJhbmdlKHJlc3VsdHNfZ2VuZXMsIHB2YWwpDQpoZWFkKHJlc3VsdHNfZ2VuZXMpDQpgYGANCg0KDQojIyMgUGxvdCB0aGUgdHJhbnNjcmlwdHMgZm9yIGEgZ2VuZSBhY3Jvc3Mgc2FtcGxlcyANCg0KDQpgYGB7cn0NCnBsb3RUcmFuc2NyaXB0cyhnZW5lID0gIk1TVFJHLjY1NTEiLCBnb3duID0gYmcsIHNhbXBsZXMgPSBzYW1wbGVOYW1lcyhiZyksIG1lYXMgPSAiRlBLTSIsIGNvbG9yYnkgPSAidHJhbnNjcmlwdCIsDQogICAgICAgICAgICAgICAgbWFpbiA9ICJ0cmFuc2NyaXB0cyBmcm9tIGdlbmUgTVNUUkcuNjU1MSIpDQpgYGANCg0KDQoNCg0KIyMjIEZpbHRlciB0aGUgZGF0YSBhbmQgcmVhbmFseXplIChkbyBzdGF0dGVzdCkNCg0KIyMjIyBGaWx0ZXIgdG8gcmVtb3ZlIGxvdyBhYnVuZGFuY2UgZ2VuZXMNCg0KYGBge3J9DQpiZ19maWx0ID0gc3Vic2V0KGJnLCJyb3dWYXJzKHRleHByKGJnKSkgPiAxIixnZW5vbWVzdWJzZXQ9VFJVRSkNCmJnX2ZpbHQgIA0KYGBgDQoNCg0KIyMjIyBzdGF0dGVzdA0KDQpgYGB7cn0NCmZpbHRfdHJhbnNjcmlwdF9yZXN1bHRzID0gc3RhdHRlc3QoYmdfZmlsdCwgZmVhdHVyZT0ndHJhbnNjcmlwdCcsIG1lYXM9J0ZQS00nLCBjb3ZhcmlhdGU9J2dyb3VwJykNCmZpbHRfcmVzdWx0c190cmFuc2NyaXB0cyA8LSBhcnJhbmdlKGZpbHRfdHJhbnNjcmlwdF9yZXN1bHRzLCBwdmFsKQ0KaGVhZChmaWx0X3Jlc3VsdHNfdHJhbnNjcmlwdHMpDQpgYGANCg0KYGBge3J9DQpmaWx0X2dlbmVfcmVzdWx0cyA9IHN0YXR0ZXN0KGJnX2ZpbHQsIGZlYXR1cmU9J2dlbmUnLCBtZWFzPSdGUEtNJywgY292YXJpYXRlPSdncm91cCcpDQpmaWx0X3Jlc3VsdHNfZ2VuZXMgPC0gYXJyYW5nZShmaWx0X2dlbmVfcmVzdWx0cywgcHZhbCkNCmhlYWQoZmlsdF9nZW5lX3Jlc3VsdHMpDQpgYGANCg0KDQojIyMjIEFkZCBnZW5lIG5hbWVzIGFuZCBnZW5lIElEcyB0byB0aGUgcmVzdWx0c190cmFuc2NyaXB0cyBkYXRhIGZyYW1lIGFuZCBzb3J0IHRoZSByZXN1bHRzIGZyb20gc21hbGxlc3QgcC12YWx1ZSB0byBsYXJnZXN0Og0KDQpgYGB7cn0NCmZpbHRfcmVzdWx0c190cmFuc2NyaXB0cyA9IGRhdGEuZnJhbWUoZ2VuZU5hbWVzPWJhbGxnb3duOjpnZW5lTmFtZXMoYmdfZmlsdCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lSURzPWJhbGxnb3duOjpnZW5lSURzKGJnX2ZpbHQpLCBmaWx0X3RyYW5zY3JpcHRfcmVzdWx0cykNCg0KZmlsdF9yZXN1bHRzX3RyYW5zY3JpcHRzID0gYXJyYW5nZShmaWx0X3Jlc3VsdHNfdHJhbnNjcmlwdHMscHZhbCkNCg0KaGVhZChmaWx0X3Jlc3VsdHNfdHJhbnNjcmlwdHMpDQpgYGANCg0KDQojIyMjIFdyaXRlIHRoZSByZXN1bHRzIHRvIGEgQ1NWIChjb21tYS1zZXBhcmF0ZWQgdmFsdWVzKSBmaWxlIHRoYXQgY2FuIGJlIHNoYXJlZCwgZGlzdHJpYnV0ZWQgYW5kIGZ1cnRoZXIgYW5hbHl6ZWQNCg0KYGBge3J9DQogICAgICAgIA0Kd3JpdGUuY3N2KGZpbHRfcmVzdWx0c190cmFuc2NyaXB0cywgInJhdF9wZmNfdHJhbnNjcmlwdF9yZXN1bHRzLmNzdiIsIHJvdy5uYW1lcz1GQUxTRSkNCg0Kd3JpdGUuY3N2KGZpbHRfcmVzdWx0c19nZW5lcywgInJhdF9wZmNfZ2VuZXNfcmVzdWx0cy5jc3YiLCByb3cubmFtZXM9RkFMU0UpDQpgYGANCg0KDQoNCiMjIyMgSWRlbnRpZnkgdHJhbnNjcmlwdHMgYW5kIGdlbmVzIHdpdGggYSBxLXZhbHVlIG9mIGxlc3MgdGhhbiAwLjA1Og0KDQpgYGB7cn0gICAgICAgIA0Kc3Vic2V0KGZpbHRfcmVzdWx0c190cmFuc2NyaXB0cyxmaWx0X3Jlc3VsdHNfdHJhbnNjcmlwdHMkcXZhbDwwLjA1KQ0KYGBgDQoNCg0KYGBge3J9DQpzdWJzZXQoZmlsdF9yZXN1bHRzX2dlbmVzLGZpbHRfcmVzdWx0c19nZW5lcyRxdmFsPDAuMDUpDQpgYGANCg0KDQoNCiMjIyBGdXJ0aGVyIGFuYWx5c2lzOiBNU1RSRy4xNTM1OC90cmFuc2NyaXB0IGlkPTIyNjU3DQoNCiMjIyMgcGxvdFRyYW5zY3JpcHRzIGZvciBhIHNpbmdsZSBzYWxpbmUgc2FtcGxlIChwZmNfMDEpDQoNCmBgYHtyfQ0KDQpwbG90VHJhbnNjcmlwdHMoZ2VuZT0nTVNUUkcuMTUzNTgnLCANCiAgICAgICAgICAgICAgICBnb3duPWJnLCANCiAgICAgICAgICAgICAgICBzYW1wbGVzPSdwZmNfMDEnLCANCiAgICAgICAgICAgICAgICBtZWFzPSdGUEtNJywgDQogICAgICAgICAgICAgICAgY29sb3JieT0ndHJhbnNjcmlwdCcsIA0KICAgICAgICAgICAgICAgIG1haW49J3RyYW5zY3JpcHRzIGZyb20gZ2VuZSBNU1RSRy4xNTM1ODogc2FtcGxlIHBmY18wMSwgRlBLTScpDQpgYGANCg0KIyMjIyBwbG90VHJhbnNjcmlwdHMgZm9yIHNhbGluZSB0cmVhdGVkIHNhbXBsZXMgKHBmY18wMSwgcGZjXzAyLCBwZmNfMDMpDQoNCmBgYHtyfQ0KcGxvdFRyYW5zY3JpcHRzKGdlbmU9J01TVFJHLjE1MzU4JywgDQogICAgICAgICAgICAgICAgZ293bj1iZywgDQogICAgICAgICAgICAgICAgc2FtcGxlcz1jKCJwZmNfMDEiLCAicGZjXzAyIiwgInBmY18wMyIpLA0KICAgICAgICAgICAgICAgIG1lYXM9J0ZQS00nLCANCiAgICAgICAgICAgICAgICBjb2xvcmJ5PSd0cmFuc2NyaXB0JywgDQogICAgICAgICAgICAgICAgbWFpbj0ndHJhbnNjcmlwdHMgZnJvbSBnZW5lIE1TVFJHLjE1MzU4OiBzYW1wbGVzIHBmY18wMS1wZmNfMDMsIEZQS00nKQ0KYGBgDQoNCiMjIyMgcGxvdFRyYW5zY3JpcHRzIGZvciBuaWNvdGluZSB0cmVhdGVkIHNhbXBsZXMgKHBmY18wNCwgcGZjXzA1LCBwZmNfMDYpDQoNCmBgYHtyfQ0KcGxvdFRyYW5zY3JpcHRzKGdlbmU9J01TVFJHLjE1MzU4JywgDQogICAgICAgICAgICAgICAgZ293bj1iZywgDQogICAgICAgICAgICAgICAgc2FtcGxlcz1jKCJwZmNfMDQiLCAicGZjXzA1IiwgInBmY18wNiIpLA0KICAgICAgICAgICAgICAgIG1lYXM9J0ZQS00nLCANCiAgICAgICAgICAgICAgICBjb2xvcmJ5PSd0cmFuc2NyaXB0JywgDQogICAgICAgICAgICAgICAgbWFpbj0ndHJhbnNjcmlwdHMgZnJvbSBnZW5lIE1TVFJHLjE1MzU4OiBzYW1wbGVzIHBmY18wNC1wZmNfMDYsIEZQS00nKQ0KYGBgDQoNCg0KDQojIyMjIHBsb3RNZWFucyBmb3IgZ3JvdXBzIChzYWxpbmU9MCBhbmQgbmljb3RpbmU9MSkNCg0KYGBge3J9DQoNCnBsb3RNZWFucygnTVNUUkcuMTUzNTgnLCBiZywgZ3JvdXB2YXI9J2dyb3VwJywgbWVhcz0nRlBLTScsIGNvbG9yYnk9J3RyYW5zY3JpcHQnKQ0KDQpgYGANCg0KDQoNCiMjIyBGdXJ0aGVyIGFuYWx5c2lzOiBNU1RSRy4xNzI2NC90cmFuc2NyaXB0IGlkID0gMjUzODQNCg0KIyMjIyBwbG90VHJhbnNjcmlwdHMgZm9yIGEgc2luZ2xlIHNhbGluZSBzYW1wbGUgKHBmY18wMSkNCg0KDQpgYGB7cn0NCnBsb3RUcmFuc2NyaXB0cyhnZW5lPSdNU1RSRy4xNzI2NCcsIA0KICAgICAgICAgICAgICAgIGdvd249YmcsIA0KICAgICAgICAgICAgICAgIHNhbXBsZXM9InBmY18wMSIsDQogICAgICAgICAgICAgICAgbWVhcz0nRlBLTScsIA0KICAgICAgICAgICAgICAgIGNvbG9yYnk9J3RyYW5zY3JpcHQnLCANCiAgICAgICAgICAgICAgICBtYWluPSd0cmFuc2NyaXB0cyBmcm9tIGdlbmUgTVNUUkcuMTcyNjQ6IHNhbXBsZXMgcGZjXzAxLXBmY18wMywgRlBLTScpDQpgYGANCg0KIyMjIyBwbG90VHJhbnNjcmlwdHMgZm9yIHNhbGluZSB0cmVhdGVkIHNhbXBsZXMgKHBmY18wMSwgcGZjXzAyLCBwZmNfMDMpDQoNCg0KYGBge3J9DQpwbG90VHJhbnNjcmlwdHMoZ2VuZT0nTVNUUkcuMTcyNjQnLCANCiAgICAgICAgICAgICAgICBnb3duPWJnLCANCiAgICAgICAgICAgICAgICBzYW1wbGVzPWMoInBmY18wMSIsICJwZmNfMDIiLCAicGZjXzAzIiksDQogICAgICAgICAgICAgICAgbWVhcz0nRlBLTScsIA0KICAgICAgICAgICAgICAgIGNvbG9yYnk9J3RyYW5zY3JpcHQnLCANCiAgICAgICAgICAgICAgICBtYWluPSd0cmFuc2NyaXB0cyBmcm9tIGdlbmUgTVNUUkcuMTcyNjQ6IHNhbXBsZXMgcGZjXzAxLXBmY18wMywgRlBLTScpDQpgYGANCg0KIyMjIyBwbG90VHJhbnNjcmlwdHMgZm9yIG5pY290aW5lIHRyZWF0ZWQgc2FtcGxlcyAocGZjXzA0LCBwZmNfMDUsIHBmY18wNikNCg0KDQpgYGB7cn0NCnBsb3RUcmFuc2NyaXB0cyhnZW5lPSdNU1RSRy4xNzI2NCcsIA0KICAgICAgICAgICAgICAgIGdvd249YmcsIA0KICAgICAgICAgICAgICAgIHNhbXBsZXM9YygicGZjXzA0IiwgInBmY18wNSIsICJwZmNfMDYiKSwNCiAgICAgICAgICAgICAgICBtZWFzPSdGUEtNJywgDQogICAgICAgICAgICAgICAgY29sb3JieT0ndHJhbnNjcmlwdCcsIA0KICAgICAgICAgICAgICAgIG1haW49J3RyYW5zY3JpcHRzIGZyb20gZ2VuZSBNU1RSRy4xNzI2NDogc2FtcGxlcyBwZmNfMDQtcGZjXzA2LCBGUEtNJykNCmBgYA0KDQojIyMjIHBsb3RNZWFucyBmb3IgZ3JvdXBzIChzYWxpbmU9MCBhbmQgbmljb3RpbmU9MSkNCg0KDQpgYGB7cn0NCg0KcGxvdE1lYW5zKCdNU1RSRy4xNzI2NCcsIGJnLCBncm91cHZhcj0nZ3JvdXAnLCBtZWFzPSdGUEtNJywgY29sb3JieT0ndHJhbnNjcmlwdCcpDQoNCmBgYA0KDQoNCiMjIyBQbG90IHRoZSBzdHJ1Y3R1cmUgYW5kIGV4cHJlc3Npb24gbGV2ZWxzIGluIGEgc2FtcGxlIG9mIGFsbCB0cmFuc2NyaXB0cyB0aGF0IHNoYXJlIHRoZSBzYW1lIGdlbmUgbG9jdXMNCg0KYGBge3J9DQppZHggPC0gd2hpY2goZ2VuZUlEcyhiZyk9PSJNU1RSRy4xNzI2NCIpDQppZHgNCmBgYA0KDQojIyMjIHN0cnVjdHVyZSBhbmQgZXhwcmVzc2lvbiBsZXZlbHMgaW4gYSBzYW1wbGUgKHBmY18wMSkgb2YgYWxsIHRyYW5zY3JpcHRzIHRoYXQgc2hhcmUgdGhlIGdlbmUgbG9jdXMgMjUzODINCg0KDQpgYGB7cn0NCg0KcGxvdFRyYW5zY3JpcHRzKGJhbGxnb3duOjpnZW5lSURzKGJnKVsyNTM4Ml0sDQogICAgICAgICAgICAgICAgYmcsDQogICAgICAgICAgICAgICAgbWFpbj1jKCdHZW5lIE1TVFJHLjE3MjY0IGluIHNhbXBsZSBwZmNfMDEnKSwNCiAgICAgICAgICAgICAgICBzYW1wbGU9YygncGZjXzAxJykpDQoNCmBgYA0KIyMjIyBzdHJ1Y3R1cmUgYW5kIGV4cHJlc3Npb24gbGV2ZWxzIGluIGEgc2FtcGxlIChwZmNfMDEpIG9mIGFsbCB0cmFuc2NyaXB0cyB0aGF0IHNoYXJlIHRoZSBnZW5lIGxvY3VzIDI1Mzg0DQoNCg0KYGBge3J9DQoNCnBsb3RUcmFuc2NyaXB0cyhiYWxsZ293bjo6Z2VuZUlEcyhiZylbMjUzODRdLA0KICAgICAgICAgICAgICAgIGJnLA0KICAgICAgICAgICAgICAgIG1haW49YygnR2VuZSBNU1RSRy4xNzI2NCBpbiBzYW1wbGUgcGZjXzAxJyksDQogICAgICAgICAgICAgICAgc2FtcGxlPWMoJ3BmY18wMScpKQ0KDQpgYGANCg0KDQoNCiMjIyBBbm90aGVyIGV4YW1wbGU6IFBsb3QgdGhlIHN0cnVjdHVyZSBhbmQgZXhwcmVzc2lvbiBsZXZlbHMgaW4gYSBzYW1wbGUgb2YgYWxsIHRyYW5zY3JpcHRzIHRoYXQgc2hhcmUgdGhlIHNhbWUgZ2VuZSBsb2N1cw0KDQpgYGB7cn0NCmlkeDIgPC0gd2hpY2goZ2VuZUlEcyhiZyk9PSJNU1RSRy4xNTM1OCIpDQppZHgyDQpgYGANCg0KIyMjIyBzdHJ1Y3R1cmUgYW5kIGV4cHJlc3Npb24gbGV2ZWxzIGluIGEgc2FtcGxlIChwZmNfMDEpIG9mIGFsbCB0cmFuc2NyaXB0cyB0aGF0IHNoYXJlIHRoZSBnZW5lIGxvY3VzIDIyNjU2DQoNCmBgYHtyfQ0KDQpwbG90VHJhbnNjcmlwdHMoYmFsbGdvd246OmdlbmVJRHMoYmcpWzIyNjU2XSwNCiAgICAgICAgICAgICAgICBiZywNCiAgICAgICAgICAgICAgICBtYWluPWMoJ0dlbmUgTVNUUkcuMTUzNTggaW4gc2FtcGxlIHBmY18wMScpLA0KICAgICAgICAgICAgICAgIHNhbXBsZT1jKCdwZmNfMDEnKSkNCg0KYGBgDQoNCg0KDQojIyMjIHN0cnVjdHVyZSBhbmQgZXhwcmVzc2lvbiBsZXZlbHMgaW4gYSBzYW1wbGUgKHBmY18wMSkgb2YgYWxsIHRyYW5zY3JpcHRzIHRoYXQgc2hhcmUgdGhlIGdlbmUgbG9jdXMgMjI2NTcNCg0KYGBge3J9DQoNCnBsb3RUcmFuc2NyaXB0cyhiYWxsZ293bjo6Z2VuZUlEcyhiZylbMjI2NTddLA0KICAgICAgICAgICAgICAgIGJnLA0KICAgICAgICAgICAgICAgIG1haW49YygnR2VuZSBNU1RSRy4xNTM1OCBpbiBzYW1wbGUgcGZjXzAxJyksDQogICAgICAgICAgICAgICAgc2FtcGxlPWMoJ3BmY18wMScpKQ0KDQpgYGANCg0KDQojIyMgUGxvdHMgb2YgaW5kaXZpZHVhbCB0cmFuc2NyaXB0cyBhY3Jvc3Mgc2FtcGxlOiBNU1RSRy4xNTM1OA0KDQpgYGB7cn0NCmlkeDQgPC0gd2hpY2goZ2VuZUlEcyhiZyk9PSJNU1RSRy4xNTM1OCIpDQppZHg0DQpgYGANCg0KYGBge3J9DQpiYWxsZ293bjo6dHJhbnNjcmlwdE5hbWVzKGJnKVsyMjY1Nl0NCmBgYA0KDQoNCmBgYHtyfQ0KcGxvdChmcGttWzIyNjU2LF0gfiBwRGF0YShiZykkZ3JvdXAsDQogICAgIG1haW49cGFzdGUoYmFsbGdvd246OmdlbmVOYW1lcyhiZylbMjI2NTZdLCcgOiAnLCBiYWxsZ293bjo6dHJhbnNjcmlwdE5hbWVzKGJnKVsyMjY1Nl0pLCANCiAgICAgcGNoPTE5LA0KICAgICB4bGFiPSJUcmVhdG1lbnQiLA0KICAgICB5bGFiPSdsb2cyKEZQS00rMSknKQ0KDQpwb2ludHMoZnBrbVsyMjY1NixdIH4gaml0dGVyKGFzLm51bWVyaWMocERhdGEoYmcpJGdyb3VwKSksIGNvbD1hcy5udW1lcmljKHBEYXRhKGJnKSRncm91cCkpDQpgYGANCg0KDQpgYGB7cn0NCnBsb3QoZnBrbVsyMjY1NyxdIH4gcERhdGEoYmcpJGdyb3VwLA0KICAgICBtYWluPXBhc3RlKGJhbGxnb3duOjpnZW5lTmFtZXMoYmcpWzIyNjU3XSwnIDogJywgYmFsbGdvd246OnRyYW5zY3JpcHROYW1lcyhiZylbMjI2NTddKSwgDQogICAgIHBjaD0xOSwNCiAgICAgeGxhYj0iVHJlYXRtZW50IiwNCiAgICAgeWxhYj0nbG9nMihGUEtNKzEpJykNCg0KcG9pbnRzKGZwa21bMjI2NTcsXSB+IGppdHRlcihhcy5udW1lcmljKHBEYXRhKGJnKSRncm91cCkpLCBjb2w9YXMubnVtZXJpYyhwRGF0YShiZykkZ3JvdXApKQ0KYGBgDQoNCg0KDQoNCiMjIyBQbG90cyBvZiBpbmRpdmlkdWFsIHRyYW5zY3JpcHRzIGFjcm9zcyBzYW1wbGU6IE1TVFJHLjE3MjY0DQoNCmBgYHtyfQ0KaWR4MyA8LSB3aGljaChnZW5lSURzKGJnKT09Ik1TVFJHLjE3MjY0IikNCmlkeDMNCmBgYA0KDQpgYGB7cn0NCmJhbGxnb3duOjp0cmFuc2NyaXB0TmFtZXMoYmcpWzI1MzgyXQ0KYGBgDQoNCg0KYGBge3J9DQpwbG90KGZwa21bMjUzODIsXSB+IHBEYXRhKGJnKSRncm91cCwNCiAgICAgbWFpbj1wYXN0ZShiYWxsZ293bjo6Z2VuZU5hbWVzKGJnKVsyNTM4Ml0sJyA6ICcsIGJhbGxnb3duOjp0cmFuc2NyaXB0TmFtZXMoYmcpWzI1MzgyXSksIA0KICAgICBwY2g9MTksDQogICAgIHhsYWI9IlRyZWF0bWVudCIsDQogICAgIHlsYWI9J2xvZzIoRlBLTSsxKScpDQoNCnBvaW50cyhmcGttWzI1MzgyLF0gfiBqaXR0ZXIoYXMubnVtZXJpYyhwRGF0YShiZykkZ3JvdXApKSwgY29sPWFzLm51bWVyaWMocERhdGEoYmcpJGdyb3VwKSkNCmBgYA0KDQoNCmBgYHtyfQ0KYmFsbGdvd246OnRyYW5zY3JpcHROYW1lcyhiZylbMjUzODRdDQpgYGANCg0KDQoNCmBgYHtyfQ0KcGxvdChmcGttWzI1Mzg0LF0gfiBwRGF0YShiZykkZ3JvdXAsDQogICAgIG1haW49cGFzdGUoYmFsbGdvd246OmdlbmVOYW1lcyhiZylbMjUzODRdLCcgOiAnLCBiYWxsZ293bjo6dHJhbnNjcmlwdE5hbWVzKGJnKVsyNTM4NF0pLCANCiAgICAgcGNoPTE5LA0KICAgICB4bGFiPSJUcmVhdG1lbnQiLA0KICAgICB5bGFiPSdsb2cyKEZQS00rMSknKQ0KDQpwb2ludHMoZnBrbVsyNTM4NCxdIH4gaml0dGVyKGFzLm51bWVyaWMocERhdGEoYmcpJGdyb3VwKSksIGNvbD1hcy5udW1lcmljKHBEYXRhKGJnKSRncm91cCkpDQpgYGANCg0KDQpgYGB7cn0NCnBsb3QoZnBrbVsyNTM4NCxdIH4gcERhdGEoYmcpJGdyb3VwLA0KICAgICBtYWluPXBhc3RlKGJhbGxnb3duOjpnZW5lTmFtZXMoYmcpWzI1Mzg0XSwnIDogJywgYmFsbGdvd246OnRyYW5zY3JpcHROYW1lcyhiZylbMjUzODRdKSwgDQogICAgIHBjaD0xOSwNCiAgICAgeGxhYj0iVHJlYXRtZW50IiwNCiAgICAgeWxhYj0nbG9nMihGUEtNKzEpJykNCg0KcG9pbnRzKGZwa21bMjUzODQsXSB+IGppdHRlcihhcy5udW1lcmljKHBEYXRhKGJnKSRncm91cCkpLCBjb2w9YXMubnVtZXJpYyhwRGF0YShiZykkZ3JvdXApKQ0KYGBgDQoNCg0KDQojIyMgU29tZSBhZGRpdGlvbmFsIHBsb3R0aW5nOiBQbG90IHRoZSBhdmVyYWdlIGV4cHJlc3Npb24gbGV2ZWxzIGZvciBhbGwgdHJhbnNjcmlwdHMgb2YgYSBnZW5lIHdpdGhpbiBkaWZmZXJlbnQgZ3JvdXBzIA0KDQoNCg0KYGBge3J9DQpwbG90TWVhbnMoJ01TVFJHLjg0MjUnLCBiZywgZ3JvdXB2YXI9J2dyb3VwJywgbWVhcz0nRlBLTScsIGNvbG9yYnk9J3RyYW5zY3JpcHQnKQ0KYGBgDQoNCmBgYHtyfQ0KDQpwbG90TWVhbnMoJ01TVFJHLjg0MjUnLCBiZ19maWx0LCBncm91cHZhcj0nZ3JvdXAnLCBtZWFzPSdGUEtNJywgY29sb3JieT0ndHJhbnNjcmlwdCcpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQpwbG90TWVhbnMoJ01TVFJHLjg4NTEnLCBiZywgZ3JvdXB2YXI9J2dyb3VwJywgbWVhcz0nRlBLTScsIGNvbG9yYnk9J3RyYW5zY3JpcHQnKQ0KYGBgDQoNCmBgYHtyfQ0KcGxvdE1lYW5zKCdNU1RSRy44ODUxJywgYmdfZmlsdCwgZ3JvdXB2YXI9J2dyb3VwJywgbWVhcz0nRlBLTScsIGNvbG9yYnk9J3RyYW5zY3JpcHQnKQ0KYGBgDQoNCg0KDQoNCg==