This R Markdown-notebook contains the final annotated analysis code for the manuscript: “Overall bias and sample sizes were unchanged in ICU trials over time: a meta-epidemiological study” by Carl Thomas Anthon, Anders Granholm, Jon Henrik Laake, Anders Perner and Morten Hylander Møller.

The annotated analysis code was written by Anders Granholm according to the pre-published protocol and statistical analysis plain (doi: 10.1111/aas.13258). For further details, please see the full article and its supplementary files, which also includes the CSV-file containing the final dataset and a data dictionary.

For correspondence related to the manuscript, contact the corresponding author Carl Thomas Anthon. Questions directly related to the analysis code can also be sent to Anders Granholm.

Figures displayed in this document are scaled differently than in the final paper and supplement.

1. Setup

Load the packages/functions required for the analyses.

library(tidyverse) # Load the Tidyverse packages, used for data processing and visualisation.
plot_grid <- cowplot::plot_grid # Load this function from the cowplot package; only this function will be used from this package, and the entire library will not be loaded as this is unnecessary and cowplot overrides the default ggplot2 theme, which then has to be reset.

Import the file containing data for all the included trials.

Note: This code block uses RStudio’s API to allow manual selection of the final dataset. This requires the script to be run in a recent version of RStudio; otherwise this has to be manually replaced with the appropriate file path.

included_trials <- read_csv(rstudioapi::selectFile(filter = "CSV files (*.csv)"), col_types = cols(trial_year = col_integer(), sample_size = col_integer()))

Define the output directory where all results will be saved.

Note: This block uses RStudio’s API to allow manual selection of the directory. This requires the script to be run in a recent version of RStudio; otherwise this has to be manually replaced with the appropriate path.

output_path <- rstudioapi::selectDirectory()

Define plot theme and image settings for saving images, to allow easy changing later.

# File settings
img_dpi <- 600 # DPI - not used for vectorized formats, e.g. PDFs, but argument is kept if this is changed.
img_format <- "pdf" # File format
# Widths and heights (in millimeters) for single run chart plots
img_width <- 150
img_height <- 80
# Widths and heights (in millimeters) for the triple run chart plots
img_width_triple <- 150
img_height_triple <- 150
# Width and height (in millimeters) for the risk of bias overview plot
img_width_bias <- 200
img_height_bias <- 80

# Set ggplot2 theme
theme_set(theme_linedraw())

2. Data inspection and preparation

2.1 Helper function

The following helper function filters a dataset so only years with a certain number of trials are included, and optionally prints the excluded years. Arguments:

  • .dta: the dataset to filter.
  • minimum: the minimum number of required trials per year, default is 5.
  • verbose: if TRUE (default), the years with too few trials are printed.
filter_years <- function(.dta, minimum = 5, verbose = TRUE){
  years <- .dta %>% 
    group_by(trial_year) %>% 
    summarise(n = n()) %>% 
    filter(n < minimum) %>% 
    pull(trial_year)
  
  if (verbose){
    print(str_glue("The following years contain less than {minimum} trials and have beeen filtered from this dataset: {str_c(years, collapse = ', ')}."))
  }
  
  .dta %>% 
    filter(!(trial_year %in% years))
}

2.2 Risk of bias

Create overall_risk_of_bias variable and convert all risk of bias domains to factors.

included_trials <- included_trials %>% 
  mutate(overall_risk_of_bias = case_when(is.na(random_sequence_generation) | is.na(allocation_concealment) | is.na(blinding_of_participants_and_personnel) | is.na(blinding_of_outcome_assessment) | is.na(incomplete_outcome_data) | is.na(selective_reporting) | is.na(other_sources_of_bias) ~ NA_character_, # If any risk of bias domain is missing, the overall risk of bias will be missing
                                          random_sequence_generation == "Low" & allocation_concealment == "Low" & blinding_of_participants_and_personnel == "Low" & blinding_of_outcome_assessment == "Low" & incomplete_outcome_data == "Low" & selective_reporting == "Low" & other_sources_of_bias == "Low" ~ "Low", # If all domains are low risk, the overall risk of bias will be low as well
                                          TRUE ~ "High" # If none of the above criteria apply, the overall risk of bias will be high
         )) %>% 
  mutate_at(vars(random_sequence_generation:overall_risk_of_bias), ~factor(., levels = c("Low", "Unclear", "High")))

Assess how many trials have missing data for the overall risk of bias domain (which will be missing if any of the other domains are missing) and create dataset that only includes trials with available risk of bias ratings.

included_trials %>% 
  filter(is.na(overall_risk_of_bias)) %>% 
  str_glue_data("In total, {nrow(.)} trials have missing data for one or more risk of bias domains and will be excluded from these analyses.")
In total, 2 trials have missing data for one or more risk of bias domains and will be excluded from these analyses.
trials_bias_available <- included_trials %>% 
  filter(!is.na(overall_risk_of_bias))

Create dataset that only contains trials from years with at least 5 trials with available risk of bias ratings (for the primary analyses).

trials_bias_available_5plus <- filter_years(trials_bias_available)
The following years contain less than 5 trials and have beeen filtered from this dataset: 1977, 1978, 1981, 1982, 1983, 1984, 1986, 2017, 2018.

For all trials with available risk of bias, calculate overall distributions for each domain.

trials_bias_available %>% 
  gather(key = "bias_domain", value = "rating", random_sequence_generation:overall_risk_of_bias, factor_key = TRUE) %>% 
  select(bias_domain, rating) %>% 
  group_by(bias_domain) %>% 
  summarise(low = sum(rating == "Low") / n() * 100,
            unclear = sum(rating == "Unclear") / n() * 100,
            high = sum(rating == "High") / n() * 100) %>% 
  mutate_if(is.numeric, ~paste0(round(., 1), "%"))

Create plot visualising distributions of risk of bias for each domain (only include trials where risk of bias ratings are available).

trials_bias_available %>% 
  gather(key = "bias_domain", value = "rating", random_sequence_generation:overall_risk_of_bias, factor_key = TRUE) %>% 
  select(bias_domain, rating) %>%
  mutate(rating = factor(rating, levels = c("High", "Unclear", "Low")),
         bias_domain = fct_rev(bias_domain)) %>%  # Reverse the order to ensure proper printing in the table
  ggplot(aes(x = bias_domain, fill = rating)) + # Create the plot
  geom_bar(position = "fill", width = 0.95) +
  coord_flip() +
  labs(x = NULL, y = NULL) +
  scale_fill_manual(values = c("#C00000", "#E0E000", "#00C000"), name = "Risk of bias rating:", guide = guide_legend(reverse = TRUE)) +
  scale_y_continuous(expand = c(0, 0), breaks = 0.1 * 0:10, minor_breaks = 0.05 * 0:20, labels = paste0(10 * 0:10, "%")) +
  scale_x_discrete(expand = c(0, 0), labels = rev(c( # Use rev() to ensure that order matches the domains above
    "Random sequence generation",
    "Allocation concealment",
    "Blinding of participants and personnel",
    "Blinding of outcome assessment",
    "Incomplete outcome data",
    "Selective reporting",
    "Other sources of bias",
    "Overall risk of bias"
  ))) +
  theme(plot.margin = margin (t = 5, l = 10, r = 15, b = 5, unit = "pt"), legend.position = "bottom") # Fix plot margins to ensure all labels are printed and change legend

ggsave(paste0(output_path, "/Risk of bias overview.", img_format), width = img_width_bias, height = img_height_bias, dpi = img_dpi, units = "mm") # Save file

2.3 Sample sizes

Assess how many trials have missing data for sample size and create dataset that only includes trials with available sample sizes.

included_trials %>% 
  filter(is.na(sample_size)) %>% 
  str_glue_data("In total, {nrow(.)} trials have missing data for sample sizes and will be excluded from these analyses.")
In total, 2 trials have missing data for sample sizes and will be excluded from these analyses.
trials_size_available <- included_trials %>% 
  filter(!is.na(sample_size))

Create dataset that only contains trials from years with at least 5 trials with available sample sizes (for the primary analyses).

trials_size_available_5plus <- filter_years(trials_size_available)
The following years contain less than 5 trials and have beeen filtered from this dataset: 1977, 1978, 1981, 1982, 1983, 1984, 1986, 2017, 2018.

For all trials with available sample sizes, calculate the overall distribution.

round(summary(trials_size_available$sample_size), 1)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    3.0    42.0    82.5   224.0   181.2  7000.0 

3. Define run chart functions

Define the function that will produce the run charts and associated statistics.

This contains two helper functions, run_chart_stat and run_chart_caption which should only be called from the main function, run_chart, and not directly.

The run_chart function has the following arguments:

The function returns an annotated plot.

An additional, simplified helper function is present, triple_bias_run_chart, with the following arguments:

# Function that calculates the run chart statistics using the "val" column in the aggregated dataset from the main function that has already been sorted by year.
# This function should not be called directly
run_chart_stat <- function(val, fixed_median = NULL){
  n_total <- length(val)
  if (n_total < 1){
    stop("ERROR: run_chart_stat: number of observations (years) < 1.")
  }
  if (!(is.null(fixed_median) | is.numeric(fixed_median))) {
    stop("ERROR: run_chart_stat: fixed_median must be either NULL or a numeric value.")
  }
  med <- ifelse(is.null(fixed_median), median(val), fixed_median)
  n_useful <- sum(!near(val, med))
  
  run_longest <- 0
  run_current <- 0
  pos <- NA
  cross_n <- NA
  
  for (i in 1:n_total) {
    cur <- val[i]
    if (!near(cur, med)) {
      
      if (is.na(pos)){ # Will be true for the first value that is not equal to the median (and only once)
        pos <- !(cur > med) # Sets current position as the opposite of what it is, to start new run
        cross_n <- -1 # The first run will not count as a crossing
      }
      
      if ((cur > med ) == pos) { # If the current value is on the same side as the last one
        run_current <- run_current + 1
      } else { # If the current value is on the opposite side as the last one
        if (run_current > run_longest) {
          run_longest <- run_current
        }
        
        run_current <- 1
        cross_n <- cross_n +1
        pos <- cur > med
      }
      
    }
  }
  if (run_current > run_longest) {
    run_longest <- run_current
  }
  
  # Return results (upper and lower prediction limits calculated according to Anhøj's rules)
  list(n_total = n_total, n_useful = n_useful, median = med,
       run_UPL = round(log2(n_useful) + 3), run_longest = run_longest,
       cross_LPL = qbinom(0.05, n_useful - 1, 0.5), cross_n = cross_n, fixed_median = !is.null(fixed_median))
}

# Function that formats the caption used in each run chart
# This function should not be called directly
run_chart_caption <- function(res, percentage = NULL, dec = 1){
  res$base <- paste0(res$n_total, " observations (", res$n_useful, " useful). ", ifelse(res$fixed_median, "Fixed median: ", "Median: "), format(res$median, digits = dec, nsmall = dec), percentage, ". Longest run:")
  res$long <- paste0("[max. ", res$run_UPL, "].")
  res$cross <- paste0("[min. ", res$cross_LPL, "].")
  
  if (res$run_longest > res$run_UPL & res$cross_n < res$cross_LPL){
    # Both results are significant (non-random variation)
    res <- map(res, as.character)
    cap <- substitute(base~bold(run_longest)~long~"Crossings:"~bold(cross_n)~cross, res)
  } else if (res$run_longest > res$run_UPL) {
    # Only the longest run is significant (non-random variation)
    res <- map(res, as.character)
    cap <- substitute(base~bold(run_longest)~long~"Crossings:"~cross_n~cross, res)
  } else if (res$cross_n < res$cross_LPL) {
    # Only the number of crossings is significant (non-random variation)
    res <- map(res, as.character)
    cap <- substitute(base~run_longest~long~"Crossings:"~bold(cross_n)~cross, res)
  } else {
    # No significance (only random variation)
    res <- map(res, as.character)
    cap <- substitute(base~run_longest~long~"Crossings:"~cross_n~cross, res)
  }
  # Return caption
  cap
}

# The main function - see description above
run_chart <- function(.dta, variable, category = NULL, title = NULL, delete_titles = TRUE, fixed_median = NULL, num_agg_mean = FALSE){
  # Quote variable name and get the type of it
  var <- enquo(variable)
  var_pull <- pull(.dta, !!var)
  type <- case_when(is.factor(var_pull) ~ "factor",
                    is.integer(var_pull) ~ "integer",
                    TRUE ~ "other")
  
  # Input checks
  if (type == "factor") {
    if (is.null(category)) {
      stop("ERROR: run_chart: 'variable' is a factor (risk of bias domain?) and 'category' is NULL. 'category' must be either 'Low', 'Unclear' or 'High'.", call. = FALSE)
    } else if (!(category %in% c("Low", "Unclear", "High"))){
      stop(paste0("ERROR: run_chart: 'variable' is a factor (risk of bias domain?), 'category' is '", category, "', but must be either 'Low', 'Unclear' or 'High'."), call. = FALSE)
    }
  } else if (type == "integer") {
    if (!is.null(category)){
      warning(paste0("WARNING: run_chart: 'variable' is an integer (sample size?). 'category' is '", category, "' and will NOT be used."), call. = FALSE)
    }
  } else {
    stop(paste0("ERROR: run_chart: 'variable' must be either a factor (risk of bias category) or an integer (sample size), '", quo_name(var), "' is neither."))
  }
  
  # Remove missing data
  n_miss <- .dta %>% 
    filter(is.na(trial_year) | is.na(!!var)) %>% 
    nrow()
  if (n_miss > 0) {
    warning(paste0("WARNING: run_chart: ", n_miss, " rows with missing data in either trial_year or ", quo_name(var), " removed from the dataset prior to analyses."))
    .dta <- .dta %>% 
      filter(!is.na(trial_year) & !is.na(!!var))
  }
  
  # If delete_titles == TRUE, then set title to null
  if (delete_titles){
    title <- NULL
  }
  
  # Aggregate data
  if (type == "factor") {
    agg <- .dta %>% 
      group_by(trial_year) %>% 
      summarise(val = sum(!!var == category) / n() * 100) %>% 
      arrange(trial_year)
  } else if (type == "integer") {
    if (!num_agg_mean){
      agg <- .dta %>% 
        group_by(trial_year) %>% 
        summarise(val = median(!!var),
                  y_high = quantile(!!var, 0.75),
                  y_low = quantile(!!var, 0.25)) %>%
        arrange(trial_year)      
    } else if (num_agg_mean) {
      agg <- .dta %>% 
        group_by(trial_year) %>% 
        summarise(val = mean(!!var),
                  se_val = sd(!!var) / sqrt(n()),
                  y_high = val + 1.96 * se_val,
                  y_low_tmp = val - 1.96 * se_val,
                  y_low = ifelse(y_low_tmp < 0, 0, y_low_tmp)) %>%  # 95% confidence intervals (CIs) below 0 are impossible
        arrange(trial_year)
    }

  }
  
  # Calculate stats
  stats <- agg %>%
    pull(val) %>% 
    run_chart_stat(fixed_median = fixed_median)
  
  # General plot aspects
  gg <- ggplot(data = agg, aes(x = trial_year, y = val)) +
    labs(caption = run_chart_caption(stats, if_else(type == "factor", "%", "")), x = NULL, y = NULL, subtitle = title) + # The title argument provided is used for a ggplot2 subtitle, due to the default smaller font size
    theme(plot.caption = element_text(hjust = 0.5)) + # Align caption in the middle
    scale_x_continuous(limits = c(1975, 2020), breaks = 1975 + 5 * 0:8, minor_breaks = 1975:2020, expand = c(0, 0))
  
  # Add different aspects for risk of bias domains and sample sizes
  if (type == "factor") {
    # Risk of bias domains - different y-axis for overall risk of bias plots and subdomains
    if (quo_name(var) == "overall_risk_of_bias") {
      gg <- gg +
        scale_y_continuous(limits = c(0, 50), breaks = 10 * 0:5, minor_breaks = 5 * 0:10, labels = paste0(10 * 0:5, "%"), expand = c(0.015, 0))
    } else {
      gg <- gg +
        scale_y_continuous(limits = c(0, 100), breaks = 20 * 0:5, minor_breaks = 5 * 0:20, labels = paste0(20 * 0:5, "%"), expand = c(0.015, 0))
    }
  } else if (type == "integer") {
    # Sample sizes - different y-axis according to aggregation function
    gg <- gg +
      scale_y_continuous(breaks = 100 * 0:15, minor_breaks = 25 * 0:60, expand = c(0, 0)) + # Axis long enough for both types of plots - different limits for median/mean values are set in next line
      coord_cartesian(ylim = c(0, ifelse(!num_agg_mean, 600, 1400))) + # Limits are set here to avoid outliers for 95% CIs of yearly means to be removed
      geom_ribbon(aes(ymin = y_low, ymax = y_high), fill = "#B5B5B5", alpha = 0.80) # Add grey shaded area
  }
  
  # Add points and lines
  gg <- gg + geom_point(size = 2) +
    geom_line() +
    geom_hline(yintercept = stats$median, size = 1.25)
  
  # Return plot
  gg
}

# Simple helper function that creates a combined plot with all 3 risk of bias ratings
triple_bias_run_chart <- function(.dta, variable, title_add = NULL){
  variable <- enquo(variable)
  title_base <- str_replace_all(str_to_title(quo_name(variable)), "_", " ")
  plot_grid(
    run_chart(.dta, !!variable, category = "Low", title = paste0(title_base, title_add)) + ylab("Low"),
    run_chart(.dta, !!variable, category = "Unclear") + ylab("Unclear"),
    run_chart(.dta, !!variable, category = "High") + ylab("High"),
    nrow = 3, ncol = 1)
}

4. Primary analysis

For all primary analyses, only years with 5 or more trials are used.

Analysis 1.1: Percentage of overall low risk of bias trials per year

trials_bias_available_5plus %>% 
  run_chart(overall_risk_of_bias, "Low", title = "Overall low risk of bias")

ggsave(paste0(output_path, "/1.1 Primary analysis - overall low risk of bias.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 1.2: Annual median sample sizes

trials_size_available_5plus %>% 
  run_chart(sample_size, title = "Median (IQR) sample sizes")

ggsave(paste0(output_path, "/1.2 Primary analysis - sample sizes.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 1.2ph1: Post-hoc analysis of the annual mean sample sizes

trials_size_available_5plus %>% 
  run_chart(sample_size, title = "Mean (95% CI) sample sizes (post-hoc analysis)", num_agg_mean = TRUE)

ggsave(paste0(output_path, "/1.2ph1 Primary analysis - sample sizes, post-hoc analysis using mean values.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 1.3: Yearly proportion of low, unclear and high risk of bias ratings in each of the seven domains

# Random sequence generation
trials_bias_available_5plus %>%
  triple_bias_run_chart(random_sequence_generation)
ggsave(paste0(output_path, "/1.3A Primary analysis - Random sequence generation.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Allocation concealment
trials_bias_available_5plus %>%
  triple_bias_run_chart(allocation_concealment)
ggsave(paste0(output_path, "/1.3B Primary analysis - Allocation concealment.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of participants and personnel
trials_bias_available_5plus %>%
  triple_bias_run_chart(blinding_of_participants_and_personnel)
ggsave(paste0(output_path, "/1.3C Primary analysis - Blinding of participants and personnel.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of outcome assessment
trials_bias_available_5plus %>%
  triple_bias_run_chart(blinding_of_outcome_assessment)
ggsave(paste0(output_path, "/1.3D Primary analysis - Blinding of outcome assessment.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Incomplete outcome data
trials_bias_available_5plus %>%
  triple_bias_run_chart(incomplete_outcome_data)
ggsave(paste0(output_path, "/1.3E Primary analysis - Incomplete outcome data.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Selective reporting
trials_bias_available_5plus %>%
  triple_bias_run_chart(selective_reporting)
ggsave(paste0(output_path, "/1.3F Primary analysis - Selective reporting.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Other sources of bias
trials_bias_available_5plus %>%
  triple_bias_run_chart(other_sources_of_bias)
ggsave(paste0(output_path, "/1.3G Primary analysis - Other sources of bias.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")

5. Sensitivity analysis #1 - all trials from years with 5 or more trials, but separated according to type of intervention

As for the primary analyses, only years with 5 or more trials are used here.

Assess the distribution of intervention types.

included_trials %>% 
  group_by(review_intervention_category) %>% 
  summarise(n = n())

Rather few medical device and management trials are included. Thus, these analyses will contain few data points and should be interpreted with caution.

5.1 Sensitivity analysis #1A - drug trials

Create dataset for risk of bias analyses.

trials_bias_available_5plus_drug <- trials_bias_available %>% 
  filter(review_intervention_category == "Drug") %>% 
  filter_years()
The following years contain less than 5 trials and have beeen filtered from this dataset: 1977, 1978, 1981, 1982, 1983, 1984, 1986, 1988, 1989, 1996, 2017, 2018.
str_glue("In total {nrow(trials_bias_available_5plus_drug)} drug trials will be included in these sensitivity analyses of risk of bias.")
In total 302 drug trials will be included in these sensitivity analyses of risk of bias.

Create dataset for sample size analysis.

trials_size_available_5plus_drug <- trials_size_available %>% 
  filter(review_intervention_category == "Drug") %>% 
  filter_years()
The following years contain less than 5 trials and have beeen filtered from this dataset: 1977, 1978, 1981, 1982, 1983, 1984, 1986, 1988, 1989, 1996, 2017, 2018.
str_glue("In total {nrow(trials_size_available_5plus_drug)} drug trials will be included in this sensitivity analysis of sample sizes.")
In total 304 drug trials will be included in this sensitivity analysis of sample sizes.

Analysis 2A.1: Percentage of overall low risk of bias trials per year - drug trials

trials_bias_available_5plus_drug %>% 
  run_chart(overall_risk_of_bias, "Low", title = "Overall low risk of bias - drug RCTs")

ggsave(paste0(output_path, "/2A.1 Sensitivity analysis - overall low risk of bias - drug trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2A.2: Annual median sample sizes - drug trials

trials_size_available_5plus_drug %>% 
  run_chart(sample_size, title = "Median (IQR) sample sizes - drug RCTs")

ggsave(paste0(output_path, "/2A.2 Sensitivity analysis - sample sizes - drug trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2A.2ph1: Post-hoc: annual mean sample sizes - drug trials

trials_size_available_5plus_drug %>% 
  run_chart(sample_size, title = "Mean (95% CI) sample sizes - drug RCTs (post-hoc analysis)", num_agg_mean = TRUE)

ggsave(paste0(output_path, "/2A.2ph1 Sensitivity analysis - sample sizes - drug trials, post-hoc using means.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2A.3: Yearly proportion of low, unclear and high risk of bias ratings in each of the seven domains - drug trials

# Random sequence generation
trials_bias_available_5plus_drug %>%
  triple_bias_run_chart(random_sequence_generation, title_add = " - drug RCTs")
ggsave(paste0(output_path, "/2A.3A Sensitivity analysis - Random sequence generation - drug trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Allocation concealment
trials_bias_available_5plus_drug %>%
  triple_bias_run_chart(allocation_concealment, title_add = " - drug RCTs")
ggsave(paste0(output_path, "/2A.3B Sensitivity analysis - Allocation concealment - drug trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of participants and personnel
trials_bias_available_5plus_drug %>%
  triple_bias_run_chart(blinding_of_participants_and_personnel, title_add = " - drug RCTs")
ggsave(paste0(output_path, "/2A.3C Sensitivity analysis - Blinding of participants and personnel - drug trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of outcome assessment
trials_bias_available_5plus_drug %>%
  triple_bias_run_chart(blinding_of_outcome_assessment, title_add = " - drug RCTs")
ggsave(paste0(output_path, "/2A.3D Sensitivity analysis - Blinding of outcome assessment - drug trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Incomplete outcome data
trials_bias_available_5plus_drug %>%
  triple_bias_run_chart(incomplete_outcome_data, title_add = " - drug RCTs")
ggsave(paste0(output_path, "/2A.3E Sensitivity analysis - Incomplete outcome data - drug trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Selective reporting
trials_bias_available_5plus_drug %>%
  triple_bias_run_chart(selective_reporting, title_add = " - drug RCTs")
ggsave(paste0(output_path, "/2A.3F Sensitivity analysis - Selective reporting - drug trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Other sources of bias
trials_bias_available_5plus_drug %>%
  triple_bias_run_chart(other_sources_of_bias, title_add = " - drug RCTs")
ggsave(paste0(output_path, "/2A.3G Sensitivity analysis - Other sources of bias - drug trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")

NOTE: The analysis of high risk of bias for allocation allocation concealment indicates non-variation, however the median yearly proportion is 0% and thus the median cannot be crossed and the runs cannot be broken in the run chart; this analysis must be interpreted with caution.

5.2 Sensitivity analysis #1B - management trials

Create dataset for risk of bias analyses.

trials_bias_available_5plus_management <- trials_bias_available %>% 
  filter(review_intervention_category == "Management") %>% 
  filter_years()
The following years contain less than 5 trials and have beeen filtered from this dataset: 1981, 1982, 1987, 1988, 1989, 1990, 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2005, 2015, 2016.
str_glue("In total {nrow(trials_bias_available_5plus_management)} management trials will be included in these sensitivity analyses of risk of bias.")
In total 111 management trials will be included in these sensitivity analyses of risk of bias.

Create dataset for sample size analysis.

trials_size_available_5plus_management <- trials_size_available %>% 
  filter(review_intervention_category == "Management") %>% 
  filter_years()
The following years contain less than 5 trials and have beeen filtered from this dataset: 1981, 1982, 1987, 1988, 1989, 1990, 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2005, 2015, 2016.
str_glue("In total {nrow(trials_size_available_5plus_management)} management trials will be included in this sensitivity analysis of sample sizes.")
In total 110 management trials will be included in this sensitivity analysis of sample sizes.

Analysis 2B.1: Percentage of overall low risk of bias trials per year - management trials

trials_bias_available_5plus_management %>% 
  run_chart(overall_risk_of_bias, "Low", title = "Overall low risk of bias - management RCTs")

ggsave(paste0(output_path, "/2B.1 Sensitivity analysis - overall low risk of bias - management trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2B.2: Annual median sample sizes - management trials

trials_size_available_5plus_management %>% 
  run_chart(sample_size, title = "Median (IQR) sample sizes - management RCTs")

ggsave(paste0(output_path, "/2B.2 Sensitivity analysis - sample sizes - management trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2B.2ph1: Post-hoc: annual mean sample sizes - management trials

trials_size_available_5plus_management %>% 
  run_chart(sample_size, title = "Mean (95% CI) sample sizes - management RCTs (post-hoc analysis)", num_agg_mean = TRUE)

ggsave(paste0(output_path, "/2B.2ph1 Sensitivity analysis - sample sizes - management trials, post-hoc using means.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2B.3: Yearly proportion of low, unclear and high risk of bias ratings in each of the seven domains - management trials

# Random sequence generation
trials_bias_available_5plus_management %>%
  triple_bias_run_chart(random_sequence_generation, title_add = " - management RCTs")
ggsave(paste0(output_path, "/2B.3A Sensitivity analysis - Random sequence generation - management trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Allocation concealment
trials_bias_available_5plus_management %>%
  triple_bias_run_chart(allocation_concealment, title_add = " - management RCTs")
ggsave(paste0(output_path, "/2B.3B Sensitivity analysis - Allocation concealment - management trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of participants and personnel
trials_bias_available_5plus_management %>%
  triple_bias_run_chart(blinding_of_participants_and_personnel, title_add = " - management RCTs")
ggsave(paste0(output_path, "/2B.3C Sensitivity analysis - Blinding of participants and personnel - management trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of outcome assessment
trials_bias_available_5plus_management %>%
  triple_bias_run_chart(blinding_of_outcome_assessment, title_add = " - management RCTs")
ggsave(paste0(output_path, "/2B.3D Sensitivity analysis - Blinding of outcome assessment - management trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Incomplete outcome data
trials_bias_available_5plus_management %>%
  triple_bias_run_chart(incomplete_outcome_data, title_add = " - management RCTs")
ggsave(paste0(output_path, "/2B.3E Sensitivity analysis - Incomplete outcome data - management trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Selective reporting
trials_bias_available_5plus_management %>%
  triple_bias_run_chart(selective_reporting, title_add = " - management RCTs")
ggsave(paste0(output_path, "/2B.3F Sensitivity analysis - Selective reporting - management trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Other sources of bias
trials_bias_available_5plus_management %>%
  triple_bias_run_chart(other_sources_of_bias, title_add = " - management RCTs")
ggsave(paste0(output_path, "/2B.3G Sensitivity analysis - Other sources of bias - management trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")

5.3 Sensitivity analysis #1C - medical device trials

Create dataset for risk of bias analyses.

trials_bias_available_5plus_device <- trials_bias_available %>% 
  filter(review_intervention_category == "Device") %>% 
  filter_years()
The following years contain less than 5 trials and have beeen filtered from this dataset: 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2003, 2007, 2008, 2010, 2015, 2016, 2017.
str_glue("In total {nrow(trials_bias_available_5plus_device)} medical device trials will be included in these sensitivity analyses of risk of bias.")
In total 77 medical device trials will be included in these sensitivity analyses of risk of bias.

Create dataset for sample size analysis.

trials_size_available_5plus_device <- trials_size_available %>% 
  filter(review_intervention_category == "Device") %>% 
  filter_years()
The following years contain less than 5 trials and have beeen filtered from this dataset: 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2003, 2007, 2008, 2010, 2015, 2016, 2017.
str_glue("In total {nrow(trials_size_available_5plus_device)} medical device trials will be included in this sensitivity analysis of sample sizes.")
In total 77 medical device trials will be included in this sensitivity analysis of sample sizes.

Analysis 2C.1: Percentage of overall low risk of bias trials per year - medical device trials

trials_bias_available_5plus_device %>% 
  run_chart(overall_risk_of_bias, "Low", title = "Overall low risk of bias - medical device RCTs")

ggsave(paste0(output_path, "/2C.1 Sensitivity analysis - overall low risk of bias - medical device trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2C.2: Annual median sample sizes - medical device trials

trials_size_available_5plus_device %>% 
  run_chart(sample_size, title = "Median (IQR) sample sizes - medical device RCTs")

ggsave(paste0(output_path, "/2C.2 Sensitivity analysis - sample sizes - medical device trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2C.2ph1: Post-hoc: annual mean sample sizes - medical device trials

trials_size_available_5plus_device %>% 
  run_chart(sample_size, title = "Mean (95% CI) sample sizes - medical device RCTs (post-hoc analysis)", num_agg_mean = TRUE)

ggsave(paste0(output_path, "/2C.2ph1 Sensitivity analysis - sample sizes - medical device trials, post-hoc using means.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 2C.3: Yearly proportion of low, unclear and high risk of bias ratings in each of the seven domains - medical device trials

# Random sequence generation
trials_bias_available_5plus_device %>%
  triple_bias_run_chart(random_sequence_generation, title_add = " - medical device RCTs")
ggsave(paste0(output_path, "/2C.3A Sensitivity analysis - Random sequence generation - medical device trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Allocation concealment
trials_bias_available_5plus_device %>%
  triple_bias_run_chart(allocation_concealment, title_add = "- medical device RCTs")
ggsave(paste0(output_path, "/2C.3B Sensitivity analysis - Allocation concealment - medical device trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of participants and personnel
trials_bias_available_5plus_device %>%
  triple_bias_run_chart(blinding_of_participants_and_personnel, title_add = " - medical device RCTs")
ggsave(paste0(output_path, "/2C.3C Sensitivity analysis - Blinding of participants and personnel - medical device trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of outcome assessment
trials_bias_available_5plus_device %>%
  triple_bias_run_chart(blinding_of_outcome_assessment, title_add = " - medical device RCTs")
ggsave(paste0(output_path, "/2C.3D Sensitivity analysis - Blinding of outcome assessment - medical device trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Incomplete outcome data
trials_bias_available_5plus_device %>%
  triple_bias_run_chart(incomplete_outcome_data, title_add = " - medical device RCTs")
ggsave(paste0(output_path, "/2C.3E Sensitivity analysis - Incomplete outcome data - medical device trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Selective reporting
trials_bias_available_5plus_device %>%
  triple_bias_run_chart(selective_reporting, title_add = " - medical device RCTs")
ggsave(paste0(output_path, "/2C.3F Sensitivity analysis - Selective reporting - medical device trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Other sources of bias
trials_bias_available_5plus_device %>%
  triple_bias_run_chart(other_sources_of_bias, title_add = " - medical device RCTs")
ggsave(paste0(output_path, "/2C.3G Sensitivity analysis - Other sources of bias - medical device trials.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")

6. Sensitivity analysis #2 - all trials

For these sensitivity analyses, all trials will be included, including trials from years with < 5 trials.

This makes the analyses - especially of the risk of bias domains - “fragile” and results should be interpreted with caution.

Analysis 3.1: Percentage of overall low risk of bias trials per year

trials_bias_available %>% 
  run_chart(overall_risk_of_bias, "Low", title = "Overall low risk of bias - all RCTs") +
  scale_y_continuous(limits = c(0, 100), breaks = 10 * 0:10, minor_breaks = 5 * 0:20, labels = paste0(10 * 0:10, "%"), expand = c(0.015, 0))
Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing scale.
ggsave(paste0(output_path, "/3.1 Sensitivity analysis - overall low risk of bias - all trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

NOTE: The y-axis goes from 0-100% in this plot, unlike the other plots of overall low risk of bias (0-50%) due to larger differences in yearly proportions caused by 1 single trial with overall low risk of bias in 2018.

These results indicate non-random variation, however, the median yearly proportion is 0%. Thus no values below the median are possible, and no crossings are possible in the run chart and runs cnanot be broken. This result should be interpreted with caution.

Analysis 3.2: Annual median sample sizes

trials_size_available %>% 
  run_chart(sample_size, title = "Median (IQR) sample sizes - all RCTs")

ggsave(paste0(output_path, "/3.2 Sensitivity analysis - sample sizes - all trials.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Analysis 3.2ph1: Annual mean sample sizes

trials_size_available %>% 
  run_chart(sample_size, title = "Mean (95% CI) sample sizes - all RCTs (post-hoc analysis)", num_agg_mean = TRUE)

ggsave(paste0(output_path, "/3.2ph1 Sensitivity analysis - sample sizes - all trials, post-hoc using mean values.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Note: for years with only 1 trial, the grey ribbon is missing as a confidence interval cannot be calculated.

Analysis 3.3: Yearly proportion of low, unclear and high risk of bias ratings in each of the seven domains - all trials

# Random sequence generation
trials_bias_available %>%
  triple_bias_run_chart(random_sequence_generation, title_add = " - all RCTs")
ggsave(paste0(output_path, "/3.3A Sensitivity analysis - Random sequence generation.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Allocation concealment
trials_bias_available %>%
  triple_bias_run_chart(allocation_concealment, title_add = " - all RCTs")
ggsave(paste0(output_path, "/3.3B Sensitivity analysis - Allocation concealment.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of participants and personnel
trials_bias_available %>%
  triple_bias_run_chart(blinding_of_participants_and_personnel, title_add = " - all RCTs")
ggsave(paste0(output_path, "/3.3C Sensitivity analysis - Blinding of participants and personnel.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Blinding of outcome assessment
trials_bias_available %>%
  triple_bias_run_chart(blinding_of_outcome_assessment, title_add = " - all RCTs")
ggsave(paste0(output_path, "/3.3D Sensitivity analysis - Blinding of outcome assessment.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Incomplete outcome data
trials_bias_available %>%
  triple_bias_run_chart(incomplete_outcome_data, title_add = " - all RCTs")
ggsave(paste0(output_path, "/3.3E Sensitivity analysis - Incomplete outcome data.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Selective reporting
trials_bias_available %>%
  triple_bias_run_chart(selective_reporting, title_add = " - all RCTs")
ggsave(paste0(output_path, "/3.3F Sensitivity analysis - Selective reporting.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")


# Other sources of bias
trials_bias_available %>%
  triple_bias_run_chart(other_sources_of_bias, title_add = " - all RCTs")
ggsave(paste0(output_path, "/3.3G Sensitivity analysis - Other sources of bias.", img_format), width = img_width_triple, height = img_height_triple, dpi = img_dpi, units = "mm")

7. Overview of the number of included trials per year

Create a table of the number of included trials per year in each analysis (and in the full dataset).

# Simple helper function
n_years <- function(.dta){
  name <- quo_name(enquo(.dta))
  .dta %>%
    group_by(trial_year) %>% 
    summarise(!!name := n()) %>% 
    arrange(trial_year)
}

tbl <- n_years(included_trials) %>% # First row is the total number of trials included
  left_join(n_years(trials_bias_available_5plus)) %>% # Primary analysis - bias in >= 5 trials /year
  left_join(n_years(trials_size_available_5plus)) %>% # Primary analysis - size in >= 5 trials/year
  left_join(n_years(trials_bias_available_5plus_drug)) %>% # Sensitivity analysis #1A (drug trials) - bias in >= 5 trials/year
  left_join(n_years(trials_size_available_5plus_drug)) %>% # Sensitivity analysis #1A (drug trials) - size in >= 5 trials/year
  left_join(n_years(trials_bias_available_5plus_management)) %>% # Sensitivity analysis #1B (management trials) - bias in >= 5 trials/year
  left_join(n_years(trials_size_available_5plus_management)) %>% # Sensitivity analysis #1B (management trials) - size in >= 5 trials/year
  left_join(n_years(trials_bias_available_5plus_device)) %>% # Sensitivity analysis #1C (medical device trials) - bias in >= 5 trials/year
  left_join(n_years(trials_size_available_5plus_device)) %>% # Sensitivity analysis #1C (medical device trials) - size in >= 5 trials/year
  left_join(n_years(trials_bias_available)) %>% # Sensitivity analysis #2 - bias in all trials
  left_join(n_years(trials_size_available)) %>% # Sensitivity analysis #2 - size in all trials
  mutate_all(~{ifelse(is.na(.), 0, .)}) # Replace all NAs (missing) with 0

tbl_total <- tbl %>%
  summarise_all(sum) %>% 
  mutate(trial_year = "Total")

tbl %>% 
  mutate(trial_year = as.character(trial_year)) %>% # Convert to string to allow merging with the "Total" row
  bind_rows(tbl_total) %>% # Merge
  print() %>% # Print to RMarkdown document
  write_csv(paste0(output_path, "/trials_per_year_in_each_analysis.csv"))

8. Additional plots

Create two additional plots visualising the absolute numbers; these plots were not pre-planned, but added during the peer review process.

Absolute number of low and high overall risk of bias trials per year:

trials_bias_available %>% 
  group_by(trial_year) %>% 
  summarise(Low = sum(overall_risk_of_bias == "Low"),
            High = sum(overall_risk_of_bias == "High")) %>% 
  gather(key = "rob", value = "n", -trial_year) %>% 
  arrange(trial_year) %>% 
  mutate(rob = factor(rob, levels = c("Low", "High"))) %>% 
  ggplot(aes(x = trial_year, y = n, fill = rob)) +
  geom_col(position = "dodge") +
  scale_fill_manual(values = c("#00C000", "#C00000"), name = "Overall risk of bias:") +
  labs(x = NULL, y = "Number of RCTs") +
  scale_x_continuous(limits = c(1975, 2020), breaks = 1975 + 5 * 0:8, minor_breaks = 1975:2020, expand = c(0, 0)) +
  scale_y_continuous(limits = c(0, 50), breaks = 0:5 * 10, minor_breaks = 0:10 * 5, expand = c(0, 0)) + 
  theme(plot.margin = margin (t = 5, l = 10, r = 15, b = 5, unit = "pt"), legend.position = "bottom") # Fix plot margins to ensure all labels are printed and change legend position
ggsave(paste0(output_path, "/Additional plots - absolute number of trials by overall risk of bias per year.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

Absolute number of small and large trials per year:

Small trials are defined as trials including <= the median overall sample size participants per year; large trials are defined as trials including > the median overal sample size participants per year.

# Calculate median
med_sample_size <- trials_size_available %>%
  pull(sample_size) %>% 
  median()

# Categorise trials
trials_size_categorised <- trials_size_available %>% 
  mutate(size_cat = ifelse(sample_size <= med_sample_size, "Small", "Large"))
str_glue("The overall median sample size is {med_sample_size}.
         {sum(trials_size_categorised$size_cat == 'Small')} trials are small and {sum(trials_size_categorised$size_cat == 'Large')} trials are large.")
The overall median sample size is 82.5.
301 trials are small and 301 trials are large.
# Plot
trials_size_categorised %>% 
  group_by(trial_year) %>% 
  summarise(Small = sum(size_cat == "Small"),
            Large = sum(size_cat == "Large")) %>% 
  gather(key = "size", value = "n", -trial_year) %>% 
  arrange(trial_year) %>% 
  mutate(size = factor(size, levels = c("Small", "Large"))) %>% 
  ggplot(aes(x = trial_year, y = n, fill = size)) +
  geom_col(position = "dodge") +
  scale_fill_manual(values = c("#C00000", "#00C000"), name = "RCT sizes:") +
  labs(x = NULL, y = "Number of RCTs") +
  scale_x_continuous(limits = c(1975, 2020), breaks = 1975 + 5 * 0:8, minor_breaks = 1975:2020, expand = c(0, 0)) +
  scale_y_continuous(limits = c(0, 30), breaks = 0:6 * 5, expand = c(0, 0)) + 
  theme(plot.margin = margin (t = 5, l = 10, r = 15, b = 5, unit = "pt"), legend.position = "bottom") # Fix plot margins to ensure all labels are printed and change legend position


ggsave(paste0(output_path, "/Additional plots - absolute number of trials by overall size per year.", img_format), width = img_width, height = img_height, dpi = img_dpi, units = "mm")

9. Date and session info

Save the date and session info for when the script was run to the RMarkdown-HTML-file.

date()
[1] "Sat May 18 16:45:31 2019"
sessionInfo()
R version 3.5.3 (2019-03-11)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.4

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

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

other attached packages:
[1] forcats_0.4.0   stringr_1.4.0   dplyr_0.8.0.1   purrr_0.3.2     readr_1.3.1     tidyr_0.8.3     tibble_2.1.1    ggplot2_3.1.1  
[9] tidyverse_1.2.1

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.1       cellranger_1.1.0 pillar_1.3.1     compiler_3.5.3   plyr_1.8.4       tools_3.5.3      digest_0.6.18   
 [8] jsonlite_1.6     lubridate_1.7.4  nlme_3.1-139     gtable_0.3.0     lattice_0.20-38  pkgconfig_2.0.2  rlang_0.3.4     
[15] cli_1.1.0        rstudioapi_0.10  haven_2.1.0      xfun_0.6         withr_2.1.2      xml2_1.2.0       httr_1.4.0      
[22] knitr_1.22       generics_0.0.2   hms_0.4.2        cowplot_0.9.4    grid_3.5.3       tidyselect_0.2.5 glue_1.3.1      
[29] R6_2.4.0         readxl_1.3.1     modelr_0.1.4     magrittr_1.5     backports_1.1.4  scales_1.0.0     rvest_0.3.3     
[36] assertthat_0.2.1 colorspace_1.4-1 labeling_0.3     stringi_1.4.3    lazyeval_0.2.2   munsell_0.5.0    broom_0.5.2     
[43] crayon_1.3.4    
LS0tCnRpdGxlOiAiT3ZlcmFsbCBiaWFzIGFuZCBzYW1wbGUgc2l6ZXMgd2VyZSB1bmNoYW5nZWQgaW4gSUNVIHRyaWFscyBvdmVyIHRpbWU6IGEgbWV0YS1lcGlkZW1pb2xvZ2ljYWwgc3R1ZHkgLSBmaW5hbCBhbmFseXNpcyBjb2RlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIFtSIE1hcmtkb3duLW5vdGVib29rXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vbm90ZWJvb2suaHRtbCkgY29udGFpbnMgdGhlIGZpbmFsIGFubm90YXRlZCBhbmFseXNpcyBjb2RlIGZvciB0aGUgbWFudXNjcmlwdDogKioqIk92ZXJhbGwgYmlhcyBhbmQgc2FtcGxlIHNpemVzIHdlcmUgdW5jaGFuZ2VkIGluIElDVSB0cmlhbHMgb3ZlciB0aW1lOiBhIG1ldGEtZXBpZGVtaW9sb2dpY2FsIHN0dWR5IioqKiBieSAqKkNhcmwgVGhvbWFzIEFudGhvbiwgQW5kZXJzIEdyYW5ob2xtLCBKb24gSGVucmlrIExhYWtlLCBBbmRlcnMgUGVybmVyIGFuZCBNb3J0ZW4gSHlsYW5kZXIgTcO4bGxlcioqLgoKVGhlIGFubm90YXRlZCBhbmFseXNpcyBjb2RlIHdhcyB3cml0dGVuIGJ5IFtBbmRlcnMgR3JhbmhvbG1dKG1haWx0bzphbmRlcnNncmFuQGdtYWlsLmNvbSkgYWNjb3JkaW5nIHRvIHRoZSBwcmUtcHVibGlzaGVkIHByb3RvY29sIGFuZCBzdGF0aXN0aWNhbCBhbmFseXNpcyBwbGFpbiAoW2RvaTogMTAuMTExMS9hYXMuMTMyNThdKGh0dHBzOi8vZG9pLm9yZy8xMC4xMTExL2Fhcy4xMzI1OCkpLiBGb3IgZnVydGhlciBkZXRhaWxzLCBwbGVhc2Ugc2VlIHRoZSBmdWxsIGFydGljbGUgYW5kIGl0cyBzdXBwbGVtZW50YXJ5IGZpbGVzLCB3aGljaCBhbHNvIGluY2x1ZGVzIHRoZSBDU1YtZmlsZSBjb250YWluaW5nIHRoZSBmaW5hbCBkYXRhc2V0IGFuZCBhIGRhdGEgZGljdGlvbmFyeS4KCkZvciBjb3JyZXNwb25kZW5jZSByZWxhdGVkIHRvIHRoZSBtYW51c2NyaXB0LCBjb250YWN0IHRoZSBjb3JyZXNwb25kaW5nIGF1dGhvciBbQ2FybCBUaG9tYXMgQW50aG9uXShtYWlsdG86Y2FybC5hbnRob25AZ21haWwuY29tKS4gUXVlc3Rpb25zIGRpcmVjdGx5IHJlbGF0ZWQgdG8gdGhlIGFuYWx5c2lzIGNvZGUgY2FuIGFsc28gYmUgc2VudCB0byBbQW5kZXJzIEdyYW5ob2xtXShtYWlsdG86YW5kZXJzZ3JhbkBnbWFpbC5jb20pLgoKRmlndXJlcyBkaXNwbGF5ZWQgaW4gdGhpcyBkb2N1bWVudCBhcmUgc2NhbGVkIGRpZmZlcmVudGx5IHRoYW4gaW4gdGhlIGZpbmFsIHBhcGVyIGFuZCBzdXBwbGVtZW50LgoKIyMjIDEuIFNldHVwCgpMb2FkIHRoZSBwYWNrYWdlcy9mdW5jdGlvbnMgcmVxdWlyZWQgZm9yIHRoZSBhbmFseXNlcy4KCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKSAjIExvYWQgdGhlIFRpZHl2ZXJzZSBwYWNrYWdlcywgdXNlZCBmb3IgZGF0YSBwcm9jZXNzaW5nIGFuZCB2aXN1YWxpc2F0aW9uLgpwbG90X2dyaWQgPC0gY293cGxvdDo6cGxvdF9ncmlkICMgTG9hZCB0aGlzIGZ1bmN0aW9uIGZyb20gdGhlIGNvd3Bsb3QgcGFja2FnZTsgb25seSB0aGlzIGZ1bmN0aW9uIHdpbGwgYmUgdXNlZCBmcm9tIHRoaXMgcGFja2FnZSwgYW5kIHRoZSBlbnRpcmUgbGlicmFyeSB3aWxsIG5vdCBiZSBsb2FkZWQgYXMgdGhpcyBpcyB1bm5lY2Vzc2FyeSBhbmQgY293cGxvdCBvdmVycmlkZXMgdGhlIGRlZmF1bHQgZ2dwbG90MiB0aGVtZSwgd2hpY2ggdGhlbiBoYXMgdG8gYmUgcmVzZXQuCmBgYAoKSW1wb3J0IHRoZSBmaWxlIGNvbnRhaW5pbmcgZGF0YSBmb3IgYWxsIHRoZSBpbmNsdWRlZCB0cmlhbHMuCgoqKk5vdGU6KiogVGhpcyBjb2RlIGJsb2NrIHVzZXMgUlN0dWRpbydzIEFQSSB0byBhbGxvdyBtYW51YWwgc2VsZWN0aW9uIG9mIHRoZSBmaW5hbCBkYXRhc2V0LiBUaGlzIHJlcXVpcmVzIHRoZSBzY3JpcHQgdG8gYmUgcnVuIGluIGEgcmVjZW50IHZlcnNpb24gb2YgUlN0dWRpbzsgb3RoZXJ3aXNlIHRoaXMgaGFzIHRvIGJlIG1hbnVhbGx5IHJlcGxhY2VkIHdpdGggdGhlIGFwcHJvcHJpYXRlIGZpbGUgcGF0aC4KCmBgYHtyfQppbmNsdWRlZF90cmlhbHMgPC0gcmVhZF9jc3YocnN0dWRpb2FwaTo6c2VsZWN0RmlsZShmaWx0ZXIgPSAiQ1NWIGZpbGVzICgqLmNzdikiKSwgY29sX3R5cGVzID0gY29scyh0cmlhbF95ZWFyID0gY29sX2ludGVnZXIoKSwgc2FtcGxlX3NpemUgPSBjb2xfaW50ZWdlcigpKSkKYGBgCgpEZWZpbmUgdGhlIG91dHB1dCBkaXJlY3Rvcnkgd2hlcmUgYWxsIHJlc3VsdHMgd2lsbCBiZSBzYXZlZC4KCioqTm90ZToqKiBUaGlzIGJsb2NrIHVzZXMgUlN0dWRpbydzIEFQSSB0byBhbGxvdyBtYW51YWwgc2VsZWN0aW9uIG9mIHRoZSBkaXJlY3RvcnkuIFRoaXMgcmVxdWlyZXMgdGhlIHNjcmlwdCB0byBiZSBydW4gaW4gYSByZWNlbnQgdmVyc2lvbiBvZiBSU3R1ZGlvOyBvdGhlcndpc2UgdGhpcyBoYXMgdG8gYmUgbWFudWFsbHkgcmVwbGFjZWQgd2l0aCB0aGUgYXBwcm9wcmlhdGUgcGF0aC4KCmBgYHtyfQpvdXRwdXRfcGF0aCA8LSByc3R1ZGlvYXBpOjpzZWxlY3REaXJlY3RvcnkoKQpgYGAKCkRlZmluZSBwbG90IHRoZW1lIGFuZCBpbWFnZSBzZXR0aW5ncyBmb3Igc2F2aW5nIGltYWdlcywgdG8gYWxsb3cgZWFzeSBjaGFuZ2luZyBsYXRlci4KCmBgYHtyfQojIEZpbGUgc2V0dGluZ3MKaW1nX2RwaSA8LSA2MDAgIyBEUEkgLSBub3QgdXNlZCBmb3IgdmVjdG9yaXplZCBmb3JtYXRzLCBlLmcuIFBERnMsIGJ1dCBhcmd1bWVudCBpcyBrZXB0IGlmIHRoaXMgaXMgY2hhbmdlZC4KaW1nX2Zvcm1hdCA8LSAicGRmIiAjIEZpbGUgZm9ybWF0CiMgV2lkdGhzIGFuZCBoZWlnaHRzIChpbiBtaWxsaW1ldGVycykgZm9yIHNpbmdsZSBydW4gY2hhcnQgcGxvdHMKaW1nX3dpZHRoIDwtIDE1MAppbWdfaGVpZ2h0IDwtIDgwCiMgV2lkdGhzIGFuZCBoZWlnaHRzIChpbiBtaWxsaW1ldGVycykgZm9yIHRoZSB0cmlwbGUgcnVuIGNoYXJ0IHBsb3RzCmltZ193aWR0aF90cmlwbGUgPC0gMTUwCmltZ19oZWlnaHRfdHJpcGxlIDwtIDE1MAojIFdpZHRoIGFuZCBoZWlnaHQgKGluIG1pbGxpbWV0ZXJzKSBmb3IgdGhlIHJpc2sgb2YgYmlhcyBvdmVydmlldyBwbG90CmltZ193aWR0aF9iaWFzIDwtIDIwMAppbWdfaGVpZ2h0X2JpYXMgPC0gODAKCiMgU2V0IGdncGxvdDIgdGhlbWUKdGhlbWVfc2V0KHRoZW1lX2xpbmVkcmF3KCkpCmBgYAoKCiMjIyAyLiBEYXRhIGluc3BlY3Rpb24gYW5kIHByZXBhcmF0aW9uCgojIyMjIDIuMSBIZWxwZXIgZnVuY3Rpb24KVGhlIGZvbGxvd2luZyBoZWxwZXIgZnVuY3Rpb24gZmlsdGVycyBhIGRhdGFzZXQgc28gb25seSB5ZWFycyB3aXRoIGEgY2VydGFpbiBudW1iZXIgb2YgdHJpYWxzIGFyZSBpbmNsdWRlZCwgYW5kIG9wdGlvbmFsbHkgcHJpbnRzIHRoZSBleGNsdWRlZCB5ZWFycy4KQXJndW1lbnRzOgoKLSAqKi5kdGEqKjogdGhlIGRhdGFzZXQgdG8gZmlsdGVyLgotICoqbWluaW11bSoqOiB0aGUgbWluaW11bSBudW1iZXIgb2YgcmVxdWlyZWQgdHJpYWxzIHBlciB5ZWFyLCBkZWZhdWx0IGlzIDUuCi0gKip2ZXJib3NlKio6IGlmIFRSVUUgKGRlZmF1bHQpLCB0aGUgeWVhcnMgd2l0aCB0b28gZmV3IHRyaWFscyBhcmUgcHJpbnRlZC4KCmBgYHtyfQpmaWx0ZXJfeWVhcnMgPC0gZnVuY3Rpb24oLmR0YSwgbWluaW11bSA9IDUsIHZlcmJvc2UgPSBUUlVFKXsKICB5ZWFycyA8LSAuZHRhICU+JSAKICAgIGdyb3VwX2J5KHRyaWFsX3llYXIpICU+JSAKICAgIHN1bW1hcmlzZShuID0gbigpKSAlPiUgCiAgICBmaWx0ZXIobiA8IG1pbmltdW0pICU+JSAKICAgIHB1bGwodHJpYWxfeWVhcikKICAKICBpZiAodmVyYm9zZSl7CiAgICBwcmludChzdHJfZ2x1ZSgiVGhlIGZvbGxvd2luZyB5ZWFycyBjb250YWluIGxlc3MgdGhhbiB7bWluaW11bX0gdHJpYWxzIGFuZCBoYXZlIGJlZWVuIGZpbHRlcmVkIGZyb20gdGhpcyBkYXRhc2V0OiB7c3RyX2MoeWVhcnMsIGNvbGxhcHNlID0gJywgJyl9LiIpKQogIH0KICAKICAuZHRhICU+JSAKICAgIGZpbHRlcighKHRyaWFsX3llYXIgJWluJSB5ZWFycykpCn0KYGBgCgoKIyMjIyAyLjIgUmlzayBvZiBiaWFzCgpDcmVhdGUgKipvdmVyYWxsX3Jpc2tfb2ZfYmlhcyoqIHZhcmlhYmxlIGFuZCBjb252ZXJ0IGFsbCByaXNrIG9mIGJpYXMgZG9tYWlucyB0byBmYWN0b3JzLgoKYGBge3J9CmluY2x1ZGVkX3RyaWFscyA8LSBpbmNsdWRlZF90cmlhbHMgJT4lIAogIG11dGF0ZShvdmVyYWxsX3Jpc2tfb2ZfYmlhcyA9IGNhc2Vfd2hlbihpcy5uYShyYW5kb21fc2VxdWVuY2VfZ2VuZXJhdGlvbikgfCBpcy5uYShhbGxvY2F0aW9uX2NvbmNlYWxtZW50KSB8IGlzLm5hKGJsaW5kaW5nX29mX3BhcnRpY2lwYW50c19hbmRfcGVyc29ubmVsKSB8IGlzLm5hKGJsaW5kaW5nX29mX291dGNvbWVfYXNzZXNzbWVudCkgfCBpcy5uYShpbmNvbXBsZXRlX291dGNvbWVfZGF0YSkgfCBpcy5uYShzZWxlY3RpdmVfcmVwb3J0aW5nKSB8IGlzLm5hKG90aGVyX3NvdXJjZXNfb2ZfYmlhcykgfiBOQV9jaGFyYWN0ZXJfLCAjIElmIGFueSByaXNrIG9mIGJpYXMgZG9tYWluIGlzIG1pc3NpbmcsIHRoZSBvdmVyYWxsIHJpc2sgb2YgYmlhcyB3aWxsIGJlIG1pc3NpbmcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tX3NlcXVlbmNlX2dlbmVyYXRpb24gPT0gIkxvdyIgJiBhbGxvY2F0aW9uX2NvbmNlYWxtZW50ID09ICJMb3ciICYgYmxpbmRpbmdfb2ZfcGFydGljaXBhbnRzX2FuZF9wZXJzb25uZWwgPT0gIkxvdyIgJiBibGluZGluZ19vZl9vdXRjb21lX2Fzc2Vzc21lbnQgPT0gIkxvdyIgJiBpbmNvbXBsZXRlX291dGNvbWVfZGF0YSA9PSAiTG93IiAmIHNlbGVjdGl2ZV9yZXBvcnRpbmcgPT0gIkxvdyIgJiBvdGhlcl9zb3VyY2VzX29mX2JpYXMgPT0gIkxvdyIgfiAiTG93IiwgIyBJZiBhbGwgZG9tYWlucyBhcmUgbG93IHJpc2ssIHRoZSBvdmVyYWxsIHJpc2sgb2YgYmlhcyB3aWxsIGJlIGxvdyBhcyB3ZWxsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiSGlnaCIgIyBJZiBub25lIG9mIHRoZSBhYm92ZSBjcml0ZXJpYSBhcHBseSwgdGhlIG92ZXJhbGwgcmlzayBvZiBiaWFzIHdpbGwgYmUgaGlnaAogICAgICAgICApKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMocmFuZG9tX3NlcXVlbmNlX2dlbmVyYXRpb246b3ZlcmFsbF9yaXNrX29mX2JpYXMpLCB+ZmFjdG9yKC4sIGxldmVscyA9IGMoIkxvdyIsICJVbmNsZWFyIiwgIkhpZ2giKSkpCmBgYAoKQXNzZXNzIGhvdyBtYW55IHRyaWFscyBoYXZlIG1pc3NpbmcgZGF0YSBmb3IgdGhlIG92ZXJhbGwgcmlzayBvZiBiaWFzIGRvbWFpbiAod2hpY2ggd2lsbCBiZSBtaXNzaW5nIGlmIGFueSBvZiB0aGUgb3RoZXIgZG9tYWlucyBhcmUgbWlzc2luZykgYW5kIGNyZWF0ZSBkYXRhc2V0IHRoYXQgb25seSBpbmNsdWRlcyB0cmlhbHMgd2l0aCBhdmFpbGFibGUgcmlzayBvZiBiaWFzIHJhdGluZ3MuCgpgYGB7cn0KaW5jbHVkZWRfdHJpYWxzICU+JSAKICBmaWx0ZXIoaXMubmEob3ZlcmFsbF9yaXNrX29mX2JpYXMpKSAlPiUgCiAgc3RyX2dsdWVfZGF0YSgiSW4gdG90YWwsIHtucm93KC4pfSB0cmlhbHMgaGF2ZSBtaXNzaW5nIGRhdGEgZm9yIG9uZSBvciBtb3JlIHJpc2sgb2YgYmlhcyBkb21haW5zIGFuZCB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gdGhlc2UgYW5hbHlzZXMuIikKCnRyaWFsc19iaWFzX2F2YWlsYWJsZSA8LSBpbmNsdWRlZF90cmlhbHMgJT4lIAogIGZpbHRlcighaXMubmEob3ZlcmFsbF9yaXNrX29mX2JpYXMpKQpgYGAKCkNyZWF0ZSBkYXRhc2V0IHRoYXQgb25seSBjb250YWlucyB0cmlhbHMgZnJvbSB5ZWFycyB3aXRoIGF0IGxlYXN0IDUgdHJpYWxzIHdpdGggYXZhaWxhYmxlIHJpc2sgb2YgYmlhcyByYXRpbmdzIChmb3IgdGhlIHByaW1hcnkgYW5hbHlzZXMpLgoKYGBge3J9CnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1cyA8LSBmaWx0ZXJfeWVhcnModHJpYWxzX2JpYXNfYXZhaWxhYmxlKQpgYGAKCkZvciBhbGwgdHJpYWxzIHdpdGggYXZhaWxhYmxlIHJpc2sgb2YgYmlhcywgY2FsY3VsYXRlIG92ZXJhbGwgZGlzdHJpYnV0aW9ucyBmb3IgZWFjaCBkb21haW4uCgpgYGB7cn0KdHJpYWxzX2JpYXNfYXZhaWxhYmxlICU+JSAKICBnYXRoZXIoa2V5ID0gImJpYXNfZG9tYWluIiwgdmFsdWUgPSAicmF0aW5nIiwgcmFuZG9tX3NlcXVlbmNlX2dlbmVyYXRpb246b3ZlcmFsbF9yaXNrX29mX2JpYXMsIGZhY3Rvcl9rZXkgPSBUUlVFKSAlPiUgCiAgc2VsZWN0KGJpYXNfZG9tYWluLCByYXRpbmcpICU+JSAKICBncm91cF9ieShiaWFzX2RvbWFpbikgJT4lIAogIHN1bW1hcmlzZShsb3cgPSBzdW0ocmF0aW5nID09ICJMb3ciKSAvIG4oKSAqIDEwMCwKICAgICAgICAgICAgdW5jbGVhciA9IHN1bShyYXRpbmcgPT0gIlVuY2xlYXIiKSAvIG4oKSAqIDEwMCwKICAgICAgICAgICAgaGlnaCA9IHN1bShyYXRpbmcgPT0gIkhpZ2giKSAvIG4oKSAqIDEwMCkgJT4lIAogIG11dGF0ZV9pZihpcy5udW1lcmljLCB+cGFzdGUwKHJvdW5kKC4sIDEpLCAiJSIpKQpgYGAKCkNyZWF0ZSBwbG90IHZpc3VhbGlzaW5nIGRpc3RyaWJ1dGlvbnMgb2YgcmlzayBvZiBiaWFzIGZvciBlYWNoIGRvbWFpbiAob25seSBpbmNsdWRlIHRyaWFscyB3aGVyZSByaXNrIG9mIGJpYXMgcmF0aW5ncyBhcmUgYXZhaWxhYmxlKS4KCmBgYHtyfQp0cmlhbHNfYmlhc19hdmFpbGFibGUgJT4lIAogIGdhdGhlcihrZXkgPSAiYmlhc19kb21haW4iLCB2YWx1ZSA9ICJyYXRpbmciLCByYW5kb21fc2VxdWVuY2VfZ2VuZXJhdGlvbjpvdmVyYWxsX3Jpc2tfb2ZfYmlhcywgZmFjdG9yX2tleSA9IFRSVUUpICU+JSAKICBzZWxlY3QoYmlhc19kb21haW4sIHJhdGluZykgJT4lCiAgbXV0YXRlKHJhdGluZyA9IGZhY3RvcihyYXRpbmcsIGxldmVscyA9IGMoIkhpZ2giLCAiVW5jbGVhciIsICJMb3ciKSksCiAgICAgICAgIGJpYXNfZG9tYWluID0gZmN0X3JldihiaWFzX2RvbWFpbikpICU+JSAgIyBSZXZlcnNlIHRoZSBvcmRlciB0byBlbnN1cmUgcHJvcGVyIHByaW50aW5nIGluIHRoZSB0YWJsZQogIGdncGxvdChhZXMoeCA9IGJpYXNfZG9tYWluLCBmaWxsID0gcmF0aW5nKSkgKyAjIENyZWF0ZSB0aGUgcGxvdAogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCB3aWR0aCA9IDAuOTUpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0MwMDAwMCIsICIjRTBFMDAwIiwgIiMwMEMwMDAiKSwgbmFtZSA9ICJSaXNrIG9mIGJpYXMgcmF0aW5nOiIsIGd1aWRlID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFKSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApLCBicmVha3MgPSAwLjEgKiAwOjEwLCBtaW5vcl9icmVha3MgPSAwLjA1ICogMDoyMCwgbGFiZWxzID0gcGFzdGUwKDEwICogMDoxMCwgIiUiKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gYygwLCAwKSwgbGFiZWxzID0gcmV2KGMoICMgVXNlIHJldigpIHRvIGVuc3VyZSB0aGF0IG9yZGVyIG1hdGNoZXMgdGhlIGRvbWFpbnMgYWJvdmUKICAgICJSYW5kb20gc2VxdWVuY2UgZ2VuZXJhdGlvbiIsCiAgICAiQWxsb2NhdGlvbiBjb25jZWFsbWVudCIsCiAgICAiQmxpbmRpbmcgb2YgcGFydGljaXBhbnRzIGFuZCBwZXJzb25uZWwiLAogICAgIkJsaW5kaW5nIG9mIG91dGNvbWUgYXNzZXNzbWVudCIsCiAgICAiSW5jb21wbGV0ZSBvdXRjb21lIGRhdGEiLAogICAgIlNlbGVjdGl2ZSByZXBvcnRpbmciLAogICAgIk90aGVyIHNvdXJjZXMgb2YgYmlhcyIsCiAgICAiT3ZlcmFsbCByaXNrIG9mIGJpYXMiCiAgKSkpICsKICB0aGVtZShwbG90Lm1hcmdpbiA9IG1hcmdpbiAodCA9IDUsIGwgPSAxMCwgciA9IDE1LCBiID0gNSwgdW5pdCA9ICJwdCIpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgIyBGaXggcGxvdCBtYXJnaW5zIHRvIGVuc3VyZSBhbGwgbGFiZWxzIGFyZSBwcmludGVkIGFuZCBjaGFuZ2UgbGVnZW5kCgpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiL1Jpc2sgb2YgYmlhcyBvdmVydmlldy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfYmlhcywgaGVpZ2h0ID0gaW1nX2hlaWdodF9iaWFzLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpICMgU2F2ZSBmaWxlCmBgYAoKIyMjIyAyLjMgU2FtcGxlIHNpemVzCgpBc3Nlc3MgaG93IG1hbnkgdHJpYWxzIGhhdmUgbWlzc2luZyBkYXRhIGZvciBzYW1wbGUgc2l6ZSBhbmQgY3JlYXRlIGRhdGFzZXQgdGhhdCBvbmx5IGluY2x1ZGVzIHRyaWFscyB3aXRoIGF2YWlsYWJsZSBzYW1wbGUgc2l6ZXMuCgpgYGB7cn0KaW5jbHVkZWRfdHJpYWxzICU+JSAKICBmaWx0ZXIoaXMubmEoc2FtcGxlX3NpemUpKSAlPiUgCiAgc3RyX2dsdWVfZGF0YSgiSW4gdG90YWwsIHtucm93KC4pfSB0cmlhbHMgaGF2ZSBtaXNzaW5nIGRhdGEgZm9yIHNhbXBsZSBzaXplcyBhbmQgd2lsbCBiZSBleGNsdWRlZCBmcm9tIHRoZXNlIGFuYWx5c2VzLiIpCgp0cmlhbHNfc2l6ZV9hdmFpbGFibGUgPC0gaW5jbHVkZWRfdHJpYWxzICU+JSAKICBmaWx0ZXIoIWlzLm5hKHNhbXBsZV9zaXplKSkKYGBgCgpDcmVhdGUgZGF0YXNldCB0aGF0IG9ubHkgY29udGFpbnMgdHJpYWxzIGZyb20geWVhcnMgd2l0aCBhdCBsZWFzdCA1IHRyaWFscyB3aXRoIGF2YWlsYWJsZSBzYW1wbGUgc2l6ZXMgKGZvciB0aGUgcHJpbWFyeSBhbmFseXNlcykuCgpgYGB7cn0KdHJpYWxzX3NpemVfYXZhaWxhYmxlXzVwbHVzIDwtIGZpbHRlcl95ZWFycyh0cmlhbHNfc2l6ZV9hdmFpbGFibGUpCmBgYAoKRm9yIGFsbCB0cmlhbHMgd2l0aCBhdmFpbGFibGUgc2FtcGxlIHNpemVzLCBjYWxjdWxhdGUgdGhlIG92ZXJhbGwgZGlzdHJpYnV0aW9uLgoKYGBge3J9CnJvdW5kKHN1bW1hcnkodHJpYWxzX3NpemVfYXZhaWxhYmxlJHNhbXBsZV9zaXplKSwgMSkKYGBgCgojIyMgMy4gRGVmaW5lIHJ1biBjaGFydCBmdW5jdGlvbnMKCkRlZmluZSB0aGUgZnVuY3Rpb24gdGhhdCB3aWxsIHByb2R1Y2UgdGhlIHJ1biBjaGFydHMgYW5kIGFzc29jaWF0ZWQgc3RhdGlzdGljcy4KClRoaXMgY29udGFpbnMgdHdvIGhlbHBlciBmdW5jdGlvbnMsICpydW5fY2hhcnRfc3RhdCogYW5kICpydW5fY2hhcnRfY2FwdGlvbiogd2hpY2ggc2hvdWxkIG9ubHkgYmUgY2FsbGVkIGZyb20gdGhlIG1haW4gZnVuY3Rpb24sICoqcnVuX2NoYXJ0KiosIGFuZCBub3QgZGlyZWN0bHkuCgpUaGUgKipydW5fY2hhcnQqKiBmdW5jdGlvbiBoYXMgdGhlIGZvbGxvd2luZyBhcmd1bWVudHM6CgotICoqLmR0YSoqOiB0aGUgZGF0YXNldCB1c2VkLgotICoqdmFyaWFibGUqKjogdGhlIHZhcmlhYmxlIChlLmcuIGEgcmlzayBvZiBiaWFzIGRvbWFpbiBvciB0aGUgc2FtcGxlIHNpemVzIHZhcmlhYmxlKSwgd2hpY2ggd2lsbCBiZSBhc3Nlc3NlZC4KLSAqKmNhdGVnb3J5Kio6IGlmIHRoZSB2YXJpYWJsZSBpcyBhIHJpc2sgb2YgYmlhcyBkb21haW4sIHRoZSByYXRpbmcgKGUuZy4gIkxvdyIpIHRoYXQgd2lsbCBiZSBhc3Nlc3NlZC4KLSAqKnRpdGxlKio6IHRoZSBwbG90IHRpdGxlLCBpZiBhbnkgaXMgd2FudGVkLiBTZWUgYXJndW1lbnQgYmVsb3cuCi0gKipkZWxldGVfdGl0bGUqKjogdGhpcyBhcmd1bWVudCB3YXMgYWRkZWQgYWZ0ZXIgdGhlIG1ham9yaXR5IG9mIHRoZSBjb2RlIHdhcyB3cml0dGVuLiBJZiBUUlVFIChjdXJyZW50IGRlZmF1bHQpLCBubyBwbG90IHRpdGxlcyB3aWxsIGJlIHVzZWQgcmVnYXJkbGVzcyBvZiB0aGUgYWJvdmUgYXJndW1lbnQuCi0gKipmaXhlZF9tZWRpYW4qKjogZGVmYXVsdHMgdG8gTlVMTCwgYW5kIHRoZW4gdGhlIG1lZGlhbiB2YWx1ZSB3aWxsIGJlIGNhbGN1bGF0ZWQgdXNpbmcgdGhlIGRhdGEgcHJvdmlkZWQuIElmIGEgbnVtZXJpYyB2YWx1ZSBpcyBwcm92aWRlZCwgdGhlIG1lZGlhbiB3aWxsIGJlIGZpeGVkIHRvIHRoaXMgdmFsdWUuIFRoaXMgYXJndW1lbnQgaXMgY3VycmVudGx5IG5vdCB1c2VkIGluIGFueSBhbmFseXNlcy4KLSAqKm51bV9hZ2dfbWVhbioqOiBkZWZhdWx0cyB0byBGQUxTRS4gSWYgRkFMU0UsIGZvciBudW1lcmljIHZhbHVlcyAoaS5lLiB5ZWFybHkgc2FtcGx5IHNpemVzKSB0aGUgbWVkaWFuIHZhbHVlIHdpbGwgYmUgdXNlZCBpbiB0aGUgcnVuIGNoYXJ0IGFuZCB0aGUgaW50ZXJxdWFydGlsZSByYW5nZSB3aWxsIGJlIGRpc3BsYXllZC4gSWYgVFJVRSwgbWVhbiB2YWx1ZXMgd2lsbCBiZSB1c2VkIGFuZCB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgbWVhbiB3aWxsIGJlIGRpc3BsYXllZCBpbnN0ZWFkLiBJZ25vcmVkIGZvciByaXNrIG9mIGJpYXMgZG9tYWlucy4KClRoZSBmdW5jdGlvbiByZXR1cm5zIGFuIGFubm90YXRlZCBwbG90LgoKQW4gYWRkaXRpb25hbCwgc2ltcGxpZmllZCBoZWxwZXIgZnVuY3Rpb24gaXMgcHJlc2VudCwgKip0cmlwbGVfYmlhc19ydW5fY2hhcnQqKiwgd2l0aCB0aGUgZm9sbG93aW5nIGFyZ3VtZW50czoKCi0gKiouZHRhKio6IHRoZSBkYXRhc2V0IHVzZWQuCi0gKip2YXJpYWJsZSoqOiB0aGUgcmlzayBvZiBiaWFzIGRvbWFpbiB0aGF0IHdpbGwgYmUgYXNzZXNzZWQuCi0gKip0aXRsZV9hZGQqKjogZXh0cmEgdGV4dCBhZGRlZCBhcyBwYXJ0IG9mIHRoZSB0aXRsZSAoYWRkZWQgZGlyZWN0bHkgYWZ0ZXIgdGhlIGJpYXMgZG9tYWluKSwgaWYgTlVMTCAoZGVmYXVsdCksIG5vdGhpbmcgd2lsbCBiZSBhZGRlZC4KCmBgYHtyfQojIEZ1bmN0aW9uIHRoYXQgY2FsY3VsYXRlcyB0aGUgcnVuIGNoYXJ0IHN0YXRpc3RpY3MgdXNpbmcgdGhlICJ2YWwiIGNvbHVtbiBpbiB0aGUgYWdncmVnYXRlZCBkYXRhc2V0IGZyb20gdGhlIG1haW4gZnVuY3Rpb24gdGhhdCBoYXMgYWxyZWFkeSBiZWVuIHNvcnRlZCBieSB5ZWFyLgojIFRoaXMgZnVuY3Rpb24gc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkKcnVuX2NoYXJ0X3N0YXQgPC0gZnVuY3Rpb24odmFsLCBmaXhlZF9tZWRpYW4gPSBOVUxMKXsKICBuX3RvdGFsIDwtIGxlbmd0aCh2YWwpCiAgaWYgKG5fdG90YWwgPCAxKXsKICAgIHN0b3AoIkVSUk9SOiBydW5fY2hhcnRfc3RhdDogbnVtYmVyIG9mIG9ic2VydmF0aW9ucyAoeWVhcnMpIDwgMS4iKQogIH0KICBpZiAoIShpcy5udWxsKGZpeGVkX21lZGlhbikgfCBpcy5udW1lcmljKGZpeGVkX21lZGlhbikpKSB7CiAgICBzdG9wKCJFUlJPUjogcnVuX2NoYXJ0X3N0YXQ6IGZpeGVkX21lZGlhbiBtdXN0IGJlIGVpdGhlciBOVUxMIG9yIGEgbnVtZXJpYyB2YWx1ZS4iKQogIH0KICBtZWQgPC0gaWZlbHNlKGlzLm51bGwoZml4ZWRfbWVkaWFuKSwgbWVkaWFuKHZhbCksIGZpeGVkX21lZGlhbikKICBuX3VzZWZ1bCA8LSBzdW0oIW5lYXIodmFsLCBtZWQpKQogIAogIHJ1bl9sb25nZXN0IDwtIDAKICBydW5fY3VycmVudCA8LSAwCiAgcG9zIDwtIE5BCiAgY3Jvc3NfbiA8LSBOQQogIAogIGZvciAoaSBpbiAxOm5fdG90YWwpIHsKICAgIGN1ciA8LSB2YWxbaV0KICAgIGlmICghbmVhcihjdXIsIG1lZCkpIHsKICAgICAgCiAgICAgIGlmIChpcy5uYShwb3MpKXsgIyBXaWxsIGJlIHRydWUgZm9yIHRoZSBmaXJzdCB2YWx1ZSB0aGF0IGlzIG5vdCBlcXVhbCB0byB0aGUgbWVkaWFuIChhbmQgb25seSBvbmNlKQogICAgICAgIHBvcyA8LSAhKGN1ciA+IG1lZCkgIyBTZXRzIGN1cnJlbnQgcG9zaXRpb24gYXMgdGhlIG9wcG9zaXRlIG9mIHdoYXQgaXQgaXMsIHRvIHN0YXJ0IG5ldyBydW4KICAgICAgICBjcm9zc19uIDwtIC0xICMgVGhlIGZpcnN0IHJ1biB3aWxsIG5vdCBjb3VudCBhcyBhIGNyb3NzaW5nCiAgICAgIH0KICAgICAgCiAgICAgIGlmICgoY3VyID4gbWVkICkgPT0gcG9zKSB7ICMgSWYgdGhlIGN1cnJlbnQgdmFsdWUgaXMgb24gdGhlIHNhbWUgc2lkZSBhcyB0aGUgbGFzdCBvbmUKICAgICAgICBydW5fY3VycmVudCA8LSBydW5fY3VycmVudCArIDEKICAgICAgfSBlbHNlIHsgIyBJZiB0aGUgY3VycmVudCB2YWx1ZSBpcyBvbiB0aGUgb3Bwb3NpdGUgc2lkZSBhcyB0aGUgbGFzdCBvbmUKICAgICAgICBpZiAocnVuX2N1cnJlbnQgPiBydW5fbG9uZ2VzdCkgewogICAgICAgICAgcnVuX2xvbmdlc3QgPC0gcnVuX2N1cnJlbnQKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgcnVuX2N1cnJlbnQgPC0gMQogICAgICAgIGNyb3NzX24gPC0gY3Jvc3NfbiArMQogICAgICAgIHBvcyA8LSBjdXIgPiBtZWQKICAgICAgfQogICAgICAKICAgIH0KICB9CiAgaWYgKHJ1bl9jdXJyZW50ID4gcnVuX2xvbmdlc3QpIHsKICAgIHJ1bl9sb25nZXN0IDwtIHJ1bl9jdXJyZW50CiAgfQogIAogICMgUmV0dXJuIHJlc3VsdHMgKHVwcGVyIGFuZCBsb3dlciBwcmVkaWN0aW9uIGxpbWl0cyBjYWxjdWxhdGVkIGFjY29yZGluZyB0byBBbmjDuGoncyBydWxlcykKICBsaXN0KG5fdG90YWwgPSBuX3RvdGFsLCBuX3VzZWZ1bCA9IG5fdXNlZnVsLCBtZWRpYW4gPSBtZWQsCiAgICAgICBydW5fVVBMID0gcm91bmQobG9nMihuX3VzZWZ1bCkgKyAzKSwgcnVuX2xvbmdlc3QgPSBydW5fbG9uZ2VzdCwKICAgICAgIGNyb3NzX0xQTCA9IHFiaW5vbSgwLjA1LCBuX3VzZWZ1bCAtIDEsIDAuNSksIGNyb3NzX24gPSBjcm9zc19uLCBmaXhlZF9tZWRpYW4gPSAhaXMubnVsbChmaXhlZF9tZWRpYW4pKQp9CgojIEZ1bmN0aW9uIHRoYXQgZm9ybWF0cyB0aGUgY2FwdGlvbiB1c2VkIGluIGVhY2ggcnVuIGNoYXJ0CiMgVGhpcyBmdW5jdGlvbiBzaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseQpydW5fY2hhcnRfY2FwdGlvbiA8LSBmdW5jdGlvbihyZXMsIHBlcmNlbnRhZ2UgPSBOVUxMLCBkZWMgPSAxKXsKICByZXMkYmFzZSA8LSBwYXN0ZTAocmVzJG5fdG90YWwsICIgb2JzZXJ2YXRpb25zICgiLCByZXMkbl91c2VmdWwsICIgdXNlZnVsKS4gIiwgaWZlbHNlKHJlcyRmaXhlZF9tZWRpYW4sICJGaXhlZCBtZWRpYW46ICIsICJNZWRpYW46ICIpLCBmb3JtYXQocmVzJG1lZGlhbiwgZGlnaXRzID0gZGVjLCBuc21hbGwgPSBkZWMpLCBwZXJjZW50YWdlLCAiLiBMb25nZXN0IHJ1bjoiKQogIHJlcyRsb25nIDwtIHBhc3RlMCgiW21heC4gIiwgcmVzJHJ1bl9VUEwsICJdLiIpCiAgcmVzJGNyb3NzIDwtIHBhc3RlMCgiW21pbi4gIiwgcmVzJGNyb3NzX0xQTCwgIl0uIikKICAKICBpZiAocmVzJHJ1bl9sb25nZXN0ID4gcmVzJHJ1bl9VUEwgJiByZXMkY3Jvc3NfbiA8IHJlcyRjcm9zc19MUEwpewogICAgIyBCb3RoIHJlc3VsdHMgYXJlIHNpZ25pZmljYW50IChub24tcmFuZG9tIHZhcmlhdGlvbikKICAgIHJlcyA8LSBtYXAocmVzLCBhcy5jaGFyYWN0ZXIpCiAgICBjYXAgPC0gc3Vic3RpdHV0ZShiYXNlfmJvbGQocnVuX2xvbmdlc3Qpfmxvbmd+IkNyb3NzaW5nczoifmJvbGQoY3Jvc3Nfbil+Y3Jvc3MsIHJlcykKICB9IGVsc2UgaWYgKHJlcyRydW5fbG9uZ2VzdCA+IHJlcyRydW5fVVBMKSB7CiAgICAjIE9ubHkgdGhlIGxvbmdlc3QgcnVuIGlzIHNpZ25pZmljYW50IChub24tcmFuZG9tIHZhcmlhdGlvbikKICAgIHJlcyA8LSBtYXAocmVzLCBhcy5jaGFyYWN0ZXIpCiAgICBjYXAgPC0gc3Vic3RpdHV0ZShiYXNlfmJvbGQocnVuX2xvbmdlc3Qpfmxvbmd+IkNyb3NzaW5nczoifmNyb3NzX25+Y3Jvc3MsIHJlcykKICB9IGVsc2UgaWYgKHJlcyRjcm9zc19uIDwgcmVzJGNyb3NzX0xQTCkgewogICAgIyBPbmx5IHRoZSBudW1iZXIgb2YgY3Jvc3NpbmdzIGlzIHNpZ25pZmljYW50IChub24tcmFuZG9tIHZhcmlhdGlvbikKICAgIHJlcyA8LSBtYXAocmVzLCBhcy5jaGFyYWN0ZXIpCiAgICBjYXAgPC0gc3Vic3RpdHV0ZShiYXNlfnJ1bl9sb25nZXN0fmxvbmd+IkNyb3NzaW5nczoifmJvbGQoY3Jvc3Nfbil+Y3Jvc3MsIHJlcykKICB9IGVsc2UgewogICAgIyBObyBzaWduaWZpY2FuY2UgKG9ubHkgcmFuZG9tIHZhcmlhdGlvbikKICAgIHJlcyA8LSBtYXAocmVzLCBhcy5jaGFyYWN0ZXIpCiAgICBjYXAgPC0gc3Vic3RpdHV0ZShiYXNlfnJ1bl9sb25nZXN0fmxvbmd+IkNyb3NzaW5nczoifmNyb3NzX25+Y3Jvc3MsIHJlcykKICB9CiAgIyBSZXR1cm4gY2FwdGlvbgogIGNhcAp9CgojIFRoZSBtYWluIGZ1bmN0aW9uIC0gc2VlIGRlc2NyaXB0aW9uIGFib3ZlCnJ1bl9jaGFydCA8LSBmdW5jdGlvbiguZHRhLCB2YXJpYWJsZSwgY2F0ZWdvcnkgPSBOVUxMLCB0aXRsZSA9IE5VTEwsIGRlbGV0ZV90aXRsZXMgPSBUUlVFLCBmaXhlZF9tZWRpYW4gPSBOVUxMLCBudW1fYWdnX21lYW4gPSBGQUxTRSl7CiAgIyBRdW90ZSB2YXJpYWJsZSBuYW1lIGFuZCBnZXQgdGhlIHR5cGUgb2YgaXQKICB2YXIgPC0gZW5xdW8odmFyaWFibGUpCiAgdmFyX3B1bGwgPC0gcHVsbCguZHRhLCAhIXZhcikKICB0eXBlIDwtIGNhc2Vfd2hlbihpcy5mYWN0b3IodmFyX3B1bGwpIH4gImZhY3RvciIsCiAgICAgICAgICAgICAgICAgICAgaXMuaW50ZWdlcih2YXJfcHVsbCkgfiAiaW50ZWdlciIsCiAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJvdGhlciIpCiAgCiAgIyBJbnB1dCBjaGVja3MKICBpZiAodHlwZSA9PSAiZmFjdG9yIikgewogICAgaWYgKGlzLm51bGwoY2F0ZWdvcnkpKSB7CiAgICAgIHN0b3AoIkVSUk9SOiBydW5fY2hhcnQ6ICd2YXJpYWJsZScgaXMgYSBmYWN0b3IgKHJpc2sgb2YgYmlhcyBkb21haW4/KSBhbmQgJ2NhdGVnb3J5JyBpcyBOVUxMLiAnY2F0ZWdvcnknIG11c3QgYmUgZWl0aGVyICdMb3cnLCAnVW5jbGVhcicgb3IgJ0hpZ2gnLiIsIGNhbGwuID0gRkFMU0UpCiAgICB9IGVsc2UgaWYgKCEoY2F0ZWdvcnkgJWluJSBjKCJMb3ciLCAiVW5jbGVhciIsICJIaWdoIikpKXsKICAgICAgc3RvcChwYXN0ZTAoIkVSUk9SOiBydW5fY2hhcnQ6ICd2YXJpYWJsZScgaXMgYSBmYWN0b3IgKHJpc2sgb2YgYmlhcyBkb21haW4/KSwgJ2NhdGVnb3J5JyBpcyAnIiwgY2F0ZWdvcnksICInLCBidXQgbXVzdCBiZSBlaXRoZXIgJ0xvdycsICdVbmNsZWFyJyBvciAnSGlnaCcuIiksIGNhbGwuID0gRkFMU0UpCiAgICB9CiAgfSBlbHNlIGlmICh0eXBlID09ICJpbnRlZ2VyIikgewogICAgaWYgKCFpcy5udWxsKGNhdGVnb3J5KSl7CiAgICAgIHdhcm5pbmcocGFzdGUwKCJXQVJOSU5HOiBydW5fY2hhcnQ6ICd2YXJpYWJsZScgaXMgYW4gaW50ZWdlciAoc2FtcGxlIHNpemU/KS4gJ2NhdGVnb3J5JyBpcyAnIiwgY2F0ZWdvcnksICInIGFuZCB3aWxsIE5PVCBiZSB1c2VkLiIpLCBjYWxsLiA9IEZBTFNFKQogICAgfQogIH0gZWxzZSB7CiAgICBzdG9wKHBhc3RlMCgiRVJST1I6IHJ1bl9jaGFydDogJ3ZhcmlhYmxlJyBtdXN0IGJlIGVpdGhlciBhIGZhY3RvciAocmlzayBvZiBiaWFzIGNhdGVnb3J5KSBvciBhbiBpbnRlZ2VyIChzYW1wbGUgc2l6ZSksICciLCBxdW9fbmFtZSh2YXIpLCAiJyBpcyBuZWl0aGVyLiIpKQogIH0KICAKICAjIFJlbW92ZSBtaXNzaW5nIGRhdGEKICBuX21pc3MgPC0gLmR0YSAlPiUgCiAgICBmaWx0ZXIoaXMubmEodHJpYWxfeWVhcikgfCBpcy5uYSghIXZhcikpICU+JSAKICAgIG5yb3coKQogIGlmIChuX21pc3MgPiAwKSB7CiAgICB3YXJuaW5nKHBhc3RlMCgiV0FSTklORzogcnVuX2NoYXJ0OiAiLCBuX21pc3MsICIgcm93cyB3aXRoIG1pc3NpbmcgZGF0YSBpbiBlaXRoZXIgdHJpYWxfeWVhciBvciAiLCBxdW9fbmFtZSh2YXIpLCAiIHJlbW92ZWQgZnJvbSB0aGUgZGF0YXNldCBwcmlvciB0byBhbmFseXNlcy4iKSkKICAgIC5kdGEgPC0gLmR0YSAlPiUgCiAgICAgIGZpbHRlcighaXMubmEodHJpYWxfeWVhcikgJiAhaXMubmEoISF2YXIpKQogIH0KICAKICAjIElmIGRlbGV0ZV90aXRsZXMgPT0gVFJVRSwgdGhlbiBzZXQgdGl0bGUgdG8gbnVsbAogIGlmIChkZWxldGVfdGl0bGVzKXsKICAgIHRpdGxlIDwtIE5VTEwKICB9CiAgCiAgIyBBZ2dyZWdhdGUgZGF0YQogIGlmICh0eXBlID09ICJmYWN0b3IiKSB7CiAgICBhZ2cgPC0gLmR0YSAlPiUgCiAgICAgIGdyb3VwX2J5KHRyaWFsX3llYXIpICU+JSAKICAgICAgc3VtbWFyaXNlKHZhbCA9IHN1bSghIXZhciA9PSBjYXRlZ29yeSkgLyBuKCkgKiAxMDApICU+JSAKICAgICAgYXJyYW5nZSh0cmlhbF95ZWFyKQogIH0gZWxzZSBpZiAodHlwZSA9PSAiaW50ZWdlciIpIHsKICAgIGlmICghbnVtX2FnZ19tZWFuKXsKICAgICAgYWdnIDwtIC5kdGEgJT4lIAogICAgICAgIGdyb3VwX2J5KHRyaWFsX3llYXIpICU+JSAKICAgICAgICBzdW1tYXJpc2UodmFsID0gbWVkaWFuKCEhdmFyKSwKICAgICAgICAgICAgICAgICAgeV9oaWdoID0gcXVhbnRpbGUoISF2YXIsIDAuNzUpLAogICAgICAgICAgICAgICAgICB5X2xvdyA9IHF1YW50aWxlKCEhdmFyLCAwLjI1KSkgJT4lCiAgICAgICAgYXJyYW5nZSh0cmlhbF95ZWFyKSAgICAgIAogICAgfSBlbHNlIGlmIChudW1fYWdnX21lYW4pIHsKICAgICAgYWdnIDwtIC5kdGEgJT4lIAogICAgICAgIGdyb3VwX2J5KHRyaWFsX3llYXIpICU+JSAKICAgICAgICBzdW1tYXJpc2UodmFsID0gbWVhbighIXZhciksCiAgICAgICAgICAgICAgICAgIHNlX3ZhbCA9IHNkKCEhdmFyKSAvIHNxcnQobigpKSwKICAgICAgICAgICAgICAgICAgeV9oaWdoID0gdmFsICsgMS45NiAqIHNlX3ZhbCwKICAgICAgICAgICAgICAgICAgeV9sb3dfdG1wID0gdmFsIC0gMS45NiAqIHNlX3ZhbCwKICAgICAgICAgICAgICAgICAgeV9sb3cgPSBpZmVsc2UoeV9sb3dfdG1wIDwgMCwgMCwgeV9sb3dfdG1wKSkgJT4lICAjIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSBiZWxvdyAwIGFyZSBpbXBvc3NpYmxlCiAgICAgICAgYXJyYW5nZSh0cmlhbF95ZWFyKQogICAgfQoKICB9CiAgCiAgIyBDYWxjdWxhdGUgc3RhdHMKICBzdGF0cyA8LSBhZ2cgJT4lCiAgICBwdWxsKHZhbCkgJT4lIAogICAgcnVuX2NoYXJ0X3N0YXQoZml4ZWRfbWVkaWFuID0gZml4ZWRfbWVkaWFuKQogIAogICMgR2VuZXJhbCBwbG90IGFzcGVjdHMKICBnZyA8LSBnZ3Bsb3QoZGF0YSA9IGFnZywgYWVzKHggPSB0cmlhbF95ZWFyLCB5ID0gdmFsKSkgKwogICAgbGFicyhjYXB0aW9uID0gcnVuX2NoYXJ0X2NhcHRpb24oc3RhdHMsIGlmX2Vsc2UodHlwZSA9PSAiZmFjdG9yIiwgIiUiLCAiIikpLCB4ID0gTlVMTCwgeSA9IE5VTEwsIHN1YnRpdGxlID0gdGl0bGUpICsgIyBUaGUgdGl0bGUgYXJndW1lbnQgcHJvdmlkZWQgaXMgdXNlZCBmb3IgYSBnZ3Bsb3QyIHN1YnRpdGxlLCBkdWUgdG8gdGhlIGRlZmF1bHQgc21hbGxlciBmb250IHNpemUKICAgIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgIyBBbGlnbiBjYXB0aW9uIGluIHRoZSBtaWRkbGUKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDE5NzUsIDIwMjApLCBicmVha3MgPSAxOTc1ICsgNSAqIDA6OCwgbWlub3JfYnJlYWtzID0gMTk3NToyMDIwLCBleHBhbmQgPSBjKDAsIDApKQogIAogICMgQWRkIGRpZmZlcmVudCBhc3BlY3RzIGZvciByaXNrIG9mIGJpYXMgZG9tYWlucyBhbmQgc2FtcGxlIHNpemVzCiAgaWYgKHR5cGUgPT0gImZhY3RvciIpIHsKICAgICMgUmlzayBvZiBiaWFzIGRvbWFpbnMgLSBkaWZmZXJlbnQgeS1heGlzIGZvciBvdmVyYWxsIHJpc2sgb2YgYmlhcyBwbG90cyBhbmQgc3ViZG9tYWlucwogICAgaWYgKHF1b19uYW1lKHZhcikgPT0gIm92ZXJhbGxfcmlza19vZl9iaWFzIikgewogICAgICBnZyA8LSBnZyArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNTApLCBicmVha3MgPSAxMCAqIDA6NSwgbWlub3JfYnJlYWtzID0gNSAqIDA6MTAsIGxhYmVscyA9IHBhc3RlMCgxMCAqIDA6NSwgIiUiKSwgZXhwYW5kID0gYygwLjAxNSwgMCkpCiAgICB9IGVsc2UgewogICAgICBnZyA8LSBnZyArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTAwKSwgYnJlYWtzID0gMjAgKiAwOjUsIG1pbm9yX2JyZWFrcyA9IDUgKiAwOjIwLCBsYWJlbHMgPSBwYXN0ZTAoMjAgKiAwOjUsICIlIiksIGV4cGFuZCA9IGMoMC4wMTUsIDApKQogICAgfQogIH0gZWxzZSBpZiAodHlwZSA9PSAiaW50ZWdlciIpIHsKICAgICMgU2FtcGxlIHNpemVzIC0gZGlmZmVyZW50IHktYXhpcyBhY2NvcmRpbmcgdG8gYWdncmVnYXRpb24gZnVuY3Rpb24KICAgIGdnIDwtIGdnICsKICAgICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IDEwMCAqIDA6MTUsIG1pbm9yX2JyZWFrcyA9IDI1ICogMDo2MCwgZXhwYW5kID0gYygwLCAwKSkgKyAjIEF4aXMgbG9uZyBlbm91Z2ggZm9yIGJvdGggdHlwZXMgb2YgcGxvdHMgLSBkaWZmZXJlbnQgbGltaXRzIGZvciBtZWRpYW4vbWVhbiB2YWx1ZXMgYXJlIHNldCBpbiBuZXh0IGxpbmUKICAgICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIGlmZWxzZSghbnVtX2FnZ19tZWFuLCA2MDAsIDE0MDApKSkgKyAjIExpbWl0cyBhcmUgc2V0IGhlcmUgdG8gYXZvaWQgb3V0bGllcnMgZm9yIDk1JSBDSXMgb2YgeWVhcmx5IG1lYW5zIHRvIGJlIHJlbW92ZWQKICAgICAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSB5X2xvdywgeW1heCA9IHlfaGlnaCksIGZpbGwgPSAiI0I1QjVCNSIsIGFscGhhID0gMC44MCkgIyBBZGQgZ3JleSBzaGFkZWQgYXJlYQogIH0KICAKICAjIEFkZCBwb2ludHMgYW5kIGxpbmVzCiAgZ2cgPC0gZ2cgKyBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgICBnZW9tX2xpbmUoKSArCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBzdGF0cyRtZWRpYW4sIHNpemUgPSAxLjI1KQogIAogICMgUmV0dXJuIHBsb3QKICBnZwp9CgojIFNpbXBsZSBoZWxwZXIgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIGEgY29tYmluZWQgcGxvdCB3aXRoIGFsbCAzIHJpc2sgb2YgYmlhcyByYXRpbmdzCnRyaXBsZV9iaWFzX3J1bl9jaGFydCA8LSBmdW5jdGlvbiguZHRhLCB2YXJpYWJsZSwgdGl0bGVfYWRkID0gTlVMTCl7CiAgdmFyaWFibGUgPC0gZW5xdW8odmFyaWFibGUpCiAgdGl0bGVfYmFzZSA8LSBzdHJfcmVwbGFjZV9hbGwoc3RyX3RvX3RpdGxlKHF1b19uYW1lKHZhcmlhYmxlKSksICJfIiwgIiAiKQogIHBsb3RfZ3JpZCgKICAgIHJ1bl9jaGFydCguZHRhLCAhIXZhcmlhYmxlLCBjYXRlZ29yeSA9ICJMb3ciLCB0aXRsZSA9IHBhc3RlMCh0aXRsZV9iYXNlLCB0aXRsZV9hZGQpKSArIHlsYWIoIkxvdyIpLAogICAgcnVuX2NoYXJ0KC5kdGEsICEhdmFyaWFibGUsIGNhdGVnb3J5ID0gIlVuY2xlYXIiKSArIHlsYWIoIlVuY2xlYXIiKSwKICAgIHJ1bl9jaGFydCguZHRhLCAhIXZhcmlhYmxlLCBjYXRlZ29yeSA9ICJIaWdoIikgKyB5bGFiKCJIaWdoIiksCiAgICBucm93ID0gMywgbmNvbCA9IDEpCn0KYGBgCgoKIyMjIDQuIFByaW1hcnkgYW5hbHlzaXMKCipGb3IgYWxsIHByaW1hcnkgYW5hbHlzZXMsIG9ubHkgeWVhcnMgd2l0aCA1IG9yIG1vcmUgdHJpYWxzIGFyZSB1c2VkKi4KCioqQW5hbHlzaXMgMS4xOiBQZXJjZW50YWdlIG9mIG92ZXJhbGwgbG93IHJpc2sgb2YgYmlhcyB0cmlhbHMgcGVyIHllYXIqKgoKYGBge3J9CnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1cyAlPiUgCiAgcnVuX2NoYXJ0KG92ZXJhbGxfcmlza19vZl9iaWFzLCAiTG93IiwgdGl0bGUgPSAiT3ZlcmFsbCBsb3cgcmlzayBvZiBiaWFzIikKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMS4xIFByaW1hcnkgYW5hbHlzaXMgLSBvdmVyYWxsIGxvdyByaXNrIG9mIGJpYXMuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoLCBoZWlnaHQgPSBpbWdfaGVpZ2h0LCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCmBgYAoKKipBbmFseXNpcyAxLjI6IEFubnVhbCBtZWRpYW4gc2FtcGxlIHNpemVzKioKCmBgYHtyfQp0cmlhbHNfc2l6ZV9hdmFpbGFibGVfNXBsdXMgJT4lIAogIHJ1bl9jaGFydChzYW1wbGVfc2l6ZSwgdGl0bGUgPSAiTWVkaWFuIChJUVIpIHNhbXBsZSBzaXplcyIpCgpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzEuMiBQcmltYXJ5IGFuYWx5c2lzIC0gc2FtcGxlIHNpemVzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aCwgaGVpZ2h0ID0gaW1nX2hlaWdodCwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQpgYGAKCioqQW5hbHlzaXMgMS4ycGgxOiBQb3N0LWhvYyBhbmFseXNpcyBvZiB0aGUgYW5udWFsIG1lYW4gc2FtcGxlIHNpemVzKioKCmBgYHtyfQp0cmlhbHNfc2l6ZV9hdmFpbGFibGVfNXBsdXMgJT4lIAogIHJ1bl9jaGFydChzYW1wbGVfc2l6ZSwgdGl0bGUgPSAiTWVhbiAoOTUlIENJKSBzYW1wbGUgc2l6ZXMgKHBvc3QtaG9jIGFuYWx5c2lzKSIsIG51bV9hZ2dfbWVhbiA9IFRSVUUpCgpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzEuMnBoMSBQcmltYXJ5IGFuYWx5c2lzIC0gc2FtcGxlIHNpemVzLCBwb3N0LWhvYyBhbmFseXNpcyB1c2luZyBtZWFuIHZhbHVlcy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKkFuYWx5c2lzIDEuMzogWWVhcmx5IHByb3BvcnRpb24gb2YgbG93LCB1bmNsZWFyIGFuZCBoaWdoIHJpc2sgb2YgYmlhcyByYXRpbmdzIGluIGVhY2ggb2YgdGhlIHNldmVuIGRvbWFpbnMqKgoKYGBge3J9CiMgUmFuZG9tIHNlcXVlbmNlIGdlbmVyYXRpb24KdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChyYW5kb21fc2VxdWVuY2VfZ2VuZXJhdGlvbikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8xLjNBIFByaW1hcnkgYW5hbHlzaXMgLSBSYW5kb20gc2VxdWVuY2UgZ2VuZXJhdGlvbi4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBBbGxvY2F0aW9uIGNvbmNlYWxtZW50CnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1cyAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYWxsb2NhdGlvbl9jb25jZWFsbWVudCkKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8xLjNCIFByaW1hcnkgYW5hbHlzaXMgLSBBbGxvY2F0aW9uIGNvbmNlYWxtZW50LiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEJsaW5kaW5nIG9mIHBhcnRpY2lwYW50cyBhbmQgcGVyc29ubmVsCnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1cyAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYmxpbmRpbmdfb2ZfcGFydGljaXBhbnRzX2FuZF9wZXJzb25uZWwpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMS4zQyBQcmltYXJ5IGFuYWx5c2lzIC0gQmxpbmRpbmcgb2YgcGFydGljaXBhbnRzIGFuZCBwZXJzb25uZWwuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoX3RyaXBsZSwgaGVpZ2h0ID0gaW1nX2hlaWdodF90cmlwbGUsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKCiMgQmxpbmRpbmcgb2Ygb3V0Y29tZSBhc3Nlc3NtZW50CnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1cyAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYmxpbmRpbmdfb2Zfb3V0Y29tZV9hc3Nlc3NtZW50KQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzEuM0QgUHJpbWFyeSBhbmFseXNpcyAtIEJsaW5kaW5nIG9mIG91dGNvbWUgYXNzZXNzbWVudC4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBJbmNvbXBsZXRlIG91dGNvbWUgZGF0YQp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXMgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KGluY29tcGxldGVfb3V0Y29tZV9kYXRhKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzEuM0UgUHJpbWFyeSBhbmFseXNpcyAtIEluY29tcGxldGUgb3V0Y29tZSBkYXRhLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIFNlbGVjdGl2ZSByZXBvcnRpbmcKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChzZWxlY3RpdmVfcmVwb3J0aW5nKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzEuM0YgUHJpbWFyeSBhbmFseXNpcyAtIFNlbGVjdGl2ZSByZXBvcnRpbmcuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoX3RyaXBsZSwgaGVpZ2h0ID0gaW1nX2hlaWdodF90cmlwbGUsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKCiMgT3RoZXIgc291cmNlcyBvZiBiaWFzCnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1cyAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQob3RoZXJfc291cmNlc19vZl9iaWFzKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzEuM0cgUHJpbWFyeSBhbmFseXNpcyAtIE90aGVyIHNvdXJjZXMgb2YgYmlhcy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQpgYGAKCiMjIyA1LiBTZW5zaXRpdml0eSBhbmFseXNpcyAjMSAtIGFsbCB0cmlhbHMgZnJvbSB5ZWFycyB3aXRoIDUgb3IgbW9yZSB0cmlhbHMsIGJ1dCBzZXBhcmF0ZWQgYWNjb3JkaW5nIHRvIHR5cGUgb2YgaW50ZXJ2ZW50aW9uCgoqQXMgZm9yIHRoZSBwcmltYXJ5IGFuYWx5c2VzLCBvbmx5IHllYXJzIHdpdGggNSBvciBtb3JlIHRyaWFscyBhcmUgdXNlZCBoZXJlKi4KCkFzc2VzcyB0aGUgZGlzdHJpYnV0aW9uIG9mIGludGVydmVudGlvbiB0eXBlcy4KCmBgYHtyfQppbmNsdWRlZF90cmlhbHMgJT4lIAogIGdyb3VwX2J5KHJldmlld19pbnRlcnZlbnRpb25fY2F0ZWdvcnkpICU+JSAKICBzdW1tYXJpc2UobiA9IG4oKSkKYGBgCgpSYXRoZXIgZmV3IG1lZGljYWwgZGV2aWNlIGFuZCBtYW5hZ2VtZW50IHRyaWFscyBhcmUgaW5jbHVkZWQuIFRodXMsIHRoZXNlIGFuYWx5c2VzIHdpbGwgY29udGFpbiBmZXcgZGF0YSBwb2ludHMgYW5kIHNob3VsZCBiZSBpbnRlcnByZXRlZCB3aXRoIGNhdXRpb24uCgojIyMjIDUuMSBTZW5zaXRpdml0eSBhbmFseXNpcyAjMUEgLSBkcnVnIHRyaWFscwoKQ3JlYXRlIGRhdGFzZXQgZm9yIHJpc2sgb2YgYmlhcyBhbmFseXNlcy4KCmBgYHtyfQp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfZHJ1ZyA8LSB0cmlhbHNfYmlhc19hdmFpbGFibGUgJT4lIAogIGZpbHRlcihyZXZpZXdfaW50ZXJ2ZW50aW9uX2NhdGVnb3J5ID09ICJEcnVnIikgJT4lIAogIGZpbHRlcl95ZWFycygpCgpzdHJfZ2x1ZSgiSW4gdG90YWwge25yb3codHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RydWcpfSBkcnVnIHRyaWFscyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZXNlIHNlbnNpdGl2aXR5IGFuYWx5c2VzIG9mIHJpc2sgb2YgYmlhcy4iKQpgYGAKCkNyZWF0ZSBkYXRhc2V0IGZvciBzYW1wbGUgc2l6ZSBhbmFseXNpcy4KCmBgYHtyfQp0cmlhbHNfc2l6ZV9hdmFpbGFibGVfNXBsdXNfZHJ1ZyA8LSB0cmlhbHNfc2l6ZV9hdmFpbGFibGUgJT4lIAogIGZpbHRlcihyZXZpZXdfaW50ZXJ2ZW50aW9uX2NhdGVnb3J5ID09ICJEcnVnIikgJT4lIAogIGZpbHRlcl95ZWFycygpCgpzdHJfZ2x1ZSgiSW4gdG90YWwge25yb3codHJpYWxzX3NpemVfYXZhaWxhYmxlXzVwbHVzX2RydWcpfSBkcnVnIHRyaWFscyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoaXMgc2Vuc2l0aXZpdHkgYW5hbHlzaXMgb2Ygc2FtcGxlIHNpemVzLiIpCmBgYAoKKipBbmFseXNpcyAyQS4xOiBQZXJjZW50YWdlIG9mIG92ZXJhbGwgbG93IHJpc2sgb2YgYmlhcyB0cmlhbHMgcGVyIHllYXIgLSBkcnVnIHRyaWFscyoqCgpgYGB7cn0KdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RydWcgJT4lIAogIHJ1bl9jaGFydChvdmVyYWxsX3Jpc2tfb2ZfYmlhcywgIkxvdyIsIHRpdGxlID0gIk92ZXJhbGwgbG93IHJpc2sgb2YgYmlhcyAtIGRydWcgUkNUcyIpCgpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJBLjEgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBvdmVyYWxsIGxvdyByaXNrIG9mIGJpYXMgLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKkFuYWx5c2lzIDJBLjI6IEFubnVhbCBtZWRpYW4gc2FtcGxlIHNpemVzIC0gZHJ1ZyB0cmlhbHMqKgoKYGBge3J9CnRyaWFsc19zaXplX2F2YWlsYWJsZV81cGx1c19kcnVnICU+JSAKICBydW5fY2hhcnQoc2FtcGxlX3NpemUsIHRpdGxlID0gIk1lZGlhbiAoSVFSKSBzYW1wbGUgc2l6ZXMgLSBkcnVnIFJDVHMiKQoKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQS4yIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gc2FtcGxlIHNpemVzIC0gZHJ1ZyB0cmlhbHMuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoLCBoZWlnaHQgPSBpbWdfaGVpZ2h0LCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCmBgYAoKKipBbmFseXNpcyAyQS4ycGgxOiBQb3N0LWhvYzogYW5udWFsIG1lYW4gc2FtcGxlIHNpemVzIC0gZHJ1ZyB0cmlhbHMqKgoKYGBge3J9CnRyaWFsc19zaXplX2F2YWlsYWJsZV81cGx1c19kcnVnICU+JSAKICBydW5fY2hhcnQoc2FtcGxlX3NpemUsIHRpdGxlID0gIk1lYW4gKDk1JSBDSSkgc2FtcGxlIHNpemVzIC0gZHJ1ZyBSQ1RzIChwb3N0LWhvYyBhbmFseXNpcykiLCBudW1fYWdnX21lYW4gPSBUUlVFKQoKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQS4ycGgxIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gc2FtcGxlIHNpemVzIC0gZHJ1ZyB0cmlhbHMsIHBvc3QtaG9jIHVzaW5nIG1lYW5zLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aCwgaGVpZ2h0ID0gaW1nX2hlaWdodCwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQpgYGAKCioqQW5hbHlzaXMgMkEuMzogWWVhcmx5IHByb3BvcnRpb24gb2YgbG93LCB1bmNsZWFyIGFuZCBoaWdoIHJpc2sgb2YgYmlhcyByYXRpbmdzIGluIGVhY2ggb2YgdGhlIHNldmVuIGRvbWFpbnMgLSBkcnVnIHRyaWFscyoqCgpgYGB7cn0KIyBSYW5kb20gc2VxdWVuY2UgZ2VuZXJhdGlvbgp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfZHJ1ZyAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQocmFuZG9tX3NlcXVlbmNlX2dlbmVyYXRpb24sIHRpdGxlX2FkZCA9ICIgLSBkcnVnIFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJBLjNBIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gUmFuZG9tIHNlcXVlbmNlIGdlbmVyYXRpb24gLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBBbGxvY2F0aW9uIGNvbmNlYWxtZW50CnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19kcnVnICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChhbGxvY2F0aW9uX2NvbmNlYWxtZW50LCB0aXRsZV9hZGQgPSAiIC0gZHJ1ZyBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQS4zQiBTZW5zaXRpdml0eSBhbmFseXNpcyAtIEFsbG9jYXRpb24gY29uY2VhbG1lbnQgLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBCbGluZGluZyBvZiBwYXJ0aWNpcGFudHMgYW5kIHBlcnNvbm5lbAp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfZHJ1ZyAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYmxpbmRpbmdfb2ZfcGFydGljaXBhbnRzX2FuZF9wZXJzb25uZWwsIHRpdGxlX2FkZCA9ICIgLSBkcnVnIFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJBLjNDIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gQmxpbmRpbmcgb2YgcGFydGljaXBhbnRzIGFuZCBwZXJzb25uZWwgLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBCbGluZGluZyBvZiBvdXRjb21lIGFzc2Vzc21lbnQKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RydWcgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KGJsaW5kaW5nX29mX291dGNvbWVfYXNzZXNzbWVudCwgdGl0bGVfYWRkID0gIiAtIGRydWcgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkEuM0QgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBCbGluZGluZyBvZiBvdXRjb21lIGFzc2Vzc21lbnQgLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBJbmNvbXBsZXRlIG91dGNvbWUgZGF0YQp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfZHJ1ZyAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoaW5jb21wbGV0ZV9vdXRjb21lX2RhdGEsIHRpdGxlX2FkZCA9ICIgLSBkcnVnIFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJBLjNFIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gSW5jb21wbGV0ZSBvdXRjb21lIGRhdGEgLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBTZWxlY3RpdmUgcmVwb3J0aW5nCnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19kcnVnICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChzZWxlY3RpdmVfcmVwb3J0aW5nLCB0aXRsZV9hZGQgPSAiIC0gZHJ1ZyBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQS4zRiBTZW5zaXRpdml0eSBhbmFseXNpcyAtIFNlbGVjdGl2ZSByZXBvcnRpbmcgLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBPdGhlciBzb3VyY2VzIG9mIGJpYXMKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RydWcgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KG90aGVyX3NvdXJjZXNfb2ZfYmlhcywgdGl0bGVfYWRkID0gIiAtIGRydWcgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkEuM0cgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBPdGhlciBzb3VyY2VzIG9mIGJpYXMgLSBkcnVnIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQpgYGAKCioqTk9URToqKiBUaGUgYW5hbHlzaXMgb2YgaGlnaCByaXNrIG9mIGJpYXMgZm9yIGFsbG9jYXRpb24gYWxsb2NhdGlvbiBjb25jZWFsbWVudCBpbmRpY2F0ZXMgbm9uLXZhcmlhdGlvbiwgaG93ZXZlciB0aGUgbWVkaWFuIHllYXJseSBwcm9wb3J0aW9uIGlzIDAlIGFuZCB0aHVzIHRoZSBtZWRpYW4gY2Fubm90IGJlIGNyb3NzZWQgYW5kIHRoZSBydW5zIGNhbm5vdCBiZSBicm9rZW4gaW4gdGhlIHJ1biBjaGFydDsgdGhpcyBhbmFseXNpcyBtdXN0IGJlIGludGVycHJldGVkIHdpdGggY2F1dGlvbi4KCiMjIyMgNS4yIFNlbnNpdGl2aXR5IGFuYWx5c2lzICMxQiAtIG1hbmFnZW1lbnQgdHJpYWxzCgpDcmVhdGUgZGF0YXNldCBmb3IgcmlzayBvZiBiaWFzIGFuYWx5c2VzLgoKYGBge3J9CnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19tYW5hZ2VtZW50IDwtIHRyaWFsc19iaWFzX2F2YWlsYWJsZSAlPiUgCiAgZmlsdGVyKHJldmlld19pbnRlcnZlbnRpb25fY2F0ZWdvcnkgPT0gIk1hbmFnZW1lbnQiKSAlPiUgCiAgZmlsdGVyX3llYXJzKCkKCnN0cl9nbHVlKCJJbiB0b3RhbCB7bnJvdyh0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfbWFuYWdlbWVudCl9IG1hbmFnZW1lbnQgdHJpYWxzIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlc2Ugc2Vuc2l0aXZpdHkgYW5hbHlzZXMgb2YgcmlzayBvZiBiaWFzLiIpCmBgYAoKQ3JlYXRlIGRhdGFzZXQgZm9yIHNhbXBsZSBzaXplIGFuYWx5c2lzLgoKYGBge3J9CnRyaWFsc19zaXplX2F2YWlsYWJsZV81cGx1c19tYW5hZ2VtZW50IDwtIHRyaWFsc19zaXplX2F2YWlsYWJsZSAlPiUgCiAgZmlsdGVyKHJldmlld19pbnRlcnZlbnRpb25fY2F0ZWdvcnkgPT0gIk1hbmFnZW1lbnQiKSAlPiUgCiAgZmlsdGVyX3llYXJzKCkKCnN0cl9nbHVlKCJJbiB0b3RhbCB7bnJvdyh0cmlhbHNfc2l6ZV9hdmFpbGFibGVfNXBsdXNfbWFuYWdlbWVudCl9IG1hbmFnZW1lbnQgdHJpYWxzIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhpcyBzZW5zaXRpdml0eSBhbmFseXNpcyBvZiBzYW1wbGUgc2l6ZXMuIikKYGBgCgoqKkFuYWx5c2lzIDJCLjE6IFBlcmNlbnRhZ2Ugb2Ygb3ZlcmFsbCBsb3cgcmlzayBvZiBiaWFzIHRyaWFscyBwZXIgeWVhciAtIG1hbmFnZW1lbnQgdHJpYWxzKioKCmBgYHtyfQp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfbWFuYWdlbWVudCAlPiUgCiAgcnVuX2NoYXJ0KG92ZXJhbGxfcmlza19vZl9iaWFzLCAiTG93IiwgdGl0bGUgPSAiT3ZlcmFsbCBsb3cgcmlzayBvZiBiaWFzIC0gbWFuYWdlbWVudCBSQ1RzIikKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkIuMSBTZW5zaXRpdml0eSBhbmFseXNpcyAtIG92ZXJhbGwgbG93IHJpc2sgb2YgYmlhcyAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aCwgaGVpZ2h0ID0gaW1nX2hlaWdodCwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQpgYGAKCioqQW5hbHlzaXMgMkIuMjogQW5udWFsIG1lZGlhbiBzYW1wbGUgc2l6ZXMgLSBtYW5hZ2VtZW50IHRyaWFscyoqCgpgYGB7cn0KdHJpYWxzX3NpemVfYXZhaWxhYmxlXzVwbHVzX21hbmFnZW1lbnQgJT4lIAogIHJ1bl9jaGFydChzYW1wbGVfc2l6ZSwgdGl0bGUgPSAiTWVkaWFuIChJUVIpIHNhbXBsZSBzaXplcyAtIG1hbmFnZW1lbnQgUkNUcyIpCgpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJCLjIgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBzYW1wbGUgc2l6ZXMgLSBtYW5hZ2VtZW50IHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKkFuYWx5c2lzIDJCLjJwaDE6IFBvc3QtaG9jOiBhbm51YWwgbWVhbiBzYW1wbGUgc2l6ZXMgLSBtYW5hZ2VtZW50IHRyaWFscyoqCgpgYGB7cn0KdHJpYWxzX3NpemVfYXZhaWxhYmxlXzVwbHVzX21hbmFnZW1lbnQgJT4lIAogIHJ1bl9jaGFydChzYW1wbGVfc2l6ZSwgdGl0bGUgPSAiTWVhbiAoOTUlIENJKSBzYW1wbGUgc2l6ZXMgLSBtYW5hZ2VtZW50IFJDVHMgKHBvc3QtaG9jIGFuYWx5c2lzKSIsIG51bV9hZ2dfbWVhbiA9IFRSVUUpCgpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJCLjJwaDEgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBzYW1wbGUgc2l6ZXMgLSBtYW5hZ2VtZW50IHRyaWFscywgcG9zdC1ob2MgdXNpbmcgbWVhbnMuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoLCBoZWlnaHQgPSBpbWdfaGVpZ2h0LCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCmBgYAoKKipBbmFseXNpcyAyQi4zOiBZZWFybHkgcHJvcG9ydGlvbiBvZiBsb3csIHVuY2xlYXIgYW5kIGhpZ2ggcmlzayBvZiBiaWFzIHJhdGluZ3MgaW4gZWFjaCBvZiB0aGUgc2V2ZW4gZG9tYWlucyAtIG1hbmFnZW1lbnQgdHJpYWxzKioKCmBgYHtyfQojIFJhbmRvbSBzZXF1ZW5jZSBnZW5lcmF0aW9uCnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19tYW5hZ2VtZW50ICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChyYW5kb21fc2VxdWVuY2VfZ2VuZXJhdGlvbiwgdGl0bGVfYWRkID0gIiAtIG1hbmFnZW1lbnQgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkIuM0EgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBSYW5kb20gc2VxdWVuY2UgZ2VuZXJhdGlvbiAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEFsbG9jYXRpb24gY29uY2VhbG1lbnQKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX21hbmFnZW1lbnQgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KGFsbG9jYXRpb25fY29uY2VhbG1lbnQsIHRpdGxlX2FkZCA9ICIgLSBtYW5hZ2VtZW50IFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJCLjNCIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gQWxsb2NhdGlvbiBjb25jZWFsbWVudCAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEJsaW5kaW5nIG9mIHBhcnRpY2lwYW50cyBhbmQgcGVyc29ubmVsCnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19tYW5hZ2VtZW50ICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChibGluZGluZ19vZl9wYXJ0aWNpcGFudHNfYW5kX3BlcnNvbm5lbCwgdGl0bGVfYWRkID0gIiAtIG1hbmFnZW1lbnQgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkIuM0MgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBCbGluZGluZyBvZiBwYXJ0aWNpcGFudHMgYW5kIHBlcnNvbm5lbCAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEJsaW5kaW5nIG9mIG91dGNvbWUgYXNzZXNzbWVudAp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfbWFuYWdlbWVudCAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYmxpbmRpbmdfb2Zfb3V0Y29tZV9hc3Nlc3NtZW50LCB0aXRsZV9hZGQgPSAiIC0gbWFuYWdlbWVudCBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQi4zRCBTZW5zaXRpdml0eSBhbmFseXNpcyAtIEJsaW5kaW5nIG9mIG91dGNvbWUgYXNzZXNzbWVudCAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEluY29tcGxldGUgb3V0Y29tZSBkYXRhCnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19tYW5hZ2VtZW50ICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChpbmNvbXBsZXRlX291dGNvbWVfZGF0YSwgdGl0bGVfYWRkID0gIiAtIG1hbmFnZW1lbnQgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkIuM0UgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBJbmNvbXBsZXRlIG91dGNvbWUgZGF0YSAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIFNlbGVjdGl2ZSByZXBvcnRpbmcKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX21hbmFnZW1lbnQgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KHNlbGVjdGl2ZV9yZXBvcnRpbmcsIHRpdGxlX2FkZCA9ICIgLSBtYW5hZ2VtZW50IFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJCLjNGIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gU2VsZWN0aXZlIHJlcG9ydGluZyAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIE90aGVyIHNvdXJjZXMgb2YgYmlhcwp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfbWFuYWdlbWVudCAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQob3RoZXJfc291cmNlc19vZl9iaWFzLCB0aXRsZV9hZGQgPSAiIC0gbWFuYWdlbWVudCBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQi4zRyBTZW5zaXRpdml0eSBhbmFseXNpcyAtIE90aGVyIHNvdXJjZXMgb2YgYmlhcyAtIG1hbmFnZW1lbnQgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCmBgYAoKIyMjIyA1LjMgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgIzFDIC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzCgpDcmVhdGUgZGF0YXNldCBmb3IgcmlzayBvZiBiaWFzIGFuYWx5c2VzLgoKYGBge3J9CnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19kZXZpY2UgPC0gdHJpYWxzX2JpYXNfYXZhaWxhYmxlICU+JSAKICBmaWx0ZXIocmV2aWV3X2ludGVydmVudGlvbl9jYXRlZ29yeSA9PSAiRGV2aWNlIikgJT4lIAogIGZpbHRlcl95ZWFycygpCgpzdHJfZ2x1ZSgiSW4gdG90YWwge25yb3codHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RldmljZSl9IG1lZGljYWwgZGV2aWNlIHRyaWFscyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZXNlIHNlbnNpdGl2aXR5IGFuYWx5c2VzIG9mIHJpc2sgb2YgYmlhcy4iKQpgYGAKCkNyZWF0ZSBkYXRhc2V0IGZvciBzYW1wbGUgc2l6ZSBhbmFseXNpcy4KCmBgYHtyfQp0cmlhbHNfc2l6ZV9hdmFpbGFibGVfNXBsdXNfZGV2aWNlIDwtIHRyaWFsc19zaXplX2F2YWlsYWJsZSAlPiUgCiAgZmlsdGVyKHJldmlld19pbnRlcnZlbnRpb25fY2F0ZWdvcnkgPT0gIkRldmljZSIpICU+JSAKICBmaWx0ZXJfeWVhcnMoKQoKc3RyX2dsdWUoIkluIHRvdGFsIHtucm93KHRyaWFsc19zaXplX2F2YWlsYWJsZV81cGx1c19kZXZpY2UpfSBtZWRpY2FsIGRldmljZSB0cmlhbHMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGlzIHNlbnNpdGl2aXR5IGFuYWx5c2lzIG9mIHNhbXBsZSBzaXplcy4iKQpgYGAKCioqQW5hbHlzaXMgMkMuMTogUGVyY2VudGFnZSBvZiBvdmVyYWxsIGxvdyByaXNrIG9mIGJpYXMgdHJpYWxzIHBlciB5ZWFyIC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzKioKCmBgYHtyfQp0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfZGV2aWNlICU+JSAKICBydW5fY2hhcnQob3ZlcmFsbF9yaXNrX29mX2JpYXMsICJMb3ciLCB0aXRsZSA9ICJPdmVyYWxsIGxvdyByaXNrIG9mIGJpYXMgLSBtZWRpY2FsIGRldmljZSBSQ1RzIikKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkMuMSBTZW5zaXRpdml0eSBhbmFseXNpcyAtIG92ZXJhbGwgbG93IHJpc2sgb2YgYmlhcyAtIG1lZGljYWwgZGV2aWNlIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKkFuYWx5c2lzIDJDLjI6IEFubnVhbCBtZWRpYW4gc2FtcGxlIHNpemVzIC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzKioKCmBgYHtyfQp0cmlhbHNfc2l6ZV9hdmFpbGFibGVfNXBsdXNfZGV2aWNlICU+JSAKICBydW5fY2hhcnQoc2FtcGxlX3NpemUsIHRpdGxlID0gIk1lZGlhbiAoSVFSKSBzYW1wbGUgc2l6ZXMgLSBtZWRpY2FsIGRldmljZSBSQ1RzIikKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkMuMiBTZW5zaXRpdml0eSBhbmFseXNpcyAtIHNhbXBsZSBzaXplcyAtIG1lZGljYWwgZGV2aWNlIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKkFuYWx5c2lzIDJDLjJwaDE6IFBvc3QtaG9jOiBhbm51YWwgbWVhbiBzYW1wbGUgc2l6ZXMgLSBtZWRpY2FsIGRldmljZSB0cmlhbHMqKgoKYGBge3J9CnRyaWFsc19zaXplX2F2YWlsYWJsZV81cGx1c19kZXZpY2UgJT4lIAogIHJ1bl9jaGFydChzYW1wbGVfc2l6ZSwgdGl0bGUgPSAiTWVhbiAoOTUlIENJKSBzYW1wbGUgc2l6ZXMgLSBtZWRpY2FsIGRldmljZSBSQ1RzIChwb3N0LWhvYyBhbmFseXNpcykiLCBudW1fYWdnX21lYW4gPSBUUlVFKQoKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQy4ycGgxIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gc2FtcGxlIHNpemVzIC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzLCBwb3N0LWhvYyB1c2luZyBtZWFucy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKkFuYWx5c2lzIDJDLjM6IFllYXJseSBwcm9wb3J0aW9uIG9mIGxvdywgdW5jbGVhciBhbmQgaGlnaCByaXNrIG9mIGJpYXMgcmF0aW5ncyBpbiBlYWNoIG9mIHRoZSBzZXZlbiBkb21haW5zIC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzKioKYGBge3J9CiMgUmFuZG9tIHNlcXVlbmNlIGdlbmVyYXRpb24KdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RldmljZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQocmFuZG9tX3NlcXVlbmNlX2dlbmVyYXRpb24sIHRpdGxlX2FkZCA9ICIgLSBtZWRpY2FsIGRldmljZSBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQy4zQSBTZW5zaXRpdml0eSBhbmFseXNpcyAtIFJhbmRvbSBzZXF1ZW5jZSBnZW5lcmF0aW9uIC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEFsbG9jYXRpb24gY29uY2VhbG1lbnQKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RldmljZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYWxsb2NhdGlvbl9jb25jZWFsbWVudCwgdGl0bGVfYWRkID0gIi0gbWVkaWNhbCBkZXZpY2UgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkMuM0IgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBBbGxvY2F0aW9uIGNvbmNlYWxtZW50IC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEJsaW5kaW5nIG9mIHBhcnRpY2lwYW50cyBhbmQgcGVyc29ubmVsCnRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19kZXZpY2UgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KGJsaW5kaW5nX29mX3BhcnRpY2lwYW50c19hbmRfcGVyc29ubmVsLCB0aXRsZV9hZGQgPSAiIC0gbWVkaWNhbCBkZXZpY2UgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkMuM0MgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBCbGluZGluZyBvZiBwYXJ0aWNpcGFudHMgYW5kIHBlcnNvbm5lbCAtIG1lZGljYWwgZGV2aWNlIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBCbGluZGluZyBvZiBvdXRjb21lIGFzc2Vzc21lbnQKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RldmljZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYmxpbmRpbmdfb2Zfb3V0Y29tZV9hc3Nlc3NtZW50LCB0aXRsZV9hZGQgPSAiIC0gbWVkaWNhbCBkZXZpY2UgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkMuM0QgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBCbGluZGluZyBvZiBvdXRjb21lIGFzc2Vzc21lbnQgLSBtZWRpY2FsIGRldmljZSB0cmlhbHMuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoX3RyaXBsZSwgaGVpZ2h0ID0gaW1nX2hlaWdodF90cmlwbGUsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKCiMgSW5jb21wbGV0ZSBvdXRjb21lIGRhdGEKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RldmljZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoaW5jb21wbGV0ZV9vdXRjb21lX2RhdGEsIHRpdGxlX2FkZCA9ICIgLSBtZWRpY2FsIGRldmljZSBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8yQy4zRSBTZW5zaXRpdml0eSBhbmFseXNpcyAtIEluY29tcGxldGUgb3V0Y29tZSBkYXRhIC0gbWVkaWNhbCBkZXZpY2UgdHJpYWxzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIFNlbGVjdGl2ZSByZXBvcnRpbmcKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RldmljZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoc2VsZWN0aXZlX3JlcG9ydGluZywgdGl0bGVfYWRkID0gIiAtIG1lZGljYWwgZGV2aWNlIFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzJDLjNGIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gU2VsZWN0aXZlIHJlcG9ydGluZyAtIG1lZGljYWwgZGV2aWNlIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGhfdHJpcGxlLCBoZWlnaHQgPSBpbWdfaGVpZ2h0X3RyaXBsZSwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQoKIyBPdGhlciBzb3VyY2VzIG9mIGJpYXMKdHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX2RldmljZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQob3RoZXJfc291cmNlc19vZl9iaWFzLCB0aXRsZV9hZGQgPSAiIC0gbWVkaWNhbCBkZXZpY2UgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMkMuM0cgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBPdGhlciBzb3VyY2VzIG9mIGJpYXMgLSBtZWRpY2FsIGRldmljZSB0cmlhbHMuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoX3RyaXBsZSwgaGVpZ2h0ID0gaW1nX2hlaWdodF90cmlwbGUsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgojIyMgNi4gU2Vuc2l0aXZpdHkgYW5hbHlzaXMgIzIgLSBhbGwgdHJpYWxzCgoqRm9yIHRoZXNlIHNlbnNpdGl2aXR5IGFuYWx5c2VzLCBhbGwgdHJpYWxzIHdpbGwgYmUgaW5jbHVkZWQsIGluY2x1ZGluZyB0cmlhbHMgZnJvbSB5ZWFycyB3aXRoIDwgNSB0cmlhbHMqLgoKVGhpcyBtYWtlcyB0aGUgYW5hbHlzZXMgLSBlc3BlY2lhbGx5IG9mIHRoZSByaXNrIG9mIGJpYXMgZG9tYWlucyAtICJmcmFnaWxlIiBhbmQgcmVzdWx0cyBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgd2l0aCBjYXV0aW9uLgoKKipBbmFseXNpcyAzLjE6IFBlcmNlbnRhZ2Ugb2Ygb3ZlcmFsbCBsb3cgcmlzayBvZiBiaWFzIHRyaWFscyBwZXIgeWVhcioqCgpgYGB7cn0KdHJpYWxzX2JpYXNfYXZhaWxhYmxlICU+JSAKICBydW5fY2hhcnQob3ZlcmFsbF9yaXNrX29mX2JpYXMsICJMb3ciLCB0aXRsZSA9ICJPdmVyYWxsIGxvdyByaXNrIG9mIGJpYXMgLSBhbGwgUkNUcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApLCBicmVha3MgPSAxMCAqIDA6MTAsIG1pbm9yX2JyZWFrcyA9IDUgKiAwOjIwLCBsYWJlbHMgPSBwYXN0ZTAoMTAgKiAwOjEwLCAiJSIpLCBleHBhbmQgPSBjKDAuMDE1LCAwKSkKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMy4xIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gb3ZlcmFsbCBsb3cgcmlzayBvZiBiaWFzIC0gYWxsIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKk5PVEUqKjogVGhlICoqeS1heGlzKiogZ29lcyBmcm9tIDAtMTAwJSBpbiB0aGlzIHBsb3QsIHVubGlrZSB0aGUgb3RoZXIgcGxvdHMgb2Ygb3ZlcmFsbCBsb3cgcmlzayBvZiBiaWFzICgwLTUwJSkgZHVlIHRvIGxhcmdlciBkaWZmZXJlbmNlcyBpbiB5ZWFybHkgcHJvcG9ydGlvbnMgY2F1c2VkIGJ5IDEgc2luZ2xlIHRyaWFsIHdpdGggb3ZlcmFsbCBsb3cgcmlzayBvZiBiaWFzIGluIDIwMTguCgpUaGVzZSByZXN1bHRzIGluZGljYXRlIG5vbi1yYW5kb20gdmFyaWF0aW9uLCBob3dldmVyLCB0aGUgbWVkaWFuIHllYXJseSBwcm9wb3J0aW9uIGlzIDAlLiBUaHVzIG5vIHZhbHVlcyBiZWxvdyB0aGUgbWVkaWFuIGFyZSBwb3NzaWJsZSwgYW5kIG5vIGNyb3NzaW5ncyBhcmUgcG9zc2libGUgaW4gdGhlIHJ1biBjaGFydCBhbmQgcnVucyBjbmFub3QgYmUgYnJva2VuLiBUaGlzIHJlc3VsdCBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgd2l0aCBjYXV0aW9uLgoKKipBbmFseXNpcyAzLjI6IEFubnVhbCBtZWRpYW4gc2FtcGxlIHNpemVzKioKCmBgYHtyfQp0cmlhbHNfc2l6ZV9hdmFpbGFibGUgJT4lIAogIHJ1bl9jaGFydChzYW1wbGVfc2l6ZSwgdGl0bGUgPSAiTWVkaWFuIChJUVIpIHNhbXBsZSBzaXplcyAtIGFsbCBSQ1RzIikKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMy4yIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gc2FtcGxlIHNpemVzIC0gYWxsIHRyaWFscy4iLCBpbWdfZm9ybWF0KSwgd2lkdGggPSBpbWdfd2lkdGgsIGhlaWdodCA9IGltZ19oZWlnaHQsIGRwaSA9IGltZ19kcGksIHVuaXRzID0gIm1tIikKYGBgCgoqKkFuYWx5c2lzIDMuMnBoMTogQW5udWFsIG1lYW4gc2FtcGxlIHNpemVzKioKCmBgYHtyfQp0cmlhbHNfc2l6ZV9hdmFpbGFibGUgJT4lIAogIHJ1bl9jaGFydChzYW1wbGVfc2l6ZSwgdGl0bGUgPSAiTWVhbiAoOTUlIENJKSBzYW1wbGUgc2l6ZXMgLSBhbGwgUkNUcyAocG9zdC1ob2MgYW5hbHlzaXMpIiwgbnVtX2FnZ19tZWFuID0gVFJVRSkKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMy4ycGgxIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gc2FtcGxlIHNpemVzIC0gYWxsIHRyaWFscywgcG9zdC1ob2MgdXNpbmcgbWVhbiB2YWx1ZXMuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoLCBoZWlnaHQgPSBpbWdfaGVpZ2h0LCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCmBgYAoKTm90ZTogZm9yIHllYXJzIHdpdGggb25seSAxIHRyaWFsLCB0aGUgZ3JleSByaWJib24gaXMgbWlzc2luZyBhcyBhIGNvbmZpZGVuY2UgaW50ZXJ2YWwgY2Fubm90IGJlIGNhbGN1bGF0ZWQuCgoqKkFuYWx5c2lzIDMuMzogWWVhcmx5IHByb3BvcnRpb24gb2YgbG93LCB1bmNsZWFyIGFuZCBoaWdoIHJpc2sgb2YgYmlhcyByYXRpbmdzIGluIGVhY2ggb2YgdGhlIHNldmVuIGRvbWFpbnMgLSBhbGwgdHJpYWxzKioKCmBgYHtyfQojIFJhbmRvbSBzZXF1ZW5jZSBnZW5lcmF0aW9uCnRyaWFsc19iaWFzX2F2YWlsYWJsZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQocmFuZG9tX3NlcXVlbmNlX2dlbmVyYXRpb24sIHRpdGxlX2FkZCA9ICIgLSBhbGwgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMy4zQSBTZW5zaXRpdml0eSBhbmFseXNpcyAtIFJhbmRvbSBzZXF1ZW5jZSBnZW5lcmF0aW9uLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEFsbG9jYXRpb24gY29uY2VhbG1lbnQKdHJpYWxzX2JpYXNfYXZhaWxhYmxlICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChhbGxvY2F0aW9uX2NvbmNlYWxtZW50LCB0aXRsZV9hZGQgPSAiIC0gYWxsIFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzMuM0IgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBBbGxvY2F0aW9uIGNvbmNlYWxtZW50LiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEJsaW5kaW5nIG9mIHBhcnRpY2lwYW50cyBhbmQgcGVyc29ubmVsCnRyaWFsc19iaWFzX2F2YWlsYWJsZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoYmxpbmRpbmdfb2ZfcGFydGljaXBhbnRzX2FuZF9wZXJzb25uZWwsIHRpdGxlX2FkZCA9ICIgLSBhbGwgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMy4zQyBTZW5zaXRpdml0eSBhbmFseXNpcyAtIEJsaW5kaW5nIG9mIHBhcnRpY2lwYW50cyBhbmQgcGVyc29ubmVsLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEJsaW5kaW5nIG9mIG91dGNvbWUgYXNzZXNzbWVudAp0cmlhbHNfYmlhc19hdmFpbGFibGUgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KGJsaW5kaW5nX29mX291dGNvbWVfYXNzZXNzbWVudCwgdGl0bGVfYWRkID0gIiAtIGFsbCBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8zLjNEIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gQmxpbmRpbmcgb2Ygb3V0Y29tZSBhc3Nlc3NtZW50LiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIEluY29tcGxldGUgb3V0Y29tZSBkYXRhCnRyaWFsc19iaWFzX2F2YWlsYWJsZSAlPiUKICB0cmlwbGVfYmlhc19ydW5fY2hhcnQoaW5jb21wbGV0ZV9vdXRjb21lX2RhdGEsIHRpdGxlX2FkZCA9ICIgLSBhbGwgUkNUcyIpCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvMy4zRSBTZW5zaXRpdml0eSBhbmFseXNpcyAtIEluY29tcGxldGUgb3V0Y29tZSBkYXRhLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIFNlbGVjdGl2ZSByZXBvcnRpbmcKdHJpYWxzX2JpYXNfYXZhaWxhYmxlICU+JQogIHRyaXBsZV9iaWFzX3J1bl9jaGFydChzZWxlY3RpdmVfcmVwb3J0aW5nLCB0aXRsZV9hZGQgPSAiIC0gYWxsIFJDVHMiKQpnZ3NhdmUocGFzdGUwKG91dHB1dF9wYXRoLCAiLzMuM0YgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgLSBTZWxlY3RpdmUgcmVwb3J0aW5nLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCgojIE90aGVyIHNvdXJjZXMgb2YgYmlhcwp0cmlhbHNfYmlhc19hdmFpbGFibGUgJT4lCiAgdHJpcGxlX2JpYXNfcnVuX2NoYXJ0KG90aGVyX3NvdXJjZXNfb2ZfYmlhcywgdGl0bGVfYWRkID0gIiAtIGFsbCBSQ1RzIikKZ2dzYXZlKHBhc3RlMChvdXRwdXRfcGF0aCwgIi8zLjNHIFNlbnNpdGl2aXR5IGFuYWx5c2lzIC0gT3RoZXIgc291cmNlcyBvZiBiaWFzLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aF90cmlwbGUsIGhlaWdodCA9IGltZ19oZWlnaHRfdHJpcGxlLCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCmBgYAoKIyMjIDcuIE92ZXJ2aWV3IG9mIHRoZSBudW1iZXIgb2YgaW5jbHVkZWQgdHJpYWxzIHBlciB5ZWFyCgpDcmVhdGUgYSB0YWJsZSBvZiB0aGUgbnVtYmVyIG9mIGluY2x1ZGVkIHRyaWFscyBwZXIgeWVhciBpbiBlYWNoIGFuYWx5c2lzIChhbmQgaW4gdGhlIGZ1bGwgZGF0YXNldCkuCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQojIFNpbXBsZSBoZWxwZXIgZnVuY3Rpb24Kbl95ZWFycyA8LSBmdW5jdGlvbiguZHRhKXsKICBuYW1lIDwtIHF1b19uYW1lKGVucXVvKC5kdGEpKQogIC5kdGEgJT4lCiAgICBncm91cF9ieSh0cmlhbF95ZWFyKSAlPiUgCiAgICBzdW1tYXJpc2UoISFuYW1lIDo9IG4oKSkgJT4lIAogICAgYXJyYW5nZSh0cmlhbF95ZWFyKQp9Cgp0YmwgPC0gbl95ZWFycyhpbmNsdWRlZF90cmlhbHMpICU+JSAjIEZpcnN0IHJvdyBpcyB0aGUgdG90YWwgbnVtYmVyIG9mIHRyaWFscyBpbmNsdWRlZAogIGxlZnRfam9pbihuX3llYXJzKHRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1cykpICU+JSAjIFByaW1hcnkgYW5hbHlzaXMgLSBiaWFzIGluID49IDUgdHJpYWxzIC95ZWFyCiAgbGVmdF9qb2luKG5feWVhcnModHJpYWxzX3NpemVfYXZhaWxhYmxlXzVwbHVzKSkgJT4lICMgUHJpbWFyeSBhbmFseXNpcyAtIHNpemUgaW4gPj0gNSB0cmlhbHMveWVhcgogIGxlZnRfam9pbihuX3llYXJzKHRyaWFsc19iaWFzX2F2YWlsYWJsZV81cGx1c19kcnVnKSkgJT4lICMgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgIzFBIChkcnVnIHRyaWFscykgLSBiaWFzIGluID49IDUgdHJpYWxzL3llYXIKICBsZWZ0X2pvaW4obl95ZWFycyh0cmlhbHNfc2l6ZV9hdmFpbGFibGVfNXBsdXNfZHJ1ZykpICU+JSAjIFNlbnNpdGl2aXR5IGFuYWx5c2lzICMxQSAoZHJ1ZyB0cmlhbHMpIC0gc2l6ZSBpbiA+PSA1IHRyaWFscy95ZWFyCiAgbGVmdF9qb2luKG5feWVhcnModHJpYWxzX2JpYXNfYXZhaWxhYmxlXzVwbHVzX21hbmFnZW1lbnQpKSAlPiUgIyBTZW5zaXRpdml0eSBhbmFseXNpcyAjMUIgKG1hbmFnZW1lbnQgdHJpYWxzKSAtIGJpYXMgaW4gPj0gNSB0cmlhbHMveWVhcgogIGxlZnRfam9pbihuX3llYXJzKHRyaWFsc19zaXplX2F2YWlsYWJsZV81cGx1c19tYW5hZ2VtZW50KSkgJT4lICMgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgIzFCIChtYW5hZ2VtZW50IHRyaWFscykgLSBzaXplIGluID49IDUgdHJpYWxzL3llYXIKICBsZWZ0X2pvaW4obl95ZWFycyh0cmlhbHNfYmlhc19hdmFpbGFibGVfNXBsdXNfZGV2aWNlKSkgJT4lICMgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgIzFDIChtZWRpY2FsIGRldmljZSB0cmlhbHMpIC0gYmlhcyBpbiA+PSA1IHRyaWFscy95ZWFyCiAgbGVmdF9qb2luKG5feWVhcnModHJpYWxzX3NpemVfYXZhaWxhYmxlXzVwbHVzX2RldmljZSkpICU+JSAjIFNlbnNpdGl2aXR5IGFuYWx5c2lzICMxQyAobWVkaWNhbCBkZXZpY2UgdHJpYWxzKSAtIHNpemUgaW4gPj0gNSB0cmlhbHMveWVhcgogIGxlZnRfam9pbihuX3llYXJzKHRyaWFsc19iaWFzX2F2YWlsYWJsZSkpICU+JSAjIFNlbnNpdGl2aXR5IGFuYWx5c2lzICMyIC0gYmlhcyBpbiBhbGwgdHJpYWxzCiAgbGVmdF9qb2luKG5feWVhcnModHJpYWxzX3NpemVfYXZhaWxhYmxlKSkgJT4lICMgU2Vuc2l0aXZpdHkgYW5hbHlzaXMgIzIgLSBzaXplIGluIGFsbCB0cmlhbHMKICBtdXRhdGVfYWxsKH57aWZlbHNlKGlzLm5hKC4pLCAwLCAuKX0pICMgUmVwbGFjZSBhbGwgTkFzIChtaXNzaW5nKSB3aXRoIDAKCnRibF90b3RhbCA8LSB0YmwgJT4lCiAgc3VtbWFyaXNlX2FsbChzdW0pICU+JSAKICBtdXRhdGUodHJpYWxfeWVhciA9ICJUb3RhbCIpCgp0YmwgJT4lIAogIG11dGF0ZSh0cmlhbF95ZWFyID0gYXMuY2hhcmFjdGVyKHRyaWFsX3llYXIpKSAlPiUgIyBDb252ZXJ0IHRvIHN0cmluZyB0byBhbGxvdyBtZXJnaW5nIHdpdGggdGhlICJUb3RhbCIgcm93CiAgYmluZF9yb3dzKHRibF90b3RhbCkgJT4lICMgTWVyZ2UKICBwcmludCgpICU+JSAjIFByaW50IHRvIFJNYXJrZG93biBkb2N1bWVudAogIHdyaXRlX2NzdihwYXN0ZTAob3V0cHV0X3BhdGgsICIvdHJpYWxzX3Blcl95ZWFyX2luX2VhY2hfYW5hbHlzaXMuY3N2IikpCmBgYAoKIyMjIDguIEFkZGl0aW9uYWwgcGxvdHMKCkNyZWF0ZSB0d28gYWRkaXRpb25hbCBwbG90cyB2aXN1YWxpc2luZyB0aGUgYWJzb2x1dGUgbnVtYmVyczsgdGhlc2UgcGxvdHMgd2VyZSBub3QgcHJlLXBsYW5uZWQsIGJ1dCBhZGRlZCBkdXJpbmcgdGhlIHBlZXIgcmV2aWV3IHByb2Nlc3MuCgoqKkFic29sdXRlIG51bWJlciBvZiBsb3cgYW5kIGhpZ2ggb3ZlcmFsbCByaXNrIG9mIGJpYXMgdHJpYWxzIHBlciB5ZWFyOioqCgpgYGB7cn0KdHJpYWxzX2JpYXNfYXZhaWxhYmxlICU+JSAKICBncm91cF9ieSh0cmlhbF95ZWFyKSAlPiUgCiAgc3VtbWFyaXNlKExvdyA9IHN1bShvdmVyYWxsX3Jpc2tfb2ZfYmlhcyA9PSAiTG93IiksCiAgICAgICAgICAgIEhpZ2ggPSBzdW0ob3ZlcmFsbF9yaXNrX29mX2JpYXMgPT0gIkhpZ2giKSkgJT4lIAogIGdhdGhlcihrZXkgPSAicm9iIiwgdmFsdWUgPSAibiIsIC10cmlhbF95ZWFyKSAlPiUgCiAgYXJyYW5nZSh0cmlhbF95ZWFyKSAlPiUgCiAgbXV0YXRlKHJvYiA9IGZhY3Rvcihyb2IsIGxldmVscyA9IGMoIkxvdyIsICJIaWdoIikpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gdHJpYWxfeWVhciwgeSA9IG4sIGZpbGwgPSByb2IpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzAwQzAwMCIsICIjQzAwMDAwIiksIG5hbWUgPSAiT3ZlcmFsbCByaXNrIG9mIGJpYXM6IikgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiTnVtYmVyIG9mIFJDVHMiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMTk3NSwgMjAyMCksIGJyZWFrcyA9IDE5NzUgKyA1ICogMDo4LCBtaW5vcl9icmVha3MgPSAxOTc1OjIwMjAsIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA1MCksIGJyZWFrcyA9IDA6NSAqIDEwLCBtaW5vcl9icmVha3MgPSAwOjEwICogNSwgZXhwYW5kID0gYygwLCAwKSkgKyAKICB0aGVtZShwbG90Lm1hcmdpbiA9IG1hcmdpbiAodCA9IDUsIGwgPSAxMCwgciA9IDE1LCBiID0gNSwgdW5pdCA9ICJwdCIpLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgIyBGaXggcGxvdCBtYXJnaW5zIHRvIGVuc3VyZSBhbGwgbGFiZWxzIGFyZSBwcmludGVkIGFuZCBjaGFuZ2UgbGVnZW5kIHBvc2l0aW9uCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvQWRkaXRpb25hbCBwbG90cyAtIGFic29sdXRlIG51bWJlciBvZiB0cmlhbHMgYnkgb3ZlcmFsbCByaXNrIG9mIGJpYXMgcGVyIHllYXIuIiwgaW1nX2Zvcm1hdCksIHdpZHRoID0gaW1nX3dpZHRoLCBoZWlnaHQgPSBpbWdfaGVpZ2h0LCBkcGkgPSBpbWdfZHBpLCB1bml0cyA9ICJtbSIpCmBgYAoKKipBYnNvbHV0ZSBudW1iZXIgb2Ygc21hbGwgYW5kIGxhcmdlIHRyaWFscyBwZXIgeWVhcjoqKgoKU21hbGwgdHJpYWxzIGFyZSBkZWZpbmVkIGFzIHRyaWFscyBpbmNsdWRpbmcgPD0gdGhlIG1lZGlhbiBvdmVyYWxsIHNhbXBsZSBzaXplIHBhcnRpY2lwYW50cyBwZXIgeWVhcjsgbGFyZ2UgdHJpYWxzIGFyZSBkZWZpbmVkIGFzIHRyaWFscyBpbmNsdWRpbmcgPiB0aGUgbWVkaWFuIG92ZXJhbCBzYW1wbGUgc2l6ZSBwYXJ0aWNpcGFudHMgcGVyIHllYXIuCgpgYGB7cn0KIyBDYWxjdWxhdGUgbWVkaWFuCm1lZF9zYW1wbGVfc2l6ZSA8LSB0cmlhbHNfc2l6ZV9hdmFpbGFibGUgJT4lCiAgcHVsbChzYW1wbGVfc2l6ZSkgJT4lIAogIG1lZGlhbigpCgojIENhdGVnb3Jpc2UgdHJpYWxzCnRyaWFsc19zaXplX2NhdGVnb3Jpc2VkIDwtIHRyaWFsc19zaXplX2F2YWlsYWJsZSAlPiUgCiAgbXV0YXRlKHNpemVfY2F0ID0gaWZlbHNlKHNhbXBsZV9zaXplIDw9IG1lZF9zYW1wbGVfc2l6ZSwgIlNtYWxsIiwgIkxhcmdlIikpCnN0cl9nbHVlKCJUaGUgb3ZlcmFsbCBtZWRpYW4gc2FtcGxlIHNpemUgaXMge21lZF9zYW1wbGVfc2l6ZX0uCiAgICAgICAgIHtzdW0odHJpYWxzX3NpemVfY2F0ZWdvcmlzZWQkc2l6ZV9jYXQgPT0gJ1NtYWxsJyl9IHRyaWFscyBhcmUgc21hbGwgYW5kIHtzdW0odHJpYWxzX3NpemVfY2F0ZWdvcmlzZWQkc2l6ZV9jYXQgPT0gJ0xhcmdlJyl9IHRyaWFscyBhcmUgbGFyZ2UuIikKCiMgUGxvdAp0cmlhbHNfc2l6ZV9jYXRlZ29yaXNlZCAlPiUgCiAgZ3JvdXBfYnkodHJpYWxfeWVhcikgJT4lIAogIHN1bW1hcmlzZShTbWFsbCA9IHN1bShzaXplX2NhdCA9PSAiU21hbGwiKSwKICAgICAgICAgICAgTGFyZ2UgPSBzdW0oc2l6ZV9jYXQgPT0gIkxhcmdlIikpICU+JSAKICBnYXRoZXIoa2V5ID0gInNpemUiLCB2YWx1ZSA9ICJuIiwgLXRyaWFsX3llYXIpICU+JSAKICBhcnJhbmdlKHRyaWFsX3llYXIpICU+JSAKICBtdXRhdGUoc2l6ZSA9IGZhY3RvcihzaXplLCBsZXZlbHMgPSBjKCJTbWFsbCIsICJMYXJnZSIpKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHRyaWFsX3llYXIsIHkgPSBuLCBmaWxsID0gc2l6ZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjQzAwMDAwIiwgIiMwMEMwMDAiKSwgbmFtZSA9ICJSQ1Qgc2l6ZXM6IikgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiTnVtYmVyIG9mIFJDVHMiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMTk3NSwgMjAyMCksIGJyZWFrcyA9IDE5NzUgKyA1ICogMDo4LCBtaW5vcl9icmVha3MgPSAxOTc1OjIwMjAsIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAzMCksIGJyZWFrcyA9IDA6NiAqIDUsIGV4cGFuZCA9IGMoMCwgMCkpICsgCiAgdGhlbWUocGxvdC5tYXJnaW4gPSBtYXJnaW4gKHQgPSA1LCBsID0gMTAsIHIgPSAxNSwgYiA9IDUsIHVuaXQgPSAicHQiKSwgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICMgRml4IHBsb3QgbWFyZ2lucyB0byBlbnN1cmUgYWxsIGxhYmVscyBhcmUgcHJpbnRlZCBhbmQgY2hhbmdlIGxlZ2VuZCBwb3NpdGlvbgoKCmdnc2F2ZShwYXN0ZTAob3V0cHV0X3BhdGgsICIvQWRkaXRpb25hbCBwbG90cyAtIGFic29sdXRlIG51bWJlciBvZiB0cmlhbHMgYnkgb3ZlcmFsbCBzaXplIHBlciB5ZWFyLiIsIGltZ19mb3JtYXQpLCB3aWR0aCA9IGltZ193aWR0aCwgaGVpZ2h0ID0gaW1nX2hlaWdodCwgZHBpID0gaW1nX2RwaSwgdW5pdHMgPSAibW0iKQpgYGAKCiMjIyA5LiBEYXRlIGFuZCBzZXNzaW9uIGluZm8KClNhdmUgdGhlIGRhdGUgYW5kIHNlc3Npb24gaW5mbyBmb3Igd2hlbiB0aGUgc2NyaXB0IHdhcyBydW4gdG8gdGhlIFJNYXJrZG93bi1IVE1MLWZpbGUuCgpgYGB7cn0KZGF0ZSgpCnNlc3Npb25JbmZvKCkKYGBg