diff --git a/HGNC_pathways/secondaryHgncSymbolsInDatabases.Rmd b/HGNC_pathways/secondaryHgncSymbolsInDatabases.Rmd index bd130ed..a063f6e 100644 --- a/HGNC_pathways/secondaryHgncSymbolsInDatabases.Rmd +++ b/HGNC_pathways/secondaryHgncSymbolsInDatabases.Rmd @@ -49,7 +49,7 @@ secondaryHGNCSymbols <- setdiff(HGNCMappings$secondarySymbol, HGNCMappings$prima ## 2. Data Download We download the data for each database, based on their API, RDF, or other data download option (depending on availability). -### 1. KEGG +### 2.1. KEGG The information in KEGG was obtained using an API call. ```{r, include=FALSE} ##Install and load required packages: @@ -62,8 +62,7 @@ library(httr) library(jsonlite) library(data.table) -## pathway map IDs listed under "1.3 Lipid metabolism" -#lipid_kegg_maps <- c("00061", "00062", "00071", "00073", "00100", "00120", "00121", "00140", "00561", "00564", "00565", "00600", "00590", "00591", "00592", "01040") +## Get all pathway map IDs first: kegg_maps_APIcall <- "https://rest.kegg.jp/list/pathway/hsa" res_maps = GET(kegg_maps_APIcall) Kegg_data_maps <- rawToChar(res_maps$content) @@ -74,6 +73,7 @@ if(length(res_maps$content)>1){ Kegg_maps_total <- rbind(Kegg_maps_total,df_maps) } +##Convert KEGG maps results to new API call to retrieve all genes within each map: kegg_maps <- Kegg_maps_total$V1 ##Add URL for query item: kegg_genes_APIcall <- paste("https://rest.kegg.jp/link/hsa/", kegg_maps, sep="") @@ -100,7 +100,7 @@ rm(list=setdiff(ls(), retain)) ``` Unfortunately, the KEGG database does not allow to retrieve the labels within the pathway images, so we cannot use it further in our comparison. -### 2. Reactome +### 2.2. Reactome For the Reactome content, we download the Physical Entity (PE) Identifier mapping files. Since the HGNC symbols are not available as a direct mapping, we retrieve all mappings from UniProt, Ensembl, and NCBI, to integrate their content on HGNC symbols. ```{r, include=FALSE} ##Only download the data, if not available already locally. @@ -150,13 +150,25 @@ retain <- append(retain, "mergedReactome") rm(list=setdiff(ls(), retain)) ``` -Compare the Reactome data against primary symbols first, then against secondary symbols, last count how many were not matching at all. +Compare the Reactome data against primary symbols first, then against secondary symbols, last count how many were not matching at all. ```{r} - +##Check overlap between prim and sec: +uniqueSec <- setdiff(secondaryHGNCSymbols, primaryHGNCSymbols) + +##Convert reactome data to vector format: +mergedReactomeVector <- mergedReactome[['HGNC']] +##Check primary symbols: +primaryMatchesReactome <- intersect(primaryHGNCSymbols, mergedReactomeVector) +##Amount: +amountPrimaryMatchesReactome <- length(primaryMatchesReactome) +##Check secondary symbols: +secondaryMatchesReactome <- intersect(uniqueSec, mergedReactomeVector) +##Amount: +amountSecondaryMatchesReactome <- length(secondaryMatchesReactome) ``` -### 3. WikiPathways +### 2.3. WikiPathways The WikiPathways data was queried in the RDF format. ```{r, include=FALSE} ##WikiPathways (original pathways) @@ -230,11 +242,51 @@ showresultsWikiPathways <- resultsWikiPathways$results remove(queryWikiPathways, resultsWikiPathways) ``` +Compare the WikiPathways data against primary symbols first, then against secondary symbols, last count how many were not matching at all. +```{r} +##Check overlap between prim and sec: +uniqueSec <- setdiff(secondaryHGNCSymbols, primaryHGNCSymbols) + +##Convert reactome data to vector format: +mergedWikiPathwaysVector <- showresultsWikiPathways[['HGNC']] +##Check primary symbols: +primaryMatchesWikiPathways <- intersect(primaryHGNCSymbols, mergedWikiPathwaysVector) +##Amount: +amountPrimaryMatchesWikiPathways <- length(primaryMatchesWikiPathways) +##Check secondary symbols: +secondaryMatchesWikiPathways <- intersect(uniqueSec, mergedWikiPathwaysVector) +##Amount: +amountSecondaryMatchesWikiPathways <- length(secondaryMatchesWikiPathways) +``` + + + +### 2.4. BiGG data Models +```{r, include=FALSE} +##Install and load required packages: +api_packages <- c("httr", "jsonlite", "data.table") +for (i in 1:length(api_packages)) { +if(!api_packages[i] %in% installed.packages()){install.packages(api_packages[i])} +} +#install.packages(c("httr", "jsonlite", "data.table")) +library(httr) +library(jsonlite) +library(data.table) +biggModelsAPIcall <- 'http://bigg.ucsd.edu/api/v2/models' +biggModels_maps = GET(biggModelsAPIcall) +biggModels_data_maps <- rawToChar(biggModels_maps$content) +biggModels_maps_total = data.frame() +if(length(biggModels_maps$content)>1){ + cleaned_biggModels_data_maps <- fread(text = biggModels_data_maps, header=FALSE, fill = TRUE, sep = '\t') + df_maps <- data.frame(cleaned_biggModels_data_maps) + biggModels_maps_total <- rbind(biggModels_maps_total,df_maps) + } +``` -### 5. Gene Ontology +### 2.5. Gene Ontology From the Quick-GO website (https://www.ebi.ac.uk/QuickGO/), we downloaded data based on the following criteria: --> Use API instead! I. Taxon: 9606 (Homo sapiens, human). @@ -253,14 +305,12 @@ work_DIR <- getwd() ## 3. Data Comparison We compare the data for each database to the secondary HGNC symbols. - ```{r} plot(cars) ``` ## 4. Data Visualization We visualize the data for all databases combined. - ```{r} plot(cars) ``` diff --git a/HGNC_pathways/secondaryHgncSymbolsInDatabases.nb.html b/HGNC_pathways/secondaryHgncSymbolsInDatabases.nb.html index ce52944..d7cf88e 100644 --- a/HGNC_pathways/secondaryHgncSymbolsInDatabases.nb.html +++ b/HGNC_pathways/secondaryHgncSymbolsInDatabases.nb.html @@ -1779,14 +1779,10 @@

0. Notebook setup

library(rstudioapi) library(dplyr) - +

 Attaching package: ‘dplyr’
 
-The following objects are masked from ‘package:data.table’:
-
-    between, first, last
-
 The following objects are masked from ‘package:stats’:
 
     filter, lag
@@ -1818,7 +1814,7 @@ 

2. Data Download

We download the data for each database, based on their API, RDF, or other data download option (depending on availability).

-

1. KEGG

+

2.1. KEGG

The information in KEGG was obtained using an API call.

@@ -1827,7 +1823,7 @@

1. KEGG

comparison.

-

2. Reactome

+

2.2. Reactome

For the Reactome content, we download the Physical Entity (PE) Identifier mapping files. Since the HGNC symbols are not available as a direct mapping, we retrieve all mappings from UniProt, Ensembl, and @@ -1838,17 +1834,59 @@

2. Reactome

secondary symbols, last count how many were not matching at all.

+ +
##Check overlap between prim and sec:
+uniqueSec <-  setdiff(secondaryHGNCSymbols, primaryHGNCSymbols)
+
+##Convert reactome data to vector format:
+mergedReactomeVector <- mergedReactome[['HGNC']]
+##Check primary symbols:
+primaryMatchesReactome <- intersect(primaryHGNCSymbols, mergedReactomeVector)
+##Amount:
+amountPrimaryMatchesReactome <- length(primaryMatchesReactome)
+##Check secondary symbols:
+secondaryMatchesReactome <- intersect(uniqueSec, mergedReactomeVector)
+##Amount:
+amountSecondaryMatchesReactome <- length(secondaryMatchesReactome)
+
-

3. WikiPathways

+

2.3. WikiPathways

The WikiPathways data was queried in the RDF format.

+

Compare the WikiPathways data against primary symbols first, then +against secondary symbols, last count how many were not matching at +all.

+ + + +
##Check overlap between prim and sec:
+uniqueSec <-  setdiff(secondaryHGNCSymbols, primaryHGNCSymbols)
+
+##Convert reactome data to vector format:
+mergedWikiPathwaysVector <- showresultsWikiPathways[['HGNC']]
+##Check primary symbols:
+primaryMatchesWikiPathways <- intersect(primaryHGNCSymbols, mergedWikiPathwaysVector)
+##Amount:
+amountPrimaryMatchesWikiPathways <- length(primaryMatchesWikiPathways)
+##Check secondary symbols:
+secondaryMatchesWikiPathways <- intersect(uniqueSec, mergedWikiPathwaysVector)
+##Amount:
+amountSecondaryMatchesWikiPathways <- length(secondaryMatchesWikiPathways)
+ + + +
+
+

2.4. BiGG data Models

+ +
-

5. Gene Ontology

+

2.5. Gene Ontology

From the Quick-GO website (https://www.ebi.ac.uk/QuickGO/), we downloaded data based on the following criteria: –> Use API instead! I. Taxon: 9606 (Homo sapiens, human).

@@ -1881,7 +1919,7 @@

4. Data Visualization

-
LS0tCnRpdGxlOiAiU2Vjb25kYXJ5IEhHTkMgU3ltYm9scyB1c2VkIGluIGRpZmZlcmVudCBEYXRhYmFzZXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIAoKVGhpcyBzY3JpcHQgY29tcGFyZXMgZ2VuZSBzeW1ib2wgbmFtZXMgZnJvbSBmb3VyIGRpZmZlcmVudCBkYXRhYmFzZXMgKEtFR0csIFJlYWN0b21lLCBXaWtpUGF0aHdheXMsIEdlbmUgT250b2xvZ3kpIHRvIHRoZSBsaXN0IG9mIG91dGRhdGVkIEhHTkMgc3ltYm9scy4KCiMjIDAuIE5vdGVib29rIHNldHVwClRoZSBmaXJzdCBzZWN0aW9uIG9mIHRoaXMgTm90ZWJvb2sgbGlzdHMgYWxsIHRoZSBsaWJyYXJpZXMgcmVxdWlyZWQgdG8gcnVuIHRoaXMgc2NyaXB0LgoKYGBge3J9CiNQYWNrYWdlIG1hbmFnZXI6CmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiLHJlcG9zID0gImh0dHA6Ly9jcmFuLnVzLnItcHJvamVjdC5vcmciKQojUGFja2FnZSBmb3IgcGF0aCB2YXJpYWJsZQppZighInJzdHVkaW9hcGkiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJyc3R1ZGlvYXBpIikKI0xpYnJhcmllcyByZXF1aXJlZCBmb3IgbWFya2Rvd24gZG9jdW1lbnRzOgppZighIm1hcmtkb3duIiAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpKXtpbnN0YWxsLnBhY2thZ2VzKCJtYXJrZG93biIpfQppZighInJtYXJrZG93biIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSl7aW5zdGFsbC5wYWNrYWdlcygicm1hcmtkb3duIil9CmlmKCEiZHBseXIiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpe2luc3RhbGwucGFja2FnZXMoImRwbHlyIil9CgojbG9hZCBsaWJyYXJpZXMKbGlicmFyeShyc3R1ZGlvYXBpKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBzZXQgd29ya2luZyBlbnZpcm9ubWVudCB0byBjdXJyZW50IGZvbGRlcgp3b3JraW5nRGlyZWN0b3J5IDwtIHNldHdkKGRpcm5hbWUocnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGgpKQpgYGAKCiMjIDEuIEhHTkMgU3ltYm9sIGRhdGEgZG93bmxvYWQKRmlyc3QsIHdlIGxvYWQgYWxsIHRoZSBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgc3ltYm9scyBvZiBIR05DIHRvIGJlIHVzZWQgaW4gdGhpcyBjb21wYXJpc29uIChiYXNlZCBvbiBkYXRhIHJlbGVhc2UgaW4gWmVub2RvKS4KV2UgZmlsdGVyIG91dCB0aGUgc3ltYm9scyB3aGljaCBhcmUgdXNlZCBhcyBib3RoIHByaW1hcnkgYW5kIHNlY29uZGFyeSBzeW1ib2xzICh3aGljaCBjb3VsZCBsZWFkIHRvIGZhbHNlIHBvc2l0aXZlIHJlc3VsdHMpLgoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CmlmKCFmaWxlLmV4aXN0cygiSEdOQ19zZWNJRDJwcmlJRC50c3YiKSl7CiAgI2Rvd25sb2FkLmZpbGUoJ2h0dHBzOi8vcmVhY3RvbWUub3JnL2Rvd25sb2FkL2N1cnJlbnQvVW5pUHJvdDJSZWFjdG9tZV9QRV9QYXRod2F5LnR4dCcsIGRlc3RmaWxlPXBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL2RhdGFJbnB1dC9VbmlQcm90MlJlYWN0b21lLnR4dCcpLCBtZXRob2QgPSAid2dldCIsIGV4dHJhID0gIi1yIC1wIC0tcmFuZG9tLXdhaXQiKSAjI1JlcGxhY2Ugd2l0aCBaZW5vZG8gZG93bmxvYWQgd2hlbiBhdmFpbGFibGUhCn0KCkhHTkNNYXBwaW5ncyA8LSBFbnNlbWJsUmVhY3RvbWUgPC0gcmVhZC5kZWxpbShwYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9kYXRhSW5wdXQvSEdOQ19zZWNJRDJwcmlJRC50c3YnKSwgaGVhZGVyID0gVFJVRSwgc2VwID0gIlx0IiwgZGVjID0gIi4iKSAjQ3JlYXRlIGRhdGFmcmFtZSBmcm9tIEhHTkMgU3ltYm9scyBkYXRhCiMjQ3JlYXRlIHVuaXF1ZSBzZXQgb2YgcHJpbWFyeSBJRHMgKHdpdGhvdXQgb3ZlcmxhcCB0byBzZWNvbmRhcmllcykKcHJpbWFyeUhHTkNTeW1ib2xzIDwtIHNldGRpZmYoSEdOQ01hcHBpbmdzJHByaW1hcnlTeW1ib2wsIEhHTkNNYXBwaW5ncyRzZWNvbmRhcnlTeW1ib2wpCgojI0NyZWF0ZSB1bmlxdWUgc2V0IG9mIHNlY29uZGFyeSBJRHMgKHdpdGhvdXQgb3ZlcmxhcCB0byBwcmltYXJpZXMpCnNlY29uZGFyeUhHTkNTeW1ib2xzIDwtIHNldGRpZmYoSEdOQ01hcHBpbmdzJHNlY29uZGFyeVN5bWJvbCwgSEdOQ01hcHBpbmdzJHByaW1hcnlTeW1ib2wpCmBgYAoKIyMgMi4gRGF0YSBEb3dubG9hZApXZSBkb3dubG9hZCB0aGUgZGF0YSBmb3IgZWFjaCBkYXRhYmFzZSwgYmFzZWQgb24gdGhlaXIgQVBJLCBSREYsIG9yIG90aGVyIGRhdGEgZG93bmxvYWQgb3B0aW9uIChkZXBlbmRpbmcgb24gYXZhaWxhYmlsaXR5KS4KCiMjIyAxLiBLRUdHClRoZSBpbmZvcm1hdGlvbiBpbiBLRUdHIHdhcyBvYnRhaW5lZCB1c2luZyBhbiBBUEkgY2FsbC4KYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMjSW5zdGFsbCBhbmQgbG9hZCByZXF1aXJlZCBwYWNrYWdlczoKYXBpX3BhY2thZ2VzIDwtIGMoImh0dHIiLCAianNvbmxpdGUiLCAiZGF0YS50YWJsZSIpCmZvciAoaSBpbiAxOmxlbmd0aChhcGlfcGFja2FnZXMpKSB7CmlmKCFhcGlfcGFja2FnZXNbaV0gJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSl7aW5zdGFsbC5wYWNrYWdlcyhhcGlfcGFja2FnZXNbaV0pfQp9CiNpbnN0YWxsLnBhY2thZ2VzKGMoImh0dHIiLCAianNvbmxpdGUiLCAiZGF0YS50YWJsZSIpKQpsaWJyYXJ5KGh0dHIpCmxpYnJhcnkoanNvbmxpdGUpCmxpYnJhcnkoZGF0YS50YWJsZSkKCiMjIHBhdGh3YXkgbWFwIElEcyBsaXN0ZWQgdW5kZXIgIjEuMyBMaXBpZCBtZXRhYm9saXNtIgojbGlwaWRfa2VnZ19tYXBzIDwtIGMoIjAwMDYxIiwgIjAwMDYyIiwgIjAwMDcxIiwgIjAwMDczIiwgIjAwMTAwIiwgIjAwMTIwIiwgIjAwMTIxIiwgIjAwMTQwIiwgIjAwNTYxIiwgIjAwNTY0IiwgIjAwNTY1IiwgIjAwNjAwIiwgIjAwNTkwIiwgIjAwNTkxIiwgIjAwNTkyIiwgIjAxMDQwIikgCmtlZ2dfbWFwc19BUEljYWxsIDwtICJodHRwczovL3Jlc3Qua2VnZy5qcC9saXN0L3BhdGh3YXkvaHNhIgpyZXNfbWFwcyA9IEdFVChrZWdnX21hcHNfQVBJY2FsbCkKS2VnZ19kYXRhX21hcHMgPC0gcmF3VG9DaGFyKHJlc19tYXBzJGNvbnRlbnQpCktlZ2dfbWFwc190b3RhbCA9IGRhdGEuZnJhbWUoKQppZihsZW5ndGgocmVzX21hcHMkY29udGVudCk+MSl7CiAgY2xlYW5lZF9LZWdnX2RhdGFfbWFwcyA8LSBmcmVhZCh0ZXh0ID0gS2VnZ19kYXRhX21hcHMsIGhlYWRlcj1GQUxTRSwgZmlsbCA9IFRSVUUsIHNlcCA9ICdcdCcpCiAgZGZfbWFwcyA8LSBkYXRhLmZyYW1lKGNsZWFuZWRfS2VnZ19kYXRhX21hcHMpCiAgS2VnZ19tYXBzX3RvdGFsIDwtIHJiaW5kKEtlZ2dfbWFwc190b3RhbCxkZl9tYXBzKQogIH0KCmtlZ2dfbWFwcyA8LSBLZWdnX21hcHNfdG90YWwkVjEKIyNBZGQgVVJMIGZvciBxdWVyeSBpdGVtOgprZWdnX2dlbmVzX0FQSWNhbGwgPC0gcGFzdGUoImh0dHBzOi8vcmVzdC5rZWdnLmpwL2xpbmsvaHNhLyIsIGtlZ2dfbWFwcywgc2VwPSIiKQoKIyNDcmVhdGUgYW4gZW1wdHkgZGF0YWZyYW1lIHRvIHN0b3JlIHRoZSByZXN1bHRzIG9mIHRoZSBsb29wOgpLZWdnX2dlbmVzX3RvdGFsID0gZGF0YS5mcmFtZSgpCgojIyBFeGVjdXRlIEFQSSBjYWxscywgZXhhbXBsZSB0byBvYnRhaW4gY2hlbWljYWwgY29tcG91bmRzIGZvciBhIFBXIG1hcDoKZm9yIChpIGluIDE6bGVuZ3RoKG5yb3coS2VnZ19tYXBzX3RvdGFsWzFdKSkpIHsKICAjI0dldCB0aGUgZ2VuZXM6CiAgcmVzX2dlbmVzID0gR0VUKGtlZ2dfZ2VuZXNfQVBJY2FsbFtpXSkKICBLZWdnX2RhdGFfZ2VuZXMgPC0gcmF3VG9DaGFyKHJlc19nZW5lcyRjb250ZW50KQogIGlmKGxlbmd0aChyZXNfZ2VuZXMkY29udGVudCk+MSl7CiAgY2xlYW5lZF9LZWdnX2RhdGFfZ2VuZXMgPC0gZnJlYWQodGV4dCA9IEtlZ2dfZGF0YV9nZW5lcywgaGVhZGVyPUZBTFNFLCBmaWxsID0gVFJVRSkKICBkZl9nZW5lcyA8LSBkYXRhLmZyYW1lKGNsZWFuZWRfS2VnZ19kYXRhX2dlbmVzKQogIEtlZ2dfZ2VuZXNfdG90YWwgPC0gcmJpbmQoS2VnZ19nZW5lc190b3RhbCxkZl9nZW5lcykKICB9Cn0KCiMjS2VlcCBvbmx5IGRhdGFmcmFtZXMgd2l0aCBuYW1lICJfdG90YWwiIHRvIHNhdmUgc3BhY2UKI3JtKGxpc3QgPSBscygpWyFncmVwbCgiX3RvdGFsIiwgbHMoKSldKQpyZXRhaW4gPSBjKCJwcmltYXJ5SEdOQ1N5bWJvbHMiLCAic2Vjb25kYXJ5SEdOQ1N5bWJvbHMiLCAid29ya2luZ0RpcmVjdG9yeSIsICJyZXRhaW4iKQpybShsaXN0PXNldGRpZmYobHMoKSwgcmV0YWluKSkKYGBgClVuZm9ydHVuYXRlbHksIHRoZSBLRUdHIGRhdGFiYXNlIGRvZXMgbm90IGFsbG93IHRvIHJldHJpZXZlIHRoZSBsYWJlbHMgd2l0aGluIHRoZSBwYXRod2F5IGltYWdlcywgc28gd2UgY2Fubm90IHVzZSBpdCBmdXJ0aGVyIGluIG91ciBjb21wYXJpc29uLgoKIyMjIDIuIFJlYWN0b21lCkZvciB0aGUgUmVhY3RvbWUgY29udGVudCwgd2UgZG93bmxvYWQgdGhlIFBoeXNpY2FsIEVudGl0eSAoUEUpIElkZW50aWZpZXIgbWFwcGluZyBmaWxlcy4gU2luY2UgdGhlIEhHTkMgc3ltYm9scyBhcmUgbm90IGF2YWlsYWJsZSBhcyBhIGRpcmVjdCBtYXBwaW5nLCB3ZSByZXRyaWV2ZSBhbGwgbWFwcGluZ3MgZnJvbSBVbmlQcm90LCBFbnNlbWJsLCBhbmQgTkNCSSwgdG8gaW50ZWdyYXRlIHRoZWlyIGNvbnRlbnQgb24gSEdOQyBzeW1ib2xzLgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KIyNPbmx5IGRvd25sb2FkIHRoZSBkYXRhLCBpZiBub3QgYXZhaWxhYmxlIGFscmVhZHkgbG9jYWxseS4KIyNVbmlQcm90IG1hcHBpbmdzCmlmKCFmaWxlLmV4aXN0cygiZGF0YUlucHV0L1VuaVByb3QyUmVhY3RvbWUudHh0IikpewogIGRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vcmVhY3RvbWUub3JnL2Rvd25sb2FkL2N1cnJlbnQvVW5pUHJvdDJSZWFjdG9tZV9QRV9QYXRod2F5LnR4dCcsIGRlc3RmaWxlPXBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL2RhdGFJbnB1dC9VbmlQcm90MlJlYWN0b21lLnR4dCcpLCBtZXRob2QgPSAid2dldCIsIGV4dHJhID0gIi1yIC1wIC0tcmFuZG9tLXdhaXQiKQp9CiMjRW5zZW1ibCBtYXBwaW5ncwppZighZmlsZS5leGlzdHMoImRhdGFJbnB1dC9FbnNlbWJsMlJlYWN0b21lLnR4dCIpKSB7CiAgZG93bmxvYWQuZmlsZSgnaHR0cHM6Ly9yZWFjdG9tZS5vcmcvZG93bmxvYWQvY3VycmVudC9FbnNlbWJsMlJlYWN0b21lX1BFX1BhdGh3YXkudHh0JywgZGVzdGZpbGU9cGFzdGUwKHdvcmtpbmdEaXJlY3RvcnksICcvZGF0YUlucHV0L0Vuc2VtYmwyUmVhY3RvbWUudHh0JyksIG1ldGhvZCA9ICJ3Z2V0IiwgZXh0cmEgPSAiLXIgLXAgLS1yYW5kb20td2FpdCIpCn0KIyNOQ0JJIG1hcHBpbmdzCmlmKCFmaWxlLmV4aXN0cygiZGF0YUlucHV0L05DQkkyUmVhY3RvbWUudHh0IikpIHsKICBkb3dubG9hZC5maWxlKCdodHRwczovL3JlYWN0b21lLm9yZy9kb3dubG9hZC9jdXJyZW50L05DQkkyUmVhY3RvbWVfUEVfUGF0aHdheS50eHQnLCBkZXN0ZmlsZT1wYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9kYXRhSW5wdXQvTkNCSTJSZWFjdG9tZS50eHQnKSwgbWV0aG9kID0gIndnZXQiLCBleHRyYSA9ICItciAtcCAtLXJhbmRvbS13YWl0IikKfQoKIyNTdG9yZSB0aGUgZGF0YSBpbiBhIGRhdGFmcmFtZSwgZXh0cmFjdCB0aGUgcmVsZXZhbnQgaW5mb3JtYXRpb24sIGFuZCBtZXJnZSByZXN1bHRzIGZyb20gdGhyZWUgbWFwcGluZyBzeXN0ZW1zIChpZiBuZWVkZWQpOgojVW5pcHJvdCBtYXBwaW5ncwpVbmlwcm90UmVhY3RvbWUgPC0gcmVhZC5kZWxpbShwYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9kYXRhSW5wdXQvVW5pUHJvdDJSZWFjdG9tZS50eHQnKSwgaGVhZGVyID0gRkFMU0UsIHNlcCA9ICJcdCIsIGRlYyA9ICIuIikgI0NyZWF0ZSBkYXRhZnJhbWUgZnJvbSBpbnB1dCBkYXRhClVuaXByb3RSZWFjdG9tZSA8LSBVbmlwcm90UmVhY3RvbWVbVW5pcHJvdFJlYWN0b21lWzhdID09ICdIb21vIHNhcGllbnMnLF0gI09ubHkga2VlcCBkYXRhIGZvciBvbmUgc3BlY2llcyAoSG9tbyBzYXBpZW5zKQpVbmlwcm90UmVhY3RvbWUgPC0gVW5pcHJvdFJlYWN0b21lW2MoMyldICNSZXRhaW4gY29sdW1uIHdpdGggSEdOQyBTeW1ib2xzClVuaXByb3RSZWFjdG9tZSA8LSBzZXBhcmF0ZShVbmlwcm90UmVhY3RvbWUsIFYzLCBpbnRvID0gYygiSEdOQyIsICJMb2NhdGlvbiIpLCBzZXAgPSAiICg/PShcXFtbXlxcXV0qXFxdKSskKSIpICMjU3BsaXQgbG9jYWxpemF0aW9uIGRhdGEgZnJvbSBIR05DIHN5bWJvbApVbmlwcm90UmVhY3RvbWUgPC0gVW5pcHJvdFJlYWN0b21lW2MoMSldICNyZW1vdmUgbG9jYWxpemF0aW9uIGRhdGEKVW5pcHJvdFJlYWN0b21lIDwtIHVuaXF1ZShVbmlwcm90UmVhY3RvbWUpICNLZWVwIHVuaXF1ZSBzeW1ib2xzIG9ubHkgCiNFbnNlbWJsIG1hcHBpbmdzCkVuc2VtYmxSZWFjdG9tZSA8LSByZWFkLmRlbGltKHBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL2RhdGFJbnB1dC9FbnNlbWJsMlJlYWN0b21lLnR4dCcpLCBoZWFkZXIgPSBGQUxTRSwgc2VwID0gIlx0IiwgZGVjID0gIi4iKSAjQ3JlYXRlIGRhdGFmcmFtZSBmcm9tIGlucHV0IGRhdGEKRW5zZW1ibFJlYWN0b21lIDwtIEVuc2VtYmxSZWFjdG9tZVtFbnNlbWJsUmVhY3RvbWVbOF0gPT0gJ0hvbW8gc2FwaWVucycsXSAjT25seSBrZWVwIGRhdGEgZm9yIG9uZSBzcGVjaWVzIChIb21vIHNhcGllbnMpCkVuc2VtYmxSZWFjdG9tZSA8LSBFbnNlbWJsUmVhY3RvbWVbYygzKV0gI1JldGFpbiBjb2x1bW4gd2l0aCBIR05DIFN5bWJvbHMKRW5zZW1ibFJlYWN0b21lIDwtIHNlcGFyYXRlKEVuc2VtYmxSZWFjdG9tZSwgVjMsIGludG8gPSBjKCJIR05DIiwgIkxvY2F0aW9uIiksIHNlcCA9ICIgKD89KFxcW1teXFxdXSpcXF0pKyQpIikgIyNTcGxpdCBsb2NhbGl6YXRpb24gZGF0YSBmcm9tIEhHTkMgc3ltYm9sCkVuc2VtYmxSZWFjdG9tZSA8LSBFbnNlbWJsUmVhY3RvbWVbYygxKV0gI3JlbW92ZSBsb2NhbGl6YXRpb24gZGF0YQpFbnNlbWJsUmVhY3RvbWUgPC0gdW5pcXVlKEVuc2VtYmxSZWFjdG9tZSkgI0tlZXAgdW5pcXVlIHN5bWJvbHMgb25seSAKI05DQkkgbWFwcGluZ3MKTkNCSVJlYWN0b21lIDwtIHJlYWQuZGVsaW0ocGFzdGUwKHdvcmtpbmdEaXJlY3RvcnksICcvZGF0YUlucHV0L05DQkkyUmVhY3RvbWUudHh0JyksIGhlYWRlciA9IEZBTFNFLCBzZXAgPSAiXHQiLCBkZWMgPSAiLiIpICNDcmVhdGUgZGF0YWZyYW1lIGZyb20gaW5wdXQgZGF0YQpOQ0JJUmVhY3RvbWUgPC0gTkNCSVJlYWN0b21lW05DQklSZWFjdG9tZVs4XSA9PSAnSG9tbyBzYXBpZW5zJyxdICNPbmx5IGtlZXAgZGF0YSBmb3Igb25lIHNwZWNpZXMgKEhvbW8gc2FwaWVucykKTkNCSVJlYWN0b21lIDwtIE5DQklSZWFjdG9tZVtjKDMpXSAjUmV0YWluIGNvbHVtbiB3aXRoIEhHTkMgU3ltYm9scwpOQ0JJUmVhY3RvbWUgPC0gc2VwYXJhdGUoTkNCSVJlYWN0b21lLCBWMywgaW50byA9IGMoIkhHTkMiLCAiTG9jYXRpb24iKSwgc2VwID0gIiAoPz0oXFxbW15cXF1dKlxcXSkrJCkiKSAjI1NwbGl0IGxvY2FsaXphdGlvbiBkYXRhIGZyb20gSEdOQyBzeW1ib2wKTkNCSVJlYWN0b21lIDwtIE5DQklSZWFjdG9tZVtjKDEpXSAjcmVtb3ZlIGxvY2FsaXphdGlvbiBkYXRhCk5DQklSZWFjdG9tZSA8LSB1bmlxdWUoTkNCSVJlYWN0b21lKSAjS2VlcCB1bmlxdWUgc3ltYm9scyBvbmx5IAoKI01lcmdlIHRoZSBkYXRhIHRvZ2V0aGVyCmRmX2xpc3QgPC0gbGlzdChVbmlwcm90UmVhY3RvbWUsIEVuc2VtYmxSZWFjdG9tZSwgTkNCSVJlYWN0b21lKQptZXJnZWRSZWFjdG9tZSA8LSBSZWR1Y2UoZnVuY3Rpb24oeCwgeSkgbWVyZ2UoeCwgeSwgYWxsPVRSVUUpLCBkZl9saXN0LCBhY2N1bXVsYXRlPUZBTFNFKQojbWVyZ2VkUmVhY3RvbWUgPC0gdW5pcXVlKG1lcmdlZFJlYWN0b21lKSAjS2VlcCB1bmlxdWUgc3ltYm9scyBvbmx5ICh0byBjaGVjayBpZiBhYm92ZSBmdW5jdGlvbiB3b3JrZWQgY29ycmVjdGx5KQoKI1JlbW92ZSB1bm5lY2Vzc2FyeSBkYXRhCnJldGFpbiA8LSBhcHBlbmQocmV0YWluLCAibWVyZ2VkUmVhY3RvbWUiKQpybShsaXN0PXNldGRpZmYobHMoKSwgcmV0YWluKSkKYGBgCgpDb21wYXJlIHRoZSBSZWFjdG9tZSBkYXRhIGFnYWluc3QgcHJpbWFyeSBzeW1ib2xzIGZpcnN0LCAgdGhlbiBhZ2FpbnN0IHNlY29uZGFyeSBzeW1ib2xzLCBsYXN0IGNvdW50IGhvdyBtYW55IHdlcmUgbm90IG1hdGNoaW5nIGF0IGFsbC4KYGBge3J9CgpgYGAKCgojIyMgMy4gV2lraVBhdGh3YXlzClRoZSBXaWtpUGF0aHdheXMgZGF0YSB3YXMgcXVlcmllZCBpbiB0aGUgUkRGIGZvcm1hdC4KYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMjV2lraVBhdGh3YXlzIChvcmlnaW5hbCBwYXRod2F5cykKCiMjI1BSSU9SIGNvZGUgdG8gaW5zdGFsbCBTUEFSUWwgcGFja2FnZTsgUGFja2FnZSBub3QgYXZhaWxhYmxlIGluIENSQU4gYW55bW9yZSwgb25seSB3b3JrcyBmb3Igb2xkZXIgdmVyc2lvbiBvZiBSCiNpZighIlNQQVJRTCIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSl7CiMgIGluc3RhbGwucGFja2FnZXMoIlNQQVJRTCIpCiN9CgojI1NvbHV0aW9uOiBkb3dubG9hZCBmcm9tIGFyY2hpdmVkIHZlcnNpb24KI0xvY2F0aW9uIHRvIGluc3RhbGwgYXJjaGl2ZWQgcGFja2FnZXM6CnBhY2thZ2VGb2xkZXIgPC1wYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9wYWNrYWdlcy9TUEFSUUwudGFyLmd6JykKZG93bmxvYWRMaW5rU1BBUlFMIDwtImh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3NyYy9jb250cmliL0FyY2hpdmUvU1BBUlFML1NQQVJRTF8xLjE2LnRhci5neiIKCiMjRG93bmxvYWQgYXJjaGl2ZWQgdmVyc2lvbiBpbnN0ZWFkOgppZighImRvd25sb2FkZXIiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpewogIGluc3RhbGwucGFja2FnZXMoImRvd25sb2FkZXIiKQp9CmxpYnJhcnkoImRvd25sb2FkZXIiKQoKIyNPbmx5IGRvd25sb2FkIGZpbGUgaWYgbmVlZGVkCmlmICghZmlsZS5leGlzdHMocGFja2FnZUZvbGRlcikpIHsKICBkb3dubG9hZC5maWxlKGRvd25sb2FkTGlua1NQQVJRTCwgcGFja2FnZUZvbGRlcikKfQoKIyNJbnN0YWxsIHRoZSBsb2NhbCB2ZXJzaW9uIG9mIHRoZSBsaWJyYXJ5Cmluc3RhbGwucGFja2FnZXMocGFja2FnZUZvbGRlciwgcmVwb3MgPSBOVUxMLCB0eXBlPSJzb3VyY2UiKQoKbGlicmFyeShTUEFSUUwpCiMjQ29ubmVjdCB0byBFbmRwb2ludCBXaWtpUGF0aHdheXMKZW5kcG9pbnR3cCA8LSAiaHR0cHM6Ly9zcGFycWwud2lraXBhdGh3YXlzLm9yZy9zcGFycWwiCgojIyAxLiBRdWVyeSBtZXRhZGF0YToKcXVlcnlNZXRhZGF0YSA8LQoiU0VMRUNUIERJU1RJTkNUID9kYXRhc2V0IChzdHIoP3RpdGxlTGl0KSBhcyA/dGl0bGUpID9kYXRlID9saWNlbnNlIApXSEVSRSB7CiAgID9kYXRhc2V0IGEgdm9pZDpEYXRhc2V0IDsKICAgZGN0ZXJtczp0aXRsZSA/dGl0bGVMaXQgOwogICBkY3Rlcm1zOmxpY2Vuc2UgP2xpY2Vuc2UgOwogICBwYXY6Y3JlYXRlZE9uID9kYXRlIC4KIH0iCiAjYmVsb3cgY29kZSBzaG91bGQgYmUgcGVyZm9ybWVkIGZpcnN0IHRvIGhhbmRsZSB0aGUgc3NsIGNlcnRpZmljYXRlIGVycm9yCm9wdGlvbnMoUkN1cmxPcHRpb25zID0gbGlzdChjYWluZm8gPSBwYXN0ZTAoIHRlbXBkaXIoKSAsICIvY2FjZXJ0LnBlbSIgKSwgc3NsLnZlcmlmeXBlZXIgPSBGQUxTRSkpCnJlc3VsdHNNZXRhZGF0YSA8LSBTUEFSUUwoZW5kcG9pbnR3cCxxdWVyeU1ldGFkYXRhLGN1cmxfYXJncz1saXN0KHVzZXJhZ2VudD1SLnZlcnNpb24uc3RyaW5nKSkKc2hvd3Jlc3VsdHNNZXRhZGF0YSA8LSByZXN1bHRzTWV0YWRhdGEkcmVzdWx0cwpyZW1vdmUocXVlcnlNZXRhZGF0YSwgcmVzdWx0c01ldGFkYXRhKQoKIyMgMi4gUXVlcnkgV2lraVBhdGh3YXlzIFBXcywgSEdOQyBzeW1ib2xzIHVzZWQgaW4gTGFiZWxzOgoKIyMgMy4gUXVlcnkgV2lraVBhdGh3YXlzIFBXcywgSEdOQyBzeW1ib2wgdXNlZCBpbiBvcmlnaW5hbCBhbm5vdGF0aW9uczoKCiMjIDQuIFF1ZXJ5IFdpa2lQYXRod2F5cyBQV3MsIEhHTkMgc3ltYm9sIE1hcHBpbmdzOgpxdWVyeVdpa2lQYXRod2F5cyA8LQoiUFJFRklYIGN1cjogICAgICAgICAgICA8aHR0cDovL3ZvY2FidWxhcmllcy53aWtpcGF0aHdheXMub3JnL3dwI0N1cmF0aW9uOj4gI3RvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBSZWFjdG9tZSBhbmQgV1AgUFdzLgoKc2VsZWN0IGRpc3RpbmN0IChmbjpzdWJzdHJpbmcoP2hnbmNJZCwzNykgYXMgP0hHTkMpIChHUk9VUF9DT05DQVQoRElTVElOQ1Qgc3RyKD93cGlkKTtzZXBhcmF0b3I9JywgJykgQVMgP3BhdGh3YXlzKSAgKENPVU5UKERJU1RJTkNUIHN0cig/d3BpZCkpIEFTID91c2FnZSkKd2hlcmUgewogID9wYXRod2F5UmVzIGEgd3A6UGF0aHdheSA7ICAgICAgICAgICAgICAgICAgICNEZWZpbmUgd2hhdCBpcyBhIHBhdGh3YXkKICAgICAgICAgICAgICB3cDpvcmdhbmlzbU5hbWUgJ0hvbW8gc2FwaWVucycgOyAjRmlsdGVyIHBhdGh3YXlzIG9uIHNwZWNpZXMgSHVtYW4KICAgICAgICAgICAgICBkY3Rlcm1zOmlkZW50aWZpZXIgP3dwaWQgOyAgICAgICAjT2J0YWluIGlkZW50aWZpZXIgb2YgcGF0aHdheQogICAgICAgICAgICAgIHdwOm9udG9sb2d5VGFnIGN1cjpBbmFseXNpc0NvbGxlY3Rpb24gLiAgI1JlYWN0b21lOiBSZWFjdG9tZV9BcHByb3ZlZCAuIFdQOiBDdXJhdGlvbjpBbmFseXNpc0NvbGxlY3Rpb24KICAKICA/cHJvdGVpbiB3cDpiZGJIZ25jU3ltYm9sID9oZ25jSWQgOyAgICAgICAgICAjRmluZCBwcm90ZWlucyBiYXNlZCBvbiBIR05DIHN5bWJvbAogICAgICAgICAgIGRjdGVybXM6aXNQYXJ0T2YgP3BhdGh3YXlSZXMgLiAgICAgICNDb25uZWN0IHByb3RlaW4gdG8gUFcKfQpPUkRFUiBCWSBERVNDICg/dXNhZ2UpCiIKIyNFeGVjdXRlIHF1ZXJ5OgpyZXN1bHRzV2lraVBhdGh3YXlzIDwtIFNQQVJRTChlbmRwb2ludHdwLHF1ZXJ5V2lraVBhdGh3YXlzLGN1cmxfYXJncz1saXN0KHVzZXJhZ2VudD1SLnZlcnNpb24uc3RyaW5nKSkKc2hvd3Jlc3VsdHNXaWtpUGF0aHdheXMgPC0gcmVzdWx0c1dpa2lQYXRod2F5cyRyZXN1bHRzCnJlbW92ZShxdWVyeVdpa2lQYXRod2F5cywgcmVzdWx0c1dpa2lQYXRod2F5cykKYGBgCgoKCgojIyMgNS4gR2VuZSBPbnRvbG9neQoKRnJvbSB0aGUgUXVpY2stR08gd2Vic2l0ZSAoaHR0cHM6Ly93d3cuZWJpLmFjLnVrL1F1aWNrR08vKSwgd2UgZG93bmxvYWRlZCBkYXRhIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgY3JpdGVyaWE6IC0tPiBVc2UgQVBJIGluc3RlYWQhCkkuIFRheG9uOiA5NjA2IChIb21vIHNhcGllbnMsIGh1bWFuKS4KCkRhdGEgd2FzIGRvd25sb2FkZWQgb246IE5vdi4gNiAoMjAyMyksIHdpdGggMSw2ODUsODkyIGFubm90YXRpb25zLCBhcyBhIFRTViBmaWxlLgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KR09fZmlsZUxvY2F0aW9uIDwtIHBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL0RhdGFJbnB1dC8uLi4gLnRzdicpCiMjR08gdGVybXMKZ29fdGVybXMgPC0gcmVhZC5kZWxpbShmaWxlID0gIkRhdGFJbnB1dC9RdWlja0dPLWFubm90YXRpb25zLTE2NTkzNTY4MDc0MDMtMjAyMjA4MDEudHN2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gJ1x0JykKZ29fdGVybXNfdW5pcXVlIDwtIHVuaXF1ZShnb190ZXJtcyRTWU1CT0wpCgojIFNldCBXb3JraW5nIERpcmVjdG9yeSBiYWNrIHRvIGN1cnJlbnQgZm9sZGVyCnNldHdkKGRpcm5hbWUocnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGgpKQp3b3JrX0RJUiA8LSBnZXR3ZCgpCgpgYGAKCiMjIDMuIERhdGEgQ29tcGFyaXNvbgpXZSBjb21wYXJlIHRoZSBkYXRhIGZvciBlYWNoIGRhdGFiYXNlIHRvIHRoZSBzZWNvbmRhcnkgSEdOQyBzeW1ib2xzLgoKYGBge3J9CnBsb3QoY2FycykKYGBgCgojIyA0LiBEYXRhIFZpc3VhbGl6YXRpb24KV2UgdmlzdWFsaXplIHRoZSBkYXRhIGZvciBhbGwgZGF0YWJhc2VzIGNvbWJpbmVkLgoKYGBge3J9CnBsb3QoY2FycykKYGBgCg==
+
LS0tCnRpdGxlOiAiU2Vjb25kYXJ5IEhHTkMgU3ltYm9scyB1c2VkIGluIGRpZmZlcmVudCBEYXRhYmFzZXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIAoKVGhpcyBzY3JpcHQgY29tcGFyZXMgZ2VuZSBzeW1ib2wgbmFtZXMgZnJvbSBmb3VyIGRpZmZlcmVudCBkYXRhYmFzZXMgKEtFR0csIFJlYWN0b21lLCBXaWtpUGF0aHdheXMsIEdlbmUgT250b2xvZ3kpIHRvIHRoZSBsaXN0IG9mIG91dGRhdGVkIEhHTkMgc3ltYm9scy4KCiMjIDAuIE5vdGVib29rIHNldHVwClRoZSBmaXJzdCBzZWN0aW9uIG9mIHRoaXMgTm90ZWJvb2sgbGlzdHMgYWxsIHRoZSBsaWJyYXJpZXMgcmVxdWlyZWQgdG8gcnVuIHRoaXMgc2NyaXB0LgoKYGBge3J9CiNQYWNrYWdlIG1hbmFnZXI6CmlmKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiLHJlcG9zID0gImh0dHA6Ly9jcmFuLnVzLnItcHJvamVjdC5vcmciKQojUGFja2FnZSBmb3IgcGF0aCB2YXJpYWJsZQppZighInJzdHVkaW9hcGkiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJyc3R1ZGlvYXBpIikKI0xpYnJhcmllcyByZXF1aXJlZCBmb3IgbWFya2Rvd24gZG9jdW1lbnRzOgppZighIm1hcmtkb3duIiAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpKXtpbnN0YWxsLnBhY2thZ2VzKCJtYXJrZG93biIpfQppZighInJtYXJrZG93biIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSl7aW5zdGFsbC5wYWNrYWdlcygicm1hcmtkb3duIil9CmlmKCEiZHBseXIiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpe2luc3RhbGwucGFja2FnZXMoImRwbHlyIil9CgojbG9hZCBsaWJyYXJpZXMKbGlicmFyeShyc3R1ZGlvYXBpKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBzZXQgd29ya2luZyBlbnZpcm9ubWVudCB0byBjdXJyZW50IGZvbGRlcgp3b3JraW5nRGlyZWN0b3J5IDwtIHNldHdkKGRpcm5hbWUocnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGgpKQpgYGAKCiMjIDEuIEhHTkMgU3ltYm9sIGRhdGEgZG93bmxvYWQKRmlyc3QsIHdlIGxvYWQgYWxsIHRoZSBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgc3ltYm9scyBvZiBIR05DIHRvIGJlIHVzZWQgaW4gdGhpcyBjb21wYXJpc29uIChiYXNlZCBvbiBkYXRhIHJlbGVhc2UgaW4gWmVub2RvKS4KV2UgZmlsdGVyIG91dCB0aGUgc3ltYm9scyB3aGljaCBhcmUgdXNlZCBhcyBib3RoIHByaW1hcnkgYW5kIHNlY29uZGFyeSBzeW1ib2xzICh3aGljaCBjb3VsZCBsZWFkIHRvIGZhbHNlIHBvc2l0aXZlIHJlc3VsdHMpLgoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CmlmKCFmaWxlLmV4aXN0cygiSEdOQ19zZWNJRDJwcmlJRC50c3YiKSl7CiAgI2Rvd25sb2FkLmZpbGUoJ2h0dHBzOi8vcmVhY3RvbWUub3JnL2Rvd25sb2FkL2N1cnJlbnQvVW5pUHJvdDJSZWFjdG9tZV9QRV9QYXRod2F5LnR4dCcsIGRlc3RmaWxlPXBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL2RhdGFJbnB1dC9VbmlQcm90MlJlYWN0b21lLnR4dCcpLCBtZXRob2QgPSAid2dldCIsIGV4dHJhID0gIi1yIC1wIC0tcmFuZG9tLXdhaXQiKSAjI1JlcGxhY2Ugd2l0aCBaZW5vZG8gZG93bmxvYWQgd2hlbiBhdmFpbGFibGUhCn0KCkhHTkNNYXBwaW5ncyA8LSBFbnNlbWJsUmVhY3RvbWUgPC0gcmVhZC5kZWxpbShwYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9kYXRhSW5wdXQvSEdOQ19zZWNJRDJwcmlJRC50c3YnKSwgaGVhZGVyID0gVFJVRSwgc2VwID0gIlx0IiwgZGVjID0gIi4iKSAjQ3JlYXRlIGRhdGFmcmFtZSBmcm9tIEhHTkMgU3ltYm9scyBkYXRhCiMjQ3JlYXRlIHVuaXF1ZSBzZXQgb2YgcHJpbWFyeSBJRHMgKHdpdGhvdXQgb3ZlcmxhcCB0byBzZWNvbmRhcmllcykKcHJpbWFyeUhHTkNTeW1ib2xzIDwtIHNldGRpZmYoSEdOQ01hcHBpbmdzJHByaW1hcnlTeW1ib2wsIEhHTkNNYXBwaW5ncyRzZWNvbmRhcnlTeW1ib2wpCgojI0NyZWF0ZSB1bmlxdWUgc2V0IG9mIHNlY29uZGFyeSBJRHMgKHdpdGhvdXQgb3ZlcmxhcCB0byBwcmltYXJpZXMpCnNlY29uZGFyeUhHTkNTeW1ib2xzIDwtIHNldGRpZmYoSEdOQ01hcHBpbmdzJHNlY29uZGFyeVN5bWJvbCwgSEdOQ01hcHBpbmdzJHByaW1hcnlTeW1ib2wpCmBgYAoKIyMgMi4gRGF0YSBEb3dubG9hZApXZSBkb3dubG9hZCB0aGUgZGF0YSBmb3IgZWFjaCBkYXRhYmFzZSwgYmFzZWQgb24gdGhlaXIgQVBJLCBSREYsIG9yIG90aGVyIGRhdGEgZG93bmxvYWQgb3B0aW9uIChkZXBlbmRpbmcgb24gYXZhaWxhYmlsaXR5KS4KCiMjIyAyLjEuIEtFR0cKVGhlIGluZm9ybWF0aW9uIGluIEtFR0cgd2FzIG9idGFpbmVkIHVzaW5nIGFuIEFQSSBjYWxsLgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KIyNJbnN0YWxsIGFuZCBsb2FkIHJlcXVpcmVkIHBhY2thZ2VzOgphcGlfcGFja2FnZXMgPC0gYygiaHR0ciIsICJqc29ubGl0ZSIsICJkYXRhLnRhYmxlIikKZm9yIChpIGluIDE6bGVuZ3RoKGFwaV9wYWNrYWdlcykpIHsKaWYoIWFwaV9wYWNrYWdlc1tpXSAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpKXtpbnN0YWxsLnBhY2thZ2VzKGFwaV9wYWNrYWdlc1tpXSl9Cn0KI2luc3RhbGwucGFja2FnZXMoYygiaHR0ciIsICJqc29ubGl0ZSIsICJkYXRhLnRhYmxlIikpCmxpYnJhcnkoaHR0cikKbGlicmFyeShqc29ubGl0ZSkKbGlicmFyeShkYXRhLnRhYmxlKQoKIyMgR2V0IGFsbCBwYXRod2F5IG1hcCBJRHMgZmlyc3Q6CmtlZ2dfbWFwc19BUEljYWxsIDwtICJodHRwczovL3Jlc3Qua2VnZy5qcC9saXN0L3BhdGh3YXkvaHNhIgpyZXNfbWFwcyA9IEdFVChrZWdnX21hcHNfQVBJY2FsbCkKS2VnZ19kYXRhX21hcHMgPC0gcmF3VG9DaGFyKHJlc19tYXBzJGNvbnRlbnQpCktlZ2dfbWFwc190b3RhbCA9IGRhdGEuZnJhbWUoKQppZihsZW5ndGgocmVzX21hcHMkY29udGVudCk+MSl7CiAgY2xlYW5lZF9LZWdnX2RhdGFfbWFwcyA8LSBmcmVhZCh0ZXh0ID0gS2VnZ19kYXRhX21hcHMsIGhlYWRlcj1GQUxTRSwgZmlsbCA9IFRSVUUsIHNlcCA9ICdcdCcpCiAgZGZfbWFwcyA8LSBkYXRhLmZyYW1lKGNsZWFuZWRfS2VnZ19kYXRhX21hcHMpCiAgS2VnZ19tYXBzX3RvdGFsIDwtIHJiaW5kKEtlZ2dfbWFwc190b3RhbCxkZl9tYXBzKQogIH0KCiMjQ29udmVydCBLRUdHIG1hcHMgcmVzdWx0cyB0byBuZXcgQVBJIGNhbGwgdG8gcmV0cmlldmUgYWxsIGdlbmVzIHdpdGhpbiBlYWNoIG1hcDoKa2VnZ19tYXBzIDwtIEtlZ2dfbWFwc190b3RhbCRWMQojI0FkZCBVUkwgZm9yIHF1ZXJ5IGl0ZW06CmtlZ2dfZ2VuZXNfQVBJY2FsbCA8LSBwYXN0ZSgiaHR0cHM6Ly9yZXN0LmtlZ2cuanAvbGluay9oc2EvIiwga2VnZ19tYXBzLCBzZXA9IiIpCgojI0NyZWF0ZSBhbiBlbXB0eSBkYXRhZnJhbWUgdG8gc3RvcmUgdGhlIHJlc3VsdHMgb2YgdGhlIGxvb3A6CktlZ2dfZ2VuZXNfdG90YWwgPSBkYXRhLmZyYW1lKCkKCiMjIEV4ZWN1dGUgQVBJIGNhbGxzLCBleGFtcGxlIHRvIG9idGFpbiBjaGVtaWNhbCBjb21wb3VuZHMgZm9yIGEgUFcgbWFwOgpmb3IgKGkgaW4gMTpsZW5ndGgobnJvdyhLZWdnX21hcHNfdG90YWxbMV0pKSkgewogICMjR2V0IHRoZSBnZW5lczoKICByZXNfZ2VuZXMgPSBHRVQoa2VnZ19nZW5lc19BUEljYWxsW2ldKQogIEtlZ2dfZGF0YV9nZW5lcyA8LSByYXdUb0NoYXIocmVzX2dlbmVzJGNvbnRlbnQpCiAgaWYobGVuZ3RoKHJlc19nZW5lcyRjb250ZW50KT4xKXsKICBjbGVhbmVkX0tlZ2dfZGF0YV9nZW5lcyA8LSBmcmVhZCh0ZXh0ID0gS2VnZ19kYXRhX2dlbmVzLCBoZWFkZXI9RkFMU0UsIGZpbGwgPSBUUlVFKQogIGRmX2dlbmVzIDwtIGRhdGEuZnJhbWUoY2xlYW5lZF9LZWdnX2RhdGFfZ2VuZXMpCiAgS2VnZ19nZW5lc190b3RhbCA8LSByYmluZChLZWdnX2dlbmVzX3RvdGFsLGRmX2dlbmVzKQogIH0KfQoKIyNLZWVwIG9ubHkgZGF0YWZyYW1lcyB3aXRoIG5hbWUgIl90b3RhbCIgdG8gc2F2ZSBzcGFjZQojcm0obGlzdCA9IGxzKClbIWdyZXBsKCJfdG90YWwiLCBscygpKV0pCnJldGFpbiA9IGMoInByaW1hcnlIR05DU3ltYm9scyIsICJzZWNvbmRhcnlIR05DU3ltYm9scyIsICJ3b3JraW5nRGlyZWN0b3J5IiwgInJldGFpbiIpCnJtKGxpc3Q9c2V0ZGlmZihscygpLCByZXRhaW4pKQpgYGAKVW5mb3J0dW5hdGVseSwgdGhlIEtFR0cgZGF0YWJhc2UgZG9lcyBub3QgYWxsb3cgdG8gcmV0cmlldmUgdGhlIGxhYmVscyB3aXRoaW4gdGhlIHBhdGh3YXkgaW1hZ2VzLCBzbyB3ZSBjYW5ub3QgdXNlIGl0IGZ1cnRoZXIgaW4gb3VyIGNvbXBhcmlzb24uCgojIyMgMi4yLiBSZWFjdG9tZQpGb3IgdGhlIFJlYWN0b21lIGNvbnRlbnQsIHdlIGRvd25sb2FkIHRoZSBQaHlzaWNhbCBFbnRpdHkgKFBFKSBJZGVudGlmaWVyIG1hcHBpbmcgZmlsZXMuIFNpbmNlIHRoZSBIR05DIHN5bWJvbHMgYXJlIG5vdCBhdmFpbGFibGUgYXMgYSBkaXJlY3QgbWFwcGluZywgd2UgcmV0cmlldmUgYWxsIG1hcHBpbmdzIGZyb20gVW5pUHJvdCwgRW5zZW1ibCwgYW5kIE5DQkksIHRvIGludGVncmF0ZSB0aGVpciBjb250ZW50IG9uIEhHTkMgc3ltYm9scy4KYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMjT25seSBkb3dubG9hZCB0aGUgZGF0YSwgaWYgbm90IGF2YWlsYWJsZSBhbHJlYWR5IGxvY2FsbHkuCiMjVW5pUHJvdCBtYXBwaW5ncwppZighZmlsZS5leGlzdHMoImRhdGFJbnB1dC9VbmlQcm90MlJlYWN0b21lLnR4dCIpKXsKICBkb3dubG9hZC5maWxlKCdodHRwczovL3JlYWN0b21lLm9yZy9kb3dubG9hZC9jdXJyZW50L1VuaVByb3QyUmVhY3RvbWVfUEVfUGF0aHdheS50eHQnLCBkZXN0ZmlsZT1wYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9kYXRhSW5wdXQvVW5pUHJvdDJSZWFjdG9tZS50eHQnKSwgbWV0aG9kID0gIndnZXQiLCBleHRyYSA9ICItciAtcCAtLXJhbmRvbS13YWl0IikKfQojI0Vuc2VtYmwgbWFwcGluZ3MKaWYoIWZpbGUuZXhpc3RzKCJkYXRhSW5wdXQvRW5zZW1ibDJSZWFjdG9tZS50eHQiKSkgewogIGRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vcmVhY3RvbWUub3JnL2Rvd25sb2FkL2N1cnJlbnQvRW5zZW1ibDJSZWFjdG9tZV9QRV9QYXRod2F5LnR4dCcsIGRlc3RmaWxlPXBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL2RhdGFJbnB1dC9FbnNlbWJsMlJlYWN0b21lLnR4dCcpLCBtZXRob2QgPSAid2dldCIsIGV4dHJhID0gIi1yIC1wIC0tcmFuZG9tLXdhaXQiKQp9CiMjTkNCSSBtYXBwaW5ncwppZighZmlsZS5leGlzdHMoImRhdGFJbnB1dC9OQ0JJMlJlYWN0b21lLnR4dCIpKSB7CiAgZG93bmxvYWQuZmlsZSgnaHR0cHM6Ly9yZWFjdG9tZS5vcmcvZG93bmxvYWQvY3VycmVudC9OQ0JJMlJlYWN0b21lX1BFX1BhdGh3YXkudHh0JywgZGVzdGZpbGU9cGFzdGUwKHdvcmtpbmdEaXJlY3RvcnksICcvZGF0YUlucHV0L05DQkkyUmVhY3RvbWUudHh0JyksIG1ldGhvZCA9ICJ3Z2V0IiwgZXh0cmEgPSAiLXIgLXAgLS1yYW5kb20td2FpdCIpCn0KCiMjU3RvcmUgdGhlIGRhdGEgaW4gYSBkYXRhZnJhbWUsIGV4dHJhY3QgdGhlIHJlbGV2YW50IGluZm9ybWF0aW9uLCBhbmQgbWVyZ2UgcmVzdWx0cyBmcm9tIHRocmVlIG1hcHBpbmcgc3lzdGVtcyAoaWYgbmVlZGVkKToKI1VuaXByb3QgbWFwcGluZ3MKVW5pcHJvdFJlYWN0b21lIDwtIHJlYWQuZGVsaW0ocGFzdGUwKHdvcmtpbmdEaXJlY3RvcnksICcvZGF0YUlucHV0L1VuaVByb3QyUmVhY3RvbWUudHh0JyksIGhlYWRlciA9IEZBTFNFLCBzZXAgPSAiXHQiLCBkZWMgPSAiLiIpICNDcmVhdGUgZGF0YWZyYW1lIGZyb20gaW5wdXQgZGF0YQpVbmlwcm90UmVhY3RvbWUgPC0gVW5pcHJvdFJlYWN0b21lW1VuaXByb3RSZWFjdG9tZVs4XSA9PSAnSG9tbyBzYXBpZW5zJyxdICNPbmx5IGtlZXAgZGF0YSBmb3Igb25lIHNwZWNpZXMgKEhvbW8gc2FwaWVucykKVW5pcHJvdFJlYWN0b21lIDwtIFVuaXByb3RSZWFjdG9tZVtjKDMpXSAjUmV0YWluIGNvbHVtbiB3aXRoIEhHTkMgU3ltYm9scwpVbmlwcm90UmVhY3RvbWUgPC0gc2VwYXJhdGUoVW5pcHJvdFJlYWN0b21lLCBWMywgaW50byA9IGMoIkhHTkMiLCAiTG9jYXRpb24iKSwgc2VwID0gIiAoPz0oXFxbW15cXF1dKlxcXSkrJCkiKSAjI1NwbGl0IGxvY2FsaXphdGlvbiBkYXRhIGZyb20gSEdOQyBzeW1ib2wKVW5pcHJvdFJlYWN0b21lIDwtIFVuaXByb3RSZWFjdG9tZVtjKDEpXSAjcmVtb3ZlIGxvY2FsaXphdGlvbiBkYXRhClVuaXByb3RSZWFjdG9tZSA8LSB1bmlxdWUoVW5pcHJvdFJlYWN0b21lKSAjS2VlcCB1bmlxdWUgc3ltYm9scyBvbmx5IAojRW5zZW1ibCBtYXBwaW5ncwpFbnNlbWJsUmVhY3RvbWUgPC0gcmVhZC5kZWxpbShwYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9kYXRhSW5wdXQvRW5zZW1ibDJSZWFjdG9tZS50eHQnKSwgaGVhZGVyID0gRkFMU0UsIHNlcCA9ICJcdCIsIGRlYyA9ICIuIikgI0NyZWF0ZSBkYXRhZnJhbWUgZnJvbSBpbnB1dCBkYXRhCkVuc2VtYmxSZWFjdG9tZSA8LSBFbnNlbWJsUmVhY3RvbWVbRW5zZW1ibFJlYWN0b21lWzhdID09ICdIb21vIHNhcGllbnMnLF0gI09ubHkga2VlcCBkYXRhIGZvciBvbmUgc3BlY2llcyAoSG9tbyBzYXBpZW5zKQpFbnNlbWJsUmVhY3RvbWUgPC0gRW5zZW1ibFJlYWN0b21lW2MoMyldICNSZXRhaW4gY29sdW1uIHdpdGggSEdOQyBTeW1ib2xzCkVuc2VtYmxSZWFjdG9tZSA8LSBzZXBhcmF0ZShFbnNlbWJsUmVhY3RvbWUsIFYzLCBpbnRvID0gYygiSEdOQyIsICJMb2NhdGlvbiIpLCBzZXAgPSAiICg/PShcXFtbXlxcXV0qXFxdKSskKSIpICMjU3BsaXQgbG9jYWxpemF0aW9uIGRhdGEgZnJvbSBIR05DIHN5bWJvbApFbnNlbWJsUmVhY3RvbWUgPC0gRW5zZW1ibFJlYWN0b21lW2MoMSldICNyZW1vdmUgbG9jYWxpemF0aW9uIGRhdGEKRW5zZW1ibFJlYWN0b21lIDwtIHVuaXF1ZShFbnNlbWJsUmVhY3RvbWUpICNLZWVwIHVuaXF1ZSBzeW1ib2xzIG9ubHkgCiNOQ0JJIG1hcHBpbmdzCk5DQklSZWFjdG9tZSA8LSByZWFkLmRlbGltKHBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL2RhdGFJbnB1dC9OQ0JJMlJlYWN0b21lLnR4dCcpLCBoZWFkZXIgPSBGQUxTRSwgc2VwID0gIlx0IiwgZGVjID0gIi4iKSAjQ3JlYXRlIGRhdGFmcmFtZSBmcm9tIGlucHV0IGRhdGEKTkNCSVJlYWN0b21lIDwtIE5DQklSZWFjdG9tZVtOQ0JJUmVhY3RvbWVbOF0gPT0gJ0hvbW8gc2FwaWVucycsXSAjT25seSBrZWVwIGRhdGEgZm9yIG9uZSBzcGVjaWVzIChIb21vIHNhcGllbnMpCk5DQklSZWFjdG9tZSA8LSBOQ0JJUmVhY3RvbWVbYygzKV0gI1JldGFpbiBjb2x1bW4gd2l0aCBIR05DIFN5bWJvbHMKTkNCSVJlYWN0b21lIDwtIHNlcGFyYXRlKE5DQklSZWFjdG9tZSwgVjMsIGludG8gPSBjKCJIR05DIiwgIkxvY2F0aW9uIiksIHNlcCA9ICIgKD89KFxcW1teXFxdXSpcXF0pKyQpIikgIyNTcGxpdCBsb2NhbGl6YXRpb24gZGF0YSBmcm9tIEhHTkMgc3ltYm9sCk5DQklSZWFjdG9tZSA8LSBOQ0JJUmVhY3RvbWVbYygxKV0gI3JlbW92ZSBsb2NhbGl6YXRpb24gZGF0YQpOQ0JJUmVhY3RvbWUgPC0gdW5pcXVlKE5DQklSZWFjdG9tZSkgI0tlZXAgdW5pcXVlIHN5bWJvbHMgb25seSAKCiNNZXJnZSB0aGUgZGF0YSB0b2dldGhlcgpkZl9saXN0IDwtIGxpc3QoVW5pcHJvdFJlYWN0b21lLCBFbnNlbWJsUmVhY3RvbWUsIE5DQklSZWFjdG9tZSkKbWVyZ2VkUmVhY3RvbWUgPC0gUmVkdWNlKGZ1bmN0aW9uKHgsIHkpIG1lcmdlKHgsIHksIGFsbD1UUlVFKSwgZGZfbGlzdCwgYWNjdW11bGF0ZT1GQUxTRSkKI21lcmdlZFJlYWN0b21lIDwtIHVuaXF1ZShtZXJnZWRSZWFjdG9tZSkgI0tlZXAgdW5pcXVlIHN5bWJvbHMgb25seSAodG8gY2hlY2sgaWYgYWJvdmUgZnVuY3Rpb24gd29ya2VkIGNvcnJlY3RseSkKCiNSZW1vdmUgdW5uZWNlc3NhcnkgZGF0YQpyZXRhaW4gPC0gYXBwZW5kKHJldGFpbiwgIm1lcmdlZFJlYWN0b21lIikKcm0obGlzdD1zZXRkaWZmKGxzKCksIHJldGFpbikpCmBgYAoKQ29tcGFyZSB0aGUgUmVhY3RvbWUgZGF0YSBhZ2FpbnN0IHByaW1hcnkgc3ltYm9scyBmaXJzdCwgdGhlbiBhZ2FpbnN0IHNlY29uZGFyeSBzeW1ib2xzLCBsYXN0IGNvdW50IGhvdyBtYW55IHdlcmUgbm90IG1hdGNoaW5nIGF0IGFsbC4KYGBge3J9CiMjQ2hlY2sgb3ZlcmxhcCBiZXR3ZWVuIHByaW0gYW5kIHNlYzoKdW5pcXVlU2VjIDwtICBzZXRkaWZmKHNlY29uZGFyeUhHTkNTeW1ib2xzLCBwcmltYXJ5SEdOQ1N5bWJvbHMpCgojI0NvbnZlcnQgcmVhY3RvbWUgZGF0YSB0byB2ZWN0b3IgZm9ybWF0OgptZXJnZWRSZWFjdG9tZVZlY3RvciA8LSBtZXJnZWRSZWFjdG9tZVtbJ0hHTkMnXV0KIyNDaGVjayBwcmltYXJ5IHN5bWJvbHM6CnByaW1hcnlNYXRjaGVzUmVhY3RvbWUgPC0gaW50ZXJzZWN0KHByaW1hcnlIR05DU3ltYm9scywgbWVyZ2VkUmVhY3RvbWVWZWN0b3IpCiMjQW1vdW50OgphbW91bnRQcmltYXJ5TWF0Y2hlc1JlYWN0b21lIDwtIGxlbmd0aChwcmltYXJ5TWF0Y2hlc1JlYWN0b21lKQojI0NoZWNrIHNlY29uZGFyeSBzeW1ib2xzOgpzZWNvbmRhcnlNYXRjaGVzUmVhY3RvbWUgPC0gaW50ZXJzZWN0KHVuaXF1ZVNlYywgbWVyZ2VkUmVhY3RvbWVWZWN0b3IpCiMjQW1vdW50OgphbW91bnRTZWNvbmRhcnlNYXRjaGVzUmVhY3RvbWUgPC0gbGVuZ3RoKHNlY29uZGFyeU1hdGNoZXNSZWFjdG9tZSkKYGBgCgoKIyMjIDIuMy4gV2lraVBhdGh3YXlzClRoZSBXaWtpUGF0aHdheXMgZGF0YSB3YXMgcXVlcmllZCBpbiB0aGUgUkRGIGZvcm1hdC4KYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMjV2lraVBhdGh3YXlzIChvcmlnaW5hbCBwYXRod2F5cykKCiMjI1BSSU9SIGNvZGUgdG8gaW5zdGFsbCBTUEFSUWwgcGFja2FnZTsgUGFja2FnZSBub3QgYXZhaWxhYmxlIGluIENSQU4gYW55bW9yZSwgb25seSB3b3JrcyBmb3Igb2xkZXIgdmVyc2lvbiBvZiBSCiNpZighIlNQQVJRTCIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSl7CiMgIGluc3RhbGwucGFja2FnZXMoIlNQQVJRTCIpCiN9CgojI1NvbHV0aW9uOiBkb3dubG9hZCBmcm9tIGFyY2hpdmVkIHZlcnNpb24KI0xvY2F0aW9uIHRvIGluc3RhbGwgYXJjaGl2ZWQgcGFja2FnZXM6CnBhY2thZ2VGb2xkZXIgPC1wYXN0ZTAod29ya2luZ0RpcmVjdG9yeSwgJy9wYWNrYWdlcy9TUEFSUUwudGFyLmd6JykKZG93bmxvYWRMaW5rU1BBUlFMIDwtImh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3NyYy9jb250cmliL0FyY2hpdmUvU1BBUlFML1NQQVJRTF8xLjE2LnRhci5neiIKCiMjRG93bmxvYWQgYXJjaGl2ZWQgdmVyc2lvbiBpbnN0ZWFkOgppZighImRvd25sb2FkZXIiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpewogIGluc3RhbGwucGFja2FnZXMoImRvd25sb2FkZXIiKQp9CmxpYnJhcnkoImRvd25sb2FkZXIiKQoKIyNPbmx5IGRvd25sb2FkIGZpbGUgaWYgbmVlZGVkCmlmICghZmlsZS5leGlzdHMocGFja2FnZUZvbGRlcikpIHsKICBkb3dubG9hZC5maWxlKGRvd25sb2FkTGlua1NQQVJRTCwgcGFja2FnZUZvbGRlcikKfQoKIyNJbnN0YWxsIHRoZSBsb2NhbCB2ZXJzaW9uIG9mIHRoZSBsaWJyYXJ5Cmluc3RhbGwucGFja2FnZXMocGFja2FnZUZvbGRlciwgcmVwb3MgPSBOVUxMLCB0eXBlPSJzb3VyY2UiKQoKbGlicmFyeShTUEFSUUwpCiMjQ29ubmVjdCB0byBFbmRwb2ludCBXaWtpUGF0aHdheXMKZW5kcG9pbnR3cCA8LSAiaHR0cHM6Ly9zcGFycWwud2lraXBhdGh3YXlzLm9yZy9zcGFycWwiCgojIyAxLiBRdWVyeSBtZXRhZGF0YToKcXVlcnlNZXRhZGF0YSA8LQoiU0VMRUNUIERJU1RJTkNUID9kYXRhc2V0IChzdHIoP3RpdGxlTGl0KSBhcyA/dGl0bGUpID9kYXRlID9saWNlbnNlIApXSEVSRSB7CiAgID9kYXRhc2V0IGEgdm9pZDpEYXRhc2V0IDsKICAgZGN0ZXJtczp0aXRsZSA/dGl0bGVMaXQgOwogICBkY3Rlcm1zOmxpY2Vuc2UgP2xpY2Vuc2UgOwogICBwYXY6Y3JlYXRlZE9uID9kYXRlIC4KIH0iCiAjYmVsb3cgY29kZSBzaG91bGQgYmUgcGVyZm9ybWVkIGZpcnN0IHRvIGhhbmRsZSB0aGUgc3NsIGNlcnRpZmljYXRlIGVycm9yCm9wdGlvbnMoUkN1cmxPcHRpb25zID0gbGlzdChjYWluZm8gPSBwYXN0ZTAoIHRlbXBkaXIoKSAsICIvY2FjZXJ0LnBlbSIgKSwgc3NsLnZlcmlmeXBlZXIgPSBGQUxTRSkpCnJlc3VsdHNNZXRhZGF0YSA8LSBTUEFSUUwoZW5kcG9pbnR3cCxxdWVyeU1ldGFkYXRhLGN1cmxfYXJncz1saXN0KHVzZXJhZ2VudD1SLnZlcnNpb24uc3RyaW5nKSkKc2hvd3Jlc3VsdHNNZXRhZGF0YSA8LSByZXN1bHRzTWV0YWRhdGEkcmVzdWx0cwpyZW1vdmUocXVlcnlNZXRhZGF0YSwgcmVzdWx0c01ldGFkYXRhKQoKIyMgMi4gUXVlcnkgV2lraVBhdGh3YXlzIFBXcywgSEdOQyBzeW1ib2xzIHVzZWQgaW4gTGFiZWxzOgoKIyMgMy4gUXVlcnkgV2lraVBhdGh3YXlzIFBXcywgSEdOQyBzeW1ib2wgdXNlZCBpbiBvcmlnaW5hbCBhbm5vdGF0aW9uczoKCiMjIDQuIFF1ZXJ5IFdpa2lQYXRod2F5cyBQV3MsIEhHTkMgc3ltYm9sIE1hcHBpbmdzOgpxdWVyeVdpa2lQYXRod2F5cyA8LQoiUFJFRklYIGN1cjogICAgICAgICAgICA8aHR0cDovL3ZvY2FidWxhcmllcy53aWtpcGF0aHdheXMub3JnL3dwI0N1cmF0aW9uOj4gI3RvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBSZWFjdG9tZSBhbmQgV1AgUFdzLgoKc2VsZWN0IGRpc3RpbmN0IChmbjpzdWJzdHJpbmcoP2hnbmNJZCwzNykgYXMgP0hHTkMpIChHUk9VUF9DT05DQVQoRElTVElOQ1Qgc3RyKD93cGlkKTtzZXBhcmF0b3I9JywgJykgQVMgP3BhdGh3YXlzKSAgKENPVU5UKERJU1RJTkNUIHN0cig/d3BpZCkpIEFTID91c2FnZSkKd2hlcmUgewogID9wYXRod2F5UmVzIGEgd3A6UGF0aHdheSA7ICAgICAgICAgICAgICAgICAgICNEZWZpbmUgd2hhdCBpcyBhIHBhdGh3YXkKICAgICAgICAgICAgICB3cDpvcmdhbmlzbU5hbWUgJ0hvbW8gc2FwaWVucycgOyAjRmlsdGVyIHBhdGh3YXlzIG9uIHNwZWNpZXMgSHVtYW4KICAgICAgICAgICAgICBkY3Rlcm1zOmlkZW50aWZpZXIgP3dwaWQgOyAgICAgICAjT2J0YWluIGlkZW50aWZpZXIgb2YgcGF0aHdheQogICAgICAgICAgICAgIHdwOm9udG9sb2d5VGFnIGN1cjpBbmFseXNpc0NvbGxlY3Rpb24gLiAgI1JlYWN0b21lOiBSZWFjdG9tZV9BcHByb3ZlZCAuIFdQOiBDdXJhdGlvbjpBbmFseXNpc0NvbGxlY3Rpb24KICAKICA/cHJvdGVpbiB3cDpiZGJIZ25jU3ltYm9sID9oZ25jSWQgOyAgICAgICAgICAjRmluZCBwcm90ZWlucyBiYXNlZCBvbiBIR05DIHN5bWJvbAogICAgICAgICAgIGRjdGVybXM6aXNQYXJ0T2YgP3BhdGh3YXlSZXMgLiAgICAgICNDb25uZWN0IHByb3RlaW4gdG8gUFcKfQpPUkRFUiBCWSBERVNDICg/dXNhZ2UpCiIKIyNFeGVjdXRlIHF1ZXJ5OgpyZXN1bHRzV2lraVBhdGh3YXlzIDwtIFNQQVJRTChlbmRwb2ludHdwLHF1ZXJ5V2lraVBhdGh3YXlzLGN1cmxfYXJncz1saXN0KHVzZXJhZ2VudD1SLnZlcnNpb24uc3RyaW5nKSkKc2hvd3Jlc3VsdHNXaWtpUGF0aHdheXMgPC0gcmVzdWx0c1dpa2lQYXRod2F5cyRyZXN1bHRzCnJlbW92ZShxdWVyeVdpa2lQYXRod2F5cywgcmVzdWx0c1dpa2lQYXRod2F5cykKYGBgCgpDb21wYXJlIHRoZSBXaWtpUGF0aHdheXMgZGF0YSBhZ2FpbnN0IHByaW1hcnkgc3ltYm9scyBmaXJzdCwgdGhlbiBhZ2FpbnN0IHNlY29uZGFyeSBzeW1ib2xzLCBsYXN0IGNvdW50IGhvdyBtYW55IHdlcmUgbm90IG1hdGNoaW5nIGF0IGFsbC4KYGBge3J9CiMjQ2hlY2sgb3ZlcmxhcCBiZXR3ZWVuIHByaW0gYW5kIHNlYzoKdW5pcXVlU2VjIDwtICBzZXRkaWZmKHNlY29uZGFyeUhHTkNTeW1ib2xzLCBwcmltYXJ5SEdOQ1N5bWJvbHMpCgojI0NvbnZlcnQgcmVhY3RvbWUgZGF0YSB0byB2ZWN0b3IgZm9ybWF0OgptZXJnZWRXaWtpUGF0aHdheXNWZWN0b3IgPC0gc2hvd3Jlc3VsdHNXaWtpUGF0aHdheXNbWydIR05DJ11dCiMjQ2hlY2sgcHJpbWFyeSBzeW1ib2xzOgpwcmltYXJ5TWF0Y2hlc1dpa2lQYXRod2F5cyA8LSBpbnRlcnNlY3QocHJpbWFyeUhHTkNTeW1ib2xzLCBtZXJnZWRXaWtpUGF0aHdheXNWZWN0b3IpCiMjQW1vdW50OgphbW91bnRQcmltYXJ5TWF0Y2hlc1dpa2lQYXRod2F5cyA8LSBsZW5ndGgocHJpbWFyeU1hdGNoZXNXaWtpUGF0aHdheXMpCiMjQ2hlY2sgc2Vjb25kYXJ5IHN5bWJvbHM6CnNlY29uZGFyeU1hdGNoZXNXaWtpUGF0aHdheXMgPC0gaW50ZXJzZWN0KHVuaXF1ZVNlYywgbWVyZ2VkV2lraVBhdGh3YXlzVmVjdG9yKQojI0Ftb3VudDoKYW1vdW50U2Vjb25kYXJ5TWF0Y2hlc1dpa2lQYXRod2F5cyA8LSBsZW5ndGgoc2Vjb25kYXJ5TWF0Y2hlc1dpa2lQYXRod2F5cykKYGBgCgoKCiMjIyAyLjQuIEJpR0cgZGF0YSBNb2RlbHMKYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMjSW5zdGFsbCBhbmQgbG9hZCByZXF1aXJlZCBwYWNrYWdlczoKYXBpX3BhY2thZ2VzIDwtIGMoImh0dHIiLCAianNvbmxpdGUiLCAiZGF0YS50YWJsZSIpCmZvciAoaSBpbiAxOmxlbmd0aChhcGlfcGFja2FnZXMpKSB7CmlmKCFhcGlfcGFja2FnZXNbaV0gJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSl7aW5zdGFsbC5wYWNrYWdlcyhhcGlfcGFja2FnZXNbaV0pfQp9CiNpbnN0YWxsLnBhY2thZ2VzKGMoImh0dHIiLCAianNvbmxpdGUiLCAiZGF0YS50YWJsZSIpKQpsaWJyYXJ5KGh0dHIpCmxpYnJhcnkoanNvbmxpdGUpCmxpYnJhcnkoZGF0YS50YWJsZSkKCmJpZ2dNb2RlbHNBUEljYWxsIDwtICdodHRwOi8vYmlnZy51Y3NkLmVkdS9hcGkvdjIvbW9kZWxzJwpiaWdnTW9kZWxzX21hcHMgPSBHRVQoYmlnZ01vZGVsc0FQSWNhbGwpCmJpZ2dNb2RlbHNfZGF0YV9tYXBzIDwtIHJhd1RvQ2hhcihiaWdnTW9kZWxzX21hcHMkY29udGVudCkKYmlnZ01vZGVsc19tYXBzX3RvdGFsID0gZGF0YS5mcmFtZSgpCmlmKGxlbmd0aChiaWdnTW9kZWxzX21hcHMkY29udGVudCk+MSl7CiAgY2xlYW5lZF9iaWdnTW9kZWxzX2RhdGFfbWFwcyA8LSBmcmVhZCh0ZXh0ID0gYmlnZ01vZGVsc19kYXRhX21hcHMsIGhlYWRlcj1GQUxTRSwgZmlsbCA9IFRSVUUsIHNlcCA9ICdcdCcpCiAgZGZfbWFwcyA8LSBkYXRhLmZyYW1lKGNsZWFuZWRfYmlnZ01vZGVsc19kYXRhX21hcHMpCiAgYmlnZ01vZGVsc19tYXBzX3RvdGFsIDwtIHJiaW5kKGJpZ2dNb2RlbHNfbWFwc190b3RhbCxkZl9tYXBzKQogIH0KCmBgYAoKCiMjIyAyLjUuIEdlbmUgT250b2xvZ3kKRnJvbSB0aGUgUXVpY2stR08gd2Vic2l0ZSAoaHR0cHM6Ly93d3cuZWJpLmFjLnVrL1F1aWNrR08vKSwgd2UgZG93bmxvYWRlZCBkYXRhIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgY3JpdGVyaWE6IC0tPiBVc2UgQVBJIGluc3RlYWQhCkkuIFRheG9uOiA5NjA2IChIb21vIHNhcGllbnMsIGh1bWFuKS4KCkRhdGEgd2FzIGRvd25sb2FkZWQgb246IE5vdi4gNiAoMjAyMyksIHdpdGggMSw2ODUsODkyIGFubm90YXRpb25zLCBhcyBhIFRTViBmaWxlLgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KR09fZmlsZUxvY2F0aW9uIDwtIHBhc3RlMCh3b3JraW5nRGlyZWN0b3J5LCAnL0RhdGFJbnB1dC8uLi4gLnRzdicpCiMjR08gdGVybXMKZ29fdGVybXMgPC0gcmVhZC5kZWxpbShmaWxlID0gIkRhdGFJbnB1dC9RdWlja0dPLWFubm90YXRpb25zLTE2NTkzNTY4MDc0MDMtMjAyMjA4MDEudHN2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gJ1x0JykKZ29fdGVybXNfdW5pcXVlIDwtIHVuaXF1ZShnb190ZXJtcyRTWU1CT0wpCgojIFNldCBXb3JraW5nIERpcmVjdG9yeSBiYWNrIHRvIGN1cnJlbnQgZm9sZGVyCnNldHdkKGRpcm5hbWUocnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGgpKQp3b3JrX0RJUiA8LSBnZXR3ZCgpCgpgYGAKCiMjIDMuIERhdGEgQ29tcGFyaXNvbgpXZSBjb21wYXJlIHRoZSBkYXRhIGZvciBlYWNoIGRhdGFiYXNlIHRvIHRoZSBzZWNvbmRhcnkgSEdOQyBzeW1ib2xzLgpgYGB7cn0KcGxvdChjYXJzKQpgYGAKCiMjIDQuIERhdGEgVmlzdWFsaXphdGlvbgpXZSB2aXN1YWxpemUgdGhlIGRhdGEgZm9yIGFsbCBkYXRhYmFzZXMgY29tYmluZWQuCmBgYHtyfQpwbG90KGNhcnMpCmBgYAo=