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
celltype4 1408 25.83%
celltype3 1384 25.39%
celltype2 1353 24.82%
celltype1 1307 23.97%

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+IDkuNSwKICAgIGxvbmdlc3RfbmFtZSA8IDQ1IH4gOC41LAogICAgbG9uZ2VzdF9uYW1lIDwgNjAgfiA3LjUsCiAgICAuZGVmYXVsdCA9IDYuNQogICkKCiAgcmV0dXJuKGxhYmVsc19mb250X3NpemUpCn0KYGBgCgoKYGBge3J9CiMnIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBvcHRpbWFsIGhlYXRtYXAgcGxvdCB2aWV3IGhlaWdodAojJwojJyBAcGFyYW0gcm93X25hbWVzIFZlY3RvciBvZiByb3duYW1lcwojJyBAcGFyYW0gY29sX25hbWVzIFZlY3RvciBvZiBjb2x1bW4gbmFtZXMKIycgQHBhcmFtIG5fc3BhY2VycyBOdW1iZXIgb2Ygc3BhY2VycyBiZXR3ZWVuIHN0YWNrZWQgaGVhdG1hcHMKIycgQHBhcmFtIHNwYWNlcl9zaXplIFNwYWNlciBzaXplIGluIGluY2hlcwojJyBAcGFyYW0gbWluX2hlaWdodCBNaW5pbWl6ZSBoZWlnaHQgcmVxdWlyZWQuIERlZmF1bHQgNCIKIycKIycgQHJldHVybiBIZWF0bWFwIGhlaWdodCBpbiBpbmNoZXMKY2FsY3VsYXRlX3Bsb3RfaGVpZ2h0IDwtIGZ1bmN0aW9uKAogICAgcm93X25hbWVzLAogICAgY29sX25hbWVzLAogICAgbl9zcGFjZXJzLAogICAgc3BhY2VyX3NpemUgPSBoZWF0bWFwX3BhZGRpbmcsCiAgICBtaW5faGVpZ2h0ID0gNCkgewogICMgZmlyc3QsIGJhc2VkIG9uIG51bWJlciBvZiBjZWxscyBpbiByb3dfbmFtZXM6CiAgIyAgIDYgY2VsbCB0eXBlcyB0byBhbiBpbmNoCiAgaGVhdF9oZWlnaHQgPC0gbGVuZ3RoKHJvd19uYW1lcykgLyA2CgogICMgbmV4dCwgYmFzZWQgb24gbmNoYXIgb2YgY29sX25hbWVzOgogICMgICAxMCBjaGFyYWN0ZXJzIHRvIGFuIGluY2gKICAjIHVzaW5nIHN0cmluZ3I6OnN0cl9sZW5ndGgoKSBpbiBjYXNlIGNvbF9uYW1lcyBpcyBhIGZhY3RvciB2ZWN0b3IKICBoZWF0X2hlaWdodCA8LSBoZWF0X2hlaWdodCArIG1heChzdHJpbmdyOjpzdHJfbGVuZ3RoKGNvbF9uYW1lcykpIC8gMTAKCiAgIyBmaW5hbGx5LCBhZGQgaW4gYW55IHBhZGRpbmcKICBoZWF0X2hlaWdodCA8LSBoZWF0X2hlaWdodCArIG5fc3BhY2VycyAqIHNwYWNlcl9zaXplCgogIHJldHVybigKICAgIG1heChjKG1pbl9oZWlnaHQsIGhlYXRfaGVpZ2h0KSkKICApCn0KYGBgCgoKYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CiMgZGVmaW5lIGxpYnJhcnkgYW5kIHNjZSBvYmplY3QKbGlicmFyeV9pZCA8LSBwYXJhbXMkbGlicmFyeQpwcm9jZXNzZWRfc2NlIDwtIHBhcmFtcyRwcm9jZXNzZWRfc2NlCgpsaWJyYXJ5X2lkIDwtICJTQ1BDTDAwMDI5NSIgCnByb2Nlc3NlZF9zY2UgPC0gcmVhZFJEUyhnbHVlOjpnbHVlKCJ7bGlicmFyeV9pZH1fcHJvY2Vzc2VkLnJkcyIpKQptZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsYXNzaWduX3JlZmVyZW5jZV9vcmdhbnMgPC0gIm9yZ2FuIgpwcm9jZXNzZWRfc2NlJHN1Ym1pdHRlcl9jZWxsdHlwZV9hbm5vdGF0aW9uIDwtIHNhbXBsZShjKCJjZWxsdHlwZTEiLCAiY2VsbHR5cGUyIiwgImNlbGx0eXBlMyIsICJjZWxsdHlwZTQiKSwgcmVwbGFjZT1ULCBzaXplID0gbGVuZ3RoKHByb2Nlc3NlZF9zY2Ukc3VibWl0dGVyX2NlbGx0eXBlX2Fubm90YXRpb24pKQogIAojIGNoZWNrIGZvciBhbm5vdGF0aW9uIG1ldGhvZHMKaGFzX3NpbmdsZXIgPC0gInNpbmdsZXIiICVpbiUgbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkY2VsbHR5cGVfbWV0aG9kcwpoYXNfY2VsbGFzc2lnbiA8LSAiY2VsbGFzc2lnbiIgJWluJSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsdHlwZV9tZXRob2RzCmhhc19zdWJtaXR0ZXIgPC0gInN1Ym1pdHRlciIgJWluJSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsdHlwZV9tZXRob2RzCgojIGNoZWNrIGZvciB1bWFwCmhhc191bWFwIDwtICJVTUFQIiAlaW4lIHJlZHVjZWREaW1OYW1lcyhwcm9jZXNzZWRfc2NlKQoKIyB3aGF0IGNlbGx0eXBlcyBhcmUgYXZhaWxhYmxlPwphdmFpbGFibGVfY2VsbHR5cGVzIDwtIGMoCiAgaWZlbHNlKGhhc19zdWJtaXR0ZXIsICJTdWJtaXR0ZXIiLCBOQSksCiAgaWZlbHNlKGhhc19zaW5nbGVyLCAiU2luZ2xlUiIsIE5BKSwKICBpZmVsc2UoaGFzX2NlbGxhc3NpZ24sICJDZWxsQXNzaWduIiwgTkEpCikgfD4KICBuYS5vbWl0KCkgfD4KICBhcy5jaGFyYWN0ZXIoKQoKIyBUaGlzIHZhcmlhYmxlIG5lZWQgdG8gYmUgZGVmaW5lZCBmb3IgZWRnZSBjb25kaXRpb25zIHdoZW4gY2VydGFpbiBjZWxsIHR5cGVzCiMgIGFyZW4ndCBhdmFpbGFibGU6CiMgIFdoZW4gd2UgaGF2ZSBjaHVua3Mgd2l0aCBgZXZhbD08aGFzX21ldGhvZD5gLCBrbml0ciBzZWVtcyB0byBuZWVkIGFsbCBvdGhlcgojICB2YXJpYWJsZXMgdXNlZCBpbiBjaHVuayBwYXJhbXMgZGVmaW5lZCwgaW5jbHVkaW5nIHBsb3QgZGltZW5zaW9uIHZhcmlhYmxlcwojICB3aGljaCB3b3VsZCBoYXZlIG9ubHkgYmVlbiBjcmVhdGVkIGluIGNodW5rcyB3aGljaCBhbHNvIGhhZCBhbiBhc3NvY2lhdGVkCiMgIGV2YWw9PGhhc19tZXRob2Q+YC4gU2luY2UgdGhvc2UgY2h1bmtzIHdvbid0IGhhdmUgYmVlbiBldmFsJ2QgaWYgRkFMU0UsIHdlCiMgIG5lZWQgdG8gZGVmaW5lIHRoaXMgdmFyaWFibGUgdG8gcHJldmVudCBlcnJvcnMsIGJ1dCB0aGlzIHZhbHVlIHdpbGwgbmV2ZXIKIyAgYWN0dWFsbHkgYmUgdXNlZC4KcGxvdF9oZWlnaHQgPC0gMQoKIyBEZXRlcm1pbmUgaWYgbGlicmFyeSBpcyBtdWx0aXBsZXhlZDoKIyAgc2FtcGxlX2lkIHNob3VsZCBiZSBkZWZpbmVkIHdpdGggbGVuZ3RoID4gMQpzYW1wbGVfaWQgPC0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkc2FtcGxlX2lkCmhhc19tdWx0aXBsZXggPC0gbGVuZ3RoKHNhbXBsZV9pZCkgPiAxCmBgYAoKPCEtLSBJZiBtdWx0aXBsZXhlZCwgb3BlbiB3aXRoIHdhcm5pbmcgIC0tPiAKYGBge3IsIGV2YWwgPSBoYXNfbXVsdGlwbGV4LCByZXN1bHRzPSdhc2lzJ30KIyBjb252ZXJ0IHNhbXBsZSBpZCB0byBidWxsZXQgc2VwYXJhdGVkIGxpc3QKbXVsdGlwbGV4X3NhbXBsZXMgPC0gcGFzdGUwKCI8bGk+IiwgcGFzdGUoc2FtcGxlX2lkLCBjb2xsYXBzZSA9ICI8L2xpPjxsaT4iLCAiPC9saT4iKSkKZ2x1ZTo6Z2x1ZSgiCiA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiPgoKIFRoaXMgbGlicmFyeSBpcyBtdWx0aXBsZXhlZCBhbmQgY29udGFpbnMgZGF0YSBmcm9tIG1vcmUgdGhhbiBvbmUgc2FtcGxlLgogRGF0YSBmcm9tIHRoZSBmb2xsb3dpbmcgc2FtcGxlcyBhcmUgaW5jbHVkZWQgaW4gdGhpcyBsaWJyYXJ5OgoKICAgIHttdWx0aXBsZXhfc2FtcGxlc30KCiAgPC9kaXY+CiIpCmBgYAoKVGhpcyByZXBvcnQgY29udGFpbnMgYSBzdW1tYXJ5IG9mIGNlbGwgdHlwZSBhbm5vdGF0aW9uIHJlc3VsdHMgZm9yIGxpYnJhcnkgYHIgbGlicmFyeV9pZGAuClRoZSBnb2FsIG9mIHRoaXMgcmVwb3J0IGlzIHRvIHByb3ZpZGUgbW9yZSBkZXRhaWxlZCBpbmZvcm1hdGlvbiBhYm91dCBjZWxsIHR5cGUgYW5ub3RhdGlvbiByZXN1bHRzIGFzIGFuIGluaXRpYWwgZXZhbHVhdGlvbiBvZiB0aGVpciBxdWFsaXR5IGFuZCByZWxpYWJpbGl0eS4KClBlcmZvcm1pbmcgY2VsbCB0eXBlIGFubm90YXRpb24gaXMgYW4gaW5oZXJlbnRseSBjaGFsbGVuZ2luZyB0YXNrIHdpdGggaGlnaCBsZXZlbHMgb2YgdW5jZXJ0YWludHksIGVzcGVjaWFsbHkgd2hlbiB1c2luZyBhdXRvbWF0ZWQgYW5ub3RhdGlvbiBtZXRob2RzLgpPbmUgd2F5IHRvIGFkZHJlc3MgdGhpcyBpcyB0byB1c2UgbXVsdGlwbGUgY2VsbCB0eXBlIGFubm90YXRpb24gYXBwcm9hY2hlcyBhbmQgY29tcGFyZSB0aGUgcmVzdWx0cywgYXMgd2UgaGF2ZSBiZWd1biB0byBkbyBpbiB0aGlzIHJlcG9ydC4KCldoZW4gbXVsdGlwbGUgbWV0aG9kcyBhbm5vdGF0ZSBhIGdpdmVuIGNlbGwgYXMgdGhlIHNhbWUgb3Igc2ltaWxhciBjZWxsIHR5cGUsIHRoaXMgbWF5IHF1YWxpdGF0aXZlbHkgaW5kaWNhdGUgYSBtb3JlIHJvYnVzdCBhbm5vdGF0aW9uLgoKTm90ZSB0aGF0IHRoZSBjb250ZW50cyBvZiB0aGlzIHJlcG9ydCB3aWxsIHZhcnkgYmFzZWQgb24gd2hpY2ggY2VsbCB0eXBlIGFubm90YXRpb25zIGFyZSBwcmVzZW50LgpGdXJ0aGVyLCBiZSBhd2FyZSB0aGF0IGRpZmZlcmVudCBjZWxsIHR5cGUgYW5ub3RhdGlvbiBtZXRob2RzIG1heSBhc3NpZ24gZGlmZmVyZW50IGxhYmVscyB0byB0aGUgc2FtZSBvciBzaW1pbGFyIGNlbGwgdHlwZSAoZS5nLiwgdGhlIGRpZmZlcmVudCBzdHJpbmcgcmVwcmVzZW50YXRpb25zIGBCIGNlbGwgbmFpdmVgIGFuZCBgTmFpdmUgQiBjZWxsYCksIGR1ZSB0byB1c2Ugb2YgZGlmZmVyZW50IHVuZGVybHlpbmcgcmVmZXJlbmNlIGRhdGFzZXRzLgoKPCEtLU5vdGUgdGhhdCB0aGUgc3BlY2lmaWMgY29udGVudHMgb2YgdGhpcyByZXBvcnQgd2lsbCBkZXBlbmQgb24gd2hpY2ggY2VsbCB0eXBlIGFubm90YXRpb25zIGFyZSBwcmVzZW50Li0tPgoqKlRoaXMgbGlicmFyeSBjb250YWlucyB0aGUgZm9sbG93aW5nIGNlbGwgdHlwZSBhbm5vdGF0aW9uczoqKgoKYGBge3IgcmVzdWx0cz0nYXNpcyd9CiMgYnVpbGQgdXAgdGhpcyBzdHJpbmcgYXMgd2UgZ286Cm1ldGhvZHNfdGV4dCA8LSAiIgoKaWYgKGhhc19zdWJtaXR0ZXIpIHsKICBtZXRob2RzX3RleHQgPC0gZ2x1ZTo6Z2x1ZSgKICAgICJ7bWV0aG9kc190ZXh0fQogICAgKiBTdWJtaXR0ZXItcHJvdmlkZWQgY2VsbCB0eXBlIGFubm90YXRpb24sIGdlbmVyYXRlZCBieSB0aGUgb3JpZ2luYWwgbGFiIHdoaWNoIHByb2R1Y2VkIHRoaXMgZGF0YS5cbiIKICApCn0KCmlmIChoYXNfc2luZ2xlcikgewogIG1ldGhvZHNfdGV4dCA8LSBnbHVlOjpnbHVlKAogICAgInttZXRob2RzX3RleHR9CiAgICAqIEFubm90YXRpb25zIGZyb20gW2BTaW5nbGVSYF0oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL1NpbmdsZVIuaHRtbCksIGEgcmVmZXJlbmNlLWJhc2VkIGFwcHJvYWNoIChbTG9vbmV5IF9ldCBhbC5fIDIwMTldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMDM4L3M0MTU5MC0wMTgtMDI3Ni15KSkuCiAgICBUaGUgYHttZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzaW5nbGVyX3JlZmVyZW5jZX1gIGRhdGFzZXQsIG9idGFpbmVkIGZyb20gdGhlIFtgY2VsbGRleGAgcGFja2FnZV0oaHR0cDovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9kYXRhL2V4cGVyaW1lbnQvaHRtbC9jZWxsZGV4Lmh0bWwpLCB3YXMgdXNlZCBmb3IgcmVmZXJlbmNlIGFubm90YXRpb25zLlxuIgogICkKfQoKaWYgKGhhc19jZWxsYXNzaWduKSB7CiAgb3JnYW5zIDwtIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGxhc3NpZ25fcmVmZXJlbmNlX29yZ2FucyB8PgogICAgc3RyaW5ncjo6c3RyX3RvX2xvd2VyKCkKICAjIHNwbGl0IHVwIGFuZCBhZGQgYW4gYGFuZGAgYmVmb3JlIHRoZSBmaW5hbCBvcmdhbgogIG9yZ2Fuc19zdHJpbmcgPC0gc3RyaW5ncjo6c3RyX3NwbGl0XzEob3JnYW5zLCBwYXR0ZXJuID0gIiwgIikgfD4KICAgIHN0cmluZ3I6OnN0cl9mbGF0dGVuX2NvbW1hKGxhc3QgPSAiLCBhbmQgIikKCiAgcmVmX25hbWUgPC0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkY2VsbGFzc2lnbl9yZWZlcmVuY2UKCiAgbWV0aG9kc190ZXh0IDwtIGdsdWU6OmdsdWUoCiAgICAie21ldGhvZHNfdGV4dH0KICAgICogQW5ub3RhdGlvbnMgZnJvbSBbYENlbGxBc3NpZ25gXShodHRwczovL2dpdGh1Yi5jb20vSXJyYXRpb25vbmUvY2VsbGFzc2lnbiksIGEgbWFya2VyLWdlbmUtYmFzZWQgYXBwcm9hY2ggKFtaaGFuZyBfZXQgYWwuXyAyMDE5XShodHRwczovL2RvaS5vcmcvMTAuMTAzOC9zNDE1OTItMDE5LTA1MjktMSkpLgogICAgTWFya2VyIGdlbmVzIGZvciBjZWxsIHR5cGVzIHdlcmUgb2J0YWluZWQgZnJvbSBbUGFuZ2xhb0RCXShodHRwczovL3BhbmdsYW9kYi5zZS8pIGFuZCBjb21waWxlZCBpbnRvIGEgcmVmZXJlbmNlIG5hbWVkIGB7cmVmX25hbWV9YC4KICAgIFRoaXMgcmVmZXJlbmNlIGluY2x1ZGVzIHRoZSBmb2xsb3dpbmcgb3JnYW5zIGFuZCB0aXNzdWUgY29tcGFydG1lbnRzOiB7b3JnYW5zX3N0cmluZ30uXG4iCiAgKQp9CgpnbHVlOjpnbHVlKCJ7bWV0aG9kc190ZXh0fSIpCmBgYAoKCjwhLS0tLS0tLSBDYWxsIHRoZSBjZWxsdHlwZXNfcWMgcmVwb3J0IHNlY3Rpb24gZnJvbSB0aGUgbWFpbiByZXBvcnQgLS0tLS0tLS0tLS0+CmBgYHtyLCBjaGlsZD0nY2VsbHR5cGVzX3FjLnJtZCd9CmBgYAoKCiMgQ2VsbCBsYWJlbCBjb21wYXJpc29uIHBsb3RzCgpUaGlzIHNlY3Rpb24gZGlzcGxheXMgaGVhdG1hcHMgY29tcGFyaW5nIGNlbGwgbGFiZWxzIGZyb20gdmFyaW91cyBtZXRob2RzLgoKV2UgdXNlIHRoZSBbSmFjY2FyZCBzaW1pbGFyaXR5IGluZGV4XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9KYWNjYXJkX2luZGV4KSB0byBkaXNwbGF5IHRoZSBhZ3JlZW1lbnQgYmV0d2VlbiBiZXR3ZWVuIHBhaXJzIG9mIGxhYmVscyBhc3NpZ25lZCBieSBkaWZmZXJlbnQgYW5ub3RhdGlvbiBtZXRob2RzLgoKVGhlIEphY2NhcmQgaW5kZXggcmVmbGVjdHMgdGhlIGRlZ3JlZSBvZiBvdmVybGFwIGJldHdlZW4gdGhlIHR3byBsYWJlbHMgYW5kIHJhbmdlcyBmcm9tIDAgdG8gMS4KCiogSWYgdGhlIGxhYmVscyBhcmUgYXNzaWduZWQgdG8gaWRlbnRpY2FsIHNldHMgb2YgY2VsbHMsIHRoZSBKYWNjYXJkIGluZGV4IHdpbGwgYmUgMS4KKiBJZiB0aGUgbGFiZWxzIGFyZSBhc3NpZ25lZCB0byBjb21wbGV0ZWx5IG5vbi1vdmVybGFwcGluZyBzZXRzIG9mIGNlbGxzLCB0aGUgSmFjY2FyZCBpbmRleCB3aWxsIGJlIDAuCgpIaWdoIGFncmVlbWVudCBiZXR3ZWVuIG1ldGhvZHMgcXVhbGl0YXRpdmVseSBpbmRpY2F0ZXMgaGlnaGVyIGNvbmZpZGVuY2UgaW4gdGhlIGNlbGwgdHlwZSBhbm5vdGF0aW9uLgoKCgoKCjwhLS0gSWYgbXVsdGlwbGV4ZWQsIHNob3cgaW5mbyBhbGVydCBpbnN0ZWFkIG9mIHRoaXMgaGVhdG1hcCAtLT4gCmBgYHtyLCBldmFsID0gaGFzX211bHRpcGxleCwgcmVzdWx0cz0nYXNpcyd9CmdsdWU6OmdsdWUoIgogPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWluZm9cIj4KCiAgTm8gaGVhdG1hcCBjb21wYXJpbmcgY2x1c3RlciBhbmQgY2VsbCB0eXBlIGFubm90YXRpb24gbGFiZWxzIGlzIHNob3duIGJlY2F1c2UgdGhlIHByZXNlbmNlIG9mIG11bHRpcGxlIHNhbXBsZXMgbWF5IGNvbmZvdW5kIGNsdXN0ZXIgYXNzaWdubWVudC4KCiAgPC9kaXY+CiIpCmBgYAoKPCEtLSBJZiBub3QgbXVsdGlwbGV4ZWQsIHNob3cgdGhlIGhlYWRlciwgdGV4dCwgYW5kIGhlYXRtYXAgLS0+IApgYGB7ciwgZXZhbCA9ICFoYXNfbXVsdGlwbGV4LCByZXN1bHRzPSdhc2lzJ30KZ2x1ZTo6Z2x1ZSgiCiAgIyMgVW5zdXBlcnZpc2VkIGNsdXN0ZXJpbmcKCiAgSGVyZSB3ZSBzaG93IHRoZSBsYWJlbHMgZnJvbSB1bnN1cGVydmlzZWQgY2x1c3RlcmluZyBjb21wYXJlZCB0byBjZWxsIHR5cGUgYW5ub3RhdGlvbnMuCiAgQ2x1c3RlciBhc3NpZ25tZW50IHdhcyBwZXJmb3JtZWQgdXNpbmcgdGhlIGB7bWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkY2x1c3Rlcl9hbGdvcml0aG19YCBhbGdvcml0aG0uCiIpCgojIENhbGN1bGF0ZSBhbGwgamFjY2FyZCBtYXRyaWNlcyBvZiBpbnRlcmVzdCBmb3IgaW5wdXQgdG8gaGVhdG1hcApqYWNjYXJkX2NsdXN0ZXJfbWF0cmljZXMgPC0gYXZhaWxhYmxlX2NlbGx0eXBlcyB8PgogIHN0cmluZ3I6OnN0cl90b19sb3dlcigpIHw+CiAgcHVycnI6OnNldF9uYW1lcyhhdmFpbGFibGVfY2VsbHR5cGVzKSB8PgogIHB1cnJyOjptYXAoXChuYW1lKSB7CiAgICBtYWtlX2phY2NhcmRfbWF0cml4KAogICAgICBjZWxsdHlwZV9kZiwKICAgICAgImNsdXN0ZXIiLAogICAgICBnbHVlOjpnbHVlKCJ7bmFtZX1fY2VsbHR5cGVfYW5ub3RhdGlvbiIpCiAgICApCiAgfSkKCmFsbF9jZWxsdHlwZXMgPC0gamFjY2FyZF9jbHVzdGVyX21hdHJpY2VzIHw+CiAgcHVycnI6Om1hcChjb2xuYW1lcykgfD4KICB1bmxpc3QoKQoKcGxvdF9oZWlnaHQgPC0gY2FsY3VsYXRlX3Bsb3RfaGVpZ2h0KAogIGFsbF9jZWxsdHlwZXMsCiAgdW5pcXVlKGNlbGx0eXBlX2RmJGNsdXN0ZXIpLAogIGxlbmd0aChqYWNjYXJkX2NsdXN0ZXJfbWF0cmljZXMpIC0gMQopCmBgYAoKCmBgYHtyLCBldmFsID0gIWhhc19tdWx0aXBsZXgsIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOC41LCB3YXJuaW5nID0gRkFMU0V9CmphY2NhcmRfY2x1c3Rlcl9tYXRyaWNlcyB8PgogIGNyZWF0ZV9oZWF0bWFwX2xpc3QoCiAgICBjb2x1bW5fdGl0bGUgPSAiQ2x1c3RlcnMiLAogICAgbGFiZWxzX2ZvbnRfc2l6ZSA9IGZpbmRfbGFiZWxfc2l6ZShhbGxfY2VsbHR5cGVzKSwKICAgICMjIGFkZGl0aW9uYWwgYXJndW1lbnRzCiAgICBjb2x1bW5fbmFtZXNfcm90ID0gMAogICkgfD4KICBDb21wbGV4SGVhdG1hcDo6ZHJhdygKICAgIGhlYXRtYXBfbGVnZW5kX3NpZGUgPSAiYm90dG9tIgogICkKYGBgCgoKCjwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gU3VibWl0dGVyIGhlYXRtYXBzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CmBgYHtyLCBldmFsID0gaGFzX3N1Ym1pdHRlciAmIChoYXNfY2VsbGFzc2lnbiB8IGhhc19zaW5nbGVyKX0KIyBkb24ndCBjb21wYXJlIHN1Ym1pdHRlciB0byBzdWJtaXR0ZXIKYXZhaWxhYmxlX2NlbGx0eXBlcyA8LSBhdmFpbGFibGVfY2VsbHR5cGVzWyEoYXZhaWxhYmxlX2NlbGx0eXBlcyA9PSAiU3VibWl0dGVyIildCgptZXRob2RzX3N0cmluZyA8LSBhdmFpbGFibGVfY2VsbHR5cGVzIHw+CiAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCJeIiwgImAiKSB8PgogIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiJCIsICJgIikgfD4KICBzdHJpbmdyOjpzdHJfZmxhdHRlbl9jb21tYSgiLCBhbmQgIikKCmtuaXRyOjphc2lzX291dHB1dCgKICBnbHVlOjpnbHVlKAogICAgIiMjIFN1Ym1pdHRlci1wcm92aWRlZCBhbm5vdGF0aW9ucwoKICBUaGlzIHNlY3Rpb24gZGlzcGxheXMgaGVhdG1hcHMgY29tcGFyaW5nIHN1Ym1pdHRlci1wcm92aWRlZCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMgdG8gdGhvc2Ugb2J0YWluZWQgZnJvbSB7bWV0aG9kc19zdHJpbmd9LiIKICApCikKYGBgCgpgYGB7ciwgZXZhbCA9IGhhc19zdWJtaXR0ZXIgJiAoaGFzX2NlbGxhc3NpZ24gfCBoYXNfc2luZ2xlcil9CiMgY2FsY3VsYXRlIG1hdHJpY2VzIGNvbXBhcmluZyB0byBzdWJtaXR0ZXIKamFjY2FyZF9zdWJtaXR0ZXJfbWF0cmljZXMgPC0gYXZhaWxhYmxlX2NlbGx0eXBlcyB8PgogIHN0cmluZ3I6OnN0cl90b19sb3dlcigpIHw+CiAgcHVycnI6Om1hcChcKG5hbWUpIHsKICAgIG1ha2VfamFjY2FyZF9tYXRyaXgoCiAgICAgIGNlbGx0eXBlX2RmLAogICAgICAic3VibWl0dGVyX2NlbGx0eXBlX2Fubm90YXRpb24iLAogICAgICBnbHVlOjpnbHVlKCJ7bmFtZX1fY2VsbHR5cGVfYW5ub3RhdGlvbiIpCiAgICApCiAgfSkgfD4KICBwdXJycjo6c2V0X25hbWVzKGF2YWlsYWJsZV9jZWxsdHlwZXMpCgojIGhvdyBtYW55IGNlbGwgdHlwZXM/CmFsbF9jZWxsdHlwZXMgPC0gamFjY2FyZF9zdWJtaXR0ZXJfbWF0cmljZXMgfD4KICBwdXJycjo6bWFwKGNvbG5hbWVzKSB8PgogIHVubGlzdCgpCgpwbG90X2hlaWdodCA8LSBjYWxjdWxhdGVfcGxvdF9oZWlnaHQoCiAgYWxsX2NlbGx0eXBlcywKICB1bmlxdWUoY2VsbHR5cGVfZGYkc3VibWl0dGVyX2NlbGx0eXBlX2Fubm90YXRpb24pLAogIGxlbmd0aChqYWNjYXJkX3N1Ym1pdHRlcl9tYXRyaWNlcykgLSAxCikKYGBgCgpgYGB7ciwgZXZhbCA9IGhhc19zdWJtaXR0ZXIgJiAoaGFzX2NlbGxhc3NpZ24gfCBoYXNfc2luZ2xlciksIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOC41LCB3YXJuaW5nID0gRkFMU0V9CmphY2NhcmRfc3VibWl0dGVyX21hdHJpY2VzIHw+CiAgY3JlYXRlX2hlYXRtYXBfbGlzdCgKICAgIGNvbHVtbl90aXRsZSA9ICJTdWJtaXR0ZXItcHJvdmlkZWQgYW5ub3RhdGlvbnMiLAogICAgbGFiZWxzX2ZvbnRfc2l6ZSA9IGZpbmRfbGFiZWxfc2l6ZShhbGxfY2VsbHR5cGVzKSwKICAgICMgYWRkaXRpb25hbCBhcmd1bWVudHMKICAgIGNvbHVtbl9uYW1lc19yb3QgPSA5MAogICkgfD4KICBDb21wbGV4SGVhdG1hcDo6ZHJhdygKICAgIGhlYXRtYXBfbGVnZW5kX3NpZGUgPSAiYm90dG9tIgogICkKYGBgCgoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tIFNpbmdsZVIvQ2VsbEFzc2lnbiBoZWF0bWFwICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfY2VsbGFzc2lnbiAmIGhhc19zaW5nbGVyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD04fQprbml0cjo6YXNpc19vdXRwdXQoIgojIyBBdXRvbWF0ZWQgYW5ub3RhdGlvbnMKClRoaXMgc2VjdGlvbiBkaXNwbGF5cyBhIGhlYXRtYXAgZGlyZWN0bHkgY29tcGFyaW5nIGBTaW5nbGVSYCBhbmQgYENlbGxBc3NpZ25gIGNlbGwgdHlwZSBhbm5vdGF0aW9ucy4KTm90ZSB0aGF0IGR1ZSB0byBkaWZmZXJlbnQgYW5ub3RhdGlvbnMgcmVmZXJlbmNlcywgdGhlc2UgbWV0aG9kcyBtYXkgdXNlIGRpZmZlcmVudCBuYW1lcyBmb3Igc2ltaWxhciBjZWxsIHR5cGVzLgoiKQoKIyBTZXQgcGxvdCBkaW1lbnNpb25zIGJhc2VkIG9uIG51bWJlciBvZiBTaW5nbGVSIGNlbGwgdHlwZXMKYWxsX2NlbGx0eXBlcyA8LSBsZXZlbHMoY2VsbHR5cGVfZGYkc2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uKQpwbG90X2hlaWdodCA8LSBjYWxjdWxhdGVfcGxvdF9oZWlnaHQoCiAgdW5pcXVlKGNlbGx0eXBlX2RmJHNpbmdsZXJfY2VsbHR5cGVfYW5ub3RhdGlvbiksCiAgdW5pcXVlKGNlbGx0eXBlX2RmJGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbiksCiAgMAopCmBgYAoKCmBgYHtyLCBldmFsID0gaGFzX2NlbGxhc3NpZ24gJiBoYXNfc2luZ2xlciwgZmlnLmhlaWdodCA9IHBsb3RfaGVpZ2h0LCBmaWcud2lkdGggPSA4LjV9CiMgQ2FsY3VsYXRlIGphY2NhcmQgbWF0cml4CnNpbmdsZXJfY2VsbGFzc2lnbl9tYXRyaXggPC0gbWFrZV9qYWNjYXJkX21hdHJpeCgKICBjZWxsdHlwZV9kZiwKICAic2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uIiwKICAiY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uIgopCgpjcmVhdGVfc2luZ2xlX2hlYXRtYXAoCiAgc2luZ2xlcl9jZWxsYXNzaWduX21hdHJpeCwKICByb3dfdGl0bGUgPSAiQ2VsbEFzc2lnbiBhbm5vdGF0aW9ucyIsCiAgY29sdW1uX3RpdGxlID0gIlNpbmdsZVIgYW5ub3RhdGlvbnMiLAogIGxhYmVsc19mb250X3NpemUgPSBmaW5kX2xhYmVsX3NpemUoYWxsX2NlbGx0eXBlcyksCiAga2VlcF9sZWdlbmRfbmFtZSA9ICJTaW5nbGVSIGFubm90YXRpb25zIiwKICBjb2xfZnVuID0gaGVhdG1hcF9jb2xfZnVuLAogICMgYWRkaXRpb25hbCBhcmd1bWVudHMKICBjb2x1bW5fbmFtZXNfcm90ID0gOTAKKSB8PgogIENvbXBsZXhIZWF0bWFwOjpkcmF3KAogICAgaGVhdG1hcF9sZWdlbmRfc2lkZSA9ICJib3R0b20iCiAgKQpgYGAKCjwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBEaWFnbm9zdGljIHBsb3RzICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CmBgYHtyLCBldmFsID0gaGFzX3NpbmdsZXIgfCBoYXNfY2VsbGFzc2lnbiB9CmtuaXRyOjphc2lzX291dHB1dCgiCiMgUXVhbGl0eSBhc3Nlc3NtZW50cyBvZiBhdXRvbWF0ZWQgYW5ub3RhdGlvbnMKIikKYGBgCgoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gU2luZ2xlUiBkZWx0YSBtZWRpYW4gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfc2luZ2xlcn0Ka25pdHI6OmFzaXNfb3V0cHV0KCIKIyMgYFNpbmdsZVJgIGFubm90YXRpb25zCgpUbyBhc3Nlc3MgdGhlIHF1YWxpdHkgb2YgYFNpbmdsZVJgIGNlbGwgdHlwZSBhbm5vdGF0aW9ucywgd2UgdXNlIHRoZSBkZWx0YSBtZWRpYW4gc3RhdGlzdGljLgoKLSBEZWx0YSBtZWRpYW4gaXMgY2FsY3VsYXRlZCBmb3IgZWFjaCBjZWxsIGFzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGBTaW5nbGVSYCBzY29yZSBvZiB0aGUgYW5ub3RhdGVkIGNlbGwgdHlwZSBsYWJlbCBhbmQgdGhlIG1lZGlhbiBzY29yZSBvZiB0aGUgb3RoZXIgY2VsbCB0eXBlIGxhYmVscyBpbiB0aGUgcmVmZXJlbmNlIGRhdGFzZXQuCi0gSGlnaGVyIGRlbHRhIG1lZGlhbiB2YWx1ZXMgaW5kaWNhdGUgaGlnaGVyIHF1YWxpdHkgY2VsbCB0eXBlIGFubm90YXRpb25zLgogIC0gVmFsdWVzIGNhbiByYW5nZSBmcm9tIDAtMS4KICAtIE5vdGUgdGhhdCB0aGVyZSBpcyBubyB1bml2ZXJzYWwgdGhyZXNob2xkIGZvciBjYWxsaW5nIGFic29sdXRlIGhpZ2ggdnMuIGxvdyBxdWFsaXR5LCBhcyBkZXNjcmliZWQgaW4gdGhlIFtgU2luZ2xlUmAgYm9vayBzZWN0aW9uIG9uICdBbm5vdGF0aW9uIGRpYWdub3N0aWNzJ10oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL2Jvb2tzL3JlbGVhc2UvU2luZ2xlUkJvb2svYW5ub3RhdGlvbi1kaWFnbm9zdGljcy5odG1sI2Fubm90YXRpb24tZGlhZ25vc3RpY3MpLgoKWW91IGNhbiBpbnRlcnByZXQgdGhpcyBwbG90IGFzIGZvbGxvd3M6CgotIEVhY2ggcG9pbnQgcmVwcmVzZW50cyB0aGUgZGVsdGEgbWVkaWFuIHN0YXRpc3RpYyBvZiBhIGdpdmVuIGNlbGwgd2hvc2UgYFNpbmdsZVJgIGFubm90YXRpb24gaXMgc2hvd24gb24gdGhlIHktYXhpcy4KLSBUaGUgcG9pbnQgc3R5bGUgaW5kaWNhdGVzIGBTaW5nbGVSYCdzIHF1YWxpdHkgYXNzZXNzbWVudCBvZiB0aGUgYW5ub3RhdGlvbjoKICAtIEhpZ2gtcXVhbGl0eSBjZWxsIGFubm90YXRpb25zIGFyZSBzaG93biBhcyBjbG9zZWQgcG9pbnRzLgogIC0gTG93LXF1YWxpdHkgY2VsbCBhbm5vdGF0aW9ucyBhcmUgc2hvd24gYXMgb3BlbiBwb2ludHMuCiAgSW4gb3RoZXIgc2VjdGlvbnMgb2YgdGhpcyByZXBvcnQsIHRoZXNlIGNlbGxzIGFyZSBsYWJlbGVkIGFzIGBVbmtub3duIGNlbGwgdHlwZXNgLgogIC0gRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gaG93IGBTaW5nbGVSYCBjYWxjdWxhdGVzIGFubm90YXRpb24gcXVhbGl0eSwgcGxlYXNlIHJlZmVyIHRvIFt0aGlzIGBTaW5nbGVSYCBkb2N1bWVudGF0aW9uXShodHRwczovL3JkcnIuaW8vYmlvYy9TaW5nbGVSL21hbi9wcnVuZVNjb3Jlcy5odG1sKS4KLSBEaWFtb25kcyByZXByZXNlbnQgdGhlIG1lZGlhbiBvZiB0aGUgZGVsdGEgbWVkaWFuIHN0YXRpc3RpYyBzcGVjaWZpY2FsbHkgYW1vbmcgaGlnaC1xdWFsaXR5IGFubm90YXRpb25zIGZvciB0aGUgZ2l2ZW4gY2VsbCB0eXBlIGFubm90YXRpb24uCiIpCmBgYAoKCmBgYHtyLCBldmFsID0gaGFzX3NpbmdsZXIsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgUHJlcGFyZSBTaW5nbGVSIHNjb3JlcyBmb3IgcGxvdAoKIyBleHRyYWN0IHNjb3JlcyBpbnRvIG1hdHJpeApzaW5nbGVyX3Njb3JlcyA8LSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzaW5nbGVyX3Jlc3VsdCRzY29yZXMKCiMgQ3JlYXRlIGRhdGEgZnJhbWUgZm9yIHBsb3R0aW5nIHdpdGggZGVsdGEgbWVkaWFuIGFuZCB0aGUgZnVsbCAqbm9uLXBydW5lZCogY2VsbCBsYWJlbHMKZGVsdGFfbWVkaWFuX2RmIDwtIHRpYmJsZTo6dGliYmxlKAogIGRlbHRhX21lZGlhbiA9IHJvd01heHMoc2luZ2xlcl9zY29yZXMpIC0gcm93TWVkaWFucyhzaW5nbGVyX3Njb3JlcyksCiAgIyBOZWVkIHRvIGdyYWIgdGhlIG5vbi1wcnVuZWQgbGFiZWwgZm9yIHRoaXMgcGxvdAogIGZ1bGxfbGFiZWxzID0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkc2luZ2xlcl9yZXN1bHQkbGFiZWxzLAogICMgaWYgcHJ1bmVkLmxhYmVscyBhcmUgTkEgPT0+IGxvdyBjb25maWRlbmNlCiAgIyBzbywgbmVnYXRlIGZvciB0aGlzIHZhcmlhYmxlOgogIGNvbmZpZGVudCA9ICFpcy5uYShtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzaW5nbGVyX3Jlc3VsdCRwcnVuZWQubGFiZWxzKQopIHw+CiAgZHBseXI6Om11dGF0ZSgKICAgIGNvbmZpZGVudCA9IGlmZWxzZShjb25maWRlbnQsICJIaWdoLXF1YWxpdHkiLCAiTG93LXF1YWxpdHkiKQogICkKCiMgSWYgb250b2xvZ2llcyB3ZXJlIHVzZWQgZm9yIGBmdWxsX2xhYmVsc2AsIHdlJ2xsIG5lZWQgdG8gbWFwIGJhY2sgdG8gY2VsbCB0eXBlIG5hbWVzCiMgIGZvciB0aGUgcGxvdCBpdHNlbGYuCmlmICgic2luZ2xlcl9jZWxsdHlwZV9vbnRvbG9neSIgJWluJSBuYW1lcyhjZWxsdHlwZV9kZikpIHsKICAjIHdlIHVzZSBpbm5lcl9qb2luIGIvYyB0aGUgYWJvdmUgdGliYmxlIGRvZXMgTk9UIGNvbnRhaW4gIlVua25vd24gY2VsbCB0eXBlIiwgd2hpY2gKICAjICB3ZSBkbyBub3Qgd2FudCB0byBkaXNwbGF5IGhlcmUKICBkZWx0YV9tZWRpYW5fZGYgPC0gZGVsdGFfbWVkaWFuX2RmIHw+CiAgICBkcGx5cjo6aW5uZXJfam9pbigKICAgICAgdGliYmxlOjp0aWJibGUoCiAgICAgICAgZnVsbF9sYWJlbHMgPSBjZWxsdHlwZV9kZiRzaW5nbGVyX2NlbGx0eXBlX29udG9sb2d5LAogICAgICAgIGNlbGx0eXBlID0gY2VsbHR5cGVfZGYkc2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uCiAgICAgICkgfD4gZHBseXI6OmRpc3RpbmN0KCkKICAgICkgfD4KICAgIGRwbHlyOjpzZWxlY3QoLWZ1bGxfbGFiZWxzKQp9IGVsc2UgewogICMgb3RoZXJ3aXNlLCBmdWxsX2xhYmVscyBhbHJlYWR5IGNvbnRhaW4gd2hhdCB3ZSB3YW50IHRvIHBsb3QsIHNvIGp1c3QgcmVuYW1lIGl0CiAgZGVsdGFfbWVkaWFuX2RmIDwtIGRlbHRhX21lZGlhbl9kZiB8PgogICAgZHBseXI6OnJlbmFtZShjZWxsdHlwZSA9IGZ1bGxfbGFiZWxzKQogICMgc3RpbGwgbmVlZCB0byBhZGQgbGV2ZWxzOgogICMgTm90ZSB0aGF0IHRoZSBsZXZlbCAiVW5rbm93biBjZWxsIHR5cGUiIHdpbGwgc3RpbGwgYmUgcHJlc2VudCwgYnV0IHRoZXJlIGlzIG5vIHN1Y2ggdmFsdWUgaW4gdGhlIGRhdGEsIHNvIGl0IHdvbid0IG1hdHRlcgogIGxldmVscyhkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUpIDwtIGxldmVscyhjZWxsdHlwZV9kZiRzaW5nbGVyX2NlbGx0eXBlX2Fubm90YXRpb24pCn0KCiMgRW5zdXJlIHdlIGhhdmUgbm8gIlVua25vd24gY2VsbCB0eXBlIiB2YWx1ZXMgbGVmdDoKaWYgKGFueShkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUgPT0gIlVua25vd24gY2VsbCB0eXBlIikpIHsKICBzdG9wKCJGYWlsZWQgdG8gcHJvY2VzcyBTaW5nbGVSIGRhdGEgZm9yIGRpYWdub3N0aWMgcGxvdC4iKQp9CgojIGFkZCBjb2x1bW4gd2l0aCBvcmRlcmVkIGxldmVscyB3aXRoIHdyYXBwZWQgbGFiZWxzIGZvciB2aXN1YWxpemF0aW9uCmRlbHRhX21lZGlhbl9kZiRhbm5vdGF0aW9uX3dyYXBwZWQgPC0gZmFjdG9yKAogIGRlbHRhX21lZGlhbl9kZiRjZWxsdHlwZSwKICAjIHJldigpIHNvIGxhcmdlIGdyb3VwcyBhcmUgYXQgdGhlIFRPUCBvZiB0aGUgcGxvdAogIGxldmVscyA9IHJldihsZXZlbHMoZGVsdGFfbWVkaWFuX2RmJGNlbGx0eXBlKSksCiAgbGFiZWxzID0gcmV2KHN0cmluZ3I6OnN0cl93cmFwKGxldmVscyhkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUpLCAzMCkpCikKCiMgU3Vic2V0IHRoZSBkYXRhIHRvIGp1c3QgY29uZmlkZW50IHBvaW50cyBmb3IgbWVkaWFuKy8tSVFSCmRlbHRhX21lZGlhbl9jb25maWRlbnRfZGYgPC0gZGVsdGFfbWVkaWFuX2RmIHw+CiAgZHBseXI6OmZpbHRlcihjb25maWRlbnQgPT0gIkhpZ2gtcXVhbGl0eSIpCgojIERldGVybWluZSBoZWlnaHQgZm9yIHBsb3QgYXJlYSBiYXNlZCBvbiBudW1iZXIgb2YgY2VsbHMKcGxvdF9oZWlnaHQgPC0gbGVuZ3RoKHVuaXF1ZShkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUpKSAvIDIuNQpgYGAKCmBgYHtyLCBldmFsID0gaGFzX3NpbmdsZXIsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOH0KIyBQbG90IGRlbHRhX21lZGlhbiBhY3Jvc3MgY2VsbHR5cGVzIGNvbG9yZWQgYnkgcHJ1bmluZwpnZ3Bsb3QoZGVsdGFfbWVkaWFuX2RmKSArCiAgYWVzKAogICAgeCA9IGRlbHRhX21lZGlhbiwKICAgIHkgPSBhbm5vdGF0aW9uX3dyYXBwZWQsCiAgICBzaGFwZSA9IGNvbmZpZGVudCwKICAgIGFscGhhID0gY29uZmlkZW50CiAgKSArCiAgZ2dmb3JjZTo6Z2VvbV9zaW5hKAogICAgc2l6ZSA9IDAuOCwKICAgIGNvbG9yID0gImJsYWNrIiwgIyB3aWxsIGdldCBhcHBsaWVkIHRvIGFsbCBjb25maWRlbnQgcG9pbnRzIGFuZCBub24tY29uZmlkZW50IG91dGxpbmUKICAgIGZpbGwgPSAid2hpdGUiLCAjIHdpbGwgYXBwbHkgdG8gbm9uLWNvbmZpZGVudCBmaWxsIG9ubHkKICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjA1KSAjIEtlZXAgYm90aCB0eXBlcyBvZiBwb2ludHMgbW9zdGx5IGluIGxpbmUKICApICsKICAjIEhhbmRsZSBwb2ludHMgYWVzdGhldGljczoKICAjICBjb25maWRlbnQgYXJlIGNsb3NlZCBibGFjayB3aXRoIGFscGhhID0gMC41CiAgIyAgbm90IGNvbmZpZGVudCBhcmUgb3BlbiBibGFjayB3aXRoIGFscGhhID0gMQogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDE5LCAyMSkpICsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjUsIDEpKSArCiAgbGFicygKICAgIHggPSAiRGVsdGEgbWVkaWFuIHN0YXRpc3RpYyIsCiAgICB5ID0gIkNlbGwgdHlwZSBhbm5vdGF0aW9uIiwKICAgIHNoYXBlID0gIkNlbGwgdHlwZSBhbm5vdGF0aW9uIHF1YWxpdHkiCiAgKSArCiAgIyBhZGQgbWVkaWFuIGRpYW1vbmQgZm9yIGNvbmZpZGVudCBwb2ludHMgb25seQogIHN0YXRfc3VtbWFyeSgKICAgIGRhdGEgPSBkZWx0YV9tZWRpYW5fY29uZmlkZW50X2RmLAogICAgY29sb3IgPSAicmVkIiwKICAgIGdlb20gPSAicG9pbnQiLAogICAgZnVuID0gIm1lZGlhbiIsCiAgICBzaGFwZSA9IDE4LAogICAgc2l6ZSA9IDIuMjUsCiAgICBhbHBoYSA9IDAuOQogICkgKwogIGd1aWRlcygKICAgIGFscGhhID0gRkFMU0UsCiAgICBzaGFwZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAxLjUsIGFscGhhID0gMC41NSkpCiAgKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIgogICkKYGBgCgoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENlbGxBc3NpZ24gcHJvYmFiaWxpdHkgcGxvdCAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfY2VsbGFzc2lnbn0Ka25pdHI6OmFzaXNfb3V0cHV0KCIKIyMgYENlbGxBc3NpZ25gIGFubm90YXRpb25zCgpUbyBhc3Nlc3MgdGhlIHF1YWxpdHkgb2YgYENlbGxBc3NpZ25gIGNlbGwgdHlwZSBhbm5vdGF0aW9ucywgd2UgY29uc2lkZXIgdGhlIHByb2JhYmlsaXR5IGFzc29jaWF0ZWQgd2l0aCB0aGUgYW5ub3RhdGVkIGNlbGwgdHlwZS4KVGhlc2UgcHJvYmFiaWxpdGllcyBhcmUgcHJvdmlkZWQgZGlyZWN0bHkgYnkgYENlbGxBc3NpZ25gOgoKLSBgQ2VsbEFzc2lnbmAgZmlyc3QgY2FsY3VsYXRlcyB0aGUgcHJvYmFiaWxpdHkgb2YgZWFjaCBjZWxsIGJlaW5nIGFubm90YXRlZCBhcyBlYWNoIGNlbGwgdHlwZSBwcmVzZW50IGluIHRoZSByZWZlcmVuY2UuCi0gYENlbGxBc3NpZ25gIHRoZW4gYW5ub3RhdGVzIGNlbGxzIGJ5IHNlbGVjdGluZyB0aGUgY2VsbCB0eXBlIHdpdGggdGhlIGhpZ2hlc3QgcHJvYmFiaWxpdHkgYW1vbmcgYWxsIGNlbGwgdHlwZXMgY29uc2lkZXJlZC4KLSBUaGVzZSBwcm9iYWJpbGl0aWVzIHJhbmdlIGZyb20gMCB0byAxLCB3aXRoIGxhcmdlciB2YWx1ZXMgaW5kaWNhdGluZyBncmVhdGVyIGNvbmZpZGVuY2UgaW4gYSBnaXZlbiBjZWxsIHR5cGUgbGFiZWwuCldlIHRoZXJlZm9yZSBleHBlY3QgcmVsaWFibGUgbGFiZWxzIHRvIGhhdmUgdmFsdWVzIGNsb3NlIHRvIDEuCgpUaGUgcGxvdCBiZWxvdyBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIGBDZWxsQXNzaWduYC1jYWxjdWxhdGVkIHByb2JhYmlsaXRpZXMgZm9yIHRoZSBmaW5hbCBjZWxsIHR5cGUgbGFiZWxzLgpMaW5lIHNlZ21lbnRzIHJlcHJlc2VudCBpbmRpdmlkdWFsIHZhbHVlcyB0aGF0IGNvbXByaXNlIGVhY2ggZGlzdHJpYnV0aW9uLgoKRm9yIGNlbGwgdHlwZXMgd2l0aCAyIG9yIGZld2VyIGxhYmVsZWQgY2VsbHMsIG9ubHkgdGhlIGluZGl2aWR1YWwgdmFsdWUgbGluZSBzZWdtZW50cyBhcmUgc2hvd24uCkxpbmUgc2VnbWVudHMgYXJlIGFsc28gdGFsbGVyIGZvciBhbnkgY2VsbCB0eXBlIGxhYmVsIHdpdGggNSBvciBmZXdlciBjZWxscy4KIikKCiMgRGV0ZXJtaW5lIGhlaWdodCBpbiBpbmNoZXMgZm9yIHBsb3QgYXJlYQpwbG90X2hlaWdodCA8LSBjZWlsaW5nKGxlbmd0aCh1bmlxdWUoY2VsbHR5cGVfZGYkY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uKSkgLyAyLjUpCmBgYAoKCmBgYHtyLCBldmFsID0gaGFzX2NlbGxhc3NpZ24sIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOH0KIyBkZWZpbmUgYmFuZHdpZHRoIGZvciBhbGwgY2FsY3VsYXRpb25zCmRlbnNpdHlfYncgPC0gMC4wMwoKIyBmaW5kIHRoZSBtYXhpbXVtIGRlbnNpdHkgYWNyb3NzIGFsbCBkaXN0cmlidXRpb25zLCBhbmQKIyAgc2F2ZSB0aGUgbWF4aW11bSBmb3IgZGV0ZXJtaW5pbmcgZ2VvbV9zZWdtZW50IGhlaWdodAp5X21heCA8LSBjZWxsdHlwZV9kZiRjZWxsYXNzaWduX21heF9wcmVkaWN0aW9uIHw+CiAgc3BsaXQoY2VsbHR5cGVfZGYkY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uKSB8PgogICMgbWFrZSBzdXJlIHdlIGdldCByaWQgb2YgYW55IHNtYWxsIGdyb3VwcwogIHB1cnJyOjpkaXNjYXJkKFwoeCkgc3VtKGlzLmZpbml0ZSh4KSkgPD0gMikgfD4KICAjIHJlbW92ZSBhbnkgTkEncyB0aGF0IG1heSBoYXZlIHNsaXBwZWQgaW4KICBwdXJycjo6bWFwX2RibCgKICAgIFwoeCkgbWF4KGRlbnNpdHkoeCwgYncgPSBkZW5zaXR5X2J3LCBuYS5ybSA9IFRSVUUpJHkpCiAgKSB8PgogIG1heChuYS5ybSA9IFRSVUUpCgojIGFkZCBjb3VudCB0byBjZWxsdHlwZV9kZiBmb3Igc2V0dGluZyBhbHBoYSBhbmQgeWVuZCB2YWx1ZXMKY2VsbHR5cGVfZGYgPC0gY2VsbHR5cGVfZGYgfD4KICBkcGx5cjo6YWRkX2NvdW50KGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbikKCiMgbWFrZSB0aGUgcGxvdCEKZ2dwbG90KGNlbGx0eXBlX2RmKSArCiAgYWVzKHggPSBjZWxsYXNzaWduX21heF9wcmVkaWN0aW9uKSArCiAgZ2VvbV9kZW5zaXR5KAogICAgYncgPSBkZW5zaXR5X2J3LAogICAgZmlsbCA9ICJncmV5NjUiLAogICAgbGluZXdpZHRoID0gMC4yNSwKICAgIGJvdW5kcyA9IGMoMCwgMSkKICApICsKICBnZW9tX3NlZ21lbnQoCiAgICBhZXMoCiAgICAgICMgc2V0IGFscGhhIHRvIHZhcnkgYmFzZWQgb24gdGhlIG51bWJlciBvZiBwb2ludHMgaW4gdGhlIHJvdyBzdWNoIHRoYXQKICAgICAgIyAgcm93cyB3aXRoIG1vcmUgcG9pbnRzIGFyZSBtb3JlIHRyYW5zcGFyZW50CiAgICAgIGFscGhhID0gcG1heCgwLjIsIDEgLSAwLjAxICogbiksCiAgICAgIHhlbmQgPSBjZWxsYXNzaWduX21heF9wcmVkaWN0aW9uLAogICAgICAjIHNldCB5ZW5kIGFzIGVpdGhlciAwIGZvciByb3dzIHdpdGggbWFueSBwb2ludHMsIG9yIHlfbWF4LzIuNSBmb3IKICAgICAgIyAgcm93cyB3aXRoIGZldyBwb2ludHMKICAgICAgeWVuZCA9IGlmZWxzZShuID4gNSwgMCwgeV9tYXggLyAyLjUpLAogICAgICB5ID0gLUluZgogICAgKSwKICAgIGNvbG9yID0gImJsdWUiCiAgKSArCiAgbGFicygKICAgIHggPSAiUHJvYmFiaWxpdHkgb2YgYW5ub3RhdGVkIGNlbGwgdHlwZSIsCiAgICB5ID0gIkNlbGwgdHlwZSBhbm5vdGF0aW9uIgogICkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMC4xLCAwLjEpKSArCiAgc2NhbGVfYWxwaGFfaWRlbnRpdHkoKSArCiAgZmFjZXRfZ3JpZCgKICAgIHJvd3MgPSB2YXJzKGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbiksCiAgICBzd2l0Y2ggPSAieSIKICApICsKICB0aGVtZSgKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgKICAgICAgYW5nbGUgPSAwLAogICAgICBoanVzdCA9IDEKICAgICksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgwLjAyLCAiaW4iKQogICkKYGBgCgoKIyBTZXNzaW9uIEluZm8KPGRldGFpbHM+CjxzdW1tYXJ5PlIgc2Vzc2lvbiBpbmZvcm1hdGlvbjwvc3VtbWFyeT4KYGBge3Igc2Vzc2lvbl9pbmZvfQppZiAocmVxdWlyZU5hbWVzcGFjZSgic2Vzc2lvbmluZm8iLCBxdWlldGx5ID0gVFJVRSkpIHsKICBzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkKfSBlbHNlIHsKICBzZXNzaW9uSW5mbygpCn0KYGBgCjwvZGV0YWlscz4K