Hands-on NGS 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 NGS 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.

Parts of this tutorial are based on the NGS tutorial from the Galaxy Project and the IGV tutorial from the Griffin lab.

The tutorial covers the following steps in our analysis pipeline


Background

Where do the data in this tutorial come from?

The data for this tutorial are publicly-available exome sequencing data downsampled to the BRCA2 region from a fictitious patient. We will use these data throughout the course to call variants, filter and discuss the clinical impact of any mutations.

Section 1: Preparation

Ignore if you have already created a Galaxy account and uploaded the example data in a previous exercise

1. Register as a new user on one of the public Galaxy servers

Make sure you check your email to activate your account

2. 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.

You can import the data by:

  1. In the tool panel located on the left, under Basic Tools select Get Data > Upload File. Click on the Paste/Fetch data button on the bottom section of the pop-up window.
  2. Upload the sequence data by selecting the files JoeBlogsBRCAPanel_R1.fastq and JoeBlogsBRCAPanel_R2.fastq. You don’t need to specify the file type or genome build. Galaxy should be able to make a reasonable guess.

  3. You should now have these 2 files in your history:
    • JoeBlogsBRCAPanel_R1.fastq
    • JoeBlogsBRCAPanel_R2.fastq

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

JoeBlogsBRCAPanel_R1.fastq

@HWI-D00461:188:HVGY2BCXY:1:1101:1363:84148/1
TGTGTCATTTCTATTATCTTTGGAACAACCATGAATTAGTCCCTTGGGGTTTTCAAATGCTGCACACTGACTCACACATTTATTTGGTTCTGTTTTTGCCTTCCCTNN
+
DDDDDIHIIIIIHIIIIIIIIIIHIIIIIIIIIHIIIIIIHHIIIIIIIHIIIHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHHIDHHIHC#

JoeBlogsBRCAPanel_R2.fastq

@HWI-D00461:188:HVGY2BCXY:1:1101:1363:84148/2
TGGAAAGACTTTTGGGGGGGGGAGTATTTTTCTTGTTTCTGGTTTTGGTTTTTTTGATCCGGGAAAGATTTTGTTTTTTGGAGGTTGGACTTTTGGGGAGGGGAAAAN
+
<00<<1111<1<11/0/<///</<0111DF11<<11111<11111<1/1<1D1///<<11<<</<1111<<11<DD1<//<110<11/11<0<0</0<0<<-//<<FE

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 JoeBlogsBRCAPanel_R1.fastq; DDDDDIHI....

Character Code Minus 33 Offset Probability
D 68 35 0.0003162278
D 68 35 0.0003162278
D 68 35 0.0003162278
D 68 35 0.0003162278
D 68 35 0.0003162278
I 73 40 0.0001000000
H 72 39 0.0001258925
I 73 40 0.0001000000

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


Section 3: Quality assessment with FastQC

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.

  • From the left hand tool panel in Galaxy, under GENOMIC FILE MANIPULATION, select FASTQ Quality Control -> FastQC
  • Select one of the FASTQ files as input and Execute the tool.
  • When the tool finishes running, you should have an HTML file in your History. Click on the eye icon to view the various quality metrics.

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

Good quality data should look something like:-

Look at the generated FastQC metrics for your uploaded fastq files. This data looks pretty good - high per-base quality scores (most above 30).

All is not lost if we observe poor quality bases towards the end of the read. There are a number of trimming options that we can use for NGS data and some of these are available through Galaxy. Check out the Trimmming Reads section of the Galaxy NGS tutorial if you are interested in how we can trim our reads.

It is also worth bearing in mind that the tool is blind to the particular type of sequencing you are performing (i.e. whole-genome, ChIP-seq, RNA-seq) and the organism being sequenced, so some warnings might be expected due to the nature of your experiment. For instance, there are known sequencing composition biases that can occur at the beginning of RNA-seq reads.

Aggregating QC reports with multiqc

For datasets with large numbers of fastq files, it may be useful to aggregate the individual reports into a single combined report.

  • Under GENOMIC FILE MANIPULATION, select FASTQ Quality Control -> MultiQC
  • Make sure Software name is set to FastQC
  • In Results file, select the RawData results files that you have just generated

You should then be able to view the fastqc plots for both the fastq files on the same page.

Section 4: Alignment

We don’t really spend much time look at fastq files, as most of our time is spent with aligned reads. i.e. we have used some software to tell us whereabouts in the genome each read belongs to. This will usually be performed for you as part of a sequencing service, but it is good to get an appreciation of the steps involved.

In this section we map the reads in our FASTQ files to a reference genome.

A plethora of different tools have been written to perform this task, and we will not describe it in detail. Links to some key publications are given below:-

Alignment relies on the reference genome being indexed so that the sequencing reads can be located more efficiently. The genome index is a highly-accessible data structure, and Galaxy includes indices for many popular genomes.

1.Align the example files

  • Find the tool GENOMICS ANALYSIS -> Mapping -> Bowtie2
  • alternatively, type bowtie in the search box
  • In Is this single-end or Paired-end? Select Paired-end
  • Set FastQ file #1 and FastQ file #2 to the two fastq files you uploaded in the previous step
  • Make sure the reference genome is set to Human (Homo sapiens):hg19
  • Press Execute
  • Wait!

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

2. View the alignments

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

About the bam file format

Unlike most of Bioinformatics, a single standard file format has emerged for aligned reads. Moreover, 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.

The .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 a md5sumdigital fingerprint” of the .fasta file used for alignment (M5).


@HD VN:1.0 SO:coordinate
@SQ SN:chr10 LN:135534747
@SQ SN:chr11 LN:135006516
@SQ SN:chr11_gl000202_random LN:40103
@SQ SN:chr12 LN:133851895
@SQ SN:chr13 LN:115169878
@SQ SN:chr14 LN:107349540
@SQ SN:chr15 LN:102531392
@SQ SN:chr16 LN:90354753
.....
.....

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

@PG ID:bowtie2 PN:bowtie2 VN:2.3.4.1 CL:"/jetstream/scratch0/main/conda/envs/mulled-v1-65d5efe4f1b69ab7166d1a5a5616adebe902133ea3e4c189d87d7de2e21ddc17/bin/bowtie2-align-s --wrapper basic-0 -p 10 -x /cvmfs/data.galaxyproject.org/byhand/hg19/hg19full/bowtie2_index/hg19full -1 input_f.fastq -2 input_r.fastq"
....
....

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

HWI-D00461:188:HVGY2BCXY:1:1109:3430:66266  163 13  32889826    42  108M    =   32889969    251 TTGGGACGAGCGCGTCTTCCGTAGTCCCAGTCCAGCGTGGCGGGGGAGCGCCTCACGCCCCGGGTCGCTGCCGCGGCTTCTTGCCCTTTTGTCTCTGCCAACCCCCAC    0D@@?GEHCHHCEHIDHH?1CCHCHI@1<CCCFC@GCCCEHIHCHICHC?HH=GHE1DE<CEHDEHHC<CCH/?HHG/<1<D@11D?G?FGHEHH01D00D;00<DH<    AS:i:-5 XN:i:0 XM:i:1 XO:i:0 XG:i:0 NM:i:1 MD:Z:21C86 YS:i:-5 YT:Z:CP
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 Position 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, bowtie2 produces a bam where the reads are in the same order as the fastq. However, this is rather inconvenient 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.

Quality 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.

3. Check 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 bowtie2.

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. For our example dataset we only have reads from a small region, so shouldn’t expect to see alignments to each chromosome.

About Duplicates

The preparation of a sequencing library requires PCR amplification of your starting material. This can lead to some DNA fragments being over-represented in your data. As our DNA fragments are formed in a random process, and relatively small compared to the number of bases to be sequenced from the genome (3Gb in humans), we tend to think the two DNA fragments that have identical starting and ending position are unlikely to have occurred due to chance. Some software, such as Picard will identify such artefacts and mark them for attention by downstream methods. i.e. they are not completely discarded from the analysis.

4. Mark Duplicates with Picard

  1. Use the tool GENOMICS TOOLKITS -> Picard -> MarkDuplicates
  2. In Select SAM/BAM dataset or dataset collection choose the bam file produced by bowtie2.
  3. What do you notice about the flag values for any reads that have the same start as another read?
  4. Interpret the meaning of these flags using the online tool

Warning the assumption about reads having the same start location being PCR duplicates falls down when we do sequencing for a very specific region of the genome. e.g. targeted sequencing from a panel of cancer genes. Running a tool to mark PCR duplicates on such data would recommend a high proportion of reads be ignored from further analysis.

5. (Optional) Re-run the alignment statistics

  1. Select the tool GENOMIC FILE MANIPULATION -> SAM/BAM -> Samtools flagstat
  2. In the BAM File to Convert box choose the bam file produced by the mark duplicates step

6. Download your bam file

For the next step you will need to download the bam file that you produced after marking duplicates. To do this, you can click the floppy disk icon.

Make sure that you click both Download dataset and Download bam_index

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. Furthermore, 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

If you are unable to download IGV, you should be able to run a web-app from the Broad Institute website with the same functionality.

https://igv.org/app/

  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. 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 further 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. Note that some downsampling may occur meaning that not all reads are displayed to reduce memory requirements.

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.

Coloured-letters within the read indicate bases that are different to the reference genome. The entire read may be coloured differently to grey, which can indicate different things depending on how the display has been configured. For example, it can highlight paired-reads with an insert size different to that expected (see here). The display of aligned reads can be configured through the menus, as described here.

LS0tCnRpdGxlOiAiIgphdXRob3I6ICJNYXJrIER1bm5pbmciCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCgoKIyBIYW5kcy1vbiBOR1MgQW5hbHlzaXMgaW4gR2FsYXh5IGFuZCBJR1YKCiMjIyBTaGVmZmllbGQgQmlvaW5mb3JtYXRpY3MgQ29yZQo8aW1nIHNyYz0ibWVkaWEvbG9nby1zbS5wbmciIGFsaWduPXJpZ2h0PgoKd2ViIDogW3NiYy5zaGVmLmFjLnVrXShodHRwOi8vc2JjLnNoZWYuYWMudWspICAKdHdpdHRlcjogW1NoZWZmQmlvaW5mQ29yZV0oaHR0cHM6Ly90d2l0dGVyLmNvbS9TaGVmZkJpb2luZkNvcmUpICAKZW1haWw6IFtiaW9pbmZvcm1hdGljcy1jb3JlQHNoZWZmaWVsZC5hYy51a10oYmlvaW5mb3JtYXRpY3MtY29yZUBzaGVmZmllbGQuYWMudWspCgotLS0tLQoKIyBUdXRvcmlhbCBPdmVydmlldwoKVGhpcyB0dXRvcmlhbCB3aWxsIGNvdmVyIHRoZSBiYXNpY3Mgb2YgTkdTIGFuYWx5c2lzIHVzaW5nIEdhbGF4eTsgYSBvcGVuLXNvdXJjZSB3ZWItYmFzZWQgcGxhdGZvcm0gZm9yIHRoZSBhbmFseXNpcyBvZiBiaW9sb2dpY2FsIGRhdGEuIFlvdSBzaG91bGQgZ2FpbiBhbiBhcHByZWNpYXRpb24gb2YgdGhlIHRhc2tzIGludm9sdmVkIGluIGEgdHlwaWNhbCBOR1MgYW5hbHlzaXMgYW5kIGJlIGNvbWZvcnRhYmxlIHdpdGggdGhlIG91dHB1dHMgZ2VuZXJhdGVkIGJ5IGEgc2VxdWVuY2luZyBzZXJ2aWNlLllvdSB3aWxsIGFsc28gdXNlIHRoZSBJbnRlZ3JhdGl2ZSBHZW5vbWljcyBWaWV3ZXIgKElHVikgdG8gKnZpZXcqIHRoZSBhbGlnbmVkIHJlYWRzIGluIGFuIGludGVyYWN0aXZlIG1hbm5lci4KClBhcnRzIG9mIHRoaXMgdHV0b3JpYWwgYXJlIGJhc2VkIG9uIHRoZSBOR1MgdHV0b3JpYWwgZnJvbSB0aGUgR2FsYXh5IFByb2plY3QgYW5kIHRoZSBJR1YgdHV0b3JpYWwgZnJvbSB0aGUgR3JpZmZpbiBsYWIuCgotIFtHYWxheHkgTkdTIFR1dG9yaWFsXShodHRwczovL2dhbGF4eXByb2plY3Qub3JnL3R1dG9yaWFscy9uZ3MvKQotIFtJR1YgVHV0b3JpYWxdKGh0dHBzOi8vZ2l0aHViLmNvbS9ncmlmZml0aGxhYi9ybmFzZXFfdHV0b3JpYWwvd2lraS9JR1YtVHV0b3JpYWwpCgpUaGUgdHV0b3JpYWwgY292ZXJzIHRoZSBmb2xsb3dpbmcgc3RlcHMgaW4gb3VyIGFuYWx5c2lzIHBpcGVsaW5lCgohW10obWVkaWEvcGlwZWxpbmUucG5nKQoKLS0tLS0KCiMjIEJhY2tncm91bmQKCiMjIyMgV2hlcmUgZG8gdGhlIGRhdGEgaW4gdGhpcyB0dXRvcmlhbCBjb21lIGZyb20/ClRoZSBkYXRhIGZvciB0aGlzIHR1dG9yaWFsIGFyZSBwdWJsaWNseS1hdmFpbGFibGUgZXhvbWUgc2VxdWVuY2luZyBkYXRhICpkb3duc2FtcGxlZCogdG8gdGhlIEJSQ0EyIHJlZ2lvbiBmcm9tIGEgZmljdGl0aW91cyBwYXRpZW50LiBXZSB3aWxsIHVzZSB0aGVzZSBkYXRhIHRocm91Z2hvdXQgdGhlIGNvdXJzZSB0byBjYWxsIHZhcmlhbnRzLCBmaWx0ZXIgYW5kIGRpc2N1c3MgdGhlIGNsaW5pY2FsIGltcGFjdCBvZiBhbnkgbXV0YXRpb25zLiAKCiMgU2VjdGlvbiAxOiBQcmVwYXJhdGlvbiAKCioqSWdub3JlIGlmIHlvdSBoYXZlIGFscmVhZHkgY3JlYXRlZCBhIEdhbGF4eSBhY2NvdW50IGFuZCB1cGxvYWRlZCB0aGUgZXhhbXBsZSBkYXRhIGluIGEgcHJldmlvdXMgZXhlcmNpc2UqKgoKIyMjIyAxLiAgUmVnaXN0ZXIgYXMgYSBuZXcgdXNlciBvbiBvbmUgb2YgdGhlIHB1YmxpYyBHYWxheHkgc2VydmVycwoKLSBodHRwczovL3VzZWdhbGF4eS5vcmcvCi0gaHR0cHM6Ly91c2VnYWxheHkub3JnLmF1Ci0gaHR0cHM6Ly91c2VnYWxheHkuZXUKCioqTWFrZSBzdXJlIHlvdSBjaGVjayB5b3VyIGVtYWlsIHRvIGFjdGl2YXRlIHlvdXIgYWNjb3VudCoqCgojIyMjIDIuICBJbXBvcnQgdGhlIGRhdGEgZm9yIHRoZSB3b3Jrc2hvcC4KCldlIGNhbiBnb2luZyB0byBpbXBvcnQgdGhlIFsqZmFzdHEqIGZpbGVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GQVNUUV9mb3JtYXQpIGZvciB0aGlzIGV4cGVyaW1lbnQuIFRoaXMgaXMgYSBzdGFuZGFyZCBmb3JtYXQgZm9yIHN0b3JpbmcgcmF3IHNlcXVlbmNpbmcgcmVhZHMgYW5kIHRoZWlyIGFzc29jaWF0ZWQgcXVhbGl0eSBzY29yZXMuIEhvd2V2ZXIsIGFzIHdlIHdpbGwgc2VlLCB0aGUgcmVwcmVzZW50YXRpb24gb2YgdGhlIHF1YWxpdHkgc2NvcmVzIGhhcyBjaGFuZ2VkIG92ZXIgdGltZS4KCllvdSBjYW4gaW1wb3J0IHRoZSBkYXRhIGJ5OgoKMS4gIEluIHRoZSB0b29sIHBhbmVsIGxvY2F0ZWQgb24gdGhlIGxlZnQsIHVuZGVyIEJhc2ljIFRvb2xzIHNlbGVjdCAqKkdldAogICAgRGF0YSA+IFVwbG9hZCBGaWxlKiouIENsaWNrIG9uIHRoZSAqKlBhc3RlL0ZldGNoIGRhdGEqKiBidXR0b24gb24gdGhlCiAgICBib3R0b20gc2VjdGlvbiBvZiB0aGUgcG9wLXVwIHdpbmRvdy4KMi4gIFVwbG9hZCB0aGUgc2VxdWVuY2UgZGF0YSBieSBzZWxlY3RpbmcgdGhlIGZpbGVzIGBKb2VCbG9nc0JSQ0FQYW5lbF9SMS5mYXN0cWAgYW5kIGBKb2VCbG9nc0JSQ0FQYW5lbF9SMi5mYXN0cWAuIFlvdSBkb24ndCBuZWVkIHRvIHNwZWNpZnkgdGhlIGZpbGUgdHlwZSBvciBnZW5vbWUgYnVpbGQuIEdhbGF4eSBzaG91bGQgYmUgYWJsZSB0byBtYWtlIGEgcmVhc29uYWJsZSBndWVzcy4KCgozLiAgWW91IHNob3VsZCBub3cgaGF2ZSB0aGVzZSAyIGZpbGVzIGluIHlvdXIgaGlzdG9yeToKICAgIC0gYEpvZUJsb2dzQlJDQVBhbmVsX1IxLmZhc3RxYAogICAgLSBgSm9lQmxvZ3NCUkNBUGFuZWxfUjIuZmFzdHFgCgoKCiMgU2VjdGlvbiAyOiBGYXN0cSBmaWxlIGZvcm1hdAoKWW91IGNhbiB2aWV3IHRoZSBmaWxlcyB5b3UganVzdCB1cGxvYWRlZCBieSBjbGlja2luZyB0aGUgKipleWUgaWNvbioqIHRoZSBoaXN0b3J5IGl0ZW0uIFRoZSBmaXJzdCBmZXcgbGluZXMgc2hvdWxkIHJlYWQgYXMgZm9sbG93cwoKCioqSm9lQmxvZ3NCUkNBUGFuZWxfUjEuZmFzdHEqKgoKYGBgCkBIV0ktRDAwNDYxOjE4ODpIVkdZMkJDWFk6MToxMTAxOjEzNjM6ODQxNDgvMQpUR1RHVENBVFRUQ1RBVFRBVENUVFRHR0FBQ0FBQ0NBVEdBQVRUQUdUQ0NDVFRHR0dHVFRUVENBQUFUR0NUR0NBQ0FDVEdBQ1RDQUNBQ0FUVFRBVFRUR0dUVENUR1RUVFRUR0NDVFRDQ0NUTk4KKwpERERERElISUlJSUlISUlJSUlJSUlJSUhJSUlJSUlJSUlISUlJSUlJSEhJSUlJSUlJSElJSUhJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUhISURISElIQyMKYGBgCgoqKkpvZUJsb2dzQlJDQVBhbmVsX1IyLmZhc3RxKioKCmBgYApASFdJLUQwMDQ2MToxODg6SFZHWTJCQ1hZOjE6MTEwMToxMzYzOjg0MTQ4LzIKVEdHQUFBR0FDVFRUVEdHR0dHR0dHR0FHVEFUVFRUVENUVEdUVFRDVEdHVFRUVEdHVFRUVFRUVEdBVENDR0dHQUFBR0FUVFRUR1RUVFRUVEdHQUdHVFRHR0FDVFRUVEdHR0dBR0dHR0FBQUFOCisKPDAwPDwxMTExPDE8MTEvMC88Ly8vPC88MDExMURGMTE8PDExMTExPDExMTExPDEvMTwxRDEvLy88PDExPDw8LzwxMTExPDwxMTxERDE8Ly88MTEwPDExLzExPDA8MDwvMDwwPDwtLy88PEZFCmBgYAoKClRoZSBmaXJzdCBsaW5lIGlzIHRoZSB1bmlxdWUgaWRlbnRpZmllciBmb3IgZWFjaCBzZXF1ZW5jZWQgcmVhZC4gSXQgY2FuIGJlIHVzZWQgdG8gZW5jb2RlIGluZm9ybWF0aW9uIHN1Y2ggYXMgdGhlICpzZXF1ZW5jaW5nIG1hY2hpbmUqLCAqZmxvdyBjZWxsKiBhbmQgKmxhbmUqIHRoYXQgdGhlIHJlYWQgd2FzIGdlbmVyYXRlZCBmcm9tIGFuZCB0aGUgcGh5c2ljYWwgY29vcmRpbmF0ZXMgb24gdGhlIGxhbmUuICAKClRoZSBxdWFsaXR5IHNjb3JlcyBhcmUgW0FTQ0lJXShodHRwOi8vYXNjaWktY29kZS5jb20vKSByZXByZXNlbnRhdGlvbnMgb2YgaG93IGNvbmZpZGVudCB3ZSBhcmUgdGhhdCBhIHBhcnRpY3VsYXIgYmFzZSBoYXMgYmVlbiBjYWxsZWQgY29ycmVjdGx5LiBMZXR0ZXJzIHRoYXQgYXJlIGZ1cnRoZXIgYWxvbmcgdGhlIGFscGhhYmV0IGluZGljYXRlIGhpZ2hlciBjb25maWRlbmNlLiBUaGlzIGlzIGltcG9ydGFudCB3aGVuIHRyeWluZyB0byBpZGVudGlmeSB0eXBlcyBvZiBnZW5vbWUgdmFyaWF0aW9uIHN1Y2ggYXMgc2luZ2xlIGJhc2UgY2hhbmdlcywgYnV0IGlzIGFsc28gaW5kaWNhdGl2ZSBvZiB0aGUgb3ZlcmFsbCBxdWFsaXR5IG9mIHRoZSBzZXF1ZW5jaW5nLiBEaWZmZXJlbnQgc2NhbGVzIGhhdmUgYmVlbiBlbXBsb3llZCBvdmVyIHRpbWUgKHJlc3VsdGluZyBpbiBhIGRpZmZlcmVudCBzZXQgb2YgY2hhcmFjdGVycyBhcHBlYXJpbmcgaW4gdGhlIGZpbGUpLiAKCgojIyMgRGVyaXZpbmcgdGhlIFF1YWxpdHkgU2NvcmUKCkZpcnN0IG9mIGFsbCwgd2UgY29udmVydCB0aGUgYmFzZS1jYWxsaW5nIHByb2JhYmlsaXR5IChwKSBpbnRvIGEgYFFgIHNjb3JlIHVzaW5nIHRoZSBmb3JtdWxhCgotIFF1YWxpdHkgc2NvcmVzICQkIFEgPSAtMTBsb2dfezEwfXAkJAogICAgKyBRID0gMzAsIHA9MC4wMDEKICAgICsgUSA9IDIwLCBwPTAuMDEKICAgICsgUSA9IDEwLCBwPTAuMQotIFRoZXNlIG51bWVyaWMgcXVhbnRpdGllcyBhcmUgKmVuY29kZWQqIGFzIFsqKkFTQ0lJKipdKGh0dHA6Ly9hc2NpaS1jb2RlLmNvbS8pIGNvZGUKICAgICsgQXQgbGVhc3QgMzMgdG8gZ2V0IHRvIG1lYW5pbmdmdWwgY2hhcmFjdGVycwogICAgKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ZBU1RRX2Zvcm1hdCkKICAgIAohW10obWVkaWEvcGhyZWQucG5nKSAgICAgIAoKIyMjIFF1YWxpdHkgU2NvcmVzIHRvIHByb2JhYmlsaXRpZXMKCi0gbG9vay11cCB0aGUgQVNDSUkgY29kZSBmb3IgZWFjaCBjaGFyYWN0ZXIKLSBzdWJ0cmFjdCB0aGUgb2Zmc2V0IHRvIGdldCB0aGUgUSBzY29yZQotIGNvbnZlcnQgdG8gYSBwcm9iYWJpbGl0eSB1c2luZyB0aGUgZm9ybXVsYTotCgokJCBwID0gMTBeey1RLzEwfSAkJAoKTGV0J3Mgc2VlIHRoaXMgY2FsY3VsYXRpb24gZm9yIHRoZSBmaXJzdCBmZXcgYmFzZXMgb2YgdGhlIGZpcnN0IHJlYWQgaW4gYEpvZUJsb2dzQlJDQVBhbmVsX1IxLmZhc3RxYDsgYERERERESUhJLi4uLmAKCkNoYXJhY3RlciAgfCBDb2RlIHwgTWludXMgMzMgT2Zmc2V0IHwgUHJvYmFiaWxpdHkKLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLQpEICB8IDY4IHwgMzUgfCAwLjAwMDMxNjIyNzgKRCAgfCA2OCB8IDM1IHwgMC4wMDAzMTYyMjc4CkQgIHwgNjggfCAzNSB8IDAuMDAwMzE2MjI3OApEICB8IDY4IHwgMzUgfCAwLjAwMDMxNjIyNzgKRCAgfCA2OCB8IDM1IHwgMC4wMDAzMTYyMjc4CkkgIHwgNzMgfCA0MCB8IDAuMDAwMTAwMDAwMApIICB8IDcyIHwgMzkgfCAwLjAwMDEyNTg5MjUKSSAgfCA3MyB8IDQwIHwgMC4wMDAxMDAwMDAwCgpJbiBwcmFjdGljZSwgd2UgZG9uJ3QgaGF2ZSB0byBjb252ZXJ0IHRoZSB2YWx1ZXMgYXMgd2UgaGF2ZSBzb2Z0d2FyZSB0aGF0IHdpbGwgZG8gdGhpcyBhdXRvbWF0aWNhbGx5CgotLS0tLQoKIyBTZWN0aW9uIDM6IFF1YWxpdHkgYXNzZXNzbWVudCB3aXRoIEZhc3RRQwoKW0Zhc3RRQ10oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjLykgaXMgYSBwb3B1bGFyIHRvb2wgZnJvbSBbQmFicmFoYW0gSW5zdGl0dXRlIEJpb2luZm9ybWF0aWNzIEdyb3VwXShodHRwczovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9pbmRleC5odG1sKSB1c2VkIGZvciAqcXVhbGl0eSBhc3Nlc3NtZW50KiBvZiBzZXF1ZW5jaW5nIGRhdGEuIE1vc3QgQmlvaW5mb3JtYXRpY3MgcGlwZWxpbmVzIHdpbGwgdXNlIEZhc3RRQywgb3Igc2ltaWxhciB0b29scyBpbiB0aGUgZmlyc3Qgc3RhZ2Ugb2YgdGhlIGFuYWx5c2lzLiBUaGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy9IZWxwLykgZm9yIEZhc3RRQyB3aWxsIGhlbHAgeW91IHRvIGludGVycHJldCB0aGUgcGxvdHMgYW5kIHN0YXRzIHByb2R1Y2VkIGJ5IHRoZSB0b29sLiBBIHRyYWZmaWMgbGlnaHQgc3lzdGVtIGlzIHVzZWQgdG8gYWxlcnQgdGhlIHVzZXIncyBhdHRlbnRpb24gdG8gcG9zc2libGUgaXNzdWVzLiAKCi0gRnJvbSB0aGUgbGVmdCBoYW5kIHRvb2wgcGFuZWwgaW4gR2FsYXh5LCB1bmRlciAqR0VOT01JQyBGSUxFIE1BTklQVUxBVElPTiosIHNlbGVjdCAqRkFTVFEgUXVhbGl0eSBDb250cm9sIC0+IEZhc3RRQyoKLSBTZWxlY3Qgb25lIG9mIHRoZSBGQVNUUSBmaWxlcyBhcyBpbnB1dCBhbmQgKkV4ZWN1dGUqIHRoZSB0b29sLgotIFdoZW4gdGhlIHRvb2wgZmluaXNoZXMgcnVubmluZywgeW91IHNob3VsZCBoYXZlIGFuIEhUTUwgZmlsZSBpbiB5b3VyIEhpc3RvcnkuIENsaWNrIG9uIHRoZSBleWUgaWNvbiB0byB2aWV3IHRoZSB2YXJpb3VzIHF1YWxpdHkgbWV0cmljcy4KClRoZSBtb3N0IGltcG9ydGFudCBpbWFnZSBpcyB3aGV0aGVyIHRoZSBiYXNlIHF1YWxpdHkgZGVjcmVhc2VzIHNpZ25pZmljYW50bHkgb3ZlciB0aGUgbGVuZ3RoIG9mIHRoZSByZWFkCgohW10obWVkaWEvZmFzdHFjLTJhLnBuZykKCkdvb2QgcXVhbGl0eSBkYXRhIHNob3VsZCBsb29rIHNvbWV0aGluZyBsaWtlOi0KCiFbXShtZWRpYS9mYXN0cWMtMmIucG5nKQoKCgpMb29rIGF0IHRoZSBnZW5lcmF0ZWQgRmFzdFFDIG1ldHJpY3MgZm9yIHlvdXIgdXBsb2FkZWQgZmFzdHEgZmlsZXMuIFRoaXMgZGF0YSBsb29rcyBwcmV0dHkgZ29vZCAtIGhpZ2ggcGVyLWJhc2UgcXVhbGl0eSBzY29yZXMgKG1vc3QgYWJvdmUgMzApLgoKQWxsIGlzIG5vdCBsb3N0IGlmIHdlIG9ic2VydmUgcG9vciBxdWFsaXR5IGJhc2VzIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgcmVhZC4gVGhlcmUgYXJlIGEgbnVtYmVyIG9mICp0cmltbWluZyogb3B0aW9ucyB0aGF0IHdlIGNhbiB1c2UgZm9yIE5HUyBkYXRhIGFuZCBzb21lIG9mIHRoZXNlIGFyZSBhdmFpbGFibGUgdGhyb3VnaCBHYWxheHkuIENoZWNrIG91dCB0aGUgW1RyaW1tbWluZyBSZWFkc10oaHR0cHM6Ly9nYWxheHlwcm9qZWN0Lm9yZy90dXRvcmlhbHMvbmdzLyN0cmltbWluZy1yZWFkcykgc2VjdGlvbiBvZiB0aGUgR2FsYXh5IE5HUyB0dXRvcmlhbCBpZiB5b3UgYXJlIGludGVyZXN0ZWQgaW4gaG93IHdlIGNhbiB0cmltIG91ciByZWFkcy4KCkl0IGlzIGFsc28gd29ydGggYmVhcmluZyBpbiBtaW5kIHRoYXQgdGhlIHRvb2wgaXMgYmxpbmQgdG8gdGhlIHBhcnRpY3VsYXIgdHlwZSBvZiBzZXF1ZW5jaW5nIHlvdSBhcmUgcGVyZm9ybWluZyAoaS5lLiB3aG9sZS1nZW5vbWUsIENoSVAtc2VxLCBSTkEtc2VxKSBhbmQgdGhlIG9yZ2FuaXNtIGJlaW5nIHNlcXVlbmNlZCwgc28gc29tZSB3YXJuaW5ncyBtaWdodCBiZSBleHBlY3RlZCBkdWUgdG8gdGhlIG5hdHVyZSBvZiB5b3VyIGV4cGVyaW1lbnQuIEZvciBpbnN0YW5jZSwgdGhlcmUgYXJlIGtub3duIHNlcXVlbmNpbmcgY29tcG9zaXRpb24gYmlhc2VzIHRoYXQgY2FuIG9jY3VyIGF0IHRoZSBiZWdpbm5pbmcgb2YgUk5BLXNlcSByZWFkcy4gCgojIyBBZ2dyZWdhdGluZyBRQyByZXBvcnRzIHdpdGggbXVsdGlxYwoKRm9yIGRhdGFzZXRzIHdpdGggbGFyZ2UgbnVtYmVycyBvZiBmYXN0cSBmaWxlcywgaXQgbWF5IGJlIHVzZWZ1bCB0byBhZ2dyZWdhdGUgdGhlIGluZGl2aWR1YWwgcmVwb3J0cyBpbnRvIGEgc2luZ2xlIGNvbWJpbmVkIHJlcG9ydC4gCgotIFVuZGVyICpHRU5PTUlDIEZJTEUgTUFOSVBVTEFUSU9OKiwgc2VsZWN0ICpGQVNUUSBRdWFsaXR5IENvbnRyb2wgLT4gTXVsdGlRQyoKLSBNYWtlIHN1cmUgKlNvZnR3YXJlIG5hbWUqIGlzIHNldCB0byBgRmFzdFFDYAotIEluICpSZXN1bHRzIGZpbGUqLCBzZWxlY3QgdGhlICoqUmF3RGF0YSoqIHJlc3VsdHMgZmlsZXMgdGhhdCB5b3UgaGF2ZSBqdXN0IGdlbmVyYXRlZAoKWW91IHNob3VsZCB0aGVuIGJlIGFibGUgdG8gdmlldyB0aGUgZmFzdHFjIHBsb3RzIGZvciBib3RoIHRoZSBmYXN0cSBmaWxlcyBvbiB0aGUgc2FtZSBwYWdlLgoKIyBTZWN0aW9uIDQ6IEFsaWdubWVudAoKV2UgZG9uJ3QgcmVhbGx5IHNwZW5kIG11Y2ggdGltZSBsb29rIGF0ICpmYXN0cSogZmlsZXMsIGFzIG1vc3Qgb2Ygb3VyIHRpbWUgaXMgc3BlbnQgd2l0aCAqYWxpZ25lZCogcmVhZHMuIGkuZS4gd2UgaGF2ZSB1c2VkIHNvbWUgc29mdHdhcmUgdG8gdGVsbCB1cyB3aGVyZWFib3V0cyBpbiB0aGUgZ2Vub21lIGVhY2ggcmVhZCBiZWxvbmdzIHRvLiBUaGlzIHdpbGwgKnVzdWFsbHkqIGJlIHBlcmZvcm1lZCBmb3IgeW91IGFzIHBhcnQgb2YgYSBzZXF1ZW5jaW5nIHNlcnZpY2UsIGJ1dCBpdCBpcyBnb29kIHRvIGdldCBhbiBhcHByZWNpYXRpb24gb2YgdGhlIHN0ZXBzIGludm9sdmVkLgoKSW4gdGhpcyBzZWN0aW9uIHdlIG1hcCB0aGUgcmVhZHMgaW4gb3VyIEZBU1RRIGZpbGVzIHRvIGEgcmVmZXJlbmNlIGdlbm9tZS4gCgpBIHBsZXRob3JhIG9mIGRpZmZlcmVudCB0b29scyBoYXZlIGJlZW4gd3JpdHRlbiB0byBwZXJmb3JtIHRoaXMgdGFzaywgYW5kIHdlIHdpbGwgbm90IGRlc2NyaWJlIGl0IGluIGRldGFpbC4gTGlua3MgdG8gc29tZSBrZXkgcHVibGljYXRpb25zIGFyZSBnaXZlbiBiZWxvdzotCgogICsgMjAwOSBCb3d0aWUgMSAtIFtMYW5nbWVhZCBldCBhbF0oaHR0cDovL2dlbm9tZWJpb2xvZ3kuY29tL2NvbnRlbnQvMTAvMy9SMjUpCiAgKyAyMDEyIEJvd3RpZSAyIC0gW0xhbmdtZWFkIGFuZCBTYWx6YmVyZ10oaHR0cDovL3d3dy5uYXR1cmUuY29tL25tZXRoL2pvdXJuYWwvdjkvbjQvZnVsbC9ubWV0aC4xOTIzLmh0bSkKICArIDIwMDkgQldBIC0gW0xpIGFuZCBEdXJiaW5dKGh0dHA6Ly9iaW9pbmZvcm1hdGljcy5veGZvcmRqb3VybmFscy5vcmcvY29udGVudC8yNS8xNC8xNzU0LmxvbmcpCiAgKyAyMDEwIEJXQSAtIFtMaSBhbmQgRHVyYmluXShodHRwOi8vYmlvaW5mb3JtYXRpY3Mub3hmb3Jkam91cm5hbHMub3JnL2NvbnRlbnQvMjYvNS81ODkpCiAgKyAyMDEzIEJXQS1NRU0gLSBbTGldKGh0dHA6Ly9hcnhpdi5vcmcvYWJzLzEzMDMuMzk5NykKCkFsaWdubWVudCByZWxpZXMgb24gdGhlIHJlZmVyZW5jZSBnZW5vbWUgYmVpbmcgKmluZGV4ZWQqIHNvIHRoYXQgdGhlIHNlcXVlbmNpbmcgcmVhZHMgY2FuIGJlIGxvY2F0ZWQgbW9yZSBlZmZpY2llbnRseS4gVGhlIGdlbm9tZSBpbmRleCBpcyBhIGhpZ2hseS1hY2Nlc3NpYmxlIGRhdGEgc3RydWN0dXJlLCBhbmQgR2FsYXh5IGluY2x1ZGVzIGluZGljZXMgZm9yIG1hbnkgcG9wdWxhciBnZW5vbWVzLiAKCiMjIyMgMS5BbGlnbiB0aGUgZXhhbXBsZSBmaWxlcyAgCgohW10obWVkaWEvYm93dGllMi10b29sLnBuZykKCi0gRmluZCB0aGUgdG9vbCAqR0VOT01JQ1MgQU5BTFlTSVMqIC0+ICpNYXBwaW5nKiAtPiAqQm93dGllMioKICArIGFsdGVybmF0aXZlbHksIHR5cGUgYGJvd3RpZWAgaW4gdGhlIHNlYXJjaCBib3gKLSBJbiAqSXMgdGhpcyBzaW5nbGUtZW5kIG9yIFBhaXJlZC1lbmQ/KiBTZWxlY3QgKipQYWlyZWQtZW5kKioKLSBTZXQgKkZhc3RRIGZpbGUgIzEqIGFuZCAqRmFzdFEgZmlsZSAjMiogdG8gdGhlIHR3byBmYXN0cSBmaWxlcyB5b3UgdXBsb2FkZWQgaW4gdGhlIHByZXZpb3VzIHN0ZXAKLSBNYWtlIHN1cmUgdGhlIHJlZmVyZW5jZSBnZW5vbWUgaXMgc2V0IHRvICoqSHVtYW4gKEhvbW8gc2FwaWVucyk6aGcxOSoqCi0gUHJlc3MgKkV4ZWN1dGUqCi0gV2FpdCEKClRoZSByZXN1bHQgd2lsbCBiZSBhIGAuYmFtYCBmaWxlIHRoYXQgd2Ugd2lsbCBkZXNjcmliZSBpbiB0aGUgbmV4dCBzZWN0aW9uLiBUaGlzIGZpbGUgaXMgbm90IGh1bWFuLXJlYWRhYmxlLCBhcyBpdCBpcyBjb21wcmVzc2VkLiBCdXQgd2UgY2FuIGNvbnZlcnQgdG8gYSByZWFkYWJsZSBmb3JtYXQgZm9yIGlsbHVzdHJhdGlvbiBwdXJwb3Nlcy4KCiMjIyMgMi4gVmlldyB0aGUgYWxpZ25tZW50cwoKMS4gIENsaWNrIG9uIHRoZSBleWUgb2YgdGhlIHJlc3VsdGluZyBmaWxlIHRvIHZpZXcgdGhlIGFsaWdubWVudHMuCgoKIVtdKG1lZGlhL2JhbS1hbGlnbm1lbnRzLnBuZykKCiMjIyBBYm91dCB0aGUgYGJhbWAgZmlsZSBmb3JtYXQKClVubGlrZSBtb3N0IG9mIEJpb2luZm9ybWF0aWNzLCBhICpzaW5nbGUgc3RhbmRhcmQqIGZpbGUgZm9ybWF0IGhhcyBlbWVyZ2VkIGZvciBhbGlnbmVkIHJlYWRzLiBNb3Jlb3ZlciwgdGhpcyBmaWxlIGZvcm1hdCBpcyBjb25zaXN0ZW50IHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB5b3UgaGF2ZSBETkEtc2VxLCBSTkEtc2VxLCBDaElQLXNlcS4uLiBkYXRhLiAKClRoZSBgYmFtYCBmaWxlIGlzIGEgY29tcHJlc3NlZCwgYmluYXJ5LCB2ZXJzaW9uIG9mIGEgYHNhbWAgZmlsZS4KCiMjIyBUaGUgYC5zYW1gIGZpbGUKCi0gKipTKiplcXVlbmNlICoqQSoqbGlnbm1lbnQvKipNKiphcCAoc2FtKSAKLSBUaGUgb3V0cHV0IGZyb20gYW4gYWxpZ25lciBzdWNoIGFzIGBid2FgCi0gU2FtZSBmb3JtYXQgcmVnYXJkbGVzcyBvZiBzZXF1ZW5jaW5nIHByb3RvY29sIChpLmUuIFJOQS1zZXEsIENoSVAtc2VxLCBETkEtc2VxIGV0YykKLSBNYXkgY29udGFpbiB1bi1tYXBwZWQgcmVhZHMKLSBQb3RlbnRpYWxseSBsYXJnZSBzaXplIG9uIGRpc2s7IH4xMDBzIG9mIEdiCiAgICArIENhbiBiZSBtYW5pcHVsYXRlZCB3aXRoIHN0YW5kYXJkIHVuaXggdG9vbHM7IGUuZy4gKmNhdCosICpoZWFkKiwgKmdyZXAqLCAqbW9yZSosICpsZXNzKi4uLi4KLSBPZmZpY2lhbCBzcGVjaWZpY2F0aW9uIGNhbiBiZSBbb2J0YWluZWQgb25saW5lXShodHRwOi8vc2FtdG9vbHMuZ2l0aHViLmlvL2h0cy1zcGVjcy9TQU12MS5wZGYpOiAtCi0gV2Ugbm9ybWFsbHkgd29yayBvbiBhIGNvbXByZXNzZWQgdmVyc2lvbiBjYWxsZWQgYSBgLmJhbWAgZmlsZS4gU2VlIGxhdGVyLgotICpIZWFkZXIqIGxpbmVzIHN0YXJ0aW5nIHdpdGggYW4gYEBgIGNoYXJhY3RlciwgZm9sbG93ZWQgYnkgdGFiLWRlbGltaXRlZCBsaW5lcwogICAgKyBIZWFkZXIgZ2l2ZXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGFsaWdubWVudCBhbmQgcmVmZXJlbmNlcyBzZXF1ZW5jZXMgdXNlZAoKClRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBoZWFkZXIgbGlzdHMgdGhlIG5hbWVzIChgU05gKSBvZiB0aGUgc2VxdWVuY2VzIChjaHJvbW9zb21lcykgdXNlZCBpbiBhbGlnbm1lbnQsIHRoZWlyIGxlbmd0aCAoYExOYCkgYW5kIGEgKm1kNXN1bSogIltkaWdpdGFsIGZpbmdlcnByaW50XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NZDVzdW0pIiBvZiB0aGUgYC5mYXN0YWAgZmlsZSB1c2VkIGZvciBhbGlnbm1lbnQgKGBNNWApLgoKYGBgCgpASEQgVk46MS4wIFNPOmNvb3JkaW5hdGUKQFNRIFNOOmNocjEwIExOOjEzNTUzNDc0NwpAU1EgU046Y2hyMTEgTE46MTM1MDA2NTE2CkBTUSBTTjpjaHIxMV9nbDAwMDIwMl9yYW5kb20gTE46NDAxMDMKQFNRIFNOOmNocjEyIExOOjEzMzg1MTg5NQpAU1EgU046Y2hyMTMgTE46MTE1MTY5ODc4CkBTUSBTTjpjaHIxNCBMTjoxMDczNDk1NDAKQFNRIFNOOmNocjE1IExOOjEwMjUzMTM5MgpAU1EgU046Y2hyMTYgTE46OTAzNTQ3NTMKLi4uLi4KLi4uLi4KCmBgYAoKCldlIGFsc28gaGF2ZSBhIHNlY3Rpb24gd2hlcmUgd2UgY2FuIHJlY29yZCB0aGUgcHJvY2Vzc2luZyBzdGVwcyB1c2VkIHRvIGRlcml2ZSB0aGUgZmlsZQpgYGAKQFBHIElEOmJvd3RpZTIgUE46Ym93dGllMiBWTjoyLjMuNC4xIENMOiIvamV0c3RyZWFtL3NjcmF0Y2gwL21haW4vY29uZGEvZW52cy9tdWxsZWQtdjEtNjVkNWVmZTRmMWI2OWFiNzE2NmQxYTVhNTYxNmFkZWJlOTAyMTMzZWEzZTRjMTg5ZDg3ZDdkZTJlMjFkZGMxNy9iaW4vYm93dGllMi1hbGlnbi1zIC0td3JhcHBlciBiYXNpYy0wIC1wIDEwIC14IC9jdm1mcy9kYXRhLmdhbGF4eXByb2plY3Qub3JnL2J5aGFuZC9oZzE5L2hnMTlmdWxsL2Jvd3RpZTJfaW5kZXgvaGcxOWZ1bGwgLTEgaW5wdXRfZi5mYXN0cSAtMiBpbnB1dF9yLmZhc3RxIgouLi4uCi4uLi4KCmBgYAoKTmV4dCBpcyBhICp0YWItZGVsaW1pdGVkKiBzZWN0aW9uIHRoYXQgZGVzY3JpYmVzIHRoZSBhbGlnbm1lbnQgb2YgZWFjaCBzZXF1ZW5jZSBpbiBkZXRhaWwuIAoKYGBgCkhXSS1EMDA0NjE6MTg4OkhWR1kyQkNYWToxOjExMDk6MzQzMDo2NjI2NgkxNjMJMTMJMzI4ODk4MjYJNDIJMTA4TQk9CTMyODg5OTY5CTI1MQlUVEdHR0FDR0FHQ0dDR1RDVFRDQ0dUQUdUQ0NDQUdUQ0NBR0NHVEdHQ0dHR0dHQUdDR0NDVENBQ0dDQ0NDR0dHVENHQ1RHQ0NHQ0dHQ1RUQ1RUR0NDQ1RUVFRHVENUQ1RHQ0NBQUNDQ0NDQUMJMERAQD9HRUhDSEhDRUhJREhIPzFDQ0hDSElAMTxDQ0NGQ0BHQ0NDRUhJSENISUNIQz9ISD1HSEUxREU8Q0VIREVISEM8Q0NILz9ISEcvPDE8REAxMUQ/Rz9GR0hFSEgwMUQwMEQ7MDA8REg8CUFTOmk6LTUgWE46aTowIFhNOmk6MSBYTzppOjAgWEc6aTowIE5NOmk6MSBNRDpaOjIxQzg2IFlTOmk6LTUgWVQ6WjpDUAoKYGBgCgohW10obWVkaWEvc2FtLWVudHJ5LWV4cGxhaW5lZC5wbmcpCgpDb2x1bW4gfCBPZmZpY2lhbCBOYW1lIHwgQnJpZWYKLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLQoxICAgICAgfCBRTkFNRSAgICAgICAgICB8IFNlcXVlbmNlIElECjIgICAgICB8IEZMQUcgICAgICAgICAgIHwgU2VxdWVuY2UgcXVhbGl0eSBleHByZXNzZWQgYXMgYSBiaXR3aXNlIGZsYWcKMyAgICAgIHwgUk5BTUUgICAgICAgICAgfCBDaHJvbW9zb21lCjQgICAgICB8IFBPUyAgICAgICAgICAgIHwgU3RhcnQgUG9zaXRpb24KNSAgICAgIHwgTUFQUSAgICAgICAgICAgfCBNYXBwaW5nIFF1YWxpdHkKNiAgICAgIHwgQ0lHQVIgICAgICAgICAgfCBEZXNjcmliZXMgcG9zaXRpb25zIG9mIG1hdGNoZXMsIGluc2VydGlvbnMsIGRlbGV0aW9ucyB3LnIudCByZWZlcmVuY2UKNyAgICAgIHwgUk5FWFQgICAgICAgICAgfCBSZWYuIG5hbWUgb2YgbWF0ZSAvIG5leHQgcmVhZAo4ICAgICAgfCBQTkVYVCAgICAgICAgICB8IFBvc2l0aW9uIG9mIG1hdGUgLyBuZXh0IHJlYWQKOSAgICAgIHwgVExFTiAgICAgICAgICAgfCBPYnNlcnZlZCBUZW1wbGF0ZSBsZW5ndGgKMTAgICAgIHwgU0VRICAgICAgICAgICAgfCBTZXF1ZW5jZQoxMSAgICAgfCBRVUFMICAgICAgICAgICB8IEJhc2UgUXVhbGl0aWVzCgpUaGVyZSBjYW4gYWxzbyBiZSBhbGwgbWFubmVyIG9mIG9wdGlvbmFsIHRhZ3MgYXMgZXh0cmEgY29sdW1ucyBpbnRyb2R1Y2UgYnkgYW4gYWxpZ25lciBvciBkb3duc3RyZWFtIGFuYWx5c2lzIHRvb2wuIEEgY29tbW9uIHVzZSBpcyB0aGUgYFJHYCB0YWcgd2hpY2ggcmVmZXJzIGJhY2sgdG8gdGhlIHJlYWQgZ3JvdXBzIGluIHRoZSBoZWFkZXIuCgoKIyMjIFNvcnRpbmcgYW5kIGluZGV4aW5nCgpZb3Ugd2lsbCBub3RpY2UgZnJvbSB0aGUgM3JkIGNvbHVtbiB0aGF0IHRoZSByZWFkcyBhcmUgb3JkZXJlZCBhY2NvcmRpbmcgdG8gdGhlaXIgc3RhcnQgcG9zaXRpb247IHdoZXJlYXMgdGhlIHJlYWRzIGluIHRoZSBgZmFzdHFgIGZpbGUgd2VyZSBhcnJhbmdlZCBpbiBvcmRlciB0aGF0IHRoZXkgd2VyZSBnZW5lcmF0ZWQgb24gdGhlIGZsb3cgY2VsbC4gQnkgZGVmYXVsdCwgYGJvd3RpZTJgIHByb2R1Y2VzIGEgYmFtIHdoZXJlIHRoZSByZWFkcyBhcmUgaW4gdGhlIHNhbWUgb3JkZXIgYXMgdGhlIGBmYXN0cWAuIEhvd2V2ZXIsIHRoaXMgaXMgcmF0aGVyIGluY29udmVuaWVudCBmb3IgYW5hbHlzaXMgd2hlcmUgd2UgcmVxdWlyZSByZWFkcyBmcm9tIHRoZSBzYW1lIGxvY2F0aW9uIHRvIGJlIG5leHQgdG8gZWFjaCBvdGhlciBpbiB0aGUgZmlsZS4KCkFuIGFkZGl0aW9uYWwgY291cGxlIG9mIHN0ZXBzIGhhdmUgYmVlbiBwZXJmb3JtZWQgYWZ0ZXIgYm93dGllMjsgc29ydGluZyB0aGUgZmlsZSBhY2NvcmRpbmcgdG8gZ2Vub21lIHBvc2l0aW9uIGFuZCBwcm9kdWNpbmcgYW4gKmluZGV4KiBmaWxlLiBUaGUgaW5kZXggZmlsZSBkb2VzIG5vdCBwcm92aWRlIGFueSB1c2VmdWwgaW5mb3JtYXRpb24gZm9yIHVzIGFuZCBjYW5ub3QgYmUgdmlld2VkIGluIEdhbGF4eS4gSG93ZXZlciwgd2Ugd2lsbCBuZWVkIGl0IGxhdGVyIG9uIHdoZW4gdmlld2luZyB0aGUgZGF0YSBpbiBJR1YuIAoKIyMjIFF1YWxpdHkgRmxhZ3MKClRoZSAqImZsYWdzIiogaW4gdGhlIHNhbSBmaWxlIGNhbiByZXByZXNlbnQgdXNlZnVsIFFDIGluZm9ybWF0aW9uCgogICsgUmVhZCBpcyB1bm1hcHBlZAogICsgUmVhZCBpcyBwYWlyZWQgLyB1bnBhaXJlZAogICsgUmVhZCBmYWlsZWQgUUMKICArIFJlYWQgaXMgYSBQQ1IgZHVwbGljYXRlIChzZWUgbGF0ZXIpCgpUaGUgY29tYmluYXRpb24gb2YgYW55IG9mIHRoZXNlIHByb3BlcnRpZXMgaXMgdXNlZCB0byBkZXJpdmUgYSBudW1lcmljIHZhbHVlCgoKRm9yIGluc3RhbmNlLCBhIHBhcnRpY3VsYXIgcmVhZCBoYXMgYSBmbGFnIG9mIDE2MwoKIVtdKG1lZGlhL2ZsYWctaGlnaGxpZ2h0LnBuZykKCgojIyMgRGVyaXZhdGlvbgoKVGhlcmUgaXMgYSBzZXQgb2YgcHJvcGVydGllcyB0aGF0IGEgcmVhZCBjYW4gcG9zc2Vzcy4gSWYgYSBwYXJ0aWN1bGFyIHByb3BlcnR5IGlzIG9ic2VydmVkLCBhIGNvcnJlc3BvbmRpbmcgcG93ZXIgb2YgMiBpcyBhZGRlZCBtdWx0aXBsaWVkIGJ5IDEuIFRoZSBmaW5hbCB2YWx1ZSBpcyBkZXJpdmVkIGJ5IHN1bW1pbmcgYWxsIHRoZSBwb3dlcnMgb2YgMi4KCiFbXShodHRwczovL2dhbGF4eXByb2plY3Qub3JnL3R1dG9yaWFscy9uZ3Mvc2FtX2ZsYWcucG5nKQoKRmxhZyBWYWx1ZSB8IE1lYW5pbmcKLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCjY5ICg9IDEgKyA0ICsgNjQpIAl8IFRoZSByZWFkIGlzIHBhaXJlZCwgaXMgdGhlIGZpcnN0IHJlYWQgaW4gdGhlIHBhaXIsIGFuZCBpcyB1bm1hcHBlZC4KNzcgKD0gMSArIDQgKyA4ICsgNjQpIHwJVGhlIHJlYWQgaXMgcGFpcmVkLCBpcyB0aGUgZmlyc3QgcmVhZCBpbiB0aGUgcGFpciwgYm90aCBhcmUgdW5tYXBwZWQuCjgzICg9IDEgKyAyICsgMTYgKyA2NCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgZmlyc3QgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGl0IGlzIG1hcHBlZCB0byB0aGUgcmV2ZXJzZSBzdHJhbmQuCjk5ICg9IDEgKyAyICsgMzIgKyA2NCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgZmlyc3QgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGl0cyBtYXRlIGlzIG1hcHBlZCB0byB0aGUgcmV2ZXJzZSBzdHJhbmQuCjEzMyAoPSAxICsgNCArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIGlzIHRoZSBzZWNvbmQgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGl0IGlzIHVubWFwcGVkLgoxMzcgKD0gMSArIDggKyAxMjgpICB8CVRoZSByZWFkIGlzIHBhaXJlZCwgaXMgdGhlIHNlY29uZCByZWFkIGluIHRoZSBwYWlyLCBhbmQgaXQgaXMgbWFwcGVkIHdoaWxlIGl0cyBtYXRlIGlzIG5vdC4KMTQxICg9IDEgKyA0ICsgOCArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIGlzIHRoZSBzZWNvbmQgcmVhZCBpbiB0aGUgcGFpciwgYnV0IGJvdGggYXJlIHVubWFwcGVkLgoxNDcgKD0gMSArIDIgKyAxNiArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgc2Vjb25kIHJlYWQgaW4gdGhlIHBhaXIsIGFuZCBtYXBwZWQgdG8gdGhlIHJldmVyc2Ugc3RyYW5kLgoxNjMgKD0gMSArIDIgKyAzMiArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgc2Vjb25kIHJlYWQgaW4gdGhlIHBhaXIsIGFuZCBpdHMgbWF0ZSBpcyBtYXBwZWQgdG8gdGhlIHJldmVyc2Ugc3RyYW5kLgoKCgpTZWUgYWxzbwoKLSBodHRwczovL2Jyb2FkaW5zdGl0dXRlLmdpdGh1Yi5pby9waWNhcmQvZXhwbGFpbi1mbGFncy5odG1sCgojIyMgSGF2ZSBhIENJR0FSIQoKCiFbXShtZWRpYS9jaWdhci1oaWdobGlnaHQucG5nKQoKVGhlICoqKkNJR0FSKioqICgqKkMqKm9tcGFjdCAqKkkqKmRpb3N5bmNyYXRpYyAqKkcqKmFwcGVkICoqQWxpZ25tZW50KiogKipSKiplcG9ydCkgc3RyaW5nIGlzIGEgd2F5IG9mIGVuY29kaW5nIHRoZSBtYXRjaCBiZXR3ZWVuIGEgZ2l2ZW4gc2VxdWVuY2UgYW5kIHRoZSBwb3NpdGlvbiBpdCBoYXMgYmVlbiBhc3NpZ25lZCBpbiB0aGUgZ2Vub21lLiBJdCBpcyBjb21wcmlzZWQgYnkgYSBzZXJpZXMgb2YgbGV0dGVycyBhbmQgbnVtYmVycyB0byBpbmRpY2F0ZSBob3cgbWFueSBjb25zZWN1dGl2ZSBiYXNlcyBoYXZlIHRoYXQgbWFwcGluZy4KCgogCiBDb2RlICB8IERlc2NyaXB0aW9uCi0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tCk0gIHwgYWxpZ25tZW50IG1hdGNoCkkgIHwgaW5zZXJ0aW9uCkQgIHwgZGVsZXRpb24KTiAgfCBza2lwcGVkClMgIHwgc29mdC1jbGlwcGluZwpIICB8IGhhcmQtY2xpcHBpbmcKCgplLmcuCgotIGA2OE1gCiAgICArIDY4IGJhc2VzIG1hdGNoaW5nIHRoZSByZWZlcmVuY2UKLSBgMVM2N01gCiAgICArIDEgc29mdC1jbGlwcGVkIHJlYWQgZm9sbG93ZWQgYnkgNjcgbWF0Y2hlcwotIGAxNU04N043ME05ME4xNk1gCiAgICArIDE1IG1hdGNoZXMgZm9sbG93aW5nIGJ5IDg3IGJhc2VzIHNraXBwZWQgZm9sbG93ZWQgYnkgNzAgbWF0Y2hlcyBldGMuCgoKIyMjIyAzLiBDaGVjayB0aGUgYWxpZ25tZW50IHN0YXRzCgpXZSB3aWxsIG5vdyBnZW5lcmF0ZSBhIGZldyBiYXNpYyBzdGF0aXN0aWNzIGFib3V0IHRoZSBhbGlnbm1lbnQgb2Ygb3VyIGRhdGEKCjEuIFNlbGVjdCB0aGUgdG9vbCAqTkdTOiBTQU10b29scyAtPiBGbGFnc3RhdCogCjIuIEluIHRoZSAqQkFNIEZpbGUgdG8gQ29udmVydCogYm94IGNob29zZSB0aGUgYmFtIGZpbGUgcHJvZHVjZWQgYnkgYm93dGllMi4KCgpUaGUgdG9vbCB3aWxsIGFsc28gcmVwb3J0IGhvdyBtYW55ICoqKlBDUiBEdXBsaWNhdGVzKioqIGhhdmUgYmVlbiBmb3VuZCBpbiB0aGUgZGF0YS4gQnV0IGFzIHdlIGhhdmVuJ3QgeWV0IHJ1biBhbnkgc29mdHdhcmUgdG8gaWRlbnRpZnkgc3VjaCByZWFkcywgdGhlIGZsYWdzdGF0IG91dHB1dCB3aWxsIHNob3cgMCByZWFkcy4KCjEuIEZpbmQgdGhlIHRvb2wgKlNBTXRvb2xzIC0+IElkeHN0YXRzKgoyLiBJbiB0aGUgKkJBTSBmaWxlKiBkcm9wZG93biBzZWxlY3QgdGhlIGJhbSBmaWxlIHByb2R1Y2VkIGJ5IGJvd3RpZTIKClRoZSBvdXRwdXQgb2YgdGhpcyB0b29sIHdpbGwgdGVsbCB5b3UgaG93IG1hbnkgcmVhZHMgYWxpZ25lZCB0byBlYWNoIGNocm9tb3NvbWUgaW4geW91ciByZWZlcmVuY2UgZ2Vub21lLiBGb3Igb3VyIGV4YW1wbGUgZGF0YXNldCB3ZSBvbmx5IGhhdmUgcmVhZHMgZnJvbSBhIHNtYWxsIHJlZ2lvbiwgc28gc2hvdWxkbid0IGV4cGVjdCB0byBzZWUgYWxpZ25tZW50cyB0byBlYWNoIGNocm9tb3NvbWUuCgoKCiMjIyBBYm91dCBEdXBsaWNhdGVzCgpUaGUgcHJlcGFyYXRpb24gb2YgYSBzZXF1ZW5jaW5nIGxpYnJhcnkgcmVxdWlyZXMgKlBDUiogYW1wbGlmaWNhdGlvbiBvZiB5b3VyIHN0YXJ0aW5nIG1hdGVyaWFsLiBUaGlzIGNhbiBsZWFkIHRvIHNvbWUgRE5BIGZyYWdtZW50cyBiZWluZyBvdmVyLXJlcHJlc2VudGVkIGluIHlvdXIgZGF0YS4gQXMgb3VyIEROQSBmcmFnbWVudHMgYXJlIGZvcm1lZCBpbiBhIHJhbmRvbSBwcm9jZXNzLCBhbmQgcmVsYXRpdmVseSBzbWFsbCBjb21wYXJlZCB0byB0aGUgbnVtYmVyIG9mIGJhc2VzIHRvIGJlIHNlcXVlbmNlZCBmcm9tIHRoZSBnZW5vbWUgKDNHYiBpbiBodW1hbnMpLCB3ZSB0ZW5kIHRvIHRoaW5rIHRoZSB0d28gRE5BIGZyYWdtZW50cyB0aGF0IGhhdmUgaWRlbnRpY2FsIHN0YXJ0aW5nIGFuZCBlbmRpbmcgcG9zaXRpb24gYXJlIHVubGlrZWx5IHRvIGhhdmUgb2NjdXJyZWQgZHVlIHRvIGNoYW5jZS4gU29tZSBzb2Z0d2FyZSwgc3VjaCBhcyBbUGljYXJkXShodHRwOi8vYnJvYWRpbnN0aXR1dGUuZ2l0aHViLmlvL3BpY2FyZC8pIHdpbGwgaWRlbnRpZnkgc3VjaCBhcnRlZmFjdHMgYW5kICptYXJrKiB0aGVtIGZvciBhdHRlbnRpb24gYnkgZG93bnN0cmVhbSBtZXRob2RzLiBpLmUuIHRoZXkgYXJlIG5vdCBjb21wbGV0ZWx5IGRpc2NhcmRlZCBmcm9tIHRoZSBhbmFseXNpcy4KCiFbXShtZWRpYS9wY3JfZHVwcy5wbmcpCgojIyMjIDQuIE1hcmsgRHVwbGljYXRlcyB3aXRoIFBpY2FyZAoKMS4gVXNlIHRoZSB0b29sICpHRU5PTUlDUyBUT09MS0lUUyAtPiBQaWNhcmQgLT4gTWFya0R1cGxpY2F0ZXMqCjIuIEluICpTZWxlY3QgU0FNL0JBTSBkYXRhc2V0IG9yIGRhdGFzZXQgY29sbGVjdGlvbiogY2hvb3NlIHRoZSBiYW0gZmlsZSBwcm9kdWNlZCBieSBib3d0aWUyLgozLiBXaGF0IGRvIHlvdSBub3RpY2UgYWJvdXQgdGhlICpmbGFnKiB2YWx1ZXMgZm9yIGFueSByZWFkcyB0aGF0IGhhdmUgdGhlIHNhbWUgKnN0YXJ0KiBhcyBhbm90aGVyIHJlYWQ/IAo0LiBJbnRlcnByZXQgdGhlIG1lYW5pbmcgb2YgdGhlc2UgZmxhZ3MgdXNpbmcgdGhlIG9ubGluZSB0b29sCiAgKyBodHRwczovL2Jyb2FkaW5zdGl0dXRlLmdpdGh1Yi5pby9waWNhcmQvZXhwbGFpbi1mbGFncy5odG1sCgoqKldhcm5pbmcqKiB0aGUgYXNzdW1wdGlvbiBhYm91dCByZWFkcyBoYXZpbmcgdGhlIHNhbWUgc3RhcnQgbG9jYXRpb24gYmVpbmcgUENSIGR1cGxpY2F0ZXMgZmFsbHMgZG93biB3aGVuIHdlIGRvIHNlcXVlbmNpbmcgZm9yIGEgdmVyeSBzcGVjaWZpYyByZWdpb24gb2YgdGhlIGdlbm9tZS4gZS5nLiB0YXJnZXRlZCBzZXF1ZW5jaW5nIGZyb20gYSBwYW5lbCBvZiBjYW5jZXIgZ2VuZXMuIFJ1bm5pbmcgYSB0b29sIHRvIG1hcmsgUENSIGR1cGxpY2F0ZXMgb24gc3VjaCBkYXRhIHdvdWxkIHJlY29tbWVuZCBhIGhpZ2ggcHJvcG9ydGlvbiBvZiByZWFkcyBiZSBpZ25vcmVkIGZyb20gZnVydGhlciBhbmFseXNpcy4KICAKIyMjIyA1LiAoT3B0aW9uYWwpIFJlLXJ1biB0aGUgYWxpZ25tZW50IHN0YXRpc3RpY3MKCjEuIFNlbGVjdCB0aGUgdG9vbCAqR0VOT01JQyBGSUxFIE1BTklQVUxBVElPTiAtPiBTQU0vQkFNIC0+IFNhbXRvb2xzIGZsYWdzdGF0KiAKMi4gSW4gdGhlICpCQU0gRmlsZSB0byBDb252ZXJ0KiBib3ggY2hvb3NlIHRoZSBiYW0gZmlsZSBwcm9kdWNlZCBieSB0aGUgKm1hcmsgZHVwbGljYXRlcyogc3RlcAoKIyMjIyA2LiBEb3dubG9hZCB5b3VyIGJhbSBmaWxlCgpGb3IgdGhlIG5leHQgc3RlcCB5b3Ugd2lsbCBuZWVkIHRvIGRvd25sb2FkIHRoZSBgYmFtYCBmaWxlIHRoYXQgeW91IHByb2R1Y2VkIGFmdGVyICptYXJraW5nIGR1cGxpY2F0ZXMqLiBUbyBkbyB0aGlzLCB5b3UgY2FuIGNsaWNrIHRoZSBmbG9wcHkgZGlzayBpY29uLgoKIVtdKG1lZGlhL2Rvd25sb2FkX2JhbS5wbmcpCgoqKk1ha2Ugc3VyZSB0aGF0IHlvdSBjbGljayBib3RoIERvd25sb2FkIGRhdGFzZXQgYW5kIERvd25sb2FkIGJhbV9pbmRleCoqCgojIFNlY3Rpb24gNS4gVmlzdWFsaXNpbmcgdGhlIGFsaWduZWQgcmVhZHMgd2l0aCBJR1YKCldoaWxzdCBCaW9pbmZvcm1hdGljcyB0b29scyBhcmUgdmVyeSBwb3dlcmZ1bCBhbmQgYWxsb3cgeW91IHRvIHBlcmZvcm0gc3RhdGlzdGljYWwgYW5hbHlzZXMgYW5kIHRlc3QgaHlwb3RoZXNlcywgdGhlcmUgaXMgbm8gc3Vic3RpdHV0ZSBmb3IgKipsb29raW5nIGF0IGFuZCBleHBsb3JpbmcgdGhlIGRhdGEqKi4gQSB0cmFpbmVkLWV5ZSBjYW4gcXVpdGUgcXVpY2tseSBnZXQgYSBzZW5zZSBvZiB0aGUgZGF0YSBxdWFsaXR5IGJlZm9yZSBhbnkgY29tcHV0YXRpb25hbCBhbmFseXNlcyBoYXZlIGJlZW4gcnVuLiBGdXJ0aGVybW9yZSwgYXMgdGhlIHBlcnNvbiByZXF1ZXN0aW5nIHRoZSBzZXF1ZW5jaW5nLCB5b3UgcHJvYmFibHkga25vdyBhIGxvdCBhYm91dCB0aGUgYmlvbG9naWNhbCBjb250ZXh0IG9mIHRoZSBzYW1wbGVzIGFuZCB3aGF0IHRvIGV4cGVjdC4KCldlIHdpbGwgbG9hZCB0aGUgYWxpZ25lZCByZWFkcyB0aGF0IHdlIGhhdmUganVzdCBjcmVhdGVkIGludG8gSUdWIGFuZCBzdGFydCB0byBnZXQgYSBmZWVsIGZvciB0aGUgcHJvY2VzcyBvZiB2YXJpYW50IGNhbGxpbmcKCjEuIERvd25sb2FkIElHVgoKWW91IGNhbiBkb3dubG9hZCBJR1YgZm9yIFdpbmRvd3MgdXNpbmcgdGhpcyBsaW5rIAoKLSBodHRwczovL3NvZnR3YXJlLmJyb2FkaW5zdGl0dXRlLm9yZy9zb2Z0d2FyZS9pZ3YvZG93bmxvYWQKCipFeHRyYWN0KiB0aGUgemlwIGZpbGUgdGhhdCB5b3UgaGF2ZSBkb3dubG9hZGVkCgoKCiFbXShtZWRpYS9leHRyYWN0X2lndi5QTkcpCgoKCkRvdWJsZS1DbGljayB0aGUgZmlsZSBgaWd2YCB0byBsYXVuY2ggSUdWCgoKCiFbXShtZWRpYS9ydW5faWd2LlBORykKCjxmb250IHNpemU9IjUiPgpJZiB5b3UgYXJlIHVuYWJsZSB0byBkb3dubG9hZCBJR1YsIHlvdSBzaG91bGQgYmUgYWJsZSB0byBydW4gYSB3ZWItYXBwIGZyb20gdGhlIEJyb2FkIEluc3RpdHV0ZSB3ZWJzaXRlIHdpdGggdGhlIHNhbWUgZnVuY3Rpb25hbGl0eS4KCmh0dHBzOi8vaWd2Lm9yZy9hcHAvCgo8L2ZvbnQ+CgoKMi4gTG9hZCBhIHJlZmVyZW5jZSBHZW5vbWUgYW5kIHNvbWUgRGF0YSBUcmFja3MKCkJ5IGRlZmF1bHQsIElHViBzaG91bGQgbG9hZCB3aXRoIEh1bWFuIGdlbm9tZSB2ZXJzaW9uICpoZzE5KiBhbHJlYWR5IGxvYWRlZC4gSXQgaXMgZXNzZW50aWFsIHRoYXQgeW91IHVzZSB0aGUgKipzYW1lIGdlbm9tZSB2ZXJzaW9uKiogdGhhdCB0aGUgcmVhZHMgd2VyZSBhbGlnbmVkIHRvLiBZb3UgY2FuIGNoZWNrIC8gY2hhbmdlIHRoZSBnZW5vbWUgYnkgY2xpY2tpbmcgdGhlIGRyb3AtZG93biBtZW51IGluIHRoZSB1cHBlci1sZWZ0CgohW10obWVkaWEvc2VsZWN0X2dlbm9tZS5QTkcpCgpXZSBjYW4gYWxzbyBsb2FkIGV4dHJhICp0cmFja3MqIGludG8gdGhlIGJyb3dzZXIgdGhhdCBjYW4gaGVscCB1cyB1bmRlcnN0YW5kIG91ciB2YXJpYW50IGNhbGxzLiBXZSBjYW4gbG9hZCBkYXRhIGZyb20gKmRiU05QKiB3aGljaCB3aWxsIHRlbGwgdXMgYWJvdXQgY29tbW9uIG11dGF0aW9ucyB0aGF0IGFscmVhZHkgYmVlbiBpZGVudGlmaWVkLiBUaGVzZSBjYW4gYmUgbG9hZGVkIHZpYSAqRmlsZSogLT4gKkxvYWQgZnJvbSBTZXJ2ZXIuLiogYW5kIHNlbGVjdGluZyBgZGJTTlAgMS40LjdgIGZyb20gdGhlIGBWYXJpYXRpb24gYW5kIFJlcGVhdHNgIHNlY3Rpb24KCiFbXShtZWRpYS9hdmFpbGFibGVfZGF0YXNldHMuUE5HKQoKCjMuIE5hdmlnYXRlIGFyb3VuZCBJR1YKCldoZW4gSUdWIGxvYWRzIHVwIHdlIHN0YXJ0IHdpdGggYSB2ZXJ5IGhpZ2gtbGV2ZWwgdmlldyBvZiB0aGUgZ2Vub21lIHdoZXJlICphbGwqIGNocm9tb3NvbWVzIGFyZSB2aXNpYmxlLiBTdWNoIGEgdmlldyBtaWdodCBiZSB1c2VmdWwgaWYgd2Ugd2VyZSBpbnRlcmVzdGVkIGluIGxhcmdlIGNvcHktbnVtYmVyIHZhcmlhdGlvbiBhY3Jvc3MgYSBjb2hvcnQgb2Ygc2FtcGxlcy4gSG93ZXZlciwgd2UgYXJlIG1vc3RseSBpbnRlcmVzdGVkIGluIGNoYW5nZXMgYXQgdGhlIGluZGl2aWR1YWwgYmFzZS1sZXZlbCB3aGljaCBpcyBub3QgcG9zc2libGUgdG8gdmlldyBhdCB0aGlzIHJlc29sdXRpb24uIFdlIG5lZWQgdG8gbmF2aWdhdGUgdG8gYSBwYXJ0aWN1bGFyIHJlZ2lvbiBvZiBpbnRlcmVzdC4KCkFsb25nc2lkZSB0aGUgZHJvcC1kb3duIG1lbnUgdXNlZCB0byBjaGFuZ2UgdGhlIGdlbm9tZSwgdGhlcmUgaXMgYSBkcm9wLWRvd24gbWVudSB0byBzZWxlY3QgYSBwYXJ0aWN1bGFyIGNocm9tb3NvbWUgYW5kIGEgYm94IHdoZXJlIHdlIGNhbiBlbnRlciB0ZXh0LiBJbnNpZGUgdGhlIHRleHQgYm94IHdlIGNhbiBlbnRlciBhIHBhcnRpY3VsYXIgZ2Vub21lIGludGVydmFsIG9mIGludGVyZXN0CgplLmcuIGBjaHIxOjEwLDAwMC0xMSwwMDBgCgoKSUdWIHNob3VsZCBub3cgYmUgZGlzcGxheWluZyBhIHJlZ2lvbiBvbiBjaHJvbW9zb21lIDEgZnJvbSBiYXNlIHBvc2l0aW9uIGAxMCwwMDBgIHRvIGAxMSwwMDBgLiAKCiFbXShtZWRpYS96b29tX3JlZ2lvbi5QTkcpCgoKQXQgdGhpcyByZXNvbHV0aW9uLCB3ZSBjYW4gc3RhcnQgdG8gc2VlIHRoZSAqZ2Vub21lIHNlcXVlbmNlKi4gRWFjaCBETkEgYmFzZSBpcyByZXByZXNlbnRlZCBieSBhIGRpZmZlcmVudCBjb2xvdXIgKEEgPSBncmVlbiwgQyA9IGJsdWUpIGFuZCBpdCBzZWVtcyB0aGF0IHRoaXMgcmVnaW9uIGlzIGhpZ2hseS1yZXBldGl0aXZlOyBjb21wcmlzaW5nIG1vc3RseSBgQ2AgYmFzZXMuIFdlIGNhbiB6b29tIGZ1cnRoZXIgaW4gdXNpbmcgdGhlIHpvb20gY29udHJvbCBpbiB0aGUgdG9wIHJpZ2h0IG9mIElHVgoKIVtdKG1lZGlhL2hvd190b196b29tLlBORykKCldlIGNhbiB1c2UgdGhlIHpvb20gY29udHJvbCwgYW5kIGFsc28gbW92ZSBhbG9uZyB0aGUgZ2Vub21lIGJ5IGhvbGRpbmcgZG93biBieSBtb3VzZSBidXR0b24gYW5kIHNsaWRpbmcgbGVmdC1hbmQtcmlnaHQsIHRvIG5hdmlnYXRlIHRvIHdoYXRldmVyIGdlbm9taWMgbG9jYXRpb24gd2Ugd2FudC4gSWYgd2Uga25vd24gdGhlIG5hbWUgb2YgdGhlIGdlbmUgd2Ugd2FudCB0byBpbnRlcnJvZ2F0ZSB3ZSBjYW4gbmF2aWdhdGUgZGlyZWN0bHkgdGhlcmUgdXNpbmcgdGhlIHRleHQgYm94CgohW10obWVkaWEvc2VsZWN0X3JlZ2lvbi5QTkcpCgpUaGUgdGV4dCBib3ggc2hvdWxkIG5vdyB1cGRhdGUgdG8gc2hvdyB0aGUgY29vcmRpbmF0ZXMgb2YgYEJSQ0ExYCAoYGNocjE3Oi4uLi5gKS4gQXQgdGhlIGJvdHRvbSBvZiB0aGUgc2NyZWVuIHdlIGNhbiBub3cgc2VlIHRoZSAqZ2VuZSBtb2RlbCogZm9yIHRoZSBnZW5lIGBCUkNBMWAuICBHZW5lcyBhcmUgcmVwcmVzZW50ZWQgYXMgbGluZXMgYW5kIGJveGVzLiBMaW5lcyByZXByZXNlbnQgaW50cm9uaWMgcmVnaW9ucyBhbmQgYm94ZXMgcmVwcmVzZW50IGV4b25pYyByZWdpb25zLiBUaGUgYXJyb3dzIGluZGljYXRlIHRoZSBkaXJlY3Rpb24gLyBzdHJhbmQgb2YgdHJhbnNjcmlwdGlvbiBmb3IgdGhlIGdlbmUuCgohW10obWVkaWEvZ2VuZV9yZWdpb24uUE5HKQoKNC4gTG9hZCB0aGUgYWxpZ25lZCByZWFkcwoKQ2hvb3NlIEZpbGUgPiBMb2FkIGZyb20gRmlsZS4uLiwgc2VsZWN0IHRoZSBiYW0gZmlsZSB0aGF0IHlvdSBkb3dubG9hZGVkIGZyb20gR2FsYXh5LCBhbmQgY2xpY2sgT0suIE5vdGUgdGhhdCB0aGUgYmFtIGFuZCBpbmRleCBmaWxlcyBtdXN0IGJlIGluIHRoZSBzYW1lIGRpcmVjdG9yeSBmb3IgSUdWIHRvIGxvYWQgdGhlc2UgcHJvcGVybHkuCgohW10obWVkaWEvc2VsZWN0X2JhbS5QTkcpCgpUaGUgbWFpbiBkaXNwbGF5IG9mIElHViBzaG91bGQgbm93IHVwZGF0ZSB0byBob2xkIHRyYWNrcyBmb3IgdGhlIGFsaWduZWQgcmVhZHMgZnJvbSB0aGlzIGJhbSBmaWxlLiBJdCBtYXkgc2VlbSBsaWtlIG5vdGhpbmcgaXMgYmVpbmcgZGlzcGxheWVkLiBUaGlzIGlzIGJlY2F1c2Ugd2UgYXJlIHpvb21lZC1vdXQgdG9vIGZhciB0byBiZSBhYmxlIHRvIHNlZSB0aGUgcmVhZHMuICoqVXNlIHRoZSB6b29tIGZ1bmN0aW9uIGFuZCBtb3ZlIGFsb25nIHRoZSBnZW5vbWUgdW50aWwgeW91IGdldCB0byB0aGUgZmlyc3QgZXhvbiBvZiBCUkNBMSoqLiBBZnRlciB5b3UgaGF2ZSB6b29tZWQtaW4gZmFyIGVub3VnaCB5b3Ugd2lsbCBzdGFydCB0byBzZWUgc29tZSBncmV5IHJlY3RhbmdsZXMuICpUaGVzZSBhcmUgdGhlIGFsaWduZWQgcmVhZHMqLiBOb3RlIHRoYXQgc29tZSAqZG93bnNhbXBsaW5nKiBtYXkgb2NjdXIgbWVhbmluZyB0aGF0IG5vdCBhbGwgcmVhZHMgYXJlIGRpc3BsYXllZCB0byByZWR1Y2UgbWVtb3J5IHJlcXVpcmVtZW50cy4KCklmIHlvdSBob3ZlciBvdmVyIGEgcGFydGljdWxhciByZWFkLCBob3cgd2lsbCBzZWUgY29sdW1ucyBmcm9tIHRoZSBiYW0gZmlsZSBiZWluZyBkaXNwbGF5ZWQgc3VjaCBhcyB0aGUgbWFwcGluZyBxdWFsaXR5IGFuZCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcGFpcmVkIHJlYWRzLgoKQ29sb3VyZWQtbGV0dGVycyB3aXRoaW4gdGhlIHJlYWQgaW5kaWNhdGUgYmFzZXMgdGhhdCBhcmUgZGlmZmVyZW50IHRvIHRoZSByZWZlcmVuY2UgZ2Vub21lLiBUaGUgZW50aXJlIHJlYWQgbWF5IGJlIGNvbG91cmVkIGRpZmZlcmVudGx5IHRvIGdyZXksIHdoaWNoIGNhbiBpbmRpY2F0ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiBob3cgdGhlIGRpc3BsYXkgaGFzIGJlZW4gY29uZmlndXJlZC4gRm9yIGV4YW1wbGUsIGl0IGNhbiBoaWdobGlnaHQgcGFpcmVkLXJlYWRzIHdpdGggYW4gKmluc2VydCBzaXplKiBkaWZmZXJlbnQgdG8gdGhhdCBleHBlY3RlZCAoW3NlZSBoZXJlXShodHRwczovL3NvZnR3YXJlLmJyb2FkaW5zdGl0dXRlLm9yZy9zb2Z0d2FyZS9pZ3YvaW50ZXJwcmV0aW5nX2luc2VydF9zaXplKSkuIFRoZSBkaXNwbGF5IG9mIGFsaWduZWQgcmVhZHMgY2FuIGJlIGNvbmZpZ3VyZWQgdGhyb3VnaCB0aGUgbWVudXMsIGFzIGRlc2NyaWJlZCBbaGVyZV0oaHR0cDovL3NvZnR3YXJlLmJyb2FkaW5zdGl0dXRlLm9yZy9zb2Z0d2FyZS9pZ3YvUHJlZmVyZW5jZXMjQWxpZ25tZW50cykuIAo=