Introduction

In this session we will learn how to perform pathway enrichment analysis using gene sets from our transcriptomics experiment by using two Cytoscape plugins - ClueGO and CluePedia. ClueGO and CluePedia are some of the most highly rated or top downloaded apps in the (Cytoscape App Store).

Installation

NOTE: You can also download/install plugins directly from the Cytoscape-App Store.

System Requirements:

  • Windows, Linux, Unix or MacOS operating system.
  • 16 GB RAM recommended. Hard disk with at least 100 MB free (for example files).
  • Java 1.8+ needed - VERY ESSENTIAL. This can be installed from the Download’s page in the Cytoscape website.
  • Cytoscape 3.7.+ installed: https://cytoscape.org/ - latest is version 3.10.2.

Note

This course is intended for an audience who wish to analyse biological data (with an example of RNA-Seq) and have no previous or only basic programming experience. However, for those who are keen and want to integrate Cytoscape (and its packages like ClueGO and CluePedia) using R or Python, then please refer to http://www.ici.upmc.fr/cluego/cluegoDocumentation.shtml to obtain the required API.

Basic Terms and Network Biology Background

Generally, the biological interpretation of large gene clusters derived from high-throughput experiments is a real challenge. Many ontology sources exist in order to capture biological information in a meaningful way.

  • The Gene Ontology (GO) projects [1] aims to capture the increasing knowledge on gene function in a controlled vocabulary applicable to all the organisms. GO describes gene products in terms of their associated biological processes, cellular components and molecular functions.

Between the terms there is a hierarchical relationship (parent-child). Due to the complexity of hierarchy structure (directed acyclic graph), the terms can be in several different levels. The specificity of the terms varies along the tree: from very general terms (in first levels of GO) to very specific ones.

  • Kyoto Encyclopedia of Genes and Genomes (KEGG) [2] is a database of biological systems that integrates genomic, chemical and systemic functional information.

  • BioCarta - BioCarta provides useful pathway information.

  • Reactome - Reactome is a free, open-source, curated and peer-reviewed pathway database.

  • WikiPathways - WikiPathways is an open, collaborative platform dedicated to the curation of biological pathways. WikiPathways thus presents a new model for pathway databases that enhances and complements ongoing efforts, such as KEGG, Reactome and Pathway Commons.

For a complete view on the studied process, several ontology sources should be consulted in order to integrate their complementary information. In each source, for each gene, there is a large amount of information. This makes the analysis of the relationship between genes and between terms very difficult to represent and comprehend. Also, for close related terms, a high degree of redundancy of their associated genes exists.

ClueGO

An open-source Java tool that extracts the non-redundant biological information for large clusters of genes, using GO, KEGG, Reactome, WikiPathways and BioCarta.

  • ClueGO is integrated in Cytoscape (https://cytoscape.org/) as a plug-in and it is taking advantage of its complex visualization environment.

ClueGO features include:

  • ClueGO allows analysis of a single gene set (cluster) or cluster comparison.
  • Different filter criteria can be applied to the terms.
  • Fusion of the related terms that have similar associated genes.
  • Functional grouping of the terms based on GO hierarchy or based on kappa score.
  • Visualize the selected terms in a functionally grouped network.
  • Charts presenting the specific terms and groups for the clusters compared.
  • Statistical significance for the terms and for the groups.
  • ClueGO can be used in combination with GOlorize (another Cytoscape tool for pathway enrichment) here.
  • Easy updatable.
  • Easy extendable.

Selection Panel

After starting Cytoscape, ClueGO can be found under the Plugins menu. Once selected, it will display the ClueGO selection panel options. See Figure below:

  1. Select the type of analysis. Besides analysis of a single gene set (cluster), ClueGO performs comparison of clusters, underlying the specificity and also the common aspects of their functionality.

  1. Select organism. For the moment, ClueGO supports Arabidopsis thaliana, Bos taurus, Caenorhabditis elegans, Danio rerio, Dictyostelium discoideum, Drosophila melanogaster, Escherichia coli, Galus galus, Homo sapiens, Magnaporthe grisea, Mus musculus, Oryza sativa, Rattus norvegicus and Saccharomyces cerevisiae.
  2. Select identifiers type (AffymetrixID, AccessionID, SymbolID).
  3. The identifiers can be uploaded from text files or interactively from a Cytoscape sub-network. ClueGO provides sample files containing specific genes (AccessionID) for Human B and NK cells. A Saccaromyces network sample (galFiltered.cys) can be found in the Cytoscape sampleData folder. In today’s course we will use bladder cancer data from the Data-File located in our tutorial folder. Here..
  4. Choose the any file with identifier
  • “Top_Down_genes_BLCA_Session3.txt”
  • “Top_Up_genes_BLCA_Session3.txt”
  1. Select the ontology/ontologies. To make ClueGO faster, we use precompiled files based on GO, KEGG and BioCarta. The precompiled files are included in the ClueGOPlugin.jar.
  2. Select the evidence code, option available for the GO based files. For more details, see http://www.geneontology.org/GO.evidence.shtml.
  3. Update the ontology (see ClueGO updates)
  4. The significance of each term or group can be calculated with hypergeometric test (enrichment, depletion). Standard is hypergeometric test two sided.
  5. Several methods for PValue correction are proposed: Bonferroni, Bonferroni step-down and BenjaminiHochberg.
  6. Advanced statistical options
  7. Select network type. We predefined selection criteria leading to a ”Global” network, a ”Medium” network or a ”Detailed” network. The ”Global” network displays GO terms found in the GO levels 1-3, with a high number of genes associated and a small percentage of uploaded genes found. Those terms provide a general biological information. At the opposite, the ”Detailed” network shows very specific terms placed in GO levels 9-14, with only few associated genes but a high percentage of the uploaded genes found. Those terms are more specific and informative underlying particular aspects of the studied gene product. The predefined settings provided by ClueGO should be combined with a customized selection for an analysis adapted to the biological question addressed (general/specific investigation) and to the number of genes involved.
  8. Advanced settings.
  9. Start the analysis.

ClueGO result

A functionally grouped annotation network, a ClueGO information table, charts with terms and groups and the loging information are the result of ClueGO analysis. The created networks and analysis results can be saved in a specified project folder and used for further analysis. If the analysis is not needed anymore, it is recommended to close the project.

Functionally Grouped Annotation Network

ClueGO visualizes the selected terms in a functionally grouped annotation network (See Figure 2) that reflects the relationships between the terms based on the similarity of their associated genes. The size of the nodes reflects the statistical significance of the terms. The degree of connectivity between terms (edges) is calculated using kappa statistics, in a similar way as described in [4]. The calculated kappa score is also used for defining functional groups. A term can be included in several groups. The reocurrence of the term is shown by adding ” n”. The not grouped terms are shown in white color. Predefined, the group leading term is the most significant term of the group. The network integrates only the positive kappa score term associations and is automatically laid out using Organic layout algorithm supported by Cytoscape.

Information table

ClueGO Information table provides information about the selected terms. From left to right:

  1. Group leading term. There are several ways of defining the leading term of the group (see Advanced Settings). Predefined, the leading term has the highest significance in the group.

  1. GOID.
  2. GO Term.
  3. Ontology Source.
  4. GO levels. Due to the complex structure of GO tree (directed acyclic graph), the GO terms can be placed in several levels. In case of using sources without hierarchical structure (KEGG, BioCarta), the level it is assigned as -1.
  5. The group or the groups that include the term.
  6. The percentage of the genes from the uploaded cluster that were associated with the term, compared with all the genes associated with the term.
  7. The number the genes from the uploaded cluster that were associated with the term.
  8. Term significance (PValue).
  9. Term significance (corrected PValue).
  10. Group significance (PValue).
  11. Group significance (corrected PValue).
  12. The genes from the uploaded cluster that were associated with the term.

Histogram with terms

The chart presents the specific terms for the user genes and information related to their associated genes. The display can be customized (see Advanced settings). Predefined, the bars represent the number of the genes from the analyzed cluster found associated with the term, and the label displayed on the bars is the percentage of found genes compared to all the genes associated with the term. Term significance information is included in the chart (see Statistics).

Overview Chart with functional groups

The overview chart presents functional groups for the user genes. The name of the group is given by the group leading term (e.g. the most significant term in the group). The group sections correlate with the number of the terms included in group. The position of the sections can be changed (right click).

Loging information

Complete information on the applied selection criteria for each analysis can be visualized in the loging information panel.

Advanced Settings

ClueGO advanced settings allows a precise adjustment of the selection criteria.

  1. GO tree level. The identifiers can be mapped in the entire ontology tree or in a GO level interval (between Min and Max levels). If selected the first GO levels (1-3), the terms will be very general. Those terms have many associated genes, so, there will be a low percentage of found genes from the user genes. The very specific terms (e.g. level 12) have associated a small number of genes. In this case, the percentage of found genes it is higher. Anyway, one has to consider the complex hierarchical GO structure that makes the terms to be in several levels. This feature is availabe while using a hierarchically structured ontology source (e.g. GO).

  2. Minimum number of identifiers from the uploaded cluster found to be associated with a term.

  3. Minimum percentage that the mapped identifiers are representing from the total associated genes with the term

  1. Fusion. The terms in parent-child relationship that share similar genes (identical, or with one gene difference) are assessed and the most representative parent or child term is retained. Note: This is an optional feature. The fusion strongly reduces the redundancy.

  2. Kappa Score shows the relationships between the terms based on their overlapping genes. It is used for creating the network and can be used for creating the groups. Initially, a term-gene matrix containing the selected terms and their associated genes is created. Based on this, a termterm similarity matrix is calculated using kappa statistics to determine the association strength between the terms (kappa score). High score = visualize in the network only the connections between close related terms, with very similar associated genes (high stringency). Low score = allows to visualize in the network the connections between less related terms (low stringency).

  3. Create functional groups. The terms can be associated in functional groups using the ontology’s hierarchy or the kappa score. When displaying the functional groups on the network, one has to consider that the network structure is calculated with kappa score. The kappa score grouping of the terms will correspond with the network structure that is calculated in the same manner. If the hierarchical grouping is used, it is possible to be a difference between the networks structure (based on the associated genes) and the functional groups defined using GO hierarchy.

  4. Use fix coloring for the groups

  5. Use random coloring for the groups

  6. The most representative term in a group is giving the name of the group. It can be considered having:

  1. the highest number of the found genes per term
  2. the highest percentage of found genes per term
  3. the highest percentage of found genes per total number of found genes
  4. the most significant PValue This selection determines the ClueGO charts display: the number/percentage/significance of the terms. If the group leading term is the term with the higher number of genes or the most significant term from the group, a label with the percentage of the found genes compared with all the associated genes with the term is displayed on the bars of the chart. Reversely, if the group leading term is representing the percentage of genes (compared to all the genes associated with the term or with all the genes found from the uploaded cluster), on the label will be displayed the number of the genes found for this term.
  1. The hierarchy based grouping consists in analyzing the selected terms through the perspective of their parent terms. The size of the groups can be defined using the number of common and different parents, that is depending on the level of the term in GO hierarchy. Since KEGG and BioCarta don’t have a hierarchical structure, the terms selected from those souces will not be grouped.

  2. For grouping the terms based on the kappa score, it is necessary to set the size of the initial group (e.g. 3) and the percentage (overlaping terms/group) for group merge (e.g. 50 percent). For more details see [4]. All the possible initial groups with the terms showing a kappa score equal or above the predefined threshold (e.g.¡= 0.3) are created. Further, the initial groups are iterratively compared and merged if they are overlapping in the defined percentage. A term can be part of several groups. The reocurrence of the term is shown by adding ” n”. If the terms have very similar associated genes, it is possible that the iterative merging of the created groups to take a longer time in the attempt of merging all the groups. In this case, it is recommnended to increase the kappa score level or to increase the percentage for group merge.

Advanced Statistical Options

  1. Select mid-P-value for a less conservative hypergeometric test.
  2. Select Doubling for a less conservative two tailed hypergeometric test.

Cluster Comparison

Once selected the option: ”Compare clusters”, two file choosers are made available. The selection of the ontology terms is following the same steps as in the analysis for a single cluster.

The difference refers to the number and the percentage of the genes per term. Those selection criteria can be flexible: Cluster1 OR Cluster2 options (1) or applied strictly for both clusters: Cluster1 AND Cluster2 options (2).

It is recommended to have comparable number of identifiers in the analysed clusters. If one cluster is much larger, the selection criteria should be applied more strictly (e.g. increase the number of genes per term).

Further, we analyze the terms trough the perspective of their associated genes. It is possible that genes from both clusters will be associated with a term, but in different proportions. We defined a term as specific for one of the clusters if the percentage of associated genes from this cluster is higher than the selected threshold (e.g. 66 percent) (3). As result, charts with specific terms for each cluster are provided. The common terms are included in a separate chart.

On the network, the different proportion of the genes from the analyzed clusters is represented with a color gradient from green, for the first cluster genes, to red for the second cluster. The visualization of the groups on the network can be switched with the one of the uploaded clusters distribution on the selected terms (see Figure below).

ClueGO result visualizations



Walk-through exercise

For the exercise, we are going to use mRNA bladder cancer data generated from RNA-Seq platform. The data can be retrived from Robertson et al. Cell 2017 or downloaded from (Here..)

ClueGO settings

  • set the type of analysis: Compare Cluster
  • select the organism: Homo Sapiens and the the type of ids used: AccessionID
  • load sample gene lists:
    • choose Cluster #1: select Top_Down_genes_BLCA_Session3.txt - (Here..)
    • choose Cluster #2: Top_Up_genes_BLCA_Session3.txt - (Here..)
  • select the Ontologies:
    • GO BiologicalProcess,
    • KEGG Pathways and
    • BioCarta pathway reactome
  • select the statistical test: Enrichment/Deplection (Two sided hypergeometric test), FisherExactTest
  • select the correction method: Bonferroni
  • click Show Advanced Settings
  • set GO Tree Level: Min 4 and Max 5
  • set the selection criteria for the terms that have associated genes from cluster 1: min 2 genes/term and minimum 4% from all the Genes associated with the term
  • select OR (e.g. min 2 genes from cluster #1 or min 2 genes from cluster #2)
  • set is specific to 66% (if 66% or the genes associated with the term are from cluster #1, the term is considered specific for this cluster)
  • set the selection criteria for the terms that have associated genes from cluster 2: min 2 genes/term and minimum 4% from all the Genes associated with the term
  • select Use GO Term Grouping
  • select Fix Group coloring
  • select Leading Group Term based on Highest Significance
  • select Kappa Score grouping with 3 terms in initial group and 50% overlap for groups to merge
  • select ShowDifference
  • Start

Customize the network using Cytoscape features

  • select Style (Cytoscape Control Panel)

  • select Node Font Size

  • set the value of FALSE (size for the name of the terms) to 0.001 and press Enter

  • set the value of TRUE (size for the name of groups) to 26 and press Enter

  • select Layout (Cytoscape menu bar)

  • set scale to 1/3

  • zoom the image

  • change the position of the leading terms to make visible the name of the group

  • change the position of notgrouped terms if due to re-scaling they are too close to a group

  • for visualizing groups press Show Groups

  • Using the filters and style options above, develop a network by using cluster compare for the two bladder cancer conditions - Normal VS Tumor.

  • Save your network in two formats: (a) as a Cytoscape Session (.sys format), and (b) as a .png or .pdf figure.

    • The cytoscape session (.sys) will be used in the next section for CluePedia analysis.

More details on using specific options can be achieved by folowing the ClueGO documentation: http://www.ici.upmc.fr/cluego/ClueGODocumentation2019.pdf


Section B - Analyse with CluePedia.

Background:

CluePedia provides insights into pathways by integrating experimental and in silico information.

  • CluePedia extends ClueGO ([3]) functionality down to genes and miRNAs. If ClueGO reveals interrelations of terms and functional groups in biological networks, CluePedia gives the posibility to enrich those networks with known and experimental data.

  • CluePedia calculates statistical dependencies (correlation) for markers of interest from experimental data. Four tests investigating linear and nonlinear dependencies between variables are implemented: Pearson correlation, Spearman’s rank, Distance correlation ([4]) and Minimal Information Criteria (MIC) ([5]). The resulting file is added to CluePedia as an additional resource for further analysis.

  • Experimental data can be normalized and visualized between adjustable thresholds on network’s nodes as a label. Relevant signals with a certain expression level, standard deviation and without missing values can be selected. Another feature allows the extraction of expression corresponding to selected markers, e.g. genes associated to a pathway, from a dataset into a new file.

  • One major advantage is the possibility to investigate in detail a pathway by combining known [3, 4] and new, experimental derived information, about genes/proteins involved. More, miRNAs [7, 8] that could influence the expression of the genes can be as well visualized together with the expression data. The location of the genes/proteins [9, 10] within cellular compartments can be automatically displayed, by the implementation of Cerebral [10] layout within CluePedia.

  • CluePedia provides an ID index file (updatable, extendable) that stores entrez gene ids and symbols and allows fast analysis.

  • Both plugins, CluePedia and ClueGO, take advantage of Cytoscape’s versatile visualization framework

Software Documentation

For detailed information on how certain functions work in CluePedia, please refer to the link here: http://www.ici.upmc.fr/cluepedia/CluePedia_Documentation.pdf

Walkthorugh Example:

  • Open the previously saved session3.sys (Part A - ClueGO Network) file in Cytoscape.

Create a ClueGO+CluePedia network of terms/pathways and genes.

  • Download CluePedia and ClueGO plugins in the Cytoscape plugin folder. Optional Download Cerebral plugin.
  • Start Cytoscape. Open ClueGO+CluePedia (Plugins menu).
  • Keep standard settings: Analysis Mode (Function), Cluster Analysis Type (Single), Organism (Homo Sapiens), Automatic recognition of ids.
  • Copy the Th1 related genes from the list provided. Genes: PDCD1LG1, IRF1, GNLY, PDCD1LG2, PDCD1, TBX21, IFNG, TNFRSF6B, ICOS, TNF, CXCL9, CXCL10, IL8, STAT1, MADCAM1, ICAM1, VCAM1, CX3CL1
  • Select Ontology: Reactome (version 10.07.2012)
  • Select Show Advanced Settings.
  • Set Gene percentage to 3%.
  • Keep all the other advanced settings.
  • Start the analysis ClueGO network of functions
  • Select CluePedia panel
  • Select Show only selected genes ClueGO+CluePedia network of functions + associated genes.

Visualize known interactions between mapped genes.

Explore a term/pathway of interest into a nested network.

See all genes associated to this term and their known interactions.

  • Select ACTIONS interaction file (CluePedia STRING-ACTIONS v9 9606 09.03.2012).
  • Select Action types: activation, binding, expression, ptmode (all scores)
  • Update the network
    • ClueGO+CluePedia network of terms and genes. Terms are interconnected based on kappa score and genes based on known interactions from STRING.
  • Select the term: Cortisol synthesis and secretion.
  • Create ClueGO Nested Network (Right mouse click)
    • CluePedia nested pathway network with all genes associated to this pathway interconnected based on known interactions from STRING (interconnection score applies to both, initial and nested network).

  • Here you obtain diffrentially expressed genes and their interactions within enriched pathways. By using your imaginagion, one can group specific pathways and ranked genes that can be associated to a specific type of phenotype.

  • Save your ClueGO, CluePedia and Cytoscape session for future use.

Further Reading:

ClueGO and CluePedia analysis for miRNA data.

Please refere the following documentation for miRNA analysis using ClueGO/CluePedia.

Bibliography

[1] M Ashburner, C A Ball, J A Blake, D Botstein, H Butler, J M Cherry, A P Davis, K Dolinski, S S Dwight, J T Eppig, M A Harris, D P Hill, L Issel-Tarver, A Kasarskis, S Lewis, J C Matese, J E Richardson, M Ringwald, G M Rubin, G Sherlock. Gene ontology: tool for the unification of biology The Gene Ontology Consortium. Nat Genet, 25:25–29, 2000.

[2] M Kanehisa, S Goto, S Kawashima, A Nakaya. The KEGG databases at GenomeNet. Nucleic Acids Res, 30:42–46, 2002.

[3] G Bindea, B Mlecnik, H Hackl, P Charoentong, M Tosolini, A Kirilovsky, WH Fridman, F Pages, Z Trajanoski, J Galon. ClueGO: a Cytoscape plug-in to decipher functionally grouped gene ontology and pathway annotation networks. Bioinformatics, 25(8):1091–3, 2009.

[4] GJ Szekely, M Rizzo. Brownian distance covariance. Annals of Applied Statistics, page 1233a1303, ˆ 2009.

[5] DN Reshef, YA Reshef, HK Finucane, SR Grossman, G McVean, PJ Turnbaugh, ES Lander, M Mitzenmacher, PC Sabeti. Detecting novel associations in large data sets. Science, 334(6062):1518–24, 2011.

[6] von Mering C., Jensen L.J., Snel B., Hooper S.D., Krupp M., Foglierini M., Jouffre N., Huynen M.A., Bork P. STRING: known and predicted protein-protein associations, integrated and transferred across organisms. Nucleic Acids Res, 33:D433–D437, 2005.

[7] D Szklarczyk, A Franceschini, M Kuhn, M Simonovic, A Roth, P Minguez, T Doerks, M Stark, J Muller, P Bork, LJ Jensen, C von Mering. The STRING database in 2011: functional interaction networks of proteins, globally integrated and scored. Nucleic Acids Res, 39(Database issue):D561– 8, 2011.

[8] A Kozomara, S Griffiths-Jones. miRBase: integrating microRNA annotation and deep-sequencing data. Nucleic Acids Res, 39(Database Issue):D152–D157, 2011.

[9] F Xiao, Z Zuo, G Cai, S Kang, X Gao, T Li. miRecords: an integrated resource for microRNAtarget interactions. Nucleic Acids Res, 37:D105–D110, 2009.

[10] A Barsky, JL Gardy, RE Hancock, T Munzner. Cerebral: a Cytoscape plugin for layout of and interaction with biolog





LS0tCnRpdGxlOiAnUGF0aHdheSBFbnJpY2htZW50IEFuYWx5c2lzIHVzaW5nIENsdWVHTyBhbmQgQ2x1ZVBlZGlhIC0gU2Vzc2lvbiAzJwphdXRob3I6ICJBdXRob3IgLSBEci4gQWtzaGF5IEJoYXQiCmRhdGU6ICdgciBmb3JtYXQoU3lzLnRpbWUoKSwgIkxhc3QgbW9kaWZpZWQ6ICVkICViICVZIilgJwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgY3NzOiBzdHlsZXNoZWV0cy9zdHlsZXMuY3NzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCjxpbWcgc3JjPSJpbWFnZXMvbG9nby1zbS5wbmciIHN0eWxlPSJwb3NpdGlvbjphYnNvbHV0ZTt0b3A6NDBweDtyaWdodDozMHB4OyIgd2lkdGg9IjIwMCIgLz4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgdGlkeSA9IFRSVUUsCiAgdGlkeS5vcHRzID0gbGlzdCh3aWR0aC5jdXRvZmYgPSA5NSksCiAgbWVzc2FnZSA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICBmaWcud2lkdGggPSAxMCwKICB0aW1lX2l0ID0gVFJVRQopCgpgYGAKCiMgSW50cm9kdWN0aW9uCgpJbiB0aGlzIHNlc3Npb24gd2Ugd2lsbCBsZWFybiBob3cgdG8gcGVyZm9ybSBwYXRod2F5IGVucmljaG1lbnQgYW5hbHlzaXMgdXNpbmcgZ2VuZSBzZXRzIGZyb20gb3VyIHRyYW5zY3JpcHRvbWljcyBleHBlcmltZW50IGJ5IHVzaW5nIHR3byAqKkN5dG9zY2FwZSBwbHVnaW5zIC0gQ2x1ZUdPIGFuZCBDbHVlUGVkaWEqKi4gQ2x1ZUdPIGFuZCBDbHVlUGVkaWEgYXJlIHNvbWUgb2YgdGhlIG1vc3QgaGlnaGx5IHJhdGVkIG9yIHRvcCBkb3dubG9hZGVkIGFwcHMgaW4gdGhlIChbQ3l0b3NjYXBlIEFwcCBTdG9yZV0oImh0dHBzOi8vYXBwcy5jeXRvc2NhcGUub3JnLyIpKS4gCgohW10oaW1hZ2VzL0N5dG9zY2FwZV9BcHBfU3RvcmUucG5nKQoKIyMgSW5zdGFsbGF0aW9uCgoqIEdvIHRvIGh0dHBzOi8vYXBwcy5jeXRvc2NhcGUub3JnL2FwcHMvY2x1ZWdvIGFuZCBjbGljayAqKkRvd25sb2FkKiogb3IgKipJbnN0YWxsKiogKGlmIHlvdXIgY3l0b3NjYXBlIGFwcGxpY2F0aW9uIGlzIG9wZW4pCiogTW9yZSBvbiBpbnN0YWxsYXRpb24sIGRvY3VtZW50YXRpb24gYW5kIGhvdyB0byBpbnRlZ3JhdGUgdGhlIHBhY2thZ2Ugd2l0aCBSIG9yIFB5dGhvbiBpcyBkZXNjcmliZWQgKFtoZXJlOl0oaHR0cDovL3d3dy5pY2kudXBtYy5mci9jbHVlZ28vY2x1ZWdvRG9jdW1lbnRhdGlvbi5zaHRtbCkpCiogQWxzbyBnbyB0byBodHRwczovL2FwcHMuY3l0b3NjYXBlLm9yZy9hcHBzL2NsdWVwZWRpYSBhbmQgY2xpY2sgKipEb3dubG9hZCoqIG9yICoqSW5zdGFsbCoqIChpZiB5b3VyIGN5dG9zY2FwZSBhcHBsaWNhdGlvbiBpcyBvcGVuKSAtIFdlIHdpbGwgYmUgdXNpbmcgaW4gdGhpcyBhcHAgaW4gdGhlIHNlY29uZCBzZXNzaW9uIG9mIHRoaXMgY291cnNlLiAKCioqTk9URTogWW91IGNhbiBhbHNvIGRvd25sb2FkL2luc3RhbGwgcGx1Z2lucyBkaXJlY3RseSBmcm9tIHRoZSBDeXRvc2NhcGUtQXBwIFN0b3JlLioqCgohW10oaW1hZ2VzL0N5dG9zY2FwZS1BcHBTdG9yZS5wbmcpCgoKIyMgU3lzdGVtIFJlcXVpcmVtZW50czogCiogV2luZG93cywgTGludXgsIFVuaXggb3IgTWFjT1Mgb3BlcmF0aW5nIHN5c3RlbS4KKiAxNiBHQiBSQU0gcmVjb21tZW5kZWQuIEhhcmQgZGlzayB3aXRoIGF0IGxlYXN0IDEwMCBNQiBmcmVlIChmb3IgZXhhbXBsZSBmaWxlcykuCiogSmF2YSAxLjgrIG5lZWRlZCAtICoqVkVSWSBFU1NFTlRJQUwqKi4gVGhpcyBjYW4gYmUgaW5zdGFsbGVkIGZyb20gdGhlIERvd25sb2FkJ3MgcGFnZSBpbiB0aGUgQ3l0b3NjYXBlIHdlYnNpdGUuIAoqICoqQ3l0b3NjYXBlIDMuNy4rKiogaW5zdGFsbGVkOiBodHRwczovL2N5dG9zY2FwZS5vcmcvIC0gbGF0ZXN0IGlzICoqdmVyc2lvbiAzLjEwLjIqKi4KIVtdKGltYWdlcy9DeXRvc2NhcGUtRG93bmxvYWRzLnBuZykKCiMjIE5vdGUgClRoaXMgY291cnNlIGlzIGludGVuZGVkIGZvciBhbiBhdWRpZW5jZSB3aG8gd2lzaCB0byBhbmFseXNlIGJpb2xvZ2ljYWwgZGF0YSAod2l0aCBhbiBleGFtcGxlIG9mIFJOQS1TZXEpIGFuZCBoYXZlIG5vIHByZXZpb3VzIG9yIG9ubHkgYmFzaWMgcHJvZ3JhbW1pbmcgZXhwZXJpZW5jZS4gSG93ZXZlciwgZm9yIHRob3NlIHdobyBhcmUga2VlbiBhbmQgd2FudCB0byBpbnRlZ3JhdGUgQ3l0b3NjYXBlIChhbmQgaXRzIHBhY2thZ2VzIGxpa2UgQ2x1ZUdPIGFuZCBDbHVlUGVkaWEpIHVzaW5nIFIgb3IgUHl0aG9uLCB0aGVuIHBsZWFzZSByZWZlciB0byBodHRwOi8vd3d3LmljaS51cG1jLmZyL2NsdWVnby9jbHVlZ29Eb2N1bWVudGF0aW9uLnNodG1sIHRvIG9idGFpbiB0aGUgcmVxdWlyZWQgQVBJLiAKCgojIyBCYXNpYyBUZXJtcyBhbmQgTmV0d29yayBCaW9sb2d5IEJhY2tncm91bmQKCkdlbmVyYWxseSwgdGhlIGJpb2xvZ2ljYWwgaW50ZXJwcmV0YXRpb24gb2YgbGFyZ2UgZ2VuZSBjbHVzdGVycyBkZXJpdmVkIGZyb20gaGlnaC10aHJvdWdocHV0IGV4cGVyaW1lbnRzIGlzIGEgcmVhbCBjaGFsbGVuZ2UuIApNYW55IG9udG9sb2d5IHNvdXJjZXMgZXhpc3QgaW4gb3JkZXIgdG8gY2FwdHVyZSBiaW9sb2dpY2FsIGluZm9ybWF0aW9uIGluIGEgbWVhbmluZ2Z1bCB3YXkuCgoqICoqVGhlIEdlbmUgT250b2xvZ3kgKEdPKSBwcm9qZWN0cyoqIFsxXSBhaW1zIHRvIGNhcHR1cmUgdGhlIGluY3JlYXNpbmcga25vd2xlZGdlIG9uIGdlbmUgZnVuY3Rpb24gaW4gYSBjb250cm9sbGVkIHZvY2FidWxhcnkgYXBwbGljYWJsZSB0byBhbGwgdGhlIG9yZ2FuaXNtcy4gKipHTyoqIGRlc2NyaWJlcyBnZW5lIHByb2R1Y3RzIGluIHRlcm1zIG9mIHRoZWlyIGFzc29jaWF0ZWQgYmlvbG9naWNhbCBwcm9jZXNzZXMsIGNlbGx1bGFyIGNvbXBvbmVudHMgYW5kIG1vbGVjdWxhciBmdW5jdGlvbnMuCgpCZXR3ZWVuIHRoZSB0ZXJtcyB0aGVyZSBpcyBhIGhpZXJhcmNoaWNhbCByZWxhdGlvbnNoaXAgKHBhcmVudC1jaGlsZCkuIER1ZSB0byB0aGUgY29tcGxleGl0eSBvZiBoaWVyYXJjaHkgc3RydWN0dXJlIChkaXJlY3RlZCBhY3ljbGljIGdyYXBoKSwgdGhlIHRlcm1zIGNhbiBiZSBpbiBzZXZlcmFsIGRpZmZlcmVudCBsZXZlbHMuIFRoZSBzcGVjaWZpY2l0eSBvZiB0aGUgdGVybXMgdmFyaWVzIGFsb25nIHRoZSB0cmVlOiBmcm9tIHZlcnkgZ2VuZXJhbCB0ZXJtcyAoaW4gZmlyc3QgbGV2ZWxzIG9mIEdPKSB0byB2ZXJ5IHNwZWNpZmljIG9uZXMuCgoqICoqS3lvdG8gRW5jeWNsb3BlZGlhIG9mIEdlbmVzIGFuZCBHZW5vbWVzIChLRUdHKSoqIFsyXSBpcyBhIGRhdGFiYXNlIG9mIGJpb2xvZ2ljYWwgc3lzdGVtcyB0aGF0IGludGVncmF0ZXMgZ2Vub21pYywgY2hlbWljYWwgYW5kIHN5c3RlbWljIGZ1bmN0aW9uYWwgaW5mb3JtYXRpb24uCgoqICoqQmlvQ2FydGEqKiAtIFtCaW9DYXJ0YV0oaHR0cHM6Ly9tYWF5YW5sYWIuY2xvdWQvSGFybW9uaXpvbWUvZGF0YXNldC9CaW9jYXJ0YStQYXRod2F5cykgcHJvdmlkZXMgdXNlZnVsIHBhdGh3YXkgaW5mb3JtYXRpb24uCgoqICoqUmVhY3RvbWUqKiAtIFtSZWFjdG9tZV0oaHR0cHM6Ly9yZWFjdG9tZS5vcmcvKSBpcyBhIGZyZWUsIG9wZW4tc291cmNlLCBjdXJhdGVkIGFuZCBwZWVyLXJldmlld2VkIHBhdGh3YXkgZGF0YWJhc2UuICAgCgoqICoqV2lraVBhdGh3YXlzKiogLSBbV2lraVBhdGh3YXlzXShodHRwczovL3d3dy53aWtpcGF0aHdheXMub3JnLykgaXMgYW4gb3BlbiwgY29sbGFib3JhdGl2ZSBwbGF0Zm9ybSBkZWRpY2F0ZWQgdG8gdGhlIGN1cmF0aW9uIG9mIGJpb2xvZ2ljYWwgcGF0aHdheXMuIFdpa2lQYXRod2F5cyB0aHVzIHByZXNlbnRzIGEgbmV3IG1vZGVsIGZvciBwYXRod2F5IGRhdGFiYXNlcyB0aGF0IGVuaGFuY2VzIGFuZCBjb21wbGVtZW50cyBvbmdvaW5nIGVmZm9ydHMsIHN1Y2ggYXMgS0VHRywgUmVhY3RvbWUgYW5kIFBhdGh3YXkgQ29tbW9ucy4gCgoKRm9yIGEgY29tcGxldGUgdmlldyBvbiB0aGUgc3R1ZGllZCBwcm9jZXNzLCBzZXZlcmFsIG9udG9sb2d5IHNvdXJjZXMgc2hvdWxkIGJlIGNvbnN1bHRlZCBpbiBvcmRlciB0byBpbnRlZ3JhdGUgdGhlaXIgY29tcGxlbWVudGFyeSBpbmZvcm1hdGlvbi4gSW4gZWFjaCBzb3VyY2UsIGZvciBlYWNoIGdlbmUsIHRoZXJlIGlzIGEgbGFyZ2UgYW1vdW50IG9mIGluZm9ybWF0aW9uLiBUaGlzIG1ha2VzIHRoZSBhbmFseXNpcyBvZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZ2VuZXMgYW5kIGJldHdlZW4gdGVybXMgdmVyeSBkaWZmaWN1bHQgdG8gcmVwcmVzZW50IGFuZCBjb21wcmVoZW5kLiBBbHNvLCBmb3IgY2xvc2UgcmVsYXRlZCB0ZXJtcywgYSBoaWdoIGRlZ3JlZSBvZiByZWR1bmRhbmN5IG9mIHRoZWlyIGFzc29jaWF0ZWQgZ2VuZXMgZXhpc3RzLgoKIyMgKipDbHVlR08qKgpBbiBvcGVuLXNvdXJjZSBKYXZhIHRvb2wgdGhhdCBleHRyYWN0cyB0aGUgbm9uLXJlZHVuZGFudCBiaW9sb2dpY2FsIGluZm9ybWF0aW9uIGZvciBsYXJnZSBjbHVzdGVycyBvZiBnZW5lcywgdXNpbmcgR08sIEtFR0csIFJlYWN0b21lLCBXaWtpUGF0aHdheXMgYW5kIEJpb0NhcnRhLiAKCiogKipDbHVlR08qKiBpcyBpbnRlZ3JhdGVkIGluICoqQ3l0b3NjYXBlKiogKGh0dHBzOi8vY3l0b3NjYXBlLm9yZy8pIGFzIGEgcGx1Zy1pbiBhbmQgaXQgaXMgdGFraW5nIGFkdmFudGFnZSBvZiBpdHMgY29tcGxleCB2aXN1YWxpemF0aW9uIGVudmlyb25tZW50Lgo8YnI+PC9icj4KCgojIyMgKipDbHVlR08qKiBmZWF0dXJlcyBpbmNsdWRlOgoKKiBDbHVlR08gYWxsb3dzIGFuYWx5c2lzIG9mIGEgc2luZ2xlIGdlbmUgc2V0IChjbHVzdGVyKSBvciBjbHVzdGVyIGNvbXBhcmlzb24uCiogRGlmZmVyZW50IGZpbHRlciBjcml0ZXJpYSBjYW4gYmUgYXBwbGllZCB0byB0aGUgdGVybXMuCiogRnVzaW9uIG9mIHRoZSByZWxhdGVkIHRlcm1zIHRoYXQgaGF2ZSBzaW1pbGFyIGFzc29jaWF0ZWQgZ2VuZXMuCiogRnVuY3Rpb25hbCBncm91cGluZyBvZiB0aGUgdGVybXMgYmFzZWQgb24gR08gaGllcmFyY2h5IG9yIGJhc2VkIG9uIGthcHBhIHNjb3JlLgoqIFZpc3VhbGl6ZSB0aGUgc2VsZWN0ZWQgdGVybXMgaW4gYSBmdW5jdGlvbmFsbHkgZ3JvdXBlZCBuZXR3b3JrLgoqIENoYXJ0cyBwcmVzZW50aW5nIHRoZSBzcGVjaWZpYyB0ZXJtcyBhbmQgZ3JvdXBzIGZvciB0aGUgY2x1c3RlcnMgY29tcGFyZWQuCiogU3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIGZvciB0aGUgdGVybXMgYW5kIGZvciB0aGUgZ3JvdXBzLgoqIENsdWVHTyBjYW4gYmUgdXNlZCBpbiBjb21iaW5hdGlvbiB3aXRoIEdPbG9yaXplIChhbm90aGVyICoqQ3l0b3NjYXBlKiogdG9vbCBmb3IgcGF0aHdheSBlbnJpY2htZW50KSBbaGVyZV0oaHR0cHM6Ly9hcHBzLmN5dG9zY2FwZS5vcmcvYXBwcy9nb2xvcml6ZSkuCiogRWFzeSB1cGRhdGFibGUuCiogRWFzeSBleHRlbmRhYmxlLgoKCiMjIFNlbGVjdGlvbiBQYW5lbAoKQWZ0ZXIgc3RhcnRpbmcgQ3l0b3NjYXBlLCAqKkNsdWVHTyoqIGNhbiBiZSBmb3VuZCB1bmRlciB0aGUgUGx1Z2lucyBtZW51LiBPbmNlIHNlbGVjdGVkLCBpdCB3aWxsIGRpc3BsYXkgdGhlIENsdWVHTyBzZWxlY3Rpb24gcGFuZWwgb3B0aW9ucy4gU2VlIEZpZ3VyZSBiZWxvdzoKCjEuIFNlbGVjdCB0aGUgdHlwZSBvZiBhbmFseXNpcy4gQmVzaWRlcyBhbmFseXNpcyBvZiBhIHNpbmdsZSBnZW5lIHNldCAoY2x1c3RlciksIENsdWVHTyBwZXJmb3JtcyBjb21wYXJpc29uIG9mIGNsdXN0ZXJzLCB1bmRlcmx5aW5nIHRoZSBzcGVjaWZpY2l0eSBhbmQgYWxzbyB0aGUgY29tbW9uIGFzcGVjdHMgb2YgdGhlaXIgZnVuY3Rpb25hbGl0eS4KCiFbXShpbWFnZXMvQ2x1ZUdPX1NlbGVjdGlvblBhbmVsLnBuZykKCjIuIFNlbGVjdCBvcmdhbmlzbS4gKipGb3IgdGhlIG1vbWVudCwgQ2x1ZUdPIHN1cHBvcnRzIEFyYWJpZG9wc2lzIHRoYWxpYW5hLCBCb3MgdGF1cnVzLCBDYWVub3JoYWJkaXRpcyBlbGVnYW5zLCBEYW5pbyByZXJpbywgRGljdHlvc3RlbGl1bSBkaXNjb2lkZXVtLCBEcm9zb3BoaWxhIG1lbGFub2dhc3RlciwgRXNjaGVyaWNoaWEgY29saSwgR2FsdXMgZ2FsdXMsIEhvbW8gc2FwaWVucywgTWFnbmFwb3J0aGUgZ3Jpc2VhLCBNdXMgbXVzY3VsdXMsIE9yeXphIHNhdGl2YSwgUmF0dHVzIG5vcnZlZ2ljdXMgYW5kIFNhY2NoYXJvbXljZXMgY2VyZXZpc2lhZS4qKiAKMy4gU2VsZWN0IGlkZW50aWZpZXJzIHR5cGUgKEFmZnltZXRyaXhJRCwgQWNjZXNzaW9uSUQsIFN5bWJvbElEKS4KNC4gVGhlIGlkZW50aWZpZXJzIGNhbiBiZSB1cGxvYWRlZCBmcm9tIHRleHQgZmlsZXMgb3IgaW50ZXJhY3RpdmVseSBmcm9tIGEgQ3l0b3NjYXBlIHN1Yi1uZXR3b3JrLgpDbHVlR08gcHJvdmlkZXMgc2FtcGxlIGZpbGVzIGNvbnRhaW5pbmcgc3BlY2lmaWMgZ2VuZXMgKEFjY2Vzc2lvbklEKSBmb3IgSHVtYW4gQiBhbmQgTksgY2VsbHMuCkEgU2FjY2Fyb215Y2VzIG5ldHdvcmsgc2FtcGxlIChnYWxGaWx0ZXJlZC5jeXMpIGNhbiBiZSBmb3VuZCBpbiB0aGUgQ3l0b3NjYXBlIHNhbXBsZURhdGEKZm9sZGVyLiBJbiB0b2RheSdzIGNvdXJzZSB3ZSB3aWxsIHVzZSBibGFkZGVyIGNhbmNlciBkYXRhIGZyb20gdGhlICoqRGF0YS1GaWxlIGxvY2F0ZWQgaW4gb3VyIHR1dG9yaWFsIGZvbGRlcioqLiBbSGVyZS4uXShodHRwczovL2dpdGh1Yi5jb20vYTFha3MvQ3l0b3NjYXBlX0NvdXJzZS90cmVlL21haW4vRGF0YV9GaWxlcykKNS4gQ2hvb3NlIHRoZSBhbnkgZmlsZSB3aXRoIGlkZW50aWZpZXIgCiogIlRvcF9Eb3duX2dlbmVzX0JMQ0FfU2Vzc2lvbjMudHh0IgoqICJUb3BfVXBfZ2VuZXNfQkxDQV9TZXNzaW9uMy50eHQiCjYuIFNlbGVjdCB0aGUgb250b2xvZ3kvb250b2xvZ2llcy4gVG8gbWFrZSBDbHVlR08gZmFzdGVyLCB3ZSB1c2UgcHJlY29tcGlsZWQgZmlsZXMgYmFzZWQgb24gR08sCktFR0cgYW5kIEJpb0NhcnRhLiBUaGUgcHJlY29tcGlsZWQgZmlsZXMgYXJlIGluY2x1ZGVkIGluIHRoZSBDbHVlR09QbHVnaW4uamFyLgo3LiBTZWxlY3QgdGhlIGV2aWRlbmNlIGNvZGUsIG9wdGlvbiBhdmFpbGFibGUgZm9yIHRoZSBHTyBiYXNlZCBmaWxlcy4gRm9yIG1vcmUgZGV0YWlscywgc2VlCmh0dHA6Ly93d3cuZ2VuZW9udG9sb2d5Lm9yZy9HTy5ldmlkZW5jZS5zaHRtbC4KOC4gVXBkYXRlIHRoZSBvbnRvbG9neSAoc2VlIENsdWVHTyB1cGRhdGVzKQo5LiBUaGUgc2lnbmlmaWNhbmNlIG9mIGVhY2ggdGVybSBvciBncm91cCBjYW4gYmUgY2FsY3VsYXRlZCB3aXRoIGh5cGVyZ2VvbWV0cmljIHRlc3QgKGVucmljaG1lbnQsCmRlcGxldGlvbikuIFN0YW5kYXJkIGlzIGh5cGVyZ2VvbWV0cmljIHRlc3QgdHdvIHNpZGVkLgoxMC4gU2V2ZXJhbCBtZXRob2RzIGZvciBQVmFsdWUgY29ycmVjdGlvbiBhcmUgcHJvcG9zZWQ6IEJvbmZlcnJvbmksIEJvbmZlcnJvbmkgc3RlcC1kb3duIGFuZCBCZW5qYW1pbmlIb2NoYmVyZy4KMTEuIEFkdmFuY2VkIHN0YXRpc3RpY2FsIG9wdGlvbnMKMTIuIFNlbGVjdCBuZXR3b3JrIHR5cGUuIFdlIHByZWRlZmluZWQgc2VsZWN0aW9uIGNyaXRlcmlhIGxlYWRpbmcgdG8gYSDigJ1HbG9iYWzigJ0gbmV0d29yaywgYSDigJ1NZWRpdW3igJ0KbmV0d29yayBvciBhIOKAnURldGFpbGVk4oCdIG5ldHdvcmsuClRoZSDigJ1HbG9iYWzigJ0gbmV0d29yayBkaXNwbGF5cyBHTyB0ZXJtcyBmb3VuZCBpbiB0aGUgR08gbGV2ZWxzIDEtMywgd2l0aCBhIGhpZ2ggbnVtYmVyIG9mCmdlbmVzIGFzc29jaWF0ZWQgYW5kIGEgc21hbGwgcGVyY2VudGFnZSBvZiB1cGxvYWRlZCBnZW5lcyBmb3VuZC4gVGhvc2UgdGVybXMgcHJvdmlkZSBhIGdlbmVyYWwKYmlvbG9naWNhbCBpbmZvcm1hdGlvbi4gQXQgdGhlIG9wcG9zaXRlLCB0aGUg4oCdRGV0YWlsZWTigJ0gbmV0d29yayBzaG93cyB2ZXJ5IHNwZWNpZmljIHRlcm1zIHBsYWNlZAppbiBHTyBsZXZlbHMgOS0xNCwgd2l0aCBvbmx5IGZldyBhc3NvY2lhdGVkIGdlbmVzIGJ1dCBhIGhpZ2ggcGVyY2VudGFnZSBvZiB0aGUgdXBsb2FkZWQgZ2VuZXMKZm91bmQuIFRob3NlIHRlcm1zIGFyZSBtb3JlIHNwZWNpZmljIGFuZCBpbmZvcm1hdGl2ZSB1bmRlcmx5aW5nIHBhcnRpY3VsYXIgYXNwZWN0cyBvZiB0aGUgc3R1ZGllZApnZW5lIHByb2R1Y3QuClRoZSBwcmVkZWZpbmVkIHNldHRpbmdzIHByb3ZpZGVkIGJ5IENsdWVHTyBzaG91bGQgYmUgY29tYmluZWQgd2l0aCBhIGN1c3RvbWl6ZWQgc2VsZWN0aW9uIGZvcgphbiBhbmFseXNpcyBhZGFwdGVkIHRvIHRoZSBiaW9sb2dpY2FsIHF1ZXN0aW9uIGFkZHJlc3NlZCAoZ2VuZXJhbC9zcGVjaWZpYyBpbnZlc3RpZ2F0aW9uKSBhbmQgdG8gdGhlCm51bWJlciBvZiBnZW5lcyBpbnZvbHZlZC4KMTMuIEFkdmFuY2VkIHNldHRpbmdzLgoxNC4gU3RhcnQgdGhlIGFuYWx5c2lzLgoKCiMjIENsdWVHTyByZXN1bHQKCkEgZnVuY3Rpb25hbGx5IGdyb3VwZWQgYW5ub3RhdGlvbiBuZXR3b3JrLCBhIENsdWVHTyBpbmZvcm1hdGlvbiB0YWJsZSwgY2hhcnRzIHdpdGggdGVybXMgYW5kIGdyb3VwcwphbmQgdGhlIGxvZ2luZyBpbmZvcm1hdGlvbiBhcmUgdGhlIHJlc3VsdCBvZiBDbHVlR08gYW5hbHlzaXMuIFRoZSBjcmVhdGVkIG5ldHdvcmtzIGFuZCBhbmFseXNpcyByZXN1bHRzCmNhbiBiZSBzYXZlZCBpbiBhIHNwZWNpZmllZCBwcm9qZWN0IGZvbGRlciBhbmQgdXNlZCBmb3IgZnVydGhlciBhbmFseXNpcy4gSWYgdGhlIGFuYWx5c2lzIGlzIG5vdCBuZWVkZWQKYW55bW9yZSwgaXQgaXMgcmVjb21tZW5kZWQgdG8gY2xvc2UgdGhlIHByb2plY3QuCgohW10oaW1hZ2VzL0NsdWVHby1SZXN1bHRzLnBuZykKCgojIyBGdW5jdGlvbmFsbHkgR3JvdXBlZCBBbm5vdGF0aW9uIE5ldHdvcmsKCkNsdWVHTyB2aXN1YWxpemVzIHRoZSBzZWxlY3RlZCB0ZXJtcyBpbiBhIGZ1bmN0aW9uYWxseSBncm91cGVkIGFubm90YXRpb24gbmV0d29yayAoU2VlIEZpZ3VyZSAyKSB0aGF0CnJlZmxlY3RzIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHRlcm1zIGJhc2VkIG9uIHRoZSBzaW1pbGFyaXR5IG9mIHRoZWlyIGFzc29jaWF0ZWQgZ2VuZXMuIFRoZSBzaXplCm9mIHRoZSBub2RlcyByZWZsZWN0cyB0aGUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIG9mIHRoZSB0ZXJtcy4gVGhlIGRlZ3JlZSBvZiBjb25uZWN0aXZpdHkgYmV0d2VlbiB0ZXJtcwooZWRnZXMpIGlzIGNhbGN1bGF0ZWQgdXNpbmcga2FwcGEgc3RhdGlzdGljcywgaW4gYSBzaW1pbGFyIHdheSBhcyBkZXNjcmliZWQgaW4gWzRdLiBUaGUgY2FsY3VsYXRlZCBrYXBwYQpzY29yZSBpcyBhbHNvIHVzZWQgZm9yIGRlZmluaW5nIGZ1bmN0aW9uYWwgZ3JvdXBzLiBBIHRlcm0gY2FuIGJlIGluY2x1ZGVkIGluIHNldmVyYWwgZ3JvdXBzLiBUaGUgcmVvY3VycmVuY2Ugb2YgdGhlIHRlcm0gaXMgc2hvd24gYnkgYWRkaW5nIOKAnSBu4oCdLiBUaGUgbm90IGdyb3VwZWQgdGVybXMgYXJlIHNob3duIGluIHdoaXRlIGNvbG9yLiBQcmVkZWZpbmVkLAp0aGUgZ3JvdXAgbGVhZGluZyB0ZXJtIGlzIHRoZSBtb3N0IHNpZ25pZmljYW50IHRlcm0gb2YgdGhlIGdyb3VwLiBUaGUgbmV0d29yayBpbnRlZ3JhdGVzIG9ubHkgdGhlIHBvc2l0aXZlCmthcHBhIHNjb3JlIHRlcm0gYXNzb2NpYXRpb25zIGFuZCBpcyBhdXRvbWF0aWNhbGx5IGxhaWQgb3V0IHVzaW5nIE9yZ2FuaWMgbGF5b3V0IGFsZ29yaXRobSBzdXBwb3J0ZWQgYnkKQ3l0b3NjYXBlLgoKCiMjIEluZm9ybWF0aW9uIHRhYmxlCgoqKkNsdWVHTyoqIEluZm9ybWF0aW9uIHRhYmxlIHByb3ZpZGVzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBzZWxlY3RlZCB0ZXJtcy4gRnJvbSBsZWZ0IHRvIHJpZ2h0OgoKMS4gR3JvdXAgbGVhZGluZyB0ZXJtLiBUaGVyZSBhcmUgc2V2ZXJhbCB3YXlzIG9mIGRlZmluaW5nIHRoZSBsZWFkaW5nIHRlcm0gb2YgdGhlIGdyb3VwIChzZWUgQWR2YW5jZWQgU2V0dGluZ3MpLiBQcmVkZWZpbmVkLCB0aGUgbGVhZGluZyB0ZXJtIGhhcyB0aGUgaGlnaGVzdCBzaWduaWZpY2FuY2UgaW4gdGhlIGdyb3VwLgoKIVtdKGltYWdlcy9DbHVlR08taW5mb1RhYmxlLnBuZykKCjIuIEdPSUQuCjMuIEdPIFRlcm0uCjQuIE9udG9sb2d5IFNvdXJjZS4KNS4gR08gbGV2ZWxzLiBEdWUgdG8gdGhlIGNvbXBsZXggc3RydWN0dXJlIG9mIEdPIHRyZWUgKGRpcmVjdGVkIGFjeWNsaWMgZ3JhcGgpLCB0aGUgR08gdGVybXMgY2FuIGJlCnBsYWNlZCBpbiBzZXZlcmFsIGxldmVscy4gSW4gY2FzZSBvZiB1c2luZyBzb3VyY2VzIHdpdGhvdXQgaGllcmFyY2hpY2FsIHN0cnVjdHVyZSAoS0VHRywgQmlvQ2FydGEpLAp0aGUgbGV2ZWwgaXQgaXMgYXNzaWduZWQgYXMgLTEuCjYuIFRoZSBncm91cCBvciB0aGUgZ3JvdXBzIHRoYXQgaW5jbHVkZSB0aGUgdGVybS4KNy4gVGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIGdlbmVzIGZyb20gdGhlIHVwbG9hZGVkIGNsdXN0ZXIgdGhhdCB3ZXJlIGFzc29jaWF0ZWQgd2l0aCB0aGUgdGVybSwgY29tcGFyZWQgd2l0aCBhbGwgdGhlIGdlbmVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgdGVybS4KOC4gVGhlIG51bWJlciB0aGUgZ2VuZXMgZnJvbSB0aGUgdXBsb2FkZWQgY2x1c3RlciB0aGF0IHdlcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSB0ZXJtLgo5LiBUZXJtIHNpZ25pZmljYW5jZSAoUFZhbHVlKS4KMTAuIFRlcm0gc2lnbmlmaWNhbmNlIChjb3JyZWN0ZWQgUFZhbHVlKS4KMTEuIEdyb3VwIHNpZ25pZmljYW5jZSAoUFZhbHVlKS4KMTIuIEdyb3VwIHNpZ25pZmljYW5jZSAoY29ycmVjdGVkIFBWYWx1ZSkuCjEzLiBUaGUgZ2VuZXMgZnJvbSB0aGUgdXBsb2FkZWQgY2x1c3RlciB0aGF0IHdlcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSB0ZXJtLgoKIyMgSGlzdG9ncmFtIHdpdGggdGVybXMKClRoZSBjaGFydCBwcmVzZW50cyB0aGUgc3BlY2lmaWMgdGVybXMgZm9yIHRoZSB1c2VyIGdlbmVzIGFuZCBpbmZvcm1hdGlvbiByZWxhdGVkIHRvIHRoZWlyIGFzc29jaWF0ZWQgZ2VuZXMuClRoZSBkaXNwbGF5IGNhbiBiZSBjdXN0b21pemVkIChzZWUgQWR2YW5jZWQgc2V0dGluZ3MpLiBQcmVkZWZpbmVkLCB0aGUgYmFycyByZXByZXNlbnQgdGhlIG51bWJlciBvZgp0aGUgZ2VuZXMgZnJvbSB0aGUgYW5hbHl6ZWQgY2x1c3RlciBmb3VuZCBhc3NvY2lhdGVkIHdpdGggdGhlIHRlcm0sIGFuZCB0aGUgbGFiZWwgZGlzcGxheWVkIG9uIHRoZSBiYXJzCmlzIHRoZSBwZXJjZW50YWdlIG9mIGZvdW5kIGdlbmVzIGNvbXBhcmVkIHRvIGFsbCB0aGUgZ2VuZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSB0ZXJtLiBUZXJtIHNpZ25pZmljYW5jZQppbmZvcm1hdGlvbiBpcyBpbmNsdWRlZCBpbiB0aGUgY2hhcnQgKHNlZSBTdGF0aXN0aWNzKS4KCiFbXShpbWFnZXMvQ2x1ZUdPLWhpc3RvZ3JhbS5wbmcpCgoKIyMgT3ZlcnZpZXcgQ2hhcnQgd2l0aCBmdW5jdGlvbmFsIGdyb3VwcwoKVGhlIG92ZXJ2aWV3IGNoYXJ0IHByZXNlbnRzIGZ1bmN0aW9uYWwgZ3JvdXBzIGZvciB0aGUgdXNlciBnZW5lcy4gVGhlIG5hbWUgb2YgdGhlIGdyb3VwIGlzIGdpdmVuIGJ5IHRoZQpncm91cCBsZWFkaW5nIHRlcm0gKGUuZy4gdGhlIG1vc3Qgc2lnbmlmaWNhbnQgdGVybSBpbiB0aGUgZ3JvdXApLiBUaGUgZ3JvdXAgc2VjdGlvbnMgY29ycmVsYXRlIHdpdGggdGhlCm51bWJlciBvZiB0aGUgdGVybXMgaW5jbHVkZWQgaW4gZ3JvdXAuIFRoZSBwb3NpdGlvbiBvZiB0aGUgc2VjdGlvbnMgY2FuIGJlIGNoYW5nZWQgKHJpZ2h0IGNsaWNrKS4KCiMjIExvZ2luZyBpbmZvcm1hdGlvbgoKQ29tcGxldGUgaW5mb3JtYXRpb24gb24gdGhlIGFwcGxpZWQgc2VsZWN0aW9uIGNyaXRlcmlhIGZvciBlYWNoIGFuYWx5c2lzIGNhbiBiZSB2aXN1YWxpemVkIGluIHRoZSBsb2dpbmcKaW5mb3JtYXRpb24gcGFuZWwuCgohW10oaW1hZ2VzL0NsdWVHTy1Mb2dpbkluZm8ucG5nKQoKIyMgQWR2YW5jZWQgU2V0dGluZ3MKCkNsdWVHTyBhZHZhbmNlZCBzZXR0aW5ncyBhbGxvd3MgYSBwcmVjaXNlIGFkanVzdG1lbnQgb2YgdGhlIHNlbGVjdGlvbiBjcml0ZXJpYS4KCiFbXShpbWFnZXMvQ2x1ZUdPLUZ1bmN0aW9uYWxHcm91cHMucG5nKQoKCgoxLiBHTyB0cmVlIGxldmVsLiBUaGUgaWRlbnRpZmllcnMgY2FuIGJlIG1hcHBlZCBpbiB0aGUgZW50aXJlIG9udG9sb2d5IHRyZWUgb3IgaW4gYSBHTyBsZXZlbCBpbnRlcnZhbAooYmV0d2VlbiBNaW4gYW5kIE1heCBsZXZlbHMpLiBJZiBzZWxlY3RlZCB0aGUgZmlyc3QgR08gbGV2ZWxzICgxLTMpLCB0aGUgdGVybXMgd2lsbCBiZSB2ZXJ5IGdlbmVyYWwuClRob3NlIHRlcm1zIGhhdmUgbWFueSBhc3NvY2lhdGVkIGdlbmVzLCBzbywgdGhlcmUgd2lsbCBiZSBhIGxvdyBwZXJjZW50YWdlIG9mIGZvdW5kIGdlbmVzIGZyb20KdGhlIHVzZXIgZ2VuZXMuIFRoZSB2ZXJ5IHNwZWNpZmljIHRlcm1zIChlLmcuIGxldmVsIDEyKSBoYXZlIGFzc29jaWF0ZWQgYSBzbWFsbCBudW1iZXIgb2YgZ2VuZXMuCkluIHRoaXMgY2FzZSwgdGhlIHBlcmNlbnRhZ2Ugb2YgZm91bmQgZ2VuZXMgaXQgaXMgaGlnaGVyLiBBbnl3YXksIG9uZSBoYXMgdG8gY29uc2lkZXIgdGhlIGNvbXBsZXgKaGllcmFyY2hpY2FsIEdPIHN0cnVjdHVyZSB0aGF0IG1ha2VzIHRoZSB0ZXJtcyB0byBiZSBpbiBzZXZlcmFsIGxldmVscy4gVGhpcyBmZWF0dXJlIGlzIGF2YWlsYWJlCndoaWxlIHVzaW5nIGEgaGllcmFyY2hpY2FsbHkgc3RydWN0dXJlZCBvbnRvbG9neSBzb3VyY2UgKGUuZy4gR08pLgoKMi4gTWluaW11bSBudW1iZXIgb2YgaWRlbnRpZmllcnMgZnJvbSB0aGUgdXBsb2FkZWQgY2x1c3RlciBmb3VuZCB0byBiZSBhc3NvY2lhdGVkIHdpdGggYSB0ZXJtLgoKMy4gTWluaW11bSBwZXJjZW50YWdlIHRoYXQgdGhlIG1hcHBlZCBpZGVudGlmaWVycyBhcmUgcmVwcmVzZW50aW5nIGZyb20gdGhlIHRvdGFsIGFzc29jaWF0ZWQgZ2VuZXMKd2l0aCB0aGUgdGVybQoKIVtdKGltYWdlcy9DbHVlR08tQWR2YW5jZWRTZXR0aW5ncy5wbmcpCgoKNC4gRnVzaW9uLiBUaGUgdGVybXMgaW4gcGFyZW50LWNoaWxkIHJlbGF0aW9uc2hpcCB0aGF0IHNoYXJlIHNpbWlsYXIgZ2VuZXMgKGlkZW50aWNhbCwgb3Igd2l0aCBvbmUgZ2VuZQpkaWZmZXJlbmNlKSBhcmUgYXNzZXNzZWQgYW5kIHRoZSBtb3N0IHJlcHJlc2VudGF0aXZlIHBhcmVudCBvciBjaGlsZCB0ZXJtIGlzIHJldGFpbmVkLgpOb3RlOiBUaGlzIGlzIGFuIG9wdGlvbmFsIGZlYXR1cmUuIFRoZSBmdXNpb24gc3Ryb25nbHkgcmVkdWNlcyB0aGUgcmVkdW5kYW5jeS4KNS4gS2FwcGEgU2NvcmUgc2hvd3MgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB0aGUgdGVybXMgYmFzZWQgb24gdGhlaXIgb3ZlcmxhcHBpbmcgZ2VuZXMuIEl0IGlzCnVzZWQgZm9yIGNyZWF0aW5nIHRoZSBuZXR3b3JrIGFuZCBjYW4gYmUgdXNlZCBmb3IgY3JlYXRpbmcgdGhlIGdyb3Vwcy4gSW5pdGlhbGx5LCBhIHRlcm0tZ2VuZQptYXRyaXggY29udGFpbmluZyB0aGUgc2VsZWN0ZWQgdGVybXMgYW5kIHRoZWlyIGFzc29jaWF0ZWQgZ2VuZXMgaXMgY3JlYXRlZC4gQmFzZWQgb24gdGhpcywgYSB0ZXJtdGVybSBzaW1pbGFyaXR5IG1hdHJpeCBpcyBjYWxjdWxhdGVkIHVzaW5nIGthcHBhIHN0YXRpc3RpY3MgdG8gZGV0ZXJtaW5lIHRoZSBhc3NvY2lhdGlvbiBzdHJlbmd0aApiZXR3ZWVuIHRoZSB0ZXJtcyAoa2FwcGEgc2NvcmUpLiBIaWdoIHNjb3JlID0gdmlzdWFsaXplIGluIHRoZSBuZXR3b3JrIG9ubHkgdGhlIGNvbm5lY3Rpb25zCmJldHdlZW4gY2xvc2UgcmVsYXRlZCB0ZXJtcywgd2l0aCB2ZXJ5IHNpbWlsYXIgYXNzb2NpYXRlZCBnZW5lcyAoaGlnaCBzdHJpbmdlbmN5KS4gTG93IHNjb3JlID0KYWxsb3dzIHRvIHZpc3VhbGl6ZSBpbiB0aGUgbmV0d29yayB0aGUgY29ubmVjdGlvbnMgYmV0d2VlbiBsZXNzIHJlbGF0ZWQgdGVybXMgKGxvdyBzdHJpbmdlbmN5KS4KNi4gQ3JlYXRlIGZ1bmN0aW9uYWwgZ3JvdXBzLiBUaGUgdGVybXMgY2FuIGJlIGFzc29jaWF0ZWQgaW4gZnVuY3Rpb25hbCBncm91cHMgdXNpbmcgdGhlIG9udG9sb2d54oCZcwpoaWVyYXJjaHkgb3IgdGhlIGthcHBhIHNjb3JlLgpXaGVuIGRpc3BsYXlpbmcgdGhlIGZ1bmN0aW9uYWwgZ3JvdXBzIG9uIHRoZSBuZXR3b3JrLCBvbmUgaGFzIHRvIGNvbnNpZGVyIHRoYXQgdGhlIG5ldHdvcmsgc3RydWN0dXJlIGlzIGNhbGN1bGF0ZWQgd2l0aCBrYXBwYSBzY29yZS4gVGhlIGthcHBhIHNjb3JlIGdyb3VwaW5nIG9mIHRoZSB0ZXJtcyB3aWxsIGNvcnJlc3BvbmQgd2l0aAp0aGUgbmV0d29yayBzdHJ1Y3R1cmUgdGhhdCBpcyBjYWxjdWxhdGVkIGluIHRoZSBzYW1lIG1hbm5lci4gSWYgdGhlIGhpZXJhcmNoaWNhbCBncm91cGluZyBpcyB1c2VkLCBpdAppcyBwb3NzaWJsZSB0byBiZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbmV0d29ya3Mgc3RydWN0dXJlIChiYXNlZCBvbiB0aGUgYXNzb2NpYXRlZCBnZW5lcykgYW5kCnRoZSBmdW5jdGlvbmFsIGdyb3VwcyBkZWZpbmVkIHVzaW5nIEdPIGhpZXJhcmNoeS4KCjcuIFVzZSBmaXggY29sb3JpbmcgZm9yIHRoZSBncm91cHMKOC4gVXNlIHJhbmRvbSBjb2xvcmluZyBmb3IgdGhlIGdyb3Vwcwo5LiBUaGUgbW9zdCByZXByZXNlbnRhdGl2ZSB0ZXJtIGluIGEgZ3JvdXAgaXMgZ2l2aW5nIHRoZSBuYW1lIG9mIHRoZSBncm91cC4gSXQgY2FuIGJlIGNvbnNpZGVyZWQgaGF2aW5nOgogIGEpIHRoZSBoaWdoZXN0IG51bWJlciBvZiB0aGUgZm91bmQgZ2VuZXMgcGVyIHRlcm0KICBiKSB0aGUgaGlnaGVzdCBwZXJjZW50YWdlIG9mIGZvdW5kIGdlbmVzIHBlciB0ZXJtCiAgYykgdGhlIGhpZ2hlc3QgcGVyY2VudGFnZSBvZiBmb3VuZCBnZW5lcyBwZXIgdG90YWwgbnVtYmVyIG9mIGZvdW5kIGdlbmVzCiAgZCkgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgUFZhbHVlClRoaXMgc2VsZWN0aW9uIGRldGVybWluZXMgdGhlIENsdWVHTyBjaGFydHMgZGlzcGxheTogdGhlIG51bWJlci9wZXJjZW50YWdlL3NpZ25pZmljYW5jZSBvZiB0aGUKdGVybXMuIElmIHRoZSBncm91cCBsZWFkaW5nIHRlcm0gaXMgdGhlIHRlcm0gd2l0aCB0aGUgaGlnaGVyIG51bWJlciBvZiBnZW5lcyBvciB0aGUgbW9zdCBzaWduaWZpY2FudCB0ZXJtIGZyb20gdGhlIGdyb3VwLCBhIGxhYmVsIHdpdGggdGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIGZvdW5kIGdlbmVzIGNvbXBhcmVkIHdpdGggYWxsIHRoZQphc3NvY2lhdGVkIGdlbmVzIHdpdGggdGhlIHRlcm0gaXMgZGlzcGxheWVkIG9uIHRoZSBiYXJzIG9mIHRoZSBjaGFydC4gUmV2ZXJzZWx5LCBpZiB0aGUgZ3JvdXAgbGVhZGluZwp0ZXJtIGlzIHJlcHJlc2VudGluZyB0aGUgcGVyY2VudGFnZSBvZiBnZW5lcyAoY29tcGFyZWQgdG8gYWxsIHRoZSBnZW5lcyBhc3NvY2lhdGVkIHdpdGggdGhlIHRlcm0Kb3Igd2l0aCBhbGwgdGhlIGdlbmVzIGZvdW5kIGZyb20gdGhlIHVwbG9hZGVkIGNsdXN0ZXIpLCBvbiB0aGUgbGFiZWwgd2lsbCBiZSBkaXNwbGF5ZWQgdGhlIG51bWJlcgpvZiB0aGUgZ2VuZXMgZm91bmQgZm9yIHRoaXMgdGVybS4KCjEwLiBUaGUgaGllcmFyY2h5IGJhc2VkIGdyb3VwaW5nIGNvbnNpc3RzIGluIGFuYWx5emluZyB0aGUgc2VsZWN0ZWQgdGVybXMgdGhyb3VnaCB0aGUgcGVyc3BlY3RpdmUKb2YgdGhlaXIgcGFyZW50IHRlcm1zLiBUaGUgc2l6ZSBvZiB0aGUgZ3JvdXBzIGNhbiBiZSBkZWZpbmVkIHVzaW5nIHRoZSBudW1iZXIgb2YgY29tbW9uIGFuZApkaWZmZXJlbnQgcGFyZW50cywgdGhhdCBpcyBkZXBlbmRpbmcgb24gdGhlIGxldmVsIG9mIHRoZSB0ZXJtIGluIEdPIGhpZXJhcmNoeS4gU2luY2UgS0VHRyBhbmQKQmlvQ2FydGEgZG9u4oCZdCBoYXZlIGEgaGllcmFyY2hpY2FsIHN0cnVjdHVyZSwgdGhlIHRlcm1zIHNlbGVjdGVkIGZyb20gdGhvc2Ugc291Y2VzIHdpbGwgbm90IGJlCmdyb3VwZWQuCgoxMS4gRm9yIGdyb3VwaW5nIHRoZSB0ZXJtcyBiYXNlZCBvbiB0aGUga2FwcGEgc2NvcmUsIGl0IGlzIG5lY2Vzc2FyeSB0byBzZXQgdGhlIHNpemUgb2YgdGhlIGluaXRpYWwgZ3JvdXAKKGUuZy4gMykgYW5kIHRoZSBwZXJjZW50YWdlIChvdmVybGFwaW5nIHRlcm1zL2dyb3VwKSBmb3IgZ3JvdXAgbWVyZ2UgKGUuZy4gNTAgcGVyY2VudCkuIEZvciBtb3JlCmRldGFpbHMgc2VlIFs0XS4gQWxsIHRoZSBwb3NzaWJsZSBpbml0aWFsIGdyb3VwcyB3aXRoIHRoZSB0ZXJtcyBzaG93aW5nIGEga2FwcGEgc2NvcmUgZXF1YWwgb3IKYWJvdmUgdGhlIHByZWRlZmluZWQgdGhyZXNob2xkIChlLmcuwqE9IDAuMykgYXJlIGNyZWF0ZWQuIEZ1cnRoZXIsIHRoZSBpbml0aWFsIGdyb3VwcyBhcmUgaXRlcnJhdGl2ZWx5CmNvbXBhcmVkIGFuZCBtZXJnZWQgaWYgdGhleSBhcmUgb3ZlcmxhcHBpbmcgaW4gdGhlIGRlZmluZWQgcGVyY2VudGFnZS4gQSB0ZXJtIGNhbiBiZSBwYXJ0IG9mCnNldmVyYWwgZ3JvdXBzLiBUaGUgcmVvY3VycmVuY2Ugb2YgdGhlIHRlcm0gaXMgc2hvd24gYnkgYWRkaW5nIOKAnSBu4oCdLiBJZiB0aGUgdGVybXMgaGF2ZSB2ZXJ5CnNpbWlsYXIgYXNzb2NpYXRlZCBnZW5lcywgaXQgaXMgcG9zc2libGUgdGhhdCB0aGUgaXRlcmF0aXZlIG1lcmdpbmcgb2YgdGhlIGNyZWF0ZWQgZ3JvdXBzIHRvIHRha2UgYQpsb25nZXIgdGltZSBpbiB0aGUgYXR0ZW1wdCBvZiBtZXJnaW5nIGFsbCB0aGUgZ3JvdXBzLiBJbiB0aGlzIGNhc2UsIGl0IGlzIHJlY29tbW5lbmRlZCB0byBpbmNyZWFzZQp0aGUga2FwcGEgc2NvcmUgbGV2ZWwgb3IgdG8gaW5jcmVhc2UgdGhlIHBlcmNlbnRhZ2UgZm9yIGdyb3VwIG1lcmdlLgoKIyMgQWR2YW5jZWQgU3RhdGlzdGljYWwgT3B0aW9ucwoxLiBTZWxlY3QgbWlkLVAtdmFsdWUgZm9yIGEgbGVzcyBjb25zZXJ2YXRpdmUgaHlwZXJnZW9tZXRyaWMgdGVzdC4KMi4gU2VsZWN0IERvdWJsaW5nIGZvciBhIGxlc3MgY29uc2VydmF0aXZlIHR3byB0YWlsZWQgaHlwZXJnZW9tZXRyaWMgdGVzdC4KCiFbXShpbWFnZXMvQ2x1ZUdPLUFkdmFuY2VkU3RhdGlzdGljYWwucG5nKQoKCiMjIENsdXN0ZXIgQ29tcGFyaXNvbgoKT25jZSBzZWxlY3RlZCB0aGUgb3B0aW9uOiAqKuKAnUNvbXBhcmUgY2x1c3RlcnPigJ0qKiwgdHdvIGZpbGUgY2hvb3NlcnMgYXJlIG1hZGUgYXZhaWxhYmxlLiBUaGUgc2VsZWN0aW9uIG9mIHRoZQpvbnRvbG9neSB0ZXJtcyBpcyBmb2xsb3dpbmcgdGhlIHNhbWUgc3RlcHMgYXMgaW4gdGhlIGFuYWx5c2lzIGZvciBhIHNpbmdsZSBjbHVzdGVyLgoKVGhlIGRpZmZlcmVuY2UgcmVmZXJzIHRvIHRoZSBudW1iZXIgYW5kIHRoZSBwZXJjZW50YWdlIG9mIHRoZSBnZW5lcyBwZXIgdGVybS4gVGhvc2Ugc2VsZWN0aW9uIGNyaXRlcmlhIGNhbgpiZSBmbGV4aWJsZTogQ2x1c3RlcjEgT1IgQ2x1c3RlcjIgb3B0aW9ucyAoMSkgb3IgYXBwbGllZCBzdHJpY3RseSBmb3IgYm90aCBjbHVzdGVyczogQ2x1c3RlcjEgQU5EIENsdXN0ZXIyCm9wdGlvbnMgKDIpLiAKCkl0IGlzIHJlY29tbWVuZGVkIHRvIGhhdmUgY29tcGFyYWJsZSBudW1iZXIgb2YgaWRlbnRpZmllcnMgaW4gdGhlIGFuYWx5c2VkIGNsdXN0ZXJzLiBJZiBvbmUKY2x1c3RlciBpcyBtdWNoIGxhcmdlciwgdGhlIHNlbGVjdGlvbiBjcml0ZXJpYSBzaG91bGQgYmUgYXBwbGllZCBtb3JlIHN0cmljdGx5IChlLmcuIGluY3JlYXNlIHRoZSBudW1iZXIgb2YKZ2VuZXMgcGVyIHRlcm0pLgoKCiFbXShpbWFnZXMvQ2x1ZUdPLUNvbXBhcmlzb24ucG5nKQoKIVtdKGltYWdlcy9DbHVlR28tQ29tbW9uVGVybXMucG5nKQoKCkZ1cnRoZXIsIHdlIGFuYWx5emUgdGhlIHRlcm1zIHRyb3VnaCB0aGUgcGVyc3BlY3RpdmUgb2YgdGhlaXIgYXNzb2NpYXRlZCBnZW5lcy4gSXQgaXMgcG9zc2libGUgdGhhdApnZW5lcyBmcm9tIGJvdGggY2x1c3RlcnMgd2lsbCBiZSBhc3NvY2lhdGVkIHdpdGggYSB0ZXJtLCBidXQgaW4gZGlmZmVyZW50IHByb3BvcnRpb25zLiBXZSBkZWZpbmVkIGEgdGVybQphcyBzcGVjaWZpYyBmb3Igb25lIG9mIHRoZSBjbHVzdGVycyBpZiB0aGUgcGVyY2VudGFnZSBvZiBhc3NvY2lhdGVkIGdlbmVzIGZyb20gdGhpcyBjbHVzdGVyIGlzIGhpZ2hlciB0aGFuCnRoZSBzZWxlY3RlZCB0aHJlc2hvbGQgKGUuZy4gNjYgcGVyY2VudCkgKDMpLiBBcyByZXN1bHQsIGNoYXJ0cyB3aXRoIHNwZWNpZmljIHRlcm1zIGZvciBlYWNoIGNsdXN0ZXIgYXJlCnByb3ZpZGVkLiBUaGUgY29tbW9uIHRlcm1zIGFyZSBpbmNsdWRlZCBpbiBhIHNlcGFyYXRlIGNoYXJ0LgoKT24gdGhlIG5ldHdvcmssIHRoZSBkaWZmZXJlbnQgcHJvcG9ydGlvbiBvZiB0aGUgZ2VuZXMgZnJvbSB0aGUgYW5hbHl6ZWQgY2x1c3RlcnMgaXMgcmVwcmVzZW50ZWQgd2l0aAphIGNvbG9yIGdyYWRpZW50IGZyb20gZ3JlZW4sIGZvciB0aGUgZmlyc3QgY2x1c3RlciBnZW5lcywgdG8gcmVkIGZvciB0aGUgc2Vjb25kIGNsdXN0ZXIuClRoZSB2aXN1YWxpemF0aW9uIG9mIHRoZSBncm91cHMgb24gdGhlIG5ldHdvcmsgY2FuIGJlIHN3aXRjaGVkIHdpdGggdGhlIG9uZSBvZiB0aGUgdXBsb2FkZWQgY2x1c3RlcnMKZGlzdHJpYnV0aW9uIG9uIHRoZSBzZWxlY3RlZCB0ZXJtcyAoc2VlIEZpZ3VyZSBiZWxvdykuCgoKIVtdKGltYWdlcy9DbHVlR08tSW50ZWdyYXRlZC5wbmcpCgojIyBDbHVlR08gcmVzdWx0IHZpc3VhbGl6YXRpb25zCgohW10oaW1hZ2VzL0NsdWVHTy1SZXN1bHRfVmlzLnBuZykKPGJyPjwvYnI+PGJyPjwvYnI+CgoKPGRpdiBjbGFzcz0iZXhlcmNpc2UiPgoKIyBXYWxrLXRocm91Z2ggZXhlcmNpc2UKCkZvciB0aGUgZXhlcmNpc2UsIHdlIGFyZSBnb2luZyB0byB1c2UgbVJOQSBibGFkZGVyIGNhbmNlciBkYXRhIGdlbmVyYXRlZCBmcm9tIFJOQS1TZXEgcGxhdGZvcm0uIFRoZSBkYXRhIGNhbiBiZSByZXRyaXZlZCBmcm9tIFJvYmVydHNvbiBldCBhbC4gQ2VsbCAyMDE3IG9yIGRvd25sb2FkZWQgZnJvbSAoW0hlcmUuLl0oaHR0cHM6Ly9naXRodWIuY29tL2ExYWtzL0N5dG9zY2FwZV9Db3Vyc2UvdHJlZS9tYWluL0RhdGFfRmlsZXMpKSAKCiMjIENsdWVHTyBzZXR0aW5ncwoKKiBzZXQgdGhlIHR5cGUgb2YgYW5hbHlzaXM6IENvbXBhcmUgQ2x1c3RlcgoqIHNlbGVjdCB0aGUgb3JnYW5pc206IEhvbW8gU2FwaWVucyBhbmQgdGhlIHRoZSB0eXBlIG9mIGlkcyB1c2VkOiBBY2Nlc3Npb25JRAoqIGxvYWQgc2FtcGxlIGdlbmUgbGlzdHM6CiAgKiAqKmNob29zZSBDbHVzdGVyICMxKio6IHNlbGVjdCBUb3BfRG93bl9nZW5lc19CTENBX1Nlc3Npb24zLnR4dCAtIChbSGVyZS4uXShodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vYTFha3MvQ3l0b3NjYXBlX0NvdXJzZS9tYWluL0RhdGFfRmlsZXMvVG9wX0Rvd25fZ2VuZXNfQkxDQV9TZXNzaW9uMy50eHQpKQogICogKipjaG9vc2UgQ2x1c3RlciAjMioqOiBUb3BfVXBfZ2VuZXNfQkxDQV9TZXNzaW9uMy50eHQgLSAoW0hlcmUuLl0oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2ExYWtzL0N5dG9zY2FwZV9Db3Vyc2UvbWFpbi9EYXRhX0ZpbGVzL1RvcF9VcF9nZW5lc19CTENBX1Nlc3Npb24zLnR4dCkpCiogc2VsZWN0IHRoZSBPbnRvbG9naWVzOgogICogR08gQmlvbG9naWNhbFByb2Nlc3MsCiAgKiBLRUdHIFBhdGh3YXlzICBhbmQKICAqIEJpb0NhcnRhIHBhdGh3YXkgcmVhY3RvbWUgCiogc2VsZWN0IHRoZSBzdGF0aXN0aWNhbCB0ZXN0OiAqKkVucmljaG1lbnQvRGVwbGVjdGlvbiAoVHdvIHNpZGVkIGh5cGVyZ2VvbWV0cmljIHRlc3QpKiosICoqRmlzaGVyRXhhY3RUZXN0KioKKiBzZWxlY3QgdGhlIGNvcnJlY3Rpb24gbWV0aG9kOiAqKkJvbmZlcnJvbmkqKgoqIGNsaWNrIFNob3cgQWR2YW5jZWQgU2V0dGluZ3MKKiBzZXQgR08gVHJlZSBMZXZlbDogTWluIDQgYW5kIE1heCA1Ciogc2V0IHRoZSBzZWxlY3Rpb24gY3JpdGVyaWEgZm9yIHRoZSB0ZXJtcyB0aGF0IGhhdmUgYXNzb2NpYXRlZCBnZW5lcyBmcm9tIGNsdXN0ZXIgMTogbWluIDIgZ2VuZXMvdGVybQphbmQgbWluaW11bSA0JSBmcm9tIGFsbCB0aGUgR2VuZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSB0ZXJtCiogc2VsZWN0IE9SIChlLmcuIG1pbiAyIGdlbmVzIGZyb20gY2x1c3RlciAjMSBvciBtaW4gMiBnZW5lcyBmcm9tIGNsdXN0ZXIgIzIpCiogc2V0IGlzIHNwZWNpZmljIHRvIDY2JSAoaWYgNjYlIG9yIHRoZSBnZW5lcyBhc3NvY2lhdGVkIHdpdGggdGhlIHRlcm0gYXJlIGZyb20gY2x1c3RlciAjMSwgdGhlIHRlcm0KaXMgY29uc2lkZXJlZCBzcGVjaWZpYyBmb3IgdGhpcyBjbHVzdGVyKQoqIHNldCB0aGUgc2VsZWN0aW9uIGNyaXRlcmlhIGZvciB0aGUgdGVybXMgdGhhdCBoYXZlIGFzc29jaWF0ZWQgZ2VuZXMgZnJvbSBjbHVzdGVyIDI6IG1pbiAyIGdlbmVzL3Rlcm0KYW5kIG1pbmltdW0gNCUgZnJvbSBhbGwgdGhlIEdlbmVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgdGVybQoqIHNlbGVjdCBVc2UgR08gVGVybSBHcm91cGluZwoqIHNlbGVjdCBGaXggR3JvdXAgY29sb3JpbmcKKiBzZWxlY3QgTGVhZGluZyBHcm91cCBUZXJtIGJhc2VkIG9uIEhpZ2hlc3QgU2lnbmlmaWNhbmNlCiogc2VsZWN0IEthcHBhIFNjb3JlIGdyb3VwaW5nIHdpdGggMyB0ZXJtcyBpbiBpbml0aWFsIGdyb3VwIGFuZCA1MCUgb3ZlcmxhcCBmb3IgZ3JvdXBzIHRvIG1lcmdlCiogc2VsZWN0IFNob3dEaWZmZXJlbmNlCiogU3RhcnQKCgojIyBDdXN0b21pemUgdGhlIG5ldHdvcmsgdXNpbmcgQ3l0b3NjYXBlIGZlYXR1cmVzCgoqIHNlbGVjdCAqKlN0eWxlKiogKEN5dG9zY2FwZSBDb250cm9sIFBhbmVsKQoqIHNlbGVjdCBOb2RlIEZvbnQgU2l6ZQoqIHNldCB0aGUgdmFsdWUgb2YgRkFMU0UgKHNpemUgZm9yIHRoZSBuYW1lIG9mIHRoZSB0ZXJtcykgdG8gMC4wMDEgYW5kIHByZXNzIEVudGVyCiogc2V0IHRoZSB2YWx1ZSBvZiBUUlVFIChzaXplIGZvciB0aGUgbmFtZSBvZiBncm91cHMpIHRvIDI2IGFuZCBwcmVzcyBFbnRlcgoqIHNlbGVjdCBMYXlvdXQgKEN5dG9zY2FwZSBtZW51IGJhcikKKiBzZXQgc2NhbGUgdG8gMS8zCiogem9vbSB0aGUgaW1hZ2UKKiBjaGFuZ2UgdGhlIHBvc2l0aW9uIG9mIHRoZSBsZWFkaW5nIHRlcm1zIHRvIG1ha2UgdmlzaWJsZSB0aGUgbmFtZSBvZiB0aGUgZ3JvdXAKKiBjaGFuZ2UgdGhlIHBvc2l0aW9uIG9mIG5vdGdyb3VwZWQgdGVybXMgaWYgZHVlIHRvIHJlLXNjYWxpbmcgdGhleSBhcmUgdG9vIGNsb3NlIHRvIGEgZ3JvdXAKKiBmb3IgdmlzdWFsaXppbmcgZ3JvdXBzIHByZXNzIFNob3cgR3JvdXBzCgoKKiBVc2luZyB0aGUgZmlsdGVycyBhbmQgc3R5bGUgb3B0aW9ucyBhYm92ZSwgZGV2ZWxvcCBhIG5ldHdvcmsgYnkgdXNpbmcgY2x1c3RlciBjb21wYXJlIGZvciB0aGUgdHdvIGJsYWRkZXIgY2FuY2VyIGNvbmRpdGlvbnMgLSBOb3JtYWwgVlMgVHVtb3IuIAoKKiBTYXZlIHlvdXIgbmV0d29yayBpbiB0d28gZm9ybWF0czogKGEpIGFzIGEgQ3l0b3NjYXBlIFNlc3Npb24gKCoqLnN5cyAqKiBmb3JtYXQpLCBhbmQgIChiKSBhcyBhICoqLnBuZyBvciAucGRmKiogZmlndXJlLgogICogVGhlIGN5dG9zY2FwZSBzZXNzaW9uICguc3lzKSB3aWxsIGJlIHVzZWQgaW4gdGhlIG5leHQgc2VjdGlvbiBmb3IgQ2x1ZVBlZGlhIGFuYWx5c2lzLiAKCk1vcmUgZGV0YWlscyBvbiB1c2luZyBzcGVjaWZpYyBvcHRpb25zIGNhbiBiZSBhY2hpZXZlZCBieSBmb2xvd2luZyB0aGUgKipDbHVlR08qKiBkb2N1bWVudGF0aW9uOiBodHRwOi8vd3d3LmljaS51cG1jLmZyL2NsdWVnby9DbHVlR09Eb2N1bWVudGF0aW9uMjAxOS5wZGYKCjwvZGl2PgoKPGJyPjwvYnI+CgojIFNlY3Rpb24gQiAtIEFuYWx5c2Ugd2l0aCBDbHVlUGVkaWEuIAoKIyMgQmFja2dyb3VuZDogCioqQ2x1ZVBlZGlhKiogcHJvdmlkZXMgaW5zaWdodHMgaW50byBwYXRod2F5cyBieSBpbnRlZ3JhdGluZyBleHBlcmltZW50YWwgYW5kIGluIHNpbGljbyBpbmZvcm1hdGlvbi4KCiogQ2x1ZVBlZGlhIGV4dGVuZHMgQ2x1ZUdPIChbM10pIGZ1bmN0aW9uYWxpdHkgZG93biB0byBnZW5lcyBhbmQgbWlSTkFzLiBJZiBDbHVlR08gcmV2ZWFscyBpbnRlcnJlbGF0aW9ucyBvZiB0ZXJtcyBhbmQgZnVuY3Rpb25hbCBncm91cHMgaW4gYmlvbG9naWNhbCBuZXR3b3JrcywgQ2x1ZVBlZGlhIGdpdmVzIHRoZSBwb3NpYmlsaXR5IHRvIGVucmljaCB0aG9zZSBuZXR3b3JrcyB3aXRoIGtub3duIGFuZCBleHBlcmltZW50YWwgZGF0YS4KCiogQ2x1ZVBlZGlhIGNhbGN1bGF0ZXMgc3RhdGlzdGljYWwgZGVwZW5kZW5jaWVzIChjb3JyZWxhdGlvbikgZm9yIG1hcmtlcnMgb2YgaW50ZXJlc3QgZnJvbSBleHBlcmltZW50YWwgZGF0YS4gRm91ciB0ZXN0cyBpbnZlc3RpZ2F0aW5nIGxpbmVhciBhbmQgbm9ubGluZWFyIGRlcGVuZGVuY2llcyBiZXR3ZWVuIHZhcmlhYmxlcyBhcmUgaW1wbGVtZW50ZWQ6IFBlYXJzb24gY29ycmVsYXRpb24sIFNwZWFybWFu4oCZcyByYW5rLCBEaXN0YW5jZSBjb3JyZWxhdGlvbiAoWzRdKSBhbmQgTWluaW1hbCBJbmZvcm1hdGlvbiBDcml0ZXJpYSAoTUlDKSAoWzVdKS4gVGhlIHJlc3VsdGluZyBmaWxlIGlzIGFkZGVkIHRvIENsdWVQZWRpYSBhcyBhbiBhZGRpdGlvbmFsCnJlc291cmNlIGZvciBmdXJ0aGVyIGFuYWx5c2lzLgoKKiBFeHBlcmltZW50YWwgZGF0YSBjYW4gYmUgbm9ybWFsaXplZCBhbmQgdmlzdWFsaXplZCBiZXR3ZWVuIGFkanVzdGFibGUgdGhyZXNob2xkcyBvbiBuZXR3b3Jr4oCZcyBub2RlcyBhcyBhIGxhYmVsLiBSZWxldmFudCBzaWduYWxzIHdpdGggYSBjZXJ0YWluIGV4cHJlc3Npb24gbGV2ZWwsIHN0YW5kYXJkIGRldmlhdGlvbgphbmQgd2l0aG91dCBtaXNzaW5nIHZhbHVlcyBjYW4gYmUgc2VsZWN0ZWQuIEFub3RoZXIgZmVhdHVyZSBhbGxvd3MgdGhlIGV4dHJhY3Rpb24gb2YgZXhwcmVzc2lvbgpjb3JyZXNwb25kaW5nIHRvIHNlbGVjdGVkIG1hcmtlcnMsIGUuZy4gZ2VuZXMgYXNzb2NpYXRlZCB0byBhIHBhdGh3YXksIGZyb20gYSBkYXRhc2V0IGludG8gYSBuZXcKZmlsZS4KCiogT25lIG1ham9yIGFkdmFudGFnZSBpcyB0aGUgcG9zc2liaWxpdHkgdG8gaW52ZXN0aWdhdGUgaW4gZGV0YWlsIGEgcGF0aHdheSBieSBjb21iaW5pbmcga25vd24gWzMsIDRdIGFuZCBuZXcsIGV4cGVyaW1lbnRhbCBkZXJpdmVkIGluZm9ybWF0aW9uLCBhYm91dCBnZW5lcy9wcm90ZWlucyBpbnZvbHZlZC4gTW9yZSwgbWlSTkFzIFs3LCA4XSB0aGF0IGNvdWxkIGluZmx1ZW5jZSB0aGUgZXhwcmVzc2lvbiBvZiB0aGUgZ2VuZXMgY2FuIGJlIGFzIHdlbGwgdmlzdWFsaXplZCB0b2dldGhlciB3aXRoIHRoZSBleHByZXNzaW9uIGRhdGEuIFRoZSBsb2NhdGlvbiBvZiB0aGUgZ2VuZXMvcHJvdGVpbnMgWzksIDEwXSB3aXRoaW4gY2VsbHVsYXIgY29tcGFydG1lbnRzIGNhbiBiZSBhdXRvbWF0aWNhbGx5IGRpc3BsYXllZCwgYnkgdGhlIGltcGxlbWVudGF0aW9uIG9mIENlcmVicmFsIFsxMF0gbGF5b3V0IHdpdGhpbiBDbHVlUGVkaWEuCgoqIENsdWVQZWRpYSBwcm92aWRlcyBhbiBJRCBpbmRleCBmaWxlICh1cGRhdGFibGUsIGV4dGVuZGFibGUpIHRoYXQgc3RvcmVzIGVudHJleiBnZW5lIGlkcyBhbmQgc3ltYm9scyBhbmQgYWxsb3dzIGZhc3QgYW5hbHlzaXMuCgoqIEJvdGggcGx1Z2lucywgQ2x1ZVBlZGlhIGFuZCBDbHVlR08sIHRha2UgYWR2YW50YWdlIG9mIEN5dG9zY2FwZeKAmXMgdmVyc2F0aWxlIHZpc3VhbGl6YXRpb24gZnJhbWV3b3JrCgoKIyMgU29mdHdhcmUgRG9jdW1lbnRhdGlvbiAKRm9yIGRldGFpbGVkIGluZm9ybWF0aW9uIG9uIGhvdyBjZXJ0YWluIGZ1bmN0aW9ucyB3b3JrIGluIENsdWVQZWRpYSwgcGxlYXNlIHJlZmVyIHRvIHRoZSBsaW5rIGhlcmU6IGh0dHA6Ly93d3cuaWNpLnVwbWMuZnIvY2x1ZXBlZGlhL0NsdWVQZWRpYV9Eb2N1bWVudGF0aW9uLnBkZgoKCiMjIFdhbGt0aG9ydWdoIEV4YW1wbGU6IAoKKiBPcGVuIHRoZSBwcmV2aW91c2x5IHNhdmVkIHNlc3Npb24zLnN5cyAqKihQYXJ0IEEgLSBDbHVlR08gTmV0d29yaykqKiBmaWxlIGluIEN5dG9zY2FwZS4KCiMjIENyZWF0ZSBhIENsdWVHTytDbHVlUGVkaWEgbmV0d29yayBvZiB0ZXJtcy9wYXRod2F5cyBhbmQgZ2VuZXMuCiogRG93bmxvYWQgQ2x1ZVBlZGlhIGFuZCBDbHVlR08gcGx1Z2lucyBpbiB0aGUgQ3l0b3NjYXBlIHBsdWdpbiBmb2xkZXIuIE9wdGlvbmFsIERvd25sb2FkIENlcmVicmFsIHBsdWdpbi4KKiBTdGFydCBDeXRvc2NhcGUuIE9wZW4gQ2x1ZUdPK0NsdWVQZWRpYSAoUGx1Z2lucyBtZW51KS4KKiBLZWVwIHN0YW5kYXJkIHNldHRpbmdzOiBBbmFseXNpcyBNb2RlIChGdW5jdGlvbiksIENsdXN0ZXIgQW5hbHlzaXMgVHlwZSAoU2luZ2xlKSwgT3JnYW5pc20gKEhvbW8gU2FwaWVucyksIEF1dG9tYXRpYyByZWNvZ25pdGlvbiBvZiBpZHMuCiogQ29weSB0aGUgVGgxIHJlbGF0ZWQgZ2VuZXMgZnJvbSB0aGUgbGlzdCBwcm92aWRlZC4KR2VuZXM6IFBEQ0QxTEcxLCBJUkYxLCBHTkxZLCBQRENEMUxHMiwgUERDRDEsIFRCWDIxLCBJRk5HLCBUTkZSU0Y2QiwKSUNPUywgVE5GLCBDWENMOSwgQ1hDTDEwLCBJTDgsIFNUQVQxLCBNQURDQU0xLCBJQ0FNMSwgVkNBTTEsIENYM0NMMQoqIFNlbGVjdCBPbnRvbG9neTogUmVhY3RvbWUgKHZlcnNpb24gMTAuMDcuMjAxMikKKiBTZWxlY3QgU2hvdyBBZHZhbmNlZCBTZXR0aW5ncy4KKiBTZXQgR2VuZSBwZXJjZW50YWdlIHRvIDMlLgoqIEtlZXAgYWxsIHRoZSBvdGhlciBhZHZhbmNlZCBzZXR0aW5ncy4KKiBTdGFydCB0aGUgYW5hbHlzaXMKKipDbHVlR08gbmV0d29yayBvZiBmdW5jdGlvbnMqKgoqIFNlbGVjdCBDbHVlUGVkaWEgcGFuZWwKKiBTZWxlY3QgU2hvdyBvbmx5IHNlbGVjdGVkIGdlbmVzCioqQ2x1ZUdPK0NsdWVQZWRpYSBuZXR3b3JrIG9mIGZ1bmN0aW9ucyArIGFzc29jaWF0ZWQgZ2VuZXMuKioKCiFbXShpbWFnZXMvQ2x1ZUdPLVBlZGlhX05ldHdvcmsucG5nKQoKCiFbXShpbWFnZXMvQ2x1ZUdPX1BlZGlhX05ldHdvcmtfMi5wbmcpCgojIyBWaXN1YWxpemUga25vd24gaW50ZXJhY3Rpb25zIGJldHdlZW4gbWFwcGVkIGdlbmVzLgoKRXhwbG9yZSBhIHRlcm0vcGF0aHdheSBvZiBpbnRlcmVzdCBpbnRvIGEgbmVzdGVkIG5ldHdvcmsuCgpTZWUgYWxsIGdlbmVzIGFzc29jaWF0ZWQgdG8gdGhpcyB0ZXJtIGFuZCB0aGVpciBrbm93biBpbnRlcmFjdGlvbnMuCgoqIFNlbGVjdCBBQ1RJT05TIGludGVyYWN0aW9uIGZpbGUgKENsdWVQZWRpYSBTVFJJTkctQUNUSU9OUyB2OSA5NjA2IDA5LjAzLjIwMTIpLgoqIFNlbGVjdCBBY3Rpb24gdHlwZXM6IGFjdGl2YXRpb24sIGJpbmRpbmcsIGV4cHJlc3Npb24sIHB0bW9kZSAoYWxsIHNjb3JlcykKKiBVcGRhdGUgdGhlIG5ldHdvcmsKICAqIENsdWVHTytDbHVlUGVkaWEgbmV0d29yayBvZiB0ZXJtcyBhbmQgZ2VuZXMuIFRlcm1zIGFyZSBpbnRlcmNvbm5lY3RlZCBiYXNlZCBvbiBrYXBwYSBzY29yZSBhbmQgZ2VuZXMgYmFzZWQgb24ga25vd24gaW50ZXJhY3Rpb25zIGZyb20gU1RSSU5HLgoKKiBTZWxlY3QgdGhlIHRlcm06ICoqQ29ydGlzb2wgc3ludGhlc2lzIGFuZCBzZWNyZXRpb24uKiogCiogQ3JlYXRlIENsdWVHTyBOZXN0ZWQgTmV0d29yayAoUmlnaHQgbW91c2UgY2xpY2spCiAgKiBDbHVlUGVkaWEgbmVzdGVkIHBhdGh3YXkgbmV0d29yayB3aXRoIGFsbCBnZW5lcyBhc3NvY2lhdGVkIHRvIHRoaXMgcGF0aHdheSBpbnRlcmNvbm5lY3RlZCBiYXNlZCBvbiBrbm93biBpbnRlcmFjdGlvbnMgZnJvbSBTVFJJTkcgKGludGVyY29ubmVjdGlvbiBzY29yZSBhcHBsaWVzIHRvIGJvdGgsIGluaXRpYWwgYW5kIG5lc3RlZCBuZXR3b3JrKS4KCiFbXShpbWFnZXMvQ2x1ZVBlZGlhX1NUUklORy5wbmcpCgoqIEhlcmUgeW91IG9idGFpbiBkaWZmcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhbmQgdGhlaXIgaW50ZXJhY3Rpb25zIHdpdGhpbiBlbnJpY2hlZCBwYXRod2F5cy4gQnkgdXNpbmcgeW91ciBpbWFnaW5hZ2lvbiwgb25lIGNhbiBncm91cCBzcGVjaWZpYyBwYXRod2F5cyBhbmQgcmFua2VkIGdlbmVzIHRoYXQgY2FuIGJlIGFzc29jaWF0ZWQgdG8gYSBzcGVjaWZpYyB0eXBlIG9mIHBoZW5vdHlwZS4gCgoqIFNhdmUgeW91ciBDbHVlR08sIENsdWVQZWRpYSBhbmQgQ3l0b3NjYXBlIHNlc3Npb24gZm9yIGZ1dHVyZSB1c2UuIAoKCiMjIEZ1cnRoZXIgUmVhZGluZzogCiMjIyBDbHVlR08gYW5kIENsdWVQZWRpYSBhbmFseXNpcyBmb3IgbWlSTkEgZGF0YS4gClBsZWFzZSByZWZlcmUgdGhlIGZvbGxvd2luZyBkb2N1bWVudGF0aW9uIGZvciBtaVJOQSBhbmFseXNpcyB1c2luZyBDbHVlR08vQ2x1ZVBlZGlhLiAKCiogaHR0cDovL3d3dy5pY2kudXBtYy5mci9jbHVlcGVkaWEvQ2x1ZUdPX0NsdWVQZWRpYV9taXJuYV9hbmFseXNpcy5wZGYKKiBodHRwOi8vd3d3LmljaS51cG1jLmZyL2NsdWVwZWRpYS9DbHVlUGVkaWFfRG9jdW1lbnRhdGlvbi5wZGYKKiBodHRwOi8vd3d3LmljaS51cG1jLmZyL2NsdWVwZWRpYS9DbHVlUGVkaWFfRmlnMV9FeGFtcGxlLnBkZgoKCgoKCgoKCgoKIyMgQmlibGlvZ3JhcGh5CgpbMV0gTSBBc2hidXJuZXIsIEMgQSBCYWxsLCBKIEEgQmxha2UsIEQgQm90c3RlaW4sIEggQnV0bGVyLCBKIE0gQ2hlcnJ5LCBBIFAgRGF2aXMsIEsgRG9saW5za2ksIFMgUyBEd2lnaHQsIEogVCBFcHBpZywgTSBBIEhhcnJpcywgRCBQIEhpbGwsIEwgSXNzZWwtVGFydmVyLCBBIEthc2Fyc2tpcywgUyBMZXdpcywgSiBDIE1hdGVzZSwgSiBFIFJpY2hhcmRzb24sIE0gUmluZ3dhbGQsIEcgTSBSdWJpbiwgRyBTaGVybG9jay4gR2VuZSBvbnRvbG9neTogdG9vbCBmb3IgdGhlIHVuaWZpY2F0aW9uIG9mIGJpb2xvZ3kgVGhlIEdlbmUgT250b2xvZ3kgQ29uc29ydGl1bS4gTmF0IEdlbmV0LCAyNToyNeKAkzI5LCAyMDAwLgoKWzJdIE0gS2FuZWhpc2EsIFMgR290bywgUyBLYXdhc2hpbWEsIEEgTmFrYXlhLiBUaGUgS0VHRyBkYXRhYmFzZXMgYXQgR2Vub21lTmV0LiBOdWNsZWljIEFjaWRzIFJlcywgMzA6NDLigJM0NiwgMjAwMi4KClszXSBHIEJpbmRlYSwgQiBNbGVjbmlrLCBIIEhhY2tsLCBQIENoYXJvZW50b25nLCBNIFRvc29saW5pLCBBIEtpcmlsb3Zza3ksIFdIIEZyaWRtYW4sIEYgUGFnZXMsClogVHJhamFub3NraSwgSiBHYWxvbi4gQ2x1ZUdPOiBhIEN5dG9zY2FwZSBwbHVnLWluIHRvIGRlY2lwaGVyIGZ1bmN0aW9uYWxseSBncm91cGVkIGdlbmUgb250b2xvZ3kgYW5kIHBhdGh3YXkgYW5ub3RhdGlvbiBuZXR3b3Jrcy4gQmlvaW5mb3JtYXRpY3MsIDI1KDgpOjEwOTHigJMzLCAyMDA5LgoKWzRdIEdKIFN6ZWtlbHksIE0gUml6em8uIEJyb3duaWFuIGRpc3RhbmNlIGNvdmFyaWFuY2UuIEFubmFscyBvZiBBcHBsaWVkIFN0YXRpc3RpY3MsIHBhZ2UgMTIzM2ExMzAzLCDLhgoyMDA5LgoKWzVdIEROIFJlc2hlZiwgWUEgUmVzaGVmLCBISyBGaW51Y2FuZSwgU1IgR3Jvc3NtYW4sIEcgTWNWZWFuLCBQSiBUdXJuYmF1Z2gsIEVTIExhbmRlciwgTSBNaXR6ZW5tYWNoZXIsIFBDIFNhYmV0aS4gRGV0ZWN0aW5nIG5vdmVsIGFzc29jaWF0aW9ucyBpbiBsYXJnZSBkYXRhIHNldHMuIFNjaWVuY2UsIDMzNCg2MDYyKToxNTE44oCTMjQsIDIwMTEuCgpbNl0gdm9uIE1lcmluZyBDLiwgSmVuc2VuIEwuSi4sIFNuZWwgQi4sIEhvb3BlciBTLkQuLCBLcnVwcCBNLiwgRm9nbGllcmluaSBNLiwgSm91ZmZyZSBOLiwgSHV5bmVuCk0uQS4sIEJvcmsgUC4gU1RSSU5HOiBrbm93biBhbmQgcHJlZGljdGVkIHByb3RlaW4tcHJvdGVpbiBhc3NvY2lhdGlvbnMsIGludGVncmF0ZWQgYW5kIHRyYW5zZmVycmVkIGFjcm9zcyBvcmdhbmlzbXMuIE51Y2xlaWMgQWNpZHMgUmVzLCAzMzpENDMz4oCTRDQzNywgMjAwNS4KCls3XSBEIFN6a2xhcmN6eWssIEEgRnJhbmNlc2NoaW5pLCBNIEt1aG4sIE0gU2ltb25vdmljLCBBIFJvdGgsIFAgTWluZ3VleiwgVCBEb2Vya3MsIE0gU3RhcmssCkogTXVsbGVyLCBQIEJvcmssIExKIEplbnNlbiwgQyB2b24gTWVyaW5nLiBUaGUgU1RSSU5HIGRhdGFiYXNlIGluIDIwMTE6IGZ1bmN0aW9uYWwgaW50ZXJhY3Rpb24KbmV0d29ya3Mgb2YgcHJvdGVpbnMsIGdsb2JhbGx5IGludGVncmF0ZWQgYW5kIHNjb3JlZC4gTnVjbGVpYyBBY2lkcyBSZXMsIDM5KERhdGFiYXNlIGlzc3VlKTpENTYx4oCTCjgsIDIwMTEuCgpbOF0gQSBLb3pvbWFyYSwgUyBHcmlmZml0aHMtSm9uZXMuIG1pUkJhc2U6IGludGVncmF0aW5nIG1pY3JvUk5BIGFubm90YXRpb24gYW5kIGRlZXAtc2VxdWVuY2luZwpkYXRhLiBOdWNsZWljIEFjaWRzIFJlcywgMzkoRGF0YWJhc2UgSXNzdWUpOkQxNTLigJNEMTU3LCAyMDExLgoKWzldIEYgWGlhbywgWiBadW8sIEcgQ2FpLCBTIEthbmcsIFggR2FvLCBUIExpLiBtaVJlY29yZHM6IGFuIGludGVncmF0ZWQgcmVzb3VyY2UgZm9yIG1pY3JvUk5BdGFyZ2V0IGludGVyYWN0aW9ucy4gTnVjbGVpYyBBY2lkcyBSZXMsIDM3OkQxMDXigJNEMTEwLCAyMDA5LgoKWzEwXSBBIEJhcnNreSwgSkwgR2FyZHksIFJFIEhhbmNvY2ssIFQgTXVuem5lci4gQ2VyZWJyYWw6IGEgQ3l0b3NjYXBlIHBsdWdpbiBmb3IgbGF5b3V0IG9mIGFuZAppbnRlcmFjdGlvbiB3aXRoIGJpb2xvZwoKCgo8YnI+CjwvYnI+PGJyPgo8L2JyPgoKIyMjIFlvdSBjYW4gb2J0YWluIGFsbCB0aGUgYW5zd2VycyB0byB0aGUgZXhlcmNpc2UgcXVlc3Rpb25zIGZyb20gdGhpcyBsaW5rIFtBbnN3ZXJzXShBbnN3ZXJzLm5iLmh0bWwpLg==