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
The Degust part of this session is based on the tutorial Differential gene expression using Galaxy and Degust from Antibiotic Resistant Pathogens Initiative (ARPI)
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
Recap
Previous sections have illustrated how to
We will now use the published counts as the input for a differential expression analysis.
Differential expression
The term differential expression was first used to refer to the process of finding statistically significant genes from a microarray gene expression study.
Such methods were developed on the premise that microarray expression values are approximately normally-distributed when appropriately transformed (e.g. by using a log\(_2\) transformation) so that a modified version of the standard t-test can be used. The same test is applied to each gene under investigation yielding a test statistic, fold-change and p-value. Similar methods have been adapted to RNA-seq data to account for the fact that the data are count-based and do not follow a normal distribution.
Interactive exploration of the results with DEGUST
http://degust.erc.monash.edu/
Degust
is a web tool that can analyse the counts files produced in the step above, to test for differential gene expression. It offers and interactive view of the differential expression results
The input file is a count matrix where each row is a measured gene, and each column is a different biological sample. Within the tool we can configure which samples belong to the different biological groups of interest.
To make this a more-realistic example, we will use the published count matrix for this dataset. This was downloaded from the Gene Expression Omnibus (GEO) under the accession number GSE60450. Note that we have shortened the column headings to help with visualisation
Download the counts from this link
Uploading the count matrix to Degust
N.B. Degust claims to accept a csv (comma-separated) file, but is in fact happy with a tabular file like the one we have just created.
- From the main degust page, click Upload your counts file
- Click on Browse
- Select the location of the file
GSE60450_Lactation-GenewiseCounts_rename.txt
, and click Open.
- Click Upload
- A Configuation page will appear.
- For Name type “GSE60450” (or whatever you want to call the analysis)
- For Info columns select EntrezGeneID and Length
- Click Add condition
- Refering to the experiment design (below), select the Basal samples and call the condition Basal
- Repeat for the Luminal samples
- Save the settings and then View the results
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 |
Overview of Degust sections
- Top black panel with Configure settings at right.
- Left: Conditions: Control and Treatment.
- Left: Method selection for DGE. Select edgeR for your method
- Top centre: Plots, with options at right.
- When either of the expression plots are selected, a heatmap appears below.
- A table of genes (or features); expression in treatment relative to control (Treatment column); and significance (FDR column).
(screenshot from the example at ARPI)
MDS plot
This is a multidimensional scaling plot which represents the variation between samples. It is a similar concept to a Principal Components Analysis (PCA) plot. The x-axis is the dimension with the highest magnitude. In a standard control/treatment setup, samples should be split along this axis. A desirable plot is shown below:-
MA-plot
Each dot shows the change in expression in one gene.
- The average expression (over both condition and treatment samples) is represented on the x-axis.
- Plot points should be symmetrical around the x-axis.
- We can see that many genes are expressed at a low level, and some are highly expressed.
- The fold change is represented on the y axis.
- If expression is significantly different between batch and chem, the dots are red. If not, they are blue. (In Degust, significant means FDR <0.05).
- At low levels of gene expression (low values of the x axis), fold changes are less likely to be significant.
Click on the dot to see the gene name.
Parallel coordinates and heatmap
Each line shows the change in expression in one gene, between control and treatment.
- Go to Options at the right.
- For FDR cut-off set at 0.001.
- This is a significance level (an adjusted p value). We will set it quite low in this example, to ensure we only examine key differences.
- Look at the Parallel Coordinates plot. There are two axes:
- Left: Control: Gene expression in the control samples. All values are set at zero.
- Right: Treatment Gene expression in the treatment samples, relative to expression in the control.
- The blocks of blue and red underneath the plot are called a heatmap.
- Each block is a gene. Click on a block to see its line in the plot above.
- Look at the row for the chem. Relative to batch, genes expressed more are red; genes expressed less are blue.
Table of genes
Table of genes
- gene_id: names of genes. Note that gene names are sometimes specific to a species, or they may be only named as a locus ID (a chromosomal location specified in the genome annotation).
- FDR: False Discovery Rate. This is an adjusted p value to show the significance of the difference in gene expression between two conditions. Click on column headings to sort. By default, this table is sorted by FDR.
- basal and luminal: log2(Fold Change) of gene expression. The default display is of fold change in the treatment relative to the control. Therefore, values in the batch column are zero. This can be changed in the Options panel at the top right.
- In some cases, a large fold change will be meaningful but in others, even a small fold change can be important biologically.
The table can be sorted according to any of the columns (e.g. fold-change or p-value)
Download and R code
Above the genes table is the option to download the results of the current analysis to a csv file. You can also download the R code required to reproduce the analysis by clicking the Show R code box underneath the Options box.
Question: How many genes are differentially-expressed in this analysis? Is this lower than you would expect? Look more closely at the MDS and QC plots.
Question: Having identified the problem with the analysis, modify the configuration and repeat. How many genes are differentially expressed this time?
Analysing a different contrast
Comparing Basal vs Luminal wasn’t really the main question of interest in the dataset, but it serves to illustrate the importance of checking QC plots.
- Create conditions Basal.Pregnant, Basal.Lactation, etc using the corrected experimental design
- Make sure that Basal.Pregnant and Basal.Lactation are both ticked as initial select
Take some time to understand the various parts of the report
Question: Make sure the FDR cut-off and abs LogFC cutoffs are set to default and download the file and rename to background.tsv
. We will use this later.
Question: How many genes are differentially-expressed with an FDR < 0.05 and abs logFC > 1. Download this file and rename it to B.preg_vs_lactation.tsv
.
Question: Repeat the analysis for Luminal.Pregnant vs Luminal.Lactation and download the table of differentially-expressed results (same FDR and log fold-change).
Overlapping Gene Lists
We might sometimes want to compare the lists of genes that we identify using different methods, or genes identified from more than one contrast. In our example dataset we can compare the genes in the contrast of pregnant vs luminal in basal and luminal cells
The website venny provides a really nice interface for doing this.
- Open both your Basal Pregnant vs Basal Lactation and Luminal Pregnant vs Luminal Lactation results files in Excel
- Go to the venny website
- Copy the names of genes with adjusted p-value less than 0.05 in the Basal analysis into the List 1 box on the venny website. List 1 can be renamed to Basal
- Copy the names of genes with adjusted p-value less than 0.05 in the Luminal analysis into the List 2 box on the venny website. List 2 can be renamed to Luminal
- venny should now report the number of genes found in each list, the size of the intersection, and genes unique to each method
- clicking on a particular overlap part of the venn diagram to display the list of genes common to both cell types. Paste this list of genes into a new Excel worksheet and save as a file
gene_overlap.csv
.
You are now ready to complete the file section on annotation and enrichment analysis
We will not go through the following section in the workshop, but feel free to work through in your own time
(Optional) Assessing Differential Expression with DESeq2
There are several sensible and respected choices for performing a differential expression analysis on RNA-seq data. Here, we will illustrate the DESeq2
method because it is readily available through Galaxy.
NGS: RNA Analysis > DESeq2
DESeq2 is an R package, that is used for analysing differential expression of RNA-Seq data and can either use exact statistical methods or generalised linear models.
DESeq2
takes an input the counts that we generated in the previous step. Reads counts have to be normalised first prior to differential expression testing. There are two main biases that need to be accounted for:-
- size of gene
- longer genes will have more reads assigned to them
- library size
- a sample that is sequenced to a higher depth will receive more reads
DESeq2
has its’ own method of normalising counts. You will probably encounter other methods of normalising RNA-seq reads such as RPKM, CPM, TPM etc. This blog provides a nice explanation of the current thinking. As part of the DESeq
output, you have the option of downloading normalised counts in various formats. Some other online visualisation tools require normalised counts as input, so it is good to have these to-hand.
In the Galaxy tool panel, under NGS Analysis, select NGS: RNA Analysis > DESeq2 and set the parameters as follows:
- 1. Factor level Batch
- Count files
batch1-htseq
batch2-htseq
- 2. Factor level: Chem
- Select columns containing control:
- For Output normalized counts table select Yes
- Execute
2. Examine the outputs from the previous step
- Examine the
DeSeq2 result file
by clicking on the eye icon. This file is a list of genes sorted by p-value from using DESeq2 to perform differential expression analysis.
- Examine the
DeSeq2 plots
file. This file has some plots from running DESeq2, including PCA and clustering.
DESeq2
reports, for each gene that is being tested, some information that we can use to determine if the gene is different between our conditions of interest. We will do more exploration of differential expression analysis in the next section using a tool that is not included in Galaxy. For now we will concentrate on the task on finding out which genes have sufficient statistical evidence for being differentially expressed between our two conditions.
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)
LS0tDQp0aXRsZTogIkRpZmZlcmVudGlhbCBFeHByZXNzaW9uIFR1dG9yaWFsIg0KYXV0aG9yOiAiTWFyayBEdW5uaW5nIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHllcw0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQoNCg0KIyBIYW5kcy1vbiBSTkEtc2VxIEFuYWx5c2lzIGluIEdhbGF4eQ0KDQojIyBBY2tub3dsZWRnZW1lbnQNCg0KX0Jhc2VkIG9uIHRoZSBSTkEtU2VxIHdvcmtzaG9wIGJ5IE1lbGJvdXJuZSBCaW9pbmZvcm1hdGljcyB3cml0dGVuIGJ5IE1haHRhYiBNaXJtb21lbmksIEFuZHJldyBMb25pZSwgSmVzc2ljYSBDaHVuZ18gW09yaWdpbmFsXShodHRwOi8vdmxzY2kuZ2l0aHViLmlvL2xzY2NfZG9jcy90dXRvcmlhbHMvcm5hX3NlcV9kZ2VfYWR2YW5jZWQvcm5hX3NlcV9hZHZhbmNlZF90dXRvcmlhbC8pDQoNCl9Nb2RpZmllZCBieSBEYXZpZCBQb3dlbGwgKE1vbmFzaCBCaW9pbmZvcm1hdGljcyBQbGF0Zm9ybSlfDQoNCl9GdXJ0aGVyIE1vZGlmaWVkIGJ5IE1hcmsgRHVubmluZyBvZiBTaGVmZmllbGQgQmlvaW5mb3JtYXRpY3MgQ29yZV8NCg0KVGhlIERlZ3VzdCBwYXJ0IG9mIHRoaXMgc2Vzc2lvbiBpcyBiYXNlZCBvbiB0aGUgdHV0b3JpYWwgW0RpZmZlcmVudGlhbCBnZW5lIGV4cHJlc3Npb24gdXNpbmcgR2FsYXh5IGFuZCBEZWd1c3RdKGh0dHA6Ly9zZXBzaXMtb21pY3MuZ2l0aHViLmlvL3R1dG9yaWFscy9tb2R1bGVzL2RnZS8pIGZyb20gQW50aWJpb3RpYyBSZXNpc3RhbnQgUGF0aG9nZW5zIEluaXRpYXRpdmUgKEFSUEkpDQoNCiMjIyBTaGVmZmllbGQgQmlvaW5mb3JtYXRpY3MgQ29yZQ0KPGltZyBzcmM9Im1lZGlhL2xvZ28tc20ucG5nIiBhbGlnbj1yaWdodD4NCg0Kd2ViIDogW3NiYy5zaGVmLmFjLnVrXShodHRwczovL3NiYy5zaGVmLmFjLnVrKSAgDQp0d2l0dGVyOiBbQFNoZWZmQmlvaW5mQ29yZV0oaHR0cHM6Ly90d2l0dGVyLmNvbS9TaGVmZkJpb2luZkNvcmUpICANCmVtYWlsOiBbYmlvaW5mb3JtYXRpY3MtY29yZUBzaGVmZmllbGQuYWMudWtdKGJpb2luZm9ybWF0aWNzLWNvcmVAc2hlZmZpZWxkLmFjLnVrKQ0KDQotLS0tLQ0KDQojIyBUdXRvcmlhbCBPdmVydmlldw0KDQpUaGlzIHR1dG9yaWFsIHdpbGwgY292ZXIgdGhlIGJhc2ljcyBvZiBSTkEtc2VxIHVzaW5nIEdhbGF4eTsgYSBvcGVuLXNvdXJjZSB3ZWItYmFzZWQgcGxhdGZvcm0gZm9yIHRoZSBhbmFseXNpcyBvZiBiaW9sb2dpY2FsIGRhdGEuIFlvdSBzaG91bGQgZ2FpbiBhbiBhcHByZWNpYXRpb24gb2YgdGhlIHRhc2tzIGludm9sdmVkIGluIGEgdHlwaWNhbCBSTkEtc2VxIGFuYWx5c2lzIGFuZCBiZSBjb21mb3J0YWJsZSB3aXRoIHRoZSBvdXRwdXRzIGdlbmVyYXRlZCBieSB0aGUgQmlvaW5mb3JtYXRpY2lhbi4NCg0KIyMjIE1vcmUgb24gR2FsYXh5DQoNClRoZSBvZmZpY2lhbCBHYWxheHkgcGFnZSBoYXMgbWFueSBbdHV0b3JpYWxzXShodHRwczovL2dhbGF4eXByb2plY3Qub3JnL2xlYXJuLykgb24gdXNpbmcgdGhlIHNlcnZpY2UsIGFuZCBleGFtcGxlcyBvZiBvdGhlciB0eXBlcyBvZiBhbmFseXNpcyB0aGF0IGNhbiBiZSBwZXJmb3JtZWQgb24gdGhlIHBsYXRmb3JtLg0KDQpUaG9zZSBldmVudHVhbGx5IHdhbnRlZCB0byBwZXJmb3JtIHRoZWlyIG93biBSTkEtc2VxIGFuYWx5c2lzIChmb3IgZXhhbXBsZSBpbiBSKSwgc2hvdWxkIGxvb2sgb3V0IGZvciBvdGhlciBjb3Vyc2VzDQoNCiMjIyBDb3Vyc2VzIG9uIGFuYWx5c2luZyBSTkEtc2VxIGRhdGEgaW4gUg0KDQotIFtTaGVmZmllbGQgQmlvaW5mb3JtYXRpY3MgQ29yZV0oaHR0cDovL3NiYy5zaGVmLmFjLnVrL3RyYWluaW5nL3JuYS1zZXEtaW4tci0yMDE5LTAxLTE0LykNCi0gW01vbmFzaCBCaW9pbmZvcm1hdGljcyBQbGF0Zm9ybV0oaHR0cDovL21vbmFzaGJpb2luZm9ybWF0aWNzcGxhdGZvcm0uZ2l0aHViLmlvL1JOQXNlcS1ERS1hbmFseXNpcy13aXRoLVIvKQ0KDQojIyBSZWNhcA0KDQpQcmV2aW91cyBzZWN0aW9ucyBoYXZlIGlsbHVzdHJhdGVkIGhvdyB0bw0KDQotIFtwZXJmb3JtIHF1YWxpdHkgYXNzZXNzbWVudCBvbiBvdXIgZmFzdHEgZmlsZXNdKDAxLXByZS1wcm9jZXNzaW5nLm5iLmh0bWwjc2VjdGlvbl8yOl9xdWFsaXR5X2Fzc2Vzc21lbnRfd2l0aF9mYXN0cWMpDQotIFthbGlnbiBmYXN0cSBmaWxlcyB0byB0aGUgcmVmZXJlbmNlIGdlbm9tZV0oMDEtcHJlLXByb2Nlc3NpbmcubmIuaHRtbCNzZWN0aW9uXzM6X2FsaWdubWVudCkNCi0gW3Zpc3VhbGlzZSB0aGUgcmVhZHMgaW4gSUdWXSgwMS1wcmUtcHJvY2Vzc2luZy5uYi5odG1sI3NlY3Rpb25fNF92aXN1YWxpc2VfdGhlX2FsaWduZWRfcmVhZHNfd2l0aF9pZ3YpDQotIFtjb3VudCBhZ2FpbnN0IGEgc2V0IG9mIHJlZmVyZW5jZSB0cmFuc2NyaXB0c10oMDEtcHJlLXByb2Nlc3NpbmcubmIuaHRtbCNzZWN0aW9uXzVfcXVhbnRpZmljYXRpb25fKGNvdW50aW5nX3JlYWRzX2luX2ZlYXR1cmVzKSkNCg0KV2Ugd2lsbCBub3cgdXNlIHRoZSBwdWJsaXNoZWQgY291bnRzIGFzIHRoZSBpbnB1dCBmb3IgYSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcy4NCg0KDQojIyBEaWZmZXJlbnRpYWwgZXhwcmVzc2lvbg0KDQpUaGUgdGVybSAqZGlmZmVyZW50aWFsIGV4cHJlc3Npb24qIHdhcyBmaXJzdCB1c2VkIHRvIHJlZmVyIHRvIHRoZSBwcm9jZXNzIG9mIGZpbmRpbmcgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBnZW5lcyBmcm9tIGEgKm1pY3JvYXJyYXkqIGdlbmUgZXhwcmVzc2lvbiBzdHVkeS4NCg0KIVtdKG1lZGlhL2RlX2V4cGxhaW5lZC5wbmcpDQoNCg0KU3VjaCBtZXRob2RzIHdlcmUgZGV2ZWxvcGVkIG9uIHRoZSBwcmVtaXNlIHRoYXQgbWljcm9hcnJheSBleHByZXNzaW9uIHZhbHVlcyBhcmUgYXBwcm94aW1hdGVseSAqbm9ybWFsbHktZGlzdHJpYnV0ZWQqIHdoZW4gYXBwcm9wcmlhdGVseSB0cmFuc2Zvcm1lZCAoZS5nLiBieSB1c2luZyBhIGxvZyRfMiQgdHJhbnNmb3JtYXRpb24pIHNvIHRoYXQgYSBtb2RpZmllZCB2ZXJzaW9uIG9mIHRoZSBzdGFuZGFyZCAqdC10ZXN0KiBjYW4gYmUgdXNlZC4gVGhlIHNhbWUgdGVzdCBpcyBhcHBsaWVkIHRvIGVhY2ggZ2VuZSB1bmRlciBpbnZlc3RpZ2F0aW9uIHlpZWxkaW5nIGEgKnRlc3Qgc3RhdGlzdGljKiwgKmZvbGQtY2hhbmdlKiBhbmQgKnAtdmFsdWUqLiBTaW1pbGFyIG1ldGhvZHMgaGF2ZSBiZWVuIGFkYXB0ZWQgdG8gUk5BLXNlcSBkYXRhIHRvIGFjY291bnQgZm9yIHRoZSBmYWN0IHRoYXQgdGhlIGRhdGEgYXJlICpjb3VudC1iYXNlZCogYW5kIGRvIG5vdCBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLg0KDQoNCiMjIEludGVyYWN0aXZlIGV4cGxvcmF0aW9uIG9mIHRoZSByZXN1bHRzIHdpdGggKkRFR1VTVCoNCg0KIVtdKG1lZGlhL3JuYV9hZHZhbmNlZF9kZWd1c3RfMS5wbmcpDQoNCjxmb250IHNpemU9IjgiPltodHRwOi8vZGVndXN0LmVyYy5tb25hc2guZWR1L10oaHR0cDovL2RlZ3VzdC5lcmMubW9uYXNoLmVkdS8pPC9mb250Pg0KDQpgRGVndXN0YCBpcyBhIHdlYiB0b29sIHRoYXQgY2FuIGFuYWx5c2UgdGhlIGNvdW50cyBmaWxlcyBwcm9kdWNlZCBpbiB0aGUgc3RlcCBhYm92ZSwgdG8gdGVzdCBmb3IgZGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbi4gSXQgb2ZmZXJzIGFuZCBpbnRlcmFjdGl2ZSB2aWV3IG9mIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiByZXN1bHRzDQoNClRoZSBpbnB1dCBmaWxlIGlzIGEgY291bnQgbWF0cml4IHdoZXJlIGVhY2ggcm93IGlzIGEgbWVhc3VyZWQgZ2VuZSwgYW5kIGVhY2ggY29sdW1uIGlzIGEgZGlmZmVyZW50IGJpb2xvZ2ljYWwgc2FtcGxlLiBXaXRoaW4gdGhlIHRvb2wgd2UgY2FuIGNvbmZpZ3VyZSB3aGljaCBzYW1wbGVzIGJlbG9uZyB0byB0aGUgZGlmZmVyZW50IGJpb2xvZ2ljYWwgZ3JvdXBzIG9mIGludGVyZXN0Lg0KDQoNCioqKlRvIG1ha2UgdGhpcyBhIG1vcmUtcmVhbGlzdGljIGV4YW1wbGUsIHdlIHdpbGwgdXNlIHRoZSBwdWJsaXNoZWQgY291bnQgbWF0cml4IGZvciB0aGlzIGRhdGFzZXQuIFRoaXMgd2FzIGRvd25sb2FkZWQgZnJvbSB0aGUgR2VuZSBFeHByZXNzaW9uIE9tbmlidXMgKEdFTykgdW5kZXIgdGhlIGFjY2Vzc2lvbiBudW1iZXIgW0dTRTYwNDUwXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L2dlby9xdWVyeS9hY2MuY2dpP2FjYz1HU0U2MDQ1MCkuIE5vdGUgdGhhdCB3ZSBoYXZlIHNob3J0ZW5lZCB0aGUgY29sdW1uIGhlYWRpbmdzIHRvIGhlbHAgd2l0aCB2aXN1YWxpc2F0aW9uKioqDQoNCkRvd25sb2FkIHRoZSBjb3VudHMgZnJvbSBbdGhpcyBsaW5rXShHU0U2MDQ1MF9MYWN0YXRpb24tR2VuZXdpc2VDb3VudHNfcmVuYW1lLnR4dCkNCg0KDQojIyMgVXBsb2FkaW5nIHRoZSBjb3VudCBtYXRyaXggdG8gRGVndXN0DQoNCk4uQi4gRGVndXN0IGNsYWltcyB0byBhY2NlcHQgYSAqY3N2KiAoY29tbWEtc2VwYXJhdGVkKSBmaWxlLCBidXQgaXMgaW4gZmFjdCBoYXBweSB3aXRoIGEgdGFidWxhciBmaWxlIGxpa2UgdGhlIG9uZSB3ZSBoYXZlIGp1c3QgY3JlYXRlZC4NCg0KLSBGcm9tIHRoZSBtYWluIGRlZ3VzdCBwYWdlLCBjbGljayAqVXBsb2FkIHlvdXIgY291bnRzIGZpbGUqDQotIENsaWNrIG9uIEJyb3dzZQ0KLSBTZWxlY3QgdGhlIGxvY2F0aW9uIG9mIHRoZSBmaWxlIGBHU0U2MDQ1MF9MYWN0YXRpb24tR2VuZXdpc2VDb3VudHNfcmVuYW1lLnR4dGAsIGFuZCBjbGljayAqT3BlbiouDQotIENsaWNrICpVcGxvYWQqDQotIEEgQ29uZmlndWF0aW9uIHBhZ2Ugd2lsbCBhcHBlYXIuDQoNCiFbXShtZWRpYS9kZWd1c3RfY29uZmlnLnBuZykNCg0KLSBGb3IgTmFtZSB0eXBlICIqR1NFNjA0NTAqIiAob3Igd2hhdGV2ZXIgeW91IHdhbnQgdG8gY2FsbCB0aGUgYW5hbHlzaXMpDQotIEZvciBJbmZvIGNvbHVtbnMgc2VsZWN0ICpFbnRyZXpHZW5lSUQqIGFuZCAqTGVuZ3RoKiANCi0gQ2xpY2sgQWRkIGNvbmRpdGlvbg0KICAgICsgUmVmZXJpbmcgdG8gdGhlIGV4cGVyaW1lbnQgZGVzaWduIChiZWxvdyksIHNlbGVjdCB0aGUgQmFzYWwgc2FtcGxlcyBhbmQgY2FsbCB0aGUgY29uZGl0aW9uIEJhc2FsDQogICAgKyBSZXBlYXQgZm9yIHRoZSBMdW1pbmFsIHNhbXBsZXMNCi0gU2F2ZSB0aGUgc2V0dGluZ3MgYW5kIHRoZW4gVmlldyB0aGUgcmVzdWx0cw0KDQpSdW4gIHwgTmFtZSB8IENlbGxUeXBlIHwgU3RhdHVzDQotLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tICANClNSUjE1NTI0NDQgfCBNQ0wxLUxBIHwgYmFzYWwgfCB2aXJnaW4NClNSUjE1NTI0NDUgfCBNQ0wxLUxCIHwgbHVtaW5hbCB8IHZpcmdpbg0KU1JSMTU1MjQ0NiB8IE1DTDEtTEMgfCBMdW1pbmFsIHwgcHJlZ25hbmN5DQpTUlIxNTUyNDQ3IHwgTUNMMS1MRCB8IEx1bWluYWwgfCBwcmVnbmFuY3kNClNSUjE1NTI0NDggfCBNQ0wxLUxFIHwgbHVtaW5hbCB8IGxhY3RhdGlvbg0KU1JSMTU1MjQ0OSB8IE1DTDEtTEYgfCBsdW1pbmFsIHwgbGFjdGF0aW9uDQpTUlIxNTUyNDUwIHwgTUNMMS1ERyB8IGJhc2FsIHwgdmlyZ2luDQpTUlIxNTUyNDUxIHwgTUNMMS1ESCB8IGx1bWluYWwgfCB2aXJnaW4NClNSUjE1NTI0NTIgfCBNQ0wxLURJIHwgYmFzYWwgfCBwcmVnbmFuY3kNClNSUjE1NTI0NTMgfCBNQ0wxLURKIHwgYmFzYWwgfCBwcmVnbmFuY3kNClNSUjE1NTI0NTQgfCBNQ0wxLURLIHwgYmFzYWwgfCBsYWN0YXRpb24NClNSUjE1NTI0NTUgfCBNQ0wxLURMIHwgYmFzYWwgfCBsYWN0YXRpb24NCg0KIyMgT3ZlcnZpZXcgb2YgRGVndXN0IHNlY3Rpb25zDQotIFRvcCBibGFjayBwYW5lbCB3aXRoIENvbmZpZ3VyZSBzZXR0aW5ncyBhdCByaWdodC4NCi0gTGVmdDogQ29uZGl0aW9uczogQ29udHJvbCBhbmQgVHJlYXRtZW50Lg0KLSBMZWZ0OiBNZXRob2Qgc2VsZWN0aW9uIGZvciBER0UuICoqU2VsZWN0IGVkZ2VSIGZvciB5b3VyIG1ldGhvZCoqDQotIFRvcCBjZW50cmU6IFBsb3RzLCB3aXRoIG9wdGlvbnMgYXQgcmlnaHQuDQotIFdoZW4gZWl0aGVyIG9mIHRoZSBleHByZXNzaW9uIHBsb3RzIGFyZSBzZWxlY3RlZCwgYSBoZWF0bWFwIGFwcGVhcnMgYmVsb3cuDQotIEEgdGFibGUgb2YgZ2VuZXMgKG9yIGZlYXR1cmVzKTsgZXhwcmVzc2lvbiBpbiB0cmVhdG1lbnQgcmVsYXRpdmUgdG8gY29udHJvbCAoVHJlYXRtZW50IGNvbHVtbik7IGFuZCBzaWduaWZpY2FuY2UgKEZEUiBjb2x1bW4pLg0KDQooc2NyZWVuc2hvdCBmcm9tIHRoZSBleGFtcGxlIGF0IEFSUEkpDQoNCiFbXShodHRwOi8vc2Vwc2lzLW9taWNzLmdpdGh1Yi5pby90dXRvcmlhbHMvbW9kdWxlcy9kZ2UvaW1hZ2VzL2ltYWdlMTIucG5nKQ0KDQojIyBNRFMgcGxvdA0KDQoNCg0KVGhpcyBpcyBhIG11bHRpZGltZW5zaW9uYWwgc2NhbGluZyBwbG90IHdoaWNoIHJlcHJlc2VudHMgdGhlIHZhcmlhdGlvbiBiZXR3ZWVuIHNhbXBsZXMuIEl0IGlzIGEgc2ltaWxhciBjb25jZXB0IHRvIGEgUHJpbmNpcGFsIENvbXBvbmVudHMgQW5hbHlzaXMgKFBDQSkgcGxvdC4gVGhlIHgtYXhpcyBpcyB0aGUgZGltZW5zaW9uIHdpdGggdGhlIGhpZ2hlc3QgbWFnbml0dWRlLiBJbiBhIHN0YW5kYXJkIGNvbnRyb2wvdHJlYXRtZW50IHNldHVwLCBzYW1wbGVzIHNob3VsZCBiZSBzcGxpdCBhbG9uZyB0aGlzIGF4aXMuIEEgZGVzaXJhYmxlIHBsb3QgaXMgc2hvd24gYmVsb3c6LQ0KDQohW10obWVkaWEvZGVndXN0X21kcy5wbmcpDQoNCiMjIE1BLXBsb3QNCg0KIVtdKG1lZGlhL2RlZ3VzdF9tYS5wbmcpDQoNCkVhY2ggZG90IHNob3dzIHRoZSBjaGFuZ2UgaW4gZXhwcmVzc2lvbiBpbiBvbmUgZ2VuZS4NCg0KLSBUaGUgYXZlcmFnZSBleHByZXNzaW9uIChvdmVyIGJvdGggY29uZGl0aW9uIGFuZCB0cmVhdG1lbnQgc2FtcGxlcykgaXMgcmVwcmVzZW50ZWQgb24gdGhlIHgtYXhpcy4NCiAgICArIFBsb3QgcG9pbnRzIHNob3VsZCBiZSBzeW1tZXRyaWNhbCBhcm91bmQgdGhlIHgtYXhpcy4NCiAgICArIFdlIGNhbiBzZWUgdGhhdCBtYW55IGdlbmVzIGFyZSBleHByZXNzZWQgYXQgYSBsb3cgbGV2ZWwsIGFuZCBzb21lIGFyZSBoaWdobHkgZXhwcmVzc2VkLg0KLSBUaGUgZm9sZCBjaGFuZ2UgaXMgcmVwcmVzZW50ZWQgb24gdGhlIHkgYXhpcy4NCiAgICArIElmIGV4cHJlc3Npb24gaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYmV0d2VlbiBiYXRjaCBhbmQgY2hlbSwgdGhlIGRvdHMgYXJlIHJlZC4gSWYgbm90LCB0aGV5IGFyZSBibHVlLiAoSW4gRGVndXN0LCBzaWduaWZpY2FudCBtZWFucyBGRFIgPDAuMDUpLg0KICAgICsgQXQgbG93IGxldmVscyBvZiBnZW5lIGV4cHJlc3Npb24gKGxvdyB2YWx1ZXMgb2YgdGhlIHggYXhpcyksIGZvbGQgY2hhbmdlcyBhcmUgbGVzcyBsaWtlbHkgdG8gYmUgc2lnbmlmaWNhbnQuDQoNCkNsaWNrIG9uIHRoZSBkb3QgdG8gc2VlIHRoZSBnZW5lIG5hbWUuDQoNCiMjIFBhcmFsbGVsIGNvb3JkaW5hdGVzIGFuZCBoZWF0bWFwDQoNCiFbXShtZWRpYS9kZWd1c3RfcGFyYWxsZWxfaGVhdG1hcC5wbmcpDQoNCkVhY2ggbGluZSBzaG93cyB0aGUgY2hhbmdlIGluIGV4cHJlc3Npb24gaW4gb25lIGdlbmUsIGJldHdlZW4gY29udHJvbCBhbmQgdHJlYXRtZW50Lg0KDQotIEdvIHRvIE9wdGlvbnMgYXQgdGhlIHJpZ2h0Lg0KICAgICsgRm9yIEZEUiBjdXQtb2ZmIHNldCBhdCAwLjAwMS4NCiAgICArIFRoaXMgaXMgYSBzaWduaWZpY2FuY2UgbGV2ZWwgKGFuIGFkanVzdGVkIHAgdmFsdWUpLiBXZSB3aWxsIHNldCBpdCBxdWl0ZSBsb3cgaW4gdGhpcyBleGFtcGxlLCB0byBlbnN1cmUgd2Ugb25seSBleGFtaW5lIGtleSBkaWZmZXJlbmNlcy4NCi0gTG9vayBhdCB0aGUgUGFyYWxsZWwgQ29vcmRpbmF0ZXMgcGxvdC4gVGhlcmUgYXJlIHR3byBheGVzOg0KICAgICsgTGVmdDogQ29udHJvbDogR2VuZSBleHByZXNzaW9uIGluIHRoZSBjb250cm9sIHNhbXBsZXMuIEFsbCB2YWx1ZXMgYXJlIHNldCBhdCB6ZXJvLg0KICAgICsgUmlnaHQ6IFRyZWF0bWVudCBHZW5lIGV4cHJlc3Npb24gaW4gdGhlIHRyZWF0bWVudCBzYW1wbGVzLCByZWxhdGl2ZSB0byBleHByZXNzaW9uIGluIHRoZSBjb250cm9sLg0KLSBUaGUgYmxvY2tzIG9mIGJsdWUgYW5kIHJlZCB1bmRlcm5lYXRoIHRoZSBwbG90IGFyZSBjYWxsZWQgYSBoZWF0bWFwLg0KICAgICsgRWFjaCBibG9jayBpcyBhIGdlbmUuIENsaWNrIG9uIGEgYmxvY2sgdG8gc2VlIGl0cyBsaW5lIGluIHRoZSBwbG90IGFib3ZlLg0KICAgICsgTG9vayBhdCB0aGUgcm93IGZvciB0aGUgY2hlbS4gUmVsYXRpdmUgdG8gYmF0Y2gsIGdlbmVzIGV4cHJlc3NlZCBtb3JlIGFyZSByZWQ7IGdlbmVzIGV4cHJlc3NlZCBsZXNzIGFyZSBibHVlLg0KDQojIyBUYWJsZSBvZiBnZW5lcw0KDQohW10obWVkaWEvZGVndXN0X2dlbmVfdGFibGUucG5nKQ0KDQpUYWJsZSBvZiBnZW5lcw0KDQotIGdlbmVfaWQ6IG5hbWVzIG9mIGdlbmVzLiBOb3RlIHRoYXQgZ2VuZSBuYW1lcyBhcmUgc29tZXRpbWVzIHNwZWNpZmljIHRvIGEgc3BlY2llcywgb3IgdGhleSBtYXkgYmUgb25seSBuYW1lZCBhcyBhIGxvY3VzIElEIChhIGNocm9tb3NvbWFsIGxvY2F0aW9uIHNwZWNpZmllZCBpbiB0aGUgZ2Vub21lIGFubm90YXRpb24pLg0KLSBGRFI6IEZhbHNlIERpc2NvdmVyeSBSYXRlLiBUaGlzIGlzIGFuIGFkanVzdGVkIHAgdmFsdWUgdG8gc2hvdyB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSBkaWZmZXJlbmNlIGluIGdlbmUgZXhwcmVzc2lvbiBiZXR3ZWVuIHR3byBjb25kaXRpb25zLiBDbGljayBvbiBjb2x1bW4gaGVhZGluZ3MgdG8gc29ydC4gQnkgZGVmYXVsdCwgdGhpcyB0YWJsZSBpcyBzb3J0ZWQgYnkgRkRSLg0KLSBiYXNhbCBhbmQgbHVtaW5hbDogbG9nMihGb2xkIENoYW5nZSkgb2YgZ2VuZSBleHByZXNzaW9uLiBUaGUgZGVmYXVsdCBkaXNwbGF5IGlzIG9mIGZvbGQgY2hhbmdlIGluIHRoZSB0cmVhdG1lbnQgcmVsYXRpdmUgdG8gdGhlIGNvbnRyb2wuIFRoZXJlZm9yZSwgdmFsdWVzIGluIHRoZSBiYXRjaCBjb2x1bW4gYXJlIHplcm8uIFRoaXMgY2FuIGJlIGNoYW5nZWQgaW4gdGhlIE9wdGlvbnMgcGFuZWwgYXQgdGhlIHRvcCByaWdodC4NCiAgICArIEluIHNvbWUgY2FzZXMsIGEgbGFyZ2UgZm9sZCBjaGFuZ2Ugd2lsbCBiZSBtZWFuaW5nZnVsIGJ1dCBpbiBvdGhlcnMsIGV2ZW4gYSBzbWFsbCBmb2xkIGNoYW5nZSBjYW4gYmUgaW1wb3J0YW50IGJpb2xvZ2ljYWxseS4NCg0KVGhlIHRhYmxlIGNhbiBiZSBzb3J0ZWQgYWNjb3JkaW5nIHRvIGFueSBvZiB0aGUgY29sdW1ucyAoZS5nLiBmb2xkLWNoYW5nZSBvciBwLXZhbHVlKQ0KDQoNCiMjIERvd25sb2FkIGFuZCBSIGNvZGUNCg0KQWJvdmUgdGhlIGdlbmVzIHRhYmxlIGlzIHRoZSBvcHRpb24gdG8gZG93bmxvYWQgdGhlIHJlc3VsdHMgb2YgdGhlIGN1cnJlbnQgYW5hbHlzaXMgdG8gYSBjc3YgZmlsZS4gWW91IGNhbiBhbHNvIGRvd25sb2FkIHRoZSAqUiogY29kZSByZXF1aXJlZCB0byByZXByb2R1Y2UgdGhlIGFuYWx5c2lzIGJ5IGNsaWNraW5nIHRoZSAqU2hvdyBSIGNvZGUqIGJveCB1bmRlcm5lYXRoIHRoZSBPcHRpb25zIGJveC4NCg0KDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LXdhcm5pbmciPg0KKipRdWVzdGlvbjoqKiBIb3cgbWFueSBnZW5lcyBhcmUgZGlmZmVyZW50aWFsbHktZXhwcmVzc2VkIGluIHRoaXMgYW5hbHlzaXM/IElzIHRoaXMgbG93ZXIgdGhhbiB5b3Ugd291bGQgZXhwZWN0PyBMb29rIG1vcmUgY2xvc2VseSBhdCB0aGUgTURTIGFuZCBRQyBwbG90cy4gDQo8L2Rpdj4NCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtd2FybmluZyI+DQoqKlF1ZXN0aW9uOioqIEhhdmluZyBpZGVudGlmaWVkIHRoZSBwcm9ibGVtIHdpdGggdGhlIGFuYWx5c2lzLCBtb2RpZnkgdGhlIGNvbmZpZ3VyYXRpb24gYW5kIHJlcGVhdC4gSG93IG1hbnkgZ2VuZXMgYXJlIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCB0aGlzIHRpbWU/DQo8L2Rpdj4NCg0KIyBBbmFseXNpbmcgYSBkaWZmZXJlbnQgY29udHJhc3QNCg0KQ29tcGFyaW5nIEJhc2FsIHZzIEx1bWluYWwgd2Fzbid0IHJlYWxseSB0aGUgbWFpbiBxdWVzdGlvbiBvZiBpbnRlcmVzdCBpbiB0aGUgZGF0YXNldCwgYnV0IGl0IHNlcnZlcyB0byBpbGx1c3RyYXRlIHRoZSBpbXBvcnRhbmNlIG9mIGNoZWNraW5nIFFDIHBsb3RzLiANCg0KLSBDcmVhdGUgY29uZGl0aW9ucyAqQmFzYWwuUHJlZ25hbnQqLCAqQmFzYWwuTGFjdGF0aW9uKiwgZXRjIHVzaW5nIHRoZSBjb3JyZWN0ZWQgZXhwZXJpbWVudGFsIGRlc2lnbg0KLSBNYWtlIHN1cmUgdGhhdCAqQmFzYWwuUHJlZ25hbnQqIGFuZCAqQmFzYWwuTGFjdGF0aW9uKiBhcmUgYm90aCB0aWNrZWQgYXMgaW5pdGlhbCBzZWxlY3QNCg0KIVtdKG1lZGlhL2RlZ3VzdC1jb3JyZWN0LWNvbmZpZy5wbmcpDQoNClRha2Ugc29tZSB0aW1lIHRvIHVuZGVyc3RhbmQgdGhlIHZhcmlvdXMgcGFydHMgb2YgdGhlIHJlcG9ydA0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCioqUXVlc3Rpb246KiogTWFrZSBzdXJlIHRoZSBGRFIgY3V0LW9mZiBhbmQgYWJzIExvZ0ZDIGN1dG9mZnMgYXJlIHNldCB0byBkZWZhdWx0IGFuZCAqZG93bmxvYWQqIHRoZSBmaWxlIGFuZCByZW5hbWUgdG8gYGJhY2tncm91bmQudHN2YC4gV2Ugd2lsbCB1c2UgdGhpcyBsYXRlci4NCjwvZGl2Pg0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCioqUXVlc3Rpb24qKjogSG93IG1hbnkgZ2VuZXMgYXJlIGRpZmZlcmVudGlhbGx5LWV4cHJlc3NlZCB3aXRoIGFuIEZEUiA8IDAuMDUgYW5kIGFicyBsb2dGQyA+IDEuIERvd25sb2FkIHRoaXMgZmlsZSBhbmQgcmVuYW1lIGl0IHRvIGBCLnByZWdfdnNfbGFjdGF0aW9uLnRzdmAuDQo8L2Rpdj4NCg0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC13YXJuaW5nIj4NCioqUXVlc3Rpb24qKjogUmVwZWF0IHRoZSBhbmFseXNpcyBmb3IgTHVtaW5hbC5QcmVnbmFudCB2cyBMdW1pbmFsLkxhY3RhdGlvbiBhbmQgZG93bmxvYWQgdGhlIHRhYmxlIG9mIGRpZmZlcmVudGlhbGx5LWV4cHJlc3NlZCByZXN1bHRzIChzYW1lIEZEUiBhbmQgbG9nIGZvbGQtY2hhbmdlKS4gDQo8L2Rpdj4NCg0KDQojIyBPdmVybGFwcGluZyBHZW5lIExpc3RzDQoNCiFbXShodHRwczovL3VwbG9hZC53aWtpbWVkaWEub3JnL3dpa2lwZWRpYS9lbi9lL2U0L1Zlbm5fc3RhaW5lZF9nbGFzcy5qcGcpDQoNCldlIG1pZ2h0IHNvbWV0aW1lcyB3YW50IHRvIGNvbXBhcmUgdGhlIGxpc3RzIG9mIGdlbmVzIHRoYXQgd2UgaWRlbnRpZnkgdXNpbmcgZGlmZmVyZW50IG1ldGhvZHMsIG9yIGdlbmVzIGlkZW50aWZpZWQgZnJvbSBtb3JlIHRoYW4gb25lIGNvbnRyYXN0LiBJbiBvdXIgZXhhbXBsZSBkYXRhc2V0IHdlIGNhbiBjb21wYXJlIHRoZSBnZW5lcyBpbiB0aGUgY29udHJhc3Qgb2YgcHJlZ25hbnQgdnMgbHVtaW5hbCBpbiBiYXNhbCBhbmQgbHVtaW5hbCBjZWxscw0KDQpUaGUgd2Vic2l0ZSAqdmVubnkqIHByb3ZpZGVzIGEgcmVhbGx5IG5pY2UgaW50ZXJmYWNlIGZvciBkb2luZyB0aGlzLg0KDQohW10obWVkaWEvdmVubnktY29uZmlnLnBuZykNCg0KLSBPcGVuIGJvdGggeW91ciAqQmFzYWwgUHJlZ25hbnQgdnMgQmFzYWwgTGFjdGF0aW9uKiBhbmQgKkx1bWluYWwgUHJlZ25hbnQgdnMgTHVtaW5hbCBMYWN0YXRpb24qIHJlc3VsdHMgZmlsZXMgaW4gRXhjZWwNCi0gR28gdG8gdGhlIHZlbm55IHdlYnNpdGUNCiAgICArIGh0dHA6Ly9iaW9pbmZvZ3AuY25iLmNzaWMuZXMvdG9vbHMvdmVubnkvDQotIENvcHkgdGhlIG5hbWVzIG9mIGdlbmVzIHdpdGggYWRqdXN0ZWQgcC12YWx1ZSBsZXNzIHRoYW4gMC4wNSBpbiB0aGUgQmFzYWwgYW5hbHlzaXMgaW50byB0aGUgKipMaXN0IDEqKiBib3ggb24gdGhlIHZlbm55IHdlYnNpdGUuICoqTGlzdCAxKiogY2FuIGJlIHJlbmFtZWQgdG8gKkJhc2FsKg0KLSBDb3B5IHRoZSBuYW1lcyBvZiBnZW5lcyB3aXRoIGFkanVzdGVkIHAtdmFsdWUgbGVzcyB0aGFuIDAuMDUgaW4gdGhlIEx1bWluYWwgYW5hbHlzaXMgaW50byB0aGUgKipMaXN0IDIqKiBib3ggb24gdGhlIHZlbm55IHdlYnNpdGUuICoqTGlzdCAyKiogY2FuIGJlIHJlbmFtZWQgdG8gKipMdW1pbmFsKioNCi0gdmVubnkgc2hvdWxkIG5vdyByZXBvcnQgdGhlIG51bWJlciBvZiBnZW5lcyBmb3VuZCBpbiBlYWNoIGxpc3QsIHRoZSBzaXplIG9mIHRoZSBpbnRlcnNlY3Rpb24sIGFuZCBnZW5lcyB1bmlxdWUgdG8gZWFjaCBtZXRob2QNCi0gY2xpY2tpbmcgb24gYSBwYXJ0aWN1bGFyIG92ZXJsYXAgcGFydCBvZiB0aGUgdmVubiBkaWFncmFtIHRvIGRpc3BsYXkgdGhlIGxpc3Qgb2YgZ2VuZXMgY29tbW9uIHRvIGJvdGggY2VsbCB0eXBlcy4gUGFzdGUgdGhpcyBsaXN0IG9mIGdlbmVzIGludG8gYSBuZXcgRXhjZWwgd29ya3NoZWV0IGFuZCBzYXZlIGFzIGEgZmlsZSBgZ2VuZV9vdmVybGFwLmNzdmAuDQoNCg0KWW91IGFyZSBub3cgcmVhZHkgdG8gY29tcGxldGUgdGhlIGZpbGUgc2VjdGlvbiBvbiBbYW5ub3RhdGlvbiBhbmQgZW5yaWNobWVudCBhbmFseXNpc10oMDMtZW5yaWNobWVudC5uYi5odG1sKQ0KDQo8YnI+DQo8YnI+DQoNCjxmb250IHNpemU9IjQiPioqKldlIHdpbGwgbm90IGdvIHRocm91Z2ggdGhlIGZvbGxvd2luZyBzZWN0aW9uIGluIHRoZSB3b3Jrc2hvcCwgYnV0IGZlZWwgZnJlZSB0byB3b3JrIHRocm91Z2ggaW4geW91ciBvd24gdGltZSoqKjwvZm9udD4NCg0KIyAoT3B0aW9uYWwpIEFzc2Vzc2luZyBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbiB3aXRoICpERVNlcTIqDQoNClRoZXJlIGFyZSBzZXZlcmFsIHNlbnNpYmxlIGFuZCByZXNwZWN0ZWQgY2hvaWNlcyBmb3IgcGVyZm9ybWluZyBhIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIG9uIFJOQS1zZXEgZGF0YS4gSGVyZSwgd2UgIHdpbGwgaWxsdXN0cmF0ZSB0aGUgYERFU2VxMmAgbWV0aG9kIGJlY2F1c2UgaXQgaXMgcmVhZGlseSBhdmFpbGFibGUgdGhyb3VnaCBHYWxheHkuIA0KDQo8ZGl2IGNsYXNzPSJhbGVydCBhbGVydC1pbmZvIj4NCg0KKipOR1M6IFJOQSBBbmFseXNpcyA+IERFU2VxMioqDQo8L2Rpdj4NCg0KDQpbREVTZXEyXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvREVTZXEyLmh0bWwpDQppcyBhbiBSIHBhY2thZ2UsIHRoYXQgaXMgdXNlZCBmb3IgYW5hbHlzaW5nIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIG9mIFJOQS1TZXEgZGF0YSBhbmQgY2FuIGVpdGhlciB1c2UgZXhhY3Qgc3RhdGlzdGljYWwgbWV0aG9kcyBvciBnZW5lcmFsaXNlZCANCmxpbmVhciBtb2RlbHMuDQoNCmBERVNlcTJgIHRha2VzIGFuIGlucHV0IHRoZSBjb3VudHMgdGhhdCB3ZSBnZW5lcmF0ZWQgaW4gdGhlIHByZXZpb3VzIHN0ZXAuIFJlYWRzIGNvdW50cyBoYXZlIHRvIGJlIG5vcm1hbGlzZWQgZmlyc3QgcHJpb3IgdG8gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gdGVzdGluZy4gVGhlcmUgYXJlIHR3byBtYWluIGJpYXNlcyB0aGF0IG5lZWQgdG8gYmUgYWNjb3VudGVkIGZvcjotDQoNCi0gc2l6ZSBvZiBnZW5lDQogICAgKyAqbG9uZ2VyKiBnZW5lcyB3aWxsIGhhdmUgbW9yZSByZWFkcyBhc3NpZ25lZCB0byB0aGVtDQotIGxpYnJhcnkgc2l6ZQ0KICAgICsgYSBzYW1wbGUgdGhhdCBpcyBzZXF1ZW5jZWQgdG8gYSBoaWdoZXIgZGVwdGggd2lsbCByZWNlaXZlIG1vcmUgcmVhZHMNCiAgDQpgREVTZXEyYCBoYXMgaXRzJyBvd24gbWV0aG9kIG9mIG5vcm1hbGlzaW5nIGNvdW50cy4gWW91IHdpbGwgcHJvYmFibHkgZW5jb3VudGVyIG90aGVyIG1ldGhvZHMgb2Ygbm9ybWFsaXNpbmcgUk5BLXNlcSByZWFkcyBzdWNoIGFzICpSUEtNKiwgKkNQTSosICpUUE0qIGV0Yy4gW1RoaXMgYmxvZ10oaHR0cHM6Ly93d3cucm5hLXNlcWJsb2cuY29tL3Jwa20tZnBrbS1hbmQtdHBtLWNsZWFybHktZXhwbGFpbmVkLykgcHJvdmlkZXMgYSBuaWNlIGV4cGxhbmF0aW9uIG9mIHRoZSBjdXJyZW50IHRoaW5raW5nLiBBcyBwYXJ0IG9mIHRoZSBgREVTZXFgIG91dHB1dCwgeW91IGhhdmUgdGhlIG9wdGlvbiBvZiBkb3dubG9hZGluZyBub3JtYWxpc2VkIGNvdW50cyBpbiB2YXJpb3VzIGZvcm1hdHMuIFNvbWUgb3RoZXIgb25saW5lIHZpc3VhbGlzYXRpb24gdG9vbHMgcmVxdWlyZSBub3JtYWxpc2VkIGNvdW50cyBhcyBpbnB1dCwgc28gaXQgaXMgZ29vZCB0byBoYXZlIHRoZXNlIHRvLWhhbmQuDQoNCg0KSW4gdGhlIEdhbGF4eSB0b29sIHBhbmVsLCB1bmRlciBOR1MgQW5hbHlzaXMsIHNlbGVjdA0KKipOR1M6IFJOQSBBbmFseXNpcyA+IERFU2VxMioqIGFuZCBzZXQgdGhlIHBhcmFtZXRlcnMgYXMgZm9sbG93czoNCg0KDQotICoqMS4gRmFjdG9yIGxldmVsKiogQmF0Y2gNCi0gKipDb3VudCBmaWxlcyoqICANCiAgICAtIGBiYXRjaDEtaHRzZXFgDQogICAgLSBgYmF0Y2gyLWh0c2VxYA0KLSAqKjIuIEZhY3RvciBsZXZlbDoqKiBDaGVtDQotICoqU2VsZWN0IGNvbHVtbnMgY29udGFpbmluZyBjb250cm9sOioqICANCiAgICAtIGBjaGVtMS1odHNlcWANCiAgICAtIGBjaGVtMi1odHNlcWANCi0gRm9yICoqT3V0cHV0IG5vcm1hbGl6ZWQgY291bnRzIHRhYmxlKiogc2VsZWN0ICoqWWVzKioNCi0gRXhlY3V0ZQ0KDQojIyMjIDIuICBFeGFtaW5lIHRoZSBvdXRwdXRzIGZyb20gdGhlIHByZXZpb3VzIHN0ZXANCjEuICBFeGFtaW5lIHRoZSBgRGVTZXEyIHJlc3VsdCBmaWxlYGJ5DQogICAgY2xpY2tpbmcgb24gdGhlICoqZXllIGljb24qKi4NCiAgICBUaGlzIGZpbGUgaXMgYSBsaXN0IG9mIGdlbmVzIHNvcnRlZCBieSBwLXZhbHVlIGZyb20gdXNpbmcgREVTZXEyIHRvDQogICAgcGVyZm9ybSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcy4NCjIuICBFeGFtaW5lIHRoZSBgRGVTZXEyIHBsb3RzYCBmaWxlLiBUaGlzIGZpbGUgaGFzIHNvbWUNCiAgICBwbG90cyBmcm9tIHJ1bm5pbmcgREVTZXEyLCBpbmNsdWRpbmcgW1BDQV0oaHR0cDovL3NldG9zYS5pby9ldi9wcmluY2lwYWwtY29tcG9uZW50LWFuYWx5c2lzLykgYW5kIGNsdXN0ZXJpbmcuDQogICAgDQoNCmBERVNlcTJgIHJlcG9ydHMsIGZvciBlYWNoIGdlbmUgdGhhdCBpcyBiZWluZyB0ZXN0ZWQsIHNvbWUgaW5mb3JtYXRpb24gdGhhdCB3ZSBjYW4gdXNlIHRvIGRldGVybWluZSBpZiB0aGUgZ2VuZSBpcyBkaWZmZXJlbnQgYmV0d2VlbiBvdXIgY29uZGl0aW9ucyBvZiBpbnRlcmVzdC4gV2Ugd2lsbCBkbyBtb3JlIGV4cGxvcmF0aW9uIG9mIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIGluIHRoZSBuZXh0IHNlY3Rpb24gdXNpbmcgYSB0b29sIHRoYXQgaXMgbm90IGluY2x1ZGVkIGluIEdhbGF4eS4gRm9yIG5vdyB3ZSB3aWxsIGNvbmNlbnRyYXRlIG9uIHRoZSB0YXNrIG9uIGZpbmRpbmcgb3V0IHdoaWNoIGdlbmVzIGhhdmUgKnN1ZmZpY2llbnQgc3RhdGlzdGljYWwgZXZpZGVuY2UqIGZvciBiZWluZyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmV0d2VlbiBvdXIgdHdvIGNvbmRpdGlvbnMuDQoNCiMjIyMgMy4gIEV4dHJhY3QgdGhlIHNpZ25pZmljYW50IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcy4gIA0KVW5kZXIgQmFzaWMgVG9vbHMsIGNsaWNrIG9uICoqRmlsdGVyIGFuZCBTb3J0ID4gRmlsdGVyKio6DQoNCi0gKipGaWx0ZXI6KiogYERFU2VxMiByZXN1bHRzIGZpbGVgDQotICoqV2l0aCBmb2xsb3dpbmcgY29uZGl0aW9uOioqIGBjNyA8IDAuMDUgYW5kIChjMyA+IDEuMCBvciBjMyA8IC0xLjApYA0KLSAqKk51bWJlciBvZiBoZWFkZXIgbGluZXMgdG8gc2tpcDoqKiAxDQotIEV4ZWN1dGUNCg0KVGhpcyB3aWxsIGtlZXAgdGhlIGdlbmVzIHRoYXQgaGF2ZSBhbiBhZGp1c3RlZCBwLXZhbHVlIChjb2x1bW4gNyBpbiB0aGUgdGFibGUpIG9mIGxlc3MNCm9yIGVxdWFsIHRvIDAuMDUgYW5kIGhhdmUgYSBmb2xkIGNoYW5nZSBvZiBncmVhdGVyIHRoYW4gMSBvciBsZXNzIHRoYW4gLTEuIFRoZXJlIHNob3VsZCBiZSAyMCBnZW5lcyBpbiB0aGlzIGZpbGUuDQpSZW5hbWUgdGhpcyBmaWxlIGJ5IGNsaWNraW5nIG9uIHRoZSAqKnBlbmNpbCBpY29uKiogb2YgYW5kIGNoYW5nZSB0aGUgbmFtZQ0KZnJvbSAiRmlsdGVyIG9uIGRhdGEgeCIgdG8gYERFU2VxMl9TaWduaWZpY2FudF9ERV9HZW5lc2ANCg0KPGRpdiBjbGFzcz0iYWxlcnQgYWxlcnQtd2FybmluZyI+DQpRdWVzdGlvbjogDQoNCldoeSBkbyB5b3UgdGhpbmsgaXQgaXMgaW1wb3J0YW50IHRvIHVzZSB0aGUgKmFkanVzdGVkKiBwLXZhbHVlIHRvIHNlbGVjdCB3aGljaCBnZW5lcyBhcmUgZGlmZmVyZW50aWFsbHktZXhwcmVzc2VkLiBXaHkgbWlnaHQgeW91IGFsc28gd2FudCB0byBzcGVjaWZ5IGEgZm9sZC1jaGFuZ2UgY3V0b2ZmPyBEaXNjdXNzIHdpdGggeW91ciBuZWlnaGJvdXJzDQoNCjwvZGl2Pg0KDQoNCiMjIFJlZmVyZW5jZXMNCg0KWzFdIE5vb2thZXcgSSwgUGFwaW5pIE0sIFBvcm5wdXR0cG9uZyBOLCBTY2FsY2luYXRpIEcsIEZhZ2VyYmVyZyBMLCBVaGzDqW4gTSwgTmllbHNlbiBKOiBBIGNvbXByZWhlbnNpdmUgY29tcGFyaXNvbiBvZiBSTkEtU2VxLWJhc2VkIHRyYW5zY3JpcHRvbWUgYW5hbHlzaXMgZnJvbSByZWFkcyB0byBkaWZmZXJlbnRpYWwgZ2VuZSBleHByZXNzaW9uIGFuZCBjcm9zcy1jb21wYXJpc29uIHdpdGggbWljcm9hcnJheXM6IGEgY2FzZSBzdHVkeSBpbiBTYWNjaGFyb215Y2VzIGNlcmV2aXNpYWUuIE51Y2xlaWMgQWNpZHMgUmVzIDIwMTIsIDQwICgyMCk6MTAwODQg4oCTIDEwMDk3LiBkb2k6MTAuMTA5My9uYXIvZ2tzODA0LiBFcHViIDIwMTIgU2VwIDEwDQoNClsyXSBHdWlyZ3VpcyBBLCBTbGFwZSBDLCBGYWlsbGEgTCwgU2F3IEosIFRyZW1ibGF5IEMsIFBvd2VsbCBELCBSb3NzZWxsbyBGLCBXZWkgQSwgU3RyYXNzZXIgQSwgQ3VydGlzIEQ6IFBVTUEgcHJvbW90ZXMgYXBvcHRvc2lzIG9mIGhlbWF0b3BvaWV0aWMgcHJvZ2VuaXRvcnMgZHJpdmluZyBsZXVrZW1pYyBwcm9ncmVzc2lvbiBpbiBhIG1vdXNlIG1vZGVsIG9mIG15ZWxvZHlzcGxhc2lhLiBDZWxsIERlYXRoIERpZmZlci4gMjAxNiBKdW47MjMoNikNCg==