Preparing data
Libraries
fpackage.check <- function(packages) { # (c) Jochem Tolsma
lapply(packages, FUN = function(x) {
if (!require(x, character.only = TRUE)) {
install.packages(x, dependencies = TRUE)
library(x, character.only = TRUE)
}
})
}
packages = c("tidyverse","kableExtra", "ggplot2", "patchwork", "foreach", "ggpattern")
fpackage.check(packages)
Import results and data
Import the NSUM data and recreate the NSUM module.
#import nells file.
load(file = "data_analysis/data/data_processed/nells_data/2022-11-09_nells-nsum-prepped-data.rds")
Import the model estimates from the estimated NSUM models. I have
chosen the model which uses Ibrahim for the ethnic names.
if (file.exists(
"data_analysis/results/nsum_output/main/combined_data/df_models_nsum_long.rds"
)) {
load(file = "data_analysis/results/nsum_output/main/combined_data/df_models_nsum_long.rds")
} else {
list_files <-
as.list(
dir(
"data_analysis/results/nsum_output/main/model/",
full.names = T
)
)
#create loop lists
kds <- list()
kdssd <- list()
data <- list()
list_df <- list()
#loop to extract information
for (i in 1:length(list_files)) {
#i = 1
print(paste0("Number ", i, " of ", length(list_files)))
load(list_files[[i]])
kds[[i]] <-
rowMeans(degree$d.values, na.rm = TRUE) # calculate rowmean of netsize iterations: so the retained chains
kdssd[[i]] <-
matrixStats::rowSds(degree$d.values) # calculate sd of 4k estimates per row: sd for those values
data[[i]] <- cbind(kds[[i]], kdssd[[i]]) # combine them
list_df[[i]] <-
cbind(as_tibble(data[[i]]), nells_nsum$id) # add NELLS id variable
strings <-
str_split(str_extract(list_files[[i]][1], pattern = "estimates.+"),
pattern = "_") # add holdout number
list_df[[i]] <- list_df[[i]] %>%
mutate(
holdout = as.numeric(str_extract(strings[[1]][2], pattern = "[[:digit:]]{1,}")))
}
#combine results and save
df_models_nsum_long <- list_df %>%
bind_rows() %>%
rename(mean = V1,
sd = V2,
id = 3)
#save image
save(df_models_nsum_long, file = "data_analysis/results/nsum_output/main/combined_data/df_models_nsum_long.rds")
}
We use Ibrahim as population for the size estimates, so let’s combine
the size estimates from holdout 10 with the other NSUM information.
#select holdout ten 10
size_selection <- df_models_nsum_long %>%
dplyr::filter(holdout == 10)
#add netsize data to NELLS data
nells_df <- size_selection %>%
left_join(nells_nsum, by = "id")
Selection of respondents
We remove 32 observations as they deviate more than 3 SD from the
mean.
nells_df <- nells_df %>%
mutate(mean_size = mean(mean, na.rm = T),
sd_size = sd(mean, na.rm = T),
z = (mean - mean_size)/sd_size) %>%
filter(z < 3)
#filter out other
nells_df <- nells_df %>%
filter(migration_background_fac != "Other")
Describing network size
First of all, we want to show the density distribution of extended
network size. We also show the median size of extended networks. These
estimates are in line with previous estimates that have been found of
extended network size.
options(scipen = 999)
size_density_plot <- nells_df %>%
ggplot(aes(x = mean)) +
geom_density(alpha = 0.4,
colour = "black",
fill = "grey") +
geom_vline(xintercept = median(nells_df$mean, na.rm = T),
colour = "red") +
annotate(
"text",
x = 1500,
y = 0.0008,
label = paste("Median:", as.character(round(
median(nells_df$mean, na.rm = T), 3
))),
colour = "black"
) +
#facet_wrap(vars(migration_background_fac)) +
scale_fill_viridis_d() +
scale_color_viridis_d() +
theme(
panel.background = element_rect(fill = "#FFFFFF"),
plot.background = element_rect(fill = "#FFFFFF"),
panel.grid = element_line(colour = "grey"),
text = element_text(family = "sans", size = 12),
axis.title.x = element_text(hjust = 0.9, face = "bold"),
axis.text.x = element_text(),
axis.line = element_blank(),
axis.title.y = element_text(hjust = 0.9, face = "bold"),
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#A9A9A9"),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "right",
legend.title = element_blank(),
legend.background = element_rect(fill = "#FFFFFF"),
legend.key = element_rect(fill = "#FFFFFF")
) +
labs(x = "Extended social network size", y = "Density")
#show plot
size_density_plot
#export plot
ggsave(size_density_plot,
file = "data_analysis/plots/descriptive/density_network_size.jpg",
width = 5,
height = 4,
dpi = 320)
Group comparison
To present differences in network size
Extended groups boxplot
nells_df <- nells_df %>%
mutate(
migration_background_fac = fct_relevel(migration_background_fac,
"Dutch",
"1st gen Turkish",
"2nd gen Turkish",
"1st gen Moroccan",
"2nd gen Moroccan"),
migration_background_fac = factor(as.numeric(migration_background_fac),
levels = 1:5,
labels = c("Dutch Majority",
"1st gen Turkish-Dutch",
"2nd gen Turkish-Dutch",
"1st gen Moroccan-Dutch",
"2nd gen Moroccan-Dutch")),
migration_background_simple_fac = case_when(
migration_background_fac == "1st gen Turkish-Dutch" ~ 2,
migration_background_fac == "2nd gen Turkish-Dutch" ~ 2,
migration_background_fac == "1st gen Moroccan-Dutch" ~ 3,
migration_background_fac == "2nd gen Moroccan-Dutch" ~ 3,
migration_background_fac == "Dutch Majority" ~ 1
),
migration_background_simple_fac = factor(
migration_background_simple_fac,
levels = 1:3,
labels = c("Dutch Majority", "Turkish-Dutch", "Moroccan-Dutch")
),
migrant_generation = case_when(
str_detect(migration_background_fac, "1st") ~ 1,
str_detect(migration_background_fac, "2nd") ~ 2
)
)
Boxplot
Create panel with complete groups (no generation distinction).
#set custom pallet
pal <- c("#66c2a5",
"#fc8d62",
"#8da0cb")
#create simple boxplot
boxplot_size_simple_groups <- nells_df %>%
ggplot(aes(x = fct_rev(migration_background_simple_fac),
y = mean,
fill = migration_background_simple_fac,
colour = migration_background_simple_fac
)) +
geom_boxplot(alpha = 0.6) +
coord_flip() +
scale_colour_manual(
values = pal,
aesthetics = c("colour", "fill")
) +
theme(
panel.background = element_rect(fill = "#FFFFFF"),
plot.background = element_rect(fill = "#FFFFFF"),
panel.grid = element_line(colour = "grey"),
text = element_text(family = "sans", size = 12),
axis.title.x = element_text(hjust = 0.9, face = "bold"),
axis.text.x = element_text(),
axis.line = element_blank(),
axis.title.y = element_text(hjust = 0.9, face = "bold"),
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#A9A9A9"),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_blank(),
legend.position = "none",
legend.title = element_blank(),
legend.background = element_rect(fill = "#FFFFFF"),
legend.key = element_rect(fill = "#FFFFFF")
) +
labs(y = "",
x = "")
Create panel with generation distinction.
#set custom pallet
pal <- c("#fc8d62",
"#fc8d62",
"#8da0cb",
"#8da0cb")
#create extended boplot
boxplot_size_extended_groups <- nells_df %>%
filter(migration_background_fac != "Dutch Majority") %>%
ggplot(aes(x = fct_rev(migration_background_fac),
y = mean,
fill = migration_background_fac,
colour = migration_background_fac
)) +
geom_boxplot_pattern(aes(pattern_density = as.factor(migrant_generation)),
alpha = 0.6,
pattern = "circle"
) +
coord_flip() +
scale_colour_manual(
values = pal,
aesthetics = c("colour", "fill")
) +
scale_pattern_density_manual(values = c("1" = 0, "2"=0.1)) +
theme(
panel.background = element_rect(fill = "#FFFFFF"),
plot.background = element_rect(fill = "#FFFFFF"),
panel.grid = element_line(colour = "grey"),
text = element_text(family = "sans", size = 12),
axis.title.x = element_text(hjust = 0.9, face = "bold"),
axis.text.x = element_text(),
axis.line = element_blank(),
axis.title.y = element_text(hjust = 0.9, face = "bold"),
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#A9A9A9"),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_blank(),
legend.position = "none",
legend.title = element_blank(),
legend.background = element_rect(fill = "#FFFFFF"),
legend.key = element_rect(fill = "#FFFFFF")
) +
labs(y = "",
x = "")
Combine panels in multipanel plot.
## Panel plot
hom_size_panel <- boxplot_size_simple_groups +
boxplot_size_extended_groups +
plot_annotation(tag_levels ='a',
tag_prefix = '(',
tag_suffix = ')') +
plot_layout(ncol = 1,
guides = "collect",
heights = c(1,2)) &
theme(legend.position='none')
hom_size_panel
ggsave(hom_size_panel,
file = "data_analysis/plots/descriptive/size_plot_panel.jpg",
width = 8,
height = 5,
dpi = 320)
Ethnic Homogeneity
Multipanel boxplot
Prepare data for ethnic homogeneity plot.
#weighted by name frequency.
nells_df <- nells_df %>%
mutate(
sum_dutch_w = knows_daan_boundary/22704 +
knows_kevin_boundary/23167 +
knows_emma_boundary/18730 +
knows_linda_boundary/29955 +
knows_albert_boundary/31767 +
knows_edwin_boundary/21866 +
knows_willemina_boundary/17133 +
knows_ingrid_boundary/31323,
sum_turkish_w = knows_ibrahim_boundary/2099 +
knows_esra_boundary/1878,
sum_moroccan_w = knows_mohammed_boundary/13448 +
knows_fatima_boundary/2808,
sum_total_w = sum_dutch_w + sum_turkish_w + sum_moroccan_w,
per_dutch_w = (sum_dutch_w / sum_total_w) * 100,
per_turkish_w = (sum_turkish_w / sum_total_w) * 100,
per_moroccan_w = (sum_moroccan_w / sum_total_w) * 100
)
#assign correct percentage co-ethnic to each group
nells_df <- nells_df %>%
mutate(per_ingroup_w = case_when(
str_detect(migration_background_fac, "kish") ~ per_turkish_w,
str_detect(migration_background_fac, "occan") ~ per_moroccan_w,
migration_background_fac == "Dutch Majority" ~ per_dutch_w,
migration_background_fac == "Other" ~ per_dutch_w
))
Create panel with complete groups (no generation distinction).
#set custom pallet
pal <- c("#66c2a5",
"#fc8d62",
"#8da0cb")
#create graph for simple groups
boxplot_hom_simple_groups <- nells_df %>%
ggplot(aes(x = fct_rev(migration_background_simple_fac),
y = per_ingroup_w,
fill = migration_background_simple_fac,
colour = migration_background_simple_fac
)) +
geom_boxplot(alpha = 0.6) +
coord_flip() +
scale_colour_manual(
values = pal,
aesthetics = c("colour", "fill")
) +
theme(
panel.background = element_rect(fill = "#FFFFFF"),
plot.background = element_rect(fill = "#FFFFFF"),
panel.grid = element_line(colour = "grey"),
text = element_text(family = "sans", size = 12),
axis.title.x = element_text(hjust = 0.9, face = "bold"),
axis.text.x = element_text(),
axis.line = element_blank(),
axis.title.y = element_text(hjust = 0.9, face = "bold"),
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#A9A9A9"),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_blank(),
legend.position = "none",
legend.title = element_blank(),
legend.background = element_rect(fill = "#FFFFFF"),
legend.key = element_rect(fill = "#FFFFFF")
) +
labs(y = "",
x = "")
Create panel with generation distinction.
#set custom pallet
pal <- c("#fc8d62",
"#fc8d62",
"#8da0cb",
"#8da0cb")
#create boxplot for extended groups
boxplot_hom_extended_groups <- nells_df %>%
filter(migration_background_fac != "Dutch Majority") %>%
ggplot(aes(x = fct_rev(migration_background_fac),
y = per_ingroup_w,
colour = migration_background_fac,
fill = migration_background_fac,
)) +
geom_boxplot_pattern(aes(pattern_density = as.factor(migrant_generation)),
alpha = 0.6,
pattern = "circle"
) +
coord_flip() +
scale_colour_manual(
values = pal,
aesthetics = c("colour", "fill")
) +
scale_pattern_density_manual(values = c("1" = 0, "2"=0.1)) +
theme(
panel.background = element_rect(fill = "#FFFFFF"),
plot.background = element_rect(fill = "#FFFFFF"),
panel.grid = element_line(colour = "grey"),
text = element_text(family = "sans", size = 12),
axis.title.x = element_text(hjust = 0.9, face = "bold"),
axis.text.x = element_text(),
axis.line = element_blank(),
axis.title.y = element_text(hjust = 0.9, face = "bold"),
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#A9A9A9"),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_blank(),
legend.position = "none",
legend.title = element_blank(),
legend.background = element_rect(fill = "#FFFFFF"),
legend.key = element_rect(fill = "#FFFFFF")
) +
labs(y = "",
x = "")
Create multipanel plot.
## Panel plot
hom_plot_panel <- boxplot_hom_simple_groups +
boxplot_hom_extended_groups +
plot_annotation(tag_levels ='a',
tag_prefix = '(',
tag_suffix = ')') +
plot_layout(ncol = 1,
guides = "collect",
heights = c(1,2)) &
theme(legend.position='none')
#show plot
hom_plot_panel
#save plor
ggsave(hom_plot_panel,
file = "data_analysis/plots/descriptive/hom_plot_panel.jpg",
width = 8,
height = 5,
dpi = 320)
Name differences
For every x (for now names) we can estimate an NB regression to see
differences between migration backgrounds. Please note: this does not
take into account naming frequency in the population. Differences
between different ethnic groups may indeed be larger or smaller for
different names.
# use a loop.
#set var_names to use in loop.
variable_names_model <- c("knows_daan",
"knows_kevin",
"knows_edwin",
"knows_albert",
"knows_emma",
"knows_linda",
"knows_ingrid",
"knows_willemina",
"knows_mohammed",
"knows_fatima",
"knows_ibrahim",
"knows_esra")
#start analysis loop
model_results <- list()
for(i in 1:length(variable_names_model)) {#i = 1
fm <- as.formula(paste(variable_names_model[[i]], "~", "migration_background_fac"))
model_results[[i]] <- MASS::glm.nb(fm,
data = nells_df)
}
#clean output with tidy r
model_results_df_list <- model_results %>%
purrr::map(.x =.,
.f = ~ broom::tidy(.x))
#add var_names to model_results
for(i in 1:length(model_results_df_list)){
model_results_df_list[[i]] <- model_results_df_list[[i]] %>%
mutate(dep_var = variable_names_model[i])
}
#combine model dfs.
model_results_df <- model_results_df_list %>%
bind_rows()
#set correct variable names
model_results_df <- model_results_df %>%
mutate(
term = case_when(
str_detect(term, "2nd gen Moroccan") ~ "2nd gen Moroccan-Dutch",
str_detect(term, "2nd gen Turkish") ~ "2nd gen Turkish-Dutch",
str_detect(term, "1st gen Moroccan") ~ "1st gen Moroccan-Dutch",
str_detect(term, "1st gen Turkish") ~ "1st gen Turkish-Dutch",
term == "(Intercept)" ~ "Intercept"
)
)
#Set correct names
correct_names <- model_results_df %>%
pull(dep_var) %>%
str_replace(., pattern = "knows_", replacement = "") %>%
str_to_title()
#drop old names and add the correct names
model_results_df <- model_results_df %>%
select(-dep_var) %>%
mutate(dep_var = correct_names)
Predicted counts plot for names and ethnicity
pred_nb_f <- function(nb_model, names){#nb_model = model_results[[1]], names = variable_names_model[[1]]
pred <- predict(object = nb_model,
type = "response",
se.fit = T
)
plot_df <- nells_df %>%
select(id, migration_background_fac) %>%
bind_cols(pred) %>%
mutate(dep_var = names)
return(plot_df)
}
model_pred_list <- map2(.x = model_results,
.y = variable_names_model,
.f = ~pred_nb_f(nb_model = .x,
names = .y))
model_pred_df <- model_pred_list %>%
bind_rows()
#Set correct names
correct_names <- model_pred_df %>%
pull(dep_var) %>%
str_replace(., pattern = "knows_", replacement = "") %>%
str_to_title()
#drop old names and add the correct names
model_pred_df <- model_pred_df %>%
select(-dep_var) %>%
mutate(dep_var = correct_names)
#set custom pallet
pal <- c("#66c2a5",
"#fc8d62",
"#fc8d62",
"#8da0cb",
"#8da0cb")
#crete plot with minority names
ethnic_names_pred_plot <- model_pred_df %>%
filter(dep_var %in% c("Mohammed",
"Fatima",
"Ibrahim",
"Esra")) %>%
ggplot(aes(x = dep_var,
y = fit,
shape = migration_background_fac)) +
geom_linerange(aes(ymin = fit - (se.fit *1.96),
ymax = fit + (se.fit *1.96)),
position = position_dodge(width = 1)) +
geom_point(aes(colour = migration_background_fac,
fill = migration_background_fac),
position = position_dodge(width = 1)) +
facet_wrap(vars(dep_var),
scales = "free",
ncol = 2) +
scale_colour_manual(
values = pal,
aesthetics = c("colour", "fill")
) +
scale_shape_manual(values = c(21,22,24,22,24)) +
theme(
panel.background = element_rect(fill = "#FFFFFF",
colour = "black"),
plot.background = element_rect(fill = "#FFFFFF"),
panel.grid = element_line(colour = "grey"),
text = element_text(family = "sans", size = 12),
axis.title.x = element_text(hjust = 0.9, face = "bold"),
axis.text.x = element_blank(),
axis.line = element_blank(),
axis.title.y = element_text(hjust = 0.9, face = "bold"),
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#FFFFFF"),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none",
legend.title = element_blank(),
legend.background = element_rect(fill = "#FFFFFF"),
legend.key = element_rect(fill = "#FFFFFF")
) +
labs(x = "",
y = "",
colour = "",
shape = "",
fill = ""
)
#set custom pallet
pal <- c("#66c2a5",
"#fc8d62",
"#fc8d62",
"#8da0cb",
"#8da0cb")
#create plot for majority names
non_ethnic_names_pred_plot <- model_pred_df %>%
filter(!dep_var %in% c("Mohammed",
"Fatima",
"Ibrahim",
"Esra")) %>%
ggplot(aes(x = dep_var,
y = fit,
shape = migration_background_fac)) +
geom_linerange(aes(ymin = fit - (se.fit *1.96),
ymax = fit + (se.fit *1.96)),
position = position_dodge(width = 1)) +
geom_point(aes(colour = migration_background_fac,
fill = migration_background_fac),
position = position_dodge(width = 1)) +
facet_wrap(vars(dep_var),
scales = "free_x",
ncol = 2) +
scale_colour_manual(
values = pal,
aesthetics = c("colour", "fill")
) +
scale_shape_manual(values = c(21,22,24,22,24)) +
theme(
panel.background = element_rect(fill = "#FFFFFF",
colour = "black"),
plot.background = element_rect(fill = "#FFFFFF"),
panel.grid = element_line(colour = "grey"),
text = element_text(family = "sans", size = 12),
axis.title.x = element_text(hjust = 0.9, face = "bold"),
axis.text.x = element_blank(),
axis.line = element_blank(),
axis.title.y = element_text(hjust = 0.9, face = "bold"),
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#FFFFFF"),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none",
legend.title = element_blank(),
legend.background = element_rect(fill = "#FFFFFF"),
legend.key = element_rect(fill = "#FFFFFF")
) +
labs(x = "",
y = "",
colour = "",
shape = "",
fill = ""
)
#Combine plots in multipanel plot
names_pred_het_panel <- ethnic_names_pred_plot +
non_ethnic_names_pred_plot +
plot_annotation(
tag_levels = 'a',
tag_prefix = '(',
tag_suffix = ')'
) +
plot_layout(ncol = 1,
heights = c(1, 3),
guides = 'collect',
) &
theme(legend.position = c(-2,-5),
legend.direction = 'vertical')
#preview plot
names_pred_het_panel
#save plot
ggsave(names_pred_het_panel,
file = "data_analysis/plots/descriptive/names_het_pred_panel.jpg",
width = 6,
height = 8,
dpi = 320)
LS0tDQp0aXRsZTogIkRlc2NyaWJpbmcgZXh0ZW5kZWQgbmV0d29yayBzaXplIGFuZCBldGhuaWMgY29tcG9zaXRpb24iDQphdXRob3I6ICJUaGlqbWVuIEplcm9lbnNlIg0KZGF0ZTogIkxhc3QgY29tcGlsZWQgb24gYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiBUUlVFDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogVFJVRQ0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIHJlc3VsdHMgPSAiYXNpcyIsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIpDQpgYGANCg0KIyBHb2FsDQpSZWNyZWF0ZSB0aGUgZGVzY3JpcHRpdmUgYW5hbHlzaXMgYW5kIHBsb3RzIHVzZWQgaW4gdGhlIHB1Ymxpc2hlZCByZXNlYXJjaCBwYXBlci4NCg0KIyBQcmVwYXJpbmcgZGF0YQ0KDQojIyBMaWJyYXJpZXMNCg0KYGBge3IgbGlicmFyaWVzIGFuZCBmaWxlcywgcmVzdWx0cyA9ICdoaWRlJ30NCmZwYWNrYWdlLmNoZWNrIDwtIGZ1bmN0aW9uKHBhY2thZ2VzKSB7ICMgKGMpIEpvY2hlbSBUb2xzbWENCiAgbGFwcGx5KHBhY2thZ2VzLCBGVU4gPSBmdW5jdGlvbih4KSB7DQogICAgaWYgKCFyZXF1aXJlKHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkpIHsNCiAgICAgIGluc3RhbGwucGFja2FnZXMoeCwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCiAgICAgIGxpYnJhcnkoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKQ0KICAgIH0NCiAgfSkNCn0NCnBhY2thZ2VzID0gYygidGlkeXZlcnNlIiwia2FibGVFeHRyYSIsICJnZ3Bsb3QyIiwgInBhdGNod29yayIsICJmb3JlYWNoIiwgImdncGF0dGVybiIpDQpmcGFja2FnZS5jaGVjayhwYWNrYWdlcykNCg0KYGBgDQoNCiMjIEltcG9ydCByZXN1bHRzIGFuZCBkYXRhDQoNCkltcG9ydCB0aGUgTlNVTSBkYXRhIGFuZCByZWNyZWF0ZSB0aGUgTlNVTSBtb2R1bGUuIA0KDQpgYGB7ciBmaWxlc30NCiNpbXBvcnQgbmVsbHMgZmlsZS4NCmxvYWQoZmlsZSA9ICJkYXRhX2FuYWx5c2lzL2RhdGEvZGF0YV9wcm9jZXNzZWQvbmVsbHNfZGF0YS8yMDIyLTExLTA5X25lbGxzLW5zdW0tcHJlcHBlZC1kYXRhLnJkcyIpDQoNCmBgYA0KDQpJbXBvcnQgdGhlIG1vZGVsIGVzdGltYXRlcyBmcm9tIHRoZSBlc3RpbWF0ZWQgTlNVTSBtb2RlbHMuIEkgaGF2ZSBjaG9zZW4gdGhlIG1vZGVsIHdoaWNoIHVzZXMgSWJyYWhpbSBmb3IgdGhlIGV0aG5pYyBuYW1lcy4NCg0KYGBge3IgaW1wb3J0IHJlc3VsdHN9DQoNCmlmIChmaWxlLmV4aXN0cygNCiAgImRhdGFfYW5hbHlzaXMvcmVzdWx0cy9uc3VtX291dHB1dC9tYWluL2NvbWJpbmVkX2RhdGEvZGZfbW9kZWxzX25zdW1fbG9uZy5yZHMiDQopKSB7DQogIGxvYWQoZmlsZSA9ICJkYXRhX2FuYWx5c2lzL3Jlc3VsdHMvbnN1bV9vdXRwdXQvbWFpbi9jb21iaW5lZF9kYXRhL2RmX21vZGVsc19uc3VtX2xvbmcucmRzIikNCn0gZWxzZSB7DQogIGxpc3RfZmlsZXMgPC0NCiAgICBhcy5saXN0KA0KICAgICAgZGlyKA0KICAgICAgICAiZGF0YV9hbmFseXNpcy9yZXN1bHRzL25zdW1fb3V0cHV0L21haW4vbW9kZWwvIiwNCiAgICAgICAgZnVsbC5uYW1lcyA9IFQNCiAgICAgICkNCiAgICApDQogICNjcmVhdGUgbG9vcCBsaXN0cw0KICBrZHMgPC0gbGlzdCgpDQogIGtkc3NkIDwtIGxpc3QoKQ0KICBkYXRhIDwtIGxpc3QoKQ0KICBsaXN0X2RmIDwtIGxpc3QoKQ0KICANCiAgI2xvb3AgdG8gZXh0cmFjdCBpbmZvcm1hdGlvbg0KICBmb3IgKGkgaW4gMTpsZW5ndGgobGlzdF9maWxlcykpIHsNCiAgICAjaSA9IDENCiAgICBwcmludChwYXN0ZTAoIk51bWJlciAiLCBpLCAiIG9mICIsIGxlbmd0aChsaXN0X2ZpbGVzKSkpDQogICAgbG9hZChsaXN0X2ZpbGVzW1tpXV0pDQogICAga2RzW1tpXV0gPC0NCiAgICAgIHJvd01lYW5zKGRlZ3JlZSRkLnZhbHVlcywgbmEucm0gPSBUUlVFKSAjIGNhbGN1bGF0ZSByb3dtZWFuIG9mIG5ldHNpemUgaXRlcmF0aW9uczogc28gdGhlIHJldGFpbmVkIGNoYWlucw0KICAgIGtkc3NkW1tpXV0gPC0NCiAgICAgIG1hdHJpeFN0YXRzOjpyb3dTZHMoZGVncmVlJGQudmFsdWVzKSAjIGNhbGN1bGF0ZSBzZCBvZiA0ayBlc3RpbWF0ZXMgcGVyIHJvdzogc2QgZm9yIHRob3NlIHZhbHVlcw0KICAgIGRhdGFbW2ldXSA8LSBjYmluZChrZHNbW2ldXSwga2Rzc2RbW2ldXSkgIyBjb21iaW5lIHRoZW0NCiAgICBsaXN0X2RmW1tpXV0gPC0NCiAgICAgIGNiaW5kKGFzX3RpYmJsZShkYXRhW1tpXV0pLCBuZWxsc19uc3VtJGlkKSAjIGFkZCBORUxMUyBpZCB2YXJpYWJsZQ0KICAgIHN0cmluZ3MgPC0NCiAgICAgIHN0cl9zcGxpdChzdHJfZXh0cmFjdChsaXN0X2ZpbGVzW1tpXV1bMV0sIHBhdHRlcm4gPSAiZXN0aW1hdGVzLisiKSwNCiAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIl8iKSAgIyBhZGQgaG9sZG91dCBudW1iZXINCiAgICBsaXN0X2RmW1tpXV0gPC0gbGlzdF9kZltbaV1dICU+JQ0KICAgICAgbXV0YXRlKA0KICAgICAgICBob2xkb3V0ID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdChzdHJpbmdzW1sxXV1bMl0sIHBhdHRlcm4gPSAiW1s6ZGlnaXQ6XV17MSx9IikpKQ0KICB9DQogICAgI2NvbWJpbmUgcmVzdWx0cyBhbmQgc2F2ZQ0KICAgIGRmX21vZGVsc19uc3VtX2xvbmcgPC0gbGlzdF9kZiAlPiUNCiAgICAgIGJpbmRfcm93cygpICU+JQ0KICAgICAgcmVuYW1lKG1lYW4gPSBWMSwNCiAgICAgICAgICAgICBzZCA9IFYyLA0KICAgICAgICAgICAgIGlkID0gMykNCiAgICAjc2F2ZSBpbWFnZQ0KICAgIHNhdmUoZGZfbW9kZWxzX25zdW1fbG9uZywgZmlsZSA9ICJkYXRhX2FuYWx5c2lzL3Jlc3VsdHMvbnN1bV9vdXRwdXQvbWFpbi9jb21iaW5lZF9kYXRhL2RmX21vZGVsc19uc3VtX2xvbmcucmRzIikNCn0NCmBgYA0KDQpXZSB1c2UgSWJyYWhpbSBhcyBwb3B1bGF0aW9uIGZvciB0aGUgc2l6ZSBlc3RpbWF0ZXMsIHNvIGxldCdzIGNvbWJpbmUgdGhlIHNpemUgZXN0aW1hdGVzIGZyb20gaG9sZG91dCAxMCB3aXRoIHRoZSBvdGhlciBOU1VNIGluZm9ybWF0aW9uLiANCg0KYGBge3IgaG9sZG91dCAyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD03fQ0KI3NlbGVjdCBob2xkb3V0IHRlbiAxMA0Kc2l6ZV9zZWxlY3Rpb24gPC0gZGZfbW9kZWxzX25zdW1fbG9uZyAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoaG9sZG91dCA9PSAxMCkgDQoNCiNhZGQgbmV0c2l6ZSBkYXRhIHRvIE5FTExTIGRhdGENCm5lbGxzX2RmIDwtIHNpemVfc2VsZWN0aW9uICU+JSANCiAgbGVmdF9qb2luKG5lbGxzX25zdW0sIGJ5ID0gImlkIikNCg0KYGBgDQoNCiMjIFNlbGVjdGlvbiBvZiByZXNwb25kZW50cw0KDQpXZSByZW1vdmUgMzIgb2JzZXJ2YXRpb25zIGFzIHRoZXkgZGV2aWF0ZSBtb3JlIHRoYW4gMyBTRCBmcm9tIHRoZSBtZWFuLiANCg0KYGBge3IgZGVsZXRlIG91dGxpZXJzfQ0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICAgIG11dGF0ZShtZWFuX3NpemUgPSBtZWFuKG1lYW4sIG5hLnJtID0gVCksDQogICAgICAgICBzZF9zaXplID0gc2QobWVhbiwgbmEucm0gPSBUKSwNCiAgICAgICAgIHogPSAobWVhbiAtIG1lYW5fc2l6ZSkvc2Rfc2l6ZSkgJT4lIA0KICBmaWx0ZXIoeiA8IDMpIA0KDQojZmlsdGVyIG91dCBvdGhlcg0KbmVsbHNfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICBmaWx0ZXIobWlncmF0aW9uX2JhY2tncm91bmRfZmFjICE9ICJPdGhlciIpDQoNCg0KYGBgDQoNCiMgRGVzY3JpYmluZyBuZXR3b3JrIHNpemUgDQoNCkZpcnN0IG9mIGFsbCwgd2Ugd2FudCB0byBzaG93IHRoZSBkZW5zaXR5IGRpc3RyaWJ1dGlvbiBvZiBleHRlbmRlZCBuZXR3b3JrIHNpemUuIFdlIGFsc28gc2hvdyB0aGUgbWVkaWFuIHNpemUgb2YgZXh0ZW5kZWQgbmV0d29ya3MuIFRoZXNlIGVzdGltYXRlcyBhcmUgaW4gbGluZSB3aXRoIHByZXZpb3VzIGVzdGltYXRlcyB0aGF0IGhhdmUgYmVlbiBmb3VuZCBvZiBleHRlbmRlZCBuZXR3b3JrIHNpemUuIA0KDQpgYGB7ciBkZW5zaXR5IHBsb3Qgc2FtcGxlLCB3aWR0aCA9IDQsIGhlaWd0aCA9IDR9DQpvcHRpb25zKHNjaXBlbiA9IDk5OSkNCg0Kc2l6ZV9kZW5zaXR5X3Bsb3QgPC0gbmVsbHNfZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IG1lYW4pKSArDQogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNCwNCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsDQogICAgICAgICAgICAgICBmaWxsID0gImdyZXkiKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lZGlhbihuZWxsc19kZiRtZWFuLCBuYS5ybSA9IFQpLA0KICAgICAgICAgICAgIGNvbG91ciA9ICJyZWQiKSArDQogIGFubm90YXRlKA0KICAgICJ0ZXh0IiwNCiAgICB4ID0gMTUwMCwNCiAgICB5ID0gMC4wMDA4LA0KICAgIGxhYmVsID0gcGFzdGUoIk1lZGlhbjoiLCBhcy5jaGFyYWN0ZXIocm91bmQoDQogICAgICBtZWRpYW4obmVsbHNfZGYkbWVhbiwgbmEucm0gPSBUKSwgMw0KICAgICkpKSwNCiAgICBjb2xvdXIgPSAiYmxhY2siDQogICkgKw0KICAjZmFjZXRfd3JhcCh2YXJzKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYykpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSArDQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsNCiAgdGhlbWUoDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIiksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNhbnMiLCBzaXplID0gMTIpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuOSwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoKSwNCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC45LCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjQTlBOUE5IiksDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIiksDQogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKQ0KICApICsNCiAgbGFicyh4ID0gIkV4dGVuZGVkIHNvY2lhbCBuZXR3b3JrIHNpemUiLCB5ID0gIkRlbnNpdHkiKQ0KDQojc2hvdyBwbG90DQpzaXplX2RlbnNpdHlfcGxvdA0KDQojZXhwb3J0IHBsb3QNCmdnc2F2ZShzaXplX2RlbnNpdHlfcGxvdCwNCiAgICAgICBmaWxlID0gImRhdGFfYW5hbHlzaXMvcGxvdHMvZGVzY3JpcHRpdmUvZGVuc2l0eV9uZXR3b3JrX3NpemUuanBnIiwNCiAgICAgICB3aWR0aCA9IDUsDQogICAgICAgaGVpZ2h0ID0gNCwNCiAgICAgICBkcGkgPSAzMjApDQoNCg0KYGBgDQoNCiMjIEdyb3VwIGNvbXBhcmlzb24NCg0KVG8gcHJlc2VudCBkaWZmZXJlbmNlcyBpbiBuZXR3b3JrIHNpemUNCg0KIyMjIEV4dGVuZGVkIGdyb3VwcyBib3hwbG90DQoNCmBgYHtyIHByZXBhcmUgZmFjdG9yIGxhYmVsc30NCm5lbGxzX2RmIDwtIG5lbGxzX2RmICU+JQ0KICBtdXRhdGUoDQogICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID0gZmN0X3JlbGV2ZWwobWlncmF0aW9uX2JhY2tncm91bmRfZmFjLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkR1dGNoIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIFR1cmtpc2giLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gVHVya2lzaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMXN0IGdlbiBNb3JvY2NhbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBNb3JvY2NhbiIpLA0KICAgICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID0gZmFjdG9yKGFzLm51bWVyaWMobWlncmF0aW9uX2JhY2tncm91bmRfZmFjKSwNCiAgICAgICAgIGxldmVscyA9IDE6NSwNCiAgICAgICAgIGxhYmVscyA9IGMoIkR1dGNoIE1ham9yaXR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxc3QgZ2VuIFR1cmtpc2gtRHV0Y2giLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjJuZCBnZW4gVHVya2lzaC1EdXRjaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMXN0IGdlbiBNb3JvY2Nhbi1EdXRjaCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMm5kIGdlbiBNb3JvY2Nhbi1EdXRjaCIpKSwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjID0gY2FzZV93aGVuKA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICIxc3QgZ2VuIFR1cmtpc2gtRHV0Y2giIH4gMiwNCiAgICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiMm5kIGdlbiBUdXJraXNoLUR1dGNoIiB+IDIsDQogICAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIjFzdCBnZW4gTW9yb2NjYW4tRHV0Y2giIH4gMywNCiAgICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiMm5kIGdlbiBNb3JvY2Nhbi1EdXRjaCIgfiAzLA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfZmFjID09ICJEdXRjaCBNYWpvcml0eSIgfiAxDQogICAgKSwNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjID0gZmFjdG9yKA0KICAgICAgbWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYywNCiAgICAgIGxldmVscyA9IDE6MywNCiAgICAgIGxhYmVscyA9IGMoIkR1dGNoIE1ham9yaXR5IiwgIlR1cmtpc2gtRHV0Y2giLCAiTW9yb2NjYW4tRHV0Y2giKQ0KICAgICksDQogICAgbWlncmFudF9nZW5lcmF0aW9uID0gY2FzZV93aGVuKA0KICAgICAgc3RyX2RldGVjdChtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsICIxc3QiKSB+IDEsDQogICAgICBzdHJfZGV0ZWN0KG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywgIjJuZCIpIH4gMg0KICAgICkNCiAgKQ0KDQpgYGANCg0KIyMjIyBCb3hwbG90IA0KDQpDcmVhdGUgcGFuZWwgd2l0aCBjb21wbGV0ZSBncm91cHMgKG5vIGdlbmVyYXRpb24gZGlzdGluY3Rpb24pLg0KDQpgYGB7ciBjb21wYXJlIHNpbXBsZSBncm91cHMgc2l6ZX0NCiNzZXQgY3VzdG9tIHBhbGxldA0KcGFsIDwtIGMoIiM2NmMyYTUiLA0KICAgICAgICAgIiNmYzhkNjIiLA0KICAgICAgICAgIiM4ZGEwY2IiKQ0KDQojY3JlYXRlIHNpbXBsZSBib3hwbG90DQpib3hwbG90X3NpemVfc2ltcGxlX2dyb3VwcyA8LSBuZWxsc19kZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gZmN0X3JldihtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjKSwNCiAgICAgICAgICAgICB5ID0gbWVhbiwNCiAgICAgICAgICAgICBmaWxsID0gbWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYywNCiAgICAgICAgICAgICBjb2xvdXIgPSBtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjDQogICAgICAgICAgICAgKSkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjYpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBwYWwsDQogICAgYWVzdGhldGljcyA9IGMoImNvbG91ciIsICJmaWxsIikNCiAgKSArDQogICB0aGVtZSgNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksDQogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAic2FucyIsIHNpemUgPSAxMiksDQogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC45LCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dCgpLA0KICAgIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjksIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNBOUE5QTkiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIikNCiAgKSArDQogIGxhYnMoeSAgPSAiIiwNCiAgICAgICB4ID0gIiIpDQpgYGANCg0KQ3JlYXRlIHBhbmVsIHdpdGggZ2VuZXJhdGlvbiBkaXN0aW5jdGlvbi4NCg0KYGBge3IgY29tcGFyZSBldGhuaWMgc2l6ZSBib3hwbG90IGV4dGVuZGVkLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD01fQ0KI3NldCBjdXN0b20gcGFsbGV0DQpwYWwgPC0gYygiI2ZjOGQ2MiIsDQogICAgICAgICAiI2ZjOGQ2MiIsDQogICAgICAgICAiIzhkYTBjYiIsDQogICAgICAgICAiIzhkYTBjYiIpDQoNCiNjcmVhdGUgZXh0ZW5kZWQgYm9wbG90DQpib3hwbG90X3NpemVfZXh0ZW5kZWRfZ3JvdXBzIDwtIG5lbGxzX2RmICU+JQ0KICBmaWx0ZXIobWlncmF0aW9uX2JhY2tncm91bmRfZmFjICE9ICJEdXRjaCBNYWpvcml0eSIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gZmN0X3JldihtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMpLA0KICAgICAgICAgICAgIHkgPSBtZWFuLA0KICAgICAgICAgICAgIGZpbGwgPSBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsDQogICAgICAgICAgICAgY29sb3VyID0gbWlncmF0aW9uX2JhY2tncm91bmRfZmFjDQogICAgICAgICAgICAgKSkgKw0KICBnZW9tX2JveHBsb3RfcGF0dGVybihhZXMocGF0dGVybl9kZW5zaXR5ID0gYXMuZmFjdG9yKG1pZ3JhbnRfZ2VuZXJhdGlvbikpLA0KICAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNiwNCiAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJjaXJjbGUiDQogICAgICAgICAgICAgICAgICAgICAgICkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKA0KICAgIHZhbHVlcyA9IHBhbCwNCiAgICBhZXN0aGV0aWNzID0gYygiY29sb3VyIiwgImZpbGwiKQ0KICApICArDQogIHNjYWxlX3BhdHRlcm5fZGVuc2l0eV9tYW51YWwodmFsdWVzID0gYygiMSIgPSAwLCAiMiI9MC4xKSkgKw0KICAgdGhlbWUoDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIiksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNhbnMiLCBzaXplID0gMTIpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuOSwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoKSwNCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC45LCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjQTlBOUE5IiksDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKSwNCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpDQogICkgKw0KICBsYWJzKHkgID0gIiIsDQogICAgICAgeCA9ICIiKQ0KYGBgDQoNCkNvbWJpbmUgcGFuZWxzIGluIG11bHRpcGFuZWwgcGxvdC4NCg0KYGBge3IgY29tcGFyZSBzaXplIHBsb3RzfQ0KDQojIyBQYW5lbCBwbG90DQpob21fc2l6ZV9wYW5lbCA8LSBib3hwbG90X3NpemVfc2ltcGxlX2dyb3VwcyArIA0KICBib3hwbG90X3NpemVfZXh0ZW5kZWRfZ3JvdXBzICsgDQogIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0nYScsDQogICAgICAgICAgICAgICAgICB0YWdfcHJlZml4ID0gJygnLA0KICAgICAgICAgICAgICAgICAgdGFnX3N1ZmZpeCA9ICcpJykgKw0KICBwbG90X2xheW91dChuY29sID0gMSwNCiAgICAgICAgICAgICAgZ3VpZGVzID0gImNvbGxlY3QiLA0KICAgICAgICAgICAgICBoZWlnaHRzID0gYygxLDIpKSAmIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb249J25vbmUnKQ0KDQoNCmhvbV9zaXplX3BhbmVsDQoNCmdnc2F2ZShob21fc2l6ZV9wYW5lbCwNCiAgICAgICBmaWxlID0gImRhdGFfYW5hbHlzaXMvcGxvdHMvZGVzY3JpcHRpdmUvc2l6ZV9wbG90X3BhbmVsLmpwZyIsDQogICAgICAgd2lkdGggPSA4LA0KICAgICAgIGhlaWdodCA9IDUsDQogICAgICAgZHBpID0gMzIwKQ0KDQpgYGANCg0KIyBFdGhuaWMgSG9tb2dlbmVpdHkNCg0KIyMgTXVsdGlwYW5lbCBib3hwbG90DQoNClByZXBhcmUgZGF0YSBmb3IgZXRobmljIGhvbW9nZW5laXR5IHBsb3QuDQoNCmBgYHtyIGNyZWF0ZSBldGhuaWMgaG9tb2dlbmVpdHl9DQojd2VpZ2h0ZWQgYnkgbmFtZSBmcmVxdWVuY3kuDQpuZWxsc19kZiA8LSBuZWxsc19kZiAlPiUNCiAgbXV0YXRlKA0KICAgIHN1bV9kdXRjaF93ID0ga25vd3NfZGFhbl9ib3VuZGFyeS8yMjcwNCArIA0KICAgICAga25vd3Nfa2V2aW5fYm91bmRhcnkvMjMxNjcgKw0KICAgICAga25vd3NfZW1tYV9ib3VuZGFyeS8xODczMCArIA0KICAgICAga25vd3NfbGluZGFfYm91bmRhcnkvMjk5NTUgKyANCiAgICAgIGtub3dzX2FsYmVydF9ib3VuZGFyeS8zMTc2NyArIA0KICAgICAga25vd3NfZWR3aW5fYm91bmRhcnkvMjE4NjYgKyANCiAgICAgIGtub3dzX3dpbGxlbWluYV9ib3VuZGFyeS8xNzEzMyArIA0KICAgICAga25vd3NfaW5ncmlkX2JvdW5kYXJ5LzMxMzIzLA0KICAgIHN1bV90dXJraXNoX3cgPSBrbm93c19pYnJhaGltX2JvdW5kYXJ5LzIwOTkgKyANCiAgICAgIGtub3dzX2VzcmFfYm91bmRhcnkvMTg3OCwNCiAgICBzdW1fbW9yb2NjYW5fdyA9IGtub3dzX21vaGFtbWVkX2JvdW5kYXJ5LzEzNDQ4ICsgDQogICAgICBrbm93c19mYXRpbWFfYm91bmRhcnkvMjgwOCwNCiAgICBzdW1fdG90YWxfdyA9IHN1bV9kdXRjaF93ICsgc3VtX3R1cmtpc2hfdyArIHN1bV9tb3JvY2Nhbl93LA0KICAgIHBlcl9kdXRjaF93ID0gKHN1bV9kdXRjaF93IC8gc3VtX3RvdGFsX3cpICogMTAwLA0KICAgIHBlcl90dXJraXNoX3cgPSAoc3VtX3R1cmtpc2hfdyAvIHN1bV90b3RhbF93KSAqIDEwMCwNCiAgICBwZXJfbW9yb2NjYW5fdyA9IChzdW1fbW9yb2NjYW5fdyAvIHN1bV90b3RhbF93KSAqIDEwMA0KICApDQoNCiNhc3NpZ24gY29ycmVjdCBwZXJjZW50YWdlIGNvLWV0aG5pYyB0byBlYWNoIGdyb3VwDQpuZWxsc19kZiA8LSBuZWxsc19kZiAlPiUgDQogIG11dGF0ZShwZXJfaW5ncm91cF93ID0gY2FzZV93aGVuKA0KICAgIHN0cl9kZXRlY3QobWlncmF0aW9uX2JhY2tncm91bmRfZmFjLCAia2lzaCIpIH4gcGVyX3R1cmtpc2hfdywNCiAgICBzdHJfZGV0ZWN0KG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywgIm9jY2FuIikgfiBwZXJfbW9yb2NjYW5fdywNCiAgICBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMgPT0gIkR1dGNoIE1ham9yaXR5IiB+IHBlcl9kdXRjaF93LA0KICAgIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyA9PSAiT3RoZXIiIH4gcGVyX2R1dGNoX3cNCiAgKSkNCg0KYGBgDQoNCkNyZWF0ZSBwYW5lbCB3aXRoIGNvbXBsZXRlIGdyb3VwcyAobm8gZ2VuZXJhdGlvbiBkaXN0aW5jdGlvbikuDQoNCmBgYHtyIGNvbXBhcmUgc2ltcGxlIGdyb3VwcyBob219DQojc2V0IGN1c3RvbSBwYWxsZXQNCnBhbCA8LSBjKCIjNjZjMmE1IiwNCiAgICAgICAgICIjZmM4ZDYyIiwNCiAgICAgICAgICIjOGRhMGNiIikNCg0KI2NyZWF0ZSBncmFwaCBmb3Igc2ltcGxlIGdyb3Vwcw0KYm94cGxvdF9ob21fc2ltcGxlX2dyb3VwcyA8LSBuZWxsc19kZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gZmN0X3JldihtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjKSwNCiAgICAgICAgICAgICB5ID0gcGVyX2luZ3JvdXBfdywNCiAgICAgICAgICAgICBmaWxsID0gbWlncmF0aW9uX2JhY2tncm91bmRfc2ltcGxlX2ZhYywNCiAgICAgICAgICAgICBjb2xvdXIgPSBtaWdyYXRpb25fYmFja2dyb3VuZF9zaW1wbGVfZmFjDQogICAgICAgICAgICAgKSkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjYpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBwYWwsDQogICAgYWVzdGhldGljcyA9IGMoImNvbG91ciIsICJmaWxsIikNCiAgKSArDQogICB0aGVtZSgNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKSwNCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksDQogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAic2FucyIsIHNpemUgPSAxMiksDQogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC45LCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dCgpLA0KICAgIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjksIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNBOUE5QTkiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIikNCiAgKSArDQogIGxhYnMoeSAgPSAiIiwNCiAgICAgICB4ID0gIiIpDQpgYGANCg0KQ3JlYXRlIHBhbmVsIHdpdGggZ2VuZXJhdGlvbiBkaXN0aW5jdGlvbi4NCg0KYGBge3IgY29tcGFyZSBldGhuaWMgaG9tIGJveHBsb3QgZXh0ZW5kZWQsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTV9DQojc2V0IGN1c3RvbSBwYWxsZXQNCnBhbCA8LSBjKCIjZmM4ZDYyIiwNCiAgICAgICAgICIjZmM4ZDYyIiwNCiAgICAgICAgICIjOGRhMGNiIiwNCiAgICAgICAgICIjOGRhMGNiIikNCg0KI2NyZWF0ZSBib3hwbG90IGZvciBleHRlbmRlZCBncm91cHMNCmJveHBsb3RfaG9tX2V4dGVuZGVkX2dyb3VwcyA8LSBuZWxsc19kZiAlPiUNCiAgZmlsdGVyKG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyAhPSAiRHV0Y2ggTWFqb3JpdHkiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZjdF9yZXYobWlncmF0aW9uX2JhY2tncm91bmRfZmFjKSwNCiAgICAgICAgICAgICB5ID0gcGVyX2luZ3JvdXBfdywNCiAgICAgICAgICAgICBjb2xvdXIgPSBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsDQogICAgICAgICAgICAgZmlsbCA9IG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywNCiAgICAgICAgICAgICApKSArDQogICAgZ2VvbV9ib3hwbG90X3BhdHRlcm4oYWVzKHBhdHRlcm5fZGVuc2l0eSA9IGFzLmZhY3RvcihtaWdyYW50X2dlbmVyYXRpb24pKSwNCiAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjYsDQogICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiY2lyY2xlIg0KICAgICAgICAgICAgICAgICAgICAgICApICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBwYWwsDQogICAgYWVzdGhldGljcyA9IGMoImNvbG91ciIsICJmaWxsIikNCiAgKSAgKw0KICBzY2FsZV9wYXR0ZXJuX2RlbnNpdHlfbWFudWFsKHZhbHVlcyA9IGMoIjEiID0gMCwgIjIiPTAuMSkpICsNCiAgIHRoZW1lKA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkiKSwNCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJzYW5zIiwgc2l6ZSA9IDEyKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjksIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KCksDQogICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuOSwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0E5QTlBOSIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIiksDQogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKQ0KICApICsNCiAgbGFicyh5ICA9ICIiLA0KICAgICAgIHggPSAiIikNCmBgYA0KDQpDcmVhdGUgbXVsdGlwYW5lbCBwbG90Lg0KDQpgYGB7ciBjb21wYXJlIHBsb3RzIGhvbX0NCg0KIyMgUGFuZWwgcGxvdA0KaG9tX3Bsb3RfcGFuZWwgPC0gYm94cGxvdF9ob21fc2ltcGxlX2dyb3VwcyArIA0KICBib3hwbG90X2hvbV9leHRlbmRlZF9ncm91cHMgKyANCiAgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSdhJywNCiAgICAgICAgICAgICAgICAgIHRhZ19wcmVmaXggPSAnKCcsDQogICAgICAgICAgICAgICAgICB0YWdfc3VmZml4ID0gJyknKSArDQogIHBsb3RfbGF5b3V0KG5jb2wgPSAxLA0KICAgICAgICAgICAgICBndWlkZXMgPSAiY29sbGVjdCIsDQogICAgICAgICAgICAgIGhlaWdodHMgPSBjKDEsMikpICYgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0nbm9uZScpDQoNCiNzaG93IHBsb3QNCmhvbV9wbG90X3BhbmVsDQoNCiNzYXZlIHBsb3INCmdnc2F2ZShob21fcGxvdF9wYW5lbCwNCiAgICAgICBmaWxlID0gImRhdGFfYW5hbHlzaXMvcGxvdHMvZGVzY3JpcHRpdmUvaG9tX3Bsb3RfcGFuZWwuanBnIiwNCiAgICAgICB3aWR0aCA9IDgsDQogICAgICAgaGVpZ2h0ID0gNSwNCiAgICAgICBkcGkgPSAzMjApDQoNCmBgYA0KDQoNCiMjIE5hbWUgZGlmZmVyZW5jZXMNCg0KRm9yIGV2ZXJ5IHggKGZvciBub3cgbmFtZXMpIHdlIGNhbiBlc3RpbWF0ZSBhbiBOQiByZWdyZXNzaW9uIHRvIHNlZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIG1pZ3JhdGlvbiBiYWNrZ3JvdW5kcy4gUGxlYXNlIG5vdGU6IHRoaXMgZG9lcyBub3QgdGFrZSBpbnRvIGFjY291bnQgbmFtaW5nIGZyZXF1ZW5jeSBpbiB0aGUgcG9wdWxhdGlvbi4gRGlmZmVyZW5jZXMgYmV0d2VlbiBkaWZmZXJlbnQgZXRobmljIGdyb3VwcyBtYXkgaW5kZWVkIGJlIGxhcmdlciBvciBzbWFsbGVyIGZvciBkaWZmZXJlbnQgbmFtZXMuIA0KDQoNCmBgYHtyIGFuYWx5c2lzIG9mIHggY2F0ZWdvcmllc30NCiMgdXNlIGEgbG9vcC4NCiNzZXQgdmFyX25hbWVzIHRvIHVzZSBpbiBsb29wLiANCnZhcmlhYmxlX25hbWVzX21vZGVsIDwtIGMoImtub3dzX2RhYW4iLA0KICAia25vd3Nfa2V2aW4iLCANCiAgImtub3dzX2Vkd2luIiwNCiAgImtub3dzX2FsYmVydCIsDQogICJrbm93c19lbW1hIiwNCiAgImtub3dzX2xpbmRhIiwNCiAgImtub3dzX2luZ3JpZCIsDQogICJrbm93c193aWxsZW1pbmEiLA0KICAia25vd3NfbW9oYW1tZWQiLA0KICAia25vd3NfZmF0aW1hIiwNCiAgImtub3dzX2licmFoaW0iLA0KICAia25vd3NfZXNyYSIpDQoNCiNzdGFydCBhbmFseXNpcyBsb29wDQptb2RlbF9yZXN1bHRzIDwtIGxpc3QoKQ0KDQpmb3IoaSBpbiAxOmxlbmd0aCh2YXJpYWJsZV9uYW1lc19tb2RlbCkpIHsjaSA9IDENCiAgZm0gPC0gYXMuZm9ybXVsYShwYXN0ZSh2YXJpYWJsZV9uYW1lc19tb2RlbFtbaV1dLCAifiIsICJtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMiKSkNCiAgbW9kZWxfcmVzdWx0c1tbaV1dIDwtIE1BU1M6OmdsbS5uYihmbSwNCiAgICAgZGF0YSA9IG5lbGxzX2RmKQ0KfQ0KDQojY2xlYW4gb3V0cHV0IHdpdGggdGlkeSByDQptb2RlbF9yZXN1bHRzX2RmX2xpc3QgPC0gbW9kZWxfcmVzdWx0cyAlPiUgDQogIHB1cnJyOjptYXAoLnggPS4sIA0KICAgICAgICAgICAgIC5mID0gfiBicm9vbTo6dGlkeSgueCkpDQoNCiNhZGQgdmFyX25hbWVzIHRvIG1vZGVsX3Jlc3VsdHMNCmZvcihpIGluIDE6bGVuZ3RoKG1vZGVsX3Jlc3VsdHNfZGZfbGlzdCkpew0KICBtb2RlbF9yZXN1bHRzX2RmX2xpc3RbW2ldXSA8LSBtb2RlbF9yZXN1bHRzX2RmX2xpc3RbW2ldXSAlPiUgDQogICAgbXV0YXRlKGRlcF92YXIgPSB2YXJpYWJsZV9uYW1lc19tb2RlbFtpXSkNCn0NCg0KI2NvbWJpbmUgbW9kZWwgZGZzLg0KbW9kZWxfcmVzdWx0c19kZiA8LSBtb2RlbF9yZXN1bHRzX2RmX2xpc3QgJT4lDQogIGJpbmRfcm93cygpIA0KDQojc2V0IGNvcnJlY3QgdmFyaWFibGUgbmFtZXMNCm1vZGVsX3Jlc3VsdHNfZGYgPC0gbW9kZWxfcmVzdWx0c19kZiAlPiUNCiAgbXV0YXRlKA0KICAgIHRlcm0gPSBjYXNlX3doZW4oDQogICAgICBzdHJfZGV0ZWN0KHRlcm0sICIybmQgZ2VuIE1vcm9jY2FuIikgfiAiMm5kIGdlbiBNb3JvY2Nhbi1EdXRjaCIsDQogICAgICBzdHJfZGV0ZWN0KHRlcm0sICIybmQgZ2VuIFR1cmtpc2giKSB+ICIybmQgZ2VuIFR1cmtpc2gtRHV0Y2giLA0KICAgICAgc3RyX2RldGVjdCh0ZXJtLCAiMXN0IGdlbiBNb3JvY2NhbiIpIH4gIjFzdCBnZW4gTW9yb2NjYW4tRHV0Y2giLA0KICAgICAgc3RyX2RldGVjdCh0ZXJtLCAiMXN0IGdlbiBUdXJraXNoIikgfiAiMXN0IGdlbiBUdXJraXNoLUR1dGNoIiwNCiAgICAgIHRlcm0gPT0gIihJbnRlcmNlcHQpIiB+ICJJbnRlcmNlcHQiDQogICAgKQ0KICApDQoNCiNTZXQgY29ycmVjdCBuYW1lcw0KY29ycmVjdF9uYW1lcyA8LSBtb2RlbF9yZXN1bHRzX2RmICU+JSANCiAgcHVsbChkZXBfdmFyKSAlPiUgDQogIHN0cl9yZXBsYWNlKC4sIHBhdHRlcm4gPSAia25vd3NfIiwgcmVwbGFjZW1lbnQgPSAiIikgJT4lIA0KICBzdHJfdG9fdGl0bGUoKQ0KDQojZHJvcCBvbGQgbmFtZXMgYW5kIGFkZCB0aGUgY29ycmVjdCBuYW1lcw0KbW9kZWxfcmVzdWx0c19kZiA8LSBtb2RlbF9yZXN1bHRzX2RmICU+JSANCiAgc2VsZWN0KC1kZXBfdmFyKSAlPiUgDQogIG11dGF0ZShkZXBfdmFyID0gY29ycmVjdF9uYW1lcykNCg0KYGBgDQoNCiMjIFByZWRpY3RlZCBjb3VudHMgcGxvdCBmb3IgbmFtZXMgYW5kIGV0aG5pY2l0eQ0KDQpgYGB7ciBwcmVkIGNvdW50IG5hbWVzIH0NCnByZWRfbmJfZiA8LSBmdW5jdGlvbihuYl9tb2RlbCwgbmFtZXMpeyNuYl9tb2RlbCA9IG1vZGVsX3Jlc3VsdHNbWzFdXSwgbmFtZXMgPSB2YXJpYWJsZV9uYW1lc19tb2RlbFtbMV1dDQpwcmVkIDwtIHByZWRpY3Qob2JqZWN0ID0gbmJfbW9kZWwsDQogICAgICAgICAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIsDQogICAgICAgICAgICAgICAgc2UuZml0ID0gVA0KICAgICAgICApDQoNCnBsb3RfZGYgPC0gbmVsbHNfZGYgJT4lIA0KICBzZWxlY3QoaWQsIG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYykgJT4lIA0KICBiaW5kX2NvbHMocHJlZCkgJT4lIA0KICBtdXRhdGUoZGVwX3ZhciA9IG5hbWVzKQ0KDQpyZXR1cm4ocGxvdF9kZikNCn0NCg0KbW9kZWxfcHJlZF9saXN0IDwtIG1hcDIoLnggPSBtb2RlbF9yZXN1bHRzLA0KICAgICAueSA9IHZhcmlhYmxlX25hbWVzX21vZGVsLA0KICAgICAuZiA9IH5wcmVkX25iX2YobmJfbW9kZWwgPSAueCwNCiAgICAgICAgICAgICAgICAgICAgIG5hbWVzID0gLnkpKQ0KDQptb2RlbF9wcmVkX2RmIDwtIG1vZGVsX3ByZWRfbGlzdCAlPiUgDQogIGJpbmRfcm93cygpDQoNCg0KI1NldCBjb3JyZWN0IG5hbWVzDQpjb3JyZWN0X25hbWVzIDwtIG1vZGVsX3ByZWRfZGYgJT4lIA0KICBwdWxsKGRlcF92YXIpICU+JSANCiAgc3RyX3JlcGxhY2UoLiwgcGF0dGVybiA9ICJrbm93c18iLCByZXBsYWNlbWVudCA9ICIiKSAlPiUgDQogIHN0cl90b190aXRsZSgpDQoNCg0KI2Ryb3Agb2xkIG5hbWVzIGFuZCBhZGQgdGhlIGNvcnJlY3QgbmFtZXMNCm1vZGVsX3ByZWRfZGYgPC0gbW9kZWxfcHJlZF9kZiAlPiUgDQogIHNlbGVjdCgtZGVwX3ZhcikgJT4lIA0KICBtdXRhdGUoZGVwX3ZhciA9IGNvcnJlY3RfbmFtZXMpDQpgYGANCg0KDQpgYGB7ciBldGhuaWMgbmFtZXMgcGxvdCBwcmVkfQ0KI3NldCBjdXN0b20gcGFsbGV0DQpwYWwgPC0gYygiIzY2YzJhNSIsDQogICAgICAgICAiI2ZjOGQ2MiIsDQogICAgICAgICAiI2ZjOGQ2MiIsDQogICAgICAgICAiIzhkYTBjYiIsDQogICAgICAgICAiIzhkYTBjYiIpDQoNCiNjcmV0ZSBwbG90IHdpdGggbWlub3JpdHkgbmFtZXMNCmV0aG5pY19uYW1lc19wcmVkX3Bsb3QgPC0gbW9kZWxfcHJlZF9kZiAlPiUgDQogIGZpbHRlcihkZXBfdmFyICVpbiUgYygiTW9oYW1tZWQiLA0KICAiRmF0aW1hIiwNCiAgIklicmFoaW0iLA0KICAiRXNyYSIpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGRlcF92YXIsDQogICAgICAgICAgICAgeSA9IGZpdCwNCiAgICAgICAgICAgICBzaGFwZSA9IG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYykpICsNCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKHltaW4gPSBmaXQgLSAoc2UuZml0ICoxLjk2KSwNCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gIGZpdCArIChzZS5maXQgKjEuOTYpKSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMsDQogICAgICAgICAgICAgICAgIGZpbGwgPSBtaWdyYXRpb25fYmFja2dyb3VuZF9mYWMpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpKSArDQogIGZhY2V0X3dyYXAodmFycyhkZXBfdmFyKSwNCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZSIsDQogICAgICAgICAgICAgbmNvbCA9IDIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBwYWwsDQogICAgYWVzdGhldGljcyA9IGMoImNvbG91ciIsICJmaWxsIikNCiAgKSArDQogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIxLDIyLDI0LDIyLDI0KSkgKw0KICB0aGVtZSgNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIiksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gInNhbnMiLCBzaXplID0gMTIpLA0KICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuOSwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuOSwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIiksDQogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKQ0KICApICsNCiAgICBsYWJzKHggPSAiIiwgDQogICAgICAgeSA9ICIiLA0KICAgICAgIGNvbG91ciA9ICIiLA0KICAgICAgIHNoYXBlID0gIiIsDQogICAgICAgZmlsbCA9ICIiDQogICAgICAgKQ0KYGBgDQoNCmBgYHtyIG5vbiBldGhuaWMgbmFtZXMgcGxvdCBwcmVkfQ0KI3NldCBjdXN0b20gcGFsbGV0DQpwYWwgPC0gYygiIzY2YzJhNSIsDQogICAgICAgICAiI2ZjOGQ2MiIsDQogICAgICAgICAiI2ZjOGQ2MiIsDQogICAgICAgICAiIzhkYTBjYiIsDQogICAgICAgICAiIzhkYTBjYiIpDQoNCiNjcmVhdGUgcGxvdCBmb3IgbWFqb3JpdHkgbmFtZXMNCm5vbl9ldGhuaWNfbmFtZXNfcHJlZF9wbG90IDwtIG1vZGVsX3ByZWRfZGYgJT4lIA0KICBmaWx0ZXIoIWRlcF92YXIgJWluJSBjKCJNb2hhbW1lZCIsDQogICJGYXRpbWEiLA0KICAiSWJyYWhpbSIsDQogICJFc3JhIikpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gZGVwX3ZhciwNCiAgICAgICAgICAgICB5ID0gZml0LA0KICAgICAgICAgICAgIHNoYXBlID0gbWlncmF0aW9uX2JhY2tncm91bmRfZmFjKSkgKw0KICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IGZpdCAtIChzZS5maXQgKjEuOTYpLA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSAgZml0ICsgKHNlLmZpdCAqMS45NikpLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYywNCiAgICAgICAgICAgICAgICAgZmlsbCA9IG1pZ3JhdGlvbl9iYWNrZ3JvdW5kX2ZhYyksDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSkpICsNCiAgZmFjZXRfd3JhcCh2YXJzKGRlcF92YXIpLA0KICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlX3giLA0KICAgICAgICAgICAgIG5jb2wgPSAyKSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwoDQogICAgdmFsdWVzID0gcGFsLA0KICAgIGFlc3RoZXRpY3MgPSBjKCJjb2xvdXIiLCAiZmlsbCIpDQogICkgKw0KICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygyMSwyMiwyNCwyMiwyNCkpICsNCiAgdGhlbWUoDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkiKSwNCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJzYW5zIiwgc2l6ZSA9IDEyKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjksIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjksIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkZGRkYiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0ZGRkZGRiIpLA0KICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRkZGRkZGIikNCiAgKSArDQogICAgbGFicyh4ID0gIiIsIA0KICAgICAgIHkgPSAiIiwNCiAgICAgICBjb2xvdXIgPSAiIiwNCiAgICAgICBzaGFwZSA9ICIiLA0KICAgICAgIGZpbGwgPSAiIg0KICAgICAgICkNCg0KYGBgDQoNCmBgYHtyIHByZWQgbmFtZXMgcGFuZWwgcGxvdCwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9OH0NCiNDb21iaW5lIHBsb3RzIGluIG11bHRpcGFuZWwgcGxvdA0KbmFtZXNfcHJlZF9oZXRfcGFuZWwgPC0gZXRobmljX25hbWVzX3ByZWRfcGxvdCArDQogIG5vbl9ldGhuaWNfbmFtZXNfcHJlZF9wbG90ICsgDQogIHBsb3RfYW5ub3RhdGlvbigNCiAgICB0YWdfbGV2ZWxzID0gJ2EnLA0KICAgIHRhZ19wcmVmaXggPSAnKCcsDQogICAgdGFnX3N1ZmZpeCA9ICcpJw0KICApICsNCiAgcGxvdF9sYXlvdXQobmNvbCA9IDEsDQogICAgICAgICAgICAgIGhlaWdodHMgPSBjKDEsIDMpLA0KICAgICAgICAgICAgICBndWlkZXMgPSAnY29sbGVjdCcsDQogICkgJg0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKC0yLC01KSwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICd2ZXJ0aWNhbCcpDQoNCiNwcmV2aWV3IHBsb3QNCm5hbWVzX3ByZWRfaGV0X3BhbmVsDQoNCiNzYXZlIHBsb3QNCmdnc2F2ZShuYW1lc19wcmVkX2hldF9wYW5lbCwNCiAgICAgICAgZmlsZSA9ICJkYXRhX2FuYWx5c2lzL3Bsb3RzL2Rlc2NyaXB0aXZlL25hbWVzX2hldF9wcmVkX3BhbmVsLmpwZyIsDQogICAgICAgd2lkdGggPSA2LA0KICAgICAgIGhlaWdodCA9IDgsDQogICAgICAgZHBpID0gMzIwKQ0KYGBgDQoNCg0KDQoNCg==