Hands-on RNA-seq Analysis in Galaxy
Acknowledgement
Based on the RNA-Seq workshop by Melbourne Bioinformatics written by Mahtab Mirmomeni, Andrew Lonie, Jessica Chung Original
Modified by David Powell (Monash Bioinformatics Platform)
Further Modified by Mark Dunning of Sheffield Bioinformatics Core
Tutorial Overview
This tutorial will cover the basics of RNA-seq 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 RNA-seq analysis and be comfortable with the outputs generated by the Bioinformatician.
More on Galaxy
The official Galaxy page has many tutorials on using the service, and examples of other types of analysis that can be performed on the platform.
Those eventually wanted to perform their own RNA-seq analysis (for example in R), should look out for other courses
Courses on analysing RNA-seq data in R
Background
Where do the data in this tutorial come from?
The data for this tutorial comes from a Nature Cell Biology paper, EGF-mediated induction of Mcl-1 at the switch to lactation is essential for alveolar cell survival [@Fu2015].
This study examines the expression profiles of basal stem-cell enriched cells (B) and committed luminal cells (L) in the mammary gland of virgin, pregnant and lactating mice. Six groups are present, with one for each combination of cell type and mouse status. Each group contains two biological replicates.
The full experimental design is as follows:-
SRR1552444 |
MCL1-LA |
basal |
virgin |
SRR1552445 |
MCL1-LB |
luminal |
virgin |
SRR1552446 |
MCL1-LC |
Luminal |
pregnancy |
SRR1552447 |
MCL1-LD |
Luminal |
pregnancy |
SRR1552448 |
MCL1-LE |
luminal |
lactation |
SRR1552449 |
MCL1-LF |
luminal |
lactation |
SRR1552450 |
MCL1-DG |
basal |
virgin |
SRR1552451 |
MCL1-DH |
luminal |
virgin |
SRR1552452 |
MCL1-DI |
basal |
pregnancy |
SRR1552453 |
MCL1-DJ |
basal |
pregnancy |
SRR1552454 |
MCL1-DK |
basal |
lactation |
SRR1552455 |
MCL1-DL |
basal |
lactation |
For this tutorial, we will assume that the wet-lab stages of the experiment have been performed and we are now in the right-hand branch of the workflow. In this tutorial we will demonstrate the steps of Quality assessment, alignment, quantification and differential expression testing.
Section 1: Preparation
1. Sign-up to the European Galaxy server
Make sure you check your email to activate your account
2. Import the RNA-seq 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. To make the practical quicker, we have downsampled the original fastq files to half a million reads.
Get Data -> Upload File
You can import the data by:
- In the tool panel located on the left, under Basic Tools select Get Data > Upload File. Click on the **Choose local file* button on the bottom section of the pop-up window.
- Navigate to the
fastq
directory of the zip file that you downloaded from google drive There are two files are single-end samples from the basal-virgin condition.
SRR1552444.fastq.gz
SRR1552450.fastq.gz
and these two files are single-end samples from the basal pregnant condition.
SRR1552452.fastq.gz
SRR1552453.fastq.gz
- You should now have these 4 files in your history:
SRR1552444.fastq.gz
SRR1552450.fastq.gz
SRR1552452.fastq.gz
SRR1552453.fastq.gz
Each read is described by 4 lines in the file:-
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). We will need to tell Galaxy which scale has been used in order that we can process the data correctly.
Deriving the Quality Score
First of all, we convert the base-calling probability (p) into a Q
score using the formula
- Quality scores \[ Q = -10log_{10}p\]
- Q = 30, p=0.001
- Q = 20, p=0.01
- Q = 10, p=0.1
- These numeric quanties are encoded as ASCII code
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} \]
In practice, we don’t have to convert the values as we have software that will do this automatically
Section 2: 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. However, it is 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), so some warnings might be expected due to the nature of your experiment.
FastQ Quality Control -> FastQC Read Quality reports
Make sure you select this tool. There is another version of FastQC present, which does not produce some of the output we need for a later step
- 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.
- Run Fastqc on the remaing fastq files, but don’t examine the results just yet.
Question: Do the data seem to be of reasonable quality?
You can use the documentation to help interpret the plots
If poor quality reads towards the ends of reads are considered to be a problem, or there is considerable adapter contamination, we can employ various tools to trim our data.
However, a recent paper demonstrated that read trimming is no longer required prior to alignment:- https://www.biorxiv.org/content/10.1101/833962v1
If you suspect contamination from adapter sequence or unacceptable quality scores towards the ends of reads various trimming options are supported by the Trimmomatic tool (amongst others)
FASTA/FASTQ -> Trimmomatic
The operations supported by trimmomatic will probably not be very informative on our example data (as it has already been processed), but you can try several operations if you get time:-
- Removing Illumina adapter sequences by setting Perform initial ILLUMINACLIP to Yes and selecting the appropriate adapter type
- Remove poor quality bases at the end of reads by choosing Cut bases off the end of a read, if below a threshold quality (TRAILING) under Select Trimmomatic operation to perform
- Remove poor quality bases at the start of reads by choosing Cut bases off the start of a read, if below a threshold quality (LEADING) under Select Trimmomatic operation to perform
- You can apply multiple operations in turn by clicking Insert Trimmomatic Operation
If you also suspect contamination by another organism, or rRNA present in your data, you can use the sortMeRNA tool to remove this artefact.
Combining QC reports
It can be quite tiresome to click through multiple QC reports and compare the results for different samples. It is useful to have all the QC plots on the same page so that we can more easily spot trends in the data.
The multiqc tool has been designed for the tasks of aggregating qc reports and combining into a single report that is easy to digest.
FASTQ Quality Control -> Multiqc
Under Which tool was used generate logs? Choose fastqc and select the RawData output from the fastqc run on each of your bam files.
Question: Repeat the FastQC analysis for the remaining fastq files and combine the reports with multiQC
. Do the fastq files seem to have consistently high-quality?
Section 3: Alignment
In this section we map the reads in our FASTQ files to a reference genome. As these reads originate from mRNA, we expect some of them will cross exon/intron boundaries when we align them to the reference genome. HISAT2
is a splice-aware mapper for RNA-seq reads that is based on Bowtie. It uses the mapping results from Bowtie to identify splice junctions between exons. More information on HISAT2 can be found here.
1. Map/align the reads with HISAT2 to the mm10 reference genome
In the left tool panel menu, under NGS Analysis, select Mapping > HISAT2 and set the parameters as follows:
- Is this single-end or paired-end data? Single-end (as individual datasets)
- FASTQ file
(Click on the multiple datasets icon and select all four of the FASTQ files)
SRR1552444.fastq.gz
SRR1552450.fastq.gz
SRR1552452.fastq.gz
SRR1552453.fastq.gz
- Source for the reference genome Use built-in genome
- Select a reference genome: Mouse (Mus Musculus): mm10
- Use defaults for the other fields
- Execute
Note: This may take a few minutes, depending on how busy the server is.
2. Rename the output files
You should have 5 output files for each of the FASTQ input files:
HISAT2 on data.. aligned reads (BAM)
It will be helpful to rename these to something shorter for the next steps.
SRR1552444.bam
SRR1552450.bam
SRR1552452.bam
SRR1552453.bam
If this step is taking too long, there is an aligned bam file present in the google drive link. You can use this in the following steps of the tutorial.
STAR is also another popular option for aligned RNA-seq reads. We won’t cover this today, or the relative merits of different methods. If you want to try STAR in your own time you can find it under.
About the aligned read format
Unlike most of Bioinfomatics, 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 first part of the header lists the names (SN
) of the sequences (chromosomes) used in alignment, their length (LN
). Sometimes, a md5sum “digital fingerprint” of the .fasta
file used for alignment (M5
) is shown.
@HD VN:1.0 SO:coordinate
@SQ SN:chr1 LN:195471971
@SQ SN:chr10 LN:130694993
@SQ SN:chr11 LN:122082543
.....
.....
If mutliple samples were present in the file (i.e. the samples have been multiplexed), read groups can be used to identify which sequencing library, sequencing centre, Lane, sample name etc.
(not present for the example data in this course)
@RG ID:SRR077850 CN:bi LB:Solexa-42057 PL:illumina PU:ILLUMINA SM:NA06984
@RG ID:SRR081675 CN:bi LB:Solexa-42316 PL:illumina PU:ILLUMINA SM:NA06984
@RG ID:SRR080818 CN:bi LB:Solexa-44770 PL:illumina PU:ILLUMINA SM:NA06984
@RG ID:SRR084838 CN:bi LB:Solexa-42316 PL:illumina PU:ILLUMINA SM:NA06984
@RG ID:SRR081730 CN:bi LB:Solexa-42316 PL:illumina PU:ILLUMINA SM:NA06984
.....
.....
Finally, we have a section where we can record the processing steps used to derive the file. This is
@PG ID:hisat2 PN:hisat2 VN:2.1.0 CL:"/mnt/pulsar/dependencies/_conda/envs/mulled-v1-e7321ba46fa5ea4c6b9a06b78e6cd5182b33c0a47c2c86b5d610e1361f8b1686/bin/hisat2-align-s --wrapper basic-0 -p 4 -x /cvmfs/data.galaxyproject.org/managed/hisat2_index/mm10/mm10 -U /tmp/16282.unp"
....
....
Next is a tab-delimited section that describes the alignment of each sequence in detail.
SRR1552450.220289 0 chr1 3200839 60 100M * 0 0 GGCTCACCAAGTATGATGGTTTCATACCCAGAAAAACATTTGTTCTTTTGGATGCCATTAGTTCAGCCAGTGTCAACATGACTAGTGGTTTCCCAAGCAC CCCFFFFDHHGDHGIIJJJIHGHGGIGHIIIGFHGHBIIHIJAGIJIJJGGCHJJIGIJJJGHCAGGHHIICGGHHHHHHFFFFFDCE;?AACCDCDDDC AS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 NM:i:0 MD:Z:100 YT:Z:UU NH:i:1
SRR1552450.138797 16 chr1 3201132 60 100M * 0 0 CATTTTTAACAGCATATTTGTCTTAGCTTTAAATCCAGAGTACTGTTTGGCTTCAAAGAAGATAGTCATCTCTGGTTCTCTTACTGAGAATAGAAAGTCT DDEEEEEEEFFFFFFFHHHHHIIGCHGEJJJJJJJJJJIJJJJJJJJJJJJIJIJJJJJJJJJJJJIGJJJJJIJJJJJJJIHJJJJHHHHHFFFFFCCC AS:i:0 XN:i:0 XM:i:0 XO:i:0 XG:i:0 NM:i:0 MD:Z:100 YT:Z:UU NH:i:1
The first 11 columns of each line have an official specification
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.
Quality Control 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 might have 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.
ReadHasProperty Binary MultiplyBy
isPaired TRUE 1 1
isProperPair TRUE 1 2
isUnmappedQuery FALSE 0 4
hasUnmappedMate FALSE 0 8
isMinusStrand FALSE 0 16
isMateMinusStrand TRUE 1 32
isFirstMateRead FALSE 0 64
isSecondMateRead TRUE 1 128
isSecondaryAlignment FALSE 0 256
isNotPassingQualityControls FALSE 0 512
isDuplicate FALSE 0 1024
Value of flag is given by
1x1 + 1x2 + 0x4 + 0x8 + 0x16 + 1x32 + 0x64 + 1x128 + 0x256 + 0x512 + 0x1024 = 163
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.
M |
alignment match |
I |
insertion |
D |
deletion |
N |
skipped |
S |
soft-clipping |
H |
hard-clipping |
e.g.
101M
- 101 bases matching the reference
1S100M
- 1 soft-clipped read followed by 100 matches
15M87N70M90N16M
- 15 matches following by 87 bases skipped followed by 70 matches etc.
sam
or bam?
Alignment algorithms such as HISAT2
tend to produce a sam
file as their raw output, whereas we usually analyse a .bam
file. The contents of both files are exactly the same. Whereas a sam
file is designed to be human-readable, a bam
file can be processed more efficiently by a computer as it is compressed and indexed.
The reads in a sam
file tend to be arranged in the order that they were generated by the sequencer. On the other hand, the bam
file that you see in Galaxy has been sorted according to the position that the reads map. If you run your own alignments using command line software, you will need to use a tool to sort and index the data before analysis.
Quality assessment of the aligned reads
samtools will calculate QC statistics for a set of aligned reads in bam format
SAM/BAM -> Samtools stats
If you view the output you will see that it is not very easy to interpret.
FASTQ Quality Control -> Multiqc
make sure Which tool was used to generate logs is set to Samtools and select the Samtools stats…. files that were produced in the previous step
Section 4. Visualise the aligned reads with IGV
Download the bam files you have created in the previous step by clicking the disk icon on the right-hand panel. Make sure to click both the Download dataset and Download index buttons. We will now visualise the alignments using the Integrative Genomics Viewer (IGV).
Introducing the IGV Browser
Whilst tools like R are very powerful and allow you to perform statistical analyses and test hypotheses, there is no substitute for looking at 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.
- IGV has been developed by the Broad Institute and is able to display most kinds of genomic data
- expression
- ChIP
- whole-genome resequencing
- shRNA
- It is a Java desktop application and can be run either locally of from the Broad website
- To run IGV yourself you will need to agree to the license and download the version for your OS
A quick tour of IGV
For more details
- Sample information panel
- Information about samples you have loaded
- e.g. Sample ID, Gender, Age, Tumour / Normal
- Genome Navigation panel
- Jump to a genomic region in
Chr:Start-End
format
- Jump to a gene symbol of interest
- Data panel
- Your sequencing reads will be displayed here
- Or whatever data you have loaded
- Attribute panel
- Gene locations
- Genome sequence (if zoomed-in at appropriate level)
- Proteins
Example
Go to File -> Load from file and select the aligned bam
files from HISAT2
. Note that the index files .bai
need to be present in the same directory. However, you only need to click on the .bam
Make sure that the genome selected is mm10
. The default wil be human hg19
- The black dotted vertical lines indicates the centre of the view
- Each of the grey pointed rectangles represents a sequencing reads
- whether the pointed bit is on the left or right indicates if the read is forward or reverse.
- A coverage track is also generated
- You should see the read that we described in detail in the previous section by hovering over the reads to display the information from the
.bam
file
The view in IGV is not static and we can scroll-along the genome by holding-down the left mouse in the data panel and dragging left and right
It’s worth noting that the display settings may be showing fewer reads than you have (downsampling) in order to conserve memory. Also, some QC-fail or PCR duplicates may be filtered.
We also have some options on how to display the reads themselves, which we can acccess by right-clicking on the bam track
Sorting alignments by:-
- start
- strand
- base
- mapping quality
- insert size
The reads themselves can also be coloured according to
- insert size
- read strand
- sample
Section 5. Quantification (Counting reads in features)
In order to test for differential expression, we need to count up how many times each “feature” is observed is each sample. The goal of such operations is to produce a count table such as that shown below. We can then apply statistical tests to these data
HTSeq-count creates a count matrix using the number of the reads from each bam file that map to the genomic features. For each feature (a gene for example) a count matrix shows how many reads were mapped to this feature.
Various rules can be used to assign counts to features
To obtain the coordinates of each gene, we can use the UCSC genome browser which is integrated into Galaxy.
Obtaining gene coordinates
Get Data -> UCSC Main table browser
Selecting the UCSC Main tool from Galaxy will take you to the UCSC table browser. From here we can extract gene coordinates for our genome of interest (sacCer3
) in gtf
format for processing with galaxy.
- Set clade to Mammal
- Set genome to Mouse
- assembly Dec.2011 (GRCm38/mm10)
- group Genes and Gene Prediction
- track NCBI RefSeq
- region genome
- output format GTF - gene transfer format (limited) and send output to Galaxy
Click get output and send query to Galaxy to be returned to Galaxy. A new job will be submitted to retrieve the coordinates from UCSC
RNA Analysis > htseq-count
- Use HTSeq-count to count the number of reads for each feature.
In the left tool panel menu, under NGS Analysis, select NGS Analysis > htseq-count and set the parameters as follows:
- Aligned SAM/BAM file
(Select one of four bam files, or all four using the multiple datasets option)
- GFF file UCSC Main on Mouse:ncbiRefSeq (genome)
- Use defaults for the other fields
- Execute
- Repeat for the remaining bam files if running on each bam separately.
- Rename the ht-seq output for each sample. Do not rename the outputs that have “(no feature)” in their name
Further QC on the aligned reads
Additional QC of the aligned reads can be obtained with the Qualimap tool. This also uses information from the genome transcript file to calculate how many reads are counted in exonic, intronic and intergenic regions. For RNA-seq this percentage should be high; at least 80 to 90%.
RNA-Seq > Qualimap RNA-Seq QC
Create a count matrix
The htseq tool is designed to produce a separate table of counts for each sample. This is not particularly useful for other tools such as Degust (see next section) which require the counts to be presented in a data matrix where each row is a gene and each column is a particular sample in the dataset.
Collection Operations -> Column Join on Collections
- In the Tabular Files section, select the
ht-seq
count files from your history SRR1552444.htseq, SRR1552450, etc… Holding the CTRL key allows multiple files to be selected
- Keep Identifier column as
1
The output should look something like this…
- Download to your computer
You are now ready to follow the next tutorial on Differential Expression
References
[1] Nookaew I, Papini M, Pornputtpong N, Scalcinati G, Fagerberg L, Uhlén M, Nielsen J: A comprehensive comparison of RNA-Seq-based transcriptome analysis from reads to differential gene expression and cross-comparison with microarrays: a case study in Saccharomyces cerevisiae. Nucleic Acids Res 2012, 40 (20):10084 – 10097. doi:10.1093/nar/gks804. Epub 2012 Sep 10
[2] Guirguis A, Slape C, Failla L, Saw J, Tremblay C, Powell D, Rossello F, Wei A, Strasser A, Curtis D: PUMA promotes apoptosis of hematopoietic progenitors driving leukemic progression in a mouse model of myelodysplasia. Cell Death Differ. 2016 Jun;23(6)
LS0tCnRpdGxlOiAiUk5BLXNlcSBQcmUtcHJvY2Vzc2luZyB0dXRvcmlhbCIKYXV0aG9yOiAiTWFyayBEdW5uaW5nIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgoKCiMgSGFuZHMtb24gUk5BLXNlcSBBbmFseXNpcyBpbiBHYWxheHkKCiMjIEFja25vd2xlZGdlbWVudAoKX0Jhc2VkIG9uIHRoZSBSTkEtU2VxIHdvcmtzaG9wIGJ5IE1lbGJvdXJuZSBCaW9pbmZvcm1hdGljcyB3cml0dGVuIGJ5IE1haHRhYiBNaXJtb21lbmksIEFuZHJldyBMb25pZSwgSmVzc2ljYSBDaHVuZ18gW09yaWdpbmFsXShodHRwOi8vdmxzY2kuZ2l0aHViLmlvL2xzY2NfZG9jcy90dXRvcmlhbHMvcm5hX3NlcV9kZ2VfYWR2YW5jZWQvcm5hX3NlcV9hZHZhbmNlZF90dXRvcmlhbC8pCgpfTW9kaWZpZWQgYnkgRGF2aWQgUG93ZWxsIChNb25hc2ggQmlvaW5mb3JtYXRpY3MgUGxhdGZvcm0pXwoKX0Z1cnRoZXIgTW9kaWZpZWQgYnkgTWFyayBEdW5uaW5nIG9mIFNoZWZmaWVsZCBCaW9pbmZvcm1hdGljcyBDb3JlXwoKCiMjIyBTaGVmZmllbGQgQmlvaW5mb3JtYXRpY3MgQ29yZQo8aW1nIHNyYz0ibWVkaWEvbG9nby1zbS5wbmciIGFsaWduPXJpZ2h0PgoKd2ViIDogW3NiYy5zaGVmLmFjLnVrXShodHRwczovL3NiYy5zaGVmLmFjLnVrKSAgCnR3aXR0ZXI6IFtAU2hlZmZCaW9pbmZDb3JlXShodHRwczovL3R3aXR0ZXIuY29tL1NoZWZmQmlvaW5mQ29yZSkgIAplbWFpbDogW2Jpb2luZm9ybWF0aWNzLWNvcmVAc2hlZmZpZWxkLmFjLnVrXShiaW9pbmZvcm1hdGljcy1jb3JlQHNoZWZmaWVsZC5hYy51aykKCi0tLS0tCgojIyBUdXRvcmlhbCBPdmVydmlldwoKVGhpcyB0dXRvcmlhbCB3aWxsIGNvdmVyIHRoZSBiYXNpY3Mgb2YgUk5BLXNlcSB1c2luZyBHYWxheHk7IGEgb3Blbi1zb3VyY2Ugd2ViLWJhc2VkIHBsYXRmb3JtIGZvciB0aGUgYW5hbHlzaXMgb2YgYmlvbG9naWNhbCBkYXRhLiBZb3Ugc2hvdWxkIGdhaW4gYW4gYXBwcmVjaWF0aW9uIG9mIHRoZSB0YXNrcyBpbnZvbHZlZCBpbiBhIHR5cGljYWwgUk5BLXNlcSBhbmFseXNpcyBhbmQgYmUgY29tZm9ydGFibGUgd2l0aCB0aGUgb3V0cHV0cyBnZW5lcmF0ZWQgYnkgdGhlIEJpb2luZm9ybWF0aWNpYW4uCgojIyMgTW9yZSBvbiBHYWxheHkKClRoZSBvZmZpY2lhbCBHYWxheHkgcGFnZSBoYXMgbWFueSBbdHV0b3JpYWxzXShodHRwczovL2dhbGF4eXByb2plY3Qub3JnL2xlYXJuLykgb24gdXNpbmcgdGhlIHNlcnZpY2UsIGFuZCBleGFtcGxlcyBvZiBvdGhlciB0eXBlcyBvZiBhbmFseXNpcyB0aGF0IGNhbiBiZSBwZXJmb3JtZWQgb24gdGhlIHBsYXRmb3JtLgoKVGhvc2UgZXZlbnR1YWxseSB3YW50ZWQgdG8gcGVyZm9ybSB0aGVpciBvd24gUk5BLXNlcSBhbmFseXNpcyAoZm9yIGV4YW1wbGUgaW4gUiksIHNob3VsZCBsb29rIG91dCBmb3Igb3RoZXIgY291cnNlcwoKIyMjIENvdXJzZXMgb24gYW5hbHlzaW5nIFJOQS1zZXEgZGF0YSBpbiBSCgotIFtTaGVmZmllbGQgQmlvaW5mb3JtYXRpY3MgQ29yZV0oaHR0cDovL3NiYy5zaGVmLmFjLnVrL3RyYWluaW5nL3JuYS1zZXEtaW4tci0yMDE5LTAxLTE0LykKLSBbTW9uYXNoIEJpb2luZm9ybWF0aWNzIFBsYXRmb3JtXShodHRwOi8vbW9uYXNoYmlvaW5mb3JtYXRpY3NwbGF0Zm9ybS5naXRodWIuaW8vUk5Bc2VxLURFLWFuYWx5c2lzLXdpdGgtUi8pCgoKCi0tLS0tCgojIyBCYWNrZ3JvdW5kCgojIyMjIFdoZXJlIGRvIHRoZSBkYXRhIGluIHRoaXMgdHV0b3JpYWwgY29tZSBmcm9tPwpUaGUgZGF0YSBmb3IgdGhpcyB0dXRvcmlhbCBjb21lcyBmcm9tIGEgTmF0dXJlIENlbGwgQmlvbG9neSBwYXBlciwgWypFR0YtbWVkaWF0ZWQgaW5kdWN0aW9uIG9mIE1jbC0xIGF0IHRoZSBzd2l0Y2ggdG8gbGFjdGF0aW9uIGlzIGVzc2VudGlhbCBmb3IgYWx2ZW9sYXIgY2VsbCBzdXJ2aXZhbCpdKGh0dHA6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMjU3MzA0NzIpIFtARnUyMDE1XS4gCgpUaGlzIHN0dWR5IGV4YW1pbmVzIHRoZSBleHByZXNzaW9uIHByb2ZpbGVzIG9mIGJhc2FsIHN0ZW0tY2VsbCBlbnJpY2hlZCBjZWxscyAoQikgYW5kIGNvbW1pdHRlZCBsdW1pbmFsIGNlbGxzIChMKSBpbiB0aGUgbWFtbWFyeSBnbGFuZCBvZiB2aXJnaW4sIHByZWduYW50IGFuZCBsYWN0YXRpbmcgbWljZS4gU2l4IGdyb3VwcyBhcmUgcHJlc2VudCwgd2l0aCBvbmUgZm9yIGVhY2ggY29tYmluYXRpb24gb2YgY2VsbCB0eXBlIGFuZCBtb3VzZSBzdGF0dXMuIEVhY2ggZ3JvdXAgY29udGFpbnMgdHdvIGJpb2xvZ2ljYWwgcmVwbGljYXRlcy4KClRoZSBmdWxsIGV4cGVyaW1lbnRhbCBkZXNpZ24gaXMgYXMgZm9sbG93czotCgpSdW4gIHwgTmFtZSB8IENlbGxUeXBlIHwgU3RhdHVzCi0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gIApTUlIxNTUyNDQ0IHwgTUNMMS1MQSB8IGJhc2FsIHwgdmlyZ2luClNSUjE1NTI0NDUgfCBNQ0wxLUxCIHwgbHVtaW5hbCB8IHZpcmdpbgpTUlIxNTUyNDQ2IHwgTUNMMS1MQyB8IEx1bWluYWwgfCBwcmVnbmFuY3kKU1JSMTU1MjQ0NyB8IE1DTDEtTEQgfCBMdW1pbmFsIHwgcHJlZ25hbmN5ClNSUjE1NTI0NDggfCBNQ0wxLUxFIHwgbHVtaW5hbCB8IGxhY3RhdGlvbgpTUlIxNTUyNDQ5IHwgTUNMMS1MRiB8IGx1bWluYWwgfCBsYWN0YXRpb24KU1JSMTU1MjQ1MCB8IE1DTDEtREcgfCBiYXNhbCB8IHZpcmdpbgpTUlIxNTUyNDUxIHwgTUNMMS1ESCB8IGx1bWluYWwgfCB2aXJnaW4KU1JSMTU1MjQ1MiB8IE1DTDEtREkgfCBiYXNhbCB8IHByZWduYW5jeQpTUlIxNTUyNDUzIHwgTUNMMS1ESiB8IGJhc2FsIHwgcHJlZ25hbmN5ClNSUjE1NTI0NTQgfCBNQ0wxLURLIHwgYmFzYWwgfCBsYWN0YXRpb24KU1JSMTU1MjQ1NSB8IE1DTDEtREwgfCBiYXNhbCB8IGxhY3RhdGlvbgoKCgpGb3IgdGhpcyB0dXRvcmlhbCwgd2Ugd2lsbCBhc3N1bWUgdGhhdCB0aGUgKndldC1sYWIqIHN0YWdlcyBvZiB0aGUgZXhwZXJpbWVudCBoYXZlIGJlZW4gcGVyZm9ybWVkIGFuZCB3ZSBhcmUgbm93IGluIHRoZSByaWdodC1oYW5kIGJyYW5jaCBvZiB0aGUgd29ya2Zsb3cuIEluIHRoaXMgdHV0b3JpYWwgd2Ugd2lsbCBkZW1vbnN0cmF0ZSB0aGUgc3RlcHMgb2YgKipRdWFsaXR5IGFzc2Vzc21lbnQqKiwgKiphbGlnbm1lbnQqKiwgKipxdWFudGlmaWNhdGlvbioqIGFuZCAqKmRpZmZlcmVudGlhbCBleHByZXNzaW9uIHRlc3RpbmcqKi4KCgojIyBTZWN0aW9uIDE6IFByZXBhcmF0aW9uCiMjIyMgMS4gU2lnbi11cCB0byB0aGUgRXVyb3BlYW4gR2FsYXh5IHNlcnZlcgoKCi0gaHR0cHM6Ly91c2VnYWxheHkuZXUKLSBVc2UgdGhpcyBsaW5rIHRvIGFjY2VzcyB0aGUgc3BlY2lhbCBxdWV1ZSBjcmVhdGVkIGZvciB0aGlzIGNvdXJzZQogICsgaHR0cHM6Ly91c2VnYWxheHkuZXUvam9pbi10cmFpbmluZy9zYmMtMjAxOTAtMTIKCgoqKk1ha2Ugc3VyZSB5b3UgY2hlY2sgeW91ciBlbWFpbCB0byBhY3RpdmF0ZSB5b3VyIGFjY291bnQqKgoKIyMjIyAyLiAgSW1wb3J0IHRoZSBSTkEtc2VxIGRhdGEgZm9yIHRoZSB3b3Jrc2hvcC4KCldlIGNhbiBnb2luZyB0byBpbXBvcnQgdGhlIFsqZmFzdHEqIGZpbGVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GQVNUUV9mb3JtYXQpIGZvciB0aGlzIGV4cGVyaW1lbnQuIFRoaXMgaXMgYSBzdGFuZGFyZCBmb3JtYXQgZm9yIHN0b3JpbmcgcmF3IHNlcXVlbmNpbmcgcmVhZHMgYW5kIHRoZWlyIGFzc29jaWF0ZWQgcXVhbGl0eSBzY29yZXMuIFRvIG1ha2UgdGhlIHByYWN0aWNhbCBxdWlja2VyLCB3ZSBoYXZlICpkb3duc2FtcGxlZCogdGhlIG9yaWdpbmFsIGZhc3RxIGZpbGVzIHRvIGhhbGYgYSBtaWxsaW9uIHJlYWRzLgoKCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPgoKIyMjIyAqKkdldCBEYXRhIC0+IFVwbG9hZCBGaWxlICoqIAoKPC9kaXY+CgpZb3UgY2FuIGltcG9ydCB0aGUgZGF0YSBieToKCjEuICBJbiB0aGUgdG9vbCBwYW5lbCBsb2NhdGVkIG9uIHRoZSBsZWZ0LCB1bmRlciBCYXNpYyBUb29scyBzZWxlY3QgKipHZXQKICAgIERhdGEgPiBVcGxvYWQgRmlsZSoqLiBDbGljayBvbiB0aGUgKipDaG9vc2UgbG9jYWwgZmlsZSogYnV0dG9uIG9uIHRoZQogICAgYm90dG9tIHNlY3Rpb24gb2YgdGhlIHBvcC11cCB3aW5kb3cuCjIuICBOYXZpZ2F0ZSB0byB0aGUgYGZhc3RxYCBkaXJlY3Rvcnkgb2YgdGhlIHppcCBmaWxlIHRoYXQgeW91IGRvd25sb2FkZWQgZnJvbSBnb29nbGUgZHJpdmUKICAgIFRoZXJlIGFyZSB0d28gZmlsZXMgYXJlIHNpbmdsZS1lbmQgc2FtcGxlcyBmcm9tIHRoZSBiYXNhbC12aXJnaW4gY29uZGl0aW9uLiAKCmBTUlIxNTUyNDQ0LmZhc3RxLmd6YApgU1JSMTU1MjQ1MC5mYXN0cS5nemAKIAogYW5kIHRoZXNlIHR3byBmaWxlcyBhcmUgc2luZ2xlLWVuZCBzYW1wbGVzIGZyb20gdGhlIGJhc2FsIHByZWduYW50IGNvbmRpdGlvbi4KCmBTUlIxNTUyNDUyLmZhc3RxLmd6YApgU1JSMTU1MjQ1My5mYXN0cS5nemAKPC9kaXY+CgozLiAgWW91IHNob3VsZCBub3cgaGF2ZSB0aGVzZSA0IGZpbGVzIGluIHlvdXIgaGlzdG9yeToKICAgIC0gYFNSUjE1NTI0NDQuZmFzdHEuZ3pgCiAgICAtIGBTUlIxNTUyNDUwLmZhc3RxLmd6YAogICAgLSBgU1JSMTU1MjQ1Mi5mYXN0cS5nemAKICAgIC0gYFNSUjE1NTI0NTMuZmFzdHEuZ3pgCgoKCkVhY2ggcmVhZCBpcyBkZXNjcmliZWQgYnkgNCBsaW5lcyBpbiB0aGUgZmlsZTotCgo8aW1nIHNyYz0ibWVkaWEvZmFzdHEtaGVhZGVyLnBuZyI+CgpUaGUgcXVhbGl0eSBzY29yZXMgYXJlIFtBU0NJSV0oaHR0cDovL2FzY2lpLWNvZGUuY29tLykgcmVwcmVzZW50YXRpb25zIG9mIGhvdyBjb25maWRlbnQgd2UgYXJlIHRoYXQgYSBwYXJ0aWN1bGFyIGJhc2UgaGFzIGJlZW4gY2FsbGVkIGNvcnJlY3RseS4gTGV0dGVycyB0aGF0IGFyZSBmdXJ0aGVyIGFsb25nIHRoZSBhbHBoYWJldCBpbmRpY2F0ZSBoaWdoZXIgY29uZmlkZW5jZS4gVGhpcyBpcyBpbXBvcnRhbnQgd2hlbiB0cnlpbmcgdG8gaWRlbnRpZnkgdHlwZXMgb2YgZ2Vub21lIHZhcmlhdGlvbiBzdWNoIGFzIHNpbmdsZSBiYXNlIGNoYW5nZXMsIGJ1dCBpcyBhbHNvIGluZGljYXRpdmUgb2YgdGhlIG92ZXJhbGwgcXVhbGl0eSBvZiB0aGUgc2VxdWVuY2luZy4gRGlmZmVyZW50IHNjYWxlcyBoYXZlIGJlZW4gZW1wbG95ZWQgb3ZlciB0aW1lIChyZXN1bHRpbmcgaW4gYSBkaWZmZXJlbnQgc2V0IG9mIGNoYXJhY3RlcnMgYXBwZWFyaW5nIGluIHRoZSBmaWxlKS4gV2Ugd2lsbCBuZWVkIHRvIHRlbGwgR2FsYXh5IHdoaWNoIHNjYWxlIGhhcyBiZWVuIHVzZWQgaW4gb3JkZXIgdGhhdCB3ZSBjYW4gcHJvY2VzcyB0aGUgZGF0YSBjb3JyZWN0bHkuCgoKIyMjIERlcml2aW5nIHRoZSBRdWFsaXR5IFNjb3JlCgpGaXJzdCBvZiBhbGwsIHdlIGNvbnZlcnQgdGhlIGJhc2UtY2FsbGluZyBwcm9iYWJpbGl0eSAocCkgaW50byBhIGBRYCBzY29yZSB1c2luZyB0aGUgZm9ybXVsYQoKLSBRdWFsaXR5IHNjb3JlcyAkJCBRID0gLTEwbG9nX3sxMH1wJCQKICAgICsgUSA9IDMwLCBwPTAuMDAxCiAgICArIFEgPSAyMCwgcD0wLjAxCiAgICArIFEgPSAxMCwgcD0wLjEKLSBUaGVzZSBudW1lcmljIHF1YW50aWVzIGFyZSAqZW5jb2RlZCogYXMgWyoqQVNDSUkqKl0oaHR0cDovL2FzY2lpLWNvZGUuY29tLykgY29kZQogICAgKyBBdCBsZWFzdCAzMyB0byBnZXQgdG8gbWVhbmluZ2Z1bCBjaGFyYWN0ZXJzCiAgICAoaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRkFTVFFfZm9ybWF0KQogICAgCiFbXShtZWRpYS9waHJlZC5wbmcpICAgICAgCgojIyMgUXVhbGl0eSBTY29yZXMgdG8gcHJvYmFiaWxpdGllcwoKLSBsb29rLXVwIHRoZSBBU0NJSSBjb2RlIGZvciBlYWNoIGNoYXJhY3RlcgotIHN1YnRyYWN0IHRoZSBvZmZzZXQgdG8gZ2V0IHRoZSBRIHNjb3JlCi0gY29udmVydCB0byBhIHByb2JhYmlsaXR5IHVzaW5nIHRoZSBmb3JtdWxhOi0KCiQkIHAgPSAxMF57LVEvMTB9ICQkCgohW10obWVkaWEvcXVhbGl0eS10by1wcm9iLnBuZykKCkluIHByYWN0aWNlLCB3ZSBkb24ndCBoYXZlIHRvIGNvbnZlcnQgdGhlIHZhbHVlcyBhcyB3ZSBoYXZlIHNvZnR3YXJlIHRoYXQgd2lsbCBkbyB0aGlzIGF1dG9tYXRpY2FsbHkKCgotLS0tLQoKIyMgU2VjdGlvbiAyOiBRdWFsaXR5IGFzc2Vzc21lbnQgd2l0aCBGYXN0UUMKCltGYXN0UUNdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pIGlzIGEgcG9wdWxhciB0b29sIGZyb20gW0JhYnJhaGFtIEluc3RpdHV0ZSBCaW9pbmZvcm1hdGljcyBHcm91cF0oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvaW5kZXguaHRtbCkgdXNlZCBmb3IgKnF1YWxpdHkgYXNzZXNzbWVudCogb2Ygc2VxdWVuY2luZyBkYXRhLiBNb3N0IEJpb2luZm9ybWF0aWNzIHBpcGVsaW5lcyB3aWxsIHVzZSBGYXN0UUMsIG9yIHNpbWlsYXIgdG9vbHMgaW4gdGhlIGZpcnN0IHN0YWdlIG9mIHRoZSBhbmFseXNpcy4gVGhlIFtkb2N1bWVudGF0aW9uXShodHRwczovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9wcm9qZWN0cy9mYXN0cWMvSGVscC8pIGZvciBGYXN0UUMgd2lsbCBoZWxwIHlvdSB0byBpbnRlcnByZXQgdGhlIHBsb3RzIGFuZCBzdGF0cyBwcm9kdWNlZCBieSB0aGUgdG9vbC4gQSB0cmFmZmljIGxpZ2h0IHN5c3RlbSBpcyB1c2VkIHRvIGFsZXJ0IHRoZSB1c2VyJ3MgYXR0ZW50aW9uIHRvIHBvc3NpYmxlIGlzc3Vlcy4gSG93ZXZlciwgaXQgaXMgd29ydGggYmVhcmluZyBpbiBtaW5kIHRoYXQgdGhlIHRvb2wgaXMgYmxpbmQgdG8gdGhlIHBhcnRpY3VsYXIgdHlwZSBvZiBzZXF1ZW5jaW5nIHlvdSBhcmUgcGVyZm9ybWluZyAoaS5lLiB3aG9sZS1nZW5vbWUsIENoSVAtc2VxLCBSTkEtc2VxKSwgc28gc29tZSB3YXJuaW5ncyBtaWdodCBiZSBleHBlY3RlZCBkdWUgdG8gdGhlIG5hdHVyZSBvZiB5b3VyIGV4cGVyaW1lbnQuCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4KCiMjIyMgKkZhc3RRIFF1YWxpdHkgQ29udHJvbCogLT4gKkZhc3RRQyBSZWFkIFF1YWxpdHkgcmVwb3J0cyoKCjwvZGl2PgoKKipNYWtlIHN1cmUgeW91IHNlbGVjdCB0aGlzIHRvb2wuIFRoZXJlIGlzIGFub3RoZXIgdmVyc2lvbiBvZiBGYXN0UUMgcHJlc2VudCwgd2hpY2ggZG9lcyBub3QgcHJvZHVjZSBzb21lIG9mIHRoZSBvdXRwdXQgd2UgbmVlZCBmb3IgYSBsYXRlciBzdGVwKioKCi0gU2VsZWN0IG9uZSBvZiB0aGUgRkFTVFEgZmlsZXMgYXMgaW5wdXQgYW5kICpFeGVjdXRlKiB0aGUgdG9vbC4KLSBXaGVuIHRoZSB0b29sIGZpbmlzaGVzIHJ1bm5pbmcsIHlvdSBzaG91bGQgaGF2ZSBhbiBIVE1MIGZpbGUgaW4geW91ciBIaXN0b3J5LiBDbGljayBvbiB0aGUgZXllIGljb24gdG8gdmlldyB0aGUgdmFyaW91cyBxdWFsaXR5IG1ldHJpY3MuCi0gUnVuIEZhc3RxYyBvbiB0aGUgcmVtYWluZyBmYXN0cSBmaWxlcywgYnV0IGRvbid0IGV4YW1pbmUgdGhlIHJlc3VsdHMganVzdCB5ZXQuCgoKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtd2FybmluZyI+CgoqKlF1ZXN0aW9uOiBEbyB0aGUgZGF0YSBzZWVtIHRvIGJlIG9mIHJlYXNvbmFibGUgcXVhbGl0eT8gKioKCllvdSBjYW4gdXNlIHRoZSBbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjL0hlbHAvMyUyMEFuYWx5c2lzJTIwTW9kdWxlcy8pIHRvIGhlbHAgaW50ZXJwcmV0IHRoZSBwbG90cwoKPC9kaXY+CgpJZiBwb29yIHF1YWxpdHkgcmVhZHMgdG93YXJkcyB0aGUgZW5kcyBvZiByZWFkcyBhcmUgY29uc2lkZXJlZCB0byBiZSBhIHByb2JsZW0sIG9yIHRoZXJlIGlzIGNvbnNpZGVyYWJsZSBhZGFwdGVyIGNvbnRhbWluYXRpb24sIHdlIGNhbiBlbXBsb3kgdmFyaW91cyB0b29scyB0byAqdHJpbSogb3VyIGRhdGEuCgpIb3dldmVyLCBhIHJlY2VudCBwYXBlciBkZW1vbnN0cmF0ZWQgdGhhdCByZWFkIHRyaW1taW5nIGlzIG5vIGxvbmdlciByZXF1aXJlZCBwcmlvciB0byBhbGlnbm1lbnQ6LSBodHRwczovL3d3dy5iaW9yeGl2Lm9yZy9jb250ZW50LzEwLjExMDEvODMzOTYydjEKCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPgoKSWYgeW91IHN1c3BlY3QgY29udGFtaW5hdGlvbiBmcm9tIGFkYXB0ZXIgc2VxdWVuY2Ugb3IgdW5hY2NlcHRhYmxlIHF1YWxpdHkgc2NvcmVzIHRvd2FyZHMgdGhlIGVuZHMgb2YgcmVhZHMgdmFyaW91cyB0cmltbWluZyBvcHRpb25zIGFyZSBzdXBwb3J0ZWQgYnkgdGhlICpUcmltbW9tYXRpYyogdG9vbCAoYW1vbmdzdCBvdGhlcnMpCgojIyMjICpGQVNUQS9GQVNUUSogLT4gKlRyaW1tb21hdGljKgoKVGhlIG9wZXJhdGlvbnMgc3VwcG9ydGVkIGJ5IHRyaW1tb21hdGljIHdpbGwgcHJvYmFibHkgbm90IGJlIHZlcnkgaW5mb3JtYXRpdmUgb24gb3VyIGV4YW1wbGUgZGF0YSAoYXMgaXQgaGFzIGFscmVhZHkgYmVlbiBwcm9jZXNzZWQpLCBidXQgeW91IGNhbiB0cnkgc2V2ZXJhbCBvcGVyYXRpb25zIGlmIHlvdSBnZXQgdGltZTotCgotIFJlbW92aW5nIElsbHVtaW5hIGFkYXB0ZXIgc2VxdWVuY2VzIGJ5IHNldHRpbmcgKlBlcmZvcm0gaW5pdGlhbCBJTExVTUlOQUNMSVAqIHRvICpZZXMqIGFuZCBzZWxlY3RpbmcgdGhlIGFwcHJvcHJpYXRlIGFkYXB0ZXIgdHlwZQotIFJlbW92ZSBwb29yIHF1YWxpdHkgYmFzZXMgYXQgdGhlIGVuZCBvZiByZWFkcyBieSBjaG9vc2luZyAqQ3V0IGJhc2VzIG9mZiB0aGUgZW5kIG9mIGEgcmVhZCwgaWYgYmVsb3cgYSB0aHJlc2hvbGQgcXVhbGl0eSAoVFJBSUxJTkcpKiB1bmRlciAqU2VsZWN0IFRyaW1tb21hdGljIG9wZXJhdGlvbiB0byBwZXJmb3JtKgotIFJlbW92ZSBwb29yIHF1YWxpdHkgYmFzZXMgYXQgdGhlIHN0YXJ0IG9mIHJlYWRzIGJ5IGNob29zaW5nICpDdXQgYmFzZXMgb2ZmIHRoZSBzdGFydCBvZiBhIHJlYWQsIGlmIGJlbG93IGEgdGhyZXNob2xkIHF1YWxpdHkgKExFQURJTkcpKiB1bmRlciAqU2VsZWN0IFRyaW1tb21hdGljIG9wZXJhdGlvbiB0byBwZXJmb3JtKgotIFlvdSBjYW4gYXBwbHkgbXVsdGlwbGUgb3BlcmF0aW9ucyBpbiB0dXJuIGJ5IGNsaWNraW5nICpJbnNlcnQgVHJpbW1vbWF0aWMgT3BlcmF0aW9uKgoKPC9kaXY+Cgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4KCklmIHlvdSBhbHNvIHN1c3BlY3QgY29udGFtaW5hdGlvbiBieSBhbm90aGVyIG9yZ2FuaXNtLCBvciByUk5BIHByZXNlbnQgaW4geW91ciBkYXRhLCB5b3UgY2FuIHVzZSB0aGUgc29ydE1lUk5BIHRvb2wgdG8gcmVtb3ZlIHRoaXMgYXJ0ZWZhY3QuCjwvZGl2PgoKCiMjIENvbWJpbmluZyBRQyByZXBvcnRzCgpJdCBjYW4gYmUgcXVpdGUgdGlyZXNvbWUgdG8gY2xpY2sgdGhyb3VnaCBtdWx0aXBsZSBRQyByZXBvcnRzIGFuZCBjb21wYXJlIHRoZSByZXN1bHRzIGZvciBkaWZmZXJlbnQgc2FtcGxlcy4gSXQgaXMgdXNlZnVsIHRvIGhhdmUgYWxsIHRoZSBRQyBwbG90cyBvbiB0aGUgc2FtZSBwYWdlIHNvIHRoYXQgd2UgY2FuIG1vcmUgZWFzaWx5IHNwb3QgdHJlbmRzIGluIHRoZSBkYXRhLgoKVGhlIFttdWx0aXFjXShodHRwczovL211bHRpcWMuaW5mby8pIHRvb2wgaGFzIGJlZW4gZGVzaWduZWQgZm9yIHRoZSB0YXNrcyBvZiBhZ2dyZWdhdGluZyBxYyByZXBvcnRzIGFuZCBjb21iaW5pbmcgaW50byBhIHNpbmdsZSByZXBvcnQgdGhhdCBpcyBlYXN5IHRvIGRpZ2VzdC4KCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4KCipGQVNUUSBRdWFsaXR5IENvbnRyb2wqIC0+ICpNdWx0aXFjKgoKPC9kaXY+CgpVbmRlciAqV2hpY2ggdG9vbCB3YXMgdXNlZCBnZW5lcmF0ZSBsb2dzPyogQ2hvb3NlICpmYXN0cWMqIGFuZCBzZWxlY3QgdGhlIFJhd0RhdGEgb3V0cHV0IGZyb20gdGhlIGZhc3RxYyBydW4gb24gZWFjaCBvZiB5b3VyIGJhbSBmaWxlcy4KCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4KClF1ZXN0aW9uOiBSZXBlYXQgdGhlIEZhc3RRQyBhbmFseXNpcyBmb3IgdGhlIHJlbWFpbmluZyBmYXN0cSBmaWxlcyBhbmQgY29tYmluZSB0aGUgcmVwb3J0cyB3aXRoIGBtdWx0aVFDYC4gRG8gdGhlIGZhc3RxIGZpbGVzIHNlZW0gdG8gaGF2ZSBjb25zaXN0ZW50bHkgaGlnaC1xdWFsaXR5Pwo8L2Rpdj4KCgojIyBTZWN0aW9uIDM6IEFsaWdubWVudAoKSW4gdGhpcyBzZWN0aW9uIHdlIG1hcCB0aGUgcmVhZHMgaW4gb3VyIEZBU1RRIGZpbGVzIHRvIGEgcmVmZXJlbmNlIGdlbm9tZS4gQXMKdGhlc2UgcmVhZHMgb3JpZ2luYXRlIGZyb20gbVJOQSwgd2UgZXhwZWN0IHNvbWUgb2YgdGhlbSB3aWxsIGNyb3NzIGV4b24vaW50cm9uCmJvdW5kYXJpZXMgd2hlbiB3ZSBhbGlnbiB0aGVtIHRvIHRoZSByZWZlcmVuY2UgZ2Vub21lLiBgSElTQVQyYCBpcyBhIHNwbGljZS1hd2FyZQptYXBwZXIgZm9yIFJOQS1zZXEgcmVhZHMgdGhhdCBpcyBiYXNlZCBvbiBCb3d0aWUuIEl0IHVzZXMgdGhlIG1hcHBpbmcgcmVzdWx0cwpmcm9tIEJvd3RpZSB0byBpZGVudGlmeSBzcGxpY2UganVuY3Rpb25zIGJldHdlZW4gZXhvbnMuIE1vcmUgaW5mb3JtYXRpb24gb24KSElTQVQyIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9jY2Iuamh1LmVkdS9zb2Z0d2FyZS9oaXNhdDIvaW5kZXguc2h0bWwpLgoKCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPgoKTWFwcGluZyAtPiBISVNBVDIKCjwvZGl2PgoKCgojIyMjIDEuICBNYXAvYWxpZ24gdGhlIHJlYWRzIHdpdGggSElTQVQyIHRvIHRoZSBtbTEwIHJlZmVyZW5jZSBnZW5vbWUKSW4gdGhlIGxlZnQgdG9vbCBwYW5lbCBtZW51LCB1bmRlciBOR1MgQW5hbHlzaXMsIHNlbGVjdAoqKk1hcHBpbmcgPiBISVNBVDIqKiBhbmQgc2V0IHRoZSBwYXJhbWV0ZXJzIGFzIGZvbGxvd3M6ICAKCi0gKipJcyB0aGlzIHNpbmdsZS1lbmQgb3IgcGFpcmVkLWVuZCBkYXRhPyoqIFNpbmdsZS1lbmQgKGFzIGluZGl2aWR1YWwgZGF0YXNldHMpICAKLSAqKkZBU1RRIGZpbGUqKiAgCihDbGljayBvbiB0aGUgbXVsdGlwbGUgZGF0YXNldHMgaWNvbiBhbmQgc2VsZWN0IGFsbCBmb3VyIG9mIHRoZQpGQVNUUSBmaWxlcykKICAgIC0gYFNSUjE1NTI0NDQuZmFzdHEuZ3pgCiAgICAtIGBTUlIxNTUyNDUwLmZhc3RxLmd6YAogICAgLSBgU1JSMTU1MjQ1Mi5mYXN0cS5nemAKICAgIC0gYFNSUjE1NTI0NTMuZmFzdHEuZ3pgCgotICoqU291cmNlIGZvciB0aGUgcmVmZXJlbmNlIGdlbm9tZSoqIFVzZQpidWlsdC1pbiBnZW5vbWUKLSAqKlNlbGVjdCBhIHJlZmVyZW5jZSBnZW5vbWU6KiogTW91c2UgKE11cyBNdXNjdWx1cyk6IG1tMTAKLSBVc2UgZGVmYXVsdHMgZm9yIHRoZSBvdGhlciBmaWVsZHMKLSBFeGVjdXRlCgoKTm90ZTogVGhpcyBtYXkgdGFrZSBhIGZldyBtaW51dGVzLCBkZXBlbmRpbmcgb24gaG93IGJ1c3kgdGhlIHNlcnZlciBpcy4KCgoKIyMjIyAyLiAgUmVuYW1lIHRoZSBvdXRwdXQgZmlsZXMKWW91IHNob3VsZCBoYXZlIDUgb3V0cHV0IGZpbGVzIGZvciBlYWNoIG9mIHRoZSBGQVNUUSBpbnB1dCBmaWxlczoKCmBISVNBVDIgb24gZGF0YS4uIGFsaWduZWQgcmVhZHMgKEJBTSlgCgpJdCB3aWxsIGJlIGhlbHBmdWwgdG8gcmVuYW1lIHRoZXNlIHRvIHNvbWV0aGluZyBzaG9ydGVyIGZvciB0aGUgbmV4dCBzdGVwcy4KCi0gYFNSUjE1NTI0NDQuYmFtYAotIGBTUlIxNTUyNDUwLmJhbWAKLSBgU1JSMTU1MjQ1Mi5iYW1gCi0gYFNSUjE1NTI0NTMuYmFtYAoKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+CgpJZiB0aGlzIHN0ZXAgaXMgdGFraW5nIHRvbyBsb25nLCB0aGVyZSBpcyBhbiBhbGlnbmVkIGJhbSBmaWxlIHByZXNlbnQgaW4gdGhlIGdvb2dsZSBkcml2ZSBsaW5rLiBZb3UgY2FuIHVzZSB0aGlzIGluIHRoZSBmb2xsb3dpbmcgc3RlcHMgb2YgdGhlIHR1dG9yaWFsLgoKPC9kaXY+Cgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4KCipTVEFSKiBpcyBhbHNvIGFub3RoZXIgcG9wdWxhciBvcHRpb24gZm9yIGFsaWduZWQgUk5BLXNlcSByZWFkcy4gV2Ugd29uJ3QgY292ZXIgdGhpcyB0b2RheSwgb3IgdGhlIHJlbGF0aXZlIG1lcml0cyBvZiBkaWZmZXJlbnQgbWV0aG9kcy4gSWYgeW91IHdhbnQgdG8gdHJ5IFNUQVIgaW4geW91ciBvd24gdGltZSB5b3UgY2FuIGZpbmQgaXQgdW5kZXIuCgoKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+CgpNYXBwaW5nIC0+IFJOQSBTVEFSCgo8L2Rpdj4KCiMjIEFib3V0IHRoZSBhbGlnbmVkIHJlYWQgZm9ybWF0CgpVbmxpa2UgbW9zdCBvZiBCaW9pbmZvbWF0aWNzLCBhICpzaW5nbGUgc3RhbmRhcmQqIGZpbGUgZm9ybWF0IGhhcyBlbWVyZ2VkIGZvciBhbGlnbmVkIHJlYWRzLiBNb3Jlb2V2ZXIsIHRoaXMgZmlsZSBmb3JtYXQgaXMgY29uc2lzdGVudCByZWdhcmRsZXNzIG9mIHdoZXRoZXIgeW91IGhhdmUgRE5BLXNlcSwgUk5BLXNlcSwgQ2hJUC1zZXEuLi4gZGF0YS4gCgoKVGhlIGZpcnN0IHBhcnQgb2YgdGhlIGhlYWRlciBsaXN0cyB0aGUgbmFtZXMgKGBTTmApIG9mIHRoZSBzZXF1ZW5jZXMgKGNocm9tb3NvbWVzKSB1c2VkIGluIGFsaWdubWVudCwgdGhlaXIgbGVuZ3RoIChgTE5gKS4gU29tZXRpbWVzLCAgYSAqbWQ1c3VtKiAiW2RpZ2l0YWwgZmluZ2VycHJpbnRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01kNXN1bSkiIG9mIHRoZSBgLmZhc3RhYCBmaWxlIHVzZWQgZm9yIGFsaWdubWVudCAoYE01YCkgaXMgc2hvd24uCgpgYGAKQEhEIFZOOjEuMCBTTzpjb29yZGluYXRlCkBTUSBTTjpjaHIxIExOOjE5NTQ3MTk3MQpAU1EgU046Y2hyMTAgTE46MTMwNjk0OTkzCkBTUSBTTjpjaHIxMSBMTjoxMjIwODI1NDMKLi4uLi4KLi4uLi4KCmBgYAoKSWYgbXV0bGlwbGUgc2FtcGxlcyB3ZXJlIHByZXNlbnQgaW4gdGhlIGZpbGUgKGkuZS4gdGhlIHNhbXBsZXMgaGF2ZSBiZWVuICptdWx0aXBsZXhlZCopLCAqcmVhZCBncm91cHMqIGNhbiBiZSB1c2VkIHRvIGlkZW50aWZ5IHdoaWNoIHNlcXVlbmNpbmcgbGlicmFyeSwgc2VxdWVuY2luZyBjZW50cmUsIExhbmUsIHNhbXBsZSBuYW1lIGV0Yy4KCigqKm5vdCBwcmVzZW50IGZvciB0aGUgZXhhbXBsZSBkYXRhIGluIHRoaXMgY291cnNlKiopCgpgYGAKQFJHCUlEOlNSUjA3Nzg1MAlDTjpiaQlMQjpTb2xleGEtNDIwNTcJUEw6aWxsdW1pbmEJUFU6SUxMVU1JTkEJU006TkEwNjk4NApAUkcJSUQ6U1JSMDgxNjc1CUNOOmJpCUxCOlNvbGV4YS00MjMxNglQTDppbGx1bWluYQlQVTpJTExVTUlOQQlTTTpOQTA2OTg0CkBSRwlJRDpTUlIwODA4MTgJQ046YmkJTEI6U29sZXhhLTQ0NzcwCVBMOmlsbHVtaW5hCVBVOklMTFVNSU5BCVNNOk5BMDY5ODQKQFJHCUlEOlNSUjA4NDgzOAlDTjpiaQlMQjpTb2xleGEtNDIzMTYJUEw6aWxsdW1pbmEJUFU6SUxMVU1JTkEJU006TkEwNjk4NApAUkcJSUQ6U1JSMDgxNzMwCUNOOmJpCUxCOlNvbGV4YS00MjMxNglQTDppbGx1bWluYQlQVTpJTExVTUlOQQlTTTpOQTA2OTg0Ci4uLi4uCi4uLi4uCgpgYGAKCkZpbmFsbHksIHdlIGhhdmUgYSBzZWN0aW9uIHdoZXJlIHdlIGNhbiByZWNvcmQgdGhlIHByb2Nlc3Npbmcgc3RlcHMgdXNlZCB0byBkZXJpdmUgdGhlIGZpbGUuIFRoaXMgaXMgCmBgYApAUEcgSUQ6aGlzYXQyIFBOOmhpc2F0MiBWTjoyLjEuMCBDTDoiL21udC9wdWxzYXIvZGVwZW5kZW5jaWVzL19jb25kYS9lbnZzL211bGxlZC12MS1lNzMyMWJhNDZmYTVlYTRjNmI5YTA2Yjc4ZTZjZDUxODJiMzNjMGE0N2MyYzg2YjVkNjEwZTEzNjFmOGIxNjg2L2Jpbi9oaXNhdDItYWxpZ24tcyAtLXdyYXBwZXIgYmFzaWMtMCAtcCA0IC14IC9jdm1mcy9kYXRhLmdhbGF4eXByb2plY3Qub3JnL21hbmFnZWQvaGlzYXQyX2luZGV4L21tMTAvbW0xMCAtVSAvdG1wLzE2MjgyLnVucCIKLi4uLgouLi4uCgpgYGAKCk5leHQgaXMgYSAqdGFiLWRlbGltaXRlZCogc2VjdGlvbiB0aGF0IGRlc2NyaWJlcyB0aGUgYWxpZ25tZW50IG9mIGVhY2ggc2VxdWVuY2UgaW4gZGV0YWlsLiAKCmBgYApTUlIxNTUyNDUwLjIyMDI4OQkwCWNocjEJMzIwMDgzOQk2MAkxMDBNCSoJMAkwCUdHQ1RDQUNDQUFHVEFUR0FUR0dUVFRDQVRBQ0NDQUdBQUFBQUNBVFRUR1RUQ1RUVFRHR0FUR0NDQVRUQUdUVENBR0NDQUdUR1RDQUFDQVRHQUNUQUdUR0dUVFRDQ0NBQUdDQUMJQ0NDRkZGRkRISEdESEdJSUpKSklIR0hHR0lHSElJSUdGSEdIQklJSElKQUdJSklKSkdHQ0hKSklHSUpKSkdIQ0FHR0hISUlDR0dISEhISEhGRkZGRkRDRTs/QUFDQ0RDREREQwlBUzppOjAgWE46aTowIFhNOmk6MCBYTzppOjAgWEc6aTowIE5NOmk6MCBNRDpaOjEwMCBZVDpaOlVVIE5IOmk6MQpTUlIxNTUyNDUwLjEzODc5NwkxNgljaHIxCTMyMDExMzIJNjAJMTAwTQkqCTAJMAlDQVRUVFRUQUFDQUdDQVRBVFRUR1RDVFRBR0NUVFRBQUFUQ0NBR0FHVEFDVEdUVFRHR0NUVENBQUFHQUFHQVRBR1RDQVRDVENUR0dUVENUQ1RUQUNUR0FHQUFUQUdBQUFHVENUCURERUVFRUVFRUZGRkZGRkZISEhISElJR0NIR0VKSkpKSkpKSkpKSUpKSkpKSkpKSkpKSklKSUpKSkpKSkpKSkpKSklHSkpKSkpJSkpKSkpKSklISkpKSkhISEhIRkZGRkZDQ0MJQVM6aTowIFhOOmk6MCBYTTppOjAgWE86aTowIFhHOmk6MCBOTTppOjAgTUQ6WjoxMDAgWVQ6WjpVVSBOSDppOjEKCmBgYAoKVGhlIGZpcnN0IDExIGNvbHVtbnMgb2YgZWFjaCBsaW5lIGhhdmUgYW4gb2ZmaWNpYWwgc3BlY2lmaWNhdGlvbgoKQ29sdW1uIHwgT2ZmaWNpYWwgTmFtZSB8IEJyaWVmCi0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0KMSAgICAgIHwgUU5BTUUgICAgICAgICAgfCBTZXF1ZW5jZSBJRAoyICAgICAgfCBGTEFHICAgICAgICAgICB8IFNlcXVlbmNlIHF1YWxpdHkgZXhwcmVzc2VkIGFzIGEgYml0d2lzZSBmbGFnCjMgICAgICB8IFJOQU1FICAgICAgICAgIHwgQ2hyb21vc29tZQo0ICAgICAgfCBQT1MgICAgICAgICAgICB8IFN0YXJ0IFBvc2l0aW9uCjUgICAgICB8IE1BUFEgICAgICAgICAgIHwgTWFwcGluZyBRdWFsaXR5CjYgICAgICB8IENJR0FSICAgICAgICAgIHwgRGVzY3JpYmVzIHBvc2l0aW9ucyBvZiBtYXRjaGVzLCBpbnNlcnRpb25zLCBkZWxldGlvbnMgdy5yLnQgcmVmZXJlbmNlCjcgICAgICB8IFJORVhUICAgICAgICAgIHwgUmVmLiBuYW1lIG9mIG1hdGUgLyBuZXh0IHJlYWQKOCAgICAgIHwgUE5FWFQgICAgICAgICAgfCBQb3N0aW9uIG9mIG1hdGUgLyBuZXh0IHJlYWQKOSAgICAgIHwgVExFTiAgICAgICAgICAgfCBPYnNlcnZlZCBUZW1wbGF0ZSBsZW5ndGgKMTAgICAgIHwgU0VRICAgICAgICAgICAgfCBTZXF1ZW5jZQoxMSAgICAgfCBRVUFMICAgICAgICAgICB8IEJhc2UgUXVhbGl0aWVzCgpUaGVyZSBjYW4gYWxzbyBiZSBhbGwgbWFubmVyIG9mIG9wdGlvbmFsIHRhZ3MgYXMgZXh0cmEgY29sdW1ucyBpbnRyb2R1Y2UgYnkgYW4gYWxpZ25lciBvciBkb3duc3RyZWFtIGFuYWx5c2lzIHRvb2wuIEEgY29tbW9uIHVzZSBpcyB0aGUgYFJHYCB0YWcgd2hpY2ggcmVmZXJzIGJhY2sgdG8gdGhlIHJlYWQgZ3JvdXBzIGluIHRoZSBoZWFkZXIuCgoKIyMjIFF1YWxpdHkgQ29udHJvbCBGbGFncwoKVGhlICoiZmxhZ3MiKiBpbiB0aGUgc2FtIGZpbGUgY2FuIHJlcHJlc2VudCB1c2VmdWwgUUMgaW5mb3JtYXRpb24KCiAgKyBSZWFkIGlzIHVubWFwcGVkCiAgKyBSZWFkIGlzIHBhaXJlZCAvIHVucGFpcmVkCiAgKyBSZWFkIGZhaWxlZCBRQwogICsgUmVhZCBpcyBhIFBDUiBkdXBsaWNhdGUgKHNlZSBsYXRlcikKClRoZSBjb21iaW5hdGlvbiBvZiBhbnkgb2YgdGhlc2UgcHJvcGVydGllcyBpcyB1c2VkIHRvIGRlcml2ZSBhIG51bWVyaWMgdmFsdWUuIEZvciBpbnN0YW5jZSwgYSBwYXJ0aWN1bGFyIHJlYWQgbWlnaHQgaGF2ZSBhIGZsYWcgb2YgMTYzCgojIyMgRGVyaXZhdGlvbgoKVGhlcmUgaXMgYSBzZXQgb2YgcHJvcGVydGllcyB0aGF0IGEgcmVhZCBjYW4gcG9zc2Vzcy4gSWYgYSBwYXJ0aWN1bGFyIHByb3BlcnR5IGlzIG9ic2VydmVkLCBhIGNvcnJlc3BvbmRpbmcgcG93ZXIgb2YgMiBpcyBhZGRlZCBtdWx0aXBsaWVkIGJ5IDEuIFRoZSBmaW5hbCB2YWx1ZSBpcyBkZXJpdmVkIGJ5IHN1bW1pbmcgYWxsIHRoZSBwb3dlcnMgb2YgMi4KCgpgYGAKIAlSZWFkSGFzUHJvcGVydHkgCUJpbmFyeSAJTXVsdGlwbHlCeQppc1BhaXJlZCAJVFJVRSAJMSAJMQppc1Byb3BlclBhaXIgCVRSVUUgCTEgCTIKaXNVbm1hcHBlZFF1ZXJ5IAlGQUxTRSAJMCAJNApoYXNVbm1hcHBlZE1hdGUgCUZBTFNFIAkwIAk4CmlzTWludXNTdHJhbmQgCUZBTFNFIAkwIAkxNgppc01hdGVNaW51c1N0cmFuZCAJVFJVRSAJMSAJMzIKaXNGaXJzdE1hdGVSZWFkIAlGQUxTRSAJMCAJNjQKaXNTZWNvbmRNYXRlUmVhZCAJVFJVRSAJMSAJMTI4CmlzU2Vjb25kYXJ5QWxpZ25tZW50IAlGQUxTRSAJMCAJMjU2CmlzTm90UGFzc2luZ1F1YWxpdHlDb250cm9scyAJRkFMU0UgCTAgCTUxMgppc0R1cGxpY2F0ZSAJRkFMU0UgCTAgCTEwMjQKCmBgYApWYWx1ZSBvZiBmbGFnIGlzIGdpdmVuIGJ5IApgYGAKMXgxICsgMXgyICsgMHg0ICsgMHg4ICsgMHgxNiArIDF4MzIgKyAweDY0ICsgMXgxMjggKyAweDI1NiArIDB4NTEyICsgMHgxMDI0ID0gMTYzCmBgYAoKU2VlIGFsc28KCi0gaHR0cHM6Ly9icm9hZGluc3RpdHV0ZS5naXRodWIuaW8vcGljYXJkL2V4cGxhaW4tZmxhZ3MuaHRtbAoKIyMjIEhhdmUgYSBDSUdBUiEKCgpUaGUgKioqQ0lHQVIqKiogKCoqQyoqb21wYWN0ICoqSSoqZGlvc3luY3JhdGljICoqRyoqYXBwZWQgKipBbGlnbm1lbnQqKiAqKlIqKmVwb3J0KSBzdHJpbmcgaXMgYSB3YXkgb2YgZW5jb2RpbmcgdGhlIG1hdGNoIGJldHdlZW4gYSBnaXZlbiBzZXF1ZW5jZSBhbmQgdGhlIHBvc2l0aW9uIGl0IGhhcyBiZWVuIGFzc2lnbmVkIGluIHRoZSBnZW5vbWUuIEl0IGlzIGNvbXByaXNlZCBieSBhIHNlcmllcyBvZiBsZXR0ZXJzIGFuZCBudW1iZXJzIHRvIGluZGljYXRlIGhvdyBtYW55IGNvbnNlY3V0aXZlIGJhc2VzIGhhdmUgdGhhdCBtYXBwaW5nLgoKCiAKIENvZGUgIHwgRGVzY3JpcHRpb24KLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0KTSAgfCBhbGlnbm1lbnQgbWF0Y2gKSSAgfCBpbnNlcnRpb24KRCAgfCBkZWxldGlvbgpOICB8IHNraXBwZWQKUyAgfCBzb2Z0LWNsaXBwaW5nCkggIHwgaGFyZC1jbGlwcGluZwoKCmUuZy4KCi0gYDEwMU1gCiAgICArIDEwMSBiYXNlcyBtYXRjaGluZyB0aGUgcmVmZXJlbmNlCi0gYDFTMTAwTWAKICAgICsgMSBzb2Z0LWNsaXBwZWQgcmVhZCBmb2xsb3dlZCBieSAxMDAgbWF0Y2hlcwotIGAxNU04N043ME05ME4xNk1gCiAgICArIDE1IG1hdGNoZXMgZm9sbG93aW5nIGJ5IDg3IGJhc2VzIHNraXBwZWQgZm9sbG93ZWQgYnkgNzAgbWF0Y2hlcyBldGMuCgojIyMgYHNhbWAgb3IgYGJhbT9gCgpBbGlnbm1lbnQgYWxnb3JpdGhtcyBzdWNoIGFzIGBISVNBVDJgIHRlbmQgdG8gcHJvZHVjZSBhIGBzYW1gIGZpbGUgYXMgdGhlaXIgcmF3IG91dHB1dCwgd2hlcmVhcyB3ZSB1c3VhbGx5IGFuYWx5c2UgYSBgLmJhbWAgZmlsZS4gVGhlIGNvbnRlbnRzIG9mIGJvdGggZmlsZXMgYXJlICpleGFjdGx5IHRoZSBzYW1lKi4gV2hlcmVhcyBhIGBzYW1gIGZpbGUgaXMgZGVzaWduZWQgdG8gYmUgKmh1bWFuLXJlYWRhYmxlKiwgYSBgYmFtYCBmaWxlIGNhbiBiZSBwcm9jZXNzZWQgKm1vcmUgZWZmaWNpZW50bHkgYnkgYSBjb21wdXRlciogYXMgaXQgaXMgY29tcHJlc3NlZCBhbmQgaW5kZXhlZC4gCgpUaGUgcmVhZHMgaW4gYSBgc2FtYCBmaWxlIHRlbmQgdG8gYmUgYXJyYW5nZWQgaW4gdGhlIG9yZGVyIHRoYXQgdGhleSB3ZXJlIGdlbmVyYXRlZCBieSB0aGUgc2VxdWVuY2VyLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlIGBiYW1gIGZpbGUgdGhhdCB5b3Ugc2VlIGluIEdhbGF4eSBoYXMgYmVlbiBzb3J0ZWQgYWNjb3JkaW5nIHRvIHRoZSBwb3NpdGlvbiB0aGF0IHRoZSByZWFkcyBtYXAuIElmIHlvdSBydW4geW91ciBvd24gYWxpZ25tZW50cyB1c2luZyBjb21tYW5kIGxpbmUgc29mdHdhcmUsIHlvdSB3aWxsIG5lZWQgdG8gdXNlIGEgdG9vbCB0byAqc29ydCBhbmQgaW5kZXgqIHRoZSBkYXRhIGJlZm9yZSBhbmFseXNpcy4KCi0tLS0tCgojIyBRdWFsaXR5IGFzc2Vzc21lbnQgb2YgdGhlIGFsaWduZWQgcmVhZHMKCipzYW10b29scyogd2lsbCBjYWxjdWxhdGUgUUMgc3RhdGlzdGljcyBmb3IgYSBzZXQgb2YgYWxpZ25lZCByZWFkcyBpbiAqYmFtKiBmb3JtYXQKCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPgoqU0FNL0JBTSAtPiBTYW10b29scyBzdGF0cyoKPC9kaXY+CgpJZiB5b3UgdmlldyB0aGUgb3V0cHV0IHlvdSB3aWxsIHNlZSB0aGF0IGl0IGlzIG5vdCB2ZXJ5IGVhc3kgdG8gaW50ZXJwcmV0LiAKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+CipGQVNUUSBRdWFsaXR5IENvbnRyb2wqIC0+ICpNdWx0aXFjKgoKbWFrZSBzdXJlICoqV2hpY2ggdG9vbCB3YXMgdXNlZCB0byBnZW5lcmF0ZSBsb2dzKiogaXMgc2V0IHRvICoqU2FtdG9vbHMqKiBhbmQgc2VsZWN0IHRoZSBTYW10b29scyBzdGF0cy4uLi4gZmlsZXMgdGhhdCB3ZXJlIHByb2R1Y2VkIGluIHRoZSBwcmV2aW91cyBzdGVwCjwvZGl2PgoKCiMjIFNlY3Rpb24gNC4gIFZpc3VhbGlzZSB0aGUgYWxpZ25lZCByZWFkcyB3aXRoIElHVgoKRG93bmxvYWQgdGhlIGJhbSBmaWxlcyB5b3UgaGF2ZSBjcmVhdGVkIGluIHRoZSBwcmV2aW91cyBzdGVwIGJ5IGNsaWNraW5nIHRoZSBkaXNrIGljb24gb24gdGhlIHJpZ2h0LWhhbmQgcGFuZWwuIE1ha2Ugc3VyZSB0byBjbGljayBib3RoIHRoZSAqKkRvd25sb2FkIGRhdGFzZXQqKiBhbmQgKipEb3dubG9hZCBpbmRleCoqIGJ1dHRvbnMuIFdlIHdpbGwgbm93IHZpc3VhbGlzZSB0aGUgYWxpZ25tZW50cyB1c2luZyB0aGUgSW50ZWdyYXRpdmUgR2Vub21pY3MgVmlld2VyIChJR1YpLgoKPGltZyBzcmM9Im1lZGlhL2Rvd25sb2FkX2JhbS5wbmciPgoKCiMjIyBJbnRyb2R1Y2luZyB0aGUgSUdWIEJyb3dzZXIKCiFbXShtZWRpYS9pZ3YucG5nKQoKV2hpbHN0IHRvb2xzIGxpa2UgUiBhcmUgdmVyeSBwb3dlcmZ1bCBhbmQgYWxsb3cgeW91IHRvIHBlcmZvcm0gc3RhdGlzdGljYWwgYW5hbHlzZXMgYW5kIHRlc3QgaHlwb3RoZXNlcywgdGhlcmUgaXMgbm8gc3Vic3RpdHV0ZSBmb3IgKioqbG9va2luZyBhdCB0aGUgZGF0YSoqKi4gQSB0cmFpbmVkLWV5ZSBjYW4gcXVpdGUgcXVpY2tseSBnZXQgYSBzZW5zZSBvZiB0aGUgZGF0YSBxdWFsaXR5IGJlZm9yZSBhbnkgY29tcHV0YXRpb25hbCBhbmFseXNlcyBoYXZlIGJlZW4gcnVuLiBGdXRoZXJtb3JlLCBhcyB0aGUgcGVyc29uIHJlcXVlc3RpbmcgdGhlIHNlcXVlbmNpbmcsIHlvdSBwcm9iYWJseSBrbm93IGEgbG90IGFib3V0IHRoZSBiaW9sb2dpY2FsIGNvbnRleHQgb2YgdGhlIHNhbXBsZXMgYW5kIHdoYXQgdG8gZXhwZWN0LiAKCi0gSUdWIGhhcyBiZWVuIGRldmVsb3BlZCBieSB0aGUgQnJvYWQgSW5zdGl0dXRlIGFuZCBpcyBhYmxlIHRvIGRpc3BsYXkgbW9zdCBraW5kcyBvZiBnZW5vbWljIGRhdGEKICAgICsgZXhwcmVzc2lvbgogICAgKyBDaElQCiAgICArIHdob2xlLWdlbm9tZSByZXNlcXVlbmNpbmcKICAgICsgc2hSTkEKLSBJdCBpcyBhICpKYXZhKiBkZXNrdG9wIGFwcGxpY2F0aW9uIGFuZCBjYW4gYmUgcnVuIGVpdGhlciBsb2NhbGx5IG9mIGZyb20gdGhlIEJyb2FkIHdlYnNpdGUKLSBUbyBydW4gSUdWIHlvdXJzZWxmIHlvdSB3aWxsIG5lZWQgdG8gYWdyZWUgdG8gdGhlIGxpY2Vuc2UgYW5kIFtkb3dubG9hZCB0aGUgdmVyc2lvbiBmb3IgeW91ciBPU10oaHR0cDovL3d3dy5icm9hZGluc3RpdHV0ZS5vcmcvc29mdHdhcmUvaWd2L2Rvd25sb2FkKQoKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+CklmIHlvdSBoYXZlIHByb2JsZW1zIHJ1bm5pbmcgSUdWLCB5b3UgbWF5IG5lZWQgdG8gZG93bmxvYWQgYW4gdXBkYXRlZCB2ZXJzaW9uIG9mIEphdmEKCmh0dHBzOi8vamF2YS5jb20vZG93bmxvYWQKCjwvZGl2PgoKIyMjIEEgcXVpY2sgdG91ciBvZiBJR1YKRm9yIG1vcmUgZGV0YWlscwoKLSBGdWxsIHNldCBvZiBzbGlkZXMgZnJvbSBbTVJDIENsaW5pY2FsIFNjaWVuY2VzIENlbnRyZV0oaHR0cDovL21yY2NzYy5naXRodWIuaW8vSUdWX2NvdXJzZS9pZ3YuaHRtbCMvKQotIElHViB0dXRvcmlhbCBmcm9tIHRoZSBbR3JpZmZ0aCBsYWIgLSBXYXNoVV0oaHR0cHM6Ly9naXRodWIuY29tL2dyaWZmaXRobGFiL3JuYXNlcV90dXRvcmlhbC93aWtpL0lHVi1UdXRvcmlhbCkKCiFbXShtZWRpYS9JR1YyLnBuZykKCjEpIFNhbXBsZSBpbmZvcm1hdGlvbiBwYW5lbAogICAgLSBJbmZvcm1hdGlvbiBhYm91dCBzYW1wbGVzIHlvdSBoYXZlIGxvYWRlZAogICAgLSBlLmcuIFNhbXBsZSBJRCwgR2VuZGVyLCBBZ2UsIFR1bW91ciAvIE5vcm1hbAogICAgCjIpIEdlbm9tZSBOYXZpZ2F0aW9uIHBhbmVsCiAgICAtIEp1bXAgdG8gYSBnZW5vbWljIHJlZ2lvbiBpbiBgQ2hyOlN0YXJ0LUVuZGAgZm9ybWF0CiAgICAtIEp1bXAgdG8gYSBnZW5lIHN5bWJvbCBvZiBpbnRlcmVzdAogICAgCjMpIERhdGEgcGFuZWwKICAgIC0gWW91ciBzZXF1ZW5jaW5nIHJlYWRzIHdpbGwgYmUgZGlzcGxheWVkIGhlcmUKICAgIC0gT3Igd2hhdGV2ZXIgZGF0YSB5b3UgaGF2ZSBsb2FkZWQKICAgICAgICArIHNlZSBpbmZvcm1hdGlvbiBvbiBbYWNjZXB0ZWQgZmlsZSBmb3JtYXRzXShodHRwOi8vd3d3LmJyb2FkaW5zdGl0dXRlLm9yZy9zb2Z0d2FyZS9pZ3YvUmVjb21tZW5kZWRGaWxlRm9ybWF0cykKCjQpIEF0dHJpYnV0ZSBwYW5lbAogICAgLSBHZW5lIGxvY2F0aW9ucwogICAgLSBHZW5vbWUgc2VxdWVuY2UgKGlmIHpvb21lZC1pbiBhdCBhcHByb3ByaWF0ZSBsZXZlbCkKICAgIC0gUHJvdGVpbnMKICAgIAojIyMgRXhhbXBsZQoKR28gdG8gKioqRmlsZSoqKiAtPiAqKipMb2FkIGZyb20gZmlsZSoqKiBhbmQgc2VsZWN0IHRoZSBhbGlnbmVkIGBiYW1gIGZpbGVzIGZyb20gYEhJU0FUMmAuIE5vdGUgdGhhdCB0aGUgaW5kZXggZmlsZXMgYC5iYWlgIG5lZWQgdG8gYmUgcHJlc2VudCBpbiB0aGUgc2FtZSBkaXJlY3RvcnkuIEhvd2V2ZXIsIHlvdSBvbmx5IG5lZWQgdG8gY2xpY2sgb24gdGhlIGAuYmFtYAoKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+Ck1ha2Ugc3VyZSB0aGF0IHRoZSBnZW5vbWUgc2VsZWN0ZWQgaXMgYG1tMTBgLiBUaGUgZGVmYXVsdCB3aWwgYmUgaHVtYW4gaGcxOQo8L2Rpdj4KCi0gVGhlIGJsYWNrIGRvdHRlZCB2ZXJ0aWNhbCBsaW5lcyBpbmRpY2F0ZXMgdGhlIGNlbnRyZSBvZiB0aGUgdmlldwotIEVhY2ggb2YgdGhlIGdyZXkgcG9pbnRlZCByZWN0YW5nbGVzIHJlcHJlc2VudHMgYSBzZXF1ZW5jaW5nIHJlYWRzCiAgICArIHdoZXRoZXIgdGhlIHBvaW50ZWQgYml0IGlzIG9uIHRoZSBsZWZ0IG9yIHJpZ2h0IGluZGljYXRlcyBpZiB0aGUgcmVhZCBpcyBmb3J3YXJkIG9yIHJldmVyc2UuCi0gQSBjb3ZlcmFnZSB0cmFjayBpcyBhbHNvIGdlbmVyYXRlZAotIFlvdSBzaG91bGQgc2VlIHRoZSByZWFkIHRoYXQgd2UgZGVzY3JpYmVkIGluIGRldGFpbCBpbiB0aGUgcHJldmlvdXMgc2VjdGlvbiBieSAqaG92ZXIqaW5nIG92ZXIgdGhlIHJlYWRzIHRvIGRpc3BsYXkgdGhlIGluZm9ybWF0aW9uIGZyb20gdGhlIGAuYmFtYCBmaWxlCgpUaGUgdmlldyBpbiBJR1YgaXMgbm90IHN0YXRpYyBhbmQgd2UgY2FuIHNjcm9sbC1hbG9uZyB0aGUgZ2Vub21lIGJ5IGhvbGRpbmctZG93biB0aGUgbGVmdCBtb3VzZSBpbiB0aGUgZGF0YSBwYW5lbCBhbmQgZHJhZ2dpbmcgbGVmdCBhbmQgcmlnaHQKCkl0J3Mgd29ydGggbm90aW5nIHRoYXQgdGhlIGRpc3BsYXkgc2V0dGluZ3MgbWF5IGJlIHNob3dpbmcgZmV3ZXIgcmVhZHMgdGhhbiB5b3UgaGF2ZSAoKmRvd25zYW1wbGluZyopIGluIG9yZGVyIHRvIGNvbnNlcnZlIG1lbW9yeS4gQWxzbywgc29tZSBRQy1mYWlsIG9yIFBDUiBkdXBsaWNhdGVzIG1heSBiZSBmaWx0ZXJlZC4KCldlIGFsc28gaGF2ZSBzb21lIG9wdGlvbnMgb24gaG93IHRvIGRpc3BsYXkgdGhlIHJlYWRzIHRoZW1zZWx2ZXMsIHdoaWNoIHdlIGNhbiBhY2NjZXNzIGJ5IHJpZ2h0LWNsaWNraW5nIG9uIHRoZSBiYW0gdHJhY2sKClNvcnRpbmcgYWxpZ25tZW50cyBieTotCgogIC0gc3RhcnQKICAtIHN0cmFuZAogIC0gYmFzZQogIC0gbWFwcGluZyBxdWFsaXR5CiAgLSBpbnNlcnQgc2l6ZQogIApUaGUgcmVhZHMgdGhlbXNlbHZlcyBjYW4gYWxzbyBiZSBjb2xvdXJlZCBhY2NvcmRpbmcgdG8KCiAgLSBpbnNlcnQgc2l6ZQogIC0gcmVhZCBzdHJhbmQKICAtIHNhbXBsZQoKCiMjIFNlY3Rpb24gNS4gUXVhbnRpZmljYXRpb24gKENvdW50aW5nIHJlYWRzIGluIGZlYXR1cmVzKQoKSW4gb3JkZXIgdG8gdGVzdCBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24sIHdlIG5lZWQgdG8gY291bnQgdXAgaG93IG1hbnkgdGltZXMgZWFjaCAiZmVhdHVyZSIgaXMgb2JzZXJ2ZWQgaXMgZWFjaCBzYW1wbGUuIFRoZSBnb2FsIG9mIHN1Y2ggb3BlcmF0aW9ucyBpcyB0byBwcm9kdWNlIGEgKmNvdW50IHRhYmxlKiBzdWNoIGFzIHRoYXQgc2hvd24gYmVsb3cuIFdlIGNhbiB0aGVuIGFwcGx5IHN0YXRpc3RpY2FsIHRlc3RzIHRvIHRoZXNlIGRhdGEKCiFbXShtZWRpYS9jb3VudHMucG5nKQoKSFRTZXEtY291bnQgY3JlYXRlcyBhIGNvdW50IG1hdHJpeCB1c2luZyB0aGUgbnVtYmVyIG9mIHRoZSByZWFkcyBmcm9tIGVhY2ggYmFtCmZpbGUgdGhhdCBtYXAgdG8gdGhlIGdlbm9taWMgZmVhdHVyZXMuIEZvciBlYWNoIGZlYXR1cmUgKGEKZ2VuZSBmb3IgZXhhbXBsZSkgYSBjb3VudCBtYXRyaXggc2hvd3MgaG93IG1hbnkgcmVhZHMgd2VyZSBtYXBwZWQgdG8gdGhpcwpmZWF0dXJlLgoKVmFyaW91cyBydWxlcyBjYW4gYmUgdXNlZCB0byBhc3NpZ24gY291bnRzIHRvIGZlYXR1cmVzCgohW10obWVkaWEvaHRzZXEucG5nKQoKVG8gb2J0YWluIHRoZSBjb29yZGluYXRlcyBvZiBlYWNoIGdlbmUsIHdlIGNhbiB1c2UgdGhlIFVDU0MgZ2Vub21lIGJyb3dzZXIgd2hpY2ggaXMgaW50ZWdyYXRlZCBpbnRvIEdhbGF4eS4KCiMjIyBPYnRhaW5pbmcgZ2VuZSBjb29yZGluYXRlcwoKCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4KCioqR2V0IERhdGEqKiAtPiAqKlVDU0MgTWFpbioqIHRhYmxlIGJyb3dzZXIKCjwvZGl2PgoKCiFbXShtZWRpYS91Y3NjX2Jyb3dzZXIucG5nKQoKU2VsZWN0aW5nIHRoZSAqKlVDU0MgTWFpbioqIHRvb2wgZnJvbSBHYWxheHkgd2lsbCB0YWtlIHlvdSB0byB0aGUgVUNTQyB0YWJsZSBicm93c2VyLiBGcm9tIGhlcmUgd2UgY2FuIGV4dHJhY3QgZ2VuZSBjb29yZGluYXRlcyBmb3Igb3VyIGdlbm9tZSBvZiBpbnRlcmVzdCAoYHNhY0NlcjNgKSBpbiBgZ3RmYCBmb3JtYXQgZm9yIHByb2Nlc3Npbmcgd2l0aCBnYWxheHkuCgotIFNldCAqY2xhZGUqIHRvICoqTWFtbWFsKioKLSBTZXQgKmdlbm9tZSogdG8gKipNb3VzZSoqCi0gKmFzc2VtYmx5KiAqKkRlYy4yMDExIChHUkNtMzgvbW0xMCkqKgotICpncm91cCogKipHZW5lcyBhbmQgR2VuZSBQcmVkaWN0aW9uKioKLSAqdHJhY2sqICoqTkNCSSBSZWZTZXEqKgotICpyZWdpb24qICoqZ2Vub21lKioKLSAqb3V0cHV0IGZvcm1hdCogKipHVEYgLSBnZW5lIHRyYW5zZmVyIGZvcm1hdCAobGltaXRlZCkqKiBhbmQgKnNlbmQgb3V0cHV0IHRvKiAqKkdhbGF4eSoqCgpDbGljayAqZ2V0IG91dHB1dCogYW5kICpzZW5kIHF1ZXJ5IHRvIEdhbGF4eSogdG8gYmUgcmV0dXJuZWQgdG8gR2FsYXh5LiBBIG5ldyBqb2Igd2lsbCBiZSBzdWJtaXR0ZWQgdG8gcmV0cmlldmUgdGhlIGNvb3JkaW5hdGVzIGZyb20gVUNTQwoKCgo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4KKipSTkEgQW5hbHlzaXMgPiBodHNlcS1jb3VudCoqCjwvZGl2PgoKMS4gIFVzZSBIVFNlcS1jb3VudCB0byBjb3VudCB0aGUgbnVtYmVyIG9mIHJlYWRzIGZvciBlYWNoIGZlYXR1cmUuICAKICAgIEluIHRoZSBsZWZ0IHRvb2wgcGFuZWwgbWVudSwgdW5kZXIgTkdTIEFuYWx5c2lzLCBzZWxlY3QKICAgICoqTkdTIEFuYWx5c2lzID4gaHRzZXEtY291bnQqKiBhbmQgc2V0IHRoZSBwYXJhbWV0ZXJzIGFzIGZvbGxvd3M6ICAKICAgIC0gKipBbGlnbmVkIFNBTS9CQU0gZmlsZSoqICAKICAgICAgKFNlbGVjdCBvbmUgb2YgZm91ciBiYW0gZmlsZXMsIG9yIGFsbCBmb3VyIHVzaW5nIHRoZSBtdWx0aXBsZSBkYXRhc2V0cyBvcHRpb24pCiAgICAtICoqR0ZGIGZpbGUqKiBVQ1NDIE1haW4gb24gTW91c2U6bmNiaVJlZlNlcSAoZ2Vub21lKQogICAgLSBVc2UgZGVmYXVsdHMgZm9yIHRoZSBvdGhlciBmaWVsZHMKICAgIC0gRXhlY3V0ZQoyLiAgUmVwZWF0IGZvciB0aGUgcmVtYWluaW5nIGJhbSBmaWxlcyBpZiBydW5uaW5nIG9uIGVhY2ggYmFtIHNlcGFyYXRlbHkuCjMuICBSZW5hbWUgdGhlIGh0LXNlcSBvdXRwdXQgZm9yIGVhY2ggc2FtcGxlLiAqKkRvIG5vdCByZW5hbWUgdGhlIG91dHB1dHMgdGhhdCBoYXZlICIobm8gZmVhdHVyZSkiIGluIHRoZWlyIG5hbWUqKgoKIyMgRnVydGhlciBRQyBvbiB0aGUgYWxpZ25lZCByZWFkcwoKQWRkaXRpb25hbCBRQyBvZiB0aGUgYWxpZ25lZCByZWFkcyBjYW4gYmUgb2J0YWluZWQgd2l0aCB0aGUgUXVhbGltYXAgdG9vbC4gVGhpcyBhbHNvIHVzZXMgaW5mb3JtYXRpb24gZnJvbSB0aGUgZ2Vub21lIHRyYW5zY3JpcHQgZmlsZSB0byBjYWxjdWxhdGUgaG93IG1hbnkgcmVhZHMgYXJlIGNvdW50ZWQgaW4gZXhvbmljLCBpbnRyb25pYyBhbmQgaW50ZXJnZW5pYyByZWdpb25zLiBGb3IgUk5BLXNlcSB0aGlzIHBlcmNlbnRhZ2Ugc2hvdWxkIGJlICpoaWdoKjsgYXQgbGVhc3QgODAgdG8gOTAlLgoKPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtaW5mbyI+CioqUk5BLVNlcSA+IFF1YWxpbWFwIFJOQS1TZXEgUUMqKgo8L2Rpdj4KCiMjIyBDcmVhdGUgYSBjb3VudCBtYXRyaXgKClRoZSBodHNlcSB0b29sIGlzIGRlc2lnbmVkIHRvIHByb2R1Y2UgYSBzZXBhcmF0ZSB0YWJsZSBvZiBjb3VudHMgZm9yIGVhY2ggc2FtcGxlLiBUaGlzIGlzIG5vdCBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBvdGhlciB0b29scyBzdWNoIGFzIERlZ3VzdCAoc2VlIG5leHQgc2VjdGlvbikgd2hpY2ggcmVxdWlyZSB0aGUgY291bnRzIHRvIGJlIHByZXNlbnRlZCBpbiBhIGRhdGEgbWF0cml4IHdoZXJlIGVhY2ggcm93IGlzIGEgZ2VuZSBhbmQgZWFjaCBjb2x1bW4gaXMgYSBwYXJ0aWN1bGFyIHNhbXBsZSBpbiB0aGUgZGF0YXNldC4KCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPgoqQ29sbGVjdGlvbiBPcGVyYXRpb25zIC0+IENvbHVtbiBKb2luKiBvbiBDb2xsZWN0aW9ucwo8L2Rpdj4KCi0gSW4gdGhlICpUYWJ1bGFyIEZpbGVzKiBzZWN0aW9uLCBzZWxlY3QgdGhlIGBodC1zZXFgIGNvdW50IGZpbGVzIGZyb20geW91ciBoaXN0b3J5ICpTUlIxNTUyNDQ0Lmh0c2VxKiwgKlNSUjE1NTI0NTAqLCBldGMuLi4gSG9sZGluZyB0aGUgQ1RSTCBrZXkgYWxsb3dzIG11bHRpcGxlIGZpbGVzIHRvIGJlIHNlbGVjdGVkCi0gS2VlcCAqSWRlbnRpZmllciBjb2x1bW4qIGFzIGAxYAoKVGhlIG91dHB1dCBzaG91bGQgbG9vayBzb21ldGhpbmcgbGlrZSB0aGlzLi4uCiFbXShtZWRpYS9jb3VudF9tYXRyaXgucG5nKQoKLSBEb3dubG9hZCB0byB5b3VyIGNvbXB1dGVyCgoKKipZb3UgYXJlIG5vdyByZWFkeSB0byBmb2xsb3cgdGhlIG5leHQgdHV0b3JpYWwgb24gW0RpZmZlcmVudGlhbCBFeHByZXNzaW9uXSgwMi1kaWZmZXJlbnRpYWwtZXhwcmVzc2lvbi5uYi5odG1sKSoqCgoKCiMjIFJlZmVyZW5jZXMKClsxXSBOb29rYWV3IEksIFBhcGluaSBNLCBQb3JucHV0dHBvbmcgTiwgU2NhbGNpbmF0aSBHLCBGYWdlcmJlcmcgTCwgVWhsw6luIE0sIE5pZWxzZW4gSjogQSBjb21wcmVoZW5zaXZlIGNvbXBhcmlzb24gb2YgUk5BLVNlcS1iYXNlZCB0cmFuc2NyaXB0b21lIGFuYWx5c2lzIGZyb20gcmVhZHMgdG8gZGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBhbmQgY3Jvc3MtY29tcGFyaXNvbiB3aXRoIG1pY3JvYXJyYXlzOiBhIGNhc2Ugc3R1ZHkgaW4gU2FjY2hhcm9teWNlcyBjZXJldmlzaWFlLiBOdWNsZWljIEFjaWRzIFJlcyAyMDEyLCA0MCAoMjApOjEwMDg0IOKAkyAxMDA5Ny4gZG9pOjEwLjEwOTMvbmFyL2drczgwNC4gRXB1YiAyMDEyIFNlcCAxMAoKWzJdIEd1aXJndWlzIEEsIFNsYXBlIEMsIEZhaWxsYSBMLCBTYXcgSiwgVHJlbWJsYXkgQywgUG93ZWxsIEQsIFJvc3NlbGxvIEYsIFdlaSBBLCBTdHJhc3NlciBBLCBDdXJ0aXMgRDogUFVNQSBwcm9tb3RlcyBhcG9wdG9zaXMgb2YgaGVtYXRvcG9pZXRpYyBwcm9nZW5pdG9ycyBkcml2aW5nIGxldWtlbWljIHByb2dyZXNzaW9uIGluIGEgbW91c2UgbW9kZWwgb2YgbXllbG9keXNwbGFzaWEuIENlbGwgRGVhdGggRGlmZmVyLiAyMDE2IEp1bjsyMyg2KQo=