Hands-on Somatic Variant Analysis in Galaxy and IGV

Sheffield Bioinformatics Core

web : sbc.shef.ac.uk
twitter: SheffBioinfCore
email: bioinformatics-core@sheffield.ac.uk


Tutorial Overview

This tutorial will cover the basics of Somatic analysis using Galaxy; a open-source web-based platform for the analysis of biological data. You should gain an appreciation of the tasks involved in a typical NGS analysis and be comfortable with the outputs generated by a sequencing service. You will also use the Integrative Genomics Viewer (IGV) to view the aligned reads in an interactive manner.

We will use training materials provided by the Galaxy Project and sign-post to relevant sections. If you want to find more detailed tutorials on IGV or Galaxy you can follow the links below:-


Background

Where do the data in this tutorial come from?

The data for this tutorial are from a cancer patient down-sampled to genes that are present in the COSMIC dataset. We will use these data throughout the course to call variants, filter and discuss the clinical impact of any mutations.

Preparation and Data Upload

If attending this workshop in-person you should have access to a private queue on the usegalaxy.eu server that will allow your jobs to run quicker.

Follow this link to register an account:-

https://usegalaxy.eu/join-training/sbc-somatic-2019-05-10

Otherwise, register as a new user on one of the public Galaxy servers

Make sure you check your email to activate your account

Import the data for the workshop.

We can going to import the fastq files for this experiment. This is a standard format for storing raw sequencing reads and their associated quality scores. However, as we will see, the representation of the quality scores has changed over time.

The fastq files for this workshop have been uploaded to google drive folder

Download all the files ending in fastq.gz and fasta.gz in this directory to your laptop

You can import the data by:

  1. In the tool panel located on the left, select Get Data > Upload File.
  2. Choose local file and browse to the directory containing the files from the google drive and select all the file. Click Open to close the file browser. The names of the files should now appear in Galaxy.
  3. Click Start to begin the upload

  4. You should now have these 5 files in your history:

  • 231335_cancer_genes_r1.fastq.gz
  • 231335_cancer_genes_r2.fastq.gz
  • 231336_cancer_genes_r1.fastq.gz
  • 231336_cancer_genes_r2.fastq.gz
  • hg19.chr5_12_17.fasta.gz

where the first two files represent the forward and reverse reads sequence data from a patient’s normal tissue, and the next two represent the data of the same patient’s tumor tissue. The final file is a cut-down reference genome for chromosomes 5, 12 and 17 only.

Section 2: Fastq file format

You can view the files you just uploaded by clicking the eye icon the history item. The first few lines should read as follows

231336_cancer_genes_r1.fastq.gz

@ST-K00265:137:HT33CBBXX:3:1213:9952:2738/1
CGGACCCCCGACATGTCTGCTGTTGCCGCCGCGCAGTCCCGCCAGTCCCTGCGCAGACTGCGCCTGCGCACCACACCGGGGTCGAGCTGGCGGGGGAGGGG
+
-AF-A<AAA7AA-AF<F7AJAJF<AJF777FAJJFJJ7-A-7-FJAAA-AFJJ<7F7F<FJ7-A-FJA<J7J77<<FJ<JJ<<JAFJ<7FJJJJ-J-A<7A

231336_cancer_genes_r2.fastq.gz

@ST-K00265:137:HT33CBBXX:3:1107:2047:6378/1
CCAGCTCGACCCCGGTGTGGTGCGCAGGCGCAGTCTGCGCAGGGACTGGCGGGACTGCGCGGCGGCAACAGCAGACATGTCGGGGGTCCGGGGCCTGTCGC
+
AA<AAFJFAJ7A-A7--AFA<FJFJJ7FFJAJ7-7-7FJJJJFJ7FFJJ7FA<<F<7FJJAAJJA<JJJFFJJ<AJF<JJFJA-<7AJJA<-AF-JJJJJ-

The first line is the unique identifier for each sequenced read. It can be used to encode information such as the sequencing machine, flow cell and lane that the read was generated from and the physical coordinates on the lane.

The quality scores are ASCII representations of how confident we are that a particular base has been called correctly. Letters that are further along the alphabet indicate higher confidence. This is important when trying to identify types of genome variation such as single base changes, but is also indicative of the overall quality of the sequencing. Different scales have been employed over time (resulting in a different set of characters appearing in the file). .

Deriving the Quality Score

First of all, we convert the base-calling probability (p) into a Q score using the formula

Quality Scores to probabilities

  • look-up the ASCII code for each character
  • subtract the offset to get the Q score
  • convert to a probability using the formula:-

\[ p = 10^{-Q/10} \]

Let’s see this calculation for the first few bases of the first read in 231336_cancer_genes_r1.fastq; -AF-A<AAA7....

Character Code Minus 33 Offset Probability
- 45 12 0.0631
A 65 32 0.0006
F 70 37 0.0002
- 45 12 0.0631
A 65 32 0.0006
< 60 27 0.0020
A 65 32 0.0006
A 65 32 0.0006

In practice, we don’t have to convert the values as we have software that will do this automatically


Section 3: Quality Assessment of NGS reads

FastQC is a popular tool from Babraham Institute Bioinformatics Group used for quality assessment of sequencing data. Most Bioinformatics pipelines will use FastQC, or similar tools in the first stage of the analysis. The documentation for FastQC will help you to interpret the plots and stats produced by the tool. A traffic light system is used to alert the user’s attention to possible issues.

The most important image is whether the base quality decreases significantly over the length of the read

Good quality data should look something like:-

We will now follow the relevant section on the Galaxy training page for QC and alignment

https://training.galaxyproject.org/training-material/topics/variant-analysis/tutorials/somatic-variants/tutorial.html#quality-control-and-mapping-of-ngs-reads

Section 4: Alignment

The result of the previous practical will be a .bam file that we will describe in the next section. This file is not human-readable, as it is compresed. But we can convert to a readable format for illustration purposes.

Viewing the alignments

Click on the eye of the resulting file to view the alignments.

A single standard file format has emerged for aligned reads. Moreoever, this file format is consistent regardless of whether you have DNA-seq, RNA-seq, ChIP-seq… data.

The bam file is a compressed, binary, version of a sam file.

  • Sequence Alignment/Map (sam)
  • The output from an aligner such as bwa
  • Same format regardless of sequencing protocol (i.e. RNA-seq, ChIP-seq, DNA-seq etc)
  • May contain un-mapped reads
  • Potentially large size on disk; ~100s of Gb
    • Can be manipulated with standard unix tools; e.g. cat, head, grep, more, less….
  • Official specification can be obtained online: -
  • We normally work on a compressed version called a .bam file. See later.
  • Header lines starting with an @ character, followed by tab-delimited lines
    • Header gives information about the alignment and references sequences used

The first part of the header lists the names (SN) of the sequences (chromosomes) used in alignment, their length (LN) and somtimes a md5sumdigital fingerprint” of the .fasta file used for alignment (M5).

@HD VN:1.3 SO:coordinate
@SQ SN:chr5 LN:180915260
@SQ SN:chr12 LN:133851895
@SQ SN:chr17 LN:81195210
@RG ID:231335 SM:Normal PL:ILLUMINA

We also have a section where we can record the processing steps used to derive the file

@PG ID:bwa PN:bwa VN:0.7.17-r1188 CL:bwa mem -t 8 -v 1 -R @RG\tID:231335\tSM:Normal\tPL:ILLUMINA localref.fa /data/dnb02/galaxy_db/files/009/352/dataset_9352452.dat /data/dnb02/galaxy_db/files/009/352/dataset_9352453.dat

Next is a tab-delimited section that describes the alignment of each sequence in detail.

ST-K00265:137:HT33CBBXX:3:2106:5944:11759   99  chr5    218378  60  101M    =   218465  188 GTATCCCCCCTCCCCCGCCAGCTCGACCCCGGTGTGGTGCGCAGGCGCAGTCTGCGCAGGGACTGGCGGGACTGCGCGGCGGCAACAGCAGACATGTCGGG   AAFFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ   NM:i:0 MD:Z:101 MC:Z:101M AS:i:101 XS:i:50 RG:Z:231335
Column Official Name Brief
1 QNAME Sequence ID
2 FLAG Sequence quality expressed as a bitwise flag
3 RNAME Chromosome
4 POS Start Position
5 MAPQ Mapping Quality
6 CIGAR Describes positions of matches, insertions, deletions w.r.t reference
7 RNEXT Ref. name of mate / next read
8 PNEXT Postion of mate / next read
9 TLEN Observed Template length
10 SEQ Sequence
11 QUAL Base Qualities

There can also be all manner of optional tags as extra columns introduce by an aligner or downstream analysis tool. A common use is the RG tag which refers back to the read groups in the header.

Sorting and indexing

You will notice from the 3rd column that the reads are ordered according to their start position; whereas the reads in the fastq file were arranged in order that they were generated on the flow cell. By default, bwa-mem produces a bam where the reads are in the same order as the fastq. However, this is rather incovenient for analysis where we require reads from the same location to be next to each other in the file.

An additional couple of steps have been performed after bowtie2; sorting the file according to genome position and producing an index file. The index file does not provide any useful information for us and cannot be viewed in Galaxy. However, we will need it later on when viewing the data in IGV.

Dr Mark Dunning presents….Fun with flags!

The “flags” in the sam file can represent useful QC information

  • Read is unmapped
  • Read is paired / unpaired
  • Read failed QC
  • Read is a PCR duplicate (see later)

The combination of any of these properties is used to derive a numeric value

For instance, a particular read has a flag of 163

Derivation

There is a set of properties that a read can possess. If a particular property is observed, a corresponding power of 2 is added multiplied by 1. The final value is derived by summing all the powers of 2.

Flag Value Meaning
69 (= 1 + 4 + 64) The read is paired, is the first read in the pair, and is unmapped.
77 (= 1 + 4 + 8 + 64) The read is paired, is the first read in the pair, both are unmapped.
83 (= 1 + 2 + 16 + 64) The read is paired, mapped in a proper pair, is the first read in the pair, and it is mapped to the reverse strand.
99 (= 1 + 2 + 32 + 64) The read is paired, mapped in a proper pair, is the first read in the pair, and its mate is mapped to the reverse strand.
133 (= 1 + 4 + 128) The read is paired, is the second read in the pair, and it is unmapped.
137 (= 1 + 8 + 128) The read is paired, is the second read in the pair, and it is mapped while its mate is not.
141 (= 1 + 4 + 8 + 128) The read is paired, is the second read in the pair, but both are unmapped.
147 (= 1 + 2 + 16 + 128) The read is paired, mapped in a proper pair, is the second read in the pair, and mapped to the reverse strand.
163 (= 1 + 2 + 32 + 128) The read is paired, mapped in a proper pair, is the second read in the pair, and its mate is mapped to the reverse strand.

See also

Have a CIGAR!

The CIGAR (Compact Idiosyncratic Gapped Alignment Report) string is a way of encoding the match between a given sequence and the position it has been assigned in the genome. It is comprised by a series of letters and numbers to indicate how many consecutive bases have that mapping.

Code Description
M alignment match
I insertion
D deletion
N skipped
S soft-clipping
H hard-clipping

e.g.

  • 68M
    • 68 bases matching the reference
  • 1S67M
    • 1 soft-clipped read followed by 67 matches
  • 15M87N70M90N16M
    • 15 matches following by 87 bases skipped followed by 70 matches etc.

Checking the alignment stats

We will now generate a few basic statistics about the alignment of our data

  1. Select the tool NGS: SAMtools -> Flagstat
  2. In the BAM File to Convert box choose the bam file produced by bwa-mem.

The tool will also report how many PCR Duplicates have been found in the data. But as we haven’t yet run any software to identify such reads, the flagstat output will show 0 reads.

  1. Find the tool SAMtools -> Idxstats
  2. In the BAM file dropdown select the bam file produced by bowtie2

The output of this tool will tell you how many reads aligned to each chromosome in your reference genome.

Optional Exercise: The multiqc tool that we introduced earlier is about to interpet the output of flagstat and idxstats. Create a report the combines the results of these metrics with the fastqc reports on the fastq files

Download your bam file

For the next setp you will need to download the bam file. To do this, you can click the floppy disk icon.

Make sure that you click both Download dataset and Download bam_index

If you have problems creating the bam file, a pre-prepared file is available from the google drive

https://drive.google.com/drive/folders/1-S8d92NmcQ7RfVjtP-FEtCizZnj_GTvX?usp=sharing

Section 5. Visualising the aligned reads with IGV

Whilst Bioinformatics tools are very powerful and allow you to perform statistical analyses and test hypotheses, there is no substitute for looking at and exploring the data. A trained-eye can quite quickly get a sense of the data quality before any computational analyses have been run. Futhermore, as the person requesting the sequencing, you probably know a lot about the biological context of the samples and what to expect.

We will load the aligned reads that we have just created into IGV and start to get a feel for the process of variant calling

  1. Download IGV

You can download IGV for Windows using this link

Extract the zip file that you have downloaded

Double-Click the file igv to launch IGV

  1. Load a reference Genome and some Data Tracks

By default, IGV should load with Human genome version hg19 already loaded. It is essential that you use the same genome version that the reads were aligned to. You can check / change the genome by clicking the drop-down menu in the upper-left

We can also load extra tracks into the browser that can help us understand our variant calls. For example, we can load data from dbSNP which will tell us about common mutations that already been identified. These can be loaded via File -> Load from Server.. and selecting dbSNP 1.4.7 from the Variation and Repeats section

  1. Navigate around IGV

When IGV loads up we start with a very high-level view of the genome where all chromosomes are visible. Such a view might be useful if we were interested in large copy-number variation across a cohort of samples. However, we are mostly interested in changes at the individual base-level which is not possible to view at this resolution. We need to navigate to a particular region of interest.

Alongside the drop-down menu used to change the genome, there is a drop-down menu to select a particular chromosome and a box where we can enter text. Inside the text box we can enter a particular genome interval of interest

e.g. chr1:10,000-11,000

IGV should now be displaying a region on chromosome 1 from base position 10,000 to 11,000.

At this resolution, we can start to see the genome sequence. Each DNA base is represented by a different colour (A = green, C = blue) and it seems that this region is highly-repetitive; comprising mostly C bases. We can zoom fruther in using the zoom control in the top right of IGV

We can use the zoom control, and also move along the genome by holding down by mouse button and sliding left-and-right, to navigate to whatever genomic location we want. If we known the name of the gene we want to interrogate we can navigate directly there using the text box

The text box should now update to show the coordinates of BRCA1 (chr17:....). At the bottom of the screen we can now see the gene model for the gene BRCA1. Genes are represented as lines and boxes. Lines represent intronic regions and boxes represent exonic regions. The arrows indicate the direction / strand of transcription for the gene.

  1. Load the aligned reads

Choose File > Load from File…, select the bam file that you downloaded from Galaxy, and click OK. Note that the bam and index files must be in the same directory for IGV to load these properly.

The main display of IGV should now update to hold tracks for the aligned reads from this bam file. It may seem like nothing is being displayed. This is because we are zoomed-out too far to be able to see the reads. Use the zoom function and move along the genome until you get to the first exon of BRCA1. After you have zoomed-in far enough you will start to see some grey rectangles. These are the aligned reads.

If you hover over a particular read, how will see columns from the bam file being displayed such as the mapping quality and information about the paired reads.

Discussion:

Later on we will have some more examples of inspecting variants, but for now let’s familiarise ourselves with IGV and what the data look like

  • Navigate to region chr17:41,244,228-41,245,700 in IGV. How many potential SNVs can you find inside the region? How many of these are likely to be somatic.

  • Navigate to position chr17:41,219,513 in IGV. Hover over the coverage track and discover the percentage of reference bases in the Tumour and the Normal. Is there evidence for a somatic variant at this position?

Section 6: Post-processing of reads and Variant Calling

Whilst we can inspect variants by eye, it would clearly be impossible to scrutinise each position in the genome to see if a variants exists there. We will employ a variant calling method to narrow-down our search for somatic variants, although as we will see, such calls still require some degree of filtering and curation. The particular tool we will use is varscan2, mainly because it is available via Galaxy. For production-level analyses a tool such as MuTect could be considered. However, there are licensing issues which preclude MuTect from being available in Galaxy.

Before we can proceed to variant calling, there are a couple of post-processing tasks that should be performed; removing duplicates and indel re-alignment.

In brief, removing duplicates removes reads that have exactly the same start and end position. Such reads are assumed to be an artefact of the PCR process and give a false impression of the coverage at affected positions. However, careful thinking is required in situations other than whole-genome sequencing and this should certainly never be applied for targeted sequencing.

Indel re-alignment deals with an artefact that can occur when placing reads close to indels. Since each read is aligned separately, alignment tools may prefer to align a read with a reference mismatch rather than consider an indel within a read. However, taking all reads into consideration around a locus may reveal the presence of an indel and prevent SNVs being falsely identified.

Before realignment

After realignment

(see this video for an explanation)

Now follow the steps in “Mapped Reads postprocessing” from the galaxy training page, before proceeding to “Variant calling and classification”

Section 7: Annotation

About vcf format

In the previous section, you will have produced a vcf file. The .vcf format was initially developed by the 1000 Genomes Project, and ownership has been subsequently transferred to Global Alliance for Genomics and Health Data Working group file format team. The format can be used to represent information about all kinds of genomic variation. In this session we will just consider SNVs.

We don’t require any specialised software to look at the contents of a vcf file. They can be opened in a bog-standard text editor, however your laptop may try and interpret the file as containing contact information (virtual contact file).

In a similar vein to the .bam and .sam files we saw earlier, the .vcf files contains many lines of header information. These describe the reference sequences and various filters that have been applied.

##fileformat=VCFv4.2
##FILTER=<ID=PASS,Description="All filters passed">
##reference=ref.fa
##contig=<ID=chr5,length=180915260>
##contig=<ID=chr12,length=133851895>
##contig=<ID=chr17,length=81195210>
##FILTER=<ID=VarCount,Description="Fewer than 4 variant-supporting reads">
##FILTER=<ID=VarFreq,Description="Variant allele frequency below 0.05">
##FILTER=<ID=VarAvgRL,Description="Average clipped length of variant-supporting reads < 90">
......
......

After many more lines of information, we finally get to the details of the actual calls themsevles. This part of the file is tab-delimited; with 10 columns for every call. The vcf specification page gives details of what should be contained in each column

Shown here is the information about three calls

#CHROM  POS ID  REF ALT QUAL    FILTER  INFO    FORMAT  NORMAL  TUMOR
chr5    225768  .   G   C   .   VarReadPos  DP=27;SS=1;SSC=0;GPV=5.1363e-16;SPV=1   GT:GQ:DP:AD:ADF:ADR 1/1:.:16:0,16:0,2:0,14  1/1:.:11:0,11:0,1:0,10
chr5    230980  .   A   G   .   PASS    DP=157;SS=1;SSC=0;GPV=0;SPV=1   GT:GQ:DP:AD:ADF:ADR 1/1:.:88:0,88:0,51:0,37 1/1:.:69:0,69:0,45:0,24
chr5    231111  .   T   C   .   PASS    DP=127;SS=1;SSC=0;GPV=0;SPV=1   GT:GQ:DP:AD:ADF:ADR 1/1:.:75:0,75:0,39:0,36 1/1:.:52:0,52:0,26:0,26

The first seven columns should look consistent across different genotype callers. The contents of the INFO and FORMAT columns will depend on what variant caller has been used. The INFO column contains metrics and other information related to each variant call as a set of KEY=VALUE pairs. Each pair is separated by a ; character.

The INFO for the a variant call may read as:-

DP=27;SS=1;SSC=0;GPV=5.1363e-16;SPV=1

or

      Key   Value
DP=27 DP    27
SS=1  SS    1
SSC=0 SSC   0
GPV=5.1.. GPV   5.1363e-16
SPV=1 SPV   1

The meaning of each key can be discovered by looking at the header for the file. e.g. ##FORMAT=<ID=DP,Number=1,Type=Integer,Description="Read depth">. So this variant has a total of 27 bases covering it.

The final two columns in the file describes the calls for the NORMAL and TUMOUR samples respectively. In the sample column (NORMAL) for the first variant we see the entry

1/1:.:16:0,16:0,2:0,14

These are values separated by a : character and they are interpreted in the same order as dictated by the FORMAT column; which is GT:GQ:DP:AD:ADF:ADR

##FORMAT=<ID=GT,Number=1,Type=String,Description=Genotype>
##FORMAT=<ID=GQ,Number=1,Type=Integer,Description="Genotype quality">
##FORMAT=<ID=DP,Number=1,Type=Integer,Description="Read depth">
##FORMAT=<ID=AD,Number=R,Type=Integer,Description="Read depth for each allele">
##FORMAT=<ID=ADF,Number=R,Type=Integer,Description="Read depth for each allele on the forward strand">
##FORMAT=<ID=ADR,Number=R,Type=Integer,Description="Read depth for each allele on the reverse strand">

So for this particular variant there is a genotype of 1\1 (Homozygous for the alternate allele) in the normal sample and a depth of 16 etc. The same genotype information is repeated for the tumour. From this we can infer whether the variant is likely to be somatic or not and gain insight into whether it is a true variant or a false positive (which we will discuss in detail later).

Discussion: Locate the lines in the vcf file that relate to some of the positions that we looked at previously in IGV. How many reads in total cover each position?

  • chr17:41244936
  • chr17:41219513
  • chr17:41234304

What kind of variants (Germline, Somatic) have been called at these positions?

You can also load the vcf into IGV, which will display details of each variant call above the aligned reads.

Annotating with SNPeff

As we have seen the standard vcf file contains genome coordinates for each variant, but gives no useful information about what gene (if any) the variant lies within or the potential impact of the variant. One such tool for adding genomic information is SNPeff which is described in the Galaxy tutorial.

  • See here; “Adding functional genomic annotations” only

SNPeff will produce a modified vcf file and a HTML report.

Discussion: Scroll through the contents of the vcf file produced by snpeff. What extra information has it added? Try and locate the variants within BRCA1. Also take some time to digest the contents of the HTML report and the information it provides

Annotation with Ensembl VEP

A useful alternative to running SNPeff within Galaxy is the online VEP tool provided by Ensembl. This will annotate our variants with gene identifiers and also provide some predictions about the impact of the variant.

More documentation on Ensembl VEP is available online

Command line tools are available, but we will use the online interface; making sure that we access the version of VEP with the correct genome version. Going straight to the Ensembl VEP website will mean using a later genome build.

The hg19 version of VEP can be accessed here. A set of coordinates can be entered into the text box, or a VCF file can be uploaded.

Upload the vcf file that you annotated with SNPeff. If you were unable to complete this step, a copy is available in the google drive; 231335_231336_VarScan_Variants_SnpEff_SS2.vcf.

You will have a choice about what transcript database to use. The output can also be configured by clicking the + symbol next to a particular section. e.g. Variants and frequency data. After selecting the options you want, scroll down to the bottom of the page and click Run. The screen should now change to let you know that VEP is running.

The screen will refresh by itself, and eventually a green Done box should appear. At which point you will be able to inspect the results

The results can be inspected online, or downloaded. Downloading as a text file is better for browsing in Excel, and can also be manipulated in languages such as R.

Assessment of Somatic calls

Click here to follow an exercise on inspecting and evaluating somatic calls

LS0tCnRpdGxlOiAiIgphdXRob3I6ICJNYXJrIER1bm5pbmciCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgoKCiMgSGFuZHMtb24gU29tYXRpYyBWYXJpYW50IEFuYWx5c2lzIGluIEdhbGF4eSBhbmQgSUdWCgojIyMgU2hlZmZpZWxkIEJpb2luZm9ybWF0aWNzIENvcmUKPGltZyBzcmM9Im1lZGlhL2xvZ28tc20ucG5nIiBhbGlnbj1yaWdodD4KCndlYiA6IFtzYmMuc2hlZi5hYy51a10oaHR0cDovL3NiYy5zaGVmLmFjLnVrKSAgCnR3aXR0ZXI6IFtTaGVmZkJpb2luZkNvcmVdKGh0dHBzOi8vdHdpdHRlci5jb20vU2hlZmZCaW9pbmZDb3JlKSAgCmVtYWlsOiBbYmlvaW5mb3JtYXRpY3MtY29yZUBzaGVmZmllbGQuYWMudWtdKGJpb2luZm9ybWF0aWNzLWNvcmVAc2hlZmZpZWxkLmFjLnVrKQoKLS0tLS0KCiMgVHV0b3JpYWwgT3ZlcnZpZXcKClRoaXMgdHV0b3JpYWwgd2lsbCBjb3ZlciB0aGUgYmFzaWNzIG9mIFNvbWF0aWMgYW5hbHlzaXMgdXNpbmcgR2FsYXh5OyBhIG9wZW4tc291cmNlIHdlYi1iYXNlZCBwbGF0Zm9ybSBmb3IgdGhlIGFuYWx5c2lzIG9mIGJpb2xvZ2ljYWwgZGF0YS4gWW91IHNob3VsZCBnYWluIGFuIGFwcHJlY2lhdGlvbiBvZiB0aGUgdGFza3MgaW52b2x2ZWQgaW4gYSB0eXBpY2FsIE5HUyBhbmFseXNpcyBhbmQgYmUgY29tZm9ydGFibGUgd2l0aCB0aGUgb3V0cHV0cyBnZW5lcmF0ZWQgYnkgYSBzZXF1ZW5jaW5nIHNlcnZpY2UuIFlvdSB3aWxsIGFsc28gdXNlIHRoZSBJbnRlZ3JhdGl2ZSBHZW5vbWljcyBWaWV3ZXIgKElHVikgdG8gKnZpZXcqIHRoZSBhbGlnbmVkIHJlYWRzIGluIGFuIGludGVyYWN0aXZlIG1hbm5lci4KCldlIHdpbGwgdXNlIHRyYWluaW5nIG1hdGVyaWFscyBwcm92aWRlZCBieSB0aGUgR2FsYXh5IFByb2plY3QgYW5kIHNpZ24tcG9zdCB0byByZWxldmFudCBzZWN0aW9ucy4gSWYgeW91IHdhbnQgdG8gZmluZCBtb3JlIGRldGFpbGVkIHR1dG9yaWFscyBvbiBJR1Ygb3IgR2FsYXh5IHlvdSBjYW4gZm9sbG93IHRoZSBsaW5rcyBiZWxvdzotCgotIFtHYWxheHkgVHJhaW5pbmcgUG9ydGFsXShodHRwczovL3RyYWluaW5nLmdhbGF4eXByb2plY3Qub3JnL3RyYWluaW5nLW1hdGVyaWFsLykKLSBbSUdWIFR1dG9yaWFsXShodHRwczovL2dpdGh1Yi5jb20vZ3JpZmZpdGhsYWIvcm5hc2VxX3R1dG9yaWFsL3dpa2kvSUdWLVR1dG9yaWFsKQoKPCEtLVRoZSB0dXRvcmlhbCBjb3ZlcnMgdGhlIGZvbGxvd2luZyBzdGVwcyBpbiBvdXIgYW5hbHlzaXMgcGlwZWxpbmUKCiFbXShtZWRpYS9waXBlbGluZS5wbmcpCi0tPgoKLS0tLS0KCiMjIEJhY2tncm91bmQKCiMjIyMgV2hlcmUgZG8gdGhlIGRhdGEgaW4gdGhpcyB0dXRvcmlhbCBjb21lIGZyb20/CgpUaGUgZGF0YSBmb3IgdGhpcyB0dXRvcmlhbCBhcmUgZnJvbSBhIGNhbmNlciBwYXRpZW50IGRvd24tc2FtcGxlZCB0byBnZW5lcyB0aGF0IGFyZSBwcmVzZW50IGluIHRoZSBDT1NNSUMgZGF0YXNldC4gV2Ugd2lsbCB1c2UgdGhlc2UgZGF0YSB0aHJvdWdob3V0IHRoZSBjb3Vyc2UgdG8gY2FsbCB2YXJpYW50cywgZmlsdGVyIGFuZCBkaXNjdXNzIHRoZSBjbGluaWNhbCBpbXBhY3Qgb2YgYW55IG11dGF0aW9ucy4gCgojIFByZXBhcmF0aW9uIGFuZCBEYXRhIFVwbG9hZAoKSWYgYXR0ZW5kaW5nIHRoaXMgd29ya3Nob3AgaW4tcGVyc29uIHlvdSBzaG91bGQgaGF2ZSBhY2Nlc3MgdG8gYSBwcml2YXRlIHF1ZXVlIG9uIHRoZSB1c2VnYWxheHkuZXUgc2VydmVyIHRoYXQgd2lsbCBhbGxvdyB5b3VyIGpvYnMgdG8gcnVuIHF1aWNrZXIuCgpGb2xsb3cgdGhpcyBsaW5rIHRvIHJlZ2lzdGVyIGFuIGFjY291bnQ6LSAKCmh0dHBzOi8vdXNlZ2FsYXh5LmV1L2pvaW4tdHJhaW5pbmcvc2JjLXNvbWF0aWMtMjAxOS0wNS0xMAoKT3RoZXJ3aXNlLCByZWdpc3RlciBhcyBhIG5ldyB1c2VyIG9uIG9uZSBvZiB0aGUgcHVibGljIEdhbGF4eSBzZXJ2ZXJzCgotIGh0dHBzOi8vdXNlZ2FsYXh5Lm9yZy8KLSBodHRwczovL3VzZWdhbGF4eS5vcmcuYXUKLSBodHRwczovL3VzZWdhbGF4eS5ldQoKKipNYWtlIHN1cmUgeW91IGNoZWNrIHlvdXIgZW1haWwgdG8gYWN0aXZhdGUgeW91ciBhY2NvdW50KioKCiMjIEltcG9ydCB0aGUgZGF0YSBmb3IgdGhlIHdvcmtzaG9wLgoKV2UgY2FuIGdvaW5nIHRvIGltcG9ydCB0aGUgWypmYXN0cSogZmlsZXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ZBU1RRX2Zvcm1hdCkgZm9yIHRoaXMgZXhwZXJpbWVudC4gVGhpcyBpcyBhIHN0YW5kYXJkIGZvcm1hdCBmb3Igc3RvcmluZyByYXcgc2VxdWVuY2luZyByZWFkcyBhbmQgdGhlaXIgYXNzb2NpYXRlZCBxdWFsaXR5IHNjb3Jlcy4gSG93ZXZlciwgYXMgd2Ugd2lsbCBzZWUsIHRoZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgcXVhbGl0eSBzY29yZXMgaGFzIGNoYW5nZWQgb3ZlciB0aW1lLgoKVGhlIGZhc3RxIGZpbGVzIGZvciB0aGlzIHdvcmtzaG9wIGhhdmUgYmVlbiB1cGxvYWRlZCB0byBnb29nbGUgZHJpdmUgZm9sZGVyCgotIFtDbGljayBoZXJlIHRvIGFjY2VzcyB0aGUgZ29vZ2xlIGZvbGRlcl0oaHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2RyaXZlL2ZvbGRlcnMvMS1TOGQ5Mk5tY1E3UmZWanRQLUZFdENpelpual9HVHZYP3VzcD1zaGFyaW5nKQoKRG93bmxvYWQgYWxsIHRoZSBmaWxlcyBlbmRpbmcgaW4gYGZhc3RxLmd6YCBhbmQgYGZhc3RhLmd6YCBpbiB0aGlzIGRpcmVjdG9yeSB0byB5b3VyIGxhcHRvcAoKWW91IGNhbiBpbXBvcnQgdGhlIGRhdGEgYnk6CgoxLiAgSW4gdGhlIHRvb2wgcGFuZWwgbG9jYXRlZCBvbiB0aGUgbGVmdCwgc2VsZWN0ICoqR2V0CiAgICBEYXRhID4gVXBsb2FkIEZpbGUqKi4gCjIuICAqKkNob29zZSBsb2NhbCBmaWxlKiogYW5kIGJyb3dzZSB0byB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgdGhlIGZpbGVzIGZyb20gdGhlIGdvb2dsZSBkcml2ZSBhbmQgc2VsZWN0IGFsbCB0aGUgZmlsZS4gQ2xpY2sgKipPcGVuKiogdG8gY2xvc2UgdGhlIGZpbGUgYnJvd3Nlci4gVGhlIG5hbWVzIG9mIHRoZSBmaWxlcyBzaG91bGQgbm93IGFwcGVhciBpbiBHYWxheHkuCjMuICBDbGljayAqKlN0YXJ0KiogdG8gYmVnaW4gdGhlIHVwbG9hZAoKMy4gIFlvdSBzaG91bGQgbm93IGhhdmUgdGhlc2UgNSBmaWxlcyBpbiB5b3VyIGhpc3Rvcnk6CgotIGAyMzEzMzVfY2FuY2VyX2dlbmVzX3IxLmZhc3RxLmd6YAotIGAyMzEzMzVfY2FuY2VyX2dlbmVzX3IyLmZhc3RxLmd6YAotIGAyMzEzMzZfY2FuY2VyX2dlbmVzX3IxLmZhc3RxLmd6YAotIGAyMzEzMzZfY2FuY2VyX2dlbmVzX3IyLmZhc3RxLmd6YAotIGBoZzE5LmNocjVfMTJfMTcuZmFzdGEuZ3pgCgp3aGVyZSB0aGUgZmlyc3QgdHdvIGZpbGVzIHJlcHJlc2VudCB0aGUgZm9yd2FyZCBhbmQgcmV2ZXJzZSByZWFkcyBzZXF1ZW5jZSBkYXRhIGZyb20gYSBwYXRpZW504oCZcyBub3JtYWwgdGlzc3VlLCBhbmQgdGhlIG5leHQgdHdvIHJlcHJlc2VudCB0aGUgZGF0YSBvZiB0aGUgc2FtZSBwYXRpZW504oCZcyB0dW1vciB0aXNzdWUuIFRoZSBmaW5hbCBmaWxlIGlzIGEgY3V0LWRvd24gcmVmZXJlbmNlIGdlbm9tZSBmb3IgY2hyb21vc29tZXMgNSwgMTIgYW5kIDE3IG9ubHkuCgoKIyBTZWN0aW9uIDI6IEZhc3RxIGZpbGUgZm9ybWF0CgpZb3UgY2FuIHZpZXcgdGhlIGZpbGVzIHlvdSBqdXN0IHVwbG9hZGVkIGJ5IGNsaWNraW5nIHRoZSAqKmV5ZSBpY29uKiogdGhlIGhpc3RvcnkgaXRlbS4gVGhlIGZpcnN0IGZldyBsaW5lcyBzaG91bGQgcmVhZCBhcyBmb2xsb3dzCgoKKioyMzEzMzZfY2FuY2VyX2dlbmVzX3IxLmZhc3RxLmd6KioKCmBgYApAU1QtSzAwMjY1OjEzNzpIVDMzQ0JCWFg6MzoxMjEzOjk5NTI6MjczOC8xCkNHR0FDQ0NDQ0dBQ0FUR1RDVEdDVEdUVEdDQ0dDQ0dDR0NBR1RDQ0NHQ0NBR1RDQ0NUR0NHQ0FHQUNUR0NHQ0NUR0NHQ0FDQ0FDQUNDR0dHR1RDR0FHQ1RHR0NHR0dHR0FHR0dHCisKLUFGLUE8QUFBN0FBLUFGPEY3QUpBSkY8QUpGNzc3RkFKSkZKSjctQS03LUZKQUFBLUFGSko8N0Y3RjxGSjctQS1GSkE8SjdKNzc8PEZKPEpKPDxKQUZKPDdGSkpKSi1KLUE8N0EKYGBgCgoqKjIzMTMzNl9jYW5jZXJfZ2VuZXNfcjIuZmFzdHEuZ3oqKgoKYGBgCkBTVC1LMDAyNjU6MTM3OkhUMzNDQkJYWDozOjExMDc6MjA0Nzo2Mzc4LzEKQ0NBR0NUQ0dBQ0NDQ0dHVEdUR0dUR0NHQ0FHR0NHQ0FHVENUR0NHQ0FHR0dBQ1RHR0NHR0dBQ1RHQ0dDR0dDR0dDQUFDQUdDQUdBQ0FUR1RDR0dHR0dUQ0NHR0dHQ0NUR1RDR0MKKwpBQTxBQUZKRkFKN0EtQTctLUFGQTxGSkZKSjdGRkpBSjctNy03RkpKSkpGSjdGRkpKN0ZBPDxGPDdGSkpBQUpKQTxKSkpGRkpKPEFKRjxKSkZKQS08N0FKSkE8LUFGLUpKSkpKLQpgYGAKCgpUaGUgZmlyc3QgbGluZSBpcyB0aGUgdW5pcXVlIGlkZW50aWZpZXIgZm9yIGVhY2ggc2VxdWVuY2VkIHJlYWQuIEl0IGNhbiBiZSB1c2VkIHRvIGVuY29kZSBpbmZvcm1hdGlvbiBzdWNoIGFzIHRoZSAqc2VxdWVuY2luZyBtYWNoaW5lKiwgKmZsb3cgY2VsbCogYW5kICpsYW5lKiB0aGF0IHRoZSByZWFkIHdhcyBnZW5lcmF0ZWQgZnJvbSBhbmQgdGhlIHBoeXNpY2FsIGNvb3JkaW5hdGVzIG9uIHRoZSBsYW5lLiAgCgpUaGUgcXVhbGl0eSBzY29yZXMgYXJlIFtBU0NJSV0oaHR0cDovL2FzY2lpLWNvZGUuY29tLykgcmVwcmVzZW50YXRpb25zIG9mIGhvdyBjb25maWRlbnQgd2UgYXJlIHRoYXQgYSBwYXJ0aWN1bGFyIGJhc2UgaGFzIGJlZW4gY2FsbGVkIGNvcnJlY3RseS4gTGV0dGVycyB0aGF0IGFyZSBmdXJ0aGVyIGFsb25nIHRoZSBhbHBoYWJldCBpbmRpY2F0ZSBoaWdoZXIgY29uZmlkZW5jZS4gVGhpcyBpcyBpbXBvcnRhbnQgd2hlbiB0cnlpbmcgdG8gaWRlbnRpZnkgdHlwZXMgb2YgZ2Vub21lIHZhcmlhdGlvbiBzdWNoIGFzIHNpbmdsZSBiYXNlIGNoYW5nZXMsIGJ1dCBpcyBhbHNvIGluZGljYXRpdmUgb2YgdGhlIG92ZXJhbGwgcXVhbGl0eSBvZiB0aGUgc2VxdWVuY2luZy4gRGlmZmVyZW50IHNjYWxlcyBoYXZlIGJlZW4gZW1wbG95ZWQgb3ZlciB0aW1lIChyZXN1bHRpbmcgaW4gYSBkaWZmZXJlbnQgc2V0IG9mIGNoYXJhY3RlcnMgYXBwZWFyaW5nIGluIHRoZSBmaWxlKS4gLiAKCgojIyMgRGVyaXZpbmcgdGhlIFF1YWxpdHkgU2NvcmUKCkZpcnN0IG9mIGFsbCwgd2UgY29udmVydCB0aGUgYmFzZS1jYWxsaW5nIHByb2JhYmlsaXR5IChwKSBpbnRvIGEgYFFgIHNjb3JlIHVzaW5nIHRoZSBmb3JtdWxhCgotIFF1YWxpdHkgc2NvcmVzICQkIFEgPSAtMTBsb2dfezEwfXAkJAogICAgKyBRID0gMzAsIHA9MC4wMDEKICAgICsgUSA9IDIwLCBwPTAuMDEKICAgICsgUSA9IDEwLCBwPTAuMQotIFRoZXNlIG51bWVyaWMgcXVhbnRpZXMgYXJlICplbmNvZGVkKiBhcyBbKipBU0NJSSoqXShodHRwOi8vYXNjaWktY29kZS5jb20vKSBjb2RlCiAgICArIEF0IGxlYXN0IDMzIHRvIGdldCB0byBtZWFuaW5nZnVsIGNoYXJhY3RlcnMKICAgIChodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GQVNUUV9mb3JtYXQpCiAgICAKIVtdKG1lZGlhL3BocmVkLnBuZykgICAgICAKCiMjIyBRdWFsaXR5IFNjb3JlcyB0byBwcm9iYWJpbGl0aWVzCgotIGxvb2stdXAgdGhlIEFTQ0lJIGNvZGUgZm9yIGVhY2ggY2hhcmFjdGVyCi0gc3VidHJhY3QgdGhlIG9mZnNldCB0byBnZXQgdGhlIFEgc2NvcmUKLSBjb252ZXJ0IHRvIGEgcHJvYmFiaWxpdHkgdXNpbmcgdGhlIGZvcm11bGE6LQoKJCQgcCA9IDEwXnstUS8xMH0gJCQKCkxldCdzIHNlZSB0aGlzIGNhbGN1bGF0aW9uIGZvciB0aGUgZmlyc3QgZmV3IGJhc2VzIG9mIHRoZSBmaXJzdCByZWFkIGluIGAyMzEzMzZfY2FuY2VyX2dlbmVzX3IxLmZhc3RxYDsgYC1BRi1BPEFBQTcuLi4uYAoKQ2hhcmFjdGVyICB8IENvZGUgfCBNaW51cyAzMyBPZmZzZXQgfCBQcm9iYWJpbGl0eQotLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tCi0gIHwgNDUgfCAxMiB8IDAuMDYzMQpBICB8IDY1IHwgMzIgfCAwLjAwMDYKRiAgfCA3MCB8IDM3IHwgMC4wMDAyCi0gIHwgNDUgfCAxMiB8IDAuMDYzMQpBICB8IDY1IHwgMzIgfCAwLjAwMDYKPCAgfCA2MCB8IDI3IHwgMC4wMDIwCkEgIHwgNjUgfCAzMiB8IDAuMDAwNgpBICB8IDY1IHwgMzIgfCAwLjAwMDYKCkluIHByYWN0aWNlLCB3ZSBkb24ndCBoYXZlIHRvIGNvbnZlcnQgdGhlIHZhbHVlcyBhcyB3ZSBoYXZlIHNvZnR3YXJlIHRoYXQgd2lsbCBkbyB0aGlzIGF1dG9tYXRpY2FsbHkKCgoKLS0tLS0KCiMgU2VjdGlvbiAzOiBRdWFsaXR5IEFzc2Vzc21lbnQgb2YgTkdTIHJlYWRzCgpbRmFzdFFDXShodHRwczovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9wcm9qZWN0cy9mYXN0cWMvKSBpcyBhIHBvcHVsYXIgdG9vbCBmcm9tIFtCYWJyYWhhbSBJbnN0aXR1dGUgQmlvaW5mb3JtYXRpY3MgR3JvdXBdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL2luZGV4Lmh0bWwpIHVzZWQgZm9yICpxdWFsaXR5IGFzc2Vzc21lbnQqIG9mIHNlcXVlbmNpbmcgZGF0YS4gTW9zdCBCaW9pbmZvcm1hdGljcyBwaXBlbGluZXMgd2lsbCB1c2UgRmFzdFFDLCBvciBzaW1pbGFyIHRvb2xzIGluIHRoZSBmaXJzdCBzdGFnZSBvZiB0aGUgYW5hbHlzaXMuIFRoZSBbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjL0hlbHAvKSBmb3IgRmFzdFFDIHdpbGwgaGVscCB5b3UgdG8gaW50ZXJwcmV0IHRoZSBwbG90cyBhbmQgc3RhdHMgcHJvZHVjZWQgYnkgdGhlIHRvb2wuIEEgdHJhZmZpYyBsaWdodCBzeXN0ZW0gaXMgdXNlZCB0byBhbGVydCB0aGUgdXNlcidzIGF0dGVudGlvbiB0byBwb3NzaWJsZSBpc3N1ZXMuIAoKVGhlIG1vc3QgaW1wb3J0YW50IGltYWdlIGlzIHdoZXRoZXIgdGhlIGJhc2UgcXVhbGl0eSBkZWNyZWFzZXMgc2lnbmlmaWNhbnRseSBvdmVyIHRoZSBsZW5ndGggb2YgdGhlIHJlYWQKCiFbXShtZWRpYS9mYXN0cWMtMmEucG5nKQoKR29vZCBxdWFsaXR5IGRhdGEgc2hvdWxkIGxvb2sgc29tZXRoaW5nIGxpa2U6LQoKIVtdKG1lZGlhL2Zhc3RxYy0yYi5wbmcpCgpXZSB3aWxsIG5vdyBmb2xsb3cgdGhlIHJlbGV2YW50IHNlY3Rpb24gb24gdGhlIEdhbGF4eSB0cmFpbmluZyBwYWdlIGZvciBRQyBhbmQgYWxpZ25tZW50CgpbaHR0cHM6Ly90cmFpbmluZy5nYWxheHlwcm9qZWN0Lm9yZy90cmFpbmluZy1tYXRlcmlhbC90b3BpY3MvdmFyaWFudC1hbmFseXNpcy90dXRvcmlhbHMvc29tYXRpYy12YXJpYW50cy90dXRvcmlhbC5odG1sI3F1YWxpdHktY29udHJvbC1hbmQtbWFwcGluZy1vZi1uZ3MtcmVhZHNdKGh0dHBzOi8vdHJhaW5pbmcuZ2FsYXh5cHJvamVjdC5vcmcvdHJhaW5pbmctbWF0ZXJpYWwvdG9waWNzL3ZhcmlhbnQtYW5hbHlzaXMvdHV0b3JpYWxzL3NvbWF0aWMtdmFyaWFudHMvdHV0b3JpYWwuaHRtbCNxdWFsaXR5LWNvbnRyb2wtYW5kLW1hcHBpbmctb2YtbmdzLXJlYWRzKQoKIyBTZWN0aW9uIDQ6IEFsaWdubWVudAoKVGhlIHJlc3VsdCBvZiB0aGUgcHJldmlvdXMgcHJhY3RpY2FsIHdpbGwgYmUgYSBgLmJhbWAgZmlsZSB0aGF0IHdlIHdpbGwgZGVzY3JpYmUgaW4gdGhlIG5leHQgc2VjdGlvbi4gVGhpcyBmaWxlIGlzIG5vdCBodW1hbi1yZWFkYWJsZSwgYXMgaXQgaXMgY29tcHJlc2VkLiBCdXQgd2UgY2FuIGNvbnZlcnQgdG8gYSByZWFkYWJsZSBmb3JtYXQgZm9yIGlsbHVzdHJhdGlvbiBwdXJwb3Nlcy4KCiMjIFZpZXdpbmcgdGhlIGFsaWdubWVudHMKCkNsaWNrIG9uIHRoZSBleWUgb2YgdGhlIHJlc3VsdGluZyBmaWxlIHRvIHZpZXcgdGhlIGFsaWdubWVudHMuCgoKIVtdKG1lZGlhL2JhbS1hbGlnbm1lbnRzLnBuZykKCkEgKnNpbmdsZSBzdGFuZGFyZCogZmlsZSBmb3JtYXQgaGFzIGVtZXJnZWQgZm9yIGFsaWduZWQgcmVhZHMuIE1vcmVvZXZlciwgdGhpcyBmaWxlIGZvcm1hdCBpcyBjb25zaXN0ZW50IHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB5b3UgaGF2ZSBETkEtc2VxLCBSTkEtc2VxLCBDaElQLXNlcS4uLiBkYXRhLiAKClRoZSBgYmFtYCBmaWxlIGlzIGEgY29tcHJlc3NlZCwgYmluYXJ5LCB2ZXJzaW9uIG9mIGEgYHNhbWAgZmlsZS4KCi0gKipTKiplcXVlbmNlICoqQSoqbGlnbm1lbnQvKipNKiphcCAoc2FtKSAKLSBUaGUgb3V0cHV0IGZyb20gYW4gYWxpZ25lciBzdWNoIGFzIGBid2FgCi0gU2FtZSBmb3JtYXQgcmVnYXJkbGVzcyBvZiBzZXF1ZW5jaW5nIHByb3RvY29sIChpLmUuIFJOQS1zZXEsIENoSVAtc2VxLCBETkEtc2VxIGV0YykKLSBNYXkgY29udGFpbiB1bi1tYXBwZWQgcmVhZHMKLSBQb3RlbnRpYWxseSBsYXJnZSBzaXplIG9uIGRpc2s7IH4xMDBzIG9mIEdiCiAgICArIENhbiBiZSBtYW5pcHVsYXRlZCB3aXRoIHN0YW5kYXJkIHVuaXggdG9vbHM7IGUuZy4gKmNhdCosICpoZWFkKiwgKmdyZXAqLCAqbW9yZSosICpsZXNzKi4uLi4KLSBPZmZpY2lhbCBzcGVjaWZpY2F0aW9uIGNhbiBiZSBbb2J0YWluZWQgb25saW5lXShodHRwOi8vc2FtdG9vbHMuZ2l0aHViLmlvL2h0cy1zcGVjcy9TQU12MS5wZGYpOiAtCi0gV2Ugbm9ybWFsbHkgd29yayBvbiBhIGNvbXByZXNzZWQgdmVyc2lvbiBjYWxsZWQgYSBgLmJhbWAgZmlsZS4gU2VlIGxhdGVyLgotICpIZWFkZXIqIGxpbmVzIHN0YXJ0aW5nIHdpdGggYW4gYEBgIGNoYXJhY3RlciwgZm9sbG93ZWQgYnkgdGFiLWRlbGltaXRlZCBsaW5lcwogICAgKyBIZWFkZXIgZ2l2ZXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGFsaWdubWVudCBhbmQgcmVmZXJlbmNlcyBzZXF1ZW5jZXMgdXNlZAoKClRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBoZWFkZXIgbGlzdHMgdGhlIG5hbWVzIChgU05gKSBvZiB0aGUgc2VxdWVuY2VzIChjaHJvbW9zb21lcykgdXNlZCBpbiBhbGlnbm1lbnQsIHRoZWlyIGxlbmd0aCAoYExOYCkgYW5kIHNvbXRpbWVzIGEgKm1kNXN1bSogIltkaWdpdGFsIGZpbmdlcnByaW50XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NZDVzdW0pIiBvZiB0aGUgYC5mYXN0YWAgZmlsZSB1c2VkIGZvciBhbGlnbm1lbnQgKGBNNWApLgoKYGBgCkBIRCBWTjoxLjMgU086Y29vcmRpbmF0ZQpAU1EgU046Y2hyNSBMTjoxODA5MTUyNjAKQFNRIFNOOmNocjEyIExOOjEzMzg1MTg5NQpAU1EgU046Y2hyMTcgTE46ODExOTUyMTAKQFJHIElEOjIzMTMzNSBTTTpOb3JtYWwgUEw6SUxMVU1JTkEKCmBgYAoKCgpXZSBhbHNvIGhhdmUgYSBzZWN0aW9uIHdoZXJlIHdlIGNhbiByZWNvcmQgdGhlIHByb2Nlc3Npbmcgc3RlcHMgdXNlZCB0byBkZXJpdmUgdGhlIGZpbGUKCmBgYApAUEcgSUQ6YndhIFBOOmJ3YSBWTjowLjcuMTctcjExODggQ0w6YndhIG1lbSAtdCA4IC12IDEgLVIgQFJHXHRJRDoyMzEzMzVcdFNNOk5vcm1hbFx0UEw6SUxMVU1JTkEgbG9jYWxyZWYuZmEgL2RhdGEvZG5iMDIvZ2FsYXh5X2RiL2ZpbGVzLzAwOS8zNTIvZGF0YXNldF85MzUyNDUyLmRhdCAvZGF0YS9kbmIwMi9nYWxheHlfZGIvZmlsZXMvMDA5LzM1Mi9kYXRhc2V0XzkzNTI0NTMuZGF0CgpgYGAKCk5leHQgaXMgYSAqdGFiLWRlbGltaXRlZCogc2VjdGlvbiB0aGF0IGRlc2NyaWJlcyB0aGUgYWxpZ25tZW50IG9mIGVhY2ggc2VxdWVuY2UgaW4gZGV0YWlsLiAKCmBgYApTVC1LMDAyNjU6MTM3OkhUMzNDQkJYWDozOjIxMDY6NTk0NDoxMTc1OQk5OQljaHI1CTIxODM3OAk2MAkxMDFNCT0JMjE4NDY1CTE4OAlHVEFUQ0NDQ0NDVENDQ0NDR0NDQUdDVENHQUNDQ0NHR1RHVEdHVEdDR0NBR0dDR0NBR1RDVEdDR0NBR0dHQUNUR0dDR0dHQUNUR0NHQ0dHQ0dHQ0FBQ0FHQ0FHQUNBVEdUQ0dHRwlBQUZGRkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSglOTTppOjAgTUQ6WjoxMDEgTUM6WjoxMDFNIEFTOmk6MTAxIFhTOmk6NTAgUkc6WjoyMzEzMzUKYGBgCgoKCkNvbHVtbiB8IE9mZmljaWFsIE5hbWUgfCBCcmllZgotLS0tLS0gfCAtLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tCjEgICAgICB8IFFOQU1FICAgICAgICAgIHwgU2VxdWVuY2UgSUQKMiAgICAgIHwgRkxBRyAgICAgICAgICAgfCBTZXF1ZW5jZSBxdWFsaXR5IGV4cHJlc3NlZCBhcyBhIGJpdHdpc2UgZmxhZwozICAgICAgfCBSTkFNRSAgICAgICAgICB8IENocm9tb3NvbWUKNCAgICAgIHwgUE9TICAgICAgICAgICAgfCBTdGFydCBQb3NpdGlvbgo1ICAgICAgfCBNQVBRICAgICAgICAgICB8IE1hcHBpbmcgUXVhbGl0eQo2ICAgICAgfCBDSUdBUiAgICAgICAgICB8IERlc2NyaWJlcyBwb3NpdGlvbnMgb2YgbWF0Y2hlcywgaW5zZXJ0aW9ucywgZGVsZXRpb25zIHcuci50IHJlZmVyZW5jZQo3ICAgICAgfCBSTkVYVCAgICAgICAgICB8IFJlZi4gbmFtZSBvZiBtYXRlIC8gbmV4dCByZWFkCjggICAgICB8IFBORVhUICAgICAgICAgIHwgUG9zdGlvbiBvZiBtYXRlIC8gbmV4dCByZWFkCjkgICAgICB8IFRMRU4gICAgICAgICAgIHwgT2JzZXJ2ZWQgVGVtcGxhdGUgbGVuZ3RoCjEwICAgICB8IFNFUSAgICAgICAgICAgIHwgU2VxdWVuY2UKMTEgICAgIHwgUVVBTCAgICAgICAgICAgfCBCYXNlIFF1YWxpdGllcwoKVGhlcmUgY2FuIGFsc28gYmUgYWxsIG1hbm5lciBvZiBvcHRpb25hbCB0YWdzIGFzIGV4dHJhIGNvbHVtbnMgaW50cm9kdWNlIGJ5IGFuIGFsaWduZXIgb3IgZG93bnN0cmVhbSBhbmFseXNpcyB0b29sLiBBIGNvbW1vbiB1c2UgaXMgdGhlIGBSR2AgdGFnIHdoaWNoIHJlZmVycyBiYWNrIHRvIHRoZSByZWFkIGdyb3VwcyBpbiB0aGUgaGVhZGVyLgoKCiMjIyBTb3J0aW5nIGFuZCBpbmRleGluZwoKWW91IHdpbGwgbm90aWNlIGZyb20gdGhlIDNyZCBjb2x1bW4gdGhhdCB0aGUgcmVhZHMgYXJlIG9yZGVyZWQgYWNjb3JkaW5nIHRvIHRoZWlyIHN0YXJ0IHBvc2l0aW9uOyB3aGVyZWFzIHRoZSByZWFkcyBpbiB0aGUgYGZhc3RxYCBmaWxlIHdlcmUgYXJyYW5nZWQgaW4gb3JkZXIgdGhhdCB0aGV5IHdlcmUgZ2VuZXJhdGVkIG9uIHRoZSBmbG93IGNlbGwuIEJ5IGRlZmF1bHQsIGBid2EtbWVtYCBwcm9kdWNlcyBhIGJhbSB3aGVyZSB0aGUgcmVhZHMgYXJlIGluIHRoZSBzYW1lIG9yZGVyIGFzIHRoZSBgZmFzdHFgLiBIb3dldmVyLCB0aGlzIGlzIHJhdGhlciBpbmNvdmVuaWVudCBmb3IgYW5hbHlzaXMgd2hlcmUgd2UgcmVxdWlyZSByZWFkcyBmcm9tIHRoZSBzYW1lIGxvY2F0aW9uIHRvIGJlIG5leHQgdG8gZWFjaCBvdGhlciBpbiB0aGUgZmlsZS4KCkFuIGFkZGl0aW9uYWwgY291cGxlIG9mIHN0ZXBzIGhhdmUgYmVlbiBwZXJmb3JtZWQgYWZ0ZXIgYm93dGllMjsgc29ydGluZyB0aGUgZmlsZSBhY2NvcmRpbmcgdG8gZ2Vub21lIHBvc2l0aW9uIGFuZCBwcm9kdWNpbmcgYW4gKmluZGV4KiBmaWxlLiBUaGUgaW5kZXggZmlsZSBkb2VzIG5vdCBwcm92aWRlIGFueSB1c2VmdWwgaW5mb3JtYXRpb24gZm9yIHVzIGFuZCBjYW5ub3QgYmUgdmlld2VkIGluIEdhbGF4eS4gSG93ZXZlciwgd2Ugd2lsbCBuZWVkIGl0IGxhdGVyIG9uIHdoZW4gdmlld2luZyB0aGUgZGF0YSBpbiBJR1YuIAoKIyMgRHIgTWFyayBEdW5uaW5nIHByZXNlbnRzLi4uLkZ1biB3aXRoIGZsYWdzIQoKVGhlICoiZmxhZ3MiKiBpbiB0aGUgc2FtIGZpbGUgY2FuIHJlcHJlc2VudCB1c2VmdWwgUUMgaW5mb3JtYXRpb24KCiAgKyBSZWFkIGlzIHVubWFwcGVkCiAgKyBSZWFkIGlzIHBhaXJlZCAvIHVucGFpcmVkCiAgKyBSZWFkIGZhaWxlZCBRQwogICsgUmVhZCBpcyBhIFBDUiBkdXBsaWNhdGUgKHNlZSBsYXRlcikKClRoZSBjb21iaW5hdGlvbiBvZiBhbnkgb2YgdGhlc2UgcHJvcGVydGllcyBpcyB1c2VkIHRvIGRlcml2ZSBhIG51bWVyaWMgdmFsdWUKCgpGb3IgaW5zdGFuY2UsIGEgcGFydGljdWxhciByZWFkIGhhcyBhIGZsYWcgb2YgMTYzCgohW10obWVkaWEvZmxhZy1oaWdobGlnaHQucG5nKQoKCiMjIyBEZXJpdmF0aW9uCgpUaGVyZSBpcyBhIHNldCBvZiBwcm9wZXJ0aWVzIHRoYXQgYSByZWFkIGNhbiBwb3NzZXNzLiBJZiBhIHBhcnRpY3VsYXIgcHJvcGVydHkgaXMgb2JzZXJ2ZWQsIGEgY29ycmVzcG9uZGluZyBwb3dlciBvZiAyIGlzIGFkZGVkIG11bHRpcGxpZWQgYnkgMS4gVGhlIGZpbmFsIHZhbHVlIGlzIGRlcml2ZWQgYnkgc3VtbWluZyBhbGwgdGhlIHBvd2VycyBvZiAyLgoKIVtdKGh0dHBzOi8vZ2FsYXh5cHJvamVjdC5vcmcvdHV0b3JpYWxzL25ncy9zYW1fZmxhZy5wbmcpCgpGbGFnIFZhbHVlIHwgTWVhbmluZwotLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KNjkgKD0gMSArIDQgKyA2NCkgCXwgVGhlIHJlYWQgaXMgcGFpcmVkLCBpcyB0aGUgZmlyc3QgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGlzIHVubWFwcGVkLgo3NyAoPSAxICsgNCArIDggKyA2NCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIGlzIHRoZSBmaXJzdCByZWFkIGluIHRoZSBwYWlyLCBib3RoIGFyZSB1bm1hcHBlZC4KODMgKD0gMSArIDIgKyAxNiArIDY0KSB8CVRoZSByZWFkIGlzIHBhaXJlZCwgbWFwcGVkIGluIGEgcHJvcGVyIHBhaXIsIGlzIHRoZSBmaXJzdCByZWFkIGluIHRoZSBwYWlyLCBhbmQgaXQgaXMgbWFwcGVkIHRvIHRoZSByZXZlcnNlIHN0cmFuZC4KOTkgKD0gMSArIDIgKyAzMiArIDY0KSB8CVRoZSByZWFkIGlzIHBhaXJlZCwgbWFwcGVkIGluIGEgcHJvcGVyIHBhaXIsIGlzIHRoZSBmaXJzdCByZWFkIGluIHRoZSBwYWlyLCBhbmQgaXRzIG1hdGUgaXMgbWFwcGVkIHRvIHRoZSByZXZlcnNlIHN0cmFuZC4KMTMzICg9IDEgKyA0ICsgMTI4KSB8CVRoZSByZWFkIGlzIHBhaXJlZCwgaXMgdGhlIHNlY29uZCByZWFkIGluIHRoZSBwYWlyLCBhbmQgaXQgaXMgdW5tYXBwZWQuCjEzNyAoPSAxICsgOCArIDEyOCkgIHwJVGhlIHJlYWQgaXMgcGFpcmVkLCBpcyB0aGUgc2Vjb25kIHJlYWQgaW4gdGhlIHBhaXIsIGFuZCBpdCBpcyBtYXBwZWQgd2hpbGUgaXRzIG1hdGUgaXMgbm90LgoxNDEgKD0gMSArIDQgKyA4ICsgMTI4KSB8CVRoZSByZWFkIGlzIHBhaXJlZCwgaXMgdGhlIHNlY29uZCByZWFkIGluIHRoZSBwYWlyLCBidXQgYm90aCBhcmUgdW5tYXBwZWQuCjE0NyAoPSAxICsgMiArIDE2ICsgMTI4KSB8CVRoZSByZWFkIGlzIHBhaXJlZCwgbWFwcGVkIGluIGEgcHJvcGVyIHBhaXIsIGlzIHRoZSBzZWNvbmQgcmVhZCBpbiB0aGUgcGFpciwgYW5kIG1hcHBlZCB0byB0aGUgcmV2ZXJzZSBzdHJhbmQuCjE2MyAoPSAxICsgMiArIDMyICsgMTI4KSB8CVRoZSByZWFkIGlzIHBhaXJlZCwgbWFwcGVkIGluIGEgcHJvcGVyIHBhaXIsIGlzIHRoZSBzZWNvbmQgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGl0cyBtYXRlIGlzIG1hcHBlZCB0byB0aGUgcmV2ZXJzZSBzdHJhbmQuCgoKClNlZSBhbHNvCgotIGh0dHBzOi8vYnJvYWRpbnN0aXR1dGUuZ2l0aHViLmlvL3BpY2FyZC9leHBsYWluLWZsYWdzLmh0bWwKCiMjIEhhdmUgYSBDSUdBUiEKCgohW10obWVkaWEvY2lnYXItaGlnaGxpZ2h0LnBuZykKClRoZSAqKipDSUdBUioqKiAoKipDKipvbXBhY3QgKipJKipkaW9zeW5jcmF0aWMgKipHKiphcHBlZCAqKkFsaWdubWVudCoqICoqUioqZXBvcnQpIHN0cmluZyBpcyBhIHdheSBvZiBlbmNvZGluZyB0aGUgbWF0Y2ggYmV0d2VlbiBhIGdpdmVuIHNlcXVlbmNlIGFuZCB0aGUgcG9zaXRpb24gaXQgaGFzIGJlZW4gYXNzaWduZWQgaW4gdGhlIGdlbm9tZS4gSXQgaXMgY29tcHJpc2VkIGJ5IGEgc2VyaWVzIG9mIGxldHRlcnMgYW5kIG51bWJlcnMgdG8gaW5kaWNhdGUgaG93IG1hbnkgY29uc2VjdXRpdmUgYmFzZXMgaGF2ZSB0aGF0IG1hcHBpbmcuCgoKIAogQ29kZSAgfCBEZXNjcmlwdGlvbgotLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLQpNICB8IGFsaWdubWVudCBtYXRjaApJICB8IGluc2VydGlvbgpEICB8IGRlbGV0aW9uCk4gIHwgc2tpcHBlZApTICB8IHNvZnQtY2xpcHBpbmcKSCAgfCBoYXJkLWNsaXBwaW5nCgoKZS5nLgoKLSBgNjhNYAogICAgKyA2OCBiYXNlcyBtYXRjaGluZyB0aGUgcmVmZXJlbmNlCi0gYDFTNjdNYAogICAgKyAxIHNvZnQtY2xpcHBlZCByZWFkIGZvbGxvd2VkIGJ5IDY3IG1hdGNoZXMKLSBgMTVNODdONzBNOTBOMTZNYAogICAgKyAxNSBtYXRjaGVzIGZvbGxvd2luZyBieSA4NyBiYXNlcyBza2lwcGVkIGZvbGxvd2VkIGJ5IDcwIG1hdGNoZXMgZXRjLgoKCiMjIENoZWNraW5nIHRoZSBhbGlnbm1lbnQgc3RhdHMKCldlIHdpbGwgbm93IGdlbmVyYXRlIGEgZmV3IGJhc2ljIHN0YXRpc3RpY3MgYWJvdXQgdGhlIGFsaWdubWVudCBvZiBvdXIgZGF0YQoKMS4gU2VsZWN0IHRoZSB0b29sICpOR1M6IFNBTXRvb2xzIC0+IEZsYWdzdGF0KiAKMi4gSW4gdGhlICpCQU0gRmlsZSB0byBDb252ZXJ0KiBib3ggY2hvb3NlIHRoZSBiYW0gZmlsZSBwcm9kdWNlZCBieSBid2EtbWVtLgoKClRoZSB0b29sIHdpbGwgYWxzbyByZXBvcnQgaG93IG1hbnkgKioqUENSIER1cGxpY2F0ZXMqKiogaGF2ZSBiZWVuIGZvdW5kIGluIHRoZSBkYXRhLiBCdXQgYXMgd2UgaGF2ZW4ndCB5ZXQgcnVuIGFueSBzb2Z0d2FyZSB0byBpZGVudGlmeSBzdWNoIHJlYWRzLCB0aGUgZmxhZ3N0YXQgb3V0cHV0IHdpbGwgc2hvdyAwIHJlYWRzLgoKMS4gRmluZCB0aGUgdG9vbCAqU0FNdG9vbHMgLT4gSWR4c3RhdHMqCjIuIEluIHRoZSAqQkFNIGZpbGUqIGRyb3Bkb3duIHNlbGVjdCB0aGUgYmFtIGZpbGUgcHJvZHVjZWQgYnkgYm93dGllMgoKVGhlIG91dHB1dCBvZiB0aGlzIHRvb2wgd2lsbCB0ZWxsIHlvdSBob3cgbWFueSByZWFkcyBhbGlnbmVkIHRvIGVhY2ggY2hyb21vc29tZSBpbiB5b3VyIHJlZmVyZW5jZSBnZW5vbWUuCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4KCioqT3B0aW9uYWwgRXhlcmNpc2U6KiogVGhlIG11bHRpcWMgdG9vbCB0aGF0IHdlIGludHJvZHVjZWQgZWFybGllciBpcyBhYm91dCB0byBpbnRlcnBldCB0aGUgb3V0cHV0IG9mIGZsYWdzdGF0IGFuZCBpZHhzdGF0cy4gQ3JlYXRlIGEgcmVwb3J0IHRoZSBjb21iaW5lcyB0aGUgcmVzdWx0cyBvZiB0aGVzZSBtZXRyaWNzIHdpdGggdGhlIGZhc3RxYyByZXBvcnRzIG9uIHRoZSBmYXN0cSBmaWxlcwoKPC9kaXY+CgoKIyMgRG93bmxvYWQgeW91ciBiYW0gZmlsZQoKRm9yIHRoZSBuZXh0IHNldHAgeW91IHdpbGwgbmVlZCB0byBkb3dubG9hZCB0aGUgYGJhbWAgZmlsZS4gVG8gZG8gdGhpcywgeW91IGNhbiBjbGljayB0aGUgZmxvcHB5IGRpc2sgaWNvbi4KCiFbXShtZWRpYS9kb3dubG9hZF9iYW0ucG5nKQoKKipNYWtlIHN1cmUgdGhhdCB5b3UgY2xpY2sgYm90aCBEb3dubG9hZCBkYXRhc2V0IGFuZCBEb3dubG9hZCBiYW1faW5kZXgqKgoKKipJZiB5b3UgaGF2ZSBwcm9ibGVtcyBjcmVhdGluZyB0aGUgYmFtIGZpbGUsIGEgcHJlLXByZXBhcmVkIGZpbGUgaXMgYXZhaWxhYmxlIGZyb20gdGhlIGdvb2dsZSBkcml2ZSoqCgpodHRwczovL2RyaXZlLmdvb2dsZS5jb20vZHJpdmUvZm9sZGVycy8xLVM4ZDkyTm1jUTdSZlZqdFAtRkV0Q2l6Wm5qX0dUdlg/dXNwPXNoYXJpbmcKCiMgU2VjdGlvbiA1LiBWaXN1YWxpc2luZyB0aGUgYWxpZ25lZCByZWFkcyB3aXRoIElHVgoKV2hpbHN0IEJpb2luZm9ybWF0aWNzIHRvb2xzIGFyZSB2ZXJ5IHBvd2VyZnVsIGFuZCBhbGxvdyB5b3UgdG8gcGVyZm9ybSBzdGF0aXN0aWNhbCBhbmFseXNlcyBhbmQgdGVzdCBoeXBvdGhlc2VzLCB0aGVyZSBpcyBubyBzdWJzdGl0dXRlIGZvciAqKmxvb2tpbmcgYXQgYW5kIGV4cGxvcmluZyB0aGUgZGF0YSoqLiBBIHRyYWluZWQtZXllIGNhbiBxdWl0ZSBxdWlja2x5IGdldCBhIHNlbnNlIG9mIHRoZSBkYXRhIHF1YWxpdHkgYmVmb3JlIGFueSBjb21wdXRhdGlvbmFsIGFuYWx5c2VzIGhhdmUgYmVlbiBydW4uIEZ1dGhlcm1vcmUsIGFzIHRoZSBwZXJzb24gcmVxdWVzdGluZyB0aGUgc2VxdWVuY2luZywgeW91IHByb2JhYmx5IGtub3cgYSBsb3QgYWJvdXQgdGhlIGJpb2xvZ2ljYWwgY29udGV4dCBvZiB0aGUgc2FtcGxlcyBhbmQgd2hhdCB0byBleHBlY3QuCgpXZSB3aWxsIGxvYWQgdGhlIGFsaWduZWQgcmVhZHMgdGhhdCB3ZSBoYXZlIGp1c3QgY3JlYXRlZCBpbnRvIElHViBhbmQgc3RhcnQgdG8gZ2V0IGEgZmVlbCBmb3IgdGhlIHByb2Nlc3Mgb2YgdmFyaWFudCBjYWxsaW5nCgoxLiBEb3dubG9hZCBJR1YKCllvdSBjYW4gZG93bmxvYWQgSUdWIGZvciBXaW5kb3dzIHVzaW5nIHRoaXMgbGluayAKCi0gaHR0cHM6Ly9zb2Z0d2FyZS5icm9hZGluc3RpdHV0ZS5vcmcvc29mdHdhcmUvaWd2L2Rvd25sb2FkCgoqRXh0cmFjdCogdGhlIHppcCBmaWxlIHRoYXQgeW91IGhhdmUgZG93bmxvYWRlZAoKCgohW10obWVkaWEvZXh0cmFjdF9pZ3YuUE5HKQoKCgpEb3VibGUtQ2xpY2sgdGhlIGZpbGUgYGlndmAgdG8gbGF1bmNoIElHVgoKCgohW10obWVkaWEvcnVuX2lndi5QTkcpCgoKCjIuIExvYWQgYSByZWZlcmVuY2UgR2Vub21lIGFuZCBzb21lIERhdGEgVHJhY2tzCgpCeSBkZWZhdWx0LCBJR1Ygc2hvdWxkIGxvYWQgd2l0aCBIdW1hbiBnZW5vbWUgdmVyc2lvbiAqaGcxOSogYWxyZWFkeSBsb2FkZWQuIEl0IGlzIGVzc2VudGlhbCB0aGF0IHlvdSB1c2UgdGhlICoqc2FtZSBnZW5vbWUgdmVyc2lvbioqIHRoYXQgdGhlIHJlYWRzIHdlcmUgYWxpZ25lZCB0by4gWW91IGNhbiBjaGVjayAvIGNoYW5nZSB0aGUgZ2Vub21lIGJ5IGNsaWNraW5nIHRoZSBkcm9wLWRvd24gbWVudSBpbiB0aGUgdXBwZXItbGVmdAoKIVtdKG1lZGlhL3NlbGVjdF9nZW5vbWUuUE5HKQoKV2UgY2FuIGFsc28gbG9hZCBleHRyYSAqdHJhY2tzKiBpbnRvIHRoZSBicm93c2VyIHRoYXQgY2FuIGhlbHAgdXMgdW5kZXJzdGFuZCBvdXIgdmFyaWFudCBjYWxscy4gRm9yIGV4YW1wbGUsIHdlIGNhbiBsb2FkIGRhdGEgZnJvbSAqZGJTTlAqIHdoaWNoIHdpbGwgdGVsbCB1cyBhYm91dCBjb21tb24gbXV0YXRpb25zIHRoYXQgYWxyZWFkeSBiZWVuIGlkZW50aWZpZWQuIFRoZXNlIGNhbiBiZSBsb2FkZWQgdmlhICpGaWxlKiAtPiAqTG9hZCBmcm9tIFNlcnZlci4uKiBhbmQgc2VsZWN0aW5nIGBkYlNOUCAxLjQuN2AgZnJvbSB0aGUgYFZhcmlhdGlvbiBhbmQgUmVwZWF0c2Agc2VjdGlvbgoKIVtdKG1lZGlhL2F2YWlsYWJsZV9kYXRhc2V0cy5QTkcpCgoKMy4gTmF2aWdhdGUgYXJvdW5kIElHVgoKV2hlbiBJR1YgbG9hZHMgdXAgd2Ugc3RhcnQgd2l0aCBhIHZlcnkgaGlnaC1sZXZlbCB2aWV3IG9mIHRoZSBnZW5vbWUgd2hlcmUgKmFsbCogY2hyb21vc29tZXMgYXJlIHZpc2libGUuIFN1Y2ggYSB2aWV3IG1pZ2h0IGJlIHVzZWZ1bCBpZiB3ZSB3ZXJlIGludGVyZXN0ZWQgaW4gbGFyZ2UgY29weS1udW1iZXIgdmFyaWF0aW9uIGFjcm9zcyBhIGNvaG9ydCBvZiBzYW1wbGVzLiBIb3dldmVyLCB3ZSBhcmUgbW9zdGx5IGludGVyZXN0ZWQgaW4gY2hhbmdlcyBhdCB0aGUgaW5kaXZpZHVhbCBiYXNlLWxldmVsIHdoaWNoIGlzIG5vdCBwb3NzaWJsZSB0byB2aWV3IGF0IHRoaXMgcmVzb2x1dGlvbi4gV2UgbmVlZCB0byBuYXZpZ2F0ZSB0byBhIHBhcnRpY3VsYXIgcmVnaW9uIG9mIGludGVyZXN0LgoKQWxvbmdzaWRlIHRoZSBkcm9wLWRvd24gbWVudSB1c2VkIHRvIGNoYW5nZSB0aGUgZ2Vub21lLCB0aGVyZSBpcyBhIGRyb3AtZG93biBtZW51IHRvIHNlbGVjdCBhIHBhcnRpY3VsYXIgY2hyb21vc29tZSBhbmQgYSBib3ggd2hlcmUgd2UgY2FuIGVudGVyIHRleHQuIEluc2lkZSB0aGUgdGV4dCBib3ggd2UgY2FuIGVudGVyIGEgcGFydGljdWxhciBnZW5vbWUgaW50ZXJ2YWwgb2YgaW50ZXJlc3QKCmUuZy4gYGNocjE6MTAsMDAwLTExLDAwMGAKCgpJR1Ygc2hvdWxkIG5vdyBiZSBkaXNwbGF5aW5nIGEgcmVnaW9uIG9uIGNocm9tb3NvbWUgMSBmcm9tIGJhc2UgcG9zaXRpb24gYDEwLDAwMGAgdG8gYDExLDAwMGAuIAoKIVtdKG1lZGlhL3pvb21fcmVnaW9uLlBORykKCgpBdCB0aGlzIHJlc29sdXRpb24sIHdlIGNhbiBzdGFydCB0byBzZWUgdGhlICpnZW5vbWUgc2VxdWVuY2UqLiBFYWNoIEROQSBiYXNlIGlzIHJlcHJlc2VudGVkIGJ5IGEgZGlmZmVyZW50IGNvbG91ciAoQSA9IGdyZWVuLCBDID0gYmx1ZSkgYW5kIGl0IHNlZW1zIHRoYXQgdGhpcyByZWdpb24gaXMgaGlnaGx5LXJlcGV0aXRpdmU7IGNvbXByaXNpbmcgbW9zdGx5IGBDYCBiYXNlcy4gV2UgY2FuIHpvb20gZnJ1dGhlciBpbiB1c2luZyB0aGUgem9vbSBjb250cm9sIGluIHRoZSB0b3AgcmlnaHQgb2YgSUdWCgohW10obWVkaWEvaG93X3RvX3pvb20uUE5HKQoKV2UgY2FuIHVzZSB0aGUgem9vbSBjb250cm9sLCBhbmQgYWxzbyBtb3ZlIGFsb25nIHRoZSBnZW5vbWUgYnkgaG9sZGluZyBkb3duIGJ5IG1vdXNlIGJ1dHRvbiBhbmQgc2xpZGluZyBsZWZ0LWFuZC1yaWdodCwgdG8gbmF2aWdhdGUgdG8gd2hhdGV2ZXIgZ2Vub21pYyBsb2NhdGlvbiB3ZSB3YW50LiBJZiB3ZSBrbm93biB0aGUgbmFtZSBvZiB0aGUgZ2VuZSB3ZSB3YW50IHRvIGludGVycm9nYXRlIHdlIGNhbiBuYXZpZ2F0ZSBkaXJlY3RseSB0aGVyZSB1c2luZyB0aGUgdGV4dCBib3gKCiFbXShtZWRpYS9zZWxlY3RfcmVnaW9uLlBORykKClRoZSB0ZXh0IGJveCBzaG91bGQgbm93IHVwZGF0ZSB0byBzaG93IHRoZSBjb29yZGluYXRlcyBvZiBgQlJDQTFgIChgY2hyMTc6Li4uLmApLiBBdCB0aGUgYm90dG9tIG9mIHRoZSBzY3JlZW4gd2UgY2FuIG5vdyBzZWUgdGhlICpnZW5lIG1vZGVsKiBmb3IgdGhlIGdlbmUgYEJSQ0ExYC4gIEdlbmVzIGFyZSByZXByZXNlbnRlZCBhcyBsaW5lcyBhbmQgYm94ZXMuIExpbmVzIHJlcHJlc2VudCBpbnRyb25pYyByZWdpb25zIGFuZCBib3hlcyByZXByZXNlbnQgZXhvbmljIHJlZ2lvbnMuIFRoZSBhcnJvd3MgaW5kaWNhdGUgdGhlIGRpcmVjdGlvbiAvIHN0cmFuZCBvZiB0cmFuc2NyaXB0aW9uIGZvciB0aGUgZ2VuZS4KCiFbXShtZWRpYS9nZW5lX3JlZ2lvbi5QTkcpCgo0LiBMb2FkIHRoZSBhbGlnbmVkIHJlYWRzCgpDaG9vc2UgRmlsZSA+IExvYWQgZnJvbSBGaWxlLi4uLCBzZWxlY3QgdGhlIGJhbSBmaWxlIHRoYXQgeW91IGRvd25sb2FkZWQgZnJvbSBHYWxheHksIGFuZCBjbGljayBPSy4gTm90ZSB0aGF0IHRoZSBiYW0gYW5kIGluZGV4IGZpbGVzIG11c3QgYmUgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGZvciBJR1YgdG8gbG9hZCB0aGVzZSBwcm9wZXJseS4KCiFbXShtZWRpYS9zZWxlY3RfYmFtLlBORykKClRoZSBtYWluIGRpc3BsYXkgb2YgSUdWIHNob3VsZCBub3cgdXBkYXRlIHRvIGhvbGQgdHJhY2tzIGZvciB0aGUgYWxpZ25lZCByZWFkcyBmcm9tIHRoaXMgYmFtIGZpbGUuIEl0IG1heSBzZWVtIGxpa2Ugbm90aGluZyBpcyBiZWluZyBkaXNwbGF5ZWQuIFRoaXMgaXMgYmVjYXVzZSB3ZSBhcmUgem9vbWVkLW91dCB0b28gZmFyIHRvIGJlIGFibGUgdG8gc2VlIHRoZSByZWFkcy4gKipVc2UgdGhlIHpvb20gZnVuY3Rpb24gYW5kIG1vdmUgYWxvbmcgdGhlIGdlbm9tZSB1bnRpbCB5b3UgZ2V0IHRvIHRoZSBmaXJzdCBleG9uIG9mIEJSQ0ExKiouIEFmdGVyIHlvdSBoYXZlIHpvb21lZC1pbiBmYXIgZW5vdWdoIHlvdSB3aWxsIHN0YXJ0IHRvIHNlZSBzb21lIGdyZXkgcmVjdGFuZ2xlcy4gKlRoZXNlIGFyZSB0aGUgYWxpZ25lZCByZWFkcyouCgoKSWYgeW91IGhvdmVyIG92ZXIgYSBwYXJ0aWN1bGFyIHJlYWQsIGhvdyB3aWxsIHNlZSBjb2x1bW5zIGZyb20gdGhlIGJhbSBmaWxlIGJlaW5nIGRpc3BsYXllZCBzdWNoIGFzIHRoZSBtYXBwaW5nIHF1YWxpdHkgYW5kIGluZm9ybWF0aW9uIGFib3V0IHRoZSBwYWlyZWQgcmVhZHMuCgoKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtd2FybmluZyI+CgoqKkRpc2N1c3Npb246KiogCgpMYXRlciBvbiB3ZSB3aWxsIGhhdmUgc29tZSBtb3JlIGV4YW1wbGVzIG9mIGluc3BlY3RpbmcgdmFyaWFudHMsIGJ1dCBmb3Igbm93IGxldCdzIGZhbWlsaWFyaXNlIG91cnNlbHZlcyB3aXRoIElHViBhbmQgd2hhdCB0aGUgZGF0YSBsb29rIGxpa2UKCi0gTmF2aWdhdGUgdG8gcmVnaW9uIGBjaHIxNzo0MSwyNDQsMjI4LTQxLDI0NSw3MDBgIGluIElHVi4gSG93IG1hbnkgcG90ZW50aWFsIFNOVnMgY2FuIHlvdSBmaW5kIGluc2lkZSB0aGUgcmVnaW9uPyBIb3cgbWFueSBvZiB0aGVzZSBhcmUgbGlrZWx5IHRvIGJlICpzb21hdGljKi4KCi0gTmF2aWdhdGUgdG8gcG9zaXRpb24gYGNocjE3OjQxLDIxOSw1MTNgIGluIElHVi4gSG92ZXIgb3ZlciB0aGUgY292ZXJhZ2UgdHJhY2sgYW5kIGRpc2NvdmVyIHRoZSBwZXJjZW50YWdlIG9mIHJlZmVyZW5jZSBiYXNlcyBpbiB0aGUgVHVtb3VyIGFuZCB0aGUgTm9ybWFsLiBJcyB0aGVyZSBldmlkZW5jZSBmb3IgYSBzb21hdGljIHZhcmlhbnQgYXQgdGhpcyBwb3NpdGlvbj8gCgoKPC9kaXY+CgojIFNlY3Rpb24gNjogUG9zdC1wcm9jZXNzaW5nIG9mIHJlYWRzIGFuZCBWYXJpYW50IENhbGxpbmcKCldoaWxzdCB3ZSBjYW4gaW5zcGVjdCB2YXJpYW50cyBieSBleWUsIGl0IHdvdWxkIGNsZWFybHkgYmUgaW1wb3NzaWJsZSB0byBzY3J1dGluaXNlIGVhY2ggcG9zaXRpb24gaW4gdGhlIGdlbm9tZSB0byBzZWUgaWYgYSB2YXJpYW50cyBleGlzdHMgdGhlcmUuIFdlIHdpbGwgZW1wbG95IGEgKnZhcmlhbnQgY2FsbGluZyogbWV0aG9kIHRvIG5hcnJvdy1kb3duIG91ciBzZWFyY2ggZm9yIHNvbWF0aWMgdmFyaWFudHMsIGFsdGhvdWdoIGFzIHdlIHdpbGwgc2VlLCBzdWNoIGNhbGxzIHN0aWxsIHJlcXVpcmUgc29tZSBkZWdyZWUgb2YgZmlsdGVyaW5nIGFuZCBjdXJhdGlvbi4gVGhlIHBhcnRpY3VsYXIgdG9vbCB3ZSB3aWxsIHVzZSBpcyBbdmFyc2NhbjJdKGh0dHA6Ly9ka29ib2xkdC5naXRodWIuaW8vdmFyc2Nhbi8pLCBtYWlubHkgYmVjYXVzZSBpdCBpcyBhdmFpbGFibGUgdmlhIEdhbGF4eS4gRm9yIHByb2R1Y3Rpb24tbGV2ZWwgYW5hbHlzZXMgYSB0b29sIHN1Y2ggYXMgW011VGVjdF0oaHR0cHM6Ly9zb2Z0d2FyZS5icm9hZGluc3RpdHV0ZS5vcmcvY2FuY2VyL2NnYS9tdXRlY3QpIGNvdWxkIGJlIGNvbnNpZGVyZWQuIEhvd2V2ZXIsIHRoZXJlIGFyZSBsaWNlbnNpbmcgaXNzdWVzIHdoaWNoIHByZWNsdWRlIE11VGVjdCBmcm9tIGJlaW5nIGF2YWlsYWJsZSBpbiBHYWxheHkuIAoKQmVmb3JlIHdlIGNhbiBwcm9jZWVkIHRvIHZhcmlhbnQgY2FsbGluZywgdGhlcmUgYXJlIGEgY291cGxlIG9mIHBvc3QtcHJvY2Vzc2luZyB0YXNrcyB0aGF0IHNob3VsZCBiZSBwZXJmb3JtZWQ7IHJlbW92aW5nIGR1cGxpY2F0ZXMgYW5kIGluZGVsIHJlLWFsaWdubWVudC4gCgpJbiBicmllZiwgcmVtb3ZpbmcgKmR1cGxpY2F0ZXMqIHJlbW92ZXMgcmVhZHMgdGhhdCBoYXZlICoqZXhhY3RseSB0aGUgc2FtZSoqIHN0YXJ0IGFuZCBlbmQgcG9zaXRpb24uIFN1Y2ggcmVhZHMgYXJlICphc3N1bWVkKiB0byBiZSBhbiBhcnRlZmFjdCBvZiB0aGUgUENSIHByb2Nlc3MgYW5kIGdpdmUgYSBmYWxzZSBpbXByZXNzaW9uIG9mIHRoZSBjb3ZlcmFnZSBhdCBhZmZlY3RlZCBwb3NpdGlvbnMuICpIb3dldmVyLCBjYXJlZnVsIHRoaW5raW5nIGlzIHJlcXVpcmVkIGluIHNpdHVhdGlvbnMgb3RoZXIgdGhhbiB3aG9sZS1nZW5vbWUgc2VxdWVuY2luZyBhbmQgdGhpcyBzaG91bGQgY2VydGFpbmx5IG5ldmVyIGJlIGFwcGxpZWQgZm9yIHRhcmdldGVkIHNlcXVlbmNpbmcqLgoKIVtdKG1lZGlhL3Bjcl9kdXBzLnBuZykKCkluZGVsIHJlLWFsaWdubWVudCBkZWFscyB3aXRoIGFuIGFydGVmYWN0IHRoYXQgY2FuIG9jY3VyIHdoZW4gcGxhY2luZyByZWFkcyBjbG9zZSB0byBpbmRlbHMuIFNpbmNlIGVhY2ggcmVhZCBpcyBhbGlnbmVkIHNlcGFyYXRlbHksIGFsaWdubWVudCB0b29scyBtYXkgcHJlZmVyIHRvIGFsaWduIGEgcmVhZCB3aXRoIGEgcmVmZXJlbmNlIG1pc21hdGNoIHJhdGhlciB0aGFuIGNvbnNpZGVyIGFuIGluZGVsIHdpdGhpbiBhIHJlYWQuIEhvd2V2ZXIsIHRha2luZyBhbGwgcmVhZHMgaW50byBjb25zaWRlcmF0aW9uIGFyb3VuZCBhIGxvY3VzIG1heSByZXZlYWwgdGhlIHByZXNlbmNlIG9mIGFuIGluZGVsIGFuZCBwcmV2ZW50IFNOVnMgYmVpbmcgZmFsc2VseSBpZGVudGlmaWVkLgoKKkJlZm9yZSByZWFsaWdubWVudCoKCiFbXShtZWRpYS9pbmRlbF9yZWFsaWduLnBuZykKCipBZnRlciByZWFsaWdubWVudCoKCiFbXShtZWRpYS9pbmRlbF9yZWFsaWduX2FmdGVyLnBuZykKCihzZWUgdGhpcyBbdmlkZW9dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9Uy1Xa1E1bjBMTFEpIGZvciBhbiBleHBsYW5hdGlvbikKCk5vdyBmb2xsb3cgdGhlIHN0ZXBzIGluIFsiTWFwcGVkIFJlYWRzIHBvc3Rwcm9jZXNzaW5nIl0oaHR0cHM6Ly90cmFpbmluZy5nYWxheHlwcm9qZWN0Lm9yZy90cmFpbmluZy1tYXRlcmlhbC90b3BpY3MvdmFyaWFudC1hbmFseXNpcy90dXRvcmlhbHMvc29tYXRpYy12YXJpYW50cy90dXRvcmlhbC5odG1sI21hcHBlZC1yZWFkcy1wb3N0cHJvY2Vzc2luZykgZnJvbSB0aGUgZ2FsYXh5IHRyYWluaW5nIHBhZ2UsIGJlZm9yZSBwcm9jZWVkaW5nIHRvIFsiVmFyaWFudCBjYWxsaW5nIGFuZCBjbGFzc2lmaWNhdGlvbiJdKGh0dHBzOi8vdHJhaW5pbmcuZ2FsYXh5cHJvamVjdC5vcmcvdHJhaW5pbmctbWF0ZXJpYWwvdG9waWNzL3ZhcmlhbnQtYW5hbHlzaXMvdHV0b3JpYWxzL3NvbWF0aWMtdmFyaWFudHMvdHV0b3JpYWwuaHRtbCN2YXJpYW50LWFubm90YXRpb24tYW5kLXJlcG9ydGluZykKCgojIFNlY3Rpb24gNzogQW5ub3RhdGlvbgoKIyMgQWJvdXQgdmNmIGZvcm1hdAoKCkluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB5b3Ugd2lsbCBoYXZlIHByb2R1Y2VkIGEgKnZjZiogZmlsZS4gVGhlIGAudmNmYCBmb3JtYXQgd2FzIGluaXRpYWxseSBkZXZlbG9wZWQgYnkgdGhlIFsxMDAwIEdlbm9tZXMgUHJvamVjdF0oaHR0cDovL3d3dy4xMDAwZ2Vub21lcy5vcmcvd2lraS9BbmFseXNpcy92Y2Y0LjApLCBhbmQgb3duZXJzaGlwIGhhcyBiZWVuIHN1YnNlcXVlbnRseSB0cmFuc2ZlcnJlZCB0byBbR2xvYmFsIEFsbGlhbmNlIGZvciBHZW5vbWljcyBhbmQgSGVhbHRoIERhdGEgV29ya2luZyBncm91cCBmaWxlIGZvcm1hdCB0ZWFtXShodHRwOi8vZ2E0Z2gub3JnLyMvZmlsZWZvcm1hdHMtdGVhbSkuIFRoZSBmb3JtYXQgY2FuIGJlIHVzZWQgdG8gcmVwcmVzZW50IGluZm9ybWF0aW9uIGFib3V0IGFsbCBraW5kcyBvZiBnZW5vbWljIHZhcmlhdGlvbi4gSW4gdGhpcyBzZXNzaW9uIHdlIHdpbGwganVzdCBjb25zaWRlciBTTlZzLgoKV2UgZG9u4oCZdCByZXF1aXJlIGFueSBzcGVjaWFsaXNlZCBzb2Z0d2FyZSB0byBsb29rIGF0IHRoZSBjb250ZW50cyBvZiBhIHZjZiBmaWxlLiBUaGV5IGNhbiBiZSBvcGVuZWQgaW4gYSBib2ctc3RhbmRhcmQgdGV4dCBlZGl0b3IsIGhvd2V2ZXIgeW91ciBsYXB0b3AgbWF5IHRyeSBhbmQgaW50ZXJwcmV0IHRoZSBmaWxlIGFzIGNvbnRhaW5pbmcgY29udGFjdCBpbmZvcm1hdGlvbiAodmlydHVhbCBjb250YWN0IGZpbGUpLgoKSW4gYSBzaW1pbGFyIHZlaW4gdG8gdGhlIGAuYmFtYCBhbmQgYC5zYW1gIGZpbGVzIHdlIHNhdyBlYXJsaWVyLCB0aGUgYC52Y2ZgIGZpbGVzIGNvbnRhaW5zIG1hbnkgbGluZXMgb2YgaGVhZGVyIGluZm9ybWF0aW9uLiBUaGVzZSBkZXNjcmliZSB0aGUgcmVmZXJlbmNlIHNlcXVlbmNlcyBhbmQgdmFyaW91cyBmaWx0ZXJzIHRoYXQgaGF2ZSBiZWVuIGFwcGxpZWQuCgoKYGBgCiMjZmlsZWZvcm1hdD1WQ0Z2NC4yCiMjRklMVEVSPTxJRD1QQVNTLERlc2NyaXB0aW9uPSJBbGwgZmlsdGVycyBwYXNzZWQiPgojI3JlZmVyZW5jZT1yZWYuZmEKIyNjb250aWc9PElEPWNocjUsbGVuZ3RoPTE4MDkxNTI2MD4KIyNjb250aWc9PElEPWNocjEyLGxlbmd0aD0xMzM4NTE4OTU+CiMjY29udGlnPTxJRD1jaHIxNyxsZW5ndGg9ODExOTUyMTA+CiMjRklMVEVSPTxJRD1WYXJDb3VudCxEZXNjcmlwdGlvbj0iRmV3ZXIgdGhhbiA0IHZhcmlhbnQtc3VwcG9ydGluZyByZWFkcyI+CiMjRklMVEVSPTxJRD1WYXJGcmVxLERlc2NyaXB0aW9uPSJWYXJpYW50IGFsbGVsZSBmcmVxdWVuY3kgYmVsb3cgMC4wNSI+CiMjRklMVEVSPTxJRD1WYXJBdmdSTCxEZXNjcmlwdGlvbj0iQXZlcmFnZSBjbGlwcGVkIGxlbmd0aCBvZiB2YXJpYW50LXN1cHBvcnRpbmcgcmVhZHMgPCA5MCI+Ci4uLi4uLgouLi4uLi4KCmBgYAoKQWZ0ZXIgbWFueSBtb3JlIGxpbmVzIG9mIGluZm9ybWF0aW9uLCB3ZSBmaW5hbGx5IGdldCB0byB0aGUgZGV0YWlscyBvZiB0aGUgYWN0dWFsIGNhbGxzIHRoZW1zZXZsZXMuIFRoaXMgcGFydCBvZiB0aGUgZmlsZSBpcyB0YWItZGVsaW1pdGVkOyB3aXRoIDEwIGNvbHVtbnMgZm9yIGV2ZXJ5IGNhbGwuIFRoZSB2Y2Ygc3BlY2lmaWNhdGlvbiBwYWdlIGdpdmVzIGRldGFpbHMgb2Ygd2hhdCBzaG91bGQgYmUgY29udGFpbmVkIGluIGVhY2ggY29sdW1uCgoKU2hvd24gaGVyZSBpcyB0aGUgaW5mb3JtYXRpb24gYWJvdXQgdGhyZWUgY2FsbHMKCmBgYAojQ0hST00JUE9TCUlECVJFRglBTFQJUVVBTAlGSUxURVIJSU5GTwlGT1JNQVQJTk9STUFMCVRVTU9SCmNocjUJMjI1NzY4CS4JRwlDCS4JVmFyUmVhZFBvcwlEUD0yNztTUz0xO1NTQz0wO0dQVj01LjEzNjNlLTE2O1NQVj0xCUdUOkdROkRQOkFEOkFERjpBRFIJMS8xOi46MTY6MCwxNjowLDI6MCwxNAkxLzE6LjoxMTowLDExOjAsMTowLDEwCmNocjUJMjMwOTgwCS4JQQlHCS4JUEFTUwlEUD0xNTc7U1M9MTtTU0M9MDtHUFY9MDtTUFY9MQlHVDpHUTpEUDpBRDpBREY6QURSCTEvMTouOjg4OjAsODg6MCw1MTowLDM3CTEvMTouOjY5OjAsNjk6MCw0NTowLDI0CmNocjUJMjMxMTExCS4JVAlDCS4JUEFTUwlEUD0xMjc7U1M9MTtTU0M9MDtHUFY9MDtTUFY9MQlHVDpHUTpEUDpBRDpBREY6QURSCTEvMTouOjc1OjAsNzU6MCwzOTowLDM2CTEvMTouOjUyOjAsNTI6MCwyNjowLDI2CmBgYAoKVGhlIGZpcnN0IHNldmVuIGNvbHVtbnMgc2hvdWxkIGxvb2sgY29uc2lzdGVudCBhY3Jvc3MgZGlmZmVyZW50IGdlbm90eXBlIGNhbGxlcnMuIFRoZSBjb250ZW50cyBvZiB0aGUgYElORk9gIGFuZCBgRk9STUFUYCBjb2x1bW5zIHdpbGwgZGVwZW5kIG9uIHdoYXQgdmFyaWFudCBjYWxsZXIgaGFzIGJlZW4gdXNlZC4gVGhlIGBJTkZPYCBjb2x1bW4gY29udGFpbnMgbWV0cmljcyBhbmQgb3RoZXIgaW5mb3JtYXRpb24gcmVsYXRlZCB0byBlYWNoIHZhcmlhbnQgY2FsbCBhcyBhIHNldCBvZiBgS0VZPVZBTFVFYCBwYWlycy4gRWFjaCBwYWlyIGlzIHNlcGFyYXRlZCBieSBhIGA7YCBjaGFyYWN0ZXIuCgpUaGUgSU5GTyBmb3IgdGhlIGEgdmFyaWFudCBjYWxsIG1heSByZWFkIGFzOi0KCmBgYApEUD0yNztTUz0xO1NTQz0wO0dQVj01LjEzNjNlLTE2O1NQVj0xCmBgYAoKb3IgCgpgYGAKICAgICAgS2V5ICAgVmFsdWUKRFA9MjcgRFAgICAgMjcKU1M9MSAgU1MgICAgMQpTU0M9MCBTU0MgICAwCkdQVj01LjEuLiBHUFYgICA1LjEzNjNlLTE2ClNQVj0xIFNQViAgIDEKCmBgYAoKVGhlIG1lYW5pbmcgb2YgZWFjaCBrZXkgY2FuIGJlIGRpc2NvdmVyZWQgYnkgbG9va2luZyBhdCB0aGUgaGVhZGVyIGZvciB0aGUgZmlsZS4gZS5nLiBgIyNGT1JNQVQ9PElEPURQLE51bWJlcj0xLFR5cGU9SW50ZWdlcixEZXNjcmlwdGlvbj0iUmVhZCBkZXB0aCI+YC4gU28gdGhpcyB2YXJpYW50IGhhcyBhIHRvdGFsIG9mIDI3IGJhc2VzIGNvdmVyaW5nIGl0LiAKCgpUaGUgZmluYWwgdHdvIGNvbHVtbnMgaW4gdGhlIGZpbGUgZGVzY3JpYmVzIHRoZSBjYWxscyBmb3IgdGhlIE5PUk1BTCBhbmQgVFVNT1VSIHNhbXBsZXMgcmVzcGVjdGl2ZWx5LiBJbiB0aGUgc2FtcGxlIGNvbHVtbiAoYE5PUk1BTGApIGZvciB0aGUgZmlyc3QgdmFyaWFudCB3ZSBzZWUgdGhlIGVudHJ5CgpgYGAKMS8xOi46MTY6MCwxNjowLDI6MCwxNApgYGAKClRoZXNlIGFyZSB2YWx1ZXMgc2VwYXJhdGVkIGJ5IGEgYDpgIGNoYXJhY3RlciBhbmQgdGhleSBhcmUgaW50ZXJwcmV0ZWQgaW4gdGhlIHNhbWUgb3JkZXIgYXMgZGljdGF0ZWQgYnkgdGhlIEZPUk1BVCBjb2x1bW47IHdoaWNoIGlzIGBHVDpHUTpEUDpBRDpBREY6QURSYAoKYGBgCiMjRk9STUFUPTxJRD1HVCxOdW1iZXI9MSxUeXBlPVN0cmluZyxEZXNjcmlwdGlvbj1HZW5vdHlwZT4KIyNGT1JNQVQ9PElEPUdRLE51bWJlcj0xLFR5cGU9SW50ZWdlcixEZXNjcmlwdGlvbj0iR2Vub3R5cGUgcXVhbGl0eSI+CiMjRk9STUFUPTxJRD1EUCxOdW1iZXI9MSxUeXBlPUludGVnZXIsRGVzY3JpcHRpb249IlJlYWQgZGVwdGgiPgojI0ZPUk1BVD08SUQ9QUQsTnVtYmVyPVIsVHlwZT1JbnRlZ2VyLERlc2NyaXB0aW9uPSJSZWFkIGRlcHRoIGZvciBlYWNoIGFsbGVsZSI+CiMjRk9STUFUPTxJRD1BREYsTnVtYmVyPVIsVHlwZT1JbnRlZ2VyLERlc2NyaXB0aW9uPSJSZWFkIGRlcHRoIGZvciBlYWNoIGFsbGVsZSBvbiB0aGUgZm9yd2FyZCBzdHJhbmQiPgojI0ZPUk1BVD08SUQ9QURSLE51bWJlcj1SLFR5cGU9SW50ZWdlcixEZXNjcmlwdGlvbj0iUmVhZCBkZXB0aCBmb3IgZWFjaCBhbGxlbGUgb24gdGhlIHJldmVyc2Ugc3RyYW5kIj4KYGBgCgpTbyBmb3IgdGhpcyBwYXJ0aWN1bGFyIHZhcmlhbnQgdGhlcmUgaXMgYSBnZW5vdHlwZSBvZiBgMVwxYCAoSG9tb3p5Z291cyBmb3IgdGhlIGFsdGVybmF0ZSBhbGxlbGUpIGluIHRoZSBub3JtYWwgc2FtcGxlIGFuZCBhIGRlcHRoIG9mIGAxNmAgZXRjLiBUaGUgc2FtZSBnZW5vdHlwZSBpbmZvcm1hdGlvbiBpcyByZXBlYXRlZCBmb3IgdGhlIHR1bW91ci4gRnJvbSB0aGlzIHdlIGNhbiBpbmZlciB3aGV0aGVyIHRoZSB2YXJpYW50IGlzIGxpa2VseSB0byBiZSBzb21hdGljIG9yIG5vdCBhbmQgZ2FpbiBpbnNpZ2h0IGludG8gd2hldGhlciBpdCBpcyBhIHRydWUgdmFyaWFudCBvciBhIGZhbHNlIHBvc2l0aXZlICh3aGljaCB3ZSB3aWxsIGRpc2N1c3MgaW4gZGV0YWlsIGxhdGVyKS4KCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4KCioqRGlzY3Vzc2lvbjoqKiBMb2NhdGUgdGhlIGxpbmVzIGluIHRoZSB2Y2YgZmlsZSB0aGF0IHJlbGF0ZSB0byBzb21lIG9mIHRoZSBwb3NpdGlvbnMgdGhhdCB3ZSBsb29rZWQgYXQgcHJldmlvdXNseSBpbiBJR1YuIEhvdyBtYW55IHJlYWRzIGluIHRvdGFsIGNvdmVyIGVhY2ggcG9zaXRpb24/CgotIGBjaHIxNzo0MTI0NDkzNmAKLSBgY2hyMTc6NDEyMTk1MTNgCi0gYGNocjE3OjQxMjM0MzA0YAoKV2hhdCBraW5kIG9mIHZhcmlhbnRzIChHZXJtbGluZSwgU29tYXRpYykgaGF2ZSBiZWVuIGNhbGxlZCBhdCB0aGVzZSBwb3NpdGlvbnM/IAoKWW91IGNhbiBhbHNvIGxvYWQgdGhlIHZjZiBpbnRvIElHViwgd2hpY2ggd2lsbCBkaXNwbGF5IGRldGFpbHMgb2YgZWFjaCB2YXJpYW50IGNhbGwgYWJvdmUgdGhlIGFsaWduZWQgcmVhZHMuCiFbXShtZWRpYS9yZWFkcy13aXRoLXZjZi5wbmcpCgo8L2Rpdj4KCgoKIyMgQW5ub3RhdGluZyB3aXRoIFNOUGVmZgoKQXMgd2UgaGF2ZSBzZWVuIHRoZSBzdGFuZGFyZCB2Y2YgZmlsZSBjb250YWlucyBnZW5vbWUgY29vcmRpbmF0ZXMgZm9yIGVhY2ggdmFyaWFudCwgYnV0IGdpdmVzIG5vIHVzZWZ1bCBpbmZvcm1hdGlvbiBhYm91dCB3aGF0IGdlbmUgKGlmIGFueSkgdGhlIHZhcmlhbnQgbGllcyB3aXRoaW4gb3IgdGhlIHBvdGVudGlhbCBpbXBhY3Qgb2YgdGhlIHZhcmlhbnQuIE9uZSBzdWNoIHRvb2wgZm9yIGFkZGluZyBnZW5vbWljIGluZm9ybWF0aW9uIGlzIFNOUGVmZiB3aGljaCBpcyBkZXNjcmliZWQgaW4gdGhlIEdhbGF4eSB0dXRvcmlhbC4KCi0gW1NlZSBoZXJlXShodHRwczovL3RyYWluaW5nLmdhbGF4eXByb2plY3Qub3JnL3RyYWluaW5nLW1hdGVyaWFsL3RvcGljcy92YXJpYW50LWFuYWx5c2lzL3R1dG9yaWFscy9zb21hdGljLXZhcmlhbnRzL3R1dG9yaWFsLmh0bWwjYWRkaW5nLWFubm90YXRpb25zLXRvLXRoZS1jYWxsZWQtdmFyaWFudHMpOyAqKiJBZGRpbmcgZnVuY3Rpb25hbCBnZW5vbWljIGFubm90YXRpb25zIiBvbmx5KioKClNOUGVmZiB3aWxsIHByb2R1Y2UgYSBtb2RpZmllZCBgdmNmYCBmaWxlIGFuZCBhIEhUTUwgcmVwb3J0LiAKCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPgoKKipEaXNjdXNzaW9uOioqIFNjcm9sbCB0aHJvdWdoIHRoZSBjb250ZW50cyBvZiB0aGUgdmNmIGZpbGUgcHJvZHVjZWQgYnkgc25wZWZmLiBXaGF0IGV4dHJhIGluZm9ybWF0aW9uIGhhcyBpdCBhZGRlZD8gVHJ5IGFuZCBsb2NhdGUgdGhlIHZhcmlhbnRzIHdpdGhpbiBgQlJDQTFgLiBBbHNvIHRha2Ugc29tZSB0aW1lIHRvIGRpZ2VzdCB0aGUgY29udGVudHMgb2YgdGhlIEhUTUwgcmVwb3J0IGFuZCB0aGUgaW5mb3JtYXRpb24gaXQgcHJvdmlkZXMKCjwvZGl2PgoKCgojIyBBbm5vdGF0aW9uIHdpdGggRW5zZW1ibCBWRVAKCkEgdXNlZnVsIGFsdGVybmF0aXZlIHRvIHJ1bm5pbmcgU05QZWZmIHdpdGhpbiBHYWxheHkgaXMgdGhlIG9ubGluZSBWRVAgdG9vbCBwcm92aWRlZCBieSBFbnNlbWJsLiBUaGlzIHdpbGwgYW5ub3RhdGUgb3VyIHZhcmlhbnRzIHdpdGggZ2VuZSBpZGVudGlmaWVycyBhbmQgYWxzbyBwcm92aWRlIHNvbWUgcHJlZGljdGlvbnMgYWJvdXQgdGhlIGltcGFjdCBvZiB0aGUgdmFyaWFudC4gCgpNb3JlIGRvY3VtZW50YXRpb24gb24gRW5zZW1ibCBWRVAgaXMgW2F2YWlsYWJsZSBvbmxpbmVdKGh0dHA6Ly9ncmNoMzcuZW5zZW1ibC5vcmcvaW5mby9kb2NzL3Rvb2xzL3ZlcC9vbmxpbmUvaW5kZXguaHRtbCkKCkNvbW1hbmQgbGluZSB0b29scyBhcmUgYXZhaWxhYmxlLCBidXQgd2Ugd2lsbCB1c2UgdGhlIG9ubGluZSBpbnRlcmZhY2U7IG1ha2luZyBzdXJlIHRoYXQgd2UgYWNjZXNzIHRoZSB2ZXJzaW9uIG9mIFZFUCB3aXRoIHRoZSBjb3JyZWN0IGdlbm9tZSB2ZXJzaW9uLiBHb2luZyBzdHJhaWdodCB0byB0aGUgRW5zZW1ibCBWRVAgd2Vic2l0ZSB3aWxsIG1lYW4gdXNpbmcgYSBsYXRlciBnZW5vbWUgYnVpbGQuCgpUaGUgKipoZzE5KiogdmVyc2lvbiBvZiBWRVAgY2FuIGJlIGFjY2Vzc2VkIFtoZXJlXShodHRwOi8vZ3JjaDM3LmVuc2VtYmwub3JnL0hvbW9fc2FwaWVucy9Ub29scy9WRVApLiBBIHNldCBvZiBjb29yZGluYXRlcyBjYW4gYmUgZW50ZXJlZCBpbnRvIHRoZSB0ZXh0IGJveCwgb3IgYSBWQ0YgZmlsZSBjYW4gYmUgdXBsb2FkZWQuCgohW10obWVkaWEvdmVwLXVwbG9hZC5wbmcpCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4KVXBsb2FkIHRoZSBgdmNmYCBmaWxlIHRoYXQgeW91IGFubm90YXRlZCB3aXRoIFNOUGVmZi4gSWYgeW91IHdlcmUgdW5hYmxlIHRvIGNvbXBsZXRlIHRoaXMgc3RlcCwgYSBjb3B5IGlzIGF2YWlsYWJsZSBpbiB0aGUgZ29vZ2xlIGRyaXZlOyBgMjMxMzM1XzIzMTMzNl9WYXJTY2FuX1ZhcmlhbnRzX1NucEVmZl9TUzIudmNmYC4KPC9kaXY+CgpZb3Ugd2lsbCBoYXZlIGEgY2hvaWNlIGFib3V0IHdoYXQgdHJhbnNjcmlwdCBkYXRhYmFzZSB0byB1c2UuIFRoZSBvdXRwdXQgY2FuIGFsc28gYmUgY29uZmlndXJlZCBieSBjbGlja2luZyB0aGUgKisqIHN5bWJvbCBuZXh0IHRvIGEgcGFydGljdWxhciBzZWN0aW9uLiBlLmcuICpWYXJpYW50cyBhbmQgZnJlcXVlbmN5IGRhdGEqLiBBZnRlciBzZWxlY3RpbmcgdGhlIG9wdGlvbnMgeW91IHdhbnQsIHNjcm9sbCBkb3duIHRvIHRoZSBib3R0b20gb2YgdGhlIHBhZ2UgYW5kIGNsaWNrICoqUnVuKiouIFRoZSBzY3JlZW4gc2hvdWxkIG5vdyBjaGFuZ2UgdG8gbGV0IHlvdSBrbm93IHRoYXQgVkVQIGlzIHJ1bm5pbmcuCgohW10obWVkaWEvdmVwLXJ1bm5pbmcucG5nKQoKVGhlIHNjcmVlbiB3aWxsIHJlZnJlc2ggYnkgaXRzZWxmLCBhbmQgZXZlbnR1YWxseSBhIGdyZWVuICpEb25lKiBib3ggc2hvdWxkIGFwcGVhci4gQXQgd2hpY2ggcG9pbnQgeW91IHdpbGwgYmUgYWJsZSB0byBpbnNwZWN0IHRoZSByZXN1bHRzCgohW10obWVkaWEvdmVwLWZpbmlzaGVkLnBuZykKClRoZSByZXN1bHRzIGNhbiBiZSBpbnNwZWN0ZWQgb25saW5lLCBvciBkb3dubG9hZGVkLiBEb3dubG9hZGluZyBhcyBhIHRleHQgZmlsZSBpcyBiZXR0ZXIgZm9yIGJyb3dzaW5nIGluIEV4Y2VsLCBhbmQgY2FuIGFsc28gYmUgbWFuaXB1bGF0ZWQgaW4gbGFuZ3VhZ2VzIHN1Y2ggYXMgUi4KCiMjIEFzc2Vzc21lbnQgb2YgU29tYXRpYyBjYWxscwoKW0NsaWNrIGhlcmVdKHNvbWF0aWNfc252X2Fzc2Vzc21lbnRfZXhlcmNpc2UuaHRtbCkgdG8gZm9sbG93IGFuIGV4ZXJjaXNlIG9uIGluc3BlY3RpbmcgYW5kIGV2YWx1YXRpbmcgc29tYXRpYyBjYWxscwo=