# ── Packages ───────────────────────────────────────────────────────────────────
suppressPackageStartupMessages({
  library(arrow)
  library(dplyr)
  library(tidyr)
  library(ggplot2)
  library(kableExtra)
  library(scales)
  library(lubridate)
  library(yaml)
})

# ── Project helpers and paths ──────────────────────────────────────────────────
source("src/utils/helpers.R")
paths <- load_paths()

# Convenience: garch_shock_ext specification paths
sp <- paths$specs$garch_shock_ext

This notebook reproduces the full empirical analysis of “Who Stays Calm in Chaos? The Financial Instability of Crypto-Assets.” Each section integrates the paper text with the R code that produced it. Heavy estimations (DFM, GARCH, rolling QR) are wrapped in eval=FALSE blocks; the notebook loads results from pre-computed parquet files in output/models/.


Abstract

This article measures financial instability in crypto-asset markets using the quantile regression framework of Baur & Schulze (2009), extended to individual assets and estimated in 18-month rolling windows. We classify each asset as financially unstable or fragile based on whether its sensitivity to systematic shocks increases in the left or right tail of its return distribution. Applied to 137 crypto-assets over 2019–2026, approximately 10% of assets exhibit Financial Instability and 16% exhibit Financial Fragility on average. Financial Instability concentrates around the 2022 Crypto-Winter while Financial Fragility peaks during the 2021 bull market, consistent with the Minsky hypothesis. Crypto markets exhibit substantially higher instability and fragility than a benchmark of individual equity stocks. A predictive portfolio exercise confirms that stable assets generate higher cumulative returns than tail-amplifying assets over the full sample.

Keywords: Financial Stability · Crypto-Assets · Contagion · Systematic Risk · Quantile


1 Introduction

Crypto-assets have expanded rapidly in both popularity and market capitalization, leading to their gradual inclusion in investment portfolios. Yet, this growing adoption raises concerns about growing interactions with traditional markets, and the financial stability of crypto-markets is a major concern. Existing works fail to produce objective conclusions on the financial stability of crypto-markets. This paper addresses this gap by adopting an operational definition of financial asset stability from Baur & Schulze (2009) that yields a binary classification for each crypto-asset in each period.

While early adoption of crypto-assets remained limited to a niche group of enthusiasts, large holders (“whales”), and individuals engaged in illegal activities (Athey et al., 2016; Foley et al., 2019; Aiello et al., 2023), the creation of crypto-exchanges accelerated the development of crypto-markets since 2017. Several works document the dynamics of retail adoption (Lammer et al., 2020; Auer et al., 2022; Cornelli et al., 2023). On the institutional side, research consistently shows rising adoption (Huang et al., 2022; Auer & Ongena, 2022). This growing adoption raises concerns from regulators and academics regarding bubble dynamics (Panetta, 2022; Kyriazis et al., 2020) and the financial stability of crypto-markets more broadly (Grippa & Mann, 2022). However, existing measures do not provide a financial stability index grounded in a formal definition and independent of benchmark selection.

Financial market instability received greater attention in the aftermath of the Bretton-Woods system collapse (Minsky, 1977). The literature has converged on several complementary notions of financial stability. From a practical perspective, it represents the absence of financial instabilities or crises (Crockett, 1996; Chant, 2003). The Financial Instability Hypothesis (Minsky, 1977, 1992) argues that financial instability is endogenous: prolonged favorable conditions foster increasingly fragile financial structures. Schinasi (2004) defines financial stability as the capacity of a financial system to fulfil its functions resiliently. Allen & Gale (2008) argue that financial instabilities transform markets from shock absorbers to shock amplifiers. Against this backdrop, Baur & Schulze (2009) propose testing financial stability via quantile regressions.

The literature examining the financial stability of crypto-assets is extensive, yet only a few studies follow established definitions. Some articles use volatility comparisons (Bhosale & Mavale, 2018; Gupta et al., 2022; Baur & Dimpfl, 2021; Kristoufek, 2023), which remain sensitive to benchmark choice and are not a direct measure of financial stability. More recent works (Chatziantoniou et al., 2021; Ando et al., 2022; Bouri et al., 2021) introduce tail-sensitive connectedness measures, yet often rely on ad hoc criteria to label stability without enabling formal coefficient comparisons across quantiles.

This article proposes to fill this gap by employing the quantile regression framework of Baur & Schulze (2009) at the individual asset level for crypto-markets. Our three contributions are:

  1. Financial Instability as left-tail amplification. We propose a definition-grounded metric — the amplification of negative systematic shocks — rather than benchmark-dependent volatility measures. Approximately 10% of crypto-assets amplify systematic shocks in their extreme negative regimes on average.

  2. Asset-level, rolling-window application. Financial Instability is episodic, concentrating in three structurally distinct waves: the 2017–2018 Crypto-Winter, the Terra/LUNA–FTX sequence of 2022, and a third episode in late 2025.

  3. Financial Fragility index. Following the Financial Instability Hypothesis, we construct an index of upside amplification as an indicator of speculative build-up. Financial Fragility peaks during the 2021 bull market, consistent with Minsky (1977, 1992).

The rest of the article is organized as follows. Section 2 presents the data and methodology. Section 3 provides our results. Section 4 reports further analyses. Section 5 presents robustness checks. Section 6 concludes.


2 Methodology and Data

2.1 Data

We collect the list of the 40 most capitalized crypto-assets on the first week of each year from 2017 to 2025 from CoinMarketCap and remove stablecoins from the sample, leading to a final sample of 137 crypto-assets. Stablecoins are identified using CoinGecko and excluded under categories “Stablecoins,” “Fiat-backed Stablecoins,” “USD Stablecoins,” and “Crypto-backed Stablecoins.”

We extract daily price data from January 1, 2018 to February 1, 2026 from CryptoCompare. Returns are measured as log-price differences. To ensure liquidity, we remove observations when the volume is below 10 tokens.1

# ── Load the final crypto panel ────────────────────────────────────────────────
# data_crypto.parquet contains log returns, market caps, and — crucially —
# resid_garch_std: the GARCH-standardised systematic shock z_t = ε_t/σ_t.
data_crypto <- arrow::read_parquet(paths$data$final$data_crypto) %>%
  mutate(date = as.Date(date)) %>%
  select(date, variable, return, resid_garch_std)

cat("Panel:", nrow(data_crypto), "obs —",
    length(unique(data_crypto$variable)), "tokens —",
    format(min(data_crypto$date)), "to", format(max(data_crypto$date)), "\n")
Panel: 312623 obs — 145 tokens — 2018-01-01 to 2026-02-01 
# ── Summary statistics ─────────────────────────────────────────────────────────
make_stats_row <- function(x, label, n_assets = NA_character_) {
  data.frame(
    Series       = label,
    Mean         = round(mean(x, na.rm=TRUE), 3),
    `Std. Dev.`  = round(sd(x, na.rm=TRUE), 3),
    Median       = round(median(x, na.rm=TRUE), 3),
    Minimum      = round(min(x, na.rm=TRUE), 3),
    Maximum      = round(max(x, na.rm=TRUE), 3),
    Observations = formatC(sum(!is.na(x)), format="d", big.mark=","),
    Assets       = n_assets,
    check.names  = FALSE
  )
}

ret_vec   <- data_crypto$return[!is.na(data_crypto$return)]
shock_vec <- data_crypto %>%
  filter(!is.na(resid_garch_std)) %>%
  distinct(date, resid_garch_std) %>%
  pull(resid_garch_std)

bind_rows(
  make_stats_row(ret_vec,   "Log returns",      n_assets = as.character(n_distinct(data_crypto$variable))),
  make_stats_row(shock_vec, "Systematic shock",  n_assets = "—")
) %>%
  kable(caption = "**Table 1 — Summary Statistics**",
        align = c("l","r","r","r","r","r","r","r")) %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE, font_size = 13) %>%
  footnote(
    general = "Log returns are daily log price changes for 137 crypto-assets over January 2018 to February 2026. The systematic shock is the standardised residual z_t = ε_t/σ_t of an eGARCH(1,1) model applied to the first-differenced Crypto-Factor.",
    general_title = "Note: "
  )
**Table 1 — Summary Statistics**
Series Mean Std. Dev. Median Minimum Maximum Observations Assets
Log returns -0.001 0.139 -0.001 -22.928 22.924 312,478 145
Systematic shock 0.007 0.969 0.032 -8.215 6.939 2,954
Note:
Log returns are daily log price changes for 137 crypto-assets over January 2018 to February 2026. The systematic shock is the standardised residual z_t = ε_t/σ_t of an eGARCH(1,1) model applied to the first-differenced Crypto-Factor.

2.2 Systematic Shocks

To estimate systematic shocks in crypto-markets, we specify a Dynamic Factor Model (DFM) for a panel of crypto-asset prices. As Rey & Miranda-Agrippino (2021) argue, the single factor of equity prices combines market risk and aggregate risk-aversion. We maintain this interpretation for crypto markets.

Let pt denote an n-dimensional vector of daily prices pi, t that are a linear combination of a common factor ft following an AR(p) process and an idiosyncratic error term εi, t:

pi, t = λi(L) ft + εi, t

ft = A1ft − 1 + ⋯ + Aqft − q + ηt

where ηt ∼ 𝒩(0,Σ) and λi is a vector of factor loadings for asset i. Following Che et al. (2023), we estimate the single factor on the 7 biggest crypto-assets by market capitalization (Bitcoin, Ethereum, Ripple, Binance Coin, Cardano, TRON and DOGE), representing around 70% of the crypto-market capitalization at the end of our sample.

# ── DFM estimation (eval=FALSE — run once via src/02_factor_and_shocks.R) ─────
# Inputs:  data/raw/* price data from CryptoCompare
# Outputs: data/intermediate/market_shocks.parquet  (contains the DFM factor
#          series, raw GARCH residuals, and resid_garch_std_crypto = z_t)
#
# The eGARCH(1,1) with Student distribution is then applied in
# src/02c_garch_std_shock.R, which patches data_crypto.parquet to add
# resid_garch_std = z_t = ε_t / σ_t.
source("src/02_factor_and_shocks.R")
source("src/02c_garch_std_shock.R")

We construct the systematic shock ft* as the standardised residuals of an eGARCH(1,1) model2 applied to the Crypto-Factor in first difference for stationarity:

$$f^*_t = z_t = \frac{\varepsilon_t}{\sigma_t}$$

where εt is the GARCH residual and σt is the estimated conditional standard deviation. By construction, zt has unit scale at every date, making cross-window shock distributions comparable. This matters because the GARCH residuals exhibit substantial variation in conditional variance across subsamples: a unit shock in a calm window is not comparable to a unit shock in a turbulent window. Standardising by σt removes this scale heterogeneity while preserving the variance-transmission channel in the dependent variable — a key distinction from alternative scalings that filter the returns themselves.3

# z_t is stored directly in data_crypto.parquet (column resid_garch_std)
# It is also in data/intermediate/market_shocks.parquet as resid_garch_std_crypto

shock_series <- data_crypto %>%
  distinct(date, z_t = resid_garch_std) %>%
  filter(!is.na(z_t)) %>%
  arrange(date)

ggplot(shock_series, aes(x = date, y = z_t)) +
  geom_line(color = "black", linewidth = 0.4, alpha = 0.85) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "grey50") +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.01)) +
  labs(x = NULL, y = expression(z[t] == epsilon[t] / sigma[t])) +
  theme_crypto()

# The factor series is saved in market_shocks.parquet
market_shocks <- arrow::read_parquet(paths$data$intermediate$market_shocks) %>%
  mutate(date = as.Date(date))

ggplot(market_shocks, aes(x = date, y = serie)) +
  geom_line(color = "black", linewidth = 0.6) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.01)) +
  labs(x = NULL, y = "Factor level") +
  theme_crypto()

2.3 Quantile Regression Framework

Our empirical strategy builds on Baur & Schulze (2009), who define financial asset stability as the absence of increasing shock sensitivity in the tails of the return distribution relative to normal conditions. For each asset i, we estimate the following quantile regression at three quantiles τ — the lower tail (τ = 0.05), the median (τ = 0.50), and the upper tail (τ = 0.95):

Qτ(ritft*) = αi(τ) + βi(τ) ft* + γi(τ) ft* ⋅ Dtlower + ϕi(τ) ft* ⋅ Dtupper + εi(τ)

where rit is the return of asset i, ft* = zt is the standardised systematic shock, and Dtlower (Dtupper) is a dummy equal to one when ft* falls in the bottom (top) 5% of its in-window distribution.

The bilateral shock dummies isolate the relationship between asset return regimes and systematic shocks of ordinary magnitude. Without them, βi(τ) would conflate the asset’s intrinsic regime-dependent sensitivity with the general co-movement induced by tail market events — confounding tail-dependence with co-exceedances. Under this setup, βi(τ) identifies how asset return regimes relate to the systematic factor under normal market conditions, while γi and ϕi capture additional sensitivity under extreme shocks.

The equation delivers three quantile-specific estimates: β̂lower ≡ β̂i(0.05), β̂med ≡ β̂i(0.50), and β̂upper ≡ β̂i(0.95). Each tail is tested against the median via a pairwise Wald test (Koenker & Machado, 1999) at the 10% significance level.

Classification rules:

  • Financial Instability (left-tail amplification): β̂lower > β̂med and Wald test rejects at 10%. Shock transmission intensifies when assets are in distress, amplifying aggregate downside risk (Forbes & Rigobon, 2001; Longin & Solnik, 2001).

  • Financial Fragility (right-tail amplification): β̂upper > β̂med and Wald test rejects at 10%. Assets amplifying positive market shocks during expansionary phases fuel price bubbles and create correlated exposures that subsequently unwind (Brunnermeier et al., 2013), consistent with the Minsky hypothesis.

To capture time variation, we estimate the equation within 18-month rolling windows, stepping monthly. Assets are included only if their return coverage exceeds 90% of the available trading days in a given window.4 Each window is self-contained: all estimates and shock quantile thresholds are computed within the window, preventing contamination by out-of-window information.

# ── Rolling QR estimation (eval=FALSE — run once via src/25_garch_shock_full.R)
#
# The function run_rolling_qr_analysis() in helpers.R parallelises over windows.
# It reads data_crypto.parquet (which already contains resid_garch_std = z_t),
# and applies the formula:
#   return ~ resid_garch_std + resid_garch_std:d_low + resid_garch_std:d_high
# with bilateral dummies (add_dummies = "bilateral", shock_q = 0.05).
#
# Output: output/models/roll_18_garch_shock_ext.parquet
#   Columns: end, variable, left_tail, right_tail,
#            beta_lower, beta_median, beta_upper,
#            p_lower, p_upper, instable, cont, spec
source("src/25_garch_shock_full.R")
# ── Load pre-computed rolling QR results ──────────────────────────────────────
roll <- arrow::read_parquet(sp$models$roll_18) %>%
  mutate(end = as.Date(end))

cat("Rolling results:", nrow(roll), "rows —",
    length(unique(roll$variable)), "tokens —",
    length(unique(roll$end)), "windows\n")
Rolling results: 7760 rows — 137 tokens — 80 windows
cat("Classification columns: cont (FI), spec (FF), instable\n")
Classification columns: cont (FI), spec (FF), instable
roll %>%
  group_by(end) %>%
  summarise(n = n_distinct(variable), .groups = "drop") %>%
  ggplot(aes(x = end, y = n)) +
  geom_line(color = "black", linewidth = 0.7) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.01)) +
  scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Number of assets") +
  theme_crypto()


3 Results

3.1 Financial Instability and Financial Fragility Dynamics

Figure 1 reports the results of our classification strategy in rolling windows, alongside crypto market capitalisation. On average, approximately 10% of crypto-assets exhibit left-tail amplification of systematic shocks. The fraction exhibiting Financial Fragility is higher, averaging 15%.

# ── Rolling shares ─────────────────────────────────────────────────────────────
shares <- roll %>%
  group_by(end) %>%
  summarise(
    fi   = mean(cont, na.rm = TRUE) * 100,
    ff   = mean(spec, na.rm = TRUE) * 100,
    n    = n_distinct(variable),
    .groups = "drop"
  )

shares %>%
  summarise(
    `FI mean (%)`  = round(mean(fi), 1),
    `FI max (%)`   = round(max(fi), 1),
    `FF mean (%)`  = round(mean(ff), 1),
    `FF max (%)`   = round(max(ff), 1),
    `Avg. N`       = round(mean(n))
  ) %>%
  kable(caption = "**Average FI/FF shares across 80 rolling windows**") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)
**Average FI/FF shares across 80 rolling windows**
FI mean (%) FI max (%) FF mean (%) FF max (%) Avg. N
10.1 33.3 15.8 35.6 97
shares %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(metric = factor(
    recode(metric, fi = "Financial Instability", ff = "Financial Fragility"),
    levels = c("Financial Instability", "Financial Fragility")
  )) %>%
  ggplot(aes(x = end, y = share / 100, color = metric, linetype = metric)) +
  geom_line(linewidth = 1) +
  scale_color_manual(
    values = c("Financial Instability" = "#d62728",
               "Financial Fragility"   = "#1f77b4"),
    name = NULL) +
  scale_linetype_manual(
    values = c("Financial Instability" = "solid",
               "Financial Fragility"   = "solid"),
    name = NULL) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

The Financial Instability share is episodic rather than persistent. Three structurally distinct episodes emerge:

  1. 2019: tail of the 2017–2018 Crypto-Winter, following Bitcoin’s peak near $20,000 in December 2017 and a subsequent decline exceeding 80%.

  2. Mid-2022 (peak: November 2022): the Terra/LUNA implosion in May 2022, followed by the failures of Three Arrows Capital and Celsius Network, and the FTX exchange collapse in November 2022. A secondary elevation persists into early 2023, coinciding with the Silicon Valley Bank failure and the brief USDC depeg.

  3. Late 2025: a third episode at the end of the estimation sample.

The Financial Fragility share exhibits a different dynamic: elevated and relatively persistent over 2020–2024. It peaks above 30% in mid-2021 during the bull market following the initial Covid-19 recovery, consistent with Lahmiri & Bekiros (2020), and remains above its sample mean through 2024. This pattern is consistent with Minsky’s Financial Instability Hypothesis (1992): speculative financing and herding accumulate during sustained price appreciation, manifesting as right-tail amplification. The increase in Financial Fragility slightly precedes the market capitalisation peak, consistent with behavioural amplification preceding aggregate overvaluation (Brunnermeier & Nagel, 2009; Stolborg et al., 2025).

Neither index co-moves systematically with aggregate market volatility over the full sample. For Financial Instability, the absence of a positive correlation with volatility is consistent with studies arguing that volatility is not a good predictor of financial crises (Danielsson et al., 2018; Sornette & Cauwels, 2018) and justifies our approach.

Financial Fragility exceeds Financial Instability throughout the sample, reflecting the asymmetric structure of crypto market cycles. Boom phases are prolonged and broad-based relative to sharp but brief crash episodes: during expansionary phases, speculative demand and momentum trading cause a large cross-section of assets to amplify positive systematic shocks simultaneously (Minsky, 1977; Bouri et al., 2019). Crash episodes, by contrast, are concentrated in time and the amplification of negative shocks is more selective. The result is a persistently higher share of assets exhibiting right-tail amplification than left-tail amplification.


4 Further Analysis

4.1 Portfolio Performance

We construct four equally-weighted portfolios formed on the rolling classification, rebalanced monthly with a one-month forward lag to ensure the classification is fully out-of-sample:

  • Financial Instability portfolio: holds assets with β̂i(0.05) > β̂i(0.50) exclusively
  • Financial Fragility portfolio: holds assets with β̂i(0.95) > β̂i(0.50) exclusively
  • Stable portfolio: all remaining assets satisfying neither criterion
  • Top-10 benchmark: equally-weighted portfolio of the ten most prominent crypto-assets
# ── Portfolio construction (eval=FALSE — run once via src/12_portfolio_performance.R)
# Uses roll_18_garch_shock_ext.parquet + daily return data from data_crypto.parquet.
# Classification at window end t → portfolio held over month t+1.
# Output: output/figures/garch_shock_ext/paper/portfolio_predictive.pdf
source("src/12_portfolio_performance.R")

# ── Helper functions (from src/12_portfolio_performance.R) ────────────────────
build_constituents <- function(roll_df, portfolio_type) {
  if (portfolio_type == "bench") {
    return(roll_df %>% distinct(end, variable) %>% mutate(in_portfolio = TRUE))
  }
  roll_df %>%
    distinct(end, variable, instable, cont, spec) %>%
    mutate(in_portfolio = case_when(
      portfolio_type == "cont_only" ~ (as.logical(cont) & !as.logical(spec)),
      portfolio_type == "spec_only" ~ (as.logical(spec) & !as.logical(cont)),
      portfolio_type == "stable"    ~ (!as.logical(instable) & !is.na(instable)),
      TRUE ~ FALSE
    )) %>%
    select(end, variable, in_portfolio)
}

build_constituents_lagged <- function(roll_df, portfolio_type) {
  build_constituents(roll_df, portfolio_type) %>%
    arrange(variable, end) %>%
    group_by(variable) %>%
    mutate(in_portfolio = lag(in_portfolio, default = FALSE)) %>%
    ungroup()
}

compute_daily_returns <- function(daily_df, constituents_df) {
  dates_sched <- sort(unique(constituents_df$end))
  ret_cap     <- log(2)
  purrr::map_dfr(seq_along(dates_sched), function(i) {
    t_start <- dates_sched[i]
    t_end   <- if (i < length(dates_sched)) dates_sched[i + 1L] else max(daily_df$date)
    members <- constituents_df %>% filter(end == t_start, in_portfolio) %>% pull(variable)
    rows    <- daily_df %>% filter(date > t_start, date <= t_end)
    if (length(members) == 0)
      return(rows %>% distinct(date) %>% mutate(port_ret = NA_real_, n_assets = 0L))
    wts <- tibble(variable = members, weight = 1 / length(members))
    rows %>%
      filter(variable %in% members) %>%
      left_join(wts, by = "variable") %>%
      mutate(simple_ret = exp(pmax(pmin(return, ret_cap), -ret_cap)) - 1) %>%
      group_by(date) %>%
      summarise(port_ret  = sum(simple_ret * weight, na.rm = TRUE) /
                              max(sum(weight[!is.na(simple_ret)]), 1e-9),
                n_assets  = sum(!is.na(simple_ret)),
                .groups = "drop")
  })
}

# ── Top-10 fixed basket ────────────────────────────────────────────────────────
TOP10 <- c("BTC","ETH","BNB","XRP","ADA","SOL","DOGE","TRX","LTC","DOT")
top10_assets <- intersect(TOP10, unique(roll$variable))
top10_const  <- roll %>% distinct(end) %>%
  crossing(variable = top10_assets) %>%
  mutate(in_portfolio = TRUE)

# ── Build lagged predictive portfolios ────────────────────────────────────────
port_types <- c(cont_only = "Financial Instability",
                spec_only = "Financial Fragility",
                stable    = "Stable")

port_data <- purrr::imap_dfr(port_types, function(label, ptype) {
  build_constituents_lagged(roll, ptype) %>%
    compute_daily_returns(data_crypto, .) %>%
    mutate(portfolio = label)
})

top10_data <- compute_daily_returns(data_crypto, top10_const) %>%
  mutate(portfolio = "Top-10")

# ── Cumulative wealth ──────────────────────────────────────────────────────────
PORT_LEVELS <- c("Stable", "Top-10", "Financial Fragility", "Financial Instability")
COLORS_PORT <- c("Financial Instability" = "#d62728",
                 "Financial Fragility"   = "#1f77b4",
                 "Stable"                = "darkgreen",
                 "Top-10"                = "black")

bind_rows(port_data, top10_data) %>%
  mutate(portfolio = factor(portfolio, levels = PORT_LEVELS)) %>%
  group_by(portfolio) %>%
  arrange(date) %>%
  mutate(cum_wealth = 100 * cumprod(ifelse(is.na(port_ret), 1, 1 + port_ret))) %>%
  ungroup() %>%
  ggplot(aes(x = date, y = cum_wealth, color = portfolio, linetype = portfolio)) +
  geom_line(linewidth = 0.9, na.rm = TRUE) +
  scale_y_log10(labels = scales::label_number(accuracy = 1)) +
  scale_color_manual(values = COLORS_PORT, name = NULL) +
  scale_linetype_manual(
    values = c("Financial Instability" = "solid", "Financial Fragility" = "solid",
               "Stable" = "solid", "Top-10" = "solid"),
    name = NULL) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  labs(x = NULL, y = "Cumulative wealth (log scale, base 100)") +
  theme_crypto()

The Stable portfolio generates the highest cumulative return over the full sample, outperforming both the Top-10 benchmark and the tail-amplification portfolios. Assets that do not amplify systematic shocks in either tail are less exposed to sharp drawdowns during stress episodes while still participating in broad market appreciation during calm phases, consistent with Ang et al. (2006). The result is consistent with the long-term performance advantage of assets avoiding crash amplification or bubble formation (Pellegrini et al., 2008).

The Financial Instability and Financial Fragility portfolios both underperform over the full sample. Both portfolios expand sharply during the 2021 bull market but decouple from the benchmark during the 2022 Crypto-Winter. This reflects the twin costs of tail amplification: assets exhibiting left-tail sensitivity underperform during downturns through shock amplification, while assets with right-tail sensitivity may overperform short-term during speculative phases but experience reversals once the speculative phase ends.

Overall, our tail-dependence portfolio analysis demonstrates the importance of incorporating tail-dependence in portfolio strategies, consistent with Bergmann et al. (2018) who show that tail dependence models outperform the Markowitz model in terms of cumulative return.

4.2 Comparisons with Equity Markets

To benchmark crypto instability against a traditional asset class, we apply the identical rolling quantile regression framework to individual equity stocks. Adjusted daily closing prices are sourced from Yahoo Finance for a universe of 143 large-cap firms spanning North America (60 stocks), Europe (54 stocks), Japan (13 stocks), China, Australia, and India (4 stocks).

The equity sample begins in January 1995 and closes in February 2026. The systematic equity shock is constructed by applying the same two-step procedure: a first principal component is extracted from 49 country-level equity price indices sourced from Datastream following Rey & Miranda-Agrippino (2021), and a GARCH(1,1) model is estimated on the first-differenced factor. Individual stocks are not used in factor construction, so the systematic shock is exogenous by design.

# ── Equity rolling QR (eval=FALSE — run once via src/25_garch_shock_full.R)
# Uses data/intermediate/stocks_panel.parquet.
# Output: output/models/stocks_roll_garch_shock_ext.parquet
#         output/figures/garch_shock_ext/equity/stocks_comparison.pdf
equity <- arrow::read_parquet(sp$models$stocks_roll) %>%
  mutate(end = as.Date(end))

cat("Equity results:", nrow(equity), "rows —",
    length(unique(equity$variable)), "stocks\n")
Equity results: 10804 rows — 143 stocks
bind_rows(
  data.frame(Group = "Crypto",
             `FI mean (%)` = round(mean(shares$fi), 1),
             `FF mean (%)` = round(mean(shares$ff), 1)),
  equity %>%
    group_by(end) %>%
    summarise(fi = mean(cont, na.rm=TRUE)*100,
              ff = mean(spec, na.rm=TRUE)*100, .groups="drop") %>%
    summarise(Group = "Equity",
              `FI mean (%)` = round(mean(fi), 1),
              `FF mean (%)` = round(mean(ff), 1))
) %>%
  kable(caption = "**Average Financial Instability and Fragility: Crypto vs. Equity**") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)
**Average Financial Instability and Fragility: Crypto vs. Equity**
Group FI.mean.... FF.mean.... FI mean (%) FF mean (%)
Crypto 10.1 15.8 NA NA
Equity NA NA 5.3 4.6
equity_shares <- equity %>%
  group_by(end) %>%
  summarise(fi = mean(cont, na.rm=TRUE)*100,
            ff = mean(spec, na.rm=TRUE)*100, .groups="drop")

bind_rows(
  shares      %>% select(end, fi, ff) %>% mutate(group = "Crypto"),
  equity_shares                        %>% mutate(group = "Equity")
) %>%
  filter(end >= as.Date("2019-07-01")) %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(
    metric = factor(recode(metric,
                           fi = "Financial Instability",
                           ff = "Financial Fragility"),
                    levels = c("Financial Instability", "Financial Fragility")),
    group  = factor(group, levels = c("Crypto", "Equity"))
  ) %>%
  ggplot(aes(x = end, y = share / 100, color = group, linetype = group)) +
  geom_line(linewidth = 0.9, na.rm = TRUE) +
  facet_wrap(~metric, ncol = 2) +
  scale_color_manual(values = c("Crypto" = "black", "Equity" = "#1f77b4"),
                     name = NULL) +
  scale_linetype_manual(values = c("Crypto" = "solid", "Equity" = "dashed"),
                        name = NULL) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

Equity markets exhibit substantially lower Financial Instability than crypto-assets, with an average share of 5.3% against 10.1% for crypto. A pronounced peak emerges in the immediate aftermath of the Covid-19 shock in 2020, during which synchronised global equity sell-offs generated left-tail amplification across a broad cross-section of individual stocks (Ramelli & Wagner, 2020; Alfaro et al., 2020). Outside of this episode, Financial Instability in equity markets remains well below the crypto benchmark.

The gap is even more pronounced for Financial Fragility. The average equity share of 4.6% is less than one-third of the crypto average of 15.7%. This divergence reflects the greater susceptibility of crypto markets to herding and momentum during expansionary phases (Bouri et al., 2021; Kyriazis et al., 2020): whereas equity prices respond to fundamental revisions in cash-flow expectations during booms, crypto valuations are more directly driven by speculative demand and sentiment. In addition, equity markets exhibit larger instability than fragility, consistent with Hu (2006) who shows that stock markets are more likely to exhibit left-tail dependence than right-tail dependence.

Taken together, these results establish a quantitative gap in financial stability between crypto-assets and equity markets. The novelty lies not in the direction of the finding but in its grounding: the Financial Instability and Financial Fragility indices are derived from a formal test of shock transmission stability rather than from a comparison against an arbitrary benchmark — a distinction that matters because volatility-based rankings are sensitive to the choice of reference asset, whereas our classification is self-contained at the asset level.


5 Robustness

5.1 Model Specification

We run several robustness checks to confirm that our results are not dependent on model specifications. The baseline uses 18-month rolling windows, τ ∈ {0.05, 0.50, 0.95}, Wald test at 10% significance, and bilateral dummies at the 5% tail threshold.

# ── All robustness estimations (eval=FALSE — run once via src/robust_garch_shock_ext.R)
# Outputs:
#   output/models/garch_shock_ext/robust_windows.parquet
#   output/models/garch_shock_ext/robust_tau_vec.parquet
#   output/models/garch_shock_ext/robust_alpha.parquet
#   output/models/garch_shock_ext/robust_threshold.parquet
# and corresponding PDF figures in output/figures/garch_shock_ext/robustness/
source("src/robust_garch_shock_ext.R")

5.1.1 Alternative Window Widths

We use shorter (6 and 12 months) and longer (24 and 30 months) windows. Shorter windows are more reactive but noisier; longer windows are smoother but slower to detect crises.

rob_win <- arrow::read_parquet(sp$models$robust_windows) %>%
  mutate(end = as.Date(end)) %>%
  group_by(end, window_months) %>%
  summarise(fi = mean(cont, na.rm=TRUE), ff = mean(spec, na.rm=TRUE), .groups="drop") %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(metric = factor(recode(metric,
    fi = "Financial Instability", ff = "Financial Fragility"),
    levels = c("Financial Instability", "Financial Fragility")))

band_win  <- rob_win %>%
  group_by(end, metric) %>%
  summarise(lo = min(share), hi = max(share), .groups = "drop")
base_win  <- rob_win %>% filter(window_months == 18)

ggplot(band_win, aes(x = end)) +
  geom_ribbon(aes(ymin = lo, ymax = hi), fill = "grey70", alpha = 0.5) +
  geom_line(data = base_win, aes(y = share), color = "black", linewidth = 0.9) +
  facet_wrap(~metric, ncol = 2) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

Despite the heterogeneity introduced by window choice, our results stay consistent across specifications — particularly for the Financial Instability index, while the Financial Fragility index exhibits larger timing differences but a similar overall dynamics.

5.1.2 Alternative Quantile Vectors

We use a stricter specification (τ ∈ {0.01, 0.50, 0.99}) and a milder specification (τ ∈ {0.10, 0.50, 0.90}).

rob_tau <- arrow::read_parquet(sp$models$robust_tau_vec) %>%
  mutate(end = as.Date(end)) %>%
  group_by(end, tau_spec) %>%
  summarise(fi = mean(cont, na.rm=TRUE), ff = mean(spec, na.rm=TRUE), .groups="drop") %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(metric = factor(recode(metric,
    fi = "Financial Instability", ff = "Financial Fragility"),
    levels = c("Financial Instability", "Financial Fragility")))

band_tau <- rob_tau %>%
  group_by(end, metric) %>%
  summarise(lo = min(share), hi = max(share), .groups = "drop")
base_tau <- rob_tau %>% filter(tau_spec == "baseline")

ggplot(band_tau, aes(x = end)) +
  geom_ribbon(aes(ymin = lo, ymax = hi), fill = "grey70", alpha = 0.5) +
  geom_line(data = base_tau, aes(y = share), color = "black", linewidth = 0.9) +
  facet_wrap(~metric, ncol = 2) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

The Financial Instability index is robust to the change of quantiles. The Financial Fragility index exhibits larger variation under the stricter specification, but the dynamics remains similar overall.

5.1.3 Alternative Significance Levels

We report results with a tighter 5% Wald test significance level alongside the baseline 10%.

rob_alpha <- arrow::read_parquet(sp$models$robust_alpha) %>%
  mutate(end = as.Date(end)) %>%
  group_by(end, alpha_val) %>%
  summarise(fi = mean(cont, na.rm=TRUE), ff = mean(spec, na.rm=TRUE), .groups="drop") %>%
  filter(abs(alpha_val - 0.05) < 1e-9 | abs(alpha_val - 0.10) < 1e-9) %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(
    metric = factor(recode(metric,
      fi = "Financial Instability", ff = "Financial Fragility"),
      levels = c("Financial Instability", "Financial Fragility")),
    alpha_label = factor(paste0(alpha_val * 100, "%"), levels = c("5%", "10%"))
  )

ggplot(rob_alpha, aes(x = end, y = share,
                      color = alpha_label, linetype = alpha_label)) +
  geom_line(linewidth = 0.9, na.rm = TRUE) +
  facet_wrap(~metric, ncol = 2) +
  scale_color_manual(values = c("5%" = "grey60", "10%" = "black"), name = NULL) +
  scale_linetype_manual(values = c("5%" = "solid", "10%" = "solid"), name = NULL) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

Consistent with using a tighter threshold, the level of Financial Instability and Financial Fragility decrease, yet the dynamics of both indices do not substantially change.

5.1.4 Alternative Extreme-Shock Thresholds

We report results for q ∈ {2.5%, 7.5%, 10%} against the baseline q = 5%.

rob_thr <- arrow::read_parquet(sp$models$robust_threshold) %>%
  mutate(end = as.Date(end)) %>%
  group_by(end, q_threshold) %>%
  summarise(fi = mean(cont, na.rm=TRUE), ff = mean(spec, na.rm=TRUE), .groups="drop") %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(metric = factor(recode(metric,
    fi = "Financial Instability", ff = "Financial Fragility"),
    levels = c("Financial Instability", "Financial Fragility")))

band_thr <- rob_thr %>%
  group_by(end, metric) %>%
  summarise(lo = min(share), hi = max(share), .groups = "drop")
base_thr <- rob_thr %>% filter(abs(q_threshold - 0.05) < 1e-9)

ggplot(band_thr, aes(x = end)) +
  geom_ribbon(aes(ymin = lo, ymax = hi), fill = "grey70", alpha = 0.5) +
  geom_line(data = base_thr, aes(y = share), color = "black", linewidth = 0.9) +
  facet_wrap(~metric, ncol = 2) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

These alternative specifications confirm that the construction of Financial Instability and Financial Fragility is not dependent on the definition of extreme systematic shock dummies.

5.2 Selection in the Asset Universe

A potential concern is that large-cap assets may be structurally more stable than smaller tokens (Amihud, 2002), so that restricting the sample to assets ever ranked in the top 50 could understate Financial Instability and Fragility in the broader crypto universe. To assess this, we replicate the rolling estimation on an independent sample of 150 tokens listed on CoinMarketCap before January 2019 but absent from the baseline universe.

# ── Extended universe estimation (eval=FALSE — run once via src/tmp_extended_universe.R)
# Downloads 150 tokens via crypto2 (CoinMarketCap, no API key needed).
# Output: output/models/roll_extended_garch_shock_ext.parquet
#         output/figures/garch_shock_ext/robustness/selection_bias_extended.pdf
source("src/tmp_extended_universe.R")
# ── Selection bias summary table ───────────────────────────────────────────────
roll_ext <- arrow::read_parquet(
  "output/models/roll_extended_garch_shock_ext.parquet"
) %>% mutate(end = as.Date(end))

ext_shares <- roll_ext %>%
  group_by(end) %>%
  summarise(fi = mean(cont, na.rm=TRUE)*100,
            ff = mean(spec, na.rm=TRUE)*100, .groups="drop")

data.frame(
  Index   = rep(c("Financial Instability","Financial Fragility"), 2),
  Universe = c(rep("Baseline (top-50, N=137)", 2), rep("Extended (smaller tokens, N≈146)", 2)),
  Mean    = c(round(mean(shares$fi),1), round(mean(shares$ff),1),
              round(mean(ext_shares$fi),1), round(mean(ext_shares$ff),1)),
  SD      = c(round(sd(shares$fi),1),   round(sd(shares$ff),1),
              round(sd(ext_shares$fi),1), round(sd(ext_shares$ff),1)),
  Min     = c(round(min(shares$fi),1),  round(min(shares$ff),1),
              round(min(ext_shares$fi),1), round(min(ext_shares$ff),1)),
  Max     = c(round(max(shares$fi),1),  round(max(shares$ff),1),
              round(max(ext_shares$fi),1), round(max(ext_shares$ff),1))
) %>%
  arrange(Index, Universe) %>%
  kable(caption = "**Table 2 — Financial Instability and Fragility: Baseline vs. Extended Universe**",
        col.names = c("Index","Universe","Mean (%)","Std. Dev.","Min","Max"),
        align = c("l","l","r","r","r","r")) %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE, font_size = 13) %>%
  footnote(general = "Time-series statistics computed over rolling estimation windows. Extended universe: 150 tokens listed before January 2019 and absent from the baseline sample, downloaded via CoinMarketCap (crypto2 package).")
**Table 2 — Financial Instability and Fragility: Baseline vs. Extended Universe**
Index Universe Mean (%) Std. Dev. Min Max
Financial Fragility Baseline (top-50, N=137) 15.8 6.6 4.6 35.6
Financial Fragility Extended (smaller tokens, N≈146) 22.0 17.1 1.4 58.4
Financial Instability Baseline (top-50, N=137) 10.1 6.4 1.0 33.3
Financial Instability Extended (smaller tokens, N≈146) 9.7 12.7 0.0 64.4
Note:
Time-series statistics computed over rolling estimation windows. Extended universe: 150 tokens listed before January 2019 and absent from the baseline sample, downloaded via CoinMarketCap (crypto2 package).

The Financial Instability index is robust: the average share of 9.7% in the extended universe is nearly identical to the baseline 10.1%, and the episodic dynamics are preserved. The Financial Fragility share is systematically higher among smaller tokens (22.0% versus 15.8%), reflecting their greater susceptibility to speculative amplification during boom phases — a genuine compositional feature rather than a downward bias in the baseline.

[WARNING] Could not convert TeX math f^*_t = z_t = \frac{\varepsilon_t}{\sigma_t}, rendering as TeX
bind_rows(
  shares     %>% select(end, fi, ff) %>% mutate(group = "Top-50 universe (baseline)"),
  ext_shares %>% select(end, fi, ff) %>% mutate(group = "Extended universe (smaller tokens)")
) %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(
    metric = factor(recode(metric,
      fi = "Financial Instability", ff = "Financial Fragility"),
      levels = c("Financial Instability", "Financial Fragility")),
    group  = factor(group, levels = c("Top-50 universe (baseline)",
                                      "Extended universe (smaller tokens)"))
  ) %>%
  ggplot(aes(x = end, y = share / 100, color = group, linetype = group)) +
  geom_line(linewidth = 0.85, na.rm = TRUE) +
  facet_wrap(~metric, ncol = 2) +
  scale_color_manual(
    values = c("Top-50 universe (baseline)" = "black",
               "Extended universe (smaller tokens)" = "#d62728"),
    name = NULL) +
  scale_linetype_manual(
    values = c("Top-50 universe (baseline)" = "solid",
               "Extended universe (smaller tokens)" = "dashed"),
    name = NULL) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

5.3 Endogeneity of Factor Constituents

The systematic shock ft* is extracted from a DFM estimated on seven benchmark assets. Because these seven assets contribute directly to the construction of the shock, their estimated quantile betas may be mechanically inflated. To assess this, we recompute the shares after excluding the seven factor constituents from the classification. No re-estimation is required: we simply exclude BTC, ETH, XRP, BNB, ADA, TRX, and DOGE when aggregating the shares.

# ── Factor constituent exclusion (eval=FALSE — run once via src/tmp_selection_bias_basket.R)
# Output: output/figures/garch_shock_ext/robustness/selection_bias.pdf
source("src/tmp_selection_bias_basket.R")
BASKET <- c("BTC", "ETH", "XRP", "BNB", "ADA", "TRX", "DOGE")

restr_shares <- roll %>%
  filter(!(variable %in% BASKET)) %>%
  group_by(end) %>%
  summarise(fi = mean(cont, na.rm=TRUE)*100,
            ff = mean(spec, na.rm=TRUE)*100, .groups="drop")

bind_rows(
  shares       %>% select(end, fi, ff) %>% mutate(group = "Baseline"),
  restr_shares %>% select(end, fi, ff) %>% mutate(group = "Excl. factor constituents")
) %>%
  pivot_longer(c(fi, ff), names_to = "metric", values_to = "share") %>%
  mutate(
    metric = factor(recode(metric,
      fi = "Financial Instability", ff = "Financial Fragility"),
      levels = c("Financial Instability", "Financial Fragility")),
    group  = factor(group, levels = c("Baseline", "Excl. factor constituents"))
  ) %>%
  ggplot(aes(x = end, y = share / 100, color = group, linetype = group)) +
  geom_line(linewidth = 0.85, na.rm = TRUE) +
  facet_wrap(~metric, ncol = 2) +
  scale_color_manual(
    values = c("Baseline" = "black", "Excl. factor constituents" = "#d62728"),
    name = NULL) +
  scale_linetype_manual(
    values = c("Baseline" = "solid", "Excl. factor constituents" = "dashed"),
    name = NULL) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y",
               expand = expansion(mult = 0.02)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                     expand = expansion(mult = c(0, 0.05))) +
  labs(x = NULL, y = "Share of assets (%)") +
  theme_crypto()

The results confirm that the factor constituents do not substantially drive the classification: the FI and FF shares are nearly identical whether or not the seven basket tokens are included in the aggregation.


6 Conclusion

This paper proposes a formal, benchmark-independent measure of financial instability for crypto-asset markets. Applying the quantile regression framework of Baur & Schulze (2009) to 137 crypto-assets in 18-month rolling windows, we construct time-varying indices of Financial Instability and Financial Fragility that classify each asset according to whether its sensitivity to a GARCH-standardised systematic shock increases in the left or right tail of its return distribution. Over 2019–2026, approximately 10% of crypto-assets exhibit Financial Instability and 16% exhibit Financial Fragility on average. Financial Instability is episodic, concentrating around the 2022 Crypto-Winter and the SVB episode, while Financial Fragility is more persistent and peaks during the 2021 bull market — a sequencing consistent with the Minsky hypothesis that prolonged expansions accumulate financial fragilities that subsequently unwind. A comparison with 143 individual equity stocks confirms that crypto markets are structurally more unstable and fragile than equity markets, with the exception of the Covid-19 episode. A predictive portfolio exercise further validates the classification: assets satisfying financial stability conditions generate higher cumulative returns over the full sample than assets exhibiting tail amplification in either direction.

Several limitations warrant acknowledgement. The rolling window design introduces a detection lag of approximately half a window length. The systematic shock is constructed from a fixed set of seven benchmark assets; while the robustness analysis confirms that excluding these constituents does not alter the aggregate indices, alternative factor specifications remain to be explored. The minimum-coverage filter may also exclude recently listed tokens during the periods when they are most actively traded.

Several directions for future research follow naturally. First, the rolling Financial Instability index could be integrated into a macroprudential monitoring framework alongside on-chain metrics and stablecoin flows. Second, the asset-level classification opens the door to cross-sectional analyses examining whether Financial Instability is predicted by token-specific characteristics such as market depth, exchange concentration, or smart-contract exposure. Third, the framework could be extended to decentralised finance (DeFi) protocols and stablecoins. Finally, the documented divergence between Financial Instability and Fragility — one episodic and crisis-driven, the other persistent and boom-driven — raises questions about the interaction between the two dimensions over the full boom-bust cycle that a structural model would be well positioned to address.


Appendix

Summary Statistics

(See Table 1 in Section 2.1.)

Crypto-Factor and Systematic Shocks

(See Figures A1 and A2 in Section 2.2.)

Equity Indices

data.frame(
  Ticker = c("^INX","^GSPTSE","^COLCAP","^SPCLXIGPA","^BVSP","^MXX","^SPBLPGPT","^IBG",
             "^GDAX","^FCHI","^FTSE","^FTMIB","^SSMI","^AEX","^OMXS30","^OMXHPI",
             "^OMXCBPI","^DFMGI","^IRTS","^IBEX","^ATX","^BFX","^WIG","^BETI","^PX",
             "^OBXP","^ISEQ","^PSI20","^TRXFLDILP",
             "^JPXNK400","^SSEC","^HSI","^KS11","^BSESN","^NZ50C","^XU100","^AXJO",
             "^STI","^KLSE","^SET100","^JKSE","^VNI","^PSI",
             "^TASI","^JALSH","^EGX30","^NGSEINDEX",".dMIBD00000P"),
  Index = c("S&P 500 (USA)","S&P/TSX Composite (Canada)","MSCI COLCAP (Colombia)",
            "S&P/CLX IGPA (Chile)","Bovespa (Brazil)","IPC (Mexico)",
            "S&P/BVL General (Peru)","S&P/BYMA (Argentina)",
            "DAX (Germany)","CAC 40 (France)","FTSE 100 (UK)","FTSE MIB (Italy)",
            "SMI (Switzerland)","AEX (Netherlands)","OMX Stockholm 30 (Sweden)",
            "OMX Helsinki (Finland)","OMX Copenhagen (Denmark)","Dubai Fin. Market (UAE)",
            "RTS Index (Russia)","IBEX 35 (Spain)","ATX (Austria)","BEL 20 (Belgium)",
            "Warsaw General (Poland)","BET (Romania)","PX Prague (Czech Rep.)",
            "Oslo OBX (Norway)","ISEQ All Share (Ireland)","PSI-20 (Portugal)","FTSE Israel",
            "JPX-Nikkei 400 (Japan)","Shanghai Composite (China)","Hang Seng (Hong Kong)",
            "KOSPI (South Korea)","BSE Sensex (India)","S&P/NZX 50 (New Zealand)",
            "BIST 100 (Turkey)","S&P/ASX 200 (Australia)","Straits Times (Singapore)",
            "FTSE Bursa KLCI (Malaysia)","SET 100 (Thailand)","IDX Composite (Indonesia)",
            "Ho Chi Minh (Vietnam)","PSEi (Philippines)",
            "Tadawul All Share (Saudi Arabia)","FTSE/JSE All Share (South Africa)",
            "EGX 30 (Egypt)","Nigeria All Share","MSCI Bangladesh")
) %>%
  kable(caption = "**Table A1 — Equity Price Indices Used to Construct the Global Equity Factor**",
        col.names = c("Ticker","Index")) %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE, font_size = 12) %>%
  footnote(general = "The first principal component of these 49 daily price index returns is used as the global equity factor. Russia (^IRTS) is included over the full sample; observations after trading suspension are excluded.")
**Table A1 — Equity Price Indices Used to Construct the Global Equity Factor**
Ticker Index
^INX S&P 500 (USA)
^GSPTSE S&P/TSX Composite (Canada)
^COLCAP MSCI COLCAP (Colombia)
^SPCLXIGPA S&P/CLX IGPA (Chile)
^BVSP Bovespa (Brazil)
^MXX IPC (Mexico)
^SPBLPGPT S&P/BVL General (Peru)
^IBG S&P/BYMA (Argentina)
^GDAX DAX (Germany)
^FCHI CAC 40 (France)
^FTSE FTSE 100 (UK)
^FTMIB FTSE MIB (Italy)
^SSMI SMI (Switzerland)
^AEX AEX (Netherlands)
^OMXS30 OMX Stockholm 30 (Sweden)
^OMXHPI OMX Helsinki (Finland)
^OMXCBPI OMX Copenhagen (Denmark)
^DFMGI Dubai Fin. Market (UAE)
^IRTS RTS Index (Russia)
^IBEX IBEX 35 (Spain)
^ATX ATX (Austria)
^BFX BEL 20 (Belgium)
^WIG Warsaw General (Poland)
^BETI BET (Romania)
^PX PX Prague (Czech Rep.)
^OBXP Oslo OBX (Norway)
^ISEQ ISEQ All Share (Ireland)
^PSI20 PSI-20 (Portugal)
^TRXFLDILP FTSE Israel
^JPXNK400 JPX-Nikkei 400 (Japan)
^SSEC Shanghai Composite (China)
^HSI Hang Seng (Hong Kong)
^KS11 KOSPI (South Korea)
^BSESN BSE Sensex (India)
^NZ50C S&P/NZX 50 (New Zealand)
^XU100 BIST 100 (Turkey)
^AXJO S&P/ASX 200 (Australia)
^STI Straits Times (Singapore)
^KLSE FTSE Bursa KLCI (Malaysia)
^SET100 SET 100 (Thailand)
^JKSE IDX Composite (Indonesia)
^VNI Ho Chi Minh (Vietnam)
^PSI PSEi (Philippines)
^TASI Tadawul All Share (Saudi Arabia)
^JALSH FTSE/JSE All Share (South Africa)
^EGX30 EGX 30 (Egypt)
^NGSEINDEX Nigeria All Share
.dMIBD00000P MSCI Bangladesh
Note:
The first principal component of these 49 daily price index returns is used as the global equity factor. Russia (^IRTS) is included over the full sample; observations after trading suspension are excluded.

Equity Stocks

stocks_tbl <- data.frame(
  Region   = c(rep("North America",1), rep("Europe",9), rep("Asia-Pacific",5), "Total"),
  Country  = c("United States","United Kingdom","Germany","France","Netherlands",
               "Italy","Spain","Switzerland","Sweden","Denmark",
               "Japan","Hong Kong","China (US-listed)","Australia","India",""),
  Exchange = c("NYSE/NASDAQ","LSE","XETRA","Euronext Paris","Euronext Amsterdam",
               "Borsa Italiana","BME","SIX","Nasdaq Stockholm","Nasdaq Copenhagen",
               "TSE","HKEX","NYSE/NASDAQ","ASX","NSE",""),
  N        = c(60,10,10,10,5,5,4,4,4,2,10,5,3,7,4,143)
)

stocks_tbl %>%
  kable(caption = "**Table A2 — Individual Equity Stocks: Composition by Country**",
        col.names = c("Region","Country","Exchange","N"),
        align = c("l","l","l","r")) %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE, font_size = 12) %>%
  row_spec(nrow(stocks_tbl), bold = TRUE) %>%
  collapse_rows(columns = 1, valign = "middle")
**Table A2 — Individual Equity Stocks: Composition by Country**
Region Country Exchange N
North America United States NYSE/NASDAQ 60
Europe United Kingdom LSE 10
Germany XETRA 10
France Euronext Paris 10
Netherlands Euronext Amsterdam 5
Italy Borsa Italiana 5
Spain BME 4
Switzerland SIX 4
Sweden Nasdaq Stockholm 4
Denmark Nasdaq Copenhagen 2
Asia-Pacific Japan TSE 10
Hong Kong HKEX 5
China (US-listed) NYSE/NASDAQ 3
Australia ASX 7
India NSE 4
Total 143

Session Information

sessionInfo()
R version 4.5.0 (2025-04-11 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 22631)

Matrix products: default
  LAPACK version 3.12.1

locale:
[1] LC_COLLATE=French_France.utf8  LC_CTYPE=French_France.utf8    LC_MONETARY=French_France.utf8
[4] LC_NUMERIC=C                   LC_TIME=French_France.utf8    

time zone: Europe/Paris
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] zoo_1.8-14        progress_1.2.3    data.table_1.17.4 quantreg_6.1      SparseM_1.84-2    purrr_1.1.0      
 [7] yaml_2.3.10       lubridate_1.9.4   scales_1.4.0      kableExtra_1.4.0  ggplot2_4.0.0     tidyr_1.3.1      
[13] dplyr_1.1.4       arrow_21.0.0.1   

loaded via a namespace (and not attached):
 [1] gtable_0.3.6       xfun_0.52          bslib_0.9.0        lattice_0.22-6     tzdb_0.5.0        
 [6] vctrs_0.6.5        tools_4.5.0        generics_0.1.4     tibble_3.2.1       pkgconfig_2.0.3   
[11] Matrix_1.7-3       RColorBrewer_1.1-3 S7_0.2.0           assertthat_0.2.1   lifecycle_1.0.4   
[16] compiler_4.5.0     farver_2.1.2       stringr_1.5.1      MatrixModels_0.5-4 textshaping_1.0.1 
[21] htmltools_0.5.8.1  sass_0.4.10        pillar_1.10.2      crayon_1.5.3       jquerylib_0.1.4   
[26] MASS_7.3-65        rsconnect_1.5.1    cachem_1.1.0       tidyselect_1.2.1   digest_0.6.37     
[31] stringi_1.8.7      labeling_0.4.3     splines_4.5.0      fastmap_1.2.0      grid_4.5.0        
[36] cli_3.6.5          magrittr_2.0.3     survival_3.8-3     withr_3.0.2        prettyunits_1.2.0 
[41] bit64_4.6.0-1      timechange_0.3.0   rmarkdown_2.29     bit_4.6.0          hms_1.1.3         
[46] evaluate_1.0.3     knitr_1.50         viridisLite_0.4.2  rlang_1.1.6        glue_1.8.0        
[51] xml2_1.3.8         svglite_2.2.2      rstudioapi_0.17.1  jsonlite_2.0.0     R6_2.6.1          
[56] systemfonts_1.3.1 

Florian Kraus — University of Bordeaux (BSE) — Compiled with R 4.5.0 and knitr 1.50.


  1. This filter removes extreme observations likely caused by thin trading or data errors, affecting less than 0.5% of the final sample.↩︎

  2. We apply an eGARCH(1,1) model with Student distribution, selected as the optimal fit by AIC and BIC. We use GARCH rather than ARMA because residuals from an AR fit exhibit significant ARCH effects.↩︎

  3. Alternative scalings we tested: (i) using raw GARCH residuals εt as regressor (between-window distributional inequality); (ii) rolling-window variance scaling of both the shock and returns (still contaminated by slow volatility cycles); (iii) filtering both returns and shock by GARCH (removes the variance channel from the dependent variable). The GARCH-standardized shock zt = εt/σt is the preferred specification.↩︎

  4. A typical 18-month window contains approximately 547 trading days, of which around 27 are extreme negative and 27 are extreme positive shock days.↩︎

LS0tDQp0aXRsZTogfA0KICAqKldobyBTdGF5cyBDYWxtIGluIENoYW9zPyoqDQogIFRoZSBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgb2YgQ3J5cHRvLUFzc2V0cw0KYXV0aG9yOiAiRmxvcmlhbiBLcmF1cyDigJQgVW5pdmVyc2l0eSBvZiBCb3JkZWF1eCAoQlNFKSINCmRhdGU6ICJKYW51YXJ5IDIwMjYiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IGZhbHNlDQogICAgdG9jX2RlcHRoOiAzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgbWF0aGpheDogbnVsbA0KICAgIGluY2x1ZGVzOg0KICAgICAgaW5faGVhZGVyOiBtYXRoamF4X2hlYWRlci5odG1sDQogICAgY3NzOiBub3RlYm9va19zdHlsZS5jc3MNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyAgICAgID0gVFJVRSwNCiAgbWVzc2FnZSAgID0gRkFMU0UsDQogIHdhcm5pbmcgICA9IEZBTFNFLA0KICBmaWcuYWxpZ24gPSAiY2VudGVyIiwNCiAgZmlnLndpZHRoID0gMTIsDQogIGZpZy5oZWlnaHQgPSA2LA0KICBvdXQud2lkdGggPSAiMTAwJSINCikNCmBgYA0KDQpgYGB7ciBpbml0fQ0KIyDilIDilIAgUGFja2FnZXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoew0KICBsaWJyYXJ5KGFycm93KQ0KICBsaWJyYXJ5KGRwbHlyKQ0KICBsaWJyYXJ5KHRpZHlyKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQogIGxpYnJhcnkoa2FibGVFeHRyYSkNCiAgbGlicmFyeShzY2FsZXMpDQogIGxpYnJhcnkobHVicmlkYXRlKQ0KICBsaWJyYXJ5KHlhbWwpDQp9KQ0KDQojIOKUgOKUgCBQcm9qZWN0IGhlbHBlcnMgYW5kIHBhdGhzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgA0Kc291cmNlKCJzcmMvdXRpbHMvaGVscGVycy5SIikNCnBhdGhzIDwtIGxvYWRfcGF0aHMoKQ0KDQojIENvbnZlbmllbmNlOiBnYXJjaF9zaG9ja19leHQgc3BlY2lmaWNhdGlvbiBwYXRocw0Kc3AgPC0gcGF0aHMkc3BlY3MkZ2FyY2hfc2hvY2tfZXh0DQpgYGANCg0KLS0tDQoNCj4gKlRoaXMgbm90ZWJvb2sgcmVwcm9kdWNlcyB0aGUgZnVsbCBlbXBpcmljYWwgYW5hbHlzaXMgb2YgIldobyBTdGF5cyBDYWxtIGluIENoYW9zPyBUaGUgRmluYW5jaWFsIEluc3RhYmlsaXR5IG9mIENyeXB0by1Bc3NldHMuIiBFYWNoIHNlY3Rpb24gaW50ZWdyYXRlcyB0aGUgcGFwZXIgdGV4dCB3aXRoIHRoZSBSIGNvZGUgdGhhdCBwcm9kdWNlZCBpdC4gSGVhdnkgZXN0aW1hdGlvbnMgKERGTSwgR0FSQ0gsIHJvbGxpbmcgUVIpIGFyZSB3cmFwcGVkIGluIGBldmFsPUZBTFNFYCBibG9ja3M7IHRoZSBub3RlYm9vayBsb2FkcyByZXN1bHRzIGZyb20gcHJlLWNvbXB1dGVkIHBhcnF1ZXQgZmlsZXMgaW4gYG91dHB1dC9tb2RlbHMvYC4qDQoNCi0tLQ0KDQojIEFic3RyYWN0IHsudW5udW1iZXJlZH0NCg0KVGhpcyBhcnRpY2xlIG1lYXN1cmVzIGZpbmFuY2lhbCBpbnN0YWJpbGl0eSBpbiBjcnlwdG8tYXNzZXQgbWFya2V0cyB1c2luZyB0aGUgcXVhbnRpbGUgcmVncmVzc2lvbiBmcmFtZXdvcmsgb2YgQmF1ciAmIFNjaHVsemUgKDIwMDkpLCBleHRlbmRlZCB0byBpbmRpdmlkdWFsIGFzc2V0cyBhbmQgZXN0aW1hdGVkIGluIDE4LW1vbnRoIHJvbGxpbmcgd2luZG93cy4gV2UgY2xhc3NpZnkgZWFjaCBhc3NldCBhcyBmaW5hbmNpYWxseSB1bnN0YWJsZSBvciBmcmFnaWxlIGJhc2VkIG9uIHdoZXRoZXIgaXRzIHNlbnNpdGl2aXR5IHRvIHN5c3RlbWF0aWMgc2hvY2tzIGluY3JlYXNlcyBpbiB0aGUgbGVmdCBvciByaWdodCB0YWlsIG9mIGl0cyByZXR1cm4gZGlzdHJpYnV0aW9uLiBBcHBsaWVkIHRvIDEzNyBjcnlwdG8tYXNzZXRzIG92ZXIgMjAxOeKAkzIwMjYsIGFwcHJveGltYXRlbHkgKioxMCUqKiBvZiBhc3NldHMgZXhoaWJpdCBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgYW5kICoqMTYlKiogZXhoaWJpdCBGaW5hbmNpYWwgRnJhZ2lsaXR5IG9uIGF2ZXJhZ2UuIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSBjb25jZW50cmF0ZXMgYXJvdW5kIHRoZSAyMDIyIENyeXB0by1XaW50ZXIgd2hpbGUgRmluYW5jaWFsIEZyYWdpbGl0eSBwZWFrcyBkdXJpbmcgdGhlIDIwMjEgYnVsbCBtYXJrZXQsIGNvbnNpc3RlbnQgd2l0aCB0aGUgTWluc2t5IGh5cG90aGVzaXMuIENyeXB0byBtYXJrZXRzIGV4aGliaXQgc3Vic3RhbnRpYWxseSBoaWdoZXIgaW5zdGFiaWxpdHkgYW5kIGZyYWdpbGl0eSB0aGFuIGEgYmVuY2htYXJrIG9mIGluZGl2aWR1YWwgZXF1aXR5IHN0b2Nrcy4gQSBwcmVkaWN0aXZlIHBvcnRmb2xpbyBleGVyY2lzZSBjb25maXJtcyB0aGF0IHN0YWJsZSBhc3NldHMgZ2VuZXJhdGUgaGlnaGVyIGN1bXVsYXRpdmUgcmV0dXJucyB0aGFuIHRhaWwtYW1wbGlmeWluZyBhc3NldHMgb3ZlciB0aGUgZnVsbCBzYW1wbGUuDQoNCioqS2V5d29yZHM6KiogRmluYW5jaWFsIFN0YWJpbGl0eSDCtyBDcnlwdG8tQXNzZXRzIMK3IENvbnRhZ2lvbiDCtyBTeXN0ZW1hdGljIFJpc2sgwrcgUXVhbnRpbGUNCg0KLS0tDQoNCiMgSW50cm9kdWN0aW9uDQoNCkNyeXB0by1hc3NldHMgaGF2ZSBleHBhbmRlZCByYXBpZGx5IGluIGJvdGggcG9wdWxhcml0eSBhbmQgbWFya2V0IGNhcGl0YWxpemF0aW9uLCBsZWFkaW5nIHRvIHRoZWlyIGdyYWR1YWwgaW5jbHVzaW9uIGluIGludmVzdG1lbnQgcG9ydGZvbGlvcy4gWWV0LCB0aGlzIGdyb3dpbmcgYWRvcHRpb24gcmFpc2VzIGNvbmNlcm5zIGFib3V0IGdyb3dpbmcgaW50ZXJhY3Rpb25zIHdpdGggdHJhZGl0aW9uYWwgbWFya2V0cywgYW5kIHRoZSBmaW5hbmNpYWwgc3RhYmlsaXR5IG9mIGNyeXB0by1tYXJrZXRzIGlzIGEgbWFqb3IgY29uY2Vybi4gRXhpc3Rpbmcgd29ya3MgZmFpbCB0byBwcm9kdWNlIG9iamVjdGl2ZSBjb25jbHVzaW9ucyBvbiB0aGUgZmluYW5jaWFsIHN0YWJpbGl0eSBvZiBjcnlwdG8tbWFya2V0cy4gVGhpcyBwYXBlciBhZGRyZXNzZXMgdGhpcyBnYXAgYnkgYWRvcHRpbmcgYW4gb3BlcmF0aW9uYWwgZGVmaW5pdGlvbiBvZiBmaW5hbmNpYWwgYXNzZXQgc3RhYmlsaXR5IGZyb20gQmF1ciAmIFNjaHVsemUgKDIwMDkpIHRoYXQgeWllbGRzIGEgYmluYXJ5IGNsYXNzaWZpY2F0aW9uIGZvciBlYWNoIGNyeXB0by1hc3NldCBpbiBlYWNoIHBlcmlvZC4NCg0KV2hpbGUgZWFybHkgYWRvcHRpb24gb2YgY3J5cHRvLWFzc2V0cyByZW1haW5lZCBsaW1pdGVkIHRvIGEgbmljaGUgZ3JvdXAgb2YgZW50aHVzaWFzdHMsIGxhcmdlIGhvbGRlcnMgKCJ3aGFsZXMiKSwgYW5kIGluZGl2aWR1YWxzIGVuZ2FnZWQgaW4gaWxsZWdhbCBhY3Rpdml0aWVzIChBdGhleSBldCBhbC4sIDIwMTY7IEZvbGV5IGV0IGFsLiwgMjAxOTsgQWllbGxvIGV0IGFsLiwgMjAyMyksIHRoZSBjcmVhdGlvbiBvZiBjcnlwdG8tZXhjaGFuZ2VzIGFjY2VsZXJhdGVkIHRoZSBkZXZlbG9wbWVudCBvZiBjcnlwdG8tbWFya2V0cyBzaW5jZSAyMDE3LiBTZXZlcmFsIHdvcmtzIGRvY3VtZW50IHRoZSBkeW5hbWljcyBvZiByZXRhaWwgYWRvcHRpb24gKExhbW1lciBldCBhbC4sIDIwMjA7IEF1ZXIgZXQgYWwuLCAyMDIyOyBDb3JuZWxsaSBldCBhbC4sIDIwMjMpLiBPbiB0aGUgaW5zdGl0dXRpb25hbCBzaWRlLCByZXNlYXJjaCBjb25zaXN0ZW50bHkgc2hvd3MgcmlzaW5nIGFkb3B0aW9uIChIdWFuZyBldCBhbC4sIDIwMjI7IEF1ZXIgJiBPbmdlbmEsIDIwMjIpLiBUaGlzIGdyb3dpbmcgYWRvcHRpb24gcmFpc2VzIGNvbmNlcm5zIGZyb20gcmVndWxhdG9ycyBhbmQgYWNhZGVtaWNzIHJlZ2FyZGluZyBidWJibGUgZHluYW1pY3MgKFBhbmV0dGEsIDIwMjI7IEt5cmlhemlzIGV0IGFsLiwgMjAyMCkgYW5kIHRoZSBmaW5hbmNpYWwgc3RhYmlsaXR5IG9mIGNyeXB0by1tYXJrZXRzIG1vcmUgYnJvYWRseSAoR3JpcHBhICYgTWFubiwgMjAyMikuIEhvd2V2ZXIsIGV4aXN0aW5nIG1lYXN1cmVzIGRvIG5vdCBwcm92aWRlIGEgZmluYW5jaWFsIHN0YWJpbGl0eSBpbmRleCBncm91bmRlZCBpbiBhIGZvcm1hbCBkZWZpbml0aW9uIGFuZCBpbmRlcGVuZGVudCBvZiBiZW5jaG1hcmsgc2VsZWN0aW9uLg0KDQpGaW5hbmNpYWwgbWFya2V0IGluc3RhYmlsaXR5IHJlY2VpdmVkIGdyZWF0ZXIgYXR0ZW50aW9uIGluIHRoZSBhZnRlcm1hdGggb2YgdGhlIEJyZXR0b24tV29vZHMgc3lzdGVtIGNvbGxhcHNlIChNaW5za3ksIDE5NzcpLiBUaGUgbGl0ZXJhdHVyZSBoYXMgY29udmVyZ2VkIG9uIHNldmVyYWwgY29tcGxlbWVudGFyeSBub3Rpb25zIG9mIGZpbmFuY2lhbCBzdGFiaWxpdHkuIEZyb20gYSBwcmFjdGljYWwgcGVyc3BlY3RpdmUsIGl0IHJlcHJlc2VudHMgdGhlIGFic2VuY2Ugb2YgZmluYW5jaWFsIGluc3RhYmlsaXRpZXMgb3IgY3Jpc2VzIChDcm9ja2V0dCwgMTk5NjsgQ2hhbnQsIDIwMDMpLiBUaGUgRmluYW5jaWFsIEluc3RhYmlsaXR5IEh5cG90aGVzaXMgKE1pbnNreSwgMTk3NywgMTk5MikgYXJndWVzIHRoYXQgZmluYW5jaWFsIGluc3RhYmlsaXR5IGlzIGVuZG9nZW5vdXM6IHByb2xvbmdlZCBmYXZvcmFibGUgY29uZGl0aW9ucyBmb3N0ZXIgaW5jcmVhc2luZ2x5IGZyYWdpbGUgZmluYW5jaWFsIHN0cnVjdHVyZXMuIFNjaGluYXNpICgyMDA0KSBkZWZpbmVzIGZpbmFuY2lhbCBzdGFiaWxpdHkgYXMgdGhlIGNhcGFjaXR5IG9mIGEgZmluYW5jaWFsIHN5c3RlbSB0byBmdWxmaWwgaXRzIGZ1bmN0aW9ucyByZXNpbGllbnRseS4gQWxsZW4gJiBHYWxlICgyMDA4KSBhcmd1ZSB0aGF0IGZpbmFuY2lhbCBpbnN0YWJpbGl0aWVzIHRyYW5zZm9ybSBtYXJrZXRzIGZyb20gc2hvY2sgYWJzb3JiZXJzIHRvIHNob2NrIGFtcGxpZmllcnMuIEFnYWluc3QgdGhpcyBiYWNrZHJvcCwgQmF1ciAmIFNjaHVsemUgKDIwMDkpIHByb3Bvc2UgdGVzdGluZyBmaW5hbmNpYWwgc3RhYmlsaXR5IHZpYSBxdWFudGlsZSByZWdyZXNzaW9ucy4NCg0KVGhlIGxpdGVyYXR1cmUgZXhhbWluaW5nIHRoZSBmaW5hbmNpYWwgc3RhYmlsaXR5IG9mIGNyeXB0by1hc3NldHMgaXMgZXh0ZW5zaXZlLCB5ZXQgb25seSBhIGZldyBzdHVkaWVzIGZvbGxvdyBlc3RhYmxpc2hlZCBkZWZpbml0aW9ucy4gU29tZSBhcnRpY2xlcyB1c2Ugdm9sYXRpbGl0eSBjb21wYXJpc29ucyAoQmhvc2FsZSAmIE1hdmFsZSwgMjAxODsgR3VwdGEgZXQgYWwuLCAyMDIyOyBCYXVyICYgRGltcGZsLCAyMDIxOyBLcmlzdG91ZmVrLCAyMDIzKSwgd2hpY2ggcmVtYWluIHNlbnNpdGl2ZSB0byBiZW5jaG1hcmsgY2hvaWNlIGFuZCBhcmUgbm90IGEgZGlyZWN0IG1lYXN1cmUgb2YgZmluYW5jaWFsIHN0YWJpbGl0eS4gTW9yZSByZWNlbnQgd29ya3MgKENoYXR6aWFudG9uaW91IGV0IGFsLiwgMjAyMTsgQW5kbyBldCBhbC4sIDIwMjI7IEJvdXJpIGV0IGFsLiwgMjAyMSkgaW50cm9kdWNlIHRhaWwtc2Vuc2l0aXZlIGNvbm5lY3RlZG5lc3MgbWVhc3VyZXMsIHlldCBvZnRlbiByZWx5IG9uIGFkIGhvYyBjcml0ZXJpYSB0byBsYWJlbCBzdGFiaWxpdHkgd2l0aG91dCBlbmFibGluZyBmb3JtYWwgY29lZmZpY2llbnQgY29tcGFyaXNvbnMgYWNyb3NzIHF1YW50aWxlcy4NCg0KVGhpcyBhcnRpY2xlIHByb3Bvc2VzIHRvIGZpbGwgdGhpcyBnYXAgYnkgZW1wbG95aW5nIHRoZSBxdWFudGlsZSByZWdyZXNzaW9uIGZyYW1ld29yayBvZiBCYXVyICYgU2NodWx6ZSAoMjAwOSkgYXQgdGhlIGluZGl2aWR1YWwgYXNzZXQgbGV2ZWwgZm9yIGNyeXB0by1tYXJrZXRzLiBPdXIgKip0aHJlZSBjb250cmlidXRpb25zKiogYXJlOg0KDQoxLiAqKkZpbmFuY2lhbCBJbnN0YWJpbGl0eSBhcyBsZWZ0LXRhaWwgYW1wbGlmaWNhdGlvbi4qKiBXZSBwcm9wb3NlIGEgZGVmaW5pdGlvbi1ncm91bmRlZCBtZXRyaWMg4oCUIHRoZSBhbXBsaWZpY2F0aW9uIG9mIG5lZ2F0aXZlIHN5c3RlbWF0aWMgc2hvY2tzIOKAlCByYXRoZXIgdGhhbiBiZW5jaG1hcmstZGVwZW5kZW50IHZvbGF0aWxpdHkgbWVhc3VyZXMuIEFwcHJveGltYXRlbHkgMTAlIG9mIGNyeXB0by1hc3NldHMgYW1wbGlmeSBzeXN0ZW1hdGljIHNob2NrcyBpbiB0aGVpciBleHRyZW1lIG5lZ2F0aXZlIHJlZ2ltZXMgb24gYXZlcmFnZS4NCg0KMi4gKipBc3NldC1sZXZlbCwgcm9sbGluZy13aW5kb3cgYXBwbGljYXRpb24uKiogRmluYW5jaWFsIEluc3RhYmlsaXR5IGlzIGVwaXNvZGljLCBjb25jZW50cmF0aW5nIGluIHRocmVlIHN0cnVjdHVyYWxseSBkaXN0aW5jdCB3YXZlczogdGhlIDIwMTfigJMyMDE4IENyeXB0by1XaW50ZXIsIHRoZSBUZXJyYS9MVU5B4oCTRlRYIHNlcXVlbmNlIG9mIDIwMjIsIGFuZCBhIHRoaXJkIGVwaXNvZGUgaW4gbGF0ZSAyMDI1Lg0KDQozLiAqKkZpbmFuY2lhbCBGcmFnaWxpdHkgaW5kZXguKiogRm9sbG93aW5nIHRoZSBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgSHlwb3RoZXNpcywgd2UgY29uc3RydWN0IGFuIGluZGV4IG9mIHVwc2lkZSBhbXBsaWZpY2F0aW9uIGFzIGFuIGluZGljYXRvciBvZiBzcGVjdWxhdGl2ZSBidWlsZC11cC4gRmluYW5jaWFsIEZyYWdpbGl0eSBwZWFrcyBkdXJpbmcgdGhlIDIwMjEgYnVsbCBtYXJrZXQsIGNvbnNpc3RlbnQgd2l0aCBNaW5za3kgKDE5NzcsIDE5OTIpLg0KDQpUaGUgcmVzdCBvZiB0aGUgYXJ0aWNsZSBpcyBvcmdhbml6ZWQgYXMgZm9sbG93cy4gU2VjdGlvbiAyIHByZXNlbnRzIHRoZSBkYXRhIGFuZCBtZXRob2RvbG9neS4gU2VjdGlvbiAzIHByb3ZpZGVzIG91ciByZXN1bHRzLiBTZWN0aW9uIDQgcmVwb3J0cyBmdXJ0aGVyIGFuYWx5c2VzLiBTZWN0aW9uIDUgcHJlc2VudHMgcm9idXN0bmVzcyBjaGVja3MuIFNlY3Rpb24gNiBjb25jbHVkZXMuDQoNCi0tLQ0KDQojIE1ldGhvZG9sb2d5IGFuZCBEYXRhIHsjbWV0aG9kb2xvZ3l9DQoNCiMjIERhdGEgeyNkYXRhfQ0KDQpXZSBjb2xsZWN0IHRoZSBsaXN0IG9mIHRoZSA0MCBtb3N0IGNhcGl0YWxpemVkIGNyeXB0by1hc3NldHMgb24gdGhlIGZpcnN0IHdlZWsgb2YgZWFjaCB5ZWFyIGZyb20gMjAxNyB0byAyMDI1IGZyb20gQ29pbk1hcmtldENhcCBhbmQgcmVtb3ZlIHN0YWJsZWNvaW5zIGZyb20gdGhlIHNhbXBsZSwgbGVhZGluZyB0byBhIGZpbmFsIHNhbXBsZSBvZiAqKjEzNyBjcnlwdG8tYXNzZXRzKiouIFN0YWJsZWNvaW5zIGFyZSBpZGVudGlmaWVkIHVzaW5nIENvaW5HZWNrbyBhbmQgZXhjbHVkZWQgdW5kZXIgY2F0ZWdvcmllcyAiU3RhYmxlY29pbnMsIiAiRmlhdC1iYWNrZWQgU3RhYmxlY29pbnMsIiAiVVNEIFN0YWJsZWNvaW5zLCIgYW5kICJDcnlwdG8tYmFja2VkIFN0YWJsZWNvaW5zLiINCg0KV2UgZXh0cmFjdCBkYWlseSBwcmljZSBkYXRhIGZyb20gKipKYW51YXJ5IDEsIDIwMTggdG8gRmVicnVhcnkgMSwgMjAyNioqIGZyb20gQ3J5cHRvQ29tcGFyZS4gUmV0dXJucyBhcmUgbWVhc3VyZWQgYXMgbG9nLXByaWNlIGRpZmZlcmVuY2VzLiBUbyBlbnN1cmUgbGlxdWlkaXR5LCB3ZSByZW1vdmUgb2JzZXJ2YXRpb25zIHdoZW4gdGhlIHZvbHVtZSBpcyBiZWxvdyAxMCB0b2tlbnMuXltUaGlzIGZpbHRlciByZW1vdmVzIGV4dHJlbWUgb2JzZXJ2YXRpb25zIGxpa2VseSBjYXVzZWQgYnkgdGhpbiB0cmFkaW5nIG9yIGRhdGEgZXJyb3JzLCBhZmZlY3RpbmcgbGVzcyB0aGFuIDAuNSUgb2YgdGhlIGZpbmFsIHNhbXBsZS5dDQoNCmBgYHtyIGxvYWQtZGF0YX0NCiMg4pSA4pSAIExvYWQgdGhlIGZpbmFsIGNyeXB0byBwYW5lbCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIANCiMgZGF0YV9jcnlwdG8ucGFycXVldCBjb250YWlucyBsb2cgcmV0dXJucywgbWFya2V0IGNhcHMsIGFuZCDigJQgY3J1Y2lhbGx5IOKAlA0KIyByZXNpZF9nYXJjaF9zdGQ6IHRoZSBHQVJDSC1zdGFuZGFyZGlzZWQgc3lzdGVtYXRpYyBzaG9jayB6X3QgPSDOtV90L8+DX3QuDQpkYXRhX2NyeXB0byA8LSBhcnJvdzo6cmVhZF9wYXJxdWV0KHBhdGhzJGRhdGEkZmluYWwkZGF0YV9jcnlwdG8pICU+JQ0KICBtdXRhdGUoZGF0ZSA9IGFzLkRhdGUoZGF0ZSkpICU+JQ0KICBzZWxlY3QoZGF0ZSwgdmFyaWFibGUsIHJldHVybiwgcmVzaWRfZ2FyY2hfc3RkKQ0KDQpjYXQoIlBhbmVsOiIsIG5yb3coZGF0YV9jcnlwdG8pLCAib2JzIOKAlCIsDQogICAgbGVuZ3RoKHVuaXF1ZShkYXRhX2NyeXB0byR2YXJpYWJsZSkpLCAidG9rZW5zIOKAlCIsDQogICAgZm9ybWF0KG1pbihkYXRhX2NyeXB0byRkYXRlKSksICJ0byIsIGZvcm1hdChtYXgoZGF0YV9jcnlwdG8kZGF0ZSkpLCAiXG4iKQ0KYGBgDQoNCmBgYHtyIHN1bW1hcnktc3RhdHMtdGFibGV9DQojIOKUgOKUgCBTdW1tYXJ5IHN0YXRpc3RpY3Mg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQptYWtlX3N0YXRzX3JvdyA8LSBmdW5jdGlvbih4LCBsYWJlbCwgbl9hc3NldHMgPSBOQV9jaGFyYWN0ZXJfKSB7DQogIGRhdGEuZnJhbWUoDQogICAgU2VyaWVzICAgICAgID0gbGFiZWwsDQogICAgTWVhbiAgICAgICAgID0gcm91bmQobWVhbih4LCBuYS5ybT1UUlVFKSwgMyksDQogICAgYFN0ZC4gRGV2LmAgID0gcm91bmQoc2QoeCwgbmEucm09VFJVRSksIDMpLA0KICAgIE1lZGlhbiAgICAgICA9IHJvdW5kKG1lZGlhbih4LCBuYS5ybT1UUlVFKSwgMyksDQogICAgTWluaW11bSAgICAgID0gcm91bmQobWluKHgsIG5hLnJtPVRSVUUpLCAzKSwNCiAgICBNYXhpbXVtICAgICAgPSByb3VuZChtYXgoeCwgbmEucm09VFJVRSksIDMpLA0KICAgIE9ic2VydmF0aW9ucyA9IGZvcm1hdEMoc3VtKCFpcy5uYSh4KSksIGZvcm1hdD0iZCIsIGJpZy5tYXJrPSIsIiksDQogICAgQXNzZXRzICAgICAgID0gbl9hc3NldHMsDQogICAgY2hlY2submFtZXMgID0gRkFMU0UNCiAgKQ0KfQ0KDQpyZXRfdmVjICAgPC0gZGF0YV9jcnlwdG8kcmV0dXJuWyFpcy5uYShkYXRhX2NyeXB0byRyZXR1cm4pXQ0Kc2hvY2tfdmVjIDwtIGRhdGFfY3J5cHRvICU+JQ0KICBmaWx0ZXIoIWlzLm5hKHJlc2lkX2dhcmNoX3N0ZCkpICU+JQ0KICBkaXN0aW5jdChkYXRlLCByZXNpZF9nYXJjaF9zdGQpICU+JQ0KICBwdWxsKHJlc2lkX2dhcmNoX3N0ZCkNCg0KYmluZF9yb3dzKA0KICBtYWtlX3N0YXRzX3JvdyhyZXRfdmVjLCAgICJMb2cgcmV0dXJucyIsICAgICAgbl9hc3NldHMgPSBhcy5jaGFyYWN0ZXIobl9kaXN0aW5jdChkYXRhX2NyeXB0byR2YXJpYWJsZSkpKSwNCiAgbWFrZV9zdGF0c19yb3coc2hvY2tfdmVjLCAiU3lzdGVtYXRpYyBzaG9jayIsICBuX2Fzc2V0cyA9ICLigJQiKQ0KKSAlPiUNCiAga2FibGUoY2FwdGlvbiA9ICIqKlRhYmxlIDEg4oCUIFN1bW1hcnkgU3RhdGlzdGljcyoqIiwNCiAgICAgICAgYWxpZ24gPSBjKCJsIiwiciIsInIiLCJyIiwiciIsInIiLCJyIiwiciIpKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJob3ZlciIsImNvbmRlbnNlZCIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwgZm9udF9zaXplID0gMTMpICU+JQ0KICBmb290bm90ZSgNCiAgICBnZW5lcmFsID0gIkxvZyByZXR1cm5zIGFyZSBkYWlseSBsb2cgcHJpY2UgY2hhbmdlcyBmb3IgMTM3IGNyeXB0by1hc3NldHMgb3ZlciBKYW51YXJ5IDIwMTggdG8gRmVicnVhcnkgMjAyNi4gVGhlIHN5c3RlbWF0aWMgc2hvY2sgaXMgdGhlIHN0YW5kYXJkaXNlZCByZXNpZHVhbCB6X3QgPSDOtV90L8+DX3Qgb2YgYW4gZUdBUkNIKDEsMSkgbW9kZWwgYXBwbGllZCB0byB0aGUgZmlyc3QtZGlmZmVyZW5jZWQgQ3J5cHRvLUZhY3Rvci4iLA0KICAgIGdlbmVyYWxfdGl0bGUgPSAiTm90ZTogIg0KICApDQpgYGANCg0KIyMgU3lzdGVtYXRpYyBTaG9ja3MgeyNzaG9ja3N9DQoNClRvIGVzdGltYXRlIHN5c3RlbWF0aWMgc2hvY2tzIGluIGNyeXB0by1tYXJrZXRzLCB3ZSBzcGVjaWZ5IGEgRHluYW1pYyBGYWN0b3IgTW9kZWwgKERGTSkgZm9yIGEgcGFuZWwgb2YgY3J5cHRvLWFzc2V0IHByaWNlcy4gQXMgUmV5ICYgTWlyYW5kYS1BZ3JpcHBpbm8gKDIwMjEpIGFyZ3VlLCB0aGUgc2luZ2xlIGZhY3RvciBvZiBlcXVpdHkgcHJpY2VzIGNvbWJpbmVzIG1hcmtldCByaXNrIGFuZCBhZ2dyZWdhdGUgcmlzay1hdmVyc2lvbi4gV2UgbWFpbnRhaW4gdGhpcyBpbnRlcnByZXRhdGlvbiBmb3IgY3J5cHRvIG1hcmtldHMuDQoNCkxldCAkcF90JCBkZW5vdGUgYW4gJG4kLWRpbWVuc2lvbmFsIHZlY3RvciBvZiBkYWlseSBwcmljZXMgJHBfe2ksdH0kIHRoYXQgYXJlIGEgbGluZWFyIGNvbWJpbmF0aW9uIG9mIGEgY29tbW9uIGZhY3RvciAkZl90JCBmb2xsb3dpbmcgYW4gJEFSKHApJCBwcm9jZXNzIGFuZCBhbiBpZGlvc3luY3JhdGljIGVycm9yIHRlcm0gJFx2YXJlcHNpbG9uX3tpLHR9JDoNCg0KJCRwX3tpLHR9ID0gXGxhbWJkYV9pKEwpXCwgZl90ICsgXHZhcmVwc2lsb25fe2ksdH0kJA0KDQokJGZfdCA9IEFfMSBmX3t0LTF9ICsgXGNkb3RzICsgQV9xIGZfe3QtcX0gKyBcZXRhX3QkJA0KDQp3aGVyZSAkXGV0YV90IFxzaW0gXG1hdGhjYWx7Tn0oMCwgXFNpZ21hKSQgYW5kICRcbGFtYmRhX2kkIGlzIGEgdmVjdG9yIG9mIGZhY3RvciBsb2FkaW5ncyBmb3IgYXNzZXQgJGkkLiBGb2xsb3dpbmcgQ2hlIGV0IGFsLiAoMjAyMyksIHdlIGVzdGltYXRlIHRoZSBzaW5nbGUgZmFjdG9yIG9uIHRoZSAqKjcgYmlnZ2VzdCBjcnlwdG8tYXNzZXRzKiogYnkgbWFya2V0IGNhcGl0YWxpemF0aW9uIChCaXRjb2luLCBFdGhlcmV1bSwgUmlwcGxlLCBCaW5hbmNlIENvaW4sIENhcmRhbm8sIFRST04gYW5kIERPR0UpLCByZXByZXNlbnRpbmcgYXJvdW5kIDcwJSBvZiB0aGUgY3J5cHRvLW1hcmtldCBjYXBpdGFsaXphdGlvbiBhdCB0aGUgZW5kIG9mIG91ciBzYW1wbGUuDQoNCmBgYHtyIGVzdGltYXRlLWRmbSwgZXZhbD1GQUxTRX0NCiMg4pSA4pSAIERGTSBlc3RpbWF0aW9uIChldmFsPUZBTFNFIOKAlCBydW4gb25jZSB2aWEgc3JjLzAyX2ZhY3Rvcl9hbmRfc2hvY2tzLlIpIOKUgOKUgOKUgOKUgOKUgA0KIyBJbnB1dHM6ICBkYXRhL3Jhdy8qIHByaWNlIGRhdGEgZnJvbSBDcnlwdG9Db21wYXJlDQojIE91dHB1dHM6IGRhdGEvaW50ZXJtZWRpYXRlL21hcmtldF9zaG9ja3MucGFycXVldCAgKGNvbnRhaW5zIHRoZSBERk0gZmFjdG9yDQojICAgICAgICAgIHNlcmllcywgcmF3IEdBUkNIIHJlc2lkdWFscywgYW5kIHJlc2lkX2dhcmNoX3N0ZF9jcnlwdG8gPSB6X3QpDQojDQojIFRoZSBlR0FSQ0goMSwxKSB3aXRoIFN0dWRlbnQgZGlzdHJpYnV0aW9uIGlzIHRoZW4gYXBwbGllZCBpbg0KIyBzcmMvMDJjX2dhcmNoX3N0ZF9zaG9jay5SLCB3aGljaCBwYXRjaGVzIGRhdGFfY3J5cHRvLnBhcnF1ZXQgdG8gYWRkDQojIHJlc2lkX2dhcmNoX3N0ZCA9IHpfdCA9IM61X3QgLyDPg190Lg0Kc291cmNlKCJzcmMvMDJfZmFjdG9yX2FuZF9zaG9ja3MuUiIpDQpzb3VyY2UoInNyYy8wMmNfZ2FyY2hfc3RkX3Nob2NrLlIiKQ0KYGBgDQoNCldlIGNvbnN0cnVjdCB0aGUgc3lzdGVtYXRpYyBzaG9jayAkZl4qX3QkIGFzIHRoZSAqKnN0YW5kYXJkaXNlZCByZXNpZHVhbHMqKiBvZiBhbiAqKmVHQVJDSCgxLDEpIG1vZGVsKipeW1dlIGFwcGx5IGFuIGVHQVJDSCgxLDEpIG1vZGVsIHdpdGggU3R1ZGVudCBkaXN0cmlidXRpb24sIHNlbGVjdGVkIGFzIHRoZSBvcHRpbWFsIGZpdCBieSBBSUMgYW5kIEJJQy4gV2UgdXNlIEdBUkNIIHJhdGhlciB0aGFuIEFSTUEgYmVjYXVzZSByZXNpZHVhbHMgZnJvbSBhbiBBUiBmaXQgZXhoaWJpdCBzaWduaWZpY2FudCBBUkNIIGVmZmVjdHMuXSBhcHBsaWVkIHRvIHRoZSBDcnlwdG8tRmFjdG9yIGluIGZpcnN0IGRpZmZlcmVuY2UgZm9yIHN0YXRpb25hcml0eToNCg0KJCRmXipfdCA9IHpfdCA9IFxmcmFje1x2YXJlcHNpbG9uX3R9e1xzaWdtYV90fSQkDQoNCndoZXJlICRcdmFyZXBzaWxvbl90JCBpcyB0aGUgR0FSQ0ggcmVzaWR1YWwgYW5kICRcc2lnbWFfdCQgaXMgdGhlIGVzdGltYXRlZCBjb25kaXRpb25hbCBzdGFuZGFyZCBkZXZpYXRpb24uIEJ5IGNvbnN0cnVjdGlvbiwgJHpfdCQgaGFzIHVuaXQgc2NhbGUgYXQgZXZlcnkgZGF0ZSwgbWFraW5nIGNyb3NzLXdpbmRvdyBzaG9jayBkaXN0cmlidXRpb25zIGNvbXBhcmFibGUuIFRoaXMgbWF0dGVycyBiZWNhdXNlIHRoZSBHQVJDSCByZXNpZHVhbHMgZXhoaWJpdCBzdWJzdGFudGlhbCB2YXJpYXRpb24gaW4gY29uZGl0aW9uYWwgdmFyaWFuY2UgYWNyb3NzIHN1YnNhbXBsZXM6IGEgdW5pdCBzaG9jayBpbiBhIGNhbG0gd2luZG93IGlzIG5vdCBjb21wYXJhYmxlIHRvIGEgdW5pdCBzaG9jayBpbiBhIHR1cmJ1bGVudCB3aW5kb3cuIFN0YW5kYXJkaXNpbmcgYnkgJFxzaWdtYV90JCByZW1vdmVzIHRoaXMgc2NhbGUgaGV0ZXJvZ2VuZWl0eSB3aGlsZSBwcmVzZXJ2aW5nIHRoZSB2YXJpYW5jZS10cmFuc21pc3Npb24gY2hhbm5lbCBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIOKAlCBhIGtleSBkaXN0aW5jdGlvbiBmcm9tIGFsdGVybmF0aXZlIHNjYWxpbmdzIHRoYXQgZmlsdGVyIHRoZSByZXR1cm5zIHRoZW1zZWx2ZXMuXltBbHRlcm5hdGl2ZSBzY2FsaW5ncyB3ZSB0ZXN0ZWQ6IChpKSB1c2luZyByYXcgR0FSQ0ggcmVzaWR1YWxzICRcdmFyZXBzaWxvbl90JCBhcyByZWdyZXNzb3IgKGJldHdlZW4td2luZG93IGRpc3RyaWJ1dGlvbmFsIGluZXF1YWxpdHkpOyAoaWkpIHJvbGxpbmctd2luZG93IHZhcmlhbmNlIHNjYWxpbmcgb2YgYm90aCB0aGUgc2hvY2sgYW5kIHJldHVybnMgKHN0aWxsIGNvbnRhbWluYXRlZCBieSBzbG93IHZvbGF0aWxpdHkgY3ljbGVzKTsgKGlpaSkgZmlsdGVyaW5nIGJvdGggcmV0dXJucyBhbmQgc2hvY2sgYnkgR0FSQ0ggKHJlbW92ZXMgdGhlIHZhcmlhbmNlIGNoYW5uZWwgZnJvbSB0aGUgZGVwZW5kZW50IHZhcmlhYmxlKS4gVGhlIEdBUkNILXN0YW5kYXJkaXplZCBzaG9jayAkel90ID0gXHZhcmVwc2lsb25fdC9cc2lnbWFfdCQgaXMgdGhlIHByZWZlcnJlZCBzcGVjaWZpY2F0aW9uLl0NCg0KYGBge3IgbG9hZC1hbmQtcGxvdC1zaG9ja3MsIGZpZy5jYXA9IioqRmlndXJlIEExIChBcHBlbmRpeCkg4oCUIFN5c3RlbWF0aWMgc2hvY2tzIGluIGNyeXB0by1tYXJrZXRzLioqIERhaWx5IGlubm92YXRpb25zIHRvIHRoZSBjcnlwdG8gbWFya2V0IGZhY3Rvcjogc3RhbmRhcmRpc2VkIHJlc2lkdWFscyAkel90ID0gXFx2YXJlcHNpbG9uX3QvXFxzaWdtYV90JCBvZiBhbiBlR0FSQ0goMSwxKSBtb2RlbCBmaXR0ZWQgdG8gdGhlIENyeXB0by1GYWN0b3Igc2VyaWVzIGluIGZpcnN0LWRpZmZlcmVuY2UuIFRoZXNlIHNob2NrcyBjb25zdGl0dXRlIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZSBpbiBhbGwgcXVhbnRpbGUgcmVncmVzc2lvbnMuIiwgZmlnLmhlaWdodD00fQ0KIyB6X3QgaXMgc3RvcmVkIGRpcmVjdGx5IGluIGRhdGFfY3J5cHRvLnBhcnF1ZXQgKGNvbHVtbiByZXNpZF9nYXJjaF9zdGQpDQojIEl0IGlzIGFsc28gaW4gZGF0YS9pbnRlcm1lZGlhdGUvbWFya2V0X3Nob2Nrcy5wYXJxdWV0IGFzIHJlc2lkX2dhcmNoX3N0ZF9jcnlwdG8NCg0Kc2hvY2tfc2VyaWVzIDwtIGRhdGFfY3J5cHRvICU+JQ0KICBkaXN0aW5jdChkYXRlLCB6X3QgPSByZXNpZF9nYXJjaF9zdGQpICU+JQ0KICBmaWx0ZXIoIWlzLm5hKHpfdCkpICU+JQ0KICBhcnJhbmdlKGRhdGUpDQoNCmdncGxvdChzaG9ja19zZXJpZXMsIGFlcyh4ID0gZGF0ZSwgeSA9IHpfdCkpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC40LCBhbHBoYSA9IDAuODUpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JleTUwIikgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiLA0KICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSAwLjAxKSkgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gZXhwcmVzc2lvbih6W3RdID09IGVwc2lsb25bdF0gLyBzaWdtYVt0XSkpICsNCiAgdGhlbWVfY3J5cHRvKCkNCmBgYA0KDQpgYGB7ciBwbG90LWZhY3RvciwgZmlnLmNhcD0iKipGaWd1cmUgQTIgKEFwcGVuZGl4KSDigJQgQ3J5cHRvLUZhY3RvciAoMjAxOOKAkzIwMjYpLioqIEVzdGltYXRlZCBhcyB0aGUgZmlyc3QgcHJpbmNpcGFsIGNvbXBvbmVudCBvZiA3IGNyeXB0by1hc3NldCBwcmljZXMgKEJUQywgRVRILCBYUlAsIEJOQiwgQURBLCBUUlgsIERPR0UpIHdpdGggYSBEeW5hbWljIEZhY3RvciBNb2RlbC4iLCBmaWcuaGVpZ2h0PTR9DQojIFRoZSBmYWN0b3Igc2VyaWVzIGlzIHNhdmVkIGluIG1hcmtldF9zaG9ja3MucGFycXVldA0KbWFya2V0X3Nob2NrcyA8LSBhcnJvdzo6cmVhZF9wYXJxdWV0KHBhdGhzJGRhdGEkaW50ZXJtZWRpYXRlJG1hcmtldF9zaG9ja3MpICU+JQ0KICBtdXRhdGUoZGF0ZSA9IGFzLkRhdGUoZGF0ZSkpDQoNCmdncGxvdChtYXJrZXRfc2hvY2tzLCBhZXMoeCA9IGRhdGUsIHkgPSBzZXJpZSkpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC42KSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsDQogICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IDAuMDEpKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiRmFjdG9yIGxldmVsIikgKw0KICB0aGVtZV9jcnlwdG8oKQ0KYGBgDQoNCiMjIFF1YW50aWxlIFJlZ3Jlc3Npb24gRnJhbWV3b3JrIHsjcXVhbnRpbGVyZWd9DQoNCk91ciBlbXBpcmljYWwgc3RyYXRlZ3kgYnVpbGRzIG9uIEJhdXIgJiBTY2h1bHplICgyMDA5KSwgd2hvIGRlZmluZSBmaW5hbmNpYWwgYXNzZXQgc3RhYmlsaXR5IGFzIHRoZSBhYnNlbmNlIG9mIGluY3JlYXNpbmcgc2hvY2sgc2Vuc2l0aXZpdHkgaW4gdGhlIHRhaWxzIG9mIHRoZSByZXR1cm4gZGlzdHJpYnV0aW9uIHJlbGF0aXZlIHRvIG5vcm1hbCBjb25kaXRpb25zLiBGb3IgZWFjaCBhc3NldCAkaSQsIHdlIGVzdGltYXRlIHRoZSBmb2xsb3dpbmcgcXVhbnRpbGUgcmVncmVzc2lvbiBhdCB0aHJlZSBxdWFudGlsZXMgJFx0YXUkIOKAlCB0aGUgbG93ZXIgdGFpbCAoJFx0YXUgPSAwLjA1JCksIHRoZSBtZWRpYW4gKCRcdGF1ID0gMC41MCQpLCBhbmQgdGhlIHVwcGVyIHRhaWwgKCRcdGF1ID0gMC45NSQpOg0KDQokJFFfXHRhdShyX3tpdH0gXG1pZCBmXipfdCkgPSBcYWxwaGFfaShcdGF1KSArIFxiZXRhX2koXHRhdSlcLCBmXipfdCArIFxnYW1tYV9pKFx0YXUpXCwgZl4qX3QgXGNkb3QgRF90XntcdGV4dHtsb3dlcn19ICsgXHBoaV9pKFx0YXUpXCwgZl4qX3QgXGNkb3QgRF90XntcdGV4dHt1cHBlcn19ICsgXHZhcmVwc2lsb25faShcdGF1KSQkDQoNCndoZXJlICRyX3tpdH0kIGlzIHRoZSByZXR1cm4gb2YgYXNzZXQgJGkkLCAkZl4qX3QgPSB6X3QkIGlzIHRoZSBzdGFuZGFyZGlzZWQgc3lzdGVtYXRpYyBzaG9jaywgYW5kICREX3Ree1x0ZXh0e2xvd2VyfX0kICgkRF90XntcdGV4dHt1cHBlcn19JCkgaXMgYSBkdW1teSBlcXVhbCB0byBvbmUgd2hlbiAkZl4qX3QkIGZhbGxzIGluIHRoZSBib3R0b20gKHRvcCkgNSUgb2YgaXRzIGluLXdpbmRvdyBkaXN0cmlidXRpb24uDQoNClRoZSBiaWxhdGVyYWwgc2hvY2sgZHVtbWllcyBpc29sYXRlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAqKmFzc2V0IHJldHVybiByZWdpbWVzKiogYW5kIHN5c3RlbWF0aWMgc2hvY2tzIG9mIG9yZGluYXJ5IG1hZ25pdHVkZS4gV2l0aG91dCB0aGVtLCAkXGJldGFfaShcdGF1KSQgd291bGQgY29uZmxhdGUgdGhlIGFzc2V0J3MgaW50cmluc2ljIHJlZ2ltZS1kZXBlbmRlbnQgc2Vuc2l0aXZpdHkgd2l0aCB0aGUgZ2VuZXJhbCBjby1tb3ZlbWVudCBpbmR1Y2VkIGJ5IHRhaWwgbWFya2V0IGV2ZW50cyDigJQgY29uZm91bmRpbmcgdGFpbC1kZXBlbmRlbmNlIHdpdGggY28tZXhjZWVkYW5jZXMuIFVuZGVyIHRoaXMgc2V0dXAsICRcYmV0YV9pKFx0YXUpJCBpZGVudGlmaWVzIGhvdyBhc3NldCByZXR1cm4gcmVnaW1lcyByZWxhdGUgdG8gdGhlIHN5c3RlbWF0aWMgZmFjdG9yIHVuZGVyICoqbm9ybWFsIG1hcmtldCBjb25kaXRpb25zKiosIHdoaWxlICRcZ2FtbWFfaSQgYW5kICRccGhpX2kkIGNhcHR1cmUgYWRkaXRpb25hbCBzZW5zaXRpdml0eSB1bmRlciBleHRyZW1lIHNob2Nrcy4NCg0KVGhlIGVxdWF0aW9uIGRlbGl2ZXJzIHRocmVlIHF1YW50aWxlLXNwZWNpZmljIGVzdGltYXRlczogJFxoYXR7XGJldGF9XntcdGV4dHtsb3dlcn19IFxlcXVpdiBcaGF0e1xiZXRhfV9pKDAuMDUpJCwgJFxoYXR7XGJldGF9XntcdGV4dHttZWR9fSBcZXF1aXYgXGhhdHtcYmV0YX1faSgwLjUwKSQsIGFuZCAkXGhhdHtcYmV0YX1ee1x0ZXh0e3VwcGVyfX0gXGVxdWl2IFxoYXR7XGJldGF9X2koMC45NSkkLiBFYWNoIHRhaWwgaXMgdGVzdGVkIGFnYWluc3QgdGhlIG1lZGlhbiB2aWEgYSAqKnBhaXJ3aXNlIFdhbGQgdGVzdCoqIChLb2Vua2VyICYgTWFjaGFkbywgMTk5OSkgYXQgdGhlICoqMTAlIHNpZ25pZmljYW5jZSBsZXZlbCoqLg0KDQoqKkNsYXNzaWZpY2F0aW9uIHJ1bGVzOioqDQoNCi0gKipGaW5hbmNpYWwgSW5zdGFiaWxpdHkqKiAobGVmdC10YWlsIGFtcGxpZmljYXRpb24pOiAkXGhhdHtcYmV0YX1ee1x0ZXh0e2xvd2VyfX0gPiBcaGF0e1xiZXRhfV57XHRleHR7bWVkfX0kIGFuZCBXYWxkIHRlc3QgcmVqZWN0cyBhdCAxMCUuIFNob2NrIHRyYW5zbWlzc2lvbiBpbnRlbnNpZmllcyB3aGVuIGFzc2V0cyBhcmUgaW4gZGlzdHJlc3MsIGFtcGxpZnlpbmcgYWdncmVnYXRlIGRvd25zaWRlIHJpc2sgKEZvcmJlcyAmIFJpZ29ib24sIDIwMDE7IExvbmdpbiAmIFNvbG5paywgMjAwMSkuDQoNCi0gKipGaW5hbmNpYWwgRnJhZ2lsaXR5KiogKHJpZ2h0LXRhaWwgYW1wbGlmaWNhdGlvbik6ICRcaGF0e1xiZXRhfV57XHRleHR7dXBwZXJ9fSA+IFxoYXR7XGJldGF9XntcdGV4dHttZWR9fSQgYW5kIFdhbGQgdGVzdCByZWplY3RzIGF0IDEwJS4gQXNzZXRzIGFtcGxpZnlpbmcgcG9zaXRpdmUgbWFya2V0IHNob2NrcyBkdXJpbmcgZXhwYW5zaW9uYXJ5IHBoYXNlcyBmdWVsIHByaWNlIGJ1YmJsZXMgYW5kIGNyZWF0ZSBjb3JyZWxhdGVkIGV4cG9zdXJlcyB0aGF0IHN1YnNlcXVlbnRseSB1bndpbmQgKEJydW5uZXJtZWllciBldCBhbC4sIDIwMTMpLCBjb25zaXN0ZW50IHdpdGggdGhlIE1pbnNreSBoeXBvdGhlc2lzLg0KDQpUbyBjYXB0dXJlIHRpbWUgdmFyaWF0aW9uLCB3ZSBlc3RpbWF0ZSB0aGUgZXF1YXRpb24gd2l0aGluICoqMTgtbW9udGggcm9sbGluZyB3aW5kb3dzKiosIHN0ZXBwaW5nIG1vbnRobHkuIEFzc2V0cyBhcmUgaW5jbHVkZWQgb25seSBpZiB0aGVpciByZXR1cm4gY292ZXJhZ2UgZXhjZWVkcyA5MCUgb2YgdGhlIGF2YWlsYWJsZSB0cmFkaW5nIGRheXMgaW4gYSBnaXZlbiB3aW5kb3cuXltBIHR5cGljYWwgMTgtbW9udGggd2luZG93IGNvbnRhaW5zIGFwcHJveGltYXRlbHkgNTQ3IHRyYWRpbmcgZGF5cywgb2Ygd2hpY2ggYXJvdW5kIDI3IGFyZSBleHRyZW1lIG5lZ2F0aXZlIGFuZCAyNyBhcmUgZXh0cmVtZSBwb3NpdGl2ZSBzaG9jayBkYXlzLl0gRWFjaCB3aW5kb3cgaXMgc2VsZi1jb250YWluZWQ6IGFsbCBlc3RpbWF0ZXMgYW5kIHNob2NrIHF1YW50aWxlIHRocmVzaG9sZHMgYXJlIGNvbXB1dGVkIHdpdGhpbiB0aGUgd2luZG93LCBwcmV2ZW50aW5nIGNvbnRhbWluYXRpb24gYnkgb3V0LW9mLXdpbmRvdyBpbmZvcm1hdGlvbi4NCg0KYGBge3Igcm9sbGluZy1xciwgZXZhbD1GQUxTRX0NCiMg4pSA4pSAIFJvbGxpbmcgUVIgZXN0aW1hdGlvbiAoZXZhbD1GQUxTRSDigJQgcnVuIG9uY2UgdmlhIHNyYy8yNV9nYXJjaF9zaG9ja19mdWxsLlIpDQojDQojIFRoZSBmdW5jdGlvbiBydW5fcm9sbGluZ19xcl9hbmFseXNpcygpIGluIGhlbHBlcnMuUiBwYXJhbGxlbGlzZXMgb3ZlciB3aW5kb3dzLg0KIyBJdCByZWFkcyBkYXRhX2NyeXB0by5wYXJxdWV0ICh3aGljaCBhbHJlYWR5IGNvbnRhaW5zIHJlc2lkX2dhcmNoX3N0ZCA9IHpfdCksDQojIGFuZCBhcHBsaWVzIHRoZSBmb3JtdWxhOg0KIyAgIHJldHVybiB+IHJlc2lkX2dhcmNoX3N0ZCArIHJlc2lkX2dhcmNoX3N0ZDpkX2xvdyArIHJlc2lkX2dhcmNoX3N0ZDpkX2hpZ2gNCiMgd2l0aCBiaWxhdGVyYWwgZHVtbWllcyAoYWRkX2R1bW1pZXMgPSAiYmlsYXRlcmFsIiwgc2hvY2tfcSA9IDAuMDUpLg0KIw0KIyBPdXRwdXQ6IG91dHB1dC9tb2RlbHMvcm9sbF8xOF9nYXJjaF9zaG9ja19leHQucGFycXVldA0KIyAgIENvbHVtbnM6IGVuZCwgdmFyaWFibGUsIGxlZnRfdGFpbCwgcmlnaHRfdGFpbCwNCiMgICAgICAgICAgICBiZXRhX2xvd2VyLCBiZXRhX21lZGlhbiwgYmV0YV91cHBlciwNCiMgICAgICAgICAgICBwX2xvd2VyLCBwX3VwcGVyLCBpbnN0YWJsZSwgY29udCwgc3BlYw0Kc291cmNlKCJzcmMvMjVfZ2FyY2hfc2hvY2tfZnVsbC5SIikNCmBgYA0KDQpgYGB7ciBsb2FkLXJvbGxpbmd9DQojIOKUgOKUgCBMb2FkIHByZS1jb21wdXRlZCByb2xsaW5nIFFSIHJlc3VsdHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQpyb2xsIDwtIGFycm93OjpyZWFkX3BhcnF1ZXQoc3AkbW9kZWxzJHJvbGxfMTgpICU+JQ0KICBtdXRhdGUoZW5kID0gYXMuRGF0ZShlbmQpKQ0KDQpjYXQoIlJvbGxpbmcgcmVzdWx0czoiLCBucm93KHJvbGwpLCAicm93cyDigJQiLA0KICAgIGxlbmd0aCh1bmlxdWUocm9sbCR2YXJpYWJsZSkpLCAidG9rZW5zIOKAlCIsDQogICAgbGVuZ3RoKHVuaXF1ZShyb2xsJGVuZCkpLCAid2luZG93c1xuIikNCmNhdCgiQ2xhc3NpZmljYXRpb24gY29sdW1uczogY29udCAoRkkpLCBzcGVjIChGRiksIGluc3RhYmxlXG4iKQ0KYGBgDQoNCmBgYHtyIG4tYXNzZXRzLXBsb3QsIGZpZy5jYXA9IioqRmlndXJlIEEzIChBcHBlbmRpeCkg4oCUIE51bWJlciBvZiBhc3NldHMgaW4gdGhlIHJvbGxpbmcgZXN0aW1hdGlvbiBzYW1wbGUuKiogQW4gYXNzZXQgaXMgaW5jbHVkZWQgaWYgaXRzIHJldHVybiBjb3ZlcmFnZSB3aXRoaW4gdGhlIHdpbmRvdyBpcyBhdCBsZWFzdCA5MCUuIFRoZSBmaWd1cmUgaWxsdXN0cmF0ZXMgdGhlIGV4cGFuc2lvbiBvZiB0aGUgY3J5cHRvIHVuaXZlcnNlIG92ZXIgdGhlIHNhbXBsZSBwZXJpb2QuIiwgZmlnLmhlaWdodD00fQ0Kcm9sbCAlPiUNCiAgZ3JvdXBfYnkoZW5kKSAlPiUNCiAgc3VtbWFyaXNlKG4gPSBuX2Rpc3RpbmN0KHZhcmlhYmxlKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lDQogIGdncGxvdChhZXMoeCA9IGVuZCwgeSA9IG4pKSArDQogIGdlb21fbGluZShjb2xvciA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuNykgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiLA0KICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSAwLjAxKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBOQSksIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwLjA1KSkpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9ICJOdW1iZXIgb2YgYXNzZXRzIikgKw0KICB0aGVtZV9jcnlwdG8oKQ0KYGBgDQoNCi0tLQ0KDQojIFJlc3VsdHMgeyNyZXN1bHRzfQ0KDQojIyBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgYW5kIEZpbmFuY2lhbCBGcmFnaWxpdHkgRHluYW1pY3MNCg0KRmlndXJlIDEgcmVwb3J0cyB0aGUgcmVzdWx0cyBvZiBvdXIgY2xhc3NpZmljYXRpb24gc3RyYXRlZ3kgaW4gcm9sbGluZyB3aW5kb3dzLCBhbG9uZ3NpZGUgY3J5cHRvIG1hcmtldCBjYXBpdGFsaXNhdGlvbi4gT24gYXZlcmFnZSwgYXBwcm94aW1hdGVseSAqKjEwJSBvZiBjcnlwdG8tYXNzZXRzKiogZXhoaWJpdCBsZWZ0LXRhaWwgYW1wbGlmaWNhdGlvbiBvZiBzeXN0ZW1hdGljIHNob2Nrcy4gVGhlIGZyYWN0aW9uIGV4aGliaXRpbmcgKipGaW5hbmNpYWwgRnJhZ2lsaXR5KiogaXMgaGlnaGVyLCBhdmVyYWdpbmcgMTUlLg0KDQpgYGB7ciBjb21wdXRlLXNoYXJlc30NCiMg4pSA4pSAIFJvbGxpbmcgc2hhcmVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgA0Kc2hhcmVzIDwtIHJvbGwgJT4lDQogIGdyb3VwX2J5KGVuZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBmaSAgID0gbWVhbihjb250LCBuYS5ybSA9IFRSVUUpICogMTAwLA0KICAgIGZmICAgPSBtZWFuKHNwZWMsIG5hLnJtID0gVFJVRSkgKiAxMDAsDQogICAgbiAgICA9IG5fZGlzdGluY3QodmFyaWFibGUpLA0KICAgIC5ncm91cHMgPSAiZHJvcCINCiAgKQ0KDQpzaGFyZXMgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBgRkkgbWVhbiAoJSlgICA9IHJvdW5kKG1lYW4oZmkpLCAxKSwNCiAgICBgRkkgbWF4ICglKWAgICA9IHJvdW5kKG1heChmaSksIDEpLA0KICAgIGBGRiBtZWFuICglKWAgID0gcm91bmQobWVhbihmZiksIDEpLA0KICAgIGBGRiBtYXggKCUpYCAgID0gcm91bmQobWF4KGZmKSwgMSksDQogICAgYEF2Zy4gTmAgICAgICAgPSByb3VuZChtZWFuKG4pKQ0KICApICU+JQ0KICBrYWJsZShjYXB0aW9uID0gIioqQXZlcmFnZSBGSS9GRiBzaGFyZXMgYWNyb3NzIDgwIHJvbGxpbmcgd2luZG93cyoqIikgJT4lDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQ0KYGBgDQoNCmBgYHtyIGZpZy1iYXNlbGluZSwgZmlnLmNhcD0iKipGaWd1cmUgMSDigJQgRmluYW5jaWFsIEluc3RhYmlsaXR5IGFuZCBGaW5hbmNpYWwgRnJhZ2lsaXR5IGR5bmFtaWNzLioqIEZyYWN0aW9uIG9mIGNyeXB0by1hc3NldHMgZXhoaWJpdGluZyBpbmNyZWFzaW5nIGxlZnQtdGFpbCBkZXBlbmRlbmNlIChGaW5hbmNpYWwgSW5zdGFiaWxpdHkpIGFuZCByaWdodC10YWlsIGRlcGVuZGVuY2UgKEZpbmFuY2lhbCBGcmFnaWxpdHkpIHRvIHRoZSBzeXN0ZW1hdGljIHNob2NrLiBSb2xsaW5nIDE4LW1vbnRoIHdpbmRvd3MsIG1vbnRobHkgc3RlcC4iLCBmaWcuaGVpZ2h0PTZ9DQpzaGFyZXMgJT4lDQogIHBpdm90X2xvbmdlcihjKGZpLCBmZiksIG5hbWVzX3RvID0gIm1ldHJpYyIsIHZhbHVlc190byA9ICJzaGFyZSIpICU+JQ0KICBtdXRhdGUobWV0cmljID0gZmFjdG9yKA0KICAgIHJlY29kZShtZXRyaWMsIGZpID0gIkZpbmFuY2lhbCBJbnN0YWJpbGl0eSIsIGZmID0gIkZpbmFuY2lhbCBGcmFnaWxpdHkiKSwNCiAgICBsZXZlbHMgPSBjKCJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiLCAiRmluYW5jaWFsIEZyYWdpbGl0eSIpDQogICkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBlbmQsIHkgPSBzaGFyZSAvIDEwMCwgY29sb3IgPSBtZXRyaWMsIGxpbmV0eXBlID0gbWV0cmljKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwoDQogICAgdmFsdWVzID0gYygiRmluYW5jaWFsIEluc3RhYmlsaXR5IiA9ICIjZDYyNzI4IiwNCiAgICAgICAgICAgICAgICJGaW5hbmNpYWwgRnJhZ2lsaXR5IiAgID0gIiMxZjc3YjQiKSwNCiAgICBuYW1lID0gTlVMTCkgKw0KICBzY2FsZV9saW5ldHlwZV9tYW51YWwoDQogICAgdmFsdWVzID0gYygiRmluYW5jaWFsIEluc3RhYmlsaXR5IiA9ICJzb2xpZCIsDQogICAgICAgICAgICAgICAiRmluYW5jaWFsIEZyYWdpbGl0eSIgICA9ICJzb2xpZCIpLA0KICAgIG5hbWUgPSBOVUxMKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsDQogICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IDAuMDIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksDQogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4wNSkpKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiU2hhcmUgb2YgYXNzZXRzICglKSIpICsNCiAgdGhlbWVfY3J5cHRvKCkNCmBgYA0KDQoqKlRoZSBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgc2hhcmUgaXMgZXBpc29kaWMgcmF0aGVyIHRoYW4gcGVyc2lzdGVudC4qKiBUaHJlZSBzdHJ1Y3R1cmFsbHkgZGlzdGluY3QgZXBpc29kZXMgZW1lcmdlOg0KDQoxLiAqKjIwMTkqKjogdGFpbCBvZiB0aGUgMjAxN+KAkzIwMTggQ3J5cHRvLVdpbnRlciwgZm9sbG93aW5nIEJpdGNvaW4ncyBwZWFrIG5lYXIgXCQyMCwwMDAgaW4gRGVjZW1iZXIgMjAxNyBhbmQgYSBzdWJzZXF1ZW50IGRlY2xpbmUgZXhjZWVkaW5nIDgwJS4NCg0KMi4gKipNaWQtMjAyMioqIChwZWFrOiBOb3ZlbWJlciAyMDIyKTogdGhlIFRlcnJhL0xVTkEgaW1wbG9zaW9uIGluIE1heSAyMDIyLCBmb2xsb3dlZCBieSB0aGUgZmFpbHVyZXMgb2YgVGhyZWUgQXJyb3dzIENhcGl0YWwgYW5kIENlbHNpdXMgTmV0d29yaywgYW5kIHRoZSBGVFggZXhjaGFuZ2UgY29sbGFwc2UgaW4gTm92ZW1iZXIgMjAyMi4gQSBzZWNvbmRhcnkgZWxldmF0aW9uIHBlcnNpc3RzIGludG8gZWFybHkgMjAyMywgY29pbmNpZGluZyB3aXRoIHRoZSBTaWxpY29uIFZhbGxleSBCYW5rIGZhaWx1cmUgYW5kIHRoZSBicmllZiBVU0RDIGRlcGVnLg0KDQozLiAqKkxhdGUgMjAyNSoqOiBhIHRoaXJkIGVwaXNvZGUgYXQgdGhlIGVuZCBvZiB0aGUgZXN0aW1hdGlvbiBzYW1wbGUuDQoNCioqVGhlIEZpbmFuY2lhbCBGcmFnaWxpdHkgc2hhcmUgZXhoaWJpdHMgYSBkaWZmZXJlbnQgZHluYW1pYyoqOiBlbGV2YXRlZCBhbmQgcmVsYXRpdmVseSBwZXJzaXN0ZW50IG92ZXIgMjAyMOKAkzIwMjQuIEl0IHBlYWtzIGFib3ZlIDMwJSBpbiBtaWQtMjAyMSBkdXJpbmcgdGhlIGJ1bGwgbWFya2V0IGZvbGxvd2luZyB0aGUgaW5pdGlhbCBDb3ZpZC0xOSByZWNvdmVyeSwgY29uc2lzdGVudCB3aXRoIExhaG1pcmkgJiBCZWtpcm9zICgyMDIwKSwgYW5kIHJlbWFpbnMgYWJvdmUgaXRzIHNhbXBsZSBtZWFuIHRocm91Z2ggMjAyNC4gVGhpcyBwYXR0ZXJuIGlzIGNvbnNpc3RlbnQgd2l0aCBNaW5za3kncyBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgSHlwb3RoZXNpcyAoMTk5Mik6IHNwZWN1bGF0aXZlIGZpbmFuY2luZyBhbmQgaGVyZGluZyBhY2N1bXVsYXRlIGR1cmluZyBzdXN0YWluZWQgcHJpY2UgYXBwcmVjaWF0aW9uLCBtYW5pZmVzdGluZyBhcyByaWdodC10YWlsIGFtcGxpZmljYXRpb24uIFRoZSBpbmNyZWFzZSBpbiBGaW5hbmNpYWwgRnJhZ2lsaXR5IHNsaWdodGx5IHByZWNlZGVzIHRoZSBtYXJrZXQgY2FwaXRhbGlzYXRpb24gcGVhaywgY29uc2lzdGVudCB3aXRoIGJlaGF2aW91cmFsIGFtcGxpZmljYXRpb24gcHJlY2VkaW5nIGFnZ3JlZ2F0ZSBvdmVydmFsdWF0aW9uIChCcnVubmVybWVpZXIgJiBOYWdlbCwgMjAwOTsgU3RvbGJvcmcgZXQgYWwuLCAyMDI1KS4NCg0KTmVpdGhlciBpbmRleCBjby1tb3ZlcyBzeXN0ZW1hdGljYWxseSB3aXRoIGFnZ3JlZ2F0ZSBtYXJrZXQgdm9sYXRpbGl0eSBvdmVyIHRoZSBmdWxsIHNhbXBsZS4gRm9yIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSwgdGhlIGFic2VuY2Ugb2YgYSBwb3NpdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIHZvbGF0aWxpdHkgaXMgY29uc2lzdGVudCB3aXRoIHN0dWRpZXMgYXJndWluZyB0aGF0IHZvbGF0aWxpdHkgaXMgbm90IGEgZ29vZCBwcmVkaWN0b3Igb2YgZmluYW5jaWFsIGNyaXNlcyAoRGFuaWVsc3NvbiBldCBhbC4sIDIwMTg7IFNvcm5ldHRlICYgQ2F1d2VscywgMjAxOCkgYW5kIGp1c3RpZmllcyBvdXIgYXBwcm9hY2guDQoNCioqRmluYW5jaWFsIEZyYWdpbGl0eSBleGNlZWRzIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSB0aHJvdWdob3V0IHRoZSBzYW1wbGUqKiwgcmVmbGVjdGluZyB0aGUgYXN5bW1ldHJpYyBzdHJ1Y3R1cmUgb2YgY3J5cHRvIG1hcmtldCBjeWNsZXMuIEJvb20gcGhhc2VzIGFyZSBwcm9sb25nZWQgYW5kIGJyb2FkLWJhc2VkIHJlbGF0aXZlIHRvIHNoYXJwIGJ1dCBicmllZiBjcmFzaCBlcGlzb2RlczogZHVyaW5nIGV4cGFuc2lvbmFyeSBwaGFzZXMsIHNwZWN1bGF0aXZlIGRlbWFuZCBhbmQgbW9tZW50dW0gdHJhZGluZyBjYXVzZSBhIGxhcmdlIGNyb3NzLXNlY3Rpb24gb2YgYXNzZXRzIHRvIGFtcGxpZnkgcG9zaXRpdmUgc3lzdGVtYXRpYyBzaG9ja3Mgc2ltdWx0YW5lb3VzbHkgKE1pbnNreSwgMTk3NzsgQm91cmkgZXQgYWwuLCAyMDE5KS4gQ3Jhc2ggZXBpc29kZXMsIGJ5IGNvbnRyYXN0LCBhcmUgY29uY2VudHJhdGVkIGluIHRpbWUgYW5kIHRoZSBhbXBsaWZpY2F0aW9uIG9mIG5lZ2F0aXZlIHNob2NrcyBpcyBtb3JlIHNlbGVjdGl2ZS4gVGhlIHJlc3VsdCBpcyBhIHBlcnNpc3RlbnRseSBoaWdoZXIgc2hhcmUgb2YgYXNzZXRzIGV4aGliaXRpbmcgcmlnaHQtdGFpbCBhbXBsaWZpY2F0aW9uIHRoYW4gbGVmdC10YWlsIGFtcGxpZmljYXRpb24uDQoNCi0tLQ0KDQojIEZ1cnRoZXIgQW5hbHlzaXMgeyNmdXJ0aGVyfQ0KDQojIyBQb3J0Zm9saW8gUGVyZm9ybWFuY2UgeyNwb3J0Zm9saW99DQoNCldlIGNvbnN0cnVjdCBmb3VyIGVxdWFsbHktd2VpZ2h0ZWQgcG9ydGZvbGlvcyBmb3JtZWQgb24gdGhlIHJvbGxpbmcgY2xhc3NpZmljYXRpb24sIHJlYmFsYW5jZWQgbW9udGhseSB3aXRoIGEgKipvbmUtbW9udGggZm9yd2FyZCBsYWcqKiB0byBlbnN1cmUgdGhlIGNsYXNzaWZpY2F0aW9uIGlzIGZ1bGx5IG91dC1vZi1zYW1wbGU6DQoNCi0gKipGaW5hbmNpYWwgSW5zdGFiaWxpdHkqKiBwb3J0Zm9saW86IGhvbGRzIGFzc2V0cyB3aXRoICRcaGF0e1xiZXRhfV9pKDAuMDUpID4gXGhhdHtcYmV0YX1faSgwLjUwKSQgZXhjbHVzaXZlbHkNCi0gKipGaW5hbmNpYWwgRnJhZ2lsaXR5KiogcG9ydGZvbGlvOiBob2xkcyBhc3NldHMgd2l0aCAkXGhhdHtcYmV0YX1faSgwLjk1KSA+IFxoYXR7XGJldGF9X2koMC41MCkkIGV4Y2x1c2l2ZWx5DQotICoqU3RhYmxlKiogcG9ydGZvbGlvOiBhbGwgcmVtYWluaW5nIGFzc2V0cyBzYXRpc2Z5aW5nIG5laXRoZXIgY3JpdGVyaW9uDQotICoqVG9wLTEwKiogYmVuY2htYXJrOiBlcXVhbGx5LXdlaWdodGVkIHBvcnRmb2xpbyBvZiB0aGUgdGVuIG1vc3QgcHJvbWluZW50IGNyeXB0by1hc3NldHMNCg0KYGBge3IgcG9ydGZvbGlvLWNvZGUsIGV2YWw9RkFMU0V9DQojIOKUgOKUgCBQb3J0Zm9saW8gY29uc3RydWN0aW9uIChldmFsPUZBTFNFIOKAlCBydW4gb25jZSB2aWEgc3JjLzEyX3BvcnRmb2xpb19wZXJmb3JtYW5jZS5SKQ0KIyBVc2VzIHJvbGxfMThfZ2FyY2hfc2hvY2tfZXh0LnBhcnF1ZXQgKyBkYWlseSByZXR1cm4gZGF0YSBmcm9tIGRhdGFfY3J5cHRvLnBhcnF1ZXQuDQojIENsYXNzaWZpY2F0aW9uIGF0IHdpbmRvdyBlbmQgdCDihpIgcG9ydGZvbGlvIGhlbGQgb3ZlciBtb250aCB0KzEuDQojIE91dHB1dDogb3V0cHV0L2ZpZ3VyZXMvZ2FyY2hfc2hvY2tfZXh0L3BhcGVyL3BvcnRmb2xpb19wcmVkaWN0aXZlLnBkZg0Kc291cmNlKCJzcmMvMTJfcG9ydGZvbGlvX3BlcmZvcm1hbmNlLlIiKQ0KYGBgDQoNCmBgYHtyIGZpZy1wb3J0Zm9saW8sIGZpZy5jYXA9IioqRmlndXJlIDIg4oCUIFBvcnRmb2xpbyBQZXJmb3JtYW5jZSBhY3Jvc3MgQ2F0ZWdvcmllcy4qKiBDdW11bGF0aXZlIHdlYWx0aCAoYmFzZSAxMDApIG9uIGEgbG9nYXJpdGhtaWMgc2NhbGUuIFRoZSAqRmluYW5jaWFsIEluc3RhYmlsaXR5KiBwb3J0Zm9saW8gaG9sZHMgcHVyZSBsZWZ0LXRhaWwgYW1wbGlmaWVyczsgdGhlICpGaW5hbmNpYWwgRnJhZ2lsaXR5KiBwb3J0Zm9saW8gaG9sZHMgcHVyZSByaWdodC10YWlsIGFtcGxpZmllcnM7IHRoZSAqU3RhYmxlKiBwb3J0Zm9saW8gaG9sZHMgYWxsIHJlbWFpbmluZyBhc3NldHMuIFRoZSAqVG9wLTEwKiBiZW5jaG1hcmsgaXMgYW4gZXF1YWxseS13ZWlnaHRlZCBiYXNrZXQgb2YgdGhlIHRlbiBtb3N0IHByb21pbmVudCBjcnlwdG8tYXNzZXRzLiBQb3J0Zm9saW9zIGFyZSByZWJhbGFuY2VkIG1vbnRobHkgd2l0aCBhIG9uZS1tb250aCBmb3J3YXJkIGxhZyAob3V0LW9mLXNhbXBsZSkuIiwgZmlnLmhlaWdodD02fQ0KDQojIOKUgOKUgCBIZWxwZXIgZnVuY3Rpb25zIChmcm9tIHNyYy8xMl9wb3J0Zm9saW9fcGVyZm9ybWFuY2UuUikg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQpidWlsZF9jb25zdGl0dWVudHMgPC0gZnVuY3Rpb24ocm9sbF9kZiwgcG9ydGZvbGlvX3R5cGUpIHsNCiAgaWYgKHBvcnRmb2xpb190eXBlID09ICJiZW5jaCIpIHsNCiAgICByZXR1cm4ocm9sbF9kZiAlPiUgZGlzdGluY3QoZW5kLCB2YXJpYWJsZSkgJT4lIG11dGF0ZShpbl9wb3J0Zm9saW8gPSBUUlVFKSkNCiAgfQ0KICByb2xsX2RmICU+JQ0KICAgIGRpc3RpbmN0KGVuZCwgdmFyaWFibGUsIGluc3RhYmxlLCBjb250LCBzcGVjKSAlPiUNCiAgICBtdXRhdGUoaW5fcG9ydGZvbGlvID0gY2FzZV93aGVuKA0KICAgICAgcG9ydGZvbGlvX3R5cGUgPT0gImNvbnRfb25seSIgfiAoYXMubG9naWNhbChjb250KSAmICFhcy5sb2dpY2FsKHNwZWMpKSwNCiAgICAgIHBvcnRmb2xpb190eXBlID09ICJzcGVjX29ubHkiIH4gKGFzLmxvZ2ljYWwoc3BlYykgJiAhYXMubG9naWNhbChjb250KSksDQogICAgICBwb3J0Zm9saW9fdHlwZSA9PSAic3RhYmxlIiAgICB+ICghYXMubG9naWNhbChpbnN0YWJsZSkgJiAhaXMubmEoaW5zdGFibGUpKSwNCiAgICAgIFRSVUUgfiBGQUxTRQ0KICAgICkpICU+JQ0KICAgIHNlbGVjdChlbmQsIHZhcmlhYmxlLCBpbl9wb3J0Zm9saW8pDQp9DQoNCmJ1aWxkX2NvbnN0aXR1ZW50c19sYWdnZWQgPC0gZnVuY3Rpb24ocm9sbF9kZiwgcG9ydGZvbGlvX3R5cGUpIHsNCiAgYnVpbGRfY29uc3RpdHVlbnRzKHJvbGxfZGYsIHBvcnRmb2xpb190eXBlKSAlPiUNCiAgICBhcnJhbmdlKHZhcmlhYmxlLCBlbmQpICU+JQ0KICAgIGdyb3VwX2J5KHZhcmlhYmxlKSAlPiUNCiAgICBtdXRhdGUoaW5fcG9ydGZvbGlvID0gbGFnKGluX3BvcnRmb2xpbywgZGVmYXVsdCA9IEZBTFNFKSkgJT4lDQogICAgdW5ncm91cCgpDQp9DQoNCmNvbXB1dGVfZGFpbHlfcmV0dXJucyA8LSBmdW5jdGlvbihkYWlseV9kZiwgY29uc3RpdHVlbnRzX2RmKSB7DQogIGRhdGVzX3NjaGVkIDwtIHNvcnQodW5pcXVlKGNvbnN0aXR1ZW50c19kZiRlbmQpKQ0KICByZXRfY2FwICAgICA8LSBsb2coMikNCiAgcHVycnI6Om1hcF9kZnIoc2VxX2Fsb25nKGRhdGVzX3NjaGVkKSwgZnVuY3Rpb24oaSkgew0KICAgIHRfc3RhcnQgPC0gZGF0ZXNfc2NoZWRbaV0NCiAgICB0X2VuZCAgIDwtIGlmIChpIDwgbGVuZ3RoKGRhdGVzX3NjaGVkKSkgZGF0ZXNfc2NoZWRbaSArIDFMXSBlbHNlIG1heChkYWlseV9kZiRkYXRlKQ0KICAgIG1lbWJlcnMgPC0gY29uc3RpdHVlbnRzX2RmICU+JSBmaWx0ZXIoZW5kID09IHRfc3RhcnQsIGluX3BvcnRmb2xpbykgJT4lIHB1bGwodmFyaWFibGUpDQogICAgcm93cyAgICA8LSBkYWlseV9kZiAlPiUgZmlsdGVyKGRhdGUgPiB0X3N0YXJ0LCBkYXRlIDw9IHRfZW5kKQ0KICAgIGlmIChsZW5ndGgobWVtYmVycykgPT0gMCkNCiAgICAgIHJldHVybihyb3dzICU+JSBkaXN0aW5jdChkYXRlKSAlPiUgbXV0YXRlKHBvcnRfcmV0ID0gTkFfcmVhbF8sIG5fYXNzZXRzID0gMEwpKQ0KICAgIHd0cyA8LSB0aWJibGUodmFyaWFibGUgPSBtZW1iZXJzLCB3ZWlnaHQgPSAxIC8gbGVuZ3RoKG1lbWJlcnMpKQ0KICAgIHJvd3MgJT4lDQogICAgICBmaWx0ZXIodmFyaWFibGUgJWluJSBtZW1iZXJzKSAlPiUNCiAgICAgIGxlZnRfam9pbih3dHMsIGJ5ID0gInZhcmlhYmxlIikgJT4lDQogICAgICBtdXRhdGUoc2ltcGxlX3JldCA9IGV4cChwbWF4KHBtaW4ocmV0dXJuLCByZXRfY2FwKSwgLXJldF9jYXApKSAtIDEpICU+JQ0KICAgICAgZ3JvdXBfYnkoZGF0ZSkgJT4lDQogICAgICBzdW1tYXJpc2UocG9ydF9yZXQgID0gc3VtKHNpbXBsZV9yZXQgKiB3ZWlnaHQsIG5hLnJtID0gVFJVRSkgLw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KHN1bSh3ZWlnaHRbIWlzLm5hKHNpbXBsZV9yZXQpXSksIDFlLTkpLA0KICAgICAgICAgICAgICAgIG5fYXNzZXRzICA9IHN1bSghaXMubmEoc2ltcGxlX3JldCkpLA0KICAgICAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpDQogIH0pDQp9DQoNCiMg4pSA4pSAIFRvcC0xMCBmaXhlZCBiYXNrZXQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQpUT1AxMCA8LSBjKCJCVEMiLCJFVEgiLCJCTkIiLCJYUlAiLCJBREEiLCJTT0wiLCJET0dFIiwiVFJYIiwiTFRDIiwiRE9UIikNCnRvcDEwX2Fzc2V0cyA8LSBpbnRlcnNlY3QoVE9QMTAsIHVuaXF1ZShyb2xsJHZhcmlhYmxlKSkNCnRvcDEwX2NvbnN0ICA8LSByb2xsICU+JSBkaXN0aW5jdChlbmQpICU+JQ0KICBjcm9zc2luZyh2YXJpYWJsZSA9IHRvcDEwX2Fzc2V0cykgJT4lDQogIG11dGF0ZShpbl9wb3J0Zm9saW8gPSBUUlVFKQ0KDQojIOKUgOKUgCBCdWlsZCBsYWdnZWQgcHJlZGljdGl2ZSBwb3J0Zm9saW9zIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgA0KcG9ydF90eXBlcyA8LSBjKGNvbnRfb25seSA9ICJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiLA0KICAgICAgICAgICAgICAgIHNwZWNfb25seSA9ICJGaW5hbmNpYWwgRnJhZ2lsaXR5IiwNCiAgICAgICAgICAgICAgICBzdGFibGUgICAgPSAiU3RhYmxlIikNCg0KcG9ydF9kYXRhIDwtIHB1cnJyOjppbWFwX2Rmcihwb3J0X3R5cGVzLCBmdW5jdGlvbihsYWJlbCwgcHR5cGUpIHsNCiAgYnVpbGRfY29uc3RpdHVlbnRzX2xhZ2dlZChyb2xsLCBwdHlwZSkgJT4lDQogICAgY29tcHV0ZV9kYWlseV9yZXR1cm5zKGRhdGFfY3J5cHRvLCAuKSAlPiUNCiAgICBtdXRhdGUocG9ydGZvbGlvID0gbGFiZWwpDQp9KQ0KDQp0b3AxMF9kYXRhIDwtIGNvbXB1dGVfZGFpbHlfcmV0dXJucyhkYXRhX2NyeXB0bywgdG9wMTBfY29uc3QpICU+JQ0KICBtdXRhdGUocG9ydGZvbGlvID0gIlRvcC0xMCIpDQoNCiMg4pSA4pSAIEN1bXVsYXRpdmUgd2VhbHRoIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgA0KUE9SVF9MRVZFTFMgPC0gYygiU3RhYmxlIiwgIlRvcC0xMCIsICJGaW5hbmNpYWwgRnJhZ2lsaXR5IiwgIkZpbmFuY2lhbCBJbnN0YWJpbGl0eSIpDQpDT0xPUlNfUE9SVCA8LSBjKCJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiID0gIiNkNjI3MjgiLA0KICAgICAgICAgICAgICAgICAiRmluYW5jaWFsIEZyYWdpbGl0eSIgICA9ICIjMWY3N2I0IiwNCiAgICAgICAgICAgICAgICAgIlN0YWJsZSIgICAgICAgICAgICAgICAgPSAiZGFya2dyZWVuIiwNCiAgICAgICAgICAgICAgICAgIlRvcC0xMCIgICAgICAgICAgICAgICAgPSAiYmxhY2siKQ0KDQpiaW5kX3Jvd3MocG9ydF9kYXRhLCB0b3AxMF9kYXRhKSAlPiUNCiAgbXV0YXRlKHBvcnRmb2xpbyA9IGZhY3Rvcihwb3J0Zm9saW8sIGxldmVscyA9IFBPUlRfTEVWRUxTKSkgJT4lDQogIGdyb3VwX2J5KHBvcnRmb2xpbykgJT4lDQogIGFycmFuZ2UoZGF0ZSkgJT4lDQogIG11dGF0ZShjdW1fd2VhbHRoID0gMTAwICogY3VtcHJvZChpZmVsc2UoaXMubmEocG9ydF9yZXQpLCAxLCAxICsgcG9ydF9yZXQpKSkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IGN1bV93ZWFsdGgsIGNvbG9yID0gcG9ydGZvbGlvLCBsaW5ldHlwZSA9IHBvcnRmb2xpbykpICsNCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDAuOSwgbmEucm0gPSBUUlVFKSArDQogIHNjYWxlX3lfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoYWNjdXJhY3kgPSAxKSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gQ09MT1JTX1BPUlQsIG5hbWUgPSBOVUxMKSArDQogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKCJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiID0gInNvbGlkIiwgIkZpbmFuY2lhbCBGcmFnaWxpdHkiID0gInNvbGlkIiwNCiAgICAgICAgICAgICAgICJTdGFibGUiID0gInNvbGlkIiwgIlRvcC0xMCIgPSAic29saWQiKSwNCiAgICBuYW1lID0gTlVMTCkgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiLA0KICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSAwLjAyKSkgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gIkN1bXVsYXRpdmUgd2VhbHRoIChsb2cgc2NhbGUsIGJhc2UgMTAwKSIpICsNCiAgdGhlbWVfY3J5cHRvKCkNCmBgYA0KDQpUaGUgKipTdGFibGUgcG9ydGZvbGlvIGdlbmVyYXRlcyB0aGUgaGlnaGVzdCBjdW11bGF0aXZlIHJldHVybioqIG92ZXIgdGhlIGZ1bGwgc2FtcGxlLCBvdXRwZXJmb3JtaW5nIGJvdGggdGhlIFRvcC0xMCBiZW5jaG1hcmsgYW5kIHRoZSB0YWlsLWFtcGxpZmljYXRpb24gcG9ydGZvbGlvcy4gQXNzZXRzIHRoYXQgZG8gbm90IGFtcGxpZnkgc3lzdGVtYXRpYyBzaG9ja3MgaW4gZWl0aGVyIHRhaWwgYXJlIGxlc3MgZXhwb3NlZCB0byBzaGFycCBkcmF3ZG93bnMgZHVyaW5nIHN0cmVzcyBlcGlzb2RlcyB3aGlsZSBzdGlsbCBwYXJ0aWNpcGF0aW5nIGluIGJyb2FkIG1hcmtldCBhcHByZWNpYXRpb24gZHVyaW5nIGNhbG0gcGhhc2VzLCBjb25zaXN0ZW50IHdpdGggQW5nIGV0IGFsLiAoMjAwNikuIFRoZSByZXN1bHQgaXMgY29uc2lzdGVudCB3aXRoIHRoZSBsb25nLXRlcm0gcGVyZm9ybWFuY2UgYWR2YW50YWdlIG9mIGFzc2V0cyBhdm9pZGluZyBjcmFzaCBhbXBsaWZpY2F0aW9uIG9yIGJ1YmJsZSBmb3JtYXRpb24gKFBlbGxlZ3JpbmkgZXQgYWwuLCAyMDA4KS4NCg0KVGhlIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSBhbmQgRmluYW5jaWFsIEZyYWdpbGl0eSBwb3J0Zm9saW9zICoqYm90aCB1bmRlcnBlcmZvcm0qKiBvdmVyIHRoZSBmdWxsIHNhbXBsZS4gQm90aCBwb3J0Zm9saW9zIGV4cGFuZCBzaGFycGx5IGR1cmluZyB0aGUgMjAyMSBidWxsIG1hcmtldCBidXQgZGVjb3VwbGUgZnJvbSB0aGUgYmVuY2htYXJrIGR1cmluZyB0aGUgMjAyMiBDcnlwdG8tV2ludGVyLiBUaGlzIHJlZmxlY3RzIHRoZSB0d2luIGNvc3RzIG9mIHRhaWwgYW1wbGlmaWNhdGlvbjogYXNzZXRzIGV4aGliaXRpbmcgbGVmdC10YWlsIHNlbnNpdGl2aXR5IHVuZGVycGVyZm9ybSBkdXJpbmcgZG93bnR1cm5zIHRocm91Z2ggc2hvY2sgYW1wbGlmaWNhdGlvbiwgd2hpbGUgYXNzZXRzIHdpdGggcmlnaHQtdGFpbCBzZW5zaXRpdml0eSBtYXkgb3ZlcnBlcmZvcm0gc2hvcnQtdGVybSBkdXJpbmcgc3BlY3VsYXRpdmUgcGhhc2VzIGJ1dCBleHBlcmllbmNlIHJldmVyc2FscyBvbmNlIHRoZSBzcGVjdWxhdGl2ZSBwaGFzZSBlbmRzLg0KDQpPdmVyYWxsLCBvdXIgdGFpbC1kZXBlbmRlbmNlIHBvcnRmb2xpbyBhbmFseXNpcyBkZW1vbnN0cmF0ZXMgdGhlIGltcG9ydGFuY2Ugb2YgaW5jb3Jwb3JhdGluZyB0YWlsLWRlcGVuZGVuY2UgaW4gcG9ydGZvbGlvIHN0cmF0ZWdpZXMsIGNvbnNpc3RlbnQgd2l0aCBCZXJnbWFubiBldCBhbC4gKDIwMTgpIHdobyBzaG93IHRoYXQgdGFpbCBkZXBlbmRlbmNlIG1vZGVscyBvdXRwZXJmb3JtIHRoZSBNYXJrb3dpdHogbW9kZWwgaW4gdGVybXMgb2YgY3VtdWxhdGl2ZSByZXR1cm4uDQoNCiMjIENvbXBhcmlzb25zIHdpdGggRXF1aXR5IE1hcmtldHMgeyNlcXVpdHl9DQoNClRvIGJlbmNobWFyayBjcnlwdG8gaW5zdGFiaWxpdHkgYWdhaW5zdCBhIHRyYWRpdGlvbmFsIGFzc2V0IGNsYXNzLCB3ZSBhcHBseSB0aGUgaWRlbnRpY2FsIHJvbGxpbmcgcXVhbnRpbGUgcmVncmVzc2lvbiBmcmFtZXdvcmsgdG8gaW5kaXZpZHVhbCBlcXVpdHkgc3RvY2tzLiBBZGp1c3RlZCBkYWlseSBjbG9zaW5nIHByaWNlcyBhcmUgc291cmNlZCBmcm9tIFlhaG9vIEZpbmFuY2UgZm9yIGEgdW5pdmVyc2Ugb2YgKioxNDMgbGFyZ2UtY2FwIGZpcm1zKiogc3Bhbm5pbmcgTm9ydGggQW1lcmljYSAoNjAgc3RvY2tzKSwgRXVyb3BlICg1NCBzdG9ja3MpLCBKYXBhbiAoMTMgc3RvY2tzKSwgQ2hpbmEsIEF1c3RyYWxpYSwgYW5kIEluZGlhICg0IHN0b2NrcykuDQoNClRoZSBlcXVpdHkgc2FtcGxlIGJlZ2lucyBpbiBKYW51YXJ5IDE5OTUgYW5kIGNsb3NlcyBpbiBGZWJydWFyeSAyMDI2LiBUaGUgc3lzdGVtYXRpYyBlcXVpdHkgc2hvY2sgaXMgY29uc3RydWN0ZWQgYnkgYXBwbHlpbmcgdGhlIHNhbWUgdHdvLXN0ZXAgcHJvY2VkdXJlOiBhIGZpcnN0IHByaW5jaXBhbCBjb21wb25lbnQgaXMgZXh0cmFjdGVkIGZyb20gKio0OSBjb3VudHJ5LWxldmVsIGVxdWl0eSBwcmljZSBpbmRpY2VzKiogc291cmNlZCBmcm9tIERhdGFzdHJlYW0gZm9sbG93aW5nIFJleSAmIE1pcmFuZGEtQWdyaXBwaW5vICgyMDIxKSwgYW5kIGEgR0FSQ0goMSwxKSBtb2RlbCBpcyBlc3RpbWF0ZWQgb24gdGhlIGZpcnN0LWRpZmZlcmVuY2VkIGZhY3Rvci4gSW5kaXZpZHVhbCBzdG9ja3MgYXJlIG5vdCB1c2VkIGluIGZhY3RvciBjb25zdHJ1Y3Rpb24sIHNvIHRoZSBzeXN0ZW1hdGljIHNob2NrIGlzIGV4b2dlbm91cyBieSBkZXNpZ24uDQoNCmBgYHtyIGVxdWl0eS1jb2RlLCBldmFsPUZBTFNFfQ0KIyDilIDilIAgRXF1aXR5IHJvbGxpbmcgUVIgKGV2YWw9RkFMU0Ug4oCUIHJ1biBvbmNlIHZpYSBzcmMvMjVfZ2FyY2hfc2hvY2tfZnVsbC5SKQ0KIyBVc2VzIGRhdGEvaW50ZXJtZWRpYXRlL3N0b2Nrc19wYW5lbC5wYXJxdWV0Lg0KIyBPdXRwdXQ6IG91dHB1dC9tb2RlbHMvc3RvY2tzX3JvbGxfZ2FyY2hfc2hvY2tfZXh0LnBhcnF1ZXQNCiMgICAgICAgICBvdXRwdXQvZmlndXJlcy9nYXJjaF9zaG9ja19leHQvZXF1aXR5L3N0b2Nrc19jb21wYXJpc29uLnBkZg0KYGBgDQoNCmBgYHtyIGxvYWQtZXF1aXR5fQ0KZXF1aXR5IDwtIGFycm93OjpyZWFkX3BhcnF1ZXQoc3AkbW9kZWxzJHN0b2Nrc19yb2xsKSAlPiUNCiAgbXV0YXRlKGVuZCA9IGFzLkRhdGUoZW5kKSkNCg0KY2F0KCJFcXVpdHkgcmVzdWx0czoiLCBucm93KGVxdWl0eSksICJyb3dzIOKAlCIsDQogICAgbGVuZ3RoKHVuaXF1ZShlcXVpdHkkdmFyaWFibGUpKSwgInN0b2Nrc1xuIikNCg0KYmluZF9yb3dzKA0KICBkYXRhLmZyYW1lKEdyb3VwID0gIkNyeXB0byIsDQogICAgICAgICAgICAgYEZJIG1lYW4gKCUpYCA9IHJvdW5kKG1lYW4oc2hhcmVzJGZpKSwgMSksDQogICAgICAgICAgICAgYEZGIG1lYW4gKCUpYCA9IHJvdW5kKG1lYW4oc2hhcmVzJGZmKSwgMSkpLA0KICBlcXVpdHkgJT4lDQogICAgZ3JvdXBfYnkoZW5kKSAlPiUNCiAgICBzdW1tYXJpc2UoZmkgPSBtZWFuKGNvbnQsIG5hLnJtPVRSVUUpKjEwMCwNCiAgICAgICAgICAgICAgZmYgPSBtZWFuKHNwZWMsIG5hLnJtPVRSVUUpKjEwMCwgLmdyb3Vwcz0iZHJvcCIpICU+JQ0KICAgIHN1bW1hcmlzZShHcm91cCA9ICJFcXVpdHkiLA0KICAgICAgICAgICAgICBgRkkgbWVhbiAoJSlgID0gcm91bmQobWVhbihmaSksIDEpLA0KICAgICAgICAgICAgICBgRkYgbWVhbiAoJSlgID0gcm91bmQobWVhbihmZiksIDEpKQ0KKSAlPiUNCiAga2FibGUoY2FwdGlvbiA9ICIqKkF2ZXJhZ2UgRmluYW5jaWFsIEluc3RhYmlsaXR5IGFuZCBGcmFnaWxpdHk6IENyeXB0byB2cy4gRXF1aXR5KioiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJob3ZlciIpLCBmdWxsX3dpZHRoID0gRkFMU0UpDQpgYGANCg0KYGBge3IgZmlnLWVxdWl0eSwgZmlnLmNhcD0iKipGaWd1cmUgMyDigJQgRmluYW5jaWFsIEluc3RhYmlsaXR5IGFuZCBGcmFnaWxpdHkgaW4gRXF1aXR5IE1hcmtldHMuKiogUm9sbGluZyBGSSBhbmQgRkYgc2hhcmVzIGZvciBjcnlwdG8tYXNzZXRzIGFuZCBpbmRpdmlkdWFsIGVxdWl0eSBzdG9ja3Mgb3ZlciB0aGUgb3ZlcmxhcHBpbmcgZXN0aW1hdGlvbiBwZXJpb2QgKEp1bHkgMjAxOSDigJMgSmFudWFyeSAyMDI2KS4gRWFjaCBzaGFyZSBpcyB0aGUgZnJhY3Rpb24gb2YgYXNzZXRzIGNsYXNzaWZpZWQgYXMgZXhoaWJpdGluZyBsZWZ0LXRhaWwgKEZJKSBvciByaWdodC10YWlsIChGRikgYW1wbGlmaWNhdGlvbiBhdCB0aGUgMTAlIHNpZ25pZmljYW5jZSBsZXZlbC4iLCBmaWcuaGVpZ2h0PTZ9DQplcXVpdHlfc2hhcmVzIDwtIGVxdWl0eSAlPiUNCiAgZ3JvdXBfYnkoZW5kKSAlPiUNCiAgc3VtbWFyaXNlKGZpID0gbWVhbihjb250LCBuYS5ybT1UUlVFKSoxMDAsDQogICAgICAgICAgICBmZiA9IG1lYW4oc3BlYywgbmEucm09VFJVRSkqMTAwLCAuZ3JvdXBzPSJkcm9wIikNCg0KYmluZF9yb3dzKA0KICBzaGFyZXMgICAgICAlPiUgc2VsZWN0KGVuZCwgZmksIGZmKSAlPiUgbXV0YXRlKGdyb3VwID0gIkNyeXB0byIpLA0KICBlcXVpdHlfc2hhcmVzICAgICAgICAgICAgICAgICAgICAgICAgJT4lIG11dGF0ZShncm91cCA9ICJFcXVpdHkiKQ0KKSAlPiUNCiAgZmlsdGVyKGVuZCA+PSBhcy5EYXRlKCIyMDE5LTA3LTAxIikpICU+JQ0KICBwaXZvdF9sb25nZXIoYyhmaSwgZmYpLCBuYW1lc190byA9ICJtZXRyaWMiLCB2YWx1ZXNfdG8gPSAic2hhcmUiKSAlPiUNCiAgbXV0YXRlKA0KICAgIG1ldHJpYyA9IGZhY3RvcihyZWNvZGUobWV0cmljLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmkgPSAiRmluYW5jaWFsIEluc3RhYmlsaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZmID0gIkZpbmFuY2lhbCBGcmFnaWxpdHkiKSwNCiAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRmluYW5jaWFsIEluc3RhYmlsaXR5IiwgIkZpbmFuY2lhbCBGcmFnaWxpdHkiKSksDQogICAgZ3JvdXAgID0gZmFjdG9yKGdyb3VwLCBsZXZlbHMgPSBjKCJDcnlwdG8iLCAiRXF1aXR5IikpDQogICkgJT4lDQogIGdncGxvdChhZXMoeCA9IGVuZCwgeSA9IHNoYXJlIC8gMTAwLCBjb2xvciA9IGdyb3VwLCBsaW5ldHlwZSA9IGdyb3VwKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMC45LCBuYS5ybSA9IFRSVUUpICsNCiAgZmFjZXRfd3JhcCh+bWV0cmljLCBuY29sID0gMikgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQ3J5cHRvIiA9ICJibGFjayIsICJFcXVpdHkiID0gIiMxZjc3YjQiKSwNCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSBOVUxMKSArDQogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKCJDcnlwdG8iID0gInNvbGlkIiwgIkVxdWl0eSIgPSAiZGFzaGVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gTlVMTCkgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiLA0KICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSAwLjAyKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLA0KICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMDUpKSkgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gIlNoYXJlIG9mIGFzc2V0cyAoJSkiKSArDQogIHRoZW1lX2NyeXB0bygpDQpgYGANCg0KRXF1aXR5IG1hcmtldHMgZXhoaWJpdCAqKnN1YnN0YW50aWFsbHkgbG93ZXIgRmluYW5jaWFsIEluc3RhYmlsaXR5KiogdGhhbiBjcnlwdG8tYXNzZXRzLCB3aXRoIGFuIGF2ZXJhZ2Ugc2hhcmUgb2YgNS4zJSBhZ2FpbnN0IDEwLjElIGZvciBjcnlwdG8uIEEgcHJvbm91bmNlZCBwZWFrIGVtZXJnZXMgaW4gdGhlIGltbWVkaWF0ZSBhZnRlcm1hdGggb2YgdGhlIENvdmlkLTE5IHNob2NrIGluIDIwMjAsIGR1cmluZyB3aGljaCBzeW5jaHJvbmlzZWQgZ2xvYmFsIGVxdWl0eSBzZWxsLW9mZnMgZ2VuZXJhdGVkIGxlZnQtdGFpbCBhbXBsaWZpY2F0aW9uIGFjcm9zcyBhIGJyb2FkIGNyb3NzLXNlY3Rpb24gb2YgaW5kaXZpZHVhbCBzdG9ja3MgKFJhbWVsbGkgJiBXYWduZXIsIDIwMjA7IEFsZmFybyBldCBhbC4sIDIwMjApLiBPdXRzaWRlIG9mIHRoaXMgZXBpc29kZSwgRmluYW5jaWFsIEluc3RhYmlsaXR5IGluIGVxdWl0eSBtYXJrZXRzIHJlbWFpbnMgd2VsbCBiZWxvdyB0aGUgY3J5cHRvIGJlbmNobWFyay4NCg0KVGhlIGdhcCBpcyBldmVuIG1vcmUgcHJvbm91bmNlZCBmb3IgKipGaW5hbmNpYWwgRnJhZ2lsaXR5KiouIFRoZSBhdmVyYWdlIGVxdWl0eSBzaGFyZSBvZiA0LjYlIGlzIGxlc3MgdGhhbiBvbmUtdGhpcmQgb2YgdGhlIGNyeXB0byBhdmVyYWdlIG9mIDE1LjclLiBUaGlzIGRpdmVyZ2VuY2UgcmVmbGVjdHMgdGhlIGdyZWF0ZXIgc3VzY2VwdGliaWxpdHkgb2YgY3J5cHRvIG1hcmtldHMgdG8gaGVyZGluZyBhbmQgbW9tZW50dW0gZHVyaW5nIGV4cGFuc2lvbmFyeSBwaGFzZXMgKEJvdXJpIGV0IGFsLiwgMjAyMTsgS3lyaWF6aXMgZXQgYWwuLCAyMDIwKTogd2hlcmVhcyBlcXVpdHkgcHJpY2VzIHJlc3BvbmQgdG8gZnVuZGFtZW50YWwgcmV2aXNpb25zIGluIGNhc2gtZmxvdyBleHBlY3RhdGlvbnMgZHVyaW5nIGJvb21zLCBjcnlwdG8gdmFsdWF0aW9ucyBhcmUgbW9yZSBkaXJlY3RseSBkcml2ZW4gYnkgc3BlY3VsYXRpdmUgZGVtYW5kIGFuZCBzZW50aW1lbnQuIEluIGFkZGl0aW9uLCBlcXVpdHkgbWFya2V0cyBleGhpYml0IGxhcmdlciBpbnN0YWJpbGl0eSB0aGFuIGZyYWdpbGl0eSwgY29uc2lzdGVudCB3aXRoIEh1ICgyMDA2KSB3aG8gc2hvd3MgdGhhdCBzdG9jayBtYXJrZXRzIGFyZSBtb3JlIGxpa2VseSB0byBleGhpYml0IGxlZnQtdGFpbCBkZXBlbmRlbmNlIHRoYW4gcmlnaHQtdGFpbCBkZXBlbmRlbmNlLg0KDQpUYWtlbiB0b2dldGhlciwgdGhlc2UgcmVzdWx0cyBlc3RhYmxpc2ggYSAqKnF1YW50aXRhdGl2ZSBnYXAqKiBpbiBmaW5hbmNpYWwgc3RhYmlsaXR5IGJldHdlZW4gY3J5cHRvLWFzc2V0cyBhbmQgZXF1aXR5IG1hcmtldHMuIFRoZSBub3ZlbHR5IGxpZXMgbm90IGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGZpbmRpbmcgYnV0IGluIGl0cyBncm91bmRpbmc6IHRoZSBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgYW5kIEZpbmFuY2lhbCBGcmFnaWxpdHkgaW5kaWNlcyBhcmUgZGVyaXZlZCBmcm9tIGEgZm9ybWFsIHRlc3Qgb2Ygc2hvY2sgdHJhbnNtaXNzaW9uIHN0YWJpbGl0eSByYXRoZXIgdGhhbiBmcm9tIGEgY29tcGFyaXNvbiBhZ2FpbnN0IGFuIGFyYml0cmFyeSBiZW5jaG1hcmsg4oCUIGEgZGlzdGluY3Rpb24gdGhhdCBtYXR0ZXJzIGJlY2F1c2Ugdm9sYXRpbGl0eS1iYXNlZCByYW5raW5ncyBhcmUgc2Vuc2l0aXZlIHRvIHRoZSBjaG9pY2Ugb2YgcmVmZXJlbmNlIGFzc2V0LCB3aGVyZWFzIG91ciBjbGFzc2lmaWNhdGlvbiBpcyBzZWxmLWNvbnRhaW5lZCBhdCB0aGUgYXNzZXQgbGV2ZWwuDQoNCi0tLQ0KDQojIFJvYnVzdG5lc3MgeyNyb2J1c3RuZXNzfQ0KDQojIyBNb2RlbCBTcGVjaWZpY2F0aW9uDQoNCldlIHJ1biBzZXZlcmFsIHJvYnVzdG5lc3MgY2hlY2tzIHRvIGNvbmZpcm0gdGhhdCBvdXIgcmVzdWx0cyBhcmUgbm90IGRlcGVuZGVudCBvbiBtb2RlbCBzcGVjaWZpY2F0aW9ucy4gVGhlIGJhc2VsaW5lIHVzZXMgMTgtbW9udGggcm9sbGluZyB3aW5kb3dzLCAkXHRhdSBcaW4gXHswLjA1LCAwLjUwLCAwLjk1XH0kLCBXYWxkIHRlc3QgYXQgMTAlIHNpZ25pZmljYW5jZSwgYW5kIGJpbGF0ZXJhbCBkdW1taWVzIGF0IHRoZSA1JSB0YWlsIHRocmVzaG9sZC4NCg0KYGBge3Igcm9idXN0bmVzcy1jb2RlLCBldmFsPUZBTFNFfQ0KIyDilIDilIAgQWxsIHJvYnVzdG5lc3MgZXN0aW1hdGlvbnMgKGV2YWw9RkFMU0Ug4oCUIHJ1biBvbmNlIHZpYSBzcmMvcm9idXN0X2dhcmNoX3Nob2NrX2V4dC5SKQ0KIyBPdXRwdXRzOg0KIyAgIG91dHB1dC9tb2RlbHMvZ2FyY2hfc2hvY2tfZXh0L3JvYnVzdF93aW5kb3dzLnBhcnF1ZXQNCiMgICBvdXRwdXQvbW9kZWxzL2dhcmNoX3Nob2NrX2V4dC9yb2J1c3RfdGF1X3ZlYy5wYXJxdWV0DQojICAgb3V0cHV0L21vZGVscy9nYXJjaF9zaG9ja19leHQvcm9idXN0X2FscGhhLnBhcnF1ZXQNCiMgICBvdXRwdXQvbW9kZWxzL2dhcmNoX3Nob2NrX2V4dC9yb2J1c3RfdGhyZXNob2xkLnBhcnF1ZXQNCiMgYW5kIGNvcnJlc3BvbmRpbmcgUERGIGZpZ3VyZXMgaW4gb3V0cHV0L2ZpZ3VyZXMvZ2FyY2hfc2hvY2tfZXh0L3JvYnVzdG5lc3MvDQpzb3VyY2UoInNyYy9yb2J1c3RfZ2FyY2hfc2hvY2tfZXh0LlIiKQ0KYGBgDQoNCiMjIyBBbHRlcm5hdGl2ZSBXaW5kb3cgV2lkdGhzDQoNCldlIHVzZSBzaG9ydGVyICg2IGFuZCAxMiBtb250aHMpIGFuZCBsb25nZXIgKDI0IGFuZCAzMCBtb250aHMpIHdpbmRvd3MuIFNob3J0ZXIgd2luZG93cyBhcmUgbW9yZSByZWFjdGl2ZSBidXQgbm9pc2llcjsgbG9uZ2VyIHdpbmRvd3MgYXJlIHNtb290aGVyIGJ1dCBzbG93ZXIgdG8gZGV0ZWN0IGNyaXNlcy4NCg0KYGBge3IgZmlnLXJvYi13aW5kb3csIGZpZy5jYXA9IioqRmlndXJlIDQg4oCUIFJvYnVzdG5lc3MgdG8gQWx0ZXJuYXRpdmUgUm9sbGluZyBXaW5kb3cgV2lkdGguKiogVGhlIGdyZXkgYXJlYSBzcGFucyB0aGUgbWluaW11bSBhbmQgbWF4aW11bSBzaGFyZXMgYWNyb3NzIGFsdGVybmF0aXZlIHdpbmRvdyB3aWR0aHMgb2YgNiwgMTIsIDI0LCBhbmQgMzAgbW9udGhzOyB0aGUgc29saWQgbGluZSByZXBvcnRzIHRoZSBiYXNlbGluZSAxOC1tb250aCB3aW5kb3cuIiwgZmlnLmhlaWdodD02fQ0Kcm9iX3dpbiA8LSBhcnJvdzo6cmVhZF9wYXJxdWV0KHNwJG1vZGVscyRyb2J1c3Rfd2luZG93cykgJT4lDQogIG11dGF0ZShlbmQgPSBhcy5EYXRlKGVuZCkpICU+JQ0KICBncm91cF9ieShlbmQsIHdpbmRvd19tb250aHMpICU+JQ0KICBzdW1tYXJpc2UoZmkgPSBtZWFuKGNvbnQsIG5hLnJtPVRSVUUpLCBmZiA9IG1lYW4oc3BlYywgbmEucm09VFJVRSksIC5ncm91cHM9ImRyb3AiKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKGMoZmksIGZmKSwgbmFtZXNfdG8gPSAibWV0cmljIiwgdmFsdWVzX3RvID0gInNoYXJlIikgJT4lDQogIG11dGF0ZShtZXRyaWMgPSBmYWN0b3IocmVjb2RlKG1ldHJpYywNCiAgICBmaSA9ICJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiLCBmZiA9ICJGaW5hbmNpYWwgRnJhZ2lsaXR5IiksDQogICAgbGV2ZWxzID0gYygiRmluYW5jaWFsIEluc3RhYmlsaXR5IiwgIkZpbmFuY2lhbCBGcmFnaWxpdHkiKSkpDQoNCmJhbmRfd2luICA8LSByb2Jfd2luICU+JQ0KICBncm91cF9ieShlbmQsIG1ldHJpYykgJT4lDQogIHN1bW1hcmlzZShsbyA9IG1pbihzaGFyZSksIGhpID0gbWF4KHNoYXJlKSwgLmdyb3VwcyA9ICJkcm9wIikNCmJhc2Vfd2luICA8LSByb2Jfd2luICU+JSBmaWx0ZXIod2luZG93X21vbnRocyA9PSAxOCkNCg0KZ2dwbG90KGJhbmRfd2luLCBhZXMoeCA9IGVuZCkpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBsbywgeW1heCA9IGhpKSwgZmlsbCA9ICJncmV5NzAiLCBhbHBoYSA9IDAuNSkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IGJhc2Vfd2luLCBhZXMoeSA9IHNoYXJlKSwgY29sb3IgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjkpICsNCiAgZmFjZXRfd3JhcCh+bWV0cmljLCBuY29sID0gMikgKw0KICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiLA0KICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSAwLjAyKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLA0KICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMDUpKSkgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gIlNoYXJlIG9mIGFzc2V0cyAoJSkiKSArDQogIHRoZW1lX2NyeXB0bygpDQpgYGANCg0KRGVzcGl0ZSB0aGUgaGV0ZXJvZ2VuZWl0eSBpbnRyb2R1Y2VkIGJ5IHdpbmRvdyBjaG9pY2UsIG91ciByZXN1bHRzIHN0YXkgY29uc2lzdGVudCBhY3Jvc3Mgc3BlY2lmaWNhdGlvbnMg4oCUIHBhcnRpY3VsYXJseSBmb3IgdGhlIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSBpbmRleCwgd2hpbGUgdGhlIEZpbmFuY2lhbCBGcmFnaWxpdHkgaW5kZXggZXhoaWJpdHMgbGFyZ2VyIHRpbWluZyBkaWZmZXJlbmNlcyBidXQgYSBzaW1pbGFyIG92ZXJhbGwgZHluYW1pY3MuDQoNCiMjIyBBbHRlcm5hdGl2ZSBRdWFudGlsZSBWZWN0b3JzDQoNCldlIHVzZSBhIHN0cmljdGVyIHNwZWNpZmljYXRpb24gKCRcdGF1IFxpbiBcezAuMDEsIDAuNTAsIDAuOTlcfSQpIGFuZCBhIG1pbGRlciBzcGVjaWZpY2F0aW9uICgkXHRhdSBcaW4gXHswLjEwLCAwLjUwLCAwLjkwXH0kKS4NCg0KYGBge3IgZmlnLXJvYi10YXUsIGZpZy5jYXA9IioqRmlndXJlIDUg4oCUIFJvYnVzdG5lc3MgdG8gQWx0ZXJuYXRpdmUgRXh0cmVtZSBSZXR1cm5zIFF1YW50aWxlcy4qKiBUaGUgZ3JleSBhcmVhIHNwYW5zIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHNoYXJlcyBhY3Jvc3MgdGhlIHN0cmljdCBhbmQgbWlsZCBzcGVjaWZpY2F0aW9uczsgdGhlIHNvbGlkIGxpbmUgcmVwb3J0cyB0aGUgYmFzZWxpbmUgJFxcdGF1IFxcaW4gXFx7MC4wNSwgMC41MCwgMC45NVxcfSQuIiwgZmlnLmhlaWdodD02fQ0Kcm9iX3RhdSA8LSBhcnJvdzo6cmVhZF9wYXJxdWV0KHNwJG1vZGVscyRyb2J1c3RfdGF1X3ZlYykgJT4lDQogIG11dGF0ZShlbmQgPSBhcy5EYXRlKGVuZCkpICU+JQ0KICBncm91cF9ieShlbmQsIHRhdV9zcGVjKSAlPiUNCiAgc3VtbWFyaXNlKGZpID0gbWVhbihjb250LCBuYS5ybT1UUlVFKSwgZmYgPSBtZWFuKHNwZWMsIG5hLnJtPVRSVUUpLCAuZ3JvdXBzPSJkcm9wIikgJT4lDQogIHBpdm90X2xvbmdlcihjKGZpLCBmZiksIG5hbWVzX3RvID0gIm1ldHJpYyIsIHZhbHVlc190byA9ICJzaGFyZSIpICU+JQ0KICBtdXRhdGUobWV0cmljID0gZmFjdG9yKHJlY29kZShtZXRyaWMsDQogICAgZmkgPSAiRmluYW5jaWFsIEluc3RhYmlsaXR5IiwgZmYgPSAiRmluYW5jaWFsIEZyYWdpbGl0eSIpLA0KICAgIGxldmVscyA9IGMoIkZpbmFuY2lhbCBJbnN0YWJpbGl0eSIsICJGaW5hbmNpYWwgRnJhZ2lsaXR5IikpKQ0KDQpiYW5kX3RhdSA8LSByb2JfdGF1ICU+JQ0KICBncm91cF9ieShlbmQsIG1ldHJpYykgJT4lDQogIHN1bW1hcmlzZShsbyA9IG1pbihzaGFyZSksIGhpID0gbWF4KHNoYXJlKSwgLmdyb3VwcyA9ICJkcm9wIikNCmJhc2VfdGF1IDwtIHJvYl90YXUgJT4lIGZpbHRlcih0YXVfc3BlYyA9PSAiYmFzZWxpbmUiKQ0KDQpnZ3Bsb3QoYmFuZF90YXUsIGFlcyh4ID0gZW5kKSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGxvLCB5bWF4ID0gaGkpLCBmaWxsID0gImdyZXk3MCIsIGFscGhhID0gMC41KSArDQogIGdlb21fbGluZShkYXRhID0gYmFzZV90YXUsIGFlcyh5ID0gc2hhcmUpLCBjb2xvciA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuOSkgKw0KICBmYWNldF93cmFwKH5tZXRyaWMsIG5jb2wgPSAyKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsDQogICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IDAuMDIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksDQogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4wNSkpKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiU2hhcmUgb2YgYXNzZXRzICglKSIpICsNCiAgdGhlbWVfY3J5cHRvKCkNCmBgYA0KDQpUaGUgRmluYW5jaWFsIEluc3RhYmlsaXR5IGluZGV4IGlzIHJvYnVzdCB0byB0aGUgY2hhbmdlIG9mIHF1YW50aWxlcy4gVGhlIEZpbmFuY2lhbCBGcmFnaWxpdHkgaW5kZXggZXhoaWJpdHMgbGFyZ2VyIHZhcmlhdGlvbiB1bmRlciB0aGUgc3RyaWN0ZXIgc3BlY2lmaWNhdGlvbiwgYnV0IHRoZSBkeW5hbWljcyByZW1haW5zIHNpbWlsYXIgb3ZlcmFsbC4NCg0KIyMjIEFsdGVybmF0aXZlIFNpZ25pZmljYW5jZSBMZXZlbHMNCg0KV2UgcmVwb3J0IHJlc3VsdHMgd2l0aCBhIHRpZ2h0ZXIgNSUgV2FsZCB0ZXN0IHNpZ25pZmljYW5jZSBsZXZlbCBhbG9uZ3NpZGUgdGhlIGJhc2VsaW5lIDEwJS4NCg0KYGBge3IgZmlnLXJvYi1hbHBoYSwgZmlnLmNhcD0iKipGaWd1cmUgNiDigJQgUm9idXN0bmVzcyB0byBBbHRlcm5hdGl2ZSBXYWxkIFRlc3QgU2lnbmlmaWNhbmNlIExldmVscy4qKiBUaGUgdGlnaHRlciAkXFxhbHBoYSA9IDVcXCUkIHRocmVzaG9sZCAoZ3JleSBsaW5lKSBhbG9uZ3NpZGUgdGhlIGJhc2VsaW5lICRcXGFscGhhID0gMTBcXCUkIChibGFjayBsaW5lKS4iLCBmaWcuaGVpZ2h0PTZ9DQpyb2JfYWxwaGEgPC0gYXJyb3c6OnJlYWRfcGFycXVldChzcCRtb2RlbHMkcm9idXN0X2FscGhhKSAlPiUNCiAgbXV0YXRlKGVuZCA9IGFzLkRhdGUoZW5kKSkgJT4lDQogIGdyb3VwX2J5KGVuZCwgYWxwaGFfdmFsKSAlPiUNCiAgc3VtbWFyaXNlKGZpID0gbWVhbihjb250LCBuYS5ybT1UUlVFKSwgZmYgPSBtZWFuKHNwZWMsIG5hLnJtPVRSVUUpLCAuZ3JvdXBzPSJkcm9wIikgJT4lDQogIGZpbHRlcihhYnMoYWxwaGFfdmFsIC0gMC4wNSkgPCAxZS05IHwgYWJzKGFscGhhX3ZhbCAtIDAuMTApIDwgMWUtOSkgJT4lDQogIHBpdm90X2xvbmdlcihjKGZpLCBmZiksIG5hbWVzX3RvID0gIm1ldHJpYyIsIHZhbHVlc190byA9ICJzaGFyZSIpICU+JQ0KICBtdXRhdGUoDQogICAgbWV0cmljID0gZmFjdG9yKHJlY29kZShtZXRyaWMsDQogICAgICBmaSA9ICJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiLCBmZiA9ICJGaW5hbmNpYWwgRnJhZ2lsaXR5IiksDQogICAgICBsZXZlbHMgPSBjKCJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiLCAiRmluYW5jaWFsIEZyYWdpbGl0eSIpKSwNCiAgICBhbHBoYV9sYWJlbCA9IGZhY3RvcihwYXN0ZTAoYWxwaGFfdmFsICogMTAwLCAiJSIpLCBsZXZlbHMgPSBjKCI1JSIsICIxMCUiKSkNCiAgKQ0KDQpnZ3Bsb3Qocm9iX2FscGhhLCBhZXMoeCA9IGVuZCwgeSA9IHNoYXJlLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gYWxwaGFfbGFiZWwsIGxpbmV0eXBlID0gYWxwaGFfbGFiZWwpKSArDQogIGdlb21fbGluZShsaW5ld2lkdGggPSAwLjksIG5hLnJtID0gVFJVRSkgKw0KICBmYWNldF93cmFwKH5tZXRyaWMsIG5jb2wgPSAyKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCI1JSIgPSAiZ3JleTYwIiwgIjEwJSIgPSAiYmxhY2siKSwgbmFtZSA9IE5VTEwpICsNCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoIjUlIiA9ICJzb2xpZCIsICIxMCUiID0gInNvbGlkIiksIG5hbWUgPSBOVUxMKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsDQogICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IDAuMDIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksDQogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4wNSkpKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiU2hhcmUgb2YgYXNzZXRzICglKSIpICsNCiAgdGhlbWVfY3J5cHRvKCkNCmBgYA0KDQpDb25zaXN0ZW50IHdpdGggdXNpbmcgYSB0aWdodGVyIHRocmVzaG9sZCwgdGhlIGxldmVsIG9mIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSBhbmQgRmluYW5jaWFsIEZyYWdpbGl0eSBkZWNyZWFzZSwgeWV0IHRoZSBkeW5hbWljcyBvZiBib3RoIGluZGljZXMgZG8gbm90IHN1YnN0YW50aWFsbHkgY2hhbmdlLg0KDQojIyMgQWx0ZXJuYXRpdmUgRXh0cmVtZS1TaG9jayBUaHJlc2hvbGRzDQoNCldlIHJlcG9ydCByZXN1bHRzIGZvciAkcSBcaW4gXHsyLjVcJSwgNy41XCUsIDEwXCVcfSQgYWdhaW5zdCB0aGUgYmFzZWxpbmUgJHEgPSA1XCUkLg0KDQpgYGB7ciBmaWctcm9iLXRocmVzaG9sZCwgZmlnLmNhcD0iKipGaWd1cmUgNyDigJQgUm9idXN0bmVzcyB0byBBbHRlcm5hdGl2ZSBTeXN0ZW1hdGljIFNob2NrIFRocmVzaG9sZHMuKiogVGhlIGdyZXkgYXJlYSBzcGFucyB0aGUgbWluaW11bSBhbmQgbWF4aW11bSBzaGFyZXMgYWNyb3NzICRxIFxcaW4gXFx7Mi41XFwlLCA3LjVcXCUsIDEwXFwlXFx9JDsgdGhlIHNvbGlkIGxpbmUgcmVwb3J0cyB0aGUgYmFzZWxpbmUgJHEgPSA1XFwlJC4iLCBmaWcuaGVpZ2h0PTZ9DQpyb2JfdGhyIDwtIGFycm93OjpyZWFkX3BhcnF1ZXQoc3AkbW9kZWxzJHJvYnVzdF90aHJlc2hvbGQpICU+JQ0KICBtdXRhdGUoZW5kID0gYXMuRGF0ZShlbmQpKSAlPiUNCiAgZ3JvdXBfYnkoZW5kLCBxX3RocmVzaG9sZCkgJT4lDQogIHN1bW1hcmlzZShmaSA9IG1lYW4oY29udCwgbmEucm09VFJVRSksIGZmID0gbWVhbihzcGVjLCBuYS5ybT1UUlVFKSwgLmdyb3Vwcz0iZHJvcCIpICU+JQ0KICBwaXZvdF9sb25nZXIoYyhmaSwgZmYpLCBuYW1lc190byA9ICJtZXRyaWMiLCB2YWx1ZXNfdG8gPSAic2hhcmUiKSAlPiUNCiAgbXV0YXRlKG1ldHJpYyA9IGZhY3RvcihyZWNvZGUobWV0cmljLA0KICAgIGZpID0gIkZpbmFuY2lhbCBJbnN0YWJpbGl0eSIsIGZmID0gIkZpbmFuY2lhbCBGcmFnaWxpdHkiKSwNCiAgICBsZXZlbHMgPSBjKCJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiLCAiRmluYW5jaWFsIEZyYWdpbGl0eSIpKSkNCg0KYmFuZF90aHIgPC0gcm9iX3RociAlPiUNCiAgZ3JvdXBfYnkoZW5kLCBtZXRyaWMpICU+JQ0KICBzdW1tYXJpc2UobG8gPSBtaW4oc2hhcmUpLCBoaSA9IG1heChzaGFyZSksIC5ncm91cHMgPSAiZHJvcCIpDQpiYXNlX3RociA8LSByb2JfdGhyICU+JSBmaWx0ZXIoYWJzKHFfdGhyZXNob2xkIC0gMC4wNSkgPCAxZS05KQ0KDQpnZ3Bsb3QoYmFuZF90aHIsIGFlcyh4ID0gZW5kKSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGxvLCB5bWF4ID0gaGkpLCBmaWxsID0gImdyZXk3MCIsIGFscGhhID0gMC41KSArDQogIGdlb21fbGluZShkYXRhID0gYmFzZV90aHIsIGFlcyh5ID0gc2hhcmUpLCBjb2xvciA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuOSkgKw0KICBmYWNldF93cmFwKH5tZXRyaWMsIG5jb2wgPSAyKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsDQogICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IDAuMDIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksDQogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4wNSkpKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiU2hhcmUgb2YgYXNzZXRzICglKSIpICsNCiAgdGhlbWVfY3J5cHRvKCkNCmBgYA0KDQpUaGVzZSBhbHRlcm5hdGl2ZSBzcGVjaWZpY2F0aW9ucyBjb25maXJtIHRoYXQgdGhlIGNvbnN0cnVjdGlvbiBvZiBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgYW5kIEZpbmFuY2lhbCBGcmFnaWxpdHkgaXMgbm90IGRlcGVuZGVudCBvbiB0aGUgZGVmaW5pdGlvbiBvZiBleHRyZW1lIHN5c3RlbWF0aWMgc2hvY2sgZHVtbWllcy4NCg0KIyMgU2VsZWN0aW9uIGluIHRoZSBBc3NldCBVbml2ZXJzZSB7I3NlbGVjdGlvbi1iaWFzfQ0KDQpBIHBvdGVudGlhbCBjb25jZXJuIGlzIHRoYXQgbGFyZ2UtY2FwIGFzc2V0cyBtYXkgYmUgc3RydWN0dXJhbGx5IG1vcmUgc3RhYmxlIHRoYW4gc21hbGxlciB0b2tlbnMgKEFtaWh1ZCwgMjAwMiksIHNvIHRoYXQgcmVzdHJpY3RpbmcgdGhlIHNhbXBsZSB0byBhc3NldHMgZXZlciByYW5rZWQgaW4gdGhlIHRvcCA1MCBjb3VsZCB1bmRlcnN0YXRlIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSBhbmQgRnJhZ2lsaXR5IGluIHRoZSBicm9hZGVyIGNyeXB0byB1bml2ZXJzZS4gVG8gYXNzZXNzIHRoaXMsIHdlIHJlcGxpY2F0ZSB0aGUgcm9sbGluZyBlc3RpbWF0aW9uIG9uIGFuIGluZGVwZW5kZW50IHNhbXBsZSBvZiAqKjE1MCB0b2tlbnMqKiBsaXN0ZWQgb24gQ29pbk1hcmtldENhcCBiZWZvcmUgSmFudWFyeSAyMDE5IGJ1dCBhYnNlbnQgZnJvbSB0aGUgYmFzZWxpbmUgdW5pdmVyc2UuDQoNCmBgYHtyIGV4dGVuZGVkLXVuaXZlcnNlLWNvZGUsIGV2YWw9RkFMU0V9DQojIOKUgOKUgCBFeHRlbmRlZCB1bml2ZXJzZSBlc3RpbWF0aW9uIChldmFsPUZBTFNFIOKAlCBydW4gb25jZSB2aWEgc3JjL3RtcF9leHRlbmRlZF91bml2ZXJzZS5SKQ0KIyBEb3dubG9hZHMgMTUwIHRva2VucyB2aWEgY3J5cHRvMiAoQ29pbk1hcmtldENhcCwgbm8gQVBJIGtleSBuZWVkZWQpLg0KIyBPdXRwdXQ6IG91dHB1dC9tb2RlbHMvcm9sbF9leHRlbmRlZF9nYXJjaF9zaG9ja19leHQucGFycXVldA0KIyAgICAgICAgIG91dHB1dC9maWd1cmVzL2dhcmNoX3Nob2NrX2V4dC9yb2J1c3RuZXNzL3NlbGVjdGlvbl9iaWFzX2V4dGVuZGVkLnBkZg0Kc291cmNlKCJzcmMvdG1wX2V4dGVuZGVkX3VuaXZlcnNlLlIiKQ0KYGBgDQoNCmBgYHtyIHRhYi1zZWxlY3Rpb24tYmlhc30NCiMg4pSA4pSAIFNlbGVjdGlvbiBiaWFzIHN1bW1hcnkgdGFibGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSADQpyb2xsX2V4dCA8LSBhcnJvdzo6cmVhZF9wYXJxdWV0KA0KICAib3V0cHV0L21vZGVscy9yb2xsX2V4dGVuZGVkX2dhcmNoX3Nob2NrX2V4dC5wYXJxdWV0Ig0KKSAlPiUgbXV0YXRlKGVuZCA9IGFzLkRhdGUoZW5kKSkNCg0KZXh0X3NoYXJlcyA8LSByb2xsX2V4dCAlPiUNCiAgZ3JvdXBfYnkoZW5kKSAlPiUNCiAgc3VtbWFyaXNlKGZpID0gbWVhbihjb250LCBuYS5ybT1UUlVFKSoxMDAsDQogICAgICAgICAgICBmZiA9IG1lYW4oc3BlYywgbmEucm09VFJVRSkqMTAwLCAuZ3JvdXBzPSJkcm9wIikNCg0KZGF0YS5mcmFtZSgNCiAgSW5kZXggICA9IHJlcChjKCJGaW5hbmNpYWwgSW5zdGFiaWxpdHkiLCJGaW5hbmNpYWwgRnJhZ2lsaXR5IiksIDIpLA0KICBVbml2ZXJzZSA9IGMocmVwKCJCYXNlbGluZSAodG9wLTUwLCBOPTEzNykiLCAyKSwgcmVwKCJFeHRlbmRlZCAoc21hbGxlciB0b2tlbnMsIE7iiYgxNDYpIiwgMikpLA0KICBNZWFuICAgID0gYyhyb3VuZChtZWFuKHNoYXJlcyRmaSksMSksIHJvdW5kKG1lYW4oc2hhcmVzJGZmKSwxKSwNCiAgICAgICAgICAgICAgcm91bmQobWVhbihleHRfc2hhcmVzJGZpKSwxKSwgcm91bmQobWVhbihleHRfc2hhcmVzJGZmKSwxKSksDQogIFNEICAgICAgPSBjKHJvdW5kKHNkKHNoYXJlcyRmaSksMSksICAgcm91bmQoc2Qoc2hhcmVzJGZmKSwxKSwNCiAgICAgICAgICAgICAgcm91bmQoc2QoZXh0X3NoYXJlcyRmaSksMSksIHJvdW5kKHNkKGV4dF9zaGFyZXMkZmYpLDEpKSwNCiAgTWluICAgICA9IGMocm91bmQobWluKHNoYXJlcyRmaSksMSksICByb3VuZChtaW4oc2hhcmVzJGZmKSwxKSwNCiAgICAgICAgICAgICAgcm91bmQobWluKGV4dF9zaGFyZXMkZmkpLDEpLCByb3VuZChtaW4oZXh0X3NoYXJlcyRmZiksMSkpLA0KICBNYXggICAgID0gYyhyb3VuZChtYXgoc2hhcmVzJGZpKSwxKSwgIHJvdW5kKG1heChzaGFyZXMkZmYpLDEpLA0KICAgICAgICAgICAgICByb3VuZChtYXgoZXh0X3NoYXJlcyRmaSksMSksIHJvdW5kKG1heChleHRfc2hhcmVzJGZmKSwxKSkNCikgJT4lDQogIGFycmFuZ2UoSW5kZXgsIFVuaXZlcnNlKSAlPiUNCiAga2FibGUoY2FwdGlvbiA9ICIqKlRhYmxlIDIg4oCUIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSBhbmQgRnJhZ2lsaXR5OiBCYXNlbGluZSB2cy4gRXh0ZW5kZWQgVW5pdmVyc2UqKiIsDQogICAgICAgIGNvbC5uYW1lcyA9IGMoIkluZGV4IiwiVW5pdmVyc2UiLCJNZWFuICglKSIsIlN0ZC4gRGV2LiIsIk1pbiIsIk1heCIpLA0KICAgICAgICBhbGlnbiA9IGMoImwiLCJsIiwiciIsInIiLCJyIiwiciIpKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJob3ZlciIsImNvbmRlbnNlZCIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwgZm9udF9zaXplID0gMTMpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIlRpbWUtc2VyaWVzIHN0YXRpc3RpY3MgY29tcHV0ZWQgb3ZlciByb2xsaW5nIGVzdGltYXRpb24gd2luZG93cy4gRXh0ZW5kZWQgdW5pdmVyc2U6IDE1MCB0b2tlbnMgbGlzdGVkIGJlZm9yZSBKYW51YXJ5IDIwMTkgYW5kIGFic2VudCBmcm9tIHRoZSBiYXNlbGluZSBzYW1wbGUsIGRvd25sb2FkZWQgdmlhIENvaW5NYXJrZXRDYXAgKGNyeXB0bzIgcGFja2FnZSkuIikNCmBgYA0KDQpUaGUgKipGaW5hbmNpYWwgSW5zdGFiaWxpdHkgaW5kZXggaXMgcm9idXN0Kio6IHRoZSBhdmVyYWdlIHNoYXJlIG9mIDkuNyUgaW4gdGhlIGV4dGVuZGVkIHVuaXZlcnNlIGlzIG5lYXJseSBpZGVudGljYWwgdG8gdGhlIGJhc2VsaW5lIDEwLjElLCBhbmQgdGhlIGVwaXNvZGljIGR5bmFtaWNzIGFyZSBwcmVzZXJ2ZWQuIFRoZSBGaW5hbmNpYWwgRnJhZ2lsaXR5IHNoYXJlIGlzIHN5c3RlbWF0aWNhbGx5IGhpZ2hlciBhbW9uZyBzbWFsbGVyIHRva2VucyAoMjIuMCUgdmVyc3VzIDE1LjglKSwgcmVmbGVjdGluZyB0aGVpciBncmVhdGVyIHN1c2NlcHRpYmlsaXR5IHRvIHNwZWN1bGF0aXZlIGFtcGxpZmljYXRpb24gZHVyaW5nIGJvb20gcGhhc2VzIOKAlCBhIGdlbnVpbmUgY29tcG9zaXRpb25hbCBmZWF0dXJlIHJhdGhlciB0aGFuIGEgZG93bndhcmQgYmlhcyBpbiB0aGUgYmFzZWxpbmUuDQoNCmBgYHtyIGZpZy1zZWxlY3Rpb24tZXh0ZW5kZWQsIGZpZy5jYXA9IioqRmlndXJlIDgg4oCUIFNlbGVjdGlvbiBCaWFzOiBFeHRlbmRlZCBVbml2ZXJzZS4qKiBGSSBhbmQgRkYgc2hhcmVzIGZvciB0aGUgYmFzZWxpbmUgdG9wLTUwIHVuaXZlcnNlIChibGFjayBzb2xpZCkgYW5kIHRoZSBleHRlbmRlZCBzYW1wbGUgb2YgMTUwIHNtYWxsZXIgdG9rZW5zIChyZWQgZGFzaGVkKS4gVGhlIGV4dGVuZGVkIGVzdGltYXRpb24gdXNlcyB0aGUgc2FtZSByb2xsaW5nIFFSIHNwZWNpZmljYXRpb24gYW5kIEdBUkNILXN0YW5kYXJkaXNlZCBzaG9jay4iLCBmaWcuaGVpZ2h0PTZ9DQpiaW5kX3Jvd3MoDQogIHNoYXJlcyAgICAgJT4lIHNlbGVjdChlbmQsIGZpLCBmZikgJT4lIG11dGF0ZShncm91cCA9ICJUb3AtNTAgdW5pdmVyc2UgKGJhc2VsaW5lKSIpLA0KICBleHRfc2hhcmVzICU+JSBzZWxlY3QoZW5kLCBmaSwgZmYpICU+JSBtdXRhdGUoZ3JvdXAgPSAiRXh0ZW5kZWQgdW5pdmVyc2UgKHNtYWxsZXIgdG9rZW5zKSIpDQopICU+JQ0KICBwaXZvdF9sb25nZXIoYyhmaSwgZmYpLCBuYW1lc190byA9ICJtZXRyaWMiLCB2YWx1ZXNfdG8gPSAic2hhcmUiKSAlPiUNCiAgbXV0YXRlKA0KICAgIG1ldHJpYyA9IGZhY3RvcihyZWNvZGUobWV0cmljLA0KICAgICAgZmkgPSAiRmluYW5jaWFsIEluc3RhYmlsaXR5IiwgZmYgPSAiRmluYW5jaWFsIEZyYWdpbGl0eSIpLA0KICAgICAgbGV2ZWxzID0gYygiRmluYW5jaWFsIEluc3RhYmlsaXR5IiwgIkZpbmFuY2lhbCBGcmFnaWxpdHkiKSksDQogICAgZ3JvdXAgID0gZmFjdG9yKGdyb3VwLCBsZXZlbHMgPSBjKCJUb3AtNTAgdW5pdmVyc2UgKGJhc2VsaW5lKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFeHRlbmRlZCB1bml2ZXJzZSAoc21hbGxlciB0b2tlbnMpIikpDQogICkgJT4lDQogIGdncGxvdChhZXMoeCA9IGVuZCwgeSA9IHNoYXJlIC8gMTAwLCBjb2xvciA9IGdyb3VwLCBsaW5ldHlwZSA9IGdyb3VwKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMC44NSwgbmEucm0gPSBUUlVFKSArDQogIGZhY2V0X3dyYXAofm1ldHJpYywgbmNvbCA9IDIpICsNCiAgc2NhbGVfY29sb3JfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoIlRvcC01MCB1bml2ZXJzZSAoYmFzZWxpbmUpIiA9ICJibGFjayIsDQogICAgICAgICAgICAgICAiRXh0ZW5kZWQgdW5pdmVyc2UgKHNtYWxsZXIgdG9rZW5zKSIgPSAiI2Q2MjcyOCIpLA0KICAgIG5hbWUgPSBOVUxMKSArDQogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKCJUb3AtNTAgdW5pdmVyc2UgKGJhc2VsaW5lKSIgPSAic29saWQiLA0KICAgICAgICAgICAgICAgIkV4dGVuZGVkIHVuaXZlcnNlIChzbWFsbGVyIHRva2VucykiID0gImRhc2hlZCIpLA0KICAgIG5hbWUgPSBOVUxMKSArDQogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsDQogICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IDAuMDIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksDQogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4wNSkpKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiU2hhcmUgb2YgYXNzZXRzICglKSIpICsNCiAgdGhlbWVfY3J5cHRvKCkNCmBgYA0KDQojIyBFbmRvZ2VuZWl0eSBvZiBGYWN0b3IgQ29uc3RpdHVlbnRzIHsjZW5kb2dlbmVpdHl9DQoNClRoZSBzeXN0ZW1hdGljIHNob2NrICRmXipfdCQgaXMgZXh0cmFjdGVkIGZyb20gYSBERk0gZXN0aW1hdGVkIG9uIHNldmVuIGJlbmNobWFyayBhc3NldHMuIEJlY2F1c2UgdGhlc2Ugc2V2ZW4gYXNzZXRzIGNvbnRyaWJ1dGUgZGlyZWN0bHkgdG8gdGhlIGNvbnN0cnVjdGlvbiBvZiB0aGUgc2hvY2ssIHRoZWlyIGVzdGltYXRlZCBxdWFudGlsZSBiZXRhcyBtYXkgYmUgbWVjaGFuaWNhbGx5IGluZmxhdGVkLiBUbyBhc3Nlc3MgdGhpcywgd2UgcmVjb21wdXRlIHRoZSBzaGFyZXMgYWZ0ZXIgKipleGNsdWRpbmcgdGhlIHNldmVuIGZhY3RvciBjb25zdGl0dWVudHMqKiBmcm9tIHRoZSBjbGFzc2lmaWNhdGlvbi4gTm8gcmUtZXN0aW1hdGlvbiBpcyByZXF1aXJlZDogd2Ugc2ltcGx5IGV4Y2x1ZGUgQlRDLCBFVEgsIFhSUCwgQk5CLCBBREEsIFRSWCwgYW5kIERPR0Ugd2hlbiBhZ2dyZWdhdGluZyB0aGUgc2hhcmVzLg0KDQpgYGB7ciBiYXNrZXQtcm9idXN0bmVzcy1jb2RlLCBldmFsPUZBTFNFfQ0KIyDilIDilIAgRmFjdG9yIGNvbnN0aXR1ZW50IGV4Y2x1c2lvbiAoZXZhbD1GQUxTRSDigJQgcnVuIG9uY2UgdmlhIHNyYy90bXBfc2VsZWN0aW9uX2JpYXNfYmFza2V0LlIpDQojIE91dHB1dDogb3V0cHV0L2ZpZ3VyZXMvZ2FyY2hfc2hvY2tfZXh0L3JvYnVzdG5lc3Mvc2VsZWN0aW9uX2JpYXMucGRmDQpzb3VyY2UoInNyYy90bXBfc2VsZWN0aW9uX2JpYXNfYmFza2V0LlIiKQ0KYGBgDQoNCmBgYHtyIGZpZy1iYXNrZXQsIGZpZy5jYXA9IioqRmlndXJlIDkg4oCUIEVzdGltYXRpb25zIGV4Y2x1ZGluZyBzeXN0ZW1hdGljIGZhY3RvciBjb25zdGl0dWVudHMuKiogRkkgYW5kIEZGIHNoYXJlcyBhZnRlciBleGNsdWRpbmcgdGhlIHNldmVuIGZhY3RvciBjb25zdGl0dWVudHMgZnJvbSB0aGUgY2xhc3NpZmljYXRpb24gc2FtcGxlIChkYXNoZWQgbGluZSksIGFsb25nc2lkZSB0aGUgYmFzZWxpbmUgc2hhcmVzIHRoYXQgaW5jbHVkZSBhbGwgYXNzZXRzIChzb2xpZCBsaW5lKS4iLCBmaWcuaGVpZ2h0PTZ9DQpCQVNLRVQgPC0gYygiQlRDIiwgIkVUSCIsICJYUlAiLCAiQk5CIiwgIkFEQSIsICJUUlgiLCAiRE9HRSIpDQoNCnJlc3RyX3NoYXJlcyA8LSByb2xsICU+JQ0KICBmaWx0ZXIoISh2YXJpYWJsZSAlaW4lIEJBU0tFVCkpICU+JQ0KICBncm91cF9ieShlbmQpICU+JQ0KICBzdW1tYXJpc2UoZmkgPSBtZWFuKGNvbnQsIG5hLnJtPVRSVUUpKjEwMCwNCiAgICAgICAgICAgIGZmID0gbWVhbihzcGVjLCBuYS5ybT1UUlVFKSoxMDAsIC5ncm91cHM9ImRyb3AiKQ0KDQpiaW5kX3Jvd3MoDQogIHNoYXJlcyAgICAgICAlPiUgc2VsZWN0KGVuZCwgZmksIGZmKSAlPiUgbXV0YXRlKGdyb3VwID0gIkJhc2VsaW5lIiksDQogIHJlc3RyX3NoYXJlcyAlPiUgc2VsZWN0KGVuZCwgZmksIGZmKSAlPiUgbXV0YXRlKGdyb3VwID0gIkV4Y2wuIGZhY3RvciBjb25zdGl0dWVudHMiKQ0KKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKGMoZmksIGZmKSwgbmFtZXNfdG8gPSAibWV0cmljIiwgdmFsdWVzX3RvID0gInNoYXJlIikgJT4lDQogIG11dGF0ZSgNCiAgICBtZXRyaWMgPSBmYWN0b3IocmVjb2RlKG1ldHJpYywNCiAgICAgIGZpID0gIkZpbmFuY2lhbCBJbnN0YWJpbGl0eSIsIGZmID0gIkZpbmFuY2lhbCBGcmFnaWxpdHkiKSwNCiAgICAgIGxldmVscyA9IGMoIkZpbmFuY2lhbCBJbnN0YWJpbGl0eSIsICJGaW5hbmNpYWwgRnJhZ2lsaXR5IikpLA0KICAgIGdyb3VwICA9IGZhY3Rvcihncm91cCwgbGV2ZWxzID0gYygiQmFzZWxpbmUiLCAiRXhjbC4gZmFjdG9yIGNvbnN0aXR1ZW50cyIpKQ0KICApICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBlbmQsIHkgPSBzaGFyZSAvIDEwMCwgY29sb3IgPSBncm91cCwgbGluZXR5cGUgPSBncm91cCkpICsNCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDAuODUsIG5hLnJtID0gVFJVRSkgKw0KICBmYWNldF93cmFwKH5tZXRyaWMsIG5jb2wgPSAyKSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKCJCYXNlbGluZSIgPSAiYmxhY2siLCAiRXhjbC4gZmFjdG9yIGNvbnN0aXR1ZW50cyIgPSAiI2Q2MjcyOCIpLA0KICAgIG5hbWUgPSBOVUxMKSArDQogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKCJCYXNlbGluZSIgPSAic29saWQiLCAiRXhjbC4gZmFjdG9yIGNvbnN0aXR1ZW50cyIgPSAiZGFzaGVkIiksDQogICAgbmFtZSA9IE5VTEwpICsNCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIiwNCiAgICAgICAgICAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gMC4wMikpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwNCiAgICAgICAgICAgICAgICAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwLjA1KSkpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9ICJTaGFyZSBvZiBhc3NldHMgKCUpIikgKw0KICB0aGVtZV9jcnlwdG8oKQ0KYGBgDQoNClRoZSByZXN1bHRzIGNvbmZpcm0gdGhhdCB0aGUgKipmYWN0b3IgY29uc3RpdHVlbnRzIGRvIG5vdCBzdWJzdGFudGlhbGx5IGRyaXZlIHRoZSBjbGFzc2lmaWNhdGlvbioqOiB0aGUgRkkgYW5kIEZGIHNoYXJlcyBhcmUgbmVhcmx5IGlkZW50aWNhbCB3aGV0aGVyIG9yIG5vdCB0aGUgc2V2ZW4gYmFza2V0IHRva2VucyBhcmUgaW5jbHVkZWQgaW4gdGhlIGFnZ3JlZ2F0aW9uLg0KDQotLS0NCg0KIyBDb25jbHVzaW9uIHsjY29uY2x1c2lvbn0NCg0KVGhpcyBwYXBlciBwcm9wb3NlcyBhIGZvcm1hbCwgYmVuY2htYXJrLWluZGVwZW5kZW50IG1lYXN1cmUgb2YgZmluYW5jaWFsIGluc3RhYmlsaXR5IGZvciBjcnlwdG8tYXNzZXQgbWFya2V0cy4gQXBwbHlpbmcgdGhlIHF1YW50aWxlIHJlZ3Jlc3Npb24gZnJhbWV3b3JrIG9mIEJhdXIgJiBTY2h1bHplICgyMDA5KSB0byAxMzcgY3J5cHRvLWFzc2V0cyBpbiAxOC1tb250aCByb2xsaW5nIHdpbmRvd3MsIHdlIGNvbnN0cnVjdCB0aW1lLXZhcnlpbmcgaW5kaWNlcyBvZiBGaW5hbmNpYWwgSW5zdGFiaWxpdHkgYW5kIEZpbmFuY2lhbCBGcmFnaWxpdHkgdGhhdCBjbGFzc2lmeSBlYWNoIGFzc2V0IGFjY29yZGluZyB0byB3aGV0aGVyIGl0cyBzZW5zaXRpdml0eSB0byBhIEdBUkNILXN0YW5kYXJkaXNlZCBzeXN0ZW1hdGljIHNob2NrIGluY3JlYXNlcyBpbiB0aGUgbGVmdCBvciByaWdodCB0YWlsIG9mIGl0cyByZXR1cm4gZGlzdHJpYnV0aW9uLiBPdmVyIDIwMTnigJMyMDI2LCBhcHByb3hpbWF0ZWx5ICoqMTAlIG9mIGNyeXB0by1hc3NldHMgZXhoaWJpdCBGaW5hbmNpYWwgSW5zdGFiaWxpdHkqKiBhbmQgKioxNiUgZXhoaWJpdCBGaW5hbmNpYWwgRnJhZ2lsaXR5Kiogb24gYXZlcmFnZS4gRmluYW5jaWFsIEluc3RhYmlsaXR5IGlzIGVwaXNvZGljLCBjb25jZW50cmF0aW5nIGFyb3VuZCB0aGUgMjAyMiBDcnlwdG8tV2ludGVyIGFuZCB0aGUgU1ZCIGVwaXNvZGUsIHdoaWxlIEZpbmFuY2lhbCBGcmFnaWxpdHkgaXMgbW9yZSBwZXJzaXN0ZW50IGFuZCBwZWFrcyBkdXJpbmcgdGhlIDIwMjEgYnVsbCBtYXJrZXQg4oCUIGEgc2VxdWVuY2luZyBjb25zaXN0ZW50IHdpdGggdGhlIE1pbnNreSBoeXBvdGhlc2lzIHRoYXQgcHJvbG9uZ2VkIGV4cGFuc2lvbnMgYWNjdW11bGF0ZSBmaW5hbmNpYWwgZnJhZ2lsaXRpZXMgdGhhdCBzdWJzZXF1ZW50bHkgdW53aW5kLiBBIGNvbXBhcmlzb24gd2l0aCAxNDMgaW5kaXZpZHVhbCBlcXVpdHkgc3RvY2tzIGNvbmZpcm1zIHRoYXQgY3J5cHRvIG1hcmtldHMgYXJlIHN0cnVjdHVyYWxseSBtb3JlIHVuc3RhYmxlIGFuZCBmcmFnaWxlIHRoYW4gZXF1aXR5IG1hcmtldHMsIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiB0aGUgQ292aWQtMTkgZXBpc29kZS4gQSBwcmVkaWN0aXZlIHBvcnRmb2xpbyBleGVyY2lzZSBmdXJ0aGVyIHZhbGlkYXRlcyB0aGUgY2xhc3NpZmljYXRpb246IGFzc2V0cyBzYXRpc2Z5aW5nIGZpbmFuY2lhbCBzdGFiaWxpdHkgY29uZGl0aW9ucyBnZW5lcmF0ZSBoaWdoZXIgY3VtdWxhdGl2ZSByZXR1cm5zIG92ZXIgdGhlIGZ1bGwgc2FtcGxlIHRoYW4gYXNzZXRzIGV4aGliaXRpbmcgdGFpbCBhbXBsaWZpY2F0aW9uIGluIGVpdGhlciBkaXJlY3Rpb24uDQoNClNldmVyYWwgbGltaXRhdGlvbnMgd2FycmFudCBhY2tub3dsZWRnZW1lbnQuIFRoZSByb2xsaW5nIHdpbmRvdyBkZXNpZ24gaW50cm9kdWNlcyBhIGRldGVjdGlvbiBsYWcgb2YgYXBwcm94aW1hdGVseSBoYWxmIGEgd2luZG93IGxlbmd0aC4gVGhlIHN5c3RlbWF0aWMgc2hvY2sgaXMgY29uc3RydWN0ZWQgZnJvbSBhIGZpeGVkIHNldCBvZiBzZXZlbiBiZW5jaG1hcmsgYXNzZXRzOyB3aGlsZSB0aGUgcm9idXN0bmVzcyBhbmFseXNpcyBjb25maXJtcyB0aGF0IGV4Y2x1ZGluZyB0aGVzZSBjb25zdGl0dWVudHMgZG9lcyBub3QgYWx0ZXIgdGhlIGFnZ3JlZ2F0ZSBpbmRpY2VzLCBhbHRlcm5hdGl2ZSBmYWN0b3Igc3BlY2lmaWNhdGlvbnMgcmVtYWluIHRvIGJlIGV4cGxvcmVkLiBUaGUgbWluaW11bS1jb3ZlcmFnZSBmaWx0ZXIgbWF5IGFsc28gZXhjbHVkZSByZWNlbnRseSBsaXN0ZWQgdG9rZW5zIGR1cmluZyB0aGUgcGVyaW9kcyB3aGVuIHRoZXkgYXJlIG1vc3QgYWN0aXZlbHkgdHJhZGVkLg0KDQpTZXZlcmFsIGRpcmVjdGlvbnMgZm9yIGZ1dHVyZSByZXNlYXJjaCBmb2xsb3cgbmF0dXJhbGx5LiBGaXJzdCwgdGhlIHJvbGxpbmcgRmluYW5jaWFsIEluc3RhYmlsaXR5IGluZGV4IGNvdWxkIGJlIGludGVncmF0ZWQgaW50byBhIG1hY3JvcHJ1ZGVudGlhbCBtb25pdG9yaW5nIGZyYW1ld29yayBhbG9uZ3NpZGUgb24tY2hhaW4gbWV0cmljcyBhbmQgc3RhYmxlY29pbiBmbG93cy4gU2Vjb25kLCB0aGUgYXNzZXQtbGV2ZWwgY2xhc3NpZmljYXRpb24gb3BlbnMgdGhlIGRvb3IgdG8gY3Jvc3Mtc2VjdGlvbmFsIGFuYWx5c2VzIGV4YW1pbmluZyB3aGV0aGVyIEZpbmFuY2lhbCBJbnN0YWJpbGl0eSBpcyBwcmVkaWN0ZWQgYnkgdG9rZW4tc3BlY2lmaWMgY2hhcmFjdGVyaXN0aWNzIHN1Y2ggYXMgbWFya2V0IGRlcHRoLCBleGNoYW5nZSBjb25jZW50cmF0aW9uLCBvciBzbWFydC1jb250cmFjdCBleHBvc3VyZS4gVGhpcmQsIHRoZSBmcmFtZXdvcmsgY291bGQgYmUgZXh0ZW5kZWQgdG8gZGVjZW50cmFsaXNlZCBmaW5hbmNlIChEZUZpKSBwcm90b2NvbHMgYW5kIHN0YWJsZWNvaW5zLiBGaW5hbGx5LCB0aGUgZG9jdW1lbnRlZCBkaXZlcmdlbmNlIGJldHdlZW4gRmluYW5jaWFsIEluc3RhYmlsaXR5IGFuZCBGcmFnaWxpdHkg4oCUIG9uZSBlcGlzb2RpYyBhbmQgY3Jpc2lzLWRyaXZlbiwgdGhlIG90aGVyIHBlcnNpc3RlbnQgYW5kIGJvb20tZHJpdmVuIOKAlCByYWlzZXMgcXVlc3Rpb25zIGFib3V0IHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZSB0d28gZGltZW5zaW9ucyBvdmVyIHRoZSBmdWxsIGJvb20tYnVzdCBjeWNsZSB0aGF0IGEgc3RydWN0dXJhbCBtb2RlbCB3b3VsZCBiZSB3ZWxsIHBvc2l0aW9uZWQgdG8gYWRkcmVzcy4NCg0KLS0tDQoNCiMgQXBwZW5kaXggey51bm51bWJlcmVkfQ0KDQojIyBTdW1tYXJ5IFN0YXRpc3RpY3Mgey51bm51bWJlcmVkfQ0KDQoqKFNlZSBUYWJsZSAxIGluIFNlY3Rpb24gMi4xLikqDQoNCiMjIENyeXB0by1GYWN0b3IgYW5kIFN5c3RlbWF0aWMgU2hvY2tzIHsudW5udW1iZXJlZH0NCg0KKihTZWUgRmlndXJlcyBBMSBhbmQgQTIgaW4gU2VjdGlvbiAyLjIuKSoNCg0KIyMgRXF1aXR5IEluZGljZXMgey51bm51bWJlcmVkfQ0KDQpgYGB7ciB0YWItaW5kaWNlc30NCmRhdGEuZnJhbWUoDQogIFRpY2tlciA9IGMoIl5JTlgiLCJeR1NQVFNFIiwiXkNPTENBUCIsIl5TUENMWElHUEEiLCJeQlZTUCIsIl5NWFgiLCJeU1BCTFBHUFQiLCJeSUJHIiwNCiAgICAgICAgICAgICAiXkdEQVgiLCJeRkNISSIsIl5GVFNFIiwiXkZUTUlCIiwiXlNTTUkiLCJeQUVYIiwiXk9NWFMzMCIsIl5PTVhIUEkiLA0KICAgICAgICAgICAgICJeT01YQ0JQSSIsIl5ERk1HSSIsIl5JUlRTIiwiXklCRVgiLCJeQVRYIiwiXkJGWCIsIl5XSUciLCJeQkVUSSIsIl5QWCIsDQogICAgICAgICAgICAgIl5PQlhQIiwiXklTRVEiLCJeUFNJMjAiLCJeVFJYRkxESUxQIiwNCiAgICAgICAgICAgICAiXkpQWE5LNDAwIiwiXlNTRUMiLCJeSFNJIiwiXktTMTEiLCJeQlNFU04iLCJeTlo1MEMiLCJeWFUxMDAiLCJeQVhKTyIsDQogICAgICAgICAgICAgIl5TVEkiLCJeS0xTRSIsIl5TRVQxMDAiLCJeSktTRSIsIl5WTkkiLCJeUFNJIiwNCiAgICAgICAgICAgICAiXlRBU0kiLCJeSkFMU0giLCJeRUdYMzAiLCJeTkdTRUlOREVYIiwiLmRNSUJEMDAwMDBQIiksDQogIEluZGV4ID0gYygiUyZQIDUwMCAoVVNBKSIsIlMmUC9UU1ggQ29tcG9zaXRlIChDYW5hZGEpIiwiTVNDSSBDT0xDQVAgKENvbG9tYmlhKSIsDQogICAgICAgICAgICAiUyZQL0NMWCBJR1BBIChDaGlsZSkiLCJCb3Zlc3BhIChCcmF6aWwpIiwiSVBDIChNZXhpY28pIiwNCiAgICAgICAgICAgICJTJlAvQlZMIEdlbmVyYWwgKFBlcnUpIiwiUyZQL0JZTUEgKEFyZ2VudGluYSkiLA0KICAgICAgICAgICAgIkRBWCAoR2VybWFueSkiLCJDQUMgNDAgKEZyYW5jZSkiLCJGVFNFIDEwMCAoVUspIiwiRlRTRSBNSUIgKEl0YWx5KSIsDQogICAgICAgICAgICAiU01JIChTd2l0emVybGFuZCkiLCJBRVggKE5ldGhlcmxhbmRzKSIsIk9NWCBTdG9ja2hvbG0gMzAgKFN3ZWRlbikiLA0KICAgICAgICAgICAgIk9NWCBIZWxzaW5raSAoRmlubGFuZCkiLCJPTVggQ29wZW5oYWdlbiAoRGVubWFyaykiLCJEdWJhaSBGaW4uIE1hcmtldCAoVUFFKSIsDQogICAgICAgICAgICAiUlRTIEluZGV4IChSdXNzaWEpIiwiSUJFWCAzNSAoU3BhaW4pIiwiQVRYIChBdXN0cmlhKSIsIkJFTCAyMCAoQmVsZ2l1bSkiLA0KICAgICAgICAgICAgIldhcnNhdyBHZW5lcmFsIChQb2xhbmQpIiwiQkVUIChSb21hbmlhKSIsIlBYIFByYWd1ZSAoQ3plY2ggUmVwLikiLA0KICAgICAgICAgICAgIk9zbG8gT0JYIChOb3J3YXkpIiwiSVNFUSBBbGwgU2hhcmUgKElyZWxhbmQpIiwiUFNJLTIwIChQb3J0dWdhbCkiLCJGVFNFIElzcmFlbCIsDQogICAgICAgICAgICAiSlBYLU5pa2tlaSA0MDAgKEphcGFuKSIsIlNoYW5naGFpIENvbXBvc2l0ZSAoQ2hpbmEpIiwiSGFuZyBTZW5nIChIb25nIEtvbmcpIiwNCiAgICAgICAgICAgICJLT1NQSSAoU291dGggS29yZWEpIiwiQlNFIFNlbnNleCAoSW5kaWEpIiwiUyZQL05aWCA1MCAoTmV3IFplYWxhbmQpIiwNCiAgICAgICAgICAgICJCSVNUIDEwMCAoVHVya2V5KSIsIlMmUC9BU1ggMjAwIChBdXN0cmFsaWEpIiwiU3RyYWl0cyBUaW1lcyAoU2luZ2Fwb3JlKSIsDQogICAgICAgICAgICAiRlRTRSBCdXJzYSBLTENJIChNYWxheXNpYSkiLCJTRVQgMTAwIChUaGFpbGFuZCkiLCJJRFggQ29tcG9zaXRlIChJbmRvbmVzaWEpIiwNCiAgICAgICAgICAgICJIbyBDaGkgTWluaCAoVmlldG5hbSkiLCJQU0VpIChQaGlsaXBwaW5lcykiLA0KICAgICAgICAgICAgIlRhZGF3dWwgQWxsIFNoYXJlIChTYXVkaSBBcmFiaWEpIiwiRlRTRS9KU0UgQWxsIFNoYXJlIChTb3V0aCBBZnJpY2EpIiwNCiAgICAgICAgICAgICJFR1ggMzAgKEVneXB0KSIsIk5pZ2VyaWEgQWxsIFNoYXJlIiwiTVNDSSBCYW5nbGFkZXNoIikNCikgJT4lDQogIGthYmxlKGNhcHRpb24gPSAiKipUYWJsZSBBMSDigJQgRXF1aXR5IFByaWNlIEluZGljZXMgVXNlZCB0byBDb25zdHJ1Y3QgdGhlIEdsb2JhbCBFcXVpdHkgRmFjdG9yKioiLA0KICAgICAgICBjb2wubmFtZXMgPSBjKCJUaWNrZXIiLCJJbmRleCIpKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCJob3ZlciIsImNvbmRlbnNlZCIpLA0KICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwgZm9udF9zaXplID0gMTIpICU+JQ0KICBmb290bm90ZShnZW5lcmFsID0gIlRoZSBmaXJzdCBwcmluY2lwYWwgY29tcG9uZW50IG9mIHRoZXNlIDQ5IGRhaWx5IHByaWNlIGluZGV4IHJldHVybnMgaXMgdXNlZCBhcyB0aGUgZ2xvYmFsIGVxdWl0eSBmYWN0b3IuIFJ1c3NpYSAoXklSVFMpIGlzIGluY2x1ZGVkIG92ZXIgdGhlIGZ1bGwgc2FtcGxlOyBvYnNlcnZhdGlvbnMgYWZ0ZXIgdHJhZGluZyBzdXNwZW5zaW9uIGFyZSBleGNsdWRlZC4iKQ0KYGBgDQoNCiMjIEVxdWl0eSBTdG9ja3Mgey51bm51bWJlcmVkfQ0KDQpgYGB7ciB0YWItc3RvY2tzfQ0Kc3RvY2tzX3RibCA8LSBkYXRhLmZyYW1lKA0KICBSZWdpb24gICA9IGMocmVwKCJOb3J0aCBBbWVyaWNhIiwxKSwgcmVwKCJFdXJvcGUiLDkpLCByZXAoIkFzaWEtUGFjaWZpYyIsNSksICJUb3RhbCIpLA0KICBDb3VudHJ5ICA9IGMoIlVuaXRlZCBTdGF0ZXMiLCJVbml0ZWQgS2luZ2RvbSIsIkdlcm1hbnkiLCJGcmFuY2UiLCJOZXRoZXJsYW5kcyIsDQogICAgICAgICAgICAgICAiSXRhbHkiLCJTcGFpbiIsIlN3aXR6ZXJsYW5kIiwiU3dlZGVuIiwiRGVubWFyayIsDQogICAgICAgICAgICAgICAiSmFwYW4iLCJIb25nIEtvbmciLCJDaGluYSAoVVMtbGlzdGVkKSIsIkF1c3RyYWxpYSIsIkluZGlhIiwiIiksDQogIEV4Y2hhbmdlID0gYygiTllTRS9OQVNEQVEiLCJMU0UiLCJYRVRSQSIsIkV1cm9uZXh0IFBhcmlzIiwiRXVyb25leHQgQW1zdGVyZGFtIiwNCiAgICAgICAgICAgICAgICJCb3JzYSBJdGFsaWFuYSIsIkJNRSIsIlNJWCIsIk5hc2RhcSBTdG9ja2hvbG0iLCJOYXNkYXEgQ29wZW5oYWdlbiIsDQogICAgICAgICAgICAgICAiVFNFIiwiSEtFWCIsIk5ZU0UvTkFTREFRIiwiQVNYIiwiTlNFIiwiIiksDQogIE4gICAgICAgID0gYyg2MCwxMCwxMCwxMCw1LDUsNCw0LDQsMiwxMCw1LDMsNyw0LDE0MykNCikNCg0Kc3RvY2tzX3RibCAlPiUNCiAga2FibGUoY2FwdGlvbiA9ICIqKlRhYmxlIEEyIOKAlCBJbmRpdmlkdWFsIEVxdWl0eSBTdG9ja3M6IENvbXBvc2l0aW9uIGJ5IENvdW50cnkqKiIsDQogICAgICAgIGNvbC5uYW1lcyA9IGMoIlJlZ2lvbiIsIkNvdW50cnkiLCJFeGNoYW5nZSIsIk4iKSwNCiAgICAgICAgYWxpZ24gPSBjKCJsIiwibCIsImwiLCJyIikpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsImhvdmVyIiwiY29uZGVuc2VkIiksDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFLCBmb250X3NpemUgPSAxMikgJT4lDQogIHJvd19zcGVjKG5yb3coc3RvY2tzX3RibCksIGJvbGQgPSBUUlVFKSAlPiUNCiAgY29sbGFwc2Vfcm93cyhjb2x1bW5zID0gMSwgdmFsaWduID0gIm1pZGRsZSIpDQpgYGANCg0KLS0tDQoNCiMjIFNlc3Npb24gSW5mb3JtYXRpb24gey51bm51bWJlcmVkfQ0KDQpgYGB7ciBzZXNzaW9uLWluZm8sIGNsYXNzLnNvdXJjZT0nZm9sZC1oaWRlJ30NCnNlc3Npb25JbmZvKCkNCmBgYA0KDQotLS0NCg0KKkZsb3JpYW4gS3JhdXMg4oCUIFVuaXZlcnNpdHkgb2YgQm9yZGVhdXggKEJTRSkg4oCUIGZsb3JpYW4ua3JhdXNAdS1ib3JkZWF1eC5mcioNCipDb21waWxlZCB3aXRoIFIgYHIgcGFzdGUoUi52ZXJzaW9uJG1ham9yLCBSLnZlcnNpb24kbWlub3IsIHNlcD0iLiIpYCBhbmQga25pdHIgYHIgcGFja2FnZVZlcnNpb24oImtuaXRyIilgLioNCg==