In one breath. Pooling nine randomised trials gives a headline “stroke units save ~15 days,” but the confidence interval crosses zero and the trials disagree almost completely (I² ≈ 97%). That disagreement is not noise — the benefit scales with how sick the patients are. Where strokes are severe and stays are long, stroke units help enormously; where stays are already short, they barely move the needle. The professional deliverable here is not a single pooled number — it is the explanation for why one pooled number would mislead.

1 How to read this document

New to R? Read this once and everything below will click. Already fluent? Skip straight to the next section.

Each grey box is a code chunk — the exact instructions R runs. Under most chunks sits a purple Plain-English walkthrough that translates the code, piece by piece. A little recurring grammar unlocks all of it:

  • A function is a command that does a job; you call it by its name followed by round brackets, e.g. forest(...). Whatever you put inside the brackets are its arguments — the settings you hand the command.
  • <- means “save this as.” m <- metacont(...) runs metacont and keeps the result in a box named m; afterwards we just write m to reuse it.
  • $ reaches inside a result to grab one piece: m$TE.random = “the pooled estimate stored inside m.”
  • |> is the pipe. It takes whatever is on its left and feeds it into the function on its right, so a chain reads left-to-right instead of inside-out.
  • Some sentences contain a snippet written as an r followed by a short expression, all wrapped in back-ticks. That is inline code: R replaces it with the live number when the report is built, so the words and the numbers can never disagree.
  • Packages (meta, metafor, …) are toolboxes we load once at the top; each hands us ready-made functions so we never reinvent them.

2 The clinical question

We compared organised stroke-unit care — a dedicated ward with a specialist multidisciplinary team — against conventional care on a general ward, measuring length of hospital stay, in days.

PICOP stroke inpatients · I organised stroke-unit care · C conventional general-ward care · O length of stay (days).

Lower is better: a negative Mean Difference means the stroke unit sends patients home sooner.

3 The data

Nine randomised trials assembled by Normand (1999) [1]. Each row is one trial, with the mean, SD, and sample size for both arms.

data(dat.normand1999, package = "metafor")
d <- dat.normand1999   # source = trial label; 1 = stroke unit, 2 = conventional

kable(
  d[, c("source", "n1i", "m1i", "sd1i", "n2i", "m2i", "sd2i")],
  col.names = c("Trial", "N", "Mean", "SD", "N", "Mean", "SD"),
  caption = "Length of hospital stay (days) by trial and arm."
) |>
  add_header_above(c(" " = 1, "Stroke unit" = 3, "Conventional" = 3)) |>
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE)
Length of hospital stay (days) by trial and arm.
Stroke unit
Conventional
Trial N Mean SD N Mean SD
Edinburgh 155 55 47 156 75 64
Orpington-Mild 31 27 7 32 29 4
Orpington-Moderate 75 64 17 71 119 29
Orpington-Severe 18 66 20 18 137 48
Montreal-Home 8 14 8 13 18 11
Montreal-Transfer 57 19 7 52 18 4
Newcastle 34 52 45 33 41 34
Umea 110 21 16 183 31 27
Uppsala 60 30 27 52 23 20

Plain-English walkthrough.

  • data(dat.normand1999, package = "metafor") loads a ready-made example dataset that ships inside the metafor toolbox.
  • d <- dat.normand1999 copies it into a short name, d, that is quicker to type from here on.
  • d[, c("source", "n1i", ...)] picks out just the columns we want to display, and kable(...) turns them into a tidy table.
  • col.names = c(...) gives the columns human-friendly headers, and caption = ... puts a title above the table.
  • The |> pipe then passes that table on to add_header_above() (which adds the “Stroke unit / Conventional” spanning row) and to kable_styling() (the striped, hover-highlight look).

How to read the columns. The suffix 1 is the intervention arm (stroke unit); 2 is the control arm (conventional care). Within each arm: n = sample size, m = mean length of stay, sd = standard deviation. (The trailing i in n1i/m1i/… is simply metafor’s naming convention and carries no analytic meaning.)

Two things are already visible and will matter later: conventional-care stay ranges from 18 to 137 days — a nearly ten-fold spread — and three of the trials come from a single centre (Orpington), deliberately split by stroke severity.

4 The analysis

We pool the trials as a Mean Difference under a random-effects model, estimating the between-study variance by REML and using the Hartung–Knapp adjustment for the confidence interval [3] — the modern default that guards against over-precise intervals when trials are few and heterogeneous.

m <- metacont(
  n1i, m1i, sd1i,               # stroke-unit arm
  n2i, m2i, sd2i,               # conventional arm
  studlab = source, data = d,
  sm               = "MD",      # effect measure: Mean Difference
  random           = TRUE,      # random-effects model
  common           = FALSE,
  method.tau       = "REML",
  method.random.ci = "HK",      # Hartung-Knapp confidence interval
  prediction       = TRUE,
  label.e = "Stroke unit", label.c = "Conventional"
)
summary(m)
##                          MD               95%-CI %W(random)
## Edinburgh          -20.0000 [-32.4744;  -7.5256]       11.0
## Orpington-Mild      -2.0000 [ -4.8271;   0.8271]       11.7
## Orpington-Moderate -55.0000 [-62.7656; -47.2344]       11.4
## Orpington-Severe   -71.0000 [-95.0223; -46.9777]        9.6
## Montreal-Home       -4.0000 [-12.1539;   4.1539]       11.4
## Montreal-Transfer    1.0000 [ -1.1176;   3.1176]       11.7
## Newcastle           11.0000 [ -8.0620;  30.0620]       10.3
## Umea               -10.0000 [-14.9237;  -5.0763]       11.6
## Uppsala              7.0000 [ -1.7306;  15.7306]       11.4
## 
## Number of studies: k = 9
## Number of observations: o = 1158 (o.e = 548, o.c = 610)
## 
##                            MD              95%-CI     t p-value
## Random effects model -15.1060 [-36.3187;  6.1067] -1.64  0.1392
## Prediction interval           [-78.8739; 48.6618]              
## 
## Quantifying heterogeneity (with 95%-CIs):
##  tau^2 = 684.6462 [292.9181; 2889.4513]; tau = 26.1657 [17.1149; 53.7536]
##  I^2 = 96.7% [95.2%; 97.7%]; H = 5.46 [4.54; 6.58]
## 
## Test of heterogeneity:
##       Q d.f.  p-value
##  238.92    8 < 0.0001
## 
## Details of meta-analysis methods:
## - Inverse variance method
## - Restricted maximum-likelihood estimator for tau^2
## - Q-Profile method for confidence interval of tau^2 and tau
## - Calculation of I^2 based on Q
## - Hartung-Knapp adjustment for random effects model (df = 8)
## - Prediction interval based on t-distribution (df = 8)

Plain-English walkthrough — metacont(). The name is short for meta-analysis of a continuous outcome. It takes each trial’s six summary numbers and pools them into one result. Reading its arguments in order:

  • n1i, m1i, sd1i then n2i, m2i, sd2i — the six columns it needs: sample size, mean, and standard deviation for the stroke-unit arm (1), then the same three for the conventional arm (2).
  • studlab = source — which column holds the trial name to print on each row.
  • data = d — the table where all those columns live.
  • sm = "MD" — the summary measure. “MD” = Mean Difference; because both arms are measured in the same unit (days), we can simply subtract them.
  • random = TRUE — produce the random-effects result, which allows the true effect to genuinely differ from trial to trial.
  • common = FALSE — hide the fixed-effect (“common effect”) result, which would pretend every trial is estimating one identical number.
  • method.tau = "REML" — the recipe for estimating how much the trials differ (the between-study variance, τ²). REML is the modern default.
  • method.random.ci = "HK" — use the Hartung–Knapp confidence interval, which stays honest (appropriately wide) when trials are few and disagree.
  • prediction = TRUE — also compute the prediction interval: the range a brand-new trial might plausibly fall in.
  • label.e / label.c — readable names for the experimental and control arms, used later on the plot.

Then summary(m) prints everything metacont just calculated.

5 The forest plot

forest(
  m,
  sortvar             = TE,
  leftcols            = c("studlab", "n.e", "mean.e", "sd.e", "n.c", "mean.c", "sd.c"),
  leftlabs            = c("Trial", "Total", "Mean", "SD", "Total", "Mean", "SD"),
  rightcols           = c("effect", "ci", "w.random"),
  rightlabs           = c("MD", "95% CI", "Weight"),
  label.e             = "Stroke unit", label.c = "Conventional",
  col.diamond         = "darkred",  col.diamond.lines = "black",
  col.square          = "steelblue3", col.square.lines = "steelblue3",
  common = FALSE, random = TRUE, overall = TRUE, overall.hetstat = TRUE,
  prediction          = TRUE,                # 95% prediction interval (red bar)
  spacing             = 1.2,
  colgap              = unit(3, "mm"),
  colgap.forest.left  = unit(0, "mm"),
  colgap.forest.right = unit(1, "mm"),
  xlab                = "Favours stroke unit          Favours conventional",
  squaresize = 0.8,
  digits = 1, digits.mean = 1, digits.sd = 1,
  digits.pval = 2, digits.pval.Q = 2, digits.I2 = 1, digits.tau2 = 1,
  fontsize = 11, fs.heading = 12, fs.study = 11, fs.random = 11,
  fs.hetstat = 10, fs.axis = 10, fs.xlab = 12, fs.smlab = 12,
  col.hetstat = "gray50"
)
Forest plot showing wide disagreement across the nine stroke-unit trials, with a pooled diamond whose confidence interval crosses the line of no effect.

Forest plot of the nine trials. Squares are trial-level mean differences (size <U+221D> weight); the red diamond is the random-effects pooled estimate and the red bar is the 95% prediction interval.

Plain-English walkthrough — forest(). forest(m, ...) draws the classic forest plot from the pooled object m. There are many arguments, but they only do a handful of jobs:

  • What to show, and where. leftcols / leftlabs list the columns (and their headers) down the left side; rightcols / rightlabs do the same on the right (the effect, its CI, and each trial’s weight). sortvar = TE orders the trials by effect size.
  • The overall result. random = TRUE, common = FALSE, overall, and overall.hetstat show the random-effects diamond and the heterogeneity statistics; prediction = TRUE adds the red prediction-interval bar.
  • Colours & sizes. col.diamond, col.square, squaresize, spacing, and the colgap* arguments are pure cosmetics — the diamond colour, the box colour, how big the boxes are, and the gaps between columns.
  • Rounding. Every digits* argument sets how many decimals a given number shows (e.g. digits = 1 → one decimal place for the effects).
  • Font sizes. fontsize is the baseline; each fs.* fine-tunes one element (heading, study rows, heterogeneity line, axis, labels).
  • xlab = "Favours stroke unit … Favours conventional" labels which side of the vertical line is the good-news side.

In short: the first few arguments decide the plot’s content, and the long tail of col.*, fs.*, and digits.* simply polishes its appearance.

6 What the numbers are telling us

res <- data.frame(
  Metric = c("Pooled MD (random effects)", "95% confidence interval",
             "95% prediction interval", "I² (inconsistency)",
             "τ² (between-trial variance)", "Cochran's Q (p-value)"),
  Value = c(
    sprintf("%.1f days", m$TE.random),
    sprintf("%.1f to %.1f days", m$lower.random, m$upper.random),
    sprintf("%.1f to %.1f days", m$lower.predict, m$upper.predict),
    sprintf("%.0f%%", m$I2 * 100),
    sprintf("%.1f", m$tau2),
    format.pval(m$pval.Q, digits = 2, eps = 0.001)
  )
)
kable(res, col.names = c("", "Result"),
      caption = "Random-effects summary.") |>
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Random-effects summary.
Result
Pooled MD (random effects) -15.1 days
95% confidence interval -36.3 to 6.1 days
95% prediction interval -78.9 to 48.7 days
I<U+00B2> (inconsistency) 97%
<U+03C4><U+00B2> (between-trial variance) 684.6
Cochran’s Q (p-value) <0.001

Plain-English walkthrough. This chunk builds the summary table by hand so we control exactly what appears.

  • data.frame(Metric = ..., Value = ...) makes a two-column table: the labels on the left, the formatted results on the right.
  • sprintf("%.1f days", m$TE.random) is text formatting: %.1f means “a number with one decimal,” so the pooled estimate prints as, e.g., -15.1 days. Each value is pulled straight from the model with $ (m$TE.random, m$I2, m$tau2, …), so the table can never drift away from the analysis.
  • format.pval(..., eps = 0.001) prints very small p-values neatly as < 0.001 instead of a long string of zeros.
  • kable() |> kable_styling() renders and styles the table, just as before.

The pooled estimate of -15.1 days looks impressive, but two signals stop us from reporting it:

  1. The 95% confidence interval (-36.3 to 6.1) crosses zero — the pooled effect is not statistically distinguishable from “no difference.”
  2. I² is 97% [5] — the trials essentially do not agree. The 95% prediction interval [7], -78.9 to 48.7 days, makes this concrete: a new trial could plausibly land anywhere from a large benefit to a large harm.

When a prediction interval is that wide, a single pooled number is not a finding — it is an average of things that don’t belong together. So we don’t report it. We ask why the trials disagree.

7 Hunting for the cause

The trial labels hint at the answer. Three trials come from one centre (Orpington) split by stroke severity; the rest span different countries and health systems, and length of stay depends heavily on both case-mix and how each system manages discharge. Because conventional-care stay ranges from 18 to 137 days, a natural question is whether baseline stay explains the disagreement. We test it with a meta-regression.

mr <- metareg(m, ~ m2i)   # does control-arm mean explain the between-trial MD?
mr
## 
## Mixed-Effects Model (k = 9; tau^2 estimator: REML)
## 
## tau^2 (estimated amount of residual heterogeneity):     18.4346 (SE = 17.2577)
## tau (square root of estimated tau^2 value):             4.2936
## I^2 (residual heterogeneity / unaccounted variability): 72.19%
## H^2 (unaccounted variability / sampling variability):   3.60
## R^2 (amount of heterogeneity accounted for):            97.31%
## 
## Test for Residual Heterogeneity:
## QE(df = 7) = 19.1945, p-val = 0.0076
## 
## Test of Moderators (coefficient 2):
## F(df1 = 1, df2 = 7) = 68.4411, p-val < .0001
## 
## Model Results:
## 
##          estimate      se     tval  df    pval    ci.lb    ci.ub      
## intrcpt   12.5103  3.6203   3.4556   7  0.0106   3.9497  21.0709    * 
## m2i       -0.5505  0.0665  -8.2729   7  <.0001  -0.7079  -0.3932  *** 
## 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Plain-English walkthrough — metareg(). A meta-regression asks whether some trait of the trials explains why their results disagree.

  • metareg(m, ~ m2i) — take the pooled object m and test one predictor. The ~ m2i part is an R formula; read it as “explain the effect using m2i” (the control-arm mean — i.e. baseline length of stay).
  • Printing mr reports the slope (how much the effect shifts per extra baseline day), its p-value, and — the share of the between-trial disagreement that this one predictor accounts for.

Baseline stay explains almost all of the between-trial variation (R² ≈ 97%, slope p < 0.001): trials where patients would otherwise stay a long time (severe strokes) show the biggest reductions, while trials with already-short stays show almost none. The heterogeneity was never noise — it was baseline-dependence.

Read this before believing it. Regressing the Mean Difference on the control-group mean is exploratory, not confirmatory. The control mean is part of the outcome itself (MD = intervention − control), so the two are mathematically linked and part of this association is built in. Treat it as hypothesis-generating, not proof.

8 A cleaner test: the Orpington severity gradient

The caveat above has a clean answer. Instead of baseline stay — which is tangled with the outcome — we use an independent moderator: pre-randomisation stroke severity. The three Orpington trials are ideal, because they hold the hospital, team, and health system constant and vary only by severity.

orp <- subset(d, grepl("Orpington", source))
orp$severity <- c("Mild", "Moderate", "Severe")
orp$MD <- orp$m1i - orp$m2i    # stroke unit - conventional

kable(orp[, c("severity", "m1i", "m2i", "MD")],
      col.names = c("Stroke severity", "Stroke-unit mean",
                    "Conventional mean", "Mean difference (days)"),
      caption = "Orpington trials — same centre, same team, severity the only difference.") |>
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Orpington trials <u+2014> same centre, same team, severity the only difference.</u+2014>
Stroke severity Stroke-unit mean Conventional mean Mean difference (days)
2 Mild 27 29 -2
3 Moderate 64 119 -55
4 Severe 66 137 -71

Plain-English walkthrough.

  • subset(d, grepl("Orpington", source)) — keep only the rows whose source name contains the text “Orpington.” grepl() is a text search that returns TRUE/FALSE for every row, and subset() keeps the TRUE ones.
  • orp$severity <- c("Mild", "Moderate", "Severe") — add a new column by hand, labelling those three rows.
  • orp$MD <- orp$m1i - orp$m2i — compute each trial’s mean difference directly (stroke-unit mean minus conventional mean) — the very subtraction metacont does internally.
  • kable(...) |> kable_styling(...) — display it as a tidy table.

Holding the system fixed, the mean difference goes from -2 days (mild) → -55 days (moderate) → -71 days (severe). A clean, monotonic dose–response on an independent clinical characteristic — exactly the confirmatory signal the baseline-stay regression could only hint at.

This is the defensible version of the story: severity is clinically meaningful, available in the source trials, and not mathematically bound to the outcome. In a real review, we would pre-specify it as the moderator and extract it during data collection.

9 Sensitivity: is any single trial driving the result?

Before drawing conclusions, we check that no one trial is doing all the work, by re-pooling with each trial removed in turn (leave-one-out).

forest(metainf(m, pooled = "random"),
       col.square = "steelblue3", col.diamond = "darkred",
       fontsize = 11)
Leave-one-out forest plot; the pooled estimate stays negative but modest regardless of which trial is removed.

Leave-one-out analysis: the pooled estimate re-computed with each trial omitted.

Plain-English walkthrough — metainf(). metainf(m, pooled = "random") re-runs the random-effects pool nine times — each run leaving one trial out (“inf” is short for influence). Wrapping it in forest(...) draws one row per omission, so you can see at a glance whether dropping any single trial would change the conclusion.

The pooled estimate stays in a narrow band (roughly −9 to −18 days) and never crosses to favouring conventional care, so no single trial is fabricating the signal. The two omissions that pull the estimate toward zero are the Orpington-Moderate and Orpington-Severe trials — which is not fragility, but the same message again: the high-severity trials carry the benefit.

10 A note on small-study effects

With only 9 trials, a funnel plot and Egger’s test are underpowered and easily misread — guidance is not to test for small-study effects below ~10 studies, and severe heterogeneity makes an asymmetry test uninterpretable here anyway [5]. We therefore state the limitation explicitly rather than present a plot that cannot support a conclusion. Naming this is the honest, rigorous move.

11 What we learned

  • The naive headline — “stroke units save 15 days” — is not supported: the CI crosses zero and I² is 97%.
  • The disagreement is not noise. The benefit depends on baseline severity: largest where conventional stays are longest (severe strokes), minimal where they are already short — confirmed cleanly within the Orpington centre.
  • The result is robust to leave-one-out, and small-study-effect testing is correctly withheld at this sample size.
  • Transferable method habits: (1) pick the effect measure from the outcome (MD for a shared scale); (2) default to random-effects + Hartung–Knapp;
    1. read the prediction interval, not just the CI; (4) explain heterogeneity before quoting any pooled number; and (5) prefer a moderator that is independent of the outcome.

12 Real-world validation

This teaching result echoes the definitive evidence: the Cochrane Stroke Unit Trialists’ Collaboration review found that organised stroke-unit care improves outcomes, with effects that vary by patient severity and care setting [4] — reassurance that the analytic story here points the same way as the full body of trials.

13 Reproducibility & data availability

  • Data: dat.normand1999 from the metafor package (Normand 1999) [1;6] — no private data; the analysis is fully reproducible from this document.
  • Code: every figure and number is generated in-line from the fitted model (no hard-coded results). Use the Code ▸ Download Rmd button (top-right) to get the source.
  • Environment: exact package versions are recorded in the appendix below.

14 References

  1. Normand SL. Meta-analysis: formulating, evaluating, combining, and reporting. Stat Med. 1999;18(3):321–359.
  2. Balduzzi S, Rücker G, Schwarzer G. How to perform a meta-analysis with R: a practical tutorial. Evid Based Ment Health. 2019;22(4):153–160. (the meta package)
  3. IntHout J, Ioannidis JPA, Borm GF. The Hartung–Knapp–Sidik–Jonkman method for random-effects meta-analysis is straightforward and considerably outperforms the standard DerSimonian–Laird method. BMC Med Res Methodol. 2014;14:25.
  4. Stroke Unit Trialists’ Collaboration. Organised inpatient (stroke unit) care for stroke. Cochrane Database Syst Rev. 2013;(9):CD000197.
  5. Higgins JPT, Thompson SG. Quantifying heterogeneity in a meta-analysis. Stat Med. 2002;21(11):1539–1558.
  6. Viechtbauer W. Conducting meta-analyses in R with the metafor package. J Stat Softw. 2010;36(3):1–48.
  7. IntHout J, Ioannidis JPA, Rovers MM, Goeman JJ. Plea for routinely presenting prediction intervals in meta-analysis. BMJ Open. 2016;6:e010247.

Appendix: session information

Plain-English walkthrough. sessionInfo() prints the exact R version and the version of every package used. Including it lets anyone rerun this analysis with the same tools and get the same numbers — a hallmark of trustworthy work.

sessionInfo()
## R version 4.5.2 (2025-10-31)
## Platform: x86_64-apple-darwin20
## Running under: macOS Sequoia 15.7.7
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
## 
## locale:
## [1] C
## 
## time zone: Africa/Cairo
## tzcode source: internal
## 
## attached base packages:
## [1] grid      stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
## [1] kableExtra_1.4.0 knitr_1.51       meta_8.3-0       metadat_1.4-0   
## [5] metabook_0.2-0  
## 
## loaded via a namespace (and not attached):
##  [1] sass_0.4.10         generics_0.1.4      xml2_1.5.2         
##  [4] stringi_1.8.7       lattice_0.22-7      hms_1.1.4          
##  [7] lme4_1.1-37         digest_0.6.39       magrittr_2.0.5     
## [10] evaluate_1.0.5      RColorBrewer_1.1-3  CompQuadForm_1.4.4 
## [13] fastmap_1.2.0       jsonlite_2.0.0      Matrix_1.7-4       
## [16] purrr_1.2.2         viridisLite_0.4.2   scales_1.4.0       
## [19] textshaping_1.0.4   numDeriv_2016.8-1.1 jquerylib_0.1.4    
## [22] reformulas_0.4.1    Rdpack_2.6.4        cli_3.6.6          
## [25] rlang_1.2.0         rbibutils_2.3       splines_4.5.2      
## [28] cachem_1.1.0        yaml_2.3.12         otel_0.2.0         
## [31] tools_4.5.2         tzdb_0.5.0          nloptr_2.2.1       
## [34] minqa_1.2.8         metafor_4.8-0       dplyr_1.2.1        
## [37] ggplot2_4.0.3       mathjaxr_1.8-0      boot_1.3-32        
## [40] vctrs_0.7.3         R6_2.6.1            lifecycle_1.0.5    
## [43] stringr_1.6.0       MASS_7.3-65         pkgconfig_2.0.3    
## [46] pillar_1.11.1       bslib_0.10.0        gtable_0.3.6       
## [49] glue_1.8.1          Rcpp_1.1.1-1.1      systemfonts_1.3.1  
## [52] xfun_0.57           tibble_3.3.1        tidyselect_1.2.1   
## [55] rstudioapi_0.18.0   farver_2.1.2        htmltools_0.5.9    
## [58] nlme_3.1-168        svglite_2.2.2       rmarkdown_2.31     
## [61] readr_2.2.0         compiler_4.5.2      S7_0.2.0
LS0tCnRpdGxlOiAiRG8gU3Ryb2tlIFVuaXRzIFNob3J0ZW4gSG9zcGl0YWwgU3RheT8iCnN1YnRpdGxlOiAiQSB3b3JrZWQgcmFuZG9tLWVmZmVjdHMgbWV0YS1hbmFseXNpcyBvZiA5IHJhbmRvbWlzZWQgdHJpYWxzIOKAlCBhbmQgYSBsZXNzb24gaW4gcmVhZGluZyBoZXRlcm9nZW5laXR5LCBub3QgaGlkaW5nIGl0IgphdXRob3I6CiAgLSAiQWJkZWx3YWhhYiBHaGF6eSwgTUQiCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVZJylgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB0cnVlCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogNzIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwKICBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNSwgZmlnLmFsaWduID0gImNlbnRlciIKKQoKIyBPbmUgcGxhY2UgZm9yIGV2ZXJ5IGRlcGVuZGVuY3ksIHdpdGggYSBmcmllbmRseSBzdG9wIGlmIHNvbWV0aGluZyBpcyBtaXNzaW5nLgpuZWVkIDwtIGMoIm1ldGEiLCAibWV0YWZvciIsICJrbml0ciIsICJrYWJsZUV4dHJhIiwgImdyaWQiKQptaXNzaW5nIDwtIG5lZWRbIXZhcHBseShuZWVkLCByZXF1aXJlTmFtZXNwYWNlLCBsb2dpY2FsKDEpLCBxdWlldGx5ID0gVFJVRSldCmlmIChsZW5ndGgobWlzc2luZykpCiAgc3RvcCgiUGxlYXNlIGluc3RhbGw6ICIsIHBhc3RlKG1pc3NpbmcsIGNvbGxhcHNlID0gIiwgIiksIGNhbGwuID0gRkFMU0UpCgpsaWJyYXJ5KG1ldGEpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShncmlkKQpgYGAKCmBgYHs9aHRtbH0KPHN0eWxlPgoudGxkciAgIHtiYWNrZ3JvdW5kOiNlYWY0ZmI7IGJvcmRlci1sZWZ0OjVweCBzb2xpZCAjMmM3ZmI4OyBwYWRkaW5nOjE0cHggMThweDsgYm9yZGVyLXJhZGl1czo2cHg7IG1hcmdpbjoxOHB4IDA7fQouY2F2ZWF0IHtiYWNrZ3JvdW5kOiNmZmY0ZTY7IGJvcmRlci1sZWZ0OjVweCBzb2xpZCAjZTg4NzFlOyBwYWRkaW5nOjE0cHggMThweDsgYm9yZGVyLXJhZGl1czo2cHg7IG1hcmdpbjoxOHB4IDA7fQouYnlsaW5lIHtjb2xvcjojNWI2YjdhOyBmb250LXNpemU6MC45NWVtOyBtYXJnaW4tdG9wOi04cHg7IG1hcmdpbi1ib3R0b206MjBweDt9Ci53aW4gICAge2JhY2tncm91bmQ6I2VlZjhlZTsgYm9yZGVyLWxlZnQ6NXB4IHNvbGlkICM0YTlkNGE7IHBhZGRpbmc6MTRweCAxOHB4OyBib3JkZXItcmFkaXVzOjZweDsgbWFyZ2luOjE4cHggMDt9Ci5leHBsYWluIHtiYWNrZ3JvdW5kOiNmNWYzZmI7IGJvcmRlcjoxcHggc29saWQgI2RkZDVmMDsgYm9yZGVyLWxlZnQ6NXB4IHNvbGlkICM3YjYxYzk7IHBhZGRpbmc6MTJweCAxOHB4OyBib3JkZXItcmFkaXVzOjZweDsgbWFyZ2luOjE0cHggMDsgZm9udC1zaXplOjAuOTVlbTt9Ci5leHBsYWluIGNvZGUge2JhY2tncm91bmQ6I2VjZTZmODt9Cjwvc3R5bGU+CmBgYAoKOjo6IGJ5bGluZQpFdmlkZW5jZS1zeW50aGVzaXMgd29ya2VkIGV4YW1wbGUgwrcgcHJlcGFyZWQgYnkgKipBYmRlbHdhaGFiIEdoYXp5LCBNRCoqClBvcnRmb2xpbzogKmFkZCB5b3VyIGxpbmsqIMK3IE9SQ0lEOiAqYWRkIHlvdXIgSUQqIMK3Cltkci5hYmRlbHdhaGFiLmdoYXp5XEBnbWFpbC5jb21dKG1haWx0bzpkci5hYmRlbHdhaGFiLmdoYXp5QGdtYWlsLmNvbSl7LmVtYWlsfQo6OjoKCjo6OiB0bGRyCioqSW4gb25lIGJyZWF0aC4qKiBQb29saW5nIG5pbmUgcmFuZG9taXNlZCB0cmlhbHMgZ2l2ZXMgYSBoZWFkbGluZQoic3Ryb2tlIHVuaXRzIHNhdmUgXH4xNSBkYXlzLCIgYnV0IHRoZSBjb25maWRlbmNlIGludGVydmFsIGNyb3NzZXMgemVybwphbmQgdGhlIHRyaWFscyBkaXNhZ3JlZSBhbG1vc3QgY29tcGxldGVseSAoScKyIOKJiCA5NyUpLiBUaGF0IGRpc2FncmVlbWVudAppcyAqKm5vdCBub2lzZSoqIOKAlCB0aGUgYmVuZWZpdCBzY2FsZXMgd2l0aCBob3cgc2ljayB0aGUgcGF0aWVudHMgYXJlLgpXaGVyZSBzdHJva2VzIGFyZSBzZXZlcmUgYW5kIHN0YXlzIGFyZSBsb25nLCBzdHJva2UgdW5pdHMgaGVscAplbm9ybW91c2x5OyB3aGVyZSBzdGF5cyBhcmUgYWxyZWFkeSBzaG9ydCwgdGhleSBiYXJlbHkgbW92ZSB0aGUgbmVlZGxlLgpUaGUgcHJvZmVzc2lvbmFsIGRlbGl2ZXJhYmxlIGhlcmUgaXMgbm90IGEgc2luZ2xlIHBvb2xlZCBudW1iZXIg4oCUIGl0IGlzCnRoZSAqZXhwbGFuYXRpb24qIGZvciB3aHkgb25lIHBvb2xlZCBudW1iZXIgd291bGQgbWlzbGVhZC4KOjo6CgojIEhvdyB0byByZWFkIHRoaXMgZG9jdW1lbnQKCipOZXcgdG8gUj8gUmVhZCB0aGlzIG9uY2UgYW5kIGV2ZXJ5dGhpbmcgYmVsb3cgd2lsbCBjbGljay4gQWxyZWFkeSBmbHVlbnQ/ClNraXAgc3RyYWlnaHQgdG8gdGhlIG5leHQgc2VjdGlvbi4qCgpFYWNoIGdyZXkgYm94IGlzIGEgKipjb2RlIGNodW5rKiog4oCUIHRoZSBleGFjdCBpbnN0cnVjdGlvbnMgUiBydW5zLiBVbmRlciBtb3N0CmNodW5rcyBzaXRzIGEgcHVycGxlICoqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaCoqIHRoYXQgdHJhbnNsYXRlcyB0aGUgY29kZSwKcGllY2UgYnkgcGllY2UuIEEgbGl0dGxlIHJlY3VycmluZyBncmFtbWFyIHVubG9ja3MgYWxsIG9mIGl0OgoKLSBBICoqZnVuY3Rpb24qKiBpcyBhIGNvbW1hbmQgdGhhdCBkb2VzIGEgam9iOyB5b3UgY2FsbCBpdCBieSBpdHMgbmFtZSBmb2xsb3dlZAogIGJ5IHJvdW5kIGJyYWNrZXRzLCBlLmcuIGBmb3Jlc3QoLi4uKWAuIFdoYXRldmVyIHlvdSBwdXQgaW5zaWRlIHRoZSBicmFja2V0cyBhcmUKICBpdHMgKiphcmd1bWVudHMqKiDigJQgdGhlIHNldHRpbmdzIHlvdSBoYW5kIHRoZSBjb21tYW5kLgotIGA8LWAgbWVhbnMgKioic2F2ZSB0aGlzIGFzLiIqKiBgbSA8LSBtZXRhY29udCguLi4pYCBydW5zIGBtZXRhY29udGAgYW5kIGtlZXBzCiAgdGhlIHJlc3VsdCBpbiBhIGJveCBuYW1lZCBgbWA7IGFmdGVyd2FyZHMgd2UganVzdCB3cml0ZSBgbWAgdG8gcmV1c2UgaXQuCi0gYCRgIHJlYWNoZXMgKippbnNpZGUqKiBhIHJlc3VsdCB0byBncmFiIG9uZSBwaWVjZTogYG0kVEUucmFuZG9tYCA9ICJ0aGUgcG9vbGVkCiAgZXN0aW1hdGUgc3RvcmVkIGluc2lkZSBgbWAuIgotIGB8PmAgaXMgdGhlICoqcGlwZSoqLiBJdCB0YWtlcyB3aGF0ZXZlciBpcyBvbiBpdHMgbGVmdCBhbmQgZmVlZHMgaXQgaW50byB0aGUKICBmdW5jdGlvbiBvbiBpdHMgcmlnaHQsIHNvIGEgY2hhaW4gcmVhZHMgbGVmdC10by1yaWdodCBpbnN0ZWFkIG9mIGluc2lkZS1vdXQuCi0gU29tZSBzZW50ZW5jZXMgY29udGFpbiBhIHNuaXBwZXQgd3JpdHRlbiBhcyBhbiBgcmAgZm9sbG93ZWQgYnkgYSBzaG9ydAogIGV4cHJlc3Npb24sIGFsbCB3cmFwcGVkIGluIGJhY2stdGlja3MuIFRoYXQgaXMgKippbmxpbmUgY29kZSoqOiBSIHJlcGxhY2VzIGl0CiAgd2l0aCB0aGUgbGl2ZSBudW1iZXIgd2hlbiB0aGUgcmVwb3J0IGlzIGJ1aWx0LCBzbyB0aGUgd29yZHMgYW5kIHRoZSBudW1iZXJzIGNhbgogIG5ldmVyIGRpc2FncmVlLgotICoqUGFja2FnZXMqKiAoYG1ldGFgLCBgbWV0YWZvcmAsIOKApikgYXJlIHRvb2xib3hlcyB3ZSBsb2FkIG9uY2UgYXQgdGhlIHRvcDsgZWFjaAogIGhhbmRzIHVzIHJlYWR5LW1hZGUgZnVuY3Rpb25zIHNvIHdlIG5ldmVyIHJlaW52ZW50IHRoZW0uCgojIFRoZSBjbGluaWNhbCBxdWVzdGlvbgoKV2UgY29tcGFyZWQgKipvcmdhbmlzZWQgc3Ryb2tlLXVuaXQgY2FyZSoqIOKAlCBhIGRlZGljYXRlZCB3YXJkIHdpdGggYQpzcGVjaWFsaXN0IG11bHRpZGlzY2lwbGluYXJ5IHRlYW0g4oCUIGFnYWluc3QgKipjb252ZW50aW9uYWwgY2FyZSoqIG9uIGEKZ2VuZXJhbCB3YXJkLCBtZWFzdXJpbmcgKipsZW5ndGggb2YgaG9zcGl0YWwgc3RheSwgaW4gZGF5cyoqLgoKPiAqKlBJQ08qKiDigJQgKipQKiogc3Ryb2tlIGlucGF0aWVudHMgwrcgKipJKiogb3JnYW5pc2VkIHN0cm9rZS11bml0IGNhcmUKPiDCtyAqKkMqKiBjb252ZW50aW9uYWwgZ2VuZXJhbC13YXJkIGNhcmUgwrcgKipPKiogbGVuZ3RoIG9mIHN0YXkgKGRheXMpLgoKTG93ZXIgaXMgYmV0dGVyOiBhICoqbmVnYXRpdmUgTWVhbiBEaWZmZXJlbmNlKiogbWVhbnMgdGhlIHN0cm9rZSB1bml0CnNlbmRzIHBhdGllbnRzIGhvbWUgc29vbmVyLgoKIyBUaGUgZGF0YQoKTmluZSByYW5kb21pc2VkIHRyaWFscyBhc3NlbWJsZWQgYnkgTm9ybWFuZCAoMTk5OSkgWzFdLiBFYWNoIHJvdyBpcyBvbmUKdHJpYWwsIHdpdGggdGhlIG1lYW4sIFNELCBhbmQgc2FtcGxlIHNpemUgZm9yIGJvdGggYXJtcy4KCmBgYHtyIGRhdGF9CmRhdGEoZGF0Lm5vcm1hbmQxOTk5LCBwYWNrYWdlID0gIm1ldGFmb3IiKQpkIDwtIGRhdC5ub3JtYW5kMTk5OSAgICMgc291cmNlID0gdHJpYWwgbGFiZWw7IDEgPSBzdHJva2UgdW5pdCwgMiA9IGNvbnZlbnRpb25hbAoKa2FibGUoCiAgZFssIGMoInNvdXJjZSIsICJuMWkiLCAibTFpIiwgInNkMWkiLCAibjJpIiwgIm0yaSIsICJzZDJpIildLAogIGNvbC5uYW1lcyA9IGMoIlRyaWFsIiwgIk4iLCAiTWVhbiIsICJTRCIsICJOIiwgIk1lYW4iLCAiU0QiKSwKICBjYXB0aW9uID0gIkxlbmd0aCBvZiBob3NwaXRhbCBzdGF5IChkYXlzKSBieSB0cmlhbCBhbmQgYXJtLiIKKSB8PgogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIgPSAxLCAiU3Ryb2tlIHVuaXQiID0gMywgIkNvbnZlbnRpb25hbCIgPSAzKSkgfD4KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgo6OjogZXhwbGFpbgoqKlBsYWluLUVuZ2xpc2ggd2Fsa3Rocm91Z2guKioKCi0gYGRhdGEoZGF0Lm5vcm1hbmQxOTk5LCBwYWNrYWdlID0gIm1ldGFmb3IiKWAgbG9hZHMgYSByZWFkeS1tYWRlIGV4YW1wbGUKICBkYXRhc2V0IHRoYXQgc2hpcHMgaW5zaWRlIHRoZSBgbWV0YWZvcmAgdG9vbGJveC4KLSBgZCA8LSBkYXQubm9ybWFuZDE5OTlgIGNvcGllcyBpdCBpbnRvIGEgc2hvcnQgbmFtZSwgYGRgLCB0aGF0IGlzIHF1aWNrZXIgdG8KICB0eXBlIGZyb20gaGVyZSBvbi4KLSBgZFssIGMoInNvdXJjZSIsICJuMWkiLCAuLi4pXWAgcGlja3Mgb3V0IGp1c3QgdGhlIGNvbHVtbnMgd2Ugd2FudCB0byBkaXNwbGF5LAogIGFuZCBga2FibGUoLi4uKWAgdHVybnMgdGhlbSBpbnRvIGEgdGlkeSB0YWJsZS4KLSBgY29sLm5hbWVzID0gYyguLi4pYCBnaXZlcyB0aGUgY29sdW1ucyBodW1hbi1mcmllbmRseSBoZWFkZXJzLCBhbmQKICBgY2FwdGlvbiA9IC4uLmAgcHV0cyBhIHRpdGxlIGFib3ZlIHRoZSB0YWJsZS4KLSBUaGUgYHw+YCBwaXBlIHRoZW4gcGFzc2VzIHRoYXQgdGFibGUgb24gdG8gYGFkZF9oZWFkZXJfYWJvdmUoKWAgKHdoaWNoIGFkZHMgdGhlCiAgIlN0cm9rZSB1bml0IC8gQ29udmVudGlvbmFsIiBzcGFubmluZyByb3cpIGFuZCB0byBga2FibGVfc3R5bGluZygpYCAodGhlCiAgc3RyaXBlZCwgaG92ZXItaGlnaGxpZ2h0IGxvb2spLgo6OjoKCioqSG93IHRvIHJlYWQgdGhlIGNvbHVtbnMuKiogVGhlIHN1ZmZpeCAqKjEqKiBpcyB0aGUgaW50ZXJ2ZW50aW9uIGFybQooc3Ryb2tlIHVuaXQpOyAqKjIqKiBpcyB0aGUgY29udHJvbCBhcm0gKGNvbnZlbnRpb25hbCBjYXJlKS4gV2l0aGluIGVhY2gKYXJtOiAqKm4qKiA9IHNhbXBsZSBzaXplLCAqKm0qKiA9IG1lYW4gbGVuZ3RoIG9mIHN0YXksICoqc2QqKiA9IHN0YW5kYXJkCmRldmlhdGlvbi4gKFRoZSB0cmFpbGluZyBgaWAgaW4gYG4xaWAvYG0xaWAv4oCmIGlzIHNpbXBseSBgbWV0YWZvcmAncwpuYW1pbmcgY29udmVudGlvbiBhbmQgY2FycmllcyBubyBhbmFseXRpYyBtZWFuaW5nLikKClR3byB0aGluZ3MgYXJlIGFscmVhZHkgdmlzaWJsZSBhbmQgd2lsbCBtYXR0ZXIgbGF0ZXI6IGNvbnZlbnRpb25hbC1jYXJlCnN0YXkgcmFuZ2VzIGZyb20gKipgciBtaW4oZCRtMmkpYCB0byBgciBtYXgoZCRtMmkpYCBkYXlzKiog4oCUIGEgbmVhcmx5CnRlbi1mb2xkIHNwcmVhZCDigJQgYW5kIHRocmVlIG9mIHRoZSB0cmlhbHMgY29tZSBmcm9tIGEgc2luZ2xlIGNlbnRyZQooT3JwaW5ndG9uKSwgZGVsaWJlcmF0ZWx5IHNwbGl0IGJ5IHN0cm9rZSBzZXZlcml0eS4KCiMgVGhlIGFuYWx5c2lzCgpXZSBwb29sIHRoZSB0cmlhbHMgYXMgYSAqKk1lYW4gRGlmZmVyZW5jZSoqIHVuZGVyIGEgKipyYW5kb20tZWZmZWN0cyoqCm1vZGVsLCBlc3RpbWF0aW5nIHRoZSBiZXR3ZWVuLXN0dWR5IHZhcmlhbmNlIGJ5IFJFTUwgYW5kIHVzaW5nIHRoZQoqKkhhcnR1bmfigJNLbmFwcCoqIGFkanVzdG1lbnQgZm9yIHRoZSBjb25maWRlbmNlIGludGVydmFsIFszXSDigJQgdGhlCm1vZGVybiBkZWZhdWx0IHRoYXQgZ3VhcmRzIGFnYWluc3Qgb3Zlci1wcmVjaXNlIGludGVydmFscyB3aGVuIHRyaWFscwphcmUgZmV3IGFuZCBoZXRlcm9nZW5lb3VzLgoKYGBge3IgcG9vbH0KbSA8LSBtZXRhY29udCgKICBuMWksIG0xaSwgc2QxaSwgICAgICAgICAgICAgICAjIHN0cm9rZS11bml0IGFybQogIG4yaSwgbTJpLCBzZDJpLCAgICAgICAgICAgICAgICMgY29udmVudGlvbmFsIGFybQogIHN0dWRsYWIgPSBzb3VyY2UsIGRhdGEgPSBkLAogIHNtICAgICAgICAgICAgICAgPSAiTUQiLCAgICAgICMgZWZmZWN0IG1lYXN1cmU6IE1lYW4gRGlmZmVyZW5jZQogIHJhbmRvbSAgICAgICAgICAgPSBUUlVFLCAgICAgICMgcmFuZG9tLWVmZmVjdHMgbW9kZWwKICBjb21tb24gICAgICAgICAgID0gRkFMU0UsCiAgbWV0aG9kLnRhdSAgICAgICA9ICJSRU1MIiwKICBtZXRob2QucmFuZG9tLmNpID0gIkhLIiwgICAgICAjIEhhcnR1bmctS25hcHAgY29uZmlkZW5jZSBpbnRlcnZhbAogIHByZWRpY3Rpb24gICAgICAgPSBUUlVFLAogIGxhYmVsLmUgPSAiU3Ryb2tlIHVuaXQiLCBsYWJlbC5jID0gIkNvbnZlbnRpb25hbCIKKQpzdW1tYXJ5KG0pCmBgYAoKOjo6IGV4cGxhaW4KKipQbGFpbi1FbmdsaXNoIHdhbGt0aHJvdWdoIOKAlCBgbWV0YWNvbnQoKWAuKiogVGhlIG5hbWUgaXMgc2hvcnQgZm9yCioqbWV0YSoqLWFuYWx5c2lzIG9mIGEgKipjb250KippbnVvdXMgb3V0Y29tZS4gSXQgdGFrZXMgZWFjaCB0cmlhbCdzIHNpeCBzdW1tYXJ5Cm51bWJlcnMgYW5kIHBvb2xzIHRoZW0gaW50byBvbmUgcmVzdWx0LiBSZWFkaW5nIGl0cyBhcmd1bWVudHMgaW4gb3JkZXI6CgotIGBuMWksIG0xaSwgc2QxaWAgdGhlbiBgbjJpLCBtMmksIHNkMmlgIOKAlCB0aGUgc2l4IGNvbHVtbnMgaXQgbmVlZHM6IHNhbXBsZQogIHNpemUsIG1lYW4sIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIHRoZSBzdHJva2UtdW5pdCBhcm0gKCoqMSoqKSwgdGhlbiB0aGUKICBzYW1lIHRocmVlIGZvciB0aGUgY29udmVudGlvbmFsIGFybSAoKioyKiopLgotIGBzdHVkbGFiID0gc291cmNlYCDigJQgd2hpY2ggY29sdW1uIGhvbGRzIHRoZSB0cmlhbCBuYW1lIHRvIHByaW50IG9uIGVhY2ggcm93LgotIGBkYXRhID0gZGAg4oCUIHRoZSB0YWJsZSB3aGVyZSBhbGwgdGhvc2UgY29sdW1ucyBsaXZlLgotIGBzbSA9ICJNRCJgIOKAlCB0aGUgKipzdW1tYXJ5IG1lYXN1cmUqKi4gIk1EIiA9IE1lYW4gRGlmZmVyZW5jZTsgYmVjYXVzZSBib3RoCiAgYXJtcyBhcmUgbWVhc3VyZWQgaW4gdGhlIHNhbWUgdW5pdCAoZGF5cyksIHdlIGNhbiBzaW1wbHkgc3VidHJhY3QgdGhlbS4KLSBgcmFuZG9tID0gVFJVRWAg4oCUIHByb2R1Y2UgdGhlICoqcmFuZG9tLWVmZmVjdHMqKiByZXN1bHQsIHdoaWNoIGFsbG93cyB0aGUgdHJ1ZQogIGVmZmVjdCB0byBnZW51aW5lbHkgZGlmZmVyIGZyb20gdHJpYWwgdG8gdHJpYWwuCi0gYGNvbW1vbiA9IEZBTFNFYCDigJQgaGlkZSB0aGUgZml4ZWQtZWZmZWN0ICgiY29tbW9uIGVmZmVjdCIpIHJlc3VsdCwgd2hpY2ggd291bGQKICBwcmV0ZW5kIGV2ZXJ5IHRyaWFsIGlzIGVzdGltYXRpbmcgb25lIGlkZW50aWNhbCBudW1iZXIuCi0gYG1ldGhvZC50YXUgPSAiUkVNTCJgIOKAlCB0aGUgcmVjaXBlIGZvciBlc3RpbWF0aW5nICpob3cgbXVjaCogdGhlIHRyaWFscyBkaWZmZXIKICAodGhlIGJldHdlZW4tc3R1ZHkgdmFyaWFuY2UsIM+EwrIpLiBSRU1MIGlzIHRoZSBtb2Rlcm4gZGVmYXVsdC4KLSBgbWV0aG9kLnJhbmRvbS5jaSA9ICJISyJgIOKAlCB1c2UgdGhlICoqSGFydHVuZ+KAk0tuYXBwKiogY29uZmlkZW5jZSBpbnRlcnZhbCwKICB3aGljaCBzdGF5cyBob25lc3QgKGFwcHJvcHJpYXRlbHkgd2lkZSkgd2hlbiB0cmlhbHMgYXJlIGZldyBhbmQgZGlzYWdyZWUuCi0gYHByZWRpY3Rpb24gPSBUUlVFYCDigJQgYWxzbyBjb21wdXRlIHRoZSAqKnByZWRpY3Rpb24gaW50ZXJ2YWwqKjogdGhlIHJhbmdlIGEKICBicmFuZC1uZXcgdHJpYWwgbWlnaHQgcGxhdXNpYmx5IGZhbGwgaW4uCi0gYGxhYmVsLmVgIC8gYGxhYmVsLmNgIOKAlCByZWFkYWJsZSBuYW1lcyBmb3IgdGhlIGV4cGVyaW1lbnRhbCBhbmQgY29udHJvbCBhcm1zLAogIHVzZWQgbGF0ZXIgb24gdGhlIHBsb3QuCgpUaGVuIGBzdW1tYXJ5KG0pYCBwcmludHMgZXZlcnl0aGluZyBgbWV0YWNvbnRgIGp1c3QgY2FsY3VsYXRlZC4KOjo6CgojIFRoZSBmb3Jlc3QgcGxvdAoKYGBge3IgZm9yZXN0LW1haW4sIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03LCBvdXQud2lkdGg9IjEwMCUiLCBmaWcuY2FwPSJGb3Jlc3QgcGxvdCBvZiB0aGUgbmluZSB0cmlhbHMuIFNxdWFyZXMgYXJlIHRyaWFsLWxldmVsIG1lYW4gZGlmZmVyZW5jZXMgKHNpemUg4oidIHdlaWdodCk7IHRoZSByZWQgZGlhbW9uZCBpcyB0aGUgcmFuZG9tLWVmZmVjdHMgcG9vbGVkIGVzdGltYXRlIGFuZCB0aGUgcmVkIGJhciBpcyB0aGUgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWwuIiwgZmlnLmFsdD0iRm9yZXN0IHBsb3Qgc2hvd2luZyB3aWRlIGRpc2FncmVlbWVudCBhY3Jvc3MgdGhlIG5pbmUgc3Ryb2tlLXVuaXQgdHJpYWxzLCB3aXRoIGEgcG9vbGVkIGRpYW1vbmQgd2hvc2UgY29uZmlkZW5jZSBpbnRlcnZhbCBjcm9zc2VzIHRoZSBsaW5lIG9mIG5vIGVmZmVjdC4ifQpmb3Jlc3QoCiAgbSwKICBzb3J0dmFyICAgICAgICAgICAgID0gVEUsCiAgbGVmdGNvbHMgICAgICAgICAgICA9IGMoInN0dWRsYWIiLCAibi5lIiwgIm1lYW4uZSIsICJzZC5lIiwgIm4uYyIsICJtZWFuLmMiLCAic2QuYyIpLAogIGxlZnRsYWJzICAgICAgICAgICAgPSBjKCJUcmlhbCIsICJUb3RhbCIsICJNZWFuIiwgIlNEIiwgIlRvdGFsIiwgIk1lYW4iLCAiU0QiKSwKICByaWdodGNvbHMgICAgICAgICAgID0gYygiZWZmZWN0IiwgImNpIiwgIncucmFuZG9tIiksCiAgcmlnaHRsYWJzICAgICAgICAgICA9IGMoIk1EIiwgIjk1JSBDSSIsICJXZWlnaHQiKSwKICBsYWJlbC5lICAgICAgICAgICAgID0gIlN0cm9rZSB1bml0IiwgbGFiZWwuYyA9ICJDb252ZW50aW9uYWwiLAogIGNvbC5kaWFtb25kICAgICAgICAgPSAiZGFya3JlZCIsICBjb2wuZGlhbW9uZC5saW5lcyA9ICJibGFjayIsCiAgY29sLnNxdWFyZSAgICAgICAgICA9ICJzdGVlbGJsdWUzIiwgY29sLnNxdWFyZS5saW5lcyA9ICJzdGVlbGJsdWUzIiwKICBjb21tb24gPSBGQUxTRSwgcmFuZG9tID0gVFJVRSwgb3ZlcmFsbCA9IFRSVUUsIG92ZXJhbGwuaGV0c3RhdCA9IFRSVUUsCiAgcHJlZGljdGlvbiAgICAgICAgICA9IFRSVUUsICAgICAgICAgICAgICAgICMgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWwgKHJlZCBiYXIpCiAgc3BhY2luZyAgICAgICAgICAgICA9IDEuMiwKICBjb2xnYXAgICAgICAgICAgICAgID0gdW5pdCgzLCAibW0iKSwKICBjb2xnYXAuZm9yZXN0LmxlZnQgID0gdW5pdCgwLCAibW0iKSwKICBjb2xnYXAuZm9yZXN0LnJpZ2h0ID0gdW5pdCgxLCAibW0iKSwKICB4bGFiICAgICAgICAgICAgICAgID0gIkZhdm91cnMgc3Ryb2tlIHVuaXQgICAgICAgICAgRmF2b3VycyBjb252ZW50aW9uYWwiLAogIHNxdWFyZXNpemUgPSAwLjgsCiAgZGlnaXRzID0gMSwgZGlnaXRzLm1lYW4gPSAxLCBkaWdpdHMuc2QgPSAxLAogIGRpZ2l0cy5wdmFsID0gMiwgZGlnaXRzLnB2YWwuUSA9IDIsIGRpZ2l0cy5JMiA9IDEsIGRpZ2l0cy50YXUyID0gMSwKICBmb250c2l6ZSA9IDExLCBmcy5oZWFkaW5nID0gMTIsIGZzLnN0dWR5ID0gMTEsIGZzLnJhbmRvbSA9IDExLAogIGZzLmhldHN0YXQgPSAxMCwgZnMuYXhpcyA9IDEwLCBmcy54bGFiID0gMTIsIGZzLnNtbGFiID0gMTIsCiAgY29sLmhldHN0YXQgPSAiZ3JheTUwIgopCmBgYAoKOjo6IGV4cGxhaW4KKipQbGFpbi1FbmdsaXNoIHdhbGt0aHJvdWdoIOKAlCBgZm9yZXN0KClgLioqIGBmb3Jlc3QobSwgLi4uKWAgZHJhd3MgdGhlIGNsYXNzaWMKZm9yZXN0IHBsb3QgZnJvbSB0aGUgcG9vbGVkIG9iamVjdCBgbWAuIFRoZXJlIGFyZSBtYW55IGFyZ3VtZW50cywgYnV0IHRoZXkgb25seQpkbyBhIGhhbmRmdWwgb2Ygam9iczoKCi0gKipXaGF0IHRvIHNob3csIGFuZCB3aGVyZS4qKiBgbGVmdGNvbHNgIC8gYGxlZnRsYWJzYCBsaXN0IHRoZSBjb2x1bW5zIChhbmQKICB0aGVpciBoZWFkZXJzKSBkb3duIHRoZSBsZWZ0IHNpZGU7IGByaWdodGNvbHNgIC8gYHJpZ2h0bGFic2AgZG8gdGhlIHNhbWUgb24gdGhlCiAgcmlnaHQgKHRoZSBlZmZlY3QsIGl0cyBDSSwgYW5kIGVhY2ggdHJpYWwncyB3ZWlnaHQpLiBgc29ydHZhciA9IFRFYCBvcmRlcnMgdGhlCiAgdHJpYWxzIGJ5IGVmZmVjdCBzaXplLgotICoqVGhlIG92ZXJhbGwgcmVzdWx0LioqIGByYW5kb20gPSBUUlVFYCwgYGNvbW1vbiA9IEZBTFNFYCwgYG92ZXJhbGxgLCBhbmQKICBgb3ZlcmFsbC5oZXRzdGF0YCBzaG93IHRoZSByYW5kb20tZWZmZWN0cyBkaWFtb25kIGFuZCB0aGUgaGV0ZXJvZ2VuZWl0eQogIHN0YXRpc3RpY3M7IGBwcmVkaWN0aW9uID0gVFJVRWAgYWRkcyB0aGUgcmVkIHByZWRpY3Rpb24taW50ZXJ2YWwgYmFyLgotICoqQ29sb3VycyAmIHNpemVzLioqIGBjb2wuZGlhbW9uZGAsIGBjb2wuc3F1YXJlYCwgYHNxdWFyZXNpemVgLCBgc3BhY2luZ2AsIGFuZAogIHRoZSBgY29sZ2FwKmAgYXJndW1lbnRzIGFyZSBwdXJlIGNvc21ldGljcyDigJQgdGhlIGRpYW1vbmQgY29sb3VyLCB0aGUgYm94CiAgY29sb3VyLCBob3cgYmlnIHRoZSBib3hlcyBhcmUsIGFuZCB0aGUgZ2FwcyBiZXR3ZWVuIGNvbHVtbnMuCi0gKipSb3VuZGluZy4qKiBFdmVyeSBgZGlnaXRzKmAgYXJndW1lbnQgc2V0cyBob3cgbWFueSBkZWNpbWFscyBhIGdpdmVuIG51bWJlcgogIHNob3dzIChlLmcuIGBkaWdpdHMgPSAxYCDihpIgb25lIGRlY2ltYWwgcGxhY2UgZm9yIHRoZSBlZmZlY3RzKS4KLSAqKkZvbnQgc2l6ZXMuKiogYGZvbnRzaXplYCBpcyB0aGUgYmFzZWxpbmU7IGVhY2ggYGZzLipgIGZpbmUtdHVuZXMgb25lIGVsZW1lbnQKICAoaGVhZGluZywgc3R1ZHkgcm93cywgaGV0ZXJvZ2VuZWl0eSBsaW5lLCBheGlzLCBsYWJlbHMpLgotIGB4bGFiID0gIkZhdm91cnMgc3Ryb2tlIHVuaXQg4oCmIEZhdm91cnMgY29udmVudGlvbmFsImAgbGFiZWxzIHdoaWNoIHNpZGUgb2YgdGhlCiAgdmVydGljYWwgbGluZSBpcyB0aGUgZ29vZC1uZXdzIHNpZGUuCgpJbiBzaG9ydDogdGhlIGZpcnN0IGZldyBhcmd1bWVudHMgZGVjaWRlIHRoZSBwbG90J3MgKmNvbnRlbnQqLCBhbmQgdGhlIGxvbmcgdGFpbApvZiBgY29sLipgLCBgZnMuKmAsIGFuZCBgZGlnaXRzLipgIHNpbXBseSBwb2xpc2hlcyBpdHMgKmFwcGVhcmFuY2UqLgo6OjoKCiMgV2hhdCB0aGUgbnVtYmVycyBhcmUgdGVsbGluZyB1cwoKYGBge3Igc3VtbWFyeS10YWJsZX0KcmVzIDwtIGRhdGEuZnJhbWUoCiAgTWV0cmljID0gYygiUG9vbGVkIE1EIChyYW5kb20gZWZmZWN0cykiLCAiOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwiLAogICAgICAgICAgICAgIjk1JSBwcmVkaWN0aW9uIGludGVydmFsIiwgIknCsiAoaW5jb25zaXN0ZW5jeSkiLAogICAgICAgICAgICAgIs+EwrIgKGJldHdlZW4tdHJpYWwgdmFyaWFuY2UpIiwgIkNvY2hyYW4ncyBRIChwLXZhbHVlKSIpLAogIFZhbHVlID0gYygKICAgIHNwcmludGYoIiUuMWYgZGF5cyIsIG0kVEUucmFuZG9tKSwKICAgIHNwcmludGYoIiUuMWYgdG8gJS4xZiBkYXlzIiwgbSRsb3dlci5yYW5kb20sIG0kdXBwZXIucmFuZG9tKSwKICAgIHNwcmludGYoIiUuMWYgdG8gJS4xZiBkYXlzIiwgbSRsb3dlci5wcmVkaWN0LCBtJHVwcGVyLnByZWRpY3QpLAogICAgc3ByaW50ZigiJS4wZiUlIiwgbSRJMiAqIDEwMCksCiAgICBzcHJpbnRmKCIlLjFmIiwgbSR0YXUyKSwKICAgIGZvcm1hdC5wdmFsKG0kcHZhbC5RLCBkaWdpdHMgPSAyLCBlcHMgPSAwLjAwMSkKICApCikKa2FibGUocmVzLCBjb2wubmFtZXMgPSBjKCIiLCAiUmVzdWx0IiksCiAgICAgIGNhcHRpb24gPSAiUmFuZG9tLWVmZmVjdHMgc3VtbWFyeS4iKSB8PgogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgo6OjogZXhwbGFpbgoqKlBsYWluLUVuZ2xpc2ggd2Fsa3Rocm91Z2guKiogVGhpcyBjaHVuayBidWlsZHMgdGhlIHN1bW1hcnkgdGFibGUgYnkgaGFuZCBzbyB3ZQpjb250cm9sIGV4YWN0bHkgd2hhdCBhcHBlYXJzLgoKLSBgZGF0YS5mcmFtZShNZXRyaWMgPSAuLi4sIFZhbHVlID0gLi4uKWAgbWFrZXMgYSB0d28tY29sdW1uIHRhYmxlOiB0aGUgbGFiZWxzIG9uCiAgdGhlIGxlZnQsIHRoZSBmb3JtYXR0ZWQgcmVzdWx0cyBvbiB0aGUgcmlnaHQuCi0gYHNwcmludGYoIiUuMWYgZGF5cyIsIG0kVEUucmFuZG9tKWAgaXMgdGV4dCBmb3JtYXR0aW5nOiBgJS4xZmAgbWVhbnMgImEgbnVtYmVyCiAgd2l0aCBvbmUgZGVjaW1hbCwiIHNvIHRoZSBwb29sZWQgZXN0aW1hdGUgcHJpbnRzIGFzLCBlLmcuLCBgLTE1LjEgZGF5c2AuIEVhY2gKICB2YWx1ZSBpcyBwdWxsZWQgc3RyYWlnaHQgZnJvbSB0aGUgbW9kZWwgd2l0aCBgJGAgKGBtJFRFLnJhbmRvbWAsIGBtJEkyYCwKICBgbSR0YXUyYCwg4oCmKSwgc28gdGhlIHRhYmxlIGNhbiBuZXZlciBkcmlmdCBhd2F5IGZyb20gdGhlIGFuYWx5c2lzLgotIGBmb3JtYXQucHZhbCguLi4sIGVwcyA9IDAuMDAxKWAgcHJpbnRzIHZlcnkgc21hbGwgcC12YWx1ZXMgbmVhdGx5IGFzIGA8IDAuMDAxYAogIGluc3RlYWQgb2YgYSBsb25nIHN0cmluZyBvZiB6ZXJvcy4KLSBga2FibGUoKSB8PiBrYWJsZV9zdHlsaW5nKClgIHJlbmRlcnMgYW5kIHN0eWxlcyB0aGUgdGFibGUsIGp1c3QgYXMgYmVmb3JlLgo6OjoKClRoZSBwb29sZWQgZXN0aW1hdGUgb2YgKipgciByb3VuZChtJFRFLnJhbmRvbSwgMSlgIGRheXMqKiBsb29rcwppbXByZXNzaXZlLCBidXQgdHdvIHNpZ25hbHMgc3RvcCB1cyBmcm9tIHJlcG9ydGluZyBpdDoKCjEuICBUaGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgKGByIHJvdW5kKG0kbG93ZXIucmFuZG9tLCAxKWAgdG8KICAgIGByIHJvdW5kKG0kdXBwZXIucmFuZG9tLCAxKWApICoqY3Jvc3NlcyB6ZXJvKiog4oCUIHRoZSBwb29sZWQgZWZmZWN0CiAgICBpcyBub3Qgc3RhdGlzdGljYWxseSBkaXN0aW5ndWlzaGFibGUgZnJvbSAibm8gZGlmZmVyZW5jZS4iCjIuICAqKknCsiBpcyBgciByb3VuZChtJEkyICogMTAwKWAlKiogWzVdIOKAlCB0aGUgdHJpYWxzIGVzc2VudGlhbGx5IGRvIG5vdAogICAgYWdyZWUuIFRoZSA5NSUgKipwcmVkaWN0aW9uIGludGVydmFsKiogWzddLAogICAgYHIgcm91bmQobSRsb3dlci5wcmVkaWN0LCAxKWAgdG8gYHIgcm91bmQobSR1cHBlci5wcmVkaWN0LCAxKWAgZGF5cywKICAgIG1ha2VzIHRoaXMgY29uY3JldGU6IGEgKm5ldyogdHJpYWwgY291bGQgcGxhdXNpYmx5IGxhbmQgYW55d2hlcmUKICAgIGZyb20gYSBsYXJnZSBiZW5lZml0IHRvIGEgbGFyZ2UgaGFybS4KCldoZW4gYSBwcmVkaWN0aW9uIGludGVydmFsIGlzIHRoYXQgd2lkZSwgYSBzaW5nbGUgcG9vbGVkIG51bWJlciBpcyBub3QgYQpmaW5kaW5nIOKAlCBpdCBpcyBhbiBhdmVyYWdlIG9mIHRoaW5ncyB0aGF0IGRvbid0IGJlbG9uZyB0b2dldGhlci4gU28gd2UKZG9uJ3QgcmVwb3J0IGl0LiBXZSBhc2sgKndoeSB0aGUgdHJpYWxzIGRpc2FncmVlKi4KCiMgSHVudGluZyBmb3IgdGhlIGNhdXNlCgpUaGUgdHJpYWwgbGFiZWxzIGhpbnQgYXQgdGhlIGFuc3dlci4gVGhyZWUgdHJpYWxzIGNvbWUgZnJvbSBvbmUgY2VudHJlCihPcnBpbmd0b24pIHNwbGl0IGJ5ICoqc3Ryb2tlIHNldmVyaXR5Kio7IHRoZSByZXN0IHNwYW4gZGlmZmVyZW50CmNvdW50cmllcyBhbmQgaGVhbHRoIHN5c3RlbXMsIGFuZCBsZW5ndGggb2Ygc3RheSBkZXBlbmRzIGhlYXZpbHkgb24gYm90aApjYXNlLW1peCBhbmQgaG93IGVhY2ggc3lzdGVtIG1hbmFnZXMgZGlzY2hhcmdlLiBCZWNhdXNlCmNvbnZlbnRpb25hbC1jYXJlIHN0YXkgcmFuZ2VzIGZyb20gYHIgbWluKGQkbTJpKWAgdG8gYHIgbWF4KGQkbTJpKWAKZGF5cywgYSBuYXR1cmFsIHF1ZXN0aW9uIGlzIHdoZXRoZXIgKipiYXNlbGluZSBzdGF5KiogZXhwbGFpbnMgdGhlCmRpc2FncmVlbWVudC4gV2UgdGVzdCBpdCB3aXRoIGEgbWV0YS1yZWdyZXNzaW9uLgoKYGBge3IgZXhwbG9yZX0KbXIgPC0gbWV0YXJlZyhtLCB+IG0yaSkgICAjIGRvZXMgY29udHJvbC1hcm0gbWVhbiBleHBsYWluIHRoZSBiZXR3ZWVuLXRyaWFsIE1EPwptcgpgYGAKCjo6OiBleHBsYWluCioqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaCDigJQgYG1ldGFyZWcoKWAuKiogQSAqKm1ldGEtcmVncmVzc2lvbioqIGFza3Mgd2hldGhlcgpzb21lIHRyYWl0IG9mIHRoZSB0cmlhbHMgZXhwbGFpbnMgd2h5IHRoZWlyIHJlc3VsdHMgZGlzYWdyZWUuCgotIGBtZXRhcmVnKG0sIH4gbTJpKWAg4oCUIHRha2UgdGhlIHBvb2xlZCBvYmplY3QgYG1gIGFuZCB0ZXN0IG9uZSBwcmVkaWN0b3IuIFRoZQogIGB+IG0yaWAgcGFydCBpcyBhbiBSICoqZm9ybXVsYSoqOyByZWFkIGl0IGFzICJleHBsYWluIHRoZSBlZmZlY3QgKnVzaW5nKiBgbTJpYCIKICAodGhlIGNvbnRyb2wtYXJtIG1lYW4g4oCUIGkuZS4gYmFzZWxpbmUgbGVuZ3RoIG9mIHN0YXkpLgotIFByaW50aW5nIGBtcmAgcmVwb3J0cyB0aGUgKipzbG9wZSoqIChob3cgbXVjaCB0aGUgZWZmZWN0IHNoaWZ0cyBwZXIgZXh0cmEKICBiYXNlbGluZSBkYXkpLCBpdHMgKipwLXZhbHVlKiosIGFuZCAqKlLCsioqIOKAlCB0aGUgc2hhcmUgb2YgdGhlIGJldHdlZW4tdHJpYWwKICBkaXNhZ3JlZW1lbnQgdGhhdCB0aGlzIG9uZSBwcmVkaWN0b3IgYWNjb3VudHMgZm9yLgo6OjoKCkJhc2VsaW5lIHN0YXkgZXhwbGFpbnMgKiphbG1vc3QgYWxsKiogb2YgdGhlIGJldHdlZW4tdHJpYWwgdmFyaWF0aW9uCigqKlLCsiDiiYggYHIgcm91bmQobXIkUjIpYCUqKiwgc2xvcGUgKnAqIFw8IDAuMDAxKTogdHJpYWxzIHdoZXJlIHBhdGllbnRzCndvdWxkIG90aGVyd2lzZSBzdGF5IGEgbG9uZyB0aW1lIChzZXZlcmUgc3Ryb2tlcykgc2hvdyB0aGUgYmlnZ2VzdApyZWR1Y3Rpb25zLCB3aGlsZSB0cmlhbHMgd2l0aCBhbHJlYWR5LXNob3J0IHN0YXlzIHNob3cgYWxtb3N0IG5vbmUuIFRoZQpoZXRlcm9nZW5laXR5IHdhcyBuZXZlciBub2lzZSDigJQgaXQgd2FzICoqYmFzZWxpbmUtZGVwZW5kZW5jZSoqLgoKOjo6IGNhdmVhdAoqKlJlYWQgdGhpcyBiZWZvcmUgYmVsaWV2aW5nIGl0LioqIFJlZ3Jlc3NpbmcgdGhlIE1lYW4gRGlmZmVyZW5jZSBvbiB0aGUKY29udHJvbC1ncm91cCBtZWFuIGlzICoqZXhwbG9yYXRvcnkqKiwgbm90IGNvbmZpcm1hdG9yeS4gVGhlIGNvbnRyb2wKbWVhbiBpcyBwYXJ0IG9mIHRoZSBvdXRjb21lIGl0c2VsZiAoTUQgPSBpbnRlcnZlbnRpb24g4oiSIGNvbnRyb2wpLCBzbyB0aGUKdHdvIGFyZSBtYXRoZW1hdGljYWxseSBsaW5rZWQgYW5kIHBhcnQgb2YgdGhpcyBhc3NvY2lhdGlvbiBpcyBidWlsdCBpbi4KVHJlYXQgaXQgYXMgKipoeXBvdGhlc2lzLWdlbmVyYXRpbmcqKiwgbm90IHByb29mLgo6OjoKCiMgQSBjbGVhbmVyIHRlc3Q6IHRoZSBPcnBpbmd0b24gc2V2ZXJpdHkgZ3JhZGllbnQKClRoZSBjYXZlYXQgYWJvdmUgaGFzIGEgY2xlYW4gYW5zd2VyLiBJbnN0ZWFkIG9mIGJhc2VsaW5lIHN0YXkg4oCUIHdoaWNoIGlzCnRhbmdsZWQgd2l0aCB0aGUgb3V0Y29tZSDigJQgd2UgdXNlIGFuICoqaW5kZXBlbmRlbnQqKiBtb2RlcmF0b3I6CnByZS1yYW5kb21pc2F0aW9uICoqc3Ryb2tlIHNldmVyaXR5KiouIFRoZSB0aHJlZSBPcnBpbmd0b24gdHJpYWxzIGFyZQppZGVhbCwgYmVjYXVzZSB0aGV5IGhvbGQgdGhlIGhvc3BpdGFsLCB0ZWFtLCBhbmQgaGVhbHRoIHN5c3RlbQoqY29uc3RhbnQqIGFuZCB2YXJ5IG9ubHkgYnkgc2V2ZXJpdHkuCgpgYGB7ciBvcnBpbmd0b259Cm9ycCA8LSBzdWJzZXQoZCwgZ3JlcGwoIk9ycGluZ3RvbiIsIHNvdXJjZSkpCm9ycCRzZXZlcml0eSA8LSBjKCJNaWxkIiwgIk1vZGVyYXRlIiwgIlNldmVyZSIpCm9ycCRNRCA8LSBvcnAkbTFpIC0gb3JwJG0yaSAgICAjIHN0cm9rZSB1bml0IC0gY29udmVudGlvbmFsCgprYWJsZShvcnBbLCBjKCJzZXZlcml0eSIsICJtMWkiLCAibTJpIiwgIk1EIildLAogICAgICBjb2wubmFtZXMgPSBjKCJTdHJva2Ugc2V2ZXJpdHkiLCAiU3Ryb2tlLXVuaXQgbWVhbiIsCiAgICAgICAgICAgICAgICAgICAgIkNvbnZlbnRpb25hbCBtZWFuIiwgIk1lYW4gZGlmZmVyZW5jZSAoZGF5cykiKSwKICAgICAgY2FwdGlvbiA9ICJPcnBpbmd0b24gdHJpYWxzIOKAlCBzYW1lIGNlbnRyZSwgc2FtZSB0ZWFtLCBzZXZlcml0eSB0aGUgb25seSBkaWZmZXJlbmNlLiIpIHw+CiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQpgYGAKCjo6OiBleHBsYWluCioqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaC4qKgoKLSBgc3Vic2V0KGQsIGdyZXBsKCJPcnBpbmd0b24iLCBzb3VyY2UpKWAg4oCUIGtlZXAgb25seSB0aGUgcm93cyB3aG9zZSBgc291cmNlYAogIG5hbWUgKmNvbnRhaW5zKiB0aGUgdGV4dCAiT3JwaW5ndG9uLiIgYGdyZXBsKClgIGlzIGEgdGV4dCBzZWFyY2ggdGhhdCByZXR1cm5zCiAgVFJVRS9GQUxTRSBmb3IgZXZlcnkgcm93LCBhbmQgYHN1YnNldCgpYCBrZWVwcyB0aGUgVFJVRSBvbmVzLgotIGBvcnAkc2V2ZXJpdHkgPC0gYygiTWlsZCIsICJNb2RlcmF0ZSIsICJTZXZlcmUiKWAg4oCUIGFkZCBhIG5ldyBjb2x1bW4gYnkgaGFuZCwKICBsYWJlbGxpbmcgdGhvc2UgdGhyZWUgcm93cy4KLSBgb3JwJE1EIDwtIG9ycCRtMWkgLSBvcnAkbTJpYCDigJQgY29tcHV0ZSBlYWNoIHRyaWFsJ3MgbWVhbiBkaWZmZXJlbmNlIGRpcmVjdGx5CiAgKHN0cm9rZS11bml0IG1lYW4gbWludXMgY29udmVudGlvbmFsIG1lYW4pIOKAlCB0aGUgdmVyeSBzdWJ0cmFjdGlvbiBgbWV0YWNvbnRgCiAgZG9lcyBpbnRlcm5hbGx5LgotIGBrYWJsZSguLi4pIHw+IGthYmxlX3N0eWxpbmcoLi4uKWAg4oCUIGRpc3BsYXkgaXQgYXMgYSB0aWR5IHRhYmxlLgo6OjoKCjo6OiB3aW4KSG9sZGluZyB0aGUgc3lzdGVtIGZpeGVkLCB0aGUgbWVhbiBkaWZmZXJlbmNlIGdvZXMgZnJvbSAqKmByIG9ycCRNRFsxXWAKZGF5cyoqIChtaWxkKSDihpIgKipgciBvcnAkTURbMl1gIGRheXMqKiAobW9kZXJhdGUpIOKGkiAqKmByIG9ycCRNRFszXWAKZGF5cyoqIChzZXZlcmUpLiBBIGNsZWFuLCBtb25vdG9uaWMgZG9zZeKAk3Jlc3BvbnNlIG9uIGFuICppbmRlcGVuZGVudCoKY2xpbmljYWwgY2hhcmFjdGVyaXN0aWMg4oCUIGV4YWN0bHkgdGhlIGNvbmZpcm1hdG9yeSBzaWduYWwgdGhlCmJhc2VsaW5lLXN0YXkgcmVncmVzc2lvbiBjb3VsZCBvbmx5IGhpbnQgYXQuCjo6OgoKVGhpcyBpcyB0aGUgZGVmZW5zaWJsZSB2ZXJzaW9uIG9mIHRoZSBzdG9yeTogc2V2ZXJpdHkgaXMgY2xpbmljYWxseQptZWFuaW5nZnVsLCBhdmFpbGFibGUgaW4gdGhlIHNvdXJjZSB0cmlhbHMsIGFuZCBub3QgbWF0aGVtYXRpY2FsbHkgYm91bmQKdG8gdGhlIG91dGNvbWUuIEluIGEgcmVhbCByZXZpZXcsIHdlIHdvdWxkICoqcHJlLXNwZWNpZnkqKiBpdCBhcyB0aGUKbW9kZXJhdG9yIGFuZCBleHRyYWN0IGl0IGR1cmluZyBkYXRhIGNvbGxlY3Rpb24uCgojIFNlbnNpdGl2aXR5OiBpcyBhbnkgc2luZ2xlIHRyaWFsIGRyaXZpbmcgdGhlIHJlc3VsdD8KCkJlZm9yZSBkcmF3aW5nIGNvbmNsdXNpb25zLCB3ZSBjaGVjayB0aGF0IG5vIG9uZSB0cmlhbCBpcyBkb2luZyBhbGwgdGhlCndvcmssIGJ5IHJlLXBvb2xpbmcgd2l0aCBlYWNoIHRyaWFsIHJlbW92ZWQgaW4gdHVybiAobGVhdmUtb25lLW91dCkuCgpgYGB7ciBsb28sIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTUuNSwgb3V0LndpZHRoPSIxMDAlIiwgZmlnLmNhcD0iTGVhdmUtb25lLW91dCBhbmFseXNpczogdGhlIHBvb2xlZCBlc3RpbWF0ZSByZS1jb21wdXRlZCB3aXRoIGVhY2ggdHJpYWwgb21pdHRlZC4iLCBmaWcuYWx0PSJMZWF2ZS1vbmUtb3V0IGZvcmVzdCBwbG90OyB0aGUgcG9vbGVkIGVzdGltYXRlIHN0YXlzIG5lZ2F0aXZlIGJ1dCBtb2Rlc3QgcmVnYXJkbGVzcyBvZiB3aGljaCB0cmlhbCBpcyByZW1vdmVkLiJ9CmZvcmVzdChtZXRhaW5mKG0sIHBvb2xlZCA9ICJyYW5kb20iKSwKICAgICAgIGNvbC5zcXVhcmUgPSAic3RlZWxibHVlMyIsIGNvbC5kaWFtb25kID0gImRhcmtyZWQiLAogICAgICAgZm9udHNpemUgPSAxMSkKYGBgCgo6OjogZXhwbGFpbgoqKlBsYWluLUVuZ2xpc2ggd2Fsa3Rocm91Z2gg4oCUIGBtZXRhaW5mKClgLioqIGBtZXRhaW5mKG0sIHBvb2xlZCA9ICJyYW5kb20iKWAKcmUtcnVucyB0aGUgcmFuZG9tLWVmZmVjdHMgcG9vbCAqKm5pbmUgdGltZXMqKiDigJQgZWFjaCBydW4gbGVhdmluZyBvbmUgdHJpYWwgb3V0CigiaW5mIiBpcyBzaG9ydCBmb3IgKmluZmx1ZW5jZSopLiBXcmFwcGluZyBpdCBpbiBgZm9yZXN0KC4uLilgIGRyYXdzIG9uZSByb3cgcGVyCm9taXNzaW9uLCBzbyB5b3UgY2FuIHNlZSBhdCBhIGdsYW5jZSB3aGV0aGVyIGRyb3BwaW5nIGFueSBzaW5nbGUgdHJpYWwgd291bGQKY2hhbmdlIHRoZSBjb25jbHVzaW9uLgo6OjoKClRoZSBwb29sZWQgZXN0aW1hdGUgc3RheXMgaW4gYSBuYXJyb3cgYmFuZCAocm91Z2hseSDiiJI5IHRvIOKIkjE4IGRheXMpIGFuZApuZXZlciBjcm9zc2VzIHRvIGZhdm91cmluZyBjb252ZW50aW9uYWwgY2FyZSwgc28gbm8gc2luZ2xlIHRyaWFsIGlzCmZhYnJpY2F0aW5nIHRoZSBzaWduYWwuIFRoZSB0d28gb21pc3Npb25zIHRoYXQgcHVsbCB0aGUgZXN0aW1hdGUKKnRvd2FyZCogemVybyBhcmUgdGhlICoqT3JwaW5ndG9uLU1vZGVyYXRlKiogYW5kICoqT3JwaW5ndG9uLVNldmVyZSoqCnRyaWFscyDigJQgd2hpY2ggaXMgbm90IGZyYWdpbGl0eSwgYnV0IHRoZSBzYW1lIG1lc3NhZ2UgYWdhaW46IHRoZQpoaWdoLXNldmVyaXR5IHRyaWFscyBjYXJyeSB0aGUgYmVuZWZpdC4KCiMgQSBub3RlIG9uIHNtYWxsLXN0dWR5IGVmZmVjdHMKCldpdGggb25seSAqKmByIG0ka2AgdHJpYWxzKiosIGEgZnVubmVsIHBsb3QgYW5kIEVnZ2VyJ3MgdGVzdCBhcmUKdW5kZXJwb3dlcmVkIGFuZCBlYXNpbHkgbWlzcmVhZCDigJQgZ3VpZGFuY2UgaXMgbm90IHRvIHRlc3QgZm9yCnNtYWxsLXN0dWR5IGVmZmVjdHMgYmVsb3cgXH4xMCBzdHVkaWVzLCBhbmQgc2V2ZXJlIGhldGVyb2dlbmVpdHkgbWFrZXMKYW4gYXN5bW1ldHJ5IHRlc3QgdW5pbnRlcnByZXRhYmxlIGhlcmUgYW55d2F5IFs1XS4gV2UgdGhlcmVmb3JlICoqc3RhdGUKdGhlIGxpbWl0YXRpb24gZXhwbGljaXRseSoqIHJhdGhlciB0aGFuIHByZXNlbnQgYSBwbG90IHRoYXQgY2Fubm90CnN1cHBvcnQgYSBjb25jbHVzaW9uLiBOYW1pbmcgdGhpcyBpcyB0aGUgaG9uZXN0LCByaWdvcm91cyBtb3ZlLgoKIyBXaGF0IHdlIGxlYXJuZWQKCi0gVGhlIG5haXZlIGhlYWRsaW5lIOKAlCAic3Ryb2tlIHVuaXRzIHNhdmUgYHIgYWJzKHJvdW5kKG0kVEUucmFuZG9tKSlgCiAgZGF5cyIg4oCUIGlzICoqbm90IHN1cHBvcnRlZCoqOiB0aGUgQ0kgY3Jvc3NlcyB6ZXJvIGFuZCBJwrIgaXMKICBgciByb3VuZChtJEkyICogMTAwKWAlLgotIFRoZSBkaXNhZ3JlZW1lbnQgaXMgKipub3Qgbm9pc2UqKi4gVGhlIGJlbmVmaXQgKipkZXBlbmRzIG9uIGJhc2VsaW5lCiAgc2V2ZXJpdHkqKjogbGFyZ2VzdCB3aGVyZSBjb252ZW50aW9uYWwgc3RheXMgYXJlIGxvbmdlc3QgKHNldmVyZQogIHN0cm9rZXMpLCBtaW5pbWFsIHdoZXJlIHRoZXkgYXJlIGFscmVhZHkgc2hvcnQg4oCUIGNvbmZpcm1lZCBjbGVhbmx5CiAgd2l0aGluIHRoZSBPcnBpbmd0b24gY2VudHJlLgotIFRoZSByZXN1bHQgaXMgKipyb2J1c3QqKiB0byBsZWF2ZS1vbmUtb3V0LCBhbmQgc21hbGwtc3R1ZHktZWZmZWN0CiAgdGVzdGluZyBpcyBjb3JyZWN0bHkgKip3aXRoaGVsZCoqIGF0IHRoaXMgc2FtcGxlIHNpemUuCi0gKipUcmFuc2ZlcmFibGUgbWV0aG9kIGhhYml0czoqKiAoMSkgcGljayB0aGUgZWZmZWN0IG1lYXN1cmUgZnJvbSB0aGUKICBvdXRjb21lIChNRCBmb3IgYSBzaGFyZWQgc2NhbGUpOyAoMikgZGVmYXVsdCB0byByYW5kb20tZWZmZWN0cyArCiAgSGFydHVuZ+KAk0tuYXBwOwogICgzKSByZWFkIHRoZSAqKnByZWRpY3Rpb24gaW50ZXJ2YWwqKiwgbm90IGp1c3QgdGhlIENJOyAoNCkgKipleHBsYWluCiAgICAgIGhldGVyb2dlbmVpdHkqKiBiZWZvcmUgcXVvdGluZyBhbnkgcG9vbGVkIG51bWJlcjsgYW5kICg1KSBwcmVmZXIgYQogICAgICBtb2RlcmF0b3IgdGhhdCBpcyAqaW5kZXBlbmRlbnQqIG9mIHRoZSBvdXRjb21lLgoKIyBSZWFsLXdvcmxkIHZhbGlkYXRpb24KClRoaXMgdGVhY2hpbmcgcmVzdWx0IGVjaG9lcyB0aGUgZGVmaW5pdGl2ZSBldmlkZW5jZTogdGhlIENvY2hyYW5lCioqU3Ryb2tlIFVuaXQgVHJpYWxpc3RzJyBDb2xsYWJvcmF0aW9uKiogcmV2aWV3IGZvdW5kIHRoYXQgb3JnYW5pc2VkCnN0cm9rZS11bml0IGNhcmUgaW1wcm92ZXMgb3V0Y29tZXMsIHdpdGggZWZmZWN0cyB0aGF0IHZhcnkgYnkgcGF0aWVudApzZXZlcml0eSBhbmQgY2FyZSBzZXR0aW5nIFs0XSDigJQgcmVhc3N1cmFuY2UgdGhhdCB0aGUgYW5hbHl0aWMgc3RvcnkgaGVyZQpwb2ludHMgdGhlIHNhbWUgd2F5IGFzIHRoZSBmdWxsIGJvZHkgb2YgdHJpYWxzLgoKIyBSZXByb2R1Y2liaWxpdHkgJiBkYXRhIGF2YWlsYWJpbGl0eQoKLSAqKkRhdGE6KiogYGRhdC5ub3JtYW5kMTk5OWAgZnJvbSB0aGUgYG1ldGFmb3JgIHBhY2thZ2UgKE5vcm1hbmQgMTk5OSkKICBbMTs2XSDigJQgbm8gcHJpdmF0ZSBkYXRhOyB0aGUgYW5hbHlzaXMgaXMgZnVsbHkgcmVwcm9kdWNpYmxlIGZyb20gdGhpcwogIGRvY3VtZW50LgotICoqQ29kZToqKiBldmVyeSBmaWd1cmUgYW5kIG51bWJlciBpcyBnZW5lcmF0ZWQgaW4tbGluZSBmcm9tIHRoZSBmaXR0ZWQKICBtb2RlbCAobm8gaGFyZC1jb2RlZCByZXN1bHRzKS4gVXNlIHRoZSAqKkNvZGUg4pa4IERvd25sb2FkIFJtZCoqIGJ1dHRvbgogICh0b3AtcmlnaHQpIHRvIGdldCB0aGUgc291cmNlLgotICoqRW52aXJvbm1lbnQ6KiogZXhhY3QgcGFja2FnZSB2ZXJzaW9ucyBhcmUgcmVjb3JkZWQgaW4gdGhlIGFwcGVuZGl4CiAgYmVsb3cuCgojIFJlZmVyZW5jZXMgeyNyZWZlcmVuY2VzfQoKMS4gIE5vcm1hbmQgU0wuIE1ldGEtYW5hbHlzaXM6IGZvcm11bGF0aW5nLCBldmFsdWF0aW5nLCBjb21iaW5pbmcsIGFuZAogICAgcmVwb3J0aW5nLiAqU3RhdCBNZWQuKiAxOTk5OzE4KDMpOjMyMeKAkzM1OS4KMi4gIEJhbGR1enppIFMsIFLDvGNrZXIgRywgU2Nod2FyemVyIEcuIEhvdyB0byBwZXJmb3JtIGEgbWV0YS1hbmFseXNpcwogICAgd2l0aCBSOiBhIHByYWN0aWNhbCB0dXRvcmlhbC4gKkV2aWQgQmFzZWQgTWVudCBIZWFsdGguKgogICAgMjAxOTsyMig0KToxNTPigJMxNjAuICh0aGUgYG1ldGFgIHBhY2thZ2UpCjMuICBJbnRIb3V0IEosIElvYW5uaWRpcyBKUEEsIEJvcm0gR0YuIFRoZSBIYXJ0dW5n4oCTS25hcHDigJNTaWRpa+KAk0pvbmttYW4KICAgIG1ldGhvZCBmb3IgcmFuZG9tLWVmZmVjdHMgbWV0YS1hbmFseXNpcyBpcyBzdHJhaWdodGZvcndhcmQgYW5kCiAgICBjb25zaWRlcmFibHkgb3V0cGVyZm9ybXMgdGhlIHN0YW5kYXJkIERlclNpbW9uaWFu4oCTTGFpcmQgbWV0aG9kLiAqQk1DCiAgICBNZWQgUmVzIE1ldGhvZG9sLiogMjAxNDsxNDoyNS4KNC4gIFN0cm9rZSBVbml0IFRyaWFsaXN0cycgQ29sbGFib3JhdGlvbi4gT3JnYW5pc2VkIGlucGF0aWVudCAoc3Ryb2tlCiAgICB1bml0KSBjYXJlIGZvciBzdHJva2UuICpDb2NocmFuZSBEYXRhYmFzZSBTeXN0IFJldi4qCiAgICAyMDEzOyg5KTpDRDAwMDE5Ny4KNS4gIEhpZ2dpbnMgSlBULCBUaG9tcHNvbiBTRy4gUXVhbnRpZnlpbmcgaGV0ZXJvZ2VuZWl0eSBpbiBhCiAgICBtZXRhLWFuYWx5c2lzLiAqU3RhdCBNZWQuKiAyMDAyOzIxKDExKToxNTM54oCTMTU1OC4KNi4gIFZpZWNodGJhdWVyIFcuIENvbmR1Y3RpbmcgbWV0YS1hbmFseXNlcyBpbiBSIHdpdGggdGhlIG1ldGFmb3IKICAgIHBhY2thZ2UuICpKIFN0YXQgU29mdHcuKiAyMDEwOzM2KDMpOjHigJM0OC4KNy4gIEludEhvdXQgSiwgSW9hbm5pZGlzIEpQQSwgUm92ZXJzIE1NLCBHb2VtYW4gSkouIFBsZWEgZm9yIHJvdXRpbmVseQogICAgcHJlc2VudGluZyBwcmVkaWN0aW9uIGludGVydmFscyBpbiBtZXRhLWFuYWx5c2lzLiAqQk1KIE9wZW4uKgogICAgMjAxNjs2OmUwMTAyNDcuCgojIEFwcGVuZGl4OiBzZXNzaW9uIGluZm9ybWF0aW9uIHsudW5udW1iZXJlZH0KCjo6OiBleHBsYWluCioqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaC4qKiBgc2Vzc2lvbkluZm8oKWAgcHJpbnRzIHRoZSBleGFjdCBSIHZlcnNpb24gYW5kIHRoZQp2ZXJzaW9uIG9mIGV2ZXJ5IHBhY2thZ2UgdXNlZC4gSW5jbHVkaW5nIGl0IGxldHMgYW55b25lIHJlcnVuIHRoaXMgYW5hbHlzaXMgd2l0aAp0aGUgc2FtZSB0b29scyBhbmQgZ2V0IHRoZSBzYW1lIG51bWJlcnMg4oCUIGEgaGFsbG1hcmsgb2YgdHJ1c3R3b3J0aHkgd29yay4KOjo6CgpgYGB7ciBzZXNzaW9uLCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0Kc2Vzc2lvbkluZm8oKQpgYGAK