This report contains a summary of cell type annotation results for library SCPCL000001. 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. Please note that all cell type annotation reference datasets are derived from normal (not tumor) tissue.
This library contains the following cell type annotations:
- 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 brain-compartment
. This reference includes the following organs and tissue compartments: brain, embryo, immune system, and vasculature.
Cell type Annotation Summary
The plots and tables included here detail the results from performing cell type annotation.
Statistics
When reprocessing this library, old results from running SingleR and CellAssign were used. This means results were calculated with a slightly different set of cells. Any cells that are missing have been annotated as Unclassified cell
in the object and will not be shown in any plots.
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
|
neuron
|
2315
|
88.19%
|
macrophage
|
196
|
7.47%
|
monocyte
|
12
|
0.46%
|
effector memory CD8-positive, alpha-beta T cell
|
11
|
0.42%
|
CD4-positive, alpha-beta T cell
|
10
|
0.38%
|
mesangial cell
|
8
|
0.3%
|
fat cell
|
6
|
0.23%
|
central memory CD8-positive, alpha-beta T cell
|
5
|
0.19%
|
naive B cell
|
5
|
0.19%
|
central memory CD4-positive, alpha-beta T cell
|
4
|
0.15%
|
chondrocyte
|
4
|
0.15%
|
melanocyte
|
4
|
0.15%
|
natural killer cell
|
4
|
0.15%
|
class switched memory B cell
|
3
|
0.11%
|
erythrocyte
|
3
|
0.11%
|
astrocyte
|
2
|
0.08%
|
CD8-positive, alpha-beta T cell
|
1
|
0.04%
|
common lymphoid progenitor
|
1
|
0.04%
|
granulocyte monocyte progenitor cell
|
1
|
0.04%
|
hematopoietic stem cell
|
1
|
0.04%
|
muscle cell
|
1
|
0.04%
|
plasma cell
|
1
|
0.04%
|
Unknown cell type
|
27
|
1.03%
|
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
|
Purkinje neurons
|
1872
|
71.31%
|
Microglia
|
200
|
7.62%
|
Gamma delta T cells
|
111
|
4.23%
|
T memory cells
|
25
|
0.95%
|
Oligodendrocytes
|
15
|
0.57%
|
Dendritic cells
|
13
|
0.5%
|
B cells
|
12
|
0.46%
|
Satellite glial cells
|
11
|
0.42%
|
Schwann cells
|
8
|
0.3%
|
Meningeal cells
|
7
|
0.27%
|
T cells
|
7
|
0.27%
|
NK cells
|
6
|
0.23%
|
Astrocytes
|
4
|
0.15%
|
Macrophages
|
4
|
0.15%
|
Megakaryocytes
|
3
|
0.11%
|
Monocytes
|
3
|
0.11%
|
Neural stem/precursor cells
|
3
|
0.11%
|
Tanycytes
|
3
|
0.11%
|
Endothelial cells
|
2
|
0.08%
|
Natural killer T cells
|
2
|
0.08%
|
Neutrophils
|
2
|
0.08%
|
Nuocytes
|
2
|
0.08%
|
Choroid plexus cells
|
1
|
0.04%
|
Dopaminergic neurons
|
1
|
0.04%
|
Endothelial cells (blood brain barrier)
|
1
|
0.04%
|
Epiblast cells
|
1
|
0.04%
|
GABAergic neurons
|
1
|
0.04%
|
Oligodendrocyte progenitor cells
|
1
|
0.04%
|
Serotonergic neurons
|
1
|
0.04%
|
Trophoblast cells
|
1
|
0.04%
|
Unknown cell type
|
302
|
11.5%
|
UMAPs
In this section, we show UMAPs colored by clusters. Clusters were calculated using the graph-based Louvain algorithm with Jaccard weighting.

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.

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.2 (2023-10-31)
## os Ubuntu 22.04.3 LTS
## system x86_64, linux-gnu
## ui X11
## language (EN)
## collate en_US.UTF-8
## ctype en_US.UTF-8
## tz Etc/UTC
## date 2024-03-18
## pandoc 2.9.2.1 @ /usr/bin/ (via rmarkdown)
##
## ─ Packages ───────────────────────────────────────────────────────────────────
## package * version date (UTC) lib source
## abind 1.4-5 2016-07-21 [1] RSPM (R 4.3.0)
## beachmat 2.16.0 2023-04-25 [1] Bioconductor
## beeswarm 0.4.0 2021-06-01 [1] RSPM (R 4.3.0)
## Biobase * 2.60.0 2023-04-25 [1] Bioconductor
## BiocGenerics * 0.46.0 2023-04-25 [1] Bioconductor
## BiocNeighbors 1.18.0 2023-04-25 [1] Bioconductor
## BiocParallel 1.34.2 2023-05-22 [1] Bioconductor
## BiocSingular 1.16.0 2023-04-25 [1] Bioconductor
## bitops 1.0-7 2021-04-24 [1] RSPM (R 4.3.0)
## bluster 1.10.0 2023-04-25 [1] Bioconductor
## bslib 0.5.1 2023-08-11 [1] RSPM (R 4.3.0)
## cachem 1.0.8 2023-05-01 [1] RSPM (R 4.3.0)
## Cairo 1.6-1 2023-08-18 [1] RSPM (R 4.3.0)
## circlize 0.4.15 2022-05-10 [1] RSPM (R 4.3.0)
## cli 3.6.1 2023-03-23 [1] RSPM (R 4.3.0)
## clue 0.3-65 2023-09-23 [1] RSPM (R 4.3.0)
## cluster 2.1.4 2022-08-22 [2] CRAN (R 4.3.2)
## codetools 0.2-19 2023-02-01 [2] CRAN (R 4.3.2)
## colorspace 2.1-0 2023-01-23 [1] RSPM (R 4.3.0)
## ComplexHeatmap 2.16.0 2023-04-25 [1] Bioconductor
## cowplot 1.1.1 2020-12-30 [1] RSPM (R 4.3.0)
## crayon 1.5.2 2022-09-29 [1] RSPM (R 4.3.0)
## DelayedArray 0.26.7 2023-07-28 [1] Bioconductor
## DelayedMatrixStats 1.22.6 2023-08-28 [1] Bioconductor
## digest 0.6.33 2023-07-07 [1] RSPM (R 4.3.0)
## doParallel 1.0.17 2022-02-07 [1] RSPM (R 4.3.0)
## dplyr * 1.1.4 2023-11-17 [1] RSPM (R 4.3.0)
## dqrng 0.3.1 2023-08-30 [1] RSPM (R 4.3.0)
## edgeR 3.42.4 2023-05-31 [1] Bioconductor
## evaluate 0.23 2023-11-01 [1] RSPM (R 4.3.0)
## fansi 1.0.5 2023-10-08 [1] RSPM (R 4.3.0)
## farver 2.1.1 2022-07-06 [1] RSPM (R 4.3.0)
## fastmap 1.1.1 2023-02-24 [1] RSPM (R 4.3.0)
## flexmix 2.3-19 2023-03-16 [1] RSPM (R 4.3.0)
## forcats 1.0.0 2023-01-29 [1] RSPM (R 4.3.0)
## foreach 1.5.2 2022-02-02 [1] RSPM (R 4.3.0)
## generics 0.1.3 2022-07-05 [1] RSPM (R 4.3.0)
## GenomeInfoDb * 1.36.4 2023-10-02 [1] Bioconductor
## GenomeInfoDbData 1.2.10 2024-03-08 [1] Bioconductor
## GenomicRanges * 1.52.1 2023-10-08 [1] Bioconductor
## getopt 1.20.4 2023-10-01 [1] RSPM (R 4.3.0)
## GetoptLong 1.0.5 2020-12-15 [1] RSPM (R 4.3.0)
## ggbeeswarm 0.7.2 2023-04-29 [1] RSPM (R 4.3.0)
## ggforce 0.4.1 2022-10-04 [1] RSPM (R 4.3.0)
## ggplot2 * 3.4.4 2023-10-12 [1] RSPM (R 4.3.0)
## ggrepel 0.9.4 2023-10-13 [1] RSPM (R 4.3.0)
## GlobalOptions 0.1.2 2020-06-10 [1] RSPM (R 4.3.0)
## glue 1.6.2 2022-02-24 [1] RSPM (R 4.3.0)
## gridExtra 2.3 2017-09-09 [1] RSPM (R 4.3.0)
## gtable 0.3.4 2023-08-21 [1] RSPM (R 4.3.0)
## highr 0.10 2022-12-22 [1] RSPM (R 4.3.0)
## hms 1.1.3 2023-03-21 [1] RSPM (R 4.3.0)
## htmltools 0.5.7 2023-11-03 [1] RSPM (R 4.3.0)
## httr 1.4.7 2023-08-15 [1] RSPM (R 4.3.0)
## igraph 1.5.1 2023-08-10 [1] RSPM (R 4.3.0)
## IRanges * 2.34.1 2023-06-22 [1] Bioconductor
## irlba 2.3.5.1 2022-10-03 [1] RSPM (R 4.3.0)
## iterators 1.0.14 2022-02-05 [1] RSPM (R 4.3.0)
## jquerylib 0.1.4 2021-04-26 [1] RSPM (R 4.3.0)
## jsonlite 1.8.7 2023-06-29 [1] RSPM (R 4.3.0)
## kableExtra 1.3.4 2021-02-20 [1] RSPM (R 4.3.0)
## knitr 1.45 2023-10-30 [1] RSPM (R 4.3.0)
## labeling 0.4.3 2023-08-29 [1] RSPM (R 4.3.0)
## lattice 0.22-5 2023-10-24 [1] RSPM (R 4.3.0)
## lifecycle 1.0.4 2023-11-07 [1] RSPM (R 4.3.0)
## limma 3.56.2 2023-06-04 [1] Bioconductor
## locfit 1.5-9.8 2023-06-11 [1] RSPM (R 4.3.0)
## lubridate 1.9.3 2023-09-27 [1] RSPM (R 4.3.0)
## magrittr 2.0.3 2022-03-30 [1] RSPM (R 4.3.0)
## MASS 7.3-60 2023-05-04 [2] CRAN (R 4.3.2)
## Matrix 1.6-3 2023-11-14 [1] RSPM (R 4.3.0)
## MatrixGenerics * 1.12.3 2023-07-30 [1] Bioconductor
## matrixStats * 1.1.0 2023-11-07 [1] RSPM (R 4.3.0)
## metapod 1.8.0 2023-04-25 [1] Bioconductor
## miQC 1.8.0 2023-04-27 [1] Bioconductor
## modeltools 0.2-23 2020-03-05 [1] RSPM (R 4.3.0)
## munsell 0.5.0 2018-06-12 [1] RSPM (R 4.3.0)
## nnet 7.3-19 2023-05-03 [2] CRAN (R 4.3.2)
## optparse * 1.7.3 2022-07-20 [1] RSPM (R 4.3.0)
## pillar 1.9.0 2023-03-22 [1] RSPM (R 4.3.0)
## pkgconfig 2.0.3 2019-09-22 [1] RSPM (R 4.3.0)
## png 0.1-8 2022-11-29 [1] RSPM (R 4.3.0)
## polyclip 1.10-6 2023-09-27 [1] RSPM (R 4.3.0)
## purrr 1.0.2 2023-08-10 [1] RSPM (R 4.3.0)
## R6 2.5.1 2021-08-19 [1] RSPM (R 4.3.0)
## RColorBrewer 1.1-3 2022-04-03 [1] RSPM (R 4.3.0)
## Rcpp 1.0.11 2023-07-06 [1] RSPM (R 4.3.0)
## RCurl 1.98-1.13 2023-11-02 [1] RSPM (R 4.3.0)
## readr 2.1.4 2023-02-10 [1] RSPM (R 4.3.0)
## rjson 0.2.21 2022-01-09 [1] RSPM (R 4.3.0)
## rlang 1.1.2 2023-11-04 [1] RSPM (R 4.3.0)
## rmarkdown 2.25 2023-09-18 [1] RSPM (R 4.3.0)
## rstudioapi 0.15.0 2023-07-07 [1] RSPM (R 4.3.0)
## rsvd 1.0.5 2021-04-16 [1] RSPM (R 4.3.0)
## rvest 1.0.3 2022-08-19 [1] RSPM (R 4.3.0)
## S4Arrays 1.0.6 2023-08-30 [1] Bioconductor
## S4Vectors * 0.38.2 2023-09-22 [1] Bioconductor
## sass 0.4.7 2023-07-15 [1] RSPM (R 4.3.0)
## ScaledMatrix 1.8.1 2023-05-03 [1] Bioconductor
## scales 1.2.1 2022-08-20 [1] RSPM (R 4.3.0)
## scater 1.28.0 2023-04-25 [1] Bioconductor
## scpcaTools 0.3.2 2024-03-12 [1] Github (AlexsLemonade/scpcaTools@20c9029)
## scran 1.28.2 2023-07-23 [1] Bioconductor
## scuttle 1.10.3 2023-10-10 [1] Bioconductor
## sessioninfo 1.2.2 2021-12-06 [1] RSPM (R 4.3.0)
## shape 1.4.6 2021-05-19 [1] RSPM (R 4.3.0)
## SingleCellExperiment * 1.22.0 2023-04-25 [1] Bioconductor
## sparseMatrixStats 1.12.2 2023-07-02 [1] Bioconductor
## statmod 1.5.0 2023-01-06 [1] RSPM (R 4.3.0)
## stringi 1.8.1 2023-11-13 [1] RSPM (R 4.3.0)
## stringr 1.5.1 2023-11-14 [1] RSPM (R 4.3.0)
## SummarizedExperiment * 1.30.2 2023-06-06 [1] Bioconductor
## svglite 2.1.2 2023-10-11 [1] RSPM (R 4.3.0)
## systemfonts 1.0.5 2023-10-09 [1] RSPM (R 4.3.0)
## tibble 3.2.1 2023-03-20 [1] RSPM (R 4.3.0)
## tidyr 1.3.0 2023-01-24 [1] RSPM (R 4.3.0)
## tidyselect 1.2.0 2022-10-10 [1] RSPM (R 4.3.0)
## timechange 0.2.0 2023-01-11 [1] RSPM (R 4.3.0)
## tweenr 2.0.2 2022-09-06 [1] RSPM (R 4.3.0)
## tzdb 0.4.0 2023-05-12 [1] RSPM (R 4.3.0)
## utf8 1.2.4 2023-10-22 [1] RSPM (R 4.3.0)
## vctrs 0.6.4 2023-10-12 [1] RSPM (R 4.3.0)
## vipor 0.4.5 2017-03-22 [1] RSPM (R 4.3.0)
## viridis 0.6.4 2023-07-22 [1] RSPM (R 4.3.0)
## viridisLite 0.4.2 2023-05-02 [1] RSPM (R 4.3.0)
## webshot 0.5.5 2023-06-26 [1] RSPM (R 4.3.0)
## withr 2.5.2 2023-10-30 [1] RSPM (R 4.3.0)
## xfun 0.41 2023-11-01 [1] RSPM (R 4.3.0)
## xml2 1.3.5 2023-07-06 [1] RSPM (R 4.3.0)
## XVector 0.40.0 2023-04-25 [1] Bioconductor
## yaml 2.3.7 2023-01-23 [1] RSPM (R 4.3.0)
## zlibbioc 1.46.0 2023-04-25 [1] Bioconductor
##
## [1] /usr/local/lib/R/site-library
## [2] /usr/local/lib/R/library
##
## ──────────────────────────────────────────────────────────────────────────────
LS0tCnBhcmFtczoKICBsaWJyYXJ5OiBFeGFtcGxlCiAgcHJvY2Vzc2VkX3NjZTogTlVMTAogIGRhdGU6ICFyIFN5cy5EYXRlKCkKdGl0bGU6ICJgciBnbHVlOjpnbHVlKCdTY1BDQSBTdXBwbGVtZW50YWwgY2VsbCB0eXBlIHJlcG9ydCBmb3Ige3BhcmFtcyRsaWJyYXJ5fScpYCIKYXV0aG9yOiAiQ2hpbGRob29kIENhbmNlciBEYXRhIExhYiIKZGF0ZTogImByIHBhcmFtcyRkYXRlYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIG1lc3NhZ2UgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQojIGtuaXRyIG9wdGlvbnMKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBGQUxTRQopCgpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQpsaWJyYXJ5KGdncGxvdDIpCgojIFNldCBkZWZhdWx0IGdncGxvdCB0aGVtZQp0aGVtZV9zZXQoCiAgdGhlbWVfYncoKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ocmVwKDIwLCA0KSksCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpCiAgICApCikKCiMgVGhpcyBfaXNfIHRoZSBzdXBwbGVtZW50YWwgcmVwb3J0CiMgd2Ugc2hvdWxkIG5vdCBwcmludCB0aGUgY2h1bmsgZnJvbSBjZWxsdHlwZXNfcWMucm1kIHJlY2FwaXR1bGF0aW5nIGJ1bGxldHMKIyAgYW5kIHBvaW50aW5nIHVzZXJzIHRvIHRoaXMgc3VwcCByZXBvcnQKaXNfc3VwcGxlbWVudGFsIDwtIFRSVUUKYGBgCgo8IS0tIEltcG9ydCBzaGFyZWQgZnVuY3Rpb25zIGZvciBjZWxsIHR5cGUgd3JhbmdsaW5nIC0tPgpgYGB7ciwgY2hpbGQ9J3V0aWxzL2NlbGx0eXBlX2Z1bmN0aW9ucy5ybWQnfQpgYGAKYGBge3IsIGNoaWxkPSd1dGlscy9yZXBvcnRfZnVuY3Rpb25zLnJtZCd9CmBgYAoKCjwhLS0gRGVmaW5lIGhlbHBlciBmdW5jdGlvbnMgZm9yIGNhbGN1bGF0aW5nIEphY2NhcmQgbWF0cmljZXMgLS0+CmBgYHtyfQojJyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgSmFjY2FyZCBzaW1pbGFyaXR5IG9uIHR3byB2ZWN0b3JzCiMnCiMnIEBwYXJhbSB2ZWMxIEZpcnN0IHZlY3RvcgojJyBAcGFyYW0gdmVjMiBTZWNvbmQgdmVjdG9yCiMnCiMnIEByZXR1cm4gSmFjY2FyZCBzaW1pbGFyaXR5IGJldHdlZW4gdGhlIHZlY3RvcnMKamFjY2FyZCA8LSBmdW5jdGlvbih2ZWMxLCB2ZWMyKSB7CiAgbGVuZ3RoKGludGVyc2VjdCh2ZWMxLCB2ZWMyKSkgLyBsZW5ndGgodW5pb24odmVjMSwgdmVjMikpCn0KCgojIFdyYXBwZXIgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIGphY2NhcmQgc2ltaWxhcml0eSBtYXRyaXggZm9yIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKIycKIycgQHBhcmFtIGNlbGx0eXBlX2RmIFRoZSBjZWxsdHlwZV9kZiBkYXRhIGZyYW1lIHdoaWNoIG11c3QgY29udGFpbiB0aGVzZSBjb2x1bW5zOgojJyAgIGBjb2xuYW1lMWAsIGBjb2xuYW1lMmAsIGFuZCBgYmFyY29kZXNgCiMnIEBwYXJhbSBjb2xuYW1lMSBDb2x1bW4gbmFtZSwgYXMgYSBzdHJpbmcsIG9mIGZpcnN0IGNhdGVnb3JpY2FsIHZhcmlhYmxlIG9mIGludGVyZXN0CiMnIEBwYXJhbSBjb2xuYW1lMiBDb2x1bW4gbmFtZSwgYXMgYSBzdHJpbmcsIG9mIHNlY29uZCBjYXRlZ29yaWNhbCB2YXJpYWJsZSBvZiBpbnRlcmVzdAojJwojJyBAcmV0dXJuIEphY2NhcmQgc2ltaWxhcml0eSBtYXRyaXggZm9yIHRoZSB0d28gY29sdW1ucy4gYGNvbG5hbWUxYCB2YWx1ZXMgd2lsbAojJyAgIGJlIHJvdyBuYW1lcyBhbmQgYGNvbG5hbWUyYCB2YWx1ZXMgd2lsbCBiZSBjb2x1bW4gbmFtZXMgaW4gdGhlIGZpbmFsIG1hdHJpeAptYWtlX2phY2NhcmRfbWF0cml4IDwtIGZ1bmN0aW9uKGNlbGx0eXBlX2RmLCBjb2xuYW1lMSwgY29sbmFtZTIpIHsKICAjIG1ha2UgbGlzdHMgb2YgYmFyY29kZXMgZm9yIGVhY2ggY2F0ZWdvcnksIG5hbWVkIGJ5IHRoZSBjYXRlZ29yeQogIGlkMV9saXN0IDwtIHNwbGl0KGNlbGx0eXBlX2RmJGJhcmNvZGVzLCBjZWxsdHlwZV9kZltbY29sbmFtZTFdXSkKICBpZDJfbGlzdCA8LSBzcGxpdChjZWxsdHlwZV9kZiRiYXJjb2RlcywgY2VsbHR5cGVfZGZbW2NvbG5hbWUyXV0pCgogICMgY3JlYXRlIHRoZSBncmlkIG9mIGNvbXBhcmlzb25zCiAgY3Jvc3NfZGYgPC0gdGlkeXI6OmV4cGFuZF9ncmlkKGlkMSA9IG5hbWVzKGlkMV9saXN0KSwgaWQyID0gbmFtZXMoaWQyX2xpc3QpKQoKICAjIGNhbGN1bGF0ZSBhIHNpbmdsZSBKYWNjYXJkIGluZGV4IGZvciBlYWNoIGNvbWJpbmF0aW9uIHVzaW5nIHNwbGl0IGxpc3RzICYgaWRzCiAgamFjY2FyZF9zY29yZXMgPC0gY3Jvc3NfZGYgfD4KICAgIHB1cnJyOjpwbWFwX2RibChcKGlkMSwgaWQyKXsKICAgICAgamFjY2FyZChpZDFfbGlzdFtbaWQxXV0sIGlkMl9saXN0W1tpZDJdXSkKICAgIH0pCgogICMgYWRkIHNjb3JlcyB0byB0aGUgY29tcGFyaXNvbiBncmlkIGFuZCBjb252ZXJ0IHRvIG1hdHJpeAogIGphY2NhcmRfbWF0cml4IDwtIGNyb3NzX2RmIHw+CiAgICBkcGx5cjo6bXV0YXRlKGphY2NhcmQgPSBqYWNjYXJkX3Njb3JlcykgfD4KICAgICMgY29udmVydCB0byBtYXRyaXgKICAgIHRpZHlyOjpwaXZvdF93aWRlcigKICAgICAgbmFtZXNfZnJvbSA9ICJpZDIiLAogICAgICB2YWx1ZXNfZnJvbSA9ICJqYWNjYXJkIgogICAgKSB8PgogICAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXModmFyID0gImlkMSIpIHw+CiAgICBhcy5tYXRyaXgoKQoKICByZXR1cm4oamFjY2FyZF9tYXRyaXgpCn0KYGBgCgoKPCEtLSBEZWZpbmUgdmFyaWFibGVzLCBvcHRpb25zLCBhbmQgZnVuY3Rpb25zIGZvciBwbG90dGluZyBoZWF0bWFwcyAtLT4KYGBge3J9CiMgRGVmaW5lIGNvbG9yIHJhbXAgZm9yIHNoYXJlZCB1c2UgaW4gdGhlIGhlYXRtYXAKaGVhdG1hcF9jb2xfZnVuIDwtIGNpcmNsaXplOjpjb2xvclJhbXAyKGMoMCwgMSksIGNvbG9ycyA9IGMoIndoaXRlIiwgImRhcmtzbGF0ZWJsdWUiKSkKCiMgU2V0IGhlYXRtYXAgcGFkZGluZyBvcHRpb24KaGVhdG1hcF9wYWRkaW5nIDwtIDAuMgpDb21wbGV4SGVhdG1hcDo6aHRfb3B0KFRJVExFX1BBRERJTkcgPSBncmlkOjp1bml0KGhlYXRtYXBfcGFkZGluZywgImluIikpCgojJyBDcmVhdGUgYSBDb21wbGV4SGVhdG1hcCBmcm9tIGEgbWF0cml4CiMnCiMnIEBwYXJhbSBtYXQgTWF0cml4IHRvIGNyZWF0ZSBoZWF0bWFwIGZyb20uCiMnIEBwYXJhbSByb3dfdGl0bGUgTGFiZWwgZm9yIHJvdyB0aXRsZS4KIycgQHBhcmFtIGNvbHVtbl90aXRsZSBMYWJlbCBmb3IgY29sdW1uIHRpdGxlLgojJyBAcGFyYW0gbGFiZWxzX2ZvbnRfc2l6ZSBGb250IHNpemUgdG8gdXNlIGZvciByb3dzIGFuZCBjb2x1bW4gbGFiZWxzLgojJyBAcGFyYW0ga2VlcF9sZWdlbmRfbmFtZSBUaGUgbmFtZSB0byB1c2UgaW4gdGhlIGxlZ2VuZAojJyBAcGFyYW0gY29sX2Z1biBDb2xvciBmdW5jdGlvbiBmb3IgdGhlIGhlYXRtYXAgcGFsZXR0ZS4gRGVmYXVsdCBpcyBgaGVhdG1hcF9jb2xfZnVuYC4KIycgQHBhcmFtIC4uLiBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIGBDb21wbGV4SGVhdG1hcDo6SGVhdG1hcCgpYAojJwojJyBAcmV0dXJuIEEgQ29tcGxleEhlYXRtYXAgb2JqZWN0CmNyZWF0ZV9zaW5nbGVfaGVhdG1hcCA8LSBmdW5jdGlvbigKICAgIG1hdCwKICAgIHJvd190aXRsZSwKICAgIGNvbHVtbl90aXRsZSwKICAgIGxhYmVsc19mb250X3NpemUsCiAgICBrZWVwX2xlZ2VuZF9uYW1lLAogICAgY29sX2Z1biA9IGhlYXRtYXBfY29sX2Z1biwKICAgIC4uLikgewogIGhlYXQgPC0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoCiAgICB0KG1hdCksICMgdHJhbnNwb3NlIGJlY2F1c2UgbWF0cml4IHJvd3MgYXJlIGluIGNvbW1vbiAmIHdlIHdhbnQgYSB2ZXJ0aWNhbCBhcnJhbmdlbWVudAogICAgY29sID0gY29sX2Z1biwKICAgIGJvcmRlciA9IFRSVUUsICMgZWFjaCBoZWF0bWFwIGdldHMgaXRzIG93biBvdXRsaW5lCiAgICAjIyBSb3cgcGFyYW1ldGVycwogICAgY2x1c3Rlcl9yb3dzID0gRkFMU0UsCiAgICByb3dfdGl0bGUgPSByb3dfdGl0bGUsICMgZWFjaCBoZWF0bWFwIGdldHMgaXRzIG93biB0aXRsZQogICAgcm93X3RpdGxlX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDEwKSwKICAgIHJvd190aXRsZV9zaWRlID0gInJpZ2h0IiwKICAgIHJvd19uYW1lc19zaWRlID0gImxlZnQiLAogICAgcm93X25hbWVzX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IGxhYmVsc19mb250X3NpemUpLAogICAgIyMgQ29sdW1uIHBhcmFtZXRlcnMKICAgIGNsdXN0ZXJfY29sdW1ucyA9IEZBTFNFLAogICAgY29sdW1uX3RpdGxlID0gY29sdW1uX3RpdGxlLAogICAgY29sdW1uX3RpdGxlX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDEwKSwKICAgIGNvbHVtbl9uYW1lc19zaWRlID0gImJvdHRvbSIsCiAgICBjb2x1bW5fbmFtZXNfZ3AgPSBncmlkOjpncGFyKGZvbnRzaXplID0gbGFiZWxzX2ZvbnRfc2l6ZSksCiAgICAjIyMgcGFzc2VkIGluIGFyZ3MKICAgIC4uLiwKICAgICMjIExlZ2VuZCBwYXJhbWV0ZXJzCiAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbSA9IGxpc3QoCiAgICAgIHRpdGxlID0gIkphY2NhcmQgaW5kZXgiLAogICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgIGxlZ2VuZF93aWR0aCA9IHVuaXQoMS41LCAiaW4iKQogICAgKSwKICAgICMgb25seSBrZWVwIGxlZ2VuZHMgdGhhdCBtYXRjaCBga2VlcF9sZWdlbmRfbmFtZWAKICAgIHNob3dfaGVhdG1hcF9sZWdlbmQgPSByb3dfdGl0bGUgPT0ga2VlcF9sZWdlbmRfbmFtZSwKICApCgogIHJldHVybihoZWF0KQp9CgojJyBGdW5jdGlvbiB0byBwbG90IGEgdmVydGljYWxseS1zdGFja2VkIENvbXBsZXhIZWF0bWFwIGZyb20gYSBsaXN0IG9mIG1hdHJpY2VzCiMnCiMnIEBwYXJhbSBtYXRyaXhfbGlzdCBMaXN0IG9mIG1hdHJpY2VzIHRvIHBsb3QgaW4gYSB2ZXJ0aWNhbCBsYXlvdXQKIycgQHBhcmFtIGNvbHVtbl90aXRsZSBUaXRsZSB0byB1c2UgZm9yIGNvbHVtbnMsIHNoYXJlZCBhbW9uZyBhbGwgaGVhdG1hcHMKIycgQHBhcmFtIGxhYmVsc19mb250X3NpemUgRm9udCBzaXplIHRvIHVzZSBmb3Igcm93cyBhbmQgY29sdW1uIGxhYmVscwojJyBAcGFyYW0gY29sX2Z1biBDb2xvciBmdW5jdGlvbiBmb3IgdGhlIGhlYXRtYXAgcGFsZXR0ZS4gRGVmYXVsdCBpcyBgaGVhdG1hdF9jb2xfZnVuYAojJyBAcGFyYW0gLi4uIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gYENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKClgCiMnCiMnIEByZXR1cm4gQSBsaXN0IG9mIENvbXBsZXhIZWF0bWFwIG9iamVjdHMKY3JlYXRlX2hlYXRtYXBfbGlzdCA8LSBmdW5jdGlvbigKICAgIG1hdHJpeF9saXN0LAogICAgY29sdW1uX3RpdGxlLAogICAgbGFiZWxzX2ZvbnRfc2l6ZSwKICAgIGNvbF9mdW4gPSBoZWF0bWFwX2NvbF9mdW4sCiAgICAuLi4pIHsKICAjIFdlIG9ubHkgd2FudCBvbmUgc2hhcmVkIGxlZ2VuZCBpbiB0aGUgZW5kLCBhcmJpdHJhcmlseSBncmFiIHRoZSBmaXJzdCBvbmUKICBrZWVwX2xlZ2VuZF9uYW1lIDwtIG5hbWVzKG1hdHJpeF9saXN0KVsxXQoKICBoZWF0bWFwX2xpc3QgPC0gbWF0cml4X2xpc3QgfD4KICAgIHB1cnJyOjppbWFwKAogICAgICBcKG1hdCwgbmFtZSkgY3JlYXRlX3NpbmdsZV9oZWF0bWFwKAogICAgICAgIG1hdCwKICAgICAgICBuYW1lLAogICAgICAgIGNvbHVtbl90aXRsZSwKICAgICAgICBsYWJlbHNfZm9udF9zaXplLAogICAgICAgIGtlZXBfbGVnZW5kX25hbWUsCiAgICAgICAgY29sX2Z1biwKICAgICAgICAuLi4KICAgICAgKQogICAgKSB8PgogICAgIyBjb25jYXRlbmF0ZSB2ZXJ0aWNhbGx5IGludG8gSGVhdG1hcExpc3Qgb2JqZWN0CiAgICBwdXJycjo6cmVkdWNlKENvbXBsZXhIZWF0bWFwOjpgJXYlYCkKCiAgcmV0dXJuKGhlYXRtYXBfbGlzdCkKfQoKCiMnIERldGVybWluZSB0aGUgbGFiZWwgZm9udCBzaXplIGJhc2VkIG9uICMgY2hhcmFjdGVycyBpbiBjZWxsIHR5cGUgbGFiZWxzCiMnCiMnIEBwYXJhbSBpbnB1dF9sYWJlbHMgVmVjdG9yIG9mIGNlbGwgdHlwZSBsYWJlbHMKIycKIycgQHJldHVybiBGb250IHNpemUgbnVtZXJpYyBhcyBkZXRlcm1pbmVkIGJ5IGxvbmdlc3QgY2VsbCB0eXBlIGxhYmVsCmZpbmRfbGFiZWxfc2l6ZSA8LSBmdW5jdGlvbihpbnB1dF9sYWJlbHMpIHsKICBsb25nZXN0X25hbWUgPC0gaW5wdXRfbGFiZWxzIHw+CiAgICBzdHJpbmdyOjpzdHJfbGVuZ3RoKCkgfD4KICAgIG1heCgpCgogIGxhYmVsc19mb250X3NpemUgPC0gZHBseXI6OmNhc2Vfd2hlbigKICAgIGxvbmdlc3RfbmFtZSA8IDM1IH4gOS41LAogICAgbG9uZ2VzdF9uYW1lIDwgNDUgfiA4LjUsCiAgICBsb25nZXN0X25hbWUgPCA2MCB+IDcuNSwKICAgIC5kZWZhdWx0ID0gNi41CiAgKQoKICByZXR1cm4obGFiZWxzX2ZvbnRfc2l6ZSkKfQpgYGAKCgpgYGB7cn0KIycgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIG9wdGltYWwgaGVhdG1hcCBwbG90IHZpZXcgaGVpZ2h0CiMnCiMnIEBwYXJhbSByb3dfbmFtZXMgVmVjdG9yIG9mIHJvd25hbWVzCiMnIEBwYXJhbSBjb2xfbmFtZXMgVmVjdG9yIG9mIGNvbHVtbiBuYW1lcwojJyBAcGFyYW0gbl9zcGFjZXJzIE51bWJlciBvZiBzcGFjZXJzIGJldHdlZW4gc3RhY2tlZCBoZWF0bWFwcwojJyBAcGFyYW0gc3BhY2VyX3NpemUgU3BhY2VyIHNpemUgaW4gaW5jaGVzCiMnIEBwYXJhbSBtaW5faGVpZ2h0IE1pbmltaXplIGhlaWdodCByZXF1aXJlZC4gRGVmYXVsdCA0IgojJwojJyBAcmV0dXJuIEhlYXRtYXAgaGVpZ2h0IGluIGluY2hlcwpjYWxjdWxhdGVfcGxvdF9oZWlnaHQgPC0gZnVuY3Rpb24oCiAgICByb3dfbmFtZXMsCiAgICBjb2xfbmFtZXMsCiAgICBuX3NwYWNlcnMsCiAgICBzcGFjZXJfc2l6ZSA9IGhlYXRtYXBfcGFkZGluZywKICAgIG1pbl9oZWlnaHQgPSA0KSB7CiAgIyBmaXJzdCwgYmFzZWQgb24gbnVtYmVyIG9mIGNlbGxzIGluIHJvd19uYW1lczoKICAjICAgNiBjZWxsIHR5cGVzIHRvIGFuIGluY2gKICBoZWF0X2hlaWdodCA8LSBsZW5ndGgocm93X25hbWVzKSAvIDYKCiAgIyBuZXh0LCBiYXNlZCBvbiBuY2hhciBvZiBjb2xfbmFtZXM6CiAgIyAgIDEwIGNoYXJhY3RlcnMgdG8gYW4gaW5jaAogICMgdXNpbmcgc3RyaW5ncjo6c3RyX2xlbmd0aCgpIGluIGNhc2UgY29sX25hbWVzIGlzIGEgZmFjdG9yIHZlY3RvcgogIGhlYXRfaGVpZ2h0IDwtIGhlYXRfaGVpZ2h0ICsgbWF4KHN0cmluZ3I6OnN0cl9sZW5ndGgoY29sX25hbWVzKSkgLyAxMAoKICAjIGZpbmFsbHksIGFkZCBpbiBhbnkgcGFkZGluZwogIGhlYXRfaGVpZ2h0IDwtIGhlYXRfaGVpZ2h0ICsgbl9zcGFjZXJzICogc3BhY2VyX3NpemUKCiAgcmV0dXJuKAogICAgbWF4KGMobWluX2hlaWdodCwgaGVhdF9oZWlnaHQpKQogICkKfQpgYGAKCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBkZWZpbmUgbGlicmFyeSBhbmQgc2NlIG9iamVjdApsaWJyYXJ5X2lkIDwtIHBhcmFtcyRsaWJyYXJ5CnByb2Nlc3NlZF9zY2UgPC0gcGFyYW1zJHByb2Nlc3NlZF9zY2UKCiMgY2hlY2sgZm9yIGFubm90YXRpb24gbWV0aG9kcwpoYXNfc2luZ2xlciA8LSAic2luZ2xlciIgJWluJSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsdHlwZV9tZXRob2RzCmhhc19jZWxsYXNzaWduIDwtICJjZWxsYXNzaWduIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMKaGFzX3N1Ym1pdHRlciA8LSAic3VibWl0dGVyIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMgJiYKICAhYWxsKGlzLm5hKHByb2Nlc3NlZF9zY2Ukc3VibWl0dGVyX2NlbGx0eXBlX2Fubm90YXRpb24pKSAjIG1ha2Ugc3VyZSB0aGV5IGFyZW4ndCBhbGwgTkEKCiMgY2hlY2sgZm9yIHVtYXAKaGFzX3VtYXAgPC0gIlVNQVAiICVpbiUgcmVkdWNlZERpbU5hbWVzKHByb2Nlc3NlZF9zY2UpCgojIHdoYXQgY2VsbHR5cGVzIGFyZSBhdmFpbGFibGU/CmF2YWlsYWJsZV9jZWxsdHlwZXMgPC0gYygKICBpZmVsc2UoaGFzX3N1Ym1pdHRlciwgIlN1Ym1pdHRlciIsIE5BKSwKICBpZmVsc2UoaGFzX3NpbmdsZXIsICJTaW5nbGVSIiwgTkEpLAogIGlmZWxzZShoYXNfY2VsbGFzc2lnbiwgIkNlbGxBc3NpZ24iLCBOQSkKKSB8PgogIG5hLm9taXQoKSB8PgogIGFzLmNoYXJhY3RlcigpCgojIHdhcyBjZWxsYXNzaWduIHJ1bj8KY2VsbGFzc2lnbl9ub3RfcnVuIDwtIGNoZWNrX2NlbGxhc3NpZ25fbm90X3J1bigKICBoYXNfY2VsbGFzc2lnbiwKICBjb2xEYXRhKHByb2Nlc3NlZF9zY2UpCikKCiMgVGhpcyB2YXJpYWJsZSBuZWVkIHRvIGJlIGRlZmluZWQgZm9yIGVkZ2UgY29uZGl0aW9ucyB3aGVuIGNlcnRhaW4gY2VsbCB0eXBlcwojICBhcmVuJ3QgYXZhaWxhYmxlOgojICBXaGVuIHdlIGhhdmUgY2h1bmtzIHdpdGggYGV2YWw9PGhhc19tZXRob2Q+YCwga25pdHIgc2VlbXMgdG8gbmVlZCBhbGwgb3RoZXIKIyAgdmFyaWFibGVzIHVzZWQgaW4gY2h1bmsgcGFyYW1zIGRlZmluZWQsIGluY2x1ZGluZyBwbG90IGRpbWVuc2lvbiB2YXJpYWJsZXMKIyAgd2hpY2ggd291bGQgaGF2ZSBvbmx5IGJlZW4gY3JlYXRlZCBpbiBjaHVua3Mgd2hpY2ggYWxzbyBoYWQgYW4gYXNzb2NpYXRlZAojICBldmFsPTxoYXNfbWV0aG9kPmAuIFNpbmNlIHRob3NlIGNodW5rcyB3b24ndCBoYXZlIGJlZW4gZXZhbCdkIGlmIEZBTFNFLCB3ZQojICBuZWVkIHRvIGRlZmluZSB0aGlzIHZhcmlhYmxlIHRvIHByZXZlbnQgZXJyb3JzLCBidXQgdGhpcyB2YWx1ZSB3aWxsIG5ldmVyCiMgIGFjdHVhbGx5IGJlIHVzZWQuCnBsb3RfaGVpZ2h0IDwtIDEKCiMgRGV0ZXJtaW5lIGlmIGxpYnJhcnkgaXMgbXVsdGlwbGV4ZWQ6CiMgIHNhbXBsZV9pZCBzaG91bGQgYmUgZGVmaW5lZCB3aXRoIGxlbmd0aCA+IDEKc2FtcGxlX2lkIDwtIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJHNhbXBsZV9pZApoYXNfbXVsdGlwbGV4IDwtIGxlbmd0aChzYW1wbGVfaWQpID4gMQoKIyBkZXRlcm1pbmUgVU1BUCBwb2ludCBzaXppbmcKdW1hcF9wb2ludHNfc2l6ZXMgPC0gZGV0ZXJtaW5lX3VtYXBfcG9pbnRfc2l6ZShuY29sKHByb2Nlc3NlZF9zY2UpKQp1bWFwX3BvaW50X3NpemUgPC0gdW1hcF9wb2ludHNfc2l6ZXNbMV0KdW1hcF9mYWNldF9wb2ludF9zaXplIDwtIHVtYXBfcG9pbnRzX3NpemVzWzJdCmBgYAoKPCEtLSBJZiBtdWx0aXBsZXhlZCwgb3BlbiB3aXRoIHdhcm5pbmcgIC0tPiAKYGBge3IsIGV2YWwgPSBoYXNfbXVsdGlwbGV4LCByZXN1bHRzPSdhc2lzJ30KIyBjb252ZXJ0IHNhbXBsZSBpZCB0byBidWxsZXQgc2VwYXJhdGVkIGxpc3QKbXVsdGlwbGV4X3NhbXBsZXMgPC0gcGFzdGUwKCI8bGk+IiwgcGFzdGUoc2FtcGxlX2lkLCBjb2xsYXBzZSA9ICI8L2xpPjxsaT4iLCAiPC9saT4iKSkKZ2x1ZTo6Z2x1ZSgiCiA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiPgoKIFRoaXMgbGlicmFyeSBpcyBtdWx0aXBsZXhlZCBhbmQgY29udGFpbnMgZGF0YSBmcm9tIG1vcmUgdGhhbiBvbmUgc2FtcGxlLgogRGF0YSBmcm9tIHRoZSBmb2xsb3dpbmcgc2FtcGxlcyBhcmUgaW5jbHVkZWQgaW4gdGhpcyBsaWJyYXJ5OgoKICAgIHttdWx0aXBsZXhfc2FtcGxlc30KCiAgPC9kaXY+CiIpCmBgYAoKVGhpcyByZXBvcnQgY29udGFpbnMgYSBzdW1tYXJ5IG9mIGNlbGwgdHlwZSBhbm5vdGF0aW9uIHJlc3VsdHMgZm9yIGxpYnJhcnkgYHIgbGlicmFyeV9pZGAuClRoZSBnb2FsIG9mIHRoaXMgcmVwb3J0IGlzIHRvIHByb3ZpZGUgbW9yZSBkZXRhaWxlZCBpbmZvcm1hdGlvbiBhYm91dCBjZWxsIHR5cGUgYW5ub3RhdGlvbiByZXN1bHRzIGFzIGFuIGluaXRpYWwgZXZhbHVhdGlvbiBvZiB0aGVpciBxdWFsaXR5IGFuZCByZWxpYWJpbGl0eS4KClBlcmZvcm1pbmcgY2VsbCB0eXBlIGFubm90YXRpb24gaXMgYW4gaW5oZXJlbnRseSBjaGFsbGVuZ2luZyB0YXNrIHdpdGggaGlnaCBsZXZlbHMgb2YgdW5jZXJ0YWludHksIGVzcGVjaWFsbHkgd2hlbiB1c2luZyBhdXRvbWF0ZWQgYW5ub3RhdGlvbiBtZXRob2RzLgpPbmUgd2F5IHRvIGFkZHJlc3MgdGhpcyBpcyB0byB1c2UgbXVsdGlwbGUgY2VsbCB0eXBlIGFubm90YXRpb24gYXBwcm9hY2hlcyBhbmQgY29tcGFyZSB0aGUgcmVzdWx0cywgYXMgd2UgaGF2ZSBiZWd1biB0byBkbyBpbiB0aGlzIHJlcG9ydC4KCldoZW4gbXVsdGlwbGUgbWV0aG9kcyBhbm5vdGF0ZSBhIGdpdmVuIGNlbGwgYXMgdGhlIHNhbWUgb3Igc2ltaWxhciBjZWxsIHR5cGUsIHRoaXMgbWF5IHF1YWxpdGF0aXZlbHkgaW5kaWNhdGUgYSBtb3JlIHJvYnVzdCBhbm5vdGF0aW9uLgoKTm90ZSB0aGF0IHRoZSBjb250ZW50cyBvZiB0aGlzIHJlcG9ydCB3aWxsIHZhcnkgYmFzZWQgb24gd2hpY2ggY2VsbCB0eXBlIGFubm90YXRpb25zIGFyZSBwcmVzZW50LgpGdXJ0aGVyLCBiZSBhd2FyZSB0aGF0IGRpZmZlcmVudCBjZWxsIHR5cGUgYW5ub3RhdGlvbiBtZXRob2RzIG1heSBhc3NpZ24gZGlmZmVyZW50IGxhYmVscyB0byB0aGUgc2FtZSBvciBzaW1pbGFyIGNlbGwgdHlwZSAoZS5nLiwgdGhlIGRpZmZlcmVudCBzdHJpbmcgcmVwcmVzZW50YXRpb25zIGBCIGNlbGwgbmFpdmVgIGFuZCBgTmFpdmUgQiBjZWxsYCksIGR1ZSB0byB1c2Ugb2YgZGlmZmVyZW50IHVuZGVybHlpbmcgcmVmZXJlbmNlIGRhdGFzZXRzLgpQbGVhc2Ugbm90ZSB0aGF0IGFsbCBjZWxsIHR5cGUgYW5ub3RhdGlvbiByZWZlcmVuY2UgZGF0YXNldHMgYXJlIGRlcml2ZWQgZnJvbSBub3JtYWwgKG5vdCB0dW1vcikgdGlzc3VlLgoKPCEtLU5vdGUgdGhhdCB0aGUgc3BlY2lmaWMgY29udGVudHMgb2YgdGhpcyByZXBvcnQgd2lsbCBkZXBlbmQgb24gd2hpY2ggY2VsbCB0eXBlIGFubm90YXRpb25zIGFyZSBwcmVzZW50Li0tPgoqKlRoaXMgbGlicmFyeSBjb250YWlucyB0aGUgZm9sbG93aW5nIGNlbGwgdHlwZSBhbm5vdGF0aW9uczoqKgoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CiMgYnVpbGQgdXAgdGhpcyBzdHJpbmcgYXMgd2UgZ286Cm1ldGhvZHNfdGV4dCA8LSAiIgoKaWYgKGhhc19zdWJtaXR0ZXIpIHsKICBtZXRob2RzX3RleHQgPC0gZ2x1ZTo6Z2x1ZSgKICAgICJ7bWV0aG9kc190ZXh0fQogICAgKiBTdWJtaXR0ZXItcHJvdmlkZWQgY2VsbCB0eXBlIGFubm90YXRpb24sIGdlbmVyYXRlZCBieSB0aGUgb3JpZ2luYWwgbGFiIHdoaWNoIHByb2R1Y2VkIHRoaXMgZGF0YS5cbiIKICApCn0KCmlmIChoYXNfc2luZ2xlcikgewogIG1ldGhvZHNfdGV4dCA8LSBnbHVlOjpnbHVlKAogICAgInttZXRob2RzX3RleHR9CiAgICAqIEFubm90YXRpb25zIGZyb20gW2BTaW5nbGVSYF0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL1NpbmdsZVIuaHRtbCksIGEgcmVmZXJlbmNlLWJhc2VkIGFwcHJvYWNoIChbTG9vbmV5IF9ldCBhbC5fIDIwMTldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMDM4L3M0MTU5MC0wMTgtMDI3Ni15KSkuCiAgICBUaGUgYHttZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzaW5nbGVyX3JlZmVyZW5jZX1gIGRhdGFzZXQsIG9idGFpbmVkIGZyb20gdGhlIFtgY2VsbGRleGAgcGFja2FnZV0oaHR0cDovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9kYXRhL2V4cGVyaW1lbnQvaHRtbC9jZWxsZGV4Lmh0bWwpLCB3YXMgdXNlZCBmb3IgcmVmZXJlbmNlIGFubm90YXRpb25zLlxuIgogICkKfQoKaWYgKGhhc19jZWxsYXNzaWduKSB7CiAgb3JnYW5zIDwtIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGxhc3NpZ25fcmVmZXJlbmNlX29yZ2FucyB8PgogICAgc3RyaW5ncjo6c3RyX3RvX2xvd2VyKCkKICAjIHNwbGl0IHVwIGFuZCBhZGQgYW4gYGFuZGAgYmVmb3JlIHRoZSBmaW5hbCBvcmdhbgogIG9yZ2Fuc19zdHJpbmcgPC0gc3RyaW5ncjo6c3RyX3NwbGl0XzEob3JnYW5zLCBwYXR0ZXJuID0gIiwgIikgfD4KICAgIHN0cmluZ3I6OnN0cl9mbGF0dGVuX2NvbW1hKGxhc3QgPSAiLCBhbmQgIikKCiAgcmVmX25hbWUgPC0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkY2VsbGFzc2lnbl9yZWZlcmVuY2UKCiAgbWV0aG9kc190ZXh0IDwtIGdsdWU6OmdsdWUoCiAgICAie21ldGhvZHNfdGV4dH0KICAgICogQW5ub3RhdGlvbnMgZnJvbSBbYENlbGxBc3NpZ25gXShodHRwczovL2dpdGh1Yi5jb20vSXJyYXRpb25vbmUvY2VsbGFzc2lnbiksIGEgbWFya2VyLWdlbmUtYmFzZWQgYXBwcm9hY2ggKFtaaGFuZyBfZXQgYWwuXyAyMDE5XShodHRwczovL2RvaS5vcmcvMTAuMTAzOC9zNDE1OTItMDE5LTA1MjktMSkpLgogICAgTWFya2VyIGdlbmVzIGZvciBjZWxsIHR5cGVzIHdlcmUgb2J0YWluZWQgZnJvbSBbUGFuZ2xhb0RCXShodHRwczovL3BhbmdsYW9kYi5zZS8pIGFuZCBjb21waWxlZCBpbnRvIGEgcmVmZXJlbmNlIG5hbWVkIGB7cmVmX25hbWV9YC4KICAgIFRoaXMgcmVmZXJlbmNlIGluY2x1ZGVzIHRoZSBmb2xsb3dpbmcgb3JnYW5zIGFuZCB0aXNzdWUgY29tcGFydG1lbnRzOiB7b3JnYW5zX3N0cmluZ30uXG4iCiAgKQp9CgpnbHVlOjpnbHVlKCJ7bWV0aG9kc190ZXh0fSIpCmBgYAoKYGBge3IgZXZhbD1jZWxsYXNzaWduX25vdF9ydW4sIHJlc3VsdHM9J2FzaXMnfQpnbHVlOjpnbHVlKCIKICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWluZm9cIj4KICAgQ2VsbCB0eXBlIGFubm90YXRpb24gd2l0aCBbYENlbGxBc3NpZ25gXShodHRwczovL2dpdGh1Yi5jb20vSXJyYXRpb25vbmUvY2VsbGFzc2lnbiksIGEgbWFya2VyLWdlbmUtYmFzZWQgYXBwcm9hY2ggKFtaaGFuZyBfZXQgYWwuXyAyMDE5XShodHRwczovL2RvaS5vcmcvMTAuMTAzOC9zNDE1OTItMDE5LTA1MjktMSkpLCB3YXMgYXR0ZW1wdGVkIGJ1dCBub3QgcnVuIGR1ZSB0byBhbiBpbnN1ZmZpY2llbnQgbnVtYmVyIG9mIGNlbGxzLgogIDwvZGl2PgoiKQpgYGAKCgo8IS0tLS0tLS0gQ2FsbCB0aGUgY2VsbHR5cGVzX3FjIHJlcG9ydCBzZWN0aW9uIGZyb20gdGhlIG1haW4gcmVwb3J0IC0tLS0tLS0tLS0tPgpgYGB7ciwgY2hpbGQ9J2NlbGx0eXBlc19xYy5ybWQnfQpgYGAKCgojIENlbGwgbGFiZWwgY29tcGFyaXNvbiBwbG90cwoKVGhpcyBzZWN0aW9uIGRpc3BsYXlzIGhlYXRtYXBzIGNvbXBhcmluZyBjZWxsIGxhYmVscyBmcm9tIHZhcmlvdXMgbWV0aG9kcy4KCldlIHVzZSB0aGUgW0phY2NhcmQgc2ltaWxhcml0eSBpbmRleF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSmFjY2FyZF9pbmRleCkgdG8gZGlzcGxheSB0aGUgYWdyZWVtZW50IGJldHdlZW4gYmV0d2VlbiBwYWlycyBvZiBsYWJlbHMgYXNzaWduZWQgYnkgZGlmZmVyZW50IGFubm90YXRpb24gbWV0aG9kcy4KClRoZSBKYWNjYXJkIGluZGV4IHJlZmxlY3RzIHRoZSBkZWdyZWUgb2Ygb3ZlcmxhcCBiZXR3ZWVuIHRoZSB0d28gbGFiZWxzIGFuZCByYW5nZXMgZnJvbSAwIHRvIDEuCgoqIElmIHRoZSBsYWJlbHMgYXJlIGFzc2lnbmVkIHRvIGlkZW50aWNhbCBzZXRzIG9mIGNlbGxzLCB0aGUgSmFjY2FyZCBpbmRleCB3aWxsIGJlIDEuCiogSWYgdGhlIGxhYmVscyBhcmUgYXNzaWduZWQgdG8gY29tcGxldGVseSBub24tb3ZlcmxhcHBpbmcgc2V0cyBvZiBjZWxscywgdGhlIEphY2NhcmQgaW5kZXggd2lsbCBiZSAwLgoKSGlnaCBhZ3JlZW1lbnQgYmV0d2VlbiBtZXRob2RzIHF1YWxpdGF0aXZlbHkgaW5kaWNhdGVzIGhpZ2hlciBjb25maWRlbmNlIGluIHRoZSBjZWxsIHR5cGUgYW5ub3RhdGlvbi4KCgoKCgo8IS0tIElmIG11bHRpcGxleGVkLCBzaG93IGluZm8gYWxlcnQgaW5zdGVhZCBvZiB0aGlzIGhlYXRtYXAgLS0+IApgYGB7ciwgZXZhbCA9IGhhc19tdWx0aXBsZXgsIHJlc3VsdHM9J2FzaXMnfQpnbHVlOjpnbHVlKCIKIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogIE5vIGhlYXRtYXAgY29tcGFyaW5nIGNsdXN0ZXIgYW5kIGNlbGwgdHlwZSBhbm5vdGF0aW9uIGxhYmVscyBpcyBzaG93biBiZWNhdXNlIHRoZSBwcmVzZW5jZSBvZiBtdWx0aXBsZSBzYW1wbGVzIG1heSBjb25mb3VuZCBjbHVzdGVyIGFzc2lnbm1lbnQuCgogIDwvZGl2PgoiKQpgYGAKCjwhLS0gSWYgbm90IG11bHRpcGxleGVkLCBzaG93IHRoZSBoZWFkZXIsIHRleHQsIGFuZCBoZWF0bWFwIC0tPiAKYGBge3IsIGV2YWwgPSAhaGFzX211bHRpcGxleCwgcmVzdWx0cz0nYXNpcyd9CmdsdWU6OmdsdWUoIgogICMjIFVuc3VwZXJ2aXNlZCBjbHVzdGVyaW5nCgogIEhlcmUgd2Ugc2hvdyB0aGUgbGFiZWxzIGZyb20gdW5zdXBlcnZpc2VkIGNsdXN0ZXJpbmcgY29tcGFyZWQgdG8gY2VsbCB0eXBlIGFubm90YXRpb25zLgogIENsdXN0ZXIgYXNzaWdubWVudCB3YXMgcGVyZm9ybWVkIHVzaW5nIHRoZSBge21ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNsdXN0ZXJfYWxnb3JpdGhtfWAgYWxnb3JpdGhtLgoiKQoKIyBDYWxjdWxhdGUgYWxsIGphY2NhcmQgbWF0cmljZXMgb2YgaW50ZXJlc3QgZm9yIGlucHV0IHRvIGhlYXRtYXAKamFjY2FyZF9jbHVzdGVyX21hdHJpY2VzIDwtIGF2YWlsYWJsZV9jZWxsdHlwZXMgfD4KICBzdHJpbmdyOjpzdHJfdG9fbG93ZXIoKSB8PgogIHB1cnJyOjpzZXRfbmFtZXMoYXZhaWxhYmxlX2NlbGx0eXBlcykgfD4KICBwdXJycjo6bWFwKFwobmFtZSkgewogICAgbWFrZV9qYWNjYXJkX21hdHJpeCgKICAgICAgY2VsbHR5cGVfZGYsCiAgICAgICJjbHVzdGVyIiwKICAgICAgZ2x1ZTo6Z2x1ZSgie25hbWV9X2NlbGx0eXBlX2Fubm90YXRpb24iKQogICAgKQogIH0pCgphbGxfY2VsbHR5cGVzIDwtIGphY2NhcmRfY2x1c3Rlcl9tYXRyaWNlcyB8PgogIHB1cnJyOjptYXAoY29sbmFtZXMpIHw+CiAgdW5saXN0KCkKCnBsb3RfaGVpZ2h0IDwtIGNhbGN1bGF0ZV9wbG90X2hlaWdodCgKICBhbGxfY2VsbHR5cGVzLAogIHVuaXF1ZShjZWxsdHlwZV9kZiRjbHVzdGVyKSwKICBsZW5ndGgoamFjY2FyZF9jbHVzdGVyX21hdHJpY2VzKSAtIDEKKQpgYGAKCgpgYGB7ciwgZXZhbCA9ICFoYXNfbXVsdGlwbGV4LCBmaWcuaGVpZ2h0ID0gcGxvdF9oZWlnaHQsIGZpZy53aWR0aCA9IDguNSwgd2FybmluZyA9IEZBTFNFfQpqYWNjYXJkX2NsdXN0ZXJfbWF0cmljZXMgfD4KICBjcmVhdGVfaGVhdG1hcF9saXN0KAogICAgY29sdW1uX3RpdGxlID0gIkNsdXN0ZXJzIiwKICAgIGxhYmVsc19mb250X3NpemUgPSBmaW5kX2xhYmVsX3NpemUoYWxsX2NlbGx0eXBlcyksCiAgICAjIyBhZGRpdGlvbmFsIGFyZ3VtZW50cwogICAgY29sdW1uX25hbWVzX3JvdCA9IDAKICApIHw+CiAgQ29tcGxleEhlYXRtYXA6OmRyYXcoCiAgICBoZWF0bWFwX2xlZ2VuZF9zaWRlID0gImJvdHRvbSIKICApCmBgYAoKCgo8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIFN1Ym1pdHRlciBoZWF0bWFwcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPgpgYGB7ciwgZXZhbCA9IGhhc19zdWJtaXR0ZXIgJiAoaGFzX2NlbGxhc3NpZ24gfCBoYXNfc2luZ2xlcil9CiMgZG9uJ3QgY29tcGFyZSBzdWJtaXR0ZXIgdG8gc3VibWl0dGVyCmF2YWlsYWJsZV9jZWxsdHlwZXMgPC0gYXZhaWxhYmxlX2NlbGx0eXBlc1shKGF2YWlsYWJsZV9jZWxsdHlwZXMgPT0gIlN1Ym1pdHRlciIpXQoKbWV0aG9kc19zdHJpbmcgPC0gYXZhaWxhYmxlX2NlbGx0eXBlcyB8PgogIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiXiIsICJgIikgfD4KICBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoIiQiLCAiYCIpIHw+CiAgc3RyaW5ncjo6c3RyX2ZsYXR0ZW5fY29tbWEoIiwgYW5kICIpCgprbml0cjo6YXNpc19vdXRwdXQoCiAgZ2x1ZTo6Z2x1ZSgKICAgICIjIyBTdWJtaXR0ZXItcHJvdmlkZWQgYW5ub3RhdGlvbnMKCiAgVGhpcyBzZWN0aW9uIGRpc3BsYXlzIGhlYXRtYXBzIGNvbXBhcmluZyBzdWJtaXR0ZXItcHJvdmlkZWQgY2VsbCB0eXBlIGFubm90YXRpb25zIHRvIHRob3NlIG9idGFpbmVkIGZyb20ge21ldGhvZHNfc3RyaW5nfS4iCiAgKQopCmBgYAoKYGBge3IsIGV2YWwgPSBoYXNfc3VibWl0dGVyICYgKGhhc19jZWxsYXNzaWduIHwgaGFzX3NpbmdsZXIpfQojIGNhbGN1bGF0ZSBtYXRyaWNlcyBjb21wYXJpbmcgdG8gc3VibWl0dGVyCmphY2NhcmRfc3VibWl0dGVyX21hdHJpY2VzIDwtIGF2YWlsYWJsZV9jZWxsdHlwZXMgfD4KICBzdHJpbmdyOjpzdHJfdG9fbG93ZXIoKSB8PgogIHB1cnJyOjptYXAoXChuYW1lKSB7CiAgICBtYWtlX2phY2NhcmRfbWF0cml4KAogICAgICBjZWxsdHlwZV9kZiwKICAgICAgInN1Ym1pdHRlcl9jZWxsdHlwZV9hbm5vdGF0aW9uIiwKICAgICAgZ2x1ZTo6Z2x1ZSgie25hbWV9X2NlbGx0eXBlX2Fubm90YXRpb24iKQogICAgKQogIH0pIHw+CiAgcHVycnI6OnNldF9uYW1lcyhhdmFpbGFibGVfY2VsbHR5cGVzKQoKIyBob3cgbWFueSBjZWxsIHR5cGVzPwphbGxfY2VsbHR5cGVzIDwtIGphY2NhcmRfc3VibWl0dGVyX21hdHJpY2VzIHw+CiAgcHVycnI6Om1hcChjb2xuYW1lcykgfD4KICB1bmxpc3QoKQoKcGxvdF9oZWlnaHQgPC0gY2FsY3VsYXRlX3Bsb3RfaGVpZ2h0KAogIGFsbF9jZWxsdHlwZXMsCiAgdW5pcXVlKGNlbGx0eXBlX2RmJHN1Ym1pdHRlcl9jZWxsdHlwZV9hbm5vdGF0aW9uKSwKICBsZW5ndGgoamFjY2FyZF9zdWJtaXR0ZXJfbWF0cmljZXMpIC0gMQopCmBgYAoKYGBge3IsIGV2YWwgPSBoYXNfc3VibWl0dGVyICYgKGhhc19jZWxsYXNzaWduIHwgaGFzX3NpbmdsZXIpLCBmaWcuaGVpZ2h0ID0gcGxvdF9oZWlnaHQsIGZpZy53aWR0aCA9IDguNSwgd2FybmluZyA9IEZBTFNFfQpqYWNjYXJkX3N1Ym1pdHRlcl9tYXRyaWNlcyB8PgogIGNyZWF0ZV9oZWF0bWFwX2xpc3QoCiAgICBjb2x1bW5fdGl0bGUgPSAiU3VibWl0dGVyLXByb3ZpZGVkIGFubm90YXRpb25zIiwKICAgIGxhYmVsc19mb250X3NpemUgPSBmaW5kX2xhYmVsX3NpemUoYWxsX2NlbGx0eXBlcyksCiAgICAjIGFkZGl0aW9uYWwgYXJndW1lbnRzCiAgICBjb2x1bW5fbmFtZXNfcm90ID0gOTAKICApIHw+CiAgQ29tcGxleEhlYXRtYXA6OmRyYXcoCiAgICBoZWF0bWFwX2xlZ2VuZF9zaWRlID0gImJvdHRvbSIKICApCmBgYAoKCjwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBTaW5nbGVSL0NlbGxBc3NpZ24gaGVhdG1hcCAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CmBgYHtyLCBldmFsID0gaGFzX2NlbGxhc3NpZ24gJiBoYXNfc2luZ2xlciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OH0Ka25pdHI6OmFzaXNfb3V0cHV0KCIKIyMgQXV0b21hdGVkIGFubm90YXRpb25zCgpUaGlzIHNlY3Rpb24gZGlzcGxheXMgYSBoZWF0bWFwIGRpcmVjdGx5IGNvbXBhcmluZyBgU2luZ2xlUmAgYW5kIGBDZWxsQXNzaWduYCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMuCk5vdGUgdGhhdCBkdWUgdG8gZGlmZmVyZW50IGFubm90YXRpb25zIHJlZmVyZW5jZXMsIHRoZXNlIG1ldGhvZHMgbWF5IHVzZSBkaWZmZXJlbnQgbmFtZXMgZm9yIHNpbWlsYXIgY2VsbCB0eXBlcy4KIikKCiMgU2V0IHBsb3QgZGltZW5zaW9ucyBiYXNlZCBvbiBudW1iZXIgb2YgU2luZ2xlUiBjZWxsIHR5cGVzCmFsbF9jZWxsdHlwZXMgPC0gbGV2ZWxzKGNlbGx0eXBlX2RmJHNpbmdsZXJfY2VsbHR5cGVfYW5ub3RhdGlvbikKcGxvdF9oZWlnaHQgPC0gY2FsY3VsYXRlX3Bsb3RfaGVpZ2h0KAogIHVuaXF1ZShjZWxsdHlwZV9kZiRzaW5nbGVyX2NlbGx0eXBlX2Fubm90YXRpb24pLAogIHVuaXF1ZShjZWxsdHlwZV9kZiRjZWxsYXNzaWduX2NlbGx0eXBlX2Fubm90YXRpb24pLAogIDAKKQpgYGAKCgpgYGB7ciwgZXZhbCA9IGhhc19jZWxsYXNzaWduICYgaGFzX3NpbmdsZXIsIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOC41fQojIENhbGN1bGF0ZSBqYWNjYXJkIG1hdHJpeApzaW5nbGVyX2NlbGxhc3NpZ25fbWF0cml4IDwtIG1ha2VfamFjY2FyZF9tYXRyaXgoCiAgY2VsbHR5cGVfZGYsCiAgInNpbmdsZXJfY2VsbHR5cGVfYW5ub3RhdGlvbiIsCiAgImNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbiIKKQoKY3JlYXRlX3NpbmdsZV9oZWF0bWFwKAogIHNpbmdsZXJfY2VsbGFzc2lnbl9tYXRyaXgsCiAgcm93X3RpdGxlID0gIkNlbGxBc3NpZ24gYW5ub3RhdGlvbnMiLAogIGNvbHVtbl90aXRsZSA9ICJTaW5nbGVSIGFubm90YXRpb25zIiwKICBsYWJlbHNfZm9udF9zaXplID0gZmluZF9sYWJlbF9zaXplKGFsbF9jZWxsdHlwZXMpLAogIGtlZXBfbGVnZW5kX25hbWUgPSAiQ2VsbEFzc2lnbiBhbm5vdGF0aW9ucyIsCiAgY29sX2Z1biA9IGhlYXRtYXBfY29sX2Z1biwKICAjIGFkZGl0aW9uYWwgYXJndW1lbnRzCiAgY29sdW1uX25hbWVzX3JvdCA9IDkwCikgfD4KICBDb21wbGV4SGVhdG1hcDo6ZHJhdygKICAgIGhlYXRtYXBfbGVnZW5kX3NpZGUgPSAiYm90dG9tIgogICkKYGBgCgo8IS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gRGlhZ25vc3RpYyBwbG90cyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPgpgYGB7ciwgZXZhbCA9IGhhc19zaW5nbGVyIHwgaGFzX2NlbGxhc3NpZ24gfQprbml0cjo6YXNpc19vdXRwdXQoIgojIFF1YWxpdHkgYXNzZXNzbWVudHMgb2YgYXV0b21hdGVkIGFubm90YXRpb25zCiIpCmBgYAoKCjwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIFNpbmdsZVIgZGVsdGEgbWVkaWFuICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CmBgYHtyLCBldmFsID0gaGFzX3NpbmdsZXJ9CmtuaXRyOjphc2lzX291dHB1dCgiCiMjIGBTaW5nbGVSYCBhbm5vdGF0aW9ucwoKVG8gYXNzZXNzIHRoZSBxdWFsaXR5IG9mIGBTaW5nbGVSYCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMsIHdlIHVzZSB0aGUgZGVsdGEgbWVkaWFuIHN0YXRpc3RpYy4KCi0gRGVsdGEgbWVkaWFuIGlzIGNhbGN1bGF0ZWQgZm9yIGVhY2ggY2VsbCBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBgU2luZ2xlUmAgc2NvcmUgb2YgdGhlIGFubm90YXRlZCBjZWxsIHR5cGUgbGFiZWwgYW5kIHRoZSBtZWRpYW4gc2NvcmUgb2YgdGhlIG90aGVyIGNlbGwgdHlwZSBsYWJlbHMgaW4gdGhlIHJlZmVyZW5jZSBkYXRhc2V0LgotIEhpZ2hlciBkZWx0YSBtZWRpYW4gdmFsdWVzIGluZGljYXRlIGhpZ2hlciBxdWFsaXR5IGNlbGwgdHlwZSBhbm5vdGF0aW9ucy4KICAtIFZhbHVlcyBjYW4gcmFuZ2UgZnJvbSAwLTEuCiAgLSBOb3RlIHRoYXQgdGhlcmUgaXMgbm8gdW5pdmVyc2FsIHRocmVzaG9sZCBmb3IgY2FsbGluZyBhYnNvbHV0ZSBoaWdoIHZzLiBsb3cgcXVhbGl0eSwgYXMgZGVzY3JpYmVkIGluIHRoZSBbYFNpbmdsZVJgIGJvb2sgc2VjdGlvbiBvbiAnQW5ub3RhdGlvbiBkaWFnbm9zdGljcyddKGh0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9ib29rcy9yZWxlYXNlL1NpbmdsZVJCb29rL2Fubm90YXRpb24tZGlhZ25vc3RpY3MuaHRtbCNhbm5vdGF0aW9uLWRpYWdub3N0aWNzKS4KCllvdSBjYW4gaW50ZXJwcmV0IHRoaXMgcGxvdCBhcyBmb2xsb3dzOgoKLSBFYWNoIHBvaW50IHJlcHJlc2VudHMgdGhlIGRlbHRhIG1lZGlhbiBzdGF0aXN0aWMgb2YgYSBnaXZlbiBjZWxsIHdob3NlIGBTaW5nbGVSYCBhbm5vdGF0aW9uIGlzIHNob3duIG9uIHRoZSB5LWF4aXMuCi0gVGhlIHBvaW50IHN0eWxlIGluZGljYXRlcyBgU2luZ2xlUmAncyBxdWFsaXR5IGFzc2Vzc21lbnQgb2YgdGhlIGFubm90YXRpb246CiAgLSBIaWdoLXF1YWxpdHkgY2VsbCBhbm5vdGF0aW9ucyBhcmUgc2hvd24gYXMgY2xvc2VkIHBvaW50cy4KICAtIExvdy1xdWFsaXR5IGNlbGwgYW5ub3RhdGlvbnMgYXJlIHNob3duIGFzIG9wZW4gcG9pbnRzLgogIEluIG90aGVyIHNlY3Rpb25zIG9mIHRoaXMgcmVwb3J0LCB0aGVzZSBjZWxscyBhcmUgbGFiZWxlZCBhcyBgVW5rbm93biBjZWxsIHR5cGVzYC4KICAtIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIGhvdyBgU2luZ2xlUmAgY2FsY3VsYXRlcyBhbm5vdGF0aW9uIHF1YWxpdHksIHBsZWFzZSByZWZlciB0byBbdGhpcyBgU2luZ2xlUmAgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9yZHJyLmlvL2Jpb2MvU2luZ2xlUi9tYW4vcHJ1bmVTY29yZXMuaHRtbCkuCi0gRGlhbW9uZHMgcmVwcmVzZW50IHRoZSBtZWRpYW4gb2YgdGhlIGRlbHRhIG1lZGlhbiBzdGF0aXN0aWMgc3BlY2lmaWNhbGx5IGFtb25nIGhpZ2gtcXVhbGl0eSBhbm5vdGF0aW9ucyBmb3IgdGhlIGdpdmVuIGNlbGwgdHlwZSBhbm5vdGF0aW9uLgoiKQpgYGAKCgpgYGB7ciwgZXZhbCA9IGhhc19zaW5nbGVyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIFByZXBhcmUgU2luZ2xlUiBzY29yZXMgZm9yIHBsb3QKCiMgZXh0cmFjdCBzY29yZXMgaW50byBtYXRyaXgKc2luZ2xlcl9zY29yZXMgPC0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkc2luZ2xlcl9yZXN1bHQkc2NvcmVzCgojIENyZWF0ZSBkYXRhIGZyYW1lIGZvciBwbG90dGluZyB3aXRoIGRlbHRhIG1lZGlhbiBhbmQgdGhlIGZ1bGwgKm5vbi1wcnVuZWQqIGNlbGwgbGFiZWxzCmRlbHRhX21lZGlhbl9kZiA8LSB0aWJibGU6OnRpYmJsZSgKICBkZWx0YV9tZWRpYW4gPSByb3dNYXhzKHNpbmdsZXJfc2NvcmVzKSAtIHJvd01lZGlhbnMoc2luZ2xlcl9zY29yZXMpLAogICMgTmVlZCB0byBncmFiIHRoZSBub24tcHJ1bmVkIGxhYmVsIGZvciB0aGlzIHBsb3QKICBmdWxsX2xhYmVscyA9IG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJHNpbmdsZXJfcmVzdWx0JGxhYmVscywKICAjIGlmIHBydW5lZC5sYWJlbHMgYXJlIE5BID09PiBsb3cgY29uZmlkZW5jZQogICMgc28sIG5lZ2F0ZSBmb3IgdGhpcyB2YXJpYWJsZToKICBjb25maWRlbnQgPSAhaXMubmEobWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkc2luZ2xlcl9yZXN1bHQkcHJ1bmVkLmxhYmVscykKKSB8PgogIGRwbHlyOjptdXRhdGUoCiAgICBjb25maWRlbnQgPSBpZmVsc2UoY29uZmlkZW50LCAiSGlnaC1xdWFsaXR5IiwgIkxvdy1xdWFsaXR5IikKICApCgojIElmIG9udG9sb2dpZXMgd2VyZSB1c2VkIGZvciBgZnVsbF9sYWJlbHNgLCB3ZSdsbCBuZWVkIHRvIG1hcCBiYWNrIHRvIGNlbGwgdHlwZSBuYW1lcwojICBmb3IgdGhlIHBsb3QgaXRzZWxmLgppZiAoInNpbmdsZXJfY2VsbHR5cGVfb250b2xvZ3kiICVpbiUgbmFtZXMoY2VsbHR5cGVfZGYpKSB7CiAgIyB3ZSB1c2UgaW5uZXJfam9pbiBiL2MgdGhlIGFib3ZlIHRpYmJsZSBkb2VzIE5PVCBjb250YWluICJVbmtub3duIGNlbGwgdHlwZSIsIHdoaWNoCiAgIyAgd2UgZG8gbm90IHdhbnQgdG8gZGlzcGxheSBoZXJlCiAgZGVsdGFfbWVkaWFuX2RmIDwtIGRlbHRhX21lZGlhbl9kZiB8PgogICAgZHBseXI6OmlubmVyX2pvaW4oCiAgICAgIHRpYmJsZTo6dGliYmxlKAogICAgICAgIGZ1bGxfbGFiZWxzID0gY2VsbHR5cGVfZGYkc2luZ2xlcl9jZWxsdHlwZV9vbnRvbG9neSwKICAgICAgICBjZWxsdHlwZSA9IGNlbGx0eXBlX2RmJHNpbmdsZXJfY2VsbHR5cGVfYW5ub3RhdGlvbgogICAgICApIHw+IGRwbHlyOjpkaXN0aW5jdCgpCiAgICApIHw+CiAgICBkcGx5cjo6c2VsZWN0KC1mdWxsX2xhYmVscykKfSBlbHNlIHsKICAjIG90aGVyd2lzZSwgZnVsbF9sYWJlbHMgYWxyZWFkeSBjb250YWluIHdoYXQgd2Ugd2FudCB0byBwbG90LCBzbyBqdXN0IHJlbmFtZSBpdAogIGRlbHRhX21lZGlhbl9kZiA8LSBkZWx0YV9tZWRpYW5fZGYgfD4KICAgIGRwbHlyOjpyZW5hbWUoY2VsbHR5cGUgPSBmdWxsX2xhYmVscykKICAjIHN0aWxsIG5lZWQgdG8gYWRkIGxldmVsczoKICAjIE5vdGUgdGhhdCB0aGUgbGV2ZWwgIlVua25vd24gY2VsbCB0eXBlIiB3aWxsIHN0aWxsIGJlIHByZXNlbnQsIGJ1dCB0aGVyZSBpcyBubyBzdWNoIHZhbHVlIGluIHRoZSBkYXRhLCBzbyBpdCB3b24ndCBtYXR0ZXIKICBsZXZlbHMoZGVsdGFfbWVkaWFuX2RmJGNlbGx0eXBlKSA8LSBsZXZlbHMoY2VsbHR5cGVfZGYkc2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uKQp9CgojIEVuc3VyZSB3ZSBoYXZlIG5vICJVbmtub3duIGNlbGwgdHlwZSIgdmFsdWVzIGxlZnQ6CmlmIChhbnkoZGVsdGFfbWVkaWFuX2RmJGNlbGx0eXBlID09ICJVbmtub3duIGNlbGwgdHlwZSIpKSB7CiAgc3RvcCgiRmFpbGVkIHRvIHByb2Nlc3MgU2luZ2xlUiBkYXRhIGZvciBkaWFnbm9zdGljIHBsb3QuIikKfQoKIyBhZGQgY29sdW1uIHdpdGggb3JkZXJlZCBsZXZlbHMgd2l0aCB3cmFwcGVkIGxhYmVscyBmb3IgdmlzdWFsaXphdGlvbgpkZWx0YV9tZWRpYW5fZGYkYW5ub3RhdGlvbl93cmFwcGVkIDwtIGZhY3RvcigKICBkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUsCiAgIyByZXYoKSBzbyBsYXJnZSBncm91cHMgYXJlIGF0IHRoZSBUT1Agb2YgdGhlIHBsb3QKICBsZXZlbHMgPSByZXYobGV2ZWxzKGRlbHRhX21lZGlhbl9kZiRjZWxsdHlwZSkpLAogIGxhYmVscyA9IHJldihzdHJpbmdyOjpzdHJfd3JhcChsZXZlbHMoZGVsdGFfbWVkaWFuX2RmJGNlbGx0eXBlKSwgMzApKQopCgojIFN1YnNldCB0aGUgZGF0YSB0byBqdXN0IGNvbmZpZGVudCBwb2ludHMgZm9yIG1lZGlhbisvLUlRUgpkZWx0YV9tZWRpYW5fY29uZmlkZW50X2RmIDwtIGRlbHRhX21lZGlhbl9kZiB8PgogIGRwbHlyOjpmaWx0ZXIoY29uZmlkZW50ID09ICJIaWdoLXF1YWxpdHkiKQoKIyBEZXRlcm1pbmUgaGVpZ2h0IGZvciBwbG90IGFyZWEgYmFzZWQgb24gbnVtYmVyIG9mIGNlbGxzCnBsb3RfaGVpZ2h0IDwtIGxlbmd0aCh1bmlxdWUoZGVsdGFfbWVkaWFuX2RmJGNlbGx0eXBlKSkgLyAyLjUKYGBgCgpgYGB7ciwgZXZhbCA9IGhhc19zaW5nbGVyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBmaWcuaGVpZ2h0ID0gcGxvdF9oZWlnaHQsIGZpZy53aWR0aCA9IDh9CiMgUGxvdCBkZWx0YV9tZWRpYW4gYWNyb3NzIGNlbGx0eXBlcyBjb2xvcmVkIGJ5IHBydW5pbmcKZ2dwbG90KGRlbHRhX21lZGlhbl9kZikgKwogIGFlcygKICAgIHggPSBkZWx0YV9tZWRpYW4sCiAgICB5ID0gYW5ub3RhdGlvbl93cmFwcGVkLAogICAgc2hhcGUgPSBjb25maWRlbnQsCiAgICBhbHBoYSA9IGNvbmZpZGVudAogICkgKwogIGdnZm9yY2U6Omdlb21fc2luYSgKICAgIHNpemUgPSAwLjgsCiAgICBjb2xvciA9ICJibGFjayIsICMgd2lsbCBnZXQgYXBwbGllZCB0byBhbGwgY29uZmlkZW50IHBvaW50cyBhbmQgbm9uLWNvbmZpZGVudCBvdXRsaW5lCiAgICBmaWxsID0gIndoaXRlIiwgIyB3aWxsIGFwcGx5IHRvIG5vbi1jb25maWRlbnQgZmlsbCBvbmx5CiAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4wNSkgIyBLZWVwIGJvdGggdHlwZXMgb2YgcG9pbnRzIG1vc3RseSBpbiBsaW5lCiAgKSArCiAgIyBIYW5kbGUgcG9pbnRzIGFlc3RoZXRpY3M6CiAgIyAgY29uZmlkZW50IGFyZSBjbG9zZWQgYmxhY2sgd2l0aCBhbHBoYSA9IDAuNQogICMgIG5vdCBjb25maWRlbnQgYXJlIG9wZW4gYmxhY2sgd2l0aCBhbHBoYSA9IDEKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygxOSwgMjEpKSArCiAgc2NhbGVfYWxwaGFfbWFudWFsKHZhbHVlcyA9IGMoMC41LCAxKSkgKwogIGxhYnMoCiAgICB4ID0gIkRlbHRhIG1lZGlhbiBzdGF0aXN0aWMiLAogICAgeSA9ICJDZWxsIHR5cGUgYW5ub3RhdGlvbiIsCiAgICBzaGFwZSA9ICJDZWxsIHR5cGUgYW5ub3RhdGlvbiBxdWFsaXR5IgogICkgKwogICMgYWRkIG1lZGlhbiBkaWFtb25kIGZvciBjb25maWRlbnQgcG9pbnRzIG9ubHkKICBzdGF0X3N1bW1hcnkoCiAgICBkYXRhID0gZGVsdGFfbWVkaWFuX2NvbmZpZGVudF9kZiwKICAgIGNvbG9yID0gInJlZCIsCiAgICBnZW9tID0gInBvaW50IiwKICAgIGZ1biA9ICJtZWRpYW4iLAogICAgc2hhcGUgPSAxOCwKICAgIHNpemUgPSAyLjI1LAogICAgYWxwaGEgPSAwLjkKICApICsKICBndWlkZXMoCiAgICBhbHBoYSA9IEZBTFNFLAogICAgc2hhcGUgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gMS41LCBhbHBoYSA9IDAuNTUpKQogICkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICApCmBgYAoKCjwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBDZWxsQXNzaWduIHByb2JhYmlsaXR5IHBsb3QgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CmBgYHtyLCBldmFsID0gaGFzX2NlbGxhc3NpZ259CmtuaXRyOjphc2lzX291dHB1dCgiCiMjIGBDZWxsQXNzaWduYCBhbm5vdGF0aW9ucwoKVG8gYXNzZXNzIHRoZSBxdWFsaXR5IG9mIGBDZWxsQXNzaWduYCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMsIHdlIGNvbnNpZGVyIHRoZSBwcm9iYWJpbGl0eSBhc3NvY2lhdGVkIHdpdGggdGhlIGFubm90YXRlZCBjZWxsIHR5cGUuClRoZXNlIHByb2JhYmlsaXRpZXMgYXJlIHByb3ZpZGVkIGRpcmVjdGx5IGJ5IGBDZWxsQXNzaWduYDoKCi0gYENlbGxBc3NpZ25gIGZpcnN0IGNhbGN1bGF0ZXMgdGhlIHByb2JhYmlsaXR5IG9mIGVhY2ggY2VsbCBiZWluZyBhbm5vdGF0ZWQgYXMgZWFjaCBjZWxsIHR5cGUgcHJlc2VudCBpbiB0aGUgcmVmZXJlbmNlLgotIGBDZWxsQXNzaWduYCB0aGVuIGFubm90YXRlcyBjZWxscyBieSBzZWxlY3RpbmcgdGhlIGNlbGwgdHlwZSB3aXRoIHRoZSBoaWdoZXN0IHByb2JhYmlsaXR5IGFtb25nIGFsbCBjZWxsIHR5cGVzIGNvbnNpZGVyZWQuCi0gVGhlc2UgcHJvYmFiaWxpdGllcyByYW5nZSBmcm9tIDAgdG8gMSwgd2l0aCBsYXJnZXIgdmFsdWVzIGluZGljYXRpbmcgZ3JlYXRlciBjb25maWRlbmNlIGluIGEgZ2l2ZW4gY2VsbCB0eXBlIGxhYmVsLgpXZSB0aGVyZWZvcmUgZXhwZWN0IHJlbGlhYmxlIGxhYmVscyB0byBoYXZlIHZhbHVlcyBjbG9zZSB0byAxLgoKVGhlIHBsb3QgYmVsb3cgc2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiBgQ2VsbEFzc2lnbmAtY2FsY3VsYXRlZCBwcm9iYWJpbGl0aWVzIGZvciB0aGUgZmluYWwgY2VsbCB0eXBlIGxhYmVscy4KTGluZSBzZWdtZW50cyByZXByZXNlbnQgaW5kaXZpZHVhbCB2YWx1ZXMgdGhhdCBjb21wcmlzZSBlYWNoIGRpc3RyaWJ1dGlvbi4KCkZvciBjZWxsIHR5cGVzIHdpdGggMiBvciBmZXdlciBsYWJlbGVkIGNlbGxzLCBvbmx5IHRoZSBpbmRpdmlkdWFsIHZhbHVlIGxpbmUgc2VnbWVudHMgYXJlIHNob3duLgpMaW5lIHNlZ21lbnRzIGFyZSBhbHNvIHRhbGxlciBmb3IgYW55IGNlbGwgdHlwZSBsYWJlbCB3aXRoIDUgb3IgZmV3ZXIgY2VsbHMuCiIpCgojIERldGVybWluZSBoZWlnaHQgaW4gaW5jaGVzIGZvciBwbG90IGFyZWEKcGxvdF9oZWlnaHQgPC0gY2VpbGluZyhsZW5ndGgodW5pcXVlKGNlbGx0eXBlX2RmJGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbikpIC8gMi41KQpgYGAKCgpgYGB7ciwgZXZhbCA9IGhhc19jZWxsYXNzaWduLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBmaWcuaGVpZ2h0ID0gcGxvdF9oZWlnaHQsIGZpZy53aWR0aCA9IDh9CiMgZGVmaW5lIGJhbmR3aWR0aCBmb3IgYWxsIGNhbGN1bGF0aW9ucwpkZW5zaXR5X2J3IDwtIDAuMDMKCiMgZmluZCB0aGUgbWF4aW11bSBkZW5zaXR5IGFjcm9zcyBhbGwgZGlzdHJpYnV0aW9ucywgYW5kCiMgIHNhdmUgdGhlIG1heGltdW0gZm9yIGRldGVybWluaW5nIGdlb21fc2VnbWVudCBoZWlnaHQKeV9tYXggPC0gY2VsbHR5cGVfZGYkY2VsbGFzc2lnbl9tYXhfcHJlZGljdGlvbiB8PgogIHNwbGl0KGNlbGx0eXBlX2RmJGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbikgfD4KICAjIG1ha2Ugc3VyZSB3ZSBnZXQgcmlkIG9mIGFueSBzbWFsbCBncm91cHMKICBwdXJycjo6ZGlzY2FyZChcKHgpIHN1bShpcy5maW5pdGUoeCkpIDw9IDIpIHw+CiAgIyByZW1vdmUgYW55IE5BJ3MgdGhhdCBtYXkgaGF2ZSBzbGlwcGVkIGluCiAgcHVycnI6Om1hcF9kYmwoCiAgICBcKHgpIG1heChkZW5zaXR5KHgsIGJ3ID0gZGVuc2l0eV9idywgbmEucm0gPSBUUlVFKSR5KQogICkgfD4KICBtYXgobmEucm0gPSBUUlVFKQoKIyBhZGQgY291bnQgdG8gY2VsbHR5cGVfZGYgZm9yIHNldHRpbmcgYWxwaGEgYW5kIHllbmQgdmFsdWVzCmNlbGx0eXBlX2RmIDwtIGNlbGx0eXBlX2RmIHw+CiAgZHBseXI6OmFkZF9jb3VudChjZWxsYXNzaWduX2NlbGx0eXBlX2Fubm90YXRpb24pCgojIG1ha2UgdGhlIHBsb3QhCmdncGxvdChjZWxsdHlwZV9kZikgKwogIGFlcyh4ID0gY2VsbGFzc2lnbl9tYXhfcHJlZGljdGlvbikgKwogIGdlb21fZGVuc2l0eSgKICAgIGJ3ID0gZGVuc2l0eV9idywKICAgIGZpbGwgPSAiZ3JleTY1IiwKICAgIGxpbmV3aWR0aCA9IDAuMjUsCiAgICBib3VuZHMgPSBjKDAsIDEpCiAgKSArCiAgZ2VvbV9zZWdtZW50KAogICAgYWVzKAogICAgICAjIHNldCBhbHBoYSB0byB2YXJ5IGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgcG9pbnRzIGluIHRoZSByb3cgc3VjaCB0aGF0CiAgICAgICMgIHJvd3Mgd2l0aCBtb3JlIHBvaW50cyBhcmUgbW9yZSB0cmFuc3BhcmVudAogICAgICBhbHBoYSA9IHBtYXgoMC4yLCAxIC0gMC4wMSAqIG4pLAogICAgICB4ZW5kID0gY2VsbGFzc2lnbl9tYXhfcHJlZGljdGlvbiwKICAgICAgIyBzZXQgeWVuZCBhcyBlaXRoZXIgMCBmb3Igcm93cyB3aXRoIG1hbnkgcG9pbnRzLCBvciB5X21heC8yLjUgZm9yCiAgICAgICMgIHJvd3Mgd2l0aCBmZXcgcG9pbnRzCiAgICAgIHllbmQgPSBpZmVsc2UobiA+IDUsIDAsIHlfbWF4IC8gMi41KSwKICAgICAgeSA9IC1JbmYKICAgICksCiAgICBjb2xvciA9ICJibHVlIgogICkgKwogIGxhYnMoCiAgICB4ID0gIlByb2JhYmlsaXR5IG9mIGFubm90YXRlZCBjZWxsIHR5cGUiLAogICAgeSA9ICJDZWxsIHR5cGUgYW5ub3RhdGlvbiIKICApICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAuMSwgMC4xKSkgKwogIHNjYWxlX2FscGhhX2lkZW50aXR5KCkgKwogIGZhY2V0X2dyaWQoCiAgICByb3dzID0gdmFycyhjZWxsYXNzaWduX2NlbGx0eXBlX2Fubm90YXRpb24pLAogICAgc3dpdGNoID0gInkiCiAgKSArCiAgdGhlbWUoCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dC55LmxlZnQgPSBlbGVtZW50X3RleHQoCiAgICAgIGFuZ2xlID0gMCwKICAgICAgaGp1c3QgPSAxCiAgICApLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMC4wMiwgImluIikKICApCmBgYAoKCiMgU2Vzc2lvbiBJbmZvCjxkZXRhaWxzPgo8c3VtbWFyeT5SIHNlc3Npb24gaW5mb3JtYXRpb248L3N1bW1hcnk+CmBgYHtyIHNlc3Npb25faW5mb30KaWYgKHJlcXVpcmVOYW1lc3BhY2UoInNlc3Npb25pbmZvIiwgcXVpZXRseSA9IFRSVUUpKSB7CiAgc2Vzc2lvbmluZm86OnNlc3Npb25faW5mbygpCn0gZWxzZSB7CiAgc2Vzc2lvbkluZm8oKQp9CmBgYAo8L2RldGFpbHM+Cg==