Creative Commons License

1 The CPTAC A vs B dataset

Our first case-study is a subset of the data of the 6th study of the Clinical Proteomic Technology Assessment for Cancer (CPTAC). In this experiment, the authors spiked the Sigma Universal Protein Standard mixture 1 (UPS1) containing 48 different human proteins in a protein background of 60 ng/μL Saccharomyces cerevisiae strain BY4741 (MATa, leu2Δ0, met15Δ0, ura3Δ0, his3Δ1). Two different spike-in concentrations were used: 6A (0.25 fmol UPS1 proteins/μL) and 6B (0.74 fmol UPS1 proteins/μL) [5]. We limited ourselves to the data of LTQ-Orbitrap W at site 56. The data were searched with MaxQuant version 1.5.2.8, and detailed search settings were described in (Goeminne, Gevaert, and Clement 2016). Three replicates are available for each concentration.

2 Installation instructions and setup

You can find the installation instructions for all required software to run this exercise in software. This will install:

  • R and RStudio
  • QFeatures to read and process mass spectrometry (MS) quantitative data
  • QFeaturesGUI the graphical user interface (GUI) to QFeatures
  • msqrob2 to perform robust statistical inference for quantitative MS proteomics
  • msqrob2gui the GUI to msqrob2

Upon installation

  1. Open Rstudio, you will see the following window
Figure 1. RStudio
Figure 1. RStudio
  1. Copy and paste following commands in the console window and type enter
library(QFeaturesGUI)
library(msqrob2gui)
options(shiny.maxRequestSize = 500 * 1024^2)
  • The first line will load the QFeaturesGUI package and its dependencies (including QFeatures)
  • The second line will load the msqrob2gui package and its dependencies (including msqrob2)
  • The last line will increase the available the maximal RAM usage by the application to 500 MB.
Figure 2. Rstudio with the package loading commands
Figure 2. Rstudio with the package loading commands

3 Data preprocessing

Before analysing the data, we must perform data preprocessing. The will ensure the data meet our model assumptions. Data import and preprocessing is performed by the QFeaturesGUI application.

3.1 Open QFeaturesGUI

Run the following command (like above):

QFeaturesGUI::importQFeatures()

A new window will open with the shinyApp

Figure 3. QFeaturesGUI ShinyApp
Figure 3. QFeaturesGUI ShinyApp

It is advicable to open the shiny app in a webbrowser. You can do that by clicking on the button Open in Browser, which you can find above the blue navigation bar and the shinyApp will pop up in a new browser tab/window.

Figure 4. QFeaturesGUI in browser tab
Figure 4. QFeaturesGUI in browser tab

3.2 Import the data

Our MS-based proteomics data analysis workflows always start with 2 pieces of data:

  1. The search engine output. In this tutorial, we will use the identified and quantified peptide data by MaxQuant, called peptides.txt.
  2. An annotation file describing the experimental design. Each line corresponds to a sample and each column provides a sample annotation.

The first step is to upload the peptides.txt file. This is the file that contains your peptide-level intensities. Note that the intensities measured in each sample are stored in a separate column and each row represents a peptide. This means that MaxQuant already performed aggregation of PSM-level data into peptide-level data. For more control on PSM-level quality control and data aggregation, our data analysis workflows can also start from the evidence.txt files which contain PSM-level information, but will not be covered in this tutorial. For a MaxQuant search, the peptides.txt file can be found by default in the path_to_raw_files/combined/txt/ folder from the MaxQuant output, with path_to_raw_files the folder where raw files were saved. To upload the peptide.txt file, click on the “Browse…” button under the “assayData” tile title. You don’t need to adapt the default parameters, you can click the “Import” button right away. A preview of the table will appear and will let you quickly check the data.

Figure 5. The peptide data have been succesfully uploaded
Figure 5. The peptide data have been succesfully uploaded

You can see that MaxQuant generated a table with 11,466 lines, corresponding to 11,466 peptides. For each peptide, MaxQuant generated 71 columns containing various pieces of information, like the peptide sequence, the protein groups the peptide matches to, the charge states found,… Among these columns, there is also a set of columns containing the quantified MS intensities for each sample (i.e. columns named Intensity XXX). These will later be flagged as quantitative information.

Similarly, we need to upload the experimental annotation file which is called experimental_annotation.txt. We here provide the table as a .txt, but you can store your table in many common formats, such as .csv or .tsv. Note Excel allows you to store spreadsheets in such formats. To upload the experimental_annotation.txt file, click on the “Browse…” button under the “colData” tile title. You don’t need to adapt the default parameters, you can click the “Import” button right away. A preview of the table will appear and will let you quickly check the data. Note that uploading the annotation file is optional for data preprocessing, but you won’t be able to perform data modelling in the next section.

Figure 6. The sample annotations have been succesfully uploaded
Figure 6. The sample annotations have been succesfully uploaded

For the CPTAC dataset analysed with MaxQuant, the first column equals the names given in MaxQuant’s “Experiment” column. The second column contains the names of the quantitative columns in the table above; it should always be named quantCols as it will allow the software to correctly link the two tables. The last column is related to the study design; here the treatment provides the spike-in condition.

You are now ready to link the two tables into a QFeatures object, which is the internal representation of the data we will use for the rest of the workflow. Scroll up to the “QFeatures Converter” tile. You can leave all the default setting and click on the green button “Convert to a QFeatures object”.

After uploading your files, a preview of the data appears (feel free to click on the table row). The window should look as follows:

Figure 7. The QFeatures object is successfully converted
Figure 7. The QFeatures object is successfully converted

3.3 Configuring the preprocessing worflow

Move to the next table by clicking on “Pre-Processing Configuration” in the menu to the left. Click on the green button “+” to add a step. In this tutorial, you will need to add 7 steps in total. You should parameterise them as follows:

  1. Log Transformation
  2. Add Annotations
  3. Features filtering
  4. Normalisation
  5. Aggregation
  6. Add Annotations
  7. Features filtering

Once done, your screen should look as follows:

Figure 8. The preprocessing workflow upon configuration
Figure 8. The preprocessing workflow upon configuration

You can now click the “Confirm Current Workflow” button. On the left menu, you will see that the 3rd entry now mentions “3 Pre-processing (7 Steps)”. We will now configure and run each of these steps.

3.4 Step 1: Log transformation

For every step, you always need to load the data from the previous step (in this case the data importation). Click on the “Load assays from previous step” button. Once loaded, the data is automatically log2-transformed by default. You should not change the defaults. You will see that the intensity distribution within each sample is automatically pictured, and you can play with the plot setting (bottom right) as you wish. Your screen should be similar to this:

Figure 9. Step1: Log transformation
Figure 9. Step1: Log transformation

Once you are done, click the “Save the processed data” button. This will store the changes and make the data available for the next step. If you forget to click this button, loading the next step will lead to an error.

3.5 Step 2: add annotations

In Step 3, we will filter out features based on then number of missing values. This information is not yet available in our data for filtering, so we will add this information as a feature annotation.

  1. Move to Step 2 in the left menu.
  2. Click the button to load the previous step.
  3. Scroll at the bottom an tick the “Add missing values numbers” box
  4. Click “perform annotation”. You should see a preview of the feature annotations. You can check that the last column is “nNA” which provides the number of missing values.
  5. Click the button to save the processed data.

3.6 Step 3: peptide filtering

In this step, we will actually remove undesirable peptides. We will use the following criteria:

  • Remove peptides that could not be mapped to a protein. In the peptides.txt file of MaxQuant the variable Proteins consists of an empty character: Proteins !=
  • Remove reverse sequences (decoys). In the peptides.txt file of MaxQuant the variable Reverse is an empty character for forward sequences (targets) and an “+” character for reverse sequences: Reverse != +
  • Remove contaminants. In the peptides.txt file of MaxQuant the variable “Contaminants” or “Potential.contaminant” an empty character for non-contaminant sequences and a “+” character for contaminant sequences: Potential.contaminant != +
  • Remove peptides that were identified in less than three sample. There are 6 samples so there number of NA’s has to be smaller or equal to: nNA <= 3

To perform this filtering and carry out the sep, you can:

  1. Move to Step 3 in the left menu.
  2. Click the button to load the previous step.
  3. Click 4x the blue “Add Box” button to add 4 filtering boxes.
  4. Fill in the boxes as shown in the figure below.
  5. In the “Filtering Summary” tile, click the “Apply Filters” button.
  6. Click the button to save the processed data.
Figure 10. Step3: Feature filtering. Note the PCA plots are collapsed for better overview of the boxes.
Figure 10. Step3: Feature filtering. Note the PCA plots are collapsed for better overview of the boxes.

3.7 Step 4: Normalisation

We normalise the data by substracting the sample median from every intensity for peptide \(p\) in a sample \(i\):

\[y_{ip}^\text{norm} = y_{ip} - \hat{\mu_i}\]

with \(\hat\mu_i\) the median intensity over all observed peptides in sample \(i\).

  1. Move to Step 4 in the left menu.
  2. Click the button to load the previous step.
  3. Median normalisation is configured by default, so you can simply click the button to save the processed data.

3.8 Step 5: Summarisation

In this step, the peptide intensities will be summarised (aka aggregated) into protein intensities using robust summarisation. You can perform this as follows:

  1. Move to Step 5 in the left menu.
  2. Click the button to load the previous step.
  3. In the settings, first select “robustSummary” in the first field and then select “Proteins” as the rowData variable defining the features of the assay to aggregate.
  4. Click the button to save the processed data.

3.9 Step 6: add annotations

Repeat step 2, this will allow to perform a filtering on missing, but at the protein-level instead of peptide-level.

3.10 Step 7: protein filtering

In this step, we will remove proteins that were identified in less than 4 samples so that for most proteins at least two protein-level expression values are observed in each treatment group. So we will tolerate at most 6-4 = 2 missing values at the protein-level. You may have guessed it by now, but you can proceed with:

  1. Move to Step 7 in the left menu.
  2. Click the button to load the previous step.
  3. Click 1x the blue “Add Box” button to add a filtering box.
  4. Fill in the boxes so that the filter becomes: nNA <= 2.
  5. In the “Filtering Summary” tile, click the “Apply Filters” button.
  6. Click the button to save the processed data.

3.11 Save your progress

You now have completed the data processing. You can move to the Summary tab (in the left menu). There you will find an overview of the data and the data processing steps.

Figure 11. Summary of the data processing.
Figure 11. Summary of the data processing.

Go to the bottom of the page and click on the “Download QFeatures” button. A pop up windown will ask you to select a directory to store the resulting file. By default the file is called qfeatures_object.rds, but feel free to rename as you wish but you cannot change the file extension (.rds).

You can now close the application.

4 Statistical analysis

4.1 Open msqrob2gui

Return to your Rstudio application and run the following command:

msqrob2gui::launchMsqrob2App()

A new window will open with the shinyApp for data modelling

Figure 12. msqrob2gui ShinyApp
Figure 12. msqrob2gui ShinyApp

4.2 Import the processed data

We start the data modelling workflow with importing the data processed in the previous section:

  1. Click on “Browser…” and fetch the file you saved with the QFeaturesGUI app.
  2. In the “Select Assay”, select the last item, “quants_features_filtering_7”.

The application let’s you explore the data tables and provides a plot with the intensity distributions for each sample.

Figure 13. msqrob2gui application upon data import.
Figure 13. msqrob2gui application upon data import.

When you scroll down the page, you will find a drop down text selector (under the table). Change “run” into “treatment” and look at the principal component analysis (PCA) plot. How would you interpret this graph?

Figure 14. PCA plot of the CPTAC data set.
Figure 14. PCA plot of the CPTAC data set.

The PCA plot indicates that we can expect a treatment effect in the data as the sample belonging to one treatment can be separated from the samples belonging to the other treatment. We also see that this separation mostly occurs in the second principal componen. The first component, which explains most of the variation, does not seem to bear correlation associated with treatment. This is expected as we know that only a few protein were spiked in, so we do not expect an effect of treatment for most proteins. We will now delve into the data modelling and inference that will statistically quantify these effects for each protein individually.

4.3 Data modelling

You can now move to the data modelling tab by clicking “Model” in the menu on the left.

We will model the data with a different group mean for the variable treatment with two levels: spikein treatment A and B. We can specify this model by inserting ~1+treatment in the “Design formula” textbox. Note, that a formula always starts with a symbol ‘~’ (see the descriptive paragraph in the application).

Note that as soon as we do that, the design is visualised.

Figure 15. msqrob2 Model tab with design
Figure 15. msqrob2 Model tab with design

This visualisation shows the different group means that are modelled.

  • The group mean for the treatment A is modelled using the parameter (Intercept).
  • The group mean for the treatment B is modelled using a linear combination of the two model parameters (Intercept) + treatmentB.
  • The average difference in preprocessed protein expression value between both conditions equals treatmentB.

Remember that we log-transformed the intensities:

\[ \log_2FC_\text{B}=\log_2 B - \log_2 A = \log_2\frac{B}{A} = \text{treatmentB} \]

Note that a linear combination of model parameters is also referred to as a contrast in statistics. This contrast has the interpretation of a log2 fold change between condition B and condition A. Positive estimates denote that the abundance of the protein is on average higher in condition B, negative estimates denote that the abundance is on average higher in condition A. An estimate equal to 0 indicates that the estimated abundances are equal.

A log2 FC = 1 indicates that the average abundance in condition B is 2 x higher than the average abundance in condition A, i.e. an 2 fold upregulation in condition B as compared to condition A.

We now have to click the Fit Model! button to fit the models for each protein. We are now ready for assessing differential abundance of each protein using formal hypothesis testing.

4.4 Inference

Click on the “Inference” tab in the left menu.

In the statistical analysis we will want to test the null hypothesis that

\[ H_0: \log_2 B-\log_2 6A = 0 \]

Against the alternative that

\[ H_1: \log_2 B - \log_2 A \neq 0 \]

We can specify the null hypothesis as a linear combination of the model parameters, i.e. treatmentB = 0. We will falsify this null hypothesis for each protein separately based on the linear model. So, under the null hypothesis we reason that there is no effect of the spike-in treatment on the abundance of a specific protein. The p-value of the statistical test than indicates the probability to observe an effect (fold change), that is as extreme or more extreme (equally or more up or down regulated) than what is observed in the sample, by random change (when the null hypothesis is true and when there is in reality no effect of the treatment).

To proceed, fill in the field “Null hypothesis” with treatmentB = 0. After 1-2 second, the window is updated

Figure 16. msqrob2 Inference tab with contrast
Figure 16. msqrob2 Inference tab with contrast

4.4.1 Volcano plot

The application now also provides a volcano plot appears giving you a view on statistical significance in the y-axis, i.e. the \(-\log_{10}\) transformed p-value: a value of 1 equals to a p-value of 0.1, a value of 2 equals a p-value of 0.01, etc against biological relevance/the effect size in the x-axis, which is the \(\log_2FC\).

4.4.2 Result table

You also get a table with selected feature. By default these are all proteins that are significant with the specified “Significance level” field. You also obtain a boxplot of the log2-fold changes for all proteins that are selected in the table.

Note that 19 proteins are recovered as significant. As expected all these proteins are UPS proteins which are known to be spiked in the samples. If you untick the option only significant features in table, all proteins are shown in the table.

You can highlight proteins on the volcano plot by selecting lines of interest in the result table. You can also search for specific proteins in the list by using the search field above the table. E.g. type ups.

4.4.3 Detail plots

If you select one protein in the table, you can also explore the underlying normalised peptide intensities and protein intensities of the underlying data in the “DetailPlots”:

Figure 17. msqrob2 detail plots.
Figure 17. msqrob2 detail plots.

You can further modify the plot by coloring the data according to a design variable or by splitting the data horizontally or vertically according to design variables.

5 Report Tab

A reproducible Rmarkdown script and html report with the analysis you performed with the GUI can be downloaded in the “Report” tab.

Figure 18. msqrob2 report tab
Figure 18. msqrob2 report tab
  1. Provide a name to your project
  2. You can specify the number of detail plots you want to generate in the report. The default is 10, which indicates that detail plots will be constructed for the 10 most significant protein in your top list. Note, that the number of detail plots can be smaller if there are less than 10 proteins significant at the specified FDR-level.
  3. Click the “Generate report” button and a report will be compiled.

This will create a zip file that contains:

  • qfeaturesFile.rds: A tab delimited file with the raw intensity data.
  • report.Rmd : R/markdown file with the code for the report. If you open the file in Rstudio and if you hit the knit button the report will be compiled to html.

So, your analysis is stored in a fully reproducible way.

6 Wrap up exercise: evaluate summarisation

We further explore the difference between summarisation methods. We first assess the quality of the fold change estimates for the robust summarisation.

Go back to the “Inference” tab. We will make use of the boxplot at the bottom of the quantification tab.

  1. Untick the option only significant features in table to show all proteins in the table. The boxplot below the table visualises the log2 fold change (FC) estimates for all proteins in the table.
  2. We can now filter the ups proteins by typing “ups” in the search field above the table. Now all yeast proteins are removed from the results table and a boxplot of the ups protein log2 FCs will be made.
Figure 19. msqrob2 Inference tab with Fold Change Boxplot for all UPS proteins
Figure 19. msqrob2 Inference tab with Fold Change Boxplot for all UPS proteins

Try answering the following questions:

  • We know the real FC for the spike in proteins (see description of the data 2.2). Note, that the boxplot is showing the log2 FC. What do you observe?
  • Now select all yeast proteins. What is the real fold change and what do you observe?
  • Close and reopen the ahiny App and repeat the complete analysis, but this time apply the median summarisation method in Step 5 in the data preprocessing. What do you observe, how does that compare to the robust summarisation and try to explain this?

7 Final remark

Note, that the shiny apps are interfaces to the statistical programming software R.

The analysis can also be conducted using scripts, which gives you much more functionality and the ability to streamline, automate and document your analyses in a reproducible way.

Goeminne, L. J., K. Gevaert, and L. Clement. 2016. Peptide-level Robust Ridge Regression Improves Estimation, Sensitivity, and Specificity in Data-dependent Quantitative Label-free Shotgun Proteomics.” Mol Cell Proteomics 15 (2): 657–68.
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIHByb3Rlb21pY3MgZGF0YSBhbmFseXNpcyIKc3VidGl0bGU6ICJJbXBhY3Qgb2Ygc3VtbWFyaXNhdGlvbiIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQiCmRhdGU6ICJzdGF0T21pY3MsIEdoZW50IFVuaXZlcnNpdHkgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pbykiCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIHRoZW1lOiBmbGF0bHkgICAgICAKICAgICAgY29kZV9kb3dubG9hZDogZmFsc2UKICAgICAgdG9jOiBmYWxzZQogICAgICB0b2NfZmxvYXQ6IGZhbHNlCiAgICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKYmlibGlvZ3JhcGh5OiBtc3Fyb2IyLmJpYgotLS0KCjxhIHJlbD0ibGljZW5zZSIgaHJlZj0iaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLXNhLzQuMCI+PGltZyBhbHQ9IkNyZWF0aXZlIENvbW1vbnMgTGljZW5zZSIgc3R5bGU9ImJvcmRlci13aWR0aDowIiBzcmM9Imh0dHBzOi8vaS5jcmVhdGl2ZWNvbW1vbnMub3JnL2wvYnktbmMtc2EvNC4wLzg4eDMxLnBuZyIgLz48L2E+CgojIyBUaGUgQ1BUQUMgQSB2cyBCIGRhdGFzZXQKCk91ciBmaXJzdCBjYXNlLXN0dWR5IGlzIGEgc3Vic2V0IG9mIHRoZSBkYXRhIG9mIHRoZSA2dGggc3R1ZHkgb2YgdGhlCkNsaW5pY2FsIFByb3Rlb21pYyBUZWNobm9sb2d5IEFzc2Vzc21lbnQgZm9yIENhbmNlciAoQ1BUQUMpLiBJbiB0aGlzCmV4cGVyaW1lbnQsIHRoZSBhdXRob3JzIHNwaWtlZCB0aGUgU2lnbWEgVW5pdmVyc2FsIFByb3RlaW4gU3RhbmRhcmQKbWl4dHVyZSAxIChVUFMxKSBjb250YWluaW5nIDQ4IGRpZmZlcmVudCBodW1hbiBwcm90ZWlucyBpbiBhIHByb3RlaW4KYmFja2dyb3VuZCBvZiA2MCBuZy/OvEwgU2FjY2hhcm9teWNlcyBjZXJldmlzaWFlIHN0cmFpbiBCWTQ3NDEgKE1BVGEsCmxldTLOlDAsIG1ldDE1zpQwLCB1cmEzzpQwLCBoaXMzzpQxKS4gVHdvIGRpZmZlcmVudCBzcGlrZS1pbgpjb25jZW50cmF0aW9ucyB3ZXJlIHVzZWQ6IDZBICgwLjI1IGZtb2wgVVBTMSBwcm90ZWlucy/OvEwpIGFuZCA2QiAoMC43NApmbW9sIFVQUzEgcHJvdGVpbnMvzrxMKSBbNV0uIFdlIGxpbWl0ZWQgb3Vyc2VsdmVzIHRvIHRoZSBkYXRhIG9mCkxUUS1PcmJpdHJhcCBXIGF0IHNpdGUgNTYuIFRoZSBkYXRhIHdlcmUgc2VhcmNoZWQgd2l0aCBNYXhRdWFudAp2ZXJzaW9uIDEuNS4yLjgsIGFuZCBkZXRhaWxlZCBzZWFyY2ggc2V0dGluZ3Mgd2VyZSBkZXNjcmliZWQgaW4KW0Bnb2VtaW5uZTIwMTZdLiBUaHJlZSByZXBsaWNhdGVzIGFyZSBhdmFpbGFibGUgZm9yIGVhY2gKY29uY2VudHJhdGlvbi4KCi0gVGhlIHJhdyBkYXRhIGZpbGVzIGNhbiBiZSBkb3dubG9hZGVkIGZyb20gCiAgaHR0cHM6Ly9jcHRhYy1kYXRhLXBvcnRhbC5nZW9yZ2V0b3duLmVkdS9jcHRhYy9wdWJsaWM/c2NvcGU9UGhhc2UrSQogIChTdHVkeSA2KQoKLSBUaGUgTWF4UXVhbnQgZGF0YSBjYW4gYmUgZG93bmxvYWRlZCBbemlwIGZpbGUgd2l0aCAKICBkYXRhXShodHRwczovL2dpdGh1Yi5jb20vc3RhdE9taWNzL1BEQTI1RUJJL2FyY2hpdmUvcmVmcy9oZWFkcy9kYXRhLnppcCkuCiAgVGhlIHBlcHRpZGVzLnR4dCBmaWxlIGNhbiBiZSBmb3VuZCBpbiAKICBgZGF0YS9xdWFudGlmaWNhdGlvbi9jcHRhY0F2c0JfbGFiM2AuCgojIyBJbnN0YWxsYXRpb24gaW5zdHJ1Y3Rpb25zIGFuZCBzZXR1cAoKWW91IGNhbiBmaW5kIHRoZSBpbnN0YWxsYXRpb24gaW5zdHJ1Y3Rpb25zIGZvciBhbGwgcmVxdWlyZWQgc29mdHdhcmUKdG8gcnVuIHRoaXMgZXhlcmNpc2UgaW4gW3NvZnR3YXJlXSguL3NvZnR3YXJlLmh0bWwpLiBUaGlzIHdpbGwgCmluc3RhbGw6CgotIFIgYW5kIFJTdHVkaW8KLSBgUUZlYXR1cmVzYCB0byByZWFkIGFuZCBwcm9jZXNzIG1hc3Mgc3BlY3Ryb21ldHJ5IChNUykgcXVhbnRpdGF0aXZlIAogIGRhdGEKLSBgUUZlYXR1cmVzR1VJYCB0aGUgZ3JhcGhpY2FsIHVzZXIgaW50ZXJmYWNlIChHVUkpIHRvIFFGZWF0dXJlcwotIGBtc3Fyb2IyYCB0byBwZXJmb3JtIHJvYnVzdCBzdGF0aXN0aWNhbCBpbmZlcmVuY2UgZm9yIHF1YW50aXRhdGl2ZSBNUyAKICBwcm90ZW9taWNzCi0gYG1zcXJvYjJndWlgIHRoZSBHVUkgdG8gbXNxcm9iMgoKVXBvbiBpbnN0YWxsYXRpb24gCgoxLiBPcGVuIFJzdHVkaW8sIHlvdSB3aWxsIHNlZSB0aGUgZm9sbG93aW5nIHdpbmRvdwoKIVtGaWd1cmUgMS4gUlN0dWRpb10oLi9maWd1cmVzL3JzdHVkaW8ucG5nKQoKMi4gQ29weSBhbmQgcGFzdGUgZm9sbG93aW5nIGNvbW1hbmRzIGluIHRoZSBjb25zb2xlIHdpbmRvdyBhbmQgdHlwZSBlbnRlcgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoUUZlYXR1cmVzR1VJKQpsaWJyYXJ5KG1zcXJvYjJndWkpCm9wdGlvbnMoc2hpbnkubWF4UmVxdWVzdFNpemUgPSA1MDAgKiAxMDI0XjIpCmBgYAoKLSBUaGUgZmlyc3QgbGluZSB3aWxsIGxvYWQgdGhlIGBRRmVhdHVyZXNHVUlgIHBhY2thZ2UgYW5kIGl0cyAKICBkZXBlbmRlbmNpZXMgKGluY2x1ZGluZyBgUUZlYXR1cmVzYCkKLSBUaGUgc2Vjb25kIGxpbmUgd2lsbCBsb2FkIHRoZSBgbXNxcm9iMmd1aWAgcGFja2FnZSBhbmQgaXRzCiAgZGVwZW5kZW5jaWVzIChpbmNsdWRpbmcgYG1zcXJvYjJgKQotIFRoZSBsYXN0IGxpbmUgd2lsbCBpbmNyZWFzZSB0aGUgYXZhaWxhYmxlIHRoZSBtYXhpbWFsIFJBTSB1c2FnZSBieSAKICB0aGUgYXBwbGljYXRpb24gdG8gNTAwIE1CLgoKIVtGaWd1cmUgMi4gUnN0dWRpbyB3aXRoIHRoZSBwYWNrYWdlIGxvYWRpbmcgY29tbWFuZHNdKC4vZmlndXJlcy9yc3R1ZGlvMi5wbmcpCgojIyBEYXRhIHByZXByb2Nlc3NpbmcKCkJlZm9yZSBhbmFseXNpbmcgdGhlIGRhdGEsIHdlIG11c3QgcGVyZm9ybSBkYXRhIHByZXByb2Nlc3NpbmcuIFRoZQp3aWxsIGVuc3VyZSB0aGUgZGF0YSBtZWV0IG91ciBtb2RlbCBhc3N1bXB0aW9ucy4gRGF0YSBpbXBvcnQgYW5kCnByZXByb2Nlc3NpbmcgaXMgcGVyZm9ybWVkIGJ5IHRoZSBgUUZlYXR1cmVzR1VJYCBhcHBsaWNhdGlvbi4KCiMjIyBPcGVuIGBRRmVhdHVyZXNHVUlgIAoKUnVuIHRoZSBmb2xsb3dpbmcgY29tbWFuZCAobGlrZSBhYm92ZSk6CgpgYGB7ciwgZXZhbD1GQUxTRX0KUUZlYXR1cmVzR1VJOjppbXBvcnRRRmVhdHVyZXMoKQpgYGAKCkEgbmV3IHdpbmRvdyB3aWxsIG9wZW4gd2l0aCB0aGUgc2hpbnlBcHAKCiFbRmlndXJlIDMuIFFGZWF0dXJlc0dVSSBTaGlueUFwcF0oLi9maWd1cmVzL3FmZWF0dXJlc2d1aV9mcmVzaC5wbmcpCgpJdCBpcyBhZHZpY2FibGUgdG8gb3BlbiB0aGUgc2hpbnkgYXBwIGluIGEgd2ViYnJvd3Nlci4gWW91IGNhbiBkbwp0aGF0IGJ5IGNsaWNraW5nIG9uIHRoZSBidXR0b24gYE9wZW4gaW4gQnJvd3NlcmAsIHdoaWNoIHlvdSBjYW4gZmluZAphYm92ZSB0aGUgYmx1ZSBuYXZpZ2F0aW9uIGJhciBhbmQgdGhlIHNoaW55QXBwIHdpbGwgcG9wIHVwIGluIGEgbmV3CmJyb3dzZXIgdGFiL3dpbmRvdy4KCiFbRmlndXJlIDQuIFFGZWF0dXJlc0dVSSBpbiBicm93c2VyIHRhYl0oLi9maWd1cmVzL1FGZWF0dXJlc0dVSS5wbmcpCgojIyMgSW1wb3J0IHRoZSBkYXRhCgpPdXIgTVMtYmFzZWQgcHJvdGVvbWljcyBkYXRhIGFuYWx5c2lzIHdvcmtmbG93cyBhbHdheXMgc3RhcnQgd2l0aCAyIApwaWVjZXMgb2YgZGF0YTogCgoxLiBUaGUgc2VhcmNoIGVuZ2luZSBvdXRwdXQuIEluIHRoaXMgdHV0b3JpYWwsIHdlIHdpbGwgdXNlIHRoZQogICBpZGVudGlmaWVkIGFuZCBxdWFudGlmaWVkIHBlcHRpZGUgZGF0YSBieSBNYXhRdWFudCwgY2FsbGVkCiAgIGBwZXB0aWRlcy50eHRgLgoyLiBBbiBhbm5vdGF0aW9uIGZpbGUgZGVzY3JpYmluZyB0aGUgZXhwZXJpbWVudGFsIGRlc2lnbi4gRWFjaCBsaW5lCiAgIGNvcnJlc3BvbmRzIHRvIGEgc2FtcGxlIGFuZCBlYWNoIGNvbHVtbiBwcm92aWRlcyBhIHNhbXBsZSAKICAgYW5ub3RhdGlvbi4KClRoZSBmaXJzdCBzdGVwIGlzIHRvIHVwbG9hZCB0aGUgYHBlcHRpZGVzLnR4dGAgZmlsZS4gVGhpcyBpcyB0aGUgZmlsZQp0aGF0IGNvbnRhaW5zIHlvdXIgcGVwdGlkZS1sZXZlbCBpbnRlbnNpdGllcy4gTm90ZSB0aGF0IHRoZQppbnRlbnNpdGllcyBtZWFzdXJlZCBpbiBlYWNoIHNhbXBsZSBhcmUgc3RvcmVkIGluIGEgc2VwYXJhdGUgY29sdW1uCmFuZCBlYWNoIHJvdyByZXByZXNlbnRzIGEgcGVwdGlkZS4gVGhpcyBtZWFucyB0aGF0IE1heFF1YW50IGFscmVhZHkKcGVyZm9ybWVkIGFnZ3JlZ2F0aW9uIG9mIFBTTS1sZXZlbCBkYXRhIGludG8gcGVwdGlkZS1sZXZlbCBkYXRhLiBGb3IKbW9yZSBjb250cm9sIG9uIFBTTS1sZXZlbCBxdWFsaXR5IGNvbnRyb2wgYW5kIGRhdGEgYWdncmVnYXRpb24sIG91cgpkYXRhIGFuYWx5c2lzIHdvcmtmbG93cyBjYW4gYWxzbyBzdGFydCBmcm9tIHRoZSBgZXZpZGVuY2UudHh0YCBmaWxlcwp3aGljaCBjb250YWluIFBTTS1sZXZlbCBpbmZvcm1hdGlvbiwgYnV0IHdpbGwgbm90IGJlIGNvdmVyZWQgaW4gdGhpcwp0dXRvcmlhbC4gRm9yIGEgTWF4UXVhbnQgc2VhcmNoLCB0aGUgYHBlcHRpZGVzLnR4dGAgZmlsZSBjYW4gYmUgZm91bmQKYnkgZGVmYXVsdCBpbiB0aGUgYHBhdGhfdG9fcmF3X2ZpbGVzL2NvbWJpbmVkL3R4dC9gIGZvbGRlciBmcm9tIHRoZQpNYXhRdWFudCBvdXRwdXQsIHdpdGggYHBhdGhfdG9fcmF3X2ZpbGVzYCB0aGUgZm9sZGVyIHdoZXJlIHJhdyBmaWxlcwp3ZXJlIHNhdmVkLiBUbyB1cGxvYWQgdGhlIGBwZXB0aWRlLnR4dGAgZmlsZSwgY2xpY2sgb24gdGhlICJCcm93c2UuLi4iCmJ1dHRvbiB1bmRlciB0aGUgImFzc2F5RGF0YSIgdGlsZSB0aXRsZS4gWW91IGRvbid0IG5lZWQgdG8gYWRhcHQgdGhlCmRlZmF1bHQgcGFyYW1ldGVycywgeW91IGNhbiBjbGljayB0aGUgIkltcG9ydCIgYnV0dG9uIHJpZ2h0IGF3YXkuIEEKcHJldmlldyBvZiB0aGUgdGFibGUgd2lsbCBhcHBlYXIgYW5kIHdpbGwgbGV0IHlvdSBxdWlja2x5IGNoZWNrIHRoZQpkYXRhLgoKIVtGaWd1cmUgNS4gVGhlIHBlcHRpZGUgZGF0YSBoYXZlIGJlZW4gc3VjY2VzZnVsbHkgdXBsb2FkZWRdKC4vZmlndXJlcy9wZXB0aWRlc19pbXBvcnRlZC5wbmcpCgpZb3UgY2FuIHNlZSB0aGF0IE1heFF1YW50IGdlbmVyYXRlZCBhIHRhYmxlIHdpdGggMTEsNDY2IGxpbmVzLApjb3JyZXNwb25kaW5nIHRvIDExLDQ2NiBwZXB0aWRlcy4gRm9yIGVhY2ggcGVwdGlkZSwgTWF4UXVhbnQgZ2VuZXJhdGVkCjcxIGNvbHVtbnMgY29udGFpbmluZyB2YXJpb3VzIHBpZWNlcyBvZiBpbmZvcm1hdGlvbiwgbGlrZSB0aGUgcGVwdGlkZQpzZXF1ZW5jZSwgdGhlIHByb3RlaW4gZ3JvdXBzIHRoZSBwZXB0aWRlIG1hdGNoZXMgdG8sIHRoZSBjaGFyZ2Ugc3RhdGVzCmZvdW5kLC4uLiBBbW9uZyB0aGVzZSBjb2x1bW5zLCB0aGVyZSBpcyBhbHNvIGEgc2V0IG9mIGNvbHVtbnMKY29udGFpbmluZyB0aGUgcXVhbnRpZmllZCBNUyBpbnRlbnNpdGllcyBmb3IgZWFjaCBzYW1wbGUgKGkuZS4gY29sdW1ucwpuYW1lZCBgSW50ZW5zaXR5IFhYWGApLiBUaGVzZSB3aWxsIGxhdGVyIGJlIGZsYWdnZWQgYXMgcXVhbnRpdGF0aXZlIAppbmZvcm1hdGlvbi4KClNpbWlsYXJseSwgd2UgbmVlZCB0byB1cGxvYWQgdGhlIGV4cGVyaW1lbnRhbCBhbm5vdGF0aW9uIGZpbGUgd2hpY2ggaXMKY2FsbGVkIGBleHBlcmltZW50YWxfYW5ub3RhdGlvbi50eHRgLiBXZSBoZXJlIHByb3ZpZGUgdGhlIHRhYmxlIGFzIGEKYC50eHRgLCBidXQgeW91IGNhbiBzdG9yZSB5b3VyIHRhYmxlIGluIG1hbnkgY29tbW9uIGZvcm1hdHMsIHN1Y2ggYXMKYC5jc3ZgIG9yIGAudHN2YC4gTm90ZSBFeGNlbCBhbGxvd3MgeW91IHRvIHN0b3JlIHNwcmVhZHNoZWV0cyBpbiBzdWNoCmZvcm1hdHMuIFRvIHVwbG9hZCB0aGUgYGV4cGVyaW1lbnRhbF9hbm5vdGF0aW9uLnR4dGAgZmlsZSwgY2xpY2sgb24KdGhlICJCcm93c2UuLi4iIGJ1dHRvbiB1bmRlciB0aGUgImNvbERhdGEiIHRpbGUgdGl0bGUuIFlvdSBkb24ndCBuZWVkCnRvIGFkYXB0IHRoZSBkZWZhdWx0IHBhcmFtZXRlcnMsIHlvdSBjYW4gY2xpY2sgdGhlICJJbXBvcnQiIGJ1dHRvbgpyaWdodCBhd2F5LiBBIHByZXZpZXcgb2YgdGhlIHRhYmxlIHdpbGwgYXBwZWFyIGFuZCB3aWxsIGxldCB5b3UKcXVpY2tseSBjaGVjayB0aGUgZGF0YS4gTm90ZSB0aGF0IHVwbG9hZGluZyB0aGUgYW5ub3RhdGlvbiBmaWxlIGlzCm9wdGlvbmFsIGZvciBkYXRhIHByZXByb2Nlc3NpbmcsIGJ1dCB5b3Ugd29uJ3QgYmUgYWJsZSB0byBwZXJmb3JtIGRhdGEKbW9kZWxsaW5nIGluIHRoZSBuZXh0IHNlY3Rpb24uCgohW0ZpZ3VyZSA2LiBUaGUgc2FtcGxlIGFubm90YXRpb25zIGhhdmUgYmVlbiBzdWNjZXNmdWxseSB1cGxvYWRlZF0oLi9maWd1cmVzL2Fubm90YXRpb25zX2ltcG9ydGVkLnBuZykKCkZvciB0aGUgQ1BUQUMgZGF0YXNldCBhbmFseXNlZCB3aXRoIE1heFF1YW50LCB0aGUgZmlyc3QgY29sdW1uIGVxdWFscwp0aGUgbmFtZXMgZ2l2ZW4gaW4gTWF4UXVhbnTigJlzICJFeHBlcmltZW50IiBjb2x1bW4uIFRoZSBzZWNvbmQgY29sdW1uCmNvbnRhaW5zIHRoZSBuYW1lcyBvZiB0aGUgcXVhbnRpdGF0aXZlIGNvbHVtbnMgaW4gdGhlIHRhYmxlIGFib3ZlOyBpdApzaG91bGQgYWx3YXlzIGJlIG5hbWVkIGBxdWFudENvbHNgIGFzIGl0IHdpbGwgYWxsb3cgdGhlIHNvZnR3YXJlIHRvCmNvcnJlY3RseSBsaW5rIHRoZSB0d28gdGFibGVzLiBUaGUgbGFzdCBjb2x1bW4gaXMgcmVsYXRlZCB0byB0aGUgc3R1ZHkKZGVzaWduOyBoZXJlIHRoZSB0cmVhdG1lbnQgcHJvdmlkZXMgdGhlIHNwaWtlLWluIGNvbmRpdGlvbi4KCllvdSBhcmUgbm93IHJlYWR5IHRvIGxpbmsgdGhlIHR3byB0YWJsZXMgaW50byBhIGBRRmVhdHVyZXNgIG9iamVjdCwKd2hpY2ggaXMgdGhlIGludGVybmFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkYXRhIHdlIHdpbGwgdXNlIGZvciB0aGUKcmVzdCBvZiB0aGUgd29ya2Zsb3cuIFNjcm9sbCB1cCB0byB0aGUgIlFGZWF0dXJlcyBDb252ZXJ0ZXIiIHRpbGUuIFlvdQpjYW4gbGVhdmUgYWxsIHRoZSBkZWZhdWx0IHNldHRpbmcgYW5kIGNsaWNrIG9uIHRoZSBncmVlbiBidXR0b24KIkNvbnZlcnQgdG8gYSBRRmVhdHVyZXMgb2JqZWN0Ii4gIAoKQWZ0ZXIgdXBsb2FkaW5nIHlvdXIgZmlsZXMsIGEgcHJldmlldyBvZiB0aGUgZGF0YSBhcHBlYXJzIChmZWVsIGZyZWUKdG8gY2xpY2sgb24gdGhlIHRhYmxlIHJvdykuIFRoZSB3aW5kb3cgc2hvdWxkIGxvb2sgYXMgZm9sbG93czoKCiFbRmlndXJlIDcuIFRoZSBRRmVhdHVyZXMgb2JqZWN0IGlzIHN1Y2Nlc3NmdWxseSBjb252ZXJ0ZWRdKC4vZmlndXJlcy9xZmVhdHVyZXNfaW1wb3J0ZWQucG5nKQoKIyMjIENvbmZpZ3VyaW5nIHRoZSBwcmVwcm9jZXNzaW5nIHdvcmZsb3cKCk1vdmUgdG8gdGhlIG5leHQgdGFibGUgYnkgY2xpY2tpbmcgb24gIlByZS1Qcm9jZXNzaW5nIENvbmZpZ3VyYXRpb24iCmluIHRoZSBtZW51IHRvIHRoZSBsZWZ0LiBDbGljayBvbiB0aGUgZ3JlZW4gYnV0dG9uICIrIiB0byBhZGQgYSBzdGVwLgpJbiB0aGlzIHR1dG9yaWFsLCB5b3Ugd2lsbCBuZWVkIHRvIGFkZCA3IHN0ZXBzIGluIHRvdGFsLiBZb3Ugc2hvdWxkCnBhcmFtZXRlcmlzZSB0aGVtIGFzIGZvbGxvd3M6CgoxLiBMb2cgVHJhbnNmb3JtYXRpb24KMi4gQWRkIEFubm90YXRpb25zCjMuIEZlYXR1cmVzIGZpbHRlcmluZwo0LiBOb3JtYWxpc2F0aW9uCjUuIEFnZ3JlZ2F0aW9uCjYuIEFkZCBBbm5vdGF0aW9ucwo3LiBGZWF0dXJlcyBmaWx0ZXJpbmcKCk9uY2UgZG9uZSwgeW91ciBzY3JlZW4gc2hvdWxkIGxvb2sgYXMgZm9sbG93czoKCiFbRmlndXJlIDguIFRoZSBwcmVwcm9jZXNzaW5nIHdvcmtmbG93IHVwb24gY29uZmlndXJhdGlvbl0oLi9maWd1cmVzL3ByZXByb2Nlc3NpbmdfY29uZmlndXJhdGlvbi5wbmcpCgpZb3UgY2FuIG5vdyBjbGljayB0aGUgIkNvbmZpcm0gQ3VycmVudCBXb3JrZmxvdyIgYnV0dG9uLiBPbiB0aGUgbGVmdAptZW51LCB5b3Ugd2lsbCBzZWUgdGhhdCB0aGUgM3JkIGVudHJ5IG5vdyBtZW50aW9ucyAiMyBQcmUtcHJvY2Vzc2luZwooNyBTdGVwcykiLiBXZSB3aWxsIG5vdyBjb25maWd1cmUgYW5kIHJ1biBlYWNoIG9mIHRoZXNlIHN0ZXBzLgoKIyMjIFN0ZXAgMTogTG9nIHRyYW5zZm9ybWF0aW9uCgpGb3IgZXZlcnkgc3RlcCwgeW91IGFsd2F5cyBuZWVkIHRvIGxvYWQgdGhlIGRhdGEgZnJvbSB0aGUgcHJldmlvdXMKc3RlcCAoaW4gdGhpcyBjYXNlIHRoZSBkYXRhIGltcG9ydGF0aW9uKS4gQ2xpY2sgb24gdGhlICJMb2FkIGFzc2F5cwpmcm9tIHByZXZpb3VzIHN0ZXAiIGJ1dHRvbi4gT25jZSBsb2FkZWQsIHRoZSBkYXRhIGlzIGF1dG9tYXRpY2FsbHkKbG9nMi10cmFuc2Zvcm1lZCBieSBkZWZhdWx0LiBZb3Ugc2hvdWxkIG5vdCBjaGFuZ2UgdGhlIGRlZmF1bHRzLiBZb3UKd2lsbCBzZWUgdGhhdCB0aGUgaW50ZW5zaXR5IGRpc3RyaWJ1dGlvbiB3aXRoaW4gZWFjaCBzYW1wbGUgaXMKYXV0b21hdGljYWxseSBwaWN0dXJlZCwgYW5kIHlvdSBjYW4gcGxheSB3aXRoIHRoZSBwbG90IHNldHRpbmcgKGJvdHRvbQpyaWdodCkgYXMgeW91IHdpc2guIFlvdXIgc2NyZWVuIHNob3VsZCBiZSBzaW1pbGFyIHRvIHRoaXM6IAoKIVtGaWd1cmUgOS4gU3RlcDE6IExvZyB0cmFuc2Zvcm1hdGlvbl0oLi9maWd1cmVzL3N0ZXAxLnBuZykKCk9uY2UgeW91IGFyZSBkb25lLCBjbGljayB0aGUgIlNhdmUgdGhlIHByb2Nlc3NlZCBkYXRhIiBidXR0b24uIFRoaXMKd2lsbCBzdG9yZSB0aGUgY2hhbmdlcyBhbmQgbWFrZSB0aGUgZGF0YSBhdmFpbGFibGUgZm9yIHRoZSBuZXh0IHN0ZXAuCklmIHlvdSBmb3JnZXQgdG8gY2xpY2sgdGhpcyBidXR0b24sIGxvYWRpbmcgdGhlIG5leHQgc3RlcCB3aWxsIGxlYWQgdG8KYW4gZXJyb3IuCgojIyMgU3RlcCAyOiBhZGQgYW5ub3RhdGlvbnMKCkluIFN0ZXAgMywgd2Ugd2lsbCBmaWx0ZXIgb3V0IGZlYXR1cmVzIGJhc2VkIG9uIHRoZW4gbnVtYmVyIG9mIG1pc3NpbmcKdmFsdWVzLiBUaGlzIGluZm9ybWF0aW9uIGlzIG5vdCB5ZXQgYXZhaWxhYmxlIGluIG91ciBkYXRhIGZvcgpmaWx0ZXJpbmcsIHNvIHdlIHdpbGwgYWRkIHRoaXMgaW5mb3JtYXRpb24gYXMgYSBmZWF0dXJlIGFubm90YXRpb24uCgoxLiBNb3ZlIHRvIFN0ZXAgMiBpbiB0aGUgbGVmdCBtZW51LgoyLiBDbGljayB0aGUgYnV0dG9uIHRvIGxvYWQgdGhlIHByZXZpb3VzIHN0ZXAuIAozLiBTY3JvbGwgYXQgdGhlIGJvdHRvbSBhbiB0aWNrIHRoZSAiQWRkIG1pc3NpbmcgdmFsdWVzIG51bWJlcnMiIGJveAo0LiBDbGljayAicGVyZm9ybSBhbm5vdGF0aW9uIi4gWW91IHNob3VsZCBzZWUgYSBwcmV2aWV3IG9mIHRoZSBmZWF0dXJlCiAgIGFubm90YXRpb25zLiBZb3UgY2FuIGNoZWNrIHRoYXQgdGhlIGxhc3QgY29sdW1uIGlzICJuTkEiIHdoaWNoIAogICBwcm92aWRlcyB0aGUgbnVtYmVyIG9mIG1pc3NpbmcgdmFsdWVzLgo1LiBDbGljayB0aGUgYnV0dG9uIHRvIHNhdmUgdGhlIHByb2Nlc3NlZCBkYXRhLgoKIyMjIFN0ZXAgMzogcGVwdGlkZSBmaWx0ZXJpbmcKCkluIHRoaXMgc3RlcCwgd2Ugd2lsbCBhY3R1YWxseSByZW1vdmUgdW5kZXNpcmFibGUgcGVwdGlkZXMuIFdlIHdpbGwKdXNlIHRoZSBmb2xsb3dpbmcgY3JpdGVyaWE6CgotIFJlbW92ZSBwZXB0aWRlcyB0aGF0IGNvdWxkIG5vdCBiZSBtYXBwZWQgdG8gYSBwcm90ZWluLiBJbiB0aGUgcGVwdGlkZXMudHh0IGZpbGUgb2YgTWF4UXVhbnQgdGhlIHZhcmlhYmxlIFByb3RlaW5zIGNvbnNpc3RzIG9mIGFuIGVtcHR5IGNoYXJhY3RlcjogYFByb3RlaW5zICE9IGAgCi0gUmVtb3ZlIHJldmVyc2Ugc2VxdWVuY2VzIChkZWNveXMpLiBJbiB0aGUgcGVwdGlkZXMudHh0IGZpbGUgb2YgTWF4UXVhbnQgdGhlIHZhcmlhYmxlIFJldmVyc2UgaXMgYW4gZW1wdHkgY2hhcmFjdGVyIGZvciBmb3J3YXJkIHNlcXVlbmNlcyAodGFyZ2V0cykgYW5kIGFuICIrIiBjaGFyYWN0ZXIgZm9yIHJldmVyc2Ugc2VxdWVuY2VzOiBgUmV2ZXJzZSAhPSArYAotIFJlbW92ZSBjb250YW1pbmFudHMuIEluIHRoZSBwZXB0aWRlcy50eHQgZmlsZSBvZiBNYXhRdWFudCB0aGUgdmFyaWFibGUgIkNvbnRhbWluYW50cyIgb3IgIlBvdGVudGlhbC5jb250YW1pbmFudCIgYW4gZW1wdHkgY2hhcmFjdGVyIGZvciBub24tY29udGFtaW5hbnQgc2VxdWVuY2VzIGFuZCBhICIrIiBjaGFyYWN0ZXIgZm9yIGNvbnRhbWluYW50IHNlcXVlbmNlczogYFBvdGVudGlhbC5jb250YW1pbmFudCAhPSArYAotIFJlbW92ZSBwZXB0aWRlcyB0aGF0IHdlcmUgaWRlbnRpZmllZCBpbiBsZXNzIHRoYW4gdGhyZWUgc2FtcGxlLiBUaGVyZSBhcmUgNiBzYW1wbGVzIHNvIHRoZXJlIG51bWJlciBvZiBOQSdzIGhhcyB0byBiZSBzbWFsbGVyIG9yIGVxdWFsIHRvOiBgbk5BIDw9IDNgCgpUbyBwZXJmb3JtIHRoaXMgZmlsdGVyaW5nIGFuZCBjYXJyeSBvdXQgdGhlIHNlcCwgeW91IGNhbjoKCjEuIE1vdmUgdG8gU3RlcCAzIGluIHRoZSBsZWZ0IG1lbnUuCjIuIENsaWNrIHRoZSBidXR0b24gdG8gbG9hZCB0aGUgcHJldmlvdXMgc3RlcC4gCjMuIENsaWNrIDR4IHRoZSBibHVlICJBZGQgQm94IiBidXR0b24gdG8gYWRkIDQgZmlsdGVyaW5nIGJveGVzLgo0LiBGaWxsIGluIHRoZSBib3hlcyBhcyBzaG93biBpbiB0aGUgZmlndXJlIGJlbG93Lgo1LiBJbiB0aGUgIkZpbHRlcmluZyBTdW1tYXJ5IiB0aWxlLCBjbGljayB0aGUgIkFwcGx5IEZpbHRlcnMiIGJ1dHRvbi4KNi4gQ2xpY2sgdGhlIGJ1dHRvbiB0byBzYXZlIHRoZSBwcm9jZXNzZWQgZGF0YS4KCiFbRmlndXJlIDEwLiBTdGVwMzogRmVhdHVyZSBmaWx0ZXJpbmcuIE5vdGUgdGhlIFBDQSBwbG90cyBhcmUgY29sbGFwc2VkIGZvciBiZXR0ZXIgb3ZlcnZpZXcgb2YgdGhlIGJveGVzLl0oLi9maWd1cmVzL3N0ZXAzLnBuZykKCiMjIyBTdGVwIDQ6IE5vcm1hbGlzYXRpb24KCldlIG5vcm1hbGlzZSB0aGUgZGF0YSBieSBzdWJzdHJhY3RpbmcgdGhlIHNhbXBsZSBtZWRpYW4gZnJvbSBldmVyeQppbnRlbnNpdHkgZm9yIHBlcHRpZGUgJHAkICBpbiBhIHNhbXBsZSAkaSQ6CgokJHlfe2lwfV5cdGV4dHtub3JtfSA9IHlfe2lwfSAtIFxoYXR7XG11X2l9JCQKCndpdGggJFxoYXRcbXVfaSQgdGhlIG1lZGlhbiBpbnRlbnNpdHkgb3ZlciBhbGwgb2JzZXJ2ZWQgcGVwdGlkZXMgaW4Kc2FtcGxlICRpJC4KCjEuIE1vdmUgdG8gU3RlcCA0IGluIHRoZSBsZWZ0IG1lbnUuCjIuIENsaWNrIHRoZSBidXR0b24gdG8gbG9hZCB0aGUgcHJldmlvdXMgc3RlcC4KMy4gTWVkaWFuIG5vcm1hbGlzYXRpb24gaXMgY29uZmlndXJlZCBieSBkZWZhdWx0LCBzbyB5b3UgY2FuIHNpbXBseQogICBjbGljayB0aGUgYnV0dG9uIHRvIHNhdmUgdGhlIHByb2Nlc3NlZCBkYXRhLgoKIyMjIFN0ZXAgNTogU3VtbWFyaXNhdGlvbgoKSW4gdGhpcyBzdGVwLCB0aGUgcGVwdGlkZSBpbnRlbnNpdGllcyB3aWxsIGJlIHN1bW1hcmlzZWQgKGFrYQphZ2dyZWdhdGVkKSBpbnRvIHByb3RlaW4gaW50ZW5zaXRpZXMgdXNpbmcgcm9idXN0IHN1bW1hcmlzYXRpb24uIFlvdQpjYW4gcGVyZm9ybSB0aGlzIGFzIGZvbGxvd3M6CgoxLiBNb3ZlIHRvIFN0ZXAgNSBpbiB0aGUgbGVmdCBtZW51LgoyLiBDbGljayB0aGUgYnV0dG9uIHRvIGxvYWQgdGhlIHByZXZpb3VzIHN0ZXAuCjMuIEluIHRoZSBzZXR0aW5ncywgZmlyc3Qgc2VsZWN0ICJyb2J1c3RTdW1tYXJ5IiBpbiB0aGUgZmlyc3QgZmllbGQgYW5kCiAgIHRoZW4gc2VsZWN0ICJQcm90ZWlucyIgYXMgdGhlIHJvd0RhdGEgdmFyaWFibGUgZGVmaW5pbmcgdGhlIGZlYXR1cmVzIG9mCiAgIHRoZSBhc3NheSB0byBhZ2dyZWdhdGUuCjQuIENsaWNrIHRoZSBidXR0b24gdG8gc2F2ZSB0aGUgcHJvY2Vzc2VkIGRhdGEuCgojIyMgU3RlcCA2OiBhZGQgYW5ub3RhdGlvbnMKClJlcGVhdCBzdGVwIDIsIHRoaXMgd2lsbCBhbGxvdyB0byBwZXJmb3JtIGEgZmlsdGVyaW5nIG9uIG1pc3NpbmcsIGJ1dAphdCB0aGUgcHJvdGVpbi1sZXZlbCBpbnN0ZWFkIG9mIHBlcHRpZGUtbGV2ZWwuCgojIyMgU3RlcCA3OiBwcm90ZWluIGZpbHRlcmluZwoKSW4gdGhpcyBzdGVwLCB3ZSB3aWxsIHJlbW92ZSBwcm90ZWlucyB0aGF0IHdlcmUgaWRlbnRpZmllZCBpbiBsZXNzCnRoYW4gNCBzYW1wbGVzIHNvIHRoYXQgZm9yIG1vc3QgcHJvdGVpbnMgYXQgbGVhc3QgdHdvIHByb3RlaW4tbGV2ZWwgZXhwcmVzc2lvbiB2YWx1ZXMgYXJlIG9ic2VydmVkIGluIGVhY2ggdHJlYXRtZW50IGdyb3VwLiBTbyB3ZSB3aWxsIHRvbGVyYXRlIGF0IG1vc3QgNi00ID0gMiBtaXNzaW5nIHZhbHVlcyBhdCB0aGUgcHJvdGVpbi1sZXZlbC4gWW91IG1heSBoYXZlIGd1ZXNzZWQgaXQgYnkgbm93LCBidXQgeW91IGNhbiBwcm9jZWVkIAp3aXRoOgoKMS4gTW92ZSB0byBTdGVwIDcgaW4gdGhlIGxlZnQgbWVudS4KMi4gQ2xpY2sgdGhlIGJ1dHRvbiB0byBsb2FkIHRoZSBwcmV2aW91cyBzdGVwLiAKMy4gQ2xpY2sgMXggdGhlIGJsdWUgIkFkZCBCb3giIGJ1dHRvbiB0byBhZGQgYSBmaWx0ZXJpbmcgYm94Lgo0LiBGaWxsIGluIHRoZSBib3hlcyBzbyB0aGF0IHRoZSBmaWx0ZXIgYmVjb21lczogYG5OQSA8PSAyYC4KNS4gSW4gdGhlICJGaWx0ZXJpbmcgU3VtbWFyeSIgdGlsZSwgY2xpY2sgdGhlICJBcHBseSBGaWx0ZXJzIiBidXR0b24uCjYuIENsaWNrIHRoZSBidXR0b24gdG8gc2F2ZSB0aGUgcHJvY2Vzc2VkIGRhdGEuCgojIyMgU2F2ZSB5b3VyIHByb2dyZXNzCgpZb3Ugbm93IGhhdmUgY29tcGxldGVkIHRoZSBkYXRhIHByb2Nlc3NpbmcuIFlvdSBjYW4gbW92ZSB0byB0aGUKU3VtbWFyeSB0YWIgKGluIHRoZSBsZWZ0IG1lbnUpLiBUaGVyZSB5b3Ugd2lsbCBmaW5kIGFuIG92ZXJ2aWV3IG9mIHRoZQpkYXRhIGFuZCB0aGUgZGF0YSBwcm9jZXNzaW5nIHN0ZXBzLgoKIVtGaWd1cmUgMTEuIFN1bW1hcnkgb2YgdGhlIGRhdGEgcHJvY2Vzc2luZy5dKC4vZmlndXJlcy9wcm9jZXNzaW5nX3N1bW1hcnkucG5nKQoKR28gdG8gdGhlIGJvdHRvbSBvZiB0aGUgcGFnZSBhbmQgY2xpY2sgb24gdGhlICJEb3dubG9hZCBRRmVhdHVyZXMiCmJ1dHRvbi4gQSBwb3AgdXAgd2luZG93biB3aWxsIGFzayB5b3UgdG8gc2VsZWN0IGEgZGlyZWN0b3J5IHRvIHN0b3JlCnRoZSByZXN1bHRpbmcgZmlsZS4gQnkgZGVmYXVsdCB0aGUgZmlsZSBpcyBjYWxsZWQKYHFmZWF0dXJlc19vYmplY3QucmRzYCwgYnV0IGZlZWwgZnJlZSB0byByZW5hbWUgYXMgeW91IHdpc2ggYnV0IHlvdQpjYW5ub3QgY2hhbmdlIHRoZSBmaWxlIGV4dGVuc2lvbiAoYC5yZHNgKS4KCllvdSBjYW4gbm93IGNsb3NlIHRoZSBhcHBsaWNhdGlvbi4KCiMjIFN0YXRpc3RpY2FsIGFuYWx5c2lzCgojIyMgT3BlbiBgbXNxcm9iMmd1aWAgCgpSZXR1cm4gdG8geW91ciBSc3R1ZGlvIGFwcGxpY2F0aW9uIGFuZCBydW4gdGhlIGZvbGxvd2luZyBjb21tYW5kOgoKYGBge3IsIGV2YWw9RkFMU0V9Cm1zcXJvYjJndWk6OmxhdW5jaE1zcXJvYjJBcHAoKQpgYGAKCkEgbmV3IHdpbmRvdyB3aWxsIG9wZW4gd2l0aCB0aGUgc2hpbnlBcHAgZm9yIGRhdGEgbW9kZWxsaW5nCgohW0ZpZ3VyZSAxMi4gbXNxcm9iMmd1aSBTaGlueUFwcF0oLi9maWd1cmVzL21zcXJvYjJndWlfZnJlc2gucG5nKQoKIyMjIEltcG9ydCB0aGUgcHJvY2Vzc2VkIGRhdGEKCldlIHN0YXJ0IHRoZSBkYXRhIG1vZGVsbGluZyB3b3JrZmxvdyB3aXRoIGltcG9ydGluZyB0aGUgZGF0YSBwcm9jZXNzZWQKaW4gdGhlIHByZXZpb3VzIHNlY3Rpb246CgoxLiBDbGljayBvbiAiQnJvd3Nlci4uLiIgYW5kIGZldGNoIHRoZSBmaWxlIHlvdSBzYXZlZCB3aXRoIHRoZQogICBgUUZlYXR1cmVzR1VJYCBhcHAuCjIuIEluIHRoZSAiU2VsZWN0IEFzc2F5Iiwgc2VsZWN0IHRoZSBsYXN0IGl0ZW0sCiAgICJxdWFudHNfZmVhdHVyZXNfZmlsdGVyaW5nXzciLgoKVGhlIGFwcGxpY2F0aW9uIGxldCdzIHlvdSBleHBsb3JlIHRoZSBkYXRhIHRhYmxlcyBhbmQgcHJvdmlkZXMgYSBwbG90CndpdGggdGhlIGludGVuc2l0eSBkaXN0cmlidXRpb25zIGZvciBlYWNoIHNhbXBsZS4KCiFbRmlndXJlIDEzLiBtc3Fyb2IyZ3VpIGFwcGxpY2F0aW9uIHVwb24gZGF0YSBpbXBvcnQuXSguL2ZpZ3VyZXMvbXNxcm9iMl9pbXBvcnRlZC5wbmcpCgpXaGVuIHlvdSBzY3JvbGwgZG93biB0aGUgcGFnZSwgeW91IHdpbGwgZmluZCBhIGRyb3AgZG93biB0ZXh0IHNlbGVjdG9yCih1bmRlciB0aGUgdGFibGUpLiBDaGFuZ2UgInJ1biIgaW50byAidHJlYXRtZW50IiBhbmQgbG9vayBhdCB0aGUKcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcyAoUENBKSBwbG90LiBIb3cgd291bGQgeW91IGludGVycHJldCB0aGlzCmdyYXBoPwoKIVtGaWd1cmUgMTQuIFBDQSBwbG90IG9mIHRoZSBDUFRBQyBkYXRhIHNldC5dKC4vZmlndXJlcy9tc3Fyb2IyX3BjYS5wbmcpCgpUaGUgUENBIHBsb3QgaW5kaWNhdGVzIHRoYXQgd2UgY2FuIGV4cGVjdCBhIHRyZWF0bWVudCBlZmZlY3QgaW4gdGhlCmRhdGEgYXMgdGhlIHNhbXBsZSBiZWxvbmdpbmcgdG8gb25lIHRyZWF0bWVudCBjYW4gYmUgc2VwYXJhdGVkIGZyb20KdGhlIHNhbXBsZXMgYmVsb25naW5nIHRvIHRoZSBvdGhlciB0cmVhdG1lbnQuIFdlIGFsc28gc2VlIHRoYXQgdGhpcwpzZXBhcmF0aW9uIG1vc3RseSBvY2N1cnMgaW4gdGhlIHNlY29uZCBwcmluY2lwYWwgY29tcG9uZW4uIFRoZSBmaXJzdApjb21wb25lbnQsIHdoaWNoIGV4cGxhaW5zIG1vc3Qgb2YgdGhlIHZhcmlhdGlvbiwgZG9lcyBub3Qgc2VlbSB0byBiZWFyCmNvcnJlbGF0aW9uIGFzc29jaWF0ZWQgd2l0aCB0cmVhdG1lbnQuIFRoaXMgaXMgZXhwZWN0ZWQgYXMgd2Uga25vdwp0aGF0IG9ubHkgYSBmZXcgcHJvdGVpbiB3ZXJlIHNwaWtlZCBpbiwgc28gd2UgZG8gbm90IGV4cGVjdCBhbiBlZmZlY3QKb2YgdHJlYXRtZW50IGZvciBtb3N0IHByb3RlaW5zLiBXZSB3aWxsIG5vdyBkZWx2ZSBpbnRvIHRoZSBkYXRhCm1vZGVsbGluZyBhbmQgaW5mZXJlbmNlIHRoYXQgd2lsbCBzdGF0aXN0aWNhbGx5IHF1YW50aWZ5IHRoZXNlIGVmZmVjdHMKZm9yIGVhY2ggcHJvdGVpbiBpbmRpdmlkdWFsbHkuCgojIyMgRGF0YSBtb2RlbGxpbmcKCllvdSBjYW4gbm93IG1vdmUgdG8gdGhlIGRhdGEgbW9kZWxsaW5nIHRhYiBieSBjbGlja2luZyAiTW9kZWwiIGluIHRoZQptZW51IG9uIHRoZSBsZWZ0LiAKCldlIHdpbGwgbW9kZWwgdGhlIGRhdGEgd2l0aCBhIGRpZmZlcmVudCBncm91cCBtZWFuIGZvciB0aGUgdmFyaWFibGUKYHRyZWF0bWVudGAgd2l0aCB0d28gbGV2ZWxzOiBzcGlrZWluIHRyZWF0bWVudCBBIGFuZCBCLiBXZSBjYW4gc3BlY2lmeQp0aGlzIG1vZGVsIGJ5IGluc2VydGluZyBgfjErdHJlYXRtZW50YCBpbiB0aGUgIkRlc2lnbiBmb3JtdWxhIgp0ZXh0Ym94LiBOb3RlLCB0aGF0IGEgZm9ybXVsYSBhbHdheXMgc3RhcnRzIHdpdGggYSBzeW1ib2wgJ34nIChzZWUgdGhlCmRlc2NyaXB0aXZlIHBhcmFncmFwaCBpbiB0aGUgYXBwbGljYXRpb24pLgoKTm90ZSB0aGF0IGFzIHNvb24gYXMgd2UgZG8gdGhhdCwgdGhlIGRlc2lnbiBpcyB2aXN1YWxpc2VkLiAKCiFbRmlndXJlIDE1LiBtc3Fyb2IyIE1vZGVsIHRhYiB3aXRoIGRlc2lnbl0oLi9maWd1cmVzL21zcXJvYjJfbW9kZWwucG5nKQoKVGhpcyB2aXN1YWxpc2F0aW9uIHNob3dzIHRoZSBkaWZmZXJlbnQgZ3JvdXAgbWVhbnMgdGhhdCBhcmUgbW9kZWxsZWQuIAoKLSBUaGUgZ3JvdXAgbWVhbiBmb3IgdGhlIHRyZWF0bWVudCBBIGlzIG1vZGVsbGVkIHVzaW5nIHRoZSBwYXJhbWV0ZXIgCiAgYChJbnRlcmNlcHQpYC4gCi0gVGhlIGdyb3VwIG1lYW4gZm9yIHRoZSB0cmVhdG1lbnQgQiBpcyBtb2RlbGxlZCB1c2luZyBhIGxpbmVhciAKICBjb21iaW5hdGlvbiBvZiB0aGUgdHdvIG1vZGVsIHBhcmFtZXRlcnMgYChJbnRlcmNlcHQpICsgdHJlYXRtZW50QmAuCi0gVGhlIGF2ZXJhZ2UgZGlmZmVyZW5jZSBpbiBwcmVwcm9jZXNzZWQgcHJvdGVpbiBleHByZXNzaW9uIHZhbHVlIAogIGJldHdlZW4gYm90aCBjb25kaXRpb25zIGVxdWFscyBgdHJlYXRtZW50QmAuCgpSZW1lbWJlciB0aGF0IHdlIGxvZy10cmFuc2Zvcm1lZCB0aGUgaW50ZW5zaXRpZXM6CgokJCAKXGxvZ18yRkNfXHRleHR7Qn09XGxvZ18yIEIgLSBcbG9nXzIgQSA9IFxsb2dfMlxmcmFje0J9e0F9ID0gXHRleHR7dHJlYXRtZW50Qn0KJCQKCk5vdGUgdGhhdCBhIGxpbmVhciBjb21iaW5hdGlvbiBvZiBtb2RlbCBwYXJhbWV0ZXJzIGlzIGFsc28gcmVmZXJyZWQgdG8KYXMgYSBjb250cmFzdCBpbiBzdGF0aXN0aWNzLiBUaGlzIGNvbnRyYXN0IGhhcyB0aGUgaW50ZXJwcmV0YXRpb24gb2YgYQpsb2cyIGZvbGQgY2hhbmdlIGJldHdlZW4gY29uZGl0aW9uIEIgYW5kIGNvbmRpdGlvbiBBLiBQb3NpdGl2ZQplc3RpbWF0ZXMgZGVub3RlIHRoYXQgdGhlIGFidW5kYW5jZSBvZiB0aGUgcHJvdGVpbiBpcyBvbiBhdmVyYWdlCmhpZ2hlciBpbiBjb25kaXRpb24gQiwgbmVnYXRpdmUgZXN0aW1hdGVzIGRlbm90ZSB0aGF0IHRoZSBhYnVuZGFuY2UgaXMKb24gYXZlcmFnZSBoaWdoZXIgaW4gY29uZGl0aW9uIEEuIEFuIGVzdGltYXRlIGVxdWFsIHRvIDAgaW5kaWNhdGVzCnRoYXQgdGhlIGVzdGltYXRlZCBhYnVuZGFuY2VzIGFyZSBlcXVhbC4KCkEgbG9nMiBGQyA9IDEgaW5kaWNhdGVzIHRoYXQgdGhlIGF2ZXJhZ2UgYWJ1bmRhbmNlIGluIGNvbmRpdGlvbiBCIGlzIDIKeCBoaWdoZXIgdGhhbiB0aGUgYXZlcmFnZSBhYnVuZGFuY2UgaW4gY29uZGl0aW9uIEEsIGkuZS4gYW4gMiBmb2xkCnVwcmVndWxhdGlvbiBpbiBjb25kaXRpb24gQiBhcyBjb21wYXJlZCB0byBjb25kaXRpb24gQS4KCldlIG5vdyBoYXZlIHRvIGNsaWNrIHRoZSBgRml0IE1vZGVsIWAgYnV0dG9uIHRvIGZpdCB0aGUgbW9kZWxzIGZvcgplYWNoIHByb3RlaW4uIFdlIGFyZSBub3cgcmVhZHkgZm9yIGFzc2Vzc2luZyBkaWZmZXJlbnRpYWwgYWJ1bmRhbmNlIG9mCmVhY2ggcHJvdGVpbiB1c2luZyBmb3JtYWwgaHlwb3RoZXNpcyB0ZXN0aW5nLgoKIyMjIEluZmVyZW5jZQoKQ2xpY2sgb24gdGhlICJJbmZlcmVuY2UiIHRhYiBpbiB0aGUgbGVmdCBtZW51LgoKSW4gdGhlIHN0YXRpc3RpY2FsIGFuYWx5c2lzIHdlIHdpbGwgd2FudCB0byB0ZXN0IHRoZSBudWxsIGh5cG90aGVzaXMKdGhhdAoKJCQgSF8wOiBcbG9nXzIgQi1cbG9nXzIgNkEgPSAwICQkCgpBZ2FpbnN0IHRoZSBhbHRlcm5hdGl2ZSB0aGF0CgokJCBIXzE6IFxsb2dfMiBCIC0gXGxvZ18yIEEgXG5lcSAwICQkCgpXZSBjYW4gc3BlY2lmeSB0aGUgbnVsbCBoeXBvdGhlc2lzIGFzIGEgbGluZWFyIGNvbWJpbmF0aW9uIG9mIHRoZQptb2RlbCBwYXJhbWV0ZXJzLCBpLmUuIGB0cmVhdG1lbnRCID0gMGAuIFdlIHdpbGwgZmFsc2lmeSB0aGlzIG51bGwKaHlwb3RoZXNpcyBmb3IgZWFjaCBwcm90ZWluIHNlcGFyYXRlbHkgYmFzZWQgb24gdGhlIGxpbmVhciBtb2RlbC4gU28sCnVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMgd2UgcmVhc29uIHRoYXQgdGhlcmUgaXMgbm8gZWZmZWN0IG9mIHRoZQpzcGlrZS1pbiB0cmVhdG1lbnQgb24gdGhlIGFidW5kYW5jZSBvZiBhIHNwZWNpZmljIHByb3RlaW4uIFRoZSBwLXZhbHVlCm9mIHRoZSBzdGF0aXN0aWNhbCB0ZXN0IHRoYW4gaW5kaWNhdGVzIHRoZSBwcm9iYWJpbGl0eSB0byBvYnNlcnZlIGFuCmVmZmVjdCAoZm9sZCBjaGFuZ2UpLCB0aGF0IGlzIGFzIGV4dHJlbWUgb3IgbW9yZSBleHRyZW1lIChlcXVhbGx5IG9yCm1vcmUgdXAgb3IgZG93biByZWd1bGF0ZWQpIHRoYW4gd2hhdCBpcyBvYnNlcnZlZCBpbiB0aGUgc2FtcGxlLCBieQpyYW5kb20gY2hhbmdlICh3aGVuIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgdHJ1ZSBhbmQgd2hlbiB0aGVyZSBpcyBpbgpyZWFsaXR5IG5vIGVmZmVjdCBvZiB0aGUgdHJlYXRtZW50KS4KClRvIHByb2NlZWQsIGZpbGwgaW4gdGhlIGZpZWxkICJOdWxsIGh5cG90aGVzaXMiIHdpdGggYHRyZWF0bWVudEIgPSAwYC4KQWZ0ZXIgMS0yIHNlY29uZCwgdGhlIHdpbmRvdyBpcyB1cGRhdGVkIAoKIVtGaWd1cmUgMTYuIG1zcXJvYjIgSW5mZXJlbmNlIHRhYiB3aXRoIGNvbnRyYXN0XSguL2ZpZ3VyZXMvbXNxcm9iMl9pbmZlcmVuY2UucG5nKQoKIyMjIyBWb2xjYW5vIHBsb3QKClRoZSBhcHBsaWNhdGlvbiBub3cgYWxzbyBwcm92aWRlcyBhIHZvbGNhbm8gcGxvdCBhcHBlYXJzIGdpdmluZyB5b3UgYQp2aWV3IG9uIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBpbiB0aGUgeS1heGlzLCBpLmUuIHRoZSAkLVxsb2dfezEwfSQKdHJhbnNmb3JtZWQgcC12YWx1ZTogYSB2YWx1ZSBvZiAxIGVxdWFscyB0byBhIHAtdmFsdWUgb2YgMC4xLCBhIHZhbHVlCm9mIDIgZXF1YWxzIGEgcC12YWx1ZSBvZiAwLjAxLCBldGMgYWdhaW5zdCBiaW9sb2dpY2FsIHJlbGV2YW5jZS90aGUKZWZmZWN0IHNpemUgaW4gdGhlIHgtYXhpcywgd2hpY2ggaXMgdGhlICRcbG9nXzJGQyQuCgojIyMjIFJlc3VsdCB0YWJsZQoKWW91IGFsc28gZ2V0IGEgdGFibGUgd2l0aCBzZWxlY3RlZCBmZWF0dXJlLiBCeSBkZWZhdWx0IHRoZXNlIGFyZSBhbGwKcHJvdGVpbnMgdGhhdCBhcmUgc2lnbmlmaWNhbnQgd2l0aCB0aGUgc3BlY2lmaWVkICJTaWduaWZpY2FuY2UgbGV2ZWwiCmZpZWxkLiBZb3UgYWxzbyBvYnRhaW4gYSBib3hwbG90IG9mIHRoZSBsb2cyLWZvbGQgY2hhbmdlcyBmb3IgYWxsCnByb3RlaW5zIHRoYXQgYXJlIHNlbGVjdGVkIGluIHRoZSB0YWJsZS4KCk5vdGUgdGhhdCAxOSBwcm90ZWlucyBhcmUgcmVjb3ZlcmVkIGFzIHNpZ25pZmljYW50LiBBcyBleHBlY3RlZCBhbGwKdGhlc2UgcHJvdGVpbnMgYXJlIFVQUyBwcm90ZWlucyB3aGljaCBhcmUga25vd24gdG8gYmUgc3Bpa2VkIGluIHRoZQpzYW1wbGVzLiBJZiB5b3UgdW50aWNrIHRoZSBvcHRpb24gYG9ubHkgc2lnbmlmaWNhbnQgZmVhdHVyZXMgaW4KdGFibGVgLCBhbGwgcHJvdGVpbnMgYXJlIHNob3duIGluIHRoZSB0YWJsZS4KCllvdSBjYW4gaGlnaGxpZ2h0IHByb3RlaW5zIG9uIHRoZSB2b2xjYW5vIHBsb3QgYnkgc2VsZWN0aW5nIGxpbmVzIG9mCmludGVyZXN0IGluIHRoZSByZXN1bHQgdGFibGUuIFlvdSBjYW4gYWxzbyBzZWFyY2ggZm9yIHNwZWNpZmljCnByb3RlaW5zIGluIHRoZSBsaXN0IGJ5IHVzaW5nIHRoZSBzZWFyY2ggZmllbGQgYWJvdmUgdGhlIHRhYmxlLiBFLmcuCnR5cGUgYHVwc2AuCgojIyMjIERldGFpbCBwbG90cwoKSWYgeW91IHNlbGVjdCBvbmUgcHJvdGVpbiBpbiB0aGUgdGFibGUsIHlvdSBjYW4gYWxzbyBleHBsb3JlIHRoZQp1bmRlcmx5aW5nIG5vcm1hbGlzZWQgcGVwdGlkZSBpbnRlbnNpdGllcyBhbmQgcHJvdGVpbiBpbnRlbnNpdGllcyBvZgp0aGUgdW5kZXJseWluZyBkYXRhIGluIHRoZSAiRGV0YWlsUGxvdHMiOgoKIVtGaWd1cmUgMTcuIG1zcXJvYjIgZGV0YWlsIHBsb3RzLl0oLi9maWd1cmVzL21zcXJvYjJfZGV0YWlscGxvdHMucG5nKQoKWW91IGNhbiBmdXJ0aGVyIG1vZGlmeSB0aGUgcGxvdCBieSBjb2xvcmluZyB0aGUgZGF0YSBhY2NvcmRpbmcgdG8gYQpkZXNpZ24gdmFyaWFibGUgb3IgYnkgc3BsaXR0aW5nIHRoZSBkYXRhIGhvcml6b250YWxseSBvciB2ZXJ0aWNhbGx5CmFjY29yZGluZyB0byBkZXNpZ24gdmFyaWFibGVzLgoKIyMgUmVwb3J0IFRhYgoKQSByZXByb2R1Y2libGUgUm1hcmtkb3duIHNjcmlwdCBhbmQgaHRtbCByZXBvcnQgd2l0aCB0aGUgYW5hbHlzaXMgeW91CnBlcmZvcm1lZCB3aXRoIHRoZSBHVUkgY2FuIGJlIGRvd25sb2FkZWQgaW4gdGhlICJSZXBvcnQiIHRhYi4KCiFbRmlndXJlIDE4LiBtc3Fyb2IyIHJlcG9ydCB0YWJdKC4vZmlndXJlcy9tc3Fyb2IyX3JlcG9ydC5wbmcpCgoxLiBQcm92aWRlIGEgbmFtZSB0byB5b3VyIHByb2plY3QKMi4gWW91IGNhbiBzcGVjaWZ5IHRoZSBudW1iZXIgb2YgZGV0YWlsIHBsb3RzIHlvdSB3YW50IHRvIGdlbmVyYXRlIGluCiAgIHRoZSByZXBvcnQuIFRoZSBkZWZhdWx0IGlzIDEwLCB3aGljaCBpbmRpY2F0ZXMgdGhhdCBkZXRhaWwgcGxvdHMKICAgd2lsbCBiZSBjb25zdHJ1Y3RlZCBmb3IgdGhlIDEwIG1vc3Qgc2lnbmlmaWNhbnQgcHJvdGVpbiBpbiB5b3VyIHRvcAogICBsaXN0LiBOb3RlLCB0aGF0IHRoZSBudW1iZXIgb2YgZGV0YWlsIHBsb3RzIGNhbiBiZSBzbWFsbGVyIGlmIHRoZXJlCiAgIGFyZSBsZXNzIHRoYW4gMTAgcHJvdGVpbnMgc2lnbmlmaWNhbnQgYXQgdGhlIHNwZWNpZmllZCBGRFItbGV2ZWwuCjMuIENsaWNrIHRoZSAiR2VuZXJhdGUgcmVwb3J0IiBidXR0b24gYW5kIGEgcmVwb3J0IHdpbGwgYmUgY29tcGlsZWQuCgpUaGlzIHdpbGwgY3JlYXRlIGEgemlwIGZpbGUgdGhhdCBjb250YWluczoKCi0gYHFmZWF0dXJlc0ZpbGUucmRzYDogQSB0YWIgZGVsaW1pdGVkIGZpbGUgd2l0aCB0aGUgcmF3IGludGVuc2l0eSAKICBkYXRhLgotIGByZXBvcnQuUm1kYCA6IFIvbWFya2Rvd24gZmlsZSB3aXRoIHRoZSBjb2RlIGZvciB0aGUgcmVwb3J0LiBJZiB5b3UKICBvcGVuIHRoZSBmaWxlIGluIFJzdHVkaW8gYW5kIGlmIHlvdSBoaXQgdGhlIGtuaXQgYnV0dG9uIHRoZSByZXBvcnQKICB3aWxsIGJlIGNvbXBpbGVkIHRvIGh0bWwuCgpTbywgeW91ciBhbmFseXNpcyBpcyBzdG9yZWQgaW4gYSBmdWxseSByZXByb2R1Y2libGUgd2F5LiAKCiMjIFdyYXAgdXAgZXhlcmNpc2U6IGV2YWx1YXRlIHN1bW1hcmlzYXRpb24KCldlIGZ1cnRoZXIgZXhwbG9yZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHN1bW1hcmlzYXRpb24gbWV0aG9kcy4gV2UKZmlyc3QgYXNzZXNzIHRoZSBxdWFsaXR5IG9mIHRoZSBmb2xkIGNoYW5nZSBlc3RpbWF0ZXMgZm9yIHRoZSByb2J1c3QKc3VtbWFyaXNhdGlvbi4gCgpHbyBiYWNrIHRvIHRoZSAiSW5mZXJlbmNlIiB0YWIuIFdlIHdpbGwgbWFrZSB1c2Ugb2YgdGhlIGJveHBsb3QgYXQgdGhlCmJvdHRvbSBvZiB0aGUgcXVhbnRpZmljYXRpb24gdGFiLgoKMS4gVW50aWNrIHRoZSBvcHRpb24gYG9ubHkgc2lnbmlmaWNhbnQgZmVhdHVyZXMgaW4gdGFibGVgIHRvIHNob3cgYWxsCiAgIHByb3RlaW5zIGluIHRoZSB0YWJsZS4gVGhlIGJveHBsb3QgYmVsb3cgdGhlIHRhYmxlIHZpc3VhbGlzZXMgdGhlCiAgIGxvZzIgZm9sZCBjaGFuZ2UgKEZDKSBlc3RpbWF0ZXMgZm9yIGFsbCBwcm90ZWlucyBpbiB0aGUgdGFibGUuCjIuIFdlIGNhbiBub3cgZmlsdGVyIHRoZSB1cHMgcHJvdGVpbnMgYnkgdHlwaW5nICJ1cHMiIGluIHRoZSBzZWFyY2gKICAgZmllbGQgYWJvdmUgdGhlIHRhYmxlLiBOb3cgYWxsIHllYXN0IHByb3RlaW5zIGFyZSByZW1vdmVkIGZyb20gdGhlCiAgIHJlc3VsdHMgdGFibGUgYW5kIGEgYm94cGxvdCBvZiB0aGUgdXBzIHByb3RlaW4gbG9nMiBGQ3Mgd2lsbCBiZQogICBtYWRlLgoKIVtGaWd1cmUgMTkuIG1zcXJvYjIgSW5mZXJlbmNlIHRhYiB3aXRoIEZvbGQgQ2hhbmdlIEJveHBsb3QgZm9yIGFsbCBVUFMgcHJvdGVpbnNdKC4vZmlndXJlcy9tc3Fyb2IyX3Vwcy5wbmcpCgpUcnkgYW5zd2VyaW5nIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOgoKLSBXZSBrbm93IHRoZSByZWFsIEZDIGZvciB0aGUgc3Bpa2UgaW4gcHJvdGVpbnMgKHNlZQogIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhIDIuMikuIE5vdGUsIHRoYXQgdGhlIGJveHBsb3QgaXMgc2hvd2luZyB0aGUKICBsb2cyIEZDLiBXaGF0IGRvIHlvdSBvYnNlcnZlPwotIE5vdyBzZWxlY3QgYWxsIHllYXN0IHByb3RlaW5zLiBXaGF0IGlzIHRoZSByZWFsIGZvbGQgY2hhbmdlCiAgYW5kIHdoYXQgZG8geW91IG9ic2VydmU/Ci0gQ2xvc2UgYW5kIHJlb3BlbiB0aGUgYWhpbnkgQXBwIGFuZCByZXBlYXQgdGhlIGNvbXBsZXRlIGFuYWx5c2lzLCBidXQgdGhpcyB0aW1lIGFwcGx5IHRoZSBtZWRpYW4gc3VtbWFyaXNhdGlvbiBtZXRob2QgaW4gU3RlcCA1IGluIHRoZSBkYXRhIHByZXByb2Nlc3NpbmcuIFdoYXQgZG8KICB5b3Ugb2JzZXJ2ZSwgaG93IGRvZXMgdGhhdCBjb21wYXJlIHRvIHRoZSByb2J1c3Qgc3VtbWFyaXNhdGlvbiBhbmQKICB0cnkgdG8gZXhwbGFpbiB0aGlzPwoKIyMgRmluYWwgcmVtYXJrCgpOb3RlLCB0aGF0IHRoZSBzaGlueSBhcHBzIGFyZSBpbnRlcmZhY2VzIHRvIHRoZSBzdGF0aXN0aWNhbApwcm9ncmFtbWluZyBzb2Z0d2FyZSBSLgoKVGhlIGFuYWx5c2lzIGNhbiBhbHNvIGJlIGNvbmR1Y3RlZCB1c2luZyBzY3JpcHRzLCB3aGljaCBnaXZlcyB5b3UgbXVjaAptb3JlIGZ1bmN0aW9uYWxpdHkgYW5kIHRoZSBhYmlsaXR5IHRvIHN0cmVhbWxpbmUsIGF1dG9tYXRlIGFuZApkb2N1bWVudCB5b3VyIGFuYWx5c2VzIGluIGEgcmVwcm9kdWNpYmxlIHdheS4K