Data handling


# Start Inf data
# --------------

# read data
dtf <- read_dta("./Data/US/startinf_US.dta", encoding = "latin1")

# labels of each variable
dtf_labels <- unlist(lapply(dtf, attr, which = "label"))
# remove labels
dtf <- as.data.frame(lapply(dtf, c))

# notice that for a given frequency,
# the data begins at the start of the period
# it reports (for example with monthly data: date is on the 1st of
# each month)

# fix date
datelookup <- seq.Date(from = as.Date("1946-01-01"),
                       to = as.Date("2015-10-01"),
                       by = "quarter")
dtf$date <- datelookup[ dtf$date + abs(min(dtf$date)) + 1]
# order by date
dtf <- arrange(dtf, date)
# correct magnitude of certain variables
dtf <- dtf %>% mutate(mean_mich = mean_mich/100,
                      variance_mich = variance_mich/(100^2),
                      skewness_mich = skewness_mich) %>% 
               mutate(milong_variance = milong_sd^2,
                      sd_mich = sqrt(variance_mich))

# Greenbook data (Philly FED)
# ---------------------------

# function to compute annual growth from 4 annualized qoq gr
qa2 <- function(x1,x2,x3,x4) {
  qa <- function(x) exp((1/4)*log(1+x))-1
  return((1+qa(x1))*(1+qa(x2))*(1+qa(x3))*(1+qa(x4))-1)
}

dtf <- dtf %>%  
      arrange(date) %>%
      mutate(gPGDPF4_annual = qa2(gPGDPF1,gPGDPF2,gPGDPF3,gPGDPF4))

# Compute forward rates from Livingston survey
# --------------------------------------------

for (n0 in 6) {
  
  q <- 3
  var0 <- paste0("liv_picpi",n0,"_median")
  
  for (nf in 12) {
    
    varf <- paste0("liv_picpi",nf,"_median")
    var1 <- paste0("liv_picpi_f_",n0,"_",nf)
      
    # forward rate
    dtf[,var1] <- ( (1 + dtf[,varf])^(nf/q) ) / ( (1 + dtf[,var0])^(n0/q) )
    dtf[,var1] <- exp( (1/((nf-n0)/q)) * log(dtf[,var1])) - 1
    
    # if desired, forwards are lagged so that
    # their value at time t corresponds to
    # the expectation of the tn - t0 rate at t-tn
    if (bAdjustPeriodTiming) dtf[, var1] <- lag(dtf[, var1], nf/q)
    
  }
  
}

Error in [.data.frame(dtf, , var0) : undefined columns selected

Figures

Timespan is (mostly) 1965/06 to 1975/06

Figure 1: The evolution of the US economy

Subfigure 1(a): Actual Inflation


# actual inflation according to CPI, Core CPI, and GDP deflator between 1960 and 1980 

# vertical line width
vline_w <- 0.3 #mm

# text annotation high titles / mid titles
hfont <- 3.2
mfont <- 2
annotation_height <- 0.14

vars <- c("pi_12", "picore_12", "pigdp12")
legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("CPI Inflation"
          ,"CPI Core Inflation"
          ,"GDP Deflator Inflation")

plot <- ggplot(dtf_long %>%
                 filter(date >= as.Date("1960-01-01") &
                        date <= as.Date("1980-12-31") &
                        variable %in% c("pi_12", "picore_12", "pigdp12") &
                        !is.na(value)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable),
                    size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                             breaks = seq(0,0.16,0.04),
                             limits = c(0,0.14)) +
          scale_x_date(date_breaks="1 year", date_labels = "%Y",
                       limits = c(as.Date("1960-01-01") ,as.Date("1980-12-31")),
                       expand = c(0.02,0)) +
          geom_vline(xintercept = as.numeric(as.Date("1965-05-01")),
                     linetype = "solid", size = tfont(vline_w)) +
          geom_vline(xintercept = as.numeric(as.Date("1971-08-01")),
                     linetype = "longdash", size = tfont(vline_w)) +
          geom_vline(xintercept = as.numeric(as.Date("1973-10-01")),
                     linetype = "longdash", size = tfont(vline_w)) +
          geom_vline(xintercept = as.numeric(as.Date("1974-12-01")),
                     linetype = "solid", size = tfont(vline_w)) +
          scale_linetype_manual(breaks = vars,
                                values = linev,
                                labels = legs) +
          scale_colour_manual(breaks = vars,
                              values = legv,
                              labels = legs) +
          theme(legend.position = c(0.112,0.5)) +
          annotate("text", x = as.Date("1962-06-30"), y = annotation_height,
                   label = "Anchor In Seabed", size = tfont(hfont)) +
          annotate("text", x = as.Date("1968-06-30"), y = annotation_height,
                   label = "A Drifting Anchor", size = tfont(hfont)) +
          annotate("text", x = as.Date("1972-09-01"), y = 0.07,
                   label = "USD Off", size = tfont(mfont)) +
          annotate("text", x = as.Date("1972-09-01"), y = 0.07-0.005,
                   label = "Gold", size = tfont(mfont)) +
          geom_segment(aes(x = as.Date("1972-09-01"), xend = as.Date("1972-02-01"),
                           y = 0.07-0.005-0.005, yend = 0.07-0.005-0.005 - 0.012),
                       arrow = arrow(length = unit(0.5, "cm"))) +
          annotate("text", x = as.Date("1974-05-01"), y = 0.14,
                   label = "First Oil", size = tfont(mfont)) +
          annotate("text", x = as.Date("1974-05-01"), y = 0.14-0.005,
                   label = "Shock", size = tfont(mfont))  +
          geom_segment(aes(x = as.Date("1974-05-01"),
                           xend = as.Date("1974-01-01"),
                           y = 0.14-0.005-0.005,
                           yend = 0.14-0.005-0.005 - 0.02),
                       arrow = arrow(length = unit(0.5, "cm"))) +
          annotate("text", x = as.Date("1977-11-01"), y = annotation_height,
                   label = "Unanchored Inflation", size = tfont(hfont)) +
          theme(legend.position = c(0.42,0.7)) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))
        
print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_1_a.pdf"), plot)


# key numbers for paper
print(mean(dtf$pi_12[dtf$date >= as.Date("1966-01-01") &
                     dtf$date <= as.Date("1973-09-01")],
           na.rm = TRUE)
      )

[1] 0.04246377

# use beginning of quarter
print(dtf$pi_12[dtf$date == as.Date("1965-10-01")])

[1] 0.01923089

print(dtf$pi_12[dtf$date == as.Date("1973-07-01")])

[1] 0.06834541

Subfigure 1(b): Other macroeconomic series

fed funds, 10-year bonds, unemployment rate, federal deficit

with recession bars, 1964:1 to 1974:12


vars <- c("FEDFUNDS", "DGS10","UNRATE","FYFSDFYGDP")
legs <- c("Federal Funds Rate", "10-Year Treasury Yield", "Unemployment Rate", "Annual Federal Deficit (% GDP)")
legv <- create_legv(vars)
linev <- create_linev(vars)

plot <- ggplot(dtf_macro_long %>%
                 filter(variable %in% vars,
                        date >= as.Date("1964-01-01"),
                        date <= as.Date("1974-12-30")) %>%
                 # invert Federal Surplus to federal Deficit
                 mutate(value = ifelse(variable == "FYFSDFYGDP", -value, value)),
               aes(x = date, y = value)) +
  geom_line(aes(colour = variable,
                linetype = variable),
            size = line_size) +
  geom_hline(yintercept = 0) +
  scale_color_manual(breaks = vars, labels = legs, values = legv) +
  scale_linetype_manual(breaks = vars, labels = legs, values = linev) +
  rec_shade + # NBER Recession shading
  theme(legend.position = c(0.25,0.85)) +
  guides(colour = guide_legend(keywidth = 10, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_1_b.pdf"), plot)

Figure(s) 2


vars <- c("liv_picpi12_median",
          "spf_pigdp12_median",
          "gPGDPF4_annual"
          )

legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("Livingston median expected inflation",
          "SPF median expected inflation",
          "Greenbook inflation forecast"
         )

plot <- ggplot(dtf_long %>%
                 filter(date >= as.Date("1965-01-01") &
                        date <= as.Date("1975-06-30") &
                        variable %in% vars &
                        !is.na(value)) %>%
                 mutate(variable = factor(variable, levels = vars)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable), size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          scale_linetype_manual(breaks = vars, values = linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_2.pdf"), plot)

Figure(s) 3

expected inflation (median or mean) from Livingston,

from the SPF on GDP deflators,

and from greenbook between 1965 and 1975

Subfigure 3(a): Greenbook, FED staff


vars <- c("gPGDPF4_annual",
          "gPGDPF4",
          "gPGDPF1"
          )

legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("12 months ahead",
          "9-12 months ahead",
          "3 months ahead"
          )

plot <- ggplot(dtf_long %>%
                 filter(date >= as.Date("1965-06-01") &
                        date <= as.Date("1975-06-30") &
                        variable %in% vars &
                        !is.na(value)) %>%
                 mutate(variable = factor(variable, levels = vars)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable), size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          scale_linetype_manual(breaks = vars, values= linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) + 
          theme(legend.position = c(0.4,0.8)) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_3_a.pdf"), plot)

Subfigure 3(a): Livingston vs Forward


vars <- c("liv_picpi6_median",
          "liv_picpi12_median",
          "liv_picpi_f_6_12"
         )

legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("12 months ahead median",
          "6 months ahead median",
          "6-12 months ahead"
         )

plot <- ggplot(dtf_long %>% 
                filter(date >= as.Date("1965-06-01") &
                       date <= as.Date("1975-06-30") &
                       variable %in% vars &
                       !is.na(value)) %>%
                 mutate(variable = factor(variable, levels = vars)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable), size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          scale_linetype_manual(breaks = vars, values= linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) + 
          theme(legend.position = c(0.3,0.8)) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_3_b.pdf"), plot)

Figure(s) 4: Household qualitative expectations of inflation going up/down


vars <- c("milong_up", "milong_down")
legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("Percentage up",
          "Percentage down")

plot <- ggplot(dtf_long %>% 
                filter(date >= as.Date("1965-06-30") &
                       date <= as.Date("1975-06-30") &
                       variable %in% vars &
                       !is.na(value)) %>% 
                mutate(variable = factor(variable, levels = vars)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable), size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          scale_linetype_manual(breaks = vars, values= linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) +
          theme(legend.position = c(0.2,0.5)) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_4.pdf"), plot)

Figure(s) 5: Cross-sectional mean of expected inflation by households


vars <- c("mean_mich","milong_mean")
legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("Michigan quantitative survey mean",
          "Mankiw-Reis-Wolfers qualitative survey mean")

plot <- ggplot(dtf_long %>% 
                filter(date >= as.Date("1965-06-30") &
                       date <= as.Date("1975-06-30") &
                       variable %in% vars &
                       !is.na(value)) %>%
                 mutate(variable = factor(variable, levels = vars)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable)
                    , size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 1),
                             limits = c(0,0.12)) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          scale_linetype_manual(breaks = vars, values= linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) +
          theme(legend.position = c(0.35,0.9)) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_5.pdf"), plot)

Figure(s) 6: Disagreement about expected inflation among households

Subfigure 6(a): Cross-sectional moments


vars <- c("sd_mich",
          "skewness_mich")

legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("Standard deviation (right axis)",
          "Skewness (left axis)")

df1  <- dtf_long %>% 
        filter(date >= as.Date("1965-06-30") &
               date <= as.Date("1975-06-30") &
               variable %in% "skewness_mich" &
               !is.na(value))

df2  <- dtf_long %>% 
        filter(date >= as.Date("1965-06-30") &
               date <= as.Date("1975-06-30") &
               variable %in% "sd_mich" &
               !is.na(value))

transf_b <- 37
transf_a <- 1.2

plot <- ggplot(df1, aes(x = date)) +
          geom_line(aes(y = value, colour = variable, linetype = variable),
                    size = line_size) +
          geom_line(aes(y = value*transf_b - transf_a, colour = variable, linetype = variable),
                    data = df2, size = line_size) +
          scale_y_continuous(sec.axis = sec_axis( trans = ~ (. + transf_a)/transf_b,
                                                  labels = scales::percent_format(accuracy = 1))
                            ) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          theme(legend.position = c(0.25,0.45)) +
          scale_linetype_manual(breaks = vars, values = linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_6_a.pdf"), plot)

rm(df1, df2)

Subfigure 6(b): Three snapshots of the distribution


# 1967, 1070, 1974: Distribution of Household expectations
# get household distribution from earlier quantitative Michigan survey

dtf_michigan <- read_dta("./Data/US/michigan_moments.dta")

# handle dates
datelookup <- seq.Date(from = as.Date("1966-04-01"),
                       to = as.Date("1976-10-01"),
                       by = "quarter")
dtf_michigan$date <- datelookup[ dtf_michigan$date - min(dtf_michigan$date) + 1]

linev <- c("solid", "dashed", "dotted")
legv <- c('red','blue','green4')
legs <- c("1967", "1970", "1974")

breaks = c(1967, 1970, 1974)

dtf_michigan %<>%
  mutate(year = as.numeric(substr(as.character(date), 1, 4))) %>%
  filter(year %in% breaks) %>%
  rename(inf_downorsame = downorsame,
         inf_dontknowup = dontknowup) %>%
  # articifial data to make smooth curve
  mutate(inf_lower = 0,
         inf_higher = 0) %>%
  # to distribute mass of "dontknowup"
  mutate(mean_positive = (1.5*inf_1to2 + 3.5*inf_3to4 + 5*inf_5 + 7.5*inf_6to9 + 12*inf_10to14)/(inf_1to2 + inf_3to4 + inf_5 + inf_6to9 + inf_10to14)) %>%
  # for "those who "dontknow" use distribution as prior
  # i.e. ignore them
  pivot_longer(cols = starts_with("inf"),
               names_to = "x",
               values_to = "freq") %>%
  mutate(x = as.numeric(recode(x,
                    inf_lower = "-5",
                    inf_downorsame = "-2",
                    inf_1to2 = "1.5",
                    inf_3to4 = "3.5",
                    inf_5 = "5",
                    inf_6to9 = "7.5",
                    inf_10to14 = "12",
                    inf_higher = "17.5",
                    inf_dontknowup = as.character(mean_positive))),
         year = as.factor(year)) %>%
  select(-mean_positive) %>%
  group_by(year, x) %>%
  summarise(frequency = sum(freq),
            .groups = "drop") %>%
  group_by(year) %>%
  mutate(sum = sum(frequency),
         y = frequency/sum) %>%
  select(-c(sum, frequency))

plot <- ggplot(dtf_michigan,
               aes(x = x, y = y, col = year)) +
          stat_density(aes(x = x, weight = y,
                           colour = year, linetype = year),
                       inherit.aes = FALSE,
                       geom = "line",
                       position = "identity",
                       size = line_size,
                       bw = 1.3) +
          scale_x_discrete(limits = c(1.5, 3.5, 5, 7.5, 12)) +
          scale_colour_manual(breaks = breaks, values = legv, labels = legs) +
          scale_linetype_manual(breaks = breaks, values = linev, labels = legs) +
          theme(legend.position = c(0.1, 0.7)) +
          guides(col = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_6_b.pdf"), plot)

Figure(s) 8: Firm expectations of inflation


vars <- unique(dtf_long$variable[grepl("leew_", dtf_long$variable) &
                                 grepl("exp", dtf_long$variable)]
               )

legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("% change in prices of goods and services sold",
          "% change in prices of capital goods purchased")

plot <- ggplot(dtf_long %>% 
                filter(variable %in% vars &
                       !is.na(value) &
                       date <= as.Date("1975-01-01")) %>%
                 mutate(variable = factor(variable, levels = vars)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable), size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          theme(legend.position = c(0.4,0.85)) +
          scale_linetype_manual(breaks = vars, values = linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_8.pdf"), plot)

Figure(s) 9: Gold prices, spot, per ounce


#plot
vars <- c("gold",
          "gold_price")
legv <- c("red","blue","black")
linev <- c("solid","longdash","dashed")
legs <- c("Zurich price",
          "London price",
          "USD to gold ounce convertability")

#USD GOLD PEG
peg <- 35

#position of segment
dtf_peg <- data.frame(x1 = as.Date("1966-03-30"),
                      x2 = as.Date("1971-08-13"),
                      y1 = peg, y2 = peg,
                      leg = "USD gold convertability")

plot <- ggplot(dtf_long %>%
                 filter(date >= as.Date("1966-03-30") &
                        date <= as.Date("1971-06-30") &
                        variable %in% vars &
                        !is.na(value)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable),
                    size = line_size) +
          scale_x_date(date_breaks="1 year", date_labels = "%Y") +
          geom_segment(aes(x = x1, xend = x2, y = y1, yend = y2,
                           colour = leg, linetype = leg),
                       data = dtf_peg, size = 2) +
          scale_colour_manual(values = legv, labels = legs) +
          scale_linetype_manual(values = linev, labels = legs)  +
          theme(legend.position = c(0.2,0.9)) +
          guides(colour = guide_legend(keywidth = 5, keyheight = 1))
          
print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_9.pdf"), plot)
rm(dtf_peg)

Figure(s) 10 - 13: MATLAB or other countries

Figure(s) 14: Dropping the anchor: the US 1980s

Subfigure 14(a): Actual and survey first-order moments


dtf_MRW <- dtf
# clean original michigan values
input <- read_dta("./Data/US/MRWdata_0.dta")
input %<>% mutate(year = floor(date/100),
                  month = date %% 100,
                  quarter = lubridate::quarter(month)) %>%
  group_by(year, quarter) %>%
  summarise(mi_picpi12_mean_original = mean(mi_picpi12_mean),
            mi_picpi12_median_original = mean(mi_picpi12_median),
            .groups = "drop") %>%
  mutate(date = zoo::as.Date(zoo::as.yearqtr(year + ((quarter - 1)/4))))
  
# join
dtf_MRW %<>% left_join(input, by = "date") %>%
  select(-c(mi_picpi12_mean, mi_picpi12_median)) %>%
  rename(mi_picpi12_mean = mi_picpi12_mean_original,
         mi_picpi12_median = mi_picpi12_median_original) %>%
  select(date, spf_pigdp12_median, mi_picpi12_median)

# pivot
dtf_MRW %<>% pivot_longer(cols = !date,
                         names_to = "variable",
                         values_to = "value")
dtf_temp <- dtf_macro %>%
  select(date, CPIAUCSL, CPILFESL) %>%
  arrange(date) %>%
  mutate(inflation_CoreCPI = (CPIAUCSL - lag(CPIAUCSL, n = 4))/lag(CPIAUCSL, n = 4),
         inflation_CPI = (CPILFESL - lag(CPILFESL, n = 4))/lag(CPILFESL, n = 4)) %>%
  pivot_longer(cols = -date,
               names_to = "variable",
               values_to = "value")

dtf_dropping <- full_join(dtf_MRW, dtf_temp, by = c("date", "variable", "value")) %>%
  arrange(date, variable) %>%
  mutate(date = as.Date(date))

vars <- c("spf_pigdp12_median",
          "mi_picpi12_median",
          "inflation_CPI",
          "inflation_CoreCPI")
legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("SPF median",
          "Michigan median",
          "Inflation (CPI)",
          "Inflation (Core CPI)")

plot <- ggplot(dtf_dropping %>%
                 filter(date >= as.Date("1978-01-01") &
                        date <= as.Date("1984-12-30") &
                        variable %in% vars &
                        !is.na(value)) %>%
                 mutate(variable = factor(variable, levels = vars)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable, linetype = variable), size = line_size) +
          scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          scale_linetype_manual(breaks = vars, values= linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) +
          theme(legend.position = c(0.2,0.2)) +
          guides(linetype = guide_legend(keywidth = 5, keyheight = 1))


print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_14_a.pdf"), plot)
rm(dtf_MRW, dtf_temp)

Subfigure 14(b): Survey disagreement


# 1979 - 1985: Disagreement, Skewness for michigan; based on MRW data

# disagreement: standard deviation
# skewness: build from percentiles

vars_right <- c("mi_picpi12_sd")
vars_left <- c("mi_picpi12_skewness")
vars <- c(vars_right, vars_left)
legv <- create_legv(vars)
linev <- create_linev(vars)
legs <- c("Standard deviation (right axis)",
          "Skewness (left axis)")

transf <- 20

dtf_temp <- dtf_long %>%
  filter(date >= as.Date("1979-01-01") &
         date <= as.Date("1984-12-30") &
         variable %in% vars &
         !is.na(value)) %>%
  mutate(variable = factor(variable, levels = vars))

plot <- ggplot(dtf_temp %>%
                 filter(variable %in% c(vars_left)),
               aes(x = date, y = value)) +
          geom_line(aes(colour = variable,
                        linetype = variable),
                    size = line_size) +
          geom_line(data = dtf_temp %>%
                      filter(variable %in% c(vars_right)),
                    aes(x = date, y = transf * value,
                        colour = variable, linetype = variable,
                        order = as.numeric(variable)),
                    size = line_size) +
          scale_y_continuous(sec.axis = sec_axis(trans = ~ (. / transf),
                             labels = scales::percent_format(accuracy = 1))
                            ) +
          scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
          scale_linetype_manual(breaks = vars, values = linev, labels = legs) +  
          scale_colour_manual(breaks = vars, values = legv, labels = legs) +
          theme(legend.position = c(0.4,0.9)) +
          guides(linetype = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_14_b.pdf"), plot)
rm(dtf_temp)

Figure(s) 15: The expected inflation anchor through the pandemic

Subfigure 15(a): Actual inflation


time_series_files <- list.files("./Data/US/US_macrodata", pattern = "*.xls", full.names = TRUE)
dtf_inflation <- as.data.frame(seq.Date(from = as.Date("2016-01-01"),
                                           to = as.Date("2021-07-01"),
                                           by = "month"))
colnames(dtf_inflation) <- "date"

# clean and merge all files in the macrodata-directory
for (filename in time_series_files) {
  if (grepl("USREC", filename)) next
    skip <- 10
    input <- read_xls(filename, skip = skip)
    type_freq <- colnames(read_xls(filename, range = "A10"))
    type_freq <- tolower(gsub("Frequency: ", "", type_freq))
    
    value_name <- gsub(".xls", "", gsub("./Data/US/US_macrodata/", "", filename))
    colnames(input) <- c("date", "value")
    # determine frequency, take means over quarter if necessary
    
    if (type_freq %in% c("monthly")) { # monthly
      input %<>% rename(!!value_name := value)
      dtf_inflation %<>% left_join(input, by = "date")
    }
}

New names: * 0 -> 0...2 * 5.0999999999999996 -> 5.0999999999999996...4 * 5.0999999999999996 -> 5.0999999999999996...5 * 0.29999999999999999 -> 0.29999999999999999...8 * 0 -> 0...9 * …

dtf_inflation %<>%
  mutate(date = as.Date(date),
         CPIAUCSL = 100*( (CPIAUCSL - lag(CPIAUCSL, 12))/lag(CPIAUCSL, 12)),
         CPILFESL = 100*( (CPILFESL - lag(CPILFESL, 12))/lag(CPILFESL, 12)))

dtf_inflation %<>% pivot_longer(cols = -any_of("date"),
                                names_to = "variable",
                                values_to = "value")

vars <- c("CPILFESL", "CPIAUCSL", "PCETRIM12M159SFRBDAL")
linev <- c(create_linev(vars), "solid")
legv <- c(create_legv(vars), "black")
legs <- c("CPI Urban Core", "CPI Urban All Goods", "Trimmed Mean PCE", "Inflation Target")

plot <- ggplot(dtf_inflation %>%
                   filter(variable %in% vars,
                          date >= as.Date("2018-01-01"),
                          date <= as.Date("2021-07-01")) %>%
                   mutate(variable = as.factor(variable)),
                 aes(x = date, y = value)) +
  geom_hline(aes(col = "Inflation Target",
                 linetype = "Inflation Target"),
             yintercept = 2, size = line_size) +
  geom_line(aes(col = variable, linetype = variable),
            size = line_size) +
  scale_y_continuous(labels = function(x) paste(x, "%"), limits = c(-1, 6), breaks = seq(0, 6, by = 1)) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
  scale_linetype_manual(values = linev, labels = legs) +  
  scale_colour_manual(values = legv, labels = legs) +
  theme(legend.position = c(0.5,0.9)) +
  guides(linetype = guide_legend(keywidth = 7, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_15_a.pdf"), plot)

Subfigure 15(b): Markets and survey first-order moments


dtf_households <- read_xlsx("./Data/US/2_Michigan.xlsx", sheet = "Michigan", skip = 2)
dtf_households %<>% rename(date = Date) %>%
  mutate(date = as.Date(date),
         year = year(date),
         quarter = quarter(date)) %>%
  group_by(year, quarter) %>%
  summarise(date = first(date),
            across(starts_with("pie_michigan"), mean),
            .groups = "drop") %>%
  # skew is Pearson's 2nd nonparametric skew coefficient
  mutate(pie_michigan_sd_1y = 3*(pie_michigan_mean_1y -pie_michigan_median_1y) / pie_michigan_skew_1y,
         pie_michigan_sd_5y = 3*(pie_michigan_mean_5y -pie_michigan_median_5y) / pie_michigan_skew_5y)

# read and clean SPF one-year ahead forecast
dtf_nonhouseholds <- read_xlsx("./Data/US/Individual_CPI.xlsx")
dtf_nonhouseholds %<>%
  rename_with(tolower) %>%
  rename(pie_people_1y = cpi6) %>%
  mutate(date = year + ((quarter - 1)/4),
         date = zoo::as.Date(zoo::as.yearqtr(date))) %>%
  select(date, year, quarter, id, industry, pie_people_1y) %>%
  filter(date >= as.Date("2018-01-01")) %>%
  mutate(pie_people_1y = ifelse(pie_people_1y == "#N/A", NA, pie_people_1y),
         pie_people_1y = as.numeric(pie_people_1y),
         industry = as.factor(industry))
levels(dtf_nonhouseholds$industry) <- c("fin", "bus", "unknown")

dtf_nonhouseholds_all <- dtf_nonhouseholds %>%
  group_by(year, quarter) %>%
  summarise(date = first(date),
            pie_people_1y_all_mean = mean(pie_people_1y, na.rm = TRUE),
            pie_people_1y_all_sd = sd(pie_people_1y, na.rm = TRUE),
            pie_people_1y_all_median = median(pie_people_1y, na.rm = TRUE),
            pie_people_1y_all_interq = IQR(pie_people_1y, na.rm = TRUE),
            pie_people_1y_all_skew = moments::skewness(pie_people_1y, na.rm = TRUE),
            .groups = "drop") %>%
  select(-c(year, quarter))

dtf_nonhouseholds_fin <- dtf_nonhouseholds %>%
  filter(as.integer(industry) == 1) %>%
  group_by(year, quarter) %>%
  summarise(date = first(date),
            pie_people_1y_fin_mean = mean(pie_people_1y, na.rm = TRUE),
            pie_people_1y_fin_sd = sd(pie_people_1y, na.rm = TRUE),
            pie_people_1y_fin_median = median(pie_people_1y, na.rm = TRUE),
            pie_people_1y_fin_interq = IQR(pie_people_1y, na.rm = TRUE),
            pie_people_1y_fin_skew = moments::skewness(pie_people_1y, na.rm = TRUE),
            .groups = "drop") %>%
  select(-c(year, quarter))

dtf_nonhouseholds_bus <- dtf_nonhouseholds %>%
  filter(as.integer(industry) == 2) %>%
  group_by(year, quarter) %>%
  summarise(date = first(date),
            pie_people_1y_bus_mean = mean(pie_people_1y, na.rm = TRUE),
            pie_people_1y_bus_sd = sd(pie_people_1y, na.rm = TRUE),
            pie_people_1y_bus_median = median(pie_people_1y, na.rm = TRUE),
            pie_people_1y_bus_interq = IQR(pie_people_1y, na.rm = TRUE),
            pie_people_1y_bus_skew = moments::skewness(pie_people_1y, na.rm = TRUE),
            .groups = "drop") %>%
  select(-c(year, quarter))
  
dtf_nonhouseholds_all %<>%
  left_join(dtf_nonhouseholds_fin, by = "date") %>%
  left_join(dtf_nonhouseholds_bus, by = "date")

# join with Household Survey (Michigan survey of Consumers)
dtf_modern <- left_join(dtf_nonhouseholds_all, dtf_households, by = "date")
dtf_modern %<>% left_join(dtf_macro %>% select(date, T10YIE), by = "date")

dtf_modern %<>%
  pivot_longer(cols = -date,
               names_to = "variable",
               values_to = "value")

vars <- c("pie_michigan_mean_1y", "pie_michigan_mean_5y", "pie_people_1y_all_mean", "T10YIE")
linev <- create_linev(vars)
legv <- create_legv(vars)
legs <- c("People: Michigan 1 Year", "People: Michigan 5 Years", "Traders: SPF 1 Year", "Market: 10 year Breakeven Inflation Rate")

plot <- ggplot(dtf_modern %>%
                 filter(variable %in% vars) %>%
                 mutate(variable = as.factor(variable)),
               aes(x = date, y = value)) +
  geom_line(aes(col = variable, linetype = variable),
            size = line_size) +
  scale_y_continuous(labels = function(x) paste(x, "%")) +
  scale_linetype_manual(breaks = vars, values = linev, labels = legs) +  
  scale_colour_manual(breaks = vars, values = legv, labels = legs) +
  theme(legend.position = c(0.5,0.7)) +
  guides(linetype = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_15_b.pdf"), plot)

Subfigure 15(c): Cross-sectional disagreement of households


vars_left <- c("pie_michigan_skew_1y")
vars_right <- c("pie_michigan_sd_1y")
vars <- c(vars_right, vars_left)
legv <- c('red', 'blue')
linev <- c('solid', 'longdash')
legs <- c("Standard deviation (right axis)", "Skewness (left axis)")

plot <- ggplot(dtf_modern %>%
                 filter(variable %in% vars_left) %>%
                 mutate(variable = as.factor(variable)),
               aes(x = date, y = value)) +
  geom_line(aes(col = variable, linetype = variable),
            size = line_size) +
  geom_line(data = dtf_modern %>%
              filter(variable %in% vars_right) %>%
              mutate(variable = as.factor(variable)),
            aes(x = date, y = value / 4, col = variable, linetype = variable),
            size = line_size) +
  scale_y_continuous(sec.axis = sec_axis(trans = ~ . * 4)) +
  scale_linetype_manual(breaks = vars, values = linev, labels = legs) +  
  scale_colour_manual(breaks = vars, values = legv, labels = legs) +
  theme(legend.position = c(0.3,0.8)) +
  guides(linetype = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_15_c.pdf"), plot)

Plot 4: Distribution of Household Expectations across different months (not quarters, unlike A3!)


# Build monthly histogram of Household Inflation Expectation
dtf_histogram <- read_xlsx("./Data/US/2_Michigan.xlsx", sheet = "Next year", skip = 2)

dtf_histogram %<>%
  rename_with(tolower) %>%
  select(year, month, down, same, starts_with("up"), starts_with("dk")) %>%
  mutate(inf_lowerbound = 0, # fix tails
         inf_upperbound = 0) %>%
  rename(inf_down = down,
         inf_0 = same,
         inf_1to2 = `up by 1-2%`,
         inf_3to4 = `up by 3-4%`,
         inf_5 = `up by 5%`,
         inf_6to9 = `up by 6-9%`,
         inf_10to14 = `up by 10-14%`,
         inf_15plus = `up by 15%+`,
         inf_dontknowup = `up; dk how much`,
         inf_dontknow = `dk; na`
         ) %>%
  mutate(mean_positive = (1.5*inf_1to2 + 3.5*inf_3to4 + 5*inf_5 + 7.5*inf_6to9 + 12*inf_10to14 + 17*inf_15plus)/(inf_1to2 + inf_3to4 + inf_5 + inf_6to9 + inf_10to14 + inf_15plus)) %>% # deal with "dontknowup"
  select(-inf_dontknow) %>% # use common distribution as prior for "dontknow"
  pivot_longer(cols = starts_with("inf"),
               names_to = "x",
               values_to = "freq") %>%
  mutate(x = as.numeric(recode(x,
                    inf_lowerbound = "-5",
                    inf_down = "-2",
                    inf_0 = "0",
                    inf_1to2 = "1.5",
                    inf_3to4 = "3.5",
                    inf_5 = "5",
                    inf_6to9 = "7.5",
                    inf_10to14 = "12",
                    inf_15plus = "17",
                    inf_upperbound = "20",
                    inf_dontknowup = as.character(mean_positive)))) %>%
  select(-mean_positive) %>%
  # turn frequencies into probabilities
  group_by(year, month) %>%
  mutate(sum = sum(freq),
         y = freq /sum) %>%
  select(-c(sum, freq)) %>%
  mutate(date = year + ((month - 1)/12),
         date = zoo::as.Date(zoo::yearmon(date)),
         group = 0,
         group = ifelse(year == 2020 & month == 1, 1, group),
         group = ifelse(year == 2020 & month == 9, 2, group),
         group = ifelse(year == 2021 & month == 6, 3, group))

linev <- c("solid", "dashed", "dotted")
legv <- c('red', 'blue', 'green4')
legs <- c("2020 January", "2020 September", "2021 June")
breaks = c(1, 2, 3)

plot <- ggplot(dtf_histogram %>%
                 filter(group %in% breaks) %>%
                 mutate(group = as.factor(group)),
               aes(x = x, y = y, col = group)) +
          stat_density(aes(x = x, weight = y,
                           colour = group, linetype = group),
                       inherit.aes = FALSE,
                       geom = "line",
                       position = "identity",
                       size = line_size,
                       bw = 1.3) +
          scale_x_discrete(limits = c(0, 1.5, 3.5, 5, 7.5, 12)) +
          scale_colour_manual(breaks = breaks, values = legv, labels = legs) +
          scale_linetype_manual(breaks = breaks, values = linev, labels = legs) +
          theme(legend.position = c(0.6, 0.7)) +
          guides(col = guide_legend(keywidth = 5, keyheight = 1))

print(plot)

if (bSavePlots) my_ggsave(paste0(path_figure_out, "figure_15_d.pdf"), plot)
LS0tCnRpdGxlOiAiQnJvb2tpbmdzIFBhcGVyIC0gRmlndXJlcyAtIFVuaXRlZCBTdGF0ZXMgLSBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3Igc3RhcnRfUiwgaW5jbHVkZSA9IEZBTFNFfQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEluaXRpYXRpb24KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnJtKGxpc3QgPSBscygpKQoKIyBjbGVhbiBjb25zb2xlCmNhdCgiXDAxNCIpCgojIyMjIFBMRUFTRSBDSE9PU0UgIyMjIyMKCiMgcHJpbnQgYW5kIHNhdmUgcGxvdHM/CmJTYXZlUGxvdHMgPC0gMSAgICMgMDogbm8KICAgICAgICAgICAgICAgICAgIyAxOiB5ZXMKCiMgRXhwZWN0YXRpb25zIGF0IFQgPSBULWggb3IgVCtoPwojIHdpbGwgc2hpZnQgYnkgMTIgcGVyaW9kcyAocXVhcnRlcmx5KSwgYmUgY2FyZWZ1bCBmb3IgZS5nLiBxdWFydGVybHkgZGF0YQpiQWRqdXN0UGVyaW9kVGltaW5nIDwtIDEgICAjIDA6IFQraAogICAgICAgICAgICAgICAgICAgICAgICAgICAjIDE6IFQtaAoKIyMjIyAgQ0hPSUNFIEVORCAgICMjIyMjCgojIEJFV0FSRSBPTkxZIFZBUklBQkxFUyBVU0VEIEFSRSBBREpVU1RFRAojIElGIFlPVSBXQU5UIFRPIFVTRSBPVEhFUiBWQVJJQUJMRVMKIyBQTEVBU0UgQUREIFRIRU0gQkVMT1cgV0hFTiBUSEUgQURKVVNUTUVOVAojIElTIE1BREUKCgojIHBhY2thZ2VzCiMgbGlzdCBvZiBsaWJyYXJpZXMKcGFja2FnZXMgPC0gYygidGlkeXZlcnNlIiAgICMgZGF0YSBhbmFseXNpcwogICAgICAgICAgICAgICwia25pdHIiICAgICAgIyBtYXJrZG93bgogICAgICAgICAgICAgICwiaGF2ZW4iICAgICAgIyByZWFkIC5kdGEgZmlsZXMKICAgICAgICAgICAgICAsInJlYWR4bCIgICAgICMgcmVhZCBleGNlbCBmaWxlcwogICAgICAgICAgICAgICwibHVicmlkYXRlIiAgIyBkYXRlcwogICAgICAgICAgICAgICwidGlueXRleCIgICAgIyBmb3IgbWFya2Rvd24KICAgICAgICAgICAgICAsImNvbG9yc3BhY2UiICMgZm9yIGN1c3RvbSBjb2xvdXJpbmcgcGxvdHMKICAgICAgICAgICAgICAsIm1hZ3JpdHRyIiAgICMgcGlwZSBvcGVyYXRvcgogICAgICAgICAgICAgICwibW9tZW50cyIgICAgIyBza2V3bmVzcwopCgojIGluc3RhbGwgdGhlbSBpZiBuZWVkZWQKbmV3X3BhY2thZ2VzIDwtCiAgcGFja2FnZXNbIShwYWNrYWdlcyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywgIlBhY2thZ2UiXSldIAoKIGlmIChsZW5ndGgobmV3X3BhY2thZ2VzKSA+IDApeyAjaW5zdGFsbHMgdGhlbQogICBpbnN0YWxsLnBhY2thZ2VzKG5ld19wYWNrYWdlcywgZGVwZW5kZW5jaWVzID0gVFJVRSkKfQoKIyBsb2FkIGxpYnJhcmllcwpsYXBwbHkocGFja2FnZXMsIHJlcXVpcmUsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKCmBgYAoKYGBge3IgcGxvdF9kZWYsIGluY2x1ZGUgPSBGQUxTRX0KCiMgc2l6ZSBvZiBmaWd1cmVzIGZvciBzYXZpbmcgYW5kIGRpc3BsYXlpbmcgKGRpc3Agd2lsbCBiZSBhZGp1c3RlZCkKIyBmaWd1cmUgc2l6ZSBpbiBjbSAoZm9yIGluY2hlcyBkaXZpZGUgYnkgMC4zOTM3MDA3ODcpCmZpZ19oIDwtIDIuNSAqIDguNDM3NSogMC4zOTM3MDA3ODcgIyB3aWR0aApmaWdfdyA8LSAyLjUgKiAxNSAqIDAuMzkzNzAwNzg3ICAgICMgaGVpZ2h0CmZpZ19kaXNwX2FkaiA8LSAxICAgICAgICAgICAgICAgICAgIyBhZGp1c3RtZW50IGZvciBmaWd1cmUgZGlzcGxheQoKIyBjb252ZXJ0IGZyb20gbW0gdG8gaW50ZXJuYWwgdW5pdHMgdXNlZCBpbiBncmlkIGdncGxvdAp0Zm9udCA8LSBmdW5jdGlvbih4KSByZXR1cm4oLnB0KngpICAgICAgICAjIHRoaXMgd2F5IG5vIHJlcyBwcm9ibGVtcwp0bHdkICA8LSBmdW5jdGlvbih4KSByZXR1cm4oLnN0cm9rZSp4KSAKCiMgZ2dwbG90MiBvcHRpb25zCiMgcGxvdCBkZWZpbml0aW9ucyAKCmxlZ2VuZF90ZXh0X3NpemUgPC0gNy41CmF4aXNfdGV4dF9zaXplICAgPC0gNwoKbGVnZW5kX2tleV93aWR0aCA8LSAxMCAjIG1tCgojIHNpemUgb2YgbGluZSBmb3IgcGxvdHMKbGluZV9zaXplIDwtIHRsd2QoMSkKCnRoZW1lX3NldCgKICB0aGVtZV9taW5pbWFsKCkgKwogICAgICAgICAgICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAicGxhaW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSB0Zm9udCg2KSksCiAgICAgICAgICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgICAgICAgICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAwLjUpLAogICAgICAgICAgICAgICAgICBsZWdlbmQuYm94LmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjI1LDAuOCksCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IE5BKSwKICAgICAgICAgICAgICAgICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQobGVnZW5kX2tleV93aWR0aCwgIm1tIiksICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0Zm9udChsZWdlbmRfdGV4dF9zaXplKSksCiAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCAgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHRmb250KGF4aXNfdGV4dF9zaXplKSksCiAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgICAgICkKKQoKIyBmdW5jdGlvbnMgdG8gY3JlYXRlIGNvbG91ci9saW5lIHNjaGVtZQoKY3JlYXRlX2xlZ3YgPC0gZnVuY3Rpb24oeCkgewogICMgY29sb3VycyB0byBiZSB1c2VkIGluIHBsb3RzCiAgeSA8LSBjKCdyZWQnLCdibHVlJywnZ3JlZW40Jywnb3JhbmdlJywnb3JhbmdlJywgJ3llbGxvdycsICdwdXJwbGUnLCAnYmxhY2snKQogIG4gPC0gbGVuZ3RoKHgpCiAgeSA8LSB5WzE6bl0KICBuYW1lcyh5KSA8LSB4IAogIHJldHVybih5KQp9CgpjcmVhdGVfbGluZXYgPC0gZnVuY3Rpb24oeCkgewogICNjb2xvdXJzIHRvIGJlIHVzZWQgaW4gcGxvdHMKICB5IDwtIGMoJ3NvbGlkJywnbG9uZ2Rhc2gnLCdkb3R0ZWQnLCdkb3RkYXNoJykKICBuIDwtIGxlbmd0aCh4KQogIHkgPC0geVsxOm5dCiAgbmFtZXMoeSkgPC0geCAKICByZXR1cm4oeSkKfQoKbXlfZ2dzYXZlIDwtIGZ1bmN0aW9uKC5maWxlbmFtZSwgLnBsb3QsCiAgICAgICAgICAgICAgICAgICAgICAuZGV2aWNlID0gInBkZiIsCiAgICAgICAgICAgICAgICAgICAgICAud2lkdGggPSBmaWdfdywgLmhlaWdodCA9IGZpZ19oLCAudW5pdHMgPSAiaW4iLCAuZHBpID0gMzAwLCAuLi4pIHsKICAKICBnZ3NhdmUoZmlsZW5hbWUgPSAuZmlsZW5hbWUsIHBsb3QgPSAucGxvdCwKICAgICAgICAgZGV2aWNlID0gLmRldmljZSwgd2lkdGggPSAud2lkdGgsIGhlaWdodCA9IC5oZWlnaHQsCiAgICAgICAgIHVuaXRzID0gLnVuaXRzLCBkcGkgPSAuZHBpLCAuLi4pCiAgCn0KCmBgYAoKCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9CgojIGRpcmVjdG9yeQpkaXJlY3RvcnkgPC0gZ2V0d2QoKQpkaXJlY3RvcnkgPC0gZ3N1YigiL0NvZGUiLCAiIiwgZGlyZWN0b3J5KQpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gZGlyZWN0b3J5KQoKcGF0aF9maWd1cmVfb3V0IDwtICIuL0ZpZ3VyZXMvIgoKIyBkZWZhdWx0IGNodW5rIG9wdGlvbnMKb3B0c19jaHVuayRzZXQobWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIHJlc3VsdHMgPSAnYXNpcycsIGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICBmaWcud2lkdGggPSBmaWdfZGlzcF9hZGogKiBmaWdfdywgZmlnLmhlaWdodCA9IGZpZ19kaXNwX2FkaiAqIGZpZ19oLAogICAgICAgICAgICAgICBmaWcucmV0aW5hID0gMSkgIyBmaWd1cmUgb3B0aW9ucwoKYGBgCgojIyBEYXRhIGhhbmRsaW5nCgpgYGB7ciBsb2FkX2RhdGF9CgojIFN0YXJ0IEluZiBkYXRhCiMgLS0tLS0tLS0tLS0tLS0KCiMgcmVhZCBkYXRhCmR0ZiA8LSByZWFkX2R0YSgiLi9EYXRhL1VTL3N0YXJ0aW5mX1VTLmR0YSIsIGVuY29kaW5nID0gImxhdGluMSIpCgojIGxhYmVscyBvZiBlYWNoIHZhcmlhYmxlCmR0Zl9sYWJlbHMgPC0gdW5saXN0KGxhcHBseShkdGYsIGF0dHIsIHdoaWNoID0gImxhYmVsIikpCiMgcmVtb3ZlIGxhYmVscwpkdGYgPC0gYXMuZGF0YS5mcmFtZShsYXBwbHkoZHRmLCBjKSkKCiMgbm90aWNlIHRoYXQgZm9yIGEgZ2l2ZW4gZnJlcXVlbmN5LAojIHRoZSBkYXRhIGJlZ2lucyBhdCB0aGUgc3RhcnQgb2YgdGhlIHBlcmlvZAojIGl0IHJlcG9ydHMgKGZvciBleGFtcGxlIHdpdGggbW9udGhseSBkYXRhOiBkYXRlIGlzIG9uIHRoZSAxc3Qgb2YKIyBlYWNoIG1vbnRoKQoKIyBmaXggZGF0ZQpkYXRlbG9va3VwIDwtIHNlcS5EYXRlKGZyb20gPSBhcy5EYXRlKCIxOTQ2LTAxLTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgdG8gPSBhcy5EYXRlKCIyMDE1LTEwLTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicXVhcnRlciIpCmR0ZiRkYXRlIDwtIGRhdGVsb29rdXBbIGR0ZiRkYXRlICsgYWJzKG1pbihkdGYkZGF0ZSkpICsgMV0KIyBvcmRlciBieSBkYXRlCmR0ZiA8LSBhcnJhbmdlKGR0ZiwgZGF0ZSkKIyBjb3JyZWN0IG1hZ25pdHVkZSBvZiBjZXJ0YWluIHZhcmlhYmxlcwpkdGYgPC0gZHRmICU+JSBtdXRhdGUobWVhbl9taWNoID0gbWVhbl9taWNoLzEwMCwKICAgICAgICAgICAgICAgICAgICAgIHZhcmlhbmNlX21pY2ggPSB2YXJpYW5jZV9taWNoLygxMDBeMiksCiAgICAgICAgICAgICAgICAgICAgICBza2V3bmVzc19taWNoID0gc2tld25lc3NfbWljaCkgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUobWlsb25nX3ZhcmlhbmNlID0gbWlsb25nX3NkXjIsCiAgICAgICAgICAgICAgICAgICAgICBzZF9taWNoID0gc3FydCh2YXJpYW5jZV9taWNoKSkKCiMgR3JlZW5ib29rIGRhdGEgKFBoaWxseSBGRUQpCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIGZ1bmN0aW9uIHRvIGNvbXB1dGUgYW5udWFsIGdyb3d0aCBmcm9tIDQgYW5udWFsaXplZCBxb3EgZ3IKcWEyIDwtIGZ1bmN0aW9uKHgxLHgyLHgzLHg0KSB7CiAgcWEgPC0gZnVuY3Rpb24oeCkgZXhwKCgxLzQpKmxvZygxK3gpKS0xCiAgcmV0dXJuKCgxK3FhKHgxKSkqKDErcWEoeDIpKSooMStxYSh4MykpKigxK3FhKHg0KSktMSkKfQoKZHRmIDwtIGR0ZiAlPiUgIAogICAgICBhcnJhbmdlKGRhdGUpICU+JQogICAgICBtdXRhdGUoZ1BHRFBGNF9hbm51YWwgPSBxYTIoZ1BHRFBGMSxnUEdEUEYyLGdQR0RQRjMsZ1BHRFBGNCkpCgojIENvbXB1dGUgZm9yd2FyZCByYXRlcyBmcm9tIExpdmluZ3N0b24gc3VydmV5CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmZvciAobjAgaW4gNikgewogIAogIHEgPC0gMwogIHZhcjAgPC0gcGFzdGUwKCJsaXZfcGljcGkiLG4wLCJfbWVkaWFuIikKICAKICBmb3IgKG5mIGluIDEyKSB7CiAgICAKICAgIHZhcmYgPC0gcGFzdGUwKCJsaXZfcGljcGkiLG5mLCJfbWVkaWFuIikKICAgIHZhcjEgPC0gcGFzdGUwKCJsaXZfcGljcGlfZl8iLG4wLCJfIixuZikKICAgICAgCiAgICAjIGZvcndhcmQgcmF0ZQogICAgZHRmWyx2YXIxXSA8LSAoICgxICsgZHRmWyx2YXJmXSleKG5mL3EpICkgLyAoICgxICsgZHRmWyx2YXIwXSleKG4wL3EpICkKICAgIGR0ZlssdmFyMV0gPC0gZXhwKCAoMS8oKG5mLW4wKS9xKSkgKiBsb2coZHRmWyx2YXIxXSkpIC0gMQogICAgCiAgICAjIGlmIGRlc2lyZWQsIGZvcndhcmRzIGFyZSBsYWdnZWQgc28gdGhhdAogICAgIyB0aGVpciB2YWx1ZSBhdCB0aW1lIHQgY29ycmVzcG9uZHMgdG8KICAgICMgdGhlIGV4cGVjdGF0aW9uIG9mIHRoZSB0biAtIHQwIHJhdGUgYXQgdC10bgogICAgaWYgKGJBZGp1c3RQZXJpb2RUaW1pbmcpIGR0ZlssIHZhcjFdIDwtIGxhZyhkdGZbLCB2YXIxXSwgbmYvcSkKICAgIAogIH0KICAKfQoKIyBhZGp1c3RtZW50IG9mIGxlYWQgZGF0YQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIGJlIGNhcmVmdWwuIElmIHlvdSB1c2UgbW9yZSB0aGFuIG9uZSB5ZWFyIGhvcml6b25zLCB5b3UgaGF2ZQojIHRvIGFkanVzdCB0aGUgbGFnZ2luZwogCmlmIChiQWRqdXN0UGVyaW9kVGltaW5nKSB7CiAgZHRmIDwtIGR0ZiAlPiUKICAgIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJnUEdEUEY0IiksCiAgICAgICAgICAgICAgICAgICAibGl2X3BpY3BpMTJfbWVkaWFuIiwKICAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJzcGYiKSwKICAgICAgICAgICAgICAgICAgIGVuZHNfd2l0aCgibWljaCIpLAogICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIm1pbG9uZyIpLAogICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIm1pIikpLAogICAgICAgICAgICAgIH4gbGFnKC4sNCkgKSAlPiUKICAgIG11dGF0ZShnUEdEUEYxID0gbGFnKGdQR0RQRjEsIDEpLAogICAgICAgICAgIGdQR0RQRjIgPSBsYWcoZ1BHRFBGMiwgMiksCiAgICAgICAgICAgZ1BHRFBGMyA9IGxhZyhnUEdEUEYzLCAzKSwKICAgICAgICAgICBsaXZfcGljcGk2X21lZGlhbiA9IGxhZyhsaXZfcGljcGk2X21lZGlhbiwgMikgI3F1YXJ0ZXJseSBkYXRhCiAgICAgICAgICAgIyBub3RpY2UgdGhlcmUgaXMgbm8gIi0xIiBhcyB0aGUgcmF3IGRhdGEgaXMgZW5kIG9mIHBlcmlvZAogICAgICAgICAgICkKfQogCiMgZGF0YSBpcyBhbm51YWwgc28gcHV0dGluZyBpdCBpbiBiZWdpbm5pbmcgb2YgeWVhcgpkdGYgPC0gZHRmICU+JQogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJsZWV3XyIpLAogICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJwcm9xdWVzdCIpKSwKICAgICAgICAgICAgfmxlYWQoLiwgMykpCiAKIyBGaXNjaGVyLUh1aXppbmdhIGRhdGEKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgaW1wb3J0IC5kdGEgZmlsZSAoYXMgUmljYXJkbyBhc2tlZCB0byBiZSBzZXBhcmF0ZSkKZHRmOSA8LSByZWFkX2R0YSgiRGF0YS9VUy9maXNjaGVyX2h1aXppbmdhLmR0YSIpCgojIHRha2UgY2FyZSBvZiBkYXRlCmRhdGVsb29rdXAgPC0gc2VxLkRhdGUoYXMuRGF0ZSgiMTkzOS0wMS0wMSIpLAogICAgICAgICAgICAgICAgICAgICAgIGFzLkRhdGUoIjE5NzgtMTItMDEiKSwKICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJtb250aCIpCgpkdGY5JGRhdGUgPC0gZGF0ZWxvb2t1cFtkdGY5JGRhdGUgLSBtaW4oZHRmOSRkYXRlKSArIDFdCgojIHF1YXJ0ZXJseSBpbnN0ZWFkIG9mIG1vbnRobHkgZnJlcXVlbmN5CmR0ZjkkeXEgPC0gem9vOjphcy55ZWFycXRyKGR0ZjkkZGF0ZSkKCmR0ZjkgPC0gZHRmOSAlPiUgCiAgZ3JvdXBfYnkoeXEpICU+JQogIHN1bW1hcml6ZShkYXRlID0gZmlyc3QoZGF0ZSksCiAgICAgICAgICAgIGluZmxhdGlvbiA9IG1lYW4oaW5mbGF0aW9uLzEwMCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgdW5lbXBsb3ltZW50ID0gbWVhbih1bmVtcGxveW1lbnQvMTAwLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBzZWxlY3QoLXlxKSAlPiUgCiAgbXV0YXRlKGluZmxhdGlvbl9taW51c19lbXBsb3ltZW50ID0gaW5mbGF0aW9uIC0gdW5lbXBsb3ltZW50KSAlPiUgCiAgcmVuYW1lX2F0KHZhcnMoLWRhdGUpLCB+IHBhc3RlMCgiZ2FsbHVwXyIsLikpCgojIG1lcmdlIHRoZSB0d28KZHRmIDwtIG1lcmdlKGR0ZiwgZHRmOSwgYnkgPSAiZGF0ZSIsIGFsbCA9IFRSVUUpCnJtKGR0ZjkpCgojIHBsb3QKCiMgc2tld25lc3MgZnJvbSBNaWNoaWdhbiBzdXJ2ZXktcGVyY2VudGlsZXMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyB0YWtlIG1pZHBvaW50IG9mIGJpbnMgZnJvbSBlbXBpcmljYWwgY2RmIHRvIGVzdGltYXRlIHNrZXduZXNzCmR0ZiRtaV9waWNwaTEyX3NrZXduZXNzIDwtIHdpdGgoZHRmLAogICAgICAgICAgICAgICAgICAgICAoKDEvMC45OCkgKgogICAgICAgICAgICAgICAgICAgICAgICgwLjA0ICogKG1pX3BpY3BpMTJfNSAtICBtaV9waWNwaTEyXzEpIF4zICsKICAgICAgICAgICAgICAgICAgICAgICAgMC4wNSAqIChtaV9waWNwaTEyXzEwIC0gbWlfcGljcGkxMl81KSBeMyArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMSAqICAobWlfcGljcGkxMl8yMCAtIG1pX3BpY3BpMTJfMTApXjMgKwogICAgICAgICAgICAgICAgICAgICAgICAwLjA1ICogKG1pX3BpY3BpMTJfMjUgLSBtaV9waWNwaTEyXzIwKV4zICsKICAgICAgICAgICAgICAgICAgICAgICAgMC4wOCAqIChtaV9waWNwaTEyXzMzIC0gbWlfcGljcGkxMl8yNSleMyArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMTcgKiAobWlfcGljcGkxMl81MCAtIG1pX3BpY3BpMTJfMzMpXjMgKwogICAgICAgICAgICAgICAgICAgICAgICAwLjE3ICogKG1pX3BpY3BpMTJfNjcgLSBtaV9waWNwaTEyXzUwKV4zICsKICAgICAgICAgICAgICAgICAgICAgICAgMC4wOCAqIChtaV9waWNwaTEyXzc1IC0gbWlfcGljcGkxMl82NyleMyArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMDUgKiAobWlfcGljcGkxMl84MCAtIG1pX3BpY3BpMTJfNzUpXjMgKwogICAgICAgICAgICAgICAgICAgICAgICAwLjEgKiAgKG1pX3BpY3BpMTJfOTAgLSBtaV9waWNwaTEyXzgwKV4zICsKICAgICAgICAgICAgICAgICAgICAgICAgMC4wNSAqIChtaV9waWNwaTEyXzk1IC0gbWlfcGljcGkxMl85MCleMyArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMDQgKiAobWlfcGljcGkxMl85OSAtIG1pX3BpY3BpMTJfOTUpXjMKICAgICAgICAgICAgICAgICAgICAgICApKSAvCiAgICAgICAgICAgICAgICAgICAgICgoMS8wLjk4KSAqCiAgICAgICAgICAgICAgICAgICAgICAgICgKICAgICAgICAgICAgICAgICAgICAgICAgMC4wNCAqIChtaV9waWNwaTEyXzUgLSAgbWlfcGljcGkxMl8xKSBeMiArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMDUgKiAobWlfcGljcGkxMl8xMCAtIG1pX3BpY3BpMTJfNSkgXjIgKwogICAgICAgICAgICAgICAgICAgICAgICAwLjEgKiAgKG1pX3BpY3BpMTJfMjAgLSBtaV9waWNwaTEyXzEwKV4yICsKICAgICAgICAgICAgICAgICAgICAgICAgMC4wNSAqIChtaV9waWNwaTEyXzI1IC0gbWlfcGljcGkxMl8yMCleMiArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMDggKiAobWlfcGljcGkxMl8zMyAtIG1pX3BpY3BpMTJfMjUpXjIgKwogICAgICAgICAgICAgICAgICAgICAgICAwLjE3ICogKG1pX3BpY3BpMTJfNTAgLSBtaV9waWNwaTEyXzMzKV4yICsKICAgICAgICAgICAgICAgICAgICAgICAgMC4xNyAqIChtaV9waWNwaTEyXzY3IC0gbWlfcGljcGkxMl81MCleMiArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMDggKiAobWlfcGljcGkxMl83NSAtIG1pX3BpY3BpMTJfNjcpXjIgKwogICAgICAgICAgICAgICAgICAgICAgICAwLjA1ICogKG1pX3BpY3BpMTJfODAgLSBtaV9waWNwaTEyXzc1KV4yICsKICAgICAgICAgICAgICAgICAgICAgICAgMC4xICogIChtaV9waWNwaTEyXzkwIC0gbWlfcGljcGkxMl84MCleMiArCiAgICAgICAgICAgICAgICAgICAgICAgIDAuMDUgKiAobWlfcGljcGkxMl85NSAtIG1pX3BpY3BpMTJfOTApXjIgKwogICAgICAgICAgICAgICAgICAgICAgICAwLjA0ICogKG1pX3BpY3BpMTJfOTkgLSBtaV9waWNwaTEyXzk1KV4yCiAgICAgICAgICAgICAgICAgICAgICAgICkpXigzLzIpCiAgICAgICAgICAgICAgICAgICAgKQogCiMgcGl2b3QgZGF0YSB0byBsb25nIGZvcm1hdApkdGZfbG9uZyA8LSBwaXZvdF9sb25nZXIoZHRmICU+JSBzZWxlY3QoLWQpLAogICAgICAgICAgICAgICAgICAgICAgICAgIWRhdGUsIG5hbWVzX3RvID0gInZhcmlhYmxlIiwgdmFsdWVzX3RvID0gInZhbHVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190cmFuc2Zvcm0gPSBhcy5udW1lcmljKQoKIyByZWFkIG1hY3JvZWNvbm9taWMgZGF0YQoKdGltZV9zZXJpZXNfZmlsZXMgPC0gbGlzdC5maWxlcygiLi9EYXRhL1VTL1VTX21hY3JvZGF0YSIsIHBhdHRlcm4gPSAiKi54bHMiLCBmdWxsLm5hbWVzID0gVFJVRSkKZHRmX21hY3JvIDwtIGFzLmRhdGEuZnJhbWUoc2VxLkRhdGUoZnJvbSA9IGFzLkRhdGUoIjE5NDYtMDEtMDEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG8gPSBhcy5EYXRlKCIyMDIxLTEwLTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gInF1YXJ0ZXIiKSkKY29sbmFtZXMoZHRmX21hY3JvKSA8LSAiZGF0ZSIKCiMgY2xlYW4gYW5kIG1lcmdlIGFsbCBmaWxlcyBpbiB0aGUgbWFjcm9kYXRhLWRpcmVjdG9yeQpmb3IgKGZpbGVuYW1lIGluIHRpbWVfc2VyaWVzX2ZpbGVzKSB7CiAgaWYgKCFncmVwbCgiUm9tZXJhbmRSb21lciIsIGZpbGVuYW1lKSkgewogICAgIyBGUkVEIHNlcmllcywgcmVhZCBkYXRhCiAgICBza2lwIDwtIDEwCiAgICBpZiAoZ3JlcGwoIlVTUkVDIiwgZmlsZW5hbWUpKSBza2lwIDwtIDEyMTEKICAgIGlucHV0IDwtIHJlYWRfeGxzKGZpbGVuYW1lLCBza2lwID0gc2tpcCkKICAgIHZhbHVlX25hbWUgPC0gZ3N1YigiLnhscyIsICIiLCBnc3ViKCIuL0RhdGEvVVMvVVNfbWFjcm9kYXRhLyIsICIiLCBmaWxlbmFtZSkpCiAgICBjb2xuYW1lcyhpbnB1dCkgPC0gYygiZGF0ZSIsICJ2YWx1ZSIpCiAgICAjIGRldGVybWluZSBmcmVxdWVuY3ksIHRha2UgbWVhbnMgb3ZlciBxdWFydGVyIGlmIG5lY2Vzc2FyeQogICAgdHlwZV9mcmVxIDwtIGNvbG5hbWVzKHJlYWRfeGxzKGZpbGVuYW1lLCByYW5nZSA9ICJBMTAiKSkKICAgIHR5cGVfZnJlcSA8LSB0b2xvd2VyKGdzdWIoIkZyZXF1ZW5jeTogIiwgIiIsIHR5cGVfZnJlcSkpCiAgICAKICAgIGlmICh0eXBlX2ZyZXEgJWluJSBjKCJtb250aGx5IiwgImRhaWx5IikpIHsgIyBtb250aGx5LCBkYWlseQogICAgICBpbnB1dCAlPD4lCiAgICAgICAgbXV0YXRlKHllYXIgPSB5ZWFyKGRhdGUpLAogICAgICAgICAgICAgICBxdWFydGVyID0gcXVhcnRlcihkYXRlKSkKICAgIAogICAgICBpZiAodmFsdWVfbmFtZSA9PSAiVVNSRUMiKSB7CiAgICAgIGlucHV0ICU8PiUKICAgICAgICAgIGdyb3VwX2J5KHllYXIsIHF1YXJ0ZXIpICU+JQogICAgICAgICAgc3VtbWFyaXNlKHZhbHVlID0gbWF4KHZhbHVlKSwKICAgICAgICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIikKICAgICAgfSBlbHNlIHsKICAgICAgICBpbnB1dCAlPD4lCiAgICAgICAgICBncm91cF9ieSh5ZWFyLCBxdWFydGVyKSAlPiUKICAgICAgICAgIHN1bW1hcmlzZSh2YWx1ZSA9IG1lYW4odmFsdWUpLAogICAgICAgICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKQogICAgICB9CiAgICAgIGlucHV0ICU8PiUKICAgICAgICBtdXRhdGUodGVtcCA9IHBhc3RlMChhcy5jaGFyYWN0ZXIoeWVhciksICIgUSIsIGFzLmNoYXJhY3RlcihxdWFydGVyKSksCiAgICAgICAgICAgICAgIGRhdGUgPSB6b286OmFzLkRhdGUoem9vOjphcy55ZWFycXRyKHRlbXAsIGZvcm1hdCA9ICIlWSBRJXEiKSkpICU+JQogICAgICAgIHNlbGVjdChkYXRlLCB2YWx1ZSkgJT4lCiAgICAgICAgcmVuYW1lKCEhdmFsdWVfbmFtZSA6PSB2YWx1ZSkKICAgICAgZHRmX21hY3JvICU8PiUgbGVmdF9qb2luKGlucHV0LCBieSA9ICJkYXRlIikKICAgIH0KICAgIAogICAgaWYgKHR5cGVfZnJlcSAlaW4lIGMoImFubnVhbCwgZmlzY2FsIHllYXIiKSkgeyAjIGFubnVhbAogICAgICBpbnB1dCAlPD4lCiAgICAgICAgbXV0YXRlKHllYXIgPSB5ZWFyKGRhdGUpKSAlPiUKICAgICAgICBzZWxlY3QoeWVhciwgdmFsdWUpICU+JQogICAgICAgIHJlbmFtZSghIXZhbHVlX25hbWUgOj0gdmFsdWUpCiAgICAgIAogICAgICBkdGZfbWFjcm8gJTw+JQogICAgICAgIG11dGF0ZSh5ZWFyID0geWVhcihkYXRlKSkgJT4lCiAgICAgICAgbGVmdF9qb2luKGlucHV0LCBieSA9ICJ5ZWFyIikgJT4lCiAgICAgICAgc2VsZWN0KC15ZWFyKQogICAgfQogICAgCiAgICBpZiAodHlwZV9mcmVxICVpbiUgYygicXVhcnRlcmx5IikpIHsgIyBxdWFydGVybHkKICAgICAgaW5wdXQgJTw+JSByZW5hbWUoISF2YWx1ZV9uYW1lIDo9IHZhbHVlKQogICAgICBkdGZfbWFjcm8gJTw+JSBsZWZ0X2pvaW4oaW5wdXQsIGJ5ID0gImRhdGUiKQogICAgfQogICAgCiAgfSBlbHNlIHsgIyBSb21lciBhbmQgUm9tZXIgZGF0YQogICAgaW5wdXQgPC0gcmVhZF94bHMoZmlsZW5hbWUsIHNoZWV0ID0gIkRBVEEgQlkgTU9OVEgiKQogICAgaW5wdXQgJTw+JQogICAgICByZW5hbWUoZGF0ZSA9IERBVEUpICU+JQogICAgICBzZWxlY3QoZGF0ZSwgUkVTSUQpICU+JQogICAgICBtdXRhdGUoeWVhciA9IHllYXIoZGF0ZSksCiAgICAgICAgICAgICBxdWFydGVyID0gcXVhcnRlcihkYXRlKSkgJT4lCiAgICAgIGdyb3VwX2J5KHllYXIsIHF1YXJ0ZXIpICU+JQogICAgICBzdW1tYXJpc2UoZGF0ZSA9IGZpcnN0KGRhdGUpLAogICAgICAgICAgICAgICAgUkVTSUQgPSBtZWFuKFJFU0lEKSwKICAgICAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpICU+JQogICAgICBzZWxlY3QoZGF0ZSwgUkVTSUQpCiAgICBkdGZfbWFjcm8gJTw+JSBsZWZ0X2pvaW4oaW5wdXQsIGJ5ID0gImRhdGUiKQogIH0KfQoKcGxvdF9zdGFydCA8LSBhcy5EYXRlKCIxOTY0LTAxLTAxIikKcGxvdF9lbmQgPC0gYXMuRGF0ZSgiMTk3NC0xMi0zMCIpCgojIGNoYW5nZSByZWNlc3Npb24gaW5kaWNhdG9yIHRvIHN0YXJ0L2VuZCAoYWRhcHRlZCBmcm9tIEZhYmlhbiBTY2hlbGVyIHVuZGVyIGh0dHBzOi8vcnB1YnMuY29tL0ZTbC82MDk0NzEpCmR0Zl9tYWNybyRyZWNlc3Npb25fZGlmZiA8LSBkdGZfbWFjcm8kVVNSRUMgLSBsYWcoZHRmX21hY3JvJFVTUkVDKQpyZWNlc3Npb25fc3RhcnQgPC0gZHRmX21hY3JvW2R0Zl9tYWNybyRyZWNlc3Npb25fZGlmZiA9PSAxICYgIWlzLm5hKGR0Zl9tYWNybyRyZWNlc3Npb25fZGlmZiksIF0kZGF0ZQpyZWNlc3Npb25fZW5kICAgPC0gZHRmX21hY3JvW2R0Zl9tYWNybyRyZWNlc3Npb25fZGlmZiA9PSAtMSAmICFpcy5uYShkdGZfbWFjcm8kcmVjZXNzaW9uX2RpZmYpLF0kZGF0ZQoKcmVjZXNzaW9uX3N0YXJ0IDwtIHJlY2Vzc2lvbl9zdGFydFtyZWNlc3Npb25fc3RhcnQgPj0gcGxvdF9zdGFydCAmIHJlY2Vzc2lvbl9zdGFydCA8PSBwbG90X2VuZF0KcmVjZXNzaW9uX2VuZCAgIDwtIHJlY2Vzc2lvbl9lbmRbcmVjZXNzaW9uX2VuZCA+PSBwbG90X3N0YXJ0ICYgcmVjZXNzaW9uX2VuZCA8PSBwbG90X2VuZF0KCmlmKGxlbmd0aChyZWNlc3Npb25fc3RhcnQpID4gbGVuZ3RoKHJlY2Vzc2lvbl9lbmQpKSB7CiAgcmVjZXNzaW9uX2VuZCA8LSBjKHJlY2Vzc2lvbl9lbmQsIGFzLlBPU0lYY3QocGxvdF9lbmQpKQp9CmlmKGxlbmd0aChyZWNlc3Npb25fZW5kKSA+IGxlbmd0aChyZWNlc3Npb25fc3RhcnQpKSB7CiAgcmVjZXNzaW9uX3N0YXJ0IDwtIGMoYXMuUE9TSVhjdChwbG90X3N0YXJ0KSwgcmVjZXNzaW9uX3N0YXJ0KQp9CnJlY3MgPC0gZGF0YS5mcmFtZShyZWNlc3Npb25fc3RhcnQgPSByZWNlc3Npb25fc3RhcnQsIHJlY2Vzc2lvbl9lbmQgPSByZWNlc3Npb25fZW5kKQppZiAobnJvdyhyZWNzKSA+IDApIHsKICByZWNfc2hhZGUgPC0gZ2VvbV9yZWN0KGRhdGEgPSByZWNzLCBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHhtaW4gPSByZWNlc3Npb25fc3RhcnQsIHhtYXggPSByZWNlc3Npb25fZW5kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mKSwgYWxwaGEgPSAwLjUpICMgZmlsbCwgYWxwaGEgMC41Pwp9CgoKZHRmX21hY3JvICU8PiUKICBtdXRhdGUoR0RQQzEgPSAwLjEqKEdEUEMxIC0gbGFnKEdEUEMxKSksCiAgICAgICAgIElORFBSTyA9IDAuMSooSU5EUFJPIC0gbGFnKElORFBSTykpKQpkdGZfbWFjcm9fbG9uZyA8LSBkdGZfbWFjcm8gJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtYW55X29mKCJkYXRlIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInZhcmlhYmxlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIikKCmBgYAoKIyBGaWd1cmVzCiMjIyMgVGltZXNwYW4gaXMgKG1vc3RseSkgMTk2NS8wNiB0byAxOTc1LzA2CgojIyBGaWd1cmUgMTogVGhlIGV2b2x1dGlvbiBvZiB0aGUgVVMgZWNvbm9teQojIyBTdWJmaWd1cmUgMShhKTogQWN0dWFsIEluZmxhdGlvbgoKYGBge3IgZmlnXzFfYX0KCiMgYWN0dWFsIGluZmxhdGlvbiBhY2NvcmRpbmcgdG8gQ1BJLCBDb3JlIENQSSwgYW5kIEdEUCBkZWZsYXRvciBiZXR3ZWVuIDE5NjAgYW5kIDE5ODAgCgojIHZlcnRpY2FsIGxpbmUgd2lkdGgKdmxpbmVfdyA8LSAwLjMgI21tCgojIHRleHQgYW5ub3RhdGlvbiBoaWdoIHRpdGxlcyAvIG1pZCB0aXRsZXMKaGZvbnQgPC0gMy4yCm1mb250IDwtIDIKYW5ub3RhdGlvbl9oZWlnaHQgPC0gMC4xNAoKdmFycyA8LSBjKCJwaV8xMiIsICJwaWNvcmVfMTIiLCAicGlnZHAxMiIpCmxlZ3YgPC0gY3JlYXRlX2xlZ3YodmFycykKbGluZXYgPC0gY3JlYXRlX2xpbmV2KHZhcnMpCmxlZ3MgPC0gYygiQ1BJIEluZmxhdGlvbiIKICAgICAgICAgICwiQ1BJIENvcmUgSW5mbGF0aW9uIgogICAgICAgICAgLCJHRFAgRGVmbGF0b3IgSW5mbGF0aW9uIikKCnBsb3QgPC0gZ2dwbG90KGR0Zl9sb25nICU+JQogICAgICAgICAgICAgICAgIGZpbHRlcihkYXRlID49IGFzLkRhdGUoIjE5NjAtMDEtMDEiKSAmCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPD0gYXMuRGF0ZSgiMTk4MC0xMi0zMSIpICYKICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUgJWluJSBjKCJwaV8xMiIsICJwaWNvcmVfMTIiLCAicGlnZHAxMiIpICYKICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKHZhbHVlKSksCiAgICAgICAgICAgICAgIGFlcyh4ID0gZGF0ZSwgeSA9IHZhbHVlKSkgKwogICAgICAgICAgZ2VvbV9saW5lKGFlcyhjb2xvdXIgPSB2YXJpYWJsZSwgbGluZXR5cGUgPSB2YXJpYWJsZSksCiAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IGxpbmVfc2l6ZSkgKwogICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwwLjE2LDAuMDQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwwLjE0KSkgKwogICAgICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzPSIxIHllYXIiLCBkYXRlX2xhYmVscyA9ICIlWSIsCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyhhcy5EYXRlKCIxOTYwLTAxLTAxIikgLGFzLkRhdGUoIjE5ODAtMTItMzEiKSksCiAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLjAyLDApKSArCiAgICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUoIjE5NjUtMDUtMDEiKSksCiAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gInNvbGlkIiwgc2l6ZSA9IHRmb250KHZsaW5lX3cpKSArCiAgICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUoIjE5NzEtMDgtMDEiKSksCiAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgc2l6ZSA9IHRmb250KHZsaW5lX3cpKSArCiAgICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUoIjE5NzMtMTAtMDEiKSksCiAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gImxvbmdkYXNoIiwgc2l6ZSA9IHRmb250KHZsaW5lX3cpKSArCiAgICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBhcy5udW1lcmljKGFzLkRhdGUoIjE5NzQtMTItMDEiKSksCiAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gInNvbGlkIiwgc2l6ZSA9IHRmb250KHZsaW5lX3cpKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBsaW5ldiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsZWdzKSArCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IHZhcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGxlZ3YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4xMTIsMC41KSkgKwogICAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gYXMuRGF0ZSgiMTk2Mi0wNi0zMCIpLCB5ID0gYW5ub3RhdGlvbl9oZWlnaHQsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJBbmNob3IgSW4gU2VhYmVkIiwgc2l6ZSA9IHRmb250KGhmb250KSkgKwogICAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gYXMuRGF0ZSgiMTk2OC0wNi0zMCIpLCB5ID0gYW5ub3RhdGlvbl9oZWlnaHQsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJBIERyaWZ0aW5nIEFuY2hvciIsIHNpemUgPSB0Zm9udChoZm9udCkpICsKICAgICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGFzLkRhdGUoIjE5NzItMDktMDEiKSwgeSA9IDAuMDcsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJVU0QgT2ZmIiwgc2l6ZSA9IHRmb250KG1mb250KSkgKwogICAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gYXMuRGF0ZSgiMTk3Mi0wOS0wMSIpLCB5ID0gMC4wNy0wLjAwNSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIkdvbGQiLCBzaXplID0gdGZvbnQobWZvbnQpKSArCiAgICAgICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSBhcy5EYXRlKCIxOTcyLTA5LTAxIiksIHhlbmQgPSBhcy5EYXRlKCIxOTcyLTAyLTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAwLjA3LTAuMDA1LTAuMDA1LCB5ZW5kID0gMC4wNy0wLjAwNS0wLjAwNSAtIDAuMDEyKSwKICAgICAgICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC41LCAiY20iKSkpICsKICAgICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGFzLkRhdGUoIjE5NzQtMDUtMDEiKSwgeSA9IDAuMTQsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICJGaXJzdCBPaWwiLCBzaXplID0gdGZvbnQobWZvbnQpKSArCiAgICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSBhcy5EYXRlKCIxOTc0LTA1LTAxIiksIHkgPSAwLjE0LTAuMDA1LAogICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiU2hvY2siLCBzaXplID0gdGZvbnQobWZvbnQpKSAgKwogICAgICAgICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYXMuRGF0ZSgiMTk3NC0wNS0wMSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICB4ZW5kID0gYXMuRGF0ZSgiMTk3NC0wMS0wMSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gMC4xNC0wLjAwNS0wLjAwNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IDAuMTQtMC4wMDUtMC4wMDUgLSAwLjAyKSwKICAgICAgICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC41LCAiY20iKSkpICsKICAgICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGFzLkRhdGUoIjE5NzctMTEtMDEiKSwgeSA9IGFubm90YXRpb25faGVpZ2h0LAogICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiVW5hbmNob3JlZCBJbmZsYXRpb24iLCBzaXplID0gdGZvbnQoaGZvbnQpKSArCiAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuNDIsMC43KSkgKwogICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChrZXl3aWR0aCA9IDUsIGtleWhlaWdodCA9IDEpKQogICAgICAgIApwcmludChwbG90KQppZiAoYlNhdmVQbG90cykgbXlfZ2dzYXZlKHBhc3RlMChwYXRoX2ZpZ3VyZV9vdXQsICJmaWd1cmVfMV9hLnBkZiIpLCBwbG90KQoKCiMga2V5IG51bWJlcnMgZm9yIHBhcGVyCnByaW50KG1lYW4oZHRmJHBpXzEyW2R0ZiRkYXRlID49IGFzLkRhdGUoIjE5NjYtMDEtMDEiKSAmCiAgICAgICAgICAgICAgICAgICAgIGR0ZiRkYXRlIDw9IGFzLkRhdGUoIjE5NzMtMDktMDEiKV0sCiAgICAgICAgICAgbmEucm0gPSBUUlVFKQogICAgICApCgojIHVzZSBiZWdpbm5pbmcgb2YgcXVhcnRlcgpwcmludChkdGYkcGlfMTJbZHRmJGRhdGUgPT0gYXMuRGF0ZSgiMTk2NS0xMC0wMSIpXSkKcHJpbnQoZHRmJHBpXzEyW2R0ZiRkYXRlID09IGFzLkRhdGUoIjE5NzMtMDctMDEiKV0pCgpgYGAKIyMgU3ViZmlndXJlIDEoYik6IE90aGVyIG1hY3JvZWNvbm9taWMgc2VyaWVzCiMjIGZlZCBmdW5kcywgMTAteWVhciBib25kcywgdW5lbXBsb3ltZW50IHJhdGUsIGZlZGVyYWwgZGVmaWNpdAojIyB3aXRoIHJlY2Vzc2lvbiBiYXJzLCAxOTY0OjEgdG8gMTk3NDoxMgoKYGBge3IgZmlnXzFfYn0KCnZhcnMgPC0gYygiRkVERlVORFMiLCAiREdTMTAiLCJVTlJBVEUiLCJGWUZTREZZR0RQIikKbGVncyA8LSBjKCJGZWRlcmFsIEZ1bmRzIFJhdGUiLCAiMTAtWWVhciBUcmVhc3VyeSBZaWVsZCIsICJVbmVtcGxveW1lbnQgUmF0ZSIsICJBbm51YWwgRmVkZXJhbCBEZWZpY2l0ICglIEdEUCkiKQpsZWd2IDwtIGNyZWF0ZV9sZWd2KHZhcnMpCmxpbmV2IDwtIGNyZWF0ZV9saW5ldih2YXJzKQoKcGxvdCA8LSBnZ3Bsb3QoZHRmX21hY3JvX2xvbmcgJT4lCiAgICAgICAgICAgICAgICAgZmlsdGVyKHZhcmlhYmxlICVpbiUgdmFycywKICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA+PSBhcy5EYXRlKCIxOTY0LTAxLTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPD0gYXMuRGF0ZSgiMTk3NC0xMi0zMCIpKSAlPiUKICAgICAgICAgICAgICAgICAjIGludmVydCBGZWRlcmFsIFN1cnBsdXMgdG8gZmVkZXJhbCBEZWZpY2l0CiAgICAgICAgICAgICAgICAgbXV0YXRlKHZhbHVlID0gaWZlbHNlKHZhcmlhYmxlID09ICJGWUZTREZZR0RQIiwgLXZhbHVlLCB2YWx1ZSkpLAogICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB2YWx1ZSkpICsKICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IHZhcmlhYmxlLAogICAgICAgICAgICAgICAgbGluZXR5cGUgPSB2YXJpYWJsZSksCiAgICAgICAgICAgIHNpemUgPSBsaW5lX3NpemUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGJyZWFrcyA9IHZhcnMsIGxhYmVscyA9IGxlZ3MsIHZhbHVlcyA9IGxlZ3YpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgbGFiZWxzID0gbGVncywgdmFsdWVzID0gbGluZXYpICsKICByZWNfc2hhZGUgKyAjIE5CRVIgUmVjZXNzaW9uIHNoYWRpbmcKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuMjUsMC44NSkpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gMTAsIGtleWhlaWdodCA9IDEpKQoKcHJpbnQocGxvdCkKaWYgKGJTYXZlUGxvdHMpIG15X2dnc2F2ZShwYXN0ZTAocGF0aF9maWd1cmVfb3V0LCAiZmlndXJlXzFfYi5wZGYiKSwgcGxvdCkKCgpgYGAKCiMjIEZpZ3VyZShzKSAyCgpgYGB7ciBmaWdfMn0KCnZhcnMgPC0gYygibGl2X3BpY3BpMTJfbWVkaWFuIiwKICAgICAgICAgICJzcGZfcGlnZHAxMl9tZWRpYW4iLAogICAgICAgICAgImdQR0RQRjRfYW5udWFsIgogICAgICAgICAgKQoKbGVndiA8LSBjcmVhdGVfbGVndih2YXJzKQpsaW5ldiA8LSBjcmVhdGVfbGluZXYodmFycykKbGVncyA8LSBjKCJMaXZpbmdzdG9uIG1lZGlhbiBleHBlY3RlZCBpbmZsYXRpb24iLAogICAgICAgICAgIlNQRiBtZWRpYW4gZXhwZWN0ZWQgaW5mbGF0aW9uIiwKICAgICAgICAgICJHcmVlbmJvb2sgaW5mbGF0aW9uIGZvcmVjYXN0IgogICAgICAgICApCgpwbG90IDwtIGdncGxvdChkdGZfbG9uZyAlPiUKICAgICAgICAgICAgICAgICBmaWx0ZXIoZGF0ZSA+PSBhcy5EYXRlKCIxOTY1LTAxLTAxIikgJgogICAgICAgICAgICAgICAgICAgICAgICBkYXRlIDw9IGFzLkRhdGUoIjE5NzUtMDYtMzAiKSAmCiAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlICVpbiUgdmFycyAmCiAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYSh2YWx1ZSkpICU+JQogICAgICAgICAgICAgICAgIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gdmFycykpLAogICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB2YWx1ZSkpICsKICAgICAgICAgIGdlb21fbGluZShhZXMoY29sb3VyID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUpLCBzaXplID0gbGluZV9zaXplKSArCiAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzID0gbGluZXYsIGxhYmVscyA9IGxlZ3MpICsgIAogICAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbChicmVha3MgPSB2YXJzLCB2YWx1ZXMgPSBsZWd2LCBsYWJlbHMgPSBsZWdzKSArCiAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gNSwga2V5aGVpZ2h0ID0gMSkpCgpwcmludChwbG90KQppZiAoYlNhdmVQbG90cykgbXlfZ2dzYXZlKHBhc3RlMChwYXRoX2ZpZ3VyZV9vdXQsICJmaWd1cmVfMi5wZGYiKSwgcGxvdCkKCmBgYAoKIyMgRmlndXJlKHMpIDMKCiMgZXhwZWN0ZWQgaW5mbGF0aW9uIChtZWRpYW4gb3IgbWVhbikgZnJvbSBMaXZpbmdzdG9uLAojIGZyb20gdGhlIFNQRiBvbiBHRFAgZGVmbGF0b3JzLAojIGFuZCBmcm9tIGdyZWVuYm9vayBiZXR3ZWVuIDE5NjUgYW5kIDE5NzUKCiMjIFN1YmZpZ3VyZSAzKGEpOiBHcmVlbmJvb2ssIEZFRCBzdGFmZgoKYGBge3IgZmlnXzNfYX0KCnZhcnMgPC0gYygiZ1BHRFBGNF9hbm51YWwiLAogICAgICAgICAgImdQR0RQRjQiLAogICAgICAgICAgImdQR0RQRjEiCiAgICAgICAgICApCgpsZWd2IDwtIGNyZWF0ZV9sZWd2KHZhcnMpCmxpbmV2IDwtIGNyZWF0ZV9saW5ldih2YXJzKQpsZWdzIDwtIGMoIjEyIG1vbnRocyBhaGVhZCIsCiAgICAgICAgICAiOS0xMiBtb250aHMgYWhlYWQiLAogICAgICAgICAgIjMgbW9udGhzIGFoZWFkIgogICAgICAgICAgKQoKcGxvdCA8LSBnZ3Bsb3QoZHRmX2xvbmcgJT4lCiAgICAgICAgICAgICAgICAgZmlsdGVyKGRhdGUgPj0gYXMuRGF0ZSgiMTk2NS0wNi0wMSIpICYKICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA8PSBhcy5EYXRlKCIxOTc1LTA2LTMwIikgJgogICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSAlaW4lIHZhcnMgJgogICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEodmFsdWUpKSAlPiUKICAgICAgICAgICAgICAgICBtdXRhdGUodmFyaWFibGUgPSBmYWN0b3IodmFyaWFibGUsIGxldmVscyA9IHZhcnMpKSwKICAgICAgICAgICAgICAgYWVzKHggPSBkYXRlLCB5ID0gdmFsdWUpKSArCiAgICAgICAgICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IHZhcmlhYmxlLCBsaW5ldHlwZSA9IHZhcmlhYmxlKSwgc2l6ZSA9IGxpbmVfc2l6ZSkgKwogICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogICAgICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogICAgICAgICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKGJyZWFrcyA9IHZhcnMsIHZhbHVlcz0gbGluZXYsIGxhYmVscyA9IGxlZ3MpICsgIAogICAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbChicmVha3MgPSB2YXJzLCB2YWx1ZXMgPSBsZWd2LCBsYWJlbHMgPSBsZWdzKSArIAogICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjQsMC44KSkgKwogICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChrZXl3aWR0aCA9IDUsIGtleWhlaWdodCA9IDEpKQoKcHJpbnQocGxvdCkKaWYgKGJTYXZlUGxvdHMpIG15X2dnc2F2ZShwYXN0ZTAocGF0aF9maWd1cmVfb3V0LCAiZmlndXJlXzNfYS5wZGYiKSwgcGxvdCkKCmBgYAoKIyMgU3ViZmlndXJlIDMoYSk6IExpdmluZ3N0b24gdnMgRm9yd2FyZAoKYGBge3IgZmlnXzNfYn0KCnZhcnMgPC0gYygibGl2X3BpY3BpNl9tZWRpYW4iLAogICAgICAgICAgImxpdl9waWNwaTEyX21lZGlhbiIsCiAgICAgICAgICAibGl2X3BpY3BpX2ZfNl8xMiIKICAgICAgICAgKQoKbGVndiA8LSBjcmVhdGVfbGVndih2YXJzKQpsaW5ldiA8LSBjcmVhdGVfbGluZXYodmFycykKbGVncyA8LSBjKCIxMiBtb250aHMgYWhlYWQgbWVkaWFuIiwKICAgICAgICAgICI2IG1vbnRocyBhaGVhZCBtZWRpYW4iLAogICAgICAgICAgIjYtMTIgbW9udGhzIGFoZWFkIgogICAgICAgICApCgpwbG90IDwtIGdncGxvdChkdGZfbG9uZyAlPiUgCiAgICAgICAgICAgICAgICBmaWx0ZXIoZGF0ZSA+PSBhcy5EYXRlKCIxOTY1LTA2LTAxIikgJgogICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPD0gYXMuRGF0ZSgiMTk3NS0wNi0zMCIpICYKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSAlaW4lIHZhcnMgJgogICAgICAgICAgICAgICAgICAgICAgICFpcy5uYSh2YWx1ZSkpICU+JQogICAgICAgICAgICAgICAgIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gdmFycykpLAogICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB2YWx1ZSkpICsKICAgICAgICAgIGdlb21fbGluZShhZXMoY29sb3VyID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUpLCBzaXplID0gbGluZV9zaXplKSArCiAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IHZhcnMsIHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsgCiAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuMywwLjgpKSArCiAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gNSwga2V5aGVpZ2h0ID0gMSkpCgpwcmludChwbG90KQppZiAoYlNhdmVQbG90cykgbXlfZ2dzYXZlKHBhc3RlMChwYXRoX2ZpZ3VyZV9vdXQsICJmaWd1cmVfM19iLnBkZiIpLCBwbG90KQoKCmBgYAoKIyMgRmlndXJlKHMpIDQ6IEhvdXNlaG9sZCBxdWFsaXRhdGl2ZSBleHBlY3RhdGlvbnMgb2YgaW5mbGF0aW9uIGdvaW5nIHVwL2Rvd24KCmBgYHtyIGZpZ180fQoKdmFycyA8LSBjKCJtaWxvbmdfdXAiLCAibWlsb25nX2Rvd24iKQpsZWd2IDwtIGNyZWF0ZV9sZWd2KHZhcnMpCmxpbmV2IDwtIGNyZWF0ZV9saW5ldih2YXJzKQpsZWdzIDwtIGMoIlBlcmNlbnRhZ2UgdXAiLAogICAgICAgICAgIlBlcmNlbnRhZ2UgZG93biIpCgpwbG90IDwtIGdncGxvdChkdGZfbG9uZyAlPiUgCiAgICAgICAgICAgICAgICBmaWx0ZXIoZGF0ZSA+PSBhcy5EYXRlKCIxOTY1LTA2LTMwIikgJgogICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPD0gYXMuRGF0ZSgiMTk3NS0wNi0zMCIpICYKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSAlaW4lIHZhcnMgJgogICAgICAgICAgICAgICAgICAgICAgICFpcy5uYSh2YWx1ZSkpICU+JSAKICAgICAgICAgICAgICAgIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gdmFycykpLAogICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB2YWx1ZSkpICsKICAgICAgICAgIGdlb21fbGluZShhZXMoY29sb3VyID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUpLCBzaXplID0gbGluZV9zaXplKSArCiAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IHZhcnMsIHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yLDAuNSkpICsKICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQoa2V5d2lkdGggPSA1LCBrZXloZWlnaHQgPSAxKSkKCnByaW50KHBsb3QpCmlmIChiU2F2ZVBsb3RzKSBteV9nZ3NhdmUocGFzdGUwKHBhdGhfZmlndXJlX291dCwgImZpZ3VyZV80LnBkZiIpLCBwbG90KQoKYGBgCgojIyBGaWd1cmUocykgNTogQ3Jvc3Mtc2VjdGlvbmFsIG1lYW4gb2YgZXhwZWN0ZWQgaW5mbGF0aW9uIGJ5IGhvdXNlaG9sZHMKCmBgYHtyIGZpZ181fQoKdmFycyA8LSBjKCJtZWFuX21pY2giLCJtaWxvbmdfbWVhbiIpCmxlZ3YgPC0gY3JlYXRlX2xlZ3YodmFycykKbGluZXYgPC0gY3JlYXRlX2xpbmV2KHZhcnMpCmxlZ3MgPC0gYygiTWljaGlnYW4gcXVhbnRpdGF0aXZlIHN1cnZleSBtZWFuIiwKICAgICAgICAgICJNYW5raXctUmVpcy1Xb2xmZXJzIHF1YWxpdGF0aXZlIHN1cnZleSBtZWFuIikKCnBsb3QgPC0gZ2dwbG90KGR0Zl9sb25nICU+JSAKICAgICAgICAgICAgICAgIGZpbHRlcihkYXRlID49IGFzLkRhdGUoIjE5NjUtMDYtMzAiKSAmCiAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA8PSBhcy5EYXRlKCIxOTc1LTA2LTMwIikgJgogICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlICVpbiUgdmFycyAmCiAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKHZhbHVlKSkgJT4lCiAgICAgICAgICAgICAgICAgbXV0YXRlKHZhcmlhYmxlID0gZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSB2YXJzKSksCiAgICAgICAgICAgICAgIGFlcyh4ID0gZGF0ZSwgeSA9IHZhbHVlKSkgKwogICAgICAgICAgZ2VvbV9saW5lKGFlcyhjb2xvdXIgPSB2YXJpYWJsZSwgbGluZXR5cGUgPSB2YXJpYWJsZSkKICAgICAgICAgICAgICAgICAgICAsIHNpemUgPSBsaW5lX3NpemUpICsKICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDAuMTIpKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IHZhcnMsIHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4zNSwwLjkpKSArCiAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gNSwga2V5aGVpZ2h0ID0gMSkpCgpwcmludChwbG90KQppZiAoYlNhdmVQbG90cykgbXlfZ2dzYXZlKHBhc3RlMChwYXRoX2ZpZ3VyZV9vdXQsICJmaWd1cmVfNS5wZGYiKSwgcGxvdCkKCmBgYAoKIyMgRmlndXJlKHMpIDY6IERpc2FncmVlbWVudCBhYm91dCBleHBlY3RlZCBpbmZsYXRpb24gYW1vbmcgaG91c2Vob2xkcwojIyBTdWJmaWd1cmUgNihhKTogQ3Jvc3Mtc2VjdGlvbmFsIG1vbWVudHMKCmBgYHtyIGZpZ182X2F9Cgp2YXJzIDwtIGMoInNkX21pY2giLAogICAgICAgICAgInNrZXduZXNzX21pY2giKQoKbGVndiA8LSBjcmVhdGVfbGVndih2YXJzKQpsaW5ldiA8LSBjcmVhdGVfbGluZXYodmFycykKbGVncyA8LSBjKCJTdGFuZGFyZCBkZXZpYXRpb24gKHJpZ2h0IGF4aXMpIiwKICAgICAgICAgICJTa2V3bmVzcyAobGVmdCBheGlzKSIpCgpkZjEgIDwtIGR0Zl9sb25nICU+JSAKICAgICAgICBmaWx0ZXIoZGF0ZSA+PSBhcy5EYXRlKCIxOTY1LTA2LTMwIikgJgogICAgICAgICAgICAgICBkYXRlIDw9IGFzLkRhdGUoIjE5NzUtMDYtMzAiKSAmCiAgICAgICAgICAgICAgIHZhcmlhYmxlICVpbiUgInNrZXduZXNzX21pY2giICYKICAgICAgICAgICAgICAgIWlzLm5hKHZhbHVlKSkKCmRmMiAgPC0gZHRmX2xvbmcgJT4lIAogICAgICAgIGZpbHRlcihkYXRlID49IGFzLkRhdGUoIjE5NjUtMDYtMzAiKSAmCiAgICAgICAgICAgICAgIGRhdGUgPD0gYXMuRGF0ZSgiMTk3NS0wNi0zMCIpICYKICAgICAgICAgICAgICAgdmFyaWFibGUgJWluJSAic2RfbWljaCIgJgogICAgICAgICAgICAgICAhaXMubmEodmFsdWUpKQoKdHJhbnNmX2IgPC0gMzcKdHJhbnNmX2EgPC0gMS4yCgpwbG90IDwtIGdncGxvdChkZjEsIGFlcyh4ID0gZGF0ZSkpICsKICAgICAgICAgIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCBjb2xvdXIgPSB2YXJpYWJsZSwgbGluZXR5cGUgPSB2YXJpYWJsZSksCiAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IGxpbmVfc2l6ZSkgKwogICAgICAgICAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUqdHJhbnNmX2IgLSB0cmFuc2ZfYSwgY29sb3VyID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZjIsIHNpemUgPSBsaW5lX3NpemUpICsKICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKCB0cmFucyA9IH4gKC4gKyB0cmFuc2ZfYSkvdHJhbnNmX2IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuMjUsMC40NSkpICsKICAgICAgICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbChicmVha3MgPSB2YXJzLCB2YWx1ZXMgPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IHZhcnMsIHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQoa2V5d2lkdGggPSA1LCBrZXloZWlnaHQgPSAxKSkKCnByaW50KHBsb3QpCmlmIChiU2F2ZVBsb3RzKSBteV9nZ3NhdmUocGFzdGUwKHBhdGhfZmlndXJlX291dCwgImZpZ3VyZV82X2EucGRmIiksIHBsb3QpCgpybShkZjEsIGRmMikKCmBgYAoKIyMgU3ViZmlndXJlIDYoYik6IFRocmVlIHNuYXBzaG90cyBvZiB0aGUgZGlzdHJpYnV0aW9uCgpgYGB7ciBmaWdfNl9ifQoKIyAxOTY3LCAxMDcwLCAxOTc0OiBEaXN0cmlidXRpb24gb2YgSG91c2Vob2xkIGV4cGVjdGF0aW9ucwojIGdldCBob3VzZWhvbGQgZGlzdHJpYnV0aW9uIGZyb20gZWFybGllciBxdWFudGl0YXRpdmUgTWljaGlnYW4gc3VydmV5CgpkdGZfbWljaGlnYW4gPC0gcmVhZF9kdGEoIi4vRGF0YS9VUy9taWNoaWdhbl9tb21lbnRzLmR0YSIpCgojIGhhbmRsZSBkYXRlcwpkYXRlbG9va3VwIDwtIHNlcS5EYXRlKGZyb20gPSBhcy5EYXRlKCIxOTY2LTA0LTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgdG8gPSBhcy5EYXRlKCIxOTc2LTEwLTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAicXVhcnRlciIpCmR0Zl9taWNoaWdhbiRkYXRlIDwtIGRhdGVsb29rdXBbIGR0Zl9taWNoaWdhbiRkYXRlIC0gbWluKGR0Zl9taWNoaWdhbiRkYXRlKSArIDFdCgpsaW5ldiA8LSBjKCJzb2xpZCIsICJkYXNoZWQiLCAiZG90dGVkIikKbGVndiA8LSBjKCdyZWQnLCdibHVlJywnZ3JlZW40JykKbGVncyA8LSBjKCIxOTY3IiwgIjE5NzAiLCAiMTk3NCIpCgpicmVha3MgPSBjKDE5NjcsIDE5NzAsIDE5NzQpCgpkdGZfbWljaGlnYW4gJTw+JQogIG11dGF0ZSh5ZWFyID0gYXMubnVtZXJpYyhzdWJzdHIoYXMuY2hhcmFjdGVyKGRhdGUpLCAxLCA0KSkpICU+JQogIGZpbHRlcih5ZWFyICVpbiUgYnJlYWtzKSAlPiUKICByZW5hbWUoaW5mX2Rvd25vcnNhbWUgPSBkb3dub3JzYW1lLAogICAgICAgICBpbmZfZG9udGtub3d1cCA9IGRvbnRrbm93dXApICU+JQogICMgYXJ0aWNpZmlhbCBkYXRhIHRvIG1ha2Ugc21vb3RoIGN1cnZlCiAgbXV0YXRlKGluZl9sb3dlciA9IDAsCiAgICAgICAgIGluZl9oaWdoZXIgPSAwKSAlPiUKICAjIHRvIGRpc3RyaWJ1dGUgbWFzcyBvZiAiZG9udGtub3d1cCIKICBtdXRhdGUobWVhbl9wb3NpdGl2ZSA9ICgxLjUqaW5mXzF0bzIgKyAzLjUqaW5mXzN0bzQgKyA1KmluZl81ICsgNy41KmluZl82dG85ICsgMTIqaW5mXzEwdG8xNCkvKGluZl8xdG8yICsgaW5mXzN0bzQgKyBpbmZfNSArIGluZl82dG85ICsgaW5mXzEwdG8xNCkpICU+JQogICMgZm9yICJ0aG9zZSB3aG8gImRvbnRrbm93IiB1c2UgZGlzdHJpYnV0aW9uIGFzIHByaW9yCiAgIyBpLmUuIGlnbm9yZSB0aGVtCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgiaW5mIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIngiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiZnJlcSIpICU+JQogIG11dGF0ZSh4ID0gYXMubnVtZXJpYyhyZWNvZGUoeCwKICAgICAgICAgICAgICAgICAgICBpbmZfbG93ZXIgPSAiLTUiLAogICAgICAgICAgICAgICAgICAgIGluZl9kb3dub3JzYW1lID0gIi0yIiwKICAgICAgICAgICAgICAgICAgICBpbmZfMXRvMiA9ICIxLjUiLAogICAgICAgICAgICAgICAgICAgIGluZl8zdG80ID0gIjMuNSIsCiAgICAgICAgICAgICAgICAgICAgaW5mXzUgPSAiNSIsCiAgICAgICAgICAgICAgICAgICAgaW5mXzZ0bzkgPSAiNy41IiwKICAgICAgICAgICAgICAgICAgICBpbmZfMTB0bzE0ID0gIjEyIiwKICAgICAgICAgICAgICAgICAgICBpbmZfaGlnaGVyID0gIjE3LjUiLAogICAgICAgICAgICAgICAgICAgIGluZl9kb250a25vd3VwID0gYXMuY2hhcmFjdGVyKG1lYW5fcG9zaXRpdmUpKSksCiAgICAgICAgIHllYXIgPSBhcy5mYWN0b3IoeWVhcikpICU+JQogIHNlbGVjdCgtbWVhbl9wb3NpdGl2ZSkgJT4lCiAgZ3JvdXBfYnkoeWVhciwgeCkgJT4lCiAgc3VtbWFyaXNlKGZyZXF1ZW5jeSA9IHN1bShmcmVxKSwKICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgbXV0YXRlKHN1bSA9IHN1bShmcmVxdWVuY3kpLAogICAgICAgICB5ID0gZnJlcXVlbmN5L3N1bSkgJT4lCiAgc2VsZWN0KC1jKHN1bSwgZnJlcXVlbmN5KSkKCnBsb3QgPC0gZ2dwbG90KGR0Zl9taWNoaWdhbiwKICAgICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sID0geWVhcikpICsKICAgICAgICAgIHN0YXRfZGVuc2l0eShhZXMoeCA9IHgsIHdlaWdodCA9IHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IHllYXIsIGxpbmV0eXBlID0geWVhciksCiAgICAgICAgICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBnZW9tID0gImxpbmUiLAogICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gImlkZW50aXR5IiwKICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gbGluZV9zaXplLAogICAgICAgICAgICAgICAgICAgICAgIGJ3ID0gMS4zKSArCiAgICAgICAgICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoMS41LCAzLjUsIDUsIDcuNSwgMTIpKSArCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IGJyZWFrcywgdmFsdWVzID0gbGVndiwgbGFiZWxzID0gbGVncykgKwogICAgICAgICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKGJyZWFrcyA9IGJyZWFrcywgdmFsdWVzID0gbGluZXYsIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4xLCAwLjcpKSArCiAgICAgICAgICBndWlkZXMoY29sID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gNSwga2V5aGVpZ2h0ID0gMSkpCgpwcmludChwbG90KQppZiAoYlNhdmVQbG90cykgbXlfZ2dzYXZlKHBhc3RlMChwYXRoX2ZpZ3VyZV9vdXQsICJmaWd1cmVfNl9iLnBkZiIpLCBwbG90KQoKYGBgCgojIyBGaWd1cmUocykgNzogTWVkaWEgbWVudGlvbnMgYW5kIHB1YmxpYyBjb25jZXJucyByZWxhdGVkIHRvIGluZmxhdGlvbgoKYGBge3IgZmlnXzd9CgojIHZhcmlhYmxlcyBsZWZ0IGF4aXMKdmFyczEgPC0gYygicHJvcXVlc3RfY2VudHJhbF9iYW5rIiwKICAgICAgICAgICAicHJvcXVlc3RfaW5mbGF0aW9uIikKIyB2YXJpYWJsZXMgcmlnaHQgYXhpcwp2YXJzMiA8LSBjKCJnYWxsdXBfaW5mbGF0aW9uX21pbnVzX2VtcGxveW1lbnQiKQpsZWd2IDwtIGNyZWF0ZV9sZWd2KGModmFyczEsIHZhcnMyKSkKbGluZXYgPC0gY3JlYXRlX2xpbmV2KGModmFyczEsIHZhcnMyKSkKbGVncyA8LSBjKCJDZW50cmFsIGJhbmsgJSBtZW50aW9ucyBpbiBOWVQgKGxlZnQgYXhpcykiLAogICAgICAgICAgIkluZmxhdGlvbiAlIG1lbnRpb25zIGluIE5ZVCAobGVmdCBheGlzKSIsCiAgICAgICAgICAiQ29uY2VybiBhYm91dCBpbmZsYXRpb24gLSBhYm91dCB1bmVtcGxveW1lbnQgR2FsbHVwIChyaWdodCBheGlzKSIpCgp0cmFuc2YgPC0gNQoKZHRmX21lbnRpb25zIDwtIGR0Zl9sb25nICU+JQogICAgICAgICAgICAgICAgIGZpbHRlcihkYXRlID49IGFzLkRhdGUoIjE5NjUtMDEtMDEiKSAmCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPD0gYXMuRGF0ZSgiMTk3NC0xMi0zMSIpICYKICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUgJWluJSBjKHZhcnMxLCB2YXJzMikgJgogICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEodmFsdWUpKSAlPiUgCiAgICAgICAgICAgICAgICAgbXV0YXRlKHZhcmlhYmxlID0gZmFjdG9yKHZhcmlhYmxlLGxldmVscyA9IGModmFyczEsIHZhcnMyKSkpCgpwbG90IDwtIGdncGxvdChkdGZfbWVudGlvbnMgJT4lCiAgICAgICAgICAgICAgICAgZmlsdGVyKHZhcmlhYmxlICVpbiUgYyh2YXJzMSkpLAogICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB2YWx1ZSkpICsKICAgICAgICAgIGdlb21fbGluZShhZXMoY29sb3VyID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUpLAogICAgICAgICAgICAgICAgICAgIHNpemUgPSBsaW5lX3NpemUpICsKICAgICAgICAgIGdlb21fbGluZShkYXRhID0gZHRmX21lbnRpb25zICU+JQogICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKHZhcmlhYmxlICVpbiUgYyh2YXJzMikpLAogICAgICAgICAgICAgICAgICAgIGFlcyh5ID0gdmFsdWUgLyB0cmFuc2YsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IHZhcmlhYmxlLCBsaW5ldHlwZSA9IHZhcmlhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICBvcmRlciA9IGFzLm51bWVyaWModmFyaWFibGUpKSwgc2l6ZSA9IGxpbmVfc2l6ZSkgKwogICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWMuYXhpcyA9IHNlY19heGlzKHRyYW5zID0gfiAuICogdHJhbnNmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSAgKwogICAgICAgICAgc2NhbGVfbGluZXR5cGVfbWFudWFsKGJyZWFrcyA9IGModmFyczEsIHZhcnMyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IGModmFyczEsIHZhcnMyKSwgdmFsdWVzID0gbGVndiwgbGFiZWxzID0gbGVncykgKwogICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjM2LCAwLjg1KSkgKwogICAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChrZXl3aWR0aCA9IDUsIGtleWhlaWdodCA9IDEpKQoKCnByaW50KHBsb3QpCmlmIChiU2F2ZVBsb3RzKSBteV9nZ3NhdmUocGFzdGUwKHBhdGhfZmlndXJlX291dCwgImZpZ3VyZV83LnBkZiIpLCBwbG90KQoKCmBgYAoKIyMgRmlndXJlKHMpIDg6IEZpcm0gZXhwZWN0YXRpb25zIG9mIGluZmxhdGlvbgoKYGBge3IgZmlnXzh9Cgp2YXJzIDwtIHVuaXF1ZShkdGZfbG9uZyR2YXJpYWJsZVtncmVwbCgibGVld18iLCBkdGZfbG9uZyR2YXJpYWJsZSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiZXhwIiwgZHRmX2xvbmckdmFyaWFibGUpXQogICAgICAgICAgICAgICApCgpsZWd2IDwtIGNyZWF0ZV9sZWd2KHZhcnMpCmxpbmV2IDwtIGNyZWF0ZV9saW5ldih2YXJzKQpsZWdzIDwtIGMoIiUgY2hhbmdlIGluIHByaWNlcyBvZiBnb29kcyBhbmQgc2VydmljZXMgc29sZCIsCiAgICAgICAgICAiJSBjaGFuZ2UgaW4gcHJpY2VzIG9mIGNhcGl0YWwgZ29vZHMgcHVyY2hhc2VkIikKCnBsb3QgPC0gZ2dwbG90KGR0Zl9sb25nICU+JSAKICAgICAgICAgICAgICAgIGZpbHRlcih2YXJpYWJsZSAlaW4lIHZhcnMgJgogICAgICAgICAgICAgICAgICAgICAgICFpcy5uYSh2YWx1ZSkgJgogICAgICAgICAgICAgICAgICAgICAgIGRhdGUgPD0gYXMuRGF0ZSgiMTk3NS0wMS0wMSIpKSAlPiUKICAgICAgICAgICAgICAgICBtdXRhdGUodmFyaWFibGUgPSBmYWN0b3IodmFyaWFibGUsIGxldmVscyA9IHZhcnMpKSwKICAgICAgICAgICAgICAgYWVzKHggPSBkYXRlLCB5ID0gdmFsdWUpKSArCiAgICAgICAgICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IHZhcmlhYmxlLCBsaW5ldHlwZSA9IHZhcmlhYmxlKSwgc2l6ZSA9IGxpbmVfc2l6ZSkgKwogICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogICAgICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjQsMC44NSkpICsKICAgICAgICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbChicmVha3MgPSB2YXJzLCB2YWx1ZXMgPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IHZhcnMsIHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQoa2V5d2lkdGggPSA1LCBrZXloZWlnaHQgPSAxKSkKCnByaW50KHBsb3QpCmlmIChiU2F2ZVBsb3RzKSBteV9nZ3NhdmUocGFzdGUwKHBhdGhfZmlndXJlX291dCwgImZpZ3VyZV84LnBkZiIpLCBwbG90KQoKYGBgCgojIyBGaWd1cmUocykgOTogR29sZCBwcmljZXMsIHNwb3QsIHBlciBvdW5jZQoKYGBge3IgZmlnXzl9CgojcGxvdAp2YXJzIDwtIGMoImdvbGQiLAogICAgICAgICAgImdvbGRfcHJpY2UiKQpsZWd2IDwtIGMoInJlZCIsImJsdWUiLCJibGFjayIpCmxpbmV2IDwtIGMoInNvbGlkIiwibG9uZ2Rhc2giLCJkYXNoZWQiKQpsZWdzIDwtIGMoIlp1cmljaCBwcmljZSIsCiAgICAgICAgICAiTG9uZG9uIHByaWNlIiwKICAgICAgICAgICJVU0QgdG8gZ29sZCBvdW5jZSBjb252ZXJ0YWJpbGl0eSIpCgojVVNEIEdPTEQgUEVHCnBlZyA8LSAzNQoKI3Bvc2l0aW9uIG9mIHNlZ21lbnQKZHRmX3BlZyA8LSBkYXRhLmZyYW1lKHgxID0gYXMuRGF0ZSgiMTk2Ni0wMy0zMCIpLAogICAgICAgICAgICAgICAgICAgICAgeDIgPSBhcy5EYXRlKCIxOTcxLTA4LTEzIiksCiAgICAgICAgICAgICAgICAgICAgICB5MSA9IHBlZywgeTIgPSBwZWcsCiAgICAgICAgICAgICAgICAgICAgICBsZWcgPSAiVVNEIGdvbGQgY29udmVydGFiaWxpdHkiKQoKcGxvdCA8LSBnZ3Bsb3QoZHRmX2xvbmcgJT4lCiAgICAgICAgICAgICAgICAgZmlsdGVyKGRhdGUgPj0gYXMuRGF0ZSgiMTk2Ni0wMy0zMCIpICYKICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA8PSBhcy5EYXRlKCIxOTcxLTA2LTMwIikgJgogICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSAlaW4lIHZhcnMgJgogICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEodmFsdWUpKSwKICAgICAgICAgICAgICAgYWVzKHggPSBkYXRlLCB5ID0gdmFsdWUpKSArCiAgICAgICAgICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IHZhcmlhYmxlLCBsaW5ldHlwZSA9IHZhcmlhYmxlKSwKICAgICAgICAgICAgICAgICAgICBzaXplID0gbGluZV9zaXplKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3M9IjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIiVZIikgKwogICAgICAgICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0geDEsIHhlbmQgPSB4MiwgeSA9IHkxLCB5ZW5kID0geTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IGxlZywgbGluZXR5cGUgPSBsZWcpLAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkdGZfcGVnLCBzaXplID0gMikgKwogICAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBsZWd2LCBsYWJlbHMgPSBsZWdzKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gbGluZXYsIGxhYmVscyA9IGxlZ3MpICArCiAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuMiwwLjkpKSArCiAgICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gNSwga2V5aGVpZ2h0ID0gMSkpCiAgICAgICAgICAKcHJpbnQocGxvdCkKaWYgKGJTYXZlUGxvdHMpIG15X2dnc2F2ZShwYXN0ZTAocGF0aF9maWd1cmVfb3V0LCAiZmlndXJlXzkucGRmIiksIHBsb3QpCnJtKGR0Zl9wZWcpCgpgYGAKCiMjIEZpZ3VyZShzKSAxMCAtIDEzOiBNQVRMQUIgb3Igb3RoZXIgY291bnRyaWVzCgojIyBGaWd1cmUocykgMTQ6IERyb3BwaW5nIHRoZSBhbmNob3I6IHRoZSBVUyAxOTgwcwojIyBTdWJmaWd1cmUgMTQoYSk6IEFjdHVhbCBhbmQgc3VydmV5IGZpcnN0LW9yZGVyIG1vbWVudHMKCmBgYHtyIGZpZ18xNF9hfQoKZHRmX01SVyA8LSBkdGYKIyBjbGVhbiBvcmlnaW5hbCBtaWNoaWdhbiB2YWx1ZXMKaW5wdXQgPC0gcmVhZF9kdGEoIi4vRGF0YS9VUy9NUldkYXRhXzAuZHRhIikKaW5wdXQgJTw+JSBtdXRhdGUoeWVhciA9IGZsb29yKGRhdGUvMTAwKSwKICAgICAgICAgICAgICAgICAgbW9udGggPSBkYXRlICUlIDEwMCwKICAgICAgICAgICAgICAgICAgcXVhcnRlciA9IGx1YnJpZGF0ZTo6cXVhcnRlcihtb250aCkpICU+JQogIGdyb3VwX2J5KHllYXIsIHF1YXJ0ZXIpICU+JQogIHN1bW1hcmlzZShtaV9waWNwaTEyX21lYW5fb3JpZ2luYWwgPSBtZWFuKG1pX3BpY3BpMTJfbWVhbiksCiAgICAgICAgICAgIG1pX3BpY3BpMTJfbWVkaWFuX29yaWdpbmFsID0gbWVhbihtaV9waWNwaTEyX21lZGlhbiksCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpICU+JQogIG11dGF0ZShkYXRlID0gem9vOjphcy5EYXRlKHpvbzo6YXMueWVhcnF0cih5ZWFyICsgKChxdWFydGVyIC0gMSkvNCkpKSkKICAKIyBqb2luCmR0Zl9NUlcgJTw+JSBsZWZ0X2pvaW4oaW5wdXQsIGJ5ID0gImRhdGUiKSAlPiUKICBzZWxlY3QoLWMobWlfcGljcGkxMl9tZWFuLCBtaV9waWNwaTEyX21lZGlhbikpICU+JQogIHJlbmFtZShtaV9waWNwaTEyX21lYW4gPSBtaV9waWNwaTEyX21lYW5fb3JpZ2luYWwsCiAgICAgICAgIG1pX3BpY3BpMTJfbWVkaWFuID0gbWlfcGljcGkxMl9tZWRpYW5fb3JpZ2luYWwpICU+JQogIHNlbGVjdChkYXRlLCBzcGZfcGlnZHAxMl9tZWRpYW4sIG1pX3BpY3BpMTJfbWVkaWFuKQoKIyBwaXZvdApkdGZfTVJXICU8PiUgcGl2b3RfbG9uZ2VyKGNvbHMgPSAhZGF0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInZhcmlhYmxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIpCmR0Zl90ZW1wIDwtIGR0Zl9tYWNybyAlPiUKICBzZWxlY3QoZGF0ZSwgQ1BJQVVDU0wsIENQSUxGRVNMKSAlPiUKICBhcnJhbmdlKGRhdGUpICU+JQogIG11dGF0ZShpbmZsYXRpb25fQ29yZUNQSSA9IChDUElBVUNTTCAtIGxhZyhDUElBVUNTTCwgbiA9IDQpKS9sYWcoQ1BJQVVDU0wsIG4gPSA0KSwKICAgICAgICAgaW5mbGF0aW9uX0NQSSA9IChDUElMRkVTTCAtIGxhZyhDUElMRkVTTCwgbiA9IDQpKS9sYWcoQ1BJTEZFU0wsIG4gPSA0KSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtZGF0ZSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAidmFyaWFibGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiKQoKZHRmX2Ryb3BwaW5nIDwtIGZ1bGxfam9pbihkdGZfTVJXLCBkdGZfdGVtcCwgYnkgPSBjKCJkYXRlIiwgInZhcmlhYmxlIiwgInZhbHVlIikpICU+JQogIGFycmFuZ2UoZGF0ZSwgdmFyaWFibGUpICU+JQogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShkYXRlKSkKCnZhcnMgPC0gYygic3BmX3BpZ2RwMTJfbWVkaWFuIiwKICAgICAgICAgICJtaV9waWNwaTEyX21lZGlhbiIsCiAgICAgICAgICAiaW5mbGF0aW9uX0NQSSIsCiAgICAgICAgICAiaW5mbGF0aW9uX0NvcmVDUEkiKQpsZWd2IDwtIGNyZWF0ZV9sZWd2KHZhcnMpCmxpbmV2IDwtIGNyZWF0ZV9saW5ldih2YXJzKQpsZWdzIDwtIGMoIlNQRiBtZWRpYW4iLAogICAgICAgICAgIk1pY2hpZ2FuIG1lZGlhbiIsCiAgICAgICAgICAiSW5mbGF0aW9uIChDUEkpIiwKICAgICAgICAgICJJbmZsYXRpb24gKENvcmUgQ1BJKSIpCgpwbG90IDwtIGdncGxvdChkdGZfZHJvcHBpbmcgJT4lCiAgICAgICAgICAgICAgICAgZmlsdGVyKGRhdGUgPj0gYXMuRGF0ZSgiMTk3OC0wMS0wMSIpICYKICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZSA8PSBhcy5EYXRlKCIxOTg0LTEyLTMwIikgJgogICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSAlaW4lIHZhcnMgJgogICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEodmFsdWUpKSAlPiUKICAgICAgICAgICAgICAgICBtdXRhdGUodmFyaWFibGUgPSBmYWN0b3IodmFyaWFibGUsIGxldmVscyA9IHZhcnMpKSwKICAgICAgICAgICAgICAgYWVzKHggPSBkYXRlLCB5ID0gdmFsdWUpKSArCiAgICAgICAgICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IHZhcmlhYmxlLCBsaW5ldHlwZSA9IHZhcmlhYmxlKSwgc2l6ZSA9IGxpbmVfc2l6ZSkgKwogICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgICAgICAgICBzY2FsZV9jb2xvdXJfbWFudWFsKGJyZWFrcyA9IHZhcnMsIHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yLDAuMikpICsKICAgICAgICAgIGd1aWRlcyhsaW5ldHlwZSA9IGd1aWRlX2xlZ2VuZChrZXl3aWR0aCA9IDUsIGtleWhlaWdodCA9IDEpKQoKCnByaW50KHBsb3QpCmlmIChiU2F2ZVBsb3RzKSBteV9nZ3NhdmUocGFzdGUwKHBhdGhfZmlndXJlX291dCwgImZpZ3VyZV8xNF9hLnBkZiIpLCBwbG90KQpybShkdGZfTVJXLCBkdGZfdGVtcCkKCmBgYAoKIyMgU3ViZmlndXJlIDE0KGIpOiBTdXJ2ZXkgZGlzYWdyZWVtZW50CgpgYGB7ciBmaWdfMTRfYn0KCiMgMTk3OSAtIDE5ODU6IERpc2FncmVlbWVudCwgU2tld25lc3MgZm9yIG1pY2hpZ2FuOyBiYXNlZCBvbiBNUlcgZGF0YQoKIyBkaXNhZ3JlZW1lbnQ6IHN0YW5kYXJkIGRldmlhdGlvbgojIHNrZXduZXNzOiBidWlsZCBmcm9tIHBlcmNlbnRpbGVzCgp2YXJzX3JpZ2h0IDwtIGMoIm1pX3BpY3BpMTJfc2QiKQp2YXJzX2xlZnQgPC0gYygibWlfcGljcGkxMl9za2V3bmVzcyIpCnZhcnMgPC0gYyh2YXJzX3JpZ2h0LCB2YXJzX2xlZnQpCmxlZ3YgPC0gY3JlYXRlX2xlZ3YodmFycykKbGluZXYgPC0gY3JlYXRlX2xpbmV2KHZhcnMpCmxlZ3MgPC0gYygiU3RhbmRhcmQgZGV2aWF0aW9uIChyaWdodCBheGlzKSIsCiAgICAgICAgICAiU2tld25lc3MgKGxlZnQgYXhpcykiKQoKdHJhbnNmIDwtIDIwCgpkdGZfdGVtcCA8LSBkdGZfbG9uZyAlPiUKICBmaWx0ZXIoZGF0ZSA+PSBhcy5EYXRlKCIxOTc5LTAxLTAxIikgJgogICAgICAgICBkYXRlIDw9IGFzLkRhdGUoIjE5ODQtMTItMzAiKSAmCiAgICAgICAgIHZhcmlhYmxlICVpbiUgdmFycyAmCiAgICAgICAgICFpcy5uYSh2YWx1ZSkpICU+JQogIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgbGV2ZWxzID0gdmFycykpCgpwbG90IDwtIGdncGxvdChkdGZfdGVtcCAlPiUKICAgICAgICAgICAgICAgICBmaWx0ZXIodmFyaWFibGUgJWluJSBjKHZhcnNfbGVmdCkpLAogICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB2YWx1ZSkpICsKICAgICAgICAgIGdlb21fbGluZShhZXMoY29sb3VyID0gdmFyaWFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gdmFyaWFibGUpLAogICAgICAgICAgICAgICAgICAgIHNpemUgPSBsaW5lX3NpemUpICsKICAgICAgICAgIGdlb21fbGluZShkYXRhID0gZHRmX3RlbXAgJT4lCiAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIodmFyaWFibGUgJWluJSBjKHZhcnNfcmlnaHQpKSwKICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB0cmFuc2YgKiB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gYXMubnVtZXJpYyh2YXJpYWJsZSkpLAogICAgICAgICAgICAgICAgICAgIHNpemUgPSBsaW5lX3NpemUpICsKICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKHRyYW5zID0gfiAoLiAvIHRyYW5zZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgICAgICAgICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzID0gbGluZXYsIGxhYmVscyA9IGxlZ3MpICsgIAogICAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbChicmVha3MgPSB2YXJzLCB2YWx1ZXMgPSBsZWd2LCBsYWJlbHMgPSBsZWdzKSArCiAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuNCwwLjkpKSArCiAgICAgICAgICBndWlkZXMobGluZXR5cGUgPSBndWlkZV9sZWdlbmQoa2V5d2lkdGggPSA1LCBrZXloZWlnaHQgPSAxKSkKCnByaW50KHBsb3QpCmlmIChiU2F2ZVBsb3RzKSBteV9nZ3NhdmUocGFzdGUwKHBhdGhfZmlndXJlX291dCwgImZpZ3VyZV8xNF9iLnBkZiIpLCBwbG90KQpybShkdGZfdGVtcCkKCmBgYAoKIyMgRmlndXJlKHMpIDE1OiBUaGUgZXhwZWN0ZWQgaW5mbGF0aW9uIGFuY2hvciB0aHJvdWdoIHRoZSBwYW5kZW1pYwojIyBTdWJmaWd1cmUgMTUoYSk6IEFjdHVhbCBpbmZsYXRpb24KCmBgYHtyIGZpZ18xNV9hfQoKdGltZV9zZXJpZXNfZmlsZXMgPC0gbGlzdC5maWxlcygiLi9EYXRhL1VTL1VTX21hY3JvZGF0YSIsIHBhdHRlcm4gPSAiKi54bHMiLCBmdWxsLm5hbWVzID0gVFJVRSkKZHRmX2luZmxhdGlvbiA8LSBhcy5kYXRhLmZyYW1lKHNlcS5EYXRlKGZyb20gPSBhcy5EYXRlKCIyMDE2LTAxLTAxIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0byA9IGFzLkRhdGUoIjIwMjEtMDctMDEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gIm1vbnRoIikpCmNvbG5hbWVzKGR0Zl9pbmZsYXRpb24pIDwtICJkYXRlIgoKIyBjbGVhbiBhbmQgbWVyZ2UgYWxsIGZpbGVzIGluIHRoZSBtYWNyb2RhdGEtZGlyZWN0b3J5CmZvciAoZmlsZW5hbWUgaW4gdGltZV9zZXJpZXNfZmlsZXMpIHsKICBpZiAoZ3JlcGwoIlVTUkVDIiwgZmlsZW5hbWUpKSBuZXh0CiAgICBza2lwIDwtIDEwCiAgICBpbnB1dCA8LSByZWFkX3hscyhmaWxlbmFtZSwgc2tpcCA9IHNraXApCiAgICB0eXBlX2ZyZXEgPC0gY29sbmFtZXMocmVhZF94bHMoZmlsZW5hbWUsIHJhbmdlID0gIkExMCIpKQogICAgdHlwZV9mcmVxIDwtIHRvbG93ZXIoZ3N1YigiRnJlcXVlbmN5OiAiLCAiIiwgdHlwZV9mcmVxKSkKICAgIAogICAgdmFsdWVfbmFtZSA8LSBnc3ViKCIueGxzIiwgIiIsIGdzdWIoIi4vRGF0YS9VUy9VU19tYWNyb2RhdGEvIiwgIiIsIGZpbGVuYW1lKSkKICAgIGNvbG5hbWVzKGlucHV0KSA8LSBjKCJkYXRlIiwgInZhbHVlIikKICAgICMgZGV0ZXJtaW5lIGZyZXF1ZW5jeSwgdGFrZSBtZWFucyBvdmVyIHF1YXJ0ZXIgaWYgbmVjZXNzYXJ5CiAgICAKICAgIGlmICh0eXBlX2ZyZXEgJWluJSBjKCJtb250aGx5IikpIHsgIyBtb250aGx5CiAgICAgIGlucHV0ICU8PiUgcmVuYW1lKCEhdmFsdWVfbmFtZSA6PSB2YWx1ZSkKICAgICAgZHRmX2luZmxhdGlvbiAlPD4lIGxlZnRfam9pbihpbnB1dCwgYnkgPSAiZGF0ZSIpCiAgICB9Cn0KCmR0Zl9pbmZsYXRpb24gJTw+JQogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgQ1BJQVVDU0wgPSAxMDAqKCAoQ1BJQVVDU0wgLSBsYWcoQ1BJQVVDU0wsIDEyKSkvbGFnKENQSUFVQ1NMLCAxMikpLAogICAgICAgICBDUElMRkVTTCA9IDEwMCooIChDUElMRkVTTCAtIGxhZyhDUElMRkVTTCwgMTIpKS9sYWcoQ1BJTEZFU0wsIDEyKSkpCgpkdGZfaW5mbGF0aW9uICU8PiUgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtYW55X29mKCJkYXRlIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAidmFyaWFibGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIpCgp2YXJzIDwtIGMoIkNQSUxGRVNMIiwgIkNQSUFVQ1NMIiwgIlBDRVRSSU0xMk0xNTlTRlJCREFMIikKbGluZXYgPC0gYyhjcmVhdGVfbGluZXYodmFycyksICJzb2xpZCIpCmxlZ3YgPC0gYyhjcmVhdGVfbGVndih2YXJzKSwgImJsYWNrIikKbGVncyA8LSBjKCJDUEkgVXJiYW4gQ29yZSIsICJDUEkgVXJiYW4gQWxsIEdvb2RzIiwgIlRyaW1tZWQgTWVhbiBQQ0UiLCAiSW5mbGF0aW9uIFRhcmdldCIpCgpwbG90IDwtIGdncGxvdChkdGZfaW5mbGF0aW9uICU+JQogICAgICAgICAgICAgICAgICAgZmlsdGVyKHZhcmlhYmxlICVpbiUgdmFycywKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlID49IGFzLkRhdGUoIjIwMTgtMDEtMDEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlIDw9IGFzLkRhdGUoIjIwMjEtMDctMDEiKSkgJT4lCiAgICAgICAgICAgICAgICAgICBtdXRhdGUodmFyaWFibGUgPSBhcy5mYWN0b3IodmFyaWFibGUpKSwKICAgICAgICAgICAgICAgICBhZXMoeCA9IGRhdGUsIHkgPSB2YWx1ZSkpICsKICBnZW9tX2hsaW5lKGFlcyhjb2wgPSAiSW5mbGF0aW9uIFRhcmdldCIsCiAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSAiSW5mbGF0aW9uIFRhcmdldCIpLAogICAgICAgICAgICAgeWludGVyY2VwdCA9IDIsIHNpemUgPSBsaW5lX3NpemUpICsKICBnZW9tX2xpbmUoYWVzKGNvbCA9IHZhcmlhYmxlLCBsaW5ldHlwZSA9IHZhcmlhYmxlKSwKICAgICAgICAgICAgc2l6ZSA9IGxpbmVfc2l6ZSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZSh4LCAiJSIpLCBsaW1pdHMgPSBjKC0xLCA2KSwgYnJlYWtzID0gc2VxKDAsIDYsIGJ5ID0gMSkpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJVkiKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGxpbmV2LCBsYWJlbHMgPSBsZWdzKSArICAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuNSwwLjkpKSArCiAgZ3VpZGVzKGxpbmV0eXBlID0gZ3VpZGVfbGVnZW5kKGtleXdpZHRoID0gNywga2V5aGVpZ2h0ID0gMSkpCgpwcmludChwbG90KQppZiAoYlNhdmVQbG90cykgbXlfZ2dzYXZlKHBhc3RlMChwYXRoX2ZpZ3VyZV9vdXQsICJmaWd1cmVfMTVfYS5wZGYiKSwgcGxvdCkKCmBgYAoKIyMgU3ViZmlndXJlIDE1KGIpOiBNYXJrZXRzIGFuZCBzdXJ2ZXkgZmlyc3Qtb3JkZXIgbW9tZW50cwoKYGBge3IgZmlnXzE1X2J9CgpkdGZfaG91c2Vob2xkcyA8LSByZWFkX3hsc3goIi4vRGF0YS9VUy8yX01pY2hpZ2FuLnhsc3giLCBzaGVldCA9ICJNaWNoaWdhbiIsIHNraXAgPSAyKQpkdGZfaG91c2Vob2xkcyAlPD4lIHJlbmFtZShkYXRlID0gRGF0ZSkgJT4lCiAgbXV0YXRlKGRhdGUgPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICB5ZWFyID0geWVhcihkYXRlKSwKICAgICAgICAgcXVhcnRlciA9IHF1YXJ0ZXIoZGF0ZSkpICU+JQogIGdyb3VwX2J5KHllYXIsIHF1YXJ0ZXIpICU+JQogIHN1bW1hcmlzZShkYXRlID0gZmlyc3QoZGF0ZSksCiAgICAgICAgICAgIGFjcm9zcyhzdGFydHNfd2l0aCgicGllX21pY2hpZ2FuIiksIG1lYW4pLAogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICAjIHNrZXcgaXMgUGVhcnNvbidzIDJuZCBub25wYXJhbWV0cmljIHNrZXcgY29lZmZpY2llbnQKICBtdXRhdGUocGllX21pY2hpZ2FuX3NkXzF5ID0gMyoocGllX21pY2hpZ2FuX21lYW5fMXkgLXBpZV9taWNoaWdhbl9tZWRpYW5fMXkpIC8gcGllX21pY2hpZ2FuX3NrZXdfMXksCiAgICAgICAgIHBpZV9taWNoaWdhbl9zZF81eSA9IDMqKHBpZV9taWNoaWdhbl9tZWFuXzV5IC1waWVfbWljaGlnYW5fbWVkaWFuXzV5KSAvIHBpZV9taWNoaWdhbl9za2V3XzV5KQoKIyByZWFkIGFuZCBjbGVhbiBTUEYgb25lLXllYXIgYWhlYWQgZm9yZWNhc3QKZHRmX25vbmhvdXNlaG9sZHMgPC0gcmVhZF94bHN4KCIuL0RhdGEvVVMvSW5kaXZpZHVhbF9DUEkueGxzeCIpCmR0Zl9ub25ob3VzZWhvbGRzICU8PiUKICByZW5hbWVfd2l0aCh0b2xvd2VyKSAlPiUKICByZW5hbWUocGllX3Blb3BsZV8xeSA9IGNwaTYpICU+JQogIG11dGF0ZShkYXRlID0geWVhciArICgocXVhcnRlciAtIDEpLzQpLAogICAgICAgICBkYXRlID0gem9vOjphcy5EYXRlKHpvbzo6YXMueWVhcnF0cihkYXRlKSkpICU+JQogIHNlbGVjdChkYXRlLCB5ZWFyLCBxdWFydGVyLCBpZCwgaW5kdXN0cnksIHBpZV9wZW9wbGVfMXkpICU+JQogIGZpbHRlcihkYXRlID49IGFzLkRhdGUoIjIwMTgtMDEtMDEiKSkgJT4lCiAgbXV0YXRlKHBpZV9wZW9wbGVfMXkgPSBpZmVsc2UocGllX3Blb3BsZV8xeSA9PSAiI04vQSIsIE5BLCBwaWVfcGVvcGxlXzF5KSwKICAgICAgICAgcGllX3Blb3BsZV8xeSA9IGFzLm51bWVyaWMocGllX3Blb3BsZV8xeSksCiAgICAgICAgIGluZHVzdHJ5ID0gYXMuZmFjdG9yKGluZHVzdHJ5KSkKbGV2ZWxzKGR0Zl9ub25ob3VzZWhvbGRzJGluZHVzdHJ5KSA8LSBjKCJmaW4iLCAiYnVzIiwgInVua25vd24iKQoKZHRmX25vbmhvdXNlaG9sZHNfYWxsIDwtIGR0Zl9ub25ob3VzZWhvbGRzICU+JQogIGdyb3VwX2J5KHllYXIsIHF1YXJ0ZXIpICU+JQogIHN1bW1hcmlzZShkYXRlID0gZmlyc3QoZGF0ZSksCiAgICAgICAgICAgIHBpZV9wZW9wbGVfMXlfYWxsX21lYW4gPSBtZWFuKHBpZV9wZW9wbGVfMXksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHBpZV9wZW9wbGVfMXlfYWxsX3NkID0gc2QocGllX3Blb3BsZV8xeSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcGllX3Blb3BsZV8xeV9hbGxfbWVkaWFuID0gbWVkaWFuKHBpZV9wZW9wbGVfMXksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHBpZV9wZW9wbGVfMXlfYWxsX2ludGVycSA9IElRUihwaWVfcGVvcGxlXzF5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwaWVfcGVvcGxlXzF5X2FsbF9za2V3ID0gbW9tZW50czo6c2tld25lc3MocGllX3Blb3BsZV8xeSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgc2VsZWN0KC1jKHllYXIsIHF1YXJ0ZXIpKQoKZHRmX25vbmhvdXNlaG9sZHNfZmluIDwtIGR0Zl9ub25ob3VzZWhvbGRzICU+JQogIGZpbHRlcihhcy5pbnRlZ2VyKGluZHVzdHJ5KSA9PSAxKSAlPiUKICBncm91cF9ieSh5ZWFyLCBxdWFydGVyKSAlPiUKICBzdW1tYXJpc2UoZGF0ZSA9IGZpcnN0KGRhdGUpLAogICAgICAgICAgICBwaWVfcGVvcGxlXzF5X2Zpbl9tZWFuID0gbWVhbihwaWVfcGVvcGxlXzF5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwaWVfcGVvcGxlXzF5X2Zpbl9zZCA9IHNkKHBpZV9wZW9wbGVfMXksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHBpZV9wZW9wbGVfMXlfZmluX21lZGlhbiA9IG1lZGlhbihwaWVfcGVvcGxlXzF5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwaWVfcGVvcGxlXzF5X2Zpbl9pbnRlcnEgPSBJUVIocGllX3Blb3BsZV8xeSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcGllX3Blb3BsZV8xeV9maW5fc2tldyA9IG1vbWVudHM6OnNrZXduZXNzKHBpZV9wZW9wbGVfMXksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIpICU+JQogIHNlbGVjdCgtYyh5ZWFyLCBxdWFydGVyKSkKCmR0Zl9ub25ob3VzZWhvbGRzX2J1cyA8LSBkdGZfbm9uaG91c2Vob2xkcyAlPiUKICBmaWx0ZXIoYXMuaW50ZWdlcihpbmR1c3RyeSkgPT0gMikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgcXVhcnRlcikgJT4lCiAgc3VtbWFyaXNlKGRhdGUgPSBmaXJzdChkYXRlKSwKICAgICAgICAgICAgcGllX3Blb3BsZV8xeV9idXNfbWVhbiA9IG1lYW4ocGllX3Blb3BsZV8xeSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcGllX3Blb3BsZV8xeV9idXNfc2QgPSBzZChwaWVfcGVvcGxlXzF5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwaWVfcGVvcGxlXzF5X2J1c19tZWRpYW4gPSBtZWRpYW4ocGllX3Blb3BsZV8xeSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcGllX3Blb3BsZV8xeV9idXNfaW50ZXJxID0gSVFSKHBpZV9wZW9wbGVfMXksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHBpZV9wZW9wbGVfMXlfYnVzX3NrZXcgPSBtb21lbnRzOjpza2V3bmVzcyhwaWVfcGVvcGxlXzF5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICBzZWxlY3QoLWMoeWVhciwgcXVhcnRlcikpCiAgCmR0Zl9ub25ob3VzZWhvbGRzX2FsbCAlPD4lCiAgbGVmdF9qb2luKGR0Zl9ub25ob3VzZWhvbGRzX2ZpbiwgYnkgPSAiZGF0ZSIpICU+JQogIGxlZnRfam9pbihkdGZfbm9uaG91c2Vob2xkc19idXMsIGJ5ID0gImRhdGUiKQoKIyBqb2luIHdpdGggSG91c2Vob2xkIFN1cnZleSAoTWljaGlnYW4gc3VydmV5IG9mIENvbnN1bWVycykKZHRmX21vZGVybiA8LSBsZWZ0X2pvaW4oZHRmX25vbmhvdXNlaG9sZHNfYWxsLCBkdGZfaG91c2Vob2xkcywgYnkgPSAiZGF0ZSIpCmR0Zl9tb2Rlcm4gJTw+JSBsZWZ0X2pvaW4oZHRmX21hY3JvICU+JSBzZWxlY3QoZGF0ZSwgVDEwWUlFKSwgYnkgPSAiZGF0ZSIpCgpkdGZfbW9kZXJuICU8PiUKICBwaXZvdF9sb25nZXIoY29scyA9IC1kYXRlLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJ2YXJpYWJsZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIpCgp2YXJzIDwtIGMoInBpZV9taWNoaWdhbl9tZWFuXzF5IiwgInBpZV9taWNoaWdhbl9tZWFuXzV5IiwgInBpZV9wZW9wbGVfMXlfYWxsX21lYW4iLCAiVDEwWUlFIikKbGluZXYgPC0gY3JlYXRlX2xpbmV2KHZhcnMpCmxlZ3YgPC0gY3JlYXRlX2xlZ3YodmFycykKbGVncyA8LSBjKCJQZW9wbGU6IE1pY2hpZ2FuIDEgWWVhciIsICJQZW9wbGU6IE1pY2hpZ2FuIDUgWWVhcnMiLCAiVHJhZGVyczogU1BGIDEgWWVhciIsICJNYXJrZXQ6IDEwIHllYXIgQnJlYWtldmVuIEluZmxhdGlvbiBSYXRlIikKCnBsb3QgPC0gZ2dwbG90KGR0Zl9tb2Rlcm4gJT4lCiAgICAgICAgICAgICAgICAgZmlsdGVyKHZhcmlhYmxlICVpbiUgdmFycykgJT4lCiAgICAgICAgICAgICAgICAgbXV0YXRlKHZhcmlhYmxlID0gYXMuZmFjdG9yKHZhcmlhYmxlKSksCiAgICAgICAgICAgICAgIGFlcyh4ID0gZGF0ZSwgeSA9IHZhbHVlKSkgKwogIGdlb21fbGluZShhZXMoY29sID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUpLAogICAgICAgICAgICBzaXplID0gbGluZV9zaXplKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlKHgsICIlIikpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzID0gbGluZXYsIGxhYmVscyA9IGxlZ3MpICsgIAogIHNjYWxlX2NvbG91cl9tYW51YWwoYnJlYWtzID0gdmFycywgdmFsdWVzID0gbGVndiwgbGFiZWxzID0gbGVncykgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LDAuNykpICsKICBndWlkZXMobGluZXR5cGUgPSBndWlkZV9sZWdlbmQoa2V5d2lkdGggPSA1LCBrZXloZWlnaHQgPSAxKSkKCnByaW50KHBsb3QpCmlmIChiU2F2ZVBsb3RzKSBteV9nZ3NhdmUocGFzdGUwKHBhdGhfZmlndXJlX291dCwgImZpZ3VyZV8xNV9iLnBkZiIpLCBwbG90KQoKYGBgCgojIFN1YmZpZ3VyZSAxNShjKTogQ3Jvc3Mtc2VjdGlvbmFsIGRpc2FncmVlbWVudCBvZiBob3VzZWhvbGRzCgpgYGB7ciBmaWdfMTVfY30KCnZhcnNfbGVmdCA8LSBjKCJwaWVfbWljaGlnYW5fc2tld18xeSIpCnZhcnNfcmlnaHQgPC0gYygicGllX21pY2hpZ2FuX3NkXzF5IikKdmFycyA8LSBjKHZhcnNfcmlnaHQsIHZhcnNfbGVmdCkKbGVndiA8LSBjKCdyZWQnLCAnYmx1ZScpCmxpbmV2IDwtIGMoJ3NvbGlkJywgJ2xvbmdkYXNoJykKbGVncyA8LSBjKCJTdGFuZGFyZCBkZXZpYXRpb24gKHJpZ2h0IGF4aXMpIiwgIlNrZXduZXNzIChsZWZ0IGF4aXMpIikKCnBsb3QgPC0gZ2dwbG90KGR0Zl9tb2Rlcm4gJT4lCiAgICAgICAgICAgICAgICAgZmlsdGVyKHZhcmlhYmxlICVpbiUgdmFyc19sZWZ0KSAlPiUKICAgICAgICAgICAgICAgICBtdXRhdGUodmFyaWFibGUgPSBhcy5mYWN0b3IodmFyaWFibGUpKSwKICAgICAgICAgICAgICAgYWVzKHggPSBkYXRlLCB5ID0gdmFsdWUpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2wgPSB2YXJpYWJsZSwgbGluZXR5cGUgPSB2YXJpYWJsZSksCiAgICAgICAgICAgIHNpemUgPSBsaW5lX3NpemUpICsKICBnZW9tX2xpbmUoZGF0YSA9IGR0Zl9tb2Rlcm4gJT4lCiAgICAgICAgICAgICAgZmlsdGVyKHZhcmlhYmxlICVpbiUgdmFyc19yaWdodCkgJT4lCiAgICAgICAgICAgICAgbXV0YXRlKHZhcmlhYmxlID0gYXMuZmFjdG9yKHZhcmlhYmxlKSksCiAgICAgICAgICAgIGFlcyh4ID0gZGF0ZSwgeSA9IHZhbHVlIC8gNCwgY29sID0gdmFyaWFibGUsIGxpbmV0eXBlID0gdmFyaWFibGUpLAogICAgICAgICAgICBzaXplID0gbGluZV9zaXplKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXModHJhbnMgPSB+IC4gKiA0KSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbChicmVha3MgPSB2YXJzLCB2YWx1ZXMgPSBsaW5ldiwgbGFiZWxzID0gbGVncykgKyAgCiAgc2NhbGVfY29sb3VyX21hbnVhbChicmVha3MgPSB2YXJzLCB2YWx1ZXMgPSBsZWd2LCBsYWJlbHMgPSBsZWdzKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjMsMC44KSkgKwogIGd1aWRlcyhsaW5ldHlwZSA9IGd1aWRlX2xlZ2VuZChrZXl3aWR0aCA9IDUsIGtleWhlaWdodCA9IDEpKQoKcHJpbnQocGxvdCkKaWYgKGJTYXZlUGxvdHMpIG15X2dnc2F2ZShwYXN0ZTAocGF0aF9maWd1cmVfb3V0LCAiZmlndXJlXzE1X2MucGRmIiksIHBsb3QpCgpgYGAKCiMgUGxvdCA0OiBEaXN0cmlidXRpb24gb2YgSG91c2Vob2xkIEV4cGVjdGF0aW9ucyBhY3Jvc3MgZGlmZmVyZW50IG1vbnRocyAobm90IHF1YXJ0ZXJzLCB1bmxpa2UgQTMhKQoKYGBge3IgZmlnXzE1X2R9CgojIEJ1aWxkIG1vbnRobHkgaGlzdG9ncmFtIG9mIEhvdXNlaG9sZCBJbmZsYXRpb24gRXhwZWN0YXRpb24KZHRmX2hpc3RvZ3JhbSA8LSByZWFkX3hsc3goIi4vRGF0YS9VUy8yX01pY2hpZ2FuLnhsc3giLCBzaGVldCA9ICJOZXh0IHllYXIiLCBza2lwID0gMikKCmR0Zl9oaXN0b2dyYW0gJTw+JQogIHJlbmFtZV93aXRoKHRvbG93ZXIpICU+JQogIHNlbGVjdCh5ZWFyLCBtb250aCwgZG93biwgc2FtZSwgc3RhcnRzX3dpdGgoInVwIiksIHN0YXJ0c193aXRoKCJkayIpKSAlPiUKICBtdXRhdGUoaW5mX2xvd2VyYm91bmQgPSAwLCAjIGZpeCB0YWlscwogICAgICAgICBpbmZfdXBwZXJib3VuZCA9IDApICU+JQogIHJlbmFtZShpbmZfZG93biA9IGRvd24sCiAgICAgICAgIGluZl8wID0gc2FtZSwKICAgICAgICAgaW5mXzF0bzIgPSBgdXAgYnkgMS0yJWAsCiAgICAgICAgIGluZl8zdG80ID0gYHVwIGJ5IDMtNCVgLAogICAgICAgICBpbmZfNSA9IGB1cCBieSA1JWAsCiAgICAgICAgIGluZl82dG85ID0gYHVwIGJ5IDYtOSVgLAogICAgICAgICBpbmZfMTB0bzE0ID0gYHVwIGJ5IDEwLTE0JWAsCiAgICAgICAgIGluZl8xNXBsdXMgPSBgdXAgYnkgMTUlK2AsCiAgICAgICAgIGluZl9kb250a25vd3VwID0gYHVwOyBkayBob3cgbXVjaGAsCiAgICAgICAgIGluZl9kb250a25vdyA9IGBkazsgbmFgCiAgICAgICAgICkgJT4lCiAgbXV0YXRlKG1lYW5fcG9zaXRpdmUgPSAoMS41KmluZl8xdG8yICsgMy41KmluZl8zdG80ICsgNSppbmZfNSArIDcuNSppbmZfNnRvOSArIDEyKmluZl8xMHRvMTQgKyAxNyppbmZfMTVwbHVzKS8oaW5mXzF0bzIgKyBpbmZfM3RvNCArIGluZl81ICsgaW5mXzZ0bzkgKyBpbmZfMTB0bzE0ICsgaW5mXzE1cGx1cykpICU+JSAjIGRlYWwgd2l0aCAiZG9udGtub3d1cCIKICBzZWxlY3QoLWluZl9kb250a25vdykgJT4lICMgdXNlIGNvbW1vbiBkaXN0cmlidXRpb24gYXMgcHJpb3IgZm9yICJkb250a25vdyIKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJpbmYiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAieCIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJmcmVxIikgJT4lCiAgbXV0YXRlKHggPSBhcy5udW1lcmljKHJlY29kZSh4LAogICAgICAgICAgICAgICAgICAgIGluZl9sb3dlcmJvdW5kID0gIi01IiwKICAgICAgICAgICAgICAgICAgICBpbmZfZG93biA9ICItMiIsCiAgICAgICAgICAgICAgICAgICAgaW5mXzAgPSAiMCIsCiAgICAgICAgICAgICAgICAgICAgaW5mXzF0bzIgPSAiMS41IiwKICAgICAgICAgICAgICAgICAgICBpbmZfM3RvNCA9ICIzLjUiLAogICAgICAgICAgICAgICAgICAgIGluZl81ID0gIjUiLAogICAgICAgICAgICAgICAgICAgIGluZl82dG85ID0gIjcuNSIsCiAgICAgICAgICAgICAgICAgICAgaW5mXzEwdG8xNCA9ICIxMiIsCiAgICAgICAgICAgICAgICAgICAgaW5mXzE1cGx1cyA9ICIxNyIsCiAgICAgICAgICAgICAgICAgICAgaW5mX3VwcGVyYm91bmQgPSAiMjAiLAogICAgICAgICAgICAgICAgICAgIGluZl9kb250a25vd3VwID0gYXMuY2hhcmFjdGVyKG1lYW5fcG9zaXRpdmUpKSkpICU+JQogIHNlbGVjdCgtbWVhbl9wb3NpdGl2ZSkgJT4lCiAgIyB0dXJuIGZyZXF1ZW5jaWVzIGludG8gcHJvYmFiaWxpdGllcwogIGdyb3VwX2J5KHllYXIsIG1vbnRoKSAlPiUKICBtdXRhdGUoc3VtID0gc3VtKGZyZXEpLAogICAgICAgICB5ID0gZnJlcSAvc3VtKSAlPiUKICBzZWxlY3QoLWMoc3VtLCBmcmVxKSkgJT4lCiAgbXV0YXRlKGRhdGUgPSB5ZWFyICsgKChtb250aCAtIDEpLzEyKSwKICAgICAgICAgZGF0ZSA9IHpvbzo6YXMuRGF0ZSh6b286OnllYXJtb24oZGF0ZSkpLAogICAgICAgICBncm91cCA9IDAsCiAgICAgICAgIGdyb3VwID0gaWZlbHNlKHllYXIgPT0gMjAyMCAmIG1vbnRoID09IDEsIDEsIGdyb3VwKSwKICAgICAgICAgZ3JvdXAgPSBpZmVsc2UoeWVhciA9PSAyMDIwICYgbW9udGggPT0gOSwgMiwgZ3JvdXApLAogICAgICAgICBncm91cCA9IGlmZWxzZSh5ZWFyID09IDIwMjEgJiBtb250aCA9PSA2LCAzLCBncm91cCkpCgpsaW5ldiA8LSBjKCJzb2xpZCIsICJkYXNoZWQiLCAiZG90dGVkIikKbGVndiA8LSBjKCdyZWQnLCAnYmx1ZScsICdncmVlbjQnKQpsZWdzIDwtIGMoIjIwMjAgSmFudWFyeSIsICIyMDIwIFNlcHRlbWJlciIsICIyMDIxIEp1bmUiKQpicmVha3MgPSBjKDEsIDIsIDMpCgpwbG90IDwtIGdncGxvdChkdGZfaGlzdG9ncmFtICU+JQogICAgICAgICAgICAgICAgIGZpbHRlcihncm91cCAlaW4lIGJyZWFrcykgJT4lCiAgICAgICAgICAgICAgICAgbXV0YXRlKGdyb3VwID0gYXMuZmFjdG9yKGdyb3VwKSksCiAgICAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbCA9IGdyb3VwKSkgKwogICAgICAgICAgc3RhdF9kZW5zaXR5KGFlcyh4ID0geCwgd2VpZ2h0ID0geSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gZ3JvdXAsIGxpbmV0eXBlID0gZ3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgZ2VvbSA9ICJsaW5lIiwKICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IGxpbmVfc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICBidyA9IDEuMykgKwogICAgICAgICAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKDAsIDEuNSwgMy41LCA1LCA3LjUsIDEyKSkgKwogICAgICAgICAgc2NhbGVfY29sb3VyX21hbnVhbChicmVha3MgPSBicmVha3MsIHZhbHVlcyA9IGxlZ3YsIGxhYmVscyA9IGxlZ3MpICsKICAgICAgICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbChicmVha3MgPSBicmVha3MsIHZhbHVlcyA9IGxpbmV2LCBsYWJlbHMgPSBsZWdzKSArCiAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuNiwgMC43KSkgKwogICAgICAgICAgZ3VpZGVzKGNvbCA9IGd1aWRlX2xlZ2VuZChrZXl3aWR0aCA9IDUsIGtleWhlaWdodCA9IDEpKQoKcHJpbnQocGxvdCkKaWYgKGJTYXZlUGxvdHMpIG15X2dnc2F2ZShwYXN0ZTAocGF0aF9maWd1cmVfb3V0LCAiZmlndXJlXzE1X2QucGRmIiksIHBsb3QpCgpgYGAK