This report contains a summary of cell type annotation results for
library SCPCL000295. The goal of this report is to provide more detailed
information about cell type annotation results as an initial evaluation
of their quality and reliability.
Performing cell type annotation is an inherently challenging task
with high levels of uncertainty, especially when using automated
annotation methods. One way to address this is to use multiple cell type
annotation approaches and compare the results, as we have begun to do in
this report.
When multiple methods annotate a given cell as the same or similar
cell type, this may qualitatively indicate a more robust annotation.
Note that the contents of this report will vary based on which cell
type annotations are present. Further, be aware that different cell type
annotation methods may assign different labels to the same or similar
cell type (e.g., the different string representations
B cell naive
and Naive B cell
), due to use of
different underlying reference datasets.
This library contains the following cell type
annotations:
- Submitter-provided cell type annotation, generated by the original
lab which produced this data.
- Annotations from
SingleR
,
a reference-based approach (Looney et al.
2019). The BlueprintEncodeData
dataset, obtained from
the celldex
package, was used for reference annotations.
- Annotations from
CellAssign
,
a marker-gene-based approach (Zhang et al.
2019). Marker genes for cell types were obtained from PanglaoDB and compiled into a reference
named blood
. This reference includes the following organs
and tissue compartments: organ.
Cell type Annotation Summary
The plots and tables included here detail the results from performing
cell type annotation.
Statistics
Submitter-provided cell type annotations
In this table, cells labeled “Submitter-excluded” are those for which
submitters did not provide an annotation.
Annotated cell type
|
Number of cells
|
Percent of cells
|
celltype1
|
5452
|
100%
|
SingleR
cell type annotations
In this table, cells labeled “Unknown cell type” are those which
SingleR
pruned due to low-quality assignments. In the
processed result files, these cells are labeled
NA
.
Annotated cell type
|
Number of cells
|
Percent of cells
|
monocyte
|
2686
|
49.27%
|
granulocyte monocyte progenitor cell
|
2483
|
45.54%
|
common myeloid progenitor
|
105
|
1.93%
|
common lymphoid progenitor
|
46
|
0.84%
|
naive B cell
|
29
|
0.53%
|
hematopoietic multipotent progenitor cell
|
21
|
0.39%
|
plasma cell
|
17
|
0.31%
|
natural killer cell
|
15
|
0.28%
|
macrophage
|
14
|
0.26%
|
CD8-positive, alpha-beta T cell
|
11
|
0.2%
|
CD4-positive, alpha-beta T cell
|
7
|
0.13%
|
eosinophil
|
5
|
0.09%
|
effector memory CD8-positive, alpha-beta T cell
|
3
|
0.06%
|
central memory CD8-positive, alpha-beta T cell
|
2
|
0.04%
|
hematopoietic stem cell
|
2
|
0.04%
|
memory B cell
|
2
|
0.04%
|
effector memory CD4-positive, alpha-beta T cell
|
1
|
0.02%
|
megakaryocyte-erythroid progenitor cell
|
1
|
0.02%
|
Unknown cell type
|
2
|
0.04%
|
CellAssign
cell type annotations
In this table, cells labeled “Unknown cell type” are those which
CellAssign
could not confidently assign to a label in the
reference list. In the processed result files, these cells are labeled
"other"
.
Annotated cell type
|
Number of cells
|
Percent of cells
|
Myeloid-derived suppressor cells
|
2005
|
36.78%
|
Gamma delta T cells
|
221
|
4.05%
|
B cells naive
|
38
|
0.7%
|
Neutrophils
|
32
|
0.59%
|
Dendritic cells
|
31
|
0.57%
|
Eosinophils
|
22
|
0.4%
|
T cells
|
17
|
0.31%
|
NK cells
|
16
|
0.29%
|
B cells memory
|
13
|
0.24%
|
T memory cells
|
8
|
0.15%
|
Megakaryocytes
|
4
|
0.07%
|
Osteoclast precursor cells
|
3
|
0.06%
|
Plasma cells
|
2
|
0.04%
|
Hematopoietic stem cells
|
1
|
0.02%
|
Macrophages
|
1
|
0.02%
|
Mast cells
|
1
|
0.02%
|
Monocytes
|
1
|
0.02%
|
Nuocytes
|
1
|
0.02%
|
Red pulp macrophages
|
1
|
0.02%
|
Reticulocytes
|
1
|
0.02%
|
Unknown cell type
|
3033
|
55.63%
|
UMAPs
In this section, we show UMAPs colored by clusters. Clusters were
calculated using the graph-based louvain algorithm with jaccard
weighting.
## Warning: There were 2 warnings in `dplyr::mutate()`.
## The first warning was:
## ℹ In argument: `across(...)`.
## Caused by warning:
## ! 1 unknown level in `f`: Unknown cell type
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 1 remaining warning.

Next, we show UMAPs colored by cell types. For each cell typing
method, we show a separate faceted UMAP. In each panel, cells that were
assigned the given cell type label are colored, while all other cells
are in grey.
For legibility, only the seven most common cell types are shown. All
other cell types are grouped together and labeled “All remaining cell
types” (not to be confused with “Unknown cell type” which represents
cells that could not be classified).



Cell label comparison plots
This section displays heatmaps comparing cell labels from various
methods.
We use the Jaccard similarity
index to display the agreement between between pairs of labels
assigned by different annotation methods.
The Jaccard index reflects the degree of overlap between the two
labels and ranges from 0 to 1.
- If the labels are assigned to identical sets of cells, the Jaccard
index will be 1.
- If the labels are assigned to completely non-overlapping sets of
cells, the Jaccard index will be 0.
High agreement between methods qualitatively indicates higher
confidence in the cell type annotation.
Unsupervised clustering
Here we show the labels from unsupervised clustering compared to cell
type annotations. Cluster assignment was performed using the
louvain
algorithm.

Submitter-provided annotations
This section displays heatmaps comparing submitter-provided cell type
annotations to those obtained from SingleR
and
CellAssign
.

Automated annotations
This section displays a heatmap directly comparing
SingleR
and CellAssign
cell type annotations.
Note that due to different annotations references, these methods may use
different names for similar cell types.

Quality assessments of automated annotations
SingleR
annotations
To assess the quality of SingleR
cell type annotations,
we use the delta median statistic.
- Delta median is calculated for each cell as the difference between
the
SingleR
score of the annotated cell type label and the
median score of the other cell type labels in the reference
dataset.
- Higher delta median values indicate higher quality cell type
annotations.
You can interpret this plot as follows:
- Each point represents the delta median statistic of a given cell
whose
SingleR
annotation is shown on the y-axis.
- The point style indicates
SingleR
’s quality assessment
of the annotation:
- High-quality cell annotations are shown as closed points.
- Low-quality cell annotations are shown as open points. In other
sections of this report, these cells are labeled as
Unknown cell types
.
- For more information on how
SingleR
calculates
annotation quality, please refer to this
SingleR
documentation.
- Diamonds represent the median of the delta median statistic
specifically among high-quality annotations for the given cell type
annotation.

CellAssign
annotations
To assess the quality of CellAssign
cell type
annotations, we consider the probability associated with the annotated
cell type. These probabilities are provided directly by
CellAssign
:
CellAssign
first calculates the probability of each
cell being annotated as each cell type present in the reference.
CellAssign
then annotates cells by selecting the cell
type with the highest probability among all cell types considered.
- These probabilities range from 0 to 1, with larger values indicating
greater confidence in a given cell type label. We therefore expect
reliable labels to have values close to 1.
The plot below shows the distribution of
CellAssign
-calculated probabilities for the final cell type
labels. Line segments represent individual values that comprise each
distribution.
For cell types with 2 or fewer labeled cells, only the individual
value line segments are shown. Line segments are also taller for any
cell type label with 5 or fewer cells.

Session Info
R session information
## ─ Session info ───────────────────────────────────────────────────────────────
## setting value
## version R version 4.3.1 (2023-06-16)
## os macOS Sonoma 14.2.1
## system aarch64, darwin20
## ui X11
## language (EN)
## collate en_US.UTF-8
## ctype en_US.UTF-8
## tz America/New_York
## date 2024-01-05
## pandoc 3.1.1 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
##
## ─ Packages ───────────────────────────────────────────────────────────────────
## package * version date (UTC) lib source
## abind 1.4-5 2016-07-21 [1] CRAN (R 4.3.0)
## beachmat 2.16.0 2023-05-08 [1] Bioconductor
## Biobase * 2.60.0 2023-05-08 [1] Bioconductor
## BiocGenerics * 0.46.0 2023-06-04 [1] Bioconductor
## BiocParallel 1.34.2 2023-05-28 [1] Bioconductor
## bitops 1.0-7 2021-04-24 [1] CRAN (R 4.3.0)
## bslib 0.5.1 2023-08-11 [1] CRAN (R 4.3.0)
## cachem 1.0.8 2023-05-01 [1] CRAN (R 4.3.0)
## Cairo 1.6-1 2023-08-18 [1] CRAN (R 4.3.0)
## circlize 0.4.15 2022-05-10 [1] CRAN (R 4.3.0)
## cli 3.6.1 2023-03-23 [1] CRAN (R 4.3.0)
## clue 0.3-65 2023-09-23 [1] CRAN (R 4.3.1)
## cluster 2.1.4 2022-08-22 [2] CRAN (R 4.3.1)
## codetools 0.2-19 2023-02-01 [2] CRAN (R 4.3.1)
## colorspace 2.1-0 2023-01-23 [1] CRAN (R 4.3.0)
## ComplexHeatmap 2.16.0 2023-05-08 [1] Bioconductor
## crayon 1.5.2 2022-09-29 [1] CRAN (R 4.3.0)
## DelayedArray 0.26.7 2023-07-30 [1] Bioconductor
## DelayedMatrixStats 1.22.6 2023-09-03 [1] Bioconductor
## digest 0.6.33 2023-07-07 [1] CRAN (R 4.3.0)
## doParallel 1.0.17 2022-02-07 [1] CRAN (R 4.3.0)
## dplyr 1.1.4 2023-11-17 [1] CRAN (R 4.3.1)
## evaluate 0.23 2023-11-01 [1] CRAN (R 4.3.1)
## fansi 1.0.5 2023-10-08 [1] CRAN (R 4.3.1)
## farver 2.1.1 2022-07-06 [1] CRAN (R 4.3.0)
## fastmap 1.1.1 2023-02-24 [1] CRAN (R 4.3.0)
## flexmix 2.3-19 2023-03-16 [1] CRAN (R 4.3.0)
## forcats 1.0.0 2023-01-29 [1] CRAN (R 4.3.0)
## foreach 1.5.2 2022-02-02 [1] CRAN (R 4.3.0)
## generics 0.1.3 2022-07-05 [1] CRAN (R 4.3.0)
## GenomeInfoDb * 1.36.4 2023-10-08 [1] Bioconductor
## GenomeInfoDbData 1.2.10 2023-09-14 [1] Bioconductor
## GenomicRanges * 1.52.1 2023-10-08 [1] Bioconductor
## GetoptLong 1.0.5 2020-12-15 [1] CRAN (R 4.3.0)
## ggforce 0.4.1 2022-10-04 [1] CRAN (R 4.3.0)
## ggplot2 * 3.4.4 2023-10-12 [1] CRAN (R 4.3.1)
## GlobalOptions 0.1.2 2020-06-10 [1] CRAN (R 4.3.0)
## glue 1.6.2 2022-02-24 [1] CRAN (R 4.3.0)
## gtable 0.3.4 2023-08-21 [1] CRAN (R 4.3.0)
## highr 0.10 2022-12-22 [1] CRAN (R 4.3.0)
## htmltools 0.5.7 2023-11-03 [1] CRAN (R 4.3.1)
## httr 1.4.7 2023-08-15 [1] CRAN (R 4.3.0)
## IRanges * 2.34.1 2023-07-02 [1] Bioconductor
## iterators 1.0.14 2022-02-05 [1] CRAN (R 4.3.0)
## jquerylib 0.1.4 2021-04-26 [1] CRAN (R 4.3.0)
## jsonlite 1.8.8 2023-12-04 [1] CRAN (R 4.3.1)
## kableExtra 1.3.4 2021-02-20 [1] CRAN (R 4.3.0)
## knitr 1.45 2023-10-30 [1] CRAN (R 4.3.1)
## labeling 0.4.3 2023-08-29 [1] CRAN (R 4.3.0)
## lattice 0.21-8 2023-04-05 [2] CRAN (R 4.3.1)
## lifecycle 1.0.3 2022-10-07 [1] CRAN (R 4.3.0)
## magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.3.0)
## MASS 7.3-60 2023-05-04 [2] CRAN (R 4.3.1)
## Matrix 1.5-4.1 2023-05-18 [2] CRAN (R 4.3.1)
## MatrixGenerics * 1.12.3 2023-07-30 [1] Bioconductor
## matrixStats * 1.0.0 2023-06-02 [1] CRAN (R 4.3.0)
## miQC 1.8.0 2023-05-08 [1] Bioconductor
## modeltools 0.2-23 2020-03-05 [1] CRAN (R 4.3.0)
## munsell 0.5.0 2018-06-12 [1] CRAN (R 4.3.0)
## nnet 7.3-19 2023-05-03 [2] CRAN (R 4.3.1)
## pillar 1.9.0 2023-03-22 [1] CRAN (R 4.3.0)
## pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.3.0)
## png 0.1-8 2022-11-29 [1] CRAN (R 4.3.0)
## polyclip 1.10-6 2023-09-27 [1] CRAN (R 4.3.1)
## purrr 1.0.2 2023-08-10 [1] CRAN (R 4.3.0)
## R6 2.5.1 2021-08-19 [1] CRAN (R 4.3.0)
## RColorBrewer 1.1-3 2022-04-03 [1] CRAN (R 4.3.0)
## Rcpp 1.0.11 2023-07-06 [1] CRAN (R 4.3.0)
## RCurl 1.98-1.13 2023-11-02 [1] CRAN (R 4.3.1)
## rjson 0.2.21 2022-01-09 [1] CRAN (R 4.3.0)
## rlang 1.1.2 2023-11-04 [1] CRAN (R 4.3.1)
## rmarkdown 2.25 2023-09-18 [1] CRAN (R 4.3.1)
## rstudioapi 0.15.0 2023-07-07 [1] CRAN (R 4.3.0)
## rvest 1.0.3 2022-08-19 [1] CRAN (R 4.3.0)
## S4Arrays 1.0.6 2023-08-30 [1] Bioconductor
## S4Vectors * 0.38.2 2023-09-24 [1] Bioconductor
## sass 0.4.7 2023-07-15 [1] CRAN (R 4.3.0)
## scales 1.2.1 2022-08-20 [1] CRAN (R 4.3.0)
## scuttle 1.10.3 2023-10-15 [1] Bioconductor
## sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.3.0)
## shape 1.4.6 2021-05-19 [1] CRAN (R 4.3.0)
## SingleCellExperiment * 1.22.0 2023-05-08 [1] Bioconductor
## sparseMatrixStats 1.12.2 2023-07-02 [1] Bioconductor
## stringi 1.7.12 2023-01-11 [1] CRAN (R 4.3.0)
## stringr 1.5.1 2023-11-14 [1] CRAN (R 4.3.1)
## SummarizedExperiment * 1.30.2 2023-06-11 [1] Bioconductor
## svglite 2.1.2 2023-10-11 [1] CRAN (R 4.3.1)
## systemfonts 1.0.5 2023-10-09 [1] CRAN (R 4.3.1)
## tibble 3.2.1 2023-03-20 [1] CRAN (R 4.3.0)
## tidyr 1.3.0 2023-01-24 [1] CRAN (R 4.3.0)
## tidyselect 1.2.0 2022-10-10 [1] CRAN (R 4.3.0)
## tweenr 2.0.2 2022-09-06 [1] CRAN (R 4.3.0)
## utf8 1.2.4 2023-10-22 [1] CRAN (R 4.3.1)
## vctrs 0.6.4 2023-10-12 [1] CRAN (R 4.3.1)
## viridisLite 0.4.2 2023-05-02 [1] CRAN (R 4.3.0)
## webshot 0.5.5 2023-06-26 [1] CRAN (R 4.3.0)
## withr 2.5.2 2023-10-30 [1] CRAN (R 4.3.1)
## xfun 0.41 2023-11-01 [1] CRAN (R 4.3.1)
## xml2 1.3.6 2023-12-04 [1] CRAN (R 4.3.1)
## XVector 0.40.0 2023-05-08 [1] Bioconductor
## yaml 2.3.7 2023-01-23 [1] CRAN (R 4.3.0)
## zlibbioc 1.46.0 2023-05-08 [1] Bioconductor
##
## [1] /Users/sjspielman/Library/R/arm64/4.3/library
## [2] /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library
##
## ──────────────────────────────────────────────────────────────────────────────
LS0tCnBhcmFtczoKICBsaWJyYXJ5OiBFeGFtcGxlCiAgcHJvY2Vzc2VkX3NjZTogTlVMTAogIGRhdGU6ICFyIFN5cy5EYXRlKCkKdGl0bGU6ICJgciBnbHVlOjpnbHVlKCdTY1BDQSBTdXBwbGVtZW50YWwgY2VsbCB0eXBlIHJlcG9ydCBmb3Ige3BhcmFtcyRsaWJyYXJ5fScpYCIKYXV0aG9yOiAiQ2hpbGRob29kIENhbmNlciBEYXRhIExhYiIKZGF0ZTogImByIHBhcmFtcyRkYXRlYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIG1lc3NhZ2UgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQojIGtuaXRyIG9wdGlvbnMKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBGQUxTRQopCgpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQpsaWJyYXJ5KGdncGxvdDIpCgojIFNldCBkZWZhdWx0IGdncGxvdCB0aGVtZQp0aGVtZV9zZXQoCiAgdGhlbWVfYncoKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ocmVwKDIwLCA0KSksCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpCiAgICApCikKCiMgVGhpcyBfaXNfIHRoZSBzdXBwbGVtZW50YWwgcmVwb3J0CiMgd2Ugc2hvdWxkIG5vdCBwcmludCB0aGUgY2h1bmsgZnJvbSBjZWxsdHlwZXNfcWMucm1kIHJlY2FwaXR1bGF0aW5nIGJ1bGxldHMKIyAgYW5kIHBvaW50aW5nIHVzZXJzIHRvIHRoaXMgc3VwcCByZXBvcnQKaXNfc3VwcGxlbWVudGFsIDwtIFRSVUUKYGBgCgo8IS0tIEltcG9ydCBzaGFyZWQgZnVuY3Rpb25zIGZvciBjZWxsIHR5cGUgd3JhbmdsaW5nIC0tPgpgYGB7ciwgY2hpbGQ9J3V0aWxzL2NlbGx0eXBlX2Z1bmN0aW9ucy5ybWQnfQpgYGAKCgo8IS0tIERlZmluZSBoZWxwZXIgZnVuY3Rpb25zIGZvciBjYWxjdWxhdGluZyBKYWNjYXJkIG1hdHJpY2VzIC0tPgpgYGB7cn0KIycgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIEphY2NhcmQgc2ltaWxhcml0eSBvbiB0d28gdmVjdG9ycwojJwojJyBAcGFyYW0gdmVjMSBGaXJzdCB2ZWN0b3IKIycgQHBhcmFtIHZlYzIgU2Vjb25kIHZlY3RvcgojJwojJyBAcmV0dXJuIEphY2NhcmQgc2ltaWxhcml0eSBiZXR3ZWVuIHRoZSB2ZWN0b3JzCmphY2NhcmQgPC0gZnVuY3Rpb24odmVjMSwgdmVjMikgewogIGxlbmd0aChpbnRlcnNlY3QodmVjMSwgdmVjMikpIC8gbGVuZ3RoKHVuaW9uKHZlYzEsIHZlYzIpKQp9CgoKIyBXcmFwcGVyIGZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBqYWNjYXJkIHNpbWlsYXJpdHkgbWF0cml4IGZvciB0d28gY2F0ZWdvcmljYWwgdmFyaWFibGVzCiMnCiMnIEBwYXJhbSBjZWxsdHlwZV9kZiBUaGUgY2VsbHR5cGVfZGYgZGF0YSBmcmFtZSB3aGljaCBtdXN0IGNvbnRhaW4gdGhlc2UgY29sdW1uczoKIycgICBgY29sbmFtZTFgLCBgY29sbmFtZTJgLCBhbmQgYGJhcmNvZGVzYAojJyBAcGFyYW0gY29sbmFtZTEgQ29sdW1uIG5hbWUsIGFzIGEgc3RyaW5nLCBvZiBmaXJzdCBjYXRlZ29yaWNhbCB2YXJpYWJsZSBvZiBpbnRlcmVzdAojJyBAcGFyYW0gY29sbmFtZTIgQ29sdW1uIG5hbWUsIGFzIGEgc3RyaW5nLCBvZiBzZWNvbmQgY2F0ZWdvcmljYWwgdmFyaWFibGUgb2YgaW50ZXJlc3QKIycKIycgQHJldHVybiBKYWNjYXJkIHNpbWlsYXJpdHkgbWF0cml4IGZvciB0aGUgdHdvIGNvbHVtbnMuIGBjb2xuYW1lMWAgdmFsdWVzIHdpbGwKIycgICBiZSByb3cgbmFtZXMgYW5kIGBjb2xuYW1lMmAgdmFsdWVzIHdpbGwgYmUgY29sdW1uIG5hbWVzIGluIHRoZSBmaW5hbCBtYXRyaXgKbWFrZV9qYWNjYXJkX21hdHJpeCA8LSBmdW5jdGlvbihjZWxsdHlwZV9kZiwgY29sbmFtZTEsIGNvbG5hbWUyKSB7CiAgIyBtYWtlIGxpc3RzIG9mIGJhcmNvZGVzIGZvciBlYWNoIGNhdGVnb3J5LCBuYW1lZCBieSB0aGUgY2F0ZWdvcnkKICBpZDFfbGlzdCA8LSBzcGxpdChjZWxsdHlwZV9kZiRiYXJjb2RlcywgY2VsbHR5cGVfZGZbW2NvbG5hbWUxXV0pCiAgaWQyX2xpc3QgPC0gc3BsaXQoY2VsbHR5cGVfZGYkYmFyY29kZXMsIGNlbGx0eXBlX2RmW1tjb2xuYW1lMl1dKQoKICAjIGNyZWF0ZSB0aGUgZ3JpZCBvZiBjb21wYXJpc29ucwogIGNyb3NzX2RmIDwtIHRpZHlyOjpleHBhbmRfZ3JpZChpZDEgPSBuYW1lcyhpZDFfbGlzdCksIGlkMiA9IG5hbWVzKGlkMl9saXN0KSkKCiAgIyBjYWxjdWxhdGUgYSBzaW5nbGUgSmFjY2FyZCBpbmRleCBmb3IgZWFjaCBjb21iaW5hdGlvbiB1c2luZyBzcGxpdCBsaXN0cyAmIGlkcwogIGphY2NhcmRfc2NvcmVzIDwtIGNyb3NzX2RmIHw+CiAgICBwdXJycjo6cG1hcF9kYmwoXChpZDEsIGlkMil7CiAgICAgIGphY2NhcmQoaWQxX2xpc3RbW2lkMV1dLCBpZDJfbGlzdFtbaWQyXV0pCiAgICB9KQoKICAjIGFkZCBzY29yZXMgdG8gdGhlIGNvbXBhcmlzb24gZ3JpZCBhbmQgY29udmVydCB0byBtYXRyaXgKICBqYWNjYXJkX21hdHJpeCA8LSBjcm9zc19kZiB8PgogICAgZHBseXI6Om11dGF0ZShqYWNjYXJkID0gamFjY2FyZF9zY29yZXMpIHw+CiAgICAjIGNvbnZlcnQgdG8gbWF0cml4CiAgICB0aWR5cjo6cGl2b3Rfd2lkZXIoCiAgICAgIG5hbWVzX2Zyb20gPSAiaWQyIiwKICAgICAgdmFsdWVzX2Zyb20gPSAiamFjY2FyZCIKICAgICkgfD4KICAgIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJpZDEiKSB8PgogICAgYXMubWF0cml4KCkKCiAgcmV0dXJuKGphY2NhcmRfbWF0cml4KQp9CmBgYAoKCjwhLS0gRGVmaW5lIHZhcmlhYmxlcywgb3B0aW9ucywgYW5kIGZ1bmN0aW9ucyBmb3IgcGxvdHRpbmcgaGVhdG1hcHMgLS0+CmBgYHtyfQojIERlZmluZSBjb2xvciByYW1wIGZvciBzaGFyZWQgdXNlIGluIHRoZSBoZWF0bWFwCmhlYXRtYXBfY29sX2Z1biA8LSBjaXJjbGl6ZTo6Y29sb3JSYW1wMihjKDAsIDEpLCBjb2xvcnMgPSBjKCJ3aGl0ZSIsICJkYXJrc2xhdGVibHVlIikpCgojIFNldCBoZWF0bWFwIHBhZGRpbmcgb3B0aW9uCmhlYXRtYXBfcGFkZGluZyA8LSAwLjIKQ29tcGxleEhlYXRtYXA6Omh0X29wdChUSVRMRV9QQURESU5HID0gZ3JpZDo6dW5pdChoZWF0bWFwX3BhZGRpbmcsICJpbiIpKQoKIycgQ3JlYXRlIGEgQ29tcGxleEhlYXRtYXAgZnJvbSBhIG1hdHJpeAojJwojJyBAcGFyYW0gbWF0IE1hdHJpeCB0byBjcmVhdGUgaGVhdG1hcCBmcm9tLgojJyBAcGFyYW0gcm93X3RpdGxlIExhYmVsIGZvciByb3cgdGl0bGUuCiMnIEBwYXJhbSBjb2x1bW5fdGl0bGUgTGFiZWwgZm9yIGNvbHVtbiB0aXRsZS4KIycgQHBhcmFtIGxhYmVsc19mb250X3NpemUgRm9udCBzaXplIHRvIHVzZSBmb3Igcm93cyBhbmQgY29sdW1uIGxhYmVscy4KIycgQHBhcmFtIGtlZXBfbGVnZW5kX25hbWUgVGhlIG5hbWUgdG8gdXNlIGluIHRoZSBsZWdlbmQKIycgQHBhcmFtIGNvbF9mdW4gQ29sb3IgZnVuY3Rpb24gZm9yIHRoZSBoZWF0bWFwIHBhbGV0dGUuIERlZmF1bHQgaXMgYGhlYXRtYXBfY29sX2Z1bmAuCiMnIEBwYXJhbSAuLi4gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byBgQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoKWAKIycKIycgQHJldHVybiBBIENvbXBsZXhIZWF0bWFwIG9iamVjdApjcmVhdGVfc2luZ2xlX2hlYXRtYXAgPC0gZnVuY3Rpb24oCiAgICBtYXQsCiAgICByb3dfdGl0bGUsCiAgICBjb2x1bW5fdGl0bGUsCiAgICBsYWJlbHNfZm9udF9zaXplLAogICAga2VlcF9sZWdlbmRfbmFtZSwKICAgIGNvbF9mdW4gPSBoZWF0bWFwX2NvbF9mdW4sCiAgICAuLi4pIHsKICBoZWF0IDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKAogICAgdChtYXQpLCAjIHRyYW5zcG9zZSBiZWNhdXNlIG1hdHJpeCByb3dzIGFyZSBpbiBjb21tb24gJiB3ZSB3YW50IGEgdmVydGljYWwgYXJyYW5nZW1lbnQKICAgIGNvbCA9IGNvbF9mdW4sCiAgICBib3JkZXIgPSBUUlVFLCAjIGVhY2ggaGVhdG1hcCBnZXRzIGl0cyBvd24gb3V0bGluZQogICAgIyMgUm93IHBhcmFtZXRlcnMKICAgIGNsdXN0ZXJfcm93cyA9IEZBTFNFLAogICAgcm93X3RpdGxlID0gcm93X3RpdGxlLCAjIGVhY2ggaGVhdG1hcCBnZXRzIGl0cyBvd24gdGl0bGUKICAgIHJvd190aXRsZV9ncCA9IGdyaWQ6OmdwYXIoZm9udHNpemUgPSAxMCksCiAgICByb3dfdGl0bGVfc2lkZSA9ICJyaWdodCIsCiAgICByb3dfbmFtZXNfc2lkZSA9ICJsZWZ0IiwKICAgIHJvd19uYW1lc19ncCA9IGdyaWQ6OmdwYXIoZm9udHNpemUgPSBsYWJlbHNfZm9udF9zaXplKSwKICAgICMjIENvbHVtbiBwYXJhbWV0ZXJzCiAgICBjbHVzdGVyX2NvbHVtbnMgPSBGQUxTRSwKICAgIGNvbHVtbl90aXRsZSA9IGNvbHVtbl90aXRsZSwKICAgIGNvbHVtbl90aXRsZV9ncCA9IGdyaWQ6OmdwYXIoZm9udHNpemUgPSAxMCksCiAgICBjb2x1bW5fbmFtZXNfc2lkZSA9ICJib3R0b20iLAogICAgY29sdW1uX25hbWVzX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IGxhYmVsc19mb250X3NpemUpLAogICAgIyMjIHBhc3NlZCBpbiBhcmdzCiAgICAuLi4sCiAgICAjIyBMZWdlbmQgcGFyYW1ldGVycwogICAgaGVhdG1hcF9sZWdlbmRfcGFyYW0gPSBsaXN0KAogICAgICB0aXRsZSA9ICJKYWNjYXJkIGluZGV4IiwKICAgICAgZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgICBsZWdlbmRfd2lkdGggPSB1bml0KDEuNSwgImluIikKICAgICksCiAgICAjIG9ubHkga2VlcCBsZWdlbmRzIHRoYXQgbWF0Y2ggYGtlZXBfbGVnZW5kX25hbWVgCiAgICBzaG93X2hlYXRtYXBfbGVnZW5kID0gcm93X3RpdGxlID09IGtlZXBfbGVnZW5kX25hbWUsCiAgKQoKICByZXR1cm4oaGVhdCkKfQoKIycgRnVuY3Rpb24gdG8gcGxvdCBhIHZlcnRpY2FsbHktc3RhY2tlZCBDb21wbGV4SGVhdG1hcCBmcm9tIGEgbGlzdCBvZiBtYXRyaWNlcwojJwojJyBAcGFyYW0gbWF0cml4X2xpc3QgTGlzdCBvZiBtYXRyaWNlcyB0byBwbG90IGluIGEgdmVydGljYWwgbGF5b3V0CiMnIEBwYXJhbSBjb2x1bW5fdGl0bGUgVGl0bGUgdG8gdXNlIGZvciBjb2x1bW5zLCBzaGFyZWQgYW1vbmcgYWxsIGhlYXRtYXBzCiMnIEBwYXJhbSBsYWJlbHNfZm9udF9zaXplIEZvbnQgc2l6ZSB0byB1c2UgZm9yIHJvd3MgYW5kIGNvbHVtbiBsYWJlbHMKIycgQHBhcmFtIGNvbF9mdW4gQ29sb3IgZnVuY3Rpb24gZm9yIHRoZSBoZWF0bWFwIHBhbGV0dGUuIERlZmF1bHQgaXMgYGhlYXRtYXRfY29sX2Z1bmAKIycgQHBhcmFtIC4uLiBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIGBDb21wbGV4SGVhdG1hcDo6SGVhdG1hcCgpYAojJwojJyBAcmV0dXJuIEEgbGlzdCBvZiBDb21wbGV4SGVhdG1hcCBvYmplY3RzCmNyZWF0ZV9oZWF0bWFwX2xpc3QgPC0gZnVuY3Rpb24oCiAgICBtYXRyaXhfbGlzdCwKICAgIGNvbHVtbl90aXRsZSwKICAgIGxhYmVsc19mb250X3NpemUsCiAgICBjb2xfZnVuID0gaGVhdG1hcF9jb2xfZnVuLAogICAgLi4uKSB7CiAgIyBXZSBvbmx5IHdhbnQgb25lIHNoYXJlZCBsZWdlbmQgaW4gdGhlIGVuZCwgYXJiaXRyYXJpbHkgZ3JhYiB0aGUgZmlyc3Qgb25lCiAga2VlcF9sZWdlbmRfbmFtZSA8LSBuYW1lcyhtYXRyaXhfbGlzdClbMV0KCiAgaGVhdG1hcF9saXN0IDwtIG1hdHJpeF9saXN0IHw+CiAgICBwdXJycjo6aW1hcCgKICAgICAgXChtYXQsIG5hbWUpIGNyZWF0ZV9zaW5nbGVfaGVhdG1hcCgKICAgICAgICBtYXQsCiAgICAgICAgbmFtZSwKICAgICAgICBjb2x1bW5fdGl0bGUsCiAgICAgICAgbGFiZWxzX2ZvbnRfc2l6ZSwKICAgICAgICBrZWVwX2xlZ2VuZF9uYW1lLAogICAgICAgIGNvbF9mdW4sCiAgICAgICAgLi4uCiAgICAgICkKICAgICkgfD4KICAgICMgY29uY2F0ZW5hdGUgdmVydGljYWxseSBpbnRvIEhlYXRtYXBMaXN0IG9iamVjdAogICAgcHVycnI6OnJlZHVjZShDb21wbGV4SGVhdG1hcDo6YCV2JWApCgogIHJldHVybihoZWF0bWFwX2xpc3QpCn0KCgojJyBEZXRlcm1pbmUgdGhlIGxhYmVsIGZvbnQgc2l6ZSBiYXNlZCBvbiAjIGNoYXJhY3RlcnMgaW4gY2VsbCB0eXBlIGxhYmVscwojJwojJyBAcGFyYW0gaW5wdXRfbGFiZWxzIFZlY3RvciBvZiBjZWxsIHR5cGUgbGFiZWxzCiMnCiMnIEByZXR1cm4gRm9udCBzaXplIG51bWVyaWMgYXMgZGV0ZXJtaW5lZCBieSBsb25nZXN0IGNlbGwgdHlwZSBsYWJlbApmaW5kX2xhYmVsX3NpemUgPC0gZnVuY3Rpb24oaW5wdXRfbGFiZWxzKSB7CiAgbG9uZ2VzdF9uYW1lIDwtIGlucHV0X2xhYmVscyB8PgogICAgc3RyaW5ncjo6c3RyX2xlbmd0aCgpIHw+CiAgICBtYXgoKQoKICBsYWJlbHNfZm9udF9zaXplIDwtIGRwbHlyOjpjYXNlX3doZW4oCiAgICBsb25nZXN0X25hbWUgPCAzNSB+IDkuNSwKICAgIGxvbmdlc3RfbmFtZSA8IDQ1IH4gOC41LAogICAgbG9uZ2VzdF9uYW1lIDwgNjAgfiA3LjUsCiAgICAuZGVmYXVsdCA9IDYuNQogICkKCiAgcmV0dXJuKGxhYmVsc19mb250X3NpemUpCn0KYGBgCgoKYGBge3J9CiMnIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBvcHRpbWFsIGhlYXRtYXAgcGxvdCB2aWV3IGhlaWdodAojJwojJyBAcGFyYW0gcm93X25hbWVzIFZlY3RvciBvZiByb3duYW1lcwojJyBAcGFyYW0gY29sX25hbWVzIFZlY3RvciBvZiBjb2x1bW4gbmFtZXMKIycgQHBhcmFtIG5fc3BhY2VycyBOdW1iZXIgb2Ygc3BhY2VycyBiZXR3ZWVuIHN0YWNrZWQgaGVhdG1hcHMKIycgQHBhcmFtIHNwYWNlcl9zaXplIFNwYWNlciBzaXplIGluIGluY2hlcwojJyBAcGFyYW0gbWluX2hlaWdodCBNaW5pbWl6ZSBoZWlnaHQgcmVxdWlyZWQuIERlZmF1bHQgNCIKIycKIycgQHJldHVybiBIZWF0bWFwIGhlaWdodCBpbiBpbmNoZXMKY2FsY3VsYXRlX3Bsb3RfaGVpZ2h0IDwtIGZ1bmN0aW9uKAogICAgcm93X25hbWVzLAogICAgY29sX25hbWVzLAogICAgbl9zcGFjZXJzLAogICAgc3BhY2VyX3NpemUgPSBoZWF0bWFwX3BhZGRpbmcsCiAgICBtaW5faGVpZ2h0ID0gNCkgewogICMgZmlyc3QsIGJhc2VkIG9uIG51bWJlciBvZiBjZWxscyBpbiByb3dfbmFtZXM6CiAgIyAgIDYgY2VsbCB0eXBlcyB0byBhbiBpbmNoCiAgaGVhdF9oZWlnaHQgPC0gbGVuZ3RoKHJvd19uYW1lcykgLyA2CgogICMgbmV4dCwgYmFzZWQgb24gbmNoYXIgb2YgY29sX25hbWVzOgogICMgICAxMCBjaGFyYWN0ZXJzIHRvIGFuIGluY2gKICAjIHVzaW5nIHN0cmluZ3I6OnN0cl9sZW5ndGgoKSBpbiBjYXNlIGNvbF9uYW1lcyBpcyBhIGZhY3RvciB2ZWN0b3IKICBoZWF0X2hlaWdodCA8LSBoZWF0X2hlaWdodCArIG1heChzdHJpbmdyOjpzdHJfbGVuZ3RoKGNvbF9uYW1lcykpIC8gMTAKCiAgIyBmaW5hbGx5LCBhZGQgaW4gYW55IHBhZGRpbmcKICBoZWF0X2hlaWdodCA8LSBoZWF0X2hlaWdodCArIG5fc3BhY2VycyAqIHNwYWNlcl9zaXplCgogIHJldHVybigKICAgIG1heChjKG1pbl9oZWlnaHQsIGhlYXRfaGVpZ2h0KSkKICApCn0KYGBgCgoKYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CiMgZGVmaW5lIGxpYnJhcnkgYW5kIHNjZSBvYmplY3QKbGlicmFyeV9pZCA8LSBwYXJhbXMkbGlicmFyeQpwcm9jZXNzZWRfc2NlIDwtIHBhcmFtcyRwcm9jZXNzZWRfc2NlCgpsaWJyYXJ5X2lkIDwtICJTQ1BDTDAwMDI5NSIgCnByb2Nlc3NlZF9zY2UgPC0gcmVhZFJEUyhnbHVlOjpnbHVlKCJ7bGlicmFyeV9pZH1fcHJvY2Vzc2VkLnJkcyIpKQptZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsYXNzaWduX3JlZmVyZW5jZV9vcmdhbnMgPC0gIm9yZ2FuIgpwcm9jZXNzZWRfc2NlJHN1Ym1pdHRlcl9jZWxsdHlwZV9hbm5vdGF0aW9uIDwtICJjZWxsdHlwZTEiCiAgCiMgY2hlY2sgZm9yIGFubm90YXRpb24gbWV0aG9kcwpoYXNfc2luZ2xlciA8LSAic2luZ2xlciIgJWluJSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsdHlwZV9tZXRob2RzCmhhc19jZWxsYXNzaWduIDwtICJjZWxsYXNzaWduIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMKaGFzX3N1Ym1pdHRlciA8LSAic3VibWl0dGVyIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMKCiMgY2hlY2sgZm9yIHVtYXAKaGFzX3VtYXAgPC0gIlVNQVAiICVpbiUgcmVkdWNlZERpbU5hbWVzKHByb2Nlc3NlZF9zY2UpCgojIHdoYXQgY2VsbHR5cGVzIGFyZSBhdmFpbGFibGU/CmF2YWlsYWJsZV9jZWxsdHlwZXMgPC0gYygKICBpZmVsc2UoaGFzX3N1Ym1pdHRlciwgIlN1Ym1pdHRlciIsIE5BKSwKICBpZmVsc2UoaGFzX3NpbmdsZXIsICJTaW5nbGVSIiwgTkEpLAogIGlmZWxzZShoYXNfY2VsbGFzc2lnbiwgIkNlbGxBc3NpZ24iLCBOQSkKKSB8PgogIG5hLm9taXQoKSB8PgogIGFzLmNoYXJhY3RlcigpCgojIFRoaXMgdmFyaWFibGUgbmVlZCB0byBiZSBkZWZpbmVkIGZvciBlZGdlIGNvbmRpdGlvbnMgd2hlbiBjZXJ0YWluIGNlbGwgdHlwZXMKIyAgYXJlbid0IGF2YWlsYWJsZToKIyAgV2hlbiB3ZSBoYXZlIGNodW5rcyB3aXRoIGBldmFsPTxoYXNfbWV0aG9kPmAsIGtuaXRyIHNlZW1zIHRvIG5lZWQgYWxsIG90aGVyCiMgIHZhcmlhYmxlcyB1c2VkIGluIGNodW5rIHBhcmFtcyBkZWZpbmVkLCBpbmNsdWRpbmcgcGxvdCBkaW1lbnNpb24gdmFyaWFibGVzCiMgIHdoaWNoIHdvdWxkIGhhdmUgb25seSBiZWVuIGNyZWF0ZWQgaW4gY2h1bmtzIHdoaWNoIGFsc28gaGFkIGFuIGFzc29jaWF0ZWQKIyAgZXZhbD08aGFzX21ldGhvZD5gLiBTaW5jZSB0aG9zZSBjaHVua3Mgd29uJ3QgaGF2ZSBiZWVuIGV2YWwnZCBpZiBGQUxTRSwgd2UKIyAgbmVlZCB0byBkZWZpbmUgdGhpcyB2YXJpYWJsZSB0byBwcmV2ZW50IGVycm9ycywgYnV0IHRoaXMgdmFsdWUgd2lsbCBuZXZlcgojICBhY3R1YWxseSBiZSB1c2VkLgpwbG90X2hlaWdodCA8LSAxCgojIERldGVybWluZSBpZiBsaWJyYXJ5IGlzIG11bHRpcGxleGVkOgojICBzYW1wbGVfaWQgc2hvdWxkIGJlIGRlZmluZWQgd2l0aCBsZW5ndGggPiAxCnNhbXBsZV9pZCA8LSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzYW1wbGVfaWQKaGFzX211bHRpcGxleCA8LSBsZW5ndGgoc2FtcGxlX2lkKSA+IDEKYGBgCgo8IS0tIElmIG11bHRpcGxleGVkLCBvcGVuIHdpdGggd2FybmluZyAgLS0+IApgYGB7ciwgZXZhbCA9IGhhc19tdWx0aXBsZXgsIHJlc3VsdHM9J2FzaXMnfQojIGNvbnZlcnQgc2FtcGxlIGlkIHRvIGJ1bGxldCBzZXBhcmF0ZWQgbGlzdAptdWx0aXBsZXhfc2FtcGxlcyA8LSBwYXN0ZTAoIjxsaT4iLCBwYXN0ZShzYW1wbGVfaWQsIGNvbGxhcHNlID0gIjwvbGk+PGxpPiIsICI8L2xpPiIpKQpnbHVlOjpnbHVlKCIKIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCI+CgogVGhpcyBsaWJyYXJ5IGlzIG11bHRpcGxleGVkIGFuZCBjb250YWlucyBkYXRhIGZyb20gbW9yZSB0aGFuIG9uZSBzYW1wbGUuCiBEYXRhIGZyb20gdGhlIGZvbGxvd2luZyBzYW1wbGVzIGFyZSBpbmNsdWRlZCBpbiB0aGlzIGxpYnJhcnk6CgogICAge211bHRpcGxleF9zYW1wbGVzfQoKICA8L2Rpdj4KIikKYGBgCgpUaGlzIHJlcG9ydCBjb250YWlucyBhIHN1bW1hcnkgb2YgY2VsbCB0eXBlIGFubm90YXRpb24gcmVzdWx0cyBmb3IgbGlicmFyeSBgciBsaWJyYXJ5X2lkYC4KVGhlIGdvYWwgb2YgdGhpcyByZXBvcnQgaXMgdG8gcHJvdmlkZSBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IGNlbGwgdHlwZSBhbm5vdGF0aW9uIHJlc3VsdHMgYXMgYW4gaW5pdGlhbCBldmFsdWF0aW9uIG9mIHRoZWlyIHF1YWxpdHkgYW5kIHJlbGlhYmlsaXR5LgoKUGVyZm9ybWluZyBjZWxsIHR5cGUgYW5ub3RhdGlvbiBpcyBhbiBpbmhlcmVudGx5IGNoYWxsZW5naW5nIHRhc2sgd2l0aCBoaWdoIGxldmVscyBvZiB1bmNlcnRhaW50eSwgZXNwZWNpYWxseSB3aGVuIHVzaW5nIGF1dG9tYXRlZCBhbm5vdGF0aW9uIG1ldGhvZHMuCk9uZSB3YXkgdG8gYWRkcmVzcyB0aGlzIGlzIHRvIHVzZSBtdWx0aXBsZSBjZWxsIHR5cGUgYW5ub3RhdGlvbiBhcHByb2FjaGVzIGFuZCBjb21wYXJlIHRoZSByZXN1bHRzLCBhcyB3ZSBoYXZlIGJlZ3VuIHRvIGRvIGluIHRoaXMgcmVwb3J0LgoKV2hlbiBtdWx0aXBsZSBtZXRob2RzIGFubm90YXRlIGEgZ2l2ZW4gY2VsbCBhcyB0aGUgc2FtZSBvciBzaW1pbGFyIGNlbGwgdHlwZSwgdGhpcyBtYXkgcXVhbGl0YXRpdmVseSBpbmRpY2F0ZSBhIG1vcmUgcm9idXN0IGFubm90YXRpb24uCgpOb3RlIHRoYXQgdGhlIGNvbnRlbnRzIG9mIHRoaXMgcmVwb3J0IHdpbGwgdmFyeSBiYXNlZCBvbiB3aGljaCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMgYXJlIHByZXNlbnQuCkZ1cnRoZXIsIGJlIGF3YXJlIHRoYXQgZGlmZmVyZW50IGNlbGwgdHlwZSBhbm5vdGF0aW9uIG1ldGhvZHMgbWF5IGFzc2lnbiBkaWZmZXJlbnQgbGFiZWxzIHRvIHRoZSBzYW1lIG9yIHNpbWlsYXIgY2VsbCB0eXBlIChlLmcuLCB0aGUgZGlmZmVyZW50IHN0cmluZyByZXByZXNlbnRhdGlvbnMgYEIgY2VsbCBuYWl2ZWAgYW5kIGBOYWl2ZSBCIGNlbGxgKSwgZHVlIHRvIHVzZSBvZiBkaWZmZXJlbnQgdW5kZXJseWluZyByZWZlcmVuY2UgZGF0YXNldHMuCgo8IS0tTm90ZSB0aGF0IHRoZSBzcGVjaWZpYyBjb250ZW50cyBvZiB0aGlzIHJlcG9ydCB3aWxsIGRlcGVuZCBvbiB3aGljaCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMgYXJlIHByZXNlbnQuLS0+CioqVGhpcyBsaWJyYXJ5IGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgY2VsbCB0eXBlIGFubm90YXRpb25zOioqCgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KIyBidWlsZCB1cCB0aGlzIHN0cmluZyBhcyB3ZSBnbzoKbWV0aG9kc190ZXh0IDwtICIiCgppZiAoaGFzX3N1Ym1pdHRlcikgewogIG1ldGhvZHNfdGV4dCA8LSBnbHVlOjpnbHVlKAogICAgInttZXRob2RzX3RleHR9CiAgICAqIFN1Ym1pdHRlci1wcm92aWRlZCBjZWxsIHR5cGUgYW5ub3RhdGlvbiwgZ2VuZXJhdGVkIGJ5IHRoZSBvcmlnaW5hbCBsYWIgd2hpY2ggcHJvZHVjZWQgdGhpcyBkYXRhLlxuIgogICkKfQoKaWYgKGhhc19zaW5nbGVyKSB7CiAgbWV0aG9kc190ZXh0IDwtIGdsdWU6OmdsdWUoCiAgICAie21ldGhvZHNfdGV4dH0KICAgICogQW5ub3RhdGlvbnMgZnJvbSBbYFNpbmdsZVJgXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvU2luZ2xlUi5odG1sKSwgYSByZWZlcmVuY2UtYmFzZWQgYXBwcm9hY2ggKFtMb29uZXkgX2V0IGFsLl8gMjAxOV0oaHR0cHM6Ly9kb2kub3JnLzEwLjEwMzgvczQxNTkwLTAxOC0wMjc2LXkpKS4KICAgIFRoZSBge21ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJHNpbmdsZXJfcmVmZXJlbmNlfWAgZGF0YXNldCwgb2J0YWluZWQgZnJvbSB0aGUgW2BjZWxsZGV4YCBwYWNrYWdlXShodHRwOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2RhdGEvZXhwZXJpbWVudC9odG1sL2NlbGxkZXguaHRtbCksIHdhcyB1c2VkIGZvciByZWZlcmVuY2UgYW5ub3RhdGlvbnMuXG4iCiAgKQp9CgppZiAoaGFzX2NlbGxhc3NpZ24pIHsKICBvcmdhbnMgPC0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkY2VsbGFzc2lnbl9yZWZlcmVuY2Vfb3JnYW5zIHw+CiAgICBzdHJpbmdyOjpzdHJfdG9fbG93ZXIoKQogICMgc3BsaXQgdXAgYW5kIGFkZCBhbiBgYW5kYCBiZWZvcmUgdGhlIGZpbmFsIG9yZ2FuCiAgb3JnYW5zX3N0cmluZyA8LSBzdHJpbmdyOjpzdHJfc3BsaXRfMShvcmdhbnMsIHBhdHRlcm4gPSAiLCAiKSB8PgogICAgc3RyaW5ncjo6c3RyX2ZsYXR0ZW5fY29tbWEobGFzdCA9ICIsIGFuZCAiKQoKICByZWZfbmFtZSA8LSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsYXNzaWduX3JlZmVyZW5jZQoKICBtZXRob2RzX3RleHQgPC0gZ2x1ZTo6Z2x1ZSgKICAgICJ7bWV0aG9kc190ZXh0fQogICAgKiBBbm5vdGF0aW9ucyBmcm9tIFtgQ2VsbEFzc2lnbmBdKGh0dHBzOi8vZ2l0aHViLmNvbS9JcnJhdGlvbm9uZS9jZWxsYXNzaWduKSwgYSBtYXJrZXItZ2VuZS1iYXNlZCBhcHByb2FjaCAoW1poYW5nIF9ldCBhbC5fIDIwMTldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMDM4L3M0MTU5Mi0wMTktMDUyOS0xKSkuCiAgICBNYXJrZXIgZ2VuZXMgZm9yIGNlbGwgdHlwZXMgd2VyZSBvYnRhaW5lZCBmcm9tIFtQYW5nbGFvREJdKGh0dHBzOi8vcGFuZ2xhb2RiLnNlLykgYW5kIGNvbXBpbGVkIGludG8gYSByZWZlcmVuY2UgbmFtZWQgYHtyZWZfbmFtZX1gLgogICAgVGhpcyByZWZlcmVuY2UgaW5jbHVkZXMgdGhlIGZvbGxvd2luZyBvcmdhbnMgYW5kIHRpc3N1ZSBjb21wYXJ0bWVudHM6IHtvcmdhbnNfc3RyaW5nfS5cbiIKICApCn0KCmdsdWU6OmdsdWUoInttZXRob2RzX3RleHR9IikKYGBgCgoKPCEtLS0tLS0tIENhbGwgdGhlIGNlbGx0eXBlc19xYyByZXBvcnQgc2VjdGlvbiBmcm9tIHRoZSBtYWluIHJlcG9ydCAtLS0tLS0tLS0tLT4KYGBge3IsIGNoaWxkPSdjZWxsdHlwZXNfcWMucm1kJ30KYGBgCgoKIyBDZWxsIGxhYmVsIGNvbXBhcmlzb24gcGxvdHMKClRoaXMgc2VjdGlvbiBkaXNwbGF5cyBoZWF0bWFwcyBjb21wYXJpbmcgY2VsbCBsYWJlbHMgZnJvbSB2YXJpb3VzIG1ldGhvZHMuCgpXZSB1c2UgdGhlIFtKYWNjYXJkIHNpbWlsYXJpdHkgaW5kZXhdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0phY2NhcmRfaW5kZXgpIHRvIGRpc3BsYXkgdGhlIGFncmVlbWVudCBiZXR3ZWVuIGJldHdlZW4gcGFpcnMgb2YgbGFiZWxzIGFzc2lnbmVkIGJ5IGRpZmZlcmVudCBhbm5vdGF0aW9uIG1ldGhvZHMuCgpUaGUgSmFjY2FyZCBpbmRleCByZWZsZWN0cyB0aGUgZGVncmVlIG9mIG92ZXJsYXAgYmV0d2VlbiB0aGUgdHdvIGxhYmVscyBhbmQgcmFuZ2VzIGZyb20gMCB0byAxLgoKKiBJZiB0aGUgbGFiZWxzIGFyZSBhc3NpZ25lZCB0byBpZGVudGljYWwgc2V0cyBvZiBjZWxscywgdGhlIEphY2NhcmQgaW5kZXggd2lsbCBiZSAxLgoqIElmIHRoZSBsYWJlbHMgYXJlIGFzc2lnbmVkIHRvIGNvbXBsZXRlbHkgbm9uLW92ZXJsYXBwaW5nIHNldHMgb2YgY2VsbHMsIHRoZSBKYWNjYXJkIGluZGV4IHdpbGwgYmUgMC4KCkhpZ2ggYWdyZWVtZW50IGJldHdlZW4gbWV0aG9kcyBxdWFsaXRhdGl2ZWx5IGluZGljYXRlcyBoaWdoZXIgY29uZmlkZW5jZSBpbiB0aGUgY2VsbCB0eXBlIGFubm90YXRpb24uCgoKCgoKPCEtLSBJZiBtdWx0aXBsZXhlZCwgc2hvdyBpbmZvIGFsZXJ0IGluc3RlYWQgb2YgdGhpcyBoZWF0bWFwIC0tPiAKYGBge3IsIGV2YWwgPSBoYXNfbXVsdGlwbGV4LCByZXN1bHRzPSdhc2lzJ30KZ2x1ZTo6Z2x1ZSgiCiA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtaW5mb1wiPgoKICBObyBoZWF0bWFwIGNvbXBhcmluZyBjbHVzdGVyIGFuZCBjZWxsIHR5cGUgYW5ub3RhdGlvbiBsYWJlbHMgaXMgc2hvd24gYmVjYXVzZSB0aGUgcHJlc2VuY2Ugb2YgbXVsdGlwbGUgc2FtcGxlcyBtYXkgY29uZm91bmQgY2x1c3RlciBhc3NpZ25tZW50LgoKICA8L2Rpdj4KIikKYGBgCgo8IS0tIElmIG5vdCBtdWx0aXBsZXhlZCwgc2hvdyB0aGUgaGVhZGVyLCB0ZXh0LCBhbmQgaGVhdG1hcCAtLT4gCmBgYHtyLCBldmFsID0gIWhhc19tdWx0aXBsZXgsIHJlc3VsdHM9J2FzaXMnfQpnbHVlOjpnbHVlKCIKICAjIyBVbnN1cGVydmlzZWQgY2x1c3RlcmluZwoKICBIZXJlIHdlIHNob3cgdGhlIGxhYmVscyBmcm9tIHVuc3VwZXJ2aXNlZCBjbHVzdGVyaW5nIGNvbXBhcmVkIHRvIGNlbGwgdHlwZSBhbm5vdGF0aW9ucy4KICBDbHVzdGVyIGFzc2lnbm1lbnQgd2FzIHBlcmZvcm1lZCB1c2luZyB0aGUgYHttZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjbHVzdGVyX2FsZ29yaXRobX1gIGFsZ29yaXRobS4KIikKCiMgQ2FsY3VsYXRlIGFsbCBqYWNjYXJkIG1hdHJpY2VzIG9mIGludGVyZXN0IGZvciBpbnB1dCB0byBoZWF0bWFwCmphY2NhcmRfY2x1c3Rlcl9tYXRyaWNlcyA8LSBhdmFpbGFibGVfY2VsbHR5cGVzIHw+CiAgc3RyaW5ncjo6c3RyX3RvX2xvd2VyKCkgfD4KICBwdXJycjo6c2V0X25hbWVzKGF2YWlsYWJsZV9jZWxsdHlwZXMpIHw+CiAgcHVycnI6Om1hcChcKG5hbWUpIHsKICAgIG1ha2VfamFjY2FyZF9tYXRyaXgoCiAgICAgIGNlbGx0eXBlX2RmLAogICAgICAiY2x1c3RlciIsCiAgICAgIGdsdWU6OmdsdWUoIntuYW1lfV9jZWxsdHlwZV9hbm5vdGF0aW9uIikKICAgICkKICB9KQoKYWxsX2NlbGx0eXBlcyA8LSBqYWNjYXJkX2NsdXN0ZXJfbWF0cmljZXMgfD4KICBwdXJycjo6bWFwKGNvbG5hbWVzKSB8PgogIHVubGlzdCgpCgpwbG90X2hlaWdodCA8LSBjYWxjdWxhdGVfcGxvdF9oZWlnaHQoCiAgYWxsX2NlbGx0eXBlcywKICB1bmlxdWUoY2VsbHR5cGVfZGYkY2x1c3RlciksCiAgbGVuZ3RoKGphY2NhcmRfY2x1c3Rlcl9tYXRyaWNlcykgLSAxCikKYGBgCgoKYGBge3IsIGV2YWwgPSAhaGFzX211bHRpcGxleCwgZmlnLmhlaWdodCA9IHBsb3RfaGVpZ2h0LCBmaWcud2lkdGggPSA4LjUsIHdhcm5pbmcgPSBGQUxTRX0KamFjY2FyZF9jbHVzdGVyX21hdHJpY2VzIHw+CiAgY3JlYXRlX2hlYXRtYXBfbGlzdCgKICAgIGNvbHVtbl90aXRsZSA9ICJDbHVzdGVycyIsCiAgICBsYWJlbHNfZm9udF9zaXplID0gZmluZF9sYWJlbF9zaXplKGFsbF9jZWxsdHlwZXMpLAogICAgIyMgYWRkaXRpb25hbCBhcmd1bWVudHMKICAgIGNvbHVtbl9uYW1lc19yb3QgPSAwCiAgKSB8PgogIENvbXBsZXhIZWF0bWFwOjpkcmF3KAogICAgaGVhdG1hcF9sZWdlbmRfc2lkZSA9ICJib3R0b20iCiAgKQpgYGAKCgoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBTdWJtaXR0ZXIgaGVhdG1hcHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfc3VibWl0dGVyICYgKGhhc19jZWxsYXNzaWduIHwgaGFzX3NpbmdsZXIpfQojIGRvbid0IGNvbXBhcmUgc3VibWl0dGVyIHRvIHN1Ym1pdHRlcgphdmFpbGFibGVfY2VsbHR5cGVzIDwtIGF2YWlsYWJsZV9jZWxsdHlwZXNbIShhdmFpbGFibGVfY2VsbHR5cGVzID09ICJTdWJtaXR0ZXIiKV0KCm1ldGhvZHNfc3RyaW5nIDwtIGF2YWlsYWJsZV9jZWxsdHlwZXMgfD4KICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoIl4iLCAiYCIpIHw+CiAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCIkIiwgImAiKSB8PgogIHN0cmluZ3I6OnN0cl9mbGF0dGVuX2NvbW1hKCIsIGFuZCAiKQoKa25pdHI6OmFzaXNfb3V0cHV0KAogIGdsdWU6OmdsdWUoCiAgICAiIyMgU3VibWl0dGVyLXByb3ZpZGVkIGFubm90YXRpb25zCgogIFRoaXMgc2VjdGlvbiBkaXNwbGF5cyBoZWF0bWFwcyBjb21wYXJpbmcgc3VibWl0dGVyLXByb3ZpZGVkIGNlbGwgdHlwZSBhbm5vdGF0aW9ucyB0byB0aG9zZSBvYnRhaW5lZCBmcm9tIHttZXRob2RzX3N0cmluZ30uIgogICkKKQpgYGAKCmBgYHtyLCBldmFsID0gaGFzX3N1Ym1pdHRlciAmIChoYXNfY2VsbGFzc2lnbiB8IGhhc19zaW5nbGVyKX0KIyBjYWxjdWxhdGUgbWF0cmljZXMgY29tcGFyaW5nIHRvIHN1Ym1pdHRlcgpqYWNjYXJkX3N1Ym1pdHRlcl9tYXRyaWNlcyA8LSBhdmFpbGFibGVfY2VsbHR5cGVzIHw+CiAgc3RyaW5ncjo6c3RyX3RvX2xvd2VyKCkgfD4KICBwdXJycjo6bWFwKFwobmFtZSkgewogICAgbWFrZV9qYWNjYXJkX21hdHJpeCgKICAgICAgY2VsbHR5cGVfZGYsCiAgICAgICJzdWJtaXR0ZXJfY2VsbHR5cGVfYW5ub3RhdGlvbiIsCiAgICAgIGdsdWU6OmdsdWUoIntuYW1lfV9jZWxsdHlwZV9hbm5vdGF0aW9uIikKICAgICkKICB9KSB8PgogIHB1cnJyOjpzZXRfbmFtZXMoYXZhaWxhYmxlX2NlbGx0eXBlcykKCiMgaG93IG1hbnkgY2VsbCB0eXBlcz8KYWxsX2NlbGx0eXBlcyA8LSBqYWNjYXJkX3N1Ym1pdHRlcl9tYXRyaWNlcyB8PgogIHB1cnJyOjptYXAoY29sbmFtZXMpIHw+CiAgdW5saXN0KCkKCnBsb3RfaGVpZ2h0IDwtIGNhbGN1bGF0ZV9wbG90X2hlaWdodCgKICBhbGxfY2VsbHR5cGVzLAogIHVuaXF1ZShjZWxsdHlwZV9kZiRzdWJtaXR0ZXJfY2VsbHR5cGVfYW5ub3RhdGlvbiksCiAgbGVuZ3RoKGphY2NhcmRfc3VibWl0dGVyX21hdHJpY2VzKSAtIDEKKQpgYGAKCmBgYHtyLCBldmFsID0gaGFzX3N1Ym1pdHRlciAmIChoYXNfY2VsbGFzc2lnbiB8IGhhc19zaW5nbGVyKSwgZmlnLmhlaWdodCA9IHBsb3RfaGVpZ2h0LCBmaWcud2lkdGggPSA4LjUsIHdhcm5pbmcgPSBGQUxTRX0KamFjY2FyZF9zdWJtaXR0ZXJfbWF0cmljZXMgfD4KICBjcmVhdGVfaGVhdG1hcF9saXN0KAogICAgY29sdW1uX3RpdGxlID0gIlN1Ym1pdHRlci1wcm92aWRlZCBhbm5vdGF0aW9ucyIsCiAgICBsYWJlbHNfZm9udF9zaXplID0gZmluZF9sYWJlbF9zaXplKGFsbF9jZWxsdHlwZXMpLAogICAgIyBhZGRpdGlvbmFsIGFyZ3VtZW50cwogICAgY29sdW1uX25hbWVzX3JvdCA9IDkwCiAgKSB8PgogIENvbXBsZXhIZWF0bWFwOjpkcmF3KAogICAgaGVhdG1hcF9sZWdlbmRfc2lkZSA9ICJib3R0b20iCiAgKQpgYGAKCgo8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gU2luZ2xlUi9DZWxsQXNzaWduIGhlYXRtYXAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPgpgYGB7ciwgZXZhbCA9IGhhc19jZWxsYXNzaWduICYgaGFzX3NpbmdsZXIsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTh9CmtuaXRyOjphc2lzX291dHB1dCgiCiMjIEF1dG9tYXRlZCBhbm5vdGF0aW9ucwoKVGhpcyBzZWN0aW9uIGRpc3BsYXlzIGEgaGVhdG1hcCBkaXJlY3RseSBjb21wYXJpbmcgYFNpbmdsZVJgIGFuZCBgQ2VsbEFzc2lnbmAgY2VsbCB0eXBlIGFubm90YXRpb25zLgpOb3RlIHRoYXQgZHVlIHRvIGRpZmZlcmVudCBhbm5vdGF0aW9ucyByZWZlcmVuY2VzLCB0aGVzZSBtZXRob2RzIG1heSB1c2UgZGlmZmVyZW50IG5hbWVzIGZvciBzaW1pbGFyIGNlbGwgdHlwZXMuCiIpCgojIFNldCBwbG90IGRpbWVuc2lvbnMgYmFzZWQgb24gbnVtYmVyIG9mIFNpbmdsZVIgY2VsbCB0eXBlcwphbGxfY2VsbHR5cGVzIDwtIGxldmVscyhjZWxsdHlwZV9kZiRzaW5nbGVyX2NlbGx0eXBlX2Fubm90YXRpb24pCnBsb3RfaGVpZ2h0IDwtIGNhbGN1bGF0ZV9wbG90X2hlaWdodCgKICB1bmlxdWUoY2VsbHR5cGVfZGYkc2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uKSwKICB1bmlxdWUoY2VsbHR5cGVfZGYkY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uKSwKICAwCikKYGBgCgoKYGBge3IsIGV2YWwgPSBoYXNfY2VsbGFzc2lnbiAmIGhhc19zaW5nbGVyLCBmaWcuaGVpZ2h0ID0gcGxvdF9oZWlnaHQsIGZpZy53aWR0aCA9IDguNX0KIyBDYWxjdWxhdGUgamFjY2FyZCBtYXRyaXgKc2luZ2xlcl9jZWxsYXNzaWduX21hdHJpeCA8LSBtYWtlX2phY2NhcmRfbWF0cml4KAogIGNlbGx0eXBlX2RmLAogICJzaW5nbGVyX2NlbGx0eXBlX2Fubm90YXRpb24iLAogICJjZWxsYXNzaWduX2NlbGx0eXBlX2Fubm90YXRpb24iCikKCmNyZWF0ZV9zaW5nbGVfaGVhdG1hcCgKICBzaW5nbGVyX2NlbGxhc3NpZ25fbWF0cml4LAogIHJvd190aXRsZSA9ICJDZWxsQXNzaWduIGFubm90YXRpb25zIiwKICBjb2x1bW5fdGl0bGUgPSAiU2luZ2xlUiBhbm5vdGF0aW9ucyIsCiAgbGFiZWxzX2ZvbnRfc2l6ZSA9IGZpbmRfbGFiZWxfc2l6ZShhbGxfY2VsbHR5cGVzKSwKICBrZWVwX2xlZ2VuZF9uYW1lID0gIlNpbmdsZVIgYW5ub3RhdGlvbnMiLAogIGNvbF9mdW4gPSBoZWF0bWFwX2NvbF9mdW4sCiAgIyBhZGRpdGlvbmFsIGFyZ3VtZW50cwogIGNvbHVtbl9uYW1lc19yb3QgPSA5MAopIHw+CiAgQ29tcGxleEhlYXRtYXA6OmRyYXcoCiAgICBoZWF0bWFwX2xlZ2VuZF9zaWRlID0gImJvdHRvbSIKICApCmBgYAoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIERpYWdub3N0aWMgcGxvdHMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfc2luZ2xlciB8IGhhc19jZWxsYXNzaWduIH0Ka25pdHI6OmFzaXNfb3V0cHV0KCIKIyBRdWFsaXR5IGFzc2Vzc21lbnRzIG9mIGF1dG9tYXRlZCBhbm5vdGF0aW9ucwoiKQpgYGAKCgo8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBTaW5nbGVSIGRlbHRhIG1lZGlhbiAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPgpgYGB7ciwgZXZhbCA9IGhhc19zaW5nbGVyfQprbml0cjo6YXNpc19vdXRwdXQoIgojIyBgU2luZ2xlUmAgYW5ub3RhdGlvbnMKClRvIGFzc2VzcyB0aGUgcXVhbGl0eSBvZiBgU2luZ2xlUmAgY2VsbCB0eXBlIGFubm90YXRpb25zLCB3ZSB1c2UgdGhlIGRlbHRhIG1lZGlhbiBzdGF0aXN0aWMuCgotIERlbHRhIG1lZGlhbiBpcyBjYWxjdWxhdGVkIGZvciBlYWNoIGNlbGwgYXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgYFNpbmdsZVJgIHNjb3JlIG9mIHRoZSBhbm5vdGF0ZWQgY2VsbCB0eXBlIGxhYmVsIGFuZCB0aGUgbWVkaWFuIHNjb3JlIG9mIHRoZSBvdGhlciBjZWxsIHR5cGUgbGFiZWxzIGluIHRoZSByZWZlcmVuY2UgZGF0YXNldC4KLSBIaWdoZXIgZGVsdGEgbWVkaWFuIHZhbHVlcyBpbmRpY2F0ZSBoaWdoZXIgcXVhbGl0eSBjZWxsIHR5cGUgYW5ub3RhdGlvbnMuCiAgLSBWYWx1ZXMgY2FuIHJhbmdlIGZyb20gMC0xLgogIC0gTm90ZSB0aGF0IHRoZXJlIGlzIG5vIHVuaXZlcnNhbCB0aHJlc2hvbGQgZm9yIGNhbGxpbmcgYWJzb2x1dGUgaGlnaCB2cy4gbG93IHF1YWxpdHksIGFzIGRlc2NyaWJlZCBpbiB0aGUgW2BTaW5nbGVSYCBib29rIHNlY3Rpb24gb24gJ0Fubm90YXRpb24gZGlhZ25vc3RpY3MnXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvYm9va3MvcmVsZWFzZS9TaW5nbGVSQm9vay9hbm5vdGF0aW9uLWRpYWdub3N0aWNzLmh0bWwjYW5ub3RhdGlvbi1kaWFnbm9zdGljcykuCgpZb3UgY2FuIGludGVycHJldCB0aGlzIHBsb3QgYXMgZm9sbG93czoKCi0gRWFjaCBwb2ludCByZXByZXNlbnRzIHRoZSBkZWx0YSBtZWRpYW4gc3RhdGlzdGljIG9mIGEgZ2l2ZW4gY2VsbCB3aG9zZSBgU2luZ2xlUmAgYW5ub3RhdGlvbiBpcyBzaG93biBvbiB0aGUgeS1heGlzLgotIFRoZSBwb2ludCBzdHlsZSBpbmRpY2F0ZXMgYFNpbmdsZVJgJ3MgcXVhbGl0eSBhc3Nlc3NtZW50IG9mIHRoZSBhbm5vdGF0aW9uOgogIC0gSGlnaC1xdWFsaXR5IGNlbGwgYW5ub3RhdGlvbnMgYXJlIHNob3duIGFzIGNsb3NlZCBwb2ludHMuCiAgLSBMb3ctcXVhbGl0eSBjZWxsIGFubm90YXRpb25zIGFyZSBzaG93biBhcyBvcGVuIHBvaW50cy4KICBJbiBvdGhlciBzZWN0aW9ucyBvZiB0aGlzIHJlcG9ydCwgdGhlc2UgY2VsbHMgYXJlIGxhYmVsZWQgYXMgYFVua25vd24gY2VsbCB0eXBlc2AuCiAgLSBGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBob3cgYFNpbmdsZVJgIGNhbGN1bGF0ZXMgYW5ub3RhdGlvbiBxdWFsaXR5LCBwbGVhc2UgcmVmZXIgdG8gW3RoaXMgYFNpbmdsZVJgIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vcmRyci5pby9iaW9jL1NpbmdsZVIvbWFuL3BydW5lU2NvcmVzLmh0bWwpLgotIERpYW1vbmRzIHJlcHJlc2VudCB0aGUgbWVkaWFuIG9mIHRoZSBkZWx0YSBtZWRpYW4gc3RhdGlzdGljIHNwZWNpZmljYWxseSBhbW9uZyBoaWdoLXF1YWxpdHkgYW5ub3RhdGlvbnMgZm9yIHRoZSBnaXZlbiBjZWxsIHR5cGUgYW5ub3RhdGlvbi4KIikKYGBgCgoKYGBge3IsIGV2YWwgPSBoYXNfc2luZ2xlciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBQcmVwYXJlIFNpbmdsZVIgc2NvcmVzIGZvciBwbG90CgojIGV4dHJhY3Qgc2NvcmVzIGludG8gbWF0cml4CnNpbmdsZXJfc2NvcmVzIDwtIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJHNpbmdsZXJfcmVzdWx0JHNjb3JlcwoKIyBDcmVhdGUgZGF0YSBmcmFtZSBmb3IgcGxvdHRpbmcgd2l0aCBkZWx0YSBtZWRpYW4gYW5kIHRoZSBmdWxsICpub24tcHJ1bmVkKiBjZWxsIGxhYmVscwpkZWx0YV9tZWRpYW5fZGYgPC0gdGliYmxlOjp0aWJibGUoCiAgZGVsdGFfbWVkaWFuID0gcm93TWF4cyhzaW5nbGVyX3Njb3JlcykgLSByb3dNZWRpYW5zKHNpbmdsZXJfc2NvcmVzKSwKICAjIE5lZWQgdG8gZ3JhYiB0aGUgbm9uLXBydW5lZCBsYWJlbCBmb3IgdGhpcyBwbG90CiAgZnVsbF9sYWJlbHMgPSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzaW5nbGVyX3Jlc3VsdCRsYWJlbHMsCiAgIyBpZiBwcnVuZWQubGFiZWxzIGFyZSBOQSA9PT4gbG93IGNvbmZpZGVuY2UKICAjIHNvLCBuZWdhdGUgZm9yIHRoaXMgdmFyaWFibGU6CiAgY29uZmlkZW50ID0gIWlzLm5hKG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJHNpbmdsZXJfcmVzdWx0JHBydW5lZC5sYWJlbHMpCikgfD4KICBkcGx5cjo6bXV0YXRlKAogICAgY29uZmlkZW50ID0gaWZlbHNlKGNvbmZpZGVudCwgIkhpZ2gtcXVhbGl0eSIsICJMb3ctcXVhbGl0eSIpCiAgKQoKIyBJZiBvbnRvbG9naWVzIHdlcmUgdXNlZCBmb3IgYGZ1bGxfbGFiZWxzYCwgd2UnbGwgbmVlZCB0byBtYXAgYmFjayB0byBjZWxsIHR5cGUgbmFtZXMKIyAgZm9yIHRoZSBwbG90IGl0c2VsZi4KaWYgKCJzaW5nbGVyX2NlbGx0eXBlX29udG9sb2d5IiAlaW4lIG5hbWVzKGNlbGx0eXBlX2RmKSkgewogICMgd2UgdXNlIGlubmVyX2pvaW4gYi9jIHRoZSBhYm92ZSB0aWJibGUgZG9lcyBOT1QgY29udGFpbiAiVW5rbm93biBjZWxsIHR5cGUiLCB3aGljaAogICMgIHdlIGRvIG5vdCB3YW50IHRvIGRpc3BsYXkgaGVyZQogIGRlbHRhX21lZGlhbl9kZiA8LSBkZWx0YV9tZWRpYW5fZGYgfD4KICAgIGRwbHlyOjppbm5lcl9qb2luKAogICAgICB0aWJibGU6OnRpYmJsZSgKICAgICAgICBmdWxsX2xhYmVscyA9IGNlbGx0eXBlX2RmJHNpbmdsZXJfY2VsbHR5cGVfb250b2xvZ3ksCiAgICAgICAgY2VsbHR5cGUgPSBjZWxsdHlwZV9kZiRzaW5nbGVyX2NlbGx0eXBlX2Fubm90YXRpb24KICAgICAgKSB8PiBkcGx5cjo6ZGlzdGluY3QoKQogICAgKSB8PgogICAgZHBseXI6OnNlbGVjdCgtZnVsbF9sYWJlbHMpCn0gZWxzZSB7CiAgIyBvdGhlcndpc2UsIGZ1bGxfbGFiZWxzIGFscmVhZHkgY29udGFpbiB3aGF0IHdlIHdhbnQgdG8gcGxvdCwgc28ganVzdCByZW5hbWUgaXQKICBkZWx0YV9tZWRpYW5fZGYgPC0gZGVsdGFfbWVkaWFuX2RmIHw+CiAgICBkcGx5cjo6cmVuYW1lKGNlbGx0eXBlID0gZnVsbF9sYWJlbHMpCiAgIyBzdGlsbCBuZWVkIHRvIGFkZCBsZXZlbHM6CiAgIyBOb3RlIHRoYXQgdGhlIGxldmVsICJVbmtub3duIGNlbGwgdHlwZSIgd2lsbCBzdGlsbCBiZSBwcmVzZW50LCBidXQgdGhlcmUgaXMgbm8gc3VjaCB2YWx1ZSBpbiB0aGUgZGF0YSwgc28gaXQgd29uJ3QgbWF0dGVyCiAgbGV2ZWxzKGRlbHRhX21lZGlhbl9kZiRjZWxsdHlwZSkgPC0gbGV2ZWxzKGNlbGx0eXBlX2RmJHNpbmdsZXJfY2VsbHR5cGVfYW5ub3RhdGlvbikKfQoKIyBFbnN1cmUgd2UgaGF2ZSBubyAiVW5rbm93biBjZWxsIHR5cGUiIHZhbHVlcyBsZWZ0OgppZiAoYW55KGRlbHRhX21lZGlhbl9kZiRjZWxsdHlwZSA9PSAiVW5rbm93biBjZWxsIHR5cGUiKSkgewogIHN0b3AoIkZhaWxlZCB0byBwcm9jZXNzIFNpbmdsZVIgZGF0YSBmb3IgZGlhZ25vc3RpYyBwbG90LiIpCn0KCiMgYWRkIGNvbHVtbiB3aXRoIG9yZGVyZWQgbGV2ZWxzIHdpdGggd3JhcHBlZCBsYWJlbHMgZm9yIHZpc3VhbGl6YXRpb24KZGVsdGFfbWVkaWFuX2RmJGFubm90YXRpb25fd3JhcHBlZCA8LSBmYWN0b3IoCiAgZGVsdGFfbWVkaWFuX2RmJGNlbGx0eXBlLAogICMgcmV2KCkgc28gbGFyZ2UgZ3JvdXBzIGFyZSBhdCB0aGUgVE9QIG9mIHRoZSBwbG90CiAgbGV2ZWxzID0gcmV2KGxldmVscyhkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUpKSwKICBsYWJlbHMgPSByZXYoc3RyaW5ncjo6c3RyX3dyYXAobGV2ZWxzKGRlbHRhX21lZGlhbl9kZiRjZWxsdHlwZSksIDMwKSkKKQoKIyBTdWJzZXQgdGhlIGRhdGEgdG8ganVzdCBjb25maWRlbnQgcG9pbnRzIGZvciBtZWRpYW4rLy1JUVIKZGVsdGFfbWVkaWFuX2NvbmZpZGVudF9kZiA8LSBkZWx0YV9tZWRpYW5fZGYgfD4KICBkcGx5cjo6ZmlsdGVyKGNvbmZpZGVudCA9PSAiSGlnaC1xdWFsaXR5IikKCiMgRGV0ZXJtaW5lIGhlaWdodCBmb3IgcGxvdCBhcmVhIGJhc2VkIG9uIG51bWJlciBvZiBjZWxscwpwbG90X2hlaWdodCA8LSBsZW5ndGgodW5pcXVlKGRlbHRhX21lZGlhbl9kZiRjZWxsdHlwZSkpIC8gMi41CmBgYAoKYGBge3IsIGV2YWwgPSBoYXNfc2luZ2xlciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLmhlaWdodCA9IHBsb3RfaGVpZ2h0LCBmaWcud2lkdGggPSA4fQojIFBsb3QgZGVsdGFfbWVkaWFuIGFjcm9zcyBjZWxsdHlwZXMgY29sb3JlZCBieSBwcnVuaW5nCmdncGxvdChkZWx0YV9tZWRpYW5fZGYpICsKICBhZXMoCiAgICB4ID0gZGVsdGFfbWVkaWFuLAogICAgeSA9IGFubm90YXRpb25fd3JhcHBlZCwKICAgIHNoYXBlID0gY29uZmlkZW50LAogICAgYWxwaGEgPSBjb25maWRlbnQKICApICsKICBnZ2ZvcmNlOjpnZW9tX3NpbmEoCiAgICBzaXplID0gMC44LAogICAgY29sb3IgPSAiYmxhY2siLCAjIHdpbGwgZ2V0IGFwcGxpZWQgdG8gYWxsIGNvbmZpZGVudCBwb2ludHMgYW5kIG5vbi1jb25maWRlbnQgb3V0bGluZQogICAgZmlsbCA9ICJ3aGl0ZSIsICMgd2lsbCBhcHBseSB0byBub24tY29uZmlkZW50IGZpbGwgb25seQogICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMDUpICMgS2VlcCBib3RoIHR5cGVzIG9mIHBvaW50cyBtb3N0bHkgaW4gbGluZQogICkgKwogICMgSGFuZGxlIHBvaW50cyBhZXN0aGV0aWNzOgogICMgIGNvbmZpZGVudCBhcmUgY2xvc2VkIGJsYWNrIHdpdGggYWxwaGEgPSAwLjUKICAjICBub3QgY29uZmlkZW50IGFyZSBvcGVuIGJsYWNrIHdpdGggYWxwaGEgPSAxCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMTksIDIxKSkgKwogIHNjYWxlX2FscGhhX21hbnVhbCh2YWx1ZXMgPSBjKDAuNSwgMSkpICsKICBsYWJzKAogICAgeCA9ICJEZWx0YSBtZWRpYW4gc3RhdGlzdGljIiwKICAgIHkgPSAiQ2VsbCB0eXBlIGFubm90YXRpb24iLAogICAgc2hhcGUgPSAiQ2VsbCB0eXBlIGFubm90YXRpb24gcXVhbGl0eSIKICApICsKICAjIGFkZCBtZWRpYW4gZGlhbW9uZCBmb3IgY29uZmlkZW50IHBvaW50cyBvbmx5CiAgc3RhdF9zdW1tYXJ5KAogICAgZGF0YSA9IGRlbHRhX21lZGlhbl9jb25maWRlbnRfZGYsCiAgICBjb2xvciA9ICJyZWQiLAogICAgZ2VvbSA9ICJwb2ludCIsCiAgICBmdW4gPSAibWVkaWFuIiwKICAgIHNoYXBlID0gMTgsCiAgICBzaXplID0gMi4yNSwKICAgIGFscGhhID0gMC45CiAgKSArCiAgZ3VpZGVzKAogICAgYWxwaGEgPSBGQUxTRSwKICAgIHNoYXBlID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDEuNSwgYWxwaGEgPSAwLjU1KSkKICApICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iCiAgKQpgYGAKCgo8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gQ2VsbEFzc2lnbiBwcm9iYWJpbGl0eSBwbG90ICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPgpgYGB7ciwgZXZhbCA9IGhhc19jZWxsYXNzaWdufQprbml0cjo6YXNpc19vdXRwdXQoIgojIyBgQ2VsbEFzc2lnbmAgYW5ub3RhdGlvbnMKClRvIGFzc2VzcyB0aGUgcXVhbGl0eSBvZiBgQ2VsbEFzc2lnbmAgY2VsbCB0eXBlIGFubm90YXRpb25zLCB3ZSBjb25zaWRlciB0aGUgcHJvYmFiaWxpdHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBhbm5vdGF0ZWQgY2VsbCB0eXBlLgpUaGVzZSBwcm9iYWJpbGl0aWVzIGFyZSBwcm92aWRlZCBkaXJlY3RseSBieSBgQ2VsbEFzc2lnbmA6CgotIGBDZWxsQXNzaWduYCBmaXJzdCBjYWxjdWxhdGVzIHRoZSBwcm9iYWJpbGl0eSBvZiBlYWNoIGNlbGwgYmVpbmcgYW5ub3RhdGVkIGFzIGVhY2ggY2VsbCB0eXBlIHByZXNlbnQgaW4gdGhlIHJlZmVyZW5jZS4KLSBgQ2VsbEFzc2lnbmAgdGhlbiBhbm5vdGF0ZXMgY2VsbHMgYnkgc2VsZWN0aW5nIHRoZSBjZWxsIHR5cGUgd2l0aCB0aGUgaGlnaGVzdCBwcm9iYWJpbGl0eSBhbW9uZyBhbGwgY2VsbCB0eXBlcyBjb25zaWRlcmVkLgotIFRoZXNlIHByb2JhYmlsaXRpZXMgcmFuZ2UgZnJvbSAwIHRvIDEsIHdpdGggbGFyZ2VyIHZhbHVlcyBpbmRpY2F0aW5nIGdyZWF0ZXIgY29uZmlkZW5jZSBpbiBhIGdpdmVuIGNlbGwgdHlwZSBsYWJlbC4KV2UgdGhlcmVmb3JlIGV4cGVjdCByZWxpYWJsZSBsYWJlbHMgdG8gaGF2ZSB2YWx1ZXMgY2xvc2UgdG8gMS4KClRoZSBwbG90IGJlbG93IHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgYENlbGxBc3NpZ25gLWNhbGN1bGF0ZWQgcHJvYmFiaWxpdGllcyBmb3IgdGhlIGZpbmFsIGNlbGwgdHlwZSBsYWJlbHMuCkxpbmUgc2VnbWVudHMgcmVwcmVzZW50IGluZGl2aWR1YWwgdmFsdWVzIHRoYXQgY29tcHJpc2UgZWFjaCBkaXN0cmlidXRpb24uCgpGb3IgY2VsbCB0eXBlcyB3aXRoIDIgb3IgZmV3ZXIgbGFiZWxlZCBjZWxscywgb25seSB0aGUgaW5kaXZpZHVhbCB2YWx1ZSBsaW5lIHNlZ21lbnRzIGFyZSBzaG93bi4KTGluZSBzZWdtZW50cyBhcmUgYWxzbyB0YWxsZXIgZm9yIGFueSBjZWxsIHR5cGUgbGFiZWwgd2l0aCA1IG9yIGZld2VyIGNlbGxzLgoiKQoKIyBEZXRlcm1pbmUgaGVpZ2h0IGluIGluY2hlcyBmb3IgcGxvdCBhcmVhCnBsb3RfaGVpZ2h0IDwtIGNlaWxpbmcobGVuZ3RoKHVuaXF1ZShjZWxsdHlwZV9kZiRjZWxsYXNzaWduX2NlbGx0eXBlX2Fubm90YXRpb24pKSAvIDIuNSkKYGBgCgoKYGBge3IsIGV2YWwgPSBoYXNfY2VsbGFzc2lnbiwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLmhlaWdodCA9IHBsb3RfaGVpZ2h0LCBmaWcud2lkdGggPSA4fQojIGRlZmluZSBiYW5kd2lkdGggZm9yIGFsbCBjYWxjdWxhdGlvbnMKZGVuc2l0eV9idyA8LSAwLjAzCgojIGZpbmQgdGhlIG1heGltdW0gZGVuc2l0eSBhY3Jvc3MgYWxsIGRpc3RyaWJ1dGlvbnMsIGFuZAojICBzYXZlIHRoZSBtYXhpbXVtIGZvciBkZXRlcm1pbmluZyBnZW9tX3NlZ21lbnQgaGVpZ2h0CnlfbWF4IDwtIGNlbGx0eXBlX2RmJGNlbGxhc3NpZ25fbWF4X3ByZWRpY3Rpb24gfD4KICBzcGxpdChjZWxsdHlwZV9kZiRjZWxsYXNzaWduX2NlbGx0eXBlX2Fubm90YXRpb24pIHw+CiAgIyBtYWtlIHN1cmUgd2UgZ2V0IHJpZCBvZiBhbnkgc21hbGwgZ3JvdXBzCiAgcHVycnI6OmRpc2NhcmQoXCh4KSBzdW0oaXMuZmluaXRlKHgpKSA8PSAyKSB8PgogICMgcmVtb3ZlIGFueSBOQSdzIHRoYXQgbWF5IGhhdmUgc2xpcHBlZCBpbgogIHB1cnJyOjptYXBfZGJsKAogICAgXCh4KSBtYXgoZGVuc2l0eSh4LCBidyA9IGRlbnNpdHlfYncsIG5hLnJtID0gVFJVRSkkeSkKICApIHw+CiAgbWF4KG5hLnJtID0gVFJVRSkKCiMgYWRkIGNvdW50IHRvIGNlbGx0eXBlX2RmIGZvciBzZXR0aW5nIGFscGhhIGFuZCB5ZW5kIHZhbHVlcwpjZWxsdHlwZV9kZiA8LSBjZWxsdHlwZV9kZiB8PgogIGRwbHlyOjphZGRfY291bnQoY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uKQoKIyBtYWtlIHRoZSBwbG90IQpnZ3Bsb3QoY2VsbHR5cGVfZGYpICsKICBhZXMoeCA9IGNlbGxhc3NpZ25fbWF4X3ByZWRpY3Rpb24pICsKICBnZW9tX2RlbnNpdHkoCiAgICBidyA9IGRlbnNpdHlfYncsCiAgICBmaWxsID0gImdyZXk2NSIsCiAgICBsaW5ld2lkdGggPSAwLjI1LAogICAgYm91bmRzID0gYygwLCAxKQogICkgKwogIGdlb21fc2VnbWVudCgKICAgIGFlcygKICAgICAgIyBzZXQgYWxwaGEgdG8gdmFyeSBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHBvaW50cyBpbiB0aGUgcm93IHN1Y2ggdGhhdAogICAgICAjICByb3dzIHdpdGggbW9yZSBwb2ludHMgYXJlIG1vcmUgdHJhbnNwYXJlbnQKICAgICAgYWxwaGEgPSBwbWF4KDAuMiwgMSAtIDAuMDEgKiBuKSwKICAgICAgeGVuZCA9IGNlbGxhc3NpZ25fbWF4X3ByZWRpY3Rpb24sCiAgICAgICMgc2V0IHllbmQgYXMgZWl0aGVyIDAgZm9yIHJvd3Mgd2l0aCBtYW55IHBvaW50cywgb3IgeV9tYXgvMi41IGZvcgogICAgICAjICByb3dzIHdpdGggZmV3IHBvaW50cwogICAgICB5ZW5kID0gaWZlbHNlKG4gPiA1LCAwLCB5X21heCAvIDIuNSksCiAgICAgIHkgPSAtSW5mCiAgICApLAogICAgY29sb3IgPSAiYmx1ZSIKICApICsKICBsYWJzKAogICAgeCA9ICJQcm9iYWJpbGl0eSBvZiBhbm5vdGF0ZWQgY2VsbCB0eXBlIiwKICAgIHkgPSAiQ2VsbCB0eXBlIGFubm90YXRpb24iCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLjEsIDAuMSkpICsKICBzY2FsZV9hbHBoYV9pZGVudGl0eSgpICsKICBmYWNldF9ncmlkKAogICAgcm93cyA9IHZhcnMoY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uKSwKICAgIHN3aXRjaCA9ICJ5IgogICkgKwogIHRoZW1lKAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQueS5sZWZ0ID0gZWxlbWVudF90ZXh0KAogICAgICBhbmdsZSA9IDAsCiAgICAgIGhqdXN0ID0gMQogICAgKSwKICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuMDIsICJpbiIpCiAgKQpgYGAKCgojIFNlc3Npb24gSW5mbwo8ZGV0YWlscz4KPHN1bW1hcnk+UiBzZXNzaW9uIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgpgYGB7ciBzZXNzaW9uX2luZm99CmlmIChyZXF1aXJlTmFtZXNwYWNlKCJzZXNzaW9uaW5mbyIsIHF1aWV0bHkgPSBUUlVFKSkgewogIHNlc3Npb25pbmZvOjpzZXNzaW9uX2luZm8oKQp9IGVsc2UgewogIHNlc3Npb25JbmZvKCkKfQpgYGAKPC9kZXRhaWxzPgo=